1
0
mirror of https://github.com/bitcoin/bips.git synced 2025-05-12 12:03:29 +00:00

[BIP-119] Remove C++ Spec from BIP-119 entirely.

This commit is contained in:
Jeremy Rubin 2022-04-28 09:45:13 -07:00
parent fa09f7f857
commit cad2b3ee77

View File

@ -163,7 +163,8 @@ forming a "Payment Pool".
The below code is the main logic for verifying CHECKTEMPLATEVERIFY, described
in pythonic pseduocode. The canonical specification for the semantics of
OP_CHECKTEMPLATEVERIFY can be seen in the reference implementations.
OP_CHECKTEMPLATEVERIFY as implemented in C++ in the context of Bitcoin Core can
be seen in the reference implementation.
The execution of the opcode is as follows:
def execute_bip_119(self):
@ -236,128 +237,6 @@ optimization.
return sha256(r)
The C++ is below:
case OP_CHECKTEMPLATEVERIFY:
{
// if flags not enabled; treat as a NOP4
if (!(flags & SCRIPT_VERIFY_DEFAULT_CHECK_TEMPLATE_VERIFY_HASH)) {
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
break;
}
if (stack.size() < 1)
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
// If the argument was not 32 bytes, treat as OP_NOP4:
switch (stack.back().size()) {
case 32:
if (!checker.CheckDefaultCheckTemplateVerifyHash(stack.back())) {
return set_error(serror, SCRIPT_ERR_TEMPLATE_MISMATCH);
}
break;
default:
// future upgrade can add semantics for this opcode with different length args
// so discourage use when applicable
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
}
}
}
break;
Where
bool CheckDefaultCheckTemplateVerifyHash(const std::vector<unsigned char>& hash) {
return GetDefaultCheckTemplateVerifyHash(current_tx, current_input_index) == uint256(hash);
}
The hash is computed as follows, where the outputs_hash and sequences_hash are computed as defined in BIP-341.
/** Compute the (single) SHA256 of the concatenation of all scriptSigs in a tx. */
template <class T>
uint256 GetScriptSigsSHA256(const T& txTo)
{
CHashWriter ss(SER_GETHASH, 0);
for (const auto& in : txTo.vin) {
ss << in.scriptSig;
}
return ss.GetSHA256();
}
// not DoS safe, for reference/testing!
uint256 GetDefaultCheckTemplateVerifyHash(const CTransaction& tx, uint32_t input_index) {
return GetDefaultCheckTemplateVerifyHash(tx, GetOutputsSHA256(tx), GetSequenceSHA256(tx), input_index);
}
// not DoS safe for reference/testing!
uint256 GetDefaultCheckTemplateVerifyHash(const CTransaction& 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);
}
// DoS safe, fixed length hash!
uint256 GetDefaultCheckTemplateVerifyHashWithScript(const CTransaction& tx, const uint256& outputs_hash, const uint256& sequences_hash,
const uint256& scriptSig_hash, const uint32_t input_index) {
auto h = CHashWriter(SER_GETHASH, 0)
<< tx.nVersion
<< tx.nLockTime
<< scriptSig_hash
<< uint32_t(tx.vin.size())
<< sequences_hash
<< uint32_t(tx.vout.size())
<< outputs_hash
<< input_index;
return h.GetSHA256();
}
// DoS safe, fixed length hash!
uint256 GetDefaultCheckTemplateVerifyHashEmptyScript(const CTransaction& tx, const uint256& outputs_hash, const uint256& sequences_hash,
const uint32_t input_index) {
auto h = CHashWriter(SER_GETHASH, 0)
<< tx.nVersion
<< tx.nLockTime
<< uint32_t(tx.vin.size())
<< sequences_hash
<< uint32_t(tx.vout.size())
<< outputs_hash
<< input_index;
return h.GetSHA256();
}
case OP_CHECKTEMPLATEVERIFY:
{
// if flags not enabled; treat as a NOP4
if (!(flags & SCRIPT_VERIFY_DEFAULT_CHECK_TEMPLATE_VERIFY_HASH)) {
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
break;
}
if (stack.size() < 1)
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
// If the argument was not 32 bytes, treat as OP_NOP4:
switch (stack.back().size()) {
case 32:
if (!checker.CheckDefaultCheckTemplateVerifyHash(stack.back())) {
return set_error(serror, SCRIPT_ERR_TEMPLATE_MISMATCH);
}
break;
default:
// future upgrade can add semantics for this opcode with different length args
// so discourage use when applicable
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
}
}
}
A PayToBareDefaultCheckTemplateVerifyHash output matches the following template:
bool CScript::IsPayToBareDefaultCheckTemplateVerifyHash() const