bitcoin-ruby 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/.travis.yml +2 -7
  4. data/COPYING +1 -1
  5. data/Gemfile +2 -6
  6. data/Gemfile.lock +34 -0
  7. data/README.rdoc +16 -68
  8. data/Rakefile +3 -6
  9. data/bin/bitcoin_shell +0 -1
  10. data/{concept-examples/blockchain-pow.rb → examples/concept-blockchain-pow.rb} +0 -0
  11. data/lib/bitcoin.rb +350 -296
  12. data/lib/bitcoin/builder.rb +3 -1
  13. data/lib/bitcoin/connection.rb +2 -1
  14. data/lib/bitcoin/contracthash.rb +76 -0
  15. data/lib/bitcoin/dogecoin.rb +97 -0
  16. data/lib/bitcoin/ffi/bitcoinconsensus.rb +74 -0
  17. data/lib/bitcoin/ffi/openssl.rb +98 -2
  18. data/lib/bitcoin/ffi/secp256k1.rb +144 -0
  19. data/lib/bitcoin/key.rb +12 -2
  20. data/lib/bitcoin/logger.rb +3 -12
  21. data/lib/bitcoin/protocol/block.rb +3 -9
  22. data/lib/bitcoin/protocol/parser.rb +6 -2
  23. data/lib/bitcoin/protocol/tx.rb +44 -13
  24. data/lib/bitcoin/protocol/txin.rb +4 -2
  25. data/lib/bitcoin/protocol/txout.rb +2 -2
  26. data/lib/bitcoin/script.rb +212 -37
  27. data/lib/bitcoin/trezor/mnemonic.rb +130 -0
  28. data/lib/bitcoin/version.rb +1 -1
  29. data/spec/bitcoin/bitcoin_spec.rb +32 -3
  30. data/spec/bitcoin/builder_spec.rb +18 -0
  31. data/spec/bitcoin/contracthash_spec.rb +45 -0
  32. data/spec/bitcoin/dogecoin_spec.rb +176 -0
  33. data/spec/bitcoin/ffi_openssl.rb +45 -0
  34. data/spec/bitcoin/fixtures/156e6e1b84c5c3bd3a0927b25e4119fadce6e6d5186f363317511d1d680fae9a.json +24 -0
  35. data/spec/bitcoin/fixtures/8d0b238a06b5a70be75d543902d02d7a514d68d3252a949a513865ac3538874c.json +24 -0
  36. data/spec/bitcoin/fixtures/coinbase-toshi.json +33 -0
  37. data/spec/bitcoin/fixtures/coinbase.json +24 -0
  38. data/spec/bitcoin/fixtures/dogecoin-block-60323982f9c5ff1b5a954eac9dc1269352835f47c2c5222691d80f0d50dcf053.bin +0 -0
  39. data/spec/bitcoin/fixtures/rawtx-01-toshi.json +46 -0
  40. data/spec/bitcoin/fixtures/rawtx-02-toshi.json +46 -0
  41. data/spec/bitcoin/fixtures/rawtx-03-toshi.json +73 -0
  42. data/spec/bitcoin/fixtures/rawtx-testnet-04fdc38d6722ab4b12d79113fc4b2896bdcc5169710690ee4e78541b98e467b4.bin +0 -0
  43. data/spec/bitcoin/fixtures/rawtx-testnet-0b294c7d11dd21bcccb8393e6744fed7d4d1981a08c00e3e88838cc421f33c9f.bin +0 -0
  44. data/spec/bitcoin/fixtures/rawtx-testnet-3bc52ac063291ad92d95ddda5fd776a342083b95607ad32ed8bc6f8f7d30449e.bin +0 -0
  45. data/spec/bitcoin/fixtures/rawtx-testnet-6f0bbdd4e71a8af4305018d738184df32dbb6f27284fdebd5b56d16947f7c181.bin +0 -0
  46. data/spec/bitcoin/fixtures/rawtx-testnet-a7c9b06e275e8674cc19a5f7d3e557c72c6d93576e635b33212dbe08ab7cdb60.bin +0 -0
  47. data/spec/bitcoin/fixtures/rawtx-testnet-f80acbd2f594d04ddb0e1cacba662132104909157dff526935a3c88abe9201a5.bin +0 -0
  48. data/spec/bitcoin/protocol/block_spec.rb +0 -22
  49. data/spec/bitcoin/protocol/tx_spec.rb +145 -2
  50. data/spec/bitcoin/script/script_spec.rb +282 -0
  51. data/spec/bitcoin/secp256k1_spec.rb +48 -0
  52. data/spec/bitcoin/spec_helper.rb +0 -51
  53. data/spec/bitcoin/trezor/mnemonic_spec.rb +161 -0
  54. metadata +48 -98
  55. data/bin/bitcoin_dns_seed +0 -130
  56. data/bin/bitcoin_gui +0 -80
  57. data/bin/bitcoin_node +0 -153
  58. data/bin/bitcoin_node_cli +0 -81
  59. data/bin/bitcoin_wallet +0 -402
  60. data/doc/CONFIG.rdoc +0 -66
  61. data/doc/EXAMPLES.rdoc +0 -13
  62. data/doc/NAMECOIN.rdoc +0 -34
  63. data/doc/NODE.rdoc +0 -225
  64. data/doc/STORAGE.rdoc +0 -33
  65. data/doc/WALLET.rdoc +0 -102
  66. data/examples/balance.rb +0 -66
  67. data/examples/forwarder.rb +0 -73
  68. data/examples/index_nhash.rb +0 -24
  69. data/examples/reindex_p2sh_addrs.rb +0 -44
  70. data/examples/relay_tx.rb +0 -22
  71. data/examples/verify_tx.rb +0 -57
  72. data/lib/bitcoin/config.rb +0 -58
  73. data/lib/bitcoin/gui/addr_view.rb +0 -44
  74. data/lib/bitcoin/gui/bitcoin-ruby.png +0 -0
  75. data/lib/bitcoin/gui/bitcoin-ruby.svg +0 -80
  76. data/lib/bitcoin/gui/conn_view.rb +0 -38
  77. data/lib/bitcoin/gui/connection.rb +0 -70
  78. data/lib/bitcoin/gui/em_gtk.rb +0 -30
  79. data/lib/bitcoin/gui/gui.builder +0 -1643
  80. data/lib/bitcoin/gui/gui.rb +0 -292
  81. data/lib/bitcoin/gui/helpers.rb +0 -115
  82. data/lib/bitcoin/gui/tree_view.rb +0 -84
  83. data/lib/bitcoin/gui/tx_view.rb +0 -69
  84. data/lib/bitcoin/namecoin.rb +0 -280
  85. data/lib/bitcoin/network/command_client.rb +0 -104
  86. data/lib/bitcoin/network/command_handler.rb +0 -570
  87. data/lib/bitcoin/network/connection_handler.rb +0 -387
  88. data/lib/bitcoin/network/node.rb +0 -565
  89. data/lib/bitcoin/storage/dummy/dummy_store.rb +0 -179
  90. data/lib/bitcoin/storage/models.rb +0 -171
  91. data/lib/bitcoin/storage/sequel/migrations.rb +0 -99
  92. data/lib/bitcoin/storage/sequel/migrations/001_base_schema.rb +0 -52
  93. data/lib/bitcoin/storage/sequel/migrations/002_tx.rb +0 -45
  94. data/lib/bitcoin/storage/sequel/migrations/003_change_txin_script_sig_to_blob.rb +0 -18
  95. data/lib/bitcoin/storage/sequel/migrations/004_change_txin_prev_out_to_blob.rb +0 -18
  96. data/lib/bitcoin/storage/sequel/migrations/005_change_tx_hash_to_bytea.rb +0 -14
  97. data/lib/bitcoin/storage/sequel/migrations/006_add_tx_nhash.rb +0 -31
  98. data/lib/bitcoin/storage/sequel/migrations/007_add_prev_out_index_index.rb +0 -16
  99. data/lib/bitcoin/storage/sequel/migrations/008_add_txin_p2sh_type.rb +0 -31
  100. data/lib/bitcoin/storage/sequel/migrations/009_add_addrs_type.rb +0 -56
  101. data/lib/bitcoin/storage/sequel/sequel_store.rb +0 -551
  102. data/lib/bitcoin/storage/storage.rb +0 -517
  103. data/lib/bitcoin/storage/utxo/migrations/001_base_schema.rb +0 -52
  104. data/lib/bitcoin/storage/utxo/migrations/002_utxo.rb +0 -18
  105. data/lib/bitcoin/storage/utxo/migrations/003_update_indices.rb +0 -14
  106. data/lib/bitcoin/storage/utxo/migrations/004_add_addrs_type.rb +0 -14
  107. data/lib/bitcoin/storage/utxo/utxo_store.rb +0 -374
  108. data/lib/bitcoin/validation.rb +0 -400
  109. data/lib/bitcoin/wallet/coinselector.rb +0 -33
  110. data/lib/bitcoin/wallet/keygenerator.rb +0 -77
  111. data/lib/bitcoin/wallet/keystore.rb +0 -207
  112. data/lib/bitcoin/wallet/txdp.rb +0 -118
  113. data/lib/bitcoin/wallet/wallet.rb +0 -281
  114. data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.bin +0 -0
  115. data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.json +0 -43
  116. data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.bin +0 -0
  117. data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.json +0 -67
  118. data/spec/bitcoin/namecoin_spec.rb +0 -182
  119. data/spec/bitcoin/node/command_api_spec.rb +0 -663
  120. data/spec/bitcoin/storage/models_spec.rb +0 -104
  121. data/spec/bitcoin/storage/reorg_spec.rb +0 -236
  122. data/spec/bitcoin/storage/storage_spec.rb +0 -387
  123. data/spec/bitcoin/storage/validation_spec.rb +0 -300
  124. data/spec/bitcoin/wallet/coinselector_spec.rb +0 -38
  125. data/spec/bitcoin/wallet/keygenerator_spec.rb +0 -69
  126. data/spec/bitcoin/wallet/keystore_spec.rb +0 -190
  127. data/spec/bitcoin/wallet/txdp_spec.rb +0 -76
  128. data/spec/bitcoin/wallet/wallet_spec.rb +0 -238
