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 +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 [![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:'.
|
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
|