@@ -1539,8 +1539,9 @@ func (a *AuxSweeper) resolveContract(
15391539 }
15401540
15411541 var (
1542- sweepDesc lfn.Result [tapscriptSweepDescs ]
1543- assetOutputs []* cmsg.AssetOutput
1542+ sweepDesc lfn.Result [tapscriptSweepDescs ]
1543+ assetOutputs []* cmsg.AssetOutput
1544+ needsSecondLevel bool
15441545 )
15451546
15461547 switch req .Type {
@@ -1649,6 +1650,8 @@ func (a *AuxSweeper) resolveContract(
16491650 // sweep desc.
16501651 sweepDesc = localHtlcTimeoutSweepDesc (req )
16511652
1653+ needsSecondLevel = true
1654+
16521655 // In this case, we've broadcast a commitment, with an incoming HTLC
16531656 // that we can sweep. We'll annotate the sweepDesc with the information
16541657 // needed to sweep both this output, as well as the second level
@@ -1663,6 +1666,8 @@ func (a *AuxSweeper) resolveContract(
16631666 // sweep desc.
16641667 sweepDesc = localHtlcSucessSweepDesc (req )
16651668
1669+ needsSecondLevel = true
1670+
16661671 default :
16671672 return lfn .Errf [returnType ]("unknown resolution type: %v" ,
16681673 req .Type )
@@ -1678,35 +1683,93 @@ func (a *AuxSweeper) resolveContract(
16781683 log .Infof ("Sweeping %v asset outputs: %v" , len (assetOutputs ),
16791684 limitSpewer .Sdump (assetOutputs ))
16801685
1681- firstLevelSweepDesc := lfn .AndThen (
1682- sweepDesc ,
1683- func (sweepDesc tapscriptSweepDescs ) lfn.Result [tapscriptSweepDesc ] { //nolint:lll
1684- return lfn .Ok (sweepDesc .firstLevel )
1685- },
1686- )
1686+ tapSweepDesc , err := sweepDesc .Unpack ()
1687+ if err != nil {
1688+ return lfn.Err [tlv.Blob ](err )
1689+ }
16871690
1688- // With the sweep desc constructed above, we'll create vPackets for
1689- // each of the local assets, then sign them all.
1690- sPkts := a .createAndSignSweepVpackets (
1691- assetOutputs , req , firstLevelSweepDesc ,
1691+ // With the sweep desc constructed above, we'll create vPackets for each
1692+ // of the local assets, then sign them all.
1693+ firstLevelPkts , err := a .createAndSignSweepVpackets (
1694+ assetOutputs , req , lfn .Ok (tapSweepDesc .firstLevel ),
1695+ ).Unpack ()
1696+ if err != nil {
1697+ return lfn.Err [tlv.Blob ](err )
1698+ }
1699+
1700+ var (
1701+ secondLevelPkts []* tappsbt.VPacket
1702+ secondLevelSigDesc lfn.Option [cmsg.TapscriptSigDesc ]
16921703 )
16931704
1694- // With the vPackets fully generated and signed above, we'll serialize
1695- // it into a resolution blob to return.
1696- return lfn .AndThen (
1697- sPkts , func (vPkts []* tappsbt.VPacket ) lfn.Result [tlv.Blob ] {
1698- res := cmsg .NewContractResolution (
1699- vPkts , nil , lfn .None [cmsg.TapscriptSigDesc ](),
1700- )
1705+ // We'll only need a set of second level packets if we're sweeping a set
1706+ // of HTLC outputs on the local party's commitment transaction.
1707+ if needsSecondLevel {
1708+ log .Infof ("Creating+signing 2nd level vPkts" )
1709+
1710+ // We'll make a place holder for the second level output based
1711+ // on the assetID+value tuple.
1712+ secondLevelInputs := []* cmsg.AssetOutput {cmsg .NewAssetOutput (
1713+ assetOutputs [0 ].AssetID .Val ,
1714+ assetOutputs [0 ].Amount .Val , assetOutputs [0 ].Proof .Val ,
1715+ )}
1716+
1717+ // Unlike the first level packets, we can't yet sign the second
1718+ // level packets yet, as we don't know what the sweeping
1719+ // transaction will look like. So we'll just create them.
1720+ secondLevelPkts , err = lfn .MapOption (
1721+ func (desc tapscriptSweepDesc ) lfn.Result [[]* tappsbt.VPacket ] { //nolint:lll
1722+ return a .createSweepVpackets (
1723+ secondLevelInputs , lfn .Ok (desc ), req ,
1724+ )
1725+ },
1726+ )(tapSweepDesc .secondLevel ).UnwrapOr (
1727+ lfn.Ok [[]* tappsbt.VPacket ](nil ),
1728+ ).Unpack ()
1729+ if err != nil {
1730+ return lfn .Errf [tlv.Blob ]("unable to make " +
1731+ "second level pkts: %w" , err )
1732+ }
1733+
1734+ // We'll update some of the details of the 2nd level pkt based
1735+ // on the first lvl packet created above (as we don't yet have
1736+ // the full proof for the first lvl packet above).
1737+ for pktIdx , vPkt := range secondLevelPkts {
1738+ prevAsset := firstLevelPkts [pktIdx ].Outputs [0 ].Asset
1739+
1740+ for inputIdx , vIn := range vPkt .Inputs {
1741+ //nolint:lll
1742+ prevScriptKey := prevAsset .ScriptKey
1743+ vIn .PrevID .ScriptKey = asset .ToSerialized (
1744+ prevScriptKey .PubKey ,
1745+ )
17011746
1702- var b bytes.Buffer
1703- if err := res .Encode (& b ); err != nil {
1704- return lfn.Err [returnType ](err )
1747+ vPkt .SetInputAsset (inputIdx , prevAsset )
17051748 }
1749+ }
17061750
1707- return lfn .Ok (b .Bytes ())
1708- },
1751+ // With the vPackets fully generated and signed above, we'll
1752+ // serialize it into a resolution blob to return.
1753+ secondLevelSigDesc = lfn .MapOption (
1754+ func (d tapscriptSweepDesc ) cmsg.TapscriptSigDesc {
1755+ return cmsg .NewTapscriptSigDesc (
1756+ d .scriptTree .TapTweak (),
1757+ d .ctrlBlockBytes ,
1758+ )
1759+ },
1760+ )(tapSweepDesc .secondLevel )
1761+ }
1762+
1763+ res := cmsg .NewContractResolution (
1764+ firstLevelPkts , secondLevelPkts , secondLevelSigDesc ,
17091765 )
1766+
1767+ var b bytes.Buffer
1768+ if err := res .Encode (& b ); err != nil {
1769+ return lfn.Err [tlv.Blob ](err )
1770+ }
1771+
1772+ return lfn .Ok (b .Bytes ())
17101773}
17111774
17121775// preimageDesc is a helper struct that contains the preimage and the witness
0 commit comments