@@ -265,6 +265,8 @@ describe 'Bitcoin::Script' do
265
265
  Script.new(SCRIPT[4]).is_p2sh?.should == false
266
266
  Script.new(SCRIPT[5]).is_p2sh?.should == true
267
267
  Script.new(SCRIPT[6]).is_p2sh?.should == false
268
+ Script.from_string("OP_DUP OP_HASH160 b689ebc262f50297139e7d16c4f8909e14ed4322 OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_HASH160 1b6246121883816fc0637e4aa280aca1df219b1a OP_EQUAL")
269
+ .is_p2sh?.should == false
268
270
  end
269
271
 
270
272
  it '#is_op_return?' do
@@ -371,6 +373,7 @@ describe 'Bitcoin::Script' do
371
373
 
372
374
  Script.to_pubkey_script_sig(@sig, pub).should == expected_script
373
375
  end
376
+
374
377
  it "should reject an improperly encoding public key" do
375
378
  # Not binary encoded, like it's supposed to be.
376
379
  pub = '02bc3e2b520d4be3e2651f2ba554392ea31edd69d2081186ab98acda3c4bf45e41'
@@ -379,6 +382,21 @@ describe 'Bitcoin::Script' do
379
382
  Script.to_pubkey_script_sig(@sig, pub)
