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.
501RPCResult{RPCResult::Type::NUM, "descendantsize", "virtual transaction size of in-mempool descendants (including this one)"},502RPCResult{RPCResult::Type::NUM, "ancestorcount", "number of in-mempool ancestor transactions (including this one)"},503RPCResult{RPCResult::Type::NUM, "ancestorsize", "virtual transaction size of in-mempool ancestors (including this one)"},504RPCResult{RPCResult::Type::NUM, "chunkweight", "sigops-adjusted weight (as defined in BIP 141 and modified by '-bytespersigop') of this transaction's chunk"},505RPCResult{RPCResult::Type::STR_HEX, "wtxid", "hash of serialized transaction, including witness data"},506RPCResult{RPCResult::Type::OBJ, "fees", "",507{508RPCResult{RPCResult::Type::STR_AMOUNT, "base", "transaction fee, denominated in " + CURRENCY_UNIT},509RPCResult{RPCResult::Type::STR_AMOUNT, "modified", "transaction fee with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT},510RPCResult{RPCResult::Type::STR_AMOUNT, "ancestor", "transaction fees of in-mempool ancestors (including this one) with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT},511RPCResult{RPCResult::Type::STR_AMOUNT, "descendant", "transaction fees of in-mempool descendants (including this one) with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT},512RPCResult{RPCResult::Type::STR_AMOUNT, "chunk", "transaction fees of chunk, denominated in " + CURRENCY_UNIT},513}},514RPCResult{RPCResult::Type::ARR, "depends", "unconfirmed transactions used as inputs for this transaction",515{RPCResult{RPCResult::Type::STR_HEX, "transactionid", "parent transaction id"}}},516RPCResult{RPCResult::Type::ARR, "spentby", "unconfirmed transactions spending outputs from this transaction",517{RPCResult{RPCResult::Type::STR_HEX, "transactionid", "child transaction id"}}},518RPCResult{RPCResult::Type::BOOL, "unbroadcast", "Whether this transaction is currently unbroadcast (initial broadcast not yet acknowledged by any peers)"},519};520if (IsDeprecatedRPCEnabled("bip125")) {521list.emplace_back(RPCResult::Type::BOOL, "bip125-replaceable", "Whether this transaction signals BIP125 replaceability or has an unconfirmed ancestor signaling BIP125 replaceability. (DEPRECATED)\n");522}523return list;524}526void AppendChunkInfo(UniValue& all_chunks, FeePerWeight chunk_feerate, std::vector<const CTxMemPoolEntry *> chunk_txs)527{528UniValue chunk(UniValue::VOBJ);529chunk.pushKV("chunkfee", ValueFromAmount(chunk_feerate.fee));530chunk.pushKV("chunkweight", chunk_feerate.size);531UniValue chunk_txids(UniValue::VARR);532for (const auto& chunk_tx : chunk_txs) {533chunk_txids.push_back(chunk_tx->GetTx().GetHash().ToString());534}535chunk.pushKV("txs", std::move(chunk_txids));536all_chunks.push_back(std::move(chunk));537}539static void clusterToJSON(const CTxMemPool& pool, UniValue& info, std::vector<const CTxMemPoolEntry *> cluster) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)540{541AssertLockHeld(pool.cs);542int total_weight{0};543for (const auto& tx : cluster) {544total_weight += tx->GetAdjustedWeight();545}546info.pushKV("clusterweight", total_weight);547info.pushKV("txcount", cluster.size());549// Output the cluster by chunk. This isn't handed to us by the mempool, but550// we can calculate it by looking at the chunk feerates of each transaction551// in the cluster.552FeePerWeight current_chunk_feerate = pool.GetMainChunkFeerate(*cluster[0]);553std::vector<const CTxMemPoolEntry *> current_chunk;554current_chunk.reserve(cluster.size());556UniValue all_chunks(UniValue::VARR);557for (const auto& tx : cluster) {558if (current_chunk_feerate.size == 0) {559// We've iterated all the transactions in the previous chunk; so560// append it to the output.561AppendChunkInfo(all_chunks, pool.GetMainChunkFeerate(*current_chunk[0]), current_chunk);562current_chunk.clear();563current_chunk_feerate = pool.GetMainChunkFeerate(*tx);564}565current_chunk.push_back(tx);566current_chunk_feerate.size -= tx->GetAdjustedWeight();567}568AppendChunkInfo(all_chunks, pool.GetMainChunkFeerate(*current_chunk[0]), current_chunk);569current_chunk.clear();570info.pushKV("chunks", std::move(all_chunks));571}573static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPoolEntry& e) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)574{575AssertLockHeld(pool.cs);577auto [ancestor_count, ancestor_size, ancestor_fees] = pool.CalculateAncestorData(e);578auto [descendant_count, descendant_size, descendant_fees] = pool.CalculateDescendantData(e);580info.pushKV("vsize_adjusted", e.GetTxSize());581info.pushKV("vsize", e.GetTxSize());582info.pushKV("vsize_bip141", GetVirtualTransactionSize(e.GetTx()));583info.pushKV("weight", e.GetTxWeight());584info.pushKV("time", count_seconds(e.GetTime()));585info.pushKV("height", e.GetHeight());586info.pushKV("descendantcount", descendant_count);587info.pushKV("descendantsize", descendant_size);588info.pushKV("ancestorcount", ancestor_count);589info.pushKV("ancestorsize", ancestor_size);590info.pushKV("wtxid", e.GetTx().GetWitnessHash().ToString());591auto feerate = pool.GetMainChunkFeerate(e);592info.pushKV("chunkweight", feerate.size);594UniValue fees(UniValue::VOBJ);595fees.pushKV("base", ValueFromAmount(e.GetFee()));596fees.pushKV("modified", ValueFromAmount(e.GetModifiedFee()));597fees.pushKV("ancestor", ValueFromAmount(ancestor_fees));598fees.pushKV("descendant", ValueFromAmount(descendant_fees));599fees.pushKV("chunk", ValueFromAmount(feerate.fee));600info.pushKV("fees", std::move(fees));602const CTransaction& tx = e.GetTx();603std::set<std::string> setDepends;604for (const CTxIn& txin : tx.vin)605{606if (pool.exists(txin.prevout.hash))607setDepends.insert(txin.prevout.hash.ToString());608}610UniValue depends(UniValue::VARR);611for (const std::string& dep : setDepends)612{613depends.push_back(dep);614}616info.pushKV("depends", std::move(depends));618UniValue spent(UniValue::VARR);619for (const CTxMemPoolEntry& child : pool.GetChildren(e)) {620spent.push_back(child.GetTx().GetHash().ToString());621}623info.pushKV("spentby", std::move(spent));624info.pushKV("unbroadcast", pool.IsUnbroadcastTx(tx.GetHash()));626// Add opt-in RBF status627if (IsDeprecatedRPCEnabled("bip125")) {628bool rbfStatus = false;629RBFTransactionState rbfState = IsRBFOptIn(tx, pool);630if (rbfState == RBFTransactionState::UNKNOWN) {631throw JSONRPCError(RPC_MISC_ERROR, "Transaction is not in mempool");632} else if (rbfState == RBFTransactionState::REPLACEABLE_BIP125) {633rbfStatus = true;634}635info.pushKV("bip125-replaceable", rbfStatus);636}637}639UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose, bool include_mempool_sequence)640{641if (verbose) {642if (include_mempool_sequence) {643throw JSONRPCError(RPC_INVALID_PARAMETER, "Verbose results cannot contain mempool sequence values.");644}645LOCK(pool.cs);646UniValue o(UniValue::VOBJ);647for (const CTxMemPoolEntry& e : pool.entryAll()) {648UniValue info(UniValue::VOBJ);649entryToJSON(pool, info, e);650// Mempool has unique entries so there is no advantage in using651// UniValue::pushKV, which checks if the key already exists in O(N).652// UniValue::pushKVEnd is used instead which currently is O(1).653o.pushKVEnd(e.GetTx().GetHash().ToString(), std::move(info));654}655return o;656} else {657UniValue a(UniValue::VARR);658uint64_t mempool_sequence;659{660LOCK(pool.cs);661for (const CTxMemPoolEntry& e : pool.entryAll()) {662a.push_back(e.GetTx().GetHash().ToString());663}664mempool_sequence = pool.GetSequence();665}666if (!include_mempool_sequence) {667return a;668} else {669UniValue o(UniValue::VOBJ);670o.pushKV("txids", std::move(a));671o.pushKV("mempool_sequence", mempool_sequence);672return o;673}674}675}677static RPCMethod getmempoolfeeratediagram()678{679return RPCMethod{"getmempoolfeeratediagram",680"Returns the feerate diagram for the whole mempool.",681{},682{683RPCResult{"mempool chunks",684RPCResult::Type::ARR, "", "",685{686{687RPCResult::Type::OBJ, "", "",688{689{RPCResult::Type::NUM, "weight", "cumulative sigops-adjusted weight"},690{RPCResult::Type::STR_AMOUNT, "fee", "cumulative fee"}691}692}693}694}695},696RPCExamples{697HelpExampleCli("getmempoolfeeratediagram", "")698+ HelpExampleRpc("getmempoolfeeratediagram", "")699},700[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue701{702const CTxMemPool& mempool = EnsureAnyMemPool(request.context);703LOCK(mempool.cs);705UniValue result(UniValue::VARR);707auto diagram = mempool.GetFeerateDiagram();709for (auto f : diagram) {710UniValue o(UniValue::VOBJ);711o.pushKV("weight", f.size);712o.pushKV("fee", ValueFromAmount(f.fee));713result.push_back(o);714}715return result;716}717};718}720static RPCMethod getrawmempool()721{722return RPCMethod{723"getrawmempool",724"Returns all transaction ids in memory pool as a json array of string transaction ids.\n"725"\nHint: use getmempoolentry to fetch a specific transaction from the mempool.\n",726{727{"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "True for a json object, false for array of transaction ids"},728{"mempool_sequence", RPCArg::Type::BOOL, RPCArg::Default{false}, "If verbose=false, returns a json object with transaction list and mempool sequence number attached."},729},730{731RPCResult{"for verbose = false",732RPCResult::Type::ARR, "", "",733{734{RPCResult::Type::STR_HEX, "", "The transaction id"},735}},736RPCResult{"for verbose = true",737RPCResult::Type::OBJ_DYN, "", "",738{739{RPCResult::Type::OBJ, "transactionid", "", MempoolEntryDescription()},740}},741RPCResult{"for verbose = false and mempool_sequence = true",742RPCResult::Type::OBJ, "", "",743{744{RPCResult::Type::ARR, "txids", "",745{746{RPCResult::Type::STR_HEX, "", "The transaction id"},747}},748{RPCResult::Type::NUM, "mempool_sequence", "The mempool sequence value."},749}},750},