bitcoin-ruby 0.0.10 → 0.0.11

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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/COPYING +1 -1
  4. data/Gemfile.lock +9 -10
  5. data/README.rdoc +1 -1
  6. data/Rakefile +4 -2
  7. data/lib/bitcoin.rb +4 -2
  8. data/lib/bitcoin/bloom_filter.rb +125 -0
  9. data/lib/bitcoin/builder.rb +34 -9
  10. data/lib/bitcoin/ext_key.rb +191 -0
  11. data/lib/bitcoin/ffi/openssl.rb +1 -1
  12. data/lib/bitcoin/key.rb +6 -4
  13. data/lib/bitcoin/protocol.rb +13 -11
  14. data/lib/bitcoin/protocol/block.rb +38 -2
  15. data/lib/bitcoin/protocol/parser.rb +8 -0
  16. data/lib/bitcoin/protocol/partial_merkle_tree.rb +61 -0
  17. data/lib/bitcoin/protocol/script_witness.rb +31 -0
  18. data/lib/bitcoin/protocol/tx.rb +170 -10
  19. data/lib/bitcoin/protocol/txin.rb +8 -0
  20. data/lib/bitcoin/protocol/version.rb +2 -1
  21. data/lib/bitcoin/script.rb +58 -8
  22. data/lib/bitcoin/version.rb +1 -1
  23. data/spec/bitcoin/bloom_filter_spec.rb +23 -0
  24. data/spec/bitcoin/builder_spec.rb +12 -0
  25. data/spec/bitcoin/ext_key_spec.rb +180 -0
  26. data/spec/bitcoin/fixtures/filteredblock-0.bin +0 -0
  27. data/spec/bitcoin/fixtures/rawblock-testnet-1151351.bin +0 -0
  28. data/spec/bitcoin/fixtures/rawtx-p2wpkh.bin +0 -0
  29. data/spec/bitcoin/fixtures/rawtx-p2wpkh.json +67 -0
  30. data/spec/bitcoin/fixtures/tx-0a6a357e2f7796444e02638749d9611c008b253fb55f5dc88b739b230ed0c4c3.json +139 -0
  31. data/spec/bitcoin/fixtures/tx-28204cad1d7fc1d199e8ef4fa22f182de6258a3eaafe1bbe56ebdcacd3069a5f.json +34 -0
  32. data/spec/bitcoin/protocol/bip143_spec.rb +116 -0
  33. data/spec/bitcoin/protocol/block_spec.rb +27 -0
  34. data/spec/bitcoin/protocol/partial_merkle_tree_spec.rb +38 -0
  35. data/spec/bitcoin/protocol/tx_spec.rb +134 -1
  36. data/spec/bitcoin/script/script_spec.rb +53 -2
  37. metadata +27 -3
