@@ -382,26 +382,37 @@ func (a *AuxSweeper) createAndSignSweepVpackets(
382382
383383// tapscriptSweepDesc is a helper struct that contains the tapscript tree and
384384// the control block needed to generate a valid spend.
385- //
386- // TODO(roasbeef): only needs the merkle root?
387385type tapscriptSweepDesc struct {
386+ auxSigInfo lfn.Option [lnwallet.AuxSigDesc ]
387+
388388 scriptTree input.TapscriptDescriptor
389389
390390 ctrlBlockBytes []byte
391391
392- relativeDelay fn.Option [uint64 ]
392+ relativeDelay lfn.Option [uint64 ]
393+
394+ absoluteDelay lfn.Option [uint64 ]
395+
396+ secondLevelSigIndex lfn.Option [uint32 ]
397+ }
398+
399+ // tapscriptSweepDescs contains the sweep decs for the first and second level.
400+ // Most outputs only go to the first level, but HTLCs on our local commitment
401+ // transaction go to the second level.
402+ type tapscriptSweepDescs struct {
403+ firstLevel tapscriptSweepDesc
393404
394- absoluteDelay fn .Option [uint64 ] //nolint:unused
405+ secondLevel lfn .Option [tapscriptSweepDesc ]
395406}
396407
397408// commitNoDelaySweepDesc creates a sweep desc for a commitment output that
398409// resides on the remote party's commitment transaction. This output is a
399410// non-delay output, so we don't need to worry about the CSV delay when
400411// sweeping it.
401412func commitNoDelaySweepDesc (keyRing * lnwallet.CommitmentKeyRing ,
402- csvDelay uint32 ) lfn.Result [tapscriptSweepDesc ] {
413+ csvDelay uint32 ) lfn.Result [tapscriptSweepDescs ] {
403414
404- type returnType = tapscriptSweepDesc
415+ type returnType = tapscriptSweepDescs
405416
406417 // We'll make the script tree for the to remote script (we're remote as
407418 // this is their commitment transaction). We don't have an auxLeaf here
@@ -410,8 +421,8 @@ func commitNoDelaySweepDesc(keyRing *lnwallet.CommitmentKeyRing,
410421 keyRing .ToRemoteKey , input .NoneTapLeaf (),
411422 )
412423 if err != nil {
413- return lfn .Errf [returnType ]("unable to make remote script " +
414- "tree: %w" , err )
424+ return lfn .Errf [returnType ]("unable to make remote " +
425+ "script tree: %w" , err )
415426 }
416427
417428 // Now that we have the script tree, we'll make the control block
@@ -420,29 +431,29 @@ func commitNoDelaySweepDesc(keyRing *lnwallet.CommitmentKeyRing,
420431 input .ScriptPathSuccess ,
421432 )
422433 if err != nil {
423- return lfn .Errf [returnType ]("unable to make ctrl block: %w" ,
424- err )
425434 }
426435 ctrlBlockBytes , err := ctrlBlock .ToBytes ()
427436 if err != nil {
428- return lfn .Errf [returnType ]("unable to encode ctrl block: %w" ,
429- err )
437+ return lfn .Errf [returnType ]("unable to encode ctrl " +
438+ "block: %w" , err )
430439 }
431440
432- return lfn .Ok (tapscriptSweepDesc {
433- scriptTree : toRemoteScriptTree ,
434- relativeDelay : fn .Some (uint64 (csvDelay )),
435- ctrlBlockBytes : ctrlBlockBytes ,
441+ return lfn .Ok (tapscriptSweepDescs {
442+ firstLevel : tapscriptSweepDesc {
443+ scriptTree : toRemoteScriptTree ,
444+ relativeDelay : lfn .Some (uint64 (csvDelay )),
445+ ctrlBlockBytes : ctrlBlockBytes ,
446+ },
436447 })
437448}
438449
439450// commitDelaySweepDesc creates a sweep desc for a commitment output that
440451// resides on our local commitment transaction. This output is a delay output,
441452// so we need to mind the CSV delay when sweeping it.
442453func commitDelaySweepDesc (keyRing * lnwallet.CommitmentKeyRing ,
443- csvDelay uint32 ) lfn.Result [tapscriptSweepDesc ] {
454+ csvDelay uint32 ) lfn.Result [tapscriptSweepDescs ] {
444455
445- type returnType = tapscriptSweepDesc
456+ type returnType = tapscriptSweepDescs
446457
447458 // We'll make the script tree for the to remote script (we're remote as
448459 // this is their commitment transaction). We don't have an auxLeaf here
@@ -461,27 +472,28 @@ func commitDelaySweepDesc(keyRing *lnwallet.CommitmentKeyRing,
461472 input .ScriptPathSuccess ,
462473 )
463474 if err != nil {
464- return lfn.Err [returnType ](err )
465475 }
466476 ctrlBlockBytes , err := ctrlBlock .ToBytes ()
467477 if err != nil {
468478 return lfn.Err [returnType ](err )
469479 }
470480
471- return lfn .Ok (tapscriptSweepDesc {
472- scriptTree : toLocalScriptTree ,
473- relativeDelay : fn .Some (uint64 (csvDelay )),
474- ctrlBlockBytes : ctrlBlockBytes ,
481+ return lfn .Ok (tapscriptSweepDescs {
482+ firstLevel : tapscriptSweepDesc {
483+ scriptTree : toLocalScriptTree ,
484+ relativeDelay : lfn .Some (uint64 (csvDelay )),
485+ ctrlBlockBytes : ctrlBlockBytes ,
486+ },
475487 })
476488}
477489
478490// commitRevokeSweepDesc creates a sweep desc for a commitment output that is
479491// the local output on the remote party's commitment transaction. We can seep
480492// this in the case of a revoked commitment.
481493func commitRevokeSweepDesc (keyRing * lnwallet.CommitmentKeyRing ,
482- csvDelay uint32 ) lfn.Result [tapscriptSweepDesc ] {
494+ csvDelay uint32 ) lfn.Result [tapscriptSweepDescs ] {
483495
484- type returnType = tapscriptSweepDesc
496+ type returnType = tapscriptSweepDescs
485497
486498 // To sweep their revoked output, we'll make the script tree for the
487499 // local tree of their commitment transaction, which is actually their
@@ -504,12 +516,14 @@ func commitRevokeSweepDesc(keyRing *lnwallet.CommitmentKeyRing,
504516 }
505517 ctrlBlockBytes , err := ctrlBlock .ToBytes ()
506518 if err != nil {
507- return lfn.Err [returnType ](err )
519+ return lfn.Err [tapscriptSweepDescs ](err )
508520 }
509521
510- return lfn .Ok (tapscriptSweepDesc {
511- scriptTree : toLocalScriptTree ,
512- ctrlBlockBytes : ctrlBlockBytes ,
522+ return lfn .Ok (tapscriptSweepDescs {
523+ firstLevel : tapscriptSweepDesc {
524+ scriptTree : toLocalScriptTree ,
525+ ctrlBlockBytes : ctrlBlockBytes ,
526+ },
513527 })
514528}
515529
@@ -1159,7 +1173,7 @@ func (a *AuxSweeper) resolveContract(
11591173 }
11601174
11611175 var (
1162- sweepDesc lfn.Result [tapscriptSweepDesc ]
1176+ sweepDesc lfn.Result [tapscriptSweepDescs ]
11631177 assetOutputs []* cmsg.AssetOutput
11641178 )
11651179
@@ -1192,13 +1206,13 @@ func (a *AuxSweeper) resolveContract(
11921206 // The remote party has breached the channel. We'll sweep the revoked
11931207 // key that we learned in the past.
11941208 case input .TaprootCommitmentRevoke :
1195- // In this case, we'll be sweeping the remote party's asset
11961209 // outputs, as they broadcast a revoked commitment. For the
1210+ // In this case, we'll be sweeping the remote party's asset
11971211 // remote party, this is actually their local output.
11981212 assetOutputs = commitState .LocalAssets .Val .Outputs
11991213
1200- // As we have multiple outputs to sweep above, we'll also have
1201- // two sweep descs .
1214+ // Next, we'll make a sweep desk capable of sweeping the remote
1215+ // party's local output .
12021216 sweepDesc = commitRevokeSweepDesc (req .KeyRing , req .CsvDelay )
12031217
12041218 default :
@@ -1216,10 +1230,17 @@ func (a *AuxSweeper) resolveContract(
12161230 log .Infof ("Sweeping %v asset outputs: %v" , len (assetOutputs ),
12171231 limitSpewer .Sdump (assetOutputs ))
12181232
1233+ firstLevelSweepDesc := lfn .AndThen (
1234+ sweepDesc ,
1235+ func (sweepDesc tapscriptSweepDescs ) lfn.Result [tapscriptSweepDesc ] { //nolint:lll
1236+ return lfn .Ok (sweepDesc .firstLevel )
1237+ },
1238+ )
1239+
12191240 // With the sweep desc constructed above, we'll create vPackets for
12201241 // each of the local assets, then sign them all.
12211242 sPkts := a .createAndSignSweepVpackets (
1222- assetOutputs , req .SignDesc , sweepDesc ,
1243+ assetOutputs , req .SignDesc , firstLevelSweepDesc ,
12231244 )
12241245
12251246 // With the vPackets fully generated and signed above, we'll serialize
0 commit comments