2022-01-07 02:19:53 +01:00
|
|
|
// Copyright (c) 2013-2022 The btcsuite developers
|
|
|
|
// Use of this source code is governed by an ISC
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package txscript
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/btcsuite/btcd/btcec/v2"
|
|
|
|
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
|
|
|
|
"github.com/btcsuite/btcd/btcec/v2/schnorr"
|
|
|
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
|
|
|
"github.com/btcsuite/btcd/wire"
|
|
|
|
)
|
|
|
|
|
|
|
|
// signatureVerifier is an abstract interface that allows the op code execution
|
|
|
|
// to abstract over the _type_ of signature validation being executed. At this
|
|
|
|
// point in Bitcoin's history, there're four possible sig validation contexts:
|
|
|
|
// pre-segwit, segwit v0, segwit v1 (taproot key spend validation), and the
|
|
|
|
// base tapscript verification.
|
|
|
|
type signatureVerifier interface {
|
2024-04-10 19:58:44 +02:00
|
|
|
// Verify returns whether or not the signature verifier context deems the
|
2022-01-07 02:19:53 +01:00
|
|
|
// signature to be valid for the given context.
|
2024-04-10 19:58:44 +02:00
|
|
|
Verify() verifyResult
|
|
|
|
}
|
|
|
|
|
|
|
|
type verifyResult struct {
|
|
|
|
sigValid bool
|
|
|
|
sigMatch bool
|
2022-01-07 02:19:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// baseSigVerifier is used to verify signatures for the _base_ system, meaning
|
|
|
|
// ECDSA signatures encoded in DER or BER encoding.
|
|
|
|
type baseSigVerifier struct {
|
|
|
|
vm *Engine
|
|
|
|
|
|
|
|
pubKey *btcec.PublicKey
|
|
|
|
|
|
|
|
sig *ecdsa.Signature
|
|
|
|
|
|
|
|
fullSigBytes []byte
|
|
|
|
|
|
|
|
sigBytes []byte
|
|
|
|
pkBytes []byte
|
|
|
|
|
|
|
|
subScript []byte
|
|
|
|
|
|
|
|
hashType SigHashType
|
|
|
|
}
|
|
|
|
|
|
|
|
// parseBaseSigAndPubkey attempts to parse a signature and public key according
|
|
|
|
// to the base consensus rules, which expect an 33-byte public key and DER or
|
|
|
|
// BER encoded signature.
|
|
|
|
func parseBaseSigAndPubkey(pkBytes, fullSigBytes []byte,
|
|
|
|
vm *Engine) (*btcec.PublicKey, *ecdsa.Signature, SigHashType, error) {
|
|
|
|
|
|
|
|
strictEncoding := vm.hasFlag(ScriptVerifyStrictEncoding) ||
|
|
|
|
vm.hasFlag(ScriptVerifyDERSignatures)
|
|
|
|
|
|
|
|
// Trim off hashtype from the signature string and check if the
|
|
|
|
// signature and pubkey conform to the strict encoding requirements
|
|
|
|
// depending on the flags.
|
|
|
|
//
|
|
|
|
// NOTE: When the strict encoding flags are set, any errors in the
|
|
|
|
// signature or public encoding here result in an immediate script error
|
|
|
|
// (and thus no result bool is pushed to the data stack). This differs
|
|
|
|
// from the logic below where any errors in parsing the signature is
|
|
|
|
// treated as the signature failure resulting in false being pushed to
|
|
|
|
// the data stack. This is required because the more general script
|
|
|
|
// validation consensus rules do not have the new strict encoding
|
|
|
|
// requirements enabled by the flags.
|
|
|
|
hashType := SigHashType(fullSigBytes[len(fullSigBytes)-1])
|
|
|
|
sigBytes := fullSigBytes[:len(fullSigBytes)-1]
|
|
|
|
if err := vm.checkHashTypeEncoding(hashType); err != nil {
|
|
|
|
return nil, nil, 0, err
|
|
|
|
}
|
|
|
|
if err := vm.checkSignatureEncoding(sigBytes); err != nil {
|
|
|
|
return nil, nil, 0, err
|
|
|
|
}
|
|
|
|
if err := vm.checkPubKeyEncoding(pkBytes); err != nil {
|
|
|
|
return nil, nil, 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// First, parse the public key, which we expect to be in the proper
|
|
|
|
// encoding.
|
|
|
|
pubKey, err := btcec.ParsePubKey(pkBytes)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Next, parse the signature which should be in DER or BER depending on
|
|
|
|
// the active script flags.
|
|
|
|
var signature *ecdsa.Signature
|
|
|
|
if strictEncoding {
|
|
|
|
signature, err = ecdsa.ParseDERSignature(sigBytes)
|
|
|
|
} else {
|
|
|
|
signature, err = ecdsa.ParseSignature(sigBytes)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return pubKey, signature, hashType, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// newBaseSigVerifier returns a new instance of the base signature verifier. An
|
|
|
|
// error is returned if the signature, sighash, or public key aren't correctly
|
|
|
|
// encoded.
|
|
|
|
func newBaseSigVerifier(pkBytes, fullSigBytes []byte,
|
|
|
|
vm *Engine) (*baseSigVerifier, error) {
|
|
|
|
|
|
|
|
pubKey, sig, hashType, err := parseBaseSigAndPubkey(
|
|
|
|
pkBytes, fullSigBytes, vm,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get script starting from the most recent OP_CODESEPARATOR.
|
|
|
|
subScript := vm.subScript()
|
|
|
|
|
|
|
|
return &baseSigVerifier{
|
|
|
|
vm: vm,
|
|
|
|
pubKey: pubKey,
|
|
|
|
pkBytes: pkBytes,
|
|
|
|
sig: sig,
|
|
|
|
sigBytes: fullSigBytes[:len(fullSigBytes)-1],
|
|
|
|
subScript: subScript,
|
|
|
|
hashType: hashType,
|
|
|
|
fullSigBytes: fullSigBytes,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// verifySig attempts to verify the signature given the computed sighash. A nil
|
|
|
|
// error is returned if the signature is valid.
|
|
|
|
func (b *baseSigVerifier) verifySig(sigHash []byte) bool {
|
|
|
|
var valid bool
|
|
|
|
if b.vm.sigCache != nil {
|
|
|
|
var sigHashBytes chainhash.Hash
|
|
|
|
copy(sigHashBytes[:], sigHash[:])
|
|
|
|
|
|
|
|
valid = b.vm.sigCache.Exists(sigHashBytes, b.sigBytes, b.pkBytes)
|
|
|
|
if !valid && b.sig.Verify(sigHash, b.pubKey) {
|
|
|
|
b.vm.sigCache.Add(sigHashBytes, b.sigBytes, b.pkBytes)
|
|
|
|
valid = true
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
valid = b.sig.Verify(sigHash, b.pubKey)
|
|
|
|
}
|
|
|
|
|
|
|
|
return valid
|
|
|
|
}
|
|
|
|
|
2024-04-10 19:58:44 +02:00
|
|
|
// Verify returns whether or not the signature verifier context deems the
|
|
|
|
// signature to be valid for the given context.
|
2022-01-07 02:19:53 +01:00
|
|
|
//
|
|
|
|
// NOTE: This is part of the baseSigVerifier interface.
|
2024-04-10 19:58:44 +02:00
|
|
|
func (b *baseSigVerifier) Verify() verifyResult {
|
2022-01-07 02:19:53 +01:00
|
|
|
// Remove the signature since there is no way for a signature
|
|
|
|
// to sign itself.
|
2024-04-10 19:58:44 +02:00
|
|
|
subScript, match := removeOpcodeByData(b.subScript, b.fullSigBytes)
|
2022-01-07 02:19:53 +01:00
|
|
|
|
|
|
|
sigHash := calcSignatureHash(
|
|
|
|
subScript, b.hashType, &b.vm.tx, b.vm.txIdx,
|
|
|
|
)
|
|
|
|
|
2024-04-10 19:58:44 +02:00
|
|
|
return verifyResult{
|
|
|
|
sigValid: b.verifySig(sigHash),
|
|
|
|
sigMatch: match,
|
|
|
|
}
|
2022-01-07 02:19:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// A compile-time assertion to ensure baseSigVerifier implements the
|
|
|
|
// signatureVerifier interface.
|
|
|
|
var _ signatureVerifier = (*baseSigVerifier)(nil)
|
|
|
|
|
|
|
|
// baseSegwitSigVerifier implements signature verification for segwit v0. The
|
|
|
|
// only difference between this and the baseSigVerifier is how the sighash is
|
|
|
|
// computed.
|
|
|
|
type baseSegwitSigVerifier struct {
|
|
|
|
*baseSigVerifier
|
|
|
|
}
|
|
|
|
|
|
|
|
// newBaseSegwitSigVerifier returns a new instance of the base segwit verifier.
|
|
|
|
func newBaseSegwitSigVerifier(pkBytes, fullSigBytes []byte,
|
|
|
|
vm *Engine) (*baseSegwitSigVerifier, error) {
|
|
|
|
|
|
|
|
sigVerifier, err := newBaseSigVerifier(pkBytes, fullSigBytes, vm)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &baseSegwitSigVerifier{
|
|
|
|
baseSigVerifier: sigVerifier,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify returns true if the signature verifier context deems the signature to
|
|
|
|
// be valid for the given context.
|
|
|
|
//
|
|
|
|
// NOTE: This is part of the baseSigVerifier interface.
|
2024-04-10 19:58:44 +02:00
|
|
|
func (s *baseSegwitSigVerifier) Verify() verifyResult {
|
2022-01-07 02:19:53 +01:00
|
|
|
var sigHashes *TxSigHashes
|
|
|
|
if s.vm.hashCache != nil {
|
|
|
|
sigHashes = s.vm.hashCache
|
|
|
|
} else {
|
|
|
|
sigHashes = NewTxSigHashes(&s.vm.tx, s.vm.prevOutFetcher)
|
|
|
|
}
|
|
|
|
|
|
|
|
sigHash, err := calcWitnessSignatureHashRaw(
|
|
|
|
s.subScript, sigHashes, s.hashType, &s.vm.tx, s.vm.txIdx,
|
|
|
|
s.vm.inputAmount,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
// TODO(roasbeef): this doesn't need to return an error, should
|
|
|
|
// instead be further up the stack? this only returns an error
|
|
|
|
// if the input index is greater than the number of inputs
|
2024-04-10 19:58:44 +02:00
|
|
|
return verifyResult{}
|
2022-01-07 02:19:53 +01:00
|
|
|
}
|
|
|
|
|
2024-04-10 19:58:44 +02:00
|
|
|
return verifyResult{
|
|
|
|
sigValid: s.verifySig(sigHash),
|
|
|
|
}
|
2022-01-07 02:19:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// A compile-time assertion to ensure baseSegwitSigVerifier implements the
|
|
|
|
// signatureVerifier interface.
|
|
|
|
var _ signatureVerifier = (*baseSegwitSigVerifier)(nil)
|
|
|
|
|
|
|
|
// taprootSigVerifier verifies signatures according to the segwit v1 rules,
|
|
|
|
// which are described in BIP 341.
|
|
|
|
type taprootSigVerifier struct {
|
|
|
|
pubKey *btcec.PublicKey
|
|
|
|
pkBytes []byte
|
|
|
|
|
|
|
|
fullSigBytes []byte
|
|
|
|
sig *schnorr.Signature
|
|
|
|
|
|
|
|
hashType SigHashType
|
|
|
|
|
|
|
|
sigCache *SigCache
|
|
|
|
hashCache *TxSigHashes
|
|
|
|
|
|
|
|
tx *wire.MsgTx
|
|
|
|
|
|
|
|
inputIndex int
|
|
|
|
|
|
|
|
annex []byte
|
|
|
|
|
|
|
|
prevOuts PrevOutputFetcher
|
|
|
|
}
|
|
|
|
|
|
|
|
// parseTaprootSigAndPubKey attempts to parse the public key and signature for
|
|
|
|
// a taproot spend that may be a keyspend or script path spend. This function
|
|
|
|
// returns an error if the pubkey is invalid, or the sig is.
|
|
|
|
func parseTaprootSigAndPubKey(pkBytes, rawSig []byte,
|
|
|
|
) (*btcec.PublicKey, *schnorr.Signature, SigHashType, error) {
|
|
|
|
|
|
|
|
// Now that we have the raw key, we'll parse it into a schnorr public
|
|
|
|
// key we can work with.
|
|
|
|
pubKey, err := schnorr.ParsePubKey(pkBytes)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Next, we'll parse the signature, which may or may not be appended
|
|
|
|
// with the desired sighash flag.
|
|
|
|
var (
|
|
|
|
sig *schnorr.Signature
|
|
|
|
sigHashType SigHashType
|
|
|
|
)
|
|
|
|
switch {
|
|
|
|
// If the signature is exactly 64 bytes, then we know we're using the
|
|
|
|
// implicit SIGHASH_DEFAULT sighash type.
|
|
|
|
case len(rawSig) == schnorr.SignatureSize:
|
|
|
|
// First, parse out the signature which is just the raw sig itself.
|
|
|
|
sig, err = schnorr.ParseSignature(rawSig)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the sig is 64 bytes, then we'll assume that it's the
|
|
|
|
// default sighash type, which is actually an alias for
|
|
|
|
// SIGHASH_ALL.
|
|
|
|
sigHashType = SigHashDefault
|
|
|
|
|
|
|
|
// Otherwise, if this is a signature, with a sighash looking byte
|
|
|
|
// appended that isn't all zero, then we'll extract the sighash from
|
|
|
|
// the end of the signature.
|
|
|
|
case len(rawSig) == schnorr.SignatureSize+1 && rawSig[64] != 0:
|
|
|
|
// Extract the sighash type, then snip off the last byte so we can
|
|
|
|
// parse the signature.
|
|
|
|
sigHashType = SigHashType(rawSig[schnorr.SignatureSize])
|
|
|
|
|
|
|
|
rawSig = rawSig[:schnorr.SignatureSize]
|
|
|
|
sig, err = schnorr.ParseSignature(rawSig)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, this is an invalid signature, so we need to bail out.
|
|
|
|
default:
|
2022-03-16 01:49:45 +01:00
|
|
|
str := fmt.Sprintf("invalid sig len: %v", len(rawSig))
|
|
|
|
return nil, nil, 0, scriptError(ErrInvalidTaprootSigLen, str)
|
2022-01-07 02:19:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return pubKey, sig, sigHashType, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// newTaprootSigVerifier returns a new instance of a taproot sig verifier given
|
|
|
|
// the necessary contextual information.
|
|
|
|
func newTaprootSigVerifier(pkBytes []byte, fullSigBytes []byte,
|
|
|
|
tx *wire.MsgTx, inputIndex int, prevOuts PrevOutputFetcher,
|
|
|
|
sigCache *SigCache, hashCache *TxSigHashes,
|
|
|
|
annex []byte) (*taprootSigVerifier, error) {
|
|
|
|
|
|
|
|
pubKey, sig, sigHashType, err := parseTaprootSigAndPubKey(
|
|
|
|
pkBytes, fullSigBytes,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &taprootSigVerifier{
|
|
|
|
pubKey: pubKey,
|
|
|
|
pkBytes: pkBytes,
|
|
|
|
sig: sig,
|
|
|
|
fullSigBytes: fullSigBytes,
|
|
|
|
hashType: sigHashType,
|
|
|
|
tx: tx,
|
|
|
|
inputIndex: inputIndex,
|
|
|
|
prevOuts: prevOuts,
|
|
|
|
sigCache: sigCache,
|
|
|
|
hashCache: hashCache,
|
|
|
|
annex: annex,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// verifySig attempts to verify a BIP 340 signature using the internal public
|
|
|
|
// key and signature, and the passed sigHash as the message digest.
|
|
|
|
func (t *taprootSigVerifier) verifySig(sigHash []byte) bool {
|
|
|
|
// At this point, we can check to see if this signature is already
|
2024-03-25 14:44:25 +01:00
|
|
|
// included in the sigCache and is valid or not (if one was passed in).
|
2022-01-07 02:19:53 +01:00
|
|
|
cacheKey, _ := chainhash.NewHash(sigHash)
|
|
|
|
if t.sigCache != nil {
|
|
|
|
if t.sigCache.Exists(*cacheKey, t.fullSigBytes, t.pkBytes) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we didn't find the entry in the cache, then we'll perform full
|
|
|
|
// verification as normal, adding the entry to the cache if it's found
|
|
|
|
// to be valid.
|
|
|
|
sigValid := t.sig.Verify(sigHash, t.pubKey)
|
|
|
|
if sigValid {
|
|
|
|
if t.sigCache != nil {
|
|
|
|
// The sig is valid, so we'll add it to the cache.
|
|
|
|
t.sigCache.Add(*cacheKey, t.fullSigBytes, t.pkBytes)
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise the sig is invalid if we get to this point.
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2024-04-10 19:58:44 +02:00
|
|
|
// Verify returns whether or not the signature verifier context deems the
|
|
|
|
// signature to be valid for the given context.
|
2022-01-07 02:19:53 +01:00
|
|
|
//
|
|
|
|
// NOTE: This is part of the baseSigVerifier interface.
|
2024-04-10 19:58:44 +02:00
|
|
|
func (t *taprootSigVerifier) Verify() verifyResult {
|
2022-01-07 02:19:53 +01:00
|
|
|
var opts []TaprootSigHashOption
|
|
|
|
if t.annex != nil {
|
|
|
|
opts = append(opts, WithAnnex(t.annex))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Before we attempt to verify the signature, we'll need to first
|
|
|
|
// compute the sighash based on the input and tx information.
|
|
|
|
sigHash, err := calcTaprootSignatureHashRaw(
|
|
|
|
t.hashCache, t.hashType, t.tx, t.inputIndex, t.prevOuts,
|
|
|
|
opts...,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
// TODO(roasbeef): propagate the error here?
|
2024-04-10 19:58:44 +02:00
|
|
|
return verifyResult{}
|
2022-01-07 02:19:53 +01:00
|
|
|
}
|
|
|
|
|
2024-04-10 19:58:44 +02:00
|
|
|
return verifyResult{
|
|
|
|
sigValid: t.verifySig(sigHash),
|
|
|
|
}
|
2022-01-07 02:19:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// A compile-time assertion to ensure taprootSigVerifier implements the
|
|
|
|
// signatureVerifier interface.
|
|
|
|
var _ signatureVerifier = (*taprootSigVerifier)(nil)
|
|
|
|
|
|
|
|
// baseTapscriptSigVerifier verifies a signature for an input spending a
|
2024-04-10 16:08:30 +02:00
|
|
|
// tapscript leaf from the previous output.
|
2022-01-07 02:19:53 +01:00
|
|
|
type baseTapscriptSigVerifier struct {
|
|
|
|
*taprootSigVerifier
|
|
|
|
|
|
|
|
vm *Engine
|
|
|
|
}
|
|
|
|
|
|
|
|
// newBaseTapscriptSigVerifier returns a new sig verifier for tapscript input
|
|
|
|
// spends. If the public key or signature aren't correctly formatted, an error
|
|
|
|
// is returned.
|
|
|
|
func newBaseTapscriptSigVerifier(pkBytes, rawSig []byte,
|
|
|
|
vm *Engine) (*baseTapscriptSigVerifier, error) {
|
|
|
|
|
|
|
|
switch len(pkBytes) {
|
|
|
|
// If the public key is zero bytes, then this is invalid, and will fail
|
|
|
|
// immediately.
|
|
|
|
case 0:
|
2022-03-16 01:49:45 +01:00
|
|
|
return nil, scriptError(ErrTaprootPubkeyIsEmpty, "")
|
2022-01-07 02:19:53 +01:00
|
|
|
|
|
|
|
// If the public key is 32 byte as we expect, then we'll parse things
|
|
|
|
// as normal.
|
|
|
|
case 32:
|
|
|
|
baseTaprootVerifier, err := newTaprootSigVerifier(
|
|
|
|
pkBytes, rawSig, &vm.tx, vm.txIdx, vm.prevOutFetcher,
|
|
|
|
vm.sigCache, vm.hashCache, vm.taprootCtx.annex,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &baseTapscriptSigVerifier{
|
|
|
|
taprootSigVerifier: baseTaprootVerifier,
|
|
|
|
vm: vm,
|
|
|
|
}, nil
|
|
|
|
|
|
|
|
// Otherwise, we consider this to be an unknown public key, which means
|
|
|
|
// that we'll just assume the sig to be valid.
|
|
|
|
default:
|
|
|
|
// However, if the flag preventing usage of unknown key types
|
|
|
|
// is active, then we'll return that error.
|
|
|
|
if vm.hasFlag(ScriptVerifyDiscourageUpgradeablePubkeyType) {
|
2022-01-07 02:34:19 +01:00
|
|
|
str := fmt.Sprintf("pubkey of length %v was used",
|
2022-01-07 02:19:53 +01:00
|
|
|
len(pkBytes))
|
|
|
|
return nil, scriptError(
|
|
|
|
ErrDiscourageUpgradeablePubKeyType, str,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &baseTapscriptSigVerifier{
|
|
|
|
taprootSigVerifier: &taprootSigVerifier{},
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-10 19:58:44 +02:00
|
|
|
// Verify returns whether or not the signature verifier context deems the
|
|
|
|
// signature to be valid for the given context.
|
2022-01-07 02:19:53 +01:00
|
|
|
//
|
|
|
|
// NOTE: This is part of the baseSigVerifier interface.
|
2024-04-10 19:58:44 +02:00
|
|
|
func (b *baseTapscriptSigVerifier) Verify() verifyResult {
|
2022-01-07 02:19:53 +01:00
|
|
|
// If the public key is blank, then that means it wasn't 0 or 32 bytes,
|
|
|
|
// so we'll treat this as an unknown public key version and return
|
2024-04-10 19:58:44 +02:00
|
|
|
// that it's valid.
|
2022-01-07 02:19:53 +01:00
|
|
|
if b.pubKey == nil {
|
2024-04-10 19:58:44 +02:00
|
|
|
return verifyResult{
|
|
|
|
sigValid: true,
|
|
|
|
}
|
2022-01-07 02:19:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
var opts []TaprootSigHashOption
|
|
|
|
opts = append(opts, WithBaseTapscriptVersion(
|
|
|
|
b.vm.taprootCtx.codeSepPos, b.vm.taprootCtx.tapLeafHash[:],
|
|
|
|
))
|
|
|
|
|
|
|
|
if b.vm.taprootCtx.annex != nil {
|
|
|
|
opts = append(opts, WithAnnex(b.vm.taprootCtx.annex))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we'll compute the sighash using the tapscript message
|
|
|
|
// extensions and return the outcome.
|
|
|
|
sigHash, err := calcTaprootSignatureHashRaw(
|
|
|
|
b.hashCache, b.hashType, b.tx, b.inputIndex, b.prevOuts,
|
|
|
|
opts...,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
// TODO(roasbeef): propagate the error here?
|
2024-04-10 19:58:44 +02:00
|
|
|
return verifyResult{}
|
2022-01-07 02:19:53 +01:00
|
|
|
}
|
|
|
|
|
2024-04-10 19:58:44 +02:00
|
|
|
return verifyResult{
|
|
|
|
sigValid: b.verifySig(sigHash),
|
|
|
|
}
|
2022-01-07 02:19:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// A compile-time assertion to ensure baseTapscriptSigVerifier implements the
|
|
|
|
// signatureVerifier interface.
|
|
|
|
var _ signatureVerifier = (*baseTapscriptSigVerifier)(nil)
|