aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames O'Beirne <james.obeirne@gmail.com>2019-03-27 12:21:50 -0400
committerJames O'Beirne <james.obeirne@gmail.com>2019-05-16 09:06:54 -0400
commit403e677c9ebbf9744733010e6b0c2d1b182ee850 (patch)
tree3c97f958fc6b15676945d55a82794366d3097fb6
parent3ccbc376dd313fb7666471f24f6d9370914d00f3 (diff)
refactoring: IsInitialBlockDownload -> CChainState
We introduce CChainState.m_cached_finished_ibd because the static state it replaces would've been shared across all CChainState instances.
-rw-r--r--src/interfaces/chain.cpp4
-rw-r--r--src/interfaces/node.cpp2
-rw-r--r--src/net_processing.cpp16
-rw-r--r--src/rpc/blockchain.cpp2
-rw-r--r--src/rpc/mining.cpp2
-rw-r--r--src/validation.cpp31
-rw-r--r--src/validation.h13
7 files changed, 41 insertions, 29 deletions
diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp
index fcbc442d12..bc4be456b1 100644
--- a/src/interfaces/chain.cpp
+++ b/src/interfaces/chain.cpp
@@ -321,8 +321,8 @@ public:
CFeeRate relayDustFee() override { return ::dustRelayFee; }
bool getPruneMode() override { return ::fPruneMode; }
bool p2pEnabled() override { return g_connman != nullptr; }
- bool isReadyToBroadcast() override { return !::fImporting && !::fReindex && !IsInitialBlockDownload(); }
- bool isInitialBlockDownload() override { return IsInitialBlockDownload(); }
+ bool isReadyToBroadcast() override { return !::fImporting && !::fReindex && !isInitialBlockDownload(); }
+ bool isInitialBlockDownload() override { return ::ChainstateActive().IsInitialBlockDownload(); }
bool shutdownRequested() override { return ShutdownRequested(); }
int64_t getAdjustedTime() override { return GetAdjustedTime(); }
void initMessage(const std::string& message) override { ::uiInterface.InitMessage(message); }
diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp
index 618cd02ea6..15646b0ff4 100644
--- a/src/interfaces/node.cpp
+++ b/src/interfaces/node.cpp
@@ -197,7 +197,7 @@ public:
}
return GuessVerificationProgress(Params().TxData(), tip);
}
- bool isInitialBlockDownload() override { return IsInitialBlockDownload(); }
+ bool isInitialBlockDownload() override { return ::ChainstateActive().IsInitialBlockDownload(); }
bool getReindex() override { return ::fReindex; }
bool getImporting() override { return ::fImporting; }
void setNetworkActive(bool active) override
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index b3facdcd3a..0a51cad745 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -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
// just check that there are currently no other blocks in flight.
else if (state.IsValid() &&
- !IsInitialBlockDownload() &&
+ !::ChainstateActive().IsInitialBlockDownload() &&
mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
if (it != mapBlockSource.end()) {
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
// 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
// headers to fetch from this peer.
if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < nMinimumChainWork) {
@@ -1994,7 +1994,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (!pfrom->fInbound)
{
// Advertise our address
- if (fListen && !IsInitialBlockDownload())
+ if (fListen && !::ChainstateActive().IsInitialBlockDownload())
{
CAddress addr = GetLocalAddress(&pfrom->addr, pfrom->GetLocalServices());
FastRandomContext insecure_rand;
@@ -2229,7 +2229,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
pfrom->AddInventoryKnown(inv);
if (fBlocksOnly) {
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);
}
}
@@ -2387,7 +2387,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
}
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());
return true;
}
@@ -2609,7 +2609,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (!LookupBlockIndex(cmpctblock.header.hashPrevBlock)) {
// 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()));
return true;
}
@@ -3525,7 +3525,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
// Address refresh broadcast
int64_t nNow = GetTimeMicros();
- if (!IsInitialBlockDownload() && pto->nNextLocalAddrSend < nNow) {
+ if (!::ChainstateActive().IsInitialBlockDownload() && pto->nNextLocalAddrSend < nNow) {
AdvertiseLocal(pto);
pto->nNextLocalAddrSend = PoissonNextSend(nNow, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
}
@@ -3926,7 +3926,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
// Message: getdata (blocks)
//
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;
NodeId staller = -1;
FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller, consensusParams);
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index fef51bd709..556fea67ab 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1342,7 +1342,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
obj.pushKV("difficulty", (double)GetDifficulty(tip));
obj.pushKV("mediantime", (int64_t)tip->GetMedianTimePast());
obj.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), tip));
- obj.pushKV("initialblockdownload", IsInitialBlockDownload());
+ obj.pushKV("initialblockdownload", ::ChainstateActive().IsInitialBlockDownload());
obj.pushKV("chainwork", tip->nChainWork.GetHex());
obj.pushKV("size_on_disk", CalculateCurrentUsage());
obj.pushKV("pruned", fPruneMode);
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 1831562100..477f05f46c 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -442,7 +442,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0)
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...");
static unsigned int nTransactionsUpdatedLast;
diff --git a/src/validation.cpp b/src/validation.cpp
index 6087260c6b..ca4a7ab3e6 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -321,7 +321,7 @@ static void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age)
static bool IsCurrentForFeeEstimation() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
AssertLockHeld(cs_main);
- if (IsInitialBlockDownload())
+ if (::ChainstateActive().IsInitialBlockDownload())
return false;
if (::ChainActive().Tip()->GetBlockTime() < (GetTime() - MAX_FEE_ESTIMATION_TIP_AGE))
return false;
@@ -1022,27 +1022,30 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)
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.
- if (latchToFalse.load(std::memory_order_relaxed))
+ if (m_cached_finished_ibd.load(std::memory_order_relaxed))
return false;
LOCK(cs_main);
- if (latchToFalse.load(std::memory_order_relaxed))
+ if (m_cached_finished_ibd.load(std::memory_order_relaxed))
return false;
if (fImporting || fReindex)
return true;
- if (::ChainActive().Tip() == nullptr)
+ if (m_chain.Tip() == nullptr)
return true;
- if (::ChainActive().Tip()->nChainWork < nMinimumChainWork)
+ if (m_chain.Tip()->nChainWork < nMinimumChainWork)
return true;
- if (::ChainActive().Tip()->GetBlockTime() < (GetTime() - nMaxTipAge))
+ if (m_chain.Tip()->GetBlockTime() < (GetTime() - nMaxTipAge))
return true;
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;
}
@@ -1071,7 +1074,7 @@ static void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
AssertLockHeld(cs_main);
// 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)
- if (IsInitialBlockDownload())
+ if (::ChainstateActive().IsInitialBlockDownload())
return;
// 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;
- if (!IsInitialBlockDownload())
+ if (!::ChainstateActive().IsInitialBlockDownload())
{
int nUpgraded = 0;
const CBlockIndex* pindex = pindexNew;
@@ -2492,7 +2495,7 @@ static void NotifyHeaderTip() LOCKS_EXCLUDED(cs_main) {
if (pindexHeader != pindexHeaderOld) {
fNotify = true;
- fInitialBlockDownload = IsInitialBlockDownload();
+ fInitialBlockDownload = ::ChainstateActive().IsInitialBlockDownload();
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
// values, we should not prune too rapidly.
// 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%
nBuffer += nPruneTarget / 10;
}
diff --git a/src/validation.h b/src/validation.h
index 3eece8d2b9..d4c368a99c 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -249,8 +249,6 @@ bool LoadChainTip(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_m
void UnloadBlockIndex();
/** Run an instance of the script checking thread */
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) */
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;
+ /**
+ * 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:
//! The current chain of blockheaders we consult and build on.
//! @see CChain, CBlockIndex.
@@ -565,6 +571,9 @@ public:
void UnloadBlockIndex();
+ /** Check whether we are doing an initial block download (synchronizing from disk or network) */
+ bool IsInitialBlockDownload() const;
+
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 ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main);