lightningd: delay dataloss error after channel_reestablish reply - #9563
daywalker90 wants to merge 2 commits into
Conversation
8d85a93 to
e421761
Compare
Andezion
left a comment
There was a problem hiding this comment.
before this change, a non cln peer (LND, LDK, Eclair) got our stale reestablish. The spec says it "SHOULD send an error and fail the channel", so it could force-close on that alone. Now it depends only on our error. Have you checked that the main implementations force close on an error for a channel when the channel_id matches?
LDK and eclair do, lnd does not |
test_dataloss_protection only exercises the reconnect rescue when the first ERROR loses the race with l1's channeld exiting, so the resend path itself is almost never tested. Drop l2's first WIRE_ERROR with dev-disconnect (as test_dataloss_protection_no_broadcast does), then reconnect: l2 must resend channel->error for l1 to drop to chain. xfail(strict) for now: l2 currently replies with a stale channel_reestablish before the canned error, l1's channeld exits on the stale reply (peer-in-the-past warning) without reading the error, and l1 never goes onchain. Changelog-None
e421761 to
fe7140a
Compare
|
Reworked the approach to no break force-close behaviour with lnd |
handle_peer_spoke() replies to channel_reestablish for a closed channel and then immediately sends that channel's canned error. We must keep the reestablish reply: LND's force-close on data loss is triggered by it (syncChanStates/ProcessChanSyncMsg sees our claimed tail is in the past and returns ErrCommitSyncRemoteDataLoss, which leads to LinkFailureForceClose), not by our error, which LND treats as non-permanent. LDK and Eclair do force-close on our error. Back-to-back, however, a CLN peer loses the error: its channeld warns and exits on our stale reestablish (peer-in-the-past revocation number), and the immediately-following error is fed to that dying channeld and discarded, so the peer never drops to chain. That is what flaked test_dataloss_protection after 946f700: when the first ERROR lost the race with the peer's channeld exiting, the reconnect rescue answered reestablish-then-error and hit the same loss, so l1.wait_for_channel_onchain() timed out: > l1.wait_for_channel_onchain(l2.info['id']) ValueError: Timeout while waiting for <lambda> Send the error (and any disconnect) shortly after the reestablish reply, like channeld's own sleep() before peer_failed_err(), so the peer's channeld has exited and lightningd handles the error via handle_peer_spoke() instead. Changelog-Fixed: Protocol: a peer reconnecting to a channel where we lost state now reliably force-closes it, instead of our error racing their channeld exiting.
fe7140a to
3e1e8fd
Compare
Fixes: #9519
Hopefully entirely this time.