diff --git a/breacharbiter.go b/breacharbiter.go index df19bff1..c2b24bd3 100644 --- a/breacharbiter.go +++ b/breacharbiter.go @@ -20,6 +20,7 @@ import ( "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/lnwallet" + "github.com/lightningnetwork/lnd/sweep" ) var ( @@ -748,33 +749,6 @@ func (b *breachArbiter) handleBreachHandoff(breachEvent *ContractBreachEvent) { go b.exactRetribution(cfChan, retInfo) } -// SpendableOutput an interface which can be used by the breach arbiter to -// construct a transaction spending from outputs we control. -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 - // construct the corresponding transaction input. - OutPoint() *wire.OutPoint - - // WitnessType returns an enum specifying the type of witness that must - // 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() *lnwallet.SignDescriptor - - // BuildWitness returns a valid witness allowing this output to be - // spent, the witness should be attached to the transaction at the - // location determined by the given `txinIdx`. - BuildWitness(signer lnwallet.Signer, txn *wire.MsgTx, - hashCache *txscript.TxSigHashes, - txinIdx int) ([][]byte, error) -} - // breachedOutput contains all the information needed to sweep a breached // output. A breached output is an output that we are now entitled to due to a // revoked commitment transaction being broadcast. @@ -852,7 +826,7 @@ func (bo *breachedOutput) BuildWitness(signer lnwallet.Signer, txn *wire.MsgTx, // Add compile-time constraint ensuring breachedOutput implements // SpendableOutput. -var _ SpendableOutput = (*breachedOutput)(nil) +var _ sweep.SpendableOutput = (*breachedOutput)(nil) // retributionInfo encapsulates all the data needed to sweep all the contested // funds within a channel whose contract has been breached by the prior @@ -963,13 +937,13 @@ func (b *breachArbiter) createJusticeTx( // outputs, while simultaneously computing the estimated weight of the // transaction. var ( - spendableOutputs []SpendableOutput + spendableOutputs []sweep.SpendableOutput weightEstimate lnwallet.TxWeightEstimator ) // Allocate enough space to potentially hold each of the breached // outputs in the retribution info. - spendableOutputs = make([]SpendableOutput, 0, len(r.breachedOutputs)) + spendableOutputs = make([]sweep.SpendableOutput, 0, len(r.breachedOutputs)) // The justice transaction we construct will be a segwit transaction // that pays to a p2wkh output. Components such as the version, @@ -1023,7 +997,7 @@ func (b *breachArbiter) createJusticeTx( // sweepSpendableOutputsTxn creates a signed transaction from a sequence of // spendable outputs by sweeping the funds into a single p2wkh output. func (b *breachArbiter) sweepSpendableOutputsTxn(txWeight int64, - inputs ...SpendableOutput) (*wire.MsgTx, error) { + inputs ...sweep.SpendableOutput) (*wire.MsgTx, error) { // First, we obtain a new public key script from the wallet which we'll // sweep the funds to. @@ -1085,7 +1059,7 @@ func (b *breachArbiter) sweepSpendableOutputsTxn(txWeight int64, // witness, and attaching it to the transaction. This function accepts // an integer index representing the intended txin index, and the // breached output from which it will spend. - addWitness := func(idx int, so SpendableOutput) error { + addWitness := func(idx int, so sweep.SpendableOutput) error { // First, we construct a valid witness for this outpoint and // transaction using the SpendableOutput's witness generation // function. diff --git a/sweep/input.go b/sweep/input.go new file mode 100644 index 00000000..aab96fa3 --- /dev/null +++ b/sweep/input.go @@ -0,0 +1,58 @@ +package sweep + +import ( + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" + "github.com/lightningnetwork/lnd/lnwallet" +) + +// SpendableOutput an interface which can be used by the breach arbiter to +// construct a transaction spending from outputs we control. +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 + // construct the corresponding transaction input. + OutPoint() *wire.OutPoint + + // WitnessType returns an enum specifying the type of witness that must + // 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() *lnwallet.SignDescriptor + + // BuildWitness returns a valid witness allowing this output to be + // spent, the witness should be attached to the transaction at the + // location determined by the given `txinIdx`. + BuildWitness(signer lnwallet.Signer, txn *wire.MsgTx, + hashCache *txscript.TxSigHashes, + 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 + // blocks, that must be built on top of the confirmation height before + // the output can be spent. + BlocksToMaturity() uint32 + + // OriginChanPoint returns the outpoint of the channel from which this + // output is derived. + OriginChanPoint() *wire.OutPoint +} diff --git a/utxonursery.go b/utxonursery.go index 8eed7cb5..37ebdf11 100644 --- a/utxonursery.go +++ b/utxonursery.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/binary" "fmt" + "github.com/lightningnetwork/lnd/sweep" "io" "sync" "sync/atomic" @@ -953,14 +954,14 @@ func (u *utxoNursery) createSweepTx(kgtnOutputs []kidOutput, // outputs are CLTV locked outputs that have had their timelocks // expire. var ( - csvOutputs []CsvSpendableOutput - cltvOutputs []SpendableOutput + csvOutputs []sweep.CsvSpendableOutput + cltvOutputs []sweep.SpendableOutput weightEstimate lnwallet.TxWeightEstimator ) // Allocate enough room for both types of kindergarten outputs. - csvOutputs = make([]CsvSpendableOutput, 0, len(kgtnOutputs)) - cltvOutputs = make([]SpendableOutput, 0, len(kgtnOutputs)) + csvOutputs = make([]sweep.CsvSpendableOutput, 0, len(kgtnOutputs)) + cltvOutputs = make([]sweep.SpendableOutput, 0, len(kgtnOutputs)) // Our sweep transaction will pay to a single segwit p2wkh address, // ensure it contributes to our weight estimate. @@ -1028,8 +1029,8 @@ func (u *utxoNursery) createSweepTx(kgtnOutputs []kidOutput, // has a single output sending all the funds back to the source wallet, after // accounting for the fee estimate. func (u *utxoNursery) populateSweepTx(txWeight int64, classHeight uint32, - csvInputs []CsvSpendableOutput, - cltvInputs []SpendableOutput) (*wire.MsgTx, error) { + csvInputs []sweep.CsvSpendableOutput, + cltvInputs []sweep.SpendableOutput) (*wire.MsgTx, error) { // Generate the receiving script to which the funds will be swept. pkScript, err := u.cfg.GenSweepScript() @@ -1099,7 +1100,7 @@ func (u *utxoNursery) populateSweepTx(txWeight int64, classHeight uint32, // With all the inputs in place, use each output's unique witness // function to generate the final witness required for spending. - addWitness := func(idx int, tso SpendableOutput) error { + addWitness := func(idx int, tso sweep.SpendableOutput) error { witness, err := tso.BuildWitness( u.cfg.Signer, sweepTx, hashCache, idx, ) @@ -1635,29 +1636,6 @@ func newSweepPkScript(wallet lnwallet.WalletController) ([]byte, error) { return txscript.PayToAddrScript(sweepAddr) } -// 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 - // blocks, that must be built on top of the confirmation height before - // the output can be spent. - BlocksToMaturity() uint32 - - // OriginChanPoint returns the outpoint of the channel from which this - // output is derived. - OriginChanPoint() *wire.OutPoint -} - // babyOutput represents a two-stage CSV locked output, and is used to track // htlc outputs through incubation. The first stage requires broadcasting a // presigned timeout txn that spends from the CLTV locked output on the @@ -1971,5 +1949,5 @@ func readTxOut(r io.Reader, txo *wire.TxOut) error { // Compile-time constraint to ensure kidOutput and babyOutput implement the // CsvSpendableOutput interface. -var _ CsvSpendableOutput = (*kidOutput)(nil) -var _ CsvSpendableOutput = (*babyOutput)(nil) +var _ sweep.CsvSpendableOutput = (*kidOutput)(nil) +var _ sweep.CsvSpendableOutput = (*babyOutput)(nil)