bitcoin-ruby 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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