btcruby 1.1.4 → 1.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/RELEASE_NOTES.md +7 -0
- data/lib/btcruby.rb +1 -1
- data/lib/btcruby/address.rb +1 -0
- data/lib/btcruby/open_assets/asset_marker.rb +1 -0
- data/lib/btcruby/script/opcode.rb +3 -0
- data/lib/btcruby/script/script.rb +2 -1
- data/lib/btcruby/script/script_chunk.rb +1 -0
- data/lib/btcruby/script/script_error.rb +41 -37
- data/lib/btcruby/script/script_interpreter.rb +2 -0
- data/lib/btcruby/script/script_interpreter_plugin.rb +2 -0
- data/lib/btcruby/transaction_builder.rb +1 -0
- data/lib/btcruby/version.rb +1 -1
- data/spec/address_spec.rb +22 -22
- data/spec/base58_spec.rb +8 -8
- data/spec/block_header_spec.rb +4 -4
- data/spec/block_spec.rb +4 -4
- data/spec/currency_formatter_spec.rb +30 -30
- data/spec/data_spec.rb +3 -3
- data/spec/key_spec.rb +11 -11
- data/spec/keychain_spec.rb +12 -12
- data/spec/merkle_tree_spec.rb +3 -3
- data/spec/open_assets/asset_address_spec.rb +7 -7
- data/spec/open_assets/asset_id_spec.rb +3 -3
- data/spec/open_assets/asset_marker_spec.rb +5 -5
- data/spec/open_assets/asset_processor_spec.rb +48 -48
- data/spec/open_assets/asset_transaction_builder_spec.rb +26 -26
- data/spec/open_assets/asset_transaction_spec.rb +9 -9
- data/spec/open_assets/issuance_id_spec.rb +3 -3
- data/spec/script_interpreter_spec.rb +4 -4
- data/spec/script_spec.rb +23 -23
- data/spec/spec_helper.rb +33 -31
- data/spec/transaction_builder_spec.rb +33 -33
- data/spec/transaction_spec.rb +18 -18
- data/spec/wire_format_spec.rb +5 -5
- metadata +2 -2
data/spec/data_spec.rb
CHANGED
@@ -12,9 +12,9 @@ describe BTC::Data do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should not decode invalid hex" do
|
15
|
-
lambda { BTC.from_hex("f") }.must_raise FormatError
|
16
|
-
lambda { BTC.from_hex("dxadBEEF") }.must_raise FormatError
|
17
|
-
lambda { BTC.from_hex("-") }.must_raise FormatError
|
15
|
+
lambda { BTC.from_hex("f") }.must_raise BTC::FormatError
|
16
|
+
lambda { BTC.from_hex("dxadBEEF") }.must_raise BTC::FormatError
|
17
|
+
lambda { BTC.from_hex("-") }.must_raise BTC::FormatError
|
18
18
|
end
|
19
19
|
|
20
20
|
it "should encode valid hex" do
|
data/spec/key_spec.rb
CHANGED
@@ -128,17 +128,17 @@ describe BTC::Key do
|
|
128
128
|
2560.times do |i|
|
129
129
|
hash = BTC.sha256("tx#{i}")
|
130
130
|
sig = key.ecdsa_signature(hash) + "\x01".b
|
131
|
-
canonical = Key.validate_script_signature(sig)
|
131
|
+
canonical = BTC::Key.validate_script_signature(sig)
|
132
132
|
if !canonical
|
133
|
-
puts Diagnostics.current.last_message
|
133
|
+
puts BTC::Diagnostics.current.last_message
|
134
134
|
end
|
135
135
|
canonical.must_equal true
|
136
136
|
end
|
137
137
|
|
138
138
|
sig = "3045022100e81a33ac22d0ef25d359a5353977f0f953608b2733141239ec02363237ab6781022045c71237e95b56079e9fa88591060e4c1a4bb02c0cad1ebeb092749d4aa9754701".from_hex
|
139
|
-
canonical = Key.validate_script_signature(sig)
|
139
|
+
canonical = BTC::Key.validate_script_signature(sig)
|
140
140
|
if !canonical
|
141
|
-
puts Diagnostics.current.last_message
|
141
|
+
puts BTC::Diagnostics.current.last_message
|
142
142
|
end
|
143
143
|
canonical.must_equal true
|
144
144
|
end
|
@@ -150,7 +150,7 @@ describe BTC::Key do
|
|
150
150
|
# 2560.times do |i|
|
151
151
|
# hash = BTC.sha256("tx#{i}")
|
152
152
|
# sig = key.ecdsa_signature(hash, normalized: false) + "\x01".b
|
153
|
-
# if !Key.validate_script_signature(sig)
|
153
|
+
# if !BTC::Key.validate_script_signature(sig)
|
154
154
|
# puts sig[0, sig.size - 1].to_hex
|
155
155
|
# end
|
156
156
|
# end
|
@@ -181,23 +181,23 @@ describe BTC::Key do
|
|
181
181
|
3045022062d08bff9580238c8cd62d9d64e9c1d518932886651f46a445bff773993500f00221008029263cc9ec64589bbbe140995096c257a1fbacf5f9f5ee69a69b96c626cc7a
|
182
182
|
].each do |hex_sig|
|
183
183
|
sig = hex_sig.from_hex
|
184
|
-
canonical = Key.validate_script_signature(sig + "\x01".b)
|
184
|
+
canonical = BTC::Key.validate_script_signature(sig + "\x01".b)
|
185
185
|
canonical.must_equal false
|
186
|
-
sig2 = Key.normalized_signature(sig)
|
186
|
+
sig2 = BTC::Key.normalized_signature(sig)
|
187
187
|
sig2.wont_equal nil
|
188
188
|
sig2.wont_equal sig
|
189
|
-
canonical = Key.validate_script_signature(sig2 + "\x01".b)
|
189
|
+
canonical = BTC::Key.validate_script_signature(sig2 + "\x01".b)
|
190
190
|
if !canonical
|
191
|
-
puts Diagnostics.current.last_message
|
191
|
+
puts BTC::Diagnostics.current.last_message
|
192
192
|
end
|
193
193
|
canonical.must_equal true
|
194
194
|
|
195
195
|
# Non-canonical signature must be normalized
|
196
|
-
sig3 = Key.validate_and_normalize_script_signature(sig + "\x01".b)
|
196
|
+
sig3 = BTC::Key.validate_and_normalize_script_signature(sig + "\x01".b)
|
197
197
|
sig3.must_equal sig2 + "\x01".b
|
198
198
|
|
199
199
|
# Canonical signature should stay the same
|
200
|
-
sig4 = Key.validate_and_normalize_script_signature(sig2 + "\x01".b)
|
200
|
+
sig4 = BTC::Key.validate_and_normalize_script_signature(sig2 + "\x01".b)
|
201
201
|
sig4.must_equal sig2 + "\x01".b
|
202
202
|
end
|
203
203
|
end
|
data/spec/keychain_spec.rb
CHANGED
@@ -4,18 +4,18 @@ describe BTC::Keychain do
|
|
4
4
|
|
5
5
|
it "should support tpub/tprv prefixes for testnet" do
|
6
6
|
seed = "000102030405060708090a0b0c0d0e0f".from_hex
|
7
|
-
master = Keychain.new(seed: seed)
|
8
|
-
master.network = Network.testnet
|
7
|
+
master = BTC::Keychain.new(seed: seed)
|
8
|
+
master.network = BTC::Network.testnet
|
9
9
|
master.xpub.must_equal "tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp"
|
10
10
|
master.xprv.must_equal "tprv8ZgxMBicQKsPeDgjzdC36fs6bMjGApWDNLR9erAXMs5skhMv36j9MV5ecvfavji5khqjWaWSFhN3YcCUUdiKH6isR4Pwy3U5y5egddBr16m"
|
11
|
-
master.network = Network.mainnet
|
11
|
+
master.network = BTC::Network.mainnet
|
12
12
|
master.xpub.must_equal "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
|
13
13
|
master.xprv.must_equal "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi"
|
14
14
|
end
|
15
15
|
|
16
16
|
it "should support path API" do
|
17
17
|
seed = "000102030405060708090a0b0c0d0e0f".from_hex
|
18
|
-
master = Keychain.new(seed: seed)
|
18
|
+
master = BTC::Keychain.new(seed: seed)
|
19
19
|
master.derived_keychain("").xpub.must_equal "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
|
20
20
|
master.derived_keychain("m").xpub.must_equal "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
|
21
21
|
master.derived_keychain("0'").xpub.must_equal "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw"
|
@@ -51,7 +51,7 @@ describe BTC::Keychain do
|
|
51
51
|
# * ext prv: xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76
|
52
52
|
|
53
53
|
seed = "000102030405060708090a0b0c0d0e0f".from_hex
|
54
|
-
master = Keychain.new(seed: seed)
|
54
|
+
master = BTC::Keychain.new(seed: seed)
|
55
55
|
|
56
56
|
master.key.address.to_s.must_equal "15mKKb2eos1hWa6tisdPwwDC1a5J1y9nma"
|
57
57
|
master.key.address.to_s.must_equal master.public_keychain.key.address.to_s
|
@@ -70,7 +70,7 @@ describe BTC::Keychain do
|
|
70
70
|
master.xpub.must_equal "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
|
71
71
|
master.xprv.must_equal "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi"
|
72
72
|
|
73
|
-
master2 = Keychain.new(xprv: master.extended_private_key)
|
73
|
+
master2 = BTC::Keychain.new(xprv: master.extended_private_key)
|
74
74
|
master2.private?.must_equal true
|
75
75
|
(master2 == master).must_equal true
|
76
76
|
master2.xpub.must_equal master.xpub
|
@@ -135,7 +135,7 @@ describe BTC::Keychain do
|
|
135
135
|
# * ext prv: xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j
|
136
136
|
|
137
137
|
seed = "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542".from_hex
|
138
|
-
master = Keychain.new(seed: seed)
|
138
|
+
master = BTC::Keychain.new(seed: seed)
|
139
139
|
|
140
140
|
master.parent_fingerprint.must_equal 0
|
141
141
|
master.identifier.to_hex.must_equal "bd16bee53961a47d6ad888e29545434a89bdfe95"
|
@@ -173,7 +173,7 @@ describe BTC::Keychain do
|
|
173
173
|
end
|
174
174
|
|
175
175
|
it "should behave correctly on privkeys below 32-byte size" do
|
176
|
-
keychain = Keychain.new(seed: "stress test")
|
176
|
+
keychain = BTC::Keychain.new(seed: "stress test")
|
177
177
|
#puts keychain.extended_private_key
|
178
178
|
# Uncomment this to figure out the indexes for the shorter keys
|
179
179
|
if false
|
@@ -221,7 +221,7 @@ describe BTC::Keychain do
|
|
221
221
|
|
222
222
|
it "should verify a certain regression test" do
|
223
223
|
extprv = "xprv9s21ZrQH143K3ZhiFsU612wiYCnd5miCTnWRMRJCmbTUxnn3F2WXuTXcoEyWpsit8ZqS5ddNvsoaEQuwzNwH8nmVDS24NwHbiu5oCrj85Kz"
|
224
|
-
keychain = Keychain.new(xprv: extprv)
|
224
|
+
keychain = BTC::Keychain.new(xprv: extprv)
|
225
225
|
key0 = keychain.derived_keychain(0, hardened: false).key
|
226
226
|
# puts "UNCOMPR: #{key0.uncompressed_key.address.to_s}"
|
227
227
|
# puts " COMPR: #{key0.compressed_key.address.to_s}"
|
@@ -233,7 +233,7 @@ describe BTC::Keychain do
|
|
233
233
|
|
234
234
|
it "should support conversion to public keychain" do
|
235
235
|
seed = "000102030405060708090a0b0c0d0e0f".from_hex
|
236
|
-
master = Keychain.new(seed: seed)
|
236
|
+
master = BTC::Keychain.new(seed: seed)
|
237
237
|
|
238
238
|
m0prv = master.derived_keychain(0, hardened:true)
|
239
239
|
m0prv_pub = m0prv.public_keychain
|
@@ -248,12 +248,12 @@ describe BTC::Keychain do
|
|
248
248
|
m0prv_pub.public?.must_equal true
|
249
249
|
m0prv_pub.hardened?.must_equal true
|
250
250
|
|
251
|
-
m0prv_pub2 = Keychain.new(extended_key: m0prv.extended_public_key)
|
251
|
+
m0prv_pub2 = BTC::Keychain.new(extended_key: m0prv.extended_public_key)
|
252
252
|
m0prv_pub2.must_equal m0prv_pub
|
253
253
|
end
|
254
254
|
|
255
255
|
it "should support public-only derivation" do
|
256
|
-
keychain = Keychain.new(xpub: "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB")
|
256
|
+
keychain = BTC::Keychain.new(xpub: "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB")
|
257
257
|
m0pub = keychain.derived_keychain(0)
|
258
258
|
m0pub.extended_public_key.must_equal "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH"
|
259
259
|
m0pub.extended_private_key.must_equal nil
|
data/spec/merkle_tree_spec.rb
CHANGED
@@ -3,7 +3,7 @@ describe BTC::MerkleTree do
|
|
3
3
|
|
4
4
|
it "should compute root of one hash equal to that hash" do
|
5
5
|
hash = "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456"
|
6
|
-
MerkleTree.new(hashes: [hash.from_hex]).merkle_root.to_hex.must_equal hash
|
6
|
+
BTC::MerkleTree.new(hashes: [hash.from_hex]).merkle_root.to_hex.must_equal hash
|
7
7
|
end
|
8
8
|
|
9
9
|
it "merkle root of 2 hashes must equal hash(a+b)" do
|
@@ -11,7 +11,7 @@ describe BTC::MerkleTree do
|
|
11
11
|
b = "0c08173828583fc6ecd6ecdbcca7b6939c49c242ad5107e39deb7b0a5996b903".from_hex
|
12
12
|
r = "7de236613dd3d9fa1d86054a84952f1e0df2f130546b394a4d4dd7b76997f607".from_hex
|
13
13
|
r.to_hex.must_equal BTC.hash256(a+b).to_hex
|
14
|
-
mt = MerkleTree.new(hashes: [a,b])
|
14
|
+
mt = BTC::MerkleTree.new(hashes: [a,b])
|
15
15
|
mt.tail_duplicates?.must_equal false
|
16
16
|
mt.merkle_root.to_hex.must_equal r.to_hex
|
17
17
|
end
|
@@ -22,7 +22,7 @@ describe BTC::MerkleTree do
|
|
22
22
|
c = "80903da4e6bbdf96e8ff6fc3966b0cfd355c7e860bdd1caa8e4722d9230e40ac".from_hex
|
23
23
|
r = "5b7534123197114fa7e7459075f39d89ffab74b5c3f31fad48a025b931ff5a01".from_hex
|
24
24
|
r.to_hex.must_equal BTC.hash256(BTC.hash256(a+b)+BTC.hash256(c+c)).to_hex
|
25
|
-
mt = MerkleTree.new(hashes: [a,b,c])
|
25
|
+
mt = BTC::MerkleTree.new(hashes: [a,b,c])
|
26
26
|
mt.tail_duplicates?.must_equal false
|
27
27
|
mt.merkle_root.to_hex.must_equal r.to_hex
|
28
28
|
end
|
@@ -2,31 +2,31 @@ require_relative '../spec_helper'
|
|
2
2
|
|
3
3
|
describe BTC::AssetAddress do
|
4
4
|
it "should encode bitcoin address to a correct asset address" do
|
5
|
-
btc_address = Address.parse("16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM")
|
6
|
-
asset_address = AssetAddress.new(bitcoin_address: btc_address)
|
5
|
+
btc_address = BTC::Address.parse("16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM")
|
6
|
+
asset_address = BTC::AssetAddress.new(bitcoin_address: btc_address)
|
7
7
|
asset_address.bitcoin_address.must_equal btc_address
|
8
8
|
asset_address.to_s.must_equal "akB4NBW9UuCmHuepksob6yfZs6naHtRCPNy"
|
9
9
|
asset_address.mainnet?.must_equal true
|
10
10
|
end
|
11
11
|
it "should decode an asset address" do
|
12
|
-
asset_address = Address.parse("akB4NBW9UuCmHuepksob6yfZs6naHtRCPNy")
|
12
|
+
asset_address = BTC::Address.parse("akB4NBW9UuCmHuepksob6yfZs6naHtRCPNy")
|
13
13
|
asset_address.bitcoin_address.to_s.must_equal "16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM"
|
14
14
|
asset_address.mainnet?.must_equal true
|
15
15
|
end
|
16
16
|
it "should allow instantiating Asset Address with an Asset Address" do
|
17
|
-
asset_address = AssetAddress.new(bitcoin_address: "akB4NBW9UuCmHuepksob6yfZs6naHtRCPNy")
|
17
|
+
asset_address = BTC::AssetAddress.new(bitcoin_address: "akB4NBW9UuCmHuepksob6yfZs6naHtRCPNy")
|
18
18
|
asset_address.to_s.must_equal "akB4NBW9UuCmHuepksob6yfZs6naHtRCPNy"
|
19
19
|
asset_address.bitcoin_address.to_s.must_equal "16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM"
|
20
20
|
asset_address.mainnet?.must_equal true
|
21
21
|
end
|
22
22
|
it "should support P2SH address for assets" do
|
23
|
-
asset_address = AssetAddress.new(bitcoin_address: "3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX")
|
23
|
+
asset_address = BTC::AssetAddress.new(bitcoin_address: "3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX")
|
24
24
|
asset_address.to_s.must_equal "anQin2TDYaubr6M5MQM8kNXMitHc2hsmfGc"
|
25
25
|
asset_address.bitcoin_address.to_s.must_equal "3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX"
|
26
26
|
asset_address.mainnet?.must_equal true
|
27
27
|
|
28
|
-
asset_address = Address.parse("anQin2TDYaubr6M5MQM8kNXMitHc2hsmfGc")
|
29
|
-
asset_address.class.must_equal(AssetAddress)
|
28
|
+
asset_address = BTC::Address.parse("anQin2TDYaubr6M5MQM8kNXMitHc2hsmfGc")
|
29
|
+
asset_address.class.must_equal(BTC::AssetAddress)
|
30
30
|
asset_address.bitcoin_address.to_s.must_equal "3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX"
|
31
31
|
asset_address.mainnet?.must_equal true
|
32
32
|
end
|
@@ -2,13 +2,13 @@ require_relative '../spec_helper'
|
|
2
2
|
|
3
3
|
describe BTC::AssetID do
|
4
4
|
it "should encode script to a correct address" do
|
5
|
-
key = Key.new(private_key: "18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725".from_hex, public_key_compressed: false)
|
6
|
-
asset_id = AssetID.new(script: key.address(network: Network.mainnet).script, network: Network.mainnet)
|
5
|
+
key = BTC::Key.new(private_key: "18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725".from_hex, public_key_compressed: false)
|
6
|
+
asset_id = BTC::AssetID.new(script: key.address(network: BTC::Network.mainnet).script, network: BTC::Network.mainnet)
|
7
7
|
asset_id.to_s.must_equal "ALn3aK1fSuG27N96UGYB1kUYUpGKRhBuBC"
|
8
8
|
asset_id.is_a?(BTC::AssetID).must_equal true
|
9
9
|
end
|
10
10
|
it "should decode an asset address" do
|
11
|
-
asset_id = Address.parse("ALn3aK1fSuG27N96UGYB1kUYUpGKRhBuBC")
|
11
|
+
asset_id = BTC::Address.parse("ALn3aK1fSuG27N96UGYB1kUYUpGKRhBuBC")
|
12
12
|
asset_id.is_a?(BTC::AssetID).must_equal true
|
13
13
|
asset_id.hash.must_equal "36e0ea8e93eaa0285d641305f4c81e563aa570a2".from_hex
|
14
14
|
end
|
@@ -18,22 +18,22 @@ describe BTC::AssetMarker do
|
|
18
18
|
# - Outputs after output 3 (if any) have an asset quantity of 0.
|
19
19
|
# 0x05 The metadata is 5 bytes long.
|
20
20
|
# 0x48 0x65 0x6c 0x6c 0x6f Some arbitrary metadata.
|
21
|
-
output = TransactionOutput.new(value: 0, script: Script.new << OP_RETURN << "4f41010003ac0200e58e260548656c6c6f".from_hex)
|
22
|
-
marker = AssetMarker.new(output: output)
|
21
|
+
output = BTC::TransactionOutput.new(value: 0, script: BTC::Script.new << BTC::OP_RETURN << "4f41010003ac0200e58e260548656c6c6f".from_hex)
|
22
|
+
marker = BTC::AssetMarker.new(output: output)
|
23
23
|
marker.quantities.must_equal [300, 0, 624_485]
|
24
24
|
marker.metadata.must_equal "Hello"
|
25
25
|
|
26
|
-
marker = AssetMarker.new(script: output.script)
|
26
|
+
marker = BTC::AssetMarker.new(script: output.script)
|
27
27
|
marker.quantities.must_equal [300, 0, 624_485]
|
28
28
|
marker.metadata.must_equal "Hello"
|
29
29
|
|
30
|
-
marker = AssetMarker.new(data: output.script.op_return_data)
|
30
|
+
marker = BTC::AssetMarker.new(data: output.script.op_return_data)
|
31
31
|
marker.quantities.must_equal [300, 0, 624_485]
|
32
32
|
marker.metadata.must_equal "Hello"
|
33
33
|
end
|
34
34
|
|
35
35
|
it "should encode marker output" do
|
36
|
-
marker = AssetMarker.new
|
36
|
+
marker = BTC::AssetMarker.new
|
37
37
|
marker.data.must_equal "4f4101000000".from_hex
|
38
38
|
marker.metadata = "Hello"
|
39
39
|
marker.data.must_equal "4f410100000548656c6c6f".from_hex
|
@@ -3,21 +3,21 @@ require_relative '../spec_helper'
|
|
3
3
|
describe "Verifying transfer outputs" do
|
4
4
|
|
5
5
|
def build_asset_transaction(inputs: [], issues: [], transfers: [])
|
6
|
-
tx = Transaction.new
|
7
|
-
script = PublicKeyAddress.new(hash: "some address".hash160).script
|
6
|
+
tx = BTC::Transaction.new
|
7
|
+
script = BTC::PublicKeyAddress.new(hash: "some address".hash160).script
|
8
8
|
inputs.each do
|
9
|
-
tx.add_input(TransactionInput.new(previous_hash: "".sha256, previous_index: 0))
|
9
|
+
tx.add_input(BTC::TransactionInput.new(previous_hash: "".sha256, previous_index: 0))
|
10
10
|
end
|
11
11
|
issues.each do |tuple|
|
12
|
-
tx.add_output(TransactionOutput.new(value: 1, script: script))
|
12
|
+
tx.add_output(BTC::TransactionOutput.new(value: 1, script: script))
|
13
13
|
end
|
14
14
|
qtys = issues.map{|tuple| tuple.first} + transfers.map{|tuple| tuple.first}
|
15
|
-
tx.add_output(AssetMarker.new(quantities: qtys).output)
|
15
|
+
tx.add_output(BTC::AssetMarker.new(quantities: qtys).output)
|
16
16
|
transfers.each do |tuple|
|
17
|
-
tx.add_output(TransactionOutput.new(value: 1, script: script))
|
17
|
+
tx.add_output(BTC::TransactionOutput.new(value: 1, script: script))
|
18
18
|
end
|
19
19
|
|
20
|
-
atx = AssetTransaction.new(transaction: tx)
|
20
|
+
atx = BTC::AssetTransaction.new(transaction: tx)
|
21
21
|
atx.inputs.each_with_index do |ain, i|
|
22
22
|
amount, name = inputs[i]
|
23
23
|
if amount
|
@@ -35,7 +35,7 @@ describe "Verifying transfer outputs" do
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def asset_id(name)
|
38
|
-
name ? AssetID.new(hash: name.hash160) : nil
|
38
|
+
name ? BTC::AssetID.new(hash: name.hash160) : nil
|
39
39
|
end
|
40
40
|
|
41
41
|
def asset_transfer_must_be_verified(inputs: [], issues: [], transfers: [])
|
@@ -67,11 +67,11 @@ describe "Verifying transfer outputs" do
|
|
67
67
|
end
|
68
68
|
|
69
69
|
before do
|
70
|
-
@processor = AssetProcessor.new(source: :NOT_USED)
|
70
|
+
@processor = BTC::AssetProcessor.new(source: :NOT_USED)
|
71
71
|
end
|
72
72
|
|
73
73
|
it "should support transferring asset with overlapping and underlapping" do
|
74
|
-
Diagnostics.current.trace do
|
74
|
+
BTC::Diagnostics.current.trace do
|
75
75
|
asset_transfer_must_be_verified(
|
76
76
|
inputs: [ [100, "A"], [50, "A"], [10, "A"], [30, "B"], [14, "B"] ],
|
77
77
|
issues: [ ],
|
@@ -118,7 +118,7 @@ end
|
|
118
118
|
describe "Verifying a chain of transactions" do
|
119
119
|
|
120
120
|
class InMemoryTxSource
|
121
|
-
include AssetProcessorSource
|
121
|
+
include BTC::AssetProcessorSource
|
122
122
|
def initialize
|
123
123
|
@txs = {}
|
124
124
|
end
|
@@ -134,21 +134,21 @@ describe "Verifying a chain of transactions" do
|
|
134
134
|
end
|
135
135
|
|
136
136
|
def build_asset_transaction(inputs: [], issues: [], transfers: [])
|
137
|
-
tx = Transaction.new
|
138
|
-
script = PublicKeyAddress.new(hash: "some address".hash160).script
|
137
|
+
tx = BTC::Transaction.new
|
138
|
+
script = BTC::PublicKeyAddress.new(hash: "some address".hash160).script
|
139
139
|
inputs.each do
|
140
|
-
tx.add_input(TransactionInput.new(previous_hash: "".sha256, previous_index: 0))
|
140
|
+
tx.add_input(BTC::TransactionInput.new(previous_hash: "".sha256, previous_index: 0))
|
141
141
|
end
|
142
142
|
issues.each do |tuple|
|
143
|
-
tx.add_output(TransactionOutput.new(value: 1, script: script))
|
143
|
+
tx.add_output(BTC::TransactionOutput.new(value: 1, script: script))
|
144
144
|
end
|
145
145
|
qtys = issues.map{|tuple| tuple.first} + transfers.map{|tuple| tuple.first}
|
146
|
-
tx.add_output(AssetMarker.new(quantities: qtys).output)
|
146
|
+
tx.add_output(BTC::AssetMarker.new(quantities: qtys).output)
|
147
147
|
transfers.each do |tuple|
|
148
|
-
tx.add_output(TransactionOutput.new(value: 1, script: script))
|
148
|
+
tx.add_output(BTC::TransactionOutput.new(value: 1, script: script))
|
149
149
|
end
|
150
150
|
|
151
|
-
atx = AssetTransaction.new(transaction: tx)
|
151
|
+
atx = BTC::AssetTransaction.new(transaction: tx)
|
152
152
|
atx.inputs.each_with_index do |ain, i|
|
153
153
|
amount, name = inputs[i]
|
154
154
|
if amount
|
@@ -166,14 +166,14 @@ describe "Verifying a chain of transactions" do
|
|
166
166
|
end
|
167
167
|
|
168
168
|
def asset_id(name)
|
169
|
-
name ? AssetID.new(hash: name.hash160) : nil
|
169
|
+
name ? BTC::AssetID.new(hash: name.hash160) : nil
|
170
170
|
end
|
171
171
|
|
172
172
|
def make_transaction(inputs: [], outputs: [])
|
173
|
-
tx = Transaction.new
|
173
|
+
tx = BTC::Transaction.new
|
174
174
|
inputs.each do |inp|
|
175
175
|
txout = inp
|
176
|
-
tx.add_input(TransactionInput.new(previous_hash: txout.transaction_hash,
|
176
|
+
tx.add_input(BTC::TransactionInput.new(previous_hash: txout.transaction_hash,
|
177
177
|
previous_index: txout.index))
|
178
178
|
end
|
179
179
|
payment_outputs = []
|
@@ -192,25 +192,25 @@ describe "Verifying a chain of transactions" do
|
|
192
192
|
end
|
193
193
|
end
|
194
194
|
issue_outputs.each do |out|
|
195
|
-
tx.add_output(TransactionOutput.new(value: out[:btc], script: Address.parse(out[:address]).script))
|
195
|
+
tx.add_output(BTC::TransactionOutput.new(value: out[:btc], script: BTC::Address.parse(out[:address]).script))
|
196
196
|
end
|
197
197
|
if qtys.size > 0
|
198
|
-
tx.add_output(AssetMarker.new(quantities: qtys).output)
|
198
|
+
tx.add_output(BTC::AssetMarker.new(quantities: qtys).output)
|
199
199
|
end
|
200
200
|
(transfer_outputs + payment_outputs).each do |out|
|
201
|
-
tx.add_output(TransactionOutput.new(value: out[:btc], script: Address.parse(out[:address]).script))
|
201
|
+
tx.add_output(BTC::TransactionOutput.new(value: out[:btc], script: BTC::Address.parse(out[:address]).script))
|
202
202
|
end
|
203
203
|
tx
|
204
204
|
end
|
205
205
|
|
206
206
|
before do
|
207
207
|
@source = InMemoryTxSource.new
|
208
|
-
@processor = AssetProcessor.new(source: @source)
|
208
|
+
@processor = BTC::AssetProcessor.new(source: @source)
|
209
209
|
end
|
210
210
|
|
211
211
|
it "should verify a simple issuance chain (parent + child transaction)" do
|
212
|
-
issue_address = Address.parse("3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX")
|
213
|
-
asset_id = AssetID.new(script: issue_address.script)
|
212
|
+
issue_address = BTC::Address.parse("3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX")
|
213
|
+
asset_id = BTC::AssetID.new(script: issue_address.script)
|
214
214
|
tx1 = make_transaction(outputs: [
|
215
215
|
{btc: 10_000, address: "3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX"}
|
216
216
|
])
|
@@ -224,9 +224,9 @@ describe "Verifying a chain of transactions" do
|
|
224
224
|
]
|
225
225
|
)
|
226
226
|
@source.add_transaction(tx1)
|
227
|
-
atx = AssetTransaction.new(transaction: tx2)
|
227
|
+
atx = BTC::AssetTransaction.new(transaction: tx2)
|
228
228
|
|
229
|
-
Diagnostics.current.trace do
|
229
|
+
BTC::Diagnostics.current.trace do
|
230
230
|
@processor.verify_asset_transaction(atx).must_equal(true)
|
231
231
|
atx.outputs.map {|aout|
|
232
232
|
[aout.verified?, aout.value, aout.asset_id]
|
@@ -240,8 +240,8 @@ describe "Verifying a chain of transactions" do
|
|
240
240
|
|
241
241
|
|
242
242
|
it "should verify a transfer chain" do
|
243
|
-
issue_address = Address.parse("3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX")
|
244
|
-
asset_id = AssetID.new(script: issue_address.script)
|
243
|
+
issue_address = BTC::Address.parse("3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX")
|
244
|
+
asset_id = BTC::AssetID.new(script: issue_address.script)
|
245
245
|
tx1 = make_transaction(outputs: [
|
246
246
|
{btc: 10_000, address: "3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX"}
|
247
247
|
])
|
@@ -277,9 +277,9 @@ describe "Verifying a chain of transactions" do
|
|
277
277
|
@source.add_transaction(tx1)
|
278
278
|
@source.add_transaction(tx2)
|
279
279
|
@source.add_transaction(tx3)
|
280
|
-
atx = AssetTransaction.new(transaction: tx4)
|
280
|
+
atx = BTC::AssetTransaction.new(transaction: tx4)
|
281
281
|
|
282
|
-
Diagnostics.current.trace do
|
282
|
+
BTC::Diagnostics.current.trace do
|
283
283
|
result = @processor.verify_asset_transaction(atx)
|
284
284
|
result.must_equal(true)
|
285
285
|
atx.outputs.map {|aout|
|
@@ -293,8 +293,8 @@ describe "Verifying a chain of transactions" do
|
|
293
293
|
end
|
294
294
|
|
295
295
|
it "should fail to verify an incorrect transfer chain" do
|
296
|
-
issue_address = Address.parse("3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX")
|
297
|
-
asset_id = AssetID.new(script: issue_address.script)
|
296
|
+
issue_address = BTC::Address.parse("3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX")
|
297
|
+
asset_id = BTC::AssetID.new(script: issue_address.script)
|
298
298
|
tx1 = make_transaction(outputs: [
|
299
299
|
{btc: 10_000, address: "3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX"}
|
300
300
|
])
|
@@ -331,9 +331,9 @@ describe "Verifying a chain of transactions" do
|
|
331
331
|
@source.add_transaction(tx1)
|
332
332
|
@source.add_transaction(tx2)
|
333
333
|
@source.add_transaction(tx3)
|
334
|
-
atx = AssetTransaction.new(transaction: tx4)
|
334
|
+
atx = BTC::AssetTransaction.new(transaction: tx4)
|
335
335
|
|
336
|
-
#Diagnostics.current.trace do
|
336
|
+
#BTC::Diagnostics.current.trace do
|
337
337
|
result = @processor.verify_asset_transaction(atx)
|
338
338
|
result.must_equal(false)
|
339
339
|
atx.outputs.map {|aout|
|
@@ -347,10 +347,10 @@ describe "Verifying a chain of transactions" do
|
|
347
347
|
end
|
348
348
|
|
349
349
|
it "should verify a transfer chain with multiple assets" do
|
350
|
-
issue_address1 = Address.parse("3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX")
|
351
|
-
issue_address2 = Address.parse("3GkKDgJAWJnizg6Tz7DBM8uDtdHtrUkQ2X")
|
352
|
-
asset_id1 = AssetID.new(script: issue_address1.script)
|
353
|
-
asset_id2 = AssetID.new(script: issue_address2.script)
|
350
|
+
issue_address1 = BTC::Address.parse("3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX")
|
351
|
+
issue_address2 = BTC::Address.parse("3GkKDgJAWJnizg6Tz7DBM8uDtdHtrUkQ2X")
|
352
|
+
asset_id1 = BTC::AssetID.new(script: issue_address1.script)
|
353
|
+
asset_id2 = BTC::AssetID.new(script: issue_address2.script)
|
354
354
|
|
355
355
|
tx1 = make_transaction(outputs: [
|
356
356
|
{btc: 10_000, address: issue_address1}
|
@@ -472,9 +472,9 @@ describe "Verifying a chain of transactions" do
|
|
472
472
|
@source.add_transaction(tx7)
|
473
473
|
@source.add_transaction(tx8)
|
474
474
|
@source.add_transaction(tx9)
|
475
|
-
atx = AssetTransaction.new(transaction: tx_final)
|
475
|
+
atx = BTC::AssetTransaction.new(transaction: tx_final)
|
476
476
|
|
477
|
-
Diagnostics.current.trace do
|
477
|
+
BTC::Diagnostics.current.trace do
|
478
478
|
result = @processor.verify_asset_transaction(atx)
|
479
479
|
result.must_equal(true)
|
480
480
|
|
@@ -496,10 +496,10 @@ describe "Verifying a chain of transactions" do
|
|
496
496
|
end
|
497
497
|
|
498
498
|
it "should fail to verify a mix of assets in one output" do
|
499
|
-
issue_address1 = Address.parse("3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX")
|
500
|
-
issue_address2 = Address.parse("3GkKDgJAWJnizg6Tz7DBM8uDtdHtrUkQ2X")
|
501
|
-
asset_id1 = AssetID.new(script: issue_address1.script)
|
502
|
-
asset_id2 = AssetID.new(script: issue_address2.script)
|
499
|
+
issue_address1 = BTC::Address.parse("3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX")
|
500
|
+
issue_address2 = BTC::Address.parse("3GkKDgJAWJnizg6Tz7DBM8uDtdHtrUkQ2X")
|
501
|
+
asset_id1 = BTC::AssetID.new(script: issue_address1.script)
|
502
|
+
asset_id2 = BTC::AssetID.new(script: issue_address2.script)
|
503
503
|
|
504
504
|
tx1 = make_transaction(outputs: [
|
505
505
|
{btc: 10_000, address: issue_address1}
|
@@ -549,7 +549,7 @@ describe "Verifying a chain of transactions" do
|
|
549
549
|
@source.add_transaction(tx2)
|
550
550
|
@source.add_transaction(tx3)
|
551
551
|
@source.add_transaction(tx4)
|
552
|
-
atx = AssetTransaction.new(transaction: tx5)
|
552
|
+
atx = BTC::AssetTransaction.new(transaction: tx5)
|
553
553
|
|
554
554
|
#Diagnostics.current.trace do
|
555
555
|
result = @processor.verify_asset_transaction(atx)
|