From 8ab3dcce5dd11100bf565e0d7649daca05ae147f Mon Sep 17 00:00:00 2001 From: SomberNight Date: Wed, 21 Feb 2024 15:08:19 +0000 Subject: [PATCH] keystore: API changes for from_seed/from_bip43_rootseed/bip39_to_seed - force kwargs - add type hints --- electrum/gui/qml/qebip39recovery.py | 2 +- electrum/gui/qt/wizard/wallet.py | 2 +- electrum/keystore.py | 42 ++++++++----- electrum/scripts/bip39_recovery.py | 2 +- electrum/wallet.py | 4 +- electrum/wizard.py | 14 ++--- tests/test_wallet_vertical.py | 98 +++++++++++++++-------------- 7 files changed, 88 insertions(+), 76 deletions(-) diff --git a/electrum/gui/qml/qebip39recovery.py b/electrum/gui/qml/qebip39recovery.py index cb7d70ab5..2e4862732 100644 --- a/electrum/gui/qml/qebip39recovery.py +++ b/electrum/gui/qml/qebip39recovery.py @@ -77,7 +77,7 @@ class QEBip39RecoveryListModel(QAbstractListModel): assert wallet_type == 'standard' - self._root_seed = keystore.bip39_to_seed(seed, seed_extra_words) + self._root_seed = keystore.bip39_to_seed(seed, passphrase=seed_extra_words) self.clear() diff --git a/electrum/gui/qt/wizard/wallet.py b/electrum/gui/qt/wizard/wallet.py index 7bcc7bdae..f34dff1ac 100644 --- a/electrum/gui/qt/wizard/wallet.py +++ b/electrum/gui/qt/wizard/wallet.py @@ -712,7 +712,7 @@ class WCScriptAndDerivation(WalletWizardComponent, Logger): passphrase = self.wizard_data['seed_extra_words'] if self.wizard_data['seed_extend'] else '' if self.wizard_data['seed_variant'] == 'bip39': - root_seed = bip39_to_seed(self.wizard_data['seed'], passphrase) + root_seed = bip39_to_seed(self.wizard_data['seed'], passphrase=passphrase) elif self.wizard_data['seed_variant'] == 'slip39': root_seed = self.wizard_data['seed'].decrypt(passphrase) diff --git a/electrum/keystore.py b/electrum/keystore.py index 53e304d81..dc155cb75 100644 --- a/electrum/keystore.py +++ b/electrum/keystore.py @@ -374,7 +374,7 @@ class Deterministic_KeyStore(Software_KeyStore): def format_seed(self, seed: str) -> str: pass - def add_seed(self, seed): + def add_seed(self, seed: str) -> None: if self.seed: raise Exception("a seed exists") self.seed = self.format_seed(seed) @@ -577,7 +577,7 @@ class Xpub(MasterPublicKeyMixin): deriv_path=strpath, ) - def add_key_origin_from_root_node(self, *, derivation_prefix: str, root_node: BIP32Node): + def add_key_origin_from_root_node(self, *, derivation_prefix: str, root_node: BIP32Node) -> None: assert self.xpub # try to derive ourselves from what we were given child_node1 = root_node.subkey_at_private_derivation(derivation_prefix) @@ -677,18 +677,18 @@ class BIP32_KeyStore(Xpub, Deterministic_KeyStore): def is_watching_only(self): return self.xprv is None - def add_xpub(self, xpub): + def add_xpub(self, xpub: str) -> None: assert is_xpub(xpub) self.xpub = xpub root_fingerprint, derivation_prefix = bip32.root_fp_and_der_prefix_from_xkey(xpub) self.add_key_origin(derivation_prefix=derivation_prefix, root_fingerprint=root_fingerprint) - def add_xprv(self, xprv): + def add_xprv(self, xprv: str) -> None: assert is_xprv(xprv) self.xprv = xprv self.add_xpub(bip32.xpub_from_xprv(xprv)) - def add_xprv_from_seed(self, bip32_seed, xtype, derivation): + def add_xprv_from_seed(self, bip32_seed: bytes, *, xtype: str, derivation: str) -> None: rootnode = BIP32Node.from_rootseed(bip32_seed, xtype=xtype) node = rootnode.subkey_at_private_derivation(derivation) self.add_xprv(node.to_xprv()) @@ -735,12 +735,12 @@ class Old_KeyStore(MasterPublicKeyMixin, Deterministic_KeyStore): d['mpk'] = self.mpk return d - def add_seed(self, seedphrase): - Deterministic_KeyStore.add_seed(self, seedphrase) + def add_seed(self, seed): + Deterministic_KeyStore.add_seed(self, seed) s = self.get_hex_seed(None) self.mpk = self.mpk_from_seed(s) - def add_master_public_key(self, mpk): + def add_master_public_key(self, mpk) -> None: self.mpk = mpk def format_seed(self, seed): @@ -978,11 +978,13 @@ KeyStoreWithMPK = Union[KeyStore, MasterPublicKeyMixin] # intersection really.. AddressIndexGeneric = Union[Sequence[int], str] # can be hex pubkey str -def bip39_normalize_passphrase(passphrase): +def bip39_normalize_passphrase(passphrase: str): return normalize('NFKD', passphrase or '') -def bip39_to_seed(mnemonic, passphrase): - import hashlib, hmac + +def bip39_to_seed(mnemonic: str, *, passphrase: Optional[str]) -> bytes: + import hashlib + passphrase = passphrase or "" PBKDF2_ROUNDS = 2048 mnemonic = normalize('NFKD', ' '.join(mnemonic.split())) passphrase = bip39_normalize_passphrase(passphrase) @@ -1024,11 +1026,16 @@ def bip39_is_checksum_valid( return checksum == calculated_checksum, True -def from_bip43_rootseed(root_seed, derivation, xtype=None): +def from_bip43_rootseed( + root_seed: bytes, + *, + derivation: str, + xtype: Optional[str] = None, +): k = BIP32_KeyStore({}) if xtype is None: xtype = xtype_from_derivation(derivation) - k.add_xprv_from_seed(root_seed, xtype, derivation) + k.add_xprv_from_seed(root_seed, xtype=xtype, derivation=derivation) return k @@ -1156,7 +1163,8 @@ def purpose48_derivation(account_id: int, xtype: str) -> str: return normalize_bip32_derivation(der) -def from_seed(seed, passphrase, is_p2sh=False): +def from_seed(seed: str, *, passphrase: Optional[str], for_multisig: bool = False): + passphrase = passphrase or "" t = seed_type(seed) if t == 'old': if passphrase: @@ -1172,9 +1180,9 @@ def from_seed(seed, passphrase, is_p2sh=False): der = "m/" xtype = 'standard' else: - der = "m/1'/" if is_p2sh else "m/0'/" - xtype = 'p2wsh' if is_p2sh else 'p2wpkh' - keystore.add_xprv_from_seed(bip32_seed, xtype, der) + der = "m/1'/" if for_multisig else "m/0'/" + xtype = 'p2wsh' if for_multisig else 'p2wpkh' + keystore.add_xprv_from_seed(bip32_seed, xtype=xtype, derivation=der) else: raise BitcoinException('Unexpected seed type {}'.format(repr(t))) return keystore diff --git a/electrum/scripts/bip39_recovery.py b/electrum/scripts/bip39_recovery.py index c2a7be4e9..da51d890f 100755 --- a/electrum/scripts/bip39_recovery.py +++ b/electrum/scripts/bip39_recovery.py @@ -27,7 +27,7 @@ network.start() async def f(): try: def get_account_xpub(account_path): - root_seed = bip39_to_seed(mnemonic, passphrase) + root_seed = bip39_to_seed(mnemonic, passphrase=passphrase) root_node = BIP32Node.from_rootseed(root_seed, xtype="standard") account_node = root_node.subkey_at_private_derivation(account_path) account_xpub = account_node.to_xpub() diff --git a/electrum/wallet.py b/electrum/wallet.py index 720e8a1d0..5b4e705da 100644 --- a/electrum/wallet.py +++ b/electrum/wallet.py @@ -3909,7 +3909,7 @@ def create_new_wallet(*, path, config: SimpleConfig, passphrase=None, password=N db = WalletDB('', storage=storage, upgrade=True) seed = Mnemonic('en').make_seed(seed_type=seed_type) - k = keystore.from_seed(seed, passphrase) + k = keystore.from_seed(seed, passphrase=passphrase) db.put('keystore', k.dump()) db.put('wallet_type', 'standard') if k.can_have_deterministic_lightning_xprv(): @@ -3967,7 +3967,7 @@ def restore_wallet_from_text( if keystore.is_master_key(text): k = keystore.from_master_key(text) elif keystore.is_seed(text): - k = keystore.from_seed(text, passphrase) + k = keystore.from_seed(text, passphrase=passphrase) if k.can_have_deterministic_lightning_xprv(): db.put('lightning_xprv', k.get_lightning_xprv(None)) else: diff --git a/electrum/wizard.py b/electrum/wizard.py index 077ea2470..0bf3115a8 100644 --- a/electrum/wizard.py +++ b/electrum/wizard.py @@ -415,15 +415,15 @@ class NewWalletWizard(AbstractWizard): def keystore_from_data(self, wallet_type: str, data: dict): if data['keystore_type'] in ['createseed', 'haveseed'] and 'seed' in data: if data['seed_variant'] == 'electrum': - return keystore.from_seed(data['seed'], data['seed_extra_words'], True) + return keystore.from_seed(data['seed'], passphrase=data['seed_extra_words'], for_multisig=True) elif data['seed_variant'] == 'bip39': - root_seed = keystore.bip39_to_seed(data['seed'], data['seed_extra_words']) + root_seed = keystore.bip39_to_seed(data['seed'], passphrase=data['seed_extra_words']) derivation = normalize_bip32_derivation(data['derivation_path']) if wallet_type == 'multisig': script = data['script_type'] if data['script_type'] != 'p2sh' else 'standard' else: script = data['script_type'] if data['script_type'] != 'p2pkh' else 'standard' - return keystore.from_bip43_rootseed(root_seed, derivation, xtype=script) + return keystore.from_bip43_rootseed(root_seed, derivation=derivation, xtype=script) elif data['seed_variant'] == 'slip39': root_seed = data['seed'].decrypt(data['seed_extra_words']) derivation = normalize_bip32_derivation(data['derivation_path']) @@ -431,7 +431,7 @@ class NewWalletWizard(AbstractWizard): script = data['script_type'] if data['script_type'] != 'p2sh' else 'standard' else: script = data['script_type'] if data['script_type'] != 'p2pkh' else 'standard' - return keystore.from_bip43_rootseed(root_seed, derivation, xtype=script) + return keystore.from_bip43_rootseed(root_seed, derivation=derivation, xtype=script) else: raise Exception('Unsupported seed variant %s' % data['seed_variant']) elif data['keystore_type'] == 'masterkey' and 'master_key' in data: @@ -548,11 +548,11 @@ class NewWalletWizard(AbstractWizard): elif data['keystore_type'] in ['createseed', 'haveseed']: if data['seed_type'] in ['old', 'standard', 'segwit']: self._logger.debug('creating keystore from electrum seed') - k = keystore.from_seed(data['seed'], data['seed_extra_words'], data['wallet_type'] == 'multisig') + k = keystore.from_seed(data['seed'], passphrase=data['seed_extra_words'], for_multisig=data['wallet_type'] == 'multisig') elif data['seed_type'] in ['bip39', 'slip39']: self._logger.debug('creating keystore from %s seed' % data['seed_type']) if data['seed_type'] == 'bip39': - root_seed = keystore.bip39_to_seed(data['seed'], data['seed_extra_words']) + root_seed = keystore.bip39_to_seed(data['seed'], passphrase=data['seed_extra_words']) else: root_seed = data['seed'].decrypt(data['seed_extra_words']) derivation = normalize_bip32_derivation(data['derivation_path']) @@ -560,7 +560,7 @@ class NewWalletWizard(AbstractWizard): script = data['script_type'] if data['script_type'] != 'p2sh' else 'standard' else: script = data['script_type'] if data['script_type'] != 'p2pkh' else 'standard' - k = keystore.from_bip43_rootseed(root_seed, derivation, xtype=script) + k = keystore.from_bip43_rootseed(root_seed, derivation=derivation, xtype=script) elif is_any_2fa_seed_type(data['seed_type']): self._logger.debug('creating keystore from 2fa seed') k = keystore.from_xprv(data['x1']['xprv']) diff --git a/tests/test_wallet_vertical.py b/tests/test_wallet_vertical.py index d55a8bc8d..fcb5c61af 100644 --- a/tests/test_wallet_vertical.py +++ b/tests/test_wallet_vertical.py @@ -92,7 +92,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase): seed_words = 'cycle rocket west magnet parrot shuffle foot correct salt library feed song' self.assertEqual(seed_type(seed_words), 'standard') - ks = keystore.from_seed(seed_words, '', False) + ks = keystore.from_seed(seed_words, passphrase='', for_multisig=False) WalletIntegrityHelper.check_seeded_keystore_sanity(self, ks) self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) @@ -111,7 +111,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase): seed_words = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver' self.assertEqual(seed_type(seed_words), 'segwit') - ks = keystore.from_seed(seed_words, '', False) + ks = keystore.from_seed(seed_words, passphrase='', for_multisig=False) WalletIntegrityHelper.check_seeded_keystore_sanity(self, ks) self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) @@ -133,7 +133,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase): seed_words = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver' self.assertEqual(seed_type(seed_words), 'segwit') - ks = keystore.from_seed(seed_words, UNICODE_HORROR, False) + ks = keystore.from_seed(seed_words, passphrase=UNICODE_HORROR, for_multisig=False) WalletIntegrityHelper.check_seeded_keystore_sanity(self, ks) self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) @@ -155,7 +155,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase): seed_words = 'powerful random nobody notice nothing important anyway look away hidden message over' self.assertEqual(seed_type(seed_words), 'old') - ks = keystore.from_seed(seed_words, '', False) + ks = keystore.from_seed(seed_words, passphrase='', for_multisig=False) WalletIntegrityHelper.check_seeded_keystore_sanity(self, ks) self.assertTrue(isinstance(ks, keystore.Old_KeyStore)) @@ -277,8 +277,8 @@ class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase): seed_words = 'treat dwarf wealth gasp brass outside high rent blood crowd make initial' self.assertEqual(keystore.bip39_is_checksum_valid(seed_words), (True, True)) - root_seed = keystore.bip39_to_seed(seed_words, '') - ks = keystore.from_bip43_rootseed(root_seed, "m/44'/0'/0'") + root_seed = keystore.bip39_to_seed(seed_words, passphrase='') + ks = keystore.from_bip43_rootseed(root_seed, derivation="m/44'/0'/0'") self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) @@ -296,8 +296,8 @@ class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase): seed_words = 'treat dwarf wealth gasp brass outside high rent blood crowd make initial' self.assertEqual(keystore.bip39_is_checksum_valid(seed_words), (True, True)) - root_seed = keystore.bip39_to_seed(seed_words, UNICODE_HORROR) - ks = keystore.from_bip43_rootseed(root_seed, "m/44'/0'/0'") + root_seed = keystore.bip39_to_seed(seed_words, passphrase=UNICODE_HORROR) + ks = keystore.from_bip43_rootseed(root_seed, derivation="m/44'/0'/0'") self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) @@ -315,8 +315,8 @@ class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase): seed_words = 'treat dwarf wealth gasp brass outside high rent blood crowd make initial' self.assertEqual(keystore.bip39_is_checksum_valid(seed_words), (True, True)) - root_seed = keystore.bip39_to_seed(seed_words, '') - ks = keystore.from_bip43_rootseed(root_seed, "m/49'/0'/0'") + root_seed = keystore.bip39_to_seed(seed_words, passphrase='') + ks = keystore.from_bip43_rootseed(root_seed, derivation="m/49'/0'/0'") self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) @@ -335,8 +335,8 @@ class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase): 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)) - root_seed = keystore.bip39_to_seed(seed_words, '') - ks = keystore.from_bip43_rootseed(root_seed, "m/84'/0'/0'") + root_seed = keystore.bip39_to_seed(seed_words, passphrase='') + ks = keystore.from_bip43_rootseed(root_seed, derivation="m/84'/0'/0'") self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) @@ -354,7 +354,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase): seed_words = 'blast uniform dragon fiscal ensure vast young utility dinosaur abandon rookie sure' self.assertEqual(seed_type(seed_words), 'standard') - ks1 = keystore.from_seed(seed_words, '', True) + ks1 = keystore.from_seed(seed_words, passphrase='', for_multisig=True) WalletIntegrityHelper.check_seeded_keystore_sanity(self, ks1) self.assertTrue(isinstance(ks1, keystore.BIP32_KeyStore)) self.assertEqual(ks1.xprv, 'xprv9s21ZrQH143K3t9vo23J3hajRbzvkRLJ6Y1zFrUFAfU3t8oooMPfb7f87cn5KntgqZs5nipZkCiBFo5ZtaSD2eDo7j7CMuFV8Zu6GYLTpY6') @@ -376,7 +376,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase): seed_words = 'snow nest raise royal more walk demise rotate smooth spirit canyon gun' self.assertEqual(seed_type(seed_words), 'segwit') - ks1 = keystore.from_seed(seed_words, '', True) + ks1 = keystore.from_seed(seed_words, passphrase='', for_multisig=True) WalletIntegrityHelper.check_seeded_keystore_sanity(self, ks1) self.assertTrue(isinstance(ks1, keystore.BIP32_KeyStore)) self.assertEqual(ks1.xprv, 'ZprvAjxLRqPiDfPDxXrm8JvcoCGRAW6xUtktucG6AMtdzaEbTEJN8qcECvujfhtDU3jLJ9g3Dr3Gz5m1ypfMs8iSUh62gWyHZ73bYLRWyeHf6y4') @@ -398,8 +398,8 @@ class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase): seed_words = 'treat dwarf wealth gasp brass outside high rent blood crowd make initial' self.assertEqual(keystore.bip39_is_checksum_valid(seed_words), (True, True)) - root_seed = keystore.bip39_to_seed(seed_words, '') - ks1 = keystore.from_bip43_rootseed(root_seed, "m/45'/0") + root_seed = keystore.bip39_to_seed(seed_words, passphrase='') + ks1 = keystore.from_bip43_rootseed(root_seed, derivation="m/45'/0") self.assertTrue(isinstance(ks1, keystore.BIP32_KeyStore)) self.assertEqual(ks1.xprv, 'xprv9vyEFyXf7pYVv4eDU3hhuCEAHPHNGuxX73nwtYdpbLcqwJCPwFKknAK8pHWuHHBirCzAPDZ7UJHrYdhLfn1NkGp9rk3rVz2aEqrT93qKRD9') self.assertEqual(ks1.xpub, 'xpub69xafV4YxC6o8Yiga5EiGLAtqR7rgNgNUGiYgw3S9g9pp6XYUne1KxdcfYtxwmA3eBrzMFuYcNQKfqsXCygCo4GxQFHfywxpUbKNfYvGJka') @@ -441,7 +441,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase): async def test_bip32_extended_version_bytes(self, mock_save_db): seed_words = 'crouch dumb relax small truck age shine pink invite spatial object tenant' self.assertEqual(keystore.bip39_is_checksum_valid(seed_words), (True, True)) - bip32_seed = keystore.bip39_to_seed(seed_words, '') + bip32_seed = keystore.bip39_to_seed(seed_words, passphrase='') self.assertEqual('0df68c16e522eea9c1d8e090cfb2139c3b3a2abed78cbcb3e20be2c29185d3b8df4e8ce4e52a1206a688aeb88bfee249585b41a7444673d1f16c0d45755fa8b9', bip32_seed.hex()) @@ -510,7 +510,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase): encrypted_seed = slip39.recover_ems(mnemonics) root_seed = encrypted_seed.decrypt('TREZOR') - ks = keystore.from_bip43_rootseed(root_seed, "m/44'/0'/0'") + ks = keystore.from_bip43_rootseed(root_seed, derivation="m/44'/0'/0'") self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) @@ -536,7 +536,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase): encrypted_seed = slip39.recover_ems(mnemonics) root_seed = encrypted_seed.decrypt('TREZOR') - ks = keystore.from_bip43_rootseed(root_seed, "m/49'/0'/0'") + ks = keystore.from_bip43_rootseed(root_seed, derivation="m/49'/0'/0'") self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) @@ -566,7 +566,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase): encrypted_seed = slip39.recover_ems(mnemonics) root_seed = encrypted_seed.decrypt('TREZOR') - ks = keystore.from_bip43_rootseed(root_seed, "m/84'/0'/0'") + ks = keystore.from_bip43_rootseed(root_seed, derivation="m/84'/0'/0'") self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) @@ -594,7 +594,7 @@ class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase): encrypted_seed = slip39.recover_ems(mnemonics) root_seed = encrypted_seed.decrypt('TREZOR') - ks = keystore.from_bip43_rootseed(root_seed, "m/49'/0'/0'") + ks = keystore.from_bip43_rootseed(root_seed, derivation="m/49'/0'/0'") self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) @@ -640,7 +640,7 @@ class TestWalletKeystoreAddressIntegrityForTestnet(ElectrumTestCase): async def test_bip32_extended_version_bytes(self, mock_save_db): seed_words = 'crouch dumb relax small truck age shine pink invite spatial object tenant' self.assertEqual(keystore.bip39_is_checksum_valid(seed_words), (True, True)) - bip32_seed = keystore.bip39_to_seed(seed_words, '') + bip32_seed = keystore.bip39_to_seed(seed_words, passphrase='') self.assertEqual('0df68c16e522eea9c1d8e090cfb2139c3b3a2abed78cbcb3e20be2c29185d3b8df4e8ce4e52a1206a688aeb88bfee249585b41a7444673d1f16c0d45755fa8b9', bip32_seed.hex()) @@ -706,7 +706,7 @@ class TestWalletSending(ElectrumTestCase): def create_standard_wallet_from_seed(self, seed_words, *, config=None, gap_limit=2): if config is None: config = self.config - ks = keystore.from_seed(seed_words, '', False) + ks = keystore.from_seed(seed_words, passphrase='', for_multisig=False) return WalletIntegrityHelper.create_standard_wallet(ks, gap_limit=gap_limit, config=config) @mock.patch.object(wallet.Abstract_Wallet, 'save_db') @@ -767,7 +767,7 @@ class TestWalletSending(ElectrumTestCase): async def test_sending_between_p2sh_2of3_and_uncompressed_p2pkh(self, mock_save_db): wallet1a = WalletIntegrityHelper.create_multisig_wallet( [ - keystore.from_seed('blast uniform dragon fiscal ensure vast young utility dinosaur abandon rookie sure', '', True), + keystore.from_seed('blast uniform dragon fiscal ensure vast young utility dinosaur abandon rookie sure', passphrase='', for_multisig=True), keystore.from_xpub('tpubD6NzVbkrYhZ4YTPEgwk4zzr8wyo7pXGmbbVUnfYNtx6SgAMF5q3LN3Kch58P9hxGNsTmP7Dn49nnrmpE6upoRb1Xojg12FGLuLHkVpVtS44'), keystore.from_xpub('tpubD6NzVbkrYhZ4XJzYkhsCbDCcZRmDAKSD7bXi9mdCni7acVt45fxbTVZyU6jRGh29ULKTjoapkfFsSJvQHitcVKbQgzgkkYsAmaovcro7Mhf') ], @@ -776,7 +776,7 @@ class TestWalletSending(ElectrumTestCase): ) wallet1b = WalletIntegrityHelper.create_multisig_wallet( [ - keystore.from_seed('cycle rocket west magnet parrot shuffle foot correct salt library feed song', '', True), + keystore.from_seed('cycle rocket west magnet parrot shuffle foot correct salt library feed song', passphrase='', for_multisig=True), keystore.from_xpub('tpubD6NzVbkrYhZ4YTPEgwk4zzr8wyo7pXGmbbVUnfYNtx6SgAMF5q3LN3Kch58P9hxGNsTmP7Dn49nnrmpE6upoRb1Xojg12FGLuLHkVpVtS44'), keystore.from_xpub('tpubD6NzVbkrYhZ4YARFMEZPckrqJkw59GZD1PXtQnw14ukvWDofR7Z1HMeSCxfYEZVvg4VdZ8zGok5VxHwdrLqew5cMdQntWc5mT7mh1CSgrnX') ], @@ -849,7 +849,7 @@ class TestWalletSending(ElectrumTestCase): async def test_sending_between_p2wsh_2of3_and_p2wsh_p2sh_2of2(self, mock_save_db): wallet1a = WalletIntegrityHelper.create_multisig_wallet( [ - keystore.from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver', '', True), + keystore.from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver', passphrase='', for_multisig=True), keystore.from_xpub('Vpub5fcdcgEwTJmbmqAktuK8Kyq92fMf7sWkcP6oqAii2tG47dNbfkGEGUbfS9NuZaRywLkHE6EmUksrqo32ZL3ouLN1HTar6oRiHpDzKMAF1tf'), keystore.from_xpub('Vpub5fjkKyYnvSS4wBuakWTkNvZDaBM2vQ1MeXWq368VJHNr2eT8efqhpmZ6UUkb7s2dwCXv2Vuggjdhk4vZVyiAQTwUftvff73XcUGq2NQmWra') ], @@ -858,7 +858,7 @@ class TestWalletSending(ElectrumTestCase): ) wallet1b = WalletIntegrityHelper.create_multisig_wallet( [ - keystore.from_seed('snow nest raise royal more walk demise rotate smooth spirit canyon gun', '', True), + keystore.from_seed('snow nest raise royal more walk demise rotate smooth spirit canyon gun', passphrase='', for_multisig=True), keystore.from_xpub('Vpub5fjkKyYnvSS4wBuakWTkNvZDaBM2vQ1MeXWq368VJHNr2eT8efqhpmZ6UUkb7s2dwCXv2Vuggjdhk4vZVyiAQTwUftvff73XcUGq2NQmWra'), keystore.from_xpub('Vpub5gSKXzxK7FeKQedu2q1z9oJWxqvX72AArW3HSWpEhc8othDH8xMDu28gr7gf17sp492BuJod8Tn7anjvJrKpETwqnQqX7CS8fcYyUtedEMk') ], @@ -968,7 +968,7 @@ class TestWalletSending(ElectrumTestCase): async def test_sending_between_p2sh_1of2_and_p2wpkh_p2sh(self, mock_save_db): wallet1a = WalletIntegrityHelper.create_multisig_wallet( [ - keystore.from_seed('phone guilt ancient scan defy gasp off rotate approve ill word exchange', '', True), + keystore.from_seed('phone guilt ancient scan defy gasp off rotate approve ill word exchange', passphrase='', for_multisig=True), keystore.from_xpub('tpubD6NzVbkrYhZ4YPZ3ntVjqSCxiUUv2jikrUBU73Q3iJ7Y8iR41oYf991L5fanv7ciHjbjokdK2bjYqg1BzEUDxucU9qM5WRdBiY738wmgLP4') ], '1of2', gap_limit=2, @@ -2152,12 +2152,12 @@ class TestWalletSending(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_coinjoin_between_two_p2wpkh_electrum_seeds(self, mock_save_db): wallet1 = WalletIntegrityHelper.create_standard_wallet( - keystore.from_seed('humor argue expand gain goat shiver remove morning security casual leopard degree', ''), + keystore.from_seed('humor argue expand gain goat shiver remove morning security casual leopard degree', passphrase=''), gap_limit=2, config=self.config ) wallet2 = WalletIntegrityHelper.create_standard_wallet( - keystore.from_seed('couple fade lift useless text thank badge act august roof drastic violin', ''), + keystore.from_seed('couple fade lift useless text thank badge act august roof drastic violin', passphrase=''), gap_limit=2, config=self.config ) @@ -2844,8 +2844,8 @@ class TestWalletSending(ElectrumTestCase): """When exporting a PSBT to be signed by a hw device, test that we populate the PSBT_GLOBAL_XPUB field with wallet xpubs. """ - root_seed = keystore.bip39_to_seed("pulse mixture jazz invite dune enrich minor weapon mosquito flight fly vapor", '') - ks = keystore.from_bip43_rootseed(root_seed, "m/84'/1'/0'") + root_seed = keystore.bip39_to_seed("pulse mixture jazz invite dune enrich minor weapon mosquito flight fly vapor", passphrase='') + ks = keystore.from_bip43_rootseed(root_seed, derivation="m/84'/1'/0'") wallet = WalletIntegrityHelper.create_standard_wallet(ks, gap_limit=2, config=self.config) # bootstrap wallet @@ -2883,7 +2883,9 @@ class TestWalletSending(ElectrumTestCase): """ wallet1a = WalletIntegrityHelper.create_multisig_wallet( [ - keystore.from_bip43_rootseed(keystore.bip39_to_seed("income sample useless art skate lucky fold field bargain course hope chest", ''), "m/45h/0", xtype="standard"), + keystore.from_bip43_rootseed( + keystore.bip39_to_seed("income sample useless art skate lucky fold field bargain course hope chest", passphrase=''), + derivation="m/45h/0", xtype="standard"), keystore.from_xpub('tpubDC1y33c2iTcxCBFva3zxbQxUnbzBT1TPVrwLgwVHtqSnVRx2pbJsrHzNYmXnKEnrNqyKk9BERrpSatqVu4JHV4K4hepFQdqnMojA5NVKxcF'), ], '2of2', gap_limit=2, @@ -2902,7 +2904,9 @@ class TestWalletSending(ElectrumTestCase): wallet1b.get_keystores()[1].add_key_origin(derivation_prefix="m/45h/0", root_fingerprint="25750cf7") wallet1b_offline = WalletIntegrityHelper.create_multisig_wallet( [ - keystore.from_bip43_rootseed(keystore.bip39_to_seed("wear wasp subject october amount essay maximum monkey excuse plastic ginger donor", ''), "m/45h/0", xtype="standard"), + keystore.from_bip43_rootseed( + keystore.bip39_to_seed("wear wasp subject october amount essay maximum monkey excuse plastic ginger donor", passphrase=''), + derivation="m/45h/0", xtype="standard"), keystore.from_xpub('tpubDAKtPDG6fezcwhB7rNJ9NVEWwGokNzowW3AaMVYFTS4WKoBTNESS1NpntWYDq2uABVYM1xa5cVmu8LD2xKYipMRVLy1VjBQeVe6pixJeBgr'), ], '2of2', gap_limit=2, @@ -3055,7 +3059,7 @@ class TestWalletOfflineSigning(ElectrumTestCase): @mock.patch.object(wallet.Abstract_Wallet, 'save_db') async def test_sending_offline_old_electrum_seed_online_mpk(self, mock_save_db): wallet_offline = WalletIntegrityHelper.create_standard_wallet( - keystore.from_seed('alone body father children lead goodbye phone twist exist grass kick join', '', False), + keystore.from_seed('alone body father children lead goodbye phone twist exist grass kick join', passphrase='', for_multisig=False), gap_limit=4, config=self.config ) @@ -3568,7 +3572,7 @@ class TestWalletOfflineSigning(ElectrumTestCase): # 2-of-3 legacy p2sh multisig wallet_offline1 = WalletIntegrityHelper.create_multisig_wallet( [ - keystore.from_seed('blast uniform dragon fiscal ensure vast young utility dinosaur abandon rookie sure', '', True), + keystore.from_seed('blast uniform dragon fiscal ensure vast young utility dinosaur abandon rookie sure', passphrase='', for_multisig=True), keystore.from_xpub('tpubD6NzVbkrYhZ4YTPEgwk4zzr8wyo7pXGmbbVUnfYNtx6SgAMF5q3LN3Kch58P9hxGNsTmP7Dn49nnrmpE6upoRb1Xojg12FGLuLHkVpVtS44'), keystore.from_xpub('tpubD6NzVbkrYhZ4XJzYkhsCbDCcZRmDAKSD7bXi9mdCni7acVt45fxbTVZyU6jRGh29ULKTjoapkfFsSJvQHitcVKbQgzgkkYsAmaovcro7Mhf') ], @@ -3577,7 +3581,7 @@ class TestWalletOfflineSigning(ElectrumTestCase): ) wallet_offline2 = WalletIntegrityHelper.create_multisig_wallet( [ - keystore.from_seed('cycle rocket west magnet parrot shuffle foot correct salt library feed song', '', True), + keystore.from_seed('cycle rocket west magnet parrot shuffle foot correct salt library feed song', passphrase='', for_multisig=True), keystore.from_xpub('tpubD6NzVbkrYhZ4YTPEgwk4zzr8wyo7pXGmbbVUnfYNtx6SgAMF5q3LN3Kch58P9hxGNsTmP7Dn49nnrmpE6upoRb1Xojg12FGLuLHkVpVtS44'), keystore.from_xpub('tpubD6NzVbkrYhZ4YARFMEZPckrqJkw59GZD1PXtQnw14ukvWDofR7Z1HMeSCxfYEZVvg4VdZ8zGok5VxHwdrLqew5cMdQntWc5mT7mh1CSgrnX') ], @@ -3704,7 +3708,7 @@ class TestWalletOfflineSigning(ElectrumTestCase): # 2-of-3 p2wsh multisig wallet_offline1 = WalletIntegrityHelper.create_multisig_wallet( [ - keystore.from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver', '', True), + keystore.from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver', passphrase='', for_multisig=True), keystore.from_xpub('Vpub5fcdcgEwTJmbmqAktuK8Kyq92fMf7sWkcP6oqAii2tG47dNbfkGEGUbfS9NuZaRywLkHE6EmUksrqo32ZL3ouLN1HTar6oRiHpDzKMAF1tf'), keystore.from_xpub('Vpub5fjkKyYnvSS4wBuakWTkNvZDaBM2vQ1MeXWq368VJHNr2eT8efqhpmZ6UUkb7s2dwCXv2Vuggjdhk4vZVyiAQTwUftvff73XcUGq2NQmWra') ], @@ -3713,7 +3717,7 @@ class TestWalletOfflineSigning(ElectrumTestCase): ) wallet_offline2 = WalletIntegrityHelper.create_multisig_wallet( [ - keystore.from_seed('snow nest raise royal more walk demise rotate smooth spirit canyon gun', '', True), + keystore.from_seed('snow nest raise royal more walk demise rotate smooth spirit canyon gun', passphrase='', for_multisig=True), keystore.from_xpub('Vpub5fjkKyYnvSS4wBuakWTkNvZDaBM2vQ1MeXWq368VJHNr2eT8efqhpmZ6UUkb7s2dwCXv2Vuggjdhk4vZVyiAQTwUftvff73XcUGq2NQmWra'), keystore.from_xpub('Vpub5gSKXzxK7FeKQedu2q1z9oJWxqvX72AArW3HSWpEhc8othDH8xMDu28gr7gf17sp492BuJod8Tn7anjvJrKpETwqnQqX7CS8fcYyUtedEMk') ], @@ -3780,7 +3784,7 @@ class TestWalletCreationChecks(ElectrumTestCase): with self.assertRaises(Exception) as ctx1: w1 = WalletIntegrityHelper.create_multisig_wallet( [ - keystore.from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver', '', True), + keystore.from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver', passphrase='', for_multisig=True), keystore.from_xpub('Vpub5gSKXzxK7FeKQedu2q1z9oJWxqvX72AArW3HSWpEhc8othDH8xMDu28gr7gf17sp492BuJod8Tn7anjvJrKpETwqnQqX7CS8fcYyUtedEMk'), # collides with seed keystore.from_xpub('Vpub5fjkKyYnvSS4wBuakWTkNvZDaBM2vQ1MeXWq368VJHNr2eT8efqhpmZ6UUkb7s2dwCXv2Vuggjdhk4vZVyiAQTwUftvff73XcUGq2NQmWra'), ], @@ -3792,7 +3796,7 @@ class TestWalletCreationChecks(ElectrumTestCase): with self.assertRaises(Exception) as ctx2: w2 = WalletIntegrityHelper.create_multisig_wallet( [ - keystore.from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver', '', True), + keystore.from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver', passphrase='', for_multisig=True), keystore.from_xpub('Vpub5fcdcgEwTJmbmqAktuK8Kyq92fMf7sWkcP6oqAii2tG47dNbfkGEGUbfS9NuZaRywLkHE6EmUksrqo32ZL3ouLN1HTar6oRiHpDzKMAF1tf'), keystore.from_xpub('Vpub5fcdcgEwTJmbmqAktuK8Kyq92fMf7sWkcP6oqAii2tG47dNbfkGEGUbfS9NuZaRywLkHE6EmUksrqo32ZL3ouLN1HTar6oRiHpDzKMAF1tf'), ], @@ -3803,7 +3807,7 @@ class TestWalletCreationChecks(ElectrumTestCase): # all xpubs different. should not raise. w3 = WalletIntegrityHelper.create_multisig_wallet( [ - keystore.from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver', '', True), + keystore.from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver', passphrase='', for_multisig=True), keystore.from_xpub('Vpub5fcdcgEwTJmbmqAktuK8Kyq92fMf7sWkcP6oqAii2tG47dNbfkGEGUbfS9NuZaRywLkHE6EmUksrqo32ZL3ouLN1HTar6oRiHpDzKMAF1tf'), keystore.from_xpub('Vpub5fjkKyYnvSS4wBuakWTkNvZDaBM2vQ1MeXWq368VJHNr2eT8efqhpmZ6UUkb7s2dwCXv2Vuggjdhk4vZVyiAQTwUftvff73XcUGq2NQmWra'), ], @@ -3829,7 +3833,7 @@ class TestWalletCreationChecks(ElectrumTestCase): w1 = WalletIntegrityHelper.create_multisig_wallet( [ keystore.from_xpub('tpubD6NzVbkrYhZ4XYdbWCGSusTDQRAX4UnuqcikJAkqMYxBkvnGfUBvXBE84eyQS6e4To3Pz1xwLrEuxGgQayn4dqVXwNM7dWh4U4DgHai2scz'), - keystore.from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver', '', True), + keystore.from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver', passphrase='', for_multisig=True), ], '2of2', gap_limit=2, config=self.config @@ -3839,8 +3843,8 @@ class TestWalletCreationChecks(ElectrumTestCase): with self.assertRaises(Exception) as ctx3: w1 = WalletIntegrityHelper.create_multisig_wallet( [ - keystore.from_seed('cycle rocket west magnet parrot shuffle foot correct salt library feed song', '', True), - keystore.from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver', '', True), + keystore.from_seed('cycle rocket west magnet parrot shuffle foot correct salt library feed song', passphrase='', for_multisig=True), + keystore.from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver', passphrase='', for_multisig=True), ], '2of2', gap_limit=2, config=self.config @@ -3850,8 +3854,8 @@ class TestWalletCreationChecks(ElectrumTestCase): with self.assertRaises(Exception) as ctx4: w1 = WalletIntegrityHelper.create_multisig_wallet( [ - keystore.from_seed('cycle rocket west magnet parrot shuffle foot correct salt library feed song', '', True), - keystore.from_seed('powerful random nobody notice nothing important anyway look away hidden message over', '', True), + keystore.from_seed('cycle rocket west magnet parrot shuffle foot correct salt library feed song', passphrase='', for_multisig=True), + keystore.from_seed('powerful random nobody notice nothing important anyway look away hidden message over', passphrase='', for_multisig=True), ], '2of2', gap_limit=2, config=self.config