cnct: reuse sweep tx logic for success resolver
This commit is contained in:
parent
c1d845aa0d
commit
6977d59e35
@ -9,7 +9,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/txscript"
|
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
@ -447,59 +446,19 @@ func (h *htlcSuccessResolver) Resolve() (ContractResolver, error) {
|
|||||||
"incoming+remote htlc confirmed", h,
|
"incoming+remote htlc confirmed", h,
|
||||||
h.payHash[:])
|
h.payHash[:])
|
||||||
|
|
||||||
// In this case, we can sweep it directly from the
|
input := sweep.MakeHtlcSucceedInput(
|
||||||
// commitment output. We'll first grab a fresh address
|
&h.htlcResolution.ClaimOutpoint,
|
||||||
// from the wallet to sweep the output.
|
&h.htlcResolution.SweepSignDesc,
|
||||||
addr, err := h.NewSweepAddr()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// With our address obtained, we'll query for an
|
|
||||||
// estimate to be confirmed at ease.
|
|
||||||
//
|
|
||||||
// TODO(roasbeef): signal up if fee would be too large
|
|
||||||
// to sweep singly, need to batch
|
|
||||||
feePerKw, err := h.FeeEstimator.EstimateFeePerKW(6)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("%T(%x): using %v sat/kw to sweep htlc"+
|
|
||||||
"incoming+remote htlc confirmed", h,
|
|
||||||
h.payHash[:], int64(feePerKw))
|
|
||||||
|
|
||||||
// Using a weight estimator, we'll compute the total
|
|
||||||
// fee required, and from that the value we'll end up
|
|
||||||
// with.
|
|
||||||
totalWeight := (&lnwallet.TxWeightEstimator{}).
|
|
||||||
AddWitnessInput(lnwallet.OfferedHtlcSuccessWitnessSize).
|
|
||||||
AddP2WKHOutput().Weight()
|
|
||||||
totalFees := feePerKw.FeeForWeight(int64(totalWeight))
|
|
||||||
sweepAmt := h.htlcResolution.SweepSignDesc.Output.Value -
|
|
||||||
int64(totalFees)
|
|
||||||
|
|
||||||
// With the fee computation finished, we'll now
|
|
||||||
// construct the sweep transaction.
|
|
||||||
htlcPoint := h.htlcResolution.ClaimOutpoint
|
|
||||||
h.sweepTx = wire.NewMsgTx(2)
|
|
||||||
h.sweepTx.AddTxIn(&wire.TxIn{
|
|
||||||
PreviousOutPoint: htlcPoint,
|
|
||||||
})
|
|
||||||
h.sweepTx.AddTxOut(&wire.TxOut{
|
|
||||||
PkScript: addr,
|
|
||||||
Value: sweepAmt,
|
|
||||||
})
|
|
||||||
|
|
||||||
// With the transaction fully assembled, we can now
|
|
||||||
// generate a valid witness for the transaction.
|
|
||||||
h.htlcResolution.SweepSignDesc.SigHashes = txscript.NewTxSigHashes(
|
|
||||||
h.sweepTx,
|
|
||||||
)
|
|
||||||
h.sweepTx.TxIn[0].Witness, err = lnwallet.SenderHtlcSpendRedeem(
|
|
||||||
h.Signer, &h.htlcResolution.SweepSignDesc, h.sweepTx,
|
|
||||||
h.htlcResolution.Preimage[:],
|
h.htlcResolution.Preimage[:],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// TODO: Set tx lock time to current block height instead of
|
||||||
|
// zero. Will be taken care of once sweeper implementation is
|
||||||
|
// complete.
|
||||||
|
h.sweepTx, err = h.Sweeper.CreateSweepTx(
|
||||||
|
[]sweep.Input{&input}, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -35,13 +35,36 @@ type Input interface {
|
|||||||
BlocksToMaturity() uint32
|
BlocksToMaturity() uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// BaseInput contains all the information needed to sweep an output.
|
type inputKit struct {
|
||||||
type BaseInput struct {
|
|
||||||
outpoint wire.OutPoint
|
outpoint wire.OutPoint
|
||||||
witnessType lnwallet.WitnessType
|
witnessType lnwallet.WitnessType
|
||||||
signDesc lnwallet.SignDescriptor
|
signDesc lnwallet.SignDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// WitnessType returns the type of witness that must be generated to spend the
|
||||||
|
// breached output.
|
||||||
|
func (i *inputKit) WitnessType() lnwallet.WitnessType {
|
||||||
|
return i.witnessType
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignDesc returns the breached output's SignDescriptor, which is used during
|
||||||
|
// signing to compute the witness.
|
||||||
|
func (i *inputKit) SignDesc() *lnwallet.SignDescriptor {
|
||||||
|
return &i.signDesc
|
||||||
|
}
|
||||||
|
|
||||||
|
// BaseInput contains all the information needed to sweep a basic output
|
||||||
|
// (CSV/CLTV/no time lock)
|
||||||
|
type BaseInput struct {
|
||||||
|
inputKit
|
||||||
|
}
|
||||||
|
|
||||||
// MakeBaseInput assembles a new BaseInput that can be used to construct a
|
// MakeBaseInput assembles a new BaseInput that can be used to construct a
|
||||||
// sweep transaction.
|
// sweep transaction.
|
||||||
func MakeBaseInput(outpoint *wire.OutPoint,
|
func MakeBaseInput(outpoint *wire.OutPoint,
|
||||||
@ -49,30 +72,14 @@ func MakeBaseInput(outpoint *wire.OutPoint,
|
|||||||
signDescriptor *lnwallet.SignDescriptor) BaseInput {
|
signDescriptor *lnwallet.SignDescriptor) BaseInput {
|
||||||
|
|
||||||
return BaseInput{
|
return BaseInput{
|
||||||
|
inputKit{
|
||||||
outpoint: *outpoint,
|
outpoint: *outpoint,
|
||||||
witnessType: witnessType,
|
witnessType: witnessType,
|
||||||
signDesc: *signDescriptor,
|
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
|
// BuildWitness computes a valid witness that allows us to spend from the
|
||||||
// breached output. It does so by generating the witness generation function,
|
// breached output. It does so by generating the witness generation function,
|
||||||
// which is parameterized primarily by the witness type and sign descriptor. The
|
// which is parameterized primarily by the witness type and sign descriptor. The
|
||||||
@ -94,6 +101,54 @@ func (bi *BaseInput) BlocksToMaturity() uint32 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add compile-time constraint ensuring BaseInput implements
|
// HtlcSucceedInput constitutes a sweep input that needs a pre-image. The input
|
||||||
// SpendableOutput.
|
// 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
|
||||||
|
|
||||||
|
preimage []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeHtlcSucceedInput assembles a new redeem input that can be used to
|
||||||
|
// construct a sweep transaction.
|
||||||
|
func MakeHtlcSucceedInput(outpoint *wire.OutPoint,
|
||||||
|
signDescriptor *lnwallet.SignDescriptor,
|
||||||
|
preimage []byte) HtlcSucceedInput {
|
||||||
|
|
||||||
|
return HtlcSucceedInput{
|
||||||
|
inputKit: inputKit{
|
||||||
|
outpoint: *outpoint,
|
||||||
|
witnessType: lnwallet.HtlcAcceptedRemoteSuccess,
|
||||||
|
signDesc: *signDescriptor,
|
||||||
|
},
|
||||||
|
preimage: preimage,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
func (h *HtlcSucceedInput) BuildWitness(signer lnwallet.Signer, txn *wire.MsgTx,
|
||||||
|
hashCache *txscript.TxSigHashes, txinIdx int) ([][]byte, error) {
|
||||||
|
|
||||||
|
desc := h.signDesc
|
||||||
|
desc.SigHashes = hashCache
|
||||||
|
desc.InputIndex = txinIdx
|
||||||
|
|
||||||
|
return lnwallet.SenderHtlcSpendRedeem(
|
||||||
|
signer, &desc, txn,
|
||||||
|
h.preimage,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
func (h *HtlcSucceedInput) BlocksToMaturity() uint32 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add compile-time constraint ensuring input structs implement Input interface.
|
||||||
var _ Input = (*BaseInput)(nil)
|
var _ Input = (*BaseInput)(nil)
|
||||||
|
var _ Input = (*HtlcSucceedInput)(nil)
|
||||||
|
@ -118,6 +118,13 @@ func (s *UtxoSweeper) CreateSweepTx(inputs []Input,
|
|||||||
)
|
)
|
||||||
cltvCount++
|
cltvCount++
|
||||||
|
|
||||||
|
// An HTLC on the commitment transaction of the remote party,
|
||||||
|
// that can be swept with the preimage.
|
||||||
|
case lnwallet.HtlcAcceptedRemoteSuccess:
|
||||||
|
weightEstimate.AddWitnessInput(
|
||||||
|
lnwallet.OfferedHtlcSuccessWitnessSize,
|
||||||
|
)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
unknownCount++
|
unknownCount++
|
||||||
log.Warnf("kindergarten output in nursery store "+
|
log.Warnf("kindergarten output in nursery store "+
|
||||||
|
Loading…
Reference in New Issue
Block a user