1
0

tests: wizard: KeystoreWizard: also test disable_keystore()

This commit is contained in:
SomberNight
2025-08-14 17:06:52 +00:00
parent 6554ec674e
commit 0fea61ac3a
3 changed files with 58 additions and 14 deletions

View File

@@ -1,9 +1,14 @@
import sys import sys
from typing import TYPE_CHECKING, Optional
from PyQt6.QtCore import pyqtSignal, pyqtProperty, QObject from PyQt6.QtCore import pyqtSignal, pyqtProperty, QObject
from electrum.logging import get_logger from electrum.logging import get_logger
if TYPE_CHECKING:
from electrum.gui.qml import ElectrumQmlApplication
from electrum.plugin import BasePlugin
class PluginQObject(QObject): class PluginQObject(QObject):
logger = get_logger(__name__) logger = get_logger(__name__)
@@ -12,7 +17,7 @@ class PluginQObject(QObject):
busyChanged = pyqtSignal() busyChanged = pyqtSignal()
pluginEnabledChanged = pyqtSignal() pluginEnabledChanged = pyqtSignal()
def __init__(self, plugin, parent): def __init__(self, plugin: 'BasePlugin', parent: Optional['ElectrumQmlApplication']):
super().__init__(parent) super().__init__(parent)
self._busy = False self._busy = False

View File

@@ -3267,6 +3267,9 @@ class Abstract_Wallet(ABC, Logger, EventListener):
def disable_keystore(self, keystore: KeyStore) -> None: def disable_keystore(self, keystore: KeyStore) -> None:
raise NotImplementedError() raise NotImplementedError()
def _update_keystore(self, keystore: KeyStore) -> None:
raise NotImplementedError()
@abstractmethod @abstractmethod
def has_seed(self) -> bool: def has_seed(self) -> bool:
pass pass

View File

