zebrad: check state in obtaintips, not extendtips.
The original sync algorithm split the sync process into two phases, one that obtained prospective chain tips, and another that attempted to extend those chain tips as far as possible until encountering an error (at which point the prospective state is discarded and the process restarts). Because a previous implementation of this algorithm didn't properly enforce linkage between segments of the chain while extending tips, sometimes it would get confused and fail to discard responses that did not extend a tip. To mitigate this, a check against the state was added. However, this check can cause stalls while checkpointing, because when a checkpoint is reached we may suddenly need to commit thousands of blocks to the state. Because the sync algorithm now has a a `CheckedTip` structure that ensures that a new segment of hashes actually extends an existing one, we don't need to check against the state while extending a tip, because we don't get confused while interpreting responses. This change results in significantly smoother progress on mainnet.
This commit is contained in:
parent
65e0c22fbe
commit
0a405c737d
|
@ -368,8 +368,14 @@ where
|
|||
|
||||
tracing::debug!(?self.prospective_tips);
|
||||
|
||||
self.request_blocks(download_set.into_iter().collect())
|
||||
.await?;
|
||||
// Check that the new tips we got are actually unknown.
|
||||
for hash in &download_set {
|
||||
tracing::debug!(?hash, "checking if state contains hash");
|
||||
if self.state_contains(*hash).await? {
|
||||
return Err(eyre!("queued download of hash behind our chain tip"));
|
||||
}
|
||||
}
|
||||
self.request_blocks(download_set).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -488,8 +494,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
self.request_blocks(download_set.into_iter().collect())
|
||||
.await?;
|
||||
self.request_blocks(download_set).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -521,16 +526,9 @@ where
|
|||
}
|
||||
|
||||
/// Queue download and verify tasks for each block that isn't currently known to our node
|
||||
async fn request_blocks(&mut self, hashes: Vec<block::Hash>) -> Result<(), Report> {
|
||||
async fn request_blocks(&mut self, hashes: HashSet<block::Hash>) -> Result<(), Report> {
|
||||
tracing::debug!(hashes.len = hashes.len(), "requesting blocks");
|
||||
for hash in hashes.into_iter() {
|
||||
// If we've queued the download of a hash behind our current chain tip,
|
||||
// we've been given bad responses by our peers. Abort the sync and restart.
|
||||
tracing::debug!(?hash, "checking if state contains hash");
|
||||
if self.state_contains(hash).await? {
|
||||
return Err(eyre!("queued download of hash behind our chain tip"));
|
||||
}
|
||||
|
||||
self.downloads
|
||||
.download_and_verify(hash)
|
||||
.await
|
||||
|
|
Loading…
Reference in New Issue