Browse Source

lnworker: fix can_pay_invoice for trampoline MPP

Call it from the GUI
patch-4
ThomasV 3 years ago
parent
commit
fb6047ec46
  1. 2
      electrum/gui/kivy/uix/dialogs/invoice_dialog.py
  2. 4
      electrum/gui/qt/main_window.py
  3. 38
      electrum/lnworker.py

2
electrum/gui/kivy/uix/dialogs/invoice_dialog.py

@ -111,7 +111,7 @@ class InvoiceDialog(Factory.Popup):
self.status_color = pr_color[self.status] self.status_color = pr_color[self.status]
self.can_pay = self.status in [PR_UNPAID, PR_FAILED] self.can_pay = self.status in [PR_UNPAID, PR_FAILED]
if self.can_pay and self.is_lightning and self.app.wallet.lnworker: if self.can_pay and self.is_lightning and self.app.wallet.lnworker:
if self.amount_sat and self.amount_sat > self.app.wallet.lnworker.num_sats_can_send(): if self.amount_sat and not self.app.wallet.lnworker.can_pay_invoice(invoice):
self.warning = _('Warning') + ': ' + _('This amount exceeds the maximum you can currently send with your channels') self.warning = _('Warning') + ': ' + _('This amount exceeds the maximum you can currently send with your channels')
def on_dismiss(self): def on_dismiss(self):

4
electrum/gui/qt/main_window.py

@ -1671,8 +1671,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
key = self.wallet.get_key_for_outgoing_invoice(invoice) key = self.wallet.get_key_for_outgoing_invoice(invoice)
if amount_sat is None: if amount_sat is None:
raise Exception("missing amount for LN invoice") raise Exception("missing amount for LN invoice")
num_sats_can_send = int(self.wallet.lnworker.num_sats_can_send()) if not self.wallet.lnworker.can_pay_invoice(invoice):
if amount_sat > num_sats_can_send: num_sats_can_send = int(self.wallet.lnworker.num_sats_can_send())
lightning_needed = amount_sat - num_sats_can_send lightning_needed = amount_sat - num_sats_can_send
lightning_needed += (lightning_needed // 20) # operational safety margin lightning_needed += (lightning_needed // 20) # operational safety margin
coins = self.get_coins(nonlocal_only=True) coins = self.get_coins(nonlocal_only=True)

38
electrum/lnworker.py

@ -1090,6 +1090,40 @@ class LNWallet(LNWorker):
if invoice.is_lightning() and self.can_pay_invoice(invoice): if invoice.is_lightning() and self.can_pay_invoice(invoice):
await self.pay_invoice(invoice.lightning_invoice, attempts=10) await self.pay_invoice(invoice.lightning_invoice, attempts=10)
def can_pay_invoice(self, invoice: Invoice) -> bool:
assert invoice.is_lightning()
if invoice.get_amount_sat() > self.num_sats_can_send():
return False
# if we dont find a path because of unsynchronized DB, this method should not return False
if self.channel_db:
return True
# trampoline nodes currently cannot do legacy payments over multiple nodes
# we call create_routes_for_payment in order to find out
lnaddr = self._check_invoice(invoice.lightning_invoice, amount_msat=invoice.get_amount_msat())
min_cltv_expiry = lnaddr.get_min_final_cltv_expiry()
invoice_pubkey = lnaddr.pubkey.serialize()
invoice_features = lnaddr.get_features()
r_tags = lnaddr.get_routing_info('r')
amount_to_pay = lnaddr.get_amount_msat()
try:
routes = self.create_routes_for_payment(
amount_msat=amount_to_pay,
final_total_msat=amount_to_pay,
invoice_pubkey=invoice_pubkey,
min_cltv_expiry=min_cltv_expiry,
r_tags=r_tags,
invoice_features=invoice_features,
full_path=None,
payment_hash=bytes(32),
payment_secret=bytes(32),
trampoline_fee_level=self.INITIAL_TRAMPOLINE_FEE_LEVEL,
use_two_trampolines=False,
fwd_trampoline_onion=None
)
return True
except NoPathFound:
return False
@log_exceptions @log_exceptions
async def pay_invoice( async def pay_invoice(
self, invoice: str, *, self, invoice: str, *,
@ -2085,10 +2119,6 @@ class LNWallet(LNWorker):
can_receive = max([c.available_to_spend(REMOTE) for c in channels]) if channels else 0 can_receive = max([c.available_to_spend(REMOTE) for c in channels]) if channels else 0
return Decimal(can_receive) / 1000 return Decimal(can_receive) / 1000
def can_pay_invoice(self, invoice: Invoice) -> bool:
assert invoice.is_lightning()
return invoice.get_amount_sat() <= self.num_sats_can_send()
def can_receive_invoice(self, invoice: Invoice) -> bool: def can_receive_invoice(self, invoice: Invoice) -> bool:
assert invoice.is_lightning() assert invoice.is_lightning()
return invoice.get_amount_sat() <= self.num_sats_can_receive() return invoice.get_amount_sat() <= self.num_sats_can_receive()

Loading…
Cancel
Save