qml: show lightning invoice amounts with msat precision, allow msat precision entry for no-amount lightning invoices
What changed, and why it matters
This commit changes the mobile/QML user interface of the Electrum Bitcoin wallet so that Lightning invoice amounts are shown and entered with millisecond precision (one-thousandth of a satoshi) instead of whole satoshis. It is a precision/usability improvement for the QML GUI, not a fix for a vulnerability. There is no indication in the commit that this resolves a security issue.
No security action required. Treat as a normal UI/usability improvement. If auditing, verify that msatsInt is correctly populated and that the new regex prevents invalid inputs, but the change does not appear to introduce a vulnerability.
Security signals we found
No security-relevant keywords in commit title or message
No references to CVEs, security reports, or vulnerabilities
Change is localized to UI formatting and input validation precision
No changes to cryptographic, networking, or wallet-core logic
Evidence from the diff
The patch modifies four QML-related files. InvoiceDialog.qml now uses Config.formatMilliSats for Lightning invoices and sets msatPrecision on the BtcField. BtcField.qml adds a msatPrecision property that switches the input validator to a regex allowing three decimal places. qeinvoice.py changes the payment path for no-amount Lightning invoices from amountOverride.satsInt * 1000 to amountOverride.msatsInt. qetypes.py adds a pyqtSlot decorator to QEAmount.copyFrom. The changes are consistent with supporting sub-satoshi precision in the QML frontend only.
Changed components
electrum/gui/qml/components/InvoiceDialog.qmlelectrum/gui/qml/components/controls/BtcField.qmlelectrum/gui/qml/qeinvoice.pyelectrum/gui/qml/qetypes.pyInspect captured patch +9 / −4
diff --git a/electrum/gui/qml/components/InvoiceDialog.qml b/electrum/gui/qml/components/InvoiceDialog.qml
index 59590c6..51f41de 100644
--- a/electrum/gui/qml/components/InvoiceDialog.qml
+++ b/electrum/gui/qml/components/InvoiceDialog.qml
@@ -181,7 +181,9 @@ ElDialog {
font.pixelSize: constants.fontSizeXLarge
font.family: FixedFont
font.bold: true
- text: Config.formatSats(invoice.amount, false)
+ text: invoice.invoiceType == Invoice.LightningInvoice
+ ? Config.formatMilliSats(invoice.amount, false)
+ : Config.formatSats(invoice.amount, false)
}
Label {
@@ -223,12 +225,13 @@ ElDialog {
Layout.preferredWidth: amountFontMetrics.advanceWidth('0') * 14 + leftPadding + rightPadding
fiatfield: amountFiat
readOnly: amountMax.checked
+ msatPrecision: invoice.invoiceType == Invoice.LightningInvoice
color: readOnly
? Material.accentColor
: Material.foreground
onTextAsSatsChanged: {
if (!amountMax.checked)
- invoice.amountOverride.satsInt = textAsSats.satsInt
+ invoice.amountOverride.copyFrom(textAsSats)
}
Connections {
target: invoice.amountOverride
diff --git a/electrum/gui/qml/components/controls/BtcField.qml b/electrum/gui/qml/components/controls/BtcField.qml
index fca0455..a426243 100644
--- a/electrum/gui/qml/components/controls/BtcField.qml
+++ b/electrum/gui/qml/components/controls/BtcField.qml
@@ -7,12 +7,13 @@ TextField {
id: amount
required property TextField fiatfield
+ property bool msatPrecision: false
font.family: FixedFont
placeholderText: qsTr('Amount')
inputMethodHints: Qt.ImhDigitsOnly
validator: RegularExpressionValidator {
- regularExpression: Config.btcAmountRegex
+ regularExpression: msatPrecision ? Config.btcAmountRegexMsat : Config.btcAmountRegex
}
property Amount textAsSats
diff --git a/electrum/gui/qml/qeinvoice.py b/electrum/gui/qml/qeinvoice.py
index bedc1c6..8e3ce20 100644
--- a/electrum/gui/qml/qeinvoice.py
+++ b/electrum/gui/qml/qeinvoice.py
@@ -383,7 +383,7 @@ class QEInvoice(QObject, QtEventListener):
if self.amount.isEmpty:
if self.amountOverride.isEmpty:
raise Exception('can not pay 0 amount')
- amount_msat = self.amountOverride.satsInt * 1000
+ amount_msat = self.amountOverride.msatsInt
self._wallet.pay_lightning_invoice(self._effectiveInvoice, amount_msat)
diff --git a/electrum/gui/qml/qetypes.py b/electrum/gui/qml/qetypes.py
index 090dae9..abcb445 100644
--- a/electrum/gui/qml/qetypes.py
+++ b/electrum/gui/qml/qetypes.py
@@ -90,6 +90,7 @@ class QEAmount(QObject):
self._is_max = False
self.valueChanged.emit()
+ @pyqtSlot('QVariant')
def copyFrom(self, amount):
if not amount:
self._logger.warning('copyFrom with None argument. assuming 0') # TODO
Why this scored 18/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.