bitcoin-ruby 0.0.11 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -252,6 +252,13 @@ describe "Bitcoin::Key" do
252
252
  k.to_base58.should == "5JBAonQ4iGKFJxENExZghDtAS6YB8BsCw5mwpHSvZvP3Q2UxmT1"
253
253
  end
254
254
 
255
+ it "should raise error for private key out of range." do
256
+ proc{Bitcoin::Key.new('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141')}.should.raise(Exception)
257
+ proc{Bitcoin::Key.new('00')}.should.raise(Exception)
258
+ proc{Bitcoin::Key.new('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140')}.should.not.raise(Exception)
259
+ proc{Bitcoin::Key.new('01')}.should.not.raise(Exception)
260
+ end
261
+
255
262
  end
256
263
 
257
264
  begin
@@ -30,6 +30,9 @@ describe 'Tx' do
30
30
  proc{
31
31
  Tx.new( @payload[0][0..20] )
32
32
  }.should.raise Exception
33
+
34
+ # Deserializing a new, empty transaction works
35
+ Tx.new(Tx.new.to_payload)
33
36
  end
34
37
 
35
38
  it '#parse_data' do
@@ -38,18 +41,22 @@ describe 'Tx' do
38
41
  tx.hash.should == nil
39
42
  tx.parse_data( @payload[0] ).should == true
40
43
  tx.hash.size.should == 64
44
+ tx.payload.should == @payload[0]
41
45
 
42
46
  tx = Tx.new( nil )
43
47
  tx.parse_data( @payload[0] + "AAAA" ).should == "AAAA"
44
48
  tx.hash.size.should == 64
49
+ tx.payload.should == @payload[0]
45
50
  end
46
51
 
47
52
  it '#parse_witness_data' do
48
53
  tx = Tx.new( @payload[3] )
49
54
  tx.hash.size.should == 64
55
+ tx.payload.should == @payload[3]
50
56
 
51
57
  tx = Tx.new( @payload[3] + "AAAA" )
52
58
  tx.hash.size.should == 64
59
+ tx.payload.should == @payload[3]
53
60
  end
54
61
 
55
62
  it '#hash' do
@@ -110,6 +117,7 @@ describe 'Tx' do
110
117
  it 'Tx.from_hash' do
111
118
  orig_tx = Tx.new( @payload[0] )
112
119
  tx = Tx.from_hash( orig_tx.to_hash )
120
+ tx.payload.should == @payload[0]
113
121
  tx.to_payload.size.should == @payload[0].size
114
122
  tx.to_payload.should == @payload[0]
115
123
  tx.to_hash.should == orig_tx.to_hash
@@ -122,6 +130,7 @@ describe 'Tx' do
122
130
  # witness tx(P2WPKH)
123
131
  orig_tx = Tx.new( @payload[3] )
124
132
  tx = Tx.from_hash( orig_tx.to_hash )
133
+ tx.payload.should == @payload[3]
125
134
  tx.to_witness_payload.size.should == @payload[3].size
126
135
  tx.to_witness_payload.should == @payload[3]
127
136
  tx.to_hash == orig_tx.to_hash
@@ -463,64 +472,80 @@ describe 'Tx' do
463
472
  tx.verify_witness_input_signature(0, 'a9149993a429037b5d912407a71c252019287b8d27a587'.htb, 987654321).should == true
464
473
  end
465
474
 
466
- it '#sign_input_signature' do
467
- prev_tx = Tx.new( fixtures_file('rawtx-2f4a2717ec8c9f077a87dde6cbe0274d5238793a3f3f492b63c744837285e58a.bin') )
468
- prev_tx.hash.should == "2f4a2717ec8c9f077a87dde6cbe0274d5238793a3f3f492b63c744837285e58a"
475
+ describe '#signature_hash_for_input' do
476
+ it 'sighash_all' do
477
+ prev_tx = Tx.new( fixtures_file('rawtx-2f4a2717ec8c9f077a87dde6cbe0274d5238793a3f3f492b63c744837285e58a.bin') )
478
+ prev_tx.hash.should == "2f4a2717ec8c9f077a87dde6cbe0274d5238793a3f3f492b63c744837285e58a"
469
479
 
