sweep: create new Input interface
This commit introduces a common interface for sweep inputs. It eliminates the type checking from UtxoSweeper. Also the formerly present Amount() getter is removed. It was redundant because this value is present in SignDesc().Output.Value as well.
This commit is contained in:
parent
4dab405623
commit
7d69df77ed
@ -824,9 +824,16 @@ func (bo *breachedOutput) BuildWitness(signer lnwallet.Signer, txn *wire.MsgTx,
|
|||||||
return bo.witnessFunc(txn, hashCache, txinIdx)
|
return bo.witnessFunc(txn, hashCache, txinIdx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add compile-time constraint ensuring breachedOutput implements
|
// BlocksToMaturity returns the relative timelock, as a number of blocks, that
|
||||||
// SpendableOutput.
|
// must be built on top of the confirmation height before the output can be
|
||||||
var _ sweep.SpendableOutput = (*breachedOutput)(nil)
|
// spent.
|
||||||
|
func (bo *breachedOutput) BlocksToMaturity() uint32 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add compile-time constraint ensuring breachedOutput implements the Input
|
||||||
|
// interface.
|
||||||
|
var _ sweep.Input = (*breachedOutput)(nil)
|
||||||
|
|
||||||
// retributionInfo encapsulates all the data needed to sweep all the contested
|
// retributionInfo encapsulates all the data needed to sweep all the contested
|
||||||
// funds within a channel whose contract has been breached by the prior
|
// funds within a channel whose contract has been breached by the prior
|
||||||
@ -937,13 +944,13 @@ func (b *breachArbiter) createJusticeTx(
|
|||||||
// outputs, while simultaneously computing the estimated weight of the
|
// outputs, while simultaneously computing the estimated weight of the
|
||||||
// transaction.
|
// transaction.
|
||||||
var (
|
var (
|
||||||
spendableOutputs []sweep.SpendableOutput
|
spendableOutputs []sweep.Input
|
||||||
weightEstimate lnwallet.TxWeightEstimator
|
weightEstimate lnwallet.TxWeightEstimator
|
||||||
)
|
)
|
||||||
|
|
||||||
// Allocate enough space to potentially hold each of the breached
|
// Allocate enough space to potentially hold each of the breached
|
||||||
// outputs in the retribution info.
|
// outputs in the retribution info.
|
||||||
spendableOutputs = make([]sweep.SpendableOutput, 0, len(r.breachedOutputs))
|
spendableOutputs = make([]sweep.Input, 0, len(r.breachedOutputs))
|
||||||
|
|
||||||
// The justice transaction we construct will be a segwit transaction
|
// The justice transaction we construct will be a segwit transaction
|
||||||
// that pays to a p2wkh output. Components such as the version,
|
// that pays to a p2wkh output. Components such as the version,
|
||||||
@ -997,7 +1004,7 @@ func (b *breachArbiter) createJusticeTx(
|
|||||||
// sweepSpendableOutputsTxn creates a signed transaction from a sequence of
|
// sweepSpendableOutputsTxn creates a signed transaction from a sequence of
|
||||||
// spendable outputs by sweeping the funds into a single p2wkh output.
|
// spendable outputs by sweeping the funds into a single p2wkh output.
|
||||||
func (b *breachArbiter) sweepSpendableOutputsTxn(txWeight int64,
|
func (b *breachArbiter) sweepSpendableOutputsTxn(txWeight int64,
|
||||||
inputs ...sweep.SpendableOutput) (*wire.MsgTx, error) {
|
inputs ...sweep.Input) (*wire.MsgTx, error) {
|
||||||
|
|
||||||
// First, we obtain a new public key script from the wallet which we'll
|
// First, we obtain a new public key script from the wallet which we'll
|
||||||
// sweep the funds to.
|
// sweep the funds to.
|
||||||
@ -1011,7 +1018,7 @@ func (b *breachArbiter) sweepSpendableOutputsTxn(txWeight int64,
|
|||||||
// Compute the total amount contained in the inputs.
|
// Compute the total amount contained in the inputs.
|
||||||
var totalAmt btcutil.Amount
|
var totalAmt btcutil.Amount
|
||||||
for _, input := range inputs {
|
for _, input := range inputs {
|
||||||
totalAmt += input.Amount()
|
totalAmt += btcutil.Amount(input.SignDesc().Output.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll actually attempt to target inclusion within the next two
|
// We'll actually attempt to target inclusion within the next two
|
||||||
@ -1059,7 +1066,7 @@ func (b *breachArbiter) sweepSpendableOutputsTxn(txWeight int64,
|
|||||||
// witness, and attaching it to the transaction. This function accepts
|
// witness, and attaching it to the transaction. This function accepts
|
||||||
// an integer index representing the intended txin index, and the
|
// an integer index representing the intended txin index, and the
|
||||||
// breached output from which it will spend.
|
// breached output from which it will spend.
|
||||||
addWitness := func(idx int, so sweep.SpendableOutput) error {
|
addWitness := func(idx int, so sweep.Input) error {
|
||||||
// First, we construct a valid witness for this outpoint and
|
// First, we construct a valid witness for this outpoint and
|
||||||
// transaction using the SpendableOutput's witness generation
|
// transaction using the SpendableOutput's witness generation
|
||||||
// function.
|
// function.
|
||||||
|
@ -3,16 +3,11 @@ package sweep
|
|||||||
import (
|
import (
|
||||||
"github.com/btcsuite/btcd/txscript"
|
"github.com/btcsuite/btcd/txscript"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SpendableOutput an interface which can be used by the breach arbiter to
|
// Input contains all data needed to construct a sweep tx input.
|
||||||
// construct a transaction spending from outputs we control.
|
type Input interface {
|
||||||
type SpendableOutput interface {
|
|
||||||
// Amount returns the number of satoshis contained within the output.
|
|
||||||
Amount() btcutil.Amount
|
|
||||||
|
|
||||||
// Outpoint returns the reference to the output being spent, used to
|
// Outpoint returns the reference to the output being spent, used to
|
||||||
// construct the corresponding transaction input.
|
// construct the corresponding transaction input.
|
||||||
OutPoint() *wire.OutPoint
|
OutPoint() *wire.OutPoint
|
||||||
@ -32,27 +27,73 @@ type SpendableOutput interface {
|
|||||||
BuildWitness(signer lnwallet.Signer, txn *wire.MsgTx,
|
BuildWitness(signer lnwallet.Signer, txn *wire.MsgTx,
|
||||||
hashCache *txscript.TxSigHashes,
|
hashCache *txscript.TxSigHashes,
|
||||||
txinIdx int) ([][]byte, error)
|
txinIdx int) ([][]byte, error)
|
||||||
}
|
|
||||||
|
|
||||||
// CsvSpendableOutput is a SpendableOutput that contains all of the information
|
|
||||||
// necessary to construct, sign, and sweep an output locked with a CSV delay.
|
|
||||||
type CsvSpendableOutput interface {
|
|
||||||
SpendableOutput
|
|
||||||
|
|
||||||
// ConfHeight returns the height at which this output was confirmed.
|
|
||||||
// A zero value indicates that the output has not been confirmed.
|
|
||||||
ConfHeight() uint32
|
|
||||||
|
|
||||||
// SetConfHeight marks the height at which the output is confirmed in
|
|
||||||
// the chain.
|
|
||||||
SetConfHeight(height uint32)
|
|
||||||
|
|
||||||
// BlocksToMaturity returns the relative timelock, as a number of
|
// BlocksToMaturity returns the relative timelock, as a number of
|
||||||
// blocks, that must be built on top of the confirmation height before
|
// blocks, that must be built on top of the confirmation height before
|
||||||
// the output can be spent.
|
// the output can be spent. For non-CSV locked inputs this is always
|
||||||
|
// zero.
|
||||||
BlocksToMaturity() uint32
|
BlocksToMaturity() uint32
|
||||||
|
|
||||||
// OriginChanPoint returns the outpoint of the channel from which this
|
|
||||||
// output is derived.
|
|
||||||
OriginChanPoint() *wire.OutPoint
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BaseInput contains all the information needed to sweep an output.
|
||||||
|
type BaseInput struct {
|
||||||
|
outpoint wire.OutPoint
|
||||||
|
witnessType lnwallet.WitnessType
|
||||||
|
signDesc lnwallet.SignDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeBaseInput assembles a new BaseInput that can be used to construct a
|
||||||
|
// sweep transaction.
|
||||||
|
func MakeBaseInput(outpoint *wire.OutPoint,
|
||||||
|
witnessType lnwallet.WitnessType,
|
||||||
|
signDescriptor *lnwallet.SignDescriptor) BaseInput {
|
||||||
|
|
||||||
|
return BaseInput{
|
||||||
|
outpoint: *outpoint,
|
||||||
|
witnessType: witnessType,
|
||||||
|
signDesc: *signDescriptor,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OutPoint returns the breached output's identifier that is to be included as a
|
||||||
|
// transaction input.
|
||||||
|
func (bi *BaseInput) OutPoint() *wire.OutPoint {
|
||||||
|
return &bi.outpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
// WitnessType returns the type of witness that must be generated to spend the
|
||||||
|
// breached output.
|
||||||
|
func (bi *BaseInput) WitnessType() lnwallet.WitnessType {
|
||||||
|
return bi.witnessType
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignDesc returns the breached output's SignDescriptor, which is used during
|
||||||
|
// signing to compute the witness.
|
||||||
|
func (bi *BaseInput) SignDesc() *lnwallet.SignDescriptor {
|
||||||
|
return &bi.signDesc
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
func (bi *BaseInput) BuildWitness(signer lnwallet.Signer, txn *wire.MsgTx,
|
||||||
|
hashCache *txscript.TxSigHashes, txinIdx int) ([][]byte, error) {
|
||||||
|
|
||||||
|
witnessFunc := bi.witnessType.GenWitnessFunc(
|
||||||
|
signer, bi.SignDesc(),
|
||||||
|
)
|
||||||
|
|
||||||
|
return witnessFunc(txn, hashCache, txinIdx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlocksToMaturity returns the relative timelock, as a number of blocks, that
|
||||||
|
// must be built on top of the confirmation height before the output can be
|
||||||
|
// spent. For non-CSV locked inputs this is always zero.
|
||||||
|
func (bi *BaseInput) BlocksToMaturity() uint32 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add compile-time constraint ensuring BaseInput implements
|
||||||
|
// SpendableOutput.
|
||||||
|
var _ Input = (*BaseInput)(nil)
|
||||||
|
@ -53,7 +53,7 @@ func New(cfg *UtxoSweeperConfig) *UtxoSweeper {
|
|||||||
// - Make handling re-orgs easier.
|
// - Make handling re-orgs easier.
|
||||||
// - Thwart future possible fee sniping attempts.
|
// - Thwart future possible fee sniping attempts.
|
||||||
// - Make us blend in with the bitcoind wallet.
|
// - Make us blend in with the bitcoind wallet.
|
||||||
func (s *UtxoSweeper) CreateSweepTx(inputs []CsvSpendableOutput,
|
func (s *UtxoSweeper) CreateSweepTx(inputs []Input,
|
||||||
currentBlockHeight uint32) (*wire.MsgTx, error) {
|
currentBlockHeight uint32) (*wire.MsgTx, error) {
|
||||||
|
|
||||||
// Create a transaction which sweeps all the newly mature outputs into
|
// Create a transaction which sweeps all the newly mature outputs into
|
||||||
@ -62,18 +62,7 @@ func (s *UtxoSweeper) CreateSweepTx(inputs []CsvSpendableOutput,
|
|||||||
// TODO(roasbeef): can be more intelligent about buffering outputs to
|
// TODO(roasbeef): can be more intelligent about buffering outputs to
|
||||||
// be more efficient on-chain.
|
// be more efficient on-chain.
|
||||||
|
|
||||||
// Assemble the inputs into a slice csv spendable outputs, and also a
|
var weightEstimate lnwallet.TxWeightEstimator
|
||||||
// set of regular spendable outputs. The set of regular outputs are CLTV
|
|
||||||
// locked outputs that have had their timelocks expire.
|
|
||||||
var (
|
|
||||||
csvOutputs []CsvSpendableOutput
|
|
||||||
cltvOutputs []SpendableOutput
|
|
||||||
weightEstimate lnwallet.TxWeightEstimator
|
|
||||||
)
|
|
||||||
|
|
||||||
// Allocate enough room for both types of outputs.
|
|
||||||
csvOutputs = make([]CsvSpendableOutput, 0, len(inputs))
|
|
||||||
cltvOutputs = make([]SpendableOutput, 0, len(inputs))
|
|
||||||
|
|
||||||
// Our sweep transaction will pay to a single segwit p2wkh address,
|
// Our sweep transaction will pay to a single segwit p2wkh address,
|
||||||
// ensure it contributes to our weight estimate.
|
// ensure it contributes to our weight estimate.
|
||||||
@ -82,6 +71,8 @@ func (s *UtxoSweeper) CreateSweepTx(inputs []CsvSpendableOutput,
|
|||||||
// For each output, use its witness type to determine the estimate
|
// For each output, use its witness type to determine the estimate
|
||||||
// weight of its witness, and add it to the proper set of spendable
|
// weight of its witness, and add it to the proper set of spendable
|
||||||
// outputs.
|
// outputs.
|
||||||
|
csvCount := 0
|
||||||
|
cltvCount := 0
|
||||||
for i := range inputs {
|
for i := range inputs {
|
||||||
input := inputs[i]
|
input := inputs[i]
|
||||||
|
|
||||||
@ -93,7 +84,7 @@ func (s *UtxoSweeper) CreateSweepTx(inputs []CsvSpendableOutput,
|
|||||||
weightEstimate.AddWitnessInput(
|
weightEstimate.AddWitnessInput(
|
||||||
lnwallet.ToLocalTimeoutWitnessSize,
|
lnwallet.ToLocalTimeoutWitnessSize,
|
||||||
)
|
)
|
||||||
csvOutputs = append(csvOutputs, input)
|
csvCount++
|
||||||
|
|
||||||
// Outgoing second layer HTLC's that have confirmed within the
|
// Outgoing second layer HTLC's that have confirmed within the
|
||||||
// chain, and the output they produced is now mature enough to
|
// chain, and the output they produced is now mature enough to
|
||||||
@ -102,7 +93,7 @@ func (s *UtxoSweeper) CreateSweepTx(inputs []CsvSpendableOutput,
|
|||||||
weightEstimate.AddWitnessInput(
|
weightEstimate.AddWitnessInput(
|
||||||
lnwallet.ToLocalTimeoutWitnessSize,
|
lnwallet.ToLocalTimeoutWitnessSize,
|
||||||
)
|
)
|
||||||
csvOutputs = append(csvOutputs, input)
|
csvCount++
|
||||||
|
|
||||||
// Incoming second layer HTLC's that have confirmed within the
|
// Incoming second layer HTLC's that have confirmed within the
|
||||||
// chain, and the output they produced is now mature enough to
|
// chain, and the output they produced is now mature enough to
|
||||||
@ -111,7 +102,7 @@ func (s *UtxoSweeper) CreateSweepTx(inputs []CsvSpendableOutput,
|
|||||||
weightEstimate.AddWitnessInput(
|
weightEstimate.AddWitnessInput(
|
||||||
lnwallet.ToLocalTimeoutWitnessSize,
|
lnwallet.ToLocalTimeoutWitnessSize,
|
||||||
)
|
)
|
||||||
csvOutputs = append(csvOutputs, input)
|
csvCount++
|
||||||
|
|
||||||
// An HTLC on the commitment transaction of the remote party,
|
// An HTLC on the commitment transaction of the remote party,
|
||||||
// that has had its absolute timelock expire.
|
// that has had its absolute timelock expire.
|
||||||
@ -119,9 +110,11 @@ func (s *UtxoSweeper) CreateSweepTx(inputs []CsvSpendableOutput,
|
|||||||
weightEstimate.AddWitnessInput(
|
weightEstimate.AddWitnessInput(
|
||||||
lnwallet.AcceptedHtlcTimeoutWitnessSize,
|
lnwallet.AcceptedHtlcTimeoutWitnessSize,
|
||||||
)
|
)
|
||||||
cltvOutputs = append(cltvOutputs, input)
|
cltvCount++
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
// TODO: Also add non-timelocked outputs
|
||||||
|
|
||||||
log.Warnf("kindergarten output in nursery store "+
|
log.Warnf("kindergarten output in nursery store "+
|
||||||
"contains unexpected witness type: %v",
|
"contains unexpected witness type: %v",
|
||||||
input.WitnessType())
|
input.WitnessType())
|
||||||
@ -129,11 +122,11 @@ func (s *UtxoSweeper) CreateSweepTx(inputs []CsvSpendableOutput,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Creating sweep transaction for %v CSV inputs, %v CLTV "+
|
log.Infof("Creating sweep transaction for %v inputs (%v CSV, %v CLTV)",
|
||||||
"inputs", len(csvOutputs), len(cltvOutputs))
|
csvCount+cltvCount, csvCount, cltvCount)
|
||||||
|
|
||||||
txWeight := int64(weightEstimate.Weight())
|
txWeight := int64(weightEstimate.Weight())
|
||||||
return s.populateSweepTx(txWeight, currentBlockHeight, csvOutputs, cltvOutputs)
|
return s.populateSweepTx(txWeight, currentBlockHeight, inputs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// populateSweepTx populate the final sweeping transaction with all witnesses
|
// populateSweepTx populate the final sweeping transaction with all witnesses
|
||||||
@ -141,8 +134,7 @@ func (s *UtxoSweeper) CreateSweepTx(inputs []CsvSpendableOutput,
|
|||||||
// has a single output sending all the funds back to the source wallet, after
|
// has a single output sending all the funds back to the source wallet, after
|
||||||
// accounting for the fee estimate.
|
// accounting for the fee estimate.
|
||||||
func (s *UtxoSweeper) populateSweepTx(txWeight int64, currentBlockHeight uint32,
|
func (s *UtxoSweeper) populateSweepTx(txWeight int64, currentBlockHeight uint32,
|
||||||
csvInputs []CsvSpendableOutput,
|
inputs []Input) (*wire.MsgTx, error) {
|
||||||
cltvInputs []SpendableOutput) (*wire.MsgTx, error) {
|
|
||||||
|
|
||||||
// Generate the receiving script to which the funds will be swept.
|
// Generate the receiving script to which the funds will be swept.
|
||||||
pkScript, err := s.cfg.GenSweepScript()
|
pkScript, err := s.cfg.GenSweepScript()
|
||||||
@ -152,11 +144,8 @@ func (s *UtxoSweeper) populateSweepTx(txWeight int64, currentBlockHeight uint32,
|
|||||||
|
|
||||||
// Sum up the total value contained in the inputs.
|
// Sum up the total value contained in the inputs.
|
||||||
var totalSum btcutil.Amount
|
var totalSum btcutil.Amount
|
||||||
for _, o := range csvInputs {
|
for _, o := range inputs {
|
||||||
totalSum += o.Amount()
|
totalSum += btcutil.Amount(o.SignDesc().Output.Value)
|
||||||
}
|
|
||||||
for _, o := range cltvInputs {
|
|
||||||
totalSum += o.Amount()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Using the txn weight estimate, compute the required txn fee.
|
// Using the txn weight estimate, compute the required txn fee.
|
||||||
@ -181,25 +170,16 @@ func (s *UtxoSweeper) populateSweepTx(txWeight int64, currentBlockHeight uint32,
|
|||||||
Value: sweepAmt,
|
Value: sweepAmt,
|
||||||
})
|
})
|
||||||
|
|
||||||
// We'll also ensure that the transaction has the required lock time if
|
sweepTx.LockTime = currentBlockHeight
|
||||||
// we're sweeping any cltvInputs.
|
|
||||||
if len(cltvInputs) > 0 {
|
|
||||||
sweepTx.LockTime = currentBlockHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all inputs to the sweep transaction. Ensure that for each
|
// Add all inputs to the sweep transaction. Ensure that for each
|
||||||
// csvInput, we set the sequence number properly.
|
// csvInput, we set the sequence number properly.
|
||||||
for _, input := range csvInputs {
|
for _, input := range inputs {
|
||||||
sweepTx.AddTxIn(&wire.TxIn{
|
sweepTx.AddTxIn(&wire.TxIn{
|
||||||
PreviousOutPoint: *input.OutPoint(),
|
PreviousOutPoint: *input.OutPoint(),
|
||||||
Sequence: input.BlocksToMaturity(),
|
Sequence: input.BlocksToMaturity(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
for _, input := range cltvInputs {
|
|
||||||
sweepTx.AddTxIn(&wire.TxIn{
|
|
||||||
PreviousOutPoint: *input.OutPoint(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Before signing the transaction, check to ensure that it meets some
|
// Before signing the transaction, check to ensure that it meets some
|
||||||
// basic validity requirements.
|
// basic validity requirements.
|
||||||
@ -215,7 +195,7 @@ func (s *UtxoSweeper) populateSweepTx(txWeight int64, currentBlockHeight uint32,
|
|||||||
|
|
||||||
// With all the inputs in place, use each output's unique witness
|
// With all the inputs in place, use each output's unique witness
|
||||||
// function to generate the final witness required for spending.
|
// function to generate the final witness required for spending.
|
||||||
addWitness := func(idx int, tso SpendableOutput) error {
|
addWitness := func(idx int, tso Input) error {
|
||||||
witness, err := tso.BuildWitness(
|
witness, err := tso.BuildWitness(
|
||||||
s.cfg.Signer, sweepTx, hashCache, idx,
|
s.cfg.Signer, sweepTx, hashCache, idx,
|
||||||
)
|
)
|
||||||
@ -230,20 +210,11 @@ func (s *UtxoSweeper) populateSweepTx(txWeight int64, currentBlockHeight uint32,
|
|||||||
|
|
||||||
// Finally we'll attach a valid witness to each csv and cltv input
|
// Finally we'll attach a valid witness to each csv and cltv input
|
||||||
// within the sweeping transaction.
|
// within the sweeping transaction.
|
||||||
for i, input := range csvInputs {
|
for i, input := range inputs {
|
||||||
if err := addWitness(i, input); err != nil {
|
if err := addWitness(i, input); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add offset to relative indexes so cltv witnesses don't overwrite csv
|
|
||||||
// witnesses.
|
|
||||||
offset := len(csvInputs)
|
|
||||||
for i, input := range cltvInputs {
|
|
||||||
if err := addWitness(offset+i, input); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sweepTx, nil
|
return sweepTx, nil
|
||||||
}
|
}
|
||||||
|
@ -871,14 +871,14 @@ func (u *utxoNursery) graduateClass(classHeight uint32) error {
|
|||||||
// generated a sweep txn for this height. Generate one if there
|
// generated a sweep txn for this height. Generate one if there
|
||||||
// are kindergarten outputs or cltv crib outputs to be spent.
|
// are kindergarten outputs or cltv crib outputs to be spent.
|
||||||
if len(kgtnOutputs) > 0 {
|
if len(kgtnOutputs) > 0 {
|
||||||
csvSpendableOutputs := make([]sweep.CsvSpendableOutput,
|
sweepInputs := make([]sweep.Input,
|
||||||
len(kgtnOutputs))
|
len(kgtnOutputs))
|
||||||
for i := range kgtnOutputs {
|
for i := range kgtnOutputs {
|
||||||
csvSpendableOutputs[i] = &kgtnOutputs[i]
|
sweepInputs[i] = &kgtnOutputs[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
finalTx, err = u.cfg.Sweeper.CreateSweepTx(
|
finalTx, err = u.cfg.Sweeper.CreateSweepTx(
|
||||||
csvSpendableOutputs, classHeight)
|
sweepInputs, classHeight)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utxnLog.Errorf("Failed to create sweep txn at "+
|
utxnLog.Errorf("Failed to create sweep txn at "+
|
||||||
@ -1749,7 +1749,7 @@ func readTxOut(r io.Reader, txo *wire.TxOut) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compile-time constraint to ensure kidOutput and babyOutput implement the
|
// Compile-time constraint to ensure kidOutput implements the
|
||||||
// CsvSpendableOutput interface.
|
// Input interface.
|
||||||
var _ sweep.CsvSpendableOutput = (*kidOutput)(nil)
|
|
||||||
var _ sweep.CsvSpendableOutput = (*babyOutput)(nil)
|
var _ sweep.Input = (*kidOutput)(nil)
|
||||||
|
Loading…
Reference in New Issue
Block a user