mirror of
https://github.com/lightninglabs/loop.git
synced 2026-08-20 13:27:50 +02:00
We need the newer version of lndclient to get our synced to chain state. This requires changes to our test mock, so it is separated into a different commit. Since lndclient is expanding to be used in projects other than loop, the client interface is embedded in our mock rather than implementing functions we do not need. Functions that we already use in tests are updated accordingly. Note that while this commit bumps us to a version of lndclient that defaults to requiring lnd 0.11, we do not bump our required version yet because we are not using any new endpoints.
122 lines
3 KiB
Go
122 lines
3 KiB
Go
package sweep
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/btcsuite/btcd/btcec"
|
|
"github.com/btcsuite/btcd/txscript"
|
|
"github.com/btcsuite/btcd/wire"
|
|
"github.com/btcsuite/btcutil"
|
|
"github.com/lightninglabs/lndclient"
|
|
"github.com/lightninglabs/loop/swap"
|
|
"github.com/lightningnetwork/lnd/input"
|
|
"github.com/lightningnetwork/lnd/keychain"
|
|
)
|
|
|
|
// Sweeper creates htlc sweep txes.
|
|
type Sweeper struct {
|
|
Lnd *lndclient.LndServices
|
|
}
|
|
|
|
// CreateSweepTx creates an htlc sweep tx.
|
|
func (s *Sweeper) CreateSweepTx(
|
|
globalCtx context.Context, height int32,
|
|
htlc *swap.Htlc, htlcOutpoint wire.OutPoint,
|
|
keyBytes [33]byte,
|
|
witnessFunc func(sig []byte) (wire.TxWitness, error),
|
|
amount, fee btcutil.Amount,
|
|
destAddr btcutil.Address) (*wire.MsgTx, error) {
|
|
|
|
// Compose tx.
|
|
sweepTx := wire.NewMsgTx(2)
|
|
|
|
sweepTx.LockTime = uint32(height)
|
|
|
|
// Add HTLC input.
|
|
sweepTx.AddTxIn(&wire.TxIn{
|
|
PreviousOutPoint: htlcOutpoint,
|
|
SignatureScript: htlc.SigScript,
|
|
})
|
|
|
|
// Add output for the destination address.
|
|
sweepPkScript, err := txscript.PayToAddrScript(destAddr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
sweepTx.AddTxOut(&wire.TxOut{
|
|
PkScript: sweepPkScript,
|
|
Value: int64(amount - fee),
|
|
})
|
|
|
|
// Generate a signature for the swap htlc transaction.
|
|
|
|
key, err := btcec.ParsePubKey(keyBytes[:], btcec.S256())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
signDesc := lndclient.SignDescriptor{
|
|
WitnessScript: htlc.Script,
|
|
Output: &wire.TxOut{
|
|
Value: int64(amount),
|
|
},
|
|
HashType: txscript.SigHashAll,
|
|
InputIndex: 0,
|
|
KeyDesc: keychain.KeyDescriptor{
|
|
PubKey: key,
|
|
},
|
|
}
|
|
|
|
rawSigs, err := s.Lnd.Signer.SignOutputRaw(
|
|
globalCtx, sweepTx, []*lndclient.SignDescriptor{&signDesc},
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("signing: %v", err)
|
|
}
|
|
sig := rawSigs[0]
|
|
|
|
// Add witness stack to the tx input.
|
|
sweepTx.TxIn[0].Witness, err = witnessFunc(sig)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return sweepTx, nil
|
|
}
|
|
|
|
// GetSweepFee calculates the required tx fee to spend to P2WKH. It takes a
|
|
// function that is expected to add the weight of the input to the weight
|
|
// estimator.
|
|
func (s *Sweeper) GetSweepFee(ctx context.Context,
|
|
addInputEstimate func(*input.TxWeightEstimator),
|
|
destAddr btcutil.Address, sweepConfTarget int32) (
|
|
btcutil.Amount, error) {
|
|
|
|
// Get fee estimate from lnd.
|
|
feeRate, err := s.Lnd.WalletKit.EstimateFee(ctx, sweepConfTarget)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("estimate fee: %v", err)
|
|
}
|
|
|
|
// Calculate weight for this tx.
|
|
var weightEstimate input.TxWeightEstimator
|
|
switch destAddr.(type) {
|
|
case *btcutil.AddressWitnessScriptHash:
|
|
weightEstimate.AddP2WSHOutput()
|
|
case *btcutil.AddressWitnessPubKeyHash:
|
|
weightEstimate.AddP2WKHOutput()
|
|
case *btcutil.AddressScriptHash:
|
|
weightEstimate.AddP2SHOutput()
|
|
case *btcutil.AddressPubKeyHash:
|
|
weightEstimate.AddP2PKHOutput()
|
|
default:
|
|
return 0, fmt.Errorf("unknown address type %T", destAddr)
|
|
}
|
|
|
|
addInputEstimate(&weightEstimate)
|
|
weight := weightEstimate.Weight()
|
|
|
|
return feeRate.FeeForWeight(int64(weight)), nil
|
|
}
|