From 7b7bba22992eca4536a91249758f178b4a7e044a Mon Sep 17 00:00:00 2001 From: SomberNight Date: Tue, 30 Mar 2021 21:16:14 +0200 Subject: [PATCH] wallet_db: put 'seed_type' into keystores (incl db upgrade) --- electrum/gui/qt/main_window.py | 7 ++++++- electrum/keystore.py | 9 ++++++++- electrum/wallet_db.py | 26 +++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/electrum/gui/qt/main_window.py b/electrum/gui/qt/main_window.py index 2779b6d79..5f5debc98 100644 --- a/electrum/gui/qt/main_window.py +++ b/electrum/gui/qt/main_window.py @@ -2400,7 +2400,12 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger): wallet_type = self.wallet.db.get('wallet_type', '') if self.wallet.is_watching_only(): wallet_type += ' [{}]'.format(_('watching-only')) - seed_available = _('True') if self.wallet.has_seed() else _('False') + seed_available = _('False') + if self.wallet.has_seed(): + seed_available = _('True') + ks = self.wallet.keystore + assert isinstance(ks, keystore.Deterministic_KeyStore) + seed_available += f" ({ks.get_seed_type()})" keystore_types = [k.get_type_text() for k in self.wallet.get_keystores()] grid = QGridLayout() basename = os.path.basename(self.wallet.storage.path) diff --git a/electrum/keystore.py b/electrum/keystore.py index 414b0da5f..53c4cef66 100644 --- a/electrum/keystore.py +++ b/electrum/keystore.py @@ -282,8 +282,9 @@ class Deterministic_KeyStore(Software_KeyStore): def __init__(self, d): Software_KeyStore.__init__(self, d) - self.seed = d.get('seed', '') + self.seed = d.get('seed', '') # only electrum seeds self.passphrase = d.get('passphrase', '') + self._seed_type = d.get('seed_type', None) # only electrum seeds def is_deterministic(self): return True @@ -297,11 +298,16 @@ class Deterministic_KeyStore(Software_KeyStore): d['seed'] = self.seed if self.passphrase: d['passphrase'] = self.passphrase + if self._seed_type: + d['seed_type'] = self._seed_type return d def has_seed(self): return bool(self.seed) + def get_seed_type(self) -> Optional[str]: + return self._seed_type + def is_watching_only(self): return not self.has_seed() @@ -313,6 +319,7 @@ class Deterministic_KeyStore(Software_KeyStore): if self.seed: raise Exception("a seed exists") self.seed = self.format_seed(seed) + self._seed_type = seed_type(seed) or None def get_seed(self, password): if not self.has_seed(): diff --git a/electrum/wallet_db.py b/electrum/wallet_db.py index f740f77c0..3a602c36d 100644 --- a/electrum/wallet_db.py +++ b/electrum/wallet_db.py @@ -53,7 +53,7 @@ if TYPE_CHECKING: OLD_SEED_VERSION = 4 # electrum versions < 2.0 NEW_SEED_VERSION = 11 # electrum versions >= 2.0 -FINAL_SEED_VERSION = 39 # electrum >= 2.7 will set this to prevent +FINAL_SEED_VERSION = 40 # electrum >= 2.7 will set this to prevent # old versions from overwriting new format @@ -188,6 +188,7 @@ class WalletDB(JsonDB): self._convert_version_37() self._convert_version_38() self._convert_version_39() + self._convert_version_40() self.put('seed_version', FINAL_SEED_VERSION) # just to be sure self._after_upgrade_tasks() @@ -787,6 +788,29 @@ class WalletDB(JsonDB): self.data['imported_channel_backups'] = self.data.pop('channel_backups', {}) self.data['seed_version'] = 39 + def _convert_version_40(self): + # put 'seed_type' into keystores + if not self._is_upgrade_method_needed(39, 39): + return + for ks_name in ('keystore', *['x{}/'.format(i) for i in range(1, 16)]): + ks = self.data.get(ks_name, None) + if ks is None: continue + seed = ks.get('seed') + if not seed: continue + seed_type = None + xpub = ks.get('xpub') or None + if xpub: + assert isinstance(xpub, str) + if xpub[0:4] in ('xpub', 'tpub'): + seed_type = 'standard' + elif xpub[0:4] in ('zpub', 'Zpub', 'vpub', 'Vpub'): + seed_type = 'segwit' + elif ks.get('type') == 'old': + seed_type = 'old' + if seed_type is not None: + ks['seed_type'] = seed_type + self.data['seed_version'] = 40 + def _convert_imported(self): if not self._is_upgrade_method_needed(0, 13): return