What changed, and why it matters
This commit fixes a state-handling bug in Electrum's mobile/QML interface when scanning or processing payment invoices. Specifically, when a user scanned a Lightning invoice, leftover data from a previous LNURL-pay interaction could remain in the invoice parser, causing the app to think it should still act as an LNURL-pay and potentially pay immediately without showing the normal confirmation. The fix resets parser state when loading a new invoice, except when intentionally continuing an LNURL-pay flow.
Users of the QML/Android version of Electrum should update to a version containing this commit. Review related QML payment flows for any other state variables that may not be reset between invoice parses. Consider adding regression tests covering transitions between LNURL-pay and bolt11 invoice scans.
Security signals we found
State not reset between invoice parses, leading to stale LNURL-pay data influencing payment confirmation behavior
QML `payImmediately` decision depends on parser state that could be left over from a previous operation
Fix explicitly preserves intended LNURL-pay flow while preventing cross-invoice state contamination
Evidence from the diff
In electrum/gui/qml/qeinvoice.py, QEInvoiceParser.fromResolvedPaymentIdentifier() previously only set self.canPay = False before populating a new invoice. It did not clear _lnurlData, which drives the QML property isLnurlPay and the payImmediately behavior in onValidationSuccess. As a result, scanning a bolt11 invoice after an LNURL-pay interaction could leave stale _lnurlData, making payImmediately true and potentially auto-confirming a payment. The patch replaces the partial reset with self.clear() in fromResolvedPaymentIdentifier(), and changes the LNURL-pay callback path to call validateRecipient() directly instead of fromResolvedPaymentIdentifier() so that _lnurlData is preserved for the intended LNURL-pay confirmation flow.
Changed components
electrum/gui/qml/qeinvoice.pyQEInvoiceParser classQML invoice validation/payment confirmation flowInspect captured patch +3 / −2
diff --git a/electrum/gui/qml/qeinvoice.py b/electrum/gui/qml/qeinvoice.py
index 640363f..ad46839 100644
--- a/electrum/gui/qml/qeinvoice.py
+++ b/electrum/gui/qml/qeinvoice.py
@@ -451,7 +451,7 @@ class QEInvoiceParser(QEInvoice):
@pyqtSlot(object)
def fromResolvedPaymentIdentifier(self, resolved_pi: PaymentIdentifier) -> None:
- self.canPay = False
+ self.clear()
self.amountOverride = QEAmount()
if resolved_pi:
assert not resolved_pi.need_resolve()
@@ -653,7 +653,8 @@ class QEInvoiceParser(QEInvoice):
if orig_amount * 1000 != invoice.amount_msat: # TODO msat precision can cause trouble here
raise Exception('Unexpected amount in invoice, differs from lnurl-pay specified amount')
- self.fromResolvedPaymentIdentifier(
+ self.amountOverride = QEAmount()
+ self.validateRecipient(
PaymentIdentifier(self._wallet.wallet, invoice.lightning_invoice)
)
Why this scored 42/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.