@@ -16,12 +16,16 @@ import (
1616 "github.com/btcsuite/btcwallet/wtxmgr"
1717 "github.com/lightninglabs/lndclient"
1818 "github.com/lightninglabs/loop/assets"
19+ "github.com/lightninglabs/loop/assets/htlc"
1920 "github.com/lightninglabs/loop/utils"
2021 "github.com/lightninglabs/taproot-assets/address"
2122 "github.com/lightninglabs/taproot-assets/asset"
2223 "github.com/lightninglabs/taproot-assets/proof"
24+ "github.com/lightninglabs/taproot-assets/tappsbt"
2325 "github.com/lightninglabs/taproot-assets/taprpc"
26+ "github.com/lightninglabs/taproot-assets/taprpc/assetwalletrpc"
2427 "github.com/lightningnetwork/lnd/input"
28+ "github.com/lightningnetwork/lnd/lntypes"
2529 "github.com/lightningnetwork/lnd/lnwallet/chainfee"
2630)
2731
@@ -346,3 +350,68 @@ func getSigHash(tx *wire.MsgTx, idx int,
346350
347351 return sigHash , nil
348352}
353+
354+ // GetHTLC creates a new zero-fee HTLC packet to be able to partially sign it
355+ // and send it to the server for further processing.
356+ //
357+ // TODO(bhandras): add support for spending multiple deposits into the HTLC.
358+ func (s * Sweeper ) GetHTLC (ctx context.Context , deposit * Kit ,
359+ depositProof * proof.Proof , amount uint64 , hash lntypes.Hash ,
360+ csvExpiry uint32 ) (* htlc.SwapKit , * psbt.Packet , []* tappsbt.VPacket ,
361+ []* tappsbt.VPacket , * assetwalletrpc.CommitVirtualPsbtsResponse , error ) {
362+
363+ // Genearate the HTLC address that will be used to sweep the deposit to
364+ // in case the client is uncooperative.
365+ rpcHtlcAddr , swapKit , err := deposit .NewHtlcAddr (
366+ ctx , s .tapdClient , amount , hash , csvExpiry ,
367+ )
368+ if err != nil {
369+ return nil , nil , nil , nil , nil , fmt .Errorf ("unable to create " +
370+ "htlc addr: %v" , err )
371+ }
372+
373+ htlcAddr , err := address .DecodeAddress (
374+ rpcHtlcAddr .Encoded , & s .addressParams ,
375+ )
376+ if err != nil {
377+ return nil , nil , nil , nil , nil , err
378+ }
379+ htlcScriptKey := asset .NewScriptKey (& htlcAddr .ScriptKey )
380+
381+ // Now we can create the sweep vpacket that'd sweep the deposited
382+ // assets to the HTLC output.
383+ depositSpendVpkt , err := assets .CreateOpTrueSweepVpkt (
384+ ctx , []* proof.Proof {depositProof }, htlcScriptKey ,
385+ & htlcAddr .InternalKey , htlcAddr .TapscriptSibling ,
386+ & s .addressParams ,
387+ )
388+ if err != nil {
389+ return nil , nil , nil , nil , nil , fmt .Errorf ("unable to create " +
390+ "deposit spend vpacket: %v" , err )
391+ }
392+
393+ // By committing the virtual transaction to the BTC template we
394+ // created, our lnd node will fund the BTC level transaction with an
395+ // input to pay for the fees. We'll further add a change output to the
396+ // transaction that will be generated using the above key descriptor.
397+ feeRate := chainfee .SatPerVByte (0 )
398+
399+ // Use an empty lock ID, as we don't need to lock any UTXOs for this
400+ // operation.
401+ lockID := wtxmgr.LockID {}
402+
403+ htlcBtcPkt , activeAssets , passiveAssets , commitResp , err :=
404+ s .tapdClient .PrepareAndCommitVirtualPsbts (
405+ ctx , depositSpendVpkt , feeRate , nil ,
406+ s .addressParams .Params , nil , & lockID ,
407+ time .Duration (0 ),
408+ )
409+ if err != nil {
410+ return nil , nil , nil , nil , nil , fmt .Errorf ("deposit spend " +
411+ "HTLC prepare and commit failed: %v" , err )
412+ }
413+
414+ htlcBtcPkt .UnsignedTx .Version = 3
415+
416+ return swapKit , htlcBtcPkt , activeAssets , passiveAssets , commitResp , nil
417+ }
0 commit comments