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