From 3f50339898d04b372a59f80ad268c624e6ae08ca Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 3 Jun 2024 23:02:40 -0700 Subject: [PATCH] input: refactor all inputs to use MakeBaseInput, add opts In this commit, we refactor all the other constructors for the input to use MakeBaseInput. We also add a new set of functional options as well. This'll be useful later on to ensure that new options are properly applied to all the input types. --- input/input.go | 172 ++++++++++++++++++++++++++----------------------- input/mocks.go | 13 ++++ 2 files changed, 104 insertions(+), 81 deletions(-) diff --git a/input/input.go b/input/input.go index aef524a4c..014c26f0b 100644 --- a/input/input.go +++ b/input/input.go @@ -156,6 +156,18 @@ func (i *inputKit) UnconfParent() *TxInfo { return i.unconfParent } +// inputOpts holds options for the input. +type inputOpts struct { +} + +// defaultInputOpts returns a new inputOpts with default values. +func defaultInputOpts() *inputOpts { + return &inputOpts{} +} + +// InputOpt is a functional option argument to the input constructor. +type InputOpt func(*inputOpts) //nolint:revive + // BaseInput contains all the information needed to sweep a basic // output (CSV/CLTV/no time lock). type BaseInput struct { @@ -166,7 +178,12 @@ type BaseInput struct { // sweep transaction. func MakeBaseInput(outpoint *wire.OutPoint, witnessType WitnessType, signDescriptor *SignDescriptor, heightHint uint32, - unconfParent *TxInfo) BaseInput { + unconfParent *TxInfo, opts ...InputOpt) BaseInput { + + opt := defaultInputOpts() + for _, optF := range opts { + optF(opt) + } return BaseInput{ inputKit{ @@ -182,10 +199,11 @@ func MakeBaseInput(outpoint *wire.OutPoint, witnessType WitnessType, // NewBaseInput allocates and assembles a new *BaseInput that can be used to // construct a sweep transaction. func NewBaseInput(outpoint *wire.OutPoint, witnessType WitnessType, - signDescriptor *SignDescriptor, heightHint uint32) *BaseInput { + signDescriptor *SignDescriptor, heightHint uint32, + opts ...InputOpt) *BaseInput { input := MakeBaseInput( - outpoint, witnessType, signDescriptor, heightHint, nil, + outpoint, witnessType, signDescriptor, heightHint, nil, opts..., ) return &input @@ -195,36 +213,31 @@ func NewBaseInput(outpoint *wire.OutPoint, witnessType WitnessType, // construct a sweep transaction. func NewCsvInput(outpoint *wire.OutPoint, witnessType WitnessType, signDescriptor *SignDescriptor, heightHint uint32, - blockToMaturity uint32) *BaseInput { + blockToMaturity uint32, opts ...InputOpt) *BaseInput { - return &BaseInput{ - inputKit{ - outpoint: *outpoint, - witnessType: witnessType, - signDesc: *signDescriptor, - heightHint: heightHint, - blockToMaturity: blockToMaturity, - }, - } + input := MakeBaseInput( + outpoint, witnessType, signDescriptor, heightHint, nil, opts..., + ) + + input.blockToMaturity = blockToMaturity + + return &input } // NewCsvInputWithCltv assembles a new csv and cltv locked input that can be // used to construct a sweep transaction. func NewCsvInputWithCltv(outpoint *wire.OutPoint, witnessType WitnessType, signDescriptor *SignDescriptor, heightHint uint32, - csvDelay uint32, cltvExpiry uint32) *BaseInput { + csvDelay uint32, cltvExpiry uint32, opts ...InputOpt) *BaseInput { - return &BaseInput{ - inputKit{ - outpoint: *outpoint, - witnessType: witnessType, - signDesc: *signDescriptor, - heightHint: heightHint, - blockToMaturity: csvDelay, - cltvExpiry: cltvExpiry, - unconfParent: nil, - }, - } + input := MakeBaseInput( + outpoint, witnessType, signDescriptor, heightHint, nil, opts..., + ) + + input.blockToMaturity = csvDelay + input.cltvExpiry = cltvExpiry + + return &input } // CraftInputScript returns a valid set of input scripts allowing this output @@ -256,16 +269,16 @@ type HtlcSucceedInput struct { // construct a sweep transaction. func MakeHtlcSucceedInput(outpoint *wire.OutPoint, signDescriptor *SignDescriptor, preimage []byte, heightHint, - blocksToMaturity uint32) HtlcSucceedInput { + blocksToMaturity uint32, opts ...InputOpt) HtlcSucceedInput { + + input := MakeBaseInput( + outpoint, HtlcAcceptedRemoteSuccess, signDescriptor, + heightHint, nil, opts..., + ) + input.blockToMaturity = blocksToMaturity return HtlcSucceedInput{ - inputKit: inputKit{ - outpoint: *outpoint, - witnessType: HtlcAcceptedRemoteSuccess, - signDesc: *signDescriptor, - heightHint: heightHint, - blockToMaturity: blocksToMaturity, - }, + inputKit: input.inputKit, preimage: preimage, } } @@ -274,16 +287,17 @@ func MakeHtlcSucceedInput(outpoint *wire.OutPoint, // to spend an HTLC output for a taproot channel on the remote party's // commitment transaction. func MakeTaprootHtlcSucceedInput(op *wire.OutPoint, signDesc *SignDescriptor, - preimage []byte, heightHint, blocksToMaturity uint32) HtlcSucceedInput { + preimage []byte, heightHint, blocksToMaturity uint32, + opts ...InputOpt) HtlcSucceedInput { + + input := MakeBaseInput( + op, TaprootHtlcAcceptedRemoteSuccess, signDesc, + heightHint, nil, opts..., + ) + input.blockToMaturity = blocksToMaturity return HtlcSucceedInput{ - inputKit: inputKit{ - outpoint: *op, - witnessType: TaprootHtlcAcceptedRemoteSuccess, - signDesc: *signDesc, - heightHint: heightHint, - blockToMaturity: blocksToMaturity, - }, + inputKit: input.inputKit, preimage: preimage, } } @@ -388,7 +402,8 @@ func (i *HtlcSecondLevelAnchorInput) CraftInputScript(signer Signer, // to spend the HTLC output on our commit using the second level timeout // transaction. func MakeHtlcSecondLevelTimeoutAnchorInput(signedTx *wire.MsgTx, - signDetails *SignDetails, heightHint uint32) HtlcSecondLevelAnchorInput { + signDetails *SignDetails, heightHint uint32, + opts ...InputOpt) HtlcSecondLevelAnchorInput { // Spend an HTLC output on our local commitment tx using the // 2nd timeout transaction. @@ -408,16 +423,15 @@ func MakeHtlcSecondLevelTimeoutAnchorInput(signedTx *wire.MsgTx, ) } - return HtlcSecondLevelAnchorInput{ - inputKit: inputKit{ - outpoint: signedTx.TxIn[0].PreviousOutPoint, - witnessType: HtlcOfferedTimeoutSecondLevelInputConfirmed, - signDesc: signDetails.SignDesc, - heightHint: heightHint, + input := MakeBaseInput( + &signedTx.TxIn[0].PreviousOutPoint, + HtlcOfferedTimeoutSecondLevelInputConfirmed, + &signDetails.SignDesc, heightHint, nil, opts..., + ) + input.blockToMaturity = 1 - // CSV delay is always 1 for these inputs. - blockToMaturity: 1, - }, + return HtlcSecondLevelAnchorInput{ + inputKit: input.inputKit, SignedTx: signedTx, createWitness: createWitness, } @@ -429,7 +443,7 @@ func MakeHtlcSecondLevelTimeoutAnchorInput(signedTx *wire.MsgTx, // sweep the second level HTLC aggregated with other transactions. func MakeHtlcSecondLevelTimeoutTaprootInput(signedTx *wire.MsgTx, signDetails *SignDetails, - heightHint uint32) HtlcSecondLevelAnchorInput { + heightHint uint32, opts ...InputOpt) HtlcSecondLevelAnchorInput { createWitness := func(signer Signer, txn *wire.MsgTx, hashCache *txscript.TxSigHashes, @@ -453,16 +467,15 @@ func MakeHtlcSecondLevelTimeoutTaprootInput(signedTx *wire.MsgTx, ) } - return HtlcSecondLevelAnchorInput{ - inputKit: inputKit{ - outpoint: signedTx.TxIn[0].PreviousOutPoint, - witnessType: TaprootHtlcLocalOfferedTimeout, - signDesc: signDetails.SignDesc, - heightHint: heightHint, + input := MakeBaseInput( + &signedTx.TxIn[0].PreviousOutPoint, + TaprootHtlcLocalOfferedTimeout, + &signDetails.SignDesc, heightHint, nil, opts..., + ) + input.blockToMaturity = 1 - // CSV delay is always 1 for these inputs. - blockToMaturity: 1, - }, + return HtlcSecondLevelAnchorInput{ + inputKit: input.inputKit, SignedTx: signedTx, createWitness: createWitness, } @@ -473,7 +486,7 @@ func MakeHtlcSecondLevelTimeoutTaprootInput(signedTx *wire.MsgTx, // transaction. func MakeHtlcSecondLevelSuccessAnchorInput(signedTx *wire.MsgTx, signDetails *SignDetails, preimage lntypes.Preimage, - heightHint uint32) HtlcSecondLevelAnchorInput { + heightHint uint32, opts ...InputOpt) HtlcSecondLevelAnchorInput { // Spend an HTLC output on our local commitment tx using the 2nd // success transaction. @@ -492,18 +505,16 @@ func MakeHtlcSecondLevelSuccessAnchorInput(signedTx *wire.MsgTx, preimage[:], signer, &desc, txn, ) } + input := MakeBaseInput( + &signedTx.TxIn[0].PreviousOutPoint, + HtlcAcceptedSuccessSecondLevelInputConfirmed, + &signDetails.SignDesc, heightHint, nil, opts..., + ) + input.blockToMaturity = 1 return HtlcSecondLevelAnchorInput{ - inputKit: inputKit{ - outpoint: signedTx.TxIn[0].PreviousOutPoint, - witnessType: HtlcAcceptedSuccessSecondLevelInputConfirmed, - signDesc: signDetails.SignDesc, - heightHint: heightHint, - - // CSV delay is always 1 for these inputs. - blockToMaturity: 1, - }, SignedTx: signedTx, + inputKit: input.inputKit, createWitness: createWitness, } } @@ -513,7 +524,7 @@ func MakeHtlcSecondLevelSuccessAnchorInput(signedTx *wire.MsgTx, // commitment transaction. func MakeHtlcSecondLevelSuccessTaprootInput(signedTx *wire.MsgTx, signDetails *SignDetails, preimage lntypes.Preimage, - heightHint uint32) HtlcSecondLevelAnchorInput { + heightHint uint32, opts ...InputOpt) HtlcSecondLevelAnchorInput { createWitness := func(signer Signer, txn *wire.MsgTx, hashCache *txscript.TxSigHashes, @@ -537,16 +548,15 @@ func MakeHtlcSecondLevelSuccessTaprootInput(signedTx *wire.MsgTx, ) } - return HtlcSecondLevelAnchorInput{ - inputKit: inputKit{ - outpoint: signedTx.TxIn[0].PreviousOutPoint, - witnessType: TaprootHtlcAcceptedLocalSuccess, - signDesc: signDetails.SignDesc, - heightHint: heightHint, + input := MakeBaseInput( + &signedTx.TxIn[0].PreviousOutPoint, + TaprootHtlcAcceptedLocalSuccess, + &signDetails.SignDesc, heightHint, nil, opts..., + ) + input.blockToMaturity = 1 - // CSV delay is always 1 for these inputs. - blockToMaturity: 1, - }, + return HtlcSecondLevelAnchorInput{ + inputKit: input.inputKit, SignedTx: signedTx, createWitness: createWitness, } diff --git a/input/mocks.go b/input/mocks.go index 2f38400d8..695525955 100644 --- a/input/mocks.go +++ b/input/mocks.go @@ -8,8 +8,10 @@ import ( "github.com/btcsuite/btcd/btcec/v2/schnorr/musig2" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" + "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lntypes" + "github.com/lightningnetwork/lnd/tlv" "github.com/stretchr/testify/mock" ) @@ -127,6 +129,17 @@ func (m *MockInput) UnconfParent() *TxInfo { return info.(*TxInfo) } +func (m *MockInput) ResolutionBlob() fn.Option[tlv.Blob] { + args := m.Called() + + info := args.Get(0) + if info == nil { + return fn.None[tlv.Blob]() + } + + return info.(fn.Option[tlv.Blob]) +} + // MockWitnessType implements the `WitnessType` interface and is used by other // packages for mock testing. type MockWitnessType struct {