@@ -0,0 +1,139 @@
1
+ {
2
+ "hash": "0a6a357e2f7796444e02638749d9611c008b253fb55f5dc88b739b230ed0c4c3",
3
+ "ver": 1,
4
+ "vin_sz": 17,
5
+ "vout_sz": 2,
6
+ "lock_time": 0,
7
+ "size": 2585,
8
+ "in": [
9
+ {
10
+ "prev_out": {
11
+ "hash": "643e5f4e66373a57251fb173151e838ccd27d279aca882997e005016bb53d5aa",
12
+ "n": 0
13
+ },
14
+ "scriptSig": "304402205438cedd30ee828b0938a863e08d810526123746c1f4abee5b7bc2312373450c02207f26914f4275f8f0040ab3375bacc8c5d610c095db8ed0785de5dc57456591a601 0391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210"
15
+ },
16
+ {
17
+ "prev_out": {
18
+ "hash": "28e0fdd185542f2c6ea19030b0796051e7772b6026dd5ddccd7a2f93b73e6fc2",
19
+ "n": 0
20
+ },
21
+ "scriptSig": "3045022100f81d98c1de9bb61063a5e6671d191b400fda3a07d886e663799760393405439d0220234303c9af4bad3d665f00277fe70cdd26cd56679f114a40d9107249d29c979401 0391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210"
22
+ },
23
+ {
24
+ "prev_out": {
25
+ "hash": "f0a130a84912d03c1d284974f563c5949ac13f8342b8112edff52971599e6a45",
26
+ "n": 0
27
+ },
28
+ "scriptSig": "304402202310b00924794ef68a8f09564fd0bb128838c66bc45d1a3f95c5cab52680f166022039fc99138c29f6c434012b14aca651b1c02d97324d6bd9dd0ffced0782c7e3bd01 0391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210"
29
+ },
30
+ {
31
+ "prev_out": {
32
+ "hash": "0e53ec5dfb2cb8a71fec32dc9a634a35b7e24799295ddd5278217822e0b31f57",
33
+ "n": 0
34
+ },
35
+ "scriptSig": "3045022100d276251f1f4479d8521269ec8b1b45c6f0e779fcf1658ec627689fa8a55a9ca50220212a1e307e6182479818c543e1b47d62e4fc3ce6cc7fc78183c7071d245839df01 0391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210"
36
+ },
37
+ {
38
+ "prev_out": {
39
+ "hash": "381de9b9ae1a94d9c17f6a08ef9d341a5ce29e2e60c36a52d333ff6203e58d5d",
40
+ "n": 1
41
+ },
42
+ "scriptSig": "30450221008768eeb1240451c127b88d89047dd387d13357ce5496726fc7813edc6acd55ac022015187451c3fb66629af38fdb061dfb39899244b15c45e4a7ccc31064a059730d01 0391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210"
43
+ },
44
+ {
45
+ "prev_out": {
46
+ "hash": "f320832a9d2e2452af63154bc687493484a0e7745ebd3aaf9ca19eb80834ad60",
47
+ "n": 0
48
+ },
49
+ "scriptSig": "30450221009be4261ec050ebf33fa3d47248c7086e4c247cafbb100ea7cee4aa81cd1383f5022008a70d6402b153560096c849d7da6fe61c771a60e41ff457aac30673ceceafee01 0391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210"
50
+ },
51
+ {
52
+ "prev_out": {
53
+ "hash": "de0411a1e97484a2804ff1dbde260ac19de841bebad1880c782941aca883b4e9",
54
+ "n": 1
55
+ },
56
+ "scriptSig": "30450221009bc40eee321b39b5dc26883f79cd1f5a226fc6eed9e79e21d828f4c23190c57e022078182fd6086e265589105023d9efa4cba83f38c674a499481bd54eee196b033f01 0391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210"
57
+ },
58
+ {
59
+ "prev_out": {
60
+ "hash": "3b8b2f8efceb60ba78ca8bba206a137f14cb5ea4035e761ee204302d46b98de2",
61
+ "n": 0
62
+ },
63
+ "scriptSig": "304402200fb572b7c6916515452e370c2b6f97fcae54abe0793d804a5a53e419983fae1602205191984b6928bf4a1e25b00e5b5569a0ce1ecb82db2dea75fe4378673b53b9e801 0391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210"
64
+ },
65
+ {
66
+ "prev_out": {
67
+ "hash": "54ffff182965ed0957dba1239c27164ace5a73c9b62a660c74b7b7f15ff61e7a",
68
+ "n": 1
69
+ },
70
+ "scriptSig": "304402206bc218a925f7280d615c8ea4f0131a9f26e7fc64cff6eeeb44edb88aba14f1910220779d5d67231bc2d2d93c3c5ab74dcd193dd3d04023e58709ad7ffbf95161be6201 0391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210"
71
+ },
72
+ {
73
+ "prev_out": {
74
+ "hash": "bafd65e3c7f3f9fdfdc1ddb026131b278c3be1af90a4a6ffa78c4658f9ec0c85",
75
+ "n": 0
76
+ },
77
+ "scriptSig": "3044022047df98cc26bd2bfdc5b2b97c27aead78a214810ff023e721339292d5ce50823d02205fe99dc5f667908974dae40cc7a9475af7fa6671ba44f64a00fcd01fa12ab52301 02ca46fa75454650afba1784bc7b079d687e808634411e4beff1f70e44596308a1"
78
+ },
79
+ {
80
+ "prev_out": {
81
+ "hash": "a5e899dddb28776ea9ddac0a502316d53a4a3fca607c72f66c470e0412e34086",
82
+ "n": 0
83
+ },
84
+ "scriptSig": "304402205566aa84d3d84226d5ab93e6f253b57b3ef37eb09bb73441dae35de86271352a02206ee0b7f800f73695a2073a2967c9ad99e19f6ddf18ce877adf822e408ba9291e01 0391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210"
85
+ },
86
+ {
87
+ "prev_out": {
88
+ "hash": "7a1de137cbafb5c70405455c49c5104ca3057a1f1243e6563bb9245c9c88c191",
89
+ "n": 0
90
+ },
91
+ "scriptSig": "3045022100df61d45bbaa4571cdd6c5c822cba458cdc55285cdf7ba9cd5bb9fc18096deb9102201caf8c771204df7fd7c920c4489da7bc3a60e1d23c1a97e237c63afe53250b4a01 0391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210"
92
+ },
93
+ {
94
+ "prev_out": {
95
+ "hash": "26aa6e6d8b9e49bb0630aac301db6757c02e3619feb4ee0eea81eb1672947024",
96
+ "n": 1
97
+ },
98
+ "scriptSig": "3044022031501a0b2846b8822a32b9947b058d89d32fc758e009fc2130c2e5effc925af70220574ef3c9e350cef726c75114f0701fd8b188c6ec5f84adce0ed5c393828a5ae001 0391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210"
99
+ },
100
+ {
101
+ "prev_out": {
102
+ "hash": "402b2c02411720bf409eff60d05adad684f135838962823f3614cc657dd7bc0a",
103
+ "n": 1
104
+ },
105
+ "scriptSig": "3045022100a6ac110802b699f9a2bff0eea252d32e3d572b19214d49d8bb7405efa2af28f1022033b7563eb595f6d7ed7ec01734e17b505214fe0851352ed9c3c8120d53268e9a01 0391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210"
106
+ },
107
+ {
108
+ "prev_out": {
109
+ "hash": "7d037ceb2ee0dc03e82f17be7935d238b35d1deabf953a892a4507bfbeeb3ba4",
110
+ "n": 1
111
+ },
112
+ "scriptSig": "3045022100ebc77ed0f11d15fe630fe533dc350c2ddc1c81cfeb81d5a27d0587163f58a28c02200983b2a32a1014bab633bfc9258083ac282b79566b6b3fa45c1e6758610444f401 0391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210"
113
+ },
114
+ {
115
+ "prev_out": {
116
+ "hash": "6c1d56f31b2de4bfc6aaea28396b333102b1f600da9c6d6149e96ca43f1102b1",
117
+ "n": 1
118
+ },
119
+ "scriptSig": "3044022010f8731929a55c1c49610722e965635529ed895b2292d781b183d465799906b20220098359adcbc669cd4b294cc129b110fe035d2f76517248f4b7129f3bf793d07f01 0391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210"
120
+ },
121
+ {
122
+ "prev_out": {
123
+ "hash": "b4112b8f900a7ca0c8b0e7c4dfad35c6be5f6be46b3458974988e1cdb2fa61b8",
124
+ "n": 0
125
+ },
126
+ "scriptSig": "304402207328142bb02ef5d6496a210300f4aea71f67683b842fa3df32cae6c88b49a9bb022020f56ddff5042260cfda2c9f39b7dec858cc2f4a76a987cd2dc25945b04e15fe01 0391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210"
127
+ }
128
+ ],
129
+ "out": [
130
+ {
131
+ "value": "4.00057456",
132
+ "scriptPubKey": "OP_DUP OP_HASH160 4a5fba237213a062f6f57978f796390bdcf8d015 OP_EQUALVERIFY OP_CHECKSIG"
133
+ },
134
+ {
135
+ "value": "400.00000000",
136
+ "scriptPubKey": "OP_DUP OP_HASH160 5be32612930b8323add2212a4ec03c1562084f84 OP_EQUALVERIFY OP_CHECKSIG"
137
+ }
138
+ ]
139
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "hash": "28204cad1d7fc1d199e8ef4fa22f182de6258a3eaafe1bbe56ebdcacd3069a5f",
3
+ "ver": 1,
4
+ "vin_sz": 2,
5
+ "vout_sz": 2,
6
+ "lock_time": 0,
7
+ "size": 389,
8
+ "in": [
9
+ {
10
+ "prev_out": {
11
+ "hash": "35288d269cee1941eaebb2ea85e32b42cdb2b04284a56d8b14dcc3f5c65d6055",
12
+ "n": 0
13
+ },
14
+ "scriptSig": "3045022100aa46504baa86df8a33b1192b1b9367b4d729dc41e389f2c04f3e5c7f0559aae702205e82253a54bf5c4f65b7428551554b2045167d6d206dfe6a2e198127d3f7df1501"
15
+ },
16
+ {
17
+ "prev_out": {
18
+ "hash": "35288d269cee1941eaebb2ea85e32b42cdb2b04284a56d8b14dcc3f5c65d6055",
19
+ "n": 1
20
+ },
21
+ "scriptSig": "304402202329484c35fa9d6bb32a55a70c0982f606ce0e3634b69006138683bcd12cbb6602200c28feb1e2555c3210f1dddb299738b4ff8bbe9667b68cb8764b5ac17b7adf0001"
22
+ }
23
+ ],
24
+ "out": [
25
+ {
26
+ "value": "1.00000000",
27
+ "scriptPubKey": "046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0c OP_CHECKSIG"
28
+ },
29
+ {
30
+ "value": "24.00000000",
31
+ "scriptPubKey": "044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45af OP_CHECKSIG"
32
+ }
33
+ ]
34
+ }
@@ -0,0 +1,116 @@
1
+ # encoding: ascii-8bit
2
+
3
+ require_relative '../spec_helper.rb'
4
+
5
+ include Bitcoin::Protocol
6
+
7
+ # this spec requires secp256k1 library
8
+ describe 'BIP143 spec' do
9
+
10
+ # https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#Example
11
+
12
+ it 'Native P2WPKH' do
13
+ tx = Tx.new('0100000002fff7f7881a8099afa6940d42d1e7f6362bec38171ea3edf433541db4e4ad969f0000000000eeffffffef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a0100000000ffffffff02202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac9093510d000000001976a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac11000000'.htb)
14
+
15
+ sig_hash0 = tx.signature_hash_for_input(0, '2103c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432ac'.htb)
16
+ sig0 = Bitcoin::Secp256k1.sign(sig_hash0, 'bbc27228ddcb9209d7fd6f36b02f7dfa6252af40bb2f1cbc7a557da8027ff866'.htb) + [Tx::SIGHASH_TYPE[:all]].pack("C")
17
+
18
+ tx.in[0].script_sig = Bitcoin::Script.new(Bitcoin::Script.pack_pushdata(sig0)).to_payload
19
+
20
+ sig_hash1 = tx.signature_hash_for_witness_input(1, '00141d0f172a0ecb48aee1be1f2687d2963ae33f71a1'.htb, 600000000)
21
+ sig1 = Bitcoin::Secp256k1.sign(sig_hash1, '619c335025c7f4012e556c2a58b2506e30b8511b53ade95ea316fd8c3286feb9'.htb) + [Tx::SIGHASH_TYPE[:all]].pack("C")
22
+
23
+ tx.in[1].script_witness.stack << sig1
24
+ tx.in[1].script_witness.stack << '025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357'.htb
25
+
26
+ tx.to_witness_payload.bth.should == '01000000000102fff7f7881a8099afa6940d42d1e7f6362bec38171ea3edf433541db4e4ad969f00000000494830450221008b9d1dc26ba6a9cb62127b02742fa9d754cd3bebf337f7a55d114c8e5cdd30be022040529b194ba3f9281a99f2b1c0a19c0489bc22ede944ccf4ecbab4cc618ef3ed01eeffffffef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a0100000000ffffffff02202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac9093510d000000001976a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac000247304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee0121025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee635711000000'
27
+ end
28
+
29
+ it 'P2SH-P2WPKH' do
30
+ redeem_script = '001479091972186c449eb1ded22b78e40d009bdf0089'
31
+ tx = Tx.new('0100000001db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a54770100000000feffffff02b8b4eb0b000000001976a914a457b684d7f0d539a46a45bbc043f35b59d0d96388ac0008af2f000000001976a914fd270b1ee6abcaea97fea7ad0402e8bd8ad6d77c88ac92040000'.htb)
32
+
33
+ tx.in[0].script_sig = Bitcoin::Script.new(Bitcoin::Script.pack_pushdata(redeem_script.htb)).to_payload
34
+
35
+ sig_hash = tx.signature_hash_for_witness_input(0, redeem_script.htb, 1000000000)
36
+ sig = Bitcoin::Secp256k1.sign(sig_hash, 'eb696a065ef48a2192da5b28b694f87544b30fae8327c4510137a922f32c6dcf'.htb) + [Tx::SIGHASH_TYPE[:all]].pack("C")
37
+
38
+ tx.in[0].script_witness.stack << sig
39
+ tx.in[0].script_witness.stack << '03ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a26873'.htb
40
+
41
+ tx.to_witness_payload.bth.should == '01000000000101db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a5477010000001716001479091972186c449eb1ded22b78e40d009bdf0089feffffff02b8b4eb0b000000001976a914a457b684d7f0d539a46a45bbc043f35b59d0d96388ac0008af2f000000001976a914fd270b1ee6abcaea97fea7ad0402e8bd8ad6d77c88ac02473044022047ac8e878352d3ebbde1c94ce3a10d057c24175747116f8288e5d794d12d482f0220217f36a485cae903c713331d877c1f64677e3622ad4010726870540656fe9dcb012103ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a2687392040000'
42
+ end
43
+
44
+ it 'Native P2WSH' do
45
+ # <026dccc749adc2a9d0d89497ac511f760f45c47dc5ed9cf352a58ac706453880ae> CHECKSIGVERIFY CODESEPERATOR <0255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465> CHECKSIG
46
+ # this script needs two privkey signature
47
+ witness_script = Bitcoin::Script.new('21026dccc749adc2a9d0d89497ac511f760f45c47dc5ed9cf352a58ac706453880aeadab210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac'.htb)
48
+ script_pubkey = '00205d1b56b63d714eebe542309525f484b7e9d6f686b3781b6f61ef925d66d6f6a0'
49
+
50
+ tx = Tx.new('0100000002fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e0000000000ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac00000000'.htb)
51
+
52
+ sig_hash0 = tx.signature_hash_for_input(0, '21036d5c20fa14fb2f635474c1dc4ef5909d4568e5569b79fc94d3448486e14685f8ac'.htb)
53
+ sig0 = Bitcoin::Secp256k1.sign(sig_hash0, 'b8f28a772fccbf9b4f58a4f027e07dc2e35e7cd80529975e292ea34f84c4580c'.htb) + [Tx::SIGHASH_TYPE[:all]].pack("C")
54
+ tx.in[0].script_sig = Bitcoin::Script.new(Bitcoin::Script.pack_pushdata(sig0)).to_payload
55
+
56
+ sig_hash1 = tx.signature_hash_for_witness_input(1, script_pubkey.htb, 4900000000, witness_script.to_payload, Tx::SIGHASH_TYPE[:single])
57
+ sig1 = Bitcoin::Secp256k1.sign(sig_hash1, '8e02b539b1500aa7c81cf3fed177448a546f19d2be416c0c61ff28e577d8d0cd'.htb) + [Tx::SIGHASH_TYPE[:single]].pack("C")
58
+
59
+ sig_hash2 = tx.signature_hash_for_witness_input(1, script_pubkey.htb, 4900000000, witness_script.to_payload, Tx::SIGHASH_TYPE[:single], 1)
60
+ sig2 = Bitcoin::Secp256k1.sign(sig_hash2, '86bf2ed75935a0cbef03b89d72034bb4c189d381037a5ac121a70016db8896ec'.htb) + [Tx::SIGHASH_TYPE[:single]].pack("C")
61
+
62
+ tx.in[1].script_witness.stack << sig2
63
+ tx.in[1].script_witness.stack << sig1
64
+ tx.in[1].script_witness.stack << witness_script.to_payload
65
+
66
+ tx.to_witness_payload.bth.should == '01000000000102fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e000000004847304402200af4e47c9b9629dbecc21f73af989bdaa911f7e6f6c2e9394588a3aa68f81e9902204f3fcf6ade7e5abb1295b6774c8e0abd94ae62217367096bc02ee5e435b67da201ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac000347304402200de66acf4527789bfda55fc5459e214fa6083f936b430a762c629656216805ac0220396f550692cd347171cbc1ef1f51e15282e837bb2b30860dc77c8f78bc8501e503473044022027dc95ad6b740fe5129e7e62a75dd00f291a2aeb1200b84b09d9e3789406b6c002201a9ecd315dd6a0e632ab20bbb98948bc0c6fb204f2c286963bb48517a7058e27034721026dccc749adc2a9d0d89497ac511f760f45c47dc5ed9cf352a58ac706453880aeadab210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac00000000'
67
+ end
68
+
69
+
70
+ it 'P2SH-P2WSH' do
71
+ redeem_script = '0020a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54'
72
+ # 6-of-6 multisig
73
+ witness_script = Bitcoin::Script.new('56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae'.htb)
74
+
75
+ tx = Tx.new('010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000'.htb)
76
+ tx.in[0].script_sig = Bitcoin::Script.new(Bitcoin::Script.pack_pushdata(redeem_script.htb)).to_payload
77
+
78
+
79
+ tx.in[0].script_witness.stack << ''
80
+
81
+ sig_hash0 = tx.signature_hash_for_witness_input(0, redeem_script.htb, 987654321, witness_script.to_payload)
82
+ sig0 = Bitcoin::Secp256k1.sign(sig_hash0, '730fff80e1413068a05b57d6a58261f07551163369787f349438ea38ca80fac6'.htb) + [Tx::SIGHASH_TYPE[:all]].pack("C")
83
+ sig0.bth.should == '304402206ac44d672dac41f9b00e28f4df20c52eeb087207e8d758d76d92c6fab3b73e2b0220367750dbbe19290069cba53d096f44530e4f98acaa594810388cf7409a1870ce01'
84
+ tx.in[0].script_witness.stack << sig0
85
+
86
+ sig_hash1 = tx.signature_hash_for_witness_input(0, redeem_script.htb, 987654321, witness_script.to_payload, Tx::SIGHASH_TYPE[:none])
87
+ sig1 = Bitcoin::Secp256k1.sign(sig_hash1, '11fa3d25a17cbc22b29c44a484ba552b5a53149d106d3d853e22fdd05a2d8bb3'.htb) + [Tx::SIGHASH_TYPE[:none]].pack("C")
88
+ sig1.bth.should == '3044022068c7946a43232757cbdf9176f009a928e1cd9a1a8c212f15c1e11ac9f2925d9002205b75f937ff2f9f3c1246e547e54f62e027f64eefa2695578cc6432cdabce271502'
89
+ tx.in[0].script_witness.stack << sig1
90
+
91
+ sig_hash2 = tx.signature_hash_for_witness_input(0, redeem_script.htb, 987654321, witness_script.to_payload, Tx::SIGHASH_TYPE[:single])
92
+ sig2 = Bitcoin::Secp256k1.sign(sig_hash2, '77bf4141a87d55bdd7f3cd0bdccf6e9e642935fec45f2f30047be7b799120661'.htb) + [Tx::SIGHASH_TYPE[:single]].pack("C")
93
+ sig2.bth.should == '3044022059ebf56d98010a932cf8ecfec54c48e6139ed6adb0728c09cbe1e4fa0915302e022007cd986c8fa870ff5d2b3a89139c9fe7e499259875357e20fcbb15571c76795403'
94
+ tx.in[0].script_witness.stack << sig2
95
+
96
+ sig_hash3 = tx.signature_hash_for_witness_input(0, redeem_script.htb, 987654321, witness_script.to_payload, Tx::SIGHASH_TYPE[:all] | Tx::SIGHASH_TYPE[:anyonecanpay])
97
+ sig3 = Bitcoin::Secp256k1.sign(sig_hash3, '14af36970f5025ea3e8b5542c0f8ebe7763e674838d08808896b63c3351ffe49'.htb) + [Tx::SIGHASH_TYPE[:all] | Tx::SIGHASH_TYPE[:anyonecanpay]].pack("C")
98
+ sig3.bth.should == '3045022100fbefd94bd0a488d50b79102b5dad4ab6ced30c4069f1eaa69a4b5a763414067e02203156c6a5c9cf88f91265f5a942e96213afae16d83321c8b31bb342142a14d16381'
99
+ tx.in[0].script_witness.stack << sig3
100
+
101
+ sig_hash4 = tx.signature_hash_for_witness_input(0, redeem_script.htb, 987654321, witness_script.to_payload, Tx::SIGHASH_TYPE[:none] | Tx::SIGHASH_TYPE[:anyonecanpay])
102
+ sig4 = Bitcoin::Secp256k1.sign(sig_hash4, 'fe9a95c19eef81dde2b95c1284ef39be497d128e2aa46916fb02d552485e0323'.htb) + [Tx::SIGHASH_TYPE[:none] | Tx::SIGHASH_TYPE[:anyonecanpay]].pack("C")
103
+ sig4.bth.should == '3045022100a5263ea0553ba89221984bd7f0b13613db16e7a70c549a86de0cc0444141a407022005c360ef0ae5a5d4f9f2f87a56c1546cc8268cab08c73501d6b3be2e1e1a8a0882'
104
+ tx.in[0].script_witness.stack << sig4
105
+
106
+ sig_hash5 = tx.signature_hash_for_witness_input(0, redeem_script.htb, 987654321, witness_script.to_payload, Tx::SIGHASH_TYPE[:single] | Tx::SIGHASH_TYPE[:anyonecanpay])
107
+ sig5 = Bitcoin::Secp256k1.sign(sig_hash5, '428a7aee9f0c2af0cd19af3cf1c78149951ea528726989b2e83e4778d2c3f890'.htb) + [Tx::SIGHASH_TYPE[:single] | Tx::SIGHASH_TYPE[:anyonecanpay]].pack("C")
108
+ sig5.bth.should == '30440220525406a1482936d5a21888260dc165497a90a15669636d8edca6b9fe490d309c022032af0c646a34a44d1f4576bf6a4a74b67940f8faa84c7df9abe12a01a11e2b4783'
109
+ tx.in[0].script_witness.stack << sig5
110
+
111
+ tx.in[0].script_witness.stack << witness_script.to_payload
112
+
113
+ tx.to_witness_payload.bth.should == '0100000000010136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000023220020a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac080047304402206ac44d672dac41f9b00e28f4df20c52eeb087207e8d758d76d92c6fab3b73e2b0220367750dbbe19290069cba53d096f44530e4f98acaa594810388cf7409a1870ce01473044022068c7946a43232757cbdf9176f009a928e1cd9a1a8c212f15c1e11ac9f2925d9002205b75f937ff2f9f3c1246e547e54f62e027f64eefa2695578cc6432cdabce271502473044022059ebf56d98010a932cf8ecfec54c48e6139ed6adb0728c09cbe1e4fa0915302e022007cd986c8fa870ff5d2b3a89139c9fe7e499259875357e20fcbb15571c76795403483045022100fbefd94bd0a488d50b79102b5dad4ab6ced30c4069f1eaa69a4b5a763414067e02203156c6a5c9cf88f91265f5a942e96213afae16d83321c8b31bb342142a14d16381483045022100a5263ea0553ba89221984bd7f0b13613db16e7a70c549a86de0cc0444141a407022005c360ef0ae5a5d4f9f2f87a56c1546cc8268cab08c73501d6b3be2e1e1a8a08824730440220525406a1482936d5a21888260dc165497a90a15669636d8edca6b9fe490d309c022032af0c646a34a44d1f4576bf6a4a74b67940f8faa84c7df9abe12a01a11e2b4783cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae00000000'
114
+ end
115
+
116
+ end
@@ -20,6 +20,10 @@ describe 'Bitcoin::Protocol::Block' do
20
20
  # block 26478: 000000000214a3f06ee99a033a7f2252762d6a18d27c3cd8c8fe2278190da9f3
