btcd/txscript/sigvalidate.go

480 lines
14 KiB
Go
Raw Normal View History

// 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 {
// Verify returns true if the signature verifier context deems the
// signature to be valid for the given context.
Verify() bool
}
// 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
}
// 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.
func (b *baseSigVerifier) Verify() bool {
// Remove the signature since there is no way for a signature
// to sign itself.
subScript := removeOpcodeByData(b.subScript, b.fullSigBytes)
sigHash := calcSignatureHash(
subScript, b.hashType, &b.vm.tx, b.vm.txIdx,
)
return b.verifySig(sigHash)
}
// 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.
func (s *baseSegwitSigVerifier) Verify() bool {
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
return false
}
return s.verifySig(sigHash)
}
// 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:
str := fmt.Sprintf("invalid sig len: %v", len(rawSig))
return nil, nil, 0, scriptError(ErrInvalidTaprootSigLen, str)
}
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
// included in the sigCcahe and is valid or not (if one was passed in).
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
}
// 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.
func (t *taprootSigVerifier) Verify() bool {
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?
return false
}
return t.verifySig(sigHash)
}
// A compile-time assertion to ensure taprootSigVerifier implements the
// signatureVerifier interface.
var _ signatureVerifier = (*taprootSigVerifier)(nil)
// baseTapscriptSigVerifier verifies a signature for an input spending a
// tapscript leaf from the prevoous output.
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:
return nil, scriptError(ErrTaprootPubkeyIsEmpty, "")
// 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) {
str := fmt.Sprintf("pubkey of length %v was used",
len(pkBytes))
return nil, scriptError(
ErrDiscourageUpgradeablePubKeyType, str,
)
}
return &baseTapscriptSigVerifier{
taprootSigVerifier: &taprootSigVerifier{},
}, 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.
func (b *baseTapscriptSigVerifier) Verify() bool {
// 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
// true.
if b.pubKey == nil {
return true
}
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?
return false
}
return b.verifySig(sigHash)
}
// A compile-time assertion to ensure baseTapscriptSigVerifier implements the
// signatureVerifier interface.
var _ signatureVerifier = (*baseTapscriptSigVerifier)(nil)