380
383
  }.should.raise
381
384
  end
385
+
386
+ it "should support different hash types" do
387
+ hash_type = Script::SIGHASH_TYPE[:single]
388
+ pub = '04bc3e2b520d4be3e2651f2ba554392ea31edd69d2081186ab98acda3c4bf45e41a5f6e093277b774b5893347e38ffafce2b9e82226e6e0b378cf79b8c2eed983c'.htb
389
+ expected_script = '483045022062437a8f60651cd968137355775fa8bdb83d4ca717fdbc08bf9868a051e0542f022100f5cd626c15ef0de0803ddf299e8895743e7ff484d6335874edfe086ee0a08fec034104bc3e2b520d4be3e2651f2ba554392ea31edd69d2081186ab98acda3c4bf45e41a5f6e093277b774b5893347e38ffafce2b9e82226e6e0b378cf79b8c2eed983c'.htb
390
+
391
+ Script.to_pubkey_script_sig(@sig, pub, hash_type).should == expected_script
392
+ end
393
+
394
+ it "should generate multisig script sig" do
395
+ hash_type = Script::SIGHASH_TYPE[:none]
396
+ expected_script = '00483045022062437a8f60651cd968137355775fa8bdb83d4ca717fdbc08bf9868a051e0542f022100f5cd626c15ef0de0803ddf299e8895743e7ff484d6335874edfe086ee0a08fec02483045022062437a8f60651cd968137355775fa8bdb83d4ca717fdbc08bf9868a051e0542f022100f5cd626c15ef0de0803ddf299e8895743e7ff484d6335874edfe086ee0a08fec02'.htb
397
+
398
+ Script.to_multisig_script_sig(@sig, @sig, hash_type).should == expected_script
399
+ end
382
400
  end
383
401
 
384
402
 
@@ -635,4 +653,268 @@ OP_ENDIF")
635
653
  script.run.should == true
636
654
  end
637
655
 