21
21
  'testnet-26478' => fixtures_file('rawblock-testnet-26478.bin'),
22
22
  'testnet-265322' => fixtures_file('rawblock-testnet-265322.bin'),
23
+ # block 1151351: 000000000000031525003c4e061fd2e5ce5f4fda6121a836e66f70ec2df621de
24
+ 'testnet-1151351' => fixtures_file('rawblock-testnet-1151351.bin'),
25
+ # block 100005: 000000000000dab0130bbcc991d3d7ae6b81aa6f50a798888dfe62337458dc45
26
+ 'filtered-0' => fixtures_file('filteredblock-0.bin'),
23
27
  }
24
28
  end
25
29
 
@@ -42,6 +46,10 @@ describe 'Bitcoin::Protocol::Block' do
42
46
  block.parse_data(@blocks['0'] + "AAAA").should == "AAAA"
43
47
  block.header_info[7].should == 215
44
48
  block.to_payload.should == @blocks['0']
49
+
50
+ # parse block which includes segwit tx
51
+ block = Block.new(@blocks['testnet-1151351'])
52
+ block.mrkl_root.should == 'e4bbfc681f2bf0ed5fe13a01f5f82bd1844d406fe793a7ec590151f4ea4060d5'.htb.reverse
45
53
  end
46
54
 