470
- key = Bitcoin.open_key("56e28a425a7b588973b5db962a09b1aca7bdc4a7268cdd671d03c52a997255dc",
471
- pubkey="04324c6ebdcf079db6c9209a6b715b955622561262cde13a8a1df8ae0ef030eaa1552e31f8be90c385e27883a9d82780283d19507d7fa2e1e71a1d11bc3a52caf3")
472
- new_tx = Tx.new(nil)
473
- new_tx.add_in( TxIn.new(prev_tx.binary_hash, 0, 0) )
474
- new_tx.add_out( TxOut.value_to_address(1000000, "1BVJWLTCtjA8wRivvrCiwjNdL6KjdMUCTZ") )
475
- signature_hash = new_tx.signature_hash_for_input(0, prev_tx)
476
- sig = Bitcoin.sign_data(key, signature_hash)
477
- new_tx.in[0].script_sig = Bitcoin::Script.to_pubkey_script_sig(sig, [pubkey].pack("H*"))
480
+ key = Bitcoin.open_key("56e28a425a7b588973b5db962a09b1aca7bdc4a7268cdd671d03c52a997255dc",
481
+ pubkey="04324c6ebdcf079db6c9209a6b715b955622561262cde13a8a1df8ae0ef030eaa1552e31f8be90c385e27883a9d82780283d19507d7fa2e1e71a1d11bc3a52caf3")
482
+ new_tx = Tx.new(nil)
483
+ new_tx.add_in( TxIn.new(prev_tx.binary_hash, 0, 0) )
484
+ new_tx.add_out( TxOut.value_to_address(1000000, "1BVJWLTCtjA8wRivvrCiwjNdL6KjdMUCTZ") )
485
+ signature_hash = new_tx.signature_hash_for_input(0, prev_tx)
486
+ sig = Bitcoin.sign_data(key, signature_hash)
487
+ new_tx.in[0].script_sig = Bitcoin::Script.to_pubkey_script_sig(sig, [pubkey].pack("H*"))
478
488
 
479
- new_tx = Tx.new( new_tx.to_payload )
480
- new_tx.hash.should != nil
481
- new_tx.verify_input_signature(0, prev_tx).should == true
489
+ new_tx = Tx.new( new_tx.to_payload )
490
+ new_tx.hash.should != nil
491
+ new_tx.verify_input_signature(0, prev_tx).should == true
482
492
 
483
493
 
484
494
 
485
- prev_tx = Tx.new( fixtures_file('rawtx-14be6fff8c6014f7c9493b4a6e4a741699173f39d74431b6b844fcb41ebb9984.bin') )
486
- prev_tx.hash.should == "14be6fff8c6014f7c9493b4a6e4a741699173f39d74431b6b844fcb41ebb9984"
495
+ prev_tx = Tx.new( fixtures_file('rawtx-14be6fff8c6014f7c9493b4a6e4a741699173f39d74431b6b844fcb41ebb9984.bin') )
496
+ prev_tx.hash.should == "14be6fff8c6014f7c9493b4a6e4a741699173f39d74431b6b844fcb41ebb9984"
487
497
 
488
- key = Bitcoin.open_key("115ceda6c1e02d41ce65c35a30e82fb325fe3f815898a09e1a5d28bb1cc92c6e",
489
- pubkey="0409d103127d26ce93ee41f1b9b1ed4c1c243acf48e31eb5c4d88ad0342ccc010a1a8d838846cf7337f2b44bc73986c0a3cb0568fa93d068b2c8296ce8d47b1545")
490
- new_tx = Tx.new(nil)
491
- new_tx.add_in( TxIn.new(prev_tx.binary_hash, 0, 0) )
492
- pk_script = Bitcoin::Script.to_address_script("1FEYAh1x5jeKQMPPuv3bKnKvbgVAqXvqjW")
493
- new_tx.add_out( TxOut.new(1000000, pk_script) )
494
- signature_hash = new_tx.signature_hash_for_input(0, prev_tx)
495
- sig = Bitcoin.sign_data(key, signature_hash)
496
- new_tx.in[0].script_sig = Bitcoin::Script.to_pubkey_script_sig(sig, [pubkey].pack("H*"))
498
+ key = Bitcoin.open_key("115ceda6c1e02d41ce65c35a30e82fb325fe3f815898a09e1a5d28bb1cc92c6e",
499
+ pubkey="0409d103127d26ce93ee41f1b9b1ed4c1c243acf48e31eb5c4d88ad0342ccc010a1a8d838846cf7337f2b44bc73986c0a3cb0568fa93d068b2c8296ce8d47b1545")
500
+ new_tx = Tx.new(nil)
501
+ new_tx.add_in( TxIn.new(prev_tx.binary_hash, 0, 0) )
502
+ pk_script = Bitcoin::Script.to_address_script("1FEYAh1x5jeKQMPPuv3bKnKvbgVAqXvqjW")
503
+ new_tx.add_out( TxOut.new(1000000, pk_script) )
504
+ signature_hash = new_tx.signature_hash_for_input(0, prev_tx)
505
+ sig = Bitcoin.sign_data(key, signature_hash)
506
+ new_tx.in[0].script_sig = Bitcoin::Script.to_pubkey_script_sig(sig, [pubkey].pack("H*"))
497
507
 
