mirror of
https://github.com/btcsuite/btcd.git
synced 2025-02-23 22:47:01 +01:00
In this commit, we add a new signatureVerifier interface that will allow us to consolidate a lot of code as we'll now have 4 distinct sig+sighash types to verify: 1. pre-segwit 2. segwit v0 3. segwit v1 (taproot key spend) 4. tapscript spends We'll need to be able to handle 3 of the cases for the modified OP_CHECKSIG operator. This new abstraction allows us to keep the implementation of the function somewhat succinct. In this commit we implement a verifier for #3 which is needed to verify the top-level taproot keyspend. We expose the verifier using a new VerifyTaprootKeySpend function.
50 lines
1.4 KiB
Go
50 lines
1.4 KiB
Go
package txscript
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/btcsuite/btcd/wire"
|
|
)
|
|
|
|
// VerifyTaprootKeySpend attempts to verify a top-level taproot key spend,
|
|
// returning a non-nil error if the passed signature is invalid. If a sigCache
|
|
// is passed in, then the sig cache will be consulted to skip full verification
|
|
// of a signature that has already been seen. Witness program here should be
|
|
// the 32-byte x-only schnorr output public key.
|
|
//
|
|
// NOTE: The TxSigHashes MUST be passed in and fully populated.
|
|
func VerifyTaprootKeySpend(witnessProgram []byte, rawSig []byte, tx *wire.MsgTx,
|
|
inputIndex int, prevOuts PrevOutputFetcher, hashCache *TxSigHashes,
|
|
sigCache *SigCache) error {
|
|
|
|
// First, we'll need to extract the public key from the witness
|
|
// program.
|
|
rawKey := witnessProgram
|
|
|
|
// Extract the annex if it exists, so we can compute the proper proper
|
|
// sighash below.
|
|
var annex []byte
|
|
witness := tx.TxIn[inputIndex].Witness
|
|
if isAnnexedWitness(witness) {
|
|
annex, _ = extractAnnex(witness)
|
|
}
|
|
|
|
// Now that we have the public key, we can create a new top-level
|
|
// keyspend verifier that'll handle all the sighash and schnorr
|
|
// specifics for us.
|
|
keySpendVerifier, err := newTaprootSigVerifier(
|
|
rawKey, rawSig, tx, inputIndex, prevOuts, sigCache,
|
|
hashCache, annex,
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
valid := keySpendVerifier.Verify()
|
|
if valid {
|
|
return nil
|
|
}
|
|
|
|
// TODO(roasbeef): add proper error
|
|
return fmt.Errorf("invalid sig")
|
|
}
|