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.
251not_p2sh.clear(); not_p2sh << OP_NOP << ToByteVector(dummy) << OP_EQUAL;252BOOST_CHECK(!not_p2sh.IsPayToScriptHash());254not_p2sh.clear(); not_p2sh << OP_HASH160 << ToByteVector(dummy) << OP_CHECKSIG;255BOOST_CHECK(!not_p2sh.IsPayToScriptHash());256}258BOOST_AUTO_TEST_CASE(switchover)259{260// Test switch over code261CScript notValid;262ScriptError err;263notValid << OP_11 << OP_12 << OP_EQUALVERIFY;264CScript scriptSig;265scriptSig << Serialize(notValid);267CScript fund = GetScriptForDestination(ScriptHash(notValid));270// Validation should succeed under old rules (hash is correct):271BOOST_CHECK(Verify(scriptSig, fund, false, err));272BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));273// Fail under new:274BOOST_CHECK(!Verify(scriptSig, fund, true, err));275BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EQUALVERIFY, ScriptErrorString(err));276}278BOOST_AUTO_TEST_CASE(ValidateInputsStandardness)279{280CCoinsViewCache coins{&CoinsViewEmpty::Get()};281FillableSigningProvider keystore;282CKey key[6];283for (int i = 0; i < 6; i++)284{285key[i].MakeNewKey(true);286BOOST_CHECK(keystore.AddKey(key[i]));287}288std::vector<CPubKey> keys;289keys.reserve(3);290for (int i = 0; i < 3; i++)291keys.push_back(key[i].GetPubKey());293CMutableTransaction txFrom;294txFrom.vout.resize(10);296// First three are standard:297CScript pay1 = GetScriptForDestination(PKHash(key[0].GetPubKey()));298BOOST_CHECK(keystore.AddCScript(pay1));299CScript pay1of3 = GetScriptForMultisig(1, keys);301txFrom.vout[0].scriptPubKey = GetScriptForDestination(ScriptHash(pay1)); // P2SH (OP_CHECKSIG)302txFrom.vout[0].nValue = 1000;303txFrom.vout[1].scriptPubKey = pay1; // ordinary OP_CHECKSIG304txFrom.vout[1].nValue = 2000;305txFrom.vout[2].scriptPubKey = pay1of3; // ordinary OP_CHECKMULTISIG306txFrom.vout[2].nValue = 3000;308// vout[3] is complicated 1-of-3 AND 2-of-3309// ... that is OK if wrapped in P2SH:310CScript oneAndTwo;311oneAndTwo << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey());312oneAndTwo << OP_3 << OP_CHECKMULTISIGVERIFY;313oneAndTwo << OP_2 << ToByteVector(key[3].GetPubKey()) << ToByteVector(key[4].GetPubKey()) << ToByteVector(key[5].GetPubKey());314oneAndTwo << OP_3 << OP_CHECKMULTISIG;315BOOST_CHECK(keystore.AddCScript(oneAndTwo));316txFrom.vout[3].scriptPubKey = GetScriptForDestination(ScriptHash(oneAndTwo));317txFrom.vout[3].nValue = 4000;319// vout[4] is max sigops:320CScript fifteenSigops; fifteenSigops << OP_1;321for (unsigned i = 0; i < MAX_P2SH_SIGOPS; i++)322fifteenSigops << ToByteVector(key[i%3].GetPubKey());323fifteenSigops << OP_15 << OP_CHECKMULTISIG;324BOOST_CHECK(keystore.AddCScript(fifteenSigops));325txFrom.vout[4].scriptPubKey = GetScriptForDestination(ScriptHash(fifteenSigops));326txFrom.vout[4].nValue = 5000;328// vout[5/6] are non-standard because they exceed MAX_P2SH_SIGOPS329CScript sixteenSigops; sixteenSigops << OP_16 << OP_CHECKMULTISIG;330BOOST_CHECK(keystore.AddCScript(sixteenSigops));331txFrom.vout[5].scriptPubKey = GetScriptForDestination(ScriptHash(sixteenSigops));332txFrom.vout[5].nValue = 5000;333CScript twentySigops; twentySigops << OP_CHECKMULTISIG;334BOOST_CHECK(keystore.AddCScript(twentySigops));335txFrom.vout[6].scriptPubKey = GetScriptForDestination(ScriptHash(twentySigops));336txFrom.vout[6].nValue = 3000;338// vout[7] is non-standard because it lacks sigops339CScript no_sigops;340txFrom.vout[7].scriptPubKey = no_sigops;341txFrom.vout[7].nValue = 1000;343// vout [8] is non-standard because it contains OP_RETURN in its redeemScript.344static const unsigned char op_return[] = {OP_RETURN};345const auto op_return_script = CScript(op_return, op_return + sizeof(op_return));346txFrom.vout[8].scriptPubKey = GetScriptForDestination(ScriptHash(op_return_script));347txFrom.vout[8].nValue = 1000;349// vout[9] is non-standard because its witness is unknown350CScript witnessUnknown;351witnessUnknown << OP_16 << ToByteVector(uint256::ONE);352txFrom.vout[9].scriptPubKey = witnessUnknown;353txFrom.vout[9].nValue = 1000;355AddCoins(coins, CTransaction(txFrom), 0);357{358CMutableTransaction txTo;359txTo.vout.resize(1);360txTo.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[1].GetPubKey()));362txTo.vin.resize(5);363for (int i = 0; i < 5; i++)364{365txTo.vin[i].prevout.n = i;366txTo.vin[i].prevout.hash = txFrom.GetHash();367}368SignatureData empty;369BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 0, SIGHASH_ALL, empty));370SignatureData empty_b;371BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 1, SIGHASH_ALL, empty_b));372SignatureData empty_c;373BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 2, SIGHASH_ALL, empty_c));374// SignSignature doesn't know how to sign these. We're375// not testing validating signatures, so just create376// dummy signatures that DO include the correct P2SH scripts:377txTo.vin[3].scriptSig << OP_11 << OP_11 << std::vector<unsigned char>(oneAndTwo.begin(), oneAndTwo.end());378txTo.vin[4].scriptSig << std::vector<unsigned char>(fifteenSigops.begin(), fifteenSigops.end());380BOOST_CHECK(::ValidateInputsStandardness(CTransaction(txTo), coins).IsValid());381// 22 P2SH sigops for all inputs (1 for vin[0], 6 for vin[3], 15 for vin[4]382BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txTo), coins), 22U);383}385{386CMutableTransaction coinbase_tx_mut;387coinbase_tx_mut.vin.resize(1);388CTransaction coinbase_tx{coinbase_tx_mut};389BOOST_CHECK(coinbase_tx.IsCoinBase());390BOOST_CHECK_EQUAL(GetP2SHSigOpCount(coinbase_tx, coins), 0U);391}393// TxoutType::SCRIPTHASH394{395CMutableTransaction txToNonStd1;396txToNonStd1.vout.resize(1);397txToNonStd1.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[1].GetPubKey()));398txToNonStd1.vout[0].nValue = 1000;399txToNonStd1.vin.resize(1);400txToNonStd1.vin[0].prevout.n = 5;401txToNonStd1.vin[0].prevout.hash = txFrom.GetHash();402txToNonStd1.vin[0].scriptSig << std::vector<unsigned char>(sixteenSigops.begin(), sixteenSigops.end());404const auto txToNonStd1_res = ::ValidateInputsStandardness(CTransaction(txToNonStd1), coins);405BOOST_CHECK(txToNonStd1_res.IsInvalid());406BOOST_CHECK_EQUAL(txToNonStd1_res.GetRejectReason(), "bad-txns-nonstandard-inputs");407BOOST_CHECK_EQUAL(txToNonStd1_res.GetDebugMessage(), "p2sh redeemscript sigops exceed limit (input 0: 16 > 15)");409BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txToNonStd1), coins), 16U);410}412{413CMutableTransaction txToNonStd2;414txToNonStd2.vout.resize(1);415txToNonStd2.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[1].GetPubKey()));416txToNonStd2.vout[0].nValue = 1000;417txToNonStd2.vin.resize(1);418txToNonStd2.vin[0].prevout.n = 6;419txToNonStd2.vin[0].prevout.hash = txFrom.GetHash();420txToNonStd2.vin[0].scriptSig << std::vector<unsigned char>(twentySigops.begin(), twentySigops.end());422const auto txToNonStd2_res = ::ValidateInputsStandardness(CTransaction(txToNonStd2), coins);423BOOST_CHECK(txToNonStd2_res.IsInvalid());424BOOST_CHECK_EQUAL(txToNonStd2_res.GetRejectReason(), "bad-txns-nonstandard-inputs");425BOOST_CHECK_EQUAL(txToNonStd2_res.GetDebugMessage(), "p2sh redeemscript sigops exceed limit (input 0: 20 > 15)");426BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txToNonStd2), coins), 20U);427}429{430CMutableTransaction txToNonStd2_no_scriptSig;431txToNonStd2_no_scriptSig.vout.resize(1);432txToNonStd2_no_scriptSig.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[1].GetPubKey()));433txToNonStd2_no_scriptSig.vout[0].nValue = 1000;434txToNonStd2_no_scriptSig.vin.resize(1);435txToNonStd2_no_scriptSig.vin[0].prevout.n = 6;436txToNonStd2_no_scriptSig.vin[0].prevout.hash = txFrom.GetHash();438const auto txToNonStd2_no_scriptSig_res = ::ValidateInputsStandardness(CTransaction(txToNonStd2_no_scriptSig), coins);439BOOST_CHECK(txToNonStd2_no_scriptSig_res.IsInvalid());440BOOST_CHECK_EQUAL(txToNonStd2_no_scriptSig_res.GetRejectReason(), "bad-txns-nonstandard-inputs");441BOOST_CHECK_EQUAL(txToNonStd2_no_scriptSig_res.GetDebugMessage(), "input 0 P2SH redeemscript missing");442BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txToNonStd2_no_scriptSig), coins), 0U);443}445// TxoutType::NONSTANDARD446{447CMutableTransaction txToNonStd3;448txToNonStd3.vout.resize(1);449txToNonStd3.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[1].GetPubKey()));450txToNonStd3.vout[0].nValue = 1000;451txToNonStd3.vin.resize(1);452txToNonStd3.vin[0].prevout.n = 7;453txToNonStd3.vin[0].prevout.hash = txFrom.GetHash();455const auto txToNonStd3_res = ::ValidateInputsStandardness(CTransaction(txToNonStd3), coins);456BOOST_CHECK(txToNonStd3_res.IsInvalid());457BOOST_CHECK_EQUAL(txToNonStd3_res.GetRejectReason(), "bad-txns-nonstandard-inputs");458BOOST_CHECK_EQUAL(txToNonStd3_res.GetDebugMessage(), "input 0 script unknown");459}461// TxoutType::INCORRECT_SCRIPTSIG462{463CMutableTransaction txToNonStd4;464txToNonStd4.vout.resize(1);465txToNonStd4.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[1].GetPubKey()));466txToNonStd4.vout[0].nValue = 1000;467txToNonStd4.vin.resize(1);468txToNonStd4.vin[0].prevout.n = 8;469txToNonStd4.vin[0].prevout.hash = txFrom.GetHash();470txToNonStd4.vin[0].scriptSig = op_return_script;472const auto txToNonStd4_res = ::ValidateInputsStandardness(CTransaction(txToNonStd4), coins);473BOOST_CHECK(txToNonStd4_res.IsInvalid());474BOOST_CHECK_EQUAL(txToNonStd4_res.GetRejectReason(), "bad-txns-nonstandard-inputs");475BOOST_CHECK_EQUAL(txToNonStd4_res.GetDebugMessage(), "p2sh scriptsig malformed (input 0: OP_RETURN was encountered)");476}478// TxoutType::WITNESS_UNKNOWN479{480CMutableTransaction txWitnessUnknown;481txWitnessUnknown.vout.resize(1);482txWitnessUnknown.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[1].GetPubKey()));483txWitnessUnknown.vout[0].nValue = 1000;484txWitnessUnknown.vin.resize(1);485txWitnessUnknown.vin[0].prevout.n = 9;486txWitnessUnknown.vin[0].prevout.hash = txFrom.GetHash();487const auto txWitnessUnknown_res = ::ValidateInputsStandardness(CTransaction(txWitnessUnknown), coins);488BOOST_CHECK(txWitnessUnknown_res.IsInvalid());489BOOST_CHECK_EQUAL(txWitnessUnknown_res.GetRejectReason(), "bad-txns-nonstandard-inputs");490BOOST_CHECK_EQUAL(txWitnessUnknown_res.GetDebugMessage(), "input 0 witness program is undefined");491}492}494BOOST_AUTO_TEST_SUITE_END()
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.