commit 359882d0b18894a0ca55a33e269c9fe8d1a57f76
parent 3c755aaa90dbbbe02cceb4eb81908f5f0e8ea81f
Author: ThomasV <thomasv@electrum.org>
Date: Thu, 11 Jan 2018 16:43:34 +0100
Merge pull request #3630 from SomberNight/bip84
bip84 for sw seeds
Diffstat:
3 files changed, 42 insertions(+), 9 deletions(-)
diff --git a/lib/base_wizard.py b/lib/base_wizard.py
@@ -232,14 +232,15 @@ class BaseWizard(object):
self.derivation_dialog(f)
def derivation_dialog(self, f):
- default = bip44_derivation(0, False)
+ default = bip44_derivation(0, bip43_purpose=44)
message = '\n'.join([
_('Enter your wallet derivation here.'),
_('If you are not sure what this is, leave this field unchanged.')
])
presets = (
- ('legacy BIP44', bip44_derivation(0, False)),
- ('p2sh-segwit BIP49', bip44_derivation(0, True)),
+ ('legacy BIP44', bip44_derivation(0, bip43_purpose=44)),
+ ('p2sh-segwit BIP49', bip44_derivation(0, bip43_purpose=49)),
+ ('native-segwit BIP84', bip44_derivation(0, bip43_purpose=84)),
)
self.line_dialog(run_next=f, title=_('Derivation'), message=message,
default=default, test=bitcoin.is_bip32_derivation,
@@ -247,7 +248,10 @@ class BaseWizard(object):
def on_hw_derivation(self, name, device_info, derivation):
from .keystore import hardware_keystore
- xtype = 'p2wpkh-p2sh' if derivation.startswith("m/49'/") else 'standard'
+ xtype = keystore.xtype_from_derivation(derivation)
+ if xtype not in ('standard', 'p2wpkh-p2sh'):
+ self.show_error(_('Hardware wallet support for this script type is not yet enabled.'))
+ return
try:
xpub = self.plugin.get_xpub(device_info.device.id_, derivation, xtype, self)
except BaseException as e:
diff --git a/lib/keystore.py b/lib/keystore.py
@@ -571,10 +571,21 @@ def bip39_is_checksum_valid(mnemonic):
def from_bip39_seed(seed, passphrase, derivation):
k = BIP32_KeyStore({})
bip32_seed = bip39_to_seed(seed, passphrase)
- t = 'p2wpkh-p2sh' if derivation.startswith("m/49'") else 'standard' # bip43
- k.add_xprv_from_seed(bip32_seed, t, derivation)
+ xtype = xtype_from_derivation(derivation)
+ k.add_xprv_from_seed(bip32_seed, xtype, derivation)
return k
+
+def xtype_from_derivation(derivation):
+ """Returns the script type to be used for this derivation."""
+ if derivation.startswith("m/84'"):
+ return 'p2wpkh'
+ elif derivation.startswith("m/49'"):
+ return 'p2wpkh-p2sh'
+ else:
+ return 'standard'
+
+
# extended pubkeys
def is_xpubkey(x_pubkey):
@@ -671,10 +682,9 @@ is_private_key = lambda x: is_xprv(x) or is_private_key_list(x)
is_bip32_key = lambda x: is_xprv(x) or is_xpub(x)
-def bip44_derivation(account_id, segwit=False):
- bip = 49 if segwit else 44
+def bip44_derivation(account_id, bip43_purpose=44):
coin = 1 if bitcoin.NetworkConstants.TESTNET else 0
- return "m/%d'/%d'/%d'" % (bip, coin, int(account_id))
+ return "m/%d'/%d'/%d'" % (bip43_purpose, coin, int(account_id))
def from_seed(seed, passphrase, is_p2sh):
t = seed_type(seed)
diff --git a/lib/tests/test_wallet_vertical.py b/lib/tests/test_wallet_vertical.py
@@ -176,6 +176,25 @@ class TestWalletKeystoreAddressIntegrity(unittest.TestCase):
self.assertEqual(w.get_change_addresses()[0], '3KaBTcviBLEJajTEMstsA2GWjYoPzPK7Y7')
@mock.patch.object(storage.WalletStorage, '_write')
+ def test_bip39_seed_bip84_native_segwit(self, mock_write):
+ # test case from bip84
+ seed_words = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'
+ self.assertEqual(keystore.bip39_is_checksum_valid(seed_words), (True, True))
+
+ ks = keystore.from_bip39_seed(seed_words, '', "m/84'/0'/0'")
+
+ self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore))
+
+ self.assertEqual(ks.xprv, 'zprvAdG4iTXWBoARxkkzNpNh8r6Qag3irQB8PzEMkAFeTRXxHpbF9z4QgEvBRmfvqWvGp42t42nvgGpNgYSJA9iefm1yYNZKEm7z6qUWCroSQnE')
+ self.assertEqual(ks.xpub, 'zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs')
+
+ w = self._create_standard_wallet(ks)
+ self.assertEqual(w.txin_type, 'p2wpkh')
+
+ self.assertEqual(w.get_receiving_addresses()[0], 'bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu')
+ self.assertEqual(w.get_change_addresses()[0], 'bc1q8c6fshw2dlwun7ekn9qwf37cu2rn755upcp6el')
+
+ @mock.patch.object(storage.WalletStorage, '_write')
def test_electrum_multisig_seed_standard(self, mock_write):
seed_words = 'blast uniform dragon fiscal ensure vast young utility dinosaur abandon rookie sure'
self.assertEqual(bitcoin.seed_type(seed_words), 'standard')