@@ -2,7 +2,7 @@ import os
from electrum import SimpleConfig from electrum import SimpleConfig
from electrum.interface import ServerAddr from electrum.interface import ServerAddr
from electrum.keystore import bip44_derivation, Hardware_KeyStore from electrum.keystore import bip44_derivation, Hardware_KeyStore, KeyStore, BIP32_KeyStore
from electrum.network import NetworkParameters, ProxySettings from electrum.network import NetworkParameters, ProxySettings
from electrum.plugin import Plugins, DeviceInfo, Device from electrum.plugin import Plugins, DeviceInfo, Device
from electrum.wizard import ServerConnectWizard, NewWalletWizard, WizardViewState, KeystoreWizard from electrum.wizard import ServerConnectWizard, NewWalletWizard, WizardViewState, KeystoreWizard
@@ -124,6 +124,10 @@ class ServerConnectWizardTestCase(WizardTestCase):
class KeystoreWizardTestCase(WizardTestCase): class KeystoreWizardTestCase(WizardTestCase):
# TODO add test cases for:
# - multisig
# - 2fa
class TKeystoreWizard(KeystoreWizard): class TKeystoreWizard(KeystoreWizard):
def is_single_password(self): def is_single_password(self):
"""impl abstract reqd""" """impl abstract reqd"""
@@ -165,11 +169,20 @@ class KeystoreWizardTestCase(WizardTestCase):
wallet = Daemon._load_wallet(wallet_path, password=None, config=self.config) wallet = Daemon._load_wallet(wallet_path, password=None, config=self.config)
return wallet return wallet
def _sanity_checks_after_disabling_keystore(self, *, ks: 'KeyStore', xpub: str) -> None:
self.assertTrue(ks.is_watching_only())
self.assertTrue(ks.type in ('bip32', 'old'))
self.assertFalse(ks.has_seed())
self.assertEqual(ks.get_master_public_key(), xpub)
if isinstance(ks, BIP32_KeyStore):
self.assertEqual(ks.xprv, None)
async def test_haveseed_electrum(self): async def test_haveseed_electrum(self):
w, v = self._wizard_for() w, v = self._wizard_for()
d = v.wizard_data d = v.wizard_data
myseed = '9dk' myseed = '9dk'
mypassphrase = '' mypassphrase = ''
myxpub = 'zpub6nAZodjgiMNf9zzX1pTqd6ZVX61ax8azhUDnWRumKVUr1VYATVoqAuqv3qKsb8WJXjxei4wei2p4vnMG9RnpKnen2kmgdhvZUmug2NnHNsr'
d.update({ d.update({
'seed': myseed, 'seed_type': 'segwit', 'seed_extend': False, 'seed_variant': 'electrum', 'seed': myseed, 'seed_type': 'segwit', 'seed_extend': False, 'seed_variant': 'electrum',
}) })
@@ -177,20 +190,24 @@ class KeystoreWizardTestCase(WizardTestCase):
w.resolve_next(v.view, d) w.resolve_next(v.view, d)
ks, ishww = w._result ks, ishww = w._result
self.assertFalse(ishww) self.assertFalse(ishww)
self.assertEqual(ks.xpub, 'zpub6nAZodjgiMNf9zzX1pTqd6ZVX61ax8azhUDnWRumKVUr1VYATVoqAuqv3qKsb8WJXjxei4wei2p4vnMG9RnpKnen2kmgdhvZUmug2NnHNsr') self.assertEqual(ks.xpub, myxpub)
wallet = self._create_xpub_keystore_wallet(xpub='zpub6nAZodjgiMNf9zzX1pTqd6ZVX61ax8azhUDnWRumKVUr1VYATVoqAuqv3qKsb8WJXjxei4wei2p4vnMG9RnpKnen2kmgdhvZUmug2NnHNsr') wallet = self._create_xpub_keystore_wallet(xpub=myxpub)
self.assertTrue(wallet.get_keystore().is_watching_only()) self.assertTrue(wallet.get_keystore().is_watching_only())
wallet.enable_keystore(ks, ishww, None) wallet.enable_keystore(ks, ishww, None)
self.assertFalse(wallet.get_keystore().is_watching_only()) self.assertFalse(wallet.get_keystore().is_watching_only())
self.assertEqual(myseed, wallet.get_keystore().get_seed(None)) self.assertEqual(myseed, wallet.get_keystore().get_seed(None))
self.assertEqual(mypassphrase, wallet.get_keystore().get_passphrase(None)) self.assertEqual(mypassphrase, wallet.get_keystore().get_passphrase(None))
wallet.disable_keystore(wallet.get_keystore())
self._sanity_checks_after_disabling_keystore(ks=wallet.get_keystore(), xpub=myxpub)
async def test_haveseed_ext_electrum(self): async def test_haveseed_ext_electrum(self):
w, v = self._wizard_for() w, v = self._wizard_for()
d = v.wizard_data d = v.wizard_data
myseed = '9dk' myseed = '9dk'
mypassphrase = 'abc' mypassphrase = 'abc'
myxpub = 'zpub6oLFCUpqxT8BUzy8g5miUuRofPZ46ZjjvZfcfH7qJanRM7aRYGpNX4uBGtcJRbgcKbi7dYkiiPw1GB2sc3SufyDcZskuQEWp5jBwbNcj1VL'
d.update({ d.update({
'seed': myseed, 'seed_type': 'segwit', 'seed_extend': True, 'seed_variant': 'electrum', 'seed': myseed, 'seed_type': 'segwit', 'seed_extend': True, 'seed_variant': 'electrum',
}) })
@@ -202,20 +219,24 @@ class KeystoreWizardTestCase(WizardTestCase):
w.resolve_next(v.view, d) w.resolve_next(v.view, d)
ks, ishww = w._result ks, ishww = w._result
self.assertFalse(ishww) self.assertFalse(ishww)
self.assertEqual(ks.xpub, 'zpub6oLFCUpqxT8BUzy8g5miUuRofPZ46ZjjvZfcfH7qJanRM7aRYGpNX4uBGtcJRbgcKbi7dYkiiPw1GB2sc3SufyDcZskuQEWp5jBwbNcj1VL') self.assertEqual(ks.xpub, myxpub)
wallet = self._create_xpub_keystore_wallet(xpub='zpub6oLFCUpqxT8BUzy8g5miUuRofPZ46ZjjvZfcfH7qJanRM7aRYGpNX4uBGtcJRbgcKbi7dYkiiPw1GB2sc3SufyDcZskuQEWp5jBwbNcj1VL') wallet = self._create_xpub_keystore_wallet(xpub=myxpub)
self.assertTrue(wallet.get_keystore().is_watching_only()) self.assertTrue(wallet.get_keystore().is_watching_only())
wallet.enable_keystore(ks, ishww, None) wallet.enable_keystore(ks, ishww, None)
self.assertFalse(wallet.get_keystore().is_watching_only()) self.assertFalse(wallet.get_keystore().is_watching_only())
self.assertEqual(myseed, wallet.get_keystore().get_seed(None)) self.assertEqual(myseed, wallet.get_keystore().get_seed(None))
self.assertEqual(mypassphrase, wallet.get_keystore().get_passphrase(None)) self.assertEqual(mypassphrase, wallet.get_keystore().get_passphrase(None))
wallet.disable_keystore(wallet.get_keystore())
self._sanity_checks_after_disabling_keystore(ks=wallet.get_keystore(), xpub=myxpub)
async def test_haveseed_electrum_oldseed(self): async def test_haveseed_electrum_oldseed(self):
w, v = self._wizard_for() w, v = self._wizard_for()
d = v.wizard_data d = v.wizard_data
myseed = 'powerful random nobody notice nothing important anyway look away hidden message over' myseed = 'powerful random nobody notice nothing important anyway look away hidden message over'
mypassphrase = '' mypassphrase = ''
myxpub = 'e9d4b7866dd1e91c862aebf62a49548c7dbf7bcc6e4b7b8c9da820c7737968df9c09d5a3e271dc814a29981f81b3faaf2737b551ef5dcc6189cf0f8252c442b3'
d.update({ d.update({
'seed': myseed, 'seed': myseed,
'seed_type': 'old', 'seed_extend': False, 'seed_variant': 'electrum', 'seed_type': 'old', 'seed_extend': False, 'seed_variant': 'electrum',
@@ -224,18 +245,22 @@ class KeystoreWizardTestCase(WizardTestCase):
w.resolve_next(v.view, d) w.resolve_next(v.view, d)
ks, ishww = w._result ks, ishww = w._result
self.assertFalse(ishww) self.assertFalse(ishww)
self.assertEqual(ks.get_master_public_key(), 'e9d4b7866dd1e91c862aebf62a49548c7dbf7bcc6e4b7b8c9da820c7737968df9c09d5a3e271dc814a29981f81b3faaf2737b551ef5dcc6189cf0f8252c442b3') self.assertEqual(ks.get_master_public_key(), myxpub)
wallet = self._create_xpub_keystore_wallet(xpub='e9d4b7866dd1e91c862aebf62a49548c7dbf7bcc6e4b7b8c9da820c7737968df9c09d5a3e271dc814a29981f81b3faaf2737b551ef5dcc6189cf0f8252c442b3') wallet = self._create_xpub_keystore_wallet(xpub=myxpub)
self.assertTrue(wallet.get_keystore().is_watching_only()) self.assertTrue(wallet.get_keystore().is_watching_only())
wallet.enable_keystore(ks, ishww, None) wallet.enable_keystore(ks, ishww, None)
self.assertFalse(wallet.get_keystore().is_watching_only()) self.assertFalse(wallet.get_keystore().is_watching_only())
self.assertEqual(myseed, wallet.get_keystore().get_seed(None)) self.assertEqual(myseed, wallet.get_keystore().get_seed(None))
self.assertEqual(mypassphrase, wallet.get_keystore().get_passphrase(None)) self.assertEqual(mypassphrase, wallet.get_keystore().get_passphrase(None))
wallet.disable_keystore(wallet.get_keystore())
self._sanity_checks_after_disabling_keystore(ks=wallet.get_keystore(), xpub=myxpub)
async def test_haveseed_bip39(self): async def test_haveseed_bip39(self):
w, v = self._wizard_for() w, v = self._wizard_for()
d = v.wizard_data d = v.wizard_data
myxpub = 'zpub6jftahH18ngZwMBBp7epRdBwPMPphfdy9gM6P4n5zFUXdfQJmsYfMNZoBnQMkAoBAiQYRyDQKdpxLYp6QuTrWbgmt6v1cxnFdesyiDSocAs'
d.update({ d.update({
'seed': '9dk', 'seed_type': 'bip39', 'seed_extend': False, 'seed_variant': 'bip39', 'seed': '9dk', 'seed_type': 'bip39', 'seed_extend': False, 'seed_variant': 'bip39',
}) })
@@ -246,16 +271,20 @@ class KeystoreWizardTestCase(WizardTestCase):
v = w.resolve_next(v.view, d) v = w.resolve_next(v.view, d)
ks, ishww = w._result ks, ishww = w._result
self.assertFalse(ishww) self.assertFalse(ishww)
self.assertEqual(ks.xpub, 'zpub6jftahH18ngZwMBBp7epRdBwPMPphfdy9gM6P4n5zFUXdfQJmsYfMNZoBnQMkAoBAiQYRyDQKdpxLYp6QuTrWbgmt6v1cxnFdesyiDSocAs') self.assertEqual(ks.xpub, myxpub)
wallet = self._create_xpub_keystore_wallet(xpub='zpub6jftahH18ngZwMBBp7epRdBwPMPphfdy9gM6P4n5zFUXdfQJmsYfMNZoBnQMkAoBAiQYRyDQKdpxLYp6QuTrWbgmt6v1cxnFdesyiDSocAs') wallet = self._create_xpub_keystore_wallet(xpub=myxpub)
self.assertTrue(wallet.get_keystore().is_watching_only()) self.assertTrue(wallet.get_keystore().is_watching_only())
wallet.enable_keystore(ks, ishww, None) wallet.enable_keystore(ks, ishww, None)
self.assertFalse(wallet.get_keystore().is_watching_only()) self.assertFalse(wallet.get_keystore().is_watching_only())
wallet.disable_keystore(wallet.get_keystore())
self._sanity_checks_after_disabling_keystore(ks=wallet.get_keystore(), xpub=myxpub)
async def test_haveseed_ext_bip39(self): async def test_haveseed_ext_bip39(self):
w, v = self._wizard_for() w, v = self._wizard_for()
d = v.wizard_data d = v.wizard_data
myxpub = 'zpub6jftahH18ngZwVNQQqNX9vgARaQRs5X89bPzjruSH2hgEBr1LRZN8reopYDALiKngTd8j5jUeGDipb68BXqjP6qMFsReLGwP6naDRvzVHxy'
d.update({ d.update({
'seed': '9dk', 'seed_type': 'bip39', 'seed_extend': True, 'seed_variant': 'bip39', 'seed': '9dk', 'seed_type': 'bip39', 'seed_extend': True, 'seed_variant': 'bip39',
}) })
@@ -270,16 +299,20 @@ class KeystoreWizardTestCase(WizardTestCase):
v = w.resolve_next(v.view, d) v = w.resolve_next(v.view, d)
ks, ishww = w._result ks, ishww = w._result
self.assertFalse(ishww) self.assertFalse(ishww)
self.assertEqual(ks.xpub, 'zpub6jftahH18ngZwVNQQqNX9vgARaQRs5X89bPzjruSH2hgEBr1LRZN8reopYDALiKngTd8j5jUeGDipb68BXqjP6qMFsReLGwP6naDRvzVHxy') self.assertEqual(ks.xpub, myxpub)
wallet = self._create_xpub_keystore_wallet(xpub='zpub6jftahH18ngZwVNQQqNX9vgARaQRs5X89bPzjruSH2hgEBr1LRZN8reopYDALiKngTd8j5jUeGDipb68BXqjP6qMFsReLGwP6naDRvzVHxy') wallet = self._create_xpub_keystore_wallet(xpub=myxpub)
self.assertTrue(wallet.get_keystore().is_watching_only()) self.assertTrue(wallet.get_keystore().is_watching_only())
wallet.enable_keystore(ks, ishww, None) wallet.enable_keystore(ks, ishww, None)
self.assertFalse(wallet.get_keystore().is_watching_only()) self.assertFalse(wallet.get_keystore().is_watching_only())
wallet.disable_keystore(wallet.get_keystore())
self._sanity_checks_after_disabling_keystore(ks=wallet.get_keystore(), xpub=myxpub)
async def test_hww(self): async def test_hww(self):
w, v = self._wizard_for(hww=True) w, v = self._wizard_for(hww=True)
d = v.wizard_data d = v.wizard_data
myxpub = 'zpub6rakEaM5ps5UiQ2yhbWiEkd6ceJfmuzegwc62G4itMz8L7rRFRqh6y8bTCScXV6NfTMUhANYQnfqfBd9dYfBRKf4LD1Yyfc8UvwY1MtNKWs'
d.update({ d.update({
'hardware_device': ( 'hardware_device': (
'trezor', 'trezor',
@@ -296,7 +329,7 @@ class KeystoreWizardTestCase(WizardTestCase):
self.assertEqual('trezor_xpub', v.view) self.assertEqual('trezor_xpub', v.view)
d.update({ d.update({
'hw_type': 'trezor', 'hw_type': 'trezor',
'master_key': 'zpub6rakEaM5ps5UiQ2yhbWiEkd6ceJfmuzegwc62G4itMz8L7rRFRqh6y8bTCScXV6NfTMUhANYQnfqfBd9dYfBRKf4LD1Yyfc8UvwY1MtNKWs', 'master_key': myxpub,
'root_fingerprint': 'b3569ff0', 'root_fingerprint': 'b3569ff0',
'label': 'trezor_unittests', 'label': 'trezor_unittests',
'soft_device_id': '088C3F260B66F60E15DE0FA5', 'soft_device_id': '088C3F260B66F60E15DE0FA5',
@@ -307,12 +340,15 @@ class KeystoreWizardTestCase(WizardTestCase):
ks, ishww = w._result ks, ishww = w._result
self.assertTrue(ishww) self.assertTrue(ishww)
wallet = self._create_xpub_keystore_wallet(xpub='zpub6rakEaM5ps5UiQ2yhbWiEkd6ceJfmuzegwc62G4itMz8L7rRFRqh6y8bTCScXV6NfTMUhANYQnfqfBd9dYfBRKf4LD1Yyfc8UvwY1MtNKWs') wallet = self._create_xpub_keystore_wallet(xpub=myxpub)
self.assertTrue(wallet.get_keystore().is_watching_only()) self.assertTrue(wallet.get_keystore().is_watching_only())
wallet.enable_keystore(ks, ishww, None) wallet.enable_keystore(ks, ishww, None)
self.assertFalse(wallet.get_keystore().is_watching_only()) self.assertFalse(wallet.get_keystore().is_watching_only())
self.assertTrue(isinstance(wallet.get_keystore(), Hardware_KeyStore)) self.assertTrue(isinstance(wallet.get_keystore(), Hardware_KeyStore))
wallet.disable_keystore(wallet.get_keystore())
self._sanity_checks_after_disabling_keystore(ks=wallet.get_keystore(), xpub=myxpub)
class WalletWizardTestCase(WizardTestCase): class WalletWizardTestCase(WizardTestCase):