656
+ def build_p2sh_multisig_tx(m, *keys)
657
+ redeem_script = Bitcoin::Script.to_multisig_script(m, *keys.map(&:pub))
658
+ p2sh_address = Bitcoin.hash160_to_p2sh_address(Bitcoin.hash160(redeem_script.hth))
659
+
660
+ prev_tx = build_tx {|t| t.input {|i| i.coinbase}
661
+ t.output {|o| o.to p2sh_address; o.value 50e8 } }
662
+ tx = build_tx {|t| t.input {|i| i.prev_out prev_tx, 0 }
663
+ t.output {|o| o.to Bitcoin::Key.generate.addr; o.value 50e8 } }
664
+
665
+ sig_hash = tx.signature_hash_for_input(0, redeem_script)
666
+ return prev_tx, tx, redeem_script, sig_hash
667
+ end
668
+
669
+ it "#sort_p2sh_multisig_signatures 3-of-3" do
670
+ keys = 3.times.map { Bitcoin::Key.generate }
671
+
672
+ prev_tx, tx, redeem_script, sig_hash = build_p2sh_multisig_tx(3, *keys)
673
+ sigs = keys.map {|k| k.sign(sig_hash) }
674
+
675
+ # add sigs in all possible orders, sort them, and see if they are valid
676
+ [0, 1, 2].permutation do |order|
677
+ script_sig = Script.to_p2sh_multisig_script_sig(redeem_script)
678
+ order.each{|i| script_sig = Script.add_sig_to_multisig_script_sig(sigs[i], script_sig)}
679
+ script_sig = Script.sort_p2sh_multisig_signatures(script_sig, sig_hash)
680
+ tx.in[0].script_sig = script_sig
681
+ tx.verify_input_signature(0, prev_tx).should == true
682
+ end
683
+ end
684
+
685
+ it "#sort_p2sh_multisig_signatures 2-of-3" do
686
+ keys = 3.times.map { Bitcoin::Key.generate }
687
+
688
+ prev_tx, tx, redeem_script, sig_hash = build_p2sh_multisig_tx(2, *keys)
689
+ sigs = keys.map {|k| k.sign(sig_hash) }
690
+
691
+ # add sigs in all possible orders, sort them, and see if they are valid
692
+ [0, 1, 2].permutation(2) do |order|
693
+ script_sig = Script.to_p2sh_multisig_script_sig(redeem_script)
694
+ order.each{|i| script_sig = Script.add_sig_to_multisig_script_sig(sigs[i], script_sig)}
695
+ script_sig = Script.sort_p2sh_multisig_signatures(script_sig, sig_hash)
696
+ tx.in[0].script_sig = script_sig
697
+ tx.verify_input_signature(0, prev_tx).should == true
698
+ end
699
+ end
700
+
701
+ end
702
+
703
+ describe "Implements BIP62" do
704
+ it 'tests for incorrectly encoded S-values in signatures' do
705
+ # TX 3da75972766f0ad13319b0b461fd16823a731e44f6e9de4eb3c52d6a6fb6c8ae
706
+ sig_orig = ["304502210088984573e3e4f33db7df6aea313f1ce67a3ef3532ea89991494c7f018258371802206ceefc9291450dbd40d834f249658e0f64662d52a41cf14e20c9781144f2fe0701"].pack("H*")
707
+ Bitcoin::Script::is_low_der_signature?(sig_orig).should == true
708
+
709
+ # Set the start of the S-value to 0xff so it's well above the order of the curve divided by two
710
+ sig = sig_orig.unpack("C*")
711
+ length_r = sig[3]
712
+ sig[6 + length_r] = 0xff
713
+
714
+ Bitcoin::Script::is_low_der_signature?(sig.pack("C*")).should == false
715
+ end
716
+ it 'enforces rules 3 and 4' do
717
+ Script.new([75].pack("C") + 'A' * 75).pushes_are_canonical?.should == true
718
+ Script.new([Bitcoin::Script::OP_PUSHDATA1, 75].pack("CC") + 'A' * 75).pushes_are_canonical?.should == false
719
+ Script.new([Bitcoin::Script::OP_PUSHDATA2, 255].pack("Cv") + 'A' * 255).pushes_are_canonical?.should == false
720
+ Script.new([Bitcoin::Script::OP_PUSHDATA4, 1645].pack("CV") + 'A' * 1645).pushes_are_canonical?.should == false
721
+ end
722
+ end
723
+
724
+ describe "Implements BIP66" do
725
+ def build_crediting_tx(script_pk)
726
+ tx = Bitcoin::P::Tx.new
727
+ input = Bitcoin::P::TxIn.new(nil, 0xffffffff, 2, "\x00\x00")
728
+ output = Bitcoin::P::TxOut.new(0, script_pk)
729
+ tx.add_in(input)
730
+ tx.add_out(output)
731
+ Bitcoin::P::Tx.new(tx.to_payload)
732
+ end
733
+
734
+ def build_spending_tx(script_sig, tx_credit)
735
+ tx = Bitcoin::P::Tx.new
736
+ input = Bitcoin::P::TxIn.new(tx_credit.binary_hash, 0, 2, script_sig)
737
+ output = Bitcoin::P::TxOut.new(0, '')
738
+ tx.add_in(input)
739
+ tx.add_out(output)
740
+ Bitcoin::P::Tx.new(tx.to_payload)
741
+ end
742
+
743
+ # essentially DoTest() from script_tests.cpp
744
+ def run_script_test(script_sig_str, script_pk_str, opts={})
745
+ script_sig = Bitcoin::Script.from_string(script_sig_str)
746
+ script_pk = Bitcoin::Script.from_string(script_pk_str)
747
+ tx_credit = build_crediting_tx(script_pk.raw)
748
+ tx = build_spending_tx(script_sig.raw, tx_credit)
749
+ tx.verify_input_signature(0, tx_credit, Time.now.to_i, opts)
750
+ end
751
+
752
+ it 'overly long signature fails with DERSIG passes without' do
753
+ script_sig = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
754
+ script_pk = "0 OP_CHECKSIG OP_NOT"
755
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
756
+ run_script_test(script_sig, script_pk).should == true
757
+ end
758
+
759
+ it 'missing S fails with DERSIG passes without' do
760
+ script_sig = "3022022000000000000000000000000000000000000000000000000000000000000000000"
761
+ script_pk = "0 OP_CHECKSIG OP_NOT"
762
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
763
+ run_script_test(script_sig, script_pk).should == true
764
+ end
765
+
766
+ it 'S with invalid fails with DERSIG passes without' do
767
+ script_sig = "3024021077777777777777777777777777777777020a7777777777777777777777777777777701"
768
+ script_pk = "0 OP_CHECKSIG OP_NOT"
769
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
770
+ run_script_test(script_sig, script_pk).should == true
771
+ end
772
+
773
+ it 'non-integer R fails with DERSIG passes without' do
774
+ script_sig = "302403107777777777777777777777777777777702107777777777777777777777777777777701"
775
+ script_pk = "0 OP_CHECKSIG OP_NOT"
776
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
777
+ run_script_test(script_sig, script_pk).should == true
778
+ end
779
+
780
+ it 'non-integer S fails with DERSIG passes without' do
781
+ script_sig = "302402107777777777777777777777777777777703107777777777777777777777777777777701"
782
+ script_pk = "0 OP_CHECKSIG OP_NOT"
783
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
784
+ run_script_test(script_sig, script_pk).should == true
785
+ end
786
+
787
+ it 'zero length R fails with DERSIG passes without' do
788
+ script_sig = "3014020002107777777777777777777777777777777701"
789
+ script_pk = "0 OP_CHECKSIG OP_NOT"
790
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
791
+ run_script_test(script_sig, script_pk).should == true
792
+ end
793
+
794
+ it 'zero length S fails with DERSIG passes without' do
795
+ script_sig = "3014021077777777777777777777777777777777020001"
796
+ script_pk = "0 OP_CHECKSIG OP_NOT"
797
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
798
+ run_script_test(script_sig, script_pk).should == true
799
+ end
800
+
801
+ it 'negative S fails with DERSIG passes without' do
802
+ script_sig = "302402107777777777777777777777777777777702108777777777777777777777777777777701"
803
+ script_pk = "0 OP_CHECKSIG OP_NOT"
804
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
805
+ run_script_test(script_sig, script_pk).should == true
806
+ end
807
+
808
+ # see: https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki#examples
809
+ # see also: https://github.com/bitcoin/bitcoin/pull/5713/files
810
+ P1 = "038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508"
811
+ P2 = "03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640"
812
+
813
+ # Example 1: S1' P1 CHECKSIG (fails w/ verify_dersig, passes w/o)
814
+ it 'example 1' do
815
+ script_sig = "30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201"
816
+ script_pk = "#{P1} OP_CHECKSIG"
817
+ run_script_test(script_sig, script_pk).should == true
818
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
819
+ end
820
+
821
+ # Example 2: S1' P1 CHECKSIG NOT (fails with either)
822
+ it 'example 2' do
823
+ script_sig = "304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01"
824
+ script_pk = "#{P1} OP_CHECKSIG OP_NOT"
825
+ run_script_test(script_sig, script_pk).should == false
826
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
827
+ end
828
+
829
+ # Example 3: F P1 CHECKSIG fails (fails with either)
830
+ it 'example 3' do
831
+ script_sig = "0"
832
+ script_pk = "#{P1} OP_CHECKSIG"
833
+ run_script_test(script_sig, script_pk).should == false
834
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
835
+ end
836
+
837
+ # Example 4: F P1 CHECKSIG NOT (passes with either)
838
+ it 'example 4' do
839
+ script_sig = "0"
840
+ script_pk = "#{P1} OP_CHECKSIG OP_NOT"
841
+ run_script_test(script_sig, script_pk).should == true
842
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == true
843
+ end
844
+
845
+ # Example 5: F' P1 CHECKSIG (fails with either)
846
+ it 'example 5' do
847
+ script_sig = "1"
848
+ script_pk = "#{P1} OP_CHECKSIG"
849
+ run_script_test(script_sig, script_pk).should == false
850
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
851
+ end
852
+
853
+ # Example 6: F' P1 CHECKSIG NOT (fails w/verify_dersig, passes w/o)
854
+ it 'example 6' do
855
+ script_sig = "1"
856
+ script_pk = "#{P1} OP_CHECKSIG OP_NOT"
857
+ run_script_test(script_sig, script_pk).should == true
858
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
859
+ end
860
+
861
+ # Example 7: 0 S1' S2 2 P1 P2 2 CHECKMULTISIG (fails w/verify_dersig, passes w/o)
862
+ it 'example 7' do
863
+ s1 = "30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501"
864
+ s2 = "304402200b3d0b0375bb15c14620afa4aa10ae90a0d6a046ce217bc20fe0bc1ced68c1b802204b550acab90ae6d3478057c9ad24f9df743815b799b6449dd7e7f6d3bc6e274c01"
865
+ script_sig = "0 #{s1} #{s2}"
866
+ script_pk = "2 #{P1} #{P2} 2 OP_CHECKMULTISIG"
867
+ run_script_test(script_sig, script_pk).should == true
868
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
869
+ end
870
+
871
+ # Example 8: 0 S1' S2 2 P1 P2 2 CHECKMULTISIG NOT (fails for either)
872
+ it 'example 8' do
873
+ s1 = "30440220f00a77260d34ec2f0c59621dc710f58169d0ca06df1a88cd4b1f1b97bd46991b02201ee220c7e04f26aed03f94aa97fb09ca5627163bf4ba07e6979972ec737db22601"
874
+ s2 = "3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801"
875
+ script_sig = "0 #{s1} #{s2}"
876
+ script_pk = "2 #{P1} #{P2} 2 OP_CHECKMULTISIG OP_NOT"
877
+ run_script_test(script_sig, script_pk).should == false
878
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
879
+ end
880
+
881
+ # Example 9: 0 F S2' 2 P1 P2 2 CHECKMULTISIG fails (fails for either)
882
+ it 'example 9' do
883
+ s1 = "0"
884
+ s2 = "3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01"
885
+ script_sig = "0 #{s1} #{s2}"
886
+ script_pk = "2 #{P1} #{P2} 2 OP_CHECKMULTISIG"
887
+ run_script_test(script_sig, script_pk).should == false
888
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
889
+ end
890
+
891
+ # Example 10: 0 F S2' 2 P1 P2 2 CHECKMULTISIG NOT (fails w/verify_dersig, passes w/o)
892
+ it 'example 10' do
893
+ s1 = "0"
894
+ s2 = "30440220afa76a8f60622f813b05711f051c6c3407e32d1b1b70b0576c1f01b54e4c05c702200d58e9df044fd1845cabfbeef6e624ba0401daf7d7e084736f9ff601c3783bf501"
895
+ script_sig = "0 #{s1} #{s2}"
896
+ script_pk = "2 #{P1} #{P2} 2 OP_CHECKMULTISIG OP_NOT"
897
+ run_script_test(script_sig, script_pk).should == true
898
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
899
+ end
900
+
901
+ # Example 11: 0 S1' F 2 P1 P2 2 CHECKMULTISIG (fails for either)
902
+ it 'example 11' do
903
+ s1 = "30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501"
904
+ s2 = "0"
905
+ script_sig = "0 #{s1} #{s2}"
906
+ script_pk = "2 #{P1} #{P2} 2 OP_CHECKMULTISIG"
907
+ run_script_test(script_sig, script_pk).should == false
908
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == false
909
+ end
910
+
911
+ # Example 12: 0 S1' F 2 P1 P2 2 CHECKMULTISIG NOT (passes for either)
912
+ it 'example 12' do
913
+ s1 = "30440220f00a77260d34ec2f0c59621dc710f58169d0ca06df1a88cd4b1f1b97bd46991b02201ee220c7e04f26aed03f94aa97fb09ca5627163bf4ba07e6979972ec737db22601"
914
+ s2 = "0"
915
+ script_sig = "0 #{s1} #{s2}"
916
+ script_pk = "2 #{P1} #{P2} 2 OP_CHECKMULTISIG OP_NOT"
917
+ run_script_test(script_sig, script_pk).should == true
918
+ run_script_test(script_sig, script_pk, {verify_dersig: true}).should == true
919
+ end
638
920
  end
