@@ -4474,6 +4474,9 @@ void Chainstate::LoadExternalBlockFile(
44744474 // next block, but it's still possible to rewind to the start of the current block (without a disk read).
44754475 nRewind = nBlockPos + nSize;
44764476 blkdat.SkipTo (nRewind);
4477+
4478+ std::shared_ptr<CBlock> pblock{}; // needs to remain available after the cs_main lock is released to avoid duplicate reads from disk
4479+
44774480 {
44784481 LOCK (cs_main);
44794482 // detect out of order blocks, and store them for later
@@ -4491,7 +4494,7 @@ void Chainstate::LoadExternalBlockFile(
44914494 if (!pindex || (pindex->nStatus & BLOCK_HAVE_DATA) == 0 ) {
44924495 // This block can be processed immediately; rewind to its start, read and deserialize it.
44934496 blkdat.SetPos (nBlockPos);
4494- std::shared_ptr<CBlock> pblock{ std::make_shared<CBlock>()} ;
4497+ pblock = std::make_shared<CBlock>();
44954498 blkdat >> *pblock;
44964499 nRewind = blkdat.GetPos ();
44974500
@@ -4515,6 +4518,21 @@ void Chainstate::LoadExternalBlockFile(
45154518 }
45164519 }
45174520
4521+ if (m_blockman.IsPruneMode () && !fReindex && pblock) {
4522+ // must update the tip for pruning to work while importing with -loadblock.
4523+ // this is a tradeoff to conserve disk space at the expense of time
4524+ // spent updating the tip to be able to prune.
4525+ // otherwise, ActivateBestChain won't be called by the import process
4526+ // until after all of the block files are loaded. ActivateBestChain can be
4527+ // called by concurrent network message processing. but, that is not
4528+ // reliable for the purpose of pruning while importing.
4529+ BlockValidationState state;
4530+ if (!ActivateBestChain (state, pblock)) {
4531+ LogPrint (BCLog::REINDEX, " failed to activate chain (%s)\n " , state.ToString ());
4532+ break ;
4533+ }
4534+ }
4535+
45184536 NotifyHeaderTip (*this );
45194537
45204538 if (!blocks_with_unknown_parent) continue ;
0 commit comments