From ffa3acc0135a1def7034fe882ebccd1f5208fa06 Mon Sep 17 00:00:00 2001 From: SomberNight Date: Tue, 22 Aug 2023 18:12:15 +0000 Subject: [PATCH] invoices: don't modify .amount_msat directly --- electrum/gui/kivy/uix/screens.py | 2 +- electrum/gui/qml/qeinvoice.py | 7 +++---- electrum/gui/text.py | 2 +- electrum/invoices.py | 13 +++++++++++++ electrum/payment_identifier.py | 2 +- electrum/tests/test_invoices.py | 2 ++ 6 files changed, 21 insertions(+), 7 deletions(-) diff --git a/electrum/gui/kivy/uix/screens.py b/electrum/gui/kivy/uix/screens.py index d5191b97a..37b080126 100644 --- a/electrum/gui/kivy/uix/screens.py +++ b/electrum/gui/kivy/uix/screens.py @@ -351,7 +351,7 @@ class SendScreen(CScreen, Logger): assert type(amount_sat) is int invoice = Invoice.from_bech32(address) if invoice.amount_msat is None: - invoice.amount_msat = int(amount_sat * 1000) + invoice.set_amount_msat(int(amount_sat * 1000)) return invoice else: # on-chain diff --git a/electrum/gui/qml/qeinvoice.py b/electrum/gui/qml/qeinvoice.py index 7a73ece05..3dde33612 100644 --- a/electrum/gui/qml/qeinvoice.py +++ b/electrum/gui/qml/qeinvoice.py @@ -379,8 +379,7 @@ class QEInvoice(QObject, QtEventListener): if self.amount.isEmpty: if self.amountOverride.isEmpty: raise Exception('can not pay 0 amount') - # TODO: is update amount_msat for overrideAmount sufficient? - self._effectiveInvoice.amount_msat = self.amountOverride.satsInt * 1000 + self._effectiveInvoice.set_amount_msat(self.amountOverride.satsInt * 1000) self._wallet.pay_lightning_invoice(self._effectiveInvoice) @@ -627,9 +626,9 @@ class QEInvoiceParser(QEInvoice): if not self._effectiveInvoice.amount_msat and not self.amountOverride.isEmpty: if self.invoiceType == QEInvoice.Type.OnchainInvoice and self.amountOverride.isMax: - self._effectiveInvoice.amount_msat = '!' + self._effectiveInvoice.set_amount_msat('!') else: - self._effectiveInvoice.amount_msat = self.amountOverride.satsInt * 1000 + self._effectiveInvoice.set_amount_msat(self.amountOverride.satsInt * 1000) self.canSave = False diff --git a/electrum/gui/text.py b/electrum/gui/text.py index 1996dd1fe..f18e604be 100644 --- a/electrum/gui/text.py +++ b/electrum/gui/text.py @@ -606,7 +606,7 @@ class ElectrumGui(BaseElectrumGui, EventListener): if invoice.amount_msat is None: amount_sat = self.parse_amount(self.str_amount) if amount_sat: - invoice.amount_msat = int(amount_sat * 1000) + invoice.set_amount_msat(int(amount_sat * 1000)) else: self.show_error(_('No amount')) return diff --git a/electrum/invoices.py b/electrum/invoices.py index 9f790ea77..39e2dad43 100644 --- a/electrum/invoices.py +++ b/electrum/invoices.py @@ -178,6 +178,19 @@ class BaseInvoice(StoredObject): return amount_msat return int(amount_msat // 1000) + def set_amount_msat(self, amount_msat: Union[int, str]) -> None: + """The GUI uses this to fill the amount for a zero-amount invoice.""" + if amount_msat == "!": + amount_sat = amount_msat + else: + assert isinstance(amount_msat, int), f"{amount_msat=!r}" + assert amount_msat >= 0, amount_msat + amount_sat = (amount_msat // 1000) + int(amount_msat % 1000 > 0) # round up + if outputs := self.outputs: + assert len(self.outputs) == 1, len(self.outputs) + self.outputs = [PartialTxOutput(scriptpubkey=outputs[0].scriptpubkey, value=amount_sat)] + self.amount_msat = amount_msat + @amount_msat.validator def _validate_amount(self, attribute, value): if value is None: diff --git a/electrum/payment_identifier.py b/electrum/payment_identifier.py index 6aad287ae..c95e47467 100644 --- a/electrum/payment_identifier.py +++ b/electrum/payment_identifier.py @@ -674,7 +674,7 @@ def invoice_from_payment_identifier( if not invoice: return if invoice.amount_msat is None: - invoice.amount_msat = int(amount_sat * 1000) + invoice.set_amount_msat(int(amount_sat * 1000)) return invoice else: outputs = pi.get_onchain_outputs(amount_sat) diff --git a/electrum/tests/test_invoices.py b/electrum/tests/test_invoices.py index a5ea83fca..9f7e017c2 100644 --- a/electrum/tests/test_invoices.py +++ b/electrum/tests/test_invoices.py @@ -286,6 +286,8 @@ class TestBaseInvoice(ElectrumTestCase): ) with self.assertRaises(InvoiceError): invoice.amount_msat = 10**20 + with self.assertRaises(InvoiceError): + invoice.set_amount_msat(10**20) with self.assertRaises(InvoiceError): invoice2 = Invoice( amount_msat=10**20,