input: update all taproot script spends to optionally make the ctrl block

In this commit, we update all the taproot scripts spends to optionally
make the control block. This is useful in cases where we've already
created the control block, or may not have the items needed to construct
it in the first place.

We also add the control block to the sign descriptor itself.
This commit is contained in:
Olaoluwa Osuntokun 2023-03-01 21:34:56 -08:00
parent 405a435a84
commit 4c7da7df49
No known key found for this signature in database
GPG Key ID: 3BBD59E99B280306
5 changed files with 354 additions and 92 deletions

View File

@ -665,7 +665,7 @@ func senderHtlcTapScriptTree(senderHtlcKey, receiverHtlcKey,
// SenderHTLCScriptTaproot constructs the taproot witness program (schnorr key) // SenderHTLCScriptTaproot constructs the taproot witness program (schnorr key)
// for an outgoing HTLC on the sender's version of the commitment transaction. // for an outgoing HTLC on the sender's version of the commitment transaction.
// This method returns the top level tweaked public key that commits to both // This method returns the top level tweaked public key that commits to both
// the script paths. // the script paths. This is also known as an offered HTLC.
// //
// The returned key commits to a tapscript tree with two possible paths: // The returned key commits to a tapscript tree with two possible paths:
// //
@ -727,12 +727,21 @@ func SenderHTLCScriptTaprootRedeem(signer Signer, signDesc *SignDescriptor,
// In addition to the signature and the witness/leaf script, we also // In addition to the signature and the witness/leaf script, we also
// need to make a control block proof using the tapscript tree. // need to make a control block proof using the tapscript tree.
successTapLeafHash := txscript.NewBaseTapLeaf( var ctrlBlock []byte
signDesc.WitnessScript, if signDesc.ControlBlock == nil {
).TapHash() successControlBlock := MakeTaprootCtrlBlock(
successIdx := tapscriptTree.LeafProofIndex[successTapLeafHash] signDesc.WitnessScript, revokeKey, tapscriptTree,
successMerkleProof := tapscriptTree.LeafMerkleProofs[successIdx] )
successControlBlock := successMerkleProof.ToControlBlock(revokeKey)
ctrlBytes, err := successControlBlock.ToBytes()
if err != nil {
return nil, err
}
ctrlBlock = ctrlBytes
} else {
ctrlBlock = signDesc.ControlBlock
}
// The final witness stack is: // The final witness stack is:
// <receiver sig> <preimage> <success_script> <control_block> // <receiver sig> <preimage> <success_script> <control_block>
@ -740,10 +749,7 @@ func SenderHTLCScriptTaprootRedeem(signer Signer, signDesc *SignDescriptor,
witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType) witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType)
witnessStack[1] = preimage witnessStack[1] = preimage
witnessStack[2] = signDesc.WitnessScript witnessStack[2] = signDesc.WitnessScript
witnessStack[3], err = successControlBlock.ToBytes() witnessStack[3] = ctrlBlock
if err != nil {
return nil, err
}
return witnessStack, nil return witnessStack, nil
} }
@ -765,12 +771,20 @@ func SenderHTLCScriptTaprootTimeout(receiverSig Signature,
// With the sweep signature obtained, we'll obtain the control block // With the sweep signature obtained, we'll obtain the control block
// proof needed to perform a valid spend for the timeout path. // proof needed to perform a valid spend for the timeout path.
timeoutTapLeafHash := txscript.NewBaseTapLeaf( var ctrlBlockBytes []byte
signDesc.WitnessScript, if signDesc.ControlBlock == nil {
).TapHash() timeoutControlBlock := MakeTaprootCtrlBlock(
timeoutIdx := tapscriptTree.LeafProofIndex[timeoutTapLeafHash] signDesc.WitnessScript, revokeKey, tapscriptTree,
timeoutMerkleProof := tapscriptTree.LeafMerkleProofs[timeoutIdx] )
timeoutControlBlock := timeoutMerkleProof.ToControlBlock(revokeKey) ctrlBytes, err := timeoutControlBlock.ToBytes()
if err != nil {
return nil, err
}
ctrlBlockBytes = ctrlBytes
} else {
ctrlBlockBytes = signDesc.ControlBlock
}
// The final witness stack is: // The final witness stack is:
// <receiver sig> <local sig> <timeout_script> <control_block> // <receiver sig> <local sig> <timeout_script> <control_block>
@ -778,10 +792,7 @@ func SenderHTLCScriptTaprootTimeout(receiverSig Signature,
witnessStack[0] = maybeAppendSighash(receiverSig, receiverSigHash) witnessStack[0] = maybeAppendSighash(receiverSig, receiverSigHash)
witnessStack[1] = maybeAppendSighash(sweepSig, signDesc.HashType) witnessStack[1] = maybeAppendSighash(sweepSig, signDesc.HashType)
witnessStack[2] = signDesc.WitnessScript witnessStack[2] = signDesc.WitnessScript
witnessStack[3], err = timeoutControlBlock.ToBytes() witnessStack[3] = ctrlBlockBytes
if err != nil {
return nil, err
}
return witnessStack, nil return witnessStack, nil
} }
@ -1200,7 +1211,7 @@ func receiverHtlcTapScriptTree(senderHtlcKey, receiverHtlcKey,
// ReceiverHTLCScriptTaproot constructs the taproot witness program (schnor // ReceiverHTLCScriptTaproot constructs the taproot witness program (schnor
// key) for an incoming HTLC on the receiver's version of the commitment // key) for an incoming HTLC on the receiver's version of the commitment
// transaction. This method returns the top level tweaked public key that // transaction. This method returns the top level tweaked public key that
// commits to both the script paths. From the PoV for the receiver, this is an // commits to both the script paths. From the PoV of the receiver, this is an
// accepted HTLC. // accepted HTLC.
// //
// The returned key commits to a tapscript tree with two possible paths: // The returned key commits to a tapscript tree with two possible paths:
@ -1257,12 +1268,20 @@ func ReceiverHTLCScriptTaprootRedeem(senderSig Signature,
// In addition to the signature and the witness/leaf script, we also // In addition to the signature and the witness/leaf script, we also
// need to make a control block proof using the tapscript tree. // need to make a control block proof using the tapscript tree.
successTapLeafHash := txscript.NewBaseTapLeaf( var ctrlBlock []byte
signDesc.WitnessScript, if signDesc.ControlBlock == nil {
).TapHash() redeemControlBlock := MakeTaprootCtrlBlock(
successIdx := tapscriptTree.LeafProofIndex[successTapLeafHash] signDesc.WitnessScript, revokeKey, tapscriptTree,
successMerkleProof := tapscriptTree.LeafMerkleProofs[successIdx] )
successControlBlock := successMerkleProof.ToControlBlock(revokeKey) ctrlBytes, err := redeemControlBlock.ToBytes()
if err != nil {
return nil, err
}
ctrlBlock = ctrlBytes
} else {
ctrlBlock = signDesc.ControlBlock
}
// The final witness stack is: // The final witness stack is:
// * <sender sig> <receiver sig> <preimage> <success_script> // * <sender sig> <receiver sig> <preimage> <success_script>
@ -1272,10 +1291,7 @@ func ReceiverHTLCScriptTaprootRedeem(senderSig Signature,
witnessStack[1] = maybeAppendSighash(sweepSig, signDesc.HashType) witnessStack[1] = maybeAppendSighash(sweepSig, signDesc.HashType)
witnessStack[2] = paymentPreimage witnessStack[2] = paymentPreimage
witnessStack[3] = signDesc.WitnessScript witnessStack[3] = signDesc.WitnessScript
witnessStack[4], err = successControlBlock.ToBytes() witnessStack[4] = ctrlBlock
if err != nil {
return nil, err
}
return witnessStack, nil return witnessStack, nil
} }
@ -1311,22 +1327,25 @@ func ReceiverHTLCScriptTaprootTimeout(signer Signer, signDesc *SignDescriptor,
// In addition to the signature and the witness/leaf script, we also // In addition to the signature and the witness/leaf script, we also
// need to make a control block proof using the tapscript tree. // need to make a control block proof using the tapscript tree.
timeoutTapLeafHash := txscript.NewBaseTapLeaf( var ctrlBlock []byte
signDesc.WitnessScript, if signDesc.ControlBlock == nil {
).TapHash() timeoutControlBlock := MakeTaprootCtrlBlock(
timeoutIdx := tapscriptTree.LeafProofIndex[timeoutTapLeafHash] signDesc.WitnessScript, revokeKey, tapscriptTree,
timeoutMerkleProof := tapscriptTree.LeafMerkleProofs[timeoutIdx] )
timeoutControlBlock := timeoutMerkleProof.ToControlBlock(revokeKey) ctrlBlock, err = timeoutControlBlock.ToBytes()
if err != nil {
return nil, err
}
} else {
ctrlBlock = signDesc.ControlBlock
}
// The final witness is pretty simple, we just need to present a valid // The final witness is pretty simple, we just need to present a valid
// signature for the script, and then provide the control block. // signature for the script, and then provide the control block.
witnessStack := make(wire.TxWitness, 3) witnessStack := make(wire.TxWitness, 3)
witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType) witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType)
witnessStack[1] = signDesc.WitnessScript witnessStack[1] = signDesc.WitnessScript
witnessStack[2], err = timeoutControlBlock.ToBytes() witnessStack[2] = ctrlBlock
if err != nil {
return nil, err
}
return witnessStack, nil return witnessStack, nil
} }
@ -1542,7 +1561,7 @@ func TaprootHtlcSpendRevoke(signer Signer, signDesc *SignDescriptor,
// NOTE: The caller MUST set the txn version, sequence number, and sign // NOTE: The caller MUST set the txn version, sequence number, and sign
// descriptor's sig hash cache before invocation. // descriptor's sig hash cache before invocation.
func TaprootHtlcSpendSuccess(signer Signer, signDesc *SignDescriptor, func TaprootHtlcSpendSuccess(signer Signer, signDesc *SignDescriptor,
revokeKey *btcec.PublicKey, sweepTx *wire.MsgTx, sweepTx *wire.MsgTx, revokeKey *btcec.PublicKey,
tapscriptTree *txscript.IndexedTapScriptTree) (wire.TxWitness, error) { tapscriptTree *txscript.IndexedTapScriptTree) (wire.TxWitness, error) {
// First, we'll generate the sweep signature based on the populated // First, we'll generate the sweep signature based on the populated
@ -1553,14 +1572,21 @@ func TaprootHtlcSpendSuccess(signer Signer, signDesc *SignDescriptor,
return nil, err return nil, err
} }
var ctrlBlock []byte
if signDesc.ControlBlock == nil {
// Now that we have the sweep signature, we'll construct the control // Now that we have the sweep signature, we'll construct the control
// block needed to spend the script path. // block needed to spend the script path.
redeemTapLeafHash := txscript.NewBaseTapLeaf( redeemControlBlock := MakeTaprootCtrlBlock(
signDesc.WitnessScript, signDesc.WitnessScript, revokeKey, tapscriptTree,
).TapHash() )
redeemIdx := tapscriptTree.LeafProofIndex[redeemTapLeafHash]
redeemMerkleProof := tapscriptTree.LeafMerkleProofs[redeemIdx] ctrlBlock, err = redeemControlBlock.ToBytes()
redeemControlBlock := redeemMerkleProof.ToControlBlock(revokeKey) if err != nil {
return nil, err
}
} else {
ctrlBlock = signDesc.ControlBlock
}
// Now that we have the redeem control block, we can construct the // Now that we have the redeem control block, we can construct the
// final witness needed to spend the script: // final witness needed to spend the script:
@ -1569,10 +1595,7 @@ func TaprootHtlcSpendSuccess(signer Signer, signDesc *SignDescriptor,
witnessStack := make(wire.TxWitness, 3) witnessStack := make(wire.TxWitness, 3)
witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType) witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType)
witnessStack[1] = signDesc.WitnessScript witnessStack[1] = signDesc.WitnessScript
witnessStack[2], err = redeemControlBlock.ToBytes() witnessStack[2] = ctrlBlock
if err != nil {
return nil, err
}
return witnessStack, nil return witnessStack, nil
} }
@ -1946,6 +1969,19 @@ func TaprootCommitScriptToSelf(csvTimeout uint32,
return commitScriptTree.TaprootKey, nil return commitScriptTree.TaprootKey, nil
} }
// MakeTaprootSCtrlBlock takes a leaf script, the internal key (usually the
// revoke key), and a script tree and creates a valid control block for a spend
// of the leaf.
func MakeTaprootCtrlBlock(leafScript []byte, internalKey *btcec.PublicKey,
scriptTree *txscript.IndexedTapScriptTree) txscript.ControlBlock {
tapLeafHash := txscript.NewBaseTapLeaf(leafScript).TapHash()
scriptIdx := scriptTree.LeafProofIndex[tapLeafHash]
settleMerkleProof := scriptTree.LeafMerkleProofs[scriptIdx]
return settleMerkleProof.ToControlBlock(internalKey)
}
// TaprootCommitSpendSuccess constructs a valid witness allowing a node to // TaprootCommitSpendSuccess constructs a valid witness allowing a node to
// sweep the settled taproot output after the delay has passed for a force // sweep the settled taproot output after the delay has passed for a force
// close. // close.
@ -1955,14 +1991,24 @@ func TaprootCommitSpendSuccess(signer Signer, signDesc *SignDescriptor,
// First, we'll need to construct a valid control block to execute the // First, we'll need to construct a valid control block to execute the
// leaf script for sweep settlement. // leaf script for sweep settlement.
settleTapleafHash := txscript.NewBaseTapLeaf( //
signDesc.WitnessScript, // TODO(roasbeef); make into closure instead? only need reovke key and
).TapHash() // scriptTree to make the ctrl block -- then default version that would
settleIdx := scriptTree.LeafProofIndex[settleTapleafHash] // take froms ign desc?
settleMerkleProof := scriptTree.LeafMerkleProofs[settleIdx] var ctrlBlockBytes []byte
settleControlBlock := settleMerkleProof.ToControlBlock( if signDesc.ControlBlock == nil {
&TaprootNUMSKey, settleControlBlock := MakeTaprootCtrlBlock(
signDesc.WitnessScript, &TaprootNUMSKey, scriptTree,
) )
ctrlBytes, err := settleControlBlock.ToBytes()
if err != nil {
return nil, err
}
ctrlBlockBytes = ctrlBytes
} else {
ctrlBlockBytes = signDesc.ControlBlock
}
// With the control block created, we'll now generate the signature we // With the control block created, we'll now generate the signature we
// need to authorize the spend. // need to authorize the spend.
@ -1977,7 +2023,7 @@ func TaprootCommitSpendSuccess(signer Signer, signDesc *SignDescriptor,
witnessStack := make(wire.TxWitness, 3) witnessStack := make(wire.TxWitness, 3)
witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType) witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType)
witnessStack[1] = signDesc.WitnessScript witnessStack[1] = signDesc.WitnessScript
witnessStack[2], err = settleControlBlock.ToBytes() witnessStack[2] = ctrlBlockBytes
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1993,14 +2039,20 @@ func TaprootCommitSpendRevoke(signer Signer, signDesc *SignDescriptor,
// First, we'll need to construct a valid control block to execute the // First, we'll need to construct a valid control block to execute the
// leaf script for revocation path. // leaf script for revocation path.
revokeTapleafHash := txscript.NewBaseTapLeaf( var ctrlBlockBytes []byte
signDesc.WitnessScript, if signDesc.ControlBlock == nil {
).TapHash() revokeCtrlBlock := MakeTaprootCtrlBlock(
revokeIdx := scriptTree.LeafProofIndex[revokeTapleafHash] signDesc.WitnessScript, &TaprootNUMSKey, scriptTree,
revokeMerkleProof := scriptTree.LeafMerkleProofs[revokeIdx]
revokeControlBlock := revokeMerkleProof.ToControlBlock(
&TaprootNUMSKey,
) )
revokeBytes, err := revokeCtrlBlock.ToBytes()
if err != nil {
return nil, err
}
ctrlBlockBytes = revokeBytes
} else {
ctrlBlockBytes = signDesc.ControlBlock
}
// With the control block created, we'll now generate the signature we // With the control block created, we'll now generate the signature we
// need to authorize the spend. // need to authorize the spend.
@ -2015,10 +2067,7 @@ func TaprootCommitSpendRevoke(signer Signer, signDesc *SignDescriptor,
witnessStack := make(wire.TxWitness, 3) witnessStack := make(wire.TxWitness, 3)
witnessStack[0] = maybeAppendSighash(revokeSig, signDesc.HashType) witnessStack[0] = maybeAppendSighash(revokeSig, signDesc.HashType)
witnessStack[1] = signDesc.WitnessScript witnessStack[1] = signDesc.WitnessScript
witnessStack[2], err = revokeControlBlock.ToBytes() witnessStack[2] = ctrlBlockBytes
if err != nil {
return nil, err
}
return witnessStack, nil return witnessStack, nil
} }
@ -2307,12 +2356,20 @@ func TaprootCommitRemoteSpend(signer Signer, signDesc *SignDescriptor,
// First, we'll need to construct a valid control block to execute the // First, we'll need to construct a valid control block to execute the
// leaf script for sweep settlement. // leaf script for sweep settlement.
settleTapleafHash := txscript.NewBaseTapLeaf( var ctrlBlockBytes []byte
signDesc.WitnessScript, if signDesc.ControlBlock == nil {
).TapHash() settleControlBlock := MakeTaprootCtrlBlock(
settleIdx := scriptTree.LeafProofIndex[settleTapleafHash] signDesc.WitnessScript, &TaprootNUMSKey, scriptTree,
settleMerkleProof := scriptTree.LeafMerkleProofs[settleIdx] )
settleControlBlock := settleMerkleProof.ToControlBlock(&TaprootNUMSKey) ctrlBytes, err := settleControlBlock.ToBytes()
if err != nil {
return nil, err
}
ctrlBlockBytes = ctrlBytes
} else {
ctrlBlockBytes = signDesc.ControlBlock
}
// With the control block created, we'll now generate the signature we // With the control block created, we'll now generate the signature we
// need to authorize the spend. // need to authorize the spend.
@ -2327,10 +2384,7 @@ func TaprootCommitRemoteSpend(signer Signer, signDesc *SignDescriptor,
witnessStack := make(wire.TxWitness, 3) witnessStack := make(wire.TxWitness, 3)
witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType) witnessStack[0] = maybeAppendSighash(sweepSig, signDesc.HashType)
witnessStack[1] = signDesc.WitnessScript witnessStack[1] = signDesc.WitnessScript
witnessStack[2], err = settleControlBlock.ToBytes() witnessStack[2] = ctrlBlockBytes
if err != nil {
return nil, err
}
return witnessStack, nil return witnessStack, nil
} }
@ -2507,11 +2561,11 @@ func TaprootOutputKeyAnchor(key *btcec.PublicKey) (*btcec.PublicKey, error) {
// TaprootAnchorSpend constructs a valid witness allowing a node to sweep their // TaprootAnchorSpend constructs a valid witness allowing a node to sweep their
// anchor output. // anchor output.
func TaprootAnchorSpend(signer Signer, signDesc *SignDescriptor, func TaprootAnchorSpend(signer Signer, signDesc *SignDescriptor,
revokeTx *wire.MsgTx) (wire.TxWitness, error) { sweepTx *wire.MsgTx) (wire.TxWitness, error) {
// For this spend type, we only need a single signature which'll be a // For this spend type, we only need a single signature which'll be a
// keyspend using the revoke private key. // keyspend using the anchor private key.
sweepSig, err := signer.SignOutputRaw(revokeTx, signDesc) sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -98,6 +98,13 @@ type SignDescriptor struct {
// This MUST be set when spending Taproot outputs. // This MUST be set when spending Taproot outputs.
PrevOutputFetcher txscript.PrevOutputFetcher PrevOutputFetcher txscript.PrevOutputFetcher
// ControlBlock is a fully serialized control block that contains the
// merkle proof necessary to spend a taproot output. This may
// optionally be set if the SignMethod is
// input.TaprootScriptSpendSignMethod. In which case, this should be an
// inclusion proof for the WitnessScript.
ControlBlock []byte
// InputIndex is the target input within the transaction that should be // InputIndex is the target input within the transaction that should be
// signed. // signed.
InputIndex int InputIndex int
@ -218,6 +225,8 @@ func WriteSignDescriptor(w io.Writer, sd *SignDescriptor) error {
return err return err
} }
// TODO(roasbeef): also write ctrl block?
return nil return nil
} }

View File

@ -998,7 +998,7 @@ var witnessSizeTests = []witnessSizeTest{
} }
witness, err := input.TaprootHtlcSpendSuccess( witness, err := input.TaprootHtlcSpendSuccess(
signer, signDesc, revokeKey.PubKey(), testTx, signer, signDesc, testTx, revokeKey.PubKey(),
scriptTree, scriptTree,
) )
require.NoError(t, err) require.NoError(t, err)