47
55
  it '#hash' do
@@ -54,6 +62,10 @@ describe 'Bitcoin::Protocol::Block' do
54
62
  @block.tx[0].hash.should == "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098"
55
63
  end
56
64
 
65
+ it "#tx_hashes" do
66
+ @block.tx_hashes.should == ["0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098"]
67
+ end
68
+
57
69
  it '#to_hash' do
58
70
  @block.to_hash.keys.should == ["hash", "ver", "prev_block", "mrkl_root", "time", "bits", "nonce", "n_tx", "size", "tx", "mrkl_tree"]
59
71
  end
@@ -135,6 +147,21 @@ describe 'Bitcoin::Protocol::Block' do
135
147
 
136
148
  end
137
149
 
150
+ #
151
+ # following test cases are borrowed from
152
+ # https://github.com/bitcoinj/bitcoinj/blob/master/core/src/test/java/org/bitcoinj/core/FilteredBlockAndPartialMerkleTreeTests.java
153
+ #
154
+ it "filtered block parsing" do
155
+ block = Block.new
156
+ proc {
157
+ block.parse_data_from_io(@blocks['filtered-0'], :filtered)
158
+ }.should.not.raise Exception
159
+
160
+ block.verify_mrkl_root.should == true
161
+ block.hash.should == '000000000000dab0130bbcc991d3d7ae6b81aa6f50a798888dfe62337458dc45'
162
+ block.tx_hashes.should == ['63194f18be0af63f2c6bc9dc0f777cbefed3d9415c4af83f3ee3a3d669c00cb5']
163
+ end
164
+
138
165
  it '#header_to_json' do
