Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2011-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <primitives/transaction.h>6#include <script/interpreter.h>7#include <script/script.h>8#include <script/sigcache.h>9#include <script/sign.h>10#include <script/signingprovider.h>11#include <span.h>12#include <streams.h>13#include <test/util/json.h>14#include <util/check.h>15#include <util/fs.h>16#include <util/strencodings.h>18#include <cstdint>19#include <cstdlib>20#include <fstream>21#include <utility>22#include <vector>24#include <boost/test/unit_test.hpp>26#include <univalue.h>28script_verify_flags ParseScriptFlags(std::string strFlags);30BOOST_AUTO_TEST_SUITE(script_assets_tests)32template <typename T>33CScript ToScript(const T& byte_container)34{35auto span{MakeUCharSpan(byte_container)};36return {span.begin(), span.end()};37}39static CScript ScriptFromHex(const std::string& str)40{41return ToScript(*Assert(TryParseHex(str)));42}44static CMutableTransaction TxFromHex(const std::string& str)45{46CMutableTransaction tx;47SpanReader{ParseHex(str)} >> TX_NO_WITNESS(tx);48return tx;49}51static std::vector<CTxOut> TxOutsFromJSON(const UniValue& univalue)52{53assert(univalue.isArray());54std::vector<CTxOut> prevouts;55for (size_t i = 0; i < univalue.size(); ++i) {56CTxOut txout;57SpanReader{ParseHex(univalue[i].get_str())} >> txout;58prevouts.push_back(std::move(txout));59}60return prevouts;61}63static CScriptWitness ScriptWitnessFromJSON(const UniValue& univalue)64{65assert(univalue.isArray());66CScriptWitness scriptwitness;67for (size_t i = 0; i < univalue.size(); ++i) {68auto bytes = ParseHex(univalue[i].get_str());69scriptwitness.stack.push_back(std::move(bytes));70}71return scriptwitness;72}74static std::vector<script_verify_flags> AllConsensusFlags()75{76std::vector<script_verify_flags> ret;78for (unsigned int i = 0; i < 128; ++i) {79script_verify_flags flag = 0;80if (i & 1) flag |= SCRIPT_VERIFY_P2SH;81if (i & 2) flag |= SCRIPT_VERIFY_DERSIG;82if (i & 4) flag |= SCRIPT_VERIFY_NULLDUMMY;83if (i & 8) flag |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;84if (i & 16) flag |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;85if (i & 32) flag |= SCRIPT_VERIFY_WITNESS;86if (i & 64) flag |= SCRIPT_VERIFY_TAPROOT;88// SCRIPT_VERIFY_WITNESS requires SCRIPT_VERIFY_P2SH89if (flag & SCRIPT_VERIFY_WITNESS && !(flag & SCRIPT_VERIFY_P2SH)) continue;90// SCRIPT_VERIFY_TAPROOT requires SCRIPT_VERIFY_WITNESS91if (flag & SCRIPT_VERIFY_TAPROOT && !(flag & SCRIPT_VERIFY_WITNESS)) continue;93ret.push_back(flag);94}96return ret;97}99/** Precomputed list of all valid combinations of consensus-relevant script validation flags. */100static const std::vector<script_verify_flags> ALL_CONSENSUS_FLAGS = AllConsensusFlags();102static void AssetTest(const UniValue& test, SignatureCache& signature_cache)103{104BOOST_CHECK(test.isObject());106CMutableTransaction mtx = TxFromHex(test["tx"].get_str());107const std::vector<CTxOut> prevouts = TxOutsFromJSON(test["prevouts"]);108BOOST_CHECK(prevouts.size() == mtx.vin.size());109size_t idx = test["index"].getInt<int64_t>();110script_verify_flags test_flags{ParseScriptFlags(test["flags"].get_str())};111bool fin = test.exists("final") && test["final"].get_bool();113if (test.exists("success")) {114mtx.vin[idx].scriptSig = ScriptFromHex(test["success"]["scriptSig"].get_str());115mtx.vin[idx].scriptWitness = ScriptWitnessFromJSON(test["success"]["witness"]);116CTransaction tx(mtx);117PrecomputedTransactionData txdata;118txdata.Init(tx, std::vector<CTxOut>(prevouts));119CachingTransactionSignatureChecker txcheck(&tx, idx, prevouts[idx].nValue, true, signature_cache, txdata);121for (const auto flags : ALL_CONSENSUS_FLAGS) {122// "final": true tests are valid for all flags. Others are only valid with flags that are123// a subset of test_flags.124if (fin || ((flags & test_flags) == flags)) {125bool ret = VerifyScript(tx.vin[idx].scriptSig, prevouts[idx].scriptPubKey, &tx.vin[idx].scriptWitness, flags, txcheck, nullptr);126BOOST_CHECK(ret);127}128}129}131if (test.exists("failure")) {132mtx.vin[idx].scriptSig = ScriptFromHex(test["failure"]["scriptSig"].get_str());133mtx.vin[idx].scriptWitness = ScriptWitnessFromJSON(test["failure"]["witness"]);134CTransaction tx(mtx);135PrecomputedTransactionData txdata;136txdata.Init(tx, std::vector<CTxOut>(prevouts));137CachingTransactionSignatureChecker txcheck(&tx, idx, prevouts[idx].nValue, true, signature_cache, txdata);139for (const auto flags : ALL_CONSENSUS_FLAGS) {140// If a test is supposed to fail with test_flags, it should also fail with any superset thereof.141if ((flags & test_flags) == test_flags) {142bool ret = VerifyScript(tx.vin[idx].scriptSig, prevouts[idx].scriptPubKey, &tx.vin[idx].scriptWitness, flags, txcheck, nullptr);143BOOST_CHECK(!ret);144}145}146}147}149BOOST_AUTO_TEST_CASE(script_assets_test)150{151// See src/test/fuzz/script_assets_test_minimizer.cpp for information on how to generate152// the script_assets_test.json file used by this test.153SignatureCache signature_cache{DEFAULT_SIGNATURE_CACHE_BYTES};155const char* dir = std::getenv("DIR_UNIT_TEST_DATA");156BOOST_WARN_MESSAGE(dir != nullptr, "Variable DIR_UNIT_TEST_DATA unset, skipping script_assets_test");157if (dir == nullptr) return;158auto path = fs::path(dir) / "script_assets_test.json";159bool exists = fs::exists(path);160BOOST_WARN_MESSAGE(exists, "File $DIR_UNIT_TEST_DATA/script_assets_test.json not found, skipping script_assets_test");161if (!exists) return;162std::ifstream file{path.std_path()};163BOOST_CHECK(file.is_open());164file.seekg(0, std::ios::end);165size_t length = file.tellg();166file.seekg(0, std::ios::beg);167std::string data(length, '\0');168file.read(data.data(), data.size());169UniValue tests = read_json(data);170BOOST_CHECK(tests.isArray());171BOOST_CHECK(tests.size() > 0);173for (size_t i = 0; i < tests.size(); i++) {174AssetTest(tests[i], signature_cache);175}176file.close();177}179BOOST_AUTO_TEST_SUITE_END()
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.