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.
251template <typename T>252static T TrimAndParse(const std::string& int_str, const std::string& err)253{254const auto parsed{ToIntegral<T>(TrimStringView(int_str))};255if (!parsed.has_value()) {256throw std::runtime_error(err + " '" + int_str + "'");257}258return parsed.value();259}261static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInput)262{263std::vector<std::string> vStrInputParts = SplitString(strInput, ':');265// separate TXID:VOUT in string266if (vStrInputParts.size()<2)267throw std::runtime_error("TX input missing separator");269// extract and validate TXID270auto txid{Txid::FromHex(vStrInputParts[0])};271if (!txid) {272throw std::runtime_error("invalid TX input txid");273}275static const unsigned int minTxOutSz = 9;276static const unsigned int maxVout = MAX_BLOCK_WEIGHT / (WITNESS_SCALE_FACTOR * minTxOutSz);278// extract and validate vout279const std::string& strVout = vStrInputParts[1];280const auto vout{ToIntegral<uint32_t>(strVout)};281if (!vout || *vout > maxVout) {282throw std::runtime_error("invalid TX input vout '" + strVout + "'");283}285// extract the optional sequence number286uint32_t nSequenceIn = CTxIn::SEQUENCE_FINAL;287if (vStrInputParts.size() > 2) {288nSequenceIn = TrimAndParse<uint32_t>(vStrInputParts.at(2), "invalid TX sequence id");289}291// append to transaction input list292CTxIn txin{*txid, *vout, CScript{}, nSequenceIn};293tx.vin.push_back(txin);294}296static void MutateTxAddOutAddr(CMutableTransaction& tx, const std::string& strInput)297{298// Separate into VALUE:ADDRESS299std::vector<std::string> vStrInputParts = SplitString(strInput, ':');301if (vStrInputParts.size() != 2)302throw std::runtime_error("TX output missing or too many separators");304// Extract and validate VALUE305CAmount value = ExtractAndValidateValue(vStrInputParts[0]);307// extract and validate ADDRESS308const std::string& strAddr = vStrInputParts[1];309CTxDestination destination = DecodeDestination(strAddr);310if (!IsValidDestination(destination)) {311throw std::runtime_error("invalid TX output address");312}313CScript scriptPubKey = GetScriptForDestination(destination);315// construct TxOut, append to transaction output list316CTxOut txout(value, scriptPubKey);317tx.vout.push_back(txout);318}320static void MutateTxAddOutPubKey(CMutableTransaction& tx, const std::string& strInput)321{322// Separate into VALUE:PUBKEY[:FLAGS]323std::vector<std::string> vStrInputParts = SplitString(strInput, ':');325if (vStrInputParts.size() < 2 || vStrInputParts.size() > 3)326throw std::runtime_error("TX output missing or too many separators");328// Extract and validate VALUE329CAmount value = ExtractAndValidateValue(vStrInputParts[0]);331// Extract and validate PUBKEY332CPubKey pubkey(ParseHex(vStrInputParts[1]));333if (!pubkey.IsFullyValid())334throw std::runtime_error("invalid TX output pubkey");335CScript scriptPubKey = GetScriptForRawPubKey(pubkey);337// Extract and validate FLAGS338bool bSegWit = false;339bool bScriptHash = false;340if (vStrInputParts.size() == 3) {341const std::string& flags = vStrInputParts[2];342bSegWit = (flags.find('W') != std::string::npos);343bScriptHash = (flags.find('S') != std::string::npos);344}346if (bSegWit) {347if (!pubkey.IsCompressed()) {348throw std::runtime_error("Uncompressed pubkeys are not useable for SegWit outputs");349}350// Build a P2WPKH script351scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkey));352}353if (bScriptHash) {354// Get the ID for the script, and then construct a P2SH destination for it.355scriptPubKey = GetScriptForDestination(ScriptHash(scriptPubKey));356}358// construct TxOut, append to transaction output list359CTxOut txout(value, scriptPubKey);360tx.vout.push_back(txout);361}363static void MutateTxAddOutMultiSig(CMutableTransaction& tx, const std::string& strInput)364{365// Separate into VALUE:REQUIRED:NUMKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]366std::vector<std::string> vStrInputParts = SplitString(strInput, ':');368// Check that there are enough parameters369if (vStrInputParts.size()<3)370throw std::runtime_error("Not enough multisig parameters");372// Extract and validate VALUE373CAmount value = ExtractAndValidateValue(vStrInputParts[0]);375// Extract REQUIRED376const uint32_t required{TrimAndParse<uint32_t>(vStrInputParts.at(1), "invalid multisig required number")};378// Extract NUMKEYS379const uint32_t numkeys{TrimAndParse<uint32_t>(vStrInputParts.at(2), "invalid multisig total number")};381// Validate there are the correct number of pubkeys382if (vStrInputParts.size() < numkeys + 3)383throw std::runtime_error("incorrect number of multisig pubkeys");385if (required < 1 || required > MAX_PUBKEYS_PER_MULTISIG || numkeys < 1 || numkeys > MAX_PUBKEYS_PER_MULTISIG || numkeys < required)386throw std::runtime_error("multisig parameter mismatch. Required " \387+ ToString(required) + " of " + ToString(numkeys) + "signatures.");389// extract and validate PUBKEYs390std::vector<CPubKey> pubkeys;391for(int pos = 1; pos <= int(numkeys); pos++) {392CPubKey pubkey(ParseHex(vStrInputParts[pos + 2]));393if (!pubkey.IsFullyValid())394throw std::runtime_error("invalid TX output pubkey");395pubkeys.push_back(pubkey);396}398// Extract FLAGS399bool bSegWit = false;400bool bScriptHash = false;401if (vStrInputParts.size() == numkeys + 4) {402const std::string& flags = vStrInputParts.back();403bSegWit = (flags.find('W') != std::string::npos);404bScriptHash = (flags.find('S') != std::string::npos);405}406else if (vStrInputParts.size() > numkeys + 4) {407// Validate that there were no more parameters passed408throw std::runtime_error("Too many parameters");409}411CScript scriptPubKey = GetScriptForMultisig(required, pubkeys);413if (bSegWit) {414for (const CPubKey& pubkey : pubkeys) {415if (!pubkey.IsCompressed()) {416throw std::runtime_error("Uncompressed pubkeys are not useable for SegWit outputs");417}418}419// Build a P2WSH with the multisig script420scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(scriptPubKey));421}422if (bScriptHash) {423if (scriptPubKey.size() > MAX_SCRIPT_ELEMENT_SIZE) {424throw std::runtime_error(strprintf(425"redeemScript exceeds size limit: %d > %d", scriptPubKey.size(), MAX_SCRIPT_ELEMENT_SIZE));426}427// Get the ID for the script, and then construct a P2SH destination for it.428scriptPubKey = GetScriptForDestination(ScriptHash(scriptPubKey));429}431// construct TxOut, append to transaction output list432CTxOut txout(value, scriptPubKey);433tx.vout.push_back(txout);434}436static void MutateTxAddOutData(CMutableTransaction& tx, const std::string& strInput)437{438CAmount value = 0;440// separate [VALUE:]DATA in string441size_t pos = strInput.find(':');443if (pos==0)444throw std::runtime_error("TX output value not specified");446if (pos == std::string::npos) {447pos = 0;448} else {449// Extract and validate VALUE450value = ExtractAndValidateValue(strInput.substr(0, pos));451++pos;452}454// extract and validate DATA455const std::string strData{strInput.substr(pos, std::string::npos)};457if (!IsHex(strData))458throw std::runtime_error("invalid TX output data");460std::vector<unsigned char> data = ParseHex(strData);462CTxOut txout(value, CScript() << OP_RETURN << data);463tx.vout.push_back(txout);464}466static void MutateTxAddOutScript(CMutableTransaction& tx, const std::string& strInput)467{468// separate VALUE:SCRIPT[:FLAGS]469std::vector<std::string> vStrInputParts = SplitString(strInput, ':');470if (vStrInputParts.size() < 2)471throw std::runtime_error("TX output missing separator");473// Extract and validate VALUE474CAmount value = ExtractAndValidateValue(vStrInputParts[0]);476// extract and validate script477const std::string& strScript = vStrInputParts[1];478CScript scriptPubKey = ParseScript(strScript);480// Extract FLAGS481bool bSegWit = false;482bool bScriptHash = false;483if (vStrInputParts.size() == 3) {484const std::string& flags = vStrInputParts.back();485bSegWit = (flags.find('W') != std::string::npos);486bScriptHash = (flags.find('S') != std::string::npos);487}489if (scriptPubKey.size() > MAX_SCRIPT_SIZE) {490throw std::runtime_error(strprintf(491"script exceeds size limit: %d > %d", scriptPubKey.size(), MAX_SCRIPT_SIZE));492}494if (bSegWit) {495scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(scriptPubKey));496}497if (bScriptHash) {498if (scriptPubKey.size() > MAX_SCRIPT_ELEMENT_SIZE) {499throw std::runtime_error(strprintf(500"redeemScript exceeds size limit: %d > %d", scriptPubKey.size(), MAX_SCRIPT_ELEMENT_SIZE));
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.