From 3a7c00634e87e7c2db0d82b73f25c82195cf7350 Mon Sep 17 00:00:00 2001 From: SomberNight Date: Thu, 17 Dec 2020 15:17:08 +0100 Subject: [PATCH] wallet_db: impl convert_version_33: put 'height' field into invoices The 'height' field was added in https://github.com/spesmilo/electrum/commit/cdfaaa260942b807f809c2c0414fb242a03e945a At the time we thought we could just add it with a default value without a db upgrade; however the issue is that if old code tries to open a new db, it will fail (due to unexpected new field). Hence it is better to do an explicit conversion where old code *knows* it cannot open the new db. E | gui.qt.ElectrumGui | Traceback (most recent call last): File "...\electrum\electrum\gui\qt\__init__.py", line 257, in start_new_window wallet = self.daemon.load_wallet(path, None) File "...\electrum\electrum\daemon.py", line 488, in load_wallet db = WalletDB(storage.read(), manual_upgrades=manual_upgrades) File "...\electrum\electrum\wallet_db.py", line 72, in __init__ self.load_data(raw) File "...\electrum\electrum\wallet_db.py", line 103, in load_data self._after_upgrade_tasks() File "...\electrum\electrum\wallet_db.py", line 189, in _after_upgrade_tasks self._load_transactions() File "...\electrum\electrum\util.py", line 408, in return lambda *args, **kw_args: do_profile(args, kw_args) File "...\electrum\electrum\util.py", line 404, in do_profile o = func(*args, **kw_args) File "...\electrum\electrum\wallet_db.py", line 1139, in _load_transactions self.data = StoredDict(self.data, self, []) File "...\electrum\electrum\json_db.py", line 79, in __init__ self.__setitem__(k, v) File "...\electrum\electrum\json_db.py", line 44, in wrapper return func(self, *args, **kwargs) File "...\electrum\electrum\json_db.py", line 105, in __setitem__ v = self.db._convert_dict(self.path, key, v) File "...\electrum\electrum\wallet_db.py", line 1182, in _convert_dict v = dict((k, Invoice.from_json(x)) for k, x in v.items()) File "...\electrum\electrum\wallet_db.py", line 1182, in v = dict((k, Invoice.from_json(x)) for k, x in v.items()) File "...\electrum\electrum\invoices.py", line 108, in from_json return OnchainInvoice(**x) TypeError: __init__() got an unexpected keyword argument 'height' --- electrum/invoices.py | 2 +- electrum/wallet_db.py | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/electrum/invoices.py b/electrum/invoices.py index 6105ab4a8..c9e9584a3 100644 --- a/electrum/invoices.py +++ b/electrum/invoices.py @@ -118,7 +118,7 @@ class OnchainInvoice(Invoice): outputs = attr.ib(kw_only=True, converter=_decode_outputs) # type: List[PartialTxOutput] bip70 = attr.ib(type=str, kw_only=True) # type: Optional[str] requestor = attr.ib(type=str, kw_only=True) # type: Optional[str] - height = attr.ib(type=int, default=0, kw_only=True, validator=attr.validators.instance_of(int)) + height = attr.ib(type=int, kw_only=True, validator=attr.validators.instance_of(int)) def get_address(self) -> str: """returns the first address, to be displayed in GUI""" diff --git a/electrum/wallet_db.py b/electrum/wallet_db.py index fc792a8eb..49bc11ab1 100644 --- a/electrum/wallet_db.py +++ b/electrum/wallet_db.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: OLD_SEED_VERSION = 4 # electrum versions < 2.0 NEW_SEED_VERSION = 11 # electrum versions >= 2.0 -FINAL_SEED_VERSION = 32 # electrum >= 2.7 will set this to prevent +FINAL_SEED_VERSION = 33 # electrum >= 2.7 will set this to prevent # old versions from overwriting new format @@ -180,6 +180,7 @@ class WalletDB(JsonDB): self._convert_version_30() self._convert_version_31() self._convert_version_32() + self._convert_version_33() self.put('seed_version', FINAL_SEED_VERSION) # just to be sure self._after_upgrade_tasks() @@ -695,6 +696,20 @@ class WalletDB(JsonDB): self.data['invoices'] = invoices_new self.data['seed_version'] = 32 + def _convert_version_33(self): + if not self._is_upgrade_method_needed(32, 32): + return + + from .invoices import PR_TYPE_ONCHAIN + requests = self.data.get('payment_requests', {}) + invoices = self.data.get('invoices', {}) + for d in [invoices, requests]: + for key, item in list(d.items()): + if item['type'] == PR_TYPE_ONCHAIN: + item['height'] = item.get('height') or 0 + + self.data['seed_version'] = 33 + def _convert_imported(self): if not self._is_upgrade_method_needed(0, 13): return