Browse Source

lnworker.try_force_closing: changed to not be async (and renamed)

This is to ensure that the channel is "immediately" set to FORCE_CLOSING.
(previously it took at least one event loop iteration)
patch-4
SomberNight 3 years ago
parent
commit
556b98736e
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 6
      electrum/lnpeer.py
  2. 13
      electrum/lnworker.py
  3. 2
      electrum/tests/test_lnpeer.py

6
electrum/lnpeer.py

@ -1052,7 +1052,7 @@ class Peer(Logger):
fut.set_exception(RemoteMisbehaving("remote ahead of us"))
elif we_are_ahead:
self.logger.warning(f"channel_reestablish ({chan.get_id_for_log()}): we are ahead of remote! trying to force-close.")
asyncio.ensure_future(self.lnworker.try_force_closing(chan.channel_id))
self.lnworker.schedule_force_closing(chan.channel_id)
fut.set_exception(RemoteMisbehaving("we are ahead of remote"))
else:
# all good
@ -1382,7 +1382,7 @@ class Peer(Logger):
self.logger.info(f"on_update_fail_malformed_htlc. chan {chan.get_id_for_log()}. "
f"htlc_id {htlc_id}. failure_code={failure_code}")
if failure_code & OnionFailureCodeMetaFlag.BADONION == 0:
asyncio.ensure_future(self.lnworker.try_force_closing(chan.channel_id))
self.lnworker.schedule_force_closing(chan.channel_id)
raise RemoteMisbehaving(f"received update_fail_malformed_htlc with unexpected failure code: {failure_code}")
reason = OnionRoutingFailure(code=failure_code, data=payload["sha256_of_onion"])
chan.receive_fail_htlc(htlc_id, error_bytes=None, reason=reason)
@ -1404,7 +1404,7 @@ class Peer(Logger):
if chan.get_state() != ChannelState.OPEN:
raise RemoteMisbehaving(f"received update_add_htlc while chan.get_state() != OPEN. state was {chan.get_state()!r}")
if cltv_expiry > bitcoin.NLOCKTIME_BLOCKHEIGHT_MAX:
asyncio.ensure_future(self.lnworker.try_force_closing(chan.channel_id))
self.lnworker.schedule_force_closing(chan.channel_id)
raise RemoteMisbehaving(f"received update_add_htlc with cltv_expiry > BLOCKHEIGHT_MAX. value was {cltv_expiry}")
# add htlc
chan.receive_htlc(htlc, onion_packet)

13
electrum/lnworker.py

@ -966,7 +966,7 @@ class LNWallet(LNWorker):
if chan.get_state() == ChannelState.OPEN and chan.should_be_closed_due_to_expiring_htlcs(self.network.get_local_height()):
self.logger.info(f"force-closing due to expiring htlcs")
await self.try_force_closing(chan.channel_id)
await self.schedule_force_closing(chan.channel_id)
elif chan.get_state() == ChannelState.FUNDED:
peer = self._peers.get(chan.node_id)
@ -2109,16 +2109,21 @@ class LNWallet(LNWorker):
"""Force-close the channel. Network-related exceptions are propagated to the caller.
(automatic rebroadcasts will be scheduled)
"""
# note: as we are async, it can take a few event loop iterations between the caller
# "calling us" and us getting to run, and we only set the channel state now:
tx = self._force_close_channel(chan_id)
await self.network.broadcast_transaction(tx)
return tx.txid()
async def try_force_closing(self, chan_id: bytes) -> None:
"""Force-close the channel. Network-related exceptions are suppressed.
def schedule_force_closing(self, chan_id: bytes) -> 'asyncio.Task[None]':
"""Schedules a task to force-close the channel and returns it.
Network-related exceptions are suppressed.
(automatic rebroadcasts will be scheduled)
Note: this method is intentionally not async so that callers have a guarantee
that the channel state is set immediately.
"""
tx = self._force_close_channel(chan_id)
await self.network.try_broadcasting(tx, 'force-close')
return asyncio.create_task(self.network.try_broadcasting(tx, 'force-close'))
def remove_channel(self, chan_id):
chan = self.channels[chan_id]

2
electrum/tests/test_lnpeer.py

@ -231,7 +231,7 @@ class MockLNWallet(Logger, NetworkRetryManager[LNPeerAddr]):
pay_to_node = LNWallet.pay_to_node
pay_invoice = LNWallet.pay_invoice
force_close_channel = LNWallet.force_close_channel
try_force_closing = LNWallet.try_force_closing
schedule_force_closing = LNWallet.schedule_force_closing
get_first_timestamp = lambda self: 0
on_peer_successfully_established = LNWallet.on_peer_successfully_established
get_channel_by_id = LNWallet.get_channel_by_id

Loading…
Cancel
Save