139
166
  @block.header_to_json.should == (<<-JSON).chomp
140
167
  {
@@ -0,0 +1,38 @@
1
+ require_relative '../spec_helper.rb'
2
+ require 'set'
3
+
4
+
5
+ #
6
+ # following test cases are borrowed from
7
+ # https://github.com/bitcoinj/bitcoinj/blob/master/core/src/test/java/org/bitcoinj/core/FilteredBlockAndPartialMerkleTreeTests.java
8
+ #
9
+ describe 'Bitcoin::Protocol::PartialMerkleTree' do
10
+ it "initialize" do
11
+ hashes = [
12
+ '4c30b63cfcdc2d35e3329421b9805ef0c6565d35381ca857762ea0b3a5a128bb',
13
+ 'ca5065ff9617cbcba45eb23726df6498a9b9cafed4f54cbab9d227b0035ddefb',
14
+ 'bb15ac1d57d0182aaee61c74743a9c4f785895e563909bafec45c9a2b0ff3181',
15
+ 'd77706be8b1dcc91112eada86d424e2d0a8907c3488b6e44fda5a74a25cbc7d6',
16
+ 'bb4fa04245f4ac8a1a571d5537eac24adca1454d65eda446055479af6c6d4dd3',
17
+ 'c9ab658448c10b6921b7a4ce3021eb22ed6bb6a7fde1e5bcc4b1db6615c6abc5',
18
+ 'ca042127bfaf9f44ebce29cb29c6df9d05b47f35b2edff4f0064b578ab741fa7',
19
+ '8276222651209fe1a2c4c0fa1c58510aec8b090dd1eb1f82f9d261b8273b525b',
20
+ ].map(&:htb)
21
+ tree = Bitcoin::P::PartialMerkleTree.new(12, hashes, 'ff1a'.htb)
22
+ tree.set_value
23
+
24
+ tx_hashes = Set.new(tree.tx_hashes)
25
+ # following 6 are leaves (tx_hash) of merkle tree
26
+ tx_hashes.include?('bb28a1a5b3a02e7657a81c38355d56c6f05e80b9219432e3352ddcfc3cb6304c').should == true
27
+ tx_hashes.include?('fbde5d03b027d2b9ba4cf5d4fecab9a99864df2637b25ea4cbcb1796ff6550ca').should == true
28
+ tx_hashes.include?('8131ffb0a2c945ecaf9b9063e59558784f9c3a74741ce6ae2a18d0571dac15bb').should == true
29
+ tx_hashes.include?('c5abc61566dbb1c4bce5e1fda7b66bed22eb2130cea4b721690bc1488465abc9').should == true
30
+ tx_hashes.include?('d6c7cb254aa7a5fd446e8b48c307890a2d4e426da8ad2e1191cc1d8bbe0677d7').should == true
31
+ tx_hashes.include?('a71f74ab78b564004fffedb2357fb4059ddfc629cb29ceeb449fafbf272104ca').should == true
32
+ # following 2 are edge node of merkle tree
33
+ tx_hashes.include?('d34d6d6caf79540546a4ed654d45a1dc4ac2ea37551d571a8aacf44542a04fbb').should == false
34
+ tx_hashes.include?('5b523b27b861d2f9821febd10d098bec0a51581cfac0c4a2e19f205126227682').should == false
35
+
36
+ tree.root.value.should == '7fe79307aeb300d910d9c4bec5bacb4c7e114c7dfd6789e19f3a733debb3bb6a'
37
+ end
38
+ end
@@ -10,12 +10,14 @@ describe 'Tx' do
10
10
  fixtures_file('rawtx-01.bin'),
11
11
  fixtures_file('rawtx-02.bin'),
12
12
  fixtures_file('rawtx-03.bin'),
13
+ fixtures_file('rawtx-p2wpkh.bin'),
13
14
  ]
