mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-11-09 21:56:47 +01:00
chancloser: update RBF close documentation for taproot support
In this commit we, update the RBF cooperative close documentation to comprehensively cover the taproot channel closing flow. The documentation now explains the JIT nonce pattern, asymmetric signature roles, and the complete nonce exchange protocol for taproot channels. Key additions include detailed explanations of how nonces flow through the RBF process, the distinction between closer and closee roles, and the specific wire message extensions for PartialSigWithNonce and NextCloseeNonce fields. The documentation also covers validation requirements and implementation notes specific to taproot channels. This documentation provides a complete reference for understanding and implementing the enhanced taproot RBF cooperative close protocol.
This commit is contained in:
@@ -178,6 +178,35 @@ The `CloseErr` state provides recovery paths when protocol violations occur:
|
||||
|
||||
Recovery typically involves restarting the negotiation with a new closing offer.
|
||||
|
||||
### RBF Nonce Flow Example
|
||||
|
||||
Here's how nonces flow through an RBF cooperative close with taproot:
|
||||
|
||||
1. **Initial Shutdown**:
|
||||
- Alice sends `shutdown` with her closee nonce `NA`
|
||||
- Bob sends `shutdown` with his closee nonce `NB`
|
||||
|
||||
2. **First Close Attempt** (Alice as closer):
|
||||
- Alice sends `closing_complete`:
|
||||
- Uses Bob's nonce NB (from shutdown) to create her closer signature
|
||||
- Includes `PartialSigWithNonce` with her next closee nonce `NA2`
|
||||
- Bob sends `closing_sig`:
|
||||
- Uses Alice's nonce NA (from shutdown) to create his closee signature
|
||||
- Includes `NextCloseeNonce` with his next closee nonce `NB2`
|
||||
|
||||
3. **RBF Iteration** (Bob as closer):
|
||||
- Bob sends `closing_complete`:
|
||||
- Uses Alice's nonce NA2 (from previous `PartialSigWithNonce`) to create
|
||||
his closer signature
|
||||
- Includes `PartialSigWithNonce` with his next closee nonce `NB3`
|
||||
- Alice sends `closing_sig`:
|
||||
- Uses Bob's nonce NB2 (from previous `NextCloseeNonce`) to create her
|
||||
closee signature
|
||||
- Includes `NextCloseeNonce` with her next closee nonce `NA3`
|
||||
|
||||
The pattern continues with each party using the nonce they received in the
|
||||
previous round.
|
||||
|
||||
## Example Scenarios
|
||||
|
||||
### Standard Cooperative Close
|
||||
@@ -211,9 +240,103 @@ Recovery typically involves restarting the negotiation with a new closing offer.
|
||||
5. When agreement is reached on new fees: `ClosePending` → `CloseFin` (via
|
||||
`txn_confirmation`)
|
||||
|
||||
## Taproot Channel Support
|
||||
|
||||
### MuSig2 Nonce Handling
|
||||
|
||||
For taproot channels, the cooperative close process requires coordination for
|
||||
MuSig2 signature creation using a JIT (Just-In-Time) nonce pattern:
|
||||
|
||||
#### Nonce Exchange During Shutdown
|
||||
|
||||
For taproot channels using the modern RBF cooperative close flow:
|
||||
- The `shutdown` message includes a single nonce field:
|
||||
- `shutdown_nonce` (TLV type 8): The sender's "closee nonce" used when they
|
||||
send `closing_sig`
|
||||
- This simplified approach works because nonces are sent JIT with signatures
|
||||
|
||||
#### JIT (Just-In-Time) Nonce Pattern
|
||||
|
||||
The protocol uses an asymmetric signature pattern for taproot channels that
|
||||
optimizes nonce delivery:
|
||||
|
||||
**Asymmetric Roles**:
|
||||
- **Closer**: The party proposing a fee (sends `closing_complete`)
|
||||
- **Closee**: The party accepting the fee (sends `closing_sig`)
|
||||
|
||||
**ClosingComplete (from Closer)**:
|
||||
- Uses `PartialSigWithNonce` (98 bytes total):
|
||||
- The partial signature (32 bytes)
|
||||
- The sender's next closee nonce (66 bytes)
|
||||
- Bundles the nonce because the closee hasn't seen it yet
|
||||
- TLV types 5, 6, 7 (distinct from non-taproot types 1, 2, 3)
|
||||
|
||||
**ClosingSig (from Closee)**:
|
||||
- Uses `PartialSig` (32 bytes) + separate `NextCloseeNonce`:
|
||||
- The partial signature in TLV types 5, 6, 7
|
||||
- The next closee nonce in TLV type 22 (66 bytes)
|
||||
- Separates the nonce because the closer already knows the current nonce from
|
||||
shutdown or previous `PartialSigWithNonce`
|
||||
|
||||
This asymmetric pattern minimizes redundancy while ensuring both parties always
|
||||
have the nonces they need for signing.
|
||||
|
||||
#### Nonce State Management
|
||||
|
||||
The state machine maintains a simplified `NonceState` structure with only 2 fields:
|
||||
- `LocalCloseeNonce`: Our closee nonce sent in our shutdown message
|
||||
- `RemoteCloseeNonce`: The peer's closee nonce from their shutdown message
|
||||
|
||||
The JIT pattern eliminates complex nonce rotation:
|
||||
- New nonces arrive with signatures, not pre-generated
|
||||
- Remote nonces are updated automatically from `PartialSigWithNonce` in
|
||||
`closing_complete`
|
||||
- Local nonces are generated on-demand when creating signatures
|
||||
|
||||
### Wire Message Extensions
|
||||
|
||||
The following messages have been extended with optional TLV fields for taproot:
|
||||
|
||||
**shutdown**:
|
||||
- Type 8: `shutdown_nonce` - Sender's closee nonce for cooperative close signing
|
||||
|
||||
**closing_complete**:
|
||||
- Types 5, 6, 7: `PartialSigWithNonce` - Partial signature with embedded next closee nonce
|
||||
- Type 5: `closer_no_closee` (closer has output, closee is dust)
|
||||
- Type 6: `no_closer_closee` (closer is dust, closee has output)
|
||||
- Type 7: `closer_and_closee` (both have outputs)
|
||||
|
||||
**closing_sig**:
|
||||
- Types 5, 6, 7: `PartialSig` - Just the partial signature (32 bytes)
|
||||
- Same TLV type meanings as above
|
||||
- Type 22: `NextCloseeNonce` - Next closee nonce for RBF iterations (66 bytes)
|
||||
|
||||
### Validation Requirements
|
||||
|
||||
For taproot channels:
|
||||
- Shutdown messages MUST include the sender's closee nonce
|
||||
- ClosingComplete messages MUST use PartialSigWithNonce (includes next nonce
|
||||
bundled with signature)
|
||||
- ClosingSig messages MUST use PartialSig with separate NextCloseeNonce field
|
||||
- Terminal offers (final RBF attempts) MAY omit next nonces to signal finality
|
||||
|
||||
### 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)
|
||||
|
||||
2. After receiving a `closing_sig` message that contains a `NextCloseeNonce`
|
||||
(for RBF iterations)
|
||||
|
||||
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.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- This state machine is implemented in the `peer.go` and `channel.go` files
|
||||
within the lnd codebase
|
||||
- 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
|
||||
|
||||
Reference in New Issue
Block a user