mirror of
https://github.com/OneKeyHQ/bip39.git
synced 2026-04-05 18:43:47 +00:00
Add BIP141 tab for full segwit compatibility
This commit is contained in:
@@ -301,6 +301,9 @@
|
||||
<li id="bip49-tab">
|
||||
<a href="#bip49" role="tab" data-toggle="tab">BIP49</a>
|
||||
</li>
|
||||
<li id="bip141-tab">
|
||||
<a href="#bip141" role="tab" data-toggle="tab">BIP141</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="derivation-type tab-content">
|
||||
<div id="bip44" class="tab-pane active">
|
||||
@@ -544,6 +547,43 @@
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div id="bip141" class="tab-pane">
|
||||
<form class="form-horizontal" role="form">
|
||||
<br>
|
||||
<div class="unavailable hidden">
|
||||
<div class="form-group">
|
||||
<div class="col-sm-2"></div>
|
||||
<div class="col-sm-10">
|
||||
<p>BIP141 is unavailable for this coin.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="available">
|
||||
<div class="col-sm-2"></div>
|
||||
<div class="col-sm-10">
|
||||
<p>
|
||||
For more info see the
|
||||
<a href="https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki" target="_blank">BIP141 spec</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="bip141-path" class="col-sm-2 control-label">BIP32 Derivation Path</label>
|
||||
<div class="col-sm-10">
|
||||
<input id="bip141-path" type="text" class="bip141-path form-control" value="m/0">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">Script Semantics</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control bip141-semantics">
|
||||
<option value="p2wpkh">P2WPKH</option>
|
||||
<option value="p2wpkh-p2sh" selected>P2WPKH nested in P2SH</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<form class="form-horizontal" role="form">
|
||||
<div class="form-group">
|
||||
@@ -830,6 +870,7 @@
|
||||
<script src="js/jquery.qrcode.min.js"></script>
|
||||
<script src="js/bitcoinjs-3.3.0.js"></script>
|
||||
<script src="js/bitcoinjs-extensions.js"></script>
|
||||
<script src="js/segwit-parameters.js"></script>
|
||||
<script src="js/ethereumjs-util.js"></script>
|
||||
<script src="js/ripple-util.js"></script>
|
||||
<script src="js/sjcl-bip39.js"></script>
|
||||
|
||||
@@ -284,39 +284,6 @@ bitcoinjs.bitcoin.networks.monacoin = {
|
||||
wif: 0xb0
|
||||
};
|
||||
|
||||
bitcoinjs.bitcoin.networks.bitcoinBip49 = {
|
||||
messagePrefix: '\x18Bitcoin Signed Message:\n',
|
||||
bip32: {
|
||||
public: 0x049d7cb2,
|
||||
private: 0x049d7878
|
||||
},
|
||||
pubKeyHash: 0x00,
|
||||
scriptHash: 0x05,
|
||||
wif: 0x80
|
||||
};
|
||||
|
||||
bitcoinjs.bitcoin.networks.testnetBip49 = {
|
||||
messagePrefix: '\x18Bitcoin Signed Message:\n',
|
||||
bip32: {
|
||||
public: 0x044a5262,
|
||||
private: 0x044a4e28
|
||||
},
|
||||
pubKeyHash: 0x6f,
|
||||
scriptHash: 0xc4,
|
||||
wif: 0xef
|
||||
};
|
||||
|
||||
bitcoinjs.bitcoin.networks.litecoinBip49 = {
|
||||
messagePrefix: '\x19Litecoin Signed Message:\n',
|
||||
bip32: {
|
||||
public: 0x01b26ef6,
|
||||
private: 0x01b26792
|
||||
},
|
||||
pubKeyHash: 0x30,
|
||||
scriptHash: 0x32,
|
||||
wif: 0xb0
|
||||
};
|
||||
|
||||
bitcoinjs.bitcoin.networks.litecoinXprv = {
|
||||
messagePrefix: '\x19Litecoin Signed Message:\n',
|
||||
bip32: {
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
DOM.bip32tab = $("#bip32-tab");
|
||||
DOM.bip44tab = $("#bip44-tab");
|
||||
DOM.bip49tab = $("#bip49-tab");
|
||||
DOM.bip141tab = $("#bip141-tab");
|
||||
DOM.bip32panel = $("#bip32");
|
||||
DOM.bip44panel = $("#bip44");
|
||||
DOM.bip49panel = $("#bip49");
|
||||
@@ -72,6 +73,10 @@
|
||||
DOM.bip49accountXprv = $("#bip49 .account-xprv");
|
||||
DOM.bip49accountXpub = $("#bip49 .account-xpub");
|
||||
DOM.bip49change = $("#bip49 .change");
|
||||
DOM.bip141unavailable = $("#bip141 .unavailable");
|
||||
DOM.bip141available = $("#bip141 .available");
|
||||
DOM.bip141path = $("#bip141-path");
|
||||
DOM.bip141semantics = $(".bip141-semantics");
|
||||
DOM.generatedStrength = $(".generate-container .strength");
|
||||
DOM.hardenedAddresses = $(".hardened-addresses");
|
||||
DOM.useBitpayAddressesContainer = $(".use-bitpay-addresses-container");
|
||||
@@ -111,6 +116,8 @@
|
||||
DOM.bip44change.on("input", calcForDerivationPath);
|
||||
DOM.bip49account.on("input", calcForDerivationPath);
|
||||
DOM.bip49change.on("input", calcForDerivationPath);
|
||||
DOM.bip141path.on("input", calcForDerivationPath);
|
||||
DOM.bip141semantics.on("change", tabChanged);
|
||||
DOM.tab.on("shown.bs.tab", tabChanged);
|
||||
DOM.hardenedAddresses.on("change", calcForDerivationPath);
|
||||
DOM.indexToggle.on("click", toggleIndexes);
|
||||
@@ -138,6 +145,7 @@
|
||||
var network = networks[networkIndex];
|
||||
network.onSelect();
|
||||
if (network.segwitAvailable) {
|
||||
adjustNetworkForSegwit();
|
||||
showSegwitAvailable();
|
||||
}
|
||||
else {
|
||||
@@ -343,7 +351,7 @@
|
||||
if (bip44TabSelected()) {
|
||||
displayBip44Info();
|
||||
}
|
||||
if (bip49TabSelected()) {
|
||||
else if (bip49TabSelected()) {
|
||||
displayBip49Info();
|
||||
}
|
||||
displayBip32Info();
|
||||
@@ -523,7 +531,7 @@
|
||||
console.log("Using derivation path from BIP44 tab: " + derivationPath);
|
||||
return derivationPath;
|
||||
}
|
||||
if (bip49TabSelected()) {
|
||||
else if (bip49TabSelected()) {
|
||||
var purpose = parseIntNoNaN(DOM.bip49purpose.val(), 49);
|
||||
var coin = parseIntNoNaN(DOM.bip49coin.val(), 0);
|
||||
var account = parseIntNoNaN(DOM.bip49account.val(), 0);
|
||||
@@ -543,6 +551,11 @@
|
||||
console.log("Using derivation path from BIP32 tab: " + derivationPath);
|
||||
return derivationPath;
|
||||
}
|
||||
else if (bip141TabSelected()) {
|
||||
var derivationPath = DOM.bip141path.val();
|
||||
console.log("Using derivation path from BIP141 tab: " + derivationPath);
|
||||
return derivationPath;
|
||||
}
|
||||
else {
|
||||
console.log("Unknown derivation path");
|
||||
}
|
||||
@@ -673,7 +686,16 @@
|
||||
}
|
||||
|
||||
function segwitSelected() {
|
||||
return bip49TabSelected();
|
||||
return bip49TabSelected() || bip141TabSelected();
|
||||
}
|
||||
|
||||
function p2wpkhSelected() {
|
||||
return bip141TabSelected() && DOM.bip141semantics.val() == "p2wpkh";
|
||||
}
|
||||
|
||||
function p2wpkhInP2shSelected() {
|
||||
return bip49TabSelected() ||
|
||||
(bip141TabSelected() && DOM.bip141semantics.val() == "p2wpkh-p2sh");
|
||||
}
|
||||
|
||||
function TableRow(index, isLast) {
|
||||
@@ -683,6 +705,8 @@
|
||||
var useHardenedAddresses = DOM.hardenedAddresses.prop("checked");
|
||||
var isSegwit = segwitSelected();
|
||||
var segwitAvailable = networkHasSegwit();
|
||||
var isP2wpkh = p2wpkhSelected();
|
||||
var isP2wpkhInP2sh = p2wpkhInP2shSelected();
|
||||
|
||||
function init() {
|
||||
calculateValues();
|
||||
@@ -731,11 +755,18 @@
|
||||
if (!segwitAvailable) {
|
||||
return;
|
||||
}
|
||||
var keyhash = bitcoinjs.bitcoin.crypto.hash160(key.getPublicKeyBuffer());
|
||||
var scriptsig = bitcoinjs.bitcoin.script.witnessPubKeyHash.output.encode(keyhash);
|
||||
var addressbytes = bitcoinjs.bitcoin.crypto.hash160(scriptsig);
|
||||
var scriptpubkey = bitcoinjs.bitcoin.script.scriptHash.output.encode(addressbytes);
|
||||
address = bitcoinjs.bitcoin.address.fromOutputScript(scriptpubkey, network)
|
||||
if (isP2wpkh) {
|
||||
var keyhash = bitcoinjs.bitcoin.crypto.hash160(key.getPublicKeyBuffer());
|
||||
var scriptpubkey = bitcoinjs.bitcoin.script.witnessPubKeyHash.output.encode(keyhash);
|
||||
address = bitcoinjs.bitcoin.address.fromOutputScript(scriptpubkey, network)
|
||||
}
|
||||
else if (isP2wpkhInP2sh) {
|
||||
var keyhash = bitcoinjs.bitcoin.crypto.hash160(key.getPublicKeyBuffer());
|
||||
var scriptsig = bitcoinjs.bitcoin.script.witnessPubKeyHash.output.encode(keyhash);
|
||||
var addressbytes = bitcoinjs.bitcoin.crypto.hash160(scriptsig);
|
||||
var scriptpubkey = bitcoinjs.bitcoin.script.scriptHash.output.encode(addressbytes);
|
||||
address = bitcoinjs.bitcoin.address.fromOutputScript(scriptpubkey, network)
|
||||
}
|
||||
}
|
||||
addAddressToList(indexText, address, pubkey, privkey);
|
||||
if (isLast) {
|
||||
@@ -1233,6 +1264,10 @@
|
||||
return DOM.bip49tab.hasClass("active");
|
||||
}
|
||||
|
||||
function bip141TabSelected() {
|
||||
return DOM.bip141tab.hasClass("active");
|
||||
}
|
||||
|
||||
function setHdCoin(coinValue) {
|
||||
DOM.bip44coin.val(coinValue);
|
||||
DOM.bip49coin.val(coinValue);
|
||||
@@ -1241,11 +1276,15 @@
|
||||
function showSegwitAvailable() {
|
||||
DOM.bip49unavailable.addClass("hidden");
|
||||
DOM.bip49available.removeClass("hidden");
|
||||
DOM.bip141unavailable.addClass("hidden");
|
||||
DOM.bip141available.removeClass("hidden");
|
||||
}
|
||||
|
||||
function showSegwitUnavailable() {
|
||||
DOM.bip49available.addClass("hidden");
|
||||
DOM.bip49unavailable.removeClass("hidden");
|
||||
DOM.bip141available.addClass("hidden");
|
||||
DOM.bip141unavailable.removeClass("hidden");
|
||||
}
|
||||
|
||||
function useBitpayAddresses() {
|
||||
@@ -1266,27 +1305,18 @@
|
||||
// to avoid accidentally importing BIP49 xpub to BIP44 watch only
|
||||
// wallet.
|
||||
// See https://github.com/iancoleman/bip39/issues/125
|
||||
if (segwitSelected()) {
|
||||
if (network == bitcoinjs.bitcoin.networks.bitcoin) {
|
||||
network = bitcoinjs.bitcoin.networks.bitcoinBip49;
|
||||
}
|
||||
else if (network == bitcoinjs.bitcoin.networks.testnet) {
|
||||
network = bitcoinjs.bitcoin.networks.testnetBip49;
|
||||
}
|
||||
else if (network == bitcoinjs.bitcoin.networks.litecoin) {
|
||||
network = bitcoinjs.bitcoin.networks.litecoinBip49;
|
||||
}
|
||||
var segwitNetworks = null;
|
||||
// if a segwit network is alread selected, need to use base network to
|
||||
// look up new parameters
|
||||
if ("baseNetwork" in network) {
|
||||
network = bitcoinjs.bitcoin.networks[network.baseNetwork];
|
||||
}
|
||||
else {
|
||||
if (network == bitcoinjs.bitcoin.networks.bitcoinBip49) {
|
||||
network = bitcoinjs.bitcoin.networks.bitcoin;
|
||||
}
|
||||
else if (network == bitcoinjs.bitcoin.networks.testnetBip49) {
|
||||
network = bitcoinjs.bitcoin.networks.testnet;
|
||||
}
|
||||
else if (network == bitcoinjs.bitcoin.networks.litecoinBip49) {
|
||||
network = bitcoinjs.bitcoin.networks.litecoin;
|
||||
}
|
||||
// choose the right segwit params
|
||||
if (p2wpkhSelected() && "p2wpkh" in network) {
|
||||
network = network.p2wpkh;
|
||||
}
|
||||
else if (p2wpkhInP2shSelected() && "p2wpkhInP2sh" in network) {
|
||||
network = network.p2wpkhInP2sh;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
58
src/js/segwit-parameters.js
Normal file
58
src/js/segwit-parameters.js
Normal file
@@ -0,0 +1,58 @@
|
||||
(function() {
|
||||
|
||||
// p2wpkh
|
||||
|
||||
bitcoinjs.bitcoin.networks.bitcoin.p2wpkh = {
|
||||
baseNetwork: "bitcoin",
|
||||
messagePrefix: '\x18Bitcoin Signed Message:\n',
|
||||
bech32: 'bc',
|
||||
bip32: {
|
||||
public: 0x04b24746,
|
||||
private: 0x04b2430c
|
||||
},
|
||||
pubKeyHash: 0x00,
|
||||
scriptHash: 0x05,
|
||||
wif: 0x80
|
||||
};
|
||||
|
||||
// p2wpkh in p2sh
|
||||
|
||||
bitcoinjs.bitcoin.networks.bitcoin.p2wpkhInP2sh = {
|
||||
baseNetwork: "bitcoin",
|
||||
messagePrefix: '\x18Bitcoin Signed Message:\n',
|
||||
bech32: 'bc',
|
||||
bip32: {
|
||||
public: 0x049d7cb2,
|
||||
private: 0x049d7878
|
||||
},
|
||||
pubKeyHash: 0x00,
|
||||
scriptHash: 0x05,
|
||||
wif: 0x80
|
||||
};
|
||||
|
||||
bitcoinjs.bitcoin.networks.testnet.p2wpkhInP2sh = {
|
||||
baseNetwork: "testnet",
|
||||
messagePrefix: '\x18Bitcoin Signed Message:\n',
|
||||
bech32: 'tb',
|
||||
bip32: {
|
||||
public: 0x044a5262,
|
||||
private: 0x044a4e28
|
||||
},
|
||||
pubKeyHash: 0x6f,
|
||||
scriptHash: 0xc4,
|
||||
wif: 0xef
|
||||
};
|
||||
|
||||
bitcoinjs.bitcoin.networks.litecoin.p2wpkhInP2sh = {
|
||||
baseNetwork: "litecoin",
|
||||
messagePrefix: '\x19Litecoin Signed Message:\n',
|
||||
bip32: {
|
||||
public: 0x01b26ef6,
|
||||
private: 0x01b26792
|
||||
},
|
||||
pubKeyHash: 0x30,
|
||||
scriptHash: 0x32,
|
||||
wif: 0xb0
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -2596,4 +2596,51 @@ it('Can generate more addresses from a custom index', function(done) {
|
||||
});
|
||||
});
|
||||
|
||||
it('Can generate BIP141 addresses with P2WPKH-in-P2SH semanitcs', function(done) {
|
||||
// Sourced from BIP49 official test specs
|
||||
driver.findElement(By.css('#bip141-tab a'))
|
||||
.click();
|
||||
driver.findElement(By.css('.bip141-path'))
|
||||
.clear();
|
||||
driver.findElement(By.css('.bip141-path'))
|
||||
.sendKeys("m/49'/1'/0'/0");
|
||||
selectNetwork("BTC - Bitcoin Testnet");
|
||||
driver.findElement(By.css(".phrase"))
|
||||
.sendKeys("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about");
|
||||
driver.sleep(generateDelay).then(function() {
|
||||
getFirstAddress(function(address) {
|
||||
expect(address).toBe("2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Can generate BIP141 addresses with P2WPKH semanitcs', function(done) {
|
||||
// This result tested against bitcoinjs-lib test spec for segwit address
|
||||
// using the first private key of this mnemonic and default path m/0
|
||||
// https://github.com/bitcoinjs/bitcoinjs-lib/blob/9c8503cab0c6c30a95127042703bc18e8d28c76d/test/integration/addresses.js#L50
|
||||
// so whilst not directly comparable, substituting the private key produces
|
||||
// identical results between this tool and the bitcoinjs-lib test.
|
||||
// Private key generated is:
|
||||
// L3L8Nu9whawPBNLGtFqDhKut9DKKfG3CQoysupT7BimqVCZsLFNP
|
||||
driver.findElement(By.css('#bip141-tab a'))
|
||||
.click();
|
||||
// Choose P2WPKH
|
||||
driver.executeScript(function() {
|
||||
$(".bip141-semantics option[selected]").removeAttr("selected");
|
||||
$(".bip141-semantics option").filter(function(i,e) {
|
||||
return $(e).html() == "P2WPKH";
|
||||
}).prop("selected", true);
|
||||
$(".bip141-semantics").trigger("change");
|
||||
});
|
||||
driver.findElement(By.css(".phrase"))
|
||||
.sendKeys("abandon abandon ability");
|
||||
driver.sleep(generateDelay).then(function() {
|
||||
getFirstAddress(function(address) {
|
||||
expect(address).toBe("bc1qfwu6a5a3evygrk8zvdxxvz4547lmpyx5vsfxe9");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user