@@ -16,12 +16,16 @@ import (
16
16
"github.com/btcsuite/btcwallet/wtxmgr"
17
17
"github.com/lightninglabs/lndclient"
18
18
"github.com/lightninglabs/loop/assets"
19
+ "github.com/lightninglabs/loop/assets/htlc"
19
20
"github.com/lightninglabs/loop/utils"
20
21
"github.com/lightninglabs/taproot-assets/address"
21
22
"github.com/lightninglabs/taproot-assets/asset"
22
23
"github.com/lightninglabs/taproot-assets/proof"
24
+ "github.com/lightninglabs/taproot-assets/tappsbt"
23
25
"github.com/lightninglabs/taproot-assets/taprpc"
26
+ "github.com/lightninglabs/taproot-assets/taprpc/assetwalletrpc"
24
27
"github.com/lightningnetwork/lnd/input"
28
+ "github.com/lightningnetwork/lnd/lntypes"
25
29
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
26
30
)
27
31
@@ -346,3 +350,68 @@ func getSigHash(tx *wire.MsgTx, idx int,
346
350
347
351
return sigHash , nil
348
352
}
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