[v0.21.x-branch] Backport #11163: htlcswitch: reconcile resumed forward replays - #11188
Conversation
|
Please cherry-pick the changes locally and resolve any conflicts. git fetch origin backport-11163-to-v0.21.x-branch
git worktree add --checkout .worktree/backport-11163-to-v0.21.x-branch backport-11163-to-v0.21.x-branch
cd .worktree/backport-11163-to-v0.21.x-branch
git reset --hard HEAD^
git cherry-pick -x bb916e5f9ddd855802fee998e94d47c8218946ff
git push --force-with-lease |
In this commit, we let the switch reconcile replayed adds whose incoming circuit has already been committed. Once the interceptor resumes a forward, the switch commits its incoming circuit and removes the packet from the held set. If the incoming link then replays that add before the return packet is committed, the packet can be offered to the interceptor a second time. The circuit map still distinguishes in-memory duplicates from circuits restored during recovery. Fresh packets continue through the normal interception path.
In this commit, we recognize held duplicates before applying the current-height expiry check. The original held forward keeps its resolution handle and auto-fail deadline. This prevents a near-expiry replay from failing upstream while the interceptor can still resume the outgoing HTLC. The regression test verifies that the original handle opens and settles exactly one circuit.
In this commit, we add the public PR to the 0.20.5 and 0.21.4 release notes. The note calls out that incoming-link replays are reconciled after the interceptor resumes a forward, so operators know the duplicate interception behavior is fixed.
06cd342 to
faa5163
Compare
Re-applied the backport cleanlyThe branch previously ended in a I also re-based onto the current What applied cleanly vs. what needed resolution
8 of 10 file-changes applied cleanly, and both conflicts are confined to Conflict 1 —
|
🔴 PR Severity: CRITICAL
🔴 Critical (1 file)
🟢 Low (6 files)
AnalysisThis is a backport of #11163 to To override, add a |
ziggie1984
left a comment
There was a problem hiding this comment.
LGTM (just release note conflicts to resolve)
Backport of #11163
Change Description
In this PR, we make resumed forward-interceptor HTLCs idempotent across
incoming-link replays.
Once an interceptor resumes a forward, the switch commits its incoming circuit
and removes the packet from the held set. If the incoming link restarts before
the return packet is committed, it can replay the add. Treating that replay as a
new intercepted forward can fail the incoming HTLC while the original outgoing
HTLC remains live.
For replayed adds that already have a circuit, we now pass the add back through
the switch and wait for the circuit map to classify it before releasing the
incoming link. Fresh adds and unresolved replays still use the asynchronous
interceptor path, so a blocked interceptor callback doesn't stall the link.
We also check the held set before applying the current-height expiry cutoff. A
held replay keeps the original resolution handle and auto-fail height instead of
making a second expiry decision.
Steps to Test
Run the focused forward-interceptor tests:
Run the package tests and vet with the development build tag:
go test -tags dev ./htlcswitch -count=1 go vet -tags dev ./htlcswitchRun the two replay regressions under the race detector:
Pull Request Checklist
Testing
Code Style and Documentation
lnclicommands.