From 586190f0b4740457cb86cba632e3d64e6dfe9b0c Mon Sep 17 00:00:00 2001 From: Carl Dong Date: Mon, 12 Apr 2021 21:34:42 -0400 Subject: rpc/rest: Take and reuse local Chain/ChainState obj In all rest/rpc-related modules, if there are multiple calls to ActiveChain{,State}(), and the calls fall under the same ::cs_main lock, we can simply take a local reference and use/reuse it instead of calling ActiveChain{,State}() again and again. --- src/rpc/blockchain.cpp | 38 ++++++++++++++++++++++---------------- src/rpc/mining.cpp | 18 ++++++++++-------- src/rpc/rawtransaction.cpp | 5 +++-- 3 files changed, 35 insertions(+), 26 deletions(-) (limited to 'src/rpc') diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 4785a272c0..053b6913dc 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1009,6 +1009,8 @@ static RPCHelpMan pruneblockchain() ChainstateManager& chainman = EnsureAnyChainman(request.context); LOCK(cs_main); + CChainState& active_chainstate = chainman.ActiveChainstate(); + CChain& active_chain = active_chainstate.m_chain; int heightParam = request.params[0].get_int(); if (heightParam < 0) @@ -1018,7 +1020,7 @@ static RPCHelpMan pruneblockchain() // too low to be a block time (corresponds to timestamp from Sep 2001). if (heightParam > 1000000000) { // Add a 2 hour buffer to include blocks which might have had old timestamps - CBlockIndex* pindex = chainman.ActiveChain().FindEarliestAtLeast(heightParam - TIMESTAMP_WINDOW, 0); + CBlockIndex* pindex = active_chain.FindEarliestAtLeast(heightParam - TIMESTAMP_WINDOW, 0); if (!pindex) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Could not find block with at least the specified timestamp."); } @@ -1026,7 +1028,7 @@ static RPCHelpMan pruneblockchain() } unsigned int height = (unsigned int) heightParam; - unsigned int chainHeight = (unsigned int) chainman.ActiveChain().Height(); + unsigned int chainHeight = (unsigned int) active_chain.Height(); if (chainHeight < Params().PruneAfterHeight()) throw JSONRPCError(RPC_MISC_ERROR, "Blockchain is too short for pruning."); else if (height > chainHeight) @@ -1036,8 +1038,8 @@ static RPCHelpMan pruneblockchain() height = chainHeight - MIN_BLOCKS_TO_KEEP; } - PruneBlockFilesManual(chainman.ActiveChainstate(), height); - const CBlockIndex* block = chainman.ActiveChain().Tip(); + PruneBlockFilesManual(active_chainstate, height); + const CBlockIndex* block = active_chain.Tip(); CHECK_NONFATAL(block); while (block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) { block = block->pprev; @@ -1363,8 +1365,9 @@ RPCHelpMan getblockchaininfo() { ChainstateManager& chainman = EnsureAnyChainman(request.context); LOCK(cs_main); + CChainState& active_chainstate = chainman.ActiveChainstate(); - const CBlockIndex* tip = chainman.ActiveChain().Tip(); + const CBlockIndex* tip = active_chainstate.m_chain.Tip(); CHECK_NONFATAL(tip); const int height = tip->nHeight; UniValue obj(UniValue::VOBJ); @@ -1375,7 +1378,7 @@ RPCHelpMan getblockchaininfo() obj.pushKV("difficulty", (double)GetDifficulty(tip)); obj.pushKV("mediantime", (int64_t)tip->GetMedianTimePast()); obj.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), tip)); - obj.pushKV("initialblockdownload", chainman.ActiveChainstate().IsInitialBlockDownload()); + obj.pushKV("initialblockdownload", active_chainstate.IsInitialBlockDownload()); obj.pushKV("chainwork", tip->nChainWork.GetHex()); obj.pushKV("size_on_disk", CalculateCurrentUsage()); obj.pushKV("pruned", fPruneMode); @@ -1457,6 +1460,7 @@ static RPCHelpMan getchaintips() { ChainstateManager& chainman = EnsureAnyChainman(request.context); LOCK(cs_main); + CChain& active_chain = chainman.ActiveChain(); /* * Idea: The set of chain tips is the active chain tip, plus orphan blocks which do not have another orphan building off of them. @@ -1470,7 +1474,7 @@ static RPCHelpMan getchaintips() std::set setPrevs; for (const std::pair& item : chainman.BlockIndex()) { - if (!chainman.ActiveChain().Contains(item.second)) { + if (!active_chain.Contains(item.second)) { setOrphans.insert(item.second); setPrevs.insert(item.second->pprev); } @@ -1483,7 +1487,7 @@ static RPCHelpMan getchaintips() } // Always report the currently active tip. - setTips.insert(chainman.ActiveChain().Tip()); + setTips.insert(active_chain.Tip()); /* Construct the output array. */ UniValue res(UniValue::VARR); @@ -1492,11 +1496,11 @@ static RPCHelpMan getchaintips() obj.pushKV("height", block->nHeight); obj.pushKV("hash", block->phashBlock->GetHex()); - const int branchLen = block->nHeight - chainman.ActiveChain().FindFork(block)->nHeight; + const int branchLen = block->nHeight - active_chain.FindFork(block)->nHeight; obj.pushKV("branchlen", branchLen); std::string status; - if (chainman.ActiveChain().Contains(block)) { + if (active_chain.Contains(block)) { // This block is part of the currently active chain. status = "active"; } else if (block->nStatus & BLOCK_FAILED_MASK) { @@ -1903,11 +1907,12 @@ static RPCHelpMan getblockstats() { ChainstateManager& chainman = EnsureAnyChainman(request.context); LOCK(cs_main); + CChain& active_chain = chainman.ActiveChain(); CBlockIndex* pindex; if (request.params[0].isNum()) { const int height = request.params[0].get_int(); - const int current_tip = chainman.ActiveChain().Height(); + const int current_tip = active_chain.Height(); if (height < 0) { throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Target block height %d is negative", height)); } @@ -1915,14 +1920,14 @@ static RPCHelpMan getblockstats() throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Target block height %d after current tip %d", height, current_tip)); } - pindex = chainman.ActiveChain()[height]; + pindex = active_chain[height]; } else { const uint256 hash(ParseHashV(request.params[0], "hash_or_height")); pindex = chainman.m_blockman.LookupBlockIndex(hash); if (!pindex) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } - if (!chainman.ActiveChain().Contains(pindex)) { + if (!active_chain.Contains(pindex)) { throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Block is not in chain %s", Params().NetworkIDString())); } } @@ -2307,10 +2312,11 @@ static RPCHelpMan scantxoutset() { ChainstateManager& chainman = EnsureChainman(node); LOCK(cs_main); - chainman.ActiveChainstate().ForceFlushStateToDisk(); - pcursor = std::unique_ptr(chainman.ActiveChainstate().CoinsDB().Cursor()); + CChainState& active_chainstate = chainman.ActiveChainstate(); + active_chainstate.ForceFlushStateToDisk(); + pcursor = std::unique_ptr(active_chainstate.CoinsDB().Cursor()); CHECK_NONFATAL(pcursor); - tip = chainman.ActiveChain().Tip(); + tip = active_chainstate.m_chain.Tip(); CHECK_NONFATAL(tip); } bool res = FindScriptPubKey(g_scan_progress, g_should_abort_scan, count, pcursor.get(), needles, coins, node.rpc_interruption_point); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 15e03194a3..0cef310c50 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -608,6 +608,8 @@ static RPCHelpMan getblocktemplate() UniValue lpval = NullUniValue; std::set setClientRules; int64_t nMaxVersionPreVB = -1; + CChainState& active_chainstate = chainman.ActiveChainstate(); + CChain& active_chain = active_chainstate.m_chain; if (!request.params[0].isNull()) { const UniValue& oparam = request.params[0].get_obj(); @@ -642,12 +644,12 @@ static RPCHelpMan getblocktemplate() return "duplicate-inconclusive"; } - CBlockIndex* const pindexPrev = chainman.ActiveChain().Tip(); + CBlockIndex* const pindexPrev = active_chain.Tip(); // TestBlockValidity only supports blocks built on the current Tip if (block.hashPrevBlock != pindexPrev->GetBlockHash()) return "inconclusive-not-best-prevblk"; BlockValidationState state; - TestBlockValidity(state, Params(), chainman.ActiveChainstate(), block, pindexPrev, false, true); + TestBlockValidity(state, Params(), active_chainstate, block, pindexPrev, false, true); return BIP22ValidationResult(state); } @@ -677,7 +679,7 @@ static RPCHelpMan getblocktemplate() throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, PACKAGE_NAME " is not connected!"); } - if (chainman.ActiveChainstate().IsInitialBlockDownload()) { + if (active_chainstate.IsInitialBlockDownload()) { throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, PACKAGE_NAME " is in initial sync and waiting for blocks..."); } } @@ -703,7 +705,7 @@ static RPCHelpMan getblocktemplate() else { // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier - hashWatchedChain = chainman.ActiveChain().Tip()->GetBlockHash(); + hashWatchedChain = active_chain.Tip()->GetBlockHash(); nTransactionsUpdatedLastLP = nTransactionsUpdatedLast; } @@ -748,7 +750,7 @@ static RPCHelpMan getblocktemplate() static CBlockIndex* pindexPrev; static int64_t nStart; static std::unique_ptr pblocktemplate; - if (pindexPrev != chainman.ActiveChain().Tip() || + if (pindexPrev != active_chain.Tip() || (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5)) { // Clear pindexPrev so future calls make a new block, despite any failures from here on @@ -756,12 +758,12 @@ static RPCHelpMan getblocktemplate() // Store the pindexBest used before CreateNewBlock, to avoid races nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); - CBlockIndex* pindexPrevNew = chainman.ActiveChain().Tip(); + CBlockIndex* pindexPrevNew = active_chain.Tip(); nStart = GetTime(); // Create new block CScript scriptDummy = CScript() << OP_TRUE; - pblocktemplate = BlockAssembler(chainman.ActiveChainstate(), mempool, Params()).CreateNewBlock(scriptDummy); + pblocktemplate = BlockAssembler(active_chainstate, mempool, Params()).CreateNewBlock(scriptDummy); if (!pblocktemplate) throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); @@ -897,7 +899,7 @@ static RPCHelpMan getblocktemplate() result.pushKV("transactions", transactions); result.pushKV("coinbaseaux", aux); result.pushKV("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue); - result.pushKV("longpollid", chainman.ActiveChain().Tip()->GetBlockHash().GetHex() + ToString(nTransactionsUpdatedLast)); + result.pushKV("longpollid", active_chain.Tip()->GetBlockHash().GetHex() + ToString(nTransactionsUpdatedLast)); result.pushKV("target", hashTarget.GetHex()); result.pushKV("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1); result.pushKV("mutable", aMutable); diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 5947755819..19e9c75e32 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -268,12 +268,13 @@ static RPCHelpMan gettxoutproof() } } else { LOCK(cs_main); + CChainState& active_chainstate = chainman.ActiveChainstate(); // Loop through txids and try to find which block they're in. Exit loop once a block is found. for (const auto& tx : setTxids) { - const Coin& coin = AccessByTxid(chainman.ActiveChainstate().CoinsTip(), tx); + const Coin& coin = AccessByTxid(active_chainstate.CoinsTip(), tx); if (!coin.IsSpent()) { - pblockindex = chainman.ActiveChain()[coin.nHeight]; + pblockindex = active_chainstate.m_chain[coin.nHeight]; break; } } -- cgit v1.2.3