From 58be5a3ad5d4296f33eb2fe29846acb24f7aeb38 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Mon, 17 Mar 2025 09:01:04 +0100 Subject: [PATCH] Allow wallets to use non-deterministic lightning, if they use a software keystore. This excludes hardware wallets and watching-only wallet. Also, this forbids creation of new channels in those wallets, in case lightning was previously enabled. Fixes #9440 --- electrum/commands.py | 2 ++ electrum/gui/qml/components/Channels.qml | 2 +- electrum/gui/qt/channels_list.py | 2 +- electrum/lnpeer.py | 15 ++++++++++++--- electrum/wallet.py | 22 +++++++++++++--------- 5 files changed, 29 insertions(+), 14 deletions(-) diff --git a/electrum/commands.py b/electrum/commands.py index bd8848d90..e7f289a70 100644 --- a/electrum/commands.py +++ b/electrum/commands.py @@ -1245,6 +1245,8 @@ class Commands(Logger): @command('wpnl') async def open_channel(self, connection_string, amount, push_amount=0, public=False, zeroconf=False, password=None, wallet: Abstract_Wallet = None): + if not wallet.can_have_lightning(): + raise UserFacingException("This wallet cannot create new channels") funding_sat = satoshis(amount) push_sat = satoshis(push_amount) peer = await wallet.lnworker.add_peer(connection_string) diff --git a/electrum/gui/qml/components/Channels.qml b/electrum/gui/qml/components/Channels.qml index a240bb445..4369c8fbc 100644 --- a/electrum/gui/qml/components/Channels.qml +++ b/electrum/gui/qml/components/Channels.qml @@ -134,7 +134,7 @@ Pane { FlatButton { Layout.fillWidth: true Layout.preferredWidth: 1 - enabled: Daemon.currentWallet.confirmedBalance.satsInt > 0 + enabled: Daemon.currentWallet.canHaveLightning && Daemon.currentWallet.confirmedBalance.satsInt > 0 text: qsTr('Open Channel') onClicked: { if (Daemon.currentWallet.channelModel.count == 0) { diff --git a/electrum/gui/qt/channels_list.py b/electrum/gui/qt/channels_list.py index 372132e4f..01b746896 100644 --- a/electrum/gui/qt/channels_list.py +++ b/electrum/gui/qt/channels_list.py @@ -368,7 +368,7 @@ class ChannelsList(MyTreeView): # and maybe add item "main_window.init_lightning_dialog()" when applicable menu.setEnabled(self.wallet.has_lightning()) self.new_channel_button = EnterButton(_('New Channel'), self.main_window.new_channel_dialog) - self.new_channel_button.setEnabled(self.wallet.has_lightning()) + self.new_channel_button.setEnabled(self.wallet.can_have_lightning()) toolbar.insertWidget(2, self.new_channel_button) return toolbar diff --git a/electrum/lnpeer.py b/electrum/lnpeer.py index 856d10e24..820d9b656 100644 --- a/electrum/lnpeer.py +++ b/electrum/lnpeer.py @@ -978,15 +978,20 @@ class Peer(Logger, EventListener): Channel configurations are initialized in this method. """ + + if public and not self.lnworker.config.EXPERIMENTAL_LN_FORWARD_PAYMENTS: + raise Exception('Cannot create public channels') + + if not self.lnworker.wallet.can_have_lightning(): + # old wallet that cannot have lightning anymore + raise Exception('This wallet cannot create new channels') + # will raise if init fails await util.wait_for2(self.initialized, LN_P2P_NETWORK_TIMEOUT) # trampoline is not yet in features if self.lnworker.uses_trampoline() and not self.lnworker.is_trampoline_peer(self.pubkey): raise Exception('Not a trampoline node: ' + str(self.their_features)) - if public and not self.lnworker.config.EXPERIMENTAL_LN_FORWARD_PAYMENTS: - raise Exception('Cannot create public channels') - channel_flags = CF_ANNOUNCE_CHANNEL if public else 0 feerate = self.lnworker.current_target_feerate_per_kw() # we set a channel type for internal bookkeeping @@ -1251,6 +1256,10 @@ class Peer(Logger, EventListener): # FIXME: we might want to keep the connection open raise Exception('not accepting channels') + if not self.lnworker.wallet.can_have_lightning(): + # old wallet that cannot have lightning anymore + raise Exception('This wallet does not accept new channels') + funding_sat = payload['funding_satoshis'] push_msat = payload['push_msat'] feerate = payload['feerate_per_kw'] # note: we are not validating this diff --git a/electrum/wallet.py b/electrum/wallet.py index e2b5a7468..53d8b6715 100644 --- a/electrum/wallet.py +++ b/electrum/wallet.py @@ -520,17 +520,21 @@ class Abstract_Wallet(ABC, Logger, EventListener): return self.config.ENABLE_ANCHOR_CHANNELS and self.has_channels() def can_have_lightning(self) -> bool: - if self.config.ENABLE_ANCHOR_CHANNELS: - # this excludes hardware wallets, watching-only wallets - return self.can_have_deterministic_lightning() - else: - # we want static_remotekey to be a wallet address - return self.txin_type == 'p2wpkh' - - def can_have_deterministic_lightning(self) -> bool: + """ whether this wallet can create new channels """ + # we want static_remotekey to be a wallet address if not self.txin_type == 'p2wpkh': return False - if not self.keystore: + if self.config.ENABLE_ANCHOR_CHANNELS: + # exclude watching-only wallets + if not self.keystore: + return False + # exclude hardware wallets + if not self.keystore.may_have_password(): + return False + return True + + def can_have_deterministic_lightning(self) -> bool: + if not self.can_have_lightning(): return False return self.keystore.can_have_deterministic_lightning_xprv()