@@ -430,6 +430,61 @@ func (a *AuxSweeper) signSweepVpackets(vPackets []*tappsbt.VPacket,
430430 return nil
431431}
432432
433+ // applySignDescToVIn couples a vPkt along with the input that contained it.
434+ type vPktsWithInput struct {
435+ // btcInput is the Bitcoin that the vPkt will the spending from (on the
436+ // TAP layer).
437+ btcInput input.Input
438+
439+ // vPkts is the set of vPacket that will be used to spend the input.
440+ vPkts []* tappsbt.VPacket
441+
442+ // tapsigDesc houses the information we'll need to re-sign the vPackets
443+ // above. Note that this is only set if this is a second level packet.
444+ tapSigDesc lfn.Option [cmsg.TapscriptSigDesc ]
445+ }
446+
447+ // sweepVpkts contains the set of vPkts needed for sweeping an output. Most
448+ // outputs will only have the first level specified. The second level is needed
449+ // for HTLC outputs on our local commitment transaction.
450+ type sweepVpkts struct {
451+ // firstLevel houses vPackets that are used to sweep outputs directly
452+ // from the commitment transaction.
453+ firstLevel []vPktsWithInput
454+
455+ // secondLevel is used to sweep outputs that are created by second level
456+ // HTLC transactions.
457+ secondLevel []vPktsWithInput
458+ }
459+
460+ // isEmpty returns true if the sweepVpkts is empty.
461+ func (s sweepVpkts ) isEmpty () bool {
462+ return len (s .firstLevel ) == 0 && len (s .secondLevel ) == 0
463+ }
464+
465+ // firstLevelPkts returns a slice of the first level pkts.
466+ func (s sweepVpkts ) firstLevelPkts () []* tappsbt.VPacket {
467+ return fn .FlatMap (
468+ s .firstLevel , func (v vPktsWithInput ) []* tappsbt.VPacket {
469+ return v .vPkts
470+ },
471+ )
472+ }
473+
474+ // secondLevelPkts returns a slice of the second level pkts.
475+ func (s sweepVpkts ) secondLevelPkts () []* tappsbt.VPacket {
476+ return fn .FlatMap (
477+ s .secondLevel , func (v vPktsWithInput ) []* tappsbt.VPacket {
478+ return v .vPkts
479+ },
480+ )
481+ }
482+
483+ // allPkts returns a slice of both the first and second level pkts.
484+ func (s sweepVpkts ) allPkts () []* tappsbt.VPacket {
485+ return append (s .firstLevelPkts (), s .secondLevelPkts ()... )
486+ }
487+
433488// createAndSignSweepVpackets creates vPackets that sweep the funds from the
434489// channel to the wallet, and then signs them as well.
435490func (a * AuxSweeper ) createAndSignSweepVpackets (
@@ -1847,42 +1902,122 @@ func newBlobWithWitnessInfo(i input.Input) lfn.Result[blobWithWitnessInfo] {
18471902 secondLevel : secondLevel ,
18481903 })
18491904}
1905+
1906+ // prepVpkts decodes the set of vPkts, supplementing them as needed to ensure
1907+ // all inputs can be swept properly.
1908+ func prepVpkts (bRes lfn.Result [blobWithWitnessInfo ],
1909+ secondLevel bool ) (* vPktsWithInput , error ) {
1910+
1911+ b , err := bRes .Unpack ()
1912+ if err != nil {
1913+ return nil , err
1914+ }
1915+ var res cmsg.ContractResolution
1916+
1917+ err = res .Decode (bytes .NewReader (b .resolutionBlob ))
1918+ if err != nil {
1919+ return nil , err
1920+ }
1921+
1922+ // For each vPacket, if we have a preimage to insert, then we'll we'll
1923+ // update the witness to insert the preimage at the correct index.
1924+ var tapSigDesc lfn.Option [cmsg.TapscriptSigDesc ]
1925+ pkts := res .Vpkts1 ()
1926+ if secondLevel {
1927+ pkts = res .Vpkts2 ()
1928+ }
1929+
1930+ b .preimageInfo .WhenSome (func (p preimageDesc ) {
1931+ vIns := fn .FlatMap (
1932+ pkts ,
1933+ func (vPkt * tappsbt.VPacket ) []* tappsbt.VInput {
1934+ return vPkt .Inputs
1935+ },
1936+ )
1937+
1938+ for _ , vIn := range vIns {
1939+ prevWitness := vIn .Asset ().PrevWitnesses [0 ].TxWitness
1940+ vIn .Asset ().PrevWitnesses [0 ].TxWitness = slices .Insert (
1941+ prevWitness , p .witnessIndex ,
1942+ p .preimage [:],
1943+ )
1944+ }
1945+ })
1946+
1947+ return & vPktsWithInput {
1948+ vPkts : pkts ,
1949+ btcInput : b .input ,
1950+ tapSigDesc : tapSigDesc ,
1951+ }, nil
18501952}
18511953
18521954// extractInputVPackets extracts the vPackets from the inputs passed in. If
18531955// none of the inputs have any resolution blobs. Then an empty slice will be
18541956// returned.
1855- func extractInputVPackets (inputs []input.Input ) lfn.Result [[] * tappsbt. VPacket ] {
1856- type returnType = [] * tappsbt. VPacket
1957+ func extractInputVPackets (inputs []input.Input ) lfn.Result [sweepVpkts ] {
1958+ type returnType = sweepVpkts
18571959
18581960 // Otherwise, we'll extract the set of resolution blobs from the inputs
18591961 // passed in.
18601962 relevantInputs := fn .Filter (inputs , func (i input.Input ) bool {
18611963 return i .ResolutionBlob ().IsSome ()
18621964 })
1863- resolutionBlobs := fn .Map (relevantInputs , func (i input.Input ) tlv.Blob {
1864- // We already know this has a blob from the filter above.
1865- return i .ResolutionBlob ().UnwrapOr (nil )
1866- })
1965+ resolutionInfo := fn .Map (
1966+ relevantInputs ,
1967+ func (i input.Input ) lfn.Result [blobWithWitnessInfo ] {
1968+ return newBlobWithWitnessInfo (i )
1969+ },
1970+ )
18671971
1868- // With our set of resolution inputs extracted, we'll now decode them
1869- // in the vPackets we'll use to generate the output to addr.
1870- vPkts , err := fn .FlatMapErr (
1871- resolutionBlobs ,
1872- func (b tlv.Blob ) ([]* tappsbt.VPacket , error ) {
1873- var res cmsg.ContractResolution
1874- if err := res .Decode (bytes .NewReader (b )); err != nil {
1875- return nil , err
1876- }
1972+ firstLevelSweeps := lfn .Filter (
1973+ func (info lfn.Result [blobWithWitnessInfo ]) bool {
1974+ var secondLevel bool
1975+ info .WhenResult (func (i blobWithWitnessInfo ) {
1976+ secondLevel = i .secondLevel
1977+ })
18771978
1878- return res . VPkts (), nil
1979+ return ! secondLevel
18791980 },
1981+ resolutionInfo ,
18801982 )
1881- if err != nil {
1882- return lfn.Err [returnType ](err )
1983+ secondLevelSweeps := lfn .Filter (
1984+ func (info lfn.Result [blobWithWitnessInfo ]) bool {
1985+ var secondLevel bool
1986+ info .WhenResult (func (i blobWithWitnessInfo ) {
1987+ secondLevel = i .secondLevel
1988+ })
1989+
1990+ return secondLevel
1991+ },
1992+ resolutionInfo ,
1993+ )
1994+
1995+ // With our set of resolution inputs extracted, we'll now decode them in
1996+ // the vPackets we'll use to generate the output to addr.
1997+ var vPkts1 []vPktsWithInput
1998+ for _ , bRes := range firstLevelSweeps {
1999+ vpkt , err := prepVpkts (bRes , false )
2000+ if err != nil {
2001+ return lfn.Err [sweepVpkts ](err )
2002+ }
2003+
2004+ vPkts1 = append (vPkts1 , * vpkt )
2005+ }
2006+
2007+ var vPkts2 []vPktsWithInput
2008+ for _ , bRes := range secondLevelSweeps {
2009+ vpkt , err := prepVpkts (bRes , true )
2010+ if err != nil {
2011+ return lfn.Err [sweepVpkts ](err )
2012+ }
2013+
2014+ vPkts2 = append (vPkts1 , * vpkt )
18832015 }
18842016
1885- return lfn .Ok (vPkts )
2017+ return lfn .Ok (sweepVpkts {
2018+ firstLevel : vPkts1 ,
2019+ secondLevel : vPkts2 ,
2020+ })
18862021}
18872022
18882023// sweepContracts takes a set of inputs, and the change address we'd use to
@@ -1906,13 +2041,24 @@ func (a *AuxSweeper) sweepContracts(inputs []input.Input,
19062041
19072042 // Now that we know we have a relevant input set, extract all the
19082043 // vPackets from the inputs.
1909- vPkts , err := extractInputVPackets (inputs ).Unpack ()
2044+ sPkts , err := extractInputVPackets (inputs ).Unpack ()
19102045 if err != nil {
19112046 return lfn.Err [returnType ](err )
19122047 }
19132048
19142049 log .Infof ("Generating anchor output for vpkts=%v" ,
1915- limitSpewer .Sdump (vPkts ))
2050+ limitSpewer .Sdump (sPkts ))
2051+
2052+ // Second level packets will already be anchored to the output assigned
2053+ // to it, so we only need to re-create the commitment for the first
2054+ // level outputs, which can be swept directly into the wallet.
2055+ firstLevelVpkts := sPkts .firstLevelPkts ()
2056+
2057+ // If there're no first level vPkts, then we can just return a nil error
2058+ // as we don't have a real sweep output to create.
2059+ if len (firstLevelVpkts ) == 0 {
2060+ return lfn.Err [sweep.SweepOutput ](nil )
2061+ }
19162062
19172063 // At this point, now that we're about to generate a new output, we'll
19182064 // need an internal key, so we can update all the vPkts.
@@ -1925,8 +2071,8 @@ func (a *AuxSweeper) sweepContracts(inputs []input.Input,
19252071 if err != nil {
19262072 return lfn.Err [returnType ](err )
19272073 }
1928- for idx := range vPkts {
1929- for _ , vOut := range vPkts [idx ].Outputs {
2074+ for idx := range firstLevelVpkts {
2075+ for _ , vOut := range firstLevelVpkts [idx ].Outputs {
19302076 vOut .SetAnchorInternalKey (
19312077 internalKey , a .cfg .ChainParams .HDCoinType ,
19322078 )
@@ -1935,7 +2081,7 @@ func (a *AuxSweeper) sweepContracts(inputs []input.Input,
19352081
19362082 // Now that we have our set of resolutions, we'll make a new commitment
19372083 // out of all the vPackets contained.
1938- outCommitments , err := tapsend .CreateOutputCommitments (vPkts )
2084+ outCommitments , err := tapsend .CreateOutputCommitments (firstLevelVpkts )
19392085 if err != nil {
19402086 return lfn .Errf [returnType ]("unable to create " +
19412087 "output commitments: %w" , err )
0 commit comments