498
- new_tx = Tx.new( new_tx.to_payload )
499
- new_tx.hash.should != nil
500
- new_tx.verify_input_signature(0, prev_tx).should == true
508
+ new_tx = Tx.new( new_tx.to_payload )
509
+ new_tx.hash.should != nil
510
+ new_tx.verify_input_signature(0, prev_tx).should == true
501
511
 
502
512
 
503
513
 
504
- prev_tx = Tx.new( fixtures_file('rawtx-b5d4e8883533f99e5903ea2cf001a133a322fa6b1370b18a16c57c946a40823d.bin') )
505
- prev_tx.hash.should == "b5d4e8883533f99e5903ea2cf001a133a322fa6b1370b18a16c57c946a40823d"
514
+ prev_tx = Tx.new( fixtures_file('rawtx-b5d4e8883533f99e5903ea2cf001a133a322fa6b1370b18a16c57c946a40823d.bin') )
515
+ prev_tx.hash.should == "b5d4e8883533f99e5903ea2cf001a133a322fa6b1370b18a16c57c946a40823d"
506
516
 
507
- key = Bitcoin.open_key("56e28a425a7b588973b5db962a09b1aca7bdc4a7268cdd671d03c52a997255dc",
508
- pubkey="04324c6ebdcf079db6c9209a6b715b955622561262cde13a8a1df8ae0ef030eaa1552e31f8be90c385e27883a9d82780283d19507d7fa2e1e71a1d11bc3a52caf3")
509
- new_tx = Tx.new(nil)
510
- new_tx.add_in( TxIn.new(prev_tx.binary_hash, 0, 0) )
511
- new_tx.add_out( TxOut.value_to_address(1000000, "14yz7fob6Q16hZu4nXfmv1kRJpSYaFtet5") )
512
- signature_hash = new_tx.signature_hash_for_input(0, prev_tx)
513
- sig = Bitcoin.sign_data(key, signature_hash)
514
- new_tx.in[0].script_sig = Bitcoin::Script.to_pubkey_script_sig(sig, [pubkey].pack("H*"))
517
+ key = Bitcoin.open_key("56e28a425a7b588973b5db962a09b1aca7bdc4a7268cdd671d03c52a997255dc",
518
+ pubkey="04324c6ebdcf079db6c9209a6b715b955622561262cde13a8a1df8ae0ef030eaa1552e31f8be90c385e27883a9d82780283d19507d7fa2e1e71a1d11bc3a52caf3")
519
+ new_tx = Tx.new(nil)
520
+ new_tx.add_in( TxIn.new(prev_tx.binary_hash, 0, 0) )
521
+ new_tx.add_out( TxOut.value_to_address(1000000, "14yz7fob6Q16hZu4nXfmv1kRJpSYaFtet5") )
522
+ signature_hash = new_tx.signature_hash_for_input(0, prev_tx)
523
+ sig = Bitcoin.sign_data(key, signature_hash)
524
+ new_tx.in[0].script_sig = Bitcoin::Script.to_pubkey_script_sig(sig, [pubkey].pack("H*"))
515
525
 
516
- new_tx = Tx.new( new_tx.to_payload )
517
- new_tx.hash.should != nil
518
- new_tx.verify_input_signature(0, prev_tx).should == true
526
+ new_tx = Tx.new( new_tx.to_payload )
527
+ new_tx.hash.should != nil
528
+ new_tx.verify_input_signature(0, prev_tx).should == true
529
+ end
519
530
 
