From d5b5f82b01db60b8bbb2cb34f8679234c9a21164 Mon Sep 17 00:00:00 2001 From: SomberNight Date: Fri, 15 Jul 2022 18:00:33 +0200 Subject: [PATCH] LN invoice: better handle unknown required featured bits in bolt11 invs A user provided an invoice that requires feature bit 30. (That bit is not in the spec) To test: ``` lnbc1p324a66pp5tundykxx3q5kztsr8x00eknpn2uwe3394cnky3j9a0fswm568wnsdp9facx2mj5d9kk2um5v9khqueqv3hkuct5d9hkucqzpgxq9z0rgqsp5l73jgfgctzc92juer5rk2mqcrkj8teng53dr9vfxj4n8lulu4jmq9q8pqqqssq4gacn859tpzz99hkusnh7m93d5ncpx3t4zns8ynca7akmljpl5vh504qjz7dqwewqjh4md7xagaz5wg85knvxywrhp0sp2t09yta7lcq3qs6fy lntb1p324a66pp5tundykxx3q5kztsr8x00eknpn2uwe3394cnky3j9a0fswm568wnssp5l73jgfgctzc92juer5rk2mqcrkj8teng53dr9vfxj4n8lulu4jmqdp9facx2mj5d9kk2um5v9khqueqv3hkuct5d9hkuxq9z0rgq9q8pqqqssqdte0z9dy7ur7fagsk7r3mtfj6upq88xfylhufys87zqpamklcfgn2f3xeq3nlhvn3qy9tdgg42vq9eq99qz6rz6tzqezfhzuv6zsr5qp7cgel4 ``` --- electrum/gui/kivy/uix/screens.py | 4 ++++ electrum/gui/qml/qeinvoice.py | 22 +++++++++++++++++----- electrum/gui/qt/send_tab.py | 4 ++++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/electrum/gui/kivy/uix/screens.py b/electrum/gui/kivy/uix/screens.py index fabf86896..a9c3b4850 100644 --- a/electrum/gui/kivy/uix/screens.py +++ b/electrum/gui/kivy/uix/screens.py @@ -16,6 +16,7 @@ from electrum.invoices import (PR_DEFAULT_EXPIRATION_WHEN_CREATING, PR_PAID, PR_UNKNOWN, PR_EXPIRED, PR_INFLIGHT, pr_expiration_values, Invoice) from electrum import bitcoin, constants +from electrum import lnutil from electrum.transaction import tx_from_any, PartialTxOutput from electrum.util import (parse_URI, InvalidBitcoinURI, TxMinedInfo, maybe_extract_lightning_payment_identifier, InvoiceError, format_time, parse_max_spend, BITCOIN_BIP21_URI_SCHEME) @@ -224,6 +225,9 @@ class SendScreen(CScreen, Logger): except LnInvoiceException as e: self.app.show_info(_("Invoice is not a valid Lightning invoice: ") + repr(e)) # repr because str(Exception()) == '' return + except lnutil.IncompatibleOrInsaneFeatures as e: + self.app.show_info(_("Invoice requires unknown or incompatible Lightning feature") + f":\n{e!r}") + return self.address = invoice self.message = lnaddr.get_description() self.amount = self.app.format_amount_and_units(lnaddr.amount * bitcoin.COIN) if lnaddr.amount else '' diff --git a/electrum/gui/qml/qeinvoice.py b/electrum/gui/qml/qeinvoice.py index a0c57bf3f..32e0439ae 100644 --- a/electrum/gui/qml/qeinvoice.py +++ b/electrum/gui/qml/qeinvoice.py @@ -13,6 +13,8 @@ from electrum.invoices import (PR_UNPAID,PR_EXPIRED,PR_UNKNOWN,PR_PAID,PR_INFLIG from electrum.transaction import PartialTxOutput from electrum.lnaddr import lndecode from electrum import bitcoin +from electrum import lnutil +from electrum.lnaddr import LnInvoiceException from .qewallet import QEWallet from .qetypes import QEAmount @@ -334,11 +336,21 @@ class QEInvoiceParser(QEInvoice): self._logger.debug(repr(e)) lninvoice = None - try: - maybe_lightning_invoice = maybe_extract_lightning_payment_identifier(maybe_lightning_invoice) - lninvoice = Invoice.from_bech32(maybe_lightning_invoice) - except InvoiceError as e: - pass + maybe_lightning_invoice = maybe_extract_lightning_payment_identifier(maybe_lightning_invoice) + if maybe_lightning_invoice is not None: + try: + lninvoice = Invoice.from_bech32(maybe_lightning_invoice) + except InvoiceError as e: + e2 = e.__cause__ + if isinstance(e2, LnInvoiceException): + self.validationError.emit('unknown', _("Error parsing Lightning invoice") + f":\n{e2}") + self.clear() + return + if isinstance(e2, lnutil.IncompatibleOrInsaneFeatures): + self.validationError.emit('unknown', _("Invoice requires unknown or incompatible Lightning feature") + f":\n{e2!r}") + self.clear() + return + self._logger.exception(repr(e)) if not lninvoice and not self._bip21: self.validationError.emit('unknown',_('Unknown invoice')) diff --git a/electrum/gui/qt/send_tab.py b/electrum/gui/qt/send_tab.py index 8cb61f395..f8cb471b0 100644 --- a/electrum/gui/qt/send_tab.py +++ b/electrum/gui/qt/send_tab.py @@ -12,6 +12,7 @@ from PyQt5.QtWidgets import (QLabel, QVBoxLayout, QGridLayout, QHBoxLayout, QCompleter, QWidget, QToolTip) from electrum import util, paymentrequest +from electrum import lnutil from electrum.plugin import run_hook from electrum.i18n import _ from electrum.util import (get_asyncio_loop, bh2u, @@ -402,6 +403,9 @@ class SendTab(QWidget, MessageBoxMixin, Logger): except LnInvoiceException as e: self.show_error(_("Error parsing Lightning invoice") + f":\n{e}") return + except lnutil.IncompatibleOrInsaneFeatures as e: + self.show_error(_("Invoice requires unknown or incompatible Lightning feature") + f":\n{e!r}") + return pubkey = bh2u(lnaddr.pubkey.serialize()) for k,v in lnaddr.tags: