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.
1001t.vout[0].nValue = 329;1002CheckIsNotStandard(t, "dust");1004// Check future Witness Program versions dust threshold (non-32-byte pushes are undefined for version 1)1005for (int op = OP_1; op <= OP_16; op += 1) {1006t.vout[0].scriptPubKey = CScript() << (opcodetype)op << std::vector<unsigned char>(2, 0);1007t.vout[0].nValue = 240;1008CheckIsStandard(t);1010t.vout[0].nValue = 239;1011CheckIsNotStandard(t, "dust");1012}1014// Check anchor outputs1015t.vout[0].scriptPubKey = CScript() << OP_1 << ANCHOR_BYTES;1016BOOST_CHECK(t.vout[0].scriptPubKey.IsPayToAnchor());1017t.vout[0].nValue = 240;1018CheckIsStandard(t);1019t.vout[0].nValue = 239;1020CheckIsNotStandard(t, "dust");1021}1023BOOST_AUTO_TEST_CASE(max_standard_legacy_sigops)1024{1025CCoinsViewCache coins{&CoinsViewEmpty::Get()};1026CKey key;1027key.MakeNewKey(true);1029// Create a pathological P2SH script padded with as many sigops as is standard.1030CScript max_sigops_redeem_script{CScript() << std::vector<unsigned char>{} << key.GetPubKey()};1031for (unsigned i{0}; i < MAX_P2SH_SIGOPS - 1; ++i) max_sigops_redeem_script << OP_2DUP << OP_CHECKSIG << OP_DROP;1032max_sigops_redeem_script << OP_CHECKSIG << OP_NOT;1033const CScript max_sigops_p2sh{GetScriptForDestination(ScriptHash(max_sigops_redeem_script))};1035// Create a transaction fanning out as many such P2SH outputs as is standard to spend in a1036// single transaction, and a transaction spending them.1037CMutableTransaction tx_create, tx_max_sigops;1038const unsigned p2sh_inputs_count{MAX_TX_LEGACY_SIGOPS / MAX_P2SH_SIGOPS};1039tx_create.vout.reserve(p2sh_inputs_count);1040for (unsigned i{0}; i < p2sh_inputs_count; ++i) {1041tx_create.vout.emplace_back(424242 + i, max_sigops_p2sh);1042}1043auto prev_txid{tx_create.GetHash()};1044tx_max_sigops.vin.reserve(p2sh_inputs_count);1045for (unsigned i{0}; i < p2sh_inputs_count; ++i) {1046tx_max_sigops.vin.emplace_back(prev_txid, i, CScript() << ToByteVector(max_sigops_redeem_script));1047}1049// p2sh_inputs_count is truncated to 166 (from 166.6666..)1050BOOST_CHECK_LT(p2sh_inputs_count * MAX_P2SH_SIGOPS, MAX_TX_LEGACY_SIGOPS);1051AddCoins(coins, CTransaction(tx_create), 0, false);1053// 2490 sigops is below the limit.1054BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(tx_max_sigops), coins), 2490);1055BOOST_CHECK(::ValidateInputsStandardness(CTransaction(tx_max_sigops), coins).IsValid());1057// Adding one more input will bump this to 2505, hitting the limit.1058tx_create.vout.emplace_back(424242, max_sigops_p2sh);1059prev_txid = tx_create.GetHash();1060for (unsigned i{0}; i < p2sh_inputs_count; ++i) {1061tx_max_sigops.vin[i] = CTxIn(COutPoint(prev_txid, i), CScript() << ToByteVector(max_sigops_redeem_script));1062}1063tx_max_sigops.vin.emplace_back(prev_txid, p2sh_inputs_count, CScript() << ToByteVector(max_sigops_redeem_script));1064AddCoins(coins, CTransaction(tx_create), 0, false);1065BOOST_CHECK_GT((p2sh_inputs_count + 1) * MAX_P2SH_SIGOPS, MAX_TX_LEGACY_SIGOPS);1066auto legacy_sigops_count = GetP2SHSigOpCount(CTransaction(tx_max_sigops), coins);1067BOOST_CHECK_EQUAL(legacy_sigops_count, 2505);1068std::string reject_reason("bad-txns-nonstandard-inputs");1069std::string sigop_limit_reject_debug_message("non-witness sigops exceed bip54 limit");1070{1071auto validation_state = ValidateInputsStandardness(CTransaction(tx_max_sigops), coins);1072BOOST_CHECK(validation_state.IsInvalid());1073BOOST_CHECK_EQUAL(validation_state.GetRejectReason(), reject_reason);1074BOOST_CHECK_EQUAL(validation_state.GetDebugMessage(), sigop_limit_reject_debug_message);1075}1078// Now, check the limit can be reached with regular P2PK outputs too. Use a separate1079// preparation transaction, to demonstrate spending coins from a single tx is irrelevant.1080CMutableTransaction tx_create_p2pk;1081const auto p2pk_script{CScript() << key.GetPubKey() << OP_CHECKSIG};1082unsigned p2pk_inputs_count{10}; // From 2490 to 2500.1083for (unsigned i{0}; i < p2pk_inputs_count; ++i) {1084tx_create_p2pk.vout.emplace_back(212121 + i, p2pk_script);1085}1086prev_txid = tx_create_p2pk.GetHash();1087tx_max_sigops.vin.resize(p2sh_inputs_count); // Drop the extra input.1088for (unsigned i{0}; i < p2pk_inputs_count; ++i) {1089tx_max_sigops.vin.emplace_back(prev_txid, i);1090}1091AddCoins(coins, CTransaction(tx_create_p2pk), 0, false);1093// The transaction now contains exactly 2500 sigops, the check should pass.1094BOOST_CHECK_EQUAL(p2sh_inputs_count * MAX_P2SH_SIGOPS + p2pk_inputs_count * 1, MAX_TX_LEGACY_SIGOPS);1095BOOST_CHECK(::ValidateInputsStandardness(CTransaction(tx_max_sigops), coins).IsValid());1097// Now, add some Segwit inputs. We add one for each defined Segwit output type. The limit1098// is exclusively on non-witness sigops and therefore those should not be counted.1099CMutableTransaction tx_create_segwit;1100const auto witness_script{CScript() << key.GetPubKey() << OP_CHECKSIG};1101tx_create_segwit.vout.emplace_back(121212, GetScriptForDestination(WitnessV0KeyHash(key.GetPubKey())));1102tx_create_segwit.vout.emplace_back(131313, GetScriptForDestination(WitnessV0ScriptHash(witness_script)));1103tx_create_segwit.vout.emplace_back(141414, GetScriptForDestination(WitnessV1Taproot{XOnlyPubKey(key.GetPubKey())}));1104prev_txid = tx_create_segwit.GetHash();1105for (unsigned i{0}; i < tx_create_segwit.vout.size(); ++i) {1106tx_max_sigops.vin.emplace_back(prev_txid, i);1107}1109// The transaction now still contains exactly 2500 sigops, the check should pass.1110AddCoins(coins, CTransaction(tx_create_segwit), 0, false);1111BOOST_REQUIRE(::ValidateInputsStandardness(CTransaction(tx_max_sigops), coins).IsValid());1113// Add one more P2PK input. We'll reach the limit.1114tx_create_p2pk.vout.emplace_back(212121, p2pk_script);1115prev_txid = tx_create_p2pk.GetHash();1116tx_max_sigops.vin.resize(p2sh_inputs_count);1117++p2pk_inputs_count;1118for (unsigned i{0}; i < p2pk_inputs_count; ++i) {1119tx_max_sigops.vin.emplace_back(prev_txid, i);1120}1121AddCoins(coins, CTransaction(tx_create_p2pk), 0, false);1122auto legacy_sigop_count_p2pk = p2sh_inputs_count * MAX_P2SH_SIGOPS + p2pk_inputs_count * 1;1123BOOST_CHECK_GT(legacy_sigop_count_p2pk, MAX_TX_LEGACY_SIGOPS);1124{1125auto validation_state = ValidateInputsStandardness(CTransaction(tx_max_sigops), coins);1126BOOST_CHECK(validation_state.IsInvalid());1127BOOST_CHECK_EQUAL(validation_state.GetRejectReason(), reject_reason);1128BOOST_CHECK_EQUAL(validation_state.GetDebugMessage(), sigop_limit_reject_debug_message);1129}1130}1132BOOST_AUTO_TEST_CASE(getlegacysigopcount_inaccurate_test)1133{1134// Legacy sigops are counted inaccurately in both the scriptSig and the1135// scriptPubKey: a CHECKMULTISIG counts as MAX_PUBKEYS_PER_MULTISIG even when the1136// preceding OP_N says it takes fewer keys. Counting it accurately would1137// undercount, letting a block over the sigop limit through.1138const CScript multisig{CScript() << OP_1 << OP_CHECKMULTISIG};1140CMutableTransaction mtx;1141mtx.vin.emplace_back(COutPoint{}, multisig);1142BOOST_CHECK_EQUAL(GetLegacySigOpCount(CTransaction{mtx}), MAX_PUBKEYS_PER_MULTISIG);1144mtx.vout.emplace_back(0, multisig);1145BOOST_CHECK_EQUAL(GetLegacySigOpCount(CTransaction{mtx}), 2 * MAX_PUBKEYS_PER_MULTISIG);1146}1148BOOST_AUTO_TEST_CASE(checktxinputs_invalid_transactions_test)1149{1150auto check_invalid{[](CAmount input_value, CAmount output_value, bool coinbase, int spend_height, TxValidationResult expected_result, std::string_view expected_reason) {1151CCoinsViewCache inputs{&CoinsViewEmpty::Get()};1153const COutPoint prevout{Txid::FromUint256(uint256::ONE), 0};1154inputs.AddCoin(prevout, Coin{{input_value, CScript() << OP_TRUE}, /*nHeightIn=*/1, coinbase}, /*possible_overwrite=*/false);1156CMutableTransaction mtx;1157mtx.vin.emplace_back(prevout);1158mtx.vout.emplace_back(output_value, CScript() << OP_TRUE);1160TxValidationState state;1161CAmount txfee{0};1162BOOST_CHECK(!Consensus::CheckTxInputs(CTransaction{mtx}, state, inputs, spend_height, txfee));1163BOOST_CHECK(state.IsInvalid());1164BOOST_CHECK_EQUAL(state.GetResult(), expected_result);1165BOOST_CHECK_EQUAL(state.GetRejectReason(), expected_reason);1166}};1168check_invalid(/*input_value=*/MAX_MONEY + 1,1169/*output_value=*/0,1170/*coinbase=*/false,1171/*spend_height=*/2,1172TxValidationResult::TX_CONSENSUS, /*expected_reason=*/"bad-txns-inputvalues-outofrange");1174check_invalid(/*input_value=*/1 * COIN,1175/*output_value=*/2 * COIN,1176/*coinbase=*/false,1177/*spend_height=*/2,1178TxValidationResult::TX_CONSENSUS, /*expected_reason=*/"bad-txns-in-belowout");1180check_invalid(/*input_value=*/1 * COIN,1181/*output_value=*/0,1182/*coinbase=*/true,1183/*spend_height=*/COINBASE_MATURITY,1184TxValidationResult::TX_PREMATURE_SPEND, /*expected_reason=*/"bad-txns-premature-spend-of-coinbase");1185}1187BOOST_AUTO_TEST_CASE(isfinaltx_sequences_test)1188{1189constexpr int height{100};1191// Every transaction here has the same unsatisfied nLockTime, so only the1192// sequences decide the outcome.1193auto check_final{[](const std::vector<uint32_t>& sequences, bool expected_final) {1194CMutableTransaction mtx;1195mtx.nLockTime = height;1196for (const uint32_t sequence : sequences) {1197mtx.vin.emplace_back(COutPoint{}, CScript{}, sequence);1198}1200BOOST_CHECK_EQUAL(IsFinalTx(CTransaction{mtx}, /*nBlockHeight=*/height, /*nBlockTime=*/0), expected_final);1201}};1203check_final(/*sequences=*/{CTxIn::SEQUENCE_FINAL, CTxIn::SEQUENCE_FINAL}, /*expected_final=*/true);1205// nLockTime is only ignored when every input is SEQUENCE_FINAL1206check_final(/*sequences=*/{CTxIn::SEQUENCE_FINAL, CTxIn::MAX_SEQUENCE_NONFINAL}, /*expected_final=*/false);1207check_final(/*sequences=*/{CTxIn::MAX_SEQUENCE_NONFINAL, CTxIn::SEQUENCE_FINAL}, /*expected_final=*/false);1208}1210BOOST_AUTO_TEST_CASE(calculatesequencelocks_tx_version_test)1211{1212constexpr int coin_height{100};1214// A single input with a height-based relative locktime of one block. Only the1215// height branch is taken, so the block index is never dereferenced.1216auto check_min_height{[](uint32_t version, int expected_min_height) {1217CMutableTransaction mtx;1218mtx.version = version;1219mtx.vin.emplace_back(COutPoint{}, CScript{}, /*nSequenceIn=*/1);1221std::vector<int> prev_heights{coin_height};1222const CBlockIndex block{};1223const auto lock_pair{CalculateSequenceLocks(CTransaction{mtx}, LOCKTIME_VERIFY_SEQUENCE, prev_heights, block)};1224BOOST_CHECK_EQUAL(lock_pair.first, expected_min_height);1225}};1227// BIP68 only applies to versions 2 and up1228check_min_height(/*version=*/0, /*expected_min_height=*/-1);1229check_min_height(/*version=*/1, /*expected_min_height=*/-1);1230check_min_height(/*version=*/2, /*expected_min_height=*/coin_height);1231check_min_height(/*version=*/std::numeric_limits<uint32_t>::max(), /*expected_min_height=*/coin_height);1232}1234BOOST_AUTO_TEST_CASE(getvalueout_out_of_range_throws)1235{1236CMutableTransaction mtx;1237mtx.vout.emplace_back(MAX_MONEY + 1, CScript() << OP_TRUE);1239const CTransaction tx{mtx};1240BOOST_CHECK_EXCEPTION(tx.GetValueOut(), std::runtime_error, HasReason("GetValueOut: value out of range"));1241}1243/** Sanity check the return value of SpendsNonAnchorWitnessProg for various output types. */1244BOOST_AUTO_TEST_CASE(spends_witness_prog)1245{1246CCoinsViewCache coins{&CoinsViewEmpty::Get()};1247CKey key;1248key.MakeNewKey(true);1249const CPubKey pubkey{key.GetPubKey()};1250CMutableTransaction tx_create{}, tx_spend{};
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.