1
0

Trampoline routing.

- trampoline is enabled by default in config, to prevent download of `gossip_db`.
   (if disabled, `gossip_db` will be downloaded, regardless of the existence of channels)
 - if trampoline is enabled:
    - the wallet can only open channels with trampoline nodes
    - already-existing channels with non-trampoline nodes are frozen for sending.
 - there are two types of trampoline payments: legacy and end-to-end (e2e).
 - we decide to perform legacy or e2e based on the invoice:
    - we use trampoline_routing_opt in features to detect Eclair and Phoenix invoices
    - we use trampoline_routing_hints to detect Electrum invoices
 - when trying a legacy payment, we add a second trampoline to the path to preserve privacy.
   (we fall back to a single trampoline if the payment fails for all trampolines)
 - the trampoline list is hardcoded, it will remain so until `trampoline_routing_opt` feature flag is in INIT.
 - there are currently only two nodes in the hardcoded list, it would be nice to have more.
 - similar to Phoenix, we find the fee/cltv by trial-and-error.
    - if there is a second trampoline in the path, we use the same fee for both.
    - the final spec should add fee info in error messages, so we will be able to fine-tune fees
This commit is contained in:
ThomasV
2020-11-11 11:03:31 +01:00
parent f4fe80dfd1
commit ded449233e
19 changed files with 541 additions and 107 deletions

View File

@@ -145,6 +145,17 @@ class ChannelsList(MyTreeView):
self.main_window.show_message('success')
WaitingDialog(self, 'please wait..', task, on_success, self.on_failure)
def freeze_channel_for_sending(self, chan, b):
if self.lnworker.channel_db or self.lnworker.is_trampoline_peer(chan.node_id):
chan.set_frozen_for_sending(b)
else:
msg = ' '.join([
_("Trampoline routing is enabled, but this channel is with a non-trampoline node."),
_("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."),
])
self.main_window.show_warning(msg, title=_('Channel is frozen for sending'))
def create_menu(self, position):
menu = QMenu()
menu.setSeparatorsCollapsible(True) # consecutive separators are merged together
@@ -177,9 +188,9 @@ class ChannelsList(MyTreeView):
channel_id.hex(), title=_("Long Channel ID")))
if not chan.is_closed():
if not chan.is_frozen_for_sending():
menu.addAction(_("Freeze (for sending)"), lambda: chan.set_frozen_for_sending(True))
menu.addAction(_("Freeze (for sending)"), lambda: self.freeze_channel_for_sending(chan, True))
else:
menu.addAction(_("Unfreeze (for sending)"), lambda: chan.set_frozen_for_sending(False))
menu.addAction(_("Unfreeze (for sending)"), lambda: self.freeze_channel_for_sending(chan, False))
if not chan.is_frozen_for_receiving():
menu.addAction(_("Freeze (for receiving)"), lambda: chan.set_frozen_for_receiving(True))
else:
@@ -359,7 +370,7 @@ class ChannelsList(MyTreeView):
suggest_button = QPushButton(d, text=_('Suggest Peer'))
def on_suggest():
self.parent.wallet.network.start_gossip()
nodeid = bh2u(lnworker.lnrater.suggest_peer() or b'')
nodeid = bh2u(lnworker.suggest_peer() or b'')
if not nodeid:
remote_nodeid.setText("")
remote_nodeid.setPlaceholderText(

View File

@@ -742,7 +742,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
tools_menu.addAction(_("Electrum preferences"), self.settings_dialog)
tools_menu.addAction(_("&Network"), self.gui_object.show_network_dialog).setEnabled(bool(self.network))
tools_menu.addAction(_("&Lightning Network"), self.gui_object.show_lightning_dialog).setEnabled(bool(self.wallet.has_lightning() and self.network))
tools_menu.addAction(_("&Lightning Gossip"), self.gui_object.show_lightning_dialog).setEnabled(bool(self.wallet.has_lightning() and self.network))
tools_menu.addAction(_("Local &Watchtower"), self.gui_object.show_watchtower_dialog).setEnabled(bool(self.network and self.network.local_watchtower))
tools_menu.addAction(_("&Plugins"), self.plugins_dialog)
tools_menu.addSeparator()
@@ -2205,8 +2205,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
self.seed_button = StatusBarButton(read_QIcon("seed.png"), _("Seed"), self.show_seed_dialog )
sb.addPermanentWidget(self.seed_button)
self.lightning_button = None
if self.wallet.has_lightning() and self.network:
self.lightning_button = StatusBarButton(read_QIcon("lightning_disconnected.png"), _("Lightning Network"), self.gui_object.show_lightning_dialog)
if self.wallet.has_lightning():
self.lightning_button = StatusBarButton(read_QIcon("lightning.png"), _("Lightning Network"), self.gui_object.show_lightning_dialog)
self.update_lightning_icon()
sb.addPermanentWidget(self.lightning_button)
self.status_button = None
@@ -2247,10 +2247,10 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
if self.lightning_button is None:
return
if self.network.lngossip is None:
self.lightning_button.setVisible(False)
return
# display colorful lightning icon to signal connection
self.lightning_button.setIcon(read_QIcon("lightning.png"))
self.lightning_button.setVisible(True)
cur, total, progress_percent = self.network.lngossip.get_sync_progress_estimate()
# self.logger.debug(f"updating lngossip sync progress estimate: cur={cur}, total={total}")

View File

@@ -130,6 +130,24 @@ class SettingsDialog(WindowModalDialog):
# lightning
lightning_widgets = []
help_gossip = _("""If this option is enabled, Electrum will download the network
channels graph and compute payment path locally, instead of using trampoline payments. """)
gossip_cb = QCheckBox(_("Download network graph"))
gossip_cb.setToolTip(help_gossip)
gossip_cb.setChecked(bool(self.config.get('use_gossip', False)))
def on_gossip_checked(x):
use_gossip = bool(x)
self.config.set_key('use_gossip', use_gossip)
if use_gossip:
self.window.network.start_gossip()
else:
self.window.network.stop_gossip()
util.trigger_callback('ln_gossip_sync_progress')
# FIXME: update all wallet windows
util.trigger_callback('channels_updated', self.wallet)
gossip_cb.stateChanged.connect(on_gossip_checked)
lightning_widgets.append((gossip_cb, None))
help_local_wt = _("""If this option is checked, Electrum will
run a local watchtower and protect your channels even if your wallet is not
open. For this to work, your computer needs to be online regularly.""")