chancloser: update RBF close to match current flow
What changed, and why it matters
This commit only updates a Markdown design document (rbf_close.md) describing how RBF (Replace-By-Fee) cooperative channel closes should handle MuSig2 nonces. It does not change any source code, cryptographic operations, network behavior, or state machine logic. The changes clarify documentation wording, add a table of helper functions, and correct file references. There is no security-relevant code change to assess.
No action required. This is a documentation-only commit. If the described ordering requirement is not actually implemented in the code, a separate code-level review of rbf_coop_transitions.go, rbf_coop_states.go, and peer/musig_chan_closer.go would be warranted, but that is outside the scope of this commit.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff modifies lnwallet/chancloser/rbf_close.md, a documentation file. It rewrites the ‘Implementation Notes for Nonce Handling’ section to distinguish closer vs. closee roles, adds a ‘Critical Ordering Requirement’ note about not rotating the NextCloseeNonce until after signature verification, adds a helper function reference table, and updates implementation file references from peer.go/channel.go to rbf_coop_transitions.go/rbf_coop_states.go and peer/musig_chan_closer.go. No executable code is changed.
Changed components
lnwallet/chancloser/rbf_close.mdInspect captured patch +34 / −7
diff --git a/lnwallet/chancloser/rbf_close.md b/lnwallet/chancloser/rbf_close.md
index 0a149a7..037bb58 100644
--- a/lnwallet/chancloser/rbf_close.md
+++ b/lnwallet/chancloser/rbf_close.md
@@ -322,21 +322,48 @@ For taproot channels:
### Implementation Notes for Nonce Handling
-The MuSig2 session's `InitRemoteNonce` method is called at two specific times:
-1. When processing the remote's `shutdown` message (to initialize with their
- closee nonce)
+The MuSig2 session's `InitRemoteNonce` method is called at specific times
+depending on our role:
-2. After receiving a `closing_sig` message that contains a `NextCloseeNonce`
- (for RBF iterations)
+**When we're the Closer (LocalMusigSession)**:
+1. During `ShutdownReceived`: Store their closee nonce in `NonceState.RemoteCloseeNonce`
+2. During `SendOfferEvent`: Call `initLocalMusigCloseeNonce` with stored closee nonce
+3. During `LocalSigReceived` (when receiving their ClosingSig):
+ - Use the CURRENT `NonceState.RemoteCloseeNonce` for signature verification
+ - AFTER verification succeeds, update with `NextCloseeNonce` for future RBF
+
+**When we're the Closee (RemoteMusigSession)**:
+1. Our closee nonce was sent in our `shutdown` message
+2. During `OfferReceivedEvent`: Receive their JIT closer nonce in `ClosingComplete`
+3. Call `initRemoteMusigCloserNonce` with their closer nonce before signing
+
+**Critical Ordering Requirement**: The `NextCloseeNonce` from `ClosingSig` must NOT
+be applied until AFTER the current signature verification completes. Premature
+rotation causes signature combination failure.
The nonce from `PartialSigWithNonce` in `closing_complete` is stored but not
immediately used with `InitRemoteNonce` - it's used when we need to sign as the
closee in the next round.
+### Helper Function Reference
+
+The following helper functions manage nonce initialization:
+
+| Function | Session | Sets | Called When |
+|----------|---------|------|-------------|
+| `initLocalMusigCloseeNonce` | LocalMusigSession | Remote's closee nonce | We're closer, preparing to sign |
+| `initRemoteMusigCloserNonce` | RemoteMusigSession | Remote's closer nonce | We're closee, received ClosingComplete |
+
+Note: The function names now correctly reflect what nonce is being set:
+- `initLocalMusigCloseeNonce`: Sets remote's **closee** nonce (from their shutdown)
+- `initRemoteMusigCloserNonce`: Sets remote's **closer** nonce (from their JIT nonce in ClosingComplete)
+
## Implementation Notes
-- This state machine is implemented in the `peer.go` and `channel.go` files
-within the lnd codebase
+- This state machine is implemented in `rbf_coop_transitions.go` and
+ `rbf_coop_states.go` within the `lnwallet/chancloser` package
+- The `MusigChanCloser` adapter in `peer/musig_chan_closer.go` implements the
+ `MusigSession` interface for managing MuSig2 nonces
- State transitions are logged at the debug level
- The `ChanCloser` interface manages the state machine execution
- Taproot support requires the `MusigSession` interface for nonce coordination
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.