contraccourt+input: create HtlcSecondLevelAnchorInput and resolver for

success tx

This commit makes the HTLC resolutions having non-nil SignDetails
(meaning we can re-sign the second-level transactions) go through the
sweeper. They will be offered to the sweeper which will cluster them and
arrange them on its sweep transaction. When that is done we will further
sweep the output on this sweep transaction as any other second-level tx.

In this commit we do this for the HTLC success resolver and the
accompanying HTLC success transaction.
This commit is contained in:
Johan T. Halseth
2020-12-09 12:24:03 +01:00
parent d02b486195
commit 85ea181d67
3 changed files with 297 additions and 2 deletions

View File

@@ -4,6 +4,7 @@ import (
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/lntypes"
)
// Input represents an abstract UTXO which is to be spent using a sweeping
@@ -257,7 +258,93 @@ func (h *HtlcSucceedInput) CraftInputScript(signer Signer, txn *wire.MsgTx,
}, nil
}
// HtlcsSecondLevelAnchorInput is an input type used to spend HTLC outputs
// using a re-signed second level transaction, either via the timeout or success
// paths.
type HtlcSecondLevelAnchorInput struct {
inputKit
// SignedTx is the original second level transaction signed by the
// channel peer.
SignedTx *wire.MsgTx
// createWitness creates a witness allowing the passed transaction to
// spend the input.
createWitness func(signer Signer, txn *wire.MsgTx,
hashCache *txscript.TxSigHashes, txinIdx int) (wire.TxWitness, error)
}
// RequiredTxOut returns the tx out needed to be present on the sweep tx for
// the spend of the input to be valid.
func (i *HtlcSecondLevelAnchorInput) RequiredTxOut() *wire.TxOut {
return i.SignedTx.TxOut[0]
}
// RequiredLockTime returns the locktime needed for the sweep tx for the spend
// of the input to be valid. For a second level HTLC timeout this will be the
// CLTV expiry, for HTLC success it will be zero.
func (i *HtlcSecondLevelAnchorInput) RequiredLockTime() (uint32, bool) {
return i.SignedTx.LockTime, true
}
// CraftInputScript returns a valid set of input scripts allowing this output
// to be spent. The returns input scripts should target the input at location
// txIndex within the passed transaction. The input scripts generated by this
// method support spending p2wkh, p2wsh, and also nested p2sh outputs.
func (i *HtlcSecondLevelAnchorInput) CraftInputScript(signer Signer,
txn *wire.MsgTx, hashCache *txscript.TxSigHashes,
txinIdx int) (*Script, error) {
witness, err := i.createWitness(signer, txn, hashCache, txinIdx)
if err != nil {
return nil, err
}
return &Script{
Witness: witness,
}, nil
}
// MakeHtlcSecondLevelSuccessAnchorInput creates an input allowing the sweeper
// to spend the HTLC output on our commit using the second level success
// transaction.
func MakeHtlcSecondLevelSuccessAnchorInput(signedTx *wire.MsgTx,
signDetails *SignDetails, preimage lntypes.Preimage,
heightHint uint32) HtlcSecondLevelAnchorInput {
// Spend an HTLC output on our local commitment tx using the 2nd
// success transaction.
createWitness := func(signer Signer, txn *wire.MsgTx,
hashCache *txscript.TxSigHashes,
txinIdx int) (wire.TxWitness, error) {
desc := signDetails.SignDesc
desc.SigHashes = hashCache
desc.InputIndex = txinIdx
return ReceiverHtlcSpendRedeem(
signDetails.PeerSig, signDetails.SigHashType,
preimage[:], signer, &desc, txn,
)
}
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,
createWitness: createWitness,
}
}
// Compile-time constraints to ensure each input struct implement the Input
// interface.
var _ Input = (*BaseInput)(nil)
var _ Input = (*HtlcSucceedInput)(nil)
var _ Input = (*HtlcSecondLevelAnchorInput)(nil)