bitcoin-ruby 0.0.10 → 0.0.11

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