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 ```
This commit is contained in:
@@ -16,6 +16,7 @@ from electrum.invoices import (PR_DEFAULT_EXPIRATION_WHEN_CREATING,
|
|||||||
PR_PAID, PR_UNKNOWN, PR_EXPIRED, PR_INFLIGHT,
|
PR_PAID, PR_UNKNOWN, PR_EXPIRED, PR_INFLIGHT,
|
||||||
pr_expiration_values, Invoice)
|
pr_expiration_values, Invoice)
|
||||||
from electrum import bitcoin, constants
|
from electrum import bitcoin, constants
|
||||||
|
from electrum import lnutil
|
||||||
from electrum.transaction import tx_from_any, PartialTxOutput
|
from electrum.transaction import tx_from_any, PartialTxOutput
|
||||||
from electrum.util import (parse_URI, InvalidBitcoinURI, TxMinedInfo, maybe_extract_lightning_payment_identifier,
|
from electrum.util import (parse_URI, InvalidBitcoinURI, TxMinedInfo, maybe_extract_lightning_payment_identifier,
|
||||||
InvoiceError, format_time, parse_max_spend, BITCOIN_BIP21_URI_SCHEME)
|
InvoiceError, format_time, parse_max_spend, BITCOIN_BIP21_URI_SCHEME)
|
||||||
@@ -224,6 +225,9 @@ class SendScreen(CScreen, Logger):
|
|||||||
except LnInvoiceException as e:
|
except LnInvoiceException as e:
|
||||||
self.app.show_info(_("Invoice is not a valid Lightning invoice: ") + repr(e)) # repr because str(Exception()) == ''
|
self.app.show_info(_("Invoice is not a valid Lightning invoice: ") + repr(e)) # repr because str(Exception()) == ''
|
||||||
return
|
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.address = invoice
|
||||||
self.message = lnaddr.get_description()
|
self.message = lnaddr.get_description()
|
||||||
self.amount = self.app.format_amount_and_units(lnaddr.amount * bitcoin.COIN) if lnaddr.amount else ''
|
self.amount = self.app.format_amount_and_units(lnaddr.amount * bitcoin.COIN) if lnaddr.amount else ''
|
||||||
|
|||||||
@@ -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.transaction import PartialTxOutput
|
||||||
from electrum.lnaddr import lndecode
|
from electrum.lnaddr import lndecode
|
||||||
from electrum import bitcoin
|
from electrum import bitcoin
|
||||||
|
from electrum import lnutil
|
||||||
|
from electrum.lnaddr import LnInvoiceException
|
||||||
|
|
||||||
from .qewallet import QEWallet
|
from .qewallet import QEWallet
|
||||||
from .qetypes import QEAmount
|
from .qetypes import QEAmount
|
||||||
@@ -334,11 +336,21 @@ class QEInvoiceParser(QEInvoice):
|
|||||||
self._logger.debug(repr(e))
|
self._logger.debug(repr(e))
|
||||||
|
|
||||||
lninvoice = None
|
lninvoice = None
|
||||||
try:
|
maybe_lightning_invoice = maybe_extract_lightning_payment_identifier(maybe_lightning_invoice)
|
||||||
maybe_lightning_invoice = maybe_extract_lightning_payment_identifier(maybe_lightning_invoice)
|
if maybe_lightning_invoice is not None:
|
||||||
lninvoice = Invoice.from_bech32(maybe_lightning_invoice)
|
try:
|
||||||
except InvoiceError as e:
|
lninvoice = Invoice.from_bech32(maybe_lightning_invoice)
|
||||||
pass
|
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:
|
if not lninvoice and not self._bip21:
|
||||||
self.validationError.emit('unknown',_('Unknown invoice'))
|
self.validationError.emit('unknown',_('Unknown invoice'))
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from PyQt5.QtWidgets import (QLabel, QVBoxLayout, QGridLayout,
|
|||||||
QHBoxLayout, QCompleter, QWidget, QToolTip)
|
QHBoxLayout, QCompleter, QWidget, QToolTip)
|
||||||
|
|
||||||
from electrum import util, paymentrequest
|
from electrum import util, paymentrequest
|
||||||
|
from electrum import lnutil
|
||||||
from electrum.plugin import run_hook
|
from electrum.plugin import run_hook
|
||||||
from electrum.i18n import _
|
from electrum.i18n import _
|
||||||
from electrum.util import (get_asyncio_loop, bh2u,
|
from electrum.util import (get_asyncio_loop, bh2u,
|
||||||
@@ -402,6 +403,9 @@ class SendTab(QWidget, MessageBoxMixin, Logger):
|
|||||||
except LnInvoiceException as e:
|
except LnInvoiceException as e:
|
||||||
self.show_error(_("Error parsing Lightning invoice") + f":\n{e}")
|
self.show_error(_("Error parsing Lightning invoice") + f":\n{e}")
|
||||||
return
|
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())
|
pubkey = bh2u(lnaddr.pubkey.serialize())
|
||||||
for k,v in lnaddr.tags:
|
for k,v in lnaddr.tags:
|
||||||
|
|||||||
Reference in New Issue
Block a user