mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-06-20 22:04:19 +02:00
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.
This commit is contained in:
parent
bc3bd36902
commit
586190f0b4
@ -182,13 +182,14 @@ static bool rest_headers(const std::any& context,
|
|||||||
{
|
{
|
||||||
ChainstateManager& chainman = EnsureAnyChainman(context);
|
ChainstateManager& chainman = EnsureAnyChainman(context);
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
tip = chainman.ActiveChain().Tip();
|
CChain& active_chain = chainman.ActiveChain();
|
||||||
|
tip = active_chain.Tip();
|
||||||
const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(hash);
|
const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(hash);
|
||||||
while (pindex != nullptr && chainman.ActiveChain().Contains(pindex)) {
|
while (pindex != nullptr && active_chain.Contains(pindex)) {
|
||||||
headers.push_back(pindex);
|
headers.push_back(pindex);
|
||||||
if (headers.size() == (unsigned long)count)
|
if (headers.size() == (unsigned long)count)
|
||||||
break;
|
break;
|
||||||
pindex = chainman.ActiveChain().Next(pindex);
|
pindex = active_chain.Next(pindex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1009,6 +1009,8 @@ static RPCHelpMan pruneblockchain()
|
|||||||
|
|
||||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
CChainState& active_chainstate = chainman.ActiveChainstate();
|
||||||
|
CChain& active_chain = active_chainstate.m_chain;
|
||||||
|
|
||||||
int heightParam = request.params[0].get_int();
|
int heightParam = request.params[0].get_int();
|
||||||
if (heightParam < 0)
|
if (heightParam < 0)
|
||||||
@ -1018,7 +1020,7 @@ static RPCHelpMan pruneblockchain()
|
|||||||
// too low to be a block time (corresponds to timestamp from Sep 2001).
|
// too low to be a block time (corresponds to timestamp from Sep 2001).
|
||||||
if (heightParam > 1000000000) {
|
if (heightParam > 1000000000) {
|
||||||
// Add a 2 hour buffer to include blocks which might have had old timestamps
|
// 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) {
|
if (!pindex) {
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Could not find block with at least the specified timestamp.");
|
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 height = (unsigned int) heightParam;
|
||||||
unsigned int chainHeight = (unsigned int) chainman.ActiveChain().Height();
|
unsigned int chainHeight = (unsigned int) active_chain.Height();
|
||||||
if (chainHeight < Params().PruneAfterHeight())
|
if (chainHeight < Params().PruneAfterHeight())
|
||||||
throw JSONRPCError(RPC_MISC_ERROR, "Blockchain is too short for pruning.");
|
throw JSONRPCError(RPC_MISC_ERROR, "Blockchain is too short for pruning.");
|
||||||
else if (height > chainHeight)
|
else if (height > chainHeight)
|
||||||
@ -1036,8 +1038,8 @@ static RPCHelpMan pruneblockchain()
|
|||||||
height = chainHeight - MIN_BLOCKS_TO_KEEP;
|
height = chainHeight - MIN_BLOCKS_TO_KEEP;
|
||||||
}
|
}
|
||||||
|
|
||||||
PruneBlockFilesManual(chainman.ActiveChainstate(), height);
|
PruneBlockFilesManual(active_chainstate, height);
|
||||||
const CBlockIndex* block = chainman.ActiveChain().Tip();
|
const CBlockIndex* block = active_chain.Tip();
|
||||||
CHECK_NONFATAL(block);
|
CHECK_NONFATAL(block);
|
||||||
while (block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) {
|
while (block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) {
|
||||||
block = block->pprev;
|
block = block->pprev;
|
||||||
@ -1363,8 +1365,9 @@ RPCHelpMan getblockchaininfo()
|
|||||||
{
|
{
|
||||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||||
LOCK(cs_main);
|
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);
|
CHECK_NONFATAL(tip);
|
||||||
const int height = tip->nHeight;
|
const int height = tip->nHeight;
|
||||||
UniValue obj(UniValue::VOBJ);
|
UniValue obj(UniValue::VOBJ);
|
||||||
@ -1375,7 +1378,7 @@ RPCHelpMan getblockchaininfo()
|
|||||||
obj.pushKV("difficulty", (double)GetDifficulty(tip));
|
obj.pushKV("difficulty", (double)GetDifficulty(tip));
|
||||||
obj.pushKV("mediantime", (int64_t)tip->GetMedianTimePast());
|
obj.pushKV("mediantime", (int64_t)tip->GetMedianTimePast());
|
||||||
obj.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), tip));
|
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("chainwork", tip->nChainWork.GetHex());
|
||||||
obj.pushKV("size_on_disk", CalculateCurrentUsage());
|
obj.pushKV("size_on_disk", CalculateCurrentUsage());
|
||||||
obj.pushKV("pruned", fPruneMode);
|
obj.pushKV("pruned", fPruneMode);
|
||||||
@ -1457,6 +1460,7 @@ static RPCHelpMan getchaintips()
|
|||||||
{
|
{
|
||||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||||
LOCK(cs_main);
|
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.
|
* 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<const CBlockIndex*> setPrevs;
|
std::set<const CBlockIndex*> setPrevs;
|
||||||
|
|
||||||
for (const std::pair<const uint256, CBlockIndex*>& item : chainman.BlockIndex()) {
|
for (const std::pair<const uint256, CBlockIndex*>& item : chainman.BlockIndex()) {
|
||||||
if (!chainman.ActiveChain().Contains(item.second)) {
|
if (!active_chain.Contains(item.second)) {
|
||||||
setOrphans.insert(item.second);
|
setOrphans.insert(item.second);
|
||||||
setPrevs.insert(item.second->pprev);
|
setPrevs.insert(item.second->pprev);
|
||||||
}
|
}
|
||||||
@ -1483,7 +1487,7 @@ static RPCHelpMan getchaintips()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Always report the currently active tip.
|
// Always report the currently active tip.
|
||||||
setTips.insert(chainman.ActiveChain().Tip());
|
setTips.insert(active_chain.Tip());
|
||||||
|
|
||||||
/* Construct the output array. */
|
/* Construct the output array. */
|
||||||
UniValue res(UniValue::VARR);
|
UniValue res(UniValue::VARR);
|
||||||
@ -1492,11 +1496,11 @@ static RPCHelpMan getchaintips()
|
|||||||
obj.pushKV("height", block->nHeight);
|
obj.pushKV("height", block->nHeight);
|
||||||
obj.pushKV("hash", block->phashBlock->GetHex());
|
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);
|
obj.pushKV("branchlen", branchLen);
|
||||||
|
|
||||||
std::string status;
|
std::string status;
|
||||||
if (chainman.ActiveChain().Contains(block)) {
|
if (active_chain.Contains(block)) {
|
||||||
// This block is part of the currently active chain.
|
// This block is part of the currently active chain.
|
||||||
status = "active";
|
status = "active";
|
||||||
} else if (block->nStatus & BLOCK_FAILED_MASK) {
|
} else if (block->nStatus & BLOCK_FAILED_MASK) {
|
||||||
@ -1903,11 +1907,12 @@ static RPCHelpMan getblockstats()
|
|||||||
{
|
{
|
||||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
CChain& active_chain = chainman.ActiveChain();
|
||||||
|
|
||||||
CBlockIndex* pindex;
|
CBlockIndex* pindex;
|
||||||
if (request.params[0].isNum()) {
|
if (request.params[0].isNum()) {
|
||||||
const int height = request.params[0].get_int();
|
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) {
|
if (height < 0) {
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Target block height %d is negative", height));
|
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));
|
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 {
|
} else {
|
||||||
const uint256 hash(ParseHashV(request.params[0], "hash_or_height"));
|
const uint256 hash(ParseHashV(request.params[0], "hash_or_height"));
|
||||||
pindex = chainman.m_blockman.LookupBlockIndex(hash);
|
pindex = chainman.m_blockman.LookupBlockIndex(hash);
|
||||||
if (!pindex) {
|
if (!pindex) {
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
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()));
|
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);
|
ChainstateManager& chainman = EnsureChainman(node);
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
chainman.ActiveChainstate().ForceFlushStateToDisk();
|
CChainState& active_chainstate = chainman.ActiveChainstate();
|
||||||
pcursor = std::unique_ptr<CCoinsViewCursor>(chainman.ActiveChainstate().CoinsDB().Cursor());
|
active_chainstate.ForceFlushStateToDisk();
|
||||||
|
pcursor = std::unique_ptr<CCoinsViewCursor>(active_chainstate.CoinsDB().Cursor());
|
||||||
CHECK_NONFATAL(pcursor);
|
CHECK_NONFATAL(pcursor);
|
||||||
tip = chainman.ActiveChain().Tip();
|
tip = active_chainstate.m_chain.Tip();
|
||||||
CHECK_NONFATAL(tip);
|
CHECK_NONFATAL(tip);
|
||||||
}
|
}
|
||||||
bool res = FindScriptPubKey(g_scan_progress, g_should_abort_scan, count, pcursor.get(), needles, coins, node.rpc_interruption_point);
|
bool res = FindScriptPubKey(g_scan_progress, g_should_abort_scan, count, pcursor.get(), needles, coins, node.rpc_interruption_point);
|
||||||
|
@ -608,6 +608,8 @@ static RPCHelpMan getblocktemplate()
|
|||||||
UniValue lpval = NullUniValue;
|
UniValue lpval = NullUniValue;
|
||||||
std::set<std::string> setClientRules;
|
std::set<std::string> setClientRules;
|
||||||
int64_t nMaxVersionPreVB = -1;
|
int64_t nMaxVersionPreVB = -1;
|
||||||
|
CChainState& active_chainstate = chainman.ActiveChainstate();
|
||||||
|
CChain& active_chain = active_chainstate.m_chain;
|
||||||
if (!request.params[0].isNull())
|
if (!request.params[0].isNull())
|
||||||
{
|
{
|
||||||
const UniValue& oparam = request.params[0].get_obj();
|
const UniValue& oparam = request.params[0].get_obj();
|
||||||
@ -642,12 +644,12 @@ static RPCHelpMan getblocktemplate()
|
|||||||
return "duplicate-inconclusive";
|
return "duplicate-inconclusive";
|
||||||
}
|
}
|
||||||
|
|
||||||
CBlockIndex* const pindexPrev = chainman.ActiveChain().Tip();
|
CBlockIndex* const pindexPrev = active_chain.Tip();
|
||||||
// TestBlockValidity only supports blocks built on the current Tip
|
// TestBlockValidity only supports blocks built on the current Tip
|
||||||
if (block.hashPrevBlock != pindexPrev->GetBlockHash())
|
if (block.hashPrevBlock != pindexPrev->GetBlockHash())
|
||||||
return "inconclusive-not-best-prevblk";
|
return "inconclusive-not-best-prevblk";
|
||||||
BlockValidationState state;
|
BlockValidationState state;
|
||||||
TestBlockValidity(state, Params(), chainman.ActiveChainstate(), block, pindexPrev, false, true);
|
TestBlockValidity(state, Params(), active_chainstate, block, pindexPrev, false, true);
|
||||||
return BIP22ValidationResult(state);
|
return BIP22ValidationResult(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -677,7 +679,7 @@ static RPCHelpMan getblocktemplate()
|
|||||||
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, PACKAGE_NAME " is not connected!");
|
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...");
|
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
|
else
|
||||||
{
|
{
|
||||||
// NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
|
// 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;
|
nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -748,7 +750,7 @@ static RPCHelpMan getblocktemplate()
|
|||||||
static CBlockIndex* pindexPrev;
|
static CBlockIndex* pindexPrev;
|
||||||
static int64_t nStart;
|
static int64_t nStart;
|
||||||
static std::unique_ptr<CBlockTemplate> pblocktemplate;
|
static std::unique_ptr<CBlockTemplate> pblocktemplate;
|
||||||
if (pindexPrev != chainman.ActiveChain().Tip() ||
|
if (pindexPrev != active_chain.Tip() ||
|
||||||
(mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5))
|
(mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5))
|
||||||
{
|
{
|
||||||
// Clear pindexPrev so future calls make a new block, despite any failures from here on
|
// 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
|
// Store the pindexBest used before CreateNewBlock, to avoid races
|
||||||
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
|
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
|
||||||
CBlockIndex* pindexPrevNew = chainman.ActiveChain().Tip();
|
CBlockIndex* pindexPrevNew = active_chain.Tip();
|
||||||
nStart = GetTime();
|
nStart = GetTime();
|
||||||
|
|
||||||
// Create new block
|
// Create new block
|
||||||
CScript scriptDummy = CScript() << OP_TRUE;
|
CScript scriptDummy = CScript() << OP_TRUE;
|
||||||
pblocktemplate = BlockAssembler(chainman.ActiveChainstate(), mempool, Params()).CreateNewBlock(scriptDummy);
|
pblocktemplate = BlockAssembler(active_chainstate, mempool, Params()).CreateNewBlock(scriptDummy);
|
||||||
if (!pblocktemplate)
|
if (!pblocktemplate)
|
||||||
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
|
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
|
||||||
|
|
||||||
@ -897,7 +899,7 @@ static RPCHelpMan getblocktemplate()
|
|||||||
result.pushKV("transactions", transactions);
|
result.pushKV("transactions", transactions);
|
||||||
result.pushKV("coinbaseaux", aux);
|
result.pushKV("coinbaseaux", aux);
|
||||||
result.pushKV("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue);
|
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("target", hashTarget.GetHex());
|
||||||
result.pushKV("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1);
|
result.pushKV("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1);
|
||||||
result.pushKV("mutable", aMutable);
|
result.pushKV("mutable", aMutable);
|
||||||
|
@ -268,12 +268,13 @@ static RPCHelpMan gettxoutproof()
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOCK(cs_main);
|
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.
|
// Loop through txids and try to find which block they're in. Exit loop once a block is found.
|
||||||
for (const auto& tx : setTxids) {
|
for (const auto& tx : setTxids) {
|
||||||
const Coin& coin = AccessByTxid(chainman.ActiveChainstate().CoinsTip(), tx);
|
const Coin& coin = AccessByTxid(active_chainstate.CoinsTip(), tx);
|
||||||
if (!coin.IsSpent()) {
|
if (!coin.IsSpent()) {
|
||||||
pblockindex = chainman.ActiveChain()[coin.nHeight];
|
pblockindex = active_chainstate.m_chain[coin.nHeight];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user