multi: modify sweeper.CreateSweepTx to accept conf target, style changes

In this commit, we modify the newly introduced UtxoSweeper.CreateSweepTx
to accept the confirmation target as a param of the method rather than a
struct level variable. We do this as this allows each caller to decide
at sweep time, what the fee rate should be, rather than using a global
value that is meant to work in all scenarios. For example, anytime
we're sweeping an output with a CLTV lock that's has a dependant
transaction we need to sweep/cancel, we may require a higher fee rate
than a regular force close with a CSV output.
This commit is contained in:
Olaoluwa Osuntokun
2018-10-17 16:27:11 -07:00
parent 90fe860a3c
commit fc21bf091a
6 changed files with 93 additions and 71 deletions

View File

@@ -16,9 +16,9 @@ type Input interface {
// be generated in order to spend this output.
WitnessType() lnwallet.WitnessType
// SignDesc returns a reference to a spendable output's sign descriptor,
// which is used during signing to compute a valid witness that spends
// this output.
// SignDesc returns a reference to a spendable output's sign
// descriptor, which is used during signing to compute a valid witness
// that spends this output.
SignDesc() *lnwallet.SignDescriptor
// BuildWitness returns a valid witness allowing this output to be
@@ -41,8 +41,8 @@ type inputKit struct {
signDesc lnwallet.SignDescriptor
}
// OutPoint returns the breached output's identifier that is to be included as a
// transaction input.
// OutPoint returns the breached output's identifier that is to be included as
// a transaction input.
func (i *inputKit) OutPoint() *wire.OutPoint {
return &i.outpoint
}
@@ -67,8 +67,7 @@ type BaseInput struct {
// MakeBaseInput assembles a new BaseInput that can be used to construct a
// sweep transaction.
func MakeBaseInput(outpoint *wire.OutPoint,
witnessType lnwallet.WitnessType,
func MakeBaseInput(outpoint *wire.OutPoint, witnessType lnwallet.WitnessType,
signDescriptor *lnwallet.SignDescriptor) BaseInput {
return BaseInput{
@@ -82,8 +81,8 @@ func MakeBaseInput(outpoint *wire.OutPoint,
// BuildWitness computes a valid witness that allows us to spend from the
// breached output. It does so by generating the witness generation function,
// which is parameterized primarily by the witness type and sign descriptor. The
// method then returns the witness computed by invoking this function.
// which is parameterized primarily by the witness type and sign descriptor.
// The method then returns the witness computed by invoking this function.
func (bi *BaseInput) BuildWitness(signer lnwallet.Signer, txn *wire.MsgTx,
hashCache *txscript.TxSigHashes, txinIdx int) ([][]byte, error) {
@@ -102,8 +101,8 @@ func (bi *BaseInput) BlocksToMaturity() uint32 {
}
// HtlcSucceedInput constitutes a sweep input that needs a pre-image. The input
// is expected to reside on the commitment tx of the remote party and should not
// be a second level tx output.
// is expected to reside on the commitment tx of the remote party and should
// not be a second level tx output.
type HtlcSucceedInput struct {
inputKit
@@ -127,8 +126,8 @@ func MakeHtlcSucceedInput(outpoint *wire.OutPoint,
}
// BuildWitness computes a valid witness that allows us to spend from the
// breached output. For HtlcSpendInput it will need to make the preimage part of
// the witness.
// breached output. For HtlcSpendInput it will need to make the preimage part
// of the witness.
func (h *HtlcSucceedInput) BuildWitness(signer lnwallet.Signer, txn *wire.MsgTx,
hashCache *txscript.TxSigHashes, txinIdx int) ([][]byte, error) {
@@ -149,6 +148,7 @@ func (h *HtlcSucceedInput) BlocksToMaturity() uint32 {
return 0
}
// Add compile-time constraint ensuring input structs implement Input interface.
// Compile-time constraints to ensure each input struct implement the Input
// interface.
var _ Input = (*BaseInput)(nil)
var _ Input = (*HtlcSucceedInput)(nil)

View File

@@ -5,9 +5,9 @@ import (
"github.com/lightningnetwork/lnd/build"
)
// log is a logger that is initialized with no output filters. This
// means the package will not perform any logging by default until the caller
// requests it.
// log is a logger that is initialized with no output filters. This means the
// package will not perform any logging by default until the caller requests
// it.
var log btclog.Logger
// The default amount of logging is none.
@@ -15,15 +15,15 @@ func init() {
UseLogger(build.NewSubLogger("SWPR", nil))
}
// DisableLog disables all library log output. Logging output is disabled
// by default until UseLogger is called.
// DisableLog disables all library log output. Logging output is disabled by
// default until UseLogger is called.
func DisableLog() {
UseLogger(btclog.Disabled)
}
// UseLogger uses a specified Logger to output package logging info.
// This should be used in preference to SetLogWriter if the caller is also
// using btclog.
// UseLogger uses a specified Logger to output package logging info. This
// should be used in preference to SetLogWriter if the caller is also using
// btclog.
func UseLogger(logger btclog.Logger) {
log = logger
}

View File

@@ -8,30 +8,27 @@ import (
"github.com/lightningnetwork/lnd/lnwallet"
)
// UtxoSweeper provides the functionality to generate sweep txes. The plan is to
// extend UtxoSweeper in the future to also manage the actual sweeping process
// by itself.
// UtxoSweeper provides the functionality to generate sweep txes. The plan is
// to extend UtxoSweeper in the future to also manage the actual sweeping
// process by itself.
type UtxoSweeper struct {
cfg *UtxoSweeperConfig
}
// UtxoSweeperConfig contains dependencies of UtxoSweeper.
type UtxoSweeperConfig struct {
// GenSweepScript generates a P2WKH script belonging to the wallet where
// funds can be swept.
// GenSweepScript generates a P2WKH script belonging to the wallet
// where funds can be swept.
GenSweepScript func() ([]byte, error)
// Estimator is used when crafting sweep transactions to estimate the
// necessary fee relative to the expected size of the sweep transaction.
// necessary fee relative to the expected size of the sweep
// transaction.
Estimator lnwallet.FeeEstimator
// Signer is used by the sweeper to generate valid witnesses at the
// time the incubated outputs need to be spent.
Signer lnwallet.Signer
// ConfTarget specifies a target for the number of blocks until an
// initial confirmation.
ConfTarget uint32
}
// New returns a new UtxoSweeper instance.
@@ -45,18 +42,18 @@ func New(cfg *UtxoSweeperConfig) *UtxoSweeper {
// spends from them. This method also makes an accurate fee estimate before
// generating the required witnesses.
//
// The created transaction has a single output sending all the funds back to the
// source wallet, after accounting for the fee estimate.
// The created transaction has a single output sending all the funds back to
// the source wallet, after accounting for the fee estimate.
//
// The value of currentBlockHeight argument will be set as the tx locktime. This
// function assumes that all CLTV inputs will be unlocked after
// The value of currentBlockHeight argument will be set as the tx locktime.
// This function assumes that all CLTV inputs will be unlocked after
// currentBlockHeight. Reasons not to use the maximum of all actual CLTV expiry
// values of the inputs:
//
// - Make handling re-orgs easier.
// - Thwart future possible fee sniping attempts.
// - Make us blend in with the bitcoind wallet.
func (s *UtxoSweeper) CreateSweepTx(inputs []Input,
func (s *UtxoSweeper) CreateSweepTx(inputs []Input, confTarget uint32,
currentBlockHeight uint32) (*wire.MsgTx, error) {
// Generate the receiving script to which the funds will be swept.
@@ -66,7 +63,7 @@ func (s *UtxoSweeper) CreateSweepTx(inputs []Input,
}
// Using the txn weight estimate, compute the required txn fee.
feePerKw, err := s.cfg.Estimator.EstimateFeePerKW(s.cfg.ConfTarget)
feePerKw, err := s.cfg.Estimator.EstimateFeePerKW(confTarget)
if err != nil {
return nil, err
}
@@ -100,7 +97,6 @@ func (s *UtxoSweeper) CreateSweepTx(inputs []Input,
// Add all inputs to the sweep transaction. Ensure that for each
// csvInput, we set the sequence number properly.
for _, input := range inputs {
sweepTx.AddTxIn(&wire.TxIn{
PreviousOutPoint: *input.OutPoint(),
@@ -110,9 +106,10 @@ func (s *UtxoSweeper) CreateSweepTx(inputs []Input,
// Before signing the transaction, check to ensure that it meets some
// basic validity requirements.
// TODO(conner): add more control to sanity checks, allowing us to delay
// spending "problem" outputs, e.g. possibly batching with other classes
// if fees are too low.
//
// TODO(conner): add more control to sanity checks, allowing us to
// delay spending "problem" outputs, e.g. possibly batching with other
// classes if fees are too low.
btx := btcutil.NewTx(sweepTx)
if err := blockchain.CheckTransactionSanity(btx); err != nil {
return nil, err
@@ -149,13 +146,11 @@ func (s *UtxoSweeper) CreateSweepTx(inputs []Input,
// getWeightEstimate returns a weight estimate for the given inputs.
// Additionally, it returns counts for the number of csv and cltv inputs.
func (s *UtxoSweeper) getWeightEstimate(inputs []Input) ([]Input, int64, int, int) {
// Create a transaction which sweeps all the newly mature outputs into
// an output controlled by the wallet.
// We initialize a weight estimator so we can accurately asses the
// amount of fees we need to pay for this sweep transaction.
//
// TODO(roasbeef): can be more intelligent about buffering outputs to
// be more efficient on-chain.
var weightEstimate lnwallet.TxWeightEstimator
// Our sweep transaction will pay to a single segwit p2wkh address,
@@ -165,10 +160,10 @@ func (s *UtxoSweeper) getWeightEstimate(inputs []Input) ([]Input, int64, int, in
// For each output, use its witness type to determine the estimate
// weight of its witness, and add it to the proper set of spendable
// outputs.
csvCount := 0
cltvCount := 0
var sweepInputs []Input
var (
sweepInputs []Input
csvCount, cltvCount int
)
for i := range inputs {
input := inputs[i]