openassets-ruby 0.5.4 → 0.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d7799eb6ff465493ef1873435b320f4700499128
4
- data.tar.gz: 2a30a7092e1d2bdfc301f208c692ca617a0ae95b
3
+ metadata.gz: 72f3294a9b0b8a8936e8755c1425d11ad371e5c1
4
+ data.tar.gz: 98adc0ea523613f33fd5f528a4a1a1879a494a5a
5
5
  SHA512:
6
- metadata.gz: d5bb413b7fe229ea47230bb5b1da509693f0502132ba4383cfc0dee6af146e3b16c84bc7aa42136f13b8dcedb825072d2e53e350f2c94986dfc3b04a089d173f
7
- data.tar.gz: 77ebd36b208b46b2c88d16be49256d822a56b69eed147a374ce7a73195ecbefcab45d52cee1600b5aa26972215b50c4274a5759407cce8ae7027165d227dc82f
6
+ metadata.gz: 57873cdabe16afb4d0a2b477d7becaf5705be753af43fb739621f7d7063b965fceea94ce577c0aa3623050dc89f649a07e970d566d7b41c4dfd1271480c241dc
7
+ data.tar.gz: 3595d40e454e6fd7badb719233b6aa716ed5e26583a5c83e0ccb12fb600eb0366b80cbb9eec9ac38dcf15f8ecca5211b5fa71dfad5de30d83e278bc0fd5407e9
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # openassets-ruby [![Build Status](https://travis-ci.org/haw-itn/openassets-ruby.svg?branch=master)](https://travis-ci.org/haw-itn/openassets-ruby) [![Gem Version](https://badge.fury.io/rb/openassets-ruby.svg)](https://badge.fury.io/rb/openassets-ruby) [![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE)
2
- The implementation of the Open Assets Protocol for Ruby.
2
+ The implementation of the [Open Assets Protocol](https://github.com/OpenAssets/open-assets-protocol) for Ruby.
3
3
 
4
4
  ## Install
5
5
 
@@ -38,7 +38,7 @@ The configuration options are as follows:
38
38
  |---|---|---|
39
39
  |**network**|The using network. "mainnet" or "testnet" or "regtest" |mainnet|
40
40
  |**provider**|The RPC server. Specify possible now only "bitcoind".|bitcoind|
41
- |**cache**|The path to the database file. If you want to use in-memory database, specify ':memory:'. If do not use cache, specify 'none' .|cache.db|
41
+ |**cache**|The path to the database file. If you want to use in-memory database, specify ':memory:'. |cache.db|
42
42
  |**dust_limit**|The amount of Bitcoin, which is set to the each output of the Open Assets Protocol(issue or transfer).|600 (satoshi)|
43
43
  |**default_fees**|The default transaction fee in satoshi. If you want to use auto fee settings, specify ':auto'. (used by issue_asset and send_asset, send_bitcoin )|10000 (satoshi)|
44
44
  |**min_confirmation**|The minimum number of confirmations the transaction containing an output that used to get UTXO.|1|
@@ -28,10 +28,8 @@ module OpenAssets
28
28
  else
29
29
  raise OpenAssets::Error, 'specified unsupported provider.'
30
30
  end
31
- unless @config[:cache] == 'none'
32
- @tx_cache = Cache::TransactionCache.new(@config[:cache])
33
- @output_cache = Cache::OutputCache.new(@config[:cache])
34
- end
31
+ @tx_cache = Cache::TransactionCache.new(@config[:cache])
32
+ @output_cache = Cache::OutputCache.new(@config[:cache])
35
33
  change_network
36
34
  end
37
35
 
@@ -233,10 +231,8 @@ module OpenAssets
233
231
  marker_output_payload = OpenAssets::Protocol::MarkerOutput.parse_script(out.pk_script)
234
232
  unless marker_output_payload.nil?
235
233
  marker_output = OpenAssets::Protocol::MarkerOutput.deserialize_payload(marker_output_payload)
236
- inputs = tx.inputs.map {|input|
237
- get_output(input.previous_output, input.prev_out_index)
238
- }
239
- asset_ids = compute_asset_ids(inputs, i, tx.outputs, marker_output.asset_quantities)
234
+ prev_outs = tx.inputs.map {|input|get_output(input.previous_output, input.prev_out_index)}
235
+ asset_ids = compute_asset_ids(prev_outs, i, tx, marker_output.asset_quantities)
240
236
  return asset_ids unless asset_ids.nil?
241
237
  end
242
238
  }