14
15
 
15
16
  @json = [
16
17
  fixtures_file('rawtx-01.json'),
17
18
  fixtures_file('rawtx-02.json'),
18
- fixtures_file('rawtx-03.json')
19
+ fixtures_file('rawtx-03.json'),
20
+ fixtures_file('rawtx-p2wpkh.json')
19
21
  ]
20
22
 
21
23
 
@@ -42,11 +44,29 @@ describe 'Tx' do
42
44
  tx.hash.size.should == 64
43
45
  end
44
46
 
47
+ it '#parse_witness_data' do
48
+ tx = Tx.new( @payload[3] )
49
+ tx.hash.size.should == 64
50
+
51
+ tx = Tx.new( @payload[3] + "AAAA" )
52
+ tx.hash.size.should == 64
53
+ end
54
+
45
55
  it '#hash' do
46
56
  tx = Tx.new( @payload[0] )
47
57
  tx.hash.size.should == 64
48
58
  tx.hash.should == "6e9dd16625b62cfcd4bf02edb89ca1f5a8c30c4b1601507090fb28e59f2d02b4"
49
59
  tx.binary_hash.should == "\xB4\x02-\x9F\xE5(\xFB\x90pP\x01\x16K\f\xC3\xA8\xF5\xA1\x9C\xB8\xED\x02\xBF\xD4\xFC,\xB6%f\xD1\x9Dn"
60
+
61
+ tx = Tx.new(@payload[3])
62
+ tx.hash.size.should == 64
63
+ tx.hash.should == "f22f5168cf0bc55a31003b0fc532152da551e1ec4289c4fd92e7ec512c6e87a0"
64
+ end
65
+
66
+ it '#witness_hash' do
67
+ tx = Tx.new(@payload[3])
68
+ tx.witness_hash.size.should == 64
69
+ tx.witness_hash.should == "c9609ed4d7e60ebcf4cce2854568b54a855a12b5bda15433ca96e72cd445a5cf"
50
70
  end
51
71
 
52
72
  it '#normalized_hash' do
@@ -72,9 +92,19 @@ describe 'Tx' do
72
92
  tx.to_payload.should == @payload[0]
73
93
  end
74
94
 
95
+ it '#to_witness_payload' do
96
+ tx = Tx.new( @payload[3] )
97
+ tx.to_witness_payload.size.should == @payload[3].size
98
+ tx.to_witness_payload.should == @payload[3]
99
+ end
100
+
75
101
  it '#to_hash' do
76
102
  tx = Tx.new( @payload[0] )
77
103
  tx.to_hash.keys.should == ["hash", "ver", "vin_sz", "vout_sz", "lock_time", "size", "in", "out"]
104
+
105
+ # witness tx
106
+ tx = Tx.new( @payload[3] )
107
+ tx.to_hash.keys.should == ["hash", "ver", "vin_sz", "vout_sz", "lock_time", "size", "in", "out"]
78
108
  end
79
109
 
80
110
  it 'Tx.from_hash' do
@@ -88,12 +118,23 @@ describe 'Tx' do
88
118
  h = orig_tx.to_hash.merge("ver" => 123)
89
119
  -> { tx = Tx.from_hash(h) }.should.raise(Exception)
90
120
  .message.should == "Tx hash mismatch! Claimed: 6e9dd16625b62cfcd4bf02edb89ca1f5a8c30c4b1601507090fb28e59f2d02b4, Actual: 395cd28c334ac84ed125ec5ccd5bc29eadcc96b79c337d0a87a19df64ea3b548"
121
+
122
+ # witness tx(P2WPKH)
123
+ orig_tx = Tx.new( @payload[3] )
124
+ tx = Tx.from_hash( orig_tx.to_hash )
125
+ tx.to_witness_payload.size.should == @payload[3].size
126
+ tx.to_witness_payload.should == @payload[3]
127
+ tx.to_hash == orig_tx.to_hash
91
128
  end
92
129
 
93
130
  it 'Tx.binary_from_hash' do
94
131
  orig_tx = Tx.new( @payload[0] )
95
132
  Tx.binary_from_hash( orig_tx.to_hash ).size.should == @payload[0].size
96
133
  Tx.binary_from_hash( orig_tx.to_hash ).should == @payload[0]
134
+
135
+ orig_tx = Tx.new( @payload[3] )
136
+ Tx.binary_from_hash( orig_tx.to_hash ).size.should == @payload[3].size
137
+ Tx.binary_from_hash( orig_tx.to_hash ).should == @payload[3]
97
138
  end
98
139
 
99
140
  it '#to_json' do
@@ -108,6 +149,9 @@ describe 'Tx' do
108
149
 
109
150
  tx = Tx.new( fixtures_file('rawtx-2f4a2717ec8c9f077a87dde6cbe0274d5238793a3f3f492b63c744837285e58a.bin') )
110
151
  tx.to_json.should == fixtures_file('rawtx-2f4a2717ec8c9f077a87dde6cbe0274d5238793a3f3f492b63c744837285e58a.json')
