Browse Source

If trampoline is enabled, do not add non-trampoline nodes to invoices

Rationale: The sender should not assume that they share the same list of
hardcoded trampolines as the receiver.
master
ThomasV 2 years ago
parent
commit
120faa480e
  1. 3
      electrum/gui/messages.py
  2. 15
      electrum/gui/qt/channels_list.py
  3. 2
      electrum/lnchannel.py
  4. 2
      electrum/lnworker.py
  5. 2
      electrum/trampoline.py

3
electrum/gui/messages.py

@ -41,7 +41,6 @@ MSG_CAPITAL_GAINS = _(
) )
MSG_NON_TRAMPOLINE_CHANNEL_FROZEN_WITHOUT_GOSSIP = _( MSG_NON_TRAMPOLINE_CHANNEL_FROZEN_WITHOUT_GOSSIP = _(
"""Trampoline routing is enabled, but this channel is with a non-trampoline node. """This channel is with a non-trampoline node; it cannot be used if trampoline is enabled.
This channel may still be used for receiving, but it is frozen for sending.
If you want to keep using this channel, you need to disable trampoline routing in your preferences.""" If you want to keep using this channel, you need to disable trampoline routing in your preferences."""
) )

15
electrum/gui/qt/channels_list.py

@ -193,9 +193,12 @@ class ChannelsList(MyTreeView):
return self.network.run_from_another_thread(coro) return self.network.run_from_another_thread(coro)
WaitingDialog(self, 'please wait..', task, self.on_request_sent, self.on_failure) WaitingDialog(self, 'please wait..', task, self.on_request_sent, self.on_failure)
def freeze_channel_for_sending(self, chan, b): def set_frozen(self, chan, *, for_sending, value):
if not self.lnworker.uses_trampoline() or self.lnworker.is_trampoline_peer(chan.node_id): if not self.lnworker.uses_trampoline() or self.lnworker.is_trampoline_peer(chan.node_id):
chan.set_frozen_for_sending(b) if for_sending:
chan.set_frozen_for_sending(value)
else:
chan.set_frozen_for_receiving(value)
else: else:
msg = messages.MSG_NON_TRAMPOLINE_CHANNEL_FROZEN_WITHOUT_GOSSIP msg = messages.MSG_NON_TRAMPOLINE_CHANNEL_FROZEN_WITHOUT_GOSSIP
self.main_window.show_warning(msg, title=_('Channel is frozen for sending')) self.main_window.show_warning(msg, title=_('Channel is frozen for sending'))
@ -258,13 +261,13 @@ class ChannelsList(MyTreeView):
if not chan.is_backup() and not chan.is_closed(): if not chan.is_backup() and not chan.is_closed():
fm = menu.addMenu(_("Freeze")) fm = menu.addMenu(_("Freeze"))
if not chan.is_frozen_for_sending(): if not chan.is_frozen_for_sending():
fm.addAction(_("Freeze for sending"), lambda: self.freeze_channel_for_sending(chan, True)) fm.addAction(_("Freeze for sending"), lambda: self.set_frozen(chan, for_sending=True, value=True))
else: else:
fm.addAction(_("Unfreeze for sending"), lambda: self.freeze_channel_for_sending(chan, False)) fm.addAction(_("Unfreeze for sending"), lambda: self.set_frozen(chan, for_sending=True, value=False))
if not chan.is_frozen_for_receiving(): if not chan.is_frozen_for_receiving():
fm.addAction(_("Freeze for receiving"), lambda: chan.set_frozen_for_receiving(True)) fm.addAction(_("Freeze for receiving"), lambda: self.set_frozen(chan, for_sending=False, value=True))
else: else:
fm.addAction(_("Unfreeze for receiving"), lambda: chan.set_frozen_for_receiving(False)) fm.addAction(_("Unfreeze for receiving"), lambda: self.set_frozen(chan, for_sending=False, value=False))
if close_opts := chan.get_close_options(): if close_opts := chan.get_close_options():
cm = menu.addMenu(_("Close")) cm = menu.addMenu(_("Close"))
if ChanCloseOption.COOP_CLOSE in close_opts: if ChanCloseOption.COOP_CLOSE in close_opts:

2
electrum/lnchannel.py

@ -921,6 +921,8 @@ class Channel(AbstractChannel):
util.trigger_callback('channel', self.lnworker.wallet, self) util.trigger_callback('channel', self.lnworker.wallet, self)
def is_frozen_for_receiving(self) -> bool: def is_frozen_for_receiving(self) -> bool:
if self.lnworker and self.lnworker.uses_trampoline() and not self.lnworker.is_trampoline_peer(self.node_id):
return True
return self.storage.get('frozen_for_receiving', False) return self.storage.get('frozen_for_receiving', False)
def set_frozen_for_receiving(self, b: bool) -> None: def set_frozen_for_receiving(self, b: bool) -> None:

2
electrum/lnworker.py

@ -2068,6 +2068,8 @@ class LNWallet(LNWorker):
routing_hints = self.calc_routing_hints_for_invoice(amount_msat, channels=channels) routing_hints = self.calc_routing_hints_for_invoice(amount_msat, channels=channels)
self.logger.info(f"creating bolt11 invoice with routing_hints: {routing_hints}") self.logger.info(f"creating bolt11 invoice with routing_hints: {routing_hints}")
invoice_features = self.features.for_invoice() invoice_features = self.features.for_invoice()
if not self.uses_trampoline():
invoice_features &= ~ LnFeatures.OPTION_TRAMPOLINE_ROUTING_OPT_ELECTRUM
payment_secret = self.get_payment_secret(payment_hash) payment_secret = self.get_payment_secret(payment_hash)
amount_btc = amount_msat/Decimal(COIN*1000) if amount_msat else None amount_btc = amount_msat/Decimal(COIN*1000) if amount_msat else None
if expiry == 0: if expiry == 0:

2
electrum/trampoline.py

@ -143,7 +143,7 @@ def is_legacy_relay(invoice_features, r_tags) -> Tuple[bool, Set[bytes]]:
# endpoints connected to T1 and T2, and sender only has send-capacity with T1, while # endpoints connected to T1 and T2, and sender only has send-capacity with T1, while
# recipient only has recv-capacity with T2. # recipient only has recv-capacity with T2.
singlehop_r_tags = [x for x in r_tags if len(x) == 1] singlehop_r_tags = [x for x in r_tags if len(x) == 1]
invoice_trampolines = [x[0][0] for x in singlehop_r_tags if is_hardcoded_trampoline(x[0][0])] invoice_trampolines = [x[0][0] for x in singlehop_r_tags]
invoice_trampolines = set(invoice_trampolines) invoice_trampolines = set(invoice_trampolines)
if invoice_trampolines: if invoice_trampolines:
return False, invoice_trampolines return False, invoice_trampolines

Loading…
Cancel
Save