@@ -263,18 +259,23 @@ module OpenAssets
263
259
  end
264
260
 
265
261
  private
266
- # @param [Array[OpenAssets::Protocol::TransactionOutput] inputs The outputs referenced by the inputs of the transaction.
262
+ # @param [Array[OpenAssets::Protocol::TransactionOutput] prev_outs The outputs referenced by the inputs of the transaction.
267
263
  # @param [Integer] marker_output_index The position of the marker output in the transaction.
268
- # @param [Array[Bitcoin::Protocol::TxOut]] outputs The outputs of the transaction.
264
+ # @param [Bitcoin::Protocol::Tx] tx The transaction.
269
265
  # @param [Array[OpenAssets::Protocol::TransactionOutput]] asset_quantities The list of asset quantities of the outputs.
270
- def compute_asset_ids(inputs, marker_output_index, outputs, asset_quantities)
271
- return nil if asset_quantities.length > outputs.length - 1 || inputs.length == 0
266
+ def compute_asset_ids(prev_outs, marker_output_index, tx, asset_quantities)
267
+ outputs = tx.outputs
268
+ return nil if asset_quantities.length > outputs.length - 1 || prev_outs.length == 0
272
269
  result = []
273
270
 
274
271
  marker_output = outputs[marker_output_index]
275
272
 
276
273
  # Add the issuance outputs
277
- issuance_asset_id = pubkey_hash_to_asset_id(inputs[0].script.get_hash160)
274
+ if prev_outs[0].script.is_p2sh?
275
+ issuance_asset_id = script_to_asset_id(prev_outs[0].script.to_payload.bth)
276
+ else
277
+ issuance_asset_id = pubkey_hash_to_asset_id(prev_outs[0].script.get_hash160)
278
+ end
278
279
 
279
280
  for i in (0..marker_output_index-1)
280
281
  value = outputs[i].value
@@ -282,12 +283,11 @@ module OpenAssets
282
283
  if i < asset_quantities.length && asset_quantities[i] > 0
283
284
  payload = OpenAssets::Protocol::MarkerOutput.parse_script(marker_output.parsed_script.to_payload)
284
285
  metadata = OpenAssets::Protocol::MarkerOutput.deserialize_payload(payload).metadata
285
- if metadata.nil?
286
- output = OpenAssets::Protocol::TransactionOutput.new(value, script, issuance_asset_id, asset_quantities[i], OpenAssets::Protocol::OutputType::ISSUANCE)
287
- else
288
- output = OpenAssets::Protocol::TransactionOutput.new(
289
- value, script, issuance_asset_id, asset_quantities[i], OpenAssets::Protocol::OutputType::ISSUANCE, metadata)
286
+ if prev_outs[0].script.is_p2sh?
287
+ metadata = parse_issuance_p2sh_pointer(tx.in[0].script_sig)
290
288
  end
289
+ metadata = '' unless metadata
290
+ output = OpenAssets::Protocol::TransactionOutput.new(value, script, issuance_asset_id, asset_quantities[i], OpenAssets::Protocol::OutputType::ISSUANCE, metadata)
291
291
  else
292
292
  output = OpenAssets::Protocol::TransactionOutput.new(value, script, nil, 0, OpenAssets::Protocol::OutputType::ISSUANCE)
293
293
  end
@@ -311,14 +311,13 @@ module OpenAssets
311
311
  remove_outputs.each{|o|outputs.delete(o)}
312
312
 
313
313
  # Add the transfer outputs
314
- input_enum = inputs.each
314
+ input_enum = prev_outs.each
315
315
  input_units_left = 0
316
316
  index = 0
317
317
  for i in (marker_output_index + 1)..(outputs.length-1)
318
318
  output_asset_quantity = (i <= asset_quantities.length) ? asset_quantities[i-1] : 0
319
319
  output_units_left = output_asset_quantity
320
- asset_id = nil
321
- metadata = nil
320
+ asset_id,metadata = nil
322
321
  while output_units_left > 0
323
322
  index += 1