@@ -0,0 +1,48 @@
1
+ # encoding: ascii-8bit
2
+
3
+ require_relative 'spec_helper.rb'
4
+ require 'bitcoin'
5
+
6
+ describe 'libsecp256k1' do
7
+
8
+ it 'generate key pair' do
9
+ priv, pub = Bitcoin::Secp256k1.generate_key_pair(compressed = true)
10
+ [priv, pub].map(&:bytesize).should == [32, 33]
11
+ ["\x03", "\x02"].include?(pub[0]).should == true
12
+
13
+ priv, pub = Bitcoin::Secp256k1.generate_key_pair(compressed = false)
14
+ [priv, pub].map(&:bytesize).should == [32, 65]
15
+ ["\x04"].include?(pub[0]).should == true
16
+ end
17
+
18
+ it 'sign and verify' do
19
+ priv, pub = Bitcoin::Secp256k1.generate_key_pair
20
+ signature = Bitcoin::Secp256k1.sign("derp", priv)
21
+ Bitcoin::Secp256k1.verify("derp", signature, pub).should == true
22
+ end
23
+
24
+ it 'sign compact and recover' do
25
+ priv, pub = Bitcoin::Secp256k1.generate_key_pair(compressed=true)
26
+ signature = Bitcoin::Secp256k1.sign_compact("derp", priv, compressed=true)
27
+ signature.bytesize.should == 65
28
+ pub2 = Bitcoin::Secp256k1.recover_compact("derp", signature)
29
+ pub2.bytesize.should == 33
30
+ pub2.should == pub
31
+
32
+ # uncompressed
33
+ priv, pub = Bitcoin::Secp256k1.generate_key_pair(compressed=false)
34
+ signature = Bitcoin::Secp256k1.sign_compact("derp", priv, compressed=false)
35
+ signature.bytesize.should == 65
36
+ pub2 = Bitcoin::Secp256k1.recover_compact("derp", signature)
37
+ pub2.bytesize.should == 65
38
+ pub2.should == pub
39
+ end
40
+
41
+ it 'deterministic signature using rfc6979' do
42
+ priv, pub = Bitcoin::Secp256k1.generate_key_pair
43
+ first = Bitcoin::Secp256k1.sign("derp", priv)
44
+ second = Bitcoin::Secp256k1.sign("derp", priv)
45
+ first.should == second
46
+ end
47
+
48
+ end
@@ -9,8 +9,6 @@ begin
9
9
  ["bitcoin.rb", "opcodes.rb", "script.rb", "key.rb"].include?(file.filename.split("/").last)
