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 <common/system.h>6#include <compressor.h>7#include <core_io.h>8#include <key.h>9#include <rpc/util.h>10#include <script/interpreter.h>11#include <script/script.h>12#include <script/script_error.h>13#include <script/sigcache.h>14#include <script/sign.h>15#include <script/signingprovider.h>16#include <script/solver.h>17#include <secp256k1.h>18#include <streams.h>19#include <test/data/bip341_wallet_vectors.json.h>20#include <test/data/script_tests.json.h>21#include <test/util/common.h>22#include <test/util/json.h>23#include <test/util/random.h>24#include <test/util/setup_common.h>25#include <test/util/transaction_utils.h>26#include <univalue.h>27#include <util/check.h>28#include <util/fs.h>29#include <util/strencodings.h>30#include <util/string.h>32#include <boost/test/unit_test.hpp>34#include <cstdint>35#include <string>36#include <vector>38// Uncomment if you want to output updated JSON tests.39// #define UPDATE_JSON_TESTS41using namespace util::hex_literals;43static const script_verify_flags gFlags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;45script_verify_flags ParseScriptFlags(std::string strFlags);47struct ScriptErrorDesc48{49ScriptError_t err;50const char *name;51};53static ScriptErrorDesc script_errors[]={54{SCRIPT_ERR_OK, "OK"},55{SCRIPT_ERR_EVAL_FALSE, "EVAL_FALSE"},56{SCRIPT_ERR_OP_RETURN, "OP_RETURN"},57{SCRIPT_ERR_SCRIPT_SIZE, "SCRIPT_SIZE"},58{SCRIPT_ERR_PUSH_SIZE, "PUSH_SIZE"},59{SCRIPT_ERR_OP_COUNT, "OP_COUNT"},60{SCRIPT_ERR_STACK_SIZE, "STACK_SIZE"},61{SCRIPT_ERR_SIG_COUNT, "SIG_COUNT"},62{SCRIPT_ERR_PUBKEY_COUNT, "PUBKEY_COUNT"},63{SCRIPT_ERR_VERIFY, "VERIFY"},64{SCRIPT_ERR_EQUALVERIFY, "EQUALVERIFY"},65{SCRIPT_ERR_CHECKMULTISIGVERIFY, "CHECKMULTISIGVERIFY"},66{SCRIPT_ERR_CHECKSIGVERIFY, "CHECKSIGVERIFY"},67{SCRIPT_ERR_NUMEQUALVERIFY, "NUMEQUALVERIFY"},68{SCRIPT_ERR_BAD_OPCODE, "BAD_OPCODE"},69{SCRIPT_ERR_DISABLED_OPCODE, "DISABLED_OPCODE"},70{SCRIPT_ERR_INVALID_STACK_OPERATION, "INVALID_STACK_OPERATION"},71{SCRIPT_ERR_INVALID_ALTSTACK_OPERATION, "INVALID_ALTSTACK_OPERATION"},72{SCRIPT_ERR_UNBALANCED_CONDITIONAL, "UNBALANCED_CONDITIONAL"},73{SCRIPT_ERR_NEGATIVE_LOCKTIME, "NEGATIVE_LOCKTIME"},74{SCRIPT_ERR_UNSATISFIED_LOCKTIME, "UNSATISFIED_LOCKTIME"},75{SCRIPT_ERR_SIG_HASHTYPE, "SIG_HASHTYPE"},76{SCRIPT_ERR_SIG_DER, "SIG_DER"},77{SCRIPT_ERR_MINIMALDATA, "MINIMALDATA"},78{SCRIPT_ERR_SIG_PUSHONLY, "SIG_PUSHONLY"},79{SCRIPT_ERR_SIG_HIGH_S, "SIG_HIGH_S"},80{SCRIPT_ERR_SIG_NULLDUMMY, "SIG_NULLDUMMY"},81{SCRIPT_ERR_PUBKEYTYPE, "PUBKEYTYPE"},82{SCRIPT_ERR_CLEANSTACK, "CLEANSTACK"},83{SCRIPT_ERR_MINIMALIF, "MINIMALIF"},84{SCRIPT_ERR_SIG_NULLFAIL, "NULLFAIL"},85{SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, "DISCOURAGE_UPGRADABLE_NOPS"},86{SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM, "DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"},87{SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH, "WITNESS_PROGRAM_WRONG_LENGTH"},88{SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY, "WITNESS_PROGRAM_WITNESS_EMPTY"},89{SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH, "WITNESS_PROGRAM_MISMATCH"},90{SCRIPT_ERR_WITNESS_MALLEATED, "WITNESS_MALLEATED"},91{SCRIPT_ERR_WITNESS_MALLEATED_P2SH, "WITNESS_MALLEATED_P2SH"},92{SCRIPT_ERR_WITNESS_UNEXPECTED, "WITNESS_UNEXPECTED"},93{SCRIPT_ERR_WITNESS_PUBKEYTYPE, "WITNESS_PUBKEYTYPE"},94{SCRIPT_ERR_TAPSCRIPT_EMPTY_PUBKEY, "TAPSCRIPT_EMPTY_PUBKEY"},95{SCRIPT_ERR_OP_CODESEPARATOR, "OP_CODESEPARATOR"},96{SCRIPT_ERR_SIG_FINDANDDELETE, "SIG_FINDANDDELETE"},97{SCRIPT_ERR_SCRIPTNUM, "SCRIPTNUM"}98};100static std::string FormatScriptFlags(script_verify_flags flags)101{102return util::Join(GetScriptFlagNames(flags), ",");103}105static std::string FormatScriptError(ScriptError_t err)106{107for (const auto& se : script_errors)108if (se.err == err)109return se.name;110BOOST_ERROR("Unknown scripterror enumeration value, update script_errors in script_tests.cpp.");111return "";112}114static ScriptError_t ParseScriptError(const std::string& name)115{116for (const auto& se : script_errors)117if (se.name == name)118return se.err;119BOOST_ERROR("Unknown scripterror \"" << name << "\" in test description");120return SCRIPT_ERR_UNKNOWN_ERROR;121}123struct ScriptTest : BasicTestingSetup {124void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScriptWitness& scriptWitness, script_verify_flags flags, const std::string& message, int scriptError, CAmount nValue = 0)125{126bool expect = (scriptError == SCRIPT_ERR_OK);127if (flags & SCRIPT_VERIFY_CLEANSTACK) {128flags |= SCRIPT_VERIFY_P2SH;129flags |= SCRIPT_VERIFY_WITNESS;130}131ScriptError err;132const CTransaction txCredit{BuildCreditingTransaction(scriptPubKey, nValue)};133CMutableTransaction tx = BuildSpendingTransaction(scriptSig, scriptWitness, txCredit);134BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, &scriptWitness, flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue, MissingDataBehavior::ASSERT_FAIL), &err) == expect, message);135BOOST_CHECK_MESSAGE(err == scriptError, FormatScriptError(err) + " where " + FormatScriptError((ScriptError_t)scriptError) + " expected: " + message);137// Verify that removing flags from a passing test or adding flags to a failing test does not change the result.138for (int i = 0; i < 256; ++i) {139script_verify_flags extra_flags = script_verify_flags::from_int(m_rng.randbits(MAX_SCRIPT_VERIFY_FLAGS_BITS));140script_verify_flags combined_flags{expect ? (flags & ~extra_flags) : (flags | extra_flags)};141// Weed out some invalid flag combinations.142if (combined_flags & SCRIPT_VERIFY_CLEANSTACK && ~combined_flags & (SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS)) continue;143if (combined_flags & SCRIPT_VERIFY_WITNESS && ~combined_flags & SCRIPT_VERIFY_P2SH) continue;144BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, &scriptWitness, combined_flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue, MissingDataBehavior::ASSERT_FAIL), &err) == expect, message + strprintf(" (with flags %x)", combined_flags.as_int()));145}146}147}; // struct ScriptTest149void static NegateSignatureS(std::vector<unsigned char>& vchSig) {150// Parse the signature.151std::vector<unsigned char> r, s;152r = std::vector<unsigned char>(vchSig.begin() + 4, vchSig.begin() + 4 + vchSig[3]);153s = std::vector<unsigned char>(vchSig.begin() + 6 + vchSig[3], vchSig.begin() + 6 + vchSig[3] + vchSig[5 + vchSig[3]]);155while (s.size() < 33) {156s.insert(s.begin(), 0x00);157}158assert(s[0] == 0);159// Perform mod-n negation of s by (ab)using libsecp256k1160// (note that this function is meant to be used for negating secret keys,161// but it works for any non-zero scalar modulo the group order, i.e. also for s)162int ret = secp256k1_ec_seckey_negate(secp256k1_context_static, s.data() + 1);163assert(ret);165if (s[1] < 0x80) {166s.erase(s.begin());167}169// Reconstruct the signature.170vchSig.clear();171vchSig.push_back(0x30);172vchSig.push_back(4 + r.size() + s.size());173vchSig.push_back(0x02);174vchSig.push_back(r.size());175vchSig.insert(vchSig.end(), r.begin(), r.end());176vchSig.push_back(0x02);177vchSig.push_back(s.size());178vchSig.insert(vchSig.end(), s.begin(), s.end());179}181namespace182{183const unsigned char vchKey0[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};184const unsigned char vchKey1[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0};185const unsigned char vchKey2[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0};187struct KeyData188{189CKey key0, key0C, key1, key1C, key2, key2C;190CPubKey pubkey0, pubkey0C, pubkey0H;191CPubKey pubkey1, pubkey1C;192CPubKey pubkey2, pubkey2C;194KeyData()195{196key0.Set(vchKey0, vchKey0 + 32, false);197key0C.Set(vchKey0, vchKey0 + 32, true);198pubkey0 = key0.GetPubKey();199pubkey0H = key0.GetPubKey();200pubkey0C = key0C.GetPubKey();201*const_cast<unsigned char*>(pubkey0H.data()) = 0x06 | (pubkey0H[64] & 1);203key1.Set(vchKey1, vchKey1 + 32, false);204key1C.Set(vchKey1, vchKey1 + 32, true);205pubkey1 = key1.GetPubKey();206pubkey1C = key1C.GetPubKey();208key2.Set(vchKey2, vchKey2 + 32, false);209key2C.Set(vchKey2, vchKey2 + 32, true);210pubkey2 = key2.GetPubKey();211pubkey2C = key2C.GetPubKey();212}213};215enum class WitnessMode {216NONE,217PKH,218SH219};221class TestBuilder222{223private:224//! Actually executed script225CScript script;226//! The P2SH redeemscript227CScript redeemscript;228//! The Witness embedded script229CScript witscript;230CScriptWitness scriptWitness;231CTransactionRef creditTx;232CMutableTransaction spendTx;233bool havePush{false};234std::vector<unsigned char> push;235std::string comment;236script_verify_flags flags;237int scriptError{SCRIPT_ERR_OK};238CAmount nValue;240void DoPush()241{242if (havePush) {243spendTx.vin[0].scriptSig << push;244havePush = false;245}246}248void DoPush(const std::vector<unsigned char>& data)249{250DoPush();
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.