@@ -28,10 +28,45 @@ bool fHavePruned = false;
28
28
bool fPruneMode = false ;
29
29
uint64_t nPruneTarget = 0 ;
30
30
31
+ bool CBlockIndexWorkComparator::operator ()(const CBlockIndex* pa, const CBlockIndex* pb) const
32
+ {
33
+ // First sort by most total work, ...
34
+ if (pa->nChainWork > pb->nChainWork ) return false ;
35
+ if (pa->nChainWork < pb->nChainWork ) return true ;
36
+
37
+ // ... then by earliest time received, ...
38
+ if (pa->nSequenceId < pb->nSequenceId ) return false ;
39
+ if (pa->nSequenceId > pb->nSequenceId ) return true ;
40
+
41
+ // Use pointer address as tie breaker (should only happen with blocks
42
+ // loaded from disk, as those all have id 0).
43
+ if (pa < pb) return false ;
44
+ if (pa > pb) return true ;
45
+
46
+ // Identical blocks.
47
+ return false ;
48
+ }
49
+
50
+ bool CBlockIndexHeightOnlyComparator::operator ()(const CBlockIndex* pa, const CBlockIndex* pb) const
51
+ {
52
+ return pa->nHeight < pb->nHeight ;
53
+ }
54
+
31
55
static FILE* OpenUndoFile (const FlatFilePos& pos, bool fReadOnly = false );
32
56
static FlatFileSeq BlockFileSeq ();
33
57
static FlatFileSeq UndoFileSeq ();
34
58
59
+ std::vector<CBlockIndex*> BlockManager::GetAllBlockIndices ()
60
+ {
61
+ AssertLockHeld (cs_main);
62
+ std::vector<CBlockIndex*> rv;
63
+ rv.reserve (m_block_index.size ());
64
+ for (auto & [_, block_index] : m_block_index) {
65
+ rv.push_back (&block_index);
66
+ }
67
+ return rv;
68
+ }
69
+
35
70
CBlockIndex* BlockManager::LookupBlockIndex (const uint256& hash)
36
71
{
37
72
AssertLockHeld (cs_main);
@@ -203,55 +238,27 @@ CBlockIndex* BlockManager::InsertBlockIndex(const uint256& hash)
203
238
return nullptr ;
204
239
}
205
240
206
- // Return existing or create new
207
- auto [mi, inserted] = m_block_index.try_emplace (hash);
241
+ const auto [mi, inserted]{m_block_index.try_emplace (hash)};
208
242
CBlockIndex* pindex = &(*mi).second ;
209
243
if (inserted) {
210
244
pindex->phashBlock = &((*mi).first );
211
245
}
212
246
return pindex;
213
247
}
214
248
215
- bool BlockManager::LoadBlockIndex (
216
- const Consensus::Params& consensus_params,
217
- ChainstateManager& chainman)
249
+ bool BlockManager::LoadBlockIndex (const Consensus::Params& consensus_params)
218
250
{
219
251
if (!m_block_tree_db->LoadBlockIndexGuts (consensus_params, [this ](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED (cs_main) { return this ->InsertBlockIndex (hash); })) {
220
252
return false ;
221
253
}
222
254
223
255
// Calculate nChainWork
224
- std::vector<std::pair<int , CBlockIndex*>> vSortedByHeight;
225
- vSortedByHeight.reserve (m_block_index.size ());
226
- for (auto & [_, block_index] : m_block_index) {
227
- CBlockIndex* pindex = &block_index;
228
- vSortedByHeight.push_back (std::make_pair (pindex->nHeight , pindex));
229
- }
230
- sort (vSortedByHeight.begin (), vSortedByHeight.end ());
231
-
232
- // Find start of assumed-valid region.
233
- int first_assumed_valid_height = std::numeric_limits<int >::max ();
234
-
235
- for (const auto & [height, block] : vSortedByHeight) {
236
- if (block->IsAssumedValid ()) {
237
- auto chainstates = chainman.GetAll ();
238
-
239
- // If we encounter an assumed-valid block index entry, ensure that we have
240
- // one chainstate that tolerates assumed-valid entries and another that does
241
- // not (i.e. the background validation chainstate), since assumed-valid
242
- // entries should always be pending validation by a fully-validated chainstate.
243
- auto any_chain = [&](auto fnc) { return std::any_of (chainstates.cbegin (), chainstates.cend (), fnc); };
244
- assert (any_chain ([](auto chainstate) { return chainstate->reliesOnAssumedValid (); }));
245
- assert (any_chain ([](auto chainstate) { return !chainstate->reliesOnAssumedValid (); }));
246
-
247
- first_assumed_valid_height = height;
248
- break ;
249
- }
250
- }
256
+ std::vector<CBlockIndex*> vSortedByHeight{GetAllBlockIndices ()};
257
+ std::sort (vSortedByHeight.begin (), vSortedByHeight.end (),
258
+ CBlockIndexHeightOnlyComparator ());
251
259
252
- for (const std::pair< int , CBlockIndex*>& item : vSortedByHeight) {
260
+ for (CBlockIndex* pindex : vSortedByHeight) {
253
261
if (ShutdownRequested ()) return false ;
254
- CBlockIndex* pindex = item.second ;
255
262
pindex->nChainWork = (pindex->pprev ? pindex->pprev ->nChainWork : 0 ) + GetBlockProof (*pindex);
256
263
pindex->nTimeMax = (pindex->pprev ? std::max (pindex->pprev ->nTimeMax , pindex->nTime ) : pindex->nTime );
257
264
@@ -275,43 +282,6 @@ bool BlockManager::LoadBlockIndex(
275
282
pindex->nStatus |= BLOCK_FAILED_CHILD;
276
283
m_dirty_blockindex.insert (pindex);
277
284
}
278
- if (pindex->IsAssumedValid () ||
279
- (pindex->IsValid (BLOCK_VALID_TRANSACTIONS) &&
280
- (pindex->HaveTxsDownloaded () || pindex->pprev == nullptr ))) {
281
-
282
- // Fill each chainstate's block candidate set. Only add assumed-valid
283
- // blocks to the tip candidate set if the chainstate is allowed to rely on
284
- // assumed-valid blocks.
285
- //
286
- // If all setBlockIndexCandidates contained the assumed-valid blocks, the
287
- // background chainstate's ActivateBestChain() call would add assumed-valid
288
- // blocks to the chain (based on how FindMostWorkChain() works). Obviously
289
- // we don't want this since the purpose of the background validation chain
290
- // is to validate assued-valid blocks.
291
- //
292
- // Note: This is considering all blocks whose height is greater or equal to
293
- // the first assumed-valid block to be assumed-valid blocks, and excluding
294
- // them from the background chainstate's setBlockIndexCandidates set. This
295
- // does mean that some blocks which are not technically assumed-valid
296
- // (later blocks on a fork beginning before the first assumed-valid block)
297
- // might not get added to the background chainstate, but this is ok,
298
- // because they will still be attached to the active chainstate if they
299
- // actually contain more work.
300
- //
301
- // Instead of this height-based approach, an earlier attempt was made at
302
- // detecting "holistically" whether the block index under consideration
303
- // relied on an assumed-valid ancestor, but this proved to be too slow to
304
- // be practical.
305
- for (CChainState* chainstate : chainman.GetAll ()) {
306
- if (chainstate->reliesOnAssumedValid () ||
307
- pindex->nHeight < first_assumed_valid_height) {
308
- chainstate->setBlockIndexCandidates .insert (pindex);
309
- }
310
- }
311
- }
312
- if (pindex->nStatus & BLOCK_FAILED_MASK && (!chainman.m_best_invalid || pindex->nChainWork > chainman.m_best_invalid ->nChainWork )) {
313
- chainman.m_best_invalid = pindex;
314
- }
315
285
if (pindex->pprev ) {
316
286
pindex->BuildSkip ();
317
287
}
@@ -355,9 +325,9 @@ bool BlockManager::WriteBlockIndexDB()
355
325
return true ;
356
326
}
357
327
358
- bool BlockManager::LoadBlockIndexDB (ChainstateManager& chainman )
328
+ bool BlockManager::LoadBlockIndexDB ()
359
329
{
360
- if (!LoadBlockIndex (::Params ().GetConsensus (), chainman )) {
330
+ if (!LoadBlockIndex (::Params ().GetConsensus ())) {
361
331
return false ;
362
332
}
363
333
@@ -382,9 +352,8 @@ bool BlockManager::LoadBlockIndexDB(ChainstateManager& chainman)
382
352
LogPrintf (" Checking all blk files are present...\n " );
383
353
std::set<int > setBlkDataFiles;
384
354
for (const auto & [_, block_index] : m_block_index) {
385
- const CBlockIndex* pindex = &block_index;
386
- if (pindex->nStatus & BLOCK_HAVE_DATA) {
387
- setBlkDataFiles.insert (pindex->nFile );
355
+ if (block_index.nStatus & BLOCK_HAVE_DATA) {
356
+ setBlkDataFiles.insert (block_index.nFile );
388
357
}
389
358
}
390
359
for (std::set<int >::iterator it = setBlkDataFiles.begin (); it != setBlkDataFiles.end (); it++) {
@@ -408,13 +377,13 @@ bool BlockManager::LoadBlockIndexDB(ChainstateManager& chainman)
408
377
return true ;
409
378
}
410
379
411
- CBlockIndex* BlockManager::GetLastCheckpoint (const CCheckpointData& data)
380
+ const CBlockIndex* BlockManager::GetLastCheckpoint (const CCheckpointData& data)
412
381
{
413
382
const MapCheckpoints& checkpoints = data.mapCheckpoints ;
414
383
415
384
for (const MapCheckpoints::value_type& i : reverse_iterate (checkpoints)) {
416
385
const uint256& hash = i.second ;
417
- CBlockIndex* pindex = LookupBlockIndex (hash);
386
+ const CBlockIndex* pindex = LookupBlockIndex (hash);
418
387
if (pindex) {
419
388
return pindex;
420
389
}
0 commit comments