10
10
  end
11
11
  add_group "Protocol", "lib/bitcoin/protocol"
12
- add_group "Storage", "lib/bitcoin/storage"
13
- add_group "Wallet", "lib/bitcoin/wallet"
14
12
  add_group("Utilities") do |file|
15
13
  ["logger.rb", "openssl.rb"].include?(file.filename.split("/").last)
16
14
  end
@@ -49,33 +47,6 @@ def create_block prev, store = true, tx = [], key = Bitcoin::Key.generate, coinb
49
47
  block
50
48
  end
51
49
 
52
- # create transaction given builder +tx+
53
- # +outputs+ is an array of [value, key] pairs
54
- def create_tx(tx, prev_tx, prev_out_index, outputs, key = @key)
55
- tx.input {|i| i.prev_out prev_tx; i.prev_out_index prev_out_index; i.signature_key key }
56
- outputs.each do |value, key|
57
- tx.output {|o| o.value value; o.script {|s| s.recipient key.addr } }
58
- end
59
- end
60
-
61
- # create a chain of +n+ blocks, based on +prev_hash+ block.
62
- # influence chain properties via options:
63
- # time: start time all other times are based on
64
- # interval: time between blocks
65
- # bits: target bits each block must match
66
- def create_blocks prev_hash, n, opts = {}
67
- interval = opts[:interval] || 600
68
- time = opts[:time] || Time.now.to_i
69
- bits = opts[:bits] || 553713663
70
- block = @store.get_block(prev_hash)
71
- n.times do |i|
72
- block = create_block block.hash, true, [], @key, 50e8, {
73
- time: time += interval, bits: bits }
74
- # block = @store.get_block(block.hash)
75
- # puts "#{i} #{block.hash[0..8]} #{block.prev_block.reverse_hth[0..8]} #{Time.at(block.time).strftime('%Y-%m-%d %H:%M:%S')} c: #{block.chain} b: #{block.bits} n: #{block.nonce} w: #{block.work}"
76
- end
77
- block
78
- end
79
50
 
80
51
 
81
52
  Bitcoin::network = :bitcoin
@@ -112,28 +83,6 @@ end
112
83
  Bacon.summary_on_exit
113
84
  require 'minitest/mock'
114
85
 
115
- require 'sequel'
116
- def setup_db backend, db = nil, conf = {}
117
- uri = case db
118
- when :sqlite
119
- "sqlite:/"
120
- when :postgres
121
- ENV["TEST_DB_POSTGRES"].dup rescue nil
122
- when :mysql
123
- ENV["TEST_DB_MYSQL"].dup rescue nil
124
- end
125
- if [:postgres, :mysql].include?(db)
126
- unless uri
127
- puts "Skipping #{db} tests"
128
- return nil
129
- end
130
- db = Sequel.connect(uri)
131
- db.drop_table(*db.tables, cascade: true)
132
- end
133
- Bitcoin::Storage.send(backend, conf.merge(db: uri, log_level: :warn))
134
- end
135
-
136
-
137
86
  class Time
138
87
  class << self
139
88
  alias_method :real_new, :new
