Skip to content

Commit 3665483

Browse files
committed
Merge #8969: Decouple peer-processing-logic from block-connection-logic (bitcoin-core#2)
f5b960b Move nTimeBestReceived updating into net processing code (Matt Corallo) d8670fb Move all calls to CheckBlockIndex out of net-processing logic (Matt Corallo) d6ea737 Remove network state wipe from UnloadBlockIndex. (Matt Corallo) fc0c24f Move MarkBlockAsReceived out of ProcessNewMessage (Matt Corallo) 65f35eb Move FlushStateToDisk call out of ProcessMessages::TX into ATMP (Matt Corallo)
2 parents fcf61b8 + f5b960b commit 3665483

File tree

3 files changed

+49
-29
lines changed

3 files changed

+49
-29
lines changed

src/init.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
11031103
return false;
11041104
#endif
11051105
// ********************************************************* Step 6: network initialization
1106+
// Note that we absolutely cannot open any actual connections
1107+
// until the very end ("start node") as the UTXO/block state
1108+
// is not yet setup and may end up being set up twice if we
1109+
// need to reindex later.
11061110

11071111
assert(!g_connman);
11081112
g_connman = std::unique_ptr<CConnman>(new CConnman(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max())));

src/main.cpp

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ CCriticalSection cs_main;
6363
BlockMap mapBlockIndex;
6464
CChain chainActive;
6565
CBlockIndex *pindexBestHeader = NULL;
66-
int64_t nTimeBestReceived = 0;
66+
int64_t nTimeBestReceived = 0; // Used only to inform the wallet of when we last received a block
6767
CWaitableCriticalSection csBestBlock;
6868
CConditionVariable cvBlockChange;
6969
int nScriptCheckThreads = 0;
@@ -691,6 +691,16 @@ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& loc
691691
CCoinsViewCache *pcoinsTip = NULL;
692692
CBlockTreeDB *pblocktree = NULL;
693693

694+
enum FlushStateMode {
695+
FLUSH_STATE_NONE,
696+
FLUSH_STATE_IF_NEEDED,
697+
FLUSH_STATE_PERIODIC,
698+
FLUSH_STATE_ALWAYS
699+
};
700+
701+
// See definition for documentation
702+
bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode);
703+
694704
//////////////////////////////////////////////////////////////////////////////
695705
//
696706
// mapOrphanTransactions
@@ -1581,6 +1591,9 @@ bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const
15811591
BOOST_FOREACH(const uint256& hashTx, vHashTxToUncache)
15821592
pcoinsTip->Uncache(hashTx);
15831593
}
1594+
// After we've (potentially) uncached entries, ensure our coins cache is still within its size limits
1595+
CValidationState stateDummy;
1596+
FlushStateToDisk(stateDummy, FLUSH_STATE_PERIODIC);
15841597
return res;
15851598
}
15861599

@@ -2565,13 +2578,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
25652578
return true;
25662579
}
25672580

