qeinvoice: query self.status once in update_userinfo() and determine_can_pay()
What changed, and why it matters
This is a small code cleanup in Electrum's mobile/QML invoice screen. It stores the invoice status in a local variable so the code doesn't repeatedly ask for the same value. There is no visible security fix; it appears to be a minor maintainability or race-condition-hardening change.
No immediate action required. Treat as routine refactoring. If reviewing for security, verify whether self.status is a property that can change asynchronously and whether stronger synchronization is needed elsewhere.
Security signals we found
defensive hardening against TOCTOU-like inconsistency by caching self.status
no change to trust boundaries, input validation, cryptography, or network handling
Evidence from the diff
In qeinvoice.py, the update_userinfo() and determine_can_pay() methods previously read self.status multiple times. The patch reads self.status once into a local ‘status’ variable and uses that variable for all subsequent comparisons. This reduces the chance of inconsistent decisions if the status changes during execution, but does not change the overall logic or add validation.
Changed components
electrum/gui/qml/qeinvoice.pyQEInvoice.update_userinfo()QEInvoice.determine_can_pay()Inspect captured patch +14 / −10
diff --git a/electrum/gui/qml/qeinvoice.py b/electrum/gui/qml/qeinvoice.py
index a5f2a77..acb80bb 100644
--- a/electrum/gui/qml/qeinvoice.py
+++ b/electrum/gui/qml/qeinvoice.py
@@ -310,10 +310,12 @@ class QEInvoice(QObject, QtEventListener):
if self.amount.isEmpty:
self.userinfo = _('Enter the amount you want to send')
- if amount.isEmpty and self.status == PR_UNPAID: # unspecified amount
+ status = self.status
+
+ if amount.isEmpty and status == PR_UNPAID: # unspecified amount
return
- def userinfo_for_invoice_status(status: int) -> str:
+ def userinfo_for_invoice_status(_status: int) -> str:
return {
PR_EXPIRED: _('This invoice has expired'),
PR_PAID: _('This invoice was already paid'),
@@ -323,10 +325,10 @@ class QEInvoice(QObject, QtEventListener):
PR_BROADCAST: _('Payment in progress...') + ' (' + _('broadcast successfully') + ')',
PR_UNCONFIRMED: _('Payment in progress...') + ' (' + _('waiting for confirmation') + ')',
PR_UNKNOWN: _('Invoice has unknown status'),
- }[status]
+ }[_status]
if self.invoiceType == QEInvoice.Type.LightningInvoice:
- if self.status in [PR_UNPAID, PR_FAILED]:
+ if status in [PR_UNPAID, PR_FAILED]:
if self.get_max_spendable_lightning() >= amount.satsInt:
lnaddr = self._effectiveInvoice._lnaddr
if lnaddr.amount and amount.satsInt < lnaddr.amount * COIN:
@@ -335,13 +337,13 @@ class QEInvoice(QObject, QtEventListener):
# TODO: for onchain: validate address? subtract fee?
self.userinfo = _('Insufficient balance')
else:
- self.userinfo = userinfo_for_invoice_status(self.status)
+ self.userinfo = userinfo_for_invoice_status(status)
elif self.invoiceType == QEInvoice.Type.OnchainInvoice:
- if self.status in [PR_UNPAID, PR_FAILED]:
+ if status in [PR_UNPAID, PR_FAILED]:
if not ((amount.isMax and self.get_max_spendable_onchain() > 0) or (self.get_max_spendable_onchain() >= amount.satsInt)):
self.userinfo = _('Insufficient balance')
else:
- self.userinfo = userinfo_for_invoice_status(self.status)
+ self.userinfo = userinfo_for_invoice_status(status)
def determine_can_pay(self):
self.canPay = False
@@ -357,11 +359,13 @@ class QEInvoice(QObject, QtEventListener):
self.canSave = not bool(self._wallet.wallet.get_invoice(self._effectiveInvoice.get_id()))
- if amount.isEmpty and self.status == PR_UNPAID: # unspecified amount
+ status = self.status
+
+ if amount.isEmpty and status == PR_UNPAID: # unspecified amount
return
if self.invoiceType == QEInvoice.Type.LightningInvoice:
- if self.status in [PR_UNPAID, PR_FAILED]:
+ if status in [PR_UNPAID, PR_FAILED]:
if self.get_max_spendable_lightning() >= amount.satsInt:
lnaddr = self._effectiveInvoice._lnaddr
if not (lnaddr.amount and amount.satsInt < lnaddr.amount * COIN):
@@ -371,7 +375,7 @@ class QEInvoice(QObject, QtEventListener):
# TODO: subtract fee?
self.canPay = True
elif self.invoiceType == QEInvoice.Type.OnchainInvoice:
- if self.status in [PR_UNPAID, PR_FAILED]:
+ if status in [PR_UNPAID, PR_FAILED]:
if amount.isMax and self.get_max_spendable_onchain() > 0:
# TODO: dust limit?
self.canPay = True
Why this scored 17/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.