Browse Source

lnworker: add request_remote_force_close which can be used without state

see #6656
master
SomberNight 5 years ago
parent
commit
82c8c4280f
No known key found for this signature in database
GPG Key ID: B33B5F232C6271E9
  1. 3
      electrum/gui/qt/main_window.py
  2. 2
      electrum/lnpeer.py
  3. 28
      electrum/lnworker.py

3
electrum/gui/qt/main_window.py

@ -50,7 +50,7 @@ from PyQt5.QtWidgets import (QMessageBox, QComboBox, QSystemTrayIcon, QTabWidget
import electrum import electrum
from electrum import (keystore, ecc, constants, util, bitcoin, commands, from electrum import (keystore, ecc, constants, util, bitcoin, commands,
paymentrequest) paymentrequest, lnutil)
from electrum.bitcoin import COIN, is_address from electrum.bitcoin import COIN, is_address
from electrum.plugin import run_hook, BasePlugin from electrum.plugin import run_hook, BasePlugin
from electrum.i18n import _ from electrum.i18n import _
@ -2103,6 +2103,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
'daemon': self.gui_object.daemon, 'daemon': self.gui_object.daemon,
'util': util, 'util': util,
'bitcoin': bitcoin, 'bitcoin': bitcoin,
'lnutil': lnutil,
}) })
c = commands.Commands(config=self.config, c = commands.Commands(config=self.config,

2
electrum/lnpeer.py

@ -775,7 +775,7 @@ class Peer(Logger):
chan.set_state(ChannelState.OPENING) chan.set_state(ChannelState.OPENING)
self.lnworker.add_new_channel(chan) self.lnworker.add_new_channel(chan)
async def trigger_force_close(self, channel_id): async def trigger_force_close(self, channel_id: bytes):
await self.initialized await self.initialized
latest_point = secret_to_pubkey(42) # we need a valid point (BOLT2) latest_point = secret_to_pubkey(42) # we need a valid point (BOLT2)
self.send_message( self.send_message(

28
electrum/lnworker.py

@ -755,18 +755,18 @@ class LNWallet(LNWorker):
return {chan_id: chan for (chan_id, chan) in self.channels.items() return {chan_id: chan for (chan_id, chan) in self.channels.items()
if chan.node_id == node_id} if chan.node_id == node_id}
def channel_state_changed(self, chan): def channel_state_changed(self, chan: Channel):
self.save_channel(chan) self.save_channel(chan)
util.trigger_callback('channel', self.wallet, chan) util.trigger_callback('channel', self.wallet, chan)
def save_channel(self, chan): def save_channel(self, chan: Channel):
assert type(chan) is Channel assert type(chan) is Channel
if chan.config[REMOTE].next_per_commitment_point == chan.config[REMOTE].current_per_commitment_point: if chan.config[REMOTE].next_per_commitment_point == chan.config[REMOTE].current_per_commitment_point:
raise Exception("Tried to save channel with next_point == current_point, this should not happen") raise Exception("Tried to save channel with next_point == current_point, this should not happen")
self.wallet.save_db() self.wallet.save_db()
util.trigger_callback('channel', self.wallet, chan) util.trigger_callback('channel', self.wallet, chan)
def channel_by_txo(self, txo): def channel_by_txo(self, txo: str) -> Optional[Channel]:
for chan in self.channels.values(): for chan in self.channels.values():
if chan.funding_outpoint.to_str() == txo: if chan.funding_outpoint.to_str() == txo:
return chan return chan
@ -817,12 +817,12 @@ class LNWallet(LNWorker):
await self.network.try_broadcasting(funding_tx, 'open_channel') await self.network.try_broadcasting(funding_tx, 'open_channel')
return chan, funding_tx return chan, funding_tx
def add_channel(self, chan): def add_channel(self, chan: Channel):
with self.lock: with self.lock:
self._channels[chan.channel_id] = chan self._channels[chan.channel_id] = chan
self.lnwatcher.add_channel(chan.funding_outpoint.to_str(), chan.get_funding_address()) self.lnwatcher.add_channel(chan.funding_outpoint.to_str(), chan.get_funding_address())
def add_new_channel(self, chan): def add_new_channel(self, chan: Channel):
self.add_channel(chan) self.add_channel(chan)
channels_db = self.db.get_dict('channels') channels_db = self.db.get_dict('channels')
channels_db[chan.channel_id.hex()] = chan.storage channels_db[chan.channel_id.hex()] = chan.storage
@ -1464,6 +1464,22 @@ class LNWallet(LNWorker):
assert backup_bytes == pw_decode_with_version_and_mac(encrypted, xpub), "encrypt failed" assert backup_bytes == pw_decode_with_version_and_mac(encrypted, xpub), "encrypt failed"
return 'channel_backup:' + encrypted return 'channel_backup:' + encrypted
async def request_remote_force_close(
self, *, funding_txid: str, funding_index: int, connect_str: str,
):
"""
Requests the remote to force close a channel. Can be used without
having state or any backup for the channel.
Assumes that channel was originally opened with the same local peer (node_keypair).
Kept for console use.
Example:
network.run_from_another_thread(wallet.lnworker.request_remote_force_close(funding_txid="11a3b391bc99dbca0b2be4fdd8f18ca641896c81ae4d9596b30cbf1eef17af71", funding_index=1, connect_str="023a8dfe081c6bbd0504e599f33d39d17687de63023a8b20afcb59147d9d77c19d"))
"""
channel_id = lnutil.channel_id_from_funding_tx(funding_txid, funding_index)[0]
peer = await self.add_peer(connect_str)
await peer.trigger_force_close(channel_id)
class LNBackups(Logger): class LNBackups(Logger):
@ -1547,7 +1563,7 @@ class LNBackups(Logger):
util.trigger_callback('channels_updated', self.wallet) util.trigger_callback('channels_updated', self.wallet)
@log_exceptions @log_exceptions
async def request_force_close(self, channel_id): async def request_force_close(self, channel_id: bytes):
cb = self.channel_backups[channel_id].cb cb = self.channel_backups[channel_id].cb
# TODO also try network addresses from gossip db (as it might have changed) # TODO also try network addresses from gossip db (as it might have changed)
peer_addr = LNPeerAddr(cb.host, cb.port, cb.node_id) peer_addr = LNPeerAddr(cb.host, cb.port, cb.node_id)

Loading…
Cancel
Save