1
0

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
This commit is contained in:
ThomasV
2025-03-17 09:01:04 +01:00
parent f8714dd57a
commit 58be5a3ad5
5 changed files with 29 additions and 14 deletions

View File

@@ -1245,6 +1245,8 @@ class Commands(Logger):
@command('wpnl') @command('wpnl')
async def open_channel(self, connection_string, amount, push_amount=0, public=False, zeroconf=False, password=None, wallet: Abstract_Wallet = None): 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) funding_sat = satoshis(amount)
push_sat = satoshis(push_amount) push_sat = satoshis(push_amount)
peer = await wallet.lnworker.add_peer(connection_string) peer = await wallet.lnworker.add_peer(connection_string)

View File

@@ -134,7 +134,7 @@ Pane {
FlatButton { FlatButton {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredWidth: 1 Layout.preferredWidth: 1
enabled: Daemon.currentWallet.confirmedBalance.satsInt > 0 enabled: Daemon.currentWallet.canHaveLightning && Daemon.currentWallet.confirmedBalance.satsInt > 0
text: qsTr('Open Channel') text: qsTr('Open Channel')
onClicked: { onClicked: {
if (Daemon.currentWallet.channelModel.count == 0) { if (Daemon.currentWallet.channelModel.count == 0) {

View File

@@ -368,7 +368,7 @@ class ChannelsList(MyTreeView):
# and maybe add item "main_window.init_lightning_dialog()" when applicable # and maybe add item "main_window.init_lightning_dialog()" when applicable
menu.setEnabled(self.wallet.has_lightning()) menu.setEnabled(self.wallet.has_lightning())
self.new_channel_button = EnterButton(_('New Channel'), self.main_window.new_channel_dialog) 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) toolbar.insertWidget(2, self.new_channel_button)
return toolbar return toolbar

View File

@@ -978,15 +978,20 @@ class Peer(Logger, EventListener):
Channel configurations are initialized in this method. 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 # will raise if init fails
await util.wait_for2(self.initialized, LN_P2P_NETWORK_TIMEOUT) await util.wait_for2(self.initialized, LN_P2P_NETWORK_TIMEOUT)
# trampoline is not yet in features # trampoline is not yet in features
if self.lnworker.uses_trampoline() and not self.lnworker.is_trampoline_peer(self.pubkey): if self.lnworker.uses_trampoline() and not self.lnworker.is_trampoline_peer(self.pubkey):
raise Exception('Not a trampoline node: ' + str(self.their_features)) 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 channel_flags = CF_ANNOUNCE_CHANNEL if public else 0
feerate = self.lnworker.current_target_feerate_per_kw() feerate = self.lnworker.current_target_feerate_per_kw()
# we set a channel type for internal bookkeeping # 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 # FIXME: we might want to keep the connection open
raise Exception('not accepting channels') 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'] funding_sat = payload['funding_satoshis']
push_msat = payload['push_msat'] push_msat = payload['push_msat']
feerate = payload['feerate_per_kw'] # note: we are not validating this feerate = payload['feerate_per_kw'] # note: we are not validating this

View File

@@ -520,17 +520,21 @@ class Abstract_Wallet(ABC, Logger, EventListener):
return self.config.ENABLE_ANCHOR_CHANNELS and self.has_channels() return self.config.ENABLE_ANCHOR_CHANNELS and self.has_channels()
def can_have_lightning(self) -> bool: def can_have_lightning(self) -> bool:
if self.config.ENABLE_ANCHOR_CHANNELS: """ whether this wallet can create new channels """
# this excludes hardware wallets, watching-only wallets # we want static_remotekey to be a wallet address
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:
if not self.txin_type == 'p2wpkh': if not self.txin_type == 'p2wpkh':
return False 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 False
return self.keystore.can_have_deterministic_lightning_xprv() return self.keystore.can_have_deterministic_lightning_xprv()