money-tree 0.10.0 → 0.11.1
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.
- checksums.yaml +4 -4
- data/{donation_btc_qr_code.gif → .github/donation_btc_qr_code.gif} +0 -0
- data/.github/workflows/spec.yml +33 -0
- data/Gemfile +15 -3
- data/README.md +14 -4
- data/Rakefile +2 -2
- data/checksum/money-tree-0.11.0.gem.sha512 +1 -0
- data/checksum/money-tree-0.9.0.gem.sha512 +1 -1
- data/lib/money-tree/address.rb +16 -6
- data/lib/money-tree/key.rb +32 -25
- data/lib/money-tree/networks.rb +16 -15
- data/lib/money-tree/node.rb +49 -39
- data/lib/money-tree/support.rb +59 -34
- data/lib/money-tree/version.rb +1 -1
- data/lib/money-tree.rb +6 -7
- data/lib/openssl_extensions.rb +11 -54
- data/money-tree.gemspec +22 -30
- data/spec/{lib/money-tree → money-tree}/address_spec.rb +42 -8
- data/spec/money-tree/money_tree_spec.rb +9 -0
- data/spec/{lib/money-tree → money-tree}/node_spec.rb +425 -15
- data/spec/money-tree/openssl_extensions_spec.rb +71 -0
- data/spec/{lib/money-tree → money-tree}/private_key_spec.rb +27 -27
- data/spec/{lib/money-tree → money-tree}/public_key_spec.rb +81 -40
- data/spec/{lib/money-tree → money-tree}/support_spec.rb +4 -4
- data/spec/spec_helper.rb +15 -3
- metadata +37 -150
- checksums.yaml.gz.sig +0 -0
- data/.simplecov +0 -7
- data/.travis.yml +0 -3
- data/spec/lib/money-tree/openssl_extensions_spec.rb +0 -23
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -0
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
# Test vectors from https://en.bitcoin.it/wiki/BIP_0032_TestVectors
|
4
4
|
describe MoneyTree::Master do
|
@@ -28,11 +28,11 @@ describe MoneyTree::Master do
|
|
28
28
|
end
|
29
29
|
|
30
30
|
it "generates testnet compressed wif" do
|
31
|
-
expect(@master.private_key.to_wif(network: :bitcoin_testnet)[0]).to eql(
|
31
|
+
expect(@master.private_key.to_wif(network: :bitcoin_testnet)[0]).to eql("c")
|
32
32
|
end
|
33
33
|
|
34
34
|
it "generates testnet uncompressed wif" do
|
35
|
-
expect(@master.private_key.to_wif(compressed: false, network: :bitcoin_testnet)[0]).to eql(
|
35
|
+
expect(@master.private_key.to_wif(compressed: false, network: :bitcoin_testnet)[0]).to eql("9")
|
36
36
|
end
|
37
37
|
|
38
38
|
it "generates testnet serialized private address" do
|
@@ -44,29 +44,29 @@ describe MoneyTree::Master do
|
|
44
44
|
end
|
45
45
|
|
46
46
|
it "imports from testnet serialized private address" do
|
47
|
-
node = MoneyTree::Node.from_bip32
|
48
|
-
expect(node.to_bip32(:private, network: :bitcoin_testnet)).to eql(
|
47
|
+
node = MoneyTree::Node.from_bip32 "tprv8ZgxMBicQKsPcuN7bfUZqq78UEYapr3Tzmc9NcDXw8BnBJ47dZYr6SusnfYj7vbAYP9CP8ZiD5aVBTUo1yU5QP56mepKVvuEbu8KZQXMKNE"
|
48
|
+
expect(node.to_bip32(:private, network: :bitcoin_testnet)).to eql("tprv8ZgxMBicQKsPcuN7bfUZqq78UEYapr3Tzmc9NcDXw8BnBJ47dZYr6SusnfYj7vbAYP9CP8ZiD5aVBTUo1yU5QP56mepKVvuEbu8KZQXMKNE")
|
49
49
|
end
|
50
50
|
|
51
51
|
it "imports from testnet serialized public address" do
|
52
|
-
node = MoneyTree::Node.from_bip32
|
52
|
+
node = MoneyTree::Node.from_bip32 "tpubD6NzVbkrYhZ4YA8aUE9bBZTSyHJibBqwDny5urfwDdJc4W8od3y3Ebzy6CqsYn9CCC5P5VQ7CeZYpnT1kX3RPVPysU2rFRvYSj8BCoYYNqT"
|
53
53
|
expect(%w(m n)).to include(node.public_key.to_s(network: :bitcoin_testnet)[0])
|
54
|
-
expect(node.to_bip32(network: :bitcoin_testnet)).to eql(
|
54
|
+
expect(node.to_bip32(network: :bitcoin_testnet)).to eql("tpubD6NzVbkrYhZ4YA8aUE9bBZTSyHJibBqwDny5urfwDdJc4W8od3y3Ebzy6CqsYn9CCC5P5VQ7CeZYpnT1kX3RPVPysU2rFRvYSj8BCoYYNqT")
|
55
55
|
end
|
56
56
|
|
57
57
|
it "generates testnet subnodes from serialized private address" do
|
58
|
-
node = MoneyTree::Node.from_bip32
|
59
|
-
subnode = node.node_for_path(
|
58
|
+
node = MoneyTree::Node.from_bip32 "tprv8ZgxMBicQKsPcuN7bfUZqq78UEYapr3Tzmc9NcDXw8BnBJ47dZYr6SusnfYj7vbAYP9CP8ZiD5aVBTUo1yU5QP56mepKVvuEbu8KZQXMKNE"
|
59
|
+
subnode = node.node_for_path("1/1/1")
|
60
60
|
expect(%w(m n)).to include(subnode.public_key.to_s(network: :bitcoin_testnet)[0])
|
61
|
-
expect(subnode.to_bip32(:private, network: :bitcoin_testnet).slice(0,4)).to eql(
|
62
|
-
expect(subnode.to_bip32(network: :bitcoin_testnet).slice(0,4)).to eql(
|
61
|
+
expect(subnode.to_bip32(:private, network: :bitcoin_testnet).slice(0, 4)).to eql("tprv")
|
62
|
+
expect(subnode.to_bip32(network: :bitcoin_testnet).slice(0, 4)).to eql("tpub")
|
63
63
|
end
|
64
64
|
|
65
65
|
it "generates testnet subnodes from serialized public address" do
|
66
|
-
node = MoneyTree::Node.from_bip32
|
67
|
-
subnode = node.node_for_path(
|
66
|
+
node = MoneyTree::Node.from_bip32 "tpubD6NzVbkrYhZ4YA8aUE9bBZTSyHJibBqwDny5urfwDdJc4W8od3y3Ebzy6CqsYn9CCC5P5VQ7CeZYpnT1kX3RPVPysU2rFRvYSj8BCoYYNqT"
|
67
|
+
subnode = node.node_for_path("1/1/1")
|
68
68
|
expect(%w(m n)).to include(subnode.public_key.to_s(network: :bitcoin_testnet)[0])
|
69
|
-
expect(subnode.to_bip32(network: :bitcoin_testnet).slice(0,4)).to eql(
|
69
|
+
expect(subnode.to_bip32(network: :bitcoin_testnet).slice(0, 4)).to eql("tpub")
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
@@ -93,6 +93,8 @@ describe MoneyTree::Master do
|
|
93
93
|
expect(@master.to_identifier).to eql("3442193e1bb70916e914552172cd4e2dbc9df811")
|
94
94
|
expect(@master.to_fingerprint).to eql("3442193e")
|
95
95
|
expect(@master.to_address).to eql("15mKKb2eos1hWa6tisdPwwDC1a5J1y9nma")
|
96
|
+
expect(@master.to_p2wpkh_p2sh).to eql("3PpgpssV7mcAGpZRWiCWhodUTnjpoSZg7a")
|
97
|
+
expect(@master.to_bech32_address).to eql("bc1qx3ppj0smkuy3d6g525sh9n2w9k7fm7q3x30rtg")
|
96
98
|
end
|
97
99
|
|
98
100
|
it "generates a secret key" do
|
@@ -140,6 +142,8 @@ describe MoneyTree::Master do
|
|
140
142
|
expect(@node.to_identifier).to eql("5c1bd648ed23aa5fd50ba52b2457c11e9e80a6a7")
|
141
143
|
expect(@node.to_fingerprint).to eql("5c1bd648")
|
142
144
|
expect(@node.to_address).to eql("19Q2WoS5hSS6T8GjhK8KZLMgmWaq4neXrh")
|
145
|
+
expect(@node.to_p2wpkh_p2sh).to eql("3AbBmNbPDSzeZKHywDrH3h5v2rL8xGfT7e")
|
146
|
+
expect(@node.to_bech32_address).to eql("bc1qtsdavj8dyw49l4gt554jg47pr60gpf48ww2ens")
|
143
147
|
end
|
144
148
|
|
145
149
|
it "generates a private key" do
|
@@ -187,6 +191,8 @@ describe MoneyTree::Master do
|
|
187
191
|
expect(@node.to_identifier).to eql("5c1bd648ed23aa5fd50ba52b2457c11e9e80a6a7")
|
188
192
|
expect(@node.to_fingerprint).to eql("5c1bd648")
|
189
193
|
expect(@node.to_address).to eql("19Q2WoS5hSS6T8GjhK8KZLMgmWaq4neXrh")
|
194
|
+
expect(@node.to_p2wpkh_p2sh).to eql("3AbBmNbPDSzeZKHywDrH3h5v2rL8xGfT7e")
|
195
|
+
expect(@node.to_bech32_address).to eql("bc1qtsdavj8dyw49l4gt554jg47pr60gpf48ww2ens")
|
190
196
|
end
|
191
197
|
|
192
198
|
it "does not generate a private key" do
|
@@ -232,6 +238,8 @@ describe MoneyTree::Master do
|
|
232
238
|
expect(@node.to_identifier).to eql("bef5a2f9a56a94aab12459f72ad9cf8cf19c7bbe")
|
233
239
|
expect(@node.to_fingerprint).to eql("bef5a2f9")
|
234
240
|
expect(@node.to_address).to eql("1JQheacLPdM5ySCkrZkV66G2ApAXe1mqLj")
|
241
|
+
expect(@node.to_p2wpkh_p2sh).to eql("3DymAvEWH38HuzHZ3VwLus673bNZnYwNXu")
|
242
|
+
expect(@node.to_bech32_address).to eql("bc1qhm6697d9d2224vfyt8mj4kw03ncec7a7fdafvt")
|
235
243
|
end
|
236
244
|
|
237
245
|
it "generates a private key" do
|
@@ -279,6 +287,8 @@ describe MoneyTree::Master do
|
|
279
287
|
expect(@node.to_identifier).to eql("bef5a2f9a56a94aab12459f72ad9cf8cf19c7bbe")
|
280
288
|
expect(@node.to_fingerprint).to eql("bef5a2f9")
|
281
289
|
expect(@node.to_address).to eql("1JQheacLPdM5ySCkrZkV66G2ApAXe1mqLj")
|
290
|
+
expect(@node.to_p2wpkh_p2sh).to eql("3DymAvEWH38HuzHZ3VwLus673bNZnYwNXu")
|
291
|
+
expect(@node.to_bech32_address).to eql("bc1qhm6697d9d2224vfyt8mj4kw03ncec7a7fdafvt")
|
282
292
|
end
|
283
293
|
|
284
294
|
it "does not generate a private key" do
|
@@ -324,6 +334,8 @@ describe MoneyTree::Master do
|
|
324
334
|
expect(@node.to_identifier).to eql("d880d7d893848509a62d8fb74e32148dac68412f")
|
325
335
|
expect(@node.to_fingerprint).to eql("d880d7d8")
|
326
336
|
expect(@node.to_address).to eql("1LjmJcdPnDHhNTUgrWyhLGnRDKxQjoxAgt")
|
337
|
+
expect(@node.to_p2wpkh_p2sh).to eql("3PxPuCJMQGgkPYArciuUFakdiKC58j3Df6")
|
338
|
+
expect(@node.to_bech32_address).to eql("bc1qmzqd0kynsjzsnf3d37m5uvs53kkxssf0dr5zvn")
|
327
339
|
end
|
328
340
|
|
329
341
|
it "generates a private key" do
|
@@ -371,6 +383,8 @@ describe MoneyTree::Master do
|
|
371
383
|
expect(@node.to_identifier).to eql("d69aa102255fed74378278c7812701ea641fdf32")
|
372
384
|
expect(@node.to_fingerprint).to eql("d69aa102")
|
373
385
|
expect(@node.to_address).to eql("1LZiqrop2HGR4qrH1ULZPyBpU6AUP49Uam")
|
386
|
+
expect(@node.to_p2wpkh_p2sh).to eql("3BuqWierKkrD7XEeJL4hucMGqVCe5G4WK7")
|
387
|
+
expect(@node.to_bech32_address).to eql("bc1q66d2zq39tlkhgduz0rrczfcpafjplhejmtgugz")
|
374
388
|
end
|
375
389
|
|
376
390
|
it "generates a private key" do
|
@@ -422,10 +436,14 @@ describe MoneyTree::Master do
|
|
422
436
|
expect(@master.to_identifier).to eql("bd16bee53961a47d6ad888e29545434a89bdfe95")
|
423
437
|
expect(@master.to_fingerprint).to eql("bd16bee5")
|
424
438
|
expect(@master.to_address).to eql("1JEoxevbLLG8cVqeoGKQiAwoWbNYSUyYjg")
|
439
|
+
expect(@master.to_p2wpkh_p2sh).to eql("3QaGQQTfBvSxXnsggeGxF3zfTAo3uyeREG")
|
440
|
+
expect(@master.to_bech32_address).to eql("bc1qh5ttaefevxj866kc3r3f232rf2ymml54ypyvy3")
|
425
441
|
end
|
426
442
|
|
427
443
|
it "generates compressed and uncompressed addresses" do
|
428
444
|
expect(@master.to_address).to eql("1JEoxevbLLG8cVqeoGKQiAwoWbNYSUyYjg")
|
445
|
+
expect(@master.to_p2wpkh_p2sh).to eql("3QaGQQTfBvSxXnsggeGxF3zfTAo3uyeREG")
|
446
|
+
expect(@master.to_bech32_address).to eql("bc1qh5ttaefevxj866kc3r3f232rf2ymml54ypyvy3")
|
429
447
|
expect(@master.to_address(true)).to eql("1JEoxevbLLG8cVqeoGKQiAwoWbNYSUyYjg")
|
430
448
|
expect(@master.to_address(false)).to eql("1AEg9dFEw29kMgaN4BNHALu7AzX5XUfzSU")
|
431
449
|
end
|
@@ -476,6 +494,8 @@ describe MoneyTree::Master do
|
|
476
494
|
expect(@node.to_identifier).to eql("5a61ff8eb7aaca3010db97ebda76121610b78096")
|
477
495
|
expect(@node.to_fingerprint).to eql("5a61ff8e")
|
478
496
|
expect(@node.to_address).to eql("19EuDJdgfRkwCmRzbzVBHZWQG9QNWhftbZ")
|
497
|
+
expect(@node.to_p2wpkh_p2sh).to eql("39cFMGtVaEw6AfksMcaLpu8frZxmqngh8c")
|
498
|
+
expect(@node.to_bech32_address).to eql("bc1qtfsllr4h4t9rqyxmjl4a5asjzcgt0qykp3q3we")
|
479
499
|
end
|
480
500
|
|
481
501
|
it "generates a private key" do
|
@@ -524,6 +544,8 @@ describe MoneyTree::Master do
|
|
524
544
|
expect(@node.to_identifier).to eql("5a61ff8eb7aaca3010db97ebda76121610b78096")
|
525
545
|
expect(@node.to_fingerprint).to eql("5a61ff8e")
|
526
546
|
expect(@node.to_address).to eql("19EuDJdgfRkwCmRzbzVBHZWQG9QNWhftbZ")
|
547
|
+
expect(@node.to_p2wpkh_p2sh).to eql("39cFMGtVaEw6AfksMcaLpu8frZxmqngh8c")
|
548
|
+
expect(@node.to_bech32_address).to eql("bc1qtfsllr4h4t9rqyxmjl4a5asjzcgt0qykp3q3we")
|
527
549
|
end
|
528
550
|
|
529
551
|
it "does not generate a private key" do
|
@@ -570,6 +592,8 @@ describe MoneyTree::Master do
|
|
570
592
|
expect(@node.to_identifier).to eql("d8ab493736da02f11ed682f88339e720fb0379d1")
|
571
593
|
expect(@node.to_fingerprint).to eql("d8ab4937")
|
572
594
|
expect(@node.to_address).to eql("1Lke9bXGhn5VPrBuXgN12uGUphrttUErmk")
|
595
|
+
expect(@node.to_p2wpkh_p2sh).to eql("39oYp2KWMueN9LSVyDGUGAeDeAgdj43suV")
|
596
|
+
expect(@node.to_bech32_address).to eql("bc1qmz45jdekmgp0z8kkstugxw08yrasx7w3dse4fe")
|
573
597
|
end
|
574
598
|
|
575
599
|
it "generates a private key" do
|
@@ -617,6 +641,8 @@ describe MoneyTree::Master do
|
|
617
641
|
expect(@node.to_identifier).to eql("78412e3a2296a40de124307b6485bd19833e2e34")
|
618
642
|
expect(@node.to_fingerprint).to eql("78412e3a")
|
619
643
|
expect(@node.to_address).to eql("1BxrAr2pHpeBheusmd6fHDP2tSLAUa3qsW")
|
644
|
+
expect(@node.to_p2wpkh_p2sh).to eql("3McFiyStLZ4GzqN9Hx7rG7iyVjaX5Hf7VH")
|
645
|
+
expect(@node.to_bech32_address).to eql("bc1q0pqjuw3zj6jqmcfyxpakfpdarxpnut35gr8lsl")
|
620
646
|
end
|
621
647
|
|
622
648
|
it "generates a private key" do
|
@@ -664,6 +690,8 @@ describe MoneyTree::Master do
|
|
664
690
|
expect(@node.to_identifier).to eql("31a507b815593dfc51ffc7245ae7e5aee304246e")
|
665
691
|
expect(@node.to_fingerprint).to eql("31a507b8")
|
666
692
|
expect(@node.to_address).to eql("15XVotxCAV7sRx1PSCkQNsGw3W9jT9A94R")
|
693
|
+
expect(@node.to_p2wpkh_p2sh).to eql("35aip4nbX3wM2V3NMxHgPz1wEUQ2T7BJPY")
|
694
|
+
expect(@node.to_bech32_address).to eql("bc1qxxjs0wq4ty7lc50lcuj94el94m3sgfrwfvky9p")
|
667
695
|
end
|
668
696
|
|
669
697
|
it "generates a private key" do
|
@@ -711,6 +739,8 @@ describe MoneyTree::Master do
|
|
711
739
|
expect(@node.to_identifier).to eql("26132fdbe7bf89cbc64cf8dafa3f9f88b8666220")
|
712
740
|
expect(@node.to_fingerprint).to eql("26132fdb")
|
713
741
|
expect(@node.to_address).to eql("14UKfRV9ZPUp6ZC9PLhqbRtxdihW9em3xt")
|
742
|
+
expect(@node.to_p2wpkh_p2sh).to eql("3NUwiFMvp3CN1MYXkUjkoboYk7mHuQTTUn")
|
743
|
+
expect(@node.to_bech32_address).to eql("bc1qycfjlkl8h7yuh3jvlrd050ul3zuxvc3qphdmd3")
|
714
744
|
end
|
715
745
|
|
716
746
|
it "generates a private key" do
|
@@ -739,6 +769,386 @@ describe MoneyTree::Master do
|
|
739
769
|
end
|
740
770
|
end
|
741
771
|
|
772
|
+
describe "Test vector 3" do
|
773
|
+
describe "from a seed" do
|
774
|
+
before do
|
775
|
+
@master = MoneyTree::Master.new seed_hex: "4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be"
|
776
|
+
end
|
777
|
+
|
778
|
+
describe "m" do
|
779
|
+
it "has an index of 0" do
|
780
|
+
expect(@master.index).to eql(0)
|
781
|
+
end
|
782
|
+
|
783
|
+
it "is private" do
|
784
|
+
expect(@master.is_private?).to eql(true)
|
785
|
+
end
|
786
|
+
|
787
|
+
it "has a depth of 0" do
|
788
|
+
expect(@master.depth).to eql(0)
|
789
|
+
end
|
790
|
+
|
791
|
+
it "generates master node (Master)" do
|
792
|
+
expect(@master.to_identifier).to eql("41d63b50d8dd5e730cdf4c79a56fc929a757c548")
|
793
|
+
expect(@master.to_fingerprint).to eql("41d63b50")
|
794
|
+
expect(@master.to_address).to eql("1717ZYpXhZW5CqAbWSjDJbCey3FyKUmCSf")
|
795
|
+
expect(@master.to_p2wpkh_p2sh).to eql("3B4MJ7rJ9c5UfgKMfwqeB4Uh7kGNwqQhK6")
|
796
|
+
expect(@master.to_bech32_address).to eql("bc1qg8trk5xcm408xrxlf3u62m7f9xn4032gl36vmu")
|
797
|
+
end
|
798
|
+
|
799
|
+
it "generates a secret key" do
|
800
|
+
expect(@master.private_key.to_hex).to eql("00ddb80b067e0d4993197fe10f2657a844a384589847602d56f0c629c81aae32")
|
801
|
+
expect(@master.private_key.to_wif).to eql("KwFPqAq9SKx1sPg15Qk56mqkHwrfGPuywtLUxoWPkiTSBoxCs8am")
|
802
|
+
end
|
803
|
+
|
804
|
+
it "generates a public key" do
|
805
|
+
expect(@master.public_key.to_hex).to eql("03683af1ba5743bdfc798cf814efeeab2735ec52d95eced528e692b8e34c4e5669")
|
806
|
+
end
|
807
|
+
|
808
|
+
it "generates a chain code" do
|
809
|
+
expect(@master.chain_code_hex).to eql("01d28a3e53cffa419ec122c968b3259e16b65076495494d97cae10bbfec3c36f")
|
810
|
+
end
|
811
|
+
|
812
|
+
it "generates a serialized private key" do
|
813
|
+
expect(@master.to_serialized_hex(:private)).to eql("0488ade400000000000000000001d28a3e53cffa419ec122c968b3259e16b65076495494d97cae10bbfec3c36f0000ddb80b067e0d4993197fe10f2657a844a384589847602d56f0c629c81aae32")
|
814
|
+
expect(@master.to_bip32(:private)).to eql("xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6")
|
815
|
+
end
|
816
|
+
|
817
|
+
it "generates a serialized public_key" do
|
818
|
+
expect(@master.to_serialized_hex).to eql("0488b21e00000000000000000001d28a3e53cffa419ec122c968b3259e16b65076495494d97cae10bbfec3c36f03683af1ba5743bdfc798cf814efeeab2735ec52d95eced528e692b8e34c4e5669")
|
819
|
+
expect(@master.to_bip32).to eql("xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13")
|
820
|
+
end
|
821
|
+
end
|
822
|
+
|
823
|
+
describe "m/0p" do
|
824
|
+
before do
|
825
|
+
@node = @master.node_for_path "m/0p"
|
826
|
+
end
|
827
|
+
|
828
|
+
it "has an index of 2147483648" do
|
829
|
+
expect(@node.index).to eql(2147483648)
|
830
|
+
end
|
831
|
+
|
832
|
+
it "is private" do
|
833
|
+
expect(@node.is_private?).to eql(true)
|
834
|
+
end
|
835
|
+
|
836
|
+
it "has a depth of 1" do
|
837
|
+
expect(@node.depth).to eql(1)
|
838
|
+
end
|
839
|
+
|
840
|
+
it "generates subnode" do
|
841
|
+
expect(@node.to_identifier).to eql("c61368bb50e066acd95bd04a0b23d3837fb75698")
|
842
|
+
expect(@node.to_fingerprint).to eql("c61368bb")
|
843
|
+
expect(@node.to_address).to eql("1K4L3YxEwg8HkSEapM4iSiGuR6HeQ53KPX")
|
844
|
+
expect(@node.to_p2wpkh_p2sh).to eql("34WHhyr9rrVxVVuYpDqwUmd4yXdWFoKxLf")
|
845
|
+
expect(@node.to_bech32_address).to eql("bc1qccfk3w6supn2ek2m6p9qkg7nsdlmw45cj06e96")
|
846
|
+
end
|
847
|
+
|
848
|
+
it "generates a private key" do
|
849
|
+
expect(@node.private_key.to_hex).to eql("491f7a2eebc7b57028e0d3faa0acda02e75c33b03c48fb288c41e2ea44e1daef")
|
850
|
+
expect(@node.private_key.to_wif).to eql("KyfrPaeirL5yYAoZvfzyoKXSdszeLqg5vb6dNy9ymvjzZrMZY8GW")
|
851
|
+
end
|
852
|
+
|
853
|
+
it "generates a public key" do
|
854
|
+
expect(@node.public_key.to_hex).to eql("026557fdda1d5d43d79611f784780471f086d58e8126b8c40acb82272a7712e7f2")
|
855
|
+
end
|
856
|
+
|
857
|
+
it "generates a chain code" do
|
858
|
+
expect(@node.chain_code_hex).to eql("e5fea12a97b927fc9dc3d2cb0d1ea1cf50aa5a1fdc1f933e8906bb38df3377bd")
|
859
|
+
end
|
860
|
+
|
861
|
+
it "generates a serialized private key" do
|
862
|
+
expect(@node.to_serialized_hex(:private)).to eql("0488ade40141d63b5080000000e5fea12a97b927fc9dc3d2cb0d1ea1cf50aa5a1fdc1f933e8906bb38df3377bd00491f7a2eebc7b57028e0d3faa0acda02e75c33b03c48fb288c41e2ea44e1daef")
|
863
|
+
expect(@node.to_bip32(:private)).to eql("xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L")
|
864
|
+
end
|
865
|
+
|
866
|
+
it "generates a serialized public_key" do
|
867
|
+
expect(@node.to_serialized_hex).to eql("0488b21e0141d63b5080000000e5fea12a97b927fc9dc3d2cb0d1ea1cf50aa5a1fdc1f933e8906bb38df3377bd026557fdda1d5d43d79611f784780471f086d58e8126b8c40acb82272a7712e7f2")
|
868
|
+
expect(@node.to_bip32).to eql("xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y")
|
869
|
+
end
|
870
|
+
end
|
871
|
+
end
|
872
|
+
end
|
873
|
+
|
874
|
+
describe "Test vector 4" do
|
875
|
+
describe "from a seed" do
|
876
|
+
before do
|
877
|
+
@master = MoneyTree::Master.new seed_hex: "3ddd5602285899a946114506157c7997e5444528f3003f6134712147db19b678"
|
878
|
+
end
|
879
|
+
|
880
|
+
describe "m" do
|
881
|
+
it "has an index of 0" do
|
882
|
+
expect(@master.index).to eql(0)
|
883
|
+
end
|
884
|
+
|
885
|
+
it "is private" do
|
886
|
+
expect(@master.is_private?).to eql(true)
|
887
|
+
end
|
888
|
+
|
889
|
+
it "has a depth of 0" do
|
890
|
+
expect(@master.depth).to eql(0)
|
891
|
+
end
|
892
|
+
|
893
|
+
it "generates master node (Master)" do
|
894
|
+
expect(@master.to_identifier).to eql("ad85d95573bc609b98f2af5e06e150351f818ba9")
|
895
|
+
expect(@master.to_fingerprint).to eql("ad85d955")
|
896
|
+
expect(@master.to_address).to eql("1GpWFBBE37FQumRkrVUL6HB1bqSWCuYsKt")
|
897
|
+
expect(@master.to_p2wpkh_p2sh).to eql("33Koj9buBXM1UsNZjNdHSNeBCjxRLqVyRE")
|
898
|
+
expect(@master.to_bech32_address).to eql("bc1q4kzaj4tnh3sfhx8j4a0qdc2sx50crzaf2ka04w")
|
899
|
+
end
|
900
|
+
|
901
|
+
it "generates a secret key" do
|
902
|
+
expect(@master.private_key.to_hex).to eql("12c0d59c7aa3a10973dbd3f478b65f2516627e3fe61e00c345be9a477ad2e215")
|
903
|
+
expect(@master.private_key.to_wif).to eql("KwrAWXgyy1L75ZBRp1PzHj2aWBoYcddgrEMfF6iBJFuw8adwRNLu")
|
904
|
+
end
|
905
|
+
|
906
|
+
it "generates a public key" do
|
907
|
+
expect(@master.public_key.to_hex).to eql("026f6fedc9240f61daa9c7144b682a430a3a1366576f840bf2d070101fcbc9a02d")
|
908
|
+
end
|
909
|
+
|
910
|
+
it "generates a chain code" do
|
911
|
+
expect(@master.chain_code_hex).to eql("d0c8a1f6edf2500798c3e0b54f1b56e45f6d03e6076abd36e5e2f54101e44ce6")
|
912
|
+
end
|
913
|
+
|
914
|
+
it "generates a serialized private key" do
|
915
|
+
expect(@master.to_serialized_hex(:private)).to eql("0488ade4000000000000000000d0c8a1f6edf2500798c3e0b54f1b56e45f6d03e6076abd36e5e2f54101e44ce60012c0d59c7aa3a10973dbd3f478b65f2516627e3fe61e00c345be9a477ad2e215")
|
916
|
+
expect(@master.to_bip32(:private)).to eql("xprv9s21ZrQH143K48vGoLGRPxgo2JNkJ3J3fqkirQC2zVdk5Dgd5w14S7fRDyHH4dWNHUgkvsvNDCkvAwcSHNAQwhwgNMgZhLtQC63zxwhQmRv")
|
917
|
+
end
|
918
|
+
|
919
|
+
it "generates a serialized public_key" do
|
920
|
+
expect(@master.to_serialized_hex).to eql("0488b21e000000000000000000d0c8a1f6edf2500798c3e0b54f1b56e45f6d03e6076abd36e5e2f54101e44ce6026f6fedc9240f61daa9c7144b682a430a3a1366576f840bf2d070101fcbc9a02d")
|
921
|
+
expect(@master.to_bip32).to eql("xpub661MyMwAqRbcGczjuMoRm6dXaLDEhW1u34gKenbeYqAix21mdUKJyuyu5F1rzYGVxyL6tmgBUAEPrEz92mBXjByMRiJdba9wpnN37RLLAXa")
|
922
|
+
end
|
923
|
+
end
|
924
|
+
|
925
|
+
describe "m/0p" do
|
926
|
+
before do
|
927
|
+
@node = @master.node_for_path "m/0p"
|
928
|
+
end
|
929
|
+
|
930
|
+
it "has an index of 2147483648" do
|
931
|
+
expect(@node.index).to eql(2147483648)
|
932
|
+
end
|
933
|
+
|
934
|
+
it "is private" do
|
935
|
+
expect(@node.is_private?).to eql(true)
|
936
|
+
end
|
937
|
+
|
938
|
+
it "has a depth of 1" do
|
939
|
+
expect(@node.depth).to eql(1)
|
940
|
+
end
|
941
|
+
|
942
|
+
it "generates subnode" do
|
943
|
+
expect(@node.to_identifier).to eql("cfa61281b1762be25710658757221a6437cbcdd6")
|
944
|
+
expect(@node.to_fingerprint).to eql("cfa61281")
|
945
|
+
expect(@node.to_address).to eql("1KvwpccVR6CsN3ve2LZpxkSZ5od5262b75")
|
946
|
+
expect(@node.to_p2wpkh_p2sh).to eql("369UTJMek2ve1ANb18R91S9638scFYWJm3")
|
947
|
+
expect(@node.to_bech32_address).to eql("bc1qe7np9qd3wc47y4csvkr4wgs6vsmuhnwkve50q9")
|
948
|
+
end
|
949
|
+
|
950
|
+
it "generates a private key" do
|
951
|
+
expect(@node.private_key.to_hex).to eql("00d948e9261e41362a688b916f297121ba6bfb2274a3575ac0e456551dfd7f7e")
|
952
|
+
expect(@node.private_key.to_wif).to eql("KwFMsuZ3pmk7ebtbTiPirTpdcPkS6wvnSazU3bvixwiCw1bNQLhG")
|
953
|
+
end
|
954
|
+
|
955
|
+
it "generates a public key" do
|
956
|
+
expect(@node.public_key.to_hex).to eql("039382d2b6003446792d2917f7ac4b3edf079a1a94dd4eb010dc25109dda680a9d")
|
957
|
+
end
|
958
|
+
|
959
|
+
it "generates a chain code" do
|
960
|
+
expect(@node.chain_code_hex).to eql("cdc0f06456a14876c898790e0b3b1a41c531170aec69da44ff7b7265bfe7743b")
|
961
|
+
end
|
962
|
+
|
963
|
+
it "generates a serialized private key" do
|
964
|
+
expect(@node.to_serialized_hex(:private)).to eql("0488ade401ad85d95580000000cdc0f06456a14876c898790e0b3b1a41c531170aec69da44ff7b7265bfe7743b0000d948e9261e41362a688b916f297121ba6bfb2274a3575ac0e456551dfd7f7e")
|
965
|
+
expect(@node.to_bip32(:private)).to eql("xprv9vB7xEWwNp9kh1wQRfCCQMnZUEG21LpbR9NPCNN1dwhiZkjjeGRnaALmPXCX7SgjFTiCTT6bXes17boXtjq3xLpcDjzEuGLQBM5ohqkao9G")
|
966
|
+
end
|
967
|
+
|
968
|
+
it "generates a serialized public_key" do
|
969
|
+
expect(@node.to_serialized_hex).to eql("0488b21e01ad85d95580000000cdc0f06456a14876c898790e0b3b1a41c531170aec69da44ff7b7265bfe7743b039382d2b6003446792d2917f7ac4b3edf079a1a94dd4eb010dc25109dda680a9d")
|
970
|
+
expect(@node.to_bip32).to eql("xpub69AUMk3qDBi3uW1sXgjCmVjJ2G6WQoYSnNHyzkmdCHEhSZ4tBok37xfFEqHd2AddP56Tqp4o56AePAgCjYdvpW2PU2jbUPFKsav5ut6Ch1m")
|
971
|
+
end
|
972
|
+
end
|
973
|
+
|
974
|
+
describe "m/0'/1p" do
|
975
|
+
before do
|
976
|
+
@node = @master.node_for_path "m/0'/1p"
|
977
|
+
end
|
978
|
+
|
979
|
+
it "has an index of 1" do
|
980
|
+
expect(@node.index).to eql(2147483649)
|
981
|
+
end
|
982
|
+
|
983
|
+
it "is public" do
|
984
|
+
expect(@node.is_private?).to eql(true)
|
985
|
+
end
|
986
|
+
|
987
|
+
it "has a depth of 2" do
|
988
|
+
expect(@node.depth).to eql(2)
|
989
|
+
end
|
990
|
+
|
991
|
+
it "generates subnode" do
|
992
|
+
expect(@node.to_identifier).to eql("48b2a62638e9cb9b68f87671bc80041dbd3acf70")
|
993
|
+
expect(@node.to_fingerprint).to eql("48b2a626")
|
994
|
+
expect(@node.to_address).to eql("17dPfZg9P2zjrdkhsSAYt5YU7TwFpU6Acd")
|
995
|
+
expect(@node.to_p2wpkh_p2sh).to eql("3JvZhix4hLkSJXiWbpx7ZGXJb3AXJg5xZ3")
|
996
|
+
expect(@node.to_bech32_address).to eql("bc1qfze2vf3ca89ek68cwecmeqqyrk7n4nmsml42sp")
|
997
|
+
end
|
998
|
+
|
999
|
+
it "generates a private key" do
|
1000
|
+
expect(@node.private_key.to_hex).to eql("3a2086edd7d9df86c3487a5905a1712a9aa664bce8cc268141e07549eaa8661d")
|
1001
|
+
expect(@node.private_key.to_wif).to eql("KyAhgkU6sXTCm3eiHu81ev4jhcnEs6Toppbr8hqcm82jUFxbLX3u")
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
it "generates a public key" do
|
1005
|
+
expect(@node.public_key.to_hex).to eql("032edaf9e591ee27f3c69c36221e3c54c38088ef34e93fbb9bb2d4d9b92364cbbd")
|
1006
|
+
end
|
1007
|
+
|
1008
|
+
it "generates a chain code" do
|
1009
|
+
expect(@node.chain_code_hex).to eql("a48ee6674c5264a237703fd383bccd9fad4d9378ac98ab05e6e7029b06360c0d")
|
1010
|
+
end
|
1011
|
+
|
1012
|
+
it "generates a serialized private key" do
|
1013
|
+
expect(@node.to_serialized_hex(:private)).to eql("0488ade402cfa6128180000001a48ee6674c5264a237703fd383bccd9fad4d9378ac98ab05e6e7029b06360c0d003a2086edd7d9df86c3487a5905a1712a9aa664bce8cc268141e07549eaa8661d")
|
1014
|
+
expect(@node.to_bip32(:private)).to eql("xprv9xJocDuwtYCMNAo3Zw76WENQeAS6WGXQ55RCy7tDJ8oALr4FWkuVoHJeHVAcAqiZLE7Je3vZJHxspZdFHfnBEjHqU5hG1Jaj32dVoS6XLT1")
|
1015
|
+
end
|
1016
|
+
|
1017
|
+
it "generates a serialized public_key" do
|
1018
|
+
expect(@node.to_serialized_hex).to eql("0488b21e02cfa6128180000001a48ee6674c5264a237703fd383bccd9fad4d9378ac98ab05e6e7029b06360c0d032edaf9e591ee27f3c69c36221e3c54c38088ef34e93fbb9bb2d4d9b92364cbbd")
|
1019
|
+
expect(@node.to_bip32).to eql("xpub6BJA1jSqiukeaesWfxe6sNK9CCGaujFFSJLomWHprUL9DePQ4JDkM5d88n49sMGJxrhpjazuXYWdMf17C9T5XnxkopaeS7jGk1GyyVziaMt")
|
1020
|
+
end
|
1021
|
+
end
|
1022
|
+
|
1023
|
+
describe "M/0'/1p" do
|
1024
|
+
before do
|
1025
|
+
@node = @master.node_for_path "M/0'/1p"
|
1026
|
+
end
|
1027
|
+
|
1028
|
+
it "has an index of 1" do
|
1029
|
+
expect(@node.index).to eql(2147483649)
|
1030
|
+
end
|
1031
|
+
|
1032
|
+
it "is public" do
|
1033
|
+
expect(@node.is_private?).to eql(true)
|
1034
|
+
end
|
1035
|
+
|
1036
|
+
it "has a depth of 2" do
|
1037
|
+
expect(@node.depth).to eql(2)
|
1038
|
+
end
|
1039
|
+
|
1040
|
+
it "generates subnode" do
|
1041
|
+
expect(@node.to_identifier).to eql("48b2a62638e9cb9b68f87671bc80041dbd3acf70")
|
1042
|
+
expect(@node.to_fingerprint).to eql("48b2a626")
|
1043
|
+
expect(@node.to_address).to eql("17dPfZg9P2zjrdkhsSAYt5YU7TwFpU6Acd")
|
1044
|
+
expect(@node.to_p2wpkh_p2sh).to eql("3JvZhix4hLkSJXiWbpx7ZGXJb3AXJg5xZ3")
|
1045
|
+
expect(@node.to_bech32_address).to eql("bc1qfze2vf3ca89ek68cwecmeqqyrk7n4nmsml42sp")
|
1046
|
+
end
|
1047
|
+
|
1048
|
+
it "does not generate a private key" do
|
1049
|
+
expect(@node.private_key).to be_nil
|
1050
|
+
end
|
1051
|
+
|
1052
|
+
it "generates a public key" do
|
1053
|
+
expect(@node.public_key.to_hex).to eql("032edaf9e591ee27f3c69c36221e3c54c38088ef34e93fbb9bb2d4d9b92364cbbd")
|
1054
|
+
end
|
1055
|
+
|
1056
|
+
it "generates a chain code" do
|
1057
|
+
expect(@node.chain_code_hex).to eql("a48ee6674c5264a237703fd383bccd9fad4d9378ac98ab05e6e7029b06360c0d")
|
1058
|
+
end
|
1059
|
+
|
1060
|
+
it "generates a serialized private key" do
|
1061
|
+
expect { @node.to_serialized_hex(:private) }.to raise_error(MoneyTree::Node::PrivatePublicMismatch)
|
1062
|
+
end
|
1063
|
+
|
1064
|
+
it "generates a serialized public_key" do
|
1065
|
+
expect(@node.to_serialized_hex).to eql("0488b21e02cfa6128180000001a48ee6674c5264a237703fd383bccd9fad4d9378ac98ab05e6e7029b06360c0d032edaf9e591ee27f3c69c36221e3c54c38088ef34e93fbb9bb2d4d9b92364cbbd")
|
1066
|
+
expect(@node.to_bip32).to eql("xpub6BJA1jSqiukeaesWfxe6sNK9CCGaujFFSJLomWHprUL9DePQ4JDkM5d88n49sMGJxrhpjazuXYWdMf17C9T5XnxkopaeS7jGk1GyyVziaMt")
|
1067
|
+
end
|
1068
|
+
end
|
1069
|
+
end
|
1070
|
+
end
|
1071
|
+
|
1072
|
+
describe "Test vector 5" do
|
1073
|
+
describe "from an invalid bip32 key" do
|
1074
|
+
# it "recognizes pubkey version / prvkey mismatch" do
|
1075
|
+
# MoneyTree::Node.from_bip32 "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6LBpB85b3D2yc8sfvZU521AAwdZafEz7mnzBBsz4wKY5fTtTQBm"
|
1076
|
+
# end
|
1077
|
+
|
1078
|
+
# it "recognizes prvkey version / pubkey mismatch" do
|
1079
|
+
# MoneyTree::Node.from_bip32 "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGTQQD3dC4H2D5GBj7vWvSQaaBv5cxi9gafk7NF3pnBju6dwKvH"
|
1080
|
+
# end
|
1081
|
+
|
1082
|
+
it "recognizes invalid pubkey prefix 04" do
|
1083
|
+
expect {
|
1084
|
+
MoneyTree::Node.from_bip32 "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Txnt3siSujt9RCVYsx4qHZGc62TG4McvMGcAUjeuwZdduYEvFn"
|
1085
|
+
}.to raise_error MoneyTree::Node::ImportError
|
1086
|
+
end
|
1087
|
+
|
1088
|
+
it "recognizes invalid prvkey prefix 04" do
|
1089
|
+
expect {
|
1090
|
+
MoneyTree::Node.from_bip32 "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGpWnsj83BHtEy5Zt8CcDr1UiRXuWCmTQLxEK9vbz5gPstX92JQ"
|
1091
|
+
}.to raise_error MoneyTree::Node::ImportError
|
1092
|
+
end
|
1093
|
+
|
1094
|
+
it "recognizes invalid pubkey prefix 01" do
|
1095
|
+
expect {
|
1096
|
+
MoneyTree::Node.from_bip32 "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6N8ZMMXctdiCjxTNq964yKkwrkBJJwpzZS4HS2fxvyYUA4q2Xe4"
|
1097
|
+
}.to raise_error MoneyTree::Node::ImportError
|
1098
|
+
end
|
1099
|
+
|
1100
|
+
it "recognizes invalid prvkey prefix 01" do
|
1101
|
+
expect {
|
1102
|
+
MoneyTree::Node.from_bip32 "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD9y5gkZ6Eq3Rjuahrv17fEQ3Qen6J"
|
1103
|
+
}.to raise_error MoneyTree::Node::ImportError
|
1104
|
+
end
|
1105
|
+
|
1106
|
+
# it "recognizes zero depth with non-zero parent fingerprint" do
|
1107
|
+
# MoneyTree::Node.from_bip32 "xprv9s2SPatNQ9Vc6GTbVMFPFo7jsaZySyzk7L8n2uqKXJen3KUmvQNTuLh3fhZMBoG3G4ZW1N2kZuHEPY53qmbZzCHshoQnNf4GvELZfqTUrcv"
|
1108
|
+
# end
|
1109
|
+
|
1110
|
+
# it "recognizes zero depth with non-zero parent fingerprint" do
|
1111
|
+
# MoneyTree::Node.from_bip32 "xpub661no6RGEX3uJkY4bNnPcw4URcQTrSibUZ4NqJEw5eBkv7ovTwgiT91XX27VbEXGENhYRCf7hyEbWrR3FewATdCEebj6znwMfQkhRYHRLpJ"
|
1112
|
+
# end
|
1113
|
+
|
1114
|
+
# it "recognizes zero depth with non-zero index" do
|
1115
|
+
# MoneyTree::Node.from_bip32 "xprv9s21ZrQH4r4TsiLvyLXqM9P7k1K3EYhA1kkD6xuquB5i39AU8KF42acDyL3qsDbU9NmZn6MsGSUYZEsuoePmjzsB3eFKSUEh3Gu1N3cqVUN"
|
1116
|
+
# end
|
1117
|
+
|
1118
|
+
# it "recognizes zero depth with non-zero index" do
|
1119
|
+
# MoneyTree::Node.from_bip32 "xpub661MyMwAuDcm6CRQ5N4qiHKrJ39Xe1R1NyfouMKTTWcguwVcfrZJaNvhpebzGerh7gucBvzEQWRugZDuDXjNDRmXzSZe4c7mnTK97pTvGS8"
|
1120
|
+
# end
|
1121
|
+
|
1122
|
+
# it "recognizes unknown extended key version" do
|
1123
|
+
# MoneyTree::Node.from_bip32 "DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHGMQzT7ayAmfo4z3gY5KfbrZWZ6St24UVf2Qgo6oujFktLHdHY4"
|
1124
|
+
# end
|
1125
|
+
|
1126
|
+
# it "recognizes unknown extended key version" do
|
1127
|
+
# MoneyTree::Node.from_bip32 "DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHPmHJiEDXkTiJTVV9rHEBUem2mwVbbNfvT2MTcAqj3nesx8uBf9"
|
1128
|
+
# end
|
1129
|
+
|
1130
|
+
# it "recognizes private key 0 not in 1..n-1" do
|
1131
|
+
# MoneyTree::Node.from_bip32 "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzF93Y5wvzdUayhgkkFoicQZcP3y52uPPxFnfoLZB21Teqt1VvEHx"
|
1132
|
+
# end
|
1133
|
+
|
1134
|
+
# it "recognizes private key n not in 1..n-1" do
|
1135
|
+
# MoneyTree::Node.from_bip32 "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD5SDKr24z3aiUvKr9bJpdrcLg1y3G"
|
1136
|
+
# end
|
1137
|
+
|
1138
|
+
it "recognizes invalid pubkey 020000000000000000000000000000000000000000000000000000000000000007" do
|
1139
|
+
expect {
|
1140
|
+
MoneyTree::Node.from_bip32 "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Q5JXayek4PRsn35jii4veMimro1xefsM58PgBMrvdYre8QyULY"
|
1141
|
+
}.to raise_error OpenSSL::PKey::EC::Point::Error
|
1142
|
+
end
|
1143
|
+
|
1144
|
+
it "recognizes invalid checksum" do
|
1145
|
+
expect {
|
1146
|
+
MoneyTree::Node.from_bip32 "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHL"
|
1147
|
+
}.to raise_error EncodingError
|
1148
|
+
end
|
1149
|
+
end
|
1150
|
+
end
|
1151
|
+
|
742
1152
|
describe "negative index" do
|
743
1153
|
before do
|
744
1154
|
@master = MoneyTree::Master.new seed_hex: "000102030405060708090a0b0c0d0e0f"
|
@@ -798,7 +1208,7 @@ describe MoneyTree::Master do
|
|
798
1208
|
describe "#node_for_path" do
|
799
1209
|
it "correctly derives from a node with a chain code represented in 31 bytes" do
|
800
1210
|
@node = MoneyTree::Node.from_bip32 "tpubD6NzVbkrYhZ4WM42MZZmUZ7LjxyjBf5bGjEeLf9nJnMZqocGJWu94drvpqWsE9jE7k3h22v6gjpPGnqgBrqwGsRYwDXVRfQ2M9dfHbXP5zA"
|
801
|
-
@subnode = @node.node_for_path(
|
1211
|
+
@subnode = @node.node_for_path("m/1")
|
802
1212
|
expect(@subnode.to_bip32(network: :bitcoin_testnet)).to eql("tpubDA7bCxb3Nrcz2ChXyPqXxbG4q5oiAZUHR7wD3LAiXukuxmT65weWw84XYmjhkJTkJEM6LhNWioWTpKEkQp7j2fgVccj3PPc271xHDeMsaTY")
|
803
1213
|
end
|
804
1214
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
FIXED_KEY1 = <<-fixed_key
|
4
|
+
-----BEGIN EC PRIVATE KEY-----
|
5
|
+
MHQCAQEEIOvYaAN53KFhyLIElYFZCpm/Q2wq72Uu0kRcKeCDdlJVoAcGBSuBBAAK
|
6
|
+
oUQDQgAE4cdbt+NxMCBLg0cQYqo/UEwfzAONpz/n7ux+QrdKuH9NRulf9D4996x5
|
7
|
+
r7QBY+l5GJ+RgzLoXbFjPyPQtCV+/Q==
|
8
|
+
-----END EC PRIVATE KEY-----
|
9
|
+
fixed_key
|
10
|
+
|
11
|
+
FIXED_KEY2 = <<-fixed_key
|
12
|
+
-----BEGIN EC PRIVATE KEY-----
|
13
|
+
MHQCAQEEIP6nKLMEcH9R3hv695rCUl9OV+ueC9UX18F2PIH5wcFpoAcGBSuBBAAK
|
14
|
+
oUQDQgAErilvn3ms9cKHLNHHegiUU+NuW8c2f223vYInEV+s9ZNSGd28usAXZ6lN
|
15
|
+
O2zE534+k09fFe2skHtdoXbLJuZV8g==
|
16
|
+
-----END EC PRIVATE KEY-----
|
17
|
+
fixed_key
|
18
|
+
|
19
|
+
FIXED_SUM = "04F3C291542F410F61D61861D911F71ABD320A7B77ED571F92FEC533F61549BF218BAA47BD134847D89917F7483AFE20CCD9B1A4CBDFC443B389D1313B48E018F4"
|
20
|
+
|
21
|
+
describe MoneyTree::OpenSSLExtensions do
|
22
|
+
include MoneyTree::OpenSSLExtensions
|
23
|
+
|
24
|
+
context "with inputs" do
|
25
|
+
let(:key1) { OpenSSL::PKey::EC.new("secp256k1").generate_key }
|
26
|
+
let(:key2) { OpenSSL::PKey::EC.new("secp256k1").generate_key }
|
27
|
+
let(:point_1) { key1.public_key }
|
28
|
+
let(:point_2) { key2.public_key }
|
29
|
+
|
30
|
+
let(:point_infinity) { key1.public_key.set_to_infinity! }
|
31
|
+
|
32
|
+
let(:fixed_key1) { OpenSSL::PKey::EC.new(FIXED_KEY1) }
|
33
|
+
let(:fixed_key2) { OpenSSL::PKey::EC.new(FIXED_KEY2) }
|
34
|
+
let(:fixed_point1) { fixed_key1.public_key }
|
35
|
+
let(:fixed_point2) { fixed_key2.public_key }
|
36
|
+
let(:fixed_sum_point) { OpenSSL::PKey::EC::Point.new(OpenSSL::PKey::EC::Group.new("secp256k1"), OpenSSL::BN.new(FIXED_SUM, 16)) }
|
37
|
+
|
38
|
+
it "requires valid points" do
|
39
|
+
expect { MoneyTree::OpenSSLExtensions.add(0, 0) }.to raise_error(ArgumentError)
|
40
|
+
expect { MoneyTree::OpenSSLExtensions.add(nil, nil) }.to raise_error(ArgumentError)
|
41
|
+
expect { MoneyTree::OpenSSLExtensions.add(point_1, 0) }.to raise_error(ArgumentError)
|
42
|
+
expect { MoneyTree::OpenSSLExtensions.add(0, point_2) }.to raise_error(ArgumentError)
|
43
|
+
expect { MoneyTree::OpenSSLExtensions.add(point_infinity, point_2) }.to raise_error(ArgumentError)
|
44
|
+
expect { MoneyTree::OpenSSLExtensions.add(point_1, point_2) }.to_not raise_error
|
45
|
+
expect { MoneyTree::OpenSSLExtensions.validate_points(point_1) }.to_not raise_error
|
46
|
+
end
|
47
|
+
|
48
|
+
it "validates points correctly" do
|
49
|
+
expect { MoneyTree::OpenSSLExtensions.validate_points(point_1) }.to_not raise_error
|
50
|
+
expect { MoneyTree::OpenSSLExtensions.validate_points(point_2) }.to_not raise_error
|
51
|
+
expect { MoneyTree::OpenSSLExtensions.validate_points(point_infinity) }.to raise_error(ArgumentError)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should add points correctly" do
|
55
|
+
result = MoneyTree::OpenSSLExtensions.add(fixed_point1, fixed_point2)
|
56
|
+
|
57
|
+
expect(result).to eql(FIXED_SUM)
|
58
|
+
|
59
|
+
group = OpenSSL::PKey::EC::Group.new("secp256k1")
|
60
|
+
result_point = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new(result, 16))
|
61
|
+
|
62
|
+
expect(result_point).to eql(fixed_sum_point)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should be able to create the same hex output for the point" do
|
66
|
+
hex_output = fixed_sum_point.to_bn.to_s(16)
|
67
|
+
|
68
|
+
expect(hex_output).to eq(FIXED_SUM)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|