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.
751{752FillableSigningProvider keystore;753CCoinsViewCache coins{&CoinsViewEmpty::Get()};754std::vector<CMutableTransaction> dummyTransactions =755SetupDummyInputs(keystore, coins, {11*CENT, 50*CENT, 21*CENT, 22*CENT});757CMutableTransaction t;758t.vin.resize(1);759t.vin[0].prevout.hash = dummyTransactions[0].GetHash();760t.vin[0].prevout.n = 1;761t.vin[0].scriptSig << std::vector<unsigned char>(65, 0);762t.vout.resize(1);763t.vout[0].nValue = 90*CENT;764CKey key = GenerateRandomKey();765t.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));767constexpr auto CheckIsStandard = [](const auto& t, const unsigned int max_op_return_relay = MAX_OP_RETURN_RELAY) {768std::string reason;769BOOST_CHECK(IsStandardTx(CTransaction{t}, max_op_return_relay, g_bare_multi, g_dust, reason));770BOOST_CHECK(reason.empty());771};772constexpr auto CheckIsNotStandard = [](const auto& t, const std::string& reason_in, const unsigned int max_op_return_relay = MAX_OP_RETURN_RELAY) {773std::string reason;774BOOST_CHECK(!IsStandardTx(CTransaction{t}, max_op_return_relay, g_bare_multi, g_dust, reason));775BOOST_CHECK_EQUAL(reason_in, reason);776};778CheckIsStandard(t);780// Check dust with default relay fee:781CAmount nDustThreshold = 182 * g_dust.GetFeePerK() / 1000;782BOOST_CHECK_EQUAL(nDustThreshold, 546);784// Add dust outputs up to allowed maximum, still standard!785for (size_t i{0}; i < MAX_DUST_OUTPUTS_PER_TX; ++i) {786t.vout.emplace_back(0, t.vout[0].scriptPubKey);787CheckIsStandard(t);788}790// dust:791t.vout[0].nValue = nDustThreshold - 1;792CheckIsNotStandard(t, "dust");793// not dust:794t.vout[0].nValue = nDustThreshold;795CheckIsStandard(t);797// Disallowed version798t.version = std::numeric_limits<uint32_t>::max();799CheckIsNotStandard(t, "version");801t.version = 0;802CheckIsNotStandard(t, "version");804t.version = TX_MAX_STANDARD_VERSION + 1;805CheckIsNotStandard(t, "version");807// Allowed version808t.version = 1;809CheckIsStandard(t);811t.version = 2;812CheckIsStandard(t);814// Check dust with odd relay fee to verify rounding:815// nDustThreshold = 182 * 3702 / 1000816g_dust = CFeeRate(3702);817// dust:818t.vout[0].nValue = 674 - 1;819CheckIsNotStandard(t, "dust");820// not dust:821t.vout[0].nValue = 674;822CheckIsStandard(t);823g_dust = CFeeRate{DUST_RELAY_TX_FEE};825t.vout[0].scriptPubKey = CScript() << OP_1;826CheckIsNotStandard(t, "scriptpubkey");828// Custom 83-byte TxoutType::NULL_DATA (standard with max_op_return_relay of 83)829t.vout[0].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;830BOOST_CHECK_EQUAL(83, t.vout[0].scriptPubKey.size());831CheckIsStandard(t, /*max_op_return_relay=*/83);833// Non-standard if max_op_return_relay datacarrier arg is one less834CheckIsNotStandard(t, "datacarrier", /*max_op_return_relay=*/82);836// Data payload can be encoded in any way...837t.vout[0].scriptPubKey = CScript() << OP_RETURN << ""_hex;838CheckIsStandard(t);839t.vout[0].scriptPubKey = CScript() << OP_RETURN << "00"_hex << "01"_hex;840CheckIsStandard(t);841// OP_RESERVED *is* considered to be a PUSHDATA type opcode by IsPushOnly()!842t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_RESERVED << -1 << 0 << "01"_hex << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << 10 << 11 << 12 << 13 << 14 << 15 << 16;843CheckIsStandard(t);844t.vout[0].scriptPubKey = CScript() << OP_RETURN << 0 << "01"_hex << 2 << "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"_hex;845CheckIsStandard(t);847// ...so long as it only contains PUSHDATA's848t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_RETURN;849CheckIsNotStandard(t, "scriptpubkey");851// TxoutType::NULL_DATA w/o PUSHDATA852t.vout.resize(1);853t.vout[0].scriptPubKey = CScript() << OP_RETURN;854CheckIsStandard(t);856// Multiple TxoutType::NULL_DATA are permitted857t.vout.resize(2);858t.vout[0].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;859t.vout[0].nValue = 0;860t.vout[1].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;861t.vout[1].nValue = 0;862CheckIsStandard(t);864t.vout[0].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;865t.vout[1].scriptPubKey = CScript() << OP_RETURN;866CheckIsStandard(t);868t.vout[0].scriptPubKey = CScript() << OP_RETURN;869t.vout[1].scriptPubKey = CScript() << OP_RETURN;870CheckIsStandard(t);872t.vout[0].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;873t.vout[1].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;874const auto datacarrier_size = t.vout[0].scriptPubKey.size() + t.vout[1].scriptPubKey.size();875CheckIsStandard(t); // Default max relay should never trigger876CheckIsStandard(t, /*max_op_return_relay=*/datacarrier_size);877CheckIsNotStandard(t, "datacarrier", /*max_op_return_relay=*/datacarrier_size-1);879// Check large scriptSig (non-standard if size is >1650 bytes)880t.vout.resize(1);881t.vout[0].nValue = MAX_MONEY;882t.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));883// OP_PUSHDATA2 with len (3 bytes) + data (1647 bytes) = 1650 bytes884t.vin[0].scriptSig = CScript() << std::vector<unsigned char>(1647, 0); // 1650885CheckIsStandard(t);887t.vin[0].scriptSig = CScript() << std::vector<unsigned char>(1648, 0); // 1651888CheckIsNotStandard(t, "scriptsig-size");890// Check scriptSig format (non-standard if there are any other ops than just PUSHs)891t.vin[0].scriptSig = CScript()892<< OP_TRUE << OP_0 << OP_1NEGATE << OP_16 // OP_n (single byte pushes: n = 1, 0, -1, 16)893<< std::vector<unsigned char>(75, 0) // OP_PUSHx [...x bytes...]894<< std::vector<unsigned char>(235, 0) // OP_PUSHDATA1 x [...x bytes...]895<< std::vector<unsigned char>(1234, 0) // OP_PUSHDATA2 x [...x bytes...]896<< OP_9;897CheckIsStandard(t);899const std::vector<unsigned char> non_push_ops = { // arbitrary set of non-push operations900OP_NOP, OP_VERIFY, OP_IF, OP_ROT, OP_3DUP, OP_SIZE, OP_EQUAL, OP_ADD, OP_SUB,901OP_HASH256, OP_CODESEPARATOR, OP_CHECKSIG, OP_CHECKLOCKTIMEVERIFY };903CScript::const_iterator pc = t.vin[0].scriptSig.begin();904while (pc < t.vin[0].scriptSig.end()) {905opcodetype opcode;906CScript::const_iterator prev_pc = pc;907t.vin[0].scriptSig.GetOp(pc, opcode); // advance to next op908// for the sake of simplicity, we only replace single-byte push operations909if (opcode >= 1 && opcode <= OP_PUSHDATA4)910continue;912int index = prev_pc - t.vin[0].scriptSig.begin();913unsigned char orig_op = *prev_pc; // save op914// replace current push-op with each non-push-op915for (auto op : non_push_ops) {916t.vin[0].scriptSig[index] = op;917CheckIsNotStandard(t, "scriptsig-not-pushonly");918}919t.vin[0].scriptSig[index] = orig_op; // restore op920CheckIsStandard(t);921}923// Check tx-size (non-standard if transaction weight is > MAX_STANDARD_TX_WEIGHT)924t.vin.clear();925t.vin.resize(2438); // size per input (empty scriptSig): 41 bytes926t.vout[0].scriptPubKey = CScript() << OP_RETURN << std::vector<unsigned char>(19, 0); // output size: 30 bytes927// tx header: 12 bytes => 48 weight units928// 2438 inputs: 2438*41 = 99958 bytes => 399832 weight units929// 1 output: 30 bytes => 120 weight units930// ======================================931// total: 400000 weight units932BOOST_CHECK_EQUAL(GetTransactionWeight(CTransaction(t)), 400000);933CheckIsStandard(t);935// increase output size by one byte, so we end up with 400004 weight units936t.vout[0].scriptPubKey = CScript() << OP_RETURN << std::vector<unsigned char>(20, 0); // output size: 31 bytes937BOOST_CHECK_EQUAL(GetTransactionWeight(CTransaction(t)), 400004);938CheckIsNotStandard(t, "tx-size");940// Check bare multisig (standard if policy flag g_bare_multi is set)941g_bare_multi = true;942t.vout[0].scriptPubKey = GetScriptForMultisig(1, {key.GetPubKey()}); // simple 1-of-1943t.vin.resize(1);944t.vin[0].scriptSig = CScript() << std::vector<unsigned char>(65, 0);945CheckIsStandard(t);947g_bare_multi = false;948CheckIsNotStandard(t, "bare-multisig");949g_bare_multi = DEFAULT_PERMIT_BAREMULTISIG;951// Add dust outputs up to allowed maximum952assert(t.vout.size() == 1);953t.vout.insert(t.vout.end(), MAX_DUST_OUTPUTS_PER_TX, {0, t.vout[0].scriptPubKey});955// Check compressed P2PK outputs dust threshold (must have leading 02 or 03)956t.vout[0].scriptPubKey = CScript() << std::vector<unsigned char>(33, 0x02) << OP_CHECKSIG;957t.vout[0].nValue = 576;958CheckIsStandard(t);959t.vout[0].nValue = 575;960CheckIsNotStandard(t, "dust");962// Check uncompressed P2PK outputs dust threshold (must have leading 04/06/07)963t.vout[0].scriptPubKey = CScript() << std::vector<unsigned char>(65, 0x04) << OP_CHECKSIG;964t.vout[0].nValue = 672;965CheckIsStandard(t);966t.vout[0].nValue = 671;967CheckIsNotStandard(t, "dust");969// Check P2PKH outputs dust threshold970t.vout[0].scriptPubKey = CScript() << OP_DUP << OP_HASH160 << std::vector<unsigned char>(20, 0) << OP_EQUALVERIFY << OP_CHECKSIG;971t.vout[0].nValue = 546;972CheckIsStandard(t);973t.vout[0].nValue = 545;974CheckIsNotStandard(t, "dust");976// Check P2SH outputs dust threshold977t.vout[0].scriptPubKey = CScript() << OP_HASH160 << std::vector<unsigned char>(20, 0) << OP_EQUAL;978t.vout[0].nValue = 540;979CheckIsStandard(t);980t.vout[0].nValue = 539;981CheckIsNotStandard(t, "dust");983// Check P2WPKH outputs dust threshold984t.vout[0].scriptPubKey = CScript() << OP_0 << std::vector<unsigned char>(20, 0);985t.vout[0].nValue = 294;986CheckIsStandard(t);987t.vout[0].nValue = 293;988CheckIsNotStandard(t, "dust");990// Check P2WSH outputs dust threshold991t.vout[0].scriptPubKey = CScript() << OP_0 << std::vector<unsigned char>(32, 0);992t.vout[0].nValue = 330;993CheckIsStandard(t);994t.vout[0].nValue = 329;995CheckIsNotStandard(t, "dust");997// Check P2TR outputs dust threshold (Invalid xonly key ok!)998t.vout[0].scriptPubKey = CScript() << OP_1 << std::vector<unsigned char>(32, 0);999t.vout[0].nValue = 330;1000CheckIsStandard(t);
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.