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.
251{252pc = pc + b.size();253++nFound;254}255pc2 = pc;256}257while (script.GetOp(pc, opcode));259if (nFound > 0) {260result.insert(result.end(), pc2, end);261script = std::move(result);262}264return nFound;265}267namespace {268/** A data type to abstract out the condition stack during script execution.269*270* Conceptually it acts like a vector of booleans, one for each level of nested271* IF/THEN/ELSE, indicating whether we're in the active or inactive branch of272* each.273*274* The elements on the stack cannot be observed individually; we only need to275* expose whether the stack is empty and whether or not any false values are276* present at all. To implement OP_ELSE, a toggle_top modifier is added, which277* flips the last value without returning it.278*279* This uses an optimized implementation that does not materialize the280* actual stack. Instead, it just stores the size of the would-be stack,281* and the position of the first false value in it.282*/283class ConditionStack {284private:285//! A constant for m_first_false_pos to indicate there are no falses.286static constexpr uint32_t NO_FALSE = std::numeric_limits<uint32_t>::max();288//! The size of the implied stack.289uint32_t m_stack_size = 0;290//! The position of the first false value on the implied stack, or NO_FALSE if all true.291uint32_t m_first_false_pos = NO_FALSE;293public:294bool empty() const { return m_stack_size == 0; }295bool all_true() const { return m_first_false_pos == NO_FALSE; }296void push_back(bool f)297{298if (m_first_false_pos == NO_FALSE && !f) {299// The stack consists of all true values, and a false is added.300// The first false value will appear at the current size.301m_first_false_pos = m_stack_size;302}303++m_stack_size;304}305void pop_back()306{307assert(m_stack_size > 0);308--m_stack_size;309if (m_first_false_pos == m_stack_size) {310// When popping off the first false value, everything becomes true.311m_first_false_pos = NO_FALSE;312}313}314void toggle_top()315{316assert(m_stack_size > 0);317if (m_first_false_pos == NO_FALSE) {318// The current stack is all true values; the first false will be the top.319m_first_false_pos = m_stack_size - 1;320} else if (m_first_false_pos == m_stack_size - 1) {321// The top is the first false value; toggling it will make everything true.322m_first_false_pos = NO_FALSE;323} else {324// There is a false value, but not on top. No action is needed as toggling325// anything but the first false value is unobservable.326}327}328};329}331static bool EvalChecksigPreTapscript(const valtype& vchSig, const valtype& vchPubKey, CScript::const_iterator pbegincodehash, CScript::const_iterator pend, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool& fSuccess)332{333assert(sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0);335// Subset of script starting at the most recent codeseparator336CScript scriptCode(pbegincodehash, pend);338// Drop the signature in pre-segwit scripts but not segwit scripts339if (sigversion == SigVersion::BASE) {340int found = FindAndDelete(scriptCode, CScript() << vchSig);341if (found > 0 && (flags & SCRIPT_VERIFY_CONST_SCRIPTCODE))342return set_error(serror, SCRIPT_ERR_SIG_FINDANDDELETE);343}345if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, sigversion, serror)) {346//serror is set347return false;348}349fSuccess = checker.CheckECDSASignature(vchSig, vchPubKey, scriptCode, sigversion);351if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && vchSig.size())352return set_error(serror, SCRIPT_ERR_SIG_NULLFAIL);354return true;355}357static bool EvalChecksigTapscript(const valtype& sig, const valtype& pubkey, ScriptExecutionData& execdata, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool& success)358{359assert(sigversion == SigVersion::TAPSCRIPT);361/*362* The following validation sequence is consensus critical. Please note how --363* upgradable public key versions precede other rules;364* the script execution fails when using empty signature with invalid public key;365* the script execution fails when using non-empty invalid signature.366*/367success = !sig.empty();368if (success) {369// Implement the sigops/witnesssize ratio test.370// Passing with an upgradable public key version is also counted.371assert(execdata.m_validation_weight_left_init);372execdata.m_validation_weight_left -= VALIDATION_WEIGHT_PER_SIGOP_PASSED;373if (execdata.m_validation_weight_left < 0) {374return set_error(serror, SCRIPT_ERR_TAPSCRIPT_VALIDATION_WEIGHT);375}376}377if (pubkey.size() == 0) {378return set_error(serror, SCRIPT_ERR_TAPSCRIPT_EMPTY_PUBKEY);379} else if (pubkey.size() == 32) {380if (success && !checker.CheckSchnorrSignature(sig, pubkey, sigversion, execdata, serror)) {381return false; // serror is set382}383} else {384/*385* New public key version softforks should be defined before this `else` block.386* Generally, the new code should not do anything but failing the script execution. To avoid387* consensus bugs, it should not modify any existing values (including `success`).388*/389if ((flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE) != 0) {390return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_PUBKEYTYPE);391}392}394return true;395}397/** Helper for OP_CHECKSIG, OP_CHECKSIGVERIFY, and (in Tapscript) OP_CHECKSIGADD.398*399* A return value of false means the script fails entirely. When true is returned, the400* success variable indicates whether the signature check itself succeeded.401*/402static bool EvalChecksig(const valtype& sig, const valtype& pubkey, CScript::const_iterator pbegincodehash, CScript::const_iterator pend, ScriptExecutionData& execdata, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, bool& success)403{404switch (sigversion) {405case SigVersion::BASE:406case SigVersion::WITNESS_V0:407return EvalChecksigPreTapscript(sig, pubkey, pbegincodehash, pend, flags, checker, sigversion, serror, success);408case SigVersion::TAPSCRIPT:409return EvalChecksigTapscript(sig, pubkey, execdata, flags, checker, sigversion, serror, success);410case SigVersion::TAPROOT:411// Key path spending in Taproot has no script, so this is unreachable.412break;413}414assert(false);415}417bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, script_verify_flags flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror)418{419static const CScriptNum bnZero(0);420static const CScriptNum bnOne(1);421// static const CScriptNum bnFalse(0);422// static const CScriptNum bnTrue(1);423static const valtype vchFalse(0);424// static const valtype vchZero(0);425static const valtype vchTrue(1, 1);427// sigversion cannot be TAPROOT here, as it admits no script execution.428assert(sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0 || sigversion == SigVersion::TAPSCRIPT);430CScript::const_iterator pc = script.begin();431CScript::const_iterator pend = script.end();432CScript::const_iterator pbegincodehash = script.begin();433opcodetype opcode;434valtype vchPushValue;435ConditionStack vfExec;436std::vector<valtype> altstack;437set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);438if ((sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0) && script.size() > MAX_SCRIPT_SIZE) {439return set_error(serror, SCRIPT_ERR_SCRIPT_SIZE);440}441int nOpCount = 0;442bool fRequireMinimal = (flags & SCRIPT_VERIFY_MINIMALDATA) != 0;443uint32_t opcode_pos = 0;444execdata.m_codeseparator_pos = 0xFFFFFFFFUL;445execdata.m_codeseparator_pos_init = true;447try448{449for (; pc < pend; ++opcode_pos) {450bool fExec = vfExec.all_true();452//453// Read instruction454//455if (!script.GetOp(pc, opcode, vchPushValue))456return set_error(serror, SCRIPT_ERR_BAD_OPCODE);457if (vchPushValue.size() > MAX_SCRIPT_ELEMENT_SIZE)458return set_error(serror, SCRIPT_ERR_PUSH_SIZE);460if (sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0) {461// Note how OP_RESERVED does not count towards the opcode limit.462if (opcode > OP_16 && ++nOpCount > MAX_OPS_PER_SCRIPT) {463return set_error(serror, SCRIPT_ERR_OP_COUNT);464}465}467if (opcode == OP_CAT ||468opcode == OP_SUBSTR ||469opcode == OP_LEFT ||470opcode == OP_RIGHT ||471opcode == OP_INVERT ||472opcode == OP_AND ||473opcode == OP_OR ||474opcode == OP_XOR ||475opcode == OP_2MUL ||476opcode == OP_2DIV ||477opcode == OP_MUL ||478opcode == OP_DIV ||479opcode == OP_MOD ||480opcode == OP_LSHIFT ||481opcode == OP_RSHIFT)482return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); // Disabled opcodes (CVE-2010-5137).484// With SCRIPT_VERIFY_CONST_SCRIPTCODE, OP_CODESEPARATOR in non-segwit script is rejected even in an unexecuted branch485if (opcode == OP_CODESEPARATOR && sigversion == SigVersion::BASE && (flags & SCRIPT_VERIFY_CONST_SCRIPTCODE))486return set_error(serror, SCRIPT_ERR_OP_CODESEPARATOR);488if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) {489if (fRequireMinimal && !CheckMinimalPush(vchPushValue, opcode)) {490return set_error(serror, SCRIPT_ERR_MINIMALDATA);491}492stack.push_back(vchPushValue);493} else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF))494switch (opcode)495{496//497// Push value498//499case OP_1NEGATE:500case OP_1: