From e954bfaa54358a5f01de4bb290c2ff5a9c16c1d6 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Wed, 17 Mar 2021 15:29:47 +0100 Subject: [PATCH] request_force_close: close and reopen existing peer connection, because channel_reestablish cannot be sent twice in the same session --- electrum/lnchannel.py | 1 + electrum/lnpeer.py | 8 ++++++++ electrum/lnworker.py | 9 +++++---- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/electrum/lnchannel.py b/electrum/lnchannel.py index 1d9504df0..3fcd13ddc 100644 --- a/electrum/lnchannel.py +++ b/electrum/lnchannel.py @@ -542,6 +542,7 @@ class Channel(AbstractChannel): self._can_send_ctx_updates = True # type: bool self._receive_fail_reasons = {} # type: Dict[int, (bytes, OnionRoutingFailure)] self._ignore_max_htlc_value = False # used in tests + self.should_request_force_close = False def get_capacity(self): return self.constraints.capacity diff --git a/electrum/lnpeer.py b/electrum/lnpeer.py index bd4efa802..d392e6a45 100644 --- a/electrum/lnpeer.py +++ b/electrum/lnpeer.py @@ -897,6 +897,10 @@ class Peer(Logger): async def reestablish_channel(self, chan: Channel): await self.initialized chan_id = chan.channel_id + if chan.should_request_force_close: + await self.trigger_force_close(chan_id) + chan.should_request_force_close = False + return assert ChannelState.PREOPENING < chan.get_state() < ChannelState.FORCE_CLOSING if chan.peer_state != PeerState.DISCONNECTED: self.logger.info(f'reestablish_channel was called but channel {chan.get_id_for_log()} ' @@ -941,6 +945,10 @@ class Peer(Logger): except asyncio.TimeoutError: self.logger.info('waiting to receive channel_reestablish...') continue + except Exception as e: + # do not kill connection, because we might have other channels with that peer + self.logger.info(f'channel_reestablish failed, {e}') + return their_next_local_ctn = msg["next_commitment_number"] their_oldest_unrevoked_remote_ctn = msg["next_revocation_number"] their_local_pcp = msg.get("my_current_per_commitment_point") diff --git a/electrum/lnworker.py b/electrum/lnworker.py index cfb1d0384..933e5ae68 100644 --- a/electrum/lnworker.py +++ b/electrum/lnworker.py @@ -2012,14 +2012,15 @@ class LNWallet(LNWorker): return 'channel_backup:' + encrypted async def request_force_close(self, channel_id: bytes, *, connect_str=None) -> None: - if connect_str: - peer = await self.add_peer(connect_str) - await peer.trigger_force_close(channel_id) - elif channel_id in self.channels: + if channel_id in self.channels: chan = self.channels[channel_id] peer = self._peers.get(chan.node_id) if not peer: raise Exception('Peer not found') + chan.should_request_force_close = True + peer.close_and_cleanup() + elif connect_str: + peer = await self.add_peer(connect_str) await peer.trigger_force_close(channel_id) elif channel_id in self.channel_backups: await self.request_force_close_from_backup(channel_id)