Merge 4c5790105e7fb3a2cd207403af769fbbccd7296d into 5f4422d68dc3530c353af1f87499de1c864b60ad

This commit is contained in:
jamesob 2025-03-17 02:35:01 +00:00 committed by GitHub
commit 0839b3419e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 3336 additions and 22 deletions

View File

@ -98,6 +98,7 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
case TxoutType::MULTISIG:
case TxoutType::NULL_DATA:
case TxoutType::NONSTANDARD:
case TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY:
addressRet = CNoDestination(scriptPubKey);
return false;
} // no default case, so the compiler can warn about missing cases

View File

@ -214,6 +214,11 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) {
return false;
}
} else if (whichType == TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY) {
// after activation, only allow bare with no scriptsig.
// pre-activation disallowing enforced via discouraged logic in the
// interpreter.
if (tx.vin[i].scriptSig.size() != 0) return false;
}
}

View File

@ -124,7 +124,11 @@ static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS{MANDATORY_SCRIPT_VERI
SCRIPT_VERIFY_CONST_SCRIPTCODE |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION |
SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE};
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE |
SCRIPT_VERIFY_DISCOURAGE_CHECKTEMPLATEVERIFY |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_CHECKTEMPLATEVERIFY |
SCRIPT_VERIFY_CHECKTEMPLATEVERIFY};
/** For convenience, standard but not mandatory verify flags. */
static constexpr unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS{STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS};

View File

@ -544,6 +544,8 @@ static RPCHelpMan decodescript()
case TxoutType::WITNESS_UNKNOWN:
case TxoutType::WITNESS_V1_TAPROOT:
case TxoutType::ANCHOR:
// don't wrap CTV because P2SH CTV is a hash cycle
case TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY:
// Should not be wrapped
return false;
} // no default case, so the compiler can warn about missing cases
@ -587,6 +589,8 @@ static RPCHelpMan decodescript()
case TxoutType::WITNESS_V0_SCRIPTHASH:
case TxoutType::WITNESS_V1_TAPROOT:
case TxoutType::ANCHOR:
// don't wrap CTV because P2SH CTV is a hash cycle
case TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY:
// Should not be wrapped
return false;
} // no default case, so the compiler can warn about missing cases

View File

