refactoring: IsInitialBlockDownload -> CChainState
We introduce CChainState.m_cached_finished_ibd because the static state it replaces would've been shared across all CChainState instances.
This commit is contained in:
parent
3ccbc376dd
commit
403e677c9e
7 changed files with 41 additions and 29 deletions
|
@ -321,8 +321,8 @@ public:
|
||||||
CFeeRate relayDustFee() override { return ::dustRelayFee; }
|
CFeeRate relayDustFee() override { return ::dustRelayFee; }
|
||||||
bool getPruneMode() override { return ::fPruneMode; }
|
bool getPruneMode() override { return ::fPruneMode; }
|
||||||
bool p2pEnabled() override { return g_connman != nullptr; }
|
bool p2pEnabled() override { return g_connman != nullptr; }
|
||||||
bool isReadyToBroadcast() override { return !::fImporting && !::fReindex && !IsInitialBlockDownload(); }
|
bool isReadyToBroadcast() override { return !::fImporting && !::fReindex && !isInitialBlockDownload(); }
|
||||||
bool isInitialBlockDownload() override { return IsInitialBlockDownload(); }
|
bool isInitialBlockDownload() override { return ::ChainstateActive().IsInitialBlockDownload(); }
|
||||||
bool shutdownRequested() override { return ShutdownRequested(); }
|
bool shutdownRequested() override { return ShutdownRequested(); }
|
||||||
int64_t getAdjustedTime() override { return GetAdjustedTime(); }
|
int64_t getAdjustedTime() override { return GetAdjustedTime(); }
|
||||||
void initMessage(const std::string& message) override { ::uiInterface.InitMessage(message); }
|
void initMessage(const std::string& message) override { ::uiInterface.InitMessage(message); }
|
||||||
|
|
|
@ -197,7 +197,7 @@ public:
|
||||||
}
|
}
|
||||||
return GuessVerificationProgress(Params().TxData(), tip);
|
return GuessVerificationProgress(Params().TxData(), tip);
|
||||||
}
|
}
|
||||||
bool isInitialBlockDownload() override { return IsInitialBlockDownload(); }
|
bool isInitialBlockDownload() override { return ::ChainstateActive().IsInitialBlockDownload(); }
|
||||||
bool getReindex() override { return ::fReindex; }
|
bool getReindex() override { return ::fReindex; }
|
||||||
bool getImporting() override { return ::fImporting; }
|
bool getImporting() override { return ::fImporting; }
|
||||||
void setNetworkActive(bool active) override
|
void setNetworkActive(bool active) override
|
||||||
|
|
|
@ -1240,7 +1240,7 @@ void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationSta
|
||||||
// the tip yet so we have no way to check this directly here. Instead we
|
// the tip yet so we have no way to check this directly here. Instead we
|
||||||
// just check that there are currently no other blocks in flight.
|
// just check that there are currently no other blocks in flight.
|
||||||
else if (state.IsValid() &&
|
else if (state.IsValid() &&
|
||||||
!IsInitialBlockDownload() &&
|
!::ChainstateActive().IsInitialBlockDownload() &&
|
||||||
mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
|
mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
|
||||||
if (it != mapBlockSource.end()) {
|
if (it != mapBlockSource.end()) {
|
||||||
MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first, connman);
|
MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first, connman);
|
||||||
|
@ -1728,7 +1728,7 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve
|
||||||
}
|
}
|
||||||
// If we're in IBD, we want outbound peers that will serve us a useful
|
// If we're in IBD, we want outbound peers that will serve us a useful
|
||||||
// chain. Disconnect peers that are on chains with insufficient work.
|
// chain. Disconnect peers that are on chains with insufficient work.
|
||||||
if (IsInitialBlockDownload() && nCount != MAX_HEADERS_RESULTS) {
|
if (::ChainstateActive().IsInitialBlockDownload() && nCount != MAX_HEADERS_RESULTS) {
|
||||||
// When nCount < MAX_HEADERS_RESULTS, we know we have no more
|
// When nCount < MAX_HEADERS_RESULTS, we know we have no more
|
||||||
// headers to fetch from this peer.
|
// headers to fetch from this peer.
|
||||||
if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < nMinimumChainWork) {
|
if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < nMinimumChainWork) {
|
||||||
|
@ -1994,7 +1994,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
||||||
if (!pfrom->fInbound)
|
if (!pfrom->fInbound)
|
||||||
{
|
{
|
||||||
// Advertise our address
|
// Advertise our address
|
||||||
if (fListen && !IsInitialBlockDownload())
|
if (fListen && !::ChainstateActive().IsInitialBlockDownload())
|
||||||
{
|
{
|
||||||
CAddress addr = GetLocalAddress(&pfrom->addr, pfrom->GetLocalServices());
|
CAddress addr = GetLocalAddress(&pfrom->addr, pfrom->GetLocalServices());
|
||||||
FastRandomContext insecure_rand;
|
FastRandomContext insecure_rand;
|
||||||
|
@ -2229,7 +2229,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
||||||
pfrom->AddInventoryKnown(inv);
|
pfrom->AddInventoryKnown(inv);
|
||||||
if (fBlocksOnly) {
|
if (fBlocksOnly) {
|
||||||
LogPrint(BCLog::NET, "transaction (%s) inv sent in violation of protocol peer=%d\n", inv.hash.ToString(), pfrom->GetId());
|
LogPrint(BCLog::NET, "transaction (%s) inv sent in violation of protocol peer=%d\n", inv.hash.ToString(), pfrom->GetId());
|
||||||
} else if (!fAlreadyHave && !fImporting && !fReindex && !IsInitialBlockDownload()) {
|
} else if (!fAlreadyHave && !fImporting && !fReindex && !::ChainstateActive().IsInitialBlockDownload()) {
|
||||||
RequestTx(State(pfrom->GetId()), inv.hash, nNow);
|
RequestTx(State(pfrom->GetId()), inv.hash, nNow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2387,7 +2387,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
if (IsInitialBlockDownload() && !pfrom->fWhitelisted) {
|
if (::ChainstateActive().IsInitialBlockDownload() && !pfrom->fWhitelisted) {
|
||||||
LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because node is in initial block download\n", pfrom->GetId());
|
LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because node is in initial block download\n", pfrom->GetId());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2609,7 +2609,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
||||||
|
|
||||||
if (!LookupBlockIndex(cmpctblock.header.hashPrevBlock)) {
|
if (!LookupBlockIndex(cmpctblock.header.hashPrevBlock)) {
|
||||||
// Doesn't connect (or is genesis), instead of DoSing in AcceptBlockHeader, request deeper headers
|
// Doesn't connect (or is genesis), instead of DoSing in AcceptBlockHeader, request deeper headers
|
||||||
if (!IsInitialBlockDownload())
|
if (!::ChainstateActive().IsInitialBlockDownload())
|
||||||
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, ::ChainActive().GetLocator(pindexBestHeader), uint256()));
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, ::ChainActive().GetLocator(pindexBestHeader), uint256()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3525,7 +3525,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
|
||||||
|
|
||||||
// Address refresh broadcast
|
// Address refresh broadcast
|
||||||
int64_t nNow = GetTimeMicros();
|
int64_t nNow = GetTimeMicros();
|
||||||
if (!IsInitialBlockDownload() && pto->nNextLocalAddrSend < nNow) {
|
if (!::ChainstateActive().IsInitialBlockDownload() && pto->nNextLocalAddrSend < nNow) {
|
||||||
AdvertiseLocal(pto);
|
AdvertiseLocal(pto);
|
||||||
pto->nNextLocalAddrSend = PoissonNextSend(nNow, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
|
pto->nNextLocalAddrSend = PoissonNextSend(nNow, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
|
||||||
}
|
}
|
||||||
|
@ -3926,7 +3926,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
|
||||||
// Message: getdata (blocks)
|
// Message: getdata (blocks)
|
||||||
//
|
//
|
||||||
std::vector<CInv> vGetData;
|
std::vector<CInv> vGetData;
|
||||||
if (!pto->fClient && ((fFetch && !pto->m_limited_node) || !IsInitialBlockDownload()) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
|
if (!pto->fClient && ((fFetch && !pto->m_limited_node) || !::ChainstateActive().IsInitialBlockDownload()) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
|
||||||
std::vector<const CBlockIndex*> vToDownload;
|
std::vector<const CBlockIndex*> vToDownload;
|
||||||
NodeId staller = -1;
|
NodeId staller = -1;
|
||||||
FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller, consensusParams);
|
FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller, consensusParams);
|
||||||
|
|
|
@ -1342,7 +1342,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
|
||||||
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", IsInitialBlockDownload());
|
obj.pushKV("initialblockdownload", ::ChainstateActive().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);
|
||||||
|
|
|
@ -442,7 +442,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
|
||||||
if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0)
|
if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0)
|
||||||
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, PACKAGE_NAME " is not connected!");
|
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, PACKAGE_NAME " is not connected!");
|
||||||
|
|
||||||
if (IsInitialBlockDownload())
|
if (::ChainstateActive().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...");
|
||||||
|
|
||||||
static unsigned int nTransactionsUpdatedLast;
|
static unsigned int nTransactionsUpdatedLast;
|
||||||
|
|
|
@ -321,7 +321,7 @@ static void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age)
|
||||||
static bool IsCurrentForFeeEstimation() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
static bool IsCurrentForFeeEstimation() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
if (IsInitialBlockDownload())
|
if (::ChainstateActive().IsInitialBlockDownload())
|
||||||
return false;
|
return false;
|
||||||
if (::ChainActive().Tip()->GetBlockTime() < (GetTime() - MAX_FEE_ESTIMATION_TIP_AGE))
|
if (::ChainActive().Tip()->GetBlockTime() < (GetTime() - MAX_FEE_ESTIMATION_TIP_AGE))
|
||||||
return false;
|
return false;
|
||||||
|
@ -1022,27 +1022,30 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)
|
||||||
return nSubsidy;
|
return nSubsidy;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsInitialBlockDownload()
|
// Note that though this is marked const, we may end up modifying `m_cached_finished_ibd`, which
|
||||||
|
// is a performance-related implementation detail. This function must be marked
|
||||||
|
// `const` so that `CValidationInterface` clients (which are given a `const CChainState*`)
|
||||||
|
// can call it.
|
||||||
|
//
|
||||||
|
bool CChainState::IsInitialBlockDownload() const
|
||||||
{
|
{
|
||||||
// Once this function has returned false, it must remain false.
|
|
||||||
static std::atomic<bool> latchToFalse{false};
|
|
||||||
// Optimization: pre-test latch before taking the lock.
|
// Optimization: pre-test latch before taking the lock.
|
||||||
if (latchToFalse.load(std::memory_order_relaxed))
|
if (m_cached_finished_ibd.load(std::memory_order_relaxed))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
if (latchToFalse.load(std::memory_order_relaxed))
|
if (m_cached_finished_ibd.load(std::memory_order_relaxed))
|
||||||
return false;
|
return false;
|
||||||
if (fImporting || fReindex)
|
if (fImporting || fReindex)
|
||||||
return true;
|
return true;
|
||||||
if (::ChainActive().Tip() == nullptr)
|
if (m_chain.Tip() == nullptr)
|
||||||
return true;
|
return true;
|
||||||
if (::ChainActive().Tip()->nChainWork < nMinimumChainWork)
|
if (m_chain.Tip()->nChainWork < nMinimumChainWork)
|
||||||
return true;
|
return true;
|
||||||
if (::ChainActive().Tip()->GetBlockTime() < (GetTime() - nMaxTipAge))
|
if (m_chain.Tip()->GetBlockTime() < (GetTime() - nMaxTipAge))
|
||||||
return true;
|
return true;
|
||||||
LogPrintf("Leaving InitialBlockDownload (latching to false)\n");
|
LogPrintf("Leaving InitialBlockDownload (latching to false)\n");
|
||||||
latchToFalse.store(true, std::memory_order_relaxed);
|
m_cached_finished_ibd.store(true, std::memory_order_relaxed);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1071,7 +1074,7 @@ static void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
// Before we get past initial download, we cannot reliably alert about forks
|
// Before we get past initial download, we cannot reliably alert about forks
|
||||||
// (we assume we don't get stuck on a fork before finishing our initial sync)
|
// (we assume we don't get stuck on a fork before finishing our initial sync)
|
||||||
if (IsInitialBlockDownload())
|
if (::ChainstateActive().IsInitialBlockDownload())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If our best fork is no longer within 72 blocks (+/- 12 hours if no one mines it)
|
// If our best fork is no longer within 72 blocks (+/- 12 hours if no one mines it)
|
||||||
|
@ -2101,7 +2104,7 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string warningMessages;
|
std::string warningMessages;
|
||||||
if (!IsInitialBlockDownload())
|
if (!::ChainstateActive().IsInitialBlockDownload())
|
||||||
{
|
{
|
||||||
int nUpgraded = 0;
|
int nUpgraded = 0;
|
||||||
const CBlockIndex* pindex = pindexNew;
|
const CBlockIndex* pindex = pindexNew;
|
||||||
|
@ -2492,7 +2495,7 @@ static void NotifyHeaderTip() LOCKS_EXCLUDED(cs_main) {
|
||||||
|
|
||||||
if (pindexHeader != pindexHeaderOld) {
|
if (pindexHeader != pindexHeaderOld) {
|
||||||
fNotify = true;
|
fNotify = true;
|
||||||
fInitialBlockDownload = IsInitialBlockDownload();
|
fInitialBlockDownload = ::ChainstateActive().IsInitialBlockDownload();
|
||||||
pindexHeaderOld = pindexHeader;
|
pindexHeaderOld = pindexHeader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3621,7 +3624,7 @@ static void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfte
|
||||||
// To avoid excessive prune events negating the benefit of high dbcache
|
// To avoid excessive prune events negating the benefit of high dbcache
|
||||||
// values, we should not prune too rapidly.
|
// values, we should not prune too rapidly.
|
||||||
// So when pruning in IBD, increase the buffer a bit to avoid a re-prune too soon.
|
// So when pruning in IBD, increase the buffer a bit to avoid a re-prune too soon.
|
||||||
if (IsInitialBlockDownload()) {
|
if (::ChainstateActive().IsInitialBlockDownload()) {
|
||||||
// Since this is only relevant during IBD, we use a fixed 10%
|
// Since this is only relevant during IBD, we use a fixed 10%
|
||||||
nBuffer += nPruneTarget / 10;
|
nBuffer += nPruneTarget / 10;
|
||||||
}
|
}
|
||||||
|
|
|
@ -249,8 +249,6 @@ bool LoadChainTip(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_m
|
||||||
void UnloadBlockIndex();
|
void UnloadBlockIndex();
|
||||||
/** Run an instance of the script checking thread */
|
/** Run an instance of the script checking thread */
|
||||||
void ThreadScriptCheck(int worker_num);
|
void ThreadScriptCheck(int worker_num);
|
||||||
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
|
|
||||||
bool IsInitialBlockDownload();
|
|
||||||
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
|
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
|
||||||
bool GetTransaction(const uint256& hash, CTransactionRef& tx, const Consensus::Params& params, uint256& hashBlock, const CBlockIndex* const blockIndex = nullptr);
|
bool GetTransaction(const uint256& hash, CTransactionRef& tx, const Consensus::Params& params, uint256& hashBlock, const CBlockIndex* const blockIndex = nullptr);
|
||||||
/**
|
/**
|
||||||
|
@ -503,6 +501,14 @@ private:
|
||||||
*/
|
*/
|
||||||
CCriticalSection m_cs_chainstate;
|
CCriticalSection m_cs_chainstate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this chainstate is undergoing initial block download.
|
||||||
|
*
|
||||||
|
* Mutable because we need to be able to mark IsInitialBlockDownload()
|
||||||
|
* const, which latches this for caching purposes.
|
||||||
|
*/
|
||||||
|
mutable std::atomic<bool> m_cached_finished_ibd{false};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//! The current chain of blockheaders we consult and build on.
|
//! The current chain of blockheaders we consult and build on.
|
||||||
//! @see CChain, CBlockIndex.
|
//! @see CChain, CBlockIndex.
|
||||||
|
@ -565,6 +571,9 @@ public:
|
||||||
|
|
||||||
void UnloadBlockIndex();
|
void UnloadBlockIndex();
|
||||||
|
|
||||||
|
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
|
||||||
|
bool IsInitialBlockDownload() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||||
bool ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
bool ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||||
|
|
Loading…
Reference in a new issue