@@ -178,6 +178,35 @@ The `CloseErr` state provides recovery paths when protocol violations occur:
178
178
179
179
Recovery typically involves restarting the negotiation with a new closing offer.
180
180
181
+ ### RBF Nonce Flow Example
182
+
183
+ Here's how nonces flow through an RBF cooperative close with taproot:
184
+
185
+ 1 . ** Initial Shutdown** :
186
+ - Alice sends ` shutdown ` with her closee nonce ` NA `
187
+ - Bob sends ` shutdown ` with his closee nonce ` NB `
188
+
189
+ 2 . ** First Close Attempt** (Alice as closer):
190
+ - Alice sends ` closing_complete ` :
191
+ - Uses Bob's nonce NB (from shutdown) to create her closer signature
192
+ - Includes ` PartialSigWithNonce ` with her next closee nonce ` NA2 `
193
+ - Bob sends ` closing_sig ` :
194
+ - Uses Alice's nonce NA (from shutdown) to create his closee signature
195
+ - Includes ` NextCloseeNonce ` with his next closee nonce ` NB2 `
196
+
197
+ 3 . ** RBF Iteration** (Bob as closer):
198
+ - Bob sends ` closing_complete ` :
199
+ - Uses Alice's nonce NA2 (from previous ` PartialSigWithNonce ` ) to create
200
+ his closer signature
201
+ - Includes ` PartialSigWithNonce ` with his next closee nonce ` NB3 `
202
+ - Alice sends ` closing_sig ` :
203
+ - Uses Bob's nonce NB2 (from previous ` NextCloseeNonce ` ) to create her
204
+ closee signature
205
+ - Includes ` NextCloseeNonce ` with her next closee nonce ` NA3 `
206
+
207
+ The pattern continues with each party using the nonce they received in the
208
+ previous round.
209
+
181
210
## Example Scenarios
182
211
183
212
### Standard Cooperative Close
@@ -211,9 +240,103 @@ Recovery typically involves restarting the negotiation with a new closing offer.
211
240
5 . When agreement is reached on new fees: ` ClosePending ` → ` CloseFin ` (via
212
241
` txn_confirmation ` )
213
242
243
+ ## Taproot Channel Support
244
+
245
+ ### MuSig2 Nonce Handling
246
+
247
+ For taproot channels, the cooperative close process requires coordination for
248
+ MuSig2 signature creation using a JIT (Just-In-Time) nonce pattern:
249
+
250
+ #### Nonce Exchange During Shutdown
251
+
252
+ For taproot channels using the modern RBF cooperative close flow:
253
+ - The ` shutdown ` message includes a single nonce field:
254
+ - ` shutdown_nonce ` (TLV type 8): The sender's "closee nonce" used when they
255
+ send ` closing_sig `
256
+ - This simplified approach works because nonces are sent JIT with signatures
257
+
258
+ #### JIT (Just-In-Time) Nonce Pattern
259
+
260
+ The protocol uses an asymmetric signature pattern for taproot channels that
261
+ optimizes nonce delivery:
262
+
263
+ ** Asymmetric Roles** :
264
+ - ** Closer** : The party proposing a fee (sends ` closing_complete ` )
265
+ - ** Closee** : The party accepting the fee (sends ` closing_sig ` )
266
+
267
+ ** ClosingComplete (from Closer)** :
268
+ - Uses ` PartialSigWithNonce ` (98 bytes total):
269
+ - The partial signature (32 bytes)
270
+ - The sender's next closee nonce (66 bytes)
271
+ - Bundles the nonce because the closee hasn't seen it yet
272
+ - TLV types 5, 6, 7 (distinct from non-taproot types 1, 2, 3)
273
+
274
+ ** ClosingSig (from Closee)** :
275
+ - Uses ` PartialSig ` (32 bytes) + separate ` NextCloseeNonce ` :
276
+ - The partial signature in TLV types 5, 6, 7
277
+ - The next closee nonce in TLV type 22 (66 bytes)
278
+ - Separates the nonce because the closer already knows the current nonce from
279
+ shutdown or previous ` PartialSigWithNonce `
280
+
281
+ This asymmetric pattern minimizes redundancy while ensuring both parties always
282
+ have the nonces they need for signing.
283
+
284
+ #### Nonce State Management
285
+
286
+ The state machine maintains a simplified ` NonceState ` structure with only 2 fields:
287
+ - ` LocalCloseeNonce ` : Our closee nonce sent in our shutdown message
288
+ - ` RemoteCloseeNonce ` : The peer's closee nonce from their shutdown message
289
+
290
+ The JIT pattern eliminates complex nonce rotation:
291
+ - New nonces arrive with signatures, not pre-generated
292
+ - Remote nonces are updated automatically from ` PartialSigWithNonce ` in
293
+ ` closing_complete `
294
+ - Local nonces are generated on-demand when creating signatures
295
+
296
+ ### Wire Message Extensions
297
+
298
+ The following messages have been extended with optional TLV fields for taproot:
299
+
300
+ ** shutdown** :
301
+ - Type 8: ` shutdown_nonce ` - Sender's closee nonce for cooperative close signing
302
+
303
+ ** closing_complete** :
304
+ - Types 5, 6, 7: ` PartialSigWithNonce ` - Partial signature with embedded next closee nonce
305
+ - Type 5: ` closer_no_closee ` (closer has output, closee is dust)
306
+ - Type 6: ` no_closer_closee ` (closer is dust, closee has output)
307
+ - Type 7: ` closer_and_closee ` (both have outputs)
308
+
309
+ ** closing_sig** :
310
+ - Types 5, 6, 7: ` PartialSig ` - Just the partial signature (32 bytes)
311
+ - Same TLV type meanings as above
312
+ - Type 22: ` NextCloseeNonce ` - Next closee nonce for RBF iterations (66 bytes)
313
+
314
+ ### Validation Requirements
315
+
316
+ For taproot channels:
317
+ - Shutdown messages MUST include the sender's closee nonce
318
+ - ClosingComplete messages MUST use PartialSigWithNonce (includes next nonce
319
+ bundled with signature)
320
+ - ClosingSig messages MUST use PartialSig with separate NextCloseeNonce field
321
+ - Terminal offers (final RBF attempts) MAY omit next nonces to signal finality
322
+
323
+ ### Implementation Notes for Nonce Handling
324
+
325
+ The MuSig2 session's ` InitRemoteNonce ` method is called at two specific times:
326
+ 1 . When processing the remote's ` shutdown ` message (to initialize with their
327
+ closee nonce)
328
+
329
+ 2 . After receiving a ` closing_sig ` message that contains a ` NextCloseeNonce `
330
+ (for RBF iterations)
331
+
332
+ The nonce from ` PartialSigWithNonce ` in ` closing_complete ` is stored but not
333
+ immediately used with ` InitRemoteNonce ` - it's used when we need to sign as the
334
+ closee in the next round.
335
+
214
336
## Implementation Notes
215
337
216
338
- This state machine is implemented in the ` peer.go ` and ` channel.go ` files
217
339
within the lnd codebase
218
340
- State transitions are logged at the debug level
219
341
- The ` ChanCloser ` interface manages the state machine execution
342
+ - Taproot support requires the ` MusigSession ` interface for nonce coordination
0 commit comments