520
- #File.open("rawtx-#{new_tx.hash}.bin",'wb'){|f| f.print new_tx.to_payload }
521
- prev_tx = Tx.new( fixtures_file('rawtx-52250a162c7d03d2e1fbc5ebd1801a88612463314b55102171c5b5d817d2d7b2.bin') )
522
- prev_tx.hash.should == "52250a162c7d03d2e1fbc5ebd1801a88612463314b55102171c5b5d817d2d7b2"
523
- #File.open("rawtx-#{prev_tx.hash}.json",'wb'){|f| f.print prev_tx.to_json }
531
+ it 'sighash JSON tests' do
532
+ test_cases = JSON.parse(fixtures_file('sighash.json'))
533
+ test_cases.each do |test_case|
534
+ # Single element arrays in tests are comments.
535
+ next if test_case.length == 1
536
+
537
+ transaction = Bitcoin::Protocol::Tx.new(test_case[0].htb)
538
+ subscript = test_case[1].htb
539
+ input_index = test_case[2].to_i
540
+ hash_type = test_case[3]
541
+ amount = 0
542
+ expected_sighash = test_case[4].htb_reverse
543
+
544
+ actual_sighash = transaction.signature_hash_for_input(
545
+ input_index, subscript, hash_type, amount, 0)
546
+ actual_sighash.should == expected_sighash
547
+ end
548
+ end
524
549
  end
525
550
 
526
551
  it '#signature_hash_for_witness_input' do
@@ -758,5 +783,109 @@ describe 'Tx' do
758
783
  tx.out[1].pk_script.bth.should == 'bbbbbbbb'
759
784
  tx.out[2].pk_script.bth.should == 'cccccccc'
760
785
  end
