tdb upgrade: store channel tx height and timestamps in 'channels' - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 20d8da7e24e8377f6c752b994e7bfdb02b6fa49c DIR parent e8ee4250d9b46466478a186ee23af4383c29875e HTML Author: ThomasV <thomasv@electrum.org> Date: Sat, 22 Feb 2020 18:26:52 +0100 db upgrade: store channel tx height and timestamps in 'channels' Diffstat: M electrum/gui/qt/channels_list.py | 2 +- M electrum/lnchannel.py | 18 ++++++++++++++---- M electrum/lnwatcher.py | 4 +++- M electrum/lnworker.py | 19 +++++-------------- M electrum/wallet_db.py | 18 +++++++++++++++++- 5 files changed, 40 insertions(+), 21 deletions(-) --- DIR diff --git a/electrum/gui/qt/channels_list.py b/electrum/gui/qt/channels_list.py t@@ -120,7 +120,7 @@ class ChannelsList(MyTreeView): menu.addAction(_("Close channel"), lambda: self.close_channel(channel_id)) menu.addAction(_("Force-close channel"), lambda: self.force_close(channel_id)) else: - txid = chan.get_closing_txid() + txid, height, timestamp = chan.get_closing_height() closing_tx = self.lnworker.lnwatcher.db.get_transaction(txid) if closing_tx: menu.addAction(_("View closing transaction"), lambda: self.parent.show_transaction(closing_tx)) DIR diff --git a/electrum/lnchannel.py b/electrum/lnchannel.py t@@ -312,10 +312,20 @@ class Channel(Logger): # the closing txid has been saved return self.get_state() >= channel_states.CLOSED - def get_closing_txid(self): - item = self.lnworker.channel_timestamps.get(self.channel_id.hex()) - funding_txid, funding_height, funding_timestamp, closing_txid, closing_height, closing_timestamp = item - return closing_txid + def save_funding_height(self, txid, height, timestamp): + self.storage['funding_height'] = txid, height, timestamp + + def get_funding_height(self): + return self.storage.get('funding_height') + + def delete_funding_height(self): + self.storage.pop('funding_height', None) + + def save_closing_height(self, txid, height, timestamp): + self.storage['closing_height'] = txid, height, timestamp + + def get_closing_height(self): + return self.storage.get('closing_height') def is_redeemed(self): return self.get_state() == channel_states.REDEEMED DIR diff --git a/electrum/lnwatcher.py b/electrum/lnwatcher.py t@@ -336,11 +336,13 @@ class LNWalletWatcher(LNWatcher): if not chan: return if funding_height.height == TX_HEIGHT_LOCAL: - self.lnworker.channel_timestamps.pop(bh2u(chan.channel_id), None) + chan.delete_funding_height() return elif closing_height.height == TX_HEIGHT_LOCAL: + chan.save_funding_height(funding_txid, funding_height.height, funding_height.timestamp) await self.lnworker.update_open_channel(chan, funding_txid, funding_height) else: + chan.save_closing_height(closing_txid, closing_height.height, closing_height.timestamp) await self.lnworker.update_closed_channel(chan, funding_txid, funding_height, closing_txid, closing_height, keep_watching) async def do_breach_remedy(self, funding_outpoint, closing_tx, spenders): DIR diff --git a/electrum/lnworker.py b/electrum/lnworker.py t@@ -376,7 +376,6 @@ class LNWallet(LNWorker): self.channels[bfh(channel_id)] = Channel(c, sweep_address=self.sweep_address, lnworker=self) # timestamps of opening and closing transactions - self.channel_timestamps = self.db.get_dict('lightning_channel_timestamps') self.pending_payments = defaultdict(asyncio.Future) @ignore_exceptions t@@ -544,10 +543,10 @@ class LNWallet(LNWorker): with self.lock: channels = list(self.channels.values()) for chan in channels: - item = self.channel_timestamps.get(chan.channel_id.hex()) + item = chan.get_funding_height() if item is None: continue - funding_txid, funding_height, funding_timestamp, closing_txid, closing_height, closing_timestamp = item + funding_txid, funding_height, funding_timestamp = item item = { 'channel_id': bh2u(chan.channel_id), 'type': 'channel_opening', t@@ -559,9 +558,10 @@ class LNWallet(LNWorker): 'fee_msat': None, } out[funding_txid] = item - if not chan.is_closed(): + item = chan.get_closing_height() + if item is None: continue - assert closing_txid + closing_txid, closing_height, closing_timestamp = item item = { 'channel_id': bh2u(chan.channel_id), 'txid': closing_txid, t@@ -655,11 +655,6 @@ class LNWallet(LNWorker): return chan async def update_open_channel(self, chan, funding_txid, funding_height): - # return early to prevent overwriting closing_txid with None - if chan.is_closed(): - return - # save timestamp regardless of state, so that funding tx is returned in get_history - self.channel_timestamps[bh2u(chan.channel_id)] = chan.funding_outpoint.txid, funding_height.height, funding_height.timestamp, None, None, None if chan.get_state() == channel_states.OPEN and self.should_channel_be_closed_due_to_expiring_htlcs(chan): self.logger.info(f"force-closing due to expiring htlcs") t@@ -700,9 +695,6 @@ class LNWallet(LNWorker): async def update_closed_channel(self, chan, funding_txid, funding_height, closing_txid, closing_height, keep_watching): - # fixme: this is wasteful - self.channel_timestamps[bh2u(chan.channel_id)] = funding_txid, funding_height.height, funding_height.timestamp, closing_txid, closing_height.height, closing_height.timestamp - # remove from channel_db if chan.short_channel_id is not None: self.channel_db.remove_channel(chan.short_channel_id) t@@ -1226,7 +1218,6 @@ class LNWallet(LNWorker): assert chan.get_state() == channel_states.REDEEMED with self.lock: self.channels.pop(chan_id) - self.channel_timestamps.pop(chan_id.hex()) self.db.get('channels').pop(chan_id.hex()) self.network.trigger_callback('channels_updated', self.wallet) DIR diff --git a/electrum/wallet_db.py b/electrum/wallet_db.py t@@ -50,7 +50,7 @@ if TYPE_CHECKING: OLD_SEED_VERSION = 4 # electrum versions < 2.0 NEW_SEED_VERSION = 11 # electrum versions >= 2.0 -FINAL_SEED_VERSION = 25 # electrum >= 2.7 will set this to prevent +FINAL_SEED_VERSION = 26 # electrum >= 2.7 will set this to prevent # old versions from overwriting new format t@@ -171,6 +171,7 @@ class WalletDB(JsonDB): self._convert_version_23() self._convert_version_24() self._convert_version_25() + self._convert_version_26() self.put('seed_version', FINAL_SEED_VERSION) # just to be sure self._after_upgrade_tasks() t@@ -571,6 +572,21 @@ class WalletDB(JsonDB): } self.data['seed_version'] = 25 + def _convert_version_26(self): + if not self._is_upgrade_method_needed(25, 25): + return + channels = self.data.get('channels', {}) + channel_timestamps = self.data.pop('lightning_channel_timestamps', {}) + for channel_id, c in channels.items(): + item = channel_timestamps.get(channel_id) + if item: + funding_txid, funding_height, funding_timestamp, closing_txid, closing_height, closing_timestamp = item + if funding_txid: + c['funding_height'] = funding_txid, funding_height, funding_timestamp + if closing_txid: + c['closing_height'] = closing_txid, closing_height, closing_timestamp + self.data['seed_version'] = 26 + def _convert_imported(self): if not self._is_upgrade_method_needed(0, 13): return