aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIan Coleman <ian@iancoleman.io>2017-11-22 12:11:48 +1100
committerIan Coleman <ian@iancoleman.io>2017-11-22 13:03:47 +1100
commitc49e881294343b762109bb8104e7c1b45898c894 (patch)
treed5977e411ccc4351de1384b611c05ef1a428c213 /src
parent0fd67b5915a08168d31caaa581f55cf86591be73 (diff)
downloadBIP39-c49e881294343b762109bb8104e7c1b45898c894.tar.gz
BIP39-c49e881294343b762109bb8104e7c1b45898c894.tar.zst
BIP39-c49e881294343b762109bb8104e7c1b45898c894.zip
Add BIP141 tab for full segwit compatibility
Diffstat (limited to 'src')
-rw-r--r--src/index.html41
-rw-r--r--src/js/bitcoinjs-extensions.js33
-rw-r--r--src/js/index.js88
-rw-r--r--src/js/segwit-parameters.js58
4 files changed, 158 insertions, 62 deletions
diff --git a/src/index.html b/src/index.html
index b638b26..0126bef 100644
--- a/src/index.html
+++ b/src/index.html
@@ -301,6 +301,9 @@
301 <li id="bip49-tab"> 301 <li id="bip49-tab">
302 <a href="#bip49" role="tab" data-toggle="tab">BIP49</a> 302 <a href="#bip49" role="tab" data-toggle="tab">BIP49</a>
303 </li> 303 </li>
304 <li id="bip141-tab">
305 <a href="#bip141" role="tab" data-toggle="tab">BIP141</a>
306 </li>
304 </ul> 307 </ul>
305 <div class="derivation-type tab-content"> 308 <div class="derivation-type tab-content">
306 <div id="bip44" class="tab-pane active"> 309 <div id="bip44" class="tab-pane active">
@@ -544,6 +547,43 @@
544 </div> 547 </div>
545 </form> 548 </form>
546 </div> 549 </div>
550 <div id="bip141" class="tab-pane">
551 <form class="form-horizontal" role="form">
552 <br>
553 <div class="unavailable hidden">
554 <div class="form-group">
555 <div class="col-sm-2"></div>
556 <div class="col-sm-10">
557 <p>BIP141 is unavailable for this coin.</p>
558 </div>
559 </div>
560 </div>
561 <div class="available">
562 <div class="col-sm-2"></div>
563 <div class="col-sm-10">
564 <p>
565 For more info see the
566 <a href="https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki" target="_blank">BIP141 spec</a>
567 </p>
568 </div>
569 <div class="form-group">
570 <label for="bip141-path" class="col-sm-2 control-label">BIP32 Derivation Path</label>
571 <div class="col-sm-10">
572 <input id="bip141-path" type="text" class="bip141-path form-control" value="m/0">
573 </div>
574 </div>
575 <div class="form-group">
576 <label class="col-sm-2 control-label">Script Semantics</label>
577 <div class="col-sm-10">
578 <select class="form-control bip141-semantics">
579 <option value="p2wpkh">P2WPKH</option>
580 <option value="p2wpkh-p2sh" selected>P2WPKH nested in P2SH</option>
581 </select>
582 </div>
583 </div>
584 </div>
585 </form>
586 </div>
547 </div> 587 </div>
548 <form class="form-horizontal" role="form"> 588 <form class="form-horizontal" role="form">
549 <div class="form-group"> 589 <div class="form-group">
@@ -830,6 +870,7 @@
830 <script src="js/jquery.qrcode.min.js"></script> 870 <script src="js/jquery.qrcode.min.js"></script>
831 <script src="js/bitcoinjs-3.3.0.js"></script> 871 <script src="js/bitcoinjs-3.3.0.js"></script>
832 <script src="js/bitcoinjs-extensions.js"></script> 872 <script src="js/bitcoinjs-extensions.js"></script>
873 <script src="js/segwit-parameters.js"></script>
833 <script src="js/ethereumjs-util.js"></script> 874 <script src="js/ethereumjs-util.js"></script>
834 <script src="js/ripple-util.js"></script> 875 <script src="js/ripple-util.js"></script>
835 <script src="js/sjcl-bip39.js"></script> 876 <script src="js/sjcl-bip39.js"></script>
diff --git a/src/js/bitcoinjs-extensions.js b/src/js/bitcoinjs-extensions.js
index 63f7c6e..1509a6c 100644
--- a/src/js/bitcoinjs-extensions.js
+++ b/src/js/bitcoinjs-extensions.js
@@ -284,39 +284,6 @@ bitcoinjs.bitcoin.networks.monacoin = {
284 wif: 0xb0 284 wif: 0xb0
285}; 285};
286 286
287bitcoinjs.bitcoin.networks.bitcoinBip49 = {
288 messagePrefix: '\x18Bitcoin Signed Message:\n',
289 bip32: {
290 public: 0x049d7cb2,
291 private: 0x049d7878
292 },
293 pubKeyHash: 0x00,
294 scriptHash: 0x05,
295 wif: 0x80
296};
297
298bitcoinjs.bitcoin.networks.testnetBip49 = {
299 messagePrefix: '\x18Bitcoin Signed Message:\n',
300 bip32: {
301 public: 0x044a5262,
302 private: 0x044a4e28
303 },
304 pubKeyHash: 0x6f,
305 scriptHash: 0xc4,
306 wif: 0xef
307};
308
309bitcoinjs.bitcoin.networks.litecoinBip49 = {
310 messagePrefix: '\x19Litecoin Signed Message:\n',
311 bip32: {
312 public: 0x01b26ef6,
313 private: 0x01b26792
314 },
315 pubKeyHash: 0x30,
316 scriptHash: 0x32,
317 wif: 0xb0
318};
319
320bitcoinjs.bitcoin.networks.litecoinXprv = { 287bitcoinjs.bitcoin.networks.litecoinXprv = {
321 messagePrefix: '\x19Litecoin Signed Message:\n', 288 messagePrefix: '\x19Litecoin Signed Message:\n',
322 bip32: { 289 bip32: {
diff --git a/src/js/index.js b/src/js/index.js
index b88e9d7..261a6d1 100644
--- a/src/js/index.js
+++ b/src/js/index.js
@@ -52,6 +52,7 @@
52 DOM.bip32tab = $("#bip32-tab"); 52 DOM.bip32tab = $("#bip32-tab");
53 DOM.bip44tab = $("#bip44-tab"); 53 DOM.bip44tab = $("#bip44-tab");
54 DOM.bip49tab = $("#bip49-tab"); 54 DOM.bip49tab = $("#bip49-tab");
55 DOM.bip141tab = $("#bip141-tab");
55 DOM.bip32panel = $("#bip32"); 56 DOM.bip32panel = $("#bip32");
56 DOM.bip44panel = $("#bip44"); 57 DOM.bip44panel = $("#bip44");
57 DOM.bip49panel = $("#bip49"); 58 DOM.bip49panel = $("#bip49");
@@ -72,6 +73,10 @@
72 DOM.bip49accountXprv = $("#bip49 .account-xprv"); 73 DOM.bip49accountXprv = $("#bip49 .account-xprv");
73 DOM.bip49accountXpub = $("#bip49 .account-xpub"); 74 DOM.bip49accountXpub = $("#bip49 .account-xpub");
74 DOM.bip49change = $("#bip49 .change"); 75 DOM.bip49change = $("#bip49 .change");
76 DOM.bip141unavailable = $("#bip141 .unavailable");
77 DOM.bip141available = $("#bip141 .available");
78 DOM.bip141path = $("#bip141-path");
79 DOM.bip141semantics = $(".bip141-semantics");
75 DOM.generatedStrength = $(".generate-container .strength"); 80 DOM.generatedStrength = $(".generate-container .strength");
76 DOM.hardenedAddresses = $(".hardened-addresses"); 81 DOM.hardenedAddresses = $(".hardened-addresses");
77 DOM.useBitpayAddressesContainer = $(".use-bitpay-addresses-container"); 82 DOM.useBitpayAddressesContainer = $(".use-bitpay-addresses-container");
@@ -111,6 +116,8 @@
111 DOM.bip44change.on("input", calcForDerivationPath); 116 DOM.bip44change.on("input", calcForDerivationPath);
112 DOM.bip49account.on("input", calcForDerivationPath); 117 DOM.bip49account.on("input", calcForDerivationPath);
113 DOM.bip49change.on("input", calcForDerivationPath); 118 DOM.bip49change.on("input", calcForDerivationPath);
119 DOM.bip141path.on("input", calcForDerivationPath);
120 DOM.bip141semantics.on("change", tabChanged);
114 DOM.tab.on("shown.bs.tab", tabChanged); 121 DOM.tab.on("shown.bs.tab", tabChanged);
115 DOM.hardenedAddresses.on("change", calcForDerivationPath); 122 DOM.hardenedAddresses.on("change", calcForDerivationPath);
116 DOM.indexToggle.on("click", toggleIndexes); 123 DOM.indexToggle.on("click", toggleIndexes);
@@ -138,6 +145,7 @@
138 var network = networks[networkIndex]; 145 var network = networks[networkIndex];
139 network.onSelect(); 146 network.onSelect();
140 if (network.segwitAvailable) { 147 if (network.segwitAvailable) {
148 adjustNetworkForSegwit();
141 showSegwitAvailable(); 149 showSegwitAvailable();
142 } 150 }
143 else { 151 else {
@@ -343,7 +351,7 @@
343 if (bip44TabSelected()) { 351 if (bip44TabSelected()) {
344 displayBip44Info(); 352 displayBip44Info();
345 } 353 }
346 if (bip49TabSelected()) { 354 else if (bip49TabSelected()) {
347 displayBip49Info(); 355 displayBip49Info();
348 } 356 }
349 displayBip32Info(); 357 displayBip32Info();
@@ -523,7 +531,7 @@
523 console.log("Using derivation path from BIP44 tab: " + derivationPath); 531 console.log("Using derivation path from BIP44 tab: " + derivationPath);
524 return derivationPath; 532 return derivationPath;
525 } 533 }
526 if (bip49TabSelected()) { 534 else if (bip49TabSelected()) {
527 var purpose = parseIntNoNaN(DOM.bip49purpose.val(), 49); 535 var purpose = parseIntNoNaN(DOM.bip49purpose.val(), 49);
528 var coin = parseIntNoNaN(DOM.bip49coin.val(), 0); 536 var coin = parseIntNoNaN(DOM.bip49coin.val(), 0);
529 var account = parseIntNoNaN(DOM.bip49account.val(), 0); 537 var account = parseIntNoNaN(DOM.bip49account.val(), 0);
@@ -543,6 +551,11 @@
543 console.log("Using derivation path from BIP32 tab: " + derivationPath); 551 console.log("Using derivation path from BIP32 tab: " + derivationPath);
544 return derivationPath; 552 return derivationPath;
545 } 553 }
554 else if (bip141TabSelected()) {
555 var derivationPath = DOM.bip141path.val();
556 console.log("Using derivation path from BIP141 tab: " + derivationPath);
557 return derivationPath;
558 }
546 else { 559 else {
547 console.log("Unknown derivation path"); 560 console.log("Unknown derivation path");
548 } 561 }
@@ -673,7 +686,16 @@
673 } 686 }
674 687
675 function segwitSelected() { 688 function segwitSelected() {
676 return bip49TabSelected(); 689 return bip49TabSelected() || bip141TabSelected();
690 }
691
692 function p2wpkhSelected() {
693 return bip141TabSelected() && DOM.bip141semantics.val() == "p2wpkh";
694 }
695
696 function p2wpkhInP2shSelected() {
697 return bip49TabSelected() ||
698 (bip141TabSelected() && DOM.bip141semantics.val() == "p2wpkh-p2sh");
677 } 699 }
678 700
679 function TableRow(index, isLast) { 701 function TableRow(index, isLast) {
@@ -683,6 +705,8 @@
683 var useHardenedAddresses = DOM.hardenedAddresses.prop("checked"); 705 var useHardenedAddresses = DOM.hardenedAddresses.prop("checked");
684 var isSegwit = segwitSelected(); 706 var isSegwit = segwitSelected();
685 var segwitAvailable = networkHasSegwit(); 707 var segwitAvailable = networkHasSegwit();
708 var isP2wpkh = p2wpkhSelected();
709 var isP2wpkhInP2sh = p2wpkhInP2shSelected();
686 710
687 function init() { 711 function init() {
688 calculateValues(); 712 calculateValues();
@@ -731,11 +755,18 @@
731 if (!segwitAvailable) { 755 if (!segwitAvailable) {
732 return; 756 return;
733 } 757 }
734 var keyhash = bitcoinjs.bitcoin.crypto.hash160(key.getPublicKeyBuffer()); 758 if (isP2wpkh) {
735 var scriptsig = bitcoinjs.bitcoin.script.witnessPubKeyHash.output.encode(keyhash); 759 var keyhash = bitcoinjs.bitcoin.crypto.hash160(key.getPublicKeyBuffer());
736 var addressbytes = bitcoinjs.bitcoin.crypto.hash160(scriptsig); 760 var scriptpubkey = bitcoinjs.bitcoin.script.witnessPubKeyHash.output.encode(keyhash);
737 var scriptpubkey = bitcoinjs.bitcoin.script.scriptHash.output.encode(addressbytes); 761 address = bitcoinjs.bitcoin.address.fromOutputScript(scriptpubkey, network)
738 address = bitcoinjs.bitcoin.address.fromOutputScript(scriptpubkey, network) 762 }
763 else if (isP2wpkhInP2sh) {
764 var keyhash = bitcoinjs.bitcoin.crypto.hash160(key.getPublicKeyBuffer());
765 var scriptsig = bitcoinjs.bitcoin.script.witnessPubKeyHash.output.encode(keyhash);
766 var addressbytes = bitcoinjs.bitcoin.crypto.hash160(scriptsig);
767 var scriptpubkey = bitcoinjs.bitcoin.script.scriptHash.output.encode(addressbytes);
768 address = bitcoinjs.bitcoin.address.fromOutputScript(scriptpubkey, network)
769 }
739 } 770 }
740 addAddressToList(indexText, address, pubkey, privkey); 771 addAddressToList(indexText, address, pubkey, privkey);
741 if (isLast) { 772 if (isLast) {
@@ -1233,6 +1264,10 @@
1233 return DOM.bip49tab.hasClass("active"); 1264 return DOM.bip49tab.hasClass("active");
1234 } 1265 }
1235 1266
1267 function bip141TabSelected() {
1268 return DOM.bip141tab.hasClass("active");
1269 }
1270
1236 function setHdCoin(coinValue) { 1271 function setHdCoin(coinValue) {
1237 DOM.bip44coin.val(coinValue); 1272 DOM.bip44coin.val(coinValue);
1238 DOM.bip49coin.val(coinValue); 1273 DOM.bip49coin.val(coinValue);
@@ -1241,11 +1276,15 @@
1241 function showSegwitAvailable() { 1276 function showSegwitAvailable() {
1242 DOM.bip49unavailable.addClass("hidden"); 1277 DOM.bip49unavailable.addClass("hidden");
1243 DOM.bip49available.removeClass("hidden"); 1278 DOM.bip49available.removeClass("hidden");
1279 DOM.bip141unavailable.addClass("hidden");
1280 DOM.bip141available.removeClass("hidden");
1244 } 1281 }
1245 1282
1246 function showSegwitUnavailable() { 1283 function showSegwitUnavailable() {
1247 DOM.bip49available.addClass("hidden"); 1284 DOM.bip49available.addClass("hidden");
1248 DOM.bip49unavailable.removeClass("hidden"); 1285 DOM.bip49unavailable.removeClass("hidden");
1286 DOM.bip141available.addClass("hidden");
1287 DOM.bip141unavailable.removeClass("hidden");
1249 } 1288 }
1250 1289
1251 function useBitpayAddresses() { 1290 function useBitpayAddresses() {
@@ -1266,27 +1305,18 @@
1266 // to avoid accidentally importing BIP49 xpub to BIP44 watch only 1305 // to avoid accidentally importing BIP49 xpub to BIP44 watch only
1267 // wallet. 1306 // wallet.
1268 // See https://github.com/iancoleman/bip39/issues/125 1307 // See https://github.com/iancoleman/bip39/issues/125
1269 if (segwitSelected()) { 1308 var segwitNetworks = null;
1270 if (network == bitcoinjs.bitcoin.networks.bitcoin) { 1309 // if a segwit network is alread selected, need to use base network to
1271 network = bitcoinjs.bitcoin.networks.bitcoinBip49; 1310 // look up new parameters
1272 } 1311 if ("baseNetwork" in network) {
1273 else if (network == bitcoinjs.bitcoin.networks.testnet) { 1312 network = bitcoinjs.bitcoin.networks[network.baseNetwork];
1274 network = bitcoinjs.bitcoin.networks.testnetBip49; 1313 }
1275 } 1314 // choose the right segwit params
1276 else if (network == bitcoinjs.bitcoin.networks.litecoin) { 1315 if (p2wpkhSelected() && "p2wpkh" in network) {
1277 network = bitcoinjs.bitcoin.networks.litecoinBip49; 1316 network = network.p2wpkh;
1278 } 1317 }
1279 } 1318 else if (p2wpkhInP2shSelected() && "p2wpkhInP2sh" in network) {
1280 else { 1319 network = network.p2wpkhInP2sh;
1281 if (network == bitcoinjs.bitcoin.networks.bitcoinBip49) {
1282 network = bitcoinjs.bitcoin.networks.bitcoin;
1283 }
1284 else if (network == bitcoinjs.bitcoin.networks.testnetBip49) {
1285 network = bitcoinjs.bitcoin.networks.testnet;
1286 }
1287 else if (network == bitcoinjs.bitcoin.networks.litecoinBip49) {
1288 network = bitcoinjs.bitcoin.networks.litecoin;
1289 }
1290 } 1320 }
1291 } 1321 }
1292 1322
diff --git a/src/js/segwit-parameters.js b/src/js/segwit-parameters.js
new file mode 100644
index 0000000..38cf9e0
--- /dev/null
+++ b/src/js/segwit-parameters.js
@@ -0,0 +1,58 @@
1(function() {
2
3// p2wpkh
4
5bitcoinjs.bitcoin.networks.bitcoin.p2wpkh = {
6 baseNetwork: "bitcoin",
7 messagePrefix: '\x18Bitcoin Signed Message:\n',
8 bech32: 'bc',
9 bip32: {
10 public: 0x04b24746,
11 private: 0x04b2430c
12 },
13 pubKeyHash: 0x00,
14 scriptHash: 0x05,
15 wif: 0x80
16};
17
18// p2wpkh in p2sh
19
20bitcoinjs.bitcoin.networks.bitcoin.p2wpkhInP2sh = {
21 baseNetwork: "bitcoin",
22 messagePrefix: '\x18Bitcoin Signed Message:\n',
23 bech32: 'bc',
24 bip32: {
25 public: 0x049d7cb2,
26 private: 0x049d7878
27 },
28 pubKeyHash: 0x00,
29 scriptHash: 0x05,
30 wif: 0x80
31};
32
33bitcoinjs.bitcoin.networks.testnet.p2wpkhInP2sh = {
34 baseNetwork: "testnet",
35 messagePrefix: '\x18Bitcoin Signed Message:\n',
36 bech32: 'tb',
37 bip32: {
38 public: 0x044a5262,
39 private: 0x044a4e28
40 },
41 pubKeyHash: 0x6f,
42 scriptHash: 0xc4,
43 wif: 0xef
44};
45
46bitcoinjs.bitcoin.networks.litecoin.p2wpkhInP2sh = {
47 baseNetwork: "litecoin",
48 messagePrefix: '\x19Litecoin Signed Message:\n',
49 bip32: {
50 public: 0x01b26ef6,
51 private: 0x01b26792
52 },
53 pubKeyHash: 0x30,
54 scriptHash: 0x32,
55 wif: 0xb0
56};
57
58})();