diff --git a/src/bench/rpc_mempool.cpp b/src/bench/rpc_mempool.cpp index 4e6a73ff7c..456c17df0d 100644 --- a/src/bench/rpc_mempool.cpp +++ b/src/bench/rpc_mempool.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -21,7 +22,8 @@ static void AddTx(const CTransactionRef& tx, const CAmount& fee, CTxMemPool& poo static void RpcMempool(benchmark::Bench& bench) { - const auto testing_setup = MakeNoLogFileContext(ChainType::MAIN); + const auto testing_setup = MakeNoLogFileContext(ChainType::MAIN); + auto& chainman = *testing_setup->m_node.chainman; CTxMemPool& pool = *Assert(testing_setup->m_node.mempool); LOCK2(cs_main, pool.cs); @@ -38,7 +40,7 @@ static void RpcMempool(benchmark::Bench& bench) } bench.run([&] { - (void)MempoolToJSON(pool, /*verbose=*/true); + (void)MempoolToJSON(chainman, pool, /*verbose=*/true); }); } diff --git a/src/rest.cpp b/src/rest.cpp index 11f5f2703c..01a27ddbdb 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -685,7 +685,10 @@ static bool rest_mempool(const std::any& context, HTTPRequest* req, const std::s if (verbose && mempool_sequence) { return RESTERR(req, HTTP_BAD_REQUEST, "Verbose results cannot contain mempool sequence values. (hint: set \"verbose=false\")"); } - str_json = MempoolToJSON(*mempool, verbose, mempool_sequence).write() + "\n"; + ChainstateManager* maybe_chainman = GetChainman(context, req); + if (!maybe_chainman) return false; + ChainstateManager& chainman = *maybe_chainman; + str_json = MempoolToJSON(chainman, *mempool, verbose, mempool_sequence).write() + "\n"; } else if (param == "info/with_fee_histogram") { str_json = MempoolInfoToJSON(*mempool, MempoolInfoToJSON_const_histogram_floors).write() + "\n"; } else { diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp index 6a2ee9f833..406db722cf 100644 --- a/src/rpc/mempool.cpp +++ b/src/rpc/mempool.cpp @@ -305,6 +305,8 @@ static std::vector MempoolEntryDescription() RPCResult{RPCResult::Type::NUM, "weight", "transaction weight as defined in BIP 141."}, RPCResult{RPCResult::Type::NUM_TIME, "time", "local time transaction entered pool in seconds since 1 Jan 1970 GMT"}, RPCResult{RPCResult::Type::NUM, "height", "block height when transaction entered pool"}, + RPCResult{RPCResult::Type::NUM, "startingpriority", "Priority when transaction entered pool"}, + RPCResult{RPCResult::Type::NUM, "currentpriority", "Transaction priority now"}, RPCResult{RPCResult::Type::NUM, "descendantcount", "number of in-mempool descendant transactions (including this one)"}, RPCResult{RPCResult::Type::NUM, "descendantsize", "virtual transaction size of in-mempool descendants (including this one)"}, RPCResult{RPCResult::Type::NUM, "ancestorcount", "number of in-mempool ancestor transactions (including this one)"}, @@ -326,7 +328,7 @@ static std::vector MempoolEntryDescription() }; } -static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPoolEntry& e) EXCLUSIVE_LOCKS_REQUIRED(pool.cs) +static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPoolEntry& e, const int next_block_height) EXCLUSIVE_LOCKS_REQUIRED(pool.cs) { AssertLockHeld(pool.cs); @@ -334,6 +336,8 @@ static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPool info.pushKV("weight", (int)e.GetTxWeight()); info.pushKV("time", count_seconds(e.GetTime())); info.pushKV("height", (int)e.GetHeight()); + info.pushKV("startingpriority", e.GetStartingPriority()); + info.pushKV("currentpriority", e.GetPriority(next_block_height)); info.pushKV("descendantcount", e.GetCountWithDescendants()); info.pushKV("descendantsize", e.GetSizeWithDescendants()); info.pushKV("ancestorcount", e.GetCountWithAncestors()); @@ -383,17 +387,22 @@ static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPool info.pushKV("unbroadcast", pool.IsUnbroadcastTx(tx.GetHash())); } -UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose, bool include_mempool_sequence) +UniValue MempoolToJSON(ChainstateManager &chainman, const CTxMemPool& pool, bool verbose, bool include_mempool_sequence) { if (verbose) { if (include_mempool_sequence) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Verbose results cannot contain mempool sequence values."); } + LOCK(::cs_main); + const CChain& active_chain = chainman.ActiveChain(); + const int next_block_height = active_chain.Height() + 1; LOCK(pool.cs); + // TODO: Release cs_main after mempool.cs acquired + UniValue o(UniValue::VOBJ); for (const CTxMemPoolEntry& e : pool.entryAll()) { UniValue info(UniValue::VOBJ); - entryToJSON(pool, info, e); + entryToJSON(pool, info, e, next_block_height); // Mempool has unique entries so there is no advantage in using // UniValue::pushKV, which checks if the key already exists in O(N). // UniValue::pushKVEnd is used instead which currently is O(1). @@ -466,7 +475,9 @@ static RPCHelpMan getrawmempool() include_mempool_sequence = request.params[1].get_bool(); } - return MempoolToJSON(EnsureAnyMemPool(request.context), fVerbose, include_mempool_sequence); + NodeContext& node = EnsureAnyNodeContext(request.context); + ChainstateManager& chainman = EnsureChainman(node); + return MempoolToJSON(chainman, EnsureAnyMemPool(request.context), fVerbose, include_mempool_sequence); }, }; } @@ -502,7 +513,12 @@ static RPCHelpMan getmempoolancestors() uint256 hash = ParseHashV(request.params[0], "parameter 1"); const CTxMemPool& mempool = EnsureAnyMemPool(request.context); + ChainstateManager& chainman = EnsureAnyChainman(request.context); + LOCK(::cs_main); + const CChain& active_chain = chainman.ActiveChain(); + const int next_block_height = active_chain.Height() + 1; LOCK(mempool.cs); + // TODO: Release cs_main after mempool.cs acquired const auto entry{mempool.GetEntry(Txid::FromUint256(hash))}; if (entry == nullptr) { @@ -523,7 +539,7 @@ static RPCHelpMan getmempoolancestors() const CTxMemPoolEntry &e = *ancestorIt; const uint256& _hash = e.GetTx().GetHash(); UniValue info(UniValue::VOBJ); - entryToJSON(mempool, info, e); + entryToJSON(mempool, info, e, next_block_height); o.pushKV(_hash.ToString(), std::move(info)); } return o; @@ -563,7 +579,12 @@ static RPCHelpMan getmempooldescendants() uint256 hash = ParseHashV(request.params[0], "parameter 1"); const CTxMemPool& mempool = EnsureAnyMemPool(request.context); + ChainstateManager& chainman = EnsureAnyChainman(request.context); + LOCK(::cs_main); + const CChain& active_chain = chainman.ActiveChain(); + const int next_block_height = active_chain.Height() + 1; LOCK(mempool.cs); + // TODO: Release cs_main after mempool.cs acquired const auto it{mempool.GetIter(hash)}; if (!it) { @@ -588,7 +609,7 @@ static RPCHelpMan getmempooldescendants() const CTxMemPoolEntry &e = *descendantIt; const uint256& _hash = e.GetTx().GetHash(); UniValue info(UniValue::VOBJ); - entryToJSON(mempool, info, e); + entryToJSON(mempool, info, e, next_block_height); o.pushKV(_hash.ToString(), std::move(info)); } return o; @@ -615,7 +636,12 @@ static RPCHelpMan getmempoolentry() uint256 hash = ParseHashV(request.params[0], "parameter 1"); const CTxMemPool& mempool = EnsureAnyMemPool(request.context); + ChainstateManager& chainman = EnsureAnyChainman(request.context); + LOCK(::cs_main); + const CChain& active_chain = chainman.ActiveChain(); + const int next_block_height = active_chain.Height() + 1; LOCK(mempool.cs); + // TODO: Release cs_main after mempool.cs acquired const auto entry{mempool.GetEntry(Txid::FromUint256(hash))}; if (entry == nullptr) { @@ -623,7 +649,7 @@ static RPCHelpMan getmempoolentry() } UniValue info(UniValue::VOBJ); - entryToJSON(mempool, info, *entry); + entryToJSON(mempool, info, *entry, next_block_height); return info; }, }; diff --git a/src/rpc/mempool.h b/src/rpc/mempool.h index c775590b24..4e2af8d6e5 100644 --- a/src/rpc/mempool.h +++ b/src/rpc/mempool.h @@ -10,6 +10,7 @@ #include #include +class ChainstateManager; class CTxMemPool; class UniValue; @@ -28,6 +29,6 @@ static const MempoolHistogramFeeRates MempoolInfoToJSON_const_histogram_floors{ UniValue MempoolInfoToJSON(const CTxMemPool& pool, const std::optional& histogram_floors); /** Mempool to JSON */ -UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose = false, bool include_mempool_sequence = false); +UniValue MempoolToJSON(ChainstateManager& chainman, const CTxMemPool& pool, bool verbose = false, bool include_mempool_sequence = false); #endif // BITCOIN_RPC_MEMPOOL_H