View File

@ -1675,8 +1675,8 @@ func secondLevelHtlcSuccessWitGen(sigHash txscript.SigHashType,
} }
return TaprootHtlcSpendSuccess( return TaprootHtlcSpendSuccess(
signer, signDesc, scriptTree.revokeKey.PubKey(), signer, signDesc, spendTx,
spendTx, scriptTree.scriptTree, scriptTree.revokeKey.PubKey(), scriptTree.scriptTree,
) )
} }
} }

View File

@ -515,6 +515,205 @@ func (wt StandardWitnessType) WitnessGenerator(signer Signer,
case NestedWitnessKeyHash: case NestedWitnessKeyHash:
return signer.ComputeInputScript(tx, desc) return signer.ComputeInputScript(tx, desc)
case TaprootLocalCommitSpend:
// Ensure that the sign desc has the proper sign method
// set, and a valid prev output fetcher.
desc.SignMethod = TaprootScriptSpendSignMethod
// The control block bytes must be set at this point.
if desc.ControlBlock == nil {
return nil, fmt.Errorf("control block must be " +
"set for taproot spend")
}
witness, err := TaprootCommitSpendSuccess(
signer, desc, tx, nil,
)
if err != nil {
return nil, err
}
return &Script{
Witness: witness,
}, nil
case TaprootRemoteCommitSpend:
// Ensure that the sign desc has the proper sign method
// set, and a valid prev output fetcher.
desc.SignMethod = TaprootScriptSpendSignMethod
// The control block bytes must be set at this point.
if desc.ControlBlock == nil {
return nil, fmt.Errorf("control block must be " +
"set for taproot spend")
}
witness, err := TaprootCommitRemoteSpend(
signer, desc, tx, nil,
)
if err != nil {
return nil, err
}
return &Script{
Witness: witness,
}, nil
case TaprootAnchorSweepSpend:
// Ensure that the sign desc has the proper sign method
// set, and a valid prev output fetcher.
desc.SignMethod = TaprootKeySpendSignMethod
// The tap tweak must be set at this point.
if desc.TapTweak == nil {
return nil, fmt.Errorf("tap tweak must be " +
"set for keyspend")
}
witness, err := TaprootAnchorSpend(
signer, desc, tx,
)
if err != nil {
return nil, err
}
return &Script{
Witness: witness,
}, nil
case TaprootHtlcOfferedTimeoutSecondLevel,
TaprootHtlcAcceptedSuccessSecondLevel:
// Ensure that the sign desc has the proper sign method
// set, and a valid prev output fetcher.
desc.SignMethod = TaprootScriptSpendSignMethod
// The control block bytes must be set at this point.
if desc.ControlBlock == nil {
return nil, fmt.Errorf("control block must be " +
"set for taproot spend")
}
witness, err := TaprootHtlcSpendSuccess(
signer, desc, tx, nil, nil,
)
if err != nil {
return nil, err
}
return &Script{
Witness: witness,
}, nil
case TaprootHtlcSecondLevelRevoke:
// Ensure that the sign desc has the proper sign method
// set, and a valid prev output fetcher.
desc.SignMethod = TaprootKeySpendSignMethod
// The tap tweak must be set at this point.
if desc.TapTweak == nil {
return nil, fmt.Errorf("tap tweak must be " +
"set for keyspend")
}
witness, err := TaprootHtlcSpendRevoke(
signer, desc, tx,
)
if err != nil {
return nil, err
}
return &Script{
Witness: witness,
}, nil
case TaprootHtlcOfferedRevoke:
// Ensure that the sign desc has the proper sign method
// set, and a valid prev output fetcher.
desc.SignMethod = TaprootKeySpendSignMethod
// The tap tweak must be set at this point.
if desc.TapTweak == nil {
return nil, fmt.Errorf("tap tweak must be " +
"set for keyspend")
}
witness, err := SenderHTLCScriptTaprootRevoke(
signer, desc, tx,
)
if err != nil {
return nil, err
}
return &Script{
Witness: witness,
}, nil
case TaprootHtlcAcceptedRevoke:
// Ensure that the sign desc has the proper sign method
// set, and a valid prev output fetcher.
desc.SignMethod = TaprootKeySpendSignMethod
// The tap tweak must be set at this point.
if desc.TapTweak == nil {
return nil, fmt.Errorf("tap tweak must be " +
"set for keyspend")
}
witness, err := ReceiverHTLCScriptTaprootRevoke(
signer, desc, tx,
)
if err != nil {
return nil, err
}
return &Script{
Witness: witness,
}, nil
case TaprootHtlcOfferedRemoteTimeout:
// Ensure that the sign desc has the proper sign method
// set, and a valid prev output fetcher.
desc.SignMethod = TaprootScriptSpendSignMethod
// The control block bytes must be set at this point.
if desc.ControlBlock == nil {
return nil, fmt.Errorf("control block must be " +
"set for taproot spend")
}
witness, err := ReceiverHTLCScriptTaprootTimeout(
signer, desc, tx, -1, nil, nil,
)
if err != nil {
return nil, err
}
return &Script{
Witness: witness,
}, nil
case TaprootCommitmentRevoke:
// Ensure that the sign desc has the proper sign method
// set, and a valid prev output fetcher.
desc.SignMethod = TaprootScriptSpendSignMethod
// The control block bytes must be set at this point.
if desc.ControlBlock == nil {
return nil, fmt.Errorf("control block " +
"must be set for taproot spend")
}
witness, err := TaprootCommitSpendRevoke(
signer, desc, tx, nil,
)
if err != nil {
return nil, err
}
return &Script{
Witness: witness,
}, nil
default: default:
return nil, fmt.Errorf("unknown witness type: %v", wt) return nil, fmt.Errorf("unknown witness type: %v", wt)
} }