@@ -3426,7 +3426,7 @@ void Chainstate::TryAddBlockIndexCandidate(CBlockIndex* pindex)
3426
3426
}
3427
3427
3428
3428
/* * Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */
3429
- void Chainstate ::ReceivedBlockTransactions (const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos)
3429
+ void ChainstateManager ::ReceivedBlockTransactions (const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos)
3430
3430
{
3431
3431
AssertLockHeld (cs_main);
3432
3432
pindexNew->nTx = block.vtx .size ();
@@ -3435,7 +3435,7 @@ void Chainstate::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pin
3435
3435
pindexNew->nDataPos = pos.nPos ;
3436
3436
pindexNew->nUndoPos = 0 ;
3437
3437
pindexNew->nStatus |= BLOCK_HAVE_DATA;
3438
- if (DeploymentActiveAt (*pindexNew, m_chainman , Consensus::DEPLOYMENT_SEGWIT)) {
3438
+ if (DeploymentActiveAt (*pindexNew, * this , Consensus::DEPLOYMENT_SEGWIT)) {
3439
3439
pindexNew->nStatus |= BLOCK_OPT_WITNESS;
3440
3440
}
3441
3441
pindexNew->RaiseValidity (BLOCK_VALID_TRANSACTIONS);
@@ -3451,8 +3451,10 @@ void Chainstate::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pin
3451
3451
CBlockIndex *pindex = queue.front ();
3452
3452
queue.pop_front ();
3453
3453
pindex->nChainTx = (pindex->pprev ? pindex->pprev ->nChainTx : 0 ) + pindex->nTx ;
3454
- pindex->nSequenceId = m_chainman.nBlockSequenceId ++;
3455
- TryAddBlockIndexCandidate (pindex);
3454
+ pindex->nSequenceId = nBlockSequenceId++;
3455
+ for (Chainstate *c : GetAll ()) {
3456
+ c->TryAddBlockIndexCandidate (pindex);
3457
+ }
3456
3458
std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range = m_blockman.m_blocks_unlinked .equal_range (pindex);
3457
3459
while (range.first != range.second ) {
3458
3460
std::multimap<CBlockIndex*, CBlockIndex*>::iterator it = range.first ;
@@ -3912,7 +3914,7 @@ void ChainstateManager::ReportHeadersPresync(const arith_uint256& work, int64_t
3912
3914
}
3913
3915
3914
3916
/* * Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */
3915
- bool Chainstate ::AcceptBlock (const std::shared_ptr<const CBlock>& pblock, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested , const FlatFilePos* dbp, bool * fNewBlock , bool min_pow_checked)
3917
+ bool ChainstateManager ::AcceptBlock (const std::shared_ptr<const CBlock>& pblock, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested , const FlatFilePos* dbp, bool * fNewBlock , bool min_pow_checked)
3916
3918
{
3917
3919
const CBlock& block = *pblock;
3918
3920
@@ -3922,23 +3924,24 @@ bool Chainstate::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockV
3922
3924
CBlockIndex *pindexDummy = nullptr ;
3923
3925
CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy;
3924
3926
3925
- bool accepted_header{m_chainman. AcceptBlockHeader (block, state, &pindex, min_pow_checked)};
3926
- CheckBlockIndex ();
3927
+ bool accepted_header{AcceptBlockHeader (block, state, &pindex, min_pow_checked)};
3928
+ ActiveChainstate (). CheckBlockIndex ();
3927
3929
3928
3930
if (!accepted_header)
3929
3931
return false ;
3930
3932
3931
- // Try to process all requested blocks that we don't have, but only
3932
- // process an unrequested block if it's new and has enough work to
3933
- // advance our tip, and isn't too many blocks ahead.
3933
+ // Check all requested blocks that we do not already have for validity and
3934
+ // save them to disk. Skip processing of unrequested blocks as an anti-DoS
3935
+ // measure, unless the blocks have more work than the active chain tip, and
3936
+ // aren't too far ahead of it, so are likely to be attached soon.
3934
3937
bool fAlreadyHave = pindex->nStatus & BLOCK_HAVE_DATA;
3935
- bool fHasMoreOrSameWork = (m_chain. Tip () ? pindex->nChainWork >= m_chain. Tip ()->nChainWork : true );
3938
+ bool fHasMoreOrSameWork = (ActiveTip () ? pindex->nChainWork >= ActiveTip ()->nChainWork : true );
3936
3939
// Blocks that are too out-of-order needlessly limit the effectiveness of
3937
3940
// pruning, because pruning will not delete block files that contain any
3938
3941
// blocks which are too close in height to the tip. Apply this test
3939
3942
// regardless of whether pruning is enabled; it should generally be safe to
3940
3943
// not process unrequested blocks.
3941
- bool fTooFarAhead {pindex->nHeight > m_chain. Height () + int (MIN_BLOCKS_TO_KEEP)};
3944
+ bool fTooFarAhead {pindex->nHeight > ActiveHeight () + int (MIN_BLOCKS_TO_KEEP)};
3942
3945
3943
3946
// TODO: Decouple this function from the block download logic by removing fRequested
3944
3947
// This requires some new chain data structure to efficiently look up if a
@@ -3958,13 +3961,13 @@ bool Chainstate::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockV
3958
3961
// If our tip is behind, a peer could try to send us
3959
3962
// low-work blocks on a fake chain that we would never
3960
3963
// request; don't process these.
3961
- if (pindex->nChainWork < m_chainman. MinimumChainWork ()) return true ;
3964
+ if (pindex->nChainWork < MinimumChainWork ()) return true ;
3962
3965
}
3963
3966
3964
- const CChainParams& params{m_chainman. GetParams ()};
3967
+ const CChainParams& params{GetParams ()};
3965
3968
3966
3969
if (!CheckBlock (block, state, params.GetConsensus ()) ||
3967
- !ContextualCheckBlock (block, state, m_chainman , pindex->pprev )) {
3970
+ !ContextualCheckBlock (block, state, * this , pindex->pprev )) {
3968
3971
if (state.IsInvalid () && state.GetResult () != BlockValidationResult::BLOCK_MUTATED) {
3969
3972
pindex->nStatus |= BLOCK_FAILED_VALID;
3970
3973
m_blockman.m_dirty_blockindex .insert (pindex);
@@ -3974,7 +3977,7 @@ bool Chainstate::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockV
3974
3977
3975
3978
// Header is valid/has work, merkle tree and segwit merkle tree are good...RELAY NOW
3976
3979
// (but if it does not build on our best tip, let the SendMessages loop relay it)
3977
- if (!IsInitialBlockDownload () && m_chain. Tip () == pindex->pprev )
3980
+ if (!ActiveChainstate (). IsInitialBlockDownload () && ActiveTip () == pindex->pprev )
3978
3981
GetMainSignals ().NewPoWValidBlock (pindex, pblock);
3979
3982
3980
3983
// Write block to history file
@@ -3987,12 +3990,19 @@ bool Chainstate::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockV
3987
3990
}
3988
3991
ReceivedBlockTransactions (block, pindex, blockPos);
3989
3992
} catch (const std::runtime_error& e) {
3990
- return FatalError (m_chainman. GetNotifications (), state, std::string (" System error: " ) + e.what ());
3993
+ return FatalError (GetNotifications (), state, std::string (" System error: " ) + e.what ());
3991
3994
}
3992
3995
3993
- FlushStateToDisk (state, FlushStateMode::NONE);
3996
+ // TODO: FlushStateToDisk() handles flushing of both block and chainstate
3997
+ // data, so we should move this to ChainstateManager so that we can be more
3998
+ // intelligent about how we flush.
3999
+ // For now, since FlushStateMode::NONE is used, all that can happen is that
4000
+ // the block files may be pruned, so we can just call this on one
4001
+ // chainstate (particularly if we haven't implemented pruning with
4002
+ // background validation yet).
4003
+ ActiveChainstate ().FlushStateToDisk (state, FlushStateMode::NONE);
3994
4004
3995
- CheckBlockIndex ();
4005
+ ActiveChainstate (). CheckBlockIndex ();
3996
4006
3997
4007
return true ;
3998
4008
}
@@ -4018,7 +4028,7 @@ bool ChainstateManager::ProcessNewBlock(const std::shared_ptr<const CBlock>& blo
4018
4028
bool ret = CheckBlock (*block, state, GetConsensus ());
4019
4029
if (ret) {
4020
4030
// Store to disk
4021
- ret = ActiveChainstate (). AcceptBlock (block, state, &pindex, force_processing, nullptr , new_block, min_pow_checked);
4031
+ ret = AcceptBlock (block, state, &pindex, force_processing, nullptr , new_block, min_pow_checked);
4022
4032
}
4023
4033
if (!ret) {
4024
4034
GetMainSignals ().BlockChecked (*block, state);
@@ -4507,26 +4517,24 @@ bool Chainstate::LoadGenesisBlock()
4507
4517
return error (" %s: writing genesis block to disk failed" , __func__);
4508
4518
}
4509
4519
CBlockIndex* pindex = m_blockman.AddToBlockIndex (block, m_chainman.m_best_header );
4510
- ReceivedBlockTransactions (block, pindex, blockPos);
4520
+ m_chainman. ReceivedBlockTransactions (block, pindex, blockPos);
4511
4521
} catch (const std::runtime_error& e) {
4512
4522
return error (" %s: failed to write genesis block: %s" , __func__, e.what ());
4513
4523
}
4514
4524
4515
4525
return true ;
4516
4526
}
4517
4527
4518
- void Chainstate ::LoadExternalBlockFile (
4528
+ void ChainstateManager ::LoadExternalBlockFile (
4519
4529
FILE* fileIn,
4520
4530
FlatFilePos* dbp,
4521
4531
std::multimap<uint256, FlatFilePos>* blocks_with_unknown_parent)
4522
4532
{
4523
- AssertLockNotHeld (m_chainstate_mutex);
4524
-
4525
4533
// Either both should be specified (-reindex), or neither (-loadblock).
4526
4534
assert (!dbp == !blocks_with_unknown_parent);
4527
4535
4528
4536
const auto start{SteadyClock::now ()};
4529
- const CChainParams& params{m_chainman. GetParams ()};
4537
+ const CChainParams& params{GetParams ()};
4530
4538
4531
4539
int nLoaded = 0 ;
4532
4540
try {
@@ -4536,7 +4544,7 @@ void Chainstate::LoadExternalBlockFile(
4536
4544
// such as a block fails to deserialize.
4537
4545
uint64_t nRewind = blkdat.GetPos ();
4538
4546
while (!blkdat.eof ()) {
4539
- if (m_chainman. m_interrupt ) return ;
4547
+ if (m_interrupt) return ;
4540
4548
4541
4549
blkdat.SetPos (nRewind);
4542
4550
nRewind++; // start one byte further next time, in case of failure
@@ -4611,8 +4619,15 @@ void Chainstate::LoadExternalBlockFile(
4611
4619
4612
4620
// Activate the genesis block so normal node progress can continue
4613
4621
if (hash == params.GetConsensus ().hashGenesisBlock ) {
4614
- BlockValidationState state;
4615
- if (!ActivateBestChain (state, nullptr )) {
4622
+ bool genesis_activation_failure = false ;
4623
+ for (auto c : GetAll ()) {
4624
+ BlockValidationState state;
4625
+ if (!c->ActivateBestChain (state, nullptr )) {
4626
+ genesis_activation_failure = true ;
4627
+ break ;
4628
+ }
4629
+ }
4630
+ if (genesis_activation_failure) {
4616
4631
break ;
4617
4632
}
4618
4633
}
@@ -4625,14 +4640,21 @@ void Chainstate::LoadExternalBlockFile(
4625
4640
// until after all of the block files are loaded. ActivateBestChain can be
4626
4641
// called by concurrent network message processing. but, that is not
4627
4642
// reliable for the purpose of pruning while importing.
4628
- BlockValidationState state;
4629
- if (!ActivateBestChain (state, pblock)) {
4630
- LogPrint (BCLog::REINDEX, " failed to activate chain (%s)\n " , state.ToString ());
4643
+ bool activation_failure = false ;
4644
+ for (auto c : GetAll ()) {
4645
+ BlockValidationState state;
4646
+ if (!c->ActivateBestChain (state, pblock)) {
4647
+ LogPrint (BCLog::REINDEX, " failed to activate chain (%s)\n " , state.ToString ());
4648
+ activation_failure = true ;
4649
+ break ;
4650
+ }
4651
+ }
4652
+ if (activation_failure) {
4631
4653
break ;
4632
4654
}
4633
4655
}
4634
4656
4635
- NotifyHeaderTip (* this );
4657
+ NotifyHeaderTip (ActiveChainstate () );
4636
4658
4637
4659
if (!blocks_with_unknown_parent) continue ;
4638
4660
@@ -4658,7 +4680,7 @@ void Chainstate::LoadExternalBlockFile(
4658
4680
}
4659
4681
range.first ++;
4660
4682
blocks_with_unknown_parent->erase (it);
4661
- NotifyHeaderTip (* this );
4683
+ NotifyHeaderTip (ActiveChainstate () );
4662
4684
}
4663
4685
}
4664
4686
} catch (const std::exception& e) {
@@ -4677,7 +4699,7 @@ void Chainstate::LoadExternalBlockFile(
4677
4699
}
4678
4700
}
4679
4701
} catch (const std::runtime_error& e) {
4680
- m_chainman. GetNotifications ().fatalError (std::string (" System error: " ) + e.what ());
4702
+ GetNotifications ().fatalError (std::string (" System error: " ) + e.what ());
4681
4703
}
4682
4704
LogPrintf (" Loaded %i blocks from external file in %dms\n " , nLoaded, Ticks<std::chrono::milliseconds>(SteadyClock::now () - start));
4683
4705
}
0 commit comments