Optimize CHECKSIGADD Script Validation

This commit is contained in:
Jeremy Rubin 2022-01-19 12:32:06 -08:00
parent 807169e10b
commit cfa575266b
4 changed files with 18 additions and 11 deletions

View File

@ -1500,7 +1500,7 @@ static bool HandleMissingData(MissingDataBehavior mdb)
} }
template<typename T> template<typename T>
bool SignatureHashSchnorr(uint256& hash_out, const ScriptExecutionData& execdata, const T& tx_to, uint32_t in_pos, uint8_t hash_type, SigVersion sigversion, const PrecomputedTransactionData& cache, MissingDataBehavior mdb) bool SignatureHashSchnorr(uint256& hash_out, ScriptExecutionData& execdata, const T& tx_to, uint32_t in_pos, uint8_t hash_type, SigVersion sigversion, const PrecomputedTransactionData& cache, MissingDataBehavior mdb)
{ {
uint8_t ext_flag, key_version; uint8_t ext_flag, key_version;
switch (sigversion) { switch (sigversion) {
@ -1568,9 +1568,12 @@ bool SignatureHashSchnorr(uint256& hash_out, const ScriptExecutionData& execdata
// Data about the output (if only one). // Data about the output (if only one).
if (output_type == SIGHASH_SINGLE) { if (output_type == SIGHASH_SINGLE) {
if (in_pos >= tx_to.vout.size()) return false; if (in_pos >= tx_to.vout.size()) return false;
if (!execdata.m_output_hash) {
CHashWriter sha_single_output(SER_GETHASH, 0); CHashWriter sha_single_output(SER_GETHASH, 0);
sha_single_output << tx_to.vout[in_pos]; sha_single_output << tx_to.vout[in_pos];
ss << sha_single_output.GetSHA256(); execdata.m_output_hash = sha_single_output.GetSHA256();
}
ss << execdata.m_output_hash.value();
} }
// Additional data for BIP 342 signatures // Additional data for BIP 342 signatures
@ -1692,7 +1695,7 @@ bool GenericTransactionSignatureChecker<T>::CheckECDSASignature(const std::vecto
} }
template <class T> template <class T>
bool GenericTransactionSignatureChecker<T>::CheckSchnorrSignature(Span<const unsigned char> sig, Span<const unsigned char> pubkey_in, SigVersion sigversion, const ScriptExecutionData& execdata, ScriptError* serror) const bool GenericTransactionSignatureChecker<T>::CheckSchnorrSignature(Span<const unsigned char> sig, Span<const unsigned char> pubkey_in, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror) const
{ {
assert(sigversion == SigVersion::TAPROOT || sigversion == SigVersion::TAPSCRIPT); assert(sigversion == SigVersion::TAPROOT || sigversion == SigVersion::TAPSCRIPT);
// Schnorr signatures have 32-byte public keys. The caller is responsible for enforcing this. // Schnorr signatures have 32-byte public keys. The caller is responsible for enforcing this.

View File

@ -11,6 +11,7 @@
#include <span.h> #include <span.h>
#include <primitives/transaction.h> #include <primitives/transaction.h>
#include <optional>
#include <vector> #include <vector>
#include <stdint.h> #include <stdint.h>
@ -215,6 +216,9 @@ struct ScriptExecutionData
bool m_validation_weight_left_init = false; bool m_validation_weight_left_init = false;
//! How much validation weight is left (decremented for every successful non-empty signature check). //! How much validation weight is left (decremented for every successful non-empty signature check).
int64_t m_validation_weight_left; int64_t m_validation_weight_left;
//! The hash of the corresponding output
std::optional<uint256> m_output_hash;
}; };
/** Signature hash sizes */ /** Signature hash sizes */
@ -244,7 +248,7 @@ public:
return false; return false;
} }
virtual bool CheckSchnorrSignature(Span<const unsigned char> sig, Span<const unsigned char> pubkey, SigVersion sigversion, const ScriptExecutionData& execdata, ScriptError* serror = nullptr) const virtual bool CheckSchnorrSignature(Span<const unsigned char> sig, Span<const unsigned char> pubkey, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror = nullptr) const
{ {
return false; return false;
} }
@ -272,7 +276,7 @@ enum class MissingDataBehavior
}; };
template<typename T> template<typename T>
bool SignatureHashSchnorr(uint256& hash_out, const ScriptExecutionData& execdata, const T& tx_to, uint32_t in_pos, uint8_t hash_type, SigVersion sigversion, const PrecomputedTransactionData& cache, MissingDataBehavior mdb); bool SignatureHashSchnorr(uint256& hash_out, ScriptExecutionData& execdata, const T& tx_to, uint32_t in_pos, uint8_t hash_type, SigVersion sigversion, const PrecomputedTransactionData& cache, MissingDataBehavior mdb);
template <class T> template <class T>
class GenericTransactionSignatureChecker : public BaseSignatureChecker class GenericTransactionSignatureChecker : public BaseSignatureChecker
@ -292,7 +296,7 @@ public:
GenericTransactionSignatureChecker(const T* txToIn, unsigned int nInIn, const CAmount& amountIn, MissingDataBehavior mdb) : txTo(txToIn), m_mdb(mdb), nIn(nInIn), amount(amountIn), txdata(nullptr) {} GenericTransactionSignatureChecker(const T* txToIn, unsigned int nInIn, const CAmount& amountIn, MissingDataBehavior mdb) : txTo(txToIn), m_mdb(mdb), nIn(nInIn), amount(amountIn), txdata(nullptr) {}
GenericTransactionSignatureChecker(const T* txToIn, unsigned int nInIn, const CAmount& amountIn, const PrecomputedTransactionData& txdataIn, MissingDataBehavior mdb) : txTo(txToIn), m_mdb(mdb), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {} GenericTransactionSignatureChecker(const T* txToIn, unsigned int nInIn, const CAmount& amountIn, const PrecomputedTransactionData& txdataIn, MissingDataBehavior mdb) : txTo(txToIn), m_mdb(mdb), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {}
bool CheckECDSASignature(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override; bool CheckECDSASignature(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override;
bool CheckSchnorrSignature(Span<const unsigned char> sig, Span<const unsigned char> pubkey, SigVersion sigversion, const ScriptExecutionData& execdata, ScriptError* serror = nullptr) const override; bool CheckSchnorrSignature(Span<const unsigned char> sig, Span<const unsigned char> pubkey, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror = nullptr) const override;
bool CheckLockTime(const CScriptNum& nLockTime) const override; bool CheckLockTime(const CScriptNum& nLockTime) const override;
bool CheckSequence(const CScriptNum& nSequence) const override; bool CheckSequence(const CScriptNum& nSequence) const override;
}; };
@ -313,7 +317,7 @@ public:
return m_checker.CheckECDSASignature(scriptSig, vchPubKey, scriptCode, sigversion); return m_checker.CheckECDSASignature(scriptSig, vchPubKey, scriptCode, sigversion);
} }
bool CheckSchnorrSignature(Span<const unsigned char> sig, Span<const unsigned char> pubkey, SigVersion sigversion, const ScriptExecutionData& execdata, ScriptError* serror = nullptr) const override bool CheckSchnorrSignature(Span<const unsigned char> sig, Span<const unsigned char> pubkey, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror = nullptr) const override
{ {
return m_checker.CheckSchnorrSignature(sig, pubkey, sigversion, execdata, serror); return m_checker.CheckSchnorrSignature(sig, pubkey, sigversion, execdata, serror);
} }