2568-
enum FlushStateMode {
2569-
FLUSH_STATE_NONE,
2570-
FLUSH_STATE_IF_NEEDED,
2571-
FLUSH_STATE_PERIODIC,
2572-
FLUSH_STATE_ALWAYS
2573-
};
2574-
25752581
/**
25762582
* Update the on-disk chain state.
25772583
* The caches and indexes are flushed depending on the mode we're called with
@@ -2691,7 +2697,6 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) {
26912697
chainActive.SetTip(pindexNew);
26922698

26932699
// New best block
2694-
nTimeBestReceived = GetTime();
26952700
mempool.AddTransactionsUpdated(1);
26962701

26972702
cvBlockChange.notify_all();
@@ -3676,6 +3681,8 @@ static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state
36763681
if (ppindex)
36773682
*ppindex = pindex;
36783683

3684+
CheckBlockIndex(chainparams.GetConsensus());
3685+
36793686
return true;
36803687
}
36813688

@@ -3703,6 +3710,11 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha
37033710
// not process unrequested blocks.
37043711
bool fTooFarAhead = (pindex->nHeight > int(chainActive.Height() + MIN_BLOCKS_TO_KEEP));
37053712

3713+
// TODO: Decouple this function from the block download logic by removing fRequested
3714+
// This requires some new chain datastructure to efficiently look up if a
3715+
// block is in a chain leading to a candidate for best tip, despite not
3716+
// being such a candidate itself.
3717+
37063718
// TODO: deal better with return value and error conditions for duplicate
37073719
// and unrequested blocks.
37083720
if (fAlreadyHave) return true;
@@ -3751,13 +3763,11 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, C
37513763
{
37523764
{
37533765
LOCK(cs_main);
3754-
bool fRequested = MarkBlockAsReceived(pblock->GetHash());
3755-
fRequested |= fForceProcessing;
37563766

37573767
// Store to disk
37583768
CBlockIndex *pindex = NULL;
37593769
bool fNewBlock = false;
3760-
bool ret = AcceptBlock(*pblock, state, chainparams, &pindex, fRequested, dbp, &fNewBlock);
3770+
bool ret = AcceptBlock(*pblock, state, chainparams, &pindex, fForceProcessing, dbp, &fNewBlock);
37613771
if (pindex && pfrom) {
37623772
mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId();
37633773
if (fNewBlock) pfrom->nLastBlockTime = GetTime();
@@ -4269,6 +4279,9 @@ bool RewindBlockIndex(const CChainParams& params)
42694279
return true;
42704280
}
42714281

4282+
// May NOT be used after any connections are up as much
4283+
// of the peer-processing logic assumes a consistent
4284+
// block index state
42724285
void UnloadBlockIndex()
42734286
{
42744287
LOCK(cs_main);
@@ -4279,18 +4292,12 @@ void UnloadBlockIndex()
42794292
mempool.clear();
42804293
mapOrphanTransactions.clear();
42814294
mapOrphanTransactionsByPrev.clear();
4282-
nSyncStarted = 0;
42834295
mapBlocksUnlinked.clear();
42844296
vinfoBlockFile.clear();
42854297
nLastBlockFile = 0;
42864298
nBlockSequenceId = 1;
4287-
mapBlockSource.clear();
4288-
mapBlocksInFlight.clear();
4289-
nPreferredDownload = 0;
42904299
setDirtyBlockIndex.clear();
42914300
setDirtyFileInfo.clear();
4292-
mapNodeState.clear();
4293-
recentRejects.reset(NULL);
42944301
versionbitscache.Clear();
42954302
for (int b = 0; b < VERSIONBITS_NUM_BITS; b++) {
42964303
warningcache[b].clear();
@@ -4315,9 +4322,6 @@ bool InitBlockIndex(const CChainParams& chainparams)
43154322
{
43164323
LOCK(cs_main);
43174324

4318-
// Initialize global variables that cannot be constructed at startup.
4319-
recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
4320-
43214325
// Check whether we're already initialized
43224326
if (chainActive.Genesis() != NULL)
43234327
return true;
@@ -4706,6 +4710,11 @@ std::string GetWarnings(const std::string& strFor)
47064710
// blockchain -> download logic notification
47074711
//
47084712

4713+
PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn) : connman(connmanIn) {
4714+
// Initialize global variables that cannot be constructed at startup.
4715+
recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
4716+
}
4717+
47094718
void PeerLogicValidation::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {
47104719
const int nNewHeight = pindexNew->nHeight;
47114720
connman->SetBestHeight(nNewHeight);
@@ -4732,6 +4741,8 @@ void PeerLogicValidation::UpdatedBlockTip(const CBlockIndex *pindexNew, const CB
47324741
}
47334742
});
47344743
}
4744+
4745+
nTimeBestReceived = GetTime();
47354746
}
47364747

47374748
void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationState& state) {
@@ -5690,7 +5701,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
56905701
Misbehaving(pfrom->GetId(), nDoS);
56915702
}
56925703
}
5693-
FlushStateToDisk(state, FLUSH_STATE_PERIODIC);
56945704
}
56955705

56965706

@@ -5826,8 +5836,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
58265836
return ProcessMessage(pfrom, NetMsgType::HEADERS, vHeadersMsg, nTimeReceived, chainparams, connman);
58275837
}
58285838
}
5829-
5830-
CheckBlockIndex(chainparams.GetConsensus());
58315839
}
58325840

58335841
else if (strCommand == NetMsgType::BLOCKTXN && !fImporting && !fReindex) // Ignore blocks received while importing
@@ -5859,12 +5867,16 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
58595867
std::vector<CInv> invs;
58605868
invs.push_back(CInv(MSG_BLOCK | GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus()), resp.blockhash));
58615869
pfrom->PushMessage(NetMsgType::GETDATA, invs);
5862-
} else
5870+
} else {
5871+
MarkBlockAsReceived(resp.blockhash); // it is now an empty pointer
58635872
fBlockRead = true;
5873+
}
58645874
} // Don't hold cs_main when we call into ProcessNewBlock
58655875
if (fBlockRead) {
58665876
CValidationState state;
5867-
ProcessNewBlock(state, chainparams, pfrom, &block, false, NULL);
5877+
// Since we requested this block (it was in mapBlocksInFlight), force it to be processed,
5878+
// even if it would not be a candidate for new tip (missing previous block, chain not long enough, etc)
5879+
ProcessNewBlock(state, chainparams, pfrom, &block, true, NULL);
58685880
int nDoS;
58695881
if (state.IsInvalid(nDoS)) {
58705882
assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
@@ -6020,8 +6032,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
60206032
}
60216033
}
60226034
}
6023-
6024-
CheckBlockIndex(chainparams.GetConsensus());
60256035
}
60266036

60276037
NotifyHeaderTip();
@@ -6040,6 +6050,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
60406050
// Such an unrequested block may still be processed, subject to the
60416051
// conditions in AcceptBlock().
60426052
bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload();
6053+
{
6054+
LOCK(cs_main);
6055+
// Also always process if we requested the block explicitly, as we may
6056+
// need it even though it is not a candidate for a new best tip.
6057+
forceProcessing |= MarkBlockAsReceived(block.GetHash());
6058+
}
60436059
ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL);
60446060
int nDoS;
60456061
if (state.IsInvalid(nDoS)) {

src/main.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,7 @@ class PeerLogicValidation : public CValidationInterface {
552552
CConnman* connman;
553553

554554
public:
555-
PeerLogicValidation(CConnman* connmanIn) : connman(connmanIn) {}
555+
PeerLogicValidation(CConnman* connmanIn);
556556

557557
virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload);
558558
virtual void BlockChecked(const CBlock& block, const CValidationState& state);

0 commit comments

Comments
 (0)