@@ -0,0 +1,161 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe "Bitcoin::Trezor::Mnemonic" do
4
+
5
+ # https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki#Test_vectors
6
+ # https://github.com/trezor/python-mnemonic/blob/master/vectors.json
7
+
8
+ it "test vectors" do
9
+ [
10
+ [
11
+ "00000000000000000000000000000000",
12
+ "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
13
+ "c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04"
14
+ ],
15
+ [
16
+ "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
17
+ "legal winner thank year wave sausage worth useful legal winner thank yellow",
18
+ "2e8905819b8723fe2c1d161860e5ee1830318dbf49a83bd451cfb8440c28bd6fa457fe1296106559a3c80937a1c1069be3a3a5bd381ee6260e8d9739fce1f607"
19
+ ],
20
+ [
21
+ "80808080808080808080808080808080",
22
+ "letter advice cage absurd amount doctor acoustic avoid letter advice cage above",
23
+ "d71de856f81a8acc65e6fc851a38d4d7ec216fd0796d0a6827a3ad6ed5511a30fa280f12eb2e47ed2ac03b5c462a0358d18d69fe4f985ec81778c1b370b652a8"
24
+ ],
25
+ [
26
+ "ffffffffffffffffffffffffffffffff",
27
+ "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong",
28
+ "ac27495480225222079d7be181583751e86f571027b0497b5b5d11218e0a8a13332572917f0f8e5a589620c6f15b11c61dee327651a14c34e18231052e48c069"
29
+ ],
30
+ [
31
+ "000000000000000000000000000000000000000000000000",
32
+ "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent",
33
+ "035895f2f481b1b0f01fcf8c289c794660b289981a78f8106447707fdd9666ca06da5a9a565181599b79f53b844d8a71dd9f439c52a3d7b3e8a79c906ac845fa"
34
+ ],
35
+ [
36
+ "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
37
+ "legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal will",
38
+ "f2b94508732bcbacbcc020faefecfc89feafa6649a5491b8c952cede496c214a0c7b3c392d168748f2d4a612bada0753b52a1c7ac53c1e93abd5c6320b9e95dd"
39
+ ],
40
+ [
41
+ "808080808080808080808080808080808080808080808080",
42
+ "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter always",
43
+ "107d7c02a5aa6f38c58083ff74f04c607c2d2c0ecc55501dadd72d025b751bc27fe913ffb796f841c49b1d33b610cf0e91d3aa239027f5e99fe4ce9e5088cd65"
44
+ ],
45
+ [
46
+ "ffffffffffffffffffffffffffffffffffffffffffffffff",
47
+ "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo when",
48
+ "0cd6e5d827bb62eb8fc1e262254223817fd068a74b5b449cc2f667c3f1f985a76379b43348d952e2265b4cd129090758b3e3c2c49103b5051aac2eaeb890a528"
49
+ ],
50
+ [
51
+ "0000000000000000000000000000000000000000000000000000000000000000",
52
+ "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art",
53
+ "bda85446c68413707090a52022edd26a1c9462295029f2e60cd7c4f2bbd3097170af7a4d73245cafa9c3cca8d561a7c3de6f5d4a10be8ed2a5e608d68f92fcc8"
54
+ ],
55
+ [
56
+ "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
57
+ "legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth title",
58
+ "bc09fca1804f7e69da93c2f2028eb238c227f2e9dda30cd63699232578480a4021b146ad717fbb7e451ce9eb835f43620bf5c514db0f8add49f5d121449d3e87"
59
+ ],
60
+ [
61
+ "8080808080808080808080808080808080808080808080808080808080808080",
62
+ "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic bless",
63
+ "c0c519bd0e91a2ed54357d9d1ebef6f5af218a153624cf4f2da911a0ed8f7a09e2ef61af0aca007096df430022f7a2b6fb91661a9589097069720d015e4e982f"
64
+ ],
65
+ [
66
+ "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
67
+ "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote",
68
+ "dd48c104698c30cfe2b6142103248622fb7bb0ff692eebb00089b32d22484e1613912f0a5b694407be899ffd31ed3992c456cdf60f5d4564b8ba3f05a69890ad"
69
+ ],
70
+ [
71
+ "77c2b00716cec7213839159e404db50d",
72
+ "jelly better achieve collect unaware mountain thought cargo oxygen act hood bridge",
73
+ "b5b6d0127db1a9d2226af0c3346031d77af31e918dba64287a1b44b8ebf63cdd52676f672a290aae502472cf2d602c051f3e6f18055e84e4c43897fc4e51a6ff"
74
+ ],
75
+ [
76
+ "b63a9c59a6e641f288ebc103017f1da9f8290b3da6bdef7b",
77
+ "renew stay biology evidence goat welcome casual join adapt armor shuffle fault little machine walk stumble urge swap",
78
+ "9248d83e06f4cd98debf5b6f010542760df925ce46cf38a1bdb4e4de7d21f5c39366941c69e1bdbf2966e0f6e6dbece898a0e2f0a4c2b3e640953dfe8b7bbdc5"
79
+ ],
80
+ [
81
+ "3e141609b97933b66a060dcddc71fad1d91677db872031e85f4c015c5e7e8982",
82
+ "dignity pass list indicate nasty swamp pool script soccer toe leaf photo multiply desk host tomato cradle drill spread actor shine dismiss champion exotic",
83
+ "ff7f3184df8696d8bef94b6c03114dbee0ef89ff938712301d27ed8336ca89ef9635da20af07d4175f2bf5f3de130f39c9d9e8dd0472489c19b1a020a940da67"
84
+ ],
85
+ [
86
+ "0460ef47585604c5660618db2e6a7e7f",
87
+ "afford alter spike radar gate glance object seek swamp infant panel yellow",
88
+ "65f93a9f36b6c85cbe634ffc1f99f2b82cbb10b31edc7f087b4f6cb9e976e9faf76ff41f8f27c99afdf38f7a303ba1136ee48a4c1e7fcd3dba7aa876113a36e4"
89
+ ],
90
+ [
91
+ "72f60ebac5dd8add8d2a25a797102c3ce21bc029c200076f",
92
+ "indicate race push merry suffer human cruise dwarf pole review arch keep canvas theme poem divorce alter left",
93
+ "3bbf9daa0dfad8229786ace5ddb4e00fa98a044ae4c4975ffd5e094dba9e0bb289349dbe2091761f30f382d4e35c4a670ee8ab50758d2c55881be69e327117ba"
94
+ ],
95
+ [
96
+ "2c85efc7f24ee4573d2b81a6ec66cee209b2dcbd09d8eddc51e0215b0b68e416",
97
+ "clutch control vehicle tonight unusual clog visa ice plunge glimpse recipe series open hour vintage deposit universe tip job dress radar refuse motion taste",
98
+ "fe908f96f46668b2d5b37d82f558c77ed0d69dd0e7e043a5b0511c48c2f1064694a956f86360c93dd04052a8899497ce9e985ebe0c8c52b955e6ae86d4ff4449"
99
+ ],
100
+ [
101
+ "eaebabb2383351fd31d703840b32e9e2",
102
+ "turtle front uncle idea crush write shrug there lottery flower risk shell",
103
+ "bdfb76a0759f301b0b899a1e3985227e53b3f51e67e3f2a65363caedf3e32fde42a66c404f18d7b05818c95ef3ca1e5146646856c461c073169467511680876c"
104
+ ],
105
+ [
106
+ "7ac45cfe7722ee6c7ba84fbc2d5bd61b45cb2fe5eb65aa78",
107
+ "kiss carry display unusual confirm curtain upgrade antique rotate hello void custom frequent obey nut hole price segment",
108
+ "ed56ff6c833c07982eb7119a8f48fd363c4a9b1601cd2de736b01045c5eb8ab4f57b079403485d1c4924f0790dc10a971763337cb9f9c62226f64fff26397c79"
109
+ ],
110
+ [
111
+ "4fa1a8bc3e6d80ee1316050e862c1812031493212b7ec3f3bb1b08f168cabeef",
112
+ "exile ask congress lamp submit jacket era scheme attend cousin alcohol catch course end lucky hurt sentence oven short ball bird grab wing top",
113
+ "095ee6f817b4c2cb30a5a797360a81a40ab0f9a4e25ecd672a3f58a0b5ba0687c096a6b14d2c0deb3bdefce4f61d01ae07417d502429352e27695163f7447a8c"
114
+ ],
115
+ [
116
+ "18ab19a9f54a9274f03e5209a2ac8a91",
117
+ "board flee heavy tunnel powder denial science ski answer betray cargo cat",
118
+ "6eff1bb21562918509c73cb990260db07c0ce34ff0e3cc4a8cb3276129fbcb300bddfe005831350efd633909f476c45c88253276d9fd0df6ef48609e8bb7dca8"
119
+ ],
120
+ [
121
+ "18a2e1d81b8ecfb2a333adcb0c17a5b9eb76cc5d05db91a4",
122
+ "board blade invite damage undo sun mimic interest slam gaze truly inherit resist great inject rocket museum chief",
123
+ "f84521c777a13b61564234bf8f8b62b3afce27fc4062b51bb5e62bdfecb23864ee6ecf07c1d5a97c0834307c5c852d8ceb88e7c97923c0a3b496bedd4e5f88a9"
124
+ ],
125
+ [
126
+ "15da872c95a13dd738fbf50e427583ad61f18fd99f628c417a61cf8343c90419",
127
+ "beyond stage sleep clip because twist token leaf atom beauty genius food business side grid unable middle armed observe pair crouch tonight away coconut",
128
+ "b15509eaa2d09d3efd3e006ef42151b30367dc6e3aa5e44caba3fe4d3e352e65101fbdb86a96776b91946ff06f8eac594dc6ee1d3e82a42dfe1b40fef6bcc3fd"
129
+ ]
130
+ ].each{|data,expected_mnemonic,expected_seed|
131
+ mnemonic = Bitcoin::Trezor::Mnemonic.to_mnemonic( [data].pack("H*") )
132
+ mnemonic.should == expected_mnemonic
133
+ Bitcoin::Trezor::Mnemonic.to_seed(expected_mnemonic, 'TREZOR').should == expected_seed
134
+ }
135
+ end
136
+
137
+ =begin
138
+ it 'test utf8 nfkd' do
139
+ # The same sentence in various UTF-8 forms
140
+ words_nfkd = "Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a"
141
+ words_nfc = "P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f"
142
+ words_nfkc = "P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f"
143
+ words_nfd = "Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a"
144
+
145
+ passphrase_nfkd = "Neuve\u030cr\u030citelne\u030c bezpec\u030cne\u0301 hesli\u0301c\u030cko"
146
+ passphrase_nfc = "Neuv\u011b\u0159iteln\u011b bezpe\u010dn\xe9 hesl\xed\u010dko"
147
+ passphrase_nfkc = "Neuv\u011b\u0159iteln\u011b bezpe\u010dn\xe9 hesl\xed\u010dko"
148
+ passphrase_nfd = "Neuve\u030cr\u030citelne\u030c bezpec\u030cne\u0301 hesli\u0301c\u030cko"
149
+
150
+ seed_nfkd = Bitcoin::Trezor::Mnemonic.to_seed(words_nfkd, passphrase_nfkd)
151
+ seed_nfc = Bitcoin::Trezor::Mnemonic.to_seed(words_nfc, passphrase_nfc)
152
+ seed_nfkc = Bitcoin::Trezor::Mnemonic.to_seed(words_nfkc, passphrase_nfkc)
153
+ seed_nfd = Bitcoin::Trezor::Mnemonic.to_seed(words_nfd, passphrase_nfd)
154
+
155
+ seed_nfkd.should == seed_nfc
156
+ seed_nfkd.should == seed_nfkc
157
+ seed_nfkd.should == seed_nfd
158
+ end
159
+ =end
160
+
161
+ end