761
-
786
+
787
+ describe 'verify_input_signature' do
788
+ def parse_script(script_str)
789
+ script = Bitcoin::Script.new('')
790
+
791
+ buf = ""
792
+ script_str.split.each do |token|
793
+ opcode = Bitcoin::Script::OPCODES_PARSE_STRING[token] ||
794
+ Bitcoin::Script::OPCODES_PARSE_STRING['OP_' + token]
795
+ if opcode
796
+ buf << [opcode].pack('C')
797
+ next
798
+ end
799
+
800
+ data =
801
+ case token
802
+ when /\A-?\d+\z/
803
+ i = token.to_i
804
+ opcode =
805
+ case i
806
+ when -1 then Bitcoin::Script::OP_1NEGATE
807
+ when 0 then Bitcoin::Script::OP_0
808
+ when 1 then Bitcoin::Script::OP_1
809
+ when 2..16 then Bitcoin::Script::OP_2 + i - 2
810
+ end
811
+
812
+ if opcode
813
+ [opcode].pack('C')
814
+ else
815
+ Bitcoin::Script.pack_pushdata(script.cast_to_string(i))
816
+ end
817
+ when /\A'(.*)'\z/ then Bitcoin::Script.pack_pushdata($1)
818
+ when /\A0x([0-9a-fA-F]+)\z/ then $1.htb
819
+ else raise "Unexpected token #{token}"
820
+ end
821
+ buf << data
822
+ end
823
+ buf
824
+ end
825
+
826
+ def parse_flags(flags_str)
827
+ flags_str.split(',').each_with_object({}) do |flag_str, opts|
828
+ case flag_str.to_sym
829
+ when :STRICTENC then opts[:verify_strictenc] = true
830
+ when :DERSIG then opts[:verify_dersig] = true
831
+ when :LOW_S then opts[:verify_low_s] = true
832
+ when :SIGPUSHONLY then opts[:verify_sigpushonly] = true
833
+ when :MINIMALDATA then opts[:verify_minimaldata] = true
834
+ when :CLEANSTACK then opts[:verify_cleanstack] = true
835
+ when :SIGHASH_FORKID then opts[:fork_id] = 0
836
+ end
837
+ end
838
+ end
839
+
840
+ it 'script JSON tests' do
841
+ test_cases = JSON.parse(fixtures_file('script_tests.json'))
842
+ test_cases.each_with_index do |test_case, i|
843
+ # Single element arrays in tests are comments.
844
+ next if test_case.length == 1
845
+
846
+ value =
847
+ if test_case[0].is_a?(Array)
848
+ (test_case.shift[0] * 10**8).to_i
849
+ else
850
+ 0
851
+ end
852
+
853
+ # TODO: Implement these opcodes correctly
854
+ next if test_case[0].match(/CHECKLOCKTIMEVERIFY|CHECKSEQUENCEVERIFY|RESERVED|0x50|VERIF|VERNOTIF/)
855
+ next if test_case[1].match(/CHECKLOCKTIMEVERIFY|CHECKSEQUENCEVERIFY|RESERVED|0x50|VERIF|VERNOTIF/)
856
+
857
+ script_sig = parse_script(test_case[0])
858
+ script_pubkey = parse_script(test_case[1])
859
+ opts = parse_flags(test_case[2])
860
+ expect_success = test_case[3] == 'OK'
861
+
862
+ # A lot of the test cases are failing, so for now we only test the SIGHASH_FORKID ones.
863
+ # TODO: Get this spec passing without this line.
864
+ next unless opts[:fork_id]
865
+
866
+ crediting_tx = Tx.new
867
+ crediting_tx.add_in(TxIn.new)
868
+ crediting_tx.in[0].prev_out_hash = TxIn::NULL_HASH
869
+ crediting_tx.in[0].prev_out_index = TxIn::COINBASE_INDEX
870
+ crediting_tx.in[0].script_sig = parse_script('0 0')
871
+ crediting_tx.add_out(TxOut.new)
872
+ crediting_tx.out[0].value = value
873
+ crediting_tx.out[0].pk_script = script_pubkey
874
+ crediting_tx.refresh_hash
875
+
876
+ spending_tx = Tx.new
877
+ spending_tx.add_in(TxIn.new)
878
+ spending_tx.in[0].prev_out_hash = crediting_tx.binary_hash
879
+ spending_tx.in[0].prev_out_index = 0
880
+ spending_tx.in[0].script_sig = script_sig
881
+ spending_tx.add_out(TxOut.new)
882
+ spending_tx.out[0].value = value
883
+ spending_tx.out[0].pk_script = ''
884
+ spending_tx.refresh_hash
885
+
886
+ success = spending_tx.verify_input_signature(0, crediting_tx, Time.now.to_i, opts)
887
+ success.should == expect_success
888
+ end
889
+ end
890
+ end
762
891
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitcoin-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.11
4
+ version: 0.0.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - lian
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-05 00:00:00.000000000 Z
11
+ date: 2017-10-24 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: This is a ruby library for interacting with the bitcoin protocol/network
14
14
  email:
@@ -155,6 +155,8 @@ files:
155
155
  - spec/bitcoin/fixtures/reorg/blk_3A.dat
156
156
  - spec/bitcoin/fixtures/reorg/blk_4A.dat
157
157
  - spec/bitcoin/fixtures/reorg/blk_5A.dat
158
+ - spec/bitcoin/fixtures/script_tests.json
159
+ - spec/bitcoin/fixtures/sighash.json
158
160
  - spec/bitcoin/fixtures/testnet/block_0.bin
159
161
  - spec/bitcoin/fixtures/testnet/block_1.bin
160
162
  - spec/bitcoin/fixtures/testnet/block_2.bin
@@ -259,7 +261,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
259
261
  version: 1.3.6
260
262
  requirements: []
261
263
  rubyforge_project: bitcoin-ruby
262
- rubygems_version: 2.6.11
264
+ rubygems_version: 2.5.2
263
265
  signing_key:
264
266
  specification_version: 4
265
267
  summary: bitcoin utils and protocol in ruby
@@ -356,6 +358,8 @@ test_files:
356
358
  - spec/bitcoin/fixtures/reorg/blk_3A.dat
357
359
  - spec/bitcoin/fixtures/reorg/blk_4A.dat
358
360
  - spec/bitcoin/fixtures/reorg/blk_5A.dat
361
+ - spec/bitcoin/fixtures/script_tests.json
362
+ - spec/bitcoin/fixtures/sighash.json
359
363
  - spec/bitcoin/fixtures/testnet/block_0.bin
360
364
  - spec/bitcoin/fixtures/testnet/block_1.bin
361
365
  - spec/bitcoin/fixtures/testnet/block_2.bin