addr_sync: update "stored_height" db field immediately on wallet-open
What changed, and why it matters
This commit fixes a display bug in the Electrum wallet. If a wallet was created or restored and then quickly closed, the database did not record the last known block height. Later, opening that wallet in offline mode made all transactions appear 'unconfirmed' because the wallet had no saved height to compare against. The fix immediately saves the current block height when a wallet is opened, not just when new blocks arrive.
No security action required; this is a bug-fix commit improving offline UX. Users who noticed 'unconfirmed' labels for old transactions while offline will benefit from updating.
Security signals we found
UI/display state inconsistency
missing persistence of synchronization metadata
offline-mode behavior bug
Evidence from the diff
AddressSynchronizer previously only wrote the ‘stored_height’ database field inside on_event_blockchain_updated. For a wallet that was created/restored and closed before a subsequent block event, stored_height remained unset. On a later offline (-o) open, get_local_height() fell back to the default 0, so all historical transactions looked unconfirmed. The patch adds an _update_stored_local_height() helper and calls it from set_network() at wallet-open time, ensuring the field is persisted immediately.
Changed components
electrum/address_synchronizer.pyInspect captured patch +5 / −1
diff --git a/electrum/address_synchronizer.py b/electrum/address_synchronizer.py
index dc9bedd..9d061dd 100644
--- a/electrum/address_synchronizer.py
+++ b/electrum/address_synchronizer.py
@@ -208,12 +208,13 @@ class AddressSynchronizer(Logger, EventListener):
self.verifier = SPV(self.network, self)
self.asyncio_loop = network.asyncio_loop
self.register_callbacks()
+ self._update_stored_local_height()
@event_listener
@with_lock
def on_event_blockchain_updated(self, *args):
self.invalidate_cache()
- self.db.put('stored_height', self.get_local_height())
+ self._update_stored_local_height()
async def stop(self):
if self.network:
@@ -694,6 +695,9 @@ class AddressSynchronizer(Logger, EventListener):
return cached_local_height
return self.network.get_local_height() if self.network else self.db.get('stored_height', 0)
+ def _update_stored_local_height(self) -> None:
+ self.db.put('stored_height', self.get_local_height())
+
def set_future_tx(self, txid: str, *, wanted_height: int):
"""Mark a local tx as "future" (encumbered by a timelock).
wanted_height is the min (abs) block height at which the tx can get into the mempool (be broadcast).
Why this scored 23/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.