aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Coleman <ian@iancoleman.io>2019-12-16 13:08:28 +1100
committerIan Coleman <ian@iancoleman.io>2019-12-16 13:27:15 +1100
commit5c203fab6ac25fc76e2b805b7709d9b06ccdd995 (patch)
treec95d6897e6e6a32be1adf8abc82986f3471d4397
parent40d542ba58008762c71a304df03ef8c987cb6db5 (diff)
downloadBIP39-5c203fab6ac25fc76e2b805b7709d9b06ccdd995.tar.gz
BIP39-5c203fab6ac25fc76e2b805b7709d9b06ccdd995.tar.zst
BIP39-5c203fab6ac25fc76e2b805b7709d9b06ccdd995.zip
Add P2WSH and P2WSH-P2SH for bitcoin and testnet
Address generation still to come.
-rw-r--r--src/index.html2
-rw-r--r--src/js/index.js56
-rw-r--r--src/js/segwit-parameters.js56
-rw-r--r--tests/spec/tests.js96
4 files changed, 210 insertions, 0 deletions
diff --git a/src/index.html b/src/index.html
index 36e238f..61fe022 100644
--- a/src/index.html
+++ b/src/index.html
@@ -509,6 +509,8 @@
509 <select class="form-control bip141-semantics"> 509 <select class="form-control bip141-semantics">
510 <option value="p2wpkh">P2WPKH</option> 510 <option value="p2wpkh">P2WPKH</option>
511 <option value="p2wpkh-p2sh" selected>P2WPKH nested in P2SH</option> 511 <option value="p2wpkh-p2sh" selected>P2WPKH nested in P2SH</option>
512 <option value="p2wsh">P2WSH</option>
513 <option value="p2wsh-p2sh">P2WSH nested in P2SH</option>
512 </select> 514 </select>
513 </div> 515 </div>
514 </div> 516 </div>
diff --git a/src/js/index.js b/src/js/index.js
index 0b34ade..db47412 100644
--- a/src/js/index.js
+++ b/src/js/index.js
@@ -539,6 +539,22 @@
539 } 539 }
540 catch (e) {} 540 catch (e) {}
541 } 541 }
542 // try parsing using p2wsh network params
543 if ("p2wsh" in n) {
544 try {
545 bip32RootKey = bitcoinjs.bitcoin.HDNode.fromBase58(rootKeyBase58, n.p2wsh);
546 return;
547 }
548 catch (e) {}
549 }
550 // try parsing using p2wsh-in-p2sh network params
551 if ("p2wshInP2sh" in n) {
552 try {
553 bip32RootKey = bitcoinjs.bitcoin.HDNode.fromBase58(rootKeyBase58, n.p2wshInP2sh);
554 return;
555 }
556 catch (e) {}
557 }
542 } 558 }
543 // try the network params as currently specified 559 // try the network params as currently specified
544 bip32RootKey = bitcoinjs.bitcoin.HDNode.fromBase58(rootKeyBase58, network); 560 bip32RootKey = bitcoinjs.bitcoin.HDNode.fromBase58(rootKeyBase58, network);
@@ -681,6 +697,22 @@
681 } 697 }
682 catch (e) {} 698 catch (e) {}
683 } 699 }
700 // try parsing using p2wsh network params
701 if ("p2wsh" in n) {
702 try {
703 bitcoinjs.bitcoin.HDNode.fromBase58(rootKeyBase58, n.p2wsh);
704 return "";
705 }
706 catch (e) {}
707 }
708 // try parsing using p2wsh-in-p2sh network params
709 if ("p2wshInP2sh" in n) {
710 try {
711 bitcoinjs.bitcoin.HDNode.fromBase58(rootKeyBase58, n.p2wshInP2sh);
712 return "";
713 }
714 catch (e) {}
715 }
684 } 716 }
685 // try the network params as currently specified 717 // try the network params as currently specified
686 try { 718 try {
@@ -968,6 +1000,14 @@
968 (bip141TabSelected() && DOM.bip141semantics.val() == "p2wpkh-p2sh"); 1000 (bip141TabSelected() && DOM.bip141semantics.val() == "p2wpkh-p2sh");
969 } 1001 }
970 1002
1003 function p2wshSelected() {
1004 return bip141TabSelected() && DOM.bip141semantics.val() == "p2wsh";
1005 }
1006
1007 function p2wshInP2shSelected() {
1008 return (bip141TabSelected() && DOM.bip141semantics.val() == "p2wsh-p2sh");
1009 }
1010
971 function TableRow(index, isLast) { 1011 function TableRow(index, isLast) {
972 1012
973 var self = this; 1013 var self = this;
@@ -979,6 +1019,8 @@
979 var segwitAvailable = networkHasSegwit(); 1019 var segwitAvailable = networkHasSegwit();
980 var isP2wpkh = p2wpkhSelected(); 1020 var isP2wpkh = p2wpkhSelected();
981 var isP2wpkhInP2sh = p2wpkhInP2shSelected(); 1021 var isP2wpkhInP2sh = p2wpkhInP2shSelected();
1022 var isP2wsh = p2wshSelected();
1023 var isP2wshInP2sh = p2wshInP2shSelected();
982 1024
983 function init() { 1025 function init() {
984 calculateValues(); 1026 calculateValues();
@@ -1109,6 +1151,14 @@
1109 var scriptpubkey = bitcoinjs.bitcoin.script.scriptHash.output.encode(addressbytes); 1151 var scriptpubkey = bitcoinjs.bitcoin.script.scriptHash.output.encode(addressbytes);
1110 address = bitcoinjs.bitcoin.address.fromOutputScript(scriptpubkey, network) 1152 address = bitcoinjs.bitcoin.address.fromOutputScript(scriptpubkey, network)
1111 } 1153 }
1154 else if (isP2wsh) {
1155 // TODO
1156 address = "";
1157 }
1158 else if (isP2wshInP2sh) {
1159 // TODO
1160 address = "";
1161 }
1112 } 1162 }
1113 1163
1114 if ((networks[DOM.network.val()].name == "CRW - Crown")) { 1164 if ((networks[DOM.network.val()].name == "CRW - Crown")) {
@@ -1794,6 +1844,12 @@
1794 else if (p2wpkhInP2shSelected() && "p2wpkhInP2sh" in network) { 1844 else if (p2wpkhInP2shSelected() && "p2wpkhInP2sh" in network) {
1795 network = network.p2wpkhInP2sh; 1845 network = network.p2wpkhInP2sh;
1796 } 1846 }
1847 else if (p2wshSelected() && "p2wsh" in network) {
1848 network = network.p2wsh;
1849 }
1850 else if (p2wshInP2shSelected() && "p2wshInP2sh" in network) {
1851 network = network.p2wshInP2sh;
1852 }
1797 } 1853 }
1798 1854
1799 function lastIndexInTable() { 1855 function lastIndexInTable() {
diff --git a/src/js/segwit-parameters.js b/src/js/segwit-parameters.js
index de4d634..83d49da 100644
--- a/src/js/segwit-parameters.js
+++ b/src/js/segwit-parameters.js
@@ -56,6 +56,62 @@ bitcoinjs.bitcoin.networks.testnet.p2wpkhInP2sh = {
56 wif: 0xef 56 wif: 0xef
57}; 57};
58 58
59// p2wsh
60
61bitcoinjs.bitcoin.networks.bitcoin.p2wsh = {
62 baseNetwork: "bitcoin",
63 messagePrefix: '\x18Bitcoin Signed Message:\n',
64 bech32: 'bc',
65 bip32: {
66 public: 0x02aa7ed3,
67 private: 0x02aa7a99
68 },
69 pubKeyHash: 0x00,
70 scriptHash: 0x05,
71 wif: 0x80
72};
73
74bitcoinjs.bitcoin.networks.testnet.p2wsh = {
75 baseNetwork: "testnet",
76 messagePrefix: '\x18Bitcoin Signed Message:\n',
77 bech32: 'tb',
78 bip32: {
79 public: 0x02575483,
80 private: 0x02575048
81 },
82 pubKeyHash: 0x6f,
83 scriptHash: 0xc4,
84 wif: 0xef
85};
86
87// p2wsh in p2sh
88
89bitcoinjs.bitcoin.networks.bitcoin.p2wshInP2sh = {
90 baseNetwork: "bitcoin",
91 messagePrefix: '\x18Bitcoin Signed Message:\n',
92 bech32: 'bc',
93 bip32: {
94 public: 0x0295b43f,
95 private: 0x0295b005
96 },
97 pubKeyHash: 0x00,
98 scriptHash: 0x05,
99 wif: 0x80
100};
101
102bitcoinjs.bitcoin.networks.testnet.p2wshInP2sh = {
103 baseNetwork: "testnet",
104 messagePrefix: '\x18Bitcoin Signed Message:\n',
105 bech32: 'tb',
106 bip32: {
107 public: 0x024289ef,
108 private: 0x024285b5
109 },
110 pubKeyHash: 0x6f,
111 scriptHash: 0xc4,
112 wif: 0xef
113};
114
59bitcoinjs.bitcoin.networks.litecoin.p2wpkh = { 115bitcoinjs.bitcoin.networks.litecoin.p2wpkh = {
60 baseNetwork: "litecoin", 116 baseNetwork: "litecoin",
61 messagePrefix: '\x19Litecoin Signed Message:\n', 117 messagePrefix: '\x19Litecoin Signed Message:\n',
diff --git a/tests/spec/tests.js b/tests/spec/tests.js
index af8944c..fc71353 100644
--- a/tests/spec/tests.js
+++ b/tests/spec/tests.js
@@ -3694,6 +3694,102 @@ it('Can generate BIP141 addresses with P2WPKH-in-P2SH semanitcs', function(done)
3694 }); 3694 });
3695}); 3695});
3696 3696
3697it('Can generate BIP141 addresses with P2WSH semanitcs', function(done) {
3698 driver.findElement(By.css('#bip141-tab a'))
3699 .click();
3700 // Choose P2WSH
3701 driver.executeScript(function() {
3702 $(".bip141-semantics option[selected]").removeAttr("selected");
3703 $(".bip141-semantics option").filter(function(i,e) {
3704 return $(e).html() == "P2WSH";
3705 }).prop("selected", true);
3706 $(".bip141-semantics").trigger("change");
3707 });
3708 driver.findElement(By.css(".phrase"))
3709 .sendKeys("abandon abandon ability");
3710 driver.sleep(generateDelay).then(function() {
3711 driver.findElement(By.css("#root-key"))
3712 .getAttribute("value")
3713 .then(function(rootKey) {
3714 expect(rootKey).toBe("ZprvAhadJRUYsNge9uHspaggavxU1BUQ8QwfT4Z9UGq5sKF2mSt1mVy8EckLAaoBdmLHyP5eYDJ3LxtmzMNnLg2MRFe7QN2ueF4NCH4s5PrCDR6");
3715 // TODO check first address
3716 done();
3717 })
3718 });
3719});
3720
3721it('Can generate BIP141 addresses with P2WSH-in-P2SH semanitcs', function(done) {
3722 driver.findElement(By.css('#bip141-tab a'))
3723 .click();
3724 // Choose P2WSH-in-P2SH
3725 driver.executeScript(function() {
3726 $(".bip141-semantics option[selected]").removeAttr("selected");
3727 $(".bip141-semantics option").filter(function(i,e) {
3728 return $(e).html() == "P2WSH nested in P2SH";
3729 }).prop("selected", true);
3730 $(".bip141-semantics").trigger("change");
3731 });
3732 driver.findElement(By.css(".phrase"))
3733 .sendKeys("abandon abandon ability");
3734 driver.sleep(generateDelay).then(function() {
3735 driver.findElement(By.css("#root-key"))
3736 .getAttribute("value")
3737 .then(function(rootKey) {
3738 expect(rootKey).toBe("YprvANkMzkodih9AJc6kzDu4NqrxqDKxBnxAXx2vgswCVJs9iM4nWqoZcZ6C9NqbdrgNZjxqnjhUtJYE74mDcycLd1xWY2LV4LEsvZ1DgqxuAKe");
3739 // TODO check first address
3740 done();
3741 })
3742 });
3743});
3744
3745it('Uses Vprv for bitcoin testnet p2wsh', function(done) {
3746 selectNetwork("BTC - Bitcoin Testnet");
3747 driver.findElement(By.css('#bip141-tab a'))
3748 .click()
3749 // Choose P2WSH
3750 driver.executeScript(function() {
3751 $(".bip141-semantics option[selected]").removeAttr("selected");
3752 $(".bip141-semantics option").filter(function(i,e) {
3753 return $(e).html() == "P2WSH";
3754 }).prop("selected", true);
3755 $(".bip141-semantics").trigger("change");
3756 });
3757 driver.findElement(By.css('.phrase'))
3758 .sendKeys('abandon abandon ability');
3759 driver.sleep(generateDelay).then(function() {
3760 driver.findElement(By.css('.root-key'))
3761 .getAttribute("value")
3762 .then(function(path) {
3763 expect(path).toBe("Vprv16YtLrHXxePM5ja5hXQbiJs5JKDAc4WcaXo5rZcrVMU6bMhUg1oY7fpPku3i819gvMcHvq1h8aELDsyfCEs19vj1Q3iDHRrESWyJConkoT1");
3764 done();
3765 })
3766 });
3767});
3768
3769it('Uses Uprv for bitcoin testnet p2wsh-in-p2sh', function(done) {
3770 selectNetwork("BTC - Bitcoin Testnet");
3771 driver.findElement(By.css('#bip141-tab a'))
3772 .click()
3773 // Choose P2WSH-in-P2SH
3774 driver.executeScript(function() {
3775 $(".bip141-semantics option[selected]").removeAttr("selected");
3776 $(".bip141-semantics option").filter(function(i,e) {
3777 return $(e).html() == "P2WSH nested in P2SH";
3778 }).prop("selected", true);
3779 $(".bip141-semantics").trigger("change");
3780 });
3781 driver.findElement(By.css('.phrase'))
3782 .sendKeys('abandon abandon ability');
3783 driver.sleep(generateDelay).then(function() {
3784 driver.findElement(By.css('.root-key'))
3785 .getAttribute("value")
3786 .then(function(path) {
3787 expect(path).toBe("Uprv95RJn67y7xyEuRLHenkZYVUx9LkARJzAsVx3ZJMeyHMdVwosWD9K8JTe4Z1FeE4gwBVcnqKF3f82ZvJxkBxHS5E74fYnigxvqeke8ZV3Fp2");
3788 done();
3789 })
3790 });
3791});
3792
3697it('Can generate BIP141 addresses with P2WPKH semanitcs', function(done) { 3793it('Can generate BIP141 addresses with P2WPKH semanitcs', function(done) {
3698 // This result tested against bitcoinjs-lib test spec for segwit address 3794 // This result tested against bitcoinjs-lib test spec for segwit address
3699 // using the first private key of this mnemonic and default path m/0 3795 // using the first private key of this mnemonic and default path m/0