View File

@ -542,7 +542,7 @@ class DummySignatureChecker final : public BaseSignatureChecker
public: public:
DummySignatureChecker() {} DummySignatureChecker() {}
bool CheckECDSASignature(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override { return true; } bool CheckECDSASignature(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override { return true; }
bool CheckSchnorrSignature(Span<const unsigned char> sig, Span<const unsigned char> pubkey, SigVersion sigversion, const ScriptExecutionData& execdata, ScriptError* serror) const override { return true; } bool CheckSchnorrSignature(Span<const unsigned char> sig, Span<const unsigned char> pubkey, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror) const override { return true; }
}; };
const DummySignatureChecker DUMMY_CHECKER; const DummySignatureChecker DUMMY_CHECKER;

View File

@ -34,7 +34,7 @@ public:
return m_fuzzed_data_provider.ConsumeBool(); return m_fuzzed_data_provider.ConsumeBool();
} }
bool CheckSchnorrSignature(Span<const unsigned char> sig, Span<const unsigned char> pubkey, SigVersion sigversion, const ScriptExecutionData& execdata, ScriptError* serror = nullptr) const override bool CheckSchnorrSignature(Span<const unsigned char> sig, Span<const unsigned char> pubkey, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror = nullptr) const override
{ {
return m_fuzzed_data_provider.ConsumeBool(); return m_fuzzed_data_provider.ConsumeBool();
} }