openassets-ruby 0.5.4 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
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