324
323
  if input_units_left == 0
@@ -405,6 +404,15 @@ module OpenAssets
405
404
  decode_tx
406
405
  end
407
406
 
407
+ # parse issuance p2sh which contains asset definition pointer
408
+ def parse_issuance_p2sh_pointer(script_sig)
409
+ script = Bitcoin::Script.new(script_sig).chunks.last
410
+ redeem_script = Bitcoin::Script.new(script)
411
+ return nil unless redeem_script.chunks[1] == Bitcoin::Script::OP_DROP
412
+ asset_def = to_bytes(redeem_script.chunks[0].bth)[0..-1].map{|x|x.to_i(16).chr}.join
413
+ asset_def && asset_def.start_with?('u=') ? asset_def : nil
414
+ end
415
+
408
416
  end
409
417
 
410
418
  end
@@ -3,7 +3,7 @@ module OpenAssets
3
3
  class SSLCertificateCache < SQLiteBase
4
4
 
5
5
  def initialize
6
- path = OpenAssets.configuration && OpenAssets.configuration[:cache] != :none ? OpenAssets.configuration[:cache] : ':memory:'
6
+ path = OpenAssets.configuration ? OpenAssets.configuration[:cache] : ':memory:'
7
7
  super(path)
8
8
  end
9
9
 
@@ -2,12 +2,14 @@ module OpenAssets
2
2
  module Protocol
3
3
 
4
4
  class AssetDefinitionLoader
5
+ extend Bitcoin::Util
6
+ extend OpenAssets::Util
5
7
 
6
8
  attr_reader :loader
7
9
 
8
- def initialize(metadata)
9
- if metadata.start_with?('http://') || metadata.start_with?('https://')
10
- @loader = HttpAssetDefinitionLoader.new(metadata)
10
+ def initialize(url)
11
+ if url.start_with?('http://') || url.start_with?('https://')
12
+ @loader = HttpAssetDefinitionLoader.new(url)
11
13
  end
12
14
  end
13
15
 
@@ -17,6 +19,25 @@ module OpenAssets
17
19
  @loader.load if @loader
18
20
  end
19
21
 
22
+ # create redeem script of asset definition file using p2sh
23
+ # @param[String] url The asset definition url.
24
+ # @param[String] to The open asset address to send the asset to.
25
+ # @return[Bitcoin::Script] redeem script.
26
+ def self.create_pointer_redeem_script(url, to)
27
+ asset_def = "u=#{url}".bytes.map{|b|b.to_s(16)}.join
28
+ btc_addr = oa_address_to_address(to)
29
+ script = Bitcoin::Script.from_string("#{asset_def}")
30
+ Bitcoin::Script.new(script.append_opcode(Bitcoin::Script::OP_DROP).to_payload + Bitcoin::Script.to_address_script(btc_addr))
31
+ end
32
+
33
+ # create ps2s script which specify asset definition pointer
34
+ # @param[String] url The asset definition url.
35
+ # @param[String] to The open asset address to send the asset to.
36
+ # @return[Bitcoin::Script] p2sh script.
37
+ def self.create_pointer_p2sh(url, to)
38
+ redeem_script = create_pointer_redeem_script(url, to)
39
+ Bitcoin::Script.new(Bitcoin::Script.to_p2sh_script(hash160(redeem_script.to_payload.bth)))
40
+ end
20
41
  end
21
42
  end
22
43
  end
@@ -63,7 +63,7 @@ module OpenAssets
63
63
 
64
64
  # Creates a transaction for sending assets to many.
65
65
  # @param[Array[OpenAssets::Transaction::TransferParameters]] asset_transfer_spec The parameters of the asset being transferred.
66
- # @param[String] btc_change_script The script where to send bitcoin change, if any.
66
+ # @param[OpenAssets::Transaction::TransferParameters] btc_transfer_spec The script where to send bitcoin change, if any.
67
67
  # @param[Integer] fees The fees to include in the transaction.
68
68
  # @return[Bitcoin::Protocol:Tx] The resulting unsigned transaction.
69
69
  def transfer_assets(transfer_specs, btc_transfer_spec, fees)
@@ -38,29 +38,39 @@ module OpenAssets
38
38
  pubkey_hash_to_asset_id(hash160(pub_key))