@ -591,7 +591,42 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
break;
}
case OP_NOP1: case OP_NOP4: case OP_NOP5:
case OP_CHECKTEMPLATEVERIFY:
{
if (flags & SCRIPT_VERIFY_DISCOURAGE_CHECKTEMPLATEVERIFY) {
return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
}
// if flags not enabled; treat as a NOP4
if (!(flags & SCRIPT_VERIFY_CHECKTEMPLATEVERIFY)) {
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:
{
const Span<const unsigned char> hash{stack.back()};
if (!checker.CheckDefaultCheckTemplateVerifyHash(hash)) {
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_CHECKTEMPLATEVERIFY) {
return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
}
}
}
break;
case OP_NOP1: case OP_NOP5:
case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10:
{
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
@ -1377,6 +1412,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 +1438,64 @@ uint256 GetSpentScriptsSHA256(const std::vector<CTxOut>& outputs_spent)
return ss.GetSHA256();
}
/* Not Exported, just convenience */
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>
static bool NoScriptSigs(const TxType& tx)
{
return std::all_of(tx.vin.begin(), tx.vin.end(), [](const CTxIn& c) { return c.scriptSig.empty(); });
}
template<typename TxType>
uint256 GetDefaultCheckTemplateVerifyHash(
const TxType& tx, const uint256& outputs_hash, const uint256& sequences_hash, const uint32_t input_index) {
return NoScriptSigs(tx) ? 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)
{
@ -1427,12 +1529,19 @@ void PrecomputedTransactionData::Init(const T& txTo, std::vector<CTxOut>&& spent
if (uses_bip341_taproot && uses_bip143_segwit) break; // No need to scan further if we already need all.
}
if (uses_bip143_segwit || uses_bip341_taproot) {
// Computations shared between both sighash schemes.
m_prevouts_single_hash = GetPrevoutsSHA256(txTo);
m_sequences_single_hash = GetSequencesSHA256(txTo);
m_outputs_single_hash = GetOutputsSHA256(txTo);
}
// Each of these computations is always required for CHECKTEMPLATEVERIFY, and sometimes
// required for any segwit/taproot.
m_prevouts_single_hash = GetPrevoutsSHA256(txTo);
m_sequences_single_hash = GetSequencesSHA256(txTo);
m_outputs_single_hash = GetOutputsSHA256(txTo);
// Only required for CHECKTEMPLATEVERIFY.
//
// The empty hash is used to signal whether or not we should skip scriptSigs
// when re-computing for different indexes.
m_scriptSigs_single_hash = NoScriptSigs(txTo) ? uint256{} : GetScriptSigsSHA256(txTo);
m_bip119_ctv_ready = true;
if (uses_bip143_segwit) {
hashPrevouts = SHA256Uint256(m_prevouts_single_hash);
hashSequence = SHA256Uint256(m_sequences_single_hash);
@ -1781,6 +1890,22 @@ bool GenericTransactionSignatureChecker<T>::CheckSequence(const CScriptNum& nSeq
return true;
}
template <class T>
bool GenericTransactionSignatureChecker<T>::CheckDefaultCheckTemplateVerifyHash(const Span<const unsigned char>& hash) const
{
// Should already be checked before calling...
assert(hash.size() == 32);
if (txdata && txdata->m_bip119_ctv_ready) {
assert(txTo != nullptr);
uint256 hash_tmpl = txdata->m_scriptSigs_single_hash.IsNull() ?
GetDefaultCheckTemplateVerifyHashEmptyScript(*txTo, txdata->m_outputs_single_hash, txdata->m_sequences_single_hash, nIn) :
GetDefaultCheckTemplateVerifyHashWithScript(*txTo, txdata->m_outputs_single_hash, txdata->m_sequences_single_hash,
txdata->m_scriptSigs_single_hash, nIn);
return std::equal(hash_tmpl.begin(), hash_tmpl.end(), hash.data());
} else {
return HandleMissingData(m_mdb);
}
}
// explicit instantiation
template class GenericTransactionSignatureChecker<CTransaction>;
template class GenericTransactionSignatureChecker<CMutableTransaction>;

View File

@ -143,6 +143,15 @@ enum : uint32_t {
// Making unknown public key versions (in BIP 342 scripts) non-standard
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE = (1U << 20),
// CHECKTEMPLATEVERIFY validation (BIP-119)
SCRIPT_VERIFY_CHECKTEMPLATEVERIFY = (1U << 21),
// discourage upgradable OP_CHECKTEMPLATEVERIFY hashes
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_CHECKTEMPLATEVERIFY = (1U << 22),
// discourage OP_CHECKTEMPLATEVERIFY
SCRIPT_VERIFY_DISCOURAGE_CHECKTEMPLATEVERIFY = (1U << 23),
// Constants to point to the highest flag in use. Add new flags above this line.
//
SCRIPT_VERIFY_END_MARKER
@ -152,6 +161,9 @@ bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned i
struct PrecomputedTransactionData
{
// Order of fields is packed below (uint256 is 32 bytes, vector is 24 bytes
// (3 ptrs), ready flags (1 byte each).
// BIP341 precomputed data.
// These are single-SHA256, see https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#cite_note-16.
uint256 m_prevouts_single_hash;
@ -159,15 +171,25 @@ struct PrecomputedTransactionData
uint256 m_outputs_single_hash;
uint256 m_spent_amounts_single_hash;
uint256 m_spent_scripts_single_hash;
//! Whether the 5 fields above are initialized.
bool m_bip341_taproot_ready = false;
// BIP119 precomputed data (single SHA256).
uint256 m_scriptSigs_single_hash;
// BIP143 precomputed data (double-SHA256).
uint256 hashPrevouts, hashSequence, hashOutputs;
//! Whether the 3 fields above are initialized.
// BIP341 cached outputs.
std::vector<CTxOut> m_spent_outputs;
//! Whether the bip341 fields above are initialized.
bool m_bip341_taproot_ready = false;
//! Whether the bip119 fields above are initialized.
bool m_bip119_ctv_ready = false;
//! Whether the bip143 fields above are initialized.
bool m_bip143_segwit_ready = false;
std::vector<CTxOut> m_spent_outputs;
//! Whether m_spent_outputs is initialized.
bool m_spent_outputs_ready = false;
@ -187,6 +209,11 @@ struct PrecomputedTransactionData
explicit PrecomputedTransactionData(const T& tx);
};
/* Standard Template Hash Declarations */
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 +292,11 @@ public:
return false;
}
virtual bool CheckDefaultCheckTemplateVerifyHash(const Span<const unsigned char>& hash) const
{
return false;
}
virtual ~BaseSignatureChecker() = default;
};
@ -301,6 +333,7 @@ public:
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 CheckSequence(const CScriptNum& nSequence) const override;
bool CheckDefaultCheckTemplateVerifyHash(const Span<const unsigned char>& hash) const override;
};
using TransactionSignatureChecker = GenericTransactionSignatureChecker<CTransaction>;

View File

@ -138,7 +138,7 @@ std::string GetOpName(opcodetype opcode)
case OP_NOP1 : return "OP_NOP1";
case OP_CHECKLOCKTIMEVERIFY : return "OP_CHECKLOCKTIMEVERIFY";
case OP_CHECKSEQUENCEVERIFY : return "OP_CHECKSEQUENCEVERIFY";
case OP_NOP4 : return "OP_NOP4";
case OP_CHECKTEMPLATEVERIFY : return "OP_CHECKTEMPLATEVERIFY";
case OP_NOP5 : return "OP_NOP5";
case OP_NOP6 : return "OP_NOP6";
case OP_NOP7 : return "OP_NOP7";
@ -221,6 +221,14 @@ bool CScript::IsPayToAnchor(int version, const std::vector<unsigned char>& progr
program[1] == 0x73;
}
bool CScript::IsPayToBareDefaultCheckTemplateVerifyHash() const
{
// Extra-fast test for pay-to-bare-default-check-template-verify-hash CScripts:
return (this->size() == 34 &&
(*this)[0] == 0x20 &&
(*this)[33] == OP_CHECKTEMPLATEVERIFY);
}
bool CScript::IsPayToScriptHash() const
{
// Extra-fast test for pay-to-script-hash CScripts:

View File

@ -198,7 +198,8 @@ enum opcodetype
OP_NOP2 = OP_CHECKLOCKTIMEVERIFY,
OP_CHECKSEQUENCEVERIFY = 0xb2,
OP_NOP3 = OP_CHECKSEQUENCEVERIFY,
OP_NOP4 = 0xb3,
OP_CHECKTEMPLATEVERIFY = 0xb3,
OP_NOP4 = OP_CHECKTEMPLATEVERIFY,
OP_NOP5 = 0xb4,
OP_NOP6 = 0xb5,
OP_NOP7 = 0xb6,
@ -552,6 +553,8 @@ public:
*/
static bool IsPayToAnchor(int version, const std::vector<unsigned char>& program);
bool IsPayToBareDefaultCheckTemplateVerifyHash() const;
bool IsPayToScriptHash() const;
bool IsPayToWitnessScriptHash() const;
bool IsWitnessProgram(int& version, std::vector<unsigned char>& program) const;

View File

@ -25,6 +25,8 @@ std::string ScriptErrorString(const ScriptError serror)
return "Script failed an OP_CHECKSIGVERIFY operation";
case SCRIPT_ERR_NUMEQUALVERIFY:
return "Script failed an OP_NUMEQUALVERIFY operation";
case SCRIPT_ERR_TEMPLATE_MISMATCH:
return "Script failed an OP_CHECKTEMPLATEVERIFY operation";
case SCRIPT_ERR_SCRIPT_SIZE:
return "Script is too big";
case SCRIPT_ERR_PUSH_SIZE:

View File

@ -29,6 +29,7 @@ typedef enum ScriptError_t
SCRIPT_ERR_CHECKMULTISIGVERIFY,
SCRIPT_ERR_CHECKSIGVERIFY,
SCRIPT_ERR_NUMEQUALVERIFY,
SCRIPT_ERR_TEMPLATE_MISMATCH,
/* Logical/Format/Canonical errors */
SCRIPT_ERR_BAD_OPCODE,

View File

@ -412,6 +412,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
case TxoutType::NONSTANDARD:
case TxoutType::NULL_DATA:
case TxoutType::WITNESS_UNKNOWN:
case TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY:
return false;
case TxoutType::PUBKEY:
if (!CreateSig(creator, sigdata, provider, sig, CPubKey(vSolutions[0]), scriptPubKey, sigversion)) return false;

View File

@ -29,6 +29,7 @@ std::string GetTxnOutputType(TxoutType t)
case TxoutType::WITNESS_V0_SCRIPTHASH: return "witness_v0_scripthash";
case TxoutType::WITNESS_V1_TAPROOT: return "witness_v1_taproot";
case TxoutType::WITNESS_UNKNOWN: return "witness_unknown";
case TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY: return "bare_default_ctv_hash";
} // no default case, so the compiler can warn about missing cases
assert(false);
}
@ -151,6 +152,10 @@ TxoutType Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned c
return TxoutType::SCRIPTHASH;
}
if (scriptPubKey.IsPayToBareDefaultCheckTemplateVerifyHash()) {
return TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY;
}
int witnessversion;
std::vector<unsigned char> witnessprogram;
if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {

View File

@ -31,6 +31,7 @@ enum class TxoutType {
WITNESS_V0_SCRIPTHASH,
WITNESS_V0_KEYHASH,
WITNESS_V1_TAPROOT,
TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY,
WITNESS_UNKNOWN, //!< Only for Witness versions not already defined above
};

View File

@ -34,6 +34,7 @@ add_executable(test_bitcoin
compilerbug_tests.cpp
compress_tests.cpp
crypto_tests.cpp
ctvhash_tests.cpp
cuckoocache_tests.cpp
dbwrapper_tests.cpp
denialofservice_tests.cpp
@ -130,6 +131,7 @@ target_json_data_sources(test_bitcoin
data/base58_encode_decode.json
data/bip341_wallet_vectors.json
data/blockfilters.json
data/ctvhash.json
data/key_io_invalid.json
data/key_io_valid.json
data/script_tests.json

198
src/test/ctvhash_tests.cpp Normal file
View File

@ -0,0 +1,198 @@
// Copyright (c) 2013-2021 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <core_io.h>
#include <consensus/tx_check.h>
#include <consensus/validation.h>
#include <hash.h>
#include <script/interpreter.h>
#include <serialize.h>
#include <streams.h>
#include <test/data/ctvhash.json.h>
#include <test/util/json.h>
#include <test/util/setup_common.h>
#include <util/strencodings.h>
#include <common/system.h>
#include <random.h>
#include <boost/test/unit_test.hpp>
#include <univalue.h>
BOOST_FIXTURE_TEST_SUITE(ctvhash_tests, BasicTestingSetup)
// Goal: check that CTV Hash Functions generate correct hash
BOOST_AUTO_TEST_CASE(ctvhash_from_data)
{
UniValue tests = read_json(std::string(json_tests::ctvhash));
for (unsigned int idx = 0; idx < tests.size(); idx++) {
const UniValue& test = tests[idx];
std::string strTest = test.write();
// comment
if (test.isStr())
continue;
else if (test.isObject()) {
std::vector<uint256> hash;
std::vector<uint32_t> spend_index;
try {
auto& hash_arr = test["result"].get_array();
for (size_t i = 0; i < hash_arr.size(); ++i) {
hash.emplace_back();
hash.back().SetHexDeprecated(hash_arr[i].get_str());
// reverse because python's sha256().digest().hex() is
// backwards
std::reverse(hash.back().begin(), hash.back().end());
}
} catch (...) {
BOOST_ERROR("Bad test: Results could not be deserialized" << strTest);
break;
}
try {
auto& spend_index_arr = test["spend_index"].get_array();
for (size_t i = 0; i < spend_index_arr.size(); ++i) {
spend_index.emplace_back(spend_index_arr[i].getInt<uint32_t>());
}
} catch (...) {
BOOST_ERROR("Bad test: spend_index could not be deserialized" << strTest);
break;
}
if (spend_index.size() != hash.size()) {
BOOST_ERROR("Bad test: Spend Indexes not same length as Result Hashes: " << strTest);
break;
}
CMutableTransaction tx;
try {
// deserialize test data
BOOST_CHECK(DecodeHexTx(tx, test["hex_tx"].get_str()));
} catch (...) {
BOOST_ERROR("Bad test, couldn't deserialize hex_tx: " << strTest);
continue;
}
const PrecomputedTransactionData data{tx};
for (size_t i = 0; i < hash.size(); ++i) {
uint256 sh = GetDefaultCheckTemplateVerifyHash(tx, data.m_outputs_single_hash, data.m_sequences_single_hash, spend_index[i]);
if (sh != hash[i]) {
BOOST_ERROR("Expected: " << sh << " Got: " << hash[i] << " For:\n"
<< strTest);
}
}
// Change all of the outpoints and there should be no difference.
FastRandomContext fr;
for (auto i = 0; i < 200; ++i) {
CMutableTransaction txc = tx;
bool hash_will_change = false;
// do n mutations, 50% of being 1, 50% chance of being 2-11
const uint64_t n_mutations = fr.randbool()? (fr.randrange(10)+2) : 1;
for (uint64_t j = 0; j < n_mutations; ++j) {
// on the first 50 passes, modify in ways that will not change hash
const int mutate_field = i < 50 ? fr.randrange(2) : fr.randrange(10);
switch (mutate_field) {
case 0: {
if (tx.vin.size() > 0) {
// no need to rejection sample on 256 bits
const auto which = fr.randrange(tx.vin.size());
tx.vin[which].prevout = {Txid::FromUint256(fr.rand256()), fr.rand32()};
}
break;
}
case 1: {
if (tx.vin.size() > 0) {
const auto which = fr.randrange(tx.vin.size());
tx.vin[which].scriptWitness.stack.push_back(fr.randbytes(500));
}
break;
}
case 2: {
// Mutate a scriptSig
txc.vin[0].scriptSig.push_back('x');
hash_will_change = true;
break;
}
case 3: {
// Mutate a sequence
do {
txc.vin.back().nSequence = fr.rand32();
} while (txc.vin.back().nSequence == tx.vin.back().nSequence);
hash_will_change = true;
break;
}
case 4: {
// Mutate version
do {
txc.version = fr.rand<int32_t>();
} while (txc.version == tx.version);
hash_will_change = true;
break;
}
case 5: {
if (tx.vin.size() > 0) {
// Mutate output amount
const auto which = fr.randrange(tx.vout.size());
txc.vout[which].nValue += 1;
hash_will_change = true;
}
break;
}
case 6: {
if (tx.vin.size() > 0) {
// Mutate output script
const auto which = fr.randrange(tx.vout.size());
txc.vout[which].scriptPubKey.push_back('x');
hash_will_change = true;
}
break;
}
case 7: {
// Mutate nLockTime
do {
txc.nLockTime = fr.rand32();
} while (txc.nLockTime == tx.nLockTime);
hash_will_change = true;
break;
}
case 8: {
// don't add and remove for a mutation otherwise it may end up valid
break;
}
case 9: {
// don't add and remove for a mutation otherwise it may end up valid
break;
}
default:
assert(0);
}
}
const PrecomputedTransactionData data_txc{txc};
// iterate twice, one time with the correct spend indexes, one time with incorrect.
for (auto use_random_index = 0; use_random_index < 2; ++use_random_index) {
hash_will_change |= use_random_index != 0;
for (size_t i = 0; i < hash.size(); ++i) {
uint32_t index{spend_index[i]};
while (use_random_index && index == spend_index[i]) {
index = fr.rand32();
}
uint256 sh = GetDefaultCheckTemplateVerifyHash(txc, data_txc.m_outputs_single_hash, data_txc.m_sequences_single_hash, index);
const bool hash_equals = sh == hash[i];
if (hash_will_change && hash_equals) {
BOOST_ERROR("Expected: NOT " << hash[i] << " Got: " << sh << " For:\n"
<< strTest);
} else if (!hash_will_change && !hash_equals) {
BOOST_ERROR("Expected: " << hash[i] << " Got: " << sh << " For:\n"
<< strTest);
}
}
}
}
} else {
BOOST_ERROR("Bad test: " << strTest);
continue;
}
}
}
BOOST_AUTO_TEST_SUITE_END()

2204
src/test/data/ctvhash.json Normal file

File diff suppressed because one or more lines are too long

View File

@ -244,8 +244,8 @@
["'abcdefghijklmnopqrstuvwxyz'", "HASH256 0x4c 0x20 0xca139bc10c2f660da42666f72e89a225936fc60f193c161124a672050c434671 EQUAL", "P2SH,STRICTENC", "OK"],
["1","NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL", "P2SH,STRICTENC", "OK"],
["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL", "P2SH,STRICTENC", "OK"],
["1","NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY CHECKTEMPLATEVERIFY NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL", "P2SH,STRICTENC", "OK"],
["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY CHECKTEMPLATEVERIFY NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL", "P2SH,STRICTENC", "OK"],
["1", "NOP", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "OK", "Discourage NOPx flag allows OP_NOP"],
@ -456,7 +456,7 @@
["NOP", "NOP1 1", "P2SH,STRICTENC", "OK"],
["NOP", "CHECKLOCKTIMEVERIFY 1", "P2SH,STRICTENC", "OK"],
["NOP", "CHECKSEQUENCEVERIFY 1", "P2SH,STRICTENC", "OK"],
["NOP", "NOP4 1", "P2SH,STRICTENC", "OK"],
["NOP", "CHECKTEMPLATEVERIFY 1", "P2SH,STRICTENC", "OK"],
["NOP", "NOP5 1", "P2SH,STRICTENC", "OK"],
["NOP", "NOP6 1", "P2SH,STRICTENC", "OK"],
["NOP", "NOP7 1", "P2SH,STRICTENC", "OK"],
@ -870,12 +870,11 @@
["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
["1", "NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
["1", "NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY CHECKTEMPLATEVERIFY NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY CHECKTEMPLATEVERIFY NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
["Ensure 100% coverage of discouraged NOPS"],
["1", "NOP1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
["1", "NOP4", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
["1", "NOP5", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
["1", "NOP6", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
["1", "NOP7", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],

View File

@ -393,5 +393,100 @@
["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 1, "2 0x48 0x3045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 3 CHECKMULTISIG"]],
"0100000002dbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce000000006b4830450221009627444320dc5ef8d7f68f35010b4c050a6ed0d96b67a84db99fda9c9de58b1e02203e4b4aaa019e012e65d69b487fdf8719df72f488fa91506a80c49a33929f1fd50121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffffdbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce010000009300483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303ffffffff01a0860100000000001976a9149bc0bbdd3024da4d0c38ed1aecf5c68dd1d3fa1288ac00000000", "CONST_SCRIPTCODE"],
["CheckTemplateVerify (CTV) Tests"],
["Modified Segwit OP_CTV Spend Failed if Amount Mutated"],
[[["10bf165531fbdfac386f018d92d72dce3ad73af1f183f6fac2c7a2a1050aa51b",
0,
"0x00 0x20 0x9e650578b4f13cde08d16211f3635239e22ba3e108ba7f5fa4bd6c12f8c8219a",
155000]],
"020000000001011ba50a05a1a2c7c2faf683f1f13ad73ace2dd7928d016f38acdffb315516bf100000000000000000000ae90300000000000017a9142b697af70a75926b158a2ea0aab8054eb18490ac87d00700000000000017a9143177919dae74db1c4cd3e6e69861091c6aee9eb287b80b00000000000017a91417d751e7c17c8264e90e4831fed9c47804b2bbc887a00f00000000000017a914a46167b1fbca936b56dda9710a0c16a53fd32fe687881300000000000017a914b4a5ddbdda32760d1c61dd131007fd7e67d650e187701700000000000017a91480909aab0729614b1162d86563cbfb0c71d5bc9e87581b00000000000017a914997c99e26f67463a1f9770003f90603360408bed87401f00000000000017a9149fef27cd2e724889aa522ac6b5eb35de7582727487282300000000000017a914c7c616d8323c7046de863e2301ec0c7884626e9687102700000000000017a914b590ca292351b64cbf725bad01c3ba6da808ab0b870122200a2891d90df11c7714549c76b80b29c86d544110d958a6dabcfcd5cda1612427b300000000",
"CHECKTEMPLATEVERIFY,WITNESS,P2SH"],
["Modified Segwit OP_CTV Spend Failed if # inputs Mutated"],
[[["7438c73c9a554540dce173b485e888683e9ae5beae3ae94142e77ae2cc024e3c",
0,
"0x00 0x20 0xc19287614d027e87b85ace418cb0fc2d89241392370f0f7cf2ebb06b861c85f0",
155000],
["24040d2cd61f2ecb67e9fe5634c1d90e59b6b16028ff03003cf20f398ce27e44",
0,
"1",
155000]],
"020000000001023c4e02cce27ae74241e93aaebee59a3e6888e885b473e1dc4045559a3cc73874000000000000000000447ee28c390ff23c0003ff2860b1b6590ed9c13456fee967cb2e1fd62c0d04240000000000000000000ae90300000000000017a91406651b0a47731127630ccc27d07fb9afc041846987d00700000000000017a914c758d7ce652d5ed562253ed00e9afc34ea1f76bf87b80b00000000000017a914fe8740b477b23838679c7eaa6e452e66c58a72bc87a00f00000000000017a914cc07d98fc32e2ff65f62076f2824d63bd5a1628787881300000000000017a914acfb84e8356788c7a8312194d1833e5d5677d58e87701700000000000017a91409aad9fbb6609e4486fa5b04afbbde40659388f787581b00000000000017a914ffd3dc8f12ebb700dd45a6a58914347533b6728587401f00000000000017a914781456255e72a09dfab2211dc151165c62ab7af987282300000000000017a914ee01dfa11feb2bc68b22d6909052647c8c001ec787102700000000000017a9145dd4e76cb2cef90e09f181c55fdc42717f3d948787012220cf100c0bb5dc85c104d87c31e7b57a4a7791cc2091dc87ddaac40c91edda7f6bb30000000000",
"CHECKTEMPLATEVERIFY,WITNESS,P2SH"],
["Wrong Size CTV Argument is Discouraged"],
[[["13e313be0d1eab290bcf2b58f4ad76c3f4fd46b2ac4273c607cdc7f5a4170794",
0,
"0x00 0x20 0xaeba7cb39e708a34dd186698a80cc34e70bb92921a01f853ac691bb572b52d62",
155000]],
"02000000000101940717a4f5c7cd07c67342acb246fdf4c376adf4582bcf0b29ab1e0dbe13e3130000000000000000000ae90300000000000017a914f0ccedba146f6390e5961b2a0a39cfba046c312987d00700000000000017a91458d4792223eebb552801d6690b5985513fbddaca87b80b00000000000017a914774b6fe872b65890c610ec6edda928703fe8503e87a00f00000000000017a9148ad37662e56b5f2e472e4bdc205f0dcde8708fd787881300000000000017a9149e8680d850f172186f4e16cee442f0d0121fd46e87701700000000000017a9141394792d48889f70878ce2ee3b151de33d4b774987581b00000000000017a9142444dbb85cf5dfa3e94d2a970a4d4bb795495df687401f00000000000017a914b0437ba6b526e697e695d4f8a53482d26547b64f87282300000000000017a91408ceb5466bc28db2122f954ca59d4a4a08fc133b87102700000000000017a91486f51c990634abc769d6d9d01608ff99f93b050387010251b300000000",
"CHECKTEMPLATEVERIFY,WITNESS,P2SH,DISCOURAGE_UPGRADABLE_CHECKTEMPLATEVERIFY"],
["Empty Stack is Rejected for CTV"],
[[["e658e5b94eba5931faf2379a61a75a05b153648690527d35f7143bed462a6ebc",
0,
"0x00 0x20 0x6c9cc4747e7d287ac1abf8c65152a78d369213583e306b7d3163e12c561abaa2",
155000]],
"02000000000101bc6e2a46ed3b14f7357d5290866453b1055aa7619a37f2fa3159ba4eb9e558e60000000000000000000ae90300000000000017a914b038d0ca030a6d6bc4a06bda13ae1413ce96f37e87d00700000000000017a914fa5716162fb8f5f3cafdce1c1f5533e182c83f4d87b80b00000000000017a91417d10dea89621354333f4dfcbdafe18ec6a794da87a00f00000000000017a9142abb09f63aaecdfbe0e92fedc0afedf19194360187881300000000000017a914aab8b0219014272348de62cbc195e20151b7735787701700000000000017a914a507b83449359c82a195fc9bab99fa1b7c8289eb87581b00000000000017a91401ea6e7336fb9d5e5f36994eecade840ba938d0687401f00000000000017a914e5a474adbd25d66bb70c9b0b6a27f3eebf70b3f587282300000000000017a914d4ae33b227632cf0434f054782558baf9aa6e42d87102700000000000017a9147e4cca8f6c63cb7a56dd3c6edd2acbd031813de9870106b3746375685100000000",
"CHECKTEMPLATEVERIFY,WITNESS,P2SH"],
["Wrong Size Stack Argument is Discouraged for CTV"],
[[["e658e5b94eba5931faf2379a61a75a05b153648690527d35f7143bed462a6ebc",
0,
"0x00 0x20 0x6c9cc4747e7d287ac1abf8c65152a78d369213583e306b7d3163e12c561abaa2",
155000]],
"02000000000101bc6e2a46ed3b14f7357d5290866453b1055aa7619a37f2fa3159ba4eb9e558e60000000000000000000ae90300000000000017a914b038d0ca030a6d6bc4a06bda13ae1413ce96f37e87d00700000000000017a914fa5716162fb8f5f3cafdce1c1f5533e182c83f4d87b80b00000000000017a91417d10dea89621354333f4dfcbdafe18ec6a794da87a00f00000000000017a9142abb09f63aaecdfbe0e92fedc0afedf19194360187881300000000000017a914aab8b0219014272348de62cbc195e20151b7735787701700000000000017a914a507b83449359c82a195fc9bab99fa1b7c8289eb87581b00000000000017a91401ea6e7336fb9d5e5f36994eecade840ba938d0687401f00000000000017a914e5a474adbd25d66bb70c9b0b6a27f3eebf70b3f587282300000000000017a914d4ae33b227632cf0434f054782558baf9aa6e42d87102700000000000017a9147e4cca8f6c63cb7a56dd3c6edd2acbd031813de98702015106b3746375685100000000",
"CHECKTEMPLATEVERIFY,WITNESS,P2SH,DISCOURAGE_UPGRADABLE_CHECKTEMPLATEVERIFY"],
["Wrong TX Hash passed via the stack fails CTV"],
[[["1303ae3fc607b6eb3a4da63d3d7f4722b595db87890943618e11c3905662cae4",
0,
"0x00 0x20 0x6c9cc4747e7d287ac1abf8c65152a78d369213583e306b7d3163e12c561abaa2",
155000]],
"02000000000101e4ca625690c3118e6143098987db95b522477f3d3da64d3aebb607c63fae03130000000000000000000ae90300000000000017a9145850541d205b7b1feb1bc10112f9d739fa9a7dc287d00700000000000017a914d76b85e77e20777d5ec9d7d9998ae0c062d4669087b80b00000000000017a914c79f4a39b0580e4ec90e1b4989fc6124e4135cc187a00f00000000000017a91469635f1f4c06d66591282a02303b1435ee888d9487881300000000000017a91410d3b9b2aaffae25b6098169e2dc69928849215387701700000000000017a91456e4a3e5a3a49b9a66240288e79a8a5e8e31d05587581b00000000000017a9143936403d1a70b32c1e0e6920f9cd99cbc8a8345787401f00000000000017a9146ec4fa5a4e329f9d92ea29b65fa48c6ec1470ffa87282300000000000017a914f66743d56210c98bce8a44742b2ecfa9b7f48fdb87102700000000000017a914555c65f1c355993b46003311931eb08cf457209b870220a2638b51a692e6a8b39e87c431edde4fc1ada3dedaf9665875ac8353af44c50706b3746375685100000000",
"CHECKTEMPLATEVERIFY,WITNESS,P2SH"],
["Embedded CTV Impossible with Bare P2SH due to hash cycle"],
[[["6a869fd9a0395f35e412ad3eb7fffa61a59263b1ad16aeb5fcc30e032bc3a8bf",
0,
"OP_HASH160 0x14 0x40aec8967698985eb369afd3ad3dc571110e6a10 OP_EQUAL",
155000]],
"0200000001bfa8c32b030ec3fcb5ae16adb16392a561faffb73ead12e4355f39a0d99f866a000000002322203b8d241649e612058fd2f1b4decbe9141284f0e4dd297d95b0da01a5d8791e4bb3000000000ae90300000000000017a914b04d55bbfedf606a08795fb0c2655bb3212f2bde87d00700000000000017a914d079c2cfad655234e68159422727eefa78811b4787b80b00000000000017a9145ea3edd87eb790af8051da692f4d59e5be6ffd4b87a00f00000000000017a914e17e2c4f4fcae1ef0d5ef96c740565426009ca2187881300000000000017a9144769d9f3b6fdf14f1223d9e7f11be7873bcbcde387701700000000000017a914064529bab7b89253159c9043ef128f37f78add7a87581b00000000000017a9147bae64476db031d744b442ddee9af3e60ef1e4ea87401f00000000000017a914dd2d96d0ba673c0b9d5950223c334f19f2b6f4a487282300000000000017a9148abaaa7b977855f96afacea4c79e3caf5e7482c487102700000000000017a9140dab14b1ee04aea522639ee27d29a5f6a57758c18700000000",
"CHECKTEMPLATEVERIFY,P2SH"],
["CTV at pos 2 with >1 Input Fails if too few inputs"],
[[["eeda9ea077b04abec103ffbba6bcf41cd67cdfdabe5ccc6ed766b9cd4ed4808a",
0,
"0x20 0x3e123dbe62352fa40471c195aebd3cdec43cca8728520c8a2d5737009fa05b0b OP_CHECKTEMPLATEVERIFY",
155000]],
"02000000018a80d44ecdb966d76ecc5cbedadf7cd61cf4bca6bbff03c1be4ab077a09edaee0000000000000000000ae80300000000000017a9144dd991d2f69eed133bb9d16e298703c830e1fb2387d00700000000000017a9147a50ac55b0af704dfffc797c507db803488ad44787b80b00000000000017a914caab97b53be0b75526e011bc49b0101365f611b887a00f00000000000017a91448c947e1b16103782a7dcba1dd5896936fbc7d2587881300000000000017a914ff075d852727e7e32ff5e11b13d254cb553fb73287701700000000000017a914761069764474d5ef5d0e068e88e4ebe2edd2336087581b00000000000017a914cd76c979ed6421f5d39380b5eb3d0dc7f56e864b87401f00000000000017a91417e7563571166469e14275be7ef00d91927eee0387282300000000000017a9140f9ddd36a76392fec584f05b34d33282fbd4921287102700000000000017a91417603536acce13cf7496387f8169a7f832f08f4c8700000000",
"CHECKTEMPLATEVERIFY"],
["CTV at pos 2 with >1 Input Fails if inputs in wrong order"],
[[["eeda9ea077b04abec103ffbba6bcf41cd67cdfdabe5ccc6ed766b9cd4ed4808a",
0,
"0x20 0x3e123dbe62352fa40471c195aebd3cdec43cca8728520c8a2d5737009fa05b0b OP_CHECKTEMPLATEVERIFY",
155000],
["b6d623f1e5eaaaa83a21739f60ac173818ce6b9e13ca18ddda74e9dbe6124c0b", 0, "1", 155000]],
"02000000028a80d44ecdb966d76ecc5cbedadf7cd61cf4bca6bbff03c1be4ab077a09edaee0000000000000000000b4c12e6dbe974dadd18ca139e6bce183817ac609f73213aa8aaeae5f123d6b60000000000000000000ae80300000000000017a9144dd991d2f69eed133bb9d16e298703c830e1fb2387d00700000000000017a9147a50ac55b0af704dfffc797c507db803488ad44787b80b00000000000017a914caab97b53be0b75526e011bc49b0101365f611b887a00f00000000000017a91448c947e1b16103782a7dcba1dd5896936fbc7d2587881300000000000017a914ff075d852727e7e32ff5e11b13d254cb553fb73287701700000000000017a914761069764474d5ef5d0e068e88e4ebe2edd2336087581b00000000000017a914cd76c979ed6421f5d39380b5eb3d0dc7f56e864b87401f00000000000017a91417e7563571166469e14275be7ef00d91927eee0387282300000000000017a9140f9ddd36a76392fec584f05b34d33282fbd4921287102700000000000017a91417603536acce13cf7496387f8169a7f832f08f4c8700000000",
"CHECKTEMPLATEVERIFY"],
["CTV at pos 2 with >1 Input Fails if scriptSig of other input modified"],
[[["eeda9ea077b04abec103ffbba6bcf41cd67cdfdabe5ccc6ed766b9cd4ed4808a",
0,
"0x20 0x3e123dbe62352fa40471c195aebd3cdec43cca8728520c8a2d5737009fa05b0b OP_CHECKTEMPLATEVERIFY",
155000],
["b6d623f1e5eaaaa83a21739f60ac173818ce6b9e13ca18ddda74e9dbe6124c0b", 0, "1", 155000]],
"02000000020b4c12e6dbe974dadd18ca139e6bce183817ac609f73213aa8aaeae5f123d6b6000000000151000000008a80d44ecdb966d76ecc5cbedadf7cd61cf4bca6bbff03c1be4ab077a09edaee0000000000000000000ae80300000000000017a9144dd991d2f69eed133bb9d16e298703c830e1fb2387d00700000000000017a9147a50ac55b0af704dfffc797c507db803488ad44787b80b00000000000017a914caab97b53be0b75526e011bc49b0101365f611b887a00f00000000000017a91448c947e1b16103782a7dcba1dd5896936fbc7d2587881300000000000017a914ff075d852727e7e32ff5e11b13d254cb553fb73287701700000000000017a914761069764474d5ef5d0e068e88e4ebe2edd2336087581b00000000000017a914cd76c979ed6421f5d39380b5eb3d0dc7f56e864b87401f00000000000017a91417e7563571166469e14275be7ef00d91927eee0387282300000000000017a9140f9ddd36a76392fec584f05b34d33282fbd4921287102700000000000017a91417603536acce13cf7496387f8169a7f832f08f4c8700000000",
"CHECKTEMPLATEVERIFY"],
["CTV at pos 1 with specific scriptsigs fails with incorrect scriptSig"],
[[["a2522fa96033c5736f3142ff616426cd03a3d0f077f609e22c5a33a96e04e597",
0,
"0x20 0x4870387ef3dc7b392294140a323ec7b38dc138710f0931ce27f386a57128ea63 OP_CHECKTEMPLATEVERIFY",
155000],
["b6d623f1e5eaaaa83a21739f60ac173818ce6b9e13ca18ddda74e9dbe6124c0b", 0, "1", 155000]],
"020000000297e5046ea9335a2ce209f677f0d0a303cd266461ff42316f73c53360a92f52a2000000000151000000000b4c12e6dbe974dadd18ca139e6bce183817ac609f73213aa8aaeae5f123d6b6000000000151000000000ae80300000000000017a9143f163a8747557345ce2e6fe00c1894f2f281795e87d00700000000000017a9144cf13dfda93a7413b7e646611735656e5457657087b80b00000000000017a914868998b49df649c37a88d48c9d4a5b37290e507287a00f00000000000017a914034f9914a77571a6396482e9881745c92c3037c687881300000000000017a914a8238003e1732e2baf4334a8546d72be99af9bae87701700000000000017a91491dbac5d67d5941115a03fc7eaec09f31a5b4dfc87581b00000000000017a914e0c0f19fec3b2993b9c116c798b5429d4515596687401f00000000000017a914d6b40d98d94530f1a1eb57614680813c81a95ccd87282300000000000017a914fb0bfb072bb79611a4323981828108a3cf54b0a687102700000000000017a9149e2d11f06ba667e981b802af10be8dabd08eafff8700000000",
"CHECKTEMPLATEVERIFY"],
["Make diffs cleaner by leaving a comment here without comma at the end"]
]

View File

@ -520,5 +520,157 @@
[[["1111111111111111111111111111111111111111111111111111111111111111", 0, "0x00 0x14 0x751e76e8199196d454941c45d1b3a323f1433bd6", 5000000]],
"0100000000010111111111111111111111111111111111111111111111111111111111111111110000000000ffffffff0130244c0000000000fd02014cdc1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111175210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac02483045022100c1a4a6581996a7fdfea77d58d537955a5655c1d619b6f3ab6874f28bb2e19708022056402db6fede03caae045a3be616a1a2d0919a475ed4be828dc9ff21f24063aa01210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800000000", "NONE"],
["Check that CTV is Processed with a Taproot Spend"],
[[["f90521604b56c392ffa17a01bcae5914b8cf7728cc6cec00d90838818cc5465f", 0, "1 0x20 0x24f5fe807bcee7774dc515f0b7ee8d6ae39eefd1b590264c52ff867e22c49419", 155000]],
"020000000001015f46c58c813808d900ec6ccc2877cfb81459aebc017aa1ff92c3564b602105f90000000000000000000ae80300000000000017a914ce0036ae7d49f06967dd92cc1ffff4a878c457f987d00700000000000017a91406e00c3b362e65e03507a2858d7b6499b668669887b80b00000000000017a9142ee42c65592c59b69bfefbd03781140c67e5232487a00f00000000000017a9146b3df16a1e6651d582ca6598900cb4f2d6c9dfb887881300000000000017a914877d55932d4f38b476d4db27e4efbe159ff0a07187701700000000000017a91441e9dc892e861d252d513d594ba833cd6bc8917087581b00000000000017a914b93075800c693dcc78b0553bf9d1cf879d76a02487401f00000000000017a914e9f0ea3a2cae0ad01114e2ec3502ef08bbc50af487282300000000000017a9149a645b5293bdf8be72cb9d1460bce7d64445cfad87102700000000000017a91451e5d6b2ee24ae128234c92245df3624620ea7d3870222209eb65498bfcd4eb90e61c2c5e323a9c16c8bfd8d53ba649915bcdb572099c12fb321c0b7e0105780185688d998a8f8438aa07637a5799755688ec80175cb26c0406e0200000000",
"DISCOURAGE_CHECKTEMPLATEVERIFY"],
["Check that CTV upgradability works (taproot)"],
[[["f90521604b56c392ffa17a01bcae5914b8cf7728cc6cec00d90838818cc5465f", 0, "1 0x20 0x24f5fe807bcee7774dc515f0b7ee8d6ae39eefd1b590264c52ff867e22c49419", 155000]],
"020000000001015f46c58c813808d900ec6ccc2877cfb81459aebc017aa1ff92c3564b602105f90000000000000000000ae80300000000000017a914ce0036ae7d49f06967dd92cc1ffff4a878c457f987d00700000000000017a91406e00c3b362e65e03507a2858d7b6499b668669887b80b00000000000017a9142ee42c65592c59b69bfefbd03781140c67e5232487a00f00000000000017a9146b3df16a1e6651d582ca6598900cb4f2d6c9dfb887881300000000000017a914877d55932d4f38b476d4db27e4efbe159ff0a07187701700000000000017a91441e9dc892e861d252d513d594ba833cd6bc8917087581b00000000000017a914b93075800c693dcc78b0553bf9d1cf879d76a02487401f00000000000017a914e9f0ea3a2cae0ad01114e2ec3502ef08bbc50af487282300000000000017a9149a645b5293bdf8be72cb9d1460bce7d64445cfad87102700000000000017a91451e5d6b2ee24ae128234c92245df3624620ea7d3870222209eb65498bfcd4eb90e61c2c5e323a9c16c8bfd8d53ba649915bcdb572099c12fb321c0b7e0105780185688d998a8f8438aa07637a5799755688ec80175cb26c0406e0200000000",
"DISCOURAGE_CHECKTEMPLATEVERIFY"],
["Segwit v0 CTV Spend"],
[[["c16621d89637274011a8fb02ac487d283367f33d36de8c1ec8e323e55cb149cb",
0,
"0x00 0x20 0xf47ad51491d952cb1fad0d3f208dde482561d2170ebbbbc08e2e0292eeb4ec3d",
155000]],
"02000000000101cb49b15ce523e3c81e8cde363df36733287d48ac02fba81140273796d82166c10000000000000000000ae80300000000000017a91496e75de842d245fe846f1866f535d3d549af1eee87d00700000000000017a91443078220afb62f1dd0f13b58103c2cdea3ec31eb87b80b00000000000017a914c2aabf119c1825b1de66bc34e0792e37c198b5a987a00f00000000000017a9146e9e99a0b342e90e9360e26aa1a2b12ac7d1701e87881300000000000017a9149fc2952de5c6268759a4addd6f1336585de5a6b687701700000000000017a914f0bb53b2734e0f4027b25084630f4c7cb793f0d087581b00000000000017a914151a578ea0bbe3a24bf8335c4ee162643be28b4787401f00000000000017a9148f7ffde60fa425fa919ab9de3c7731fa4268151787282300000000000017a91454c45d77bccc359d07a2b17b4abfc78e8c3237b787102700000000000017a914e43197dbd28424b86c7c8823180e2b15192a96d1870122207427029cbb0a48361ba1b83e4fff21918618477be3d217d83b2ff846815305f6b300000000",
"DISCOURAGE_CHECKTEMPLATEVERIFY"],
["Check that CTV upgradability works (Segwit v0)"],
[[["c16621d89637274011a8fb02ac487d283367f33d36de8c1ec8e323e55cb149cb",
0,
"0x00 0x20 0xf47ad51491d952cb1fad0d3f208dde482561d2170ebbbbc08e2e0292eeb4ec3d",
155000]],
"02000000000101cb49b15ce523e3c81e8cde363df36733287d48ac02fba81140273796d82166c10000000000000000000ae80300000000000017a91496e75de842d245fe846f1866f535d3d549af1eee87d00700000000000017a91443078220afb62f1dd0f13b58103c2cdea3ec31eb87b80b00000000000017a914c2aabf119c1825b1de66bc34e0792e37c198b5a987a00f00000000000017a9146e9e99a0b342e90e9360e26aa1a2b12ac7d1701e87881300000000000017a9149fc2952de5c6268759a4addd6f1336585de5a6b687701700000000000017a914f0bb53b2734e0f4027b25084630f4c7cb793f0d087581b00000000000017a914151a578ea0bbe3a24bf8335c4ee162643be28b4787401f00000000000017a9148f7ffde60fa425fa919ab9de3c7731fa4268151787282300000000000017a91454c45d77bccc359d07a2b17b4abfc78e8c3237b787102700000000000017a914e43197dbd28424b86c7c8823180e2b15192a96d1870122207427029cbb0a48361ba1b83e4fff21918618477be3d217d83b2ff846815305f6b300000000",
"DISCOURAGE_CHECKTEMPLATEVERIFY"],
["CTV reserves different sized args for future upgrades"],
[[["e8e9805801b7fb44814531de0dd498b955651b9c25a85a043d73f18970622647",
0,
"0x00 0x20 0x65f15821061635e6807f06701bf0a12d8e89dcff88df5968bd0822c9dbb52f1c",
155000]],
"020000000001014726627089f1733d045aa8259c1b6555b998d40dde31458144fbb7015880e9e80000000000000000000ae90300000000000017a91496e75de842d245fe846f1866f535d3d549af1eee87d00700000000000017a91443078220afb62f1dd0f13b58103c2cdea3ec31eb87b80b00000000000017a914c2aabf119c1825b1de66bc34e0792e37c198b5a987a00f00000000000017a9146e9e99a0b342e90e9360e26aa1a2b12ac7d1701e87881300000000000017a9149fc2952de5c6268759a4addd6f1336585de5a6b687701700000000000017a914f0bb53b2734e0f4027b25084630f4c7cb793f0d087581b00000000000017a914151a578ea0bbe3a24bf8335c4ee162643be28b4787401f00000000000017a9148f7ffde60fa425fa919ab9de3c7731fa4268151787282300000000000017a91454c45d77bccc359d07a2b17b4abfc78e8c3237b787102700000000000017a914e43197dbd28424b86c7c8823180e2b15192a96d18702015101b300000000",
"DISCOURAGE_UPGRADABLE_CHECKTEMPLATEVERIFY,DISCOURAGE_CHECKTEMPLATEVERIFY"],
["CheckTemplateVerify Argument from Witness Stack"],
[[["e8e9805801b7fb44814531de0dd498b955651b9c25a85a043d73f18970622647",
0,
"0x00 0x20 0x65f15821061635e6807f06701bf0a12d8e89dcff88df5968bd0822c9dbb52f1c",
155000]],
"020000000001014726627089f1733d045aa8259c1b6555b998d40dde31458144fbb7015880e9e80000000000000000000ae90300000000000017a91496e75de842d245fe846f1866f535d3d549af1eee87d00700000000000017a91443078220afb62f1dd0f13b58103c2cdea3ec31eb87b80b00000000000017a914c2aabf119c1825b1de66bc34e0792e37c198b5a987a00f00000000000017a9146e9e99a0b342e90e9360e26aa1a2b12ac7d1701e87881300000000000017a9149fc2952de5c6268759a4addd6f1336585de5a6b687701700000000000017a914f0bb53b2734e0f4027b25084630f4c7cb793f0d087581b00000000000017a914151a578ea0bbe3a24bf8335c4ee162643be28b4787401f00000000000017a9148f7ffde60fa425fa919ab9de3c7731fa4268151787282300000000000017a91454c45d77bccc359d07a2b17b4abfc78e8c3237b787102700000000000017a914e43197dbd28424b86c7c8823180e2b15192a96d18702204d5783a61241bdef19c3480e094cc933c91d2bde995c8c50407099184b501f4301b300000000",
"DISCOURAGE_CHECKTEMPLATEVERIFY"],
["CheckTemplateVerify Argument from Witness Stack"],
[[["e8e9805801b7fb44814531de0dd498b955651b9c25a85a043d73f18970622647",
0,
"0x00 0x20 0x65f15821061635e6807f06701bf0a12d8e89dcff88df5968bd0822c9dbb52f1c",
155000]],
"020000000001014726627089f1733d045aa8259c1b6555b998d40dde31458144fbb7015880e9e80000000000000000000ae90300000000000017a91496e75de842d245fe846f1866f535d3d549af1eee87d00700000000000017a91443078220afb62f1dd0f13b58103c2cdea3ec31eb87b80b00000000000017a914c2aabf119c1825b1de66bc34e0792e37c198b5a987a00f00000000000017a9146e9e99a0b342e90e9360e26aa1a2b12ac7d1701e87881300000000000017a9149fc2952de5c6268759a4addd6f1336585de5a6b687701700000000000017a914f0bb53b2734e0f4027b25084630f4c7cb793f0d087581b00000000000017a914151a578ea0bbe3a24bf8335c4ee162643be28b4787401f00000000000017a9148f7ffde60fa425fa919ab9de3c7731fa4268151787282300000000000017a91454c45d77bccc359d07a2b17b4abfc78e8c3237b787102700000000000017a914e43197dbd28424b86c7c8823180e2b15192a96d18702204d5783a61241bdef19c3480e094cc933c91d2bde995c8c50407099184b501f4301b300000000",
"DISCOURAGE_CHECKTEMPLATEVERIFY"],
["BEGIN CTV congestion control tree level with 4 levels:"],
["CTV congestion control tree level 0"],
[[["d0246d069143263bca9a2b176fcf64bd8e4975c7670ed33659b4b8f88d3e7446",
0,
"0x20 0x10618b50aa1120e9e940bbea8b6d081019e38fbb9b956b0ab4f61631d05727ca OP_CHECKTEMPLATEVERIFY",
16600]],
"020000000146743e8df8b8b45936d30e67c775498ebd64cf6f172b9aca3b264391066d24d000000000000000000002781e0000000000002220bceb923d731eddf09705690d6ee697d1b3d57279ad96910cfb66a8d43a638800b3781e00000000000022201210e50077518896fd1661bffc2c1e88ad6e204ec4e8755407b42a97347c1e1bb300000000",
"DISCOURAGE_CHECKTEMPLATEVERIFY"],
["CTV congestion control tree level 1"],
[[["b69f866d47ebb75eeecfbc3b9b641f926f11035b64ff27a5a5e88b9c065bddf5",
0,
"0x20 0xbceb923d731eddf09705690d6ee697d1b3d57279ad96910cfb66a8d43a638800 OP_CHECKTEMPLATEVERIFY",
7800]],
"0200000001f5dd5b069c8be8a5a527ff645b03116f921f649b3bbccfee5eb7eb476d869fb600000000000000000002480d00000000000022204c683607ca7950380df10647b223f656cd73d1f7ad67b30caf60d78337f913b2b3480d0000000000002220805bddd8b95a3cf3729b62703de37a1533b11634de76aa4a18605b640f1f3208b300000000",
"DISCOURAGE_CHECKTEMPLATEVERIFY"],
["CTV congestion control tree level 2"],
[[["7d331a33880504fa94478c9687f3f41322ec76f81edad8e72491cbb81eea4754",
0,
"0x20 0x4c683607ca7950380df10647b223f656cd73d1f7ad67b30caf60d78337f913b2 OP_CHECKTEMPLATEVERIFY",
3400]],
"02000000015447ea1eb8cb9124e7d8da1ef876ec2213f4f387968c4794fa040588331a337d00000000000000000002b004000000000000222084ac6e0fdbe91b09d1bf68158643ad68e0b3e64373738fb35711de0835011079b3b0040000000000002220241af26179a8e861cca473244723978127c16531f71fbcc33563c4f099651f8fb300000000",
"DISCOURAGE_CHECKTEMPLATEVERIFY"],
["CTV congestion control tree level 3"],
[[["e630b2357e02d1611a0615ce3964c408823ce3269974bd94e57ddea96900da70",
0,
"0x20 0x84ac6e0fdbe91b09d1bf68158643ad68e0b3e64373738fb35711de0835011079 OP_CHECKTEMPLATEVERIFY",
1200]],
"020000000170da0069a9de7de594bd749926e33c8208c46439ce15061a61d1027e35b230e60000000000000000000264000000000000001600141ca3bdf6bd2b1fc27420316a0d13f81fcdb85cb0640000000000000016001489d611c79700d6b4ae73d853ed49b86621d5802100000000",
"DISCOURAGE_CHECKTEMPLATEVERIFY"],
["END"],
["BEGIN CTV congestion control tree level with 4 levels:"],
["CTV congestion control tree level 0"],
[[["d0246d069143263bca9a2b176fcf64bd8e4975c7670ed33659b4b8f88d3e7446",
0,
"0x20 0x10618b50aa1120e9e940bbea8b6d081019e38fbb9b956b0ab4f61631d05727ca OP_CHECKTEMPLATEVERIFY",
16600]],
"020000000146743e8df8b8b45936d30e67c775498ebd64cf6f172b9aca3b264391066d24d000000000000000000002781e0000000000002220bceb923d731eddf09705690d6ee697d1b3d57279ad96910cfb66a8d43a638800b3781e00000000000022201210e50077518896fd1661bffc2c1e88ad6e204ec4e8755407b42a97347c1e1bb300000000",
"DISCOURAGE_CHECKTEMPLATEVERIFY"],
["CTV congestion control tree level 1"],
[[["b69f866d47ebb75eeecfbc3b9b641f926f11035b64ff27a5a5e88b9c065bddf5",
0,
"0x20 0xbceb923d731eddf09705690d6ee697d1b3d57279ad96910cfb66a8d43a638800 OP_CHECKTEMPLATEVERIFY",
7800]],
"0200000001f5dd5b069c8be8a5a527ff645b03116f921f649b3bbccfee5eb7eb476d869fb600000000000000000002480d00000000000022204c683607ca7950380df10647b223f656cd73d1f7ad67b30caf60d78337f913b2b3480d0000000000002220805bddd8b95a3cf3729b62703de37a1533b11634de76aa4a18605b640f1f3208b300000000",
"DISCOURAGE_CHECKTEMPLATEVERIFY"],
["CTV congestion control tree level 2"],
[[["7d331a33880504fa94478c9687f3f41322ec76f81edad8e72491cbb81eea4754",
0,
"0x20 0x4c683607ca7950380df10647b223f656cd73d1f7ad67b30caf60d78337f913b2 OP_CHECKTEMPLATEVERIFY",
3400]],
"02000000015447ea1eb8cb9124e7d8da1ef876ec2213f4f387968c4794fa040588331a337d00000000000000000002b004000000000000222084ac6e0fdbe91b09d1bf68158643ad68e0b3e64373738fb35711de0835011079b3b0040000000000002220241af26179a8e861cca473244723978127c16531f71fbcc33563c4f099651f8fb300000000",
"DISCOURAGE_CHECKTEMPLATEVERIFY"],
["CTV congestion control tree level 3"],
[[["e630b2357e02d1611a0615ce3964c408823ce3269974bd94e57ddea96900da70",
0,
"0x20 0x84ac6e0fdbe91b09d1bf68158643ad68e0b3e64373738fb35711de0835011079 OP_CHECKTEMPLATEVERIFY",
1200]],
"020000000170da0069a9de7de594bd749926e33c8208c46439ce15061a61d1027e35b230e60000000000000000000264000000000000001600141ca3bdf6bd2b1fc27420316a0d13f81fcdb85cb0640000000000000016001489d611c79700d6b4ae73d853ed49b86621d5802100000000",
"DISCOURAGE_CHECKTEMPLATEVERIFY"],
["END"],
["Test CTV with a specific scriptsig"],
[[["32858fe9a6348d4ee5fcfce78f6dbca0b54dff169ff4cc41439adca4e5d30746",
0,
"1",
155000],
["357722dce671e5aa52abd617002baa8d5d970cef43feca3bf2d4c8b1e5d53d11",
0,
"0x20 0x08a5903863a0562c0b5608521a8a77ca02e669eb01f3981eede6bf6f2f38c2c2 OP_CHECKTEMPLATEVERIFY",
155000]],
"0200000002113dd5e5b1c8d4f23bcafe43ef0c975d8daa2b0017d6ab52aae571e6dc227735000000000151000000004607d3e5a4dc9a4341ccf49f16ff4db5a0bc6d8fe7fcfce54e8d34a6e98f8532000000000100000000000ae80300000000000017a9146422bb825e07ab99ab915223ac67f195a4fb761987d00700000000000017a914cc9fa001f8c9ff9dfdecf0ec1356d37c808aec2d87b80b00000000000017a914092f42f35fd05eaf816a090ad8f1adec8394132d87a00f00000000000017a9147cfd2a76093289ebabf860d3071b92756dbde1b787881300000000000017a914c3d81e1a59c256bff75c535878e1701943a9e48987701700000000000017a914029ddf1319c05ff38cd974ba99fdcf1cb4b88b9687581b00000000000017a9148c95279a9fd452ad7b1cb7a35fd08e7ff55946af87401f00000000000017a9149216fef0f965b2f1890a420aa725cb86ba47a9c087282300000000000017a9141424c24d8cd907a36310db639ec7d194c62d620087102700000000000017a9145b278b155e6dd103b4bf5ba78e4a95c16926c9bd8700000000",
"CLEANSTACK,DISCOURAGE_CHECKTEMPLATEVERIFY"],
[[["32858fe9a6348d4ee5fcfce78f6dbca0b54dff169ff4cc41439adca4e5d30746",
0,
"1",
155000],
["357722dce671e5aa52abd617002baa8d5d970cef43feca3bf2d4c8b1e5d53d11",
0,
"0x20 0x08a5903863a0562c0b5608521a8a77ca02e669eb01f3981eede6bf6f2f38c2c2 OP_CHECKTEMPLATEVERIFY",
155000]],
"0200000002113dd5e5b1c8d4f23bcafe43ef0c975d8daa2b0017d6ab52aae571e6dc227735000000000151000000004607d3e5a4dc9a4341ccf49f16ff4db5a0bc6d8fe7fcfce54e8d34a6e98f8532000000000100000000000ae80300000000000017a9146422bb825e07ab99ab915223ac67f195a4fb761987d00700000000000017a914cc9fa001f8c9ff9dfdecf0ec1356d37c808aec2d87b80b00000000000017a914092f42f35fd05eaf816a090ad8f1adec8394132d87a00f00000000000017a9147cfd2a76093289ebabf860d3071b92756dbde1b787881300000000000017a914c3d81e1a59c256bff75c535878e1701943a9e48987701700000000000017a914029ddf1319c05ff38cd974ba99fdcf1cb4b88b9687581b00000000000017a9148c95279a9fd452ad7b1cb7a35fd08e7ff55946af87401f00000000000017a9149216fef0f965b2f1890a420aa725cb86ba47a9c087282300000000000017a9141424c24d8cd907a36310db639ec7d194c62d620087102700000000000017a9145b278b155e6dd103b4bf5ba78e4a95c16926c9bd8700000000",
"CLEANSTACK,DISCOURAGE_CHECKTEMPLATEVERIFY"],
["Test CTV with a specific scriptsig at different index"],
[[["e2f2baee9c59389b34e39742ce05debf64aaa7a00fbdab88614f4d3c133186d5",
0,
"1",
155000],
["c88e4b769a9211d2bca7516dbeacf250585dc825e41e34a65607a444b97fb782",
0,
"0x20 0xcc06acb181a8e9893c53c92fcfcb56fc004a360964af02cfd15b9f3321385f86 OP_CHECKTEMPLATEVERIFY",
155000]],
"0200000002d58631133c4d4f6188abbd0fa0a7aa64bfde05ce4297e3349b38599ceebaf2e20000000001510000000082b77fb944a40756a6341ee425c85d5850f2acbe6d51a7bcd211929a764b8ec8000000000100000000000ae80300000000000017a914d63e77972529f4db5b32efaa4e06f66ae0b5dc0987d00700000000000017a91488b6705f8c9568c52b55ed712c257f84f64a49f587b80b00000000000017a9142be57e9a179f8d9ff8f33a788d4b54512ea9e36087a00f00000000000017a91429261b4f65796f618908de9f51669014e2e2e04f87881300000000000017a914e3a1e1d24cbba3ca9369248082988bad3ceafcfb87701700000000000017a91403801b0a9591f3b5a00a5ea60fb34dc12b4a691187581b00000000000017a91465248bc2c732db2d88db0b0d677c1514b101025b87401f00000000000017a91420021e3dc4e80c7192c1a3cd04026d22d0f8d38287282300000000000017a914df27596dbff2028791bd7692846e65d16d8fed0d87102700000000000017a9142ed128e911cab04d3277d3635f79d5e3d7e6f4c48700000000",
"CLEANSTACK,DISCOURAGE_CHECKTEMPLATEVERIFY"],
[[["e2f2baee9c59389b34e39742ce05debf64aaa7a00fbdab88614f4d3c133186d5",
0,
"1",
155000],
["c88e4b769a9211d2bca7516dbeacf250585dc825e41e34a65607a444b97fb782",
0,
"0x20 0xcc06acb181a8e9893c53c92fcfcb56fc004a360964af02cfd15b9f3321385f86 OP_CHECKTEMPLATEVERIFY",
155000]],
"0200000002d58631133c4d4f6188abbd0fa0a7aa64bfde05ce4297e3349b38599ceebaf2e20000000001510000000082b77fb944a40756a6341ee425c85d5850f2acbe6d51a7bcd211929a764b8ec8000000000100000000000ae80300000000000017a914d63e77972529f4db5b32efaa4e06f66ae0b5dc0987d00700000000000017a91488b6705f8c9568c52b55ed712c257f84f64a49f587b80b00000000000017a9142be57e9a179f8d9ff8f33a788d4b54512ea9e36087a00f00000000000017a91429261b4f65796f618908de9f51669014e2e2e04f87881300000000000017a914e3a1e1d24cbba3ca9369248082988bad3ceafcfb87701700000000000017a91403801b0a9591f3b5a00a5ea60fb34dc12b4a691187581b00000000000017a91465248bc2c732db2d88db0b0d677c1514b101025b87401f00000000000017a91420021e3dc4e80c7192c1a3cd04026d22d0f8d38287282300000000000017a914df27596dbff2028791bd7692846e65d16d8fed0d87102700000000000017a9142ed128e911cab04d3277d3635f79d5e3d7e6f4c48700000000",
"CLEANSTACK,DISCOURAGE_CHECKTEMPLATEVERIFY"],
["Make diffs cleaner by leaving a comment here without comma at the end"]
]

View File

@ -76,6 +76,7 @@ FUZZ_TARGET(script, .init = initialize_script)
assert(which_type == TxoutType::PUBKEY ||
which_type == TxoutType::NONSTANDARD ||
which_type == TxoutType::NULL_DATA ||
which_type == TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY ||
which_type == TxoutType::MULTISIG);
}
if (which_type == TxoutType::NONSTANDARD ||

View File

@ -70,6 +70,9 @@ static std::map<std::string, unsigned int> mapFlagNames = {
{std::string("DISCOURAGE_UPGRADABLE_PUBKEYTYPE"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE},
{std::string("DISCOURAGE_OP_SUCCESS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS},
{std::string("DISCOURAGE_UPGRADABLE_TAPROOT_VERSION"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION},
{std::string("DISCOURAGE_UPGRADABLE_CHECKTEMPLATEVERIFY"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_CHECKTEMPLATEVERIFY},
{std::string("DISCOURAGE_CHECKTEMPLATEVERIFY"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_CHECKTEMPLATEVERIFY},
{std::string("CHECKTEMPLATEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKTEMPLATEVERIFY},
};
unsigned int ParseScriptFlags(std::string strFlags)

View File

@ -912,6 +912,8 @@ static std::string RecurseImportData(const CScript& script, ImportData& import_d
case TxoutType::WITNESS_V1_TAPROOT:
case TxoutType::ANCHOR:
return "unrecognized script";
case TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY:
return "bare default CheckTemplateVerify hash";
} // no default case, so the compiler can warn about missing cases
NONFATAL_UNREACHABLE();
}

View File

@ -208,6 +208,11 @@ IsMineResult IsMineInner(const LegacyDataSPKM& keystore, const CScript& scriptPu
}
break;
}
case TxoutType::TX_BARE_DEFAULT_CHECKTEMPLATEVERIFY:
{
ret = IsMineResult::NO;
break;
}
} // no default case, so the compiler can warn about missing cases
if (ret == IsMineResult::NO && keystore.HaveWatchOnly(scriptPubKey)) {

View File

@ -0,0 +1,445 @@
#!/usr/bin/env python3
# Copyright (c) 2015-2021 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test (CheckTemplateVerify)
"""
from test_framework.blocktools import (
create_coinbase,
create_block,
add_witness_commitment,
)
from test_framework.messages import (
CTransaction,
CTxOut,
CTxIn,
CTxInWitness,
COutPoint,
COIN,
sha256,
)
from test_framework.p2p import P2PInterface
from test_framework.script import (
CScript,
OP_TRUE,
OP_DEPTH,
OP_ENDIF,
OP_IF,
OP_CHECKTEMPLATEVERIFY,
OP_FALSE,
OP_DROP,
taproot_construct,
)
from test_framework.script_util import script_to_p2sh_script
from test_framework.key import ECKey, compute_xonly_pubkey
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error
from test_framework.wallet import MiniWallet, MiniWalletMode
from decimal import Decimal
import random
from io import BytesIO
from test_framework.address import script_to_p2sh
CHECKTEMPLATEVERIFY_ERROR = "non-mandatory-script-verify-flag (Script failed an OP_CHECKTEMPLATEVERIFY operation)"
DISCOURAGED_ERROR = (
"non-mandatory-script-verify-flag (NOPx reserved for soft-fork upgrades)"
)
STACK_TOO_SHORT_ERROR = (
"non-mandatory-script-verify-flag (Operation not valid with the current stack size)"
)
def random_bytes(n):
return bytes(random.getrandbits(8) for i in range(n))
def template_hash_for_outputs(outputs, nIn=0, nVin=1, vin_override=None):
c = CTransaction()
c.version = 2
c.vin = vin_override
if vin_override is None:
c.vin = [CTxIn()] * nVin
c.vout = outputs
return c.get_standard_template_hash(nIn)
def random_p2sh():
return script_to_p2sh_script(random_bytes(20))
def random_real_outputs_and_script(n, nIn=0, nVin=1, vin_override=None):
outputs = [CTxOut((x + 1) * 1000, random_p2sh()) for x in range(n)]
script = CScript(
[
template_hash_for_outputs(outputs, nIn, nVin, vin_override),
OP_CHECKTEMPLATEVERIFY,
]
)
return outputs, script
def random_secure_tree(depth):
leaf_nodes = [
CTxOut(nValue=100, scriptPubKey=CScript(bytes([0, 0x14]) + random_bytes(20)))
for x in range(2 ** depth)
]
outputs_tree = [[CTxOut()] * (2 ** i) for i in range(depth)] + [leaf_nodes]
for d in range(1, depth + 2):
idxs = zip(
range(0, len(outputs_tree[-d]), 2), range(1, len(outputs_tree[-d]), 2)
)
for (idx, (a, b)) in enumerate(
[(outputs_tree[-d][i], outputs_tree[-d][j]) for (i, j) in idxs]
):
s = CScript(
bytes([0x20])
+ template_hash_for_outputs([a, b])
+ bytes([OP_CHECKTEMPLATEVERIFY])
)
a = sum(o.nValue for o in [a, b])
t = CTxOut(a + 1000, s)
outputs_tree[-d - 1][idx] = t
return outputs_tree
def create_transaction_to_script(node, wallet, txid, script, *, amount_sats):
"""Return signed transaction spending the first output of the
input txid. Note that the node must be able to sign for the
output that is being spent, and the node must not be running
multiple wallets.
"""
random_address = script_to_p2sh(CScript())
output = wallet.get_utxo(txid=txid)
rawtx = node.createrawtransaction(
inputs=[{"txid": output["txid"], "vout": output["vout"]}],
outputs={random_address: Decimal(amount_sats) / COIN},
)
tx = CTransaction()
tx.deserialize(BytesIO(bytes.fromhex(rawtx)))
# Replace with our script
tx.vout[0].scriptPubKey = script
# Sign
wallet.sign_tx(tx)
return tx
class CheckTemplateVerifyTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.extra_args = [
["-par=1"]
] # Use only one script thread to get the exact reject reason for testing
self.setup_clean_chain = True
self.rpc_timeout = 120
def get_block(self, txs):
self.tip = self.nodes[0].getbestblockhash()
self.height = self.nodes[0].getblockcount()
self.log.debug(self.height)
block = create_block(int(self.tip, 16), create_coinbase(self.height + 1))
block.vtx.extend(txs)
add_witness_commitment(block)
block.hashMerkleRoot = block.calc_merkle_root()
block.solve()
return block.serialize(True).hex(), block.hash
def add_block(self, txs):
block, h = self.get_block(txs)
reason = self.nodes[0].submitblock(block)
if reason:
self.log.debug("Reject Reason: [%s]", reason)
assert_equal(self.nodes[0].getbestblockhash(), h)
return h
def fail_block(self, txs, cause=CHECKTEMPLATEVERIFY_ERROR):
block, h = self.get_block(txs)
assert_equal(self.nodes[0].submitblock(block), cause)
assert_equal(self.nodes[0].getbestblockhash(), self.tip)
def run_test(self):
# The goal is to test a number of circumstances and combinations of parameters. Roughly:
#
# - Taproot OP_CTV
# - SegWit OP_CTV
# - SegWit OP_CTV wrong size on stack
# - fails policy
# - passes consensus
# - SegWit OP_CTV no argument in stack from program
# - fails policy and consensus with empty stack
# - passes consensus and policy when argument is the correct hash
# - passes consensus when argument is non 32 bytes
# - fails policy when argument is non 32 bytes
# - P2SH OP_CTV (impossible to spend w/o hash cycle!)
# - Bare OP_CTV
# - OP_CTV at vin index 0
# - OP_CTV at vin index > 0
# - OP_CTV with scriptSigs set
# - OP_CTV without scriptSigs set
# - OP_CTV with multiple inputs
# - accepting correct parameters
# - rejecting incorrect parameters
# - OP_CTV in a tree
#
# A few tests may seem redundant, but it is because they are testing the cached computation of the hash
# at vin index 0
wallet = MiniWallet(self.nodes[0], mode=MiniWalletMode.RAW_P2PK)
self.nodes[0].add_p2p_connection(P2PInterface())
BLOCKS = 115
self.log.info("Mining %d blocks for mature coinbases", BLOCKS)
# Drop the last 100 as they're unspendable!
coinbase_txids = [
self.nodes[0].getblock(b)["tx"][0]
for b in self.generate(wallet, BLOCKS)[:-100]
]
get_coinbase = lambda: coinbase_txids.pop()
self.log.info("Creating setup transactions")
self.log.info("Creating script for 10 random outputs")
outputs, script = random_real_outputs_and_script(10)
# Add some fee satoshis
amount_sats = sum(out.nValue for out in outputs) + 200 * 500
self.log.info("Creating funding txn for 10 random outputs as a Taproot script")
private_key = ECKey()
# use simple deterministic private key (k=1)
private_key.set((1).to_bytes(32, "big"), False)
assert private_key.is_valid
public_key, _ = compute_xonly_pubkey(private_key.get_bytes())
taproot = taproot_construct(public_key, [("only-path", script, 0xC0)])
taproot_ctv_funding_tx = create_transaction_to_script(
self.nodes[0],
wallet,
get_coinbase(),
taproot.scriptPubKey,
amount_sats=amount_sats,
)
self.log.info("Creating funding txn for 10 random outputs as a segwit script")
segwit_ctv_funding_tx = create_transaction_to_script(
self.nodes[0],
wallet,
get_coinbase(),
CScript([0, sha256(script)]),
amount_sats=amount_sats,
)
self.log.info("Creating a CTV with a non 32 byte stack segwit script")
segwit_ctv_funding_tx_wrongsize_stack = create_transaction_to_script(
self.nodes[0],
wallet,
get_coinbase(),
CScript([0, sha256(CScript([OP_TRUE, OP_CHECKTEMPLATEVERIFY]))]),
amount_sats=amount_sats,
)
self.log.info("Creating a CTV with an empty stack segwit script")
# allows either calling with empty witness stack or with a 32 byte hash (cleanstack rule)
empty_stack_script = CScript(
[OP_CHECKTEMPLATEVERIFY, OP_DEPTH, OP_IF, OP_DROP, OP_ENDIF, OP_TRUE]
)
segwit_ctv_funding_tx_empty_stack = create_transaction_to_script(
self.nodes[0],
wallet,
get_coinbase(),
CScript([0, sha256(empty_stack_script)]),
amount_sats=amount_sats,
)
self.log.info(
"Creating funding txn for 10 random outputs as a p2sh script (impossible to spend)"
)
p2sh_ctv_funding_tx = create_transaction_to_script(
self.nodes[0],
wallet,
get_coinbase(),
script_to_p2sh_script(script),
amount_sats=amount_sats,
)
# Small tree size 4 for test speed.
# Can be set to a large value like 16 (i.e., 65K txns).
TREE_SIZE = 4
self.log.info(f"Creating script for tree size depth {TREE_SIZE}")
congestion_tree_txo = random_secure_tree(TREE_SIZE)
self.log.info(f"Creating funding txn for tree size depth {TREE_SIZE}")
bare_ctv_tree_funding_tx = create_transaction_to_script(
self.nodes[0],
wallet,
get_coinbase(),
congestion_tree_txo[0][0].scriptPubKey,
amount_sats=congestion_tree_txo[0][0].nValue,
)
self.log.info("Creating script for spend at position 2")
outputs_position_2, script_position_2 = random_real_outputs_and_script(10, 1, 2)
# Add some fee satoshis
amount_position_2 = sum(out.nValue for out in outputs_position_2) + 200 * 500
self.log.info("Creating funding txn for spend at position 2")
bare_ctv_position_2_funding_tx = create_transaction_to_script(
self.nodes[0],
wallet,
get_coinbase(),
script_position_2,
amount_sats=amount_position_2,
)
self.log.info(
"Creating script for spend at position 1 with 2 non-null scriptsigs"
)
(
outputs_specific_scriptSigs,
script_specific_scriptSigs,
) = random_real_outputs_and_script(
10,
0,
2,
[CTxIn(scriptSig=CScript([OP_TRUE])), CTxIn(scriptSig=CScript([OP_FALSE]))],
)
# Add some fee satoshis
amount_specific_scriptSigs = (
sum(out.nValue for out in outputs_specific_scriptSigs) + 200 * 500
)
self.log.info(
"Creating funding txn for spend at position 1 with 2 non-null scriptsigs"
)
bare_ctv_specific_scriptSigs_funding_tx = create_transaction_to_script(
self.nodes[0],
wallet,
get_coinbase(),
script_specific_scriptSigs,
amount_sats=amount_specific_scriptSigs,
)
self.log.info(
"Creating script for spend at position 2 with 2 non-null scriptsigs"
)
(
outputs_specific_scriptSigs_position_2,
script_specific_scriptSigs_position_2,
) = random_real_outputs_and_script(
10,
1,
2,
[CTxIn(scriptSig=CScript([OP_TRUE])), CTxIn(scriptSig=CScript([OP_FALSE]))],
)
# Add some fee satoshis
amount_specific_scriptSigs_position_2 = (
sum(out.nValue for out in outputs_specific_scriptSigs_position_2)
+ 200 * 500
)
self.log.info(
"Creating funding txn for spend at position 2 with 2 non-null scriptsigs"
)
bare_ctv_specific_scriptSigs_position_2_funding_tx = (
create_transaction_to_script(
self.nodes[0],
wallet,
get_coinbase(),
script_specific_scriptSigs_position_2,
amount_sats=amount_specific_scriptSigs_position_2,
)
)
self.log.info("Creating funding txns for some anyone can spend outputs")
anyone_can_spend_funding_tx = create_transaction_to_script(
self.nodes[0],
wallet,
get_coinbase(),
CScript([OP_TRUE]),
amount_sats=amount_sats,
)
bare_anyone_can_spend_funding_tx = create_transaction_to_script(
self.nodes[0],
wallet,
get_coinbase(),
CScript([OP_TRUE]),
amount_sats=amount_sats,
)
funding_txs = [
taproot_ctv_funding_tx,
segwit_ctv_funding_tx,
segwit_ctv_funding_tx_wrongsize_stack,
segwit_ctv_funding_tx_empty_stack,
p2sh_ctv_funding_tx,
anyone_can_spend_funding_tx,
bare_ctv_tree_funding_tx,
bare_ctv_position_2_funding_tx,
bare_anyone_can_spend_funding_tx,
bare_ctv_specific_scriptSigs_funding_tx,
bare_ctv_specific_scriptSigs_position_2_funding_tx,
]
self.log.info("Obtaining TXIDs")
(
taproot_ctv_outpoint,
segwit_ctv_outpoint,
segwit_ctv_wrongsize_stack_outpoint,
segwit_ctv_empty_stack_outpoint,
p2sh_ctv_outpoint,
anyone_can_spend_outpoint,
bare_ctv_tree_outpoint,
bare_ctv_position_2_outpoint,
bare_anyone_can_spend_outpoint,
bare_ctv_specific_scriptSigs_outpoint,
bare_ctv_specific_scriptSigs_position_2_outpoint,
) = [COutPoint(int(tx.rehash(), 16), 0) for tx in funding_txs]
self.log.info("Funding all outputs")
self.add_block(funding_txs)
self.log.info("Testing Taproot OP_CHECKTEMPLATEVERIFY spend")
# Test sendrawtransaction
taproot_check_template_verify_tx = CTransaction()
taproot_check_template_verify_tx.version = 2
taproot_check_template_verify_tx.vin = [CTxIn(taproot_ctv_outpoint)]
taproot_check_template_verify_tx.vout = outputs
taproot_check_template_verify_tx.wit.vtxinwit += [CTxInWitness()]
taproot_check_template_verify_tx.wit.vtxinwit[0].scriptWitness.stack = [
script,
bytes([0xC0 + taproot.negflag]) + taproot.internal_pubkey,
]
assert_raises_rpc_error(
-26,
DISCOURAGED_ERROR,
self.nodes[0].sendrawtransaction,
taproot_check_template_verify_tx.serialize().hex(),
)
self.log.info(
"Taproot OP_CHECKTEMPLATEVERIFY spend discouraged by sendrawtransaction"
)
self.log.info("Testing Segwit OP_CHECKTEMPLATEVERIFY spend")
# Test sendrawtransaction
check_template_verify_tx = CTransaction()
check_template_verify_tx.version = 2
check_template_verify_tx.vin = [CTxIn(segwit_ctv_outpoint)]
check_template_verify_tx.vout = outputs
check_template_verify_tx.wit.vtxinwit += [CTxInWitness()]
check_template_verify_tx.wit.vtxinwit[0].scriptWitness.stack = [script]
assert_raises_rpc_error(
-26,
DISCOURAGED_ERROR,
self.nodes[0].sendrawtransaction,
check_template_verify_tx.serialize().hex(),
)
self.log.info(
"Segwit OP_CHECKTEMPLATEVERIFY spend discouraged by sendrawtransaction"
)
# TODO: In Jeremy's original patches, there were many additional tests. We
# should add these back once a proper deployment is specified for
# CHECKTEMPLATEVERIFY, and can be mocked with `-testactivationheight=`.
if __name__ == "__main__":
CheckTemplateVerifyTest(__file__).main()

View File

@ -25,6 +25,7 @@ from io import BytesIO
import math
import random
import socket
import struct
import time
import unittest
@ -633,6 +634,19 @@ class CTransaction:
r += self.nLockTime.to_bytes(4, "little")
return r
def get_standard_template_hash(self, nIn):
r = b""
r += self.version.to_bytes(4, "little")
r += self.nLockTime.to_bytes(4, "little")
if any(inp.scriptSig for inp in self.vin):
r += sha256(b"".join(ser_string(inp.scriptSig) for inp in self.vin))
r += struct.pack("<I", len(self.vin))
r += sha256(b"".join(struct.pack("<I", inp.nSequence) for inp in self.vin))
r += struct.pack("<I", len(self.vout))
r += sha256(b"".join(out.serialize() for out in self.vout))
r += struct.pack("<I", nIn)
return sha256(r)
# Only serialize with witness when explicitly called for
def serialize_with_witness(self):
flags = 0

View File

@ -240,7 +240,7 @@ OP_CHECKMULTISIGVERIFY = CScriptOp(0xaf)
OP_NOP1 = CScriptOp(0xb0)
OP_CHECKLOCKTIMEVERIFY = CScriptOp(0xb1)
OP_CHECKSEQUENCEVERIFY = CScriptOp(0xb2)
OP_NOP4 = CScriptOp(0xb3)
OP_CHECKTEMPLATEVERIFY = CScriptOp(0xb3)
OP_NOP5 = CScriptOp(0xb4)
OP_NOP6 = CScriptOp(0xb5)
OP_NOP7 = CScriptOp(0xb6)
@ -358,7 +358,7 @@ OPCODE_NAMES.update({
OP_NOP1: 'OP_NOP1',
OP_CHECKLOCKTIMEVERIFY: 'OP_CHECKLOCKTIMEVERIFY',
OP_CHECKSEQUENCEVERIFY: 'OP_CHECKSEQUENCEVERIFY',
OP_NOP4: 'OP_NOP4',
OP_CHECKTEMPLATEVERIFY : 'OP_CHECKTEMPLATEVERIFY',
OP_NOP5: 'OP_NOP5',
OP_NOP6: 'OP_NOP6',
OP_NOP7: 'OP_NOP7',

View File

@ -311,6 +311,7 @@ BASE_SCRIPTS = [
'wallet_balance.py --descriptors',
'p2p_initial_headers_sync.py',
'feature_nulldummy.py',
'feature_checktemplateverify.py',
'mempool_accept.py',
'mempool_expiry.py',
'wallet_import_with_label.py --legacy-wallet',