What changed, and why it matters
This commit fixes a bug in Electrum's Lightning wallet database handling. After a wallet restart, a specific type of encryption key used in Lightning payments was being loaded as a text string instead of raw bytes. This mismatch could cause payment error decoding to fail or behave incorrectly, potentially leading to misleading error reports or degraded handling of failed Lightning transactions. The patch registers a proper converter so the keys are loaded as bytes, and adds a warning log when decoding fails.
Apply the patch. Users running Lightning nodes with Electrum should upgrade to a version containing this fix to ensure failed Lightning payment errors are decoded correctly after wallet restarts. Monitor for any related Lightning payment failures or onion error decoding issues.
Security signals we found
Type confusion between str and bytes in cryptographic key handling
Lightning payment error path affected after wallet restart
Missing data converter in wallet database layer
Exception swallowed silently before patch; now logged
Evidence from the diff
Channel.onion_keys lacked a hex->bytes converter in wallet_db.py. When loaded from disk, StoredDict returned hex strings rather than bytes, so pop_onion_key() returned str. Code in lnworker.py that calls pop_onion_key() and passes the result to decode_onion_error() expected bytes, causing a type mismatch and exception. The patch registers /channels//onion_keys/ with bytes.fromhex and adds logging for decode failures.
Changed components
electrum/wallet_db.pyelectrum/lnworker.pyLightning Network payment error handlingChannel onion key storage/retrievalInspect captured patch +2 / −0
diff --git a/electrum/lnworker.py b/electrum/lnworker.py
index 874c749..db5d29f 100644
--- a/electrum/lnworker.py
+++ b/electrum/lnworker.py
@@ -3228,6 +3228,7 @@ class LNWallet(Logger):
[x.node_id for x in route],
onion_key)
except Exception as e:
+ self.logger.warning(f"failed to decode onion error for htlc {htlc_id}", exc_info=True)
sender_idx = None
failure_message = OnionRoutingFailure(OnionFailureCode.INVALID_ONION_PAYLOAD, str(e).encode())
else:
diff --git a/electrum/wallet_db.py b/electrum/wallet_db.py
index c20180a..9a2dca7 100644
--- a/electrum/wallet_db.py
+++ b/electrum/wallet_db.py
@@ -106,6 +106,7 @@ class WalletFileExceptionVersion51(WalletFileException): pass
# register dicts that require value conversions not handled by constructor
register_name('/transactions/*', None, lambda x: tx_from_any(x, deserialize=False, sanitize=False))
register_name('/channels/*/data_loss_protect_remote_pcp/*', None, lambda x: bytes.fromhex(x))
+register_name('/channels/*/onion_keys/*', None, lambda x: bytes.fromhex(x))
# register tuples, otherwise they will default to StoredList
register_name('/contacts/*', None, tuple)
register_name('/lightning_preimages/*', None, tuple)
Why this scored 44/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.