Add StandardTemplateHash definition

and associated SignatureChecker method.
This commit is contained in:
Jeremy Rubin 2019-10-16 14:36:34 -07:00 committed by James O'Beirne
parent cdc32994fe
commit 3e090231b8
No known key found for this signature in database
GPG key ID: 7A935DADB2C44F05
2 changed files with 91 additions and 0 deletions

View file

@ -1377,6 +1377,18 @@ uint256 GetSpentAmountsSHA256(const std::vector<CTxOut>& outputs_spent)
HashWriter ss{};
for (const auto& txout : outputs_spent) {
ss << txout.nValue;
}
return ss.GetSHA256();
}
/** Compute the (single) SHA256 of the concatenation of all scriptSigs in a tx. */
template <class T>
uint256 GetScriptSigsSHA256(const T& txTo)
{
HashWriter ss{};
for (const auto& in : txTo.vin) {
ss << in.scriptSig;
}
return ss.GetSHA256();
}
@ -1391,9 +1403,62 @@ uint256 GetSpentScriptsSHA256(const std::vector<CTxOut>& outputs_spent)
return ss.GetSHA256();
}
template<typename TxType>
uint256 GetDefaultCheckTemplateVerifyHashWithScript(
const TxType& tx, const uint256& outputs_hash, const uint256& sequences_hash,
const uint256& scriptSig_hash, const uint32_t input_index)
{
auto h = HashWriter{}
<< tx.version
<< tx.nLockTime
<< scriptSig_hash
<< uint32_t(tx.vin.size())
<< sequences_hash
<< uint32_t(tx.vout.size())
<< outputs_hash
<< input_index;
return h.GetSHA256();
}
template<typename TxType>
uint256 GetDefaultCheckTemplateVerifyHashEmptyScript(
const TxType& tx, const uint256& outputs_hash, const uint256& sequences_hash,
const uint32_t input_index)
{
auto h = HashWriter{}
<< tx.version
<< tx.nLockTime
<< uint32_t(tx.vin.size())
<< sequences_hash
<< uint32_t(tx.vout.size())
<< outputs_hash
<< input_index;
return h.GetSHA256();
}
} // namespace
template<typename TxType>
uint256 GetDefaultCheckTemplateVerifyHash(const TxType& tx, uint32_t input_index) {
return GetDefaultCheckTemplateVerifyHash(tx, GetOutputsSHA256(tx), GetSequencesSHA256(tx), input_index);
}
template<typename TxType>
uint256 GetDefaultCheckTemplateVerifyHash(
const TxType& tx, const uint256& outputs_hash, const uint256& sequences_hash, const uint32_t input_index) {
bool skip_scriptSigs = std::find_if(tx.vin.begin(), tx.vin.end(),
[](const CTxIn& c) { return c.scriptSig != CScript(); }) == tx.vin.end();
return skip_scriptSigs ? GetDefaultCheckTemplateVerifyHashEmptyScript(tx, outputs_hash, sequences_hash, input_index) :
GetDefaultCheckTemplateVerifyHashWithScript(tx, outputs_hash, sequences_hash, GetScriptSigsSHA256(tx), input_index);
}
template
uint256 GetDefaultCheckTemplateVerifyHash(
const CTransaction& tx, const uint256& outputs_hash, const uint256& sequences_hash, const uint32_t input_index);
template
uint256 GetDefaultCheckTemplateVerifyHash(
const CMutableTransaction& tx, const uint256& outputs_hash, const uint256& sequences_hash, const uint32_t input_index);
template <class T>
void PrecomputedTransactionData::Init(const T& txTo, std::vector<CTxOut>&& spent_outputs, bool force)
{
@ -1781,6 +1846,15 @@ bool GenericTransactionSignatureChecker<T>::CheckSequence(const CScriptNum& nSeq
return true;
}
template <class T>
bool GenericTransactionSignatureChecker<T>::CheckDefaultCheckTemplateVerifyHash(const std::vector<unsigned char>& hash) const
{
// Should already be checked before calling...
assert(hash.size() == 32);
assert(txTo != nullptr);
uint256 hash_tmpl = GetDefaultCheckTemplateVerifyHash(*txTo, nIn);
return std::equal(hash_tmpl.begin(), hash_tmpl.end(), hash.data());
}
// explicit instantiation
template class GenericTransactionSignatureChecker<CTransaction>;
template class GenericTransactionSignatureChecker<CMutableTransaction>;

View file

@ -187,6 +187,17 @@ struct PrecomputedTransactionData
explicit PrecomputedTransactionData(const T& tx);
};
/**
* Compute the default template hash for OP_CHECKTEMPLATEVERIFY using some precomputed
* hash inputs.
*
* (This exported interface is only used in tests.)
*/
template<typename TxType>
uint256 GetDefaultCheckTemplateVerifyHash(
const TxType& tx, const uint256& outputs_hash, const uint256& sequences_hash,
const uint32_t input_index);
enum class SigVersion
{
BASE = 0, //!< Bare scripts and BIP16 P2SH-wrapped redeemscripts
@ -265,6 +276,11 @@ public:
return false;
}
virtual bool CheckDefaultCheckTemplateVerifyHash(const std::vector<unsigned char>& hash) const
{
return false;
}
virtual ~BaseSignatureChecker() = default;
};
@ -301,6 +317,7 @@ public:
bool CheckSchnorrSignature(std::span<const unsigned char> sig, std::span<const unsigned char> pubkey, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror = nullptr) const override;
bool CheckLockTime(const CScriptNum& nLockTime) const override;
bool CheckSequence(const CScriptNum& nSequence) const override;
bool CheckDefaultCheckTemplateVerifyHash(const std::vector<unsigned char>& hash) const override;
};
using TransactionSignatureChecker = GenericTransactionSignatureChecker<CTransaction>;