39
39
  end
40
40
 
41
- def pubkey_hash_to_asset_id(hash)
41
+ def pubkey_hash_to_asset_id(pubkey_hash)
42
42
  # gen P2PKH script hash
43
43
  # P2PKH script = OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
44
44
  # (76=OP_DUP, a9=OP_HASH160, 14=Bytes to push, 88=OP_EQUALVERIFY, ac=OP_CHECKSIG)
45
- script = hash160(["76", "a9", "14", hash, "88", "ac"].join)
46
- script = oa_version_byte.to_s(16) + script # add version byte to script hash
47
- encode_base58(script + checksum(script)) # add checksum & encode
45
+ hash_to_asset_id(hash160(["76", "a9", "14", pubkey_hash, "88", "ac"].join))
46
+ end
47
+
48
+ def script_to_asset_id(script)
49
+ hash_to_asset_id(hash160(script))
50
+ end
51
+
52
+ def hash_to_asset_id(hash)
53
+ hash = oa_version_byte.to_s(16) + hash # add version byte to script hash
54
+ encode_base58(hash + checksum(hash)) # add checksum & encode
48
55
  end
49
56
 
50
57
  # LEB128 encode
51
58
  def encode_leb128(value)
52
- d7=->n{(n>>7)==0 ? [n] : d7[n>>7]+[127 & n]}
53
- msb=->a{a0=a[0].to_s(16);[(a[0]< 16 ? "0"+a0 : a0)]+a[1..-1].map{|x|(x|128).to_s(16)}}
54
- leb128=->n{msb[d7[n]].reverse.join}
55
- leb128[value]
59
+ LEB128.encode(value, false).read.bth
56
60
  end
57
61
 
58
62
  # LEB128 decode
59
63
  def decode_leb128(value)
60
- mbs = to_bytes(value).map{|x|(x.to_i(16)>=128 ? x : x+"|")}.join.split('|')
61
- num=->a{(a.size==1 ? a[0] : (num[a[0..-2]]<<7)|a[-1])}
62
- r7=->n{to_bytes(n).map{|x|(x.to_i(16))&127}}
63
- mbs.map{|x|num[r7[x].reverse]}
64
+ results = []
65
+ sio = StringIO.new
66
+ value.htb.each_byte{|b|
67
+ sio.putc(b)
68
+ if b < 128
69
+ results << LEB128.decode(sio, false)
70
+ sio = StringIO.new
71
+ end
72
+ }
73
+ results
64
74
  end
65
75
 
66
76
  def to_bytes(string)
@@ -109,17 +119,6 @@ module OpenAssets
109
119
  valid_address?(address)
110
120
  end
111
121
 
112
- # generate Asset ID from open asset address.
113
- def oa_address_to_asset_id(oa_address)
114
- address_to_asset_id(oa_address_to_address(oa_address))
115
- end
116
-
117
- # generate Asset ID from bitcoin address.
118
- def address_to_asset_id(btc_address)
119
- pubkey_hash = hash160_from_address(btc_address)
120
- pubkey_hash_to_asset_id(pubkey_hash)
121
- end
122
-
123
122
  # read variable integer
124
123
  # @param [String] data reading data
125
124
  # @param [Integer] offset the position when reading from data.
@@ -1,3 +1,3 @@
1
1
  module OpenAssets
2
- VERSION = '0.5.4'
2
+ VERSION = '0.5.5'
3
3
  end
data/lib/openassets.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'bitcoin'
2
+ require 'leb128'
2
3
  module OpenAssets
3
4
 
4
5
  autoload :Protocol, 'openassets/protocol'
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.add_runtime_dependency "rest-client", "~>1.8.0"
24
24
  spec.add_runtime_dependency "httpclient"
25
25
  spec.add_runtime_dependency "sqlite3"
26
+ spec.add_runtime_dependency "leb128"
26
27
  spec.add_development_dependency "bundler", "~> 1.9"
27
28
  spec.add_development_dependency "rake", "~> 10.0"
28
29
  spec.add_development_dependency "rspec"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openassets-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.5.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - azuchi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-09-20 00:00:00.000000000 Z
11
+ date: 2016-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bitcoin-ruby
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: leb128
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: bundler
85
99
  requirement: !ruby/object:Gem::Requirement