Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@

### Fixed

- [#6241](https://github.com/ChainSafe/forest/pull/6241) Fixed a sync issue that is caused by time traveling block(s).

## Forest v0.30.3 "Trishul"

This is a non-mandatory release that brings important enhancements in Forest's tooling capabilities.
Expand Down
1 change: 1 addition & 0 deletions src/chain_sync/bad_block_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ impl BadBlockCache {

pub fn push(&self, c: Cid) {
self.cache.push(c.into(), ());
tracing::warn!("Marked bad block: {c}");
}

/// Returns `Some` if the block CID is in bad block cache.
Expand Down
21 changes: 11 additions & 10 deletions src/chain_sync/chain_follower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ pub async fn chain_follower<DB: Blockstore + Sync + Send + 'static>(
let state_machine = state_machine.clone();
let state_changed = state_changed.clone();
let tasks = tasks.clone();
let bad_block_cache = bad_block_cache.clone();
async move {
loop {
state_changed.notified().await;
Expand All @@ -256,6 +257,7 @@ pub async fn chain_follower<DB: Blockstore + Sync + Send + 'static>(
network.clone(),
state_manager.clone(),
stateless_mode,
bad_block_cache.clone(),
);
tokio::spawn({
let state_machine = state_machine.clone();
Expand Down Expand Up @@ -679,16 +681,8 @@ impl<DB: Blockstore> SyncStateMachine<DB> {
// Remove all bad tipsets from the tipset map.
fn mark_bad_tipset(&mut self, tipset: Arc<FullTipset>) {
let mut stack = vec![tipset];

while let Some(tipset) = stack.pop() {
self.tipsets.remove(tipset.key());
// Mark all blocks in the tipset as bad
if let Some(bad_block_cache) = &self.bad_block_cache {
for block in tipset.blocks() {
bad_block_cache.push(*block.cid());
}
}

// Find all descendant tipsets (tipsets that have this tipset as a parent)
let mut to_remove = Vec::new();
let mut descendants = Vec::new();
Expand Down Expand Up @@ -837,6 +831,7 @@ impl SyncTask {
network: SyncNetworkContext<DB>,
state_manager: Arc<StateManager<DB>>,
stateless_mode: bool,
bad_block_cache: Option<Arc<BadBlockCache>>,
) -> Option<SyncEvent> {
tracing::trace!("SyncTask::execute {self}");
let cs = state_manager.chain_store();
Expand All @@ -853,8 +848,14 @@ impl SyncTask {
is_proposed_head,
} => {
let genesis = cs.genesis_tipset();
match validate_tipset(state_manager.clone(), cs, tipset.deref().clone(), &genesis)
.await
match validate_tipset(
state_manager.clone(),
cs,
tipset.deref().clone(),
&genesis,
bad_block_cache,
)
.await
{
Ok(()) => Some(SyncEvent::ValidatedTipset {
tipset,
Expand Down
20 changes: 14 additions & 6 deletions src/chain_sync/tipset_syncer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use std::sync::Arc;

use crate::chain_sync::BadBlockCache;
use crate::networks::Height;
use crate::shim::clock::ALLOWABLE_CLOCK_DRIFT;
use crate::shim::crypto::SignatureType;
Expand Down Expand Up @@ -101,6 +102,7 @@ pub async fn validate_tipset<DB: Blockstore + Send + Sync + 'static>(
chainstore: &ChainStore<DB>,
full_tipset: FullTipset,
genesis: &Tipset,
bad_block_cache: Option<Arc<BadBlockCache>>,
) -> Result<(), TipsetSyncerError> {
if full_tipset.key().eq(genesis.key()) {
trace!("Skipping genesis tipset validation");
Expand All @@ -124,12 +126,18 @@ pub async fn validate_tipset<DB: Blockstore + Send + Sync + 'static>(
chainstore.add_to_tipset_tracker(block.header());
}
Err((cid, why)) => {
warn!(
"Validating block [CID = {}] in EPOCH = {} failed: {}",
cid.clone(),
epoch,
why
);
warn!("Validating block [CID = {cid}] in EPOCH = {epoch} failed: {why}");
match &why {
TipsetSyncerError::TimeTravellingBlock(_, _) => {
// Do not mark a block as bad for temporary errors.
// See <https://github.com/filecoin-project/lotus/blob/v1.34.1/chain/sync.go#L602> in Lotus
}
_ => {
if let Some(bad_block_cache) = bad_block_cache {
bad_block_cache.push(cid);
}
}
};
return Err(why);
}
}
Expand Down
Loading