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.
251push = data;252havePush = true;253}255public:256TestBuilder(const CScript& script_, const std::string& comment_, script_verify_flags flags_, bool P2SH = false, WitnessMode wm = WitnessMode::NONE, int witnessversion = 0, CAmount nValue_ = 0) : script(script_), comment(comment_), flags(flags_), nValue(nValue_)257{258CScript scriptPubKey = script;259if (wm == WitnessMode::PKH) {260uint160 hash;261CHash160().Write(std::span{script}.subspan(1)).Finalize(hash);262script = CScript() << OP_DUP << OP_HASH160 << ToByteVector(hash) << OP_EQUALVERIFY << OP_CHECKSIG;263scriptPubKey = CScript() << witnessversion << ToByteVector(hash);264} else if (wm == WitnessMode::SH) {265witscript = scriptPubKey;266uint256 hash;267CSHA256().Write(witscript.data(), witscript.size()).Finalize(hash.begin());268scriptPubKey = CScript() << witnessversion << ToByteVector(hash);269}270if (P2SH) {271redeemscript = scriptPubKey;272scriptPubKey = CScript() << OP_HASH160 << ToByteVector(CScriptID(redeemscript)) << OP_EQUAL;273}274creditTx = MakeTransactionRef(BuildCreditingTransaction(scriptPubKey, nValue));275spendTx = BuildSpendingTransaction(CScript(), CScriptWitness(), *creditTx);276}278TestBuilder& ScriptError(ScriptError_t err)279{280scriptError = err;281return *this;282}284TestBuilder& Opcode(const opcodetype& _op)285{286DoPush();287spendTx.vin[0].scriptSig << _op;288return *this;289}291TestBuilder& Num(int num)292{293DoPush();294spendTx.vin[0].scriptSig << num;295return *this;296}298TestBuilder& Push(const std::string& hex)299{300DoPush(ParseHex(hex));301return *this;302}304TestBuilder& Push(const CScript& _script)305{306DoPush(std::vector<unsigned char>(_script.begin(), _script.end()));307return *this;308}310TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SigVersion::BASE, CAmount amount = 0)311{312uint256 hash = SignatureHash(script, spendTx, 0, nHashType, amount, sigversion);313std::vector<unsigned char> vchSig, r, s;314uint32_t iter = 0;315do {316key.Sign(hash, vchSig, false, iter++);317if ((lenS == 33) != (vchSig[5 + vchSig[3]] == 33)) {318NegateSignatureS(vchSig);319}320r = std::vector<unsigned char>(vchSig.begin() + 4, vchSig.begin() + 4 + vchSig[3]);321s = std::vector<unsigned char>(vchSig.begin() + 6 + vchSig[3], vchSig.begin() + 6 + vchSig[3] + vchSig[5 + vchSig[3]]);322} while (lenR != r.size() || lenS != s.size());323vchSig.push_back(static_cast<unsigned char>(nHashType));324DoPush(vchSig);325return *this;326}328TestBuilder& PushWitSig(const CKey& key, CAmount amount = -1, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SigVersion::WITNESS_V0)329{330if (amount == -1)331amount = nValue;332return PushSig(key, nHashType, lenR, lenS, sigversion, amount).AsWit();333}335TestBuilder& Push(const CPubKey& pubkey)336{337DoPush(std::vector<unsigned char>(pubkey.begin(), pubkey.end()));338return *this;339}341TestBuilder& PushRedeem()342{343DoPush(std::vector<unsigned char>(redeemscript.begin(), redeemscript.end()));344return *this;345}347TestBuilder& PushWitRedeem()348{349DoPush(std::vector<unsigned char>(witscript.begin(), witscript.end()));350return AsWit();351}353TestBuilder& EditPush(unsigned int pos, const std::string& hexin, const std::string& hexout)354{355assert(havePush);356std::vector<unsigned char> datain = ParseHex(hexin);357std::vector<unsigned char> dataout = ParseHex(hexout);358assert(pos + datain.size() <= push.size());359BOOST_CHECK_MESSAGE(std::vector<unsigned char>(push.begin() + pos, push.begin() + pos + datain.size()) == datain, comment);360push.erase(push.begin() + pos, push.begin() + pos + datain.size());361push.insert(push.begin() + pos, dataout.begin(), dataout.end());362return *this;363}365TestBuilder& DamagePush(unsigned int pos)366{367assert(havePush);368assert(pos < push.size());369push[pos] ^= 1;370return *this;371}373TestBuilder& Test(ScriptTest& test)374{375TestBuilder copy = *this; // Make a copy so we can rollback the push.376DoPush();377test.DoTest(creditTx->vout[0].scriptPubKey, spendTx.vin[0].scriptSig, scriptWitness, flags, comment, scriptError, nValue);378*this = copy;379return *this;380}382TestBuilder& AsWit()383{384assert(havePush);385scriptWitness.stack.push_back(push);386havePush = false;387return *this;388}390UniValue GetJSON()391{392DoPush();393UniValue array(UniValue::VARR);394if (!scriptWitness.stack.empty()) {395UniValue wit(UniValue::VARR);396for (unsigned i = 0; i < scriptWitness.stack.size(); i++) {397wit.push_back(HexStr(scriptWitness.stack[i]));398}399wit.push_back(ValueFromAmount(nValue));400array.push_back(std::move(wit));401}402array.push_back(FormatScript(spendTx.vin[0].scriptSig));403array.push_back(FormatScript(creditTx->vout[0].scriptPubKey));404array.push_back(FormatScriptFlags(flags));405array.push_back(FormatScriptError((ScriptError_t)scriptError));406array.push_back(comment);407return array;408}410std::string GetComment() const411{412return comment;413}414};416std::string JSONPrettyPrint(const UniValue& univalue)417{418std::string ret = univalue.write(4);419// Workaround for libunivalue pretty printer, which puts a space between commas and newlines420size_t pos = 0;421while ((pos = ret.find(" \n", pos)) != std::string::npos) {422ret.replace(pos, 2, "\n");423pos++;424}425return ret;426}427} // namespace429BOOST_FIXTURE_TEST_SUITE(script_tests, ScriptTest)431BOOST_AUTO_TEST_CASE(script_build)432{433const KeyData keys;435std::vector<TestBuilder> tests;437tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,438"P2PK", 0439).PushSig(keys.key0));440tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,441"P2PK, bad sig", 0442).PushSig(keys.key0).DamagePush(10).ScriptError(SCRIPT_ERR_EVAL_FALSE));444tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey1C.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG,445"P2PKH", 0446).PushSig(keys.key1).Push(keys.pubkey1C));447tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey2C.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG,448"P2PKH, bad pubkey", 0449).PushSig(keys.key2).Push(keys.pubkey2C).DamagePush(5).ScriptError(SCRIPT_ERR_EQUALVERIFY));451tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,452"P2PK anyonecanpay", 0453).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_ANYONECANPAY));454tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,455"P2PK anyonecanpay marked with normal hashtype", 0456).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_ANYONECANPAY).EditPush(70, "81", "01").ScriptError(SCRIPT_ERR_EVAL_FALSE));458tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,459"P2SH(P2PK)", SCRIPT_VERIFY_P2SH, true460).PushSig(keys.key0).PushRedeem());461tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,462"P2SH(P2PK), bad redeemscript", SCRIPT_VERIFY_P2SH, true463).PushSig(keys.key0).PushRedeem().DamagePush(10).ScriptError(SCRIPT_ERR_EVAL_FALSE));465tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey0.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG,466"P2SH(P2PKH)", SCRIPT_VERIFY_P2SH, true467).PushSig(keys.key0).Push(keys.pubkey0).PushRedeem());468tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey1.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG,469"P2SH(P2PKH), bad sig but no VERIFY_P2SH", 0, true470).PushSig(keys.key0).DamagePush(10).PushRedeem());471tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey1.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG,472"P2SH(P2PKH), bad sig", SCRIPT_VERIFY_P2SH, true473).PushSig(keys.key0).DamagePush(10).PushRedeem().ScriptError(SCRIPT_ERR_EQUALVERIFY));475tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,476"3-of-3", 0477).Num(0).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2));478tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,479"3-of-3, 2 sigs", 0480).Num(0).PushSig(keys.key0).PushSig(keys.key1).Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE));482tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,483"P2SH(2-of-3)", SCRIPT_VERIFY_P2SH, true484).Num(0).PushSig(keys.key1).PushSig(keys.key2).PushRedeem());485tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,486"P2SH(2-of-3), 1 sig", SCRIPT_VERIFY_P2SH, true487).Num(0).PushSig(keys.key1).Num(0).PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));489tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,490"P2PK with too much R padding but no DERSIG", 0491).PushSig(keys.key1, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000"));492tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,493"P2PK with too much R padding", SCRIPT_VERIFY_DERSIG494).PushSig(keys.key1, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").ScriptError(SCRIPT_ERR_SIG_DER));495tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,496"P2PK with too much S padding but no DERSIG", 0497).PushSig(keys.key1, SIGHASH_ALL).EditPush(1, "44", "45").EditPush(37, "20", "2100"));498tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,499"P2PK with too much S padding", SCRIPT_VERIFY_DERSIG500).PushSig(keys.key1, SIGHASH_ALL).EditPush(1, "44", "45").EditPush(37, "20", "2100").ScriptError(SCRIPT_ERR_SIG_DER));
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.