152
+
153
+ tx = Tx.new(@payload[3])
154
+ tx.to_json.should == @json[3]
111
155
  end
112
156
 
113
157
  it 'Tx.from_json' do
@@ -133,6 +177,11 @@ describe 'Tx' do
133
177
  Tx.from_json(fixtures_file('rawtx-02-toshi.json')).to_payload.should == Tx.from_json(fixtures_file('rawtx-02.json')).to_payload
134
178
  Tx.from_json(fixtures_file('rawtx-03-toshi.json')).to_payload.should == Tx.from_json(fixtures_file('rawtx-03.json')).to_payload
135
179
  Tx.from_json(fixtures_file('coinbase-toshi.json')).to_payload.should == Tx.from_json(fixtures_file('coinbase.json')).to_payload
180
+
181
+ # witness tx
182
+ tx = Tx.from_json(json_string = fixtures_file('rawtx-p2wpkh.json'))
183
+ tx.to_witness_payload.should == @payload[3]
184
+ tx.to_json == json_string
136
185
  end
137
186
 
138
187
  it 'Tx.binary_from_json' do
@@ -396,6 +445,24 @@ describe 'Tx' do
396
445
  tx.verify_input_signature(0, outpoint_tx).should == true
397
446
  end
398
447
 
448
+ it '#verify_witness_input_signature' do
449
+ #P2WPKH
450
+ tx = Tx.new('01000000000102fff7f7881a8099afa6940d42d1e7f6362bec38171ea3edf433541db4e4ad969f00000000494830450221008b9d1dc26ba6a9cb62127b02742fa9d754cd3bebf337f7a55d114c8e5cdd30be022040529b194ba3f9281a99f2b1c0a19c0489bc22ede944ccf4ecbab4cc618ef3ed01eeffffffef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a0100000000ffffffff02202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac9093510d000000001976a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac000247304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee0121025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee635711000000'.htb)
451
+ tx.verify_witness_input_signature(1, '00141d0f172a0ecb48aee1be1f2687d2963ae33f71a1'.htb, 600000000).should == true
452
+
453
+ # P2WSH
454
+ tx = Tx.new('01000000000102fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e000000004847304402200af4e47c9b9629dbecc21f73af989bdaa911f7e6f6c2e9394588a3aa68f81e9902204f3fcf6ade7e5abb1295b6774c8e0abd94ae62217367096bc02ee5e435b67da201ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac000347304402200de66acf4527789bfda55fc5459e214fa6083f936b430a762c629656216805ac0220396f550692cd347171cbc1ef1f51e15282e837bb2b30860dc77c8f78bc8501e503473044022027dc95ad6b740fe5129e7e62a75dd00f291a2aeb1200b84b09d9e3789406b6c002201a9ecd315dd6a0e632ab20bbb98948bc0c6fb204f2c286963bb48517a7058e27034721026dccc749adc2a9d0d89497ac511f760f45c47dc5ed9cf352a58ac706453880aeadab210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac00000000'.htb)
455
+ tx.verify_witness_input_signature(1, '00205d1b56b63d714eebe542309525f484b7e9d6f686b3781b6f61ef925d66d6f6a0'.htb, 4900000000).should == true
456
+
457
+ # P2SH-P2WPKH
458
+ tx = Bitcoin::P::Tx.new('01000000000101db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a5477010000001716001479091972186c449eb1ded22b78e40d009bdf0089feffffff02b8b4eb0b000000001976a914a457b684d7f0d539a46a45bbc043f35b59d0d96388ac0008af2f000000001976a914fd270b1ee6abcaea97fea7ad0402e8bd8ad6d77c88ac02473044022047ac8e878352d3ebbde1c94ce3a10d057c24175747116f8288e5d794d12d482f0220217f36a485cae903c713331d877c1f64677e3622ad4010726870540656fe9dcb012103ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a2687392040000'.htb)
459
+ tx.verify_witness_input_signature(0, 'a9144733f37cf4db86fbc2efed2500b4f4e49f31202387'.htb, 1000000000).should == true
460
+
461
+ # P2SH-P2WSH
462
+ tx = Bitcoin::P::Tx.new('0100000000010136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000023220020a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac080047304402206ac44d672dac41f9b00e28f4df20c52eeb087207e8d758d76d92c6fab3b73e2b0220367750dbbe19290069cba53d096f44530e4f98acaa594810388cf7409a1870ce01473044022068c7946a43232757cbdf9176f009a928e1cd9a1a8c212f15c1e11ac9f2925d9002205b75f937ff2f9f3c1246e547e54f62e027f64eefa2695578cc6432cdabce271502473044022059ebf56d98010a932cf8ecfec54c48e6139ed6adb0728c09cbe1e4fa0915302e022007cd986c8fa870ff5d2b3a89139c9fe7e499259875357e20fcbb15571c76795403483045022100fbefd94bd0a488d50b79102b5dad4ab6ced30c4069f1eaa69a4b5a763414067e02203156c6a5c9cf88f91265f5a942e96213afae16d83321c8b31bb342142a14d16381483045022100a5263ea0553ba89221984bd7f0b13613db16e7a70c549a86de0cc0444141a407022005c360ef0ae5a5d4f9f2f87a56c1546cc8268cab08c73501d6b3be2e1e1a8a08824730440220525406a1482936d5a21888260dc165497a90a15669636d8edca6b9fe490d309c022032af0c646a34a44d1f4576bf6a4a74b67940f8faa84c7df9abe12a01a11e2b4783cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae00000000'.htb)
463
+ tx.verify_witness_input_signature(0, 'a9149993a429037b5d912407a71c252019287b8d27a587'.htb, 987654321).should == true
464
+ end
465
+
399
466
  it '#sign_input_signature' do
400
467
  prev_tx = Tx.new( fixtures_file('rawtx-2f4a2717ec8c9f077a87dde6cbe0274d5238793a3f3f492b63c744837285e58a.bin') )
401
468
  prev_tx.hash.should == "2f4a2717ec8c9f077a87dde6cbe0274d5238793a3f3f492b63c744837285e58a"
@@ -455,6 +522,28 @@ describe 'Tx' do
455
522
  prev_tx.hash.should == "52250a162c7d03d2e1fbc5ebd1801a88612463314b55102171c5b5d817d2d7b2"
456
523
  #File.open("rawtx-#{prev_tx.hash}.json",'wb'){|f| f.print prev_tx.to_json }
457
524
  end
525
+
526
+ it '#signature_hash_for_witness_input' do
527
+ # P2WPKH https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#Native_P2WPKH
528
+ tx = Tx.new('0100000002fff7f7881a8099afa6940d42d1e7f6362bec38171ea3edf433541db4e4ad969f0000000000eeffffffef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a0100000000ffffffff02202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac9093510d000000001976a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac11000000'.htb)
529
+ signature_hash = tx.signature_hash_for_witness_input(1, '00141d0f172a0ecb48aee1be1f2687d2963ae33f71a1'.htb, 600000000)
530
+ signature_hash.bth.should == 'c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670'
531
+
532
+ # P2WSH https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#Native_P2WSH
533
+ tx = Tx.new('0100000002fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e0000000000ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac00000000'.htb)
534
+ script_pubkey = '00205d1b56b63d714eebe542309525f484b7e9d6f686b3781b6f61ef925d66d6f6a0'
535
+ witness_script = '21026dccc749adc2a9d0d89497ac511f760f45c47dc5ed9cf352a58ac706453880aeadab210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac'
536
+ signature_hash = tx.signature_hash_for_witness_input(1, script_pubkey.htb, 4900000000, witness_script.htb, Tx::SIGHASH_TYPE[:single])
537
+ signature_hash.bth.should == '82dde6e4f1e94d02c2b7ad03d2115d691f48d064e9d52f58194a6637e4194391'
538
+
539
+ # P2WSH with invalid witness script
540
+ tx = Tx.new('0100000002fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e0000000000ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac00000000'.htb)
541
+ script_pubkey = '00205d1b56b63d714eebe542309525f484b7e9d6f686b3781b6f61ef925d66d6f6a0'
542
+ witness_script = 'AAA'
543
+ proc{
544
+ tx.signature_hash_for_witness_input(1, script_pubkey.htb, 4900000000, witness_script.htb)
545
+ }.should.raise Exception
546
+ end
458
547
 
459
548
  it "#legacy_sigops_count" do
460
549
  Tx.new(@payload[0]).legacy_sigops_count.should == 2
@@ -625,5 +714,49 @@ describe 'Tx' do
625
714
  end
626
715
 
627
716
  end
717
+
718
+ it 'lexicographical_sort' do
719
+ tx = Bitcoin::P::Tx.from_json(fixtures_file('tx-0a6a357e2f7796444e02638749d9611c008b253fb55f5dc88b739b230ed0c4c3.json'))
720
+ tx.hash.should == '0a6a357e2f7796444e02638749d9611c008b253fb55f5dc88b739b230ed0c4c3'
721
+ tx.lexicographical_sort!
722
+ tx.in[0].previous_output.should == '0e53ec5dfb2cb8a71fec32dc9a634a35b7e24799295ddd5278217822e0b31f57'
723
+ tx.in[1].previous_output.should == '26aa6e6d8b9e49bb0630aac301db6757c02e3619feb4ee0eea81eb1672947024'
724
+ tx.in[2].previous_output.should == '28e0fdd185542f2c6ea19030b0796051e7772b6026dd5ddccd7a2f93b73e6fc2'
725
+ tx.in[3].previous_output.should == '381de9b9ae1a94d9c17f6a08ef9d341a5ce29e2e60c36a52d333ff6203e58d5d'
726
+ tx.in[4].previous_output.should == '3b8b2f8efceb60ba78ca8bba206a137f14cb5ea4035e761ee204302d46b98de2'
727
+ tx.in[5].previous_output.should == '402b2c02411720bf409eff60d05adad684f135838962823f3614cc657dd7bc0a'
728
+ tx.in[6].previous_output.should == '54ffff182965ed0957dba1239c27164ace5a73c9b62a660c74b7b7f15ff61e7a'
729
+ tx.in[7].previous_output.should == '643e5f4e66373a57251fb173151e838ccd27d279aca882997e005016bb53d5aa'
730
+ tx.in[8].previous_output.should == '6c1d56f31b2de4bfc6aaea28396b333102b1f600da9c6d6149e96ca43f1102b1'
731
+ tx.in[9].previous_output.should == '7a1de137cbafb5c70405455c49c5104ca3057a1f1243e6563bb9245c9c88c191'
732
+ tx.in[10].previous_output.should == '7d037ceb2ee0dc03e82f17be7935d238b35d1deabf953a892a4507bfbeeb3ba4'
733
+ tx.in[11].previous_output.should == 'a5e899dddb28776ea9ddac0a502316d53a4a3fca607c72f66c470e0412e34086'
734
+ tx.in[12].previous_output.should == 'b4112b8f900a7ca0c8b0e7c4dfad35c6be5f6be46b3458974988e1cdb2fa61b8'
735
+ tx.in[13].previous_output.should == 'bafd65e3c7f3f9fdfdc1ddb026131b278c3be1af90a4a6ffa78c4658f9ec0c85'
736
+ tx.in[14].previous_output.should == 'de0411a1e97484a2804ff1dbde260ac19de841bebad1880c782941aca883b4e9'
737
+ tx.in[15].previous_output.should == 'f0a130a84912d03c1d284974f563c5949ac13f8342b8112edff52971599e6a45'
738
+ tx.in[16].previous_output.should == 'f320832a9d2e2452af63154bc687493484a0e7745ebd3aaf9ca19eb80834ad60'
739
+ tx.out[0].value.should == 400057456
740
+ tx.out[1].value.should == 40000000000
741
+
742
+ tx = Bitcoin::P::Tx.from_json(fixtures_file('tx-28204cad1d7fc1d199e8ef4fa22f182de6258a3eaafe1bbe56ebdcacd3069a5f.json'))
743
+ tx.hash.should == '28204cad1d7fc1d199e8ef4fa22f182de6258a3eaafe1bbe56ebdcacd3069a5f'
744
+ tx.lexicographical_sort!
745
+ tx.in[0].previous_output.should == '35288d269cee1941eaebb2ea85e32b42cdb2b04284a56d8b14dcc3f5c65d6055'
746
+ tx.in[0].prev_out_index.should == 0
747
+ tx.in[1].previous_output.should == '35288d269cee1941eaebb2ea85e32b42cdb2b04284a56d8b14dcc3f5c65d6055'
748
+ tx.in[1].prev_out_index.should == 1
749
+ tx.out[0].value.should == 100000000
750
+ tx.out[1].value.should == 2400000000
751
+
752
+ tx = Bitcoin::P::Tx.new
753
+ tx.add_out(Bitcoin::P::TxOut.new(500, 'bbbbbbbb'.htb))
754
+ tx.add_out(Bitcoin::P::TxOut.new(500, 'aaaaaaaa'.htb))
755
+ tx.add_out(Bitcoin::P::TxOut.new(500, 'cccccccc'.htb))
756
+ tx.lexicographical_sort!
757
+ tx.out[0].pk_script.bth.should == 'aaaaaaaa'
758
+ tx.out[1].pk_script.bth.should == 'bbbbbbbb'
759
+ tx.out[2].pk_script.bth.should == 'cccccccc'
760
+ end
628
761
 
629
762
  end