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 +4 -4
- data/README.md +2 -2
- data/lib/openassets/api.rb +29 -21
- data/lib/openassets/cache/ssl_certificate_cache.rb +1 -1
- data/lib/openassets/protocol/asset_definition_loader.rb +24 -3
- data/lib/openassets/transaction/transaction_builder.rb +1 -1
- data/lib/openassets/util.rb +22 -23
- data/lib/openassets/version.rb +1 -1
- data/lib/openassets.rb +1 -0
- data/openassets-ruby.gemspec +1 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72f3294a9b0b8a8936e8755c1425d11ad371e5c1
|
4
|
+
data.tar.gz: 98adc0ea523613f33fd5f528a4a1a1879a494a5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57873cdabe16afb4d0a2b477d7becaf5705be753af43fb739621f7d7063b965fceea94ce577c0aa3623050dc89f649a07e970d566d7b41c4dfd1271480c241dc
|
7
|
+
data.tar.gz: 3595d40e454e6fd7badb719233b6aa716ed5e26583a5c83e0ccb12fb600eb0366b80cbb9eec9ac38dcf15f8ecca5211b5fa71dfad5de30d83e278bc0fd5407e9
|
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# openassets-ruby [](https://travis-ci.org/haw-itn/openassets-ruby) [](https://badge.fury.io/rb/openassets-ruby) [](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:'.
|
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|
|
data/lib/openassets/api.rb
CHANGED
@@ -28,10 +28,8 @@ module OpenAssets
|
|
28
28
|
else
|
29
29
|
raise OpenAssets::Error, 'specified unsupported provider.'
|
30
30
|
end
|
31
|
-
|
32
|
-
|
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
|
-
|
237
|
-
|
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]
|
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 [
|
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(
|
271
|
-
|
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
|
-
|
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
|
286
|
-
|
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 =
|
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
|
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(
|
9
|
-
if
|
10
|
-
@loader = HttpAssetDefinitionLoader.new(
|
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[
|
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)
|
data/lib/openassets/util.rb
CHANGED
@@ -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(
|
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
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
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
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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.
|
data/lib/openassets/version.rb
CHANGED
data/lib/openassets.rb
CHANGED
data/openassets-ruby.gemspec
CHANGED
@@ -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
|
+
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
|
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
|