@@ -428,6 +428,61 @@ func (a *AuxSweeper) signSweepVpackets(vPackets []*tappsbt.VPacket,
428428 return nil
429429}
430430
431+ // applySignDescToVIn couples a vPkt along with the input that contained it.
432+ type vPktsWithInput struct {
433+ // btcInput is the Bitcoin that the vPkt will the spending from (on the
434+ // TAP layer).
435+ btcInput input.Input
436+
437+ // vPkts is the set of vPacket that will be used to spend the input.
438+ vPkts []* tappsbt.VPacket
439+
440+ // tapsigDesc houses the information we'll need to re-sign the vPackets
441+ // above. Note that this is only set if this is a second level packet.
442+ tapSigDesc lfn.Option [cmsg.TapscriptSigDesc ]
443+ }
444+
445+ // sweepVpkts contains the set of vPkts needed for sweeping an output. Most
446+ // outputs will only have the first level specified. The second level is needed
447+ // for HTLC outputs on our local commitment transaction.
448+ type sweepVpkts struct {
449+ // firstLevel houses vPackets that are used to sweep outputs directly
450+ // from the commitment transaction.
451+ firstLevel []vPktsWithInput
452+
453+ // secondLevel is used to sweep outputs that are created by second level
454+ // HTLC transactions.
455+ secondLevel []vPktsWithInput
456+ }
457+
458+ // isEmpty returns true if the sweepVpkts is empty.
459+ func (s sweepVpkts ) isEmpty () bool {
460+ return len (s .firstLevel ) == 0 && len (s .secondLevel ) == 0
461+ }
462+
463+ // firstLevelPkts returns a slice of the first level pkts.
464+ func (s sweepVpkts ) firstLevelPkts () []* tappsbt.VPacket {
465+ return fn .FlatMap (
466+ s .firstLevel , func (v vPktsWithInput ) []* tappsbt.VPacket {
467+ return v .vPkts
468+ },
469+ )
470+ }
471+
472+ // secondLevelPkts returns a slice of the second level pkts.
473+ func (s sweepVpkts ) secondLevelPkts () []* tappsbt.VPacket {
474+ return fn .FlatMap (
475+ s .secondLevel , func (v vPktsWithInput ) []* tappsbt.VPacket {
476+ return v .vPkts
477+ },
478+ )
479+ }
480+
481+ // allPkts returns a slice of both the first and second level pkts.
482+ func (s sweepVpkts ) allPkts () []* tappsbt.VPacket {
483+ return append (s .firstLevelPkts (), s .secondLevelPkts ()... )
484+ }
485+
431486// createAndSignSweepVpackets creates vPackets that sweep the funds from the
432487// channel to the wallet, and then signs them as well.
433488func (a * AuxSweeper ) createAndSignSweepVpackets (
@@ -1837,40 +1892,119 @@ func newBlobWithWitnessInfo(i input.Input) lfn.Result[blobWithWitnessInfo] {
18371892 secondLevel : secondLevel ,
18381893 })
18391894}
1895+
1896+ // prepVpkts decodes the set of vPkts, supplementing them as needed to ensure
1897+ // all inputs can be swept properly.
1898+ func prepVpkts (bRes lfn.Result [blobWithWitnessInfo ],
1899+ secondLevel bool ) (* vPktsWithInput , error ) {
1900+
1901+ b , err := bRes .Unpack ()
1902+ if err != nil {
1903+ return nil , err
1904+ }
1905+ var res cmsg.ContractResolution
1906+
1907+ err = res .Decode (bytes .NewReader (b .resolutionBlob ))
1908+ if err != nil {
1909+ return nil , err
1910+ }
1911+
1912+ // For each vPacket, if we have a preimage to insert, then we'll we'll
1913+ // update the witness to insert the preimage at the correct index.
1914+ var tapSigDesc lfn.Option [cmsg.TapscriptSigDesc ]
1915+ pkts := res .Vpkts1 ()
1916+ if secondLevel {
1917+ pkts = res .Vpkts2 ()
1918+ }
1919+
1920+ b .preimageInfo .WhenSome (func (p preimageDesc ) {
1921+ vIns := fn .FlatMap (
1922+ pkts ,
1923+ func (vPkt * tappsbt.VPacket ) []* tappsbt.VInput {
1924+ return vPkt .Inputs
1925+ },
1926+ )
1927+
1928+ for _ , vIn := range vIns {
1929+ prevWitness := vIn .Asset ().PrevWitnesses [0 ].TxWitness
1930+ vIn .Asset ().PrevWitnesses [0 ].TxWitness = slices .Insert (
1931+ prevWitness , p .witnessIndex ,
1932+ p .preimage [:],
1933+ )
1934+ }
1935+ })
1936+
1937+ return & vPktsWithInput {
1938+ vPkts : pkts ,
1939+ btcInput : b .input ,
1940+ tapSigDesc : tapSigDesc ,
1941+ }, nil
18401942}
18411943
18421944// extractInputVPackets extracts the vPackets from the inputs passed in. If
18431945// none of the inputs have any resolution blobs. Then an empty slice will be
18441946// returned.
1845- func extractInputVPackets (inputs []input.Input ) lfn.Result [[]* tappsbt.VPacket ] {
18461947 // Otherwise, we'll extract the set of resolution blobs from the inputs
18471948 // passed in.
18481949 relevantInputs := fn .Filter (inputs , func (i input.Input ) bool {
18491950 return i .ResolutionBlob ().IsSome ()
18501951 })
1851- resolutionBlobs := fn .Map (relevantInputs , func (i input.Input ) tlv.Blob {
1852- // We already know this has a blob from the filter above.
1853- return i .ResolutionBlob ().UnwrapOr (nil )
1854- })
1952+ resolutionInfo := fn .Map (
1953+ relevantInputs ,
1954+ func (i input.Input ) lfn.Result [blobWithWitnessInfo ] {
1955+ return newBlobWithWitnessInfo (i )
1956+ },
1957+ )
18551958
1856- // With our set of resolution inputs extracted, we'll now decode them
1857- // in the vPackets we'll use to generate the output to addr.
1858- vPkts , err := fn .FlatMapErr (
1859- resolutionBlobs ,
1860- func (b tlv.Blob ) ([]* tappsbt.VPacket , error ) {
1861- var res cmsg.ContractResolution
1862- if err := res .Decode (bytes .NewReader (b )); err != nil {
1863- return nil , err
1864- }
1959+ firstLevelSweeps := lfn .Filter (
1960+ func (info lfn.Result [blobWithWitnessInfo ]) bool {
1961+ var secondLevel bool
1962+ info .WhenResult (func (i blobWithWitnessInfo ) {
1963+ secondLevel = i .secondLevel
1964+ })
18651965
1866- return res . VPkts (), nil
1966+ return ! secondLevel
18671967 },
1968+ resolutionInfo ,
18681969 )
1869- if err != nil {
1870- return lfn.Err [[]* tappsbt.VPacket ](err )
1970+ secondLevelSweeps := lfn .Filter (
1971+ func (info lfn.Result [blobWithWitnessInfo ]) bool {
1972+ var secondLevel bool
1973+ info .WhenResult (func (i blobWithWitnessInfo ) {
1974+ secondLevel = i .secondLevel
1975+ })
1976+
1977+ return secondLevel
1978+ },
1979+ resolutionInfo ,
1980+ )
1981+
1982+ // With our set of resolution inputs extracted, we'll now decode them in
1983+ // the vPackets we'll use to generate the output to addr.
1984+ var vPkts1 []vPktsWithInput
1985+ for _ , bRes := range firstLevelSweeps {
1986+ vpkt , err := prepVpkts (bRes , false )
1987+ if err != nil {
1988+ return lfn.Err [sweepVpkts ](err )
1989+ }
1990+
1991+ vPkts1 = append (vPkts1 , * vpkt )
1992+ }
1993+
1994+ var vPkts2 []vPktsWithInput
1995+ for _ , bRes := range secondLevelSweeps {
1996+ vpkt , err := prepVpkts (bRes , true )
1997+ if err != nil {
1998+ return lfn.Err [sweepVpkts ](err )
1999+ }
2000+
2001+ vPkts2 = append (vPkts1 , * vpkt )
18712002 }
18722003
1873- return lfn .Ok (vPkts )
2004+ return lfn .Ok (sweepVpkts {
2005+ firstLevel : vPkts1 ,
2006+ secondLevel : vPkts2 ,
2007+ })
18742008}
18752009
18762010// sweepContracts takes a set of inputs, and the change address we'd use to
@@ -1892,13 +2026,24 @@ func (a *AuxSweeper) sweepContracts(inputs []input.Input,
18922026
18932027 // Now that we know we have a relevant input set, extract all the
18942028 // vPackets from the inputs.
1895- vPkts , err := extractInputVPackets (inputs ).Unpack ()
2029+ sPkts , err := extractInputVPackets (inputs ).Unpack ()
18962030 if err != nil {
18972031 return lfn.Err [sweep.SweepOutput ](err )
18982032 }
18992033
19002034 log .Infof ("Generating anchor output for vpkts=%v" ,
1901- limitSpewer .Sdump (vPkts ))
2035+ limitSpewer .Sdump (sPkts ))
2036+
2037+ // Second level packets will already be anchored to the output assigned
2038+ // to it, so we only need to re-create the commitment for the first
2039+ // level outputs, which can be swept directly into the wallet.
2040+ firstLevelVpkts := sPkts .firstLevelPkts ()
2041+
2042+ // If there're no first level vPkts, then we can just return a nil error
2043+ // as we don't have a real sweep output to create.
2044+ if len (firstLevelVpkts ) == 0 {
2045+ return lfn.Err [sweep.SweepOutput ](nil )
2046+ }
19022047
19032048 // At this point, now that we're about to generate a new output, we'll
19042049 // need an internal key, so we can update all the vPkts.
@@ -1911,8 +2056,8 @@ func (a *AuxSweeper) sweepContracts(inputs []input.Input,
19112056 if err != nil {
19122057 return lfn.Err [sweep.SweepOutput ](err )
19132058 }
1914- for idx := range vPkts {
1915- for _ , vOut := range vPkts [idx ].Outputs {
2059+ for idx := range firstLevelVpkts {
2060+ for _ , vOut := range firstLevelVpkts [idx ].Outputs {
19162061 vOut .SetAnchorInternalKey (
19172062 internalKey , a .cfg .ChainParams .HDCoinType ,
19182063 )
@@ -1921,10 +2066,11 @@ func (a *AuxSweeper) sweepContracts(inputs []input.Input,
19212066
19222067 // Now that we have our set of resolutions, we'll make a new commitment
19232068 // out of all the vPackets contained.
1924- outCommitments , err := tapsend .CreateOutputCommitments (vPkts )
2069+ outCommitments , err := tapsend .CreateOutputCommitments (firstLevelVpkts )
19252070 if err != nil {
19262071 return lfn .Errf [sweep.SweepOutput ]("unable to create output " +
19272072 "commitments: %w" , err )
2073+
19282074 }
19292075
19302076 // We should only have a single output commitment at this point.
0 commit comments