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.
1001HelpExampleCli("gettxspendingprevout", "\"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":3}]\"")1002+ HelpExampleRpc("gettxspendingprevout", "\"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":3}]\"")1003+ HelpExampleCliNamed("gettxspendingprevout", {{"outputs", "[{\"txid\":\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\",\"vout\":3}]"}, {"return_spending_tx", true}})1004},1005[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue1006{1007const UniValue& output_params = request.params[0].get_array();1008if (output_params.empty()) {1009throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, outputs are missing");1010}1011const UniValue options{request.params[1].isNull() ? UniValue::VOBJ : request.params[1]};1012RPCTypeCheckObj(options,1013{1014{"mempool_only", UniValueType(UniValue::VBOOL)},1015{"return_spending_tx", UniValueType(UniValue::VBOOL)},1016}, /*fAllowNull=*/true, /*fStrict=*/true);1018const bool mempool_only{options.exists("mempool_only") ? options["mempool_only"].get_bool() : !g_txospenderindex};1019const bool return_spending_tx{options.exists("return_spending_tx") ? options["return_spending_tx"].get_bool() : false};1021// Worklist of outpoints to resolve1022struct Entry {1023COutPoint outpoint;1024size_t request_index;1025};1026std::vector<Entry> prevouts_to_process;1027prevouts_to_process.reserve(output_params.size());1028for (const size_t idx : std::views::iota(size_t{0}, output_params.size())) {1029const UniValue& o = output_params[idx].get_obj();1031RPCTypeCheckObj(o,1032{1033{"txid", UniValueType(UniValue::VSTR)},1034{"vout", UniValueType(UniValue::VNUM)},1035}, /*fAllowNull=*/false, /*fStrict=*/true);1037const Txid txid = Txid::FromUint256(ParseHashO(o, "txid"));1038const int nOutput{o.find_value("vout").getInt<int>()};1039if (nOutput < 0) {1040throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout cannot be negative");1041}1042prevouts_to_process.emplace_back(COutPoint{txid, static_cast<uint32_t>(nOutput)}, idx);1043}1045auto make_output = [&output_params, return_spending_tx](const Entry& prevout, const CTransaction* spending_tx = nullptr) {1046UniValue o{output_params[prevout.request_index]};1047if (spending_tx) {1048o.pushKV("spendingtxid", spending_tx->GetHash().ToString());1049if (return_spending_tx) {1050o.pushKV("spendingtx", EncodeHexTx(*spending_tx));1051}1052}1053return o;1054};1056std::vector<UniValue> results(output_params.size());1058// Search the mempool first1059std::vector<Entry> unresolved;1060unresolved.reserve(prevouts_to_process.size());1061{1062const CTxMemPool& mempool = EnsureAnyMemPool(request.context);1063LOCK(mempool.cs);1065// Make the result if the spending tx appears in the mempool or this is a mempool_only request1066for (const auto& prevout : prevouts_to_process) {1067const auto* spending_tx{mempool.GetConflictTx(prevout.outpoint)};1069// If the outpoint is not spent in the mempool and this is not a mempool-only1070// request, we cannot answer it yet.1071if (!spending_tx && !mempool_only) {1072unresolved.push_back(prevout);1073} else {1074results[prevout.request_index] = make_output(prevout, spending_tx);1075}1076}1077}1079// mempool_only requests resolve every outpoint above, so only other requests reach the index.1080if (!unresolved.empty() && (!g_txospenderindex || !g_txospenderindex->BlockUntilSyncedToCurrentChain())) {1081throw JSONRPCError(RPC_MISC_ERROR, "Mempool lacks a relevant spend, and txospenderindex is unavailable.");1082}1084for (const auto& prevout : unresolved) {1085const auto spender{g_txospenderindex->FindSpender(prevout.outpoint)};1086if (!spender) {1087throw JSONRPCError(RPC_MISC_ERROR, spender.error());1088}1090if (const auto& spender_opt{spender.value()}) {1091UniValue o{make_output(prevout, spender_opt->tx.get())};1092o.pushKV("blockhash", spender_opt->block_hash.GetHex());1093results[prevout.request_index] = std::move(o);1094} else {1095// Only return the input outpoint itself, which indicates it is unspent.1096results[prevout.request_index] = make_output(prevout);1097}1098}1100UniValue result{UniValue::VARR};1101result.reserve(results.size());1102for (auto& output : results) result.push_back(std::move(output));1103return result;1104},1105};1106}1108UniValue MempoolInfoToJSON(const CTxMemPool& pool)1109{1110// Make sure this call is atomic in the pool.1111LOCK(pool.cs);1112UniValue ret(UniValue::VOBJ);1113ret.pushKV("loaded", pool.GetLoadTried());1114ret.pushKV("size", pool.size());1115ret.pushKV("bytes", pool.GetTotalTxSize());1116ret.pushKV("usage", pool.DynamicMemoryUsage());1117ret.pushKV("total_fee", ValueFromAmount(pool.GetTotalFee()));1118ret.pushKV("maxmempool", pool.m_opts.max_size_bytes);1119ret.pushKV("mempoolminfee", ValueFromAmount(std::max(pool.GetMinFee(), pool.m_opts.min_relay_feerate).GetFeePerK()));1120ret.pushKV("minrelaytxfee", ValueFromAmount(pool.m_opts.min_relay_feerate.GetFeePerK()));1121ret.pushKV("incrementalrelayfee", ValueFromAmount(pool.m_opts.incremental_relay_feerate.GetFeePerK()));1122ret.pushKV("unbroadcastcount", pool.GetUnbroadcastTxs().size());1123ret.pushKV("permitbaremultisig", pool.m_opts.permit_bare_multisig);1124ret.pushKV("maxdatacarriersize", pool.m_opts.max_datacarrier_bytes.value_or(0));1125ret.pushKV("limitclustercount", pool.m_opts.limits.cluster_count);1126ret.pushKV("limitclustersize", pool.m_opts.limits.cluster_size_vbytes);1127ret.pushKV("optimal", pool.m_txgraph->DoWork(0)); // 0 work is a quick check for known optimality1128if (IsDeprecatedRPCEnabled("fullrbf")) {1129ret.pushKV("fullrbf", true);1130}1131return ret;1132}1134static RPCMethod getmempoolinfo()1135{1136return RPCMethod{"getmempoolinfo",1137"Returns details on the active state of the TX memory pool.",1138{},1139RPCResult{1140RPCResult::Type::OBJ, "", "",1141[](){1142std::vector<RPCResult> list = {1143{RPCResult::Type::BOOL, "loaded", "True if the initial load attempt of the persisted mempool finished"},1144{RPCResult::Type::NUM, "size", "Current tx count"},1145{RPCResult::Type::NUM, "bytes", "Sum of all virtual transaction sizes as defined in BIP 141. Differs from actual serialized size because witness data is discounted"},1146{RPCResult::Type::NUM, "usage", "Total memory usage for the mempool"},1147{RPCResult::Type::STR_AMOUNT, "total_fee", "Total fees for the mempool in " + CURRENCY_UNIT + ", ignoring modified fees through prioritisetransaction"},1148{RPCResult::Type::NUM, "maxmempool", "Maximum memory usage for the mempool"},1149{RPCResult::Type::STR_AMOUNT, "mempoolminfee", "Minimum fee rate in " + CURRENCY_UNIT + "/kvB for tx to be accepted. Is the maximum of minrelaytxfee and minimum mempool fee"},1150{RPCResult::Type::STR_AMOUNT, "minrelaytxfee", "Current minimum relay fee for transactions"},1151{RPCResult::Type::STR_AMOUNT, "incrementalrelayfee", "minimum fee rate increment for mempool limiting or replacement in " + CURRENCY_UNIT + "/kvB"},1152{RPCResult::Type::NUM, "unbroadcastcount", "Current number of transactions that haven't passed initial broadcast yet"},1153{RPCResult::Type::BOOL, "permitbaremultisig", "True if the mempool accepts transactions with bare multisig outputs"},1154{RPCResult::Type::NUM, "maxdatacarriersize", "Maximum number of bytes that can be used by OP_RETURN outputs in the mempool"},1155{RPCResult::Type::NUM, "limitclustercount", "Maximum number of transactions that can be in a cluster (configured by -limitclustercount)"},1156{RPCResult::Type::NUM, "limitclustersize", "Maximum size of a cluster in virtual bytes (configured by -limitclustersize)"},1157{RPCResult::Type::BOOL, "optimal", "If the mempool is in a known-optimal transaction ordering"},1158};1159if (IsDeprecatedRPCEnabled("fullrbf")) {1160list.emplace_back(RPCResult::Type::BOOL, "fullrbf", "True if the mempool accepts RBF without replaceability signaling inspection (DEPRECATED)");1161}1162return list;1163}()1164},1165RPCExamples{1166HelpExampleCli("getmempoolinfo", "")1167+ HelpExampleRpc("getmempoolinfo", "")1168},1169[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue1170{1171return MempoolInfoToJSON(EnsureAnyMemPool(request.context));1172},1173};1174}1176static RPCMethod importmempool()1177{1178return RPCMethod{1179"importmempool",1180"Import a mempool.dat file and attempt to add its contents to the mempool.\n"1181"Warning: Importing untrusted files is dangerous, especially if metadata from the file is taken over.",1182{1183{"filepath", RPCArg::Type::STR, RPCArg::Optional::NO, "The mempool file"},1184{"options",1185RPCArg::Type::OBJ_NAMED_PARAMS,1186RPCArg::Optional::OMITTED,1187"",1188{1189{"use_current_time", RPCArg::Type::BOOL, RPCArg::Default{true},1190"Whether to use the current system time or use the entry time metadata from the mempool file.\n"1191"Warning: Importing untrusted metadata may lead to unexpected issues and undesirable behavior."},1192{"apply_fee_delta_priority", RPCArg::Type::BOOL, RPCArg::Default{false},1193"Whether to apply the fee delta metadata from the mempool file.\n"1194"It will be added to any existing fee deltas.\n"1195"The fee delta can be set by the prioritisetransaction RPC.\n"1196"Warning: Importing untrusted metadata may lead to unexpected issues and undesirable behavior.\n"1197"Only set this bool if you understand what it does."},1198{"apply_unbroadcast_set", RPCArg::Type::BOOL, RPCArg::Default{false},1199"Whether to apply the unbroadcast set metadata from the mempool file.\n"1200"Warning: Importing untrusted metadata may lead to unexpected issues and undesirable behavior."},1201},1202RPCArgOptions{.oneline_description = "options"}},1203},1204RPCResult{RPCResult::Type::OBJ, "", "", std::vector<RPCResult>{}},1205RPCExamples{HelpExampleCli("importmempool", "/path/to/mempool.dat") + HelpExampleRpc("importmempool", R"("/path/to/mempool.dat")")},1206[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue {1207const NodeContext& node{EnsureAnyNodeContext(request.context)};1209CTxMemPool& mempool{EnsureMemPool(node)};1210ChainstateManager& chainman = EnsureChainman(node);1211Chainstate& chainstate = chainman.ActiveChainstate();1213if (chainman.IsInitialBlockDownload()) {1214throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Can only import the mempool after the block download and sync is done.");1215}1217const fs::path load_path{fs::u8path(self.Arg<std::string_view>("filepath"))};1218const UniValue& use_current_time{request.params[1]["use_current_time"]};1219const UniValue& apply_fee_delta{request.params[1]["apply_fee_delta_priority"]};1220const UniValue& apply_unbroadcast{request.params[1]["apply_unbroadcast_set"]};1221node::ImportMempoolOptions opts{1222.use_current_time = use_current_time.isNull() ? true : use_current_time.get_bool(),1223.apply_fee_delta_priority = apply_fee_delta.isNull() ? false : apply_fee_delta.get_bool(),1224.apply_unbroadcast_set = apply_unbroadcast.isNull() ? false : apply_unbroadcast.get_bool(),1225};1227if (!node::LoadMempool(mempool, load_path, chainstate, std::move(opts))) {1228throw JSONRPCError(RPC_MISC_ERROR, "Unable to import mempool file, see debug log for details.");1229}1231UniValue ret{UniValue::VOBJ};1232return ret;1233},1234};1235}1237static RPCMethod savemempool()1238{1239return RPCMethod{1240"savemempool",1241"Dumps the mempool to disk. It will fail until the previous dump is fully loaded.\n",1242{},1243RPCResult{1244RPCResult::Type::OBJ, "", "",1245{1246{RPCResult::Type::STR, "filename", "the directory and file where the mempool was saved"},1247}},1248RPCExamples{1249HelpExampleCli("savemempool", "")1250+ HelpExampleRpc("savemempool", "")