mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-14 12:43:40 +02:00
Fix elements multiple-header-download issue.
This fixes an issue which causes Elements to download the blockchain headers multiple times during initial block download. In particular: each time we receive an INV P2P message with a new block (about once a minute), we start downloading the headers, again, in parallel with any existing download(s) in progress. With this change, after we receive each batch of headers, we check whether any of the headers in it were new to us. If not (they were all duplicates), we stop there, and do not ask the peer for another batch. This reduces the maximum amount of duplication to about 2x, which is not ideal, but a HUGE improvement.
This commit is contained in:
parent
04cedf3f6b
commit
cdfb4c9c6c
3 changed files with 23 additions and 7 deletions
|
|
@ -4036,16 +4036,22 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex)
|
||||
bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool* duplicate)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
// Check for duplicate
|
||||
uint256 hash = block.GetHash();
|
||||
BlockMap::iterator miSelf = m_block_index.find(hash);
|
||||
CBlockIndex *pindex = nullptr;
|
||||
if (duplicate) {
|
||||
*duplicate = false;
|
||||
}
|
||||
if (hash != chainparams.GetConsensus().hashGenesisBlock) {
|
||||
if (miSelf != m_block_index.end()) {
|
||||
// Block header is already known.
|
||||
if (duplicate) {
|
||||
*duplicate = true;
|
||||
}
|
||||
pindex = miSelf->second;
|
||||
if (ppindex)
|
||||
*ppindex = pindex;
|
||||
|
|
@ -4125,17 +4131,24 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationS
|
|||
}
|
||||
|
||||
// Exposed wrapper for AcceptBlockHeader
|
||||
bool ChainstateManager::ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, BlockValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex)
|
||||
bool ChainstateManager::ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, BlockValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex, bool* all_duplicate)
|
||||
{
|
||||
AssertLockNotHeld(cs_main);
|
||||
{
|
||||
LOCK(cs_main);
|
||||
if (all_duplicate) {
|
||||
*all_duplicate = true;
|
||||
}
|
||||
bool duplicate = false;
|
||||
for (const CBlockHeader& header : headers) {
|
||||
CBlockIndex *pindex = nullptr; // Use a temp pindex instead of ppindex to avoid a const_cast
|
||||
bool accepted = m_blockman.AcceptBlockHeader(
|
||||
header, state, chainparams, &pindex);
|
||||
header, state, chainparams, &pindex, &duplicate);
|
||||
::ChainstateActive().CheckBlockIndex(chainparams.GetConsensus());
|
||||
|
||||
if (all_duplicate) {
|
||||
(*all_duplicate) &= duplicate; // False if any are false
|
||||
}
|
||||
if (!accepted) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue