From 0664f5fe1f77f08d235aa3750b59428257b0b91d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 11 Sep 2020 14:33:30 -0700 Subject: Support for Schnorr signatures and integration in SignatureCheckers (BIP 340) This enables the schnorrsig module in libsecp256k1, adds the relevant types and functions to src/pubkey, as well as in higher-level `SignatureChecker` classes. The (verification side of the) BIP340 test vectors is also added. --- src/script/interpreter.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'src/script/interpreter.cpp') diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index af8fd4912e..aef6e28118 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1521,6 +1521,12 @@ bool GenericTransactionSignatureChecker::VerifyECDSASignature(const std::vect return pubkey.Verify(sighash, vchSig); } +template +bool GenericTransactionSignatureChecker::VerifySchnorrSignature(Span sig, const XOnlyPubKey& pubkey, const uint256& sighash) const +{ + return pubkey.VerifySchnorr(sighash, sig); +} + template bool GenericTransactionSignatureChecker::CheckECDSASignature(const std::vector& vchSigIn, const std::vector& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const { @@ -1543,6 +1549,30 @@ bool GenericTransactionSignatureChecker::CheckECDSASignature(const std::vecto return true; } +template +bool GenericTransactionSignatureChecker::CheckSchnorrSignature(Span sig, Span pubkey_in, SigVersion sigversion, ScriptError* serror) const +{ + assert(sigversion == SigVersion::TAPROOT); + // Schnorr signatures have 32-byte public keys. The caller is responsible for enforcing this. + assert(pubkey_in.size() == 32); + if (sig.size() != 64 && sig.size() != 65) return set_error(serror, SCRIPT_ERR_SCHNORR_SIG_SIZE); + + XOnlyPubKey pubkey{pubkey_in}; + + uint8_t hashtype = SIGHASH_DEFAULT; + if (sig.size() == 65) { + hashtype = SpanPopBack(sig); + if (hashtype == SIGHASH_DEFAULT) return set_error(serror, SCRIPT_ERR_SCHNORR_SIG_HASHTYPE); + } + uint256 sighash; + assert(this->txdata); + if (!SignatureHashSchnorr(sighash, *txTo, nIn, hashtype, sigversion, *this->txdata)) { + return set_error(serror, SCRIPT_ERR_SCHNORR_SIG_HASHTYPE); + } + if (!VerifySchnorrSignature(sig, pubkey, sighash)) return set_error(serror, SCRIPT_ERR_SCHNORR_SIG); + return true; +} + template bool GenericTransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) const { -- cgit v1.2.3