From 348da86debcd47bd90b5172f4a1e08df77cf5016 Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Wed, 3 Jun 2026 14:19:27 +0800 Subject: [PATCH] fix: make validated block cache bounded --- src/chain/store/chain_store.rs | 22 +++++++++++++--------- src/chain_sync/chain_follower.rs | 6 +----- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/chain/store/chain_store.rs b/src/chain/store/chain_store.rs index d81a57b6c6d..975628394ea 100644 --- a/src/chain/store/chain_store.rs +++ b/src/chain/store/chain_store.rs @@ -27,11 +27,11 @@ use crate::{ interpreter::{BlockMessages, VMTrace}, rpc::chain::PathChanges, }; -use ahash::{HashMap, HashSet}; +use ahash::HashMap; use fil_actors_shared::fvm_ipld_amt::Amtv0 as Amt; use fvm_ipld_encoding::CborStore; use nonzero_ext::nonzero; -use parking_lot::{Mutex, RwLock}; +use parking_lot::RwLock; use serde::{Serialize, de::DeserializeOwned}; use std::{ num::NonZeroUsize, @@ -43,6 +43,9 @@ use tracing::{debug, error, trace, warn}; // A cap on the size of the future_sink const SINK_CAP: usize = 200; +// Assume a tipset has 5 blocks on average, we cache 1-day-worth of validated blocks. (5 * 2 * 60 * 24 = 14400) +const VALIDATED_BLOCKS_CACHE_SIZE: NonZeroUsize = nonzero!(14400usize); + /// Disambiguate the type to signify that we are expecting a delta and not an actual epoch/height /// while maintaining the same type. pub type ChainEpochDelta = ChainEpoch; @@ -78,7 +81,7 @@ pub struct ChainStore { genesis_block_header: Arc, /// validated blocks - pub(crate) validated_blocks: Arc>>, + pub(crate) validated_blocks: SizeTrackingCache, /// Needed by the Ethereum mapping. chain_config: Arc, @@ -148,7 +151,10 @@ impl ChainStore { f3_finalized_tipset, ec_calculator_finalized_epoch, genesis_block_header: genesis_block_header.into(), - validated_blocks: Default::default(), + validated_blocks: SizeTrackingCache::new_with_metrics( + "validated_blocks", + VALIDATED_BLOCKS_CACHE_SIZE, + ), chain_config, messages_in_tipset_cache: Default::default(), }) @@ -341,7 +347,7 @@ impl ChainStore { /// Checks metadata file if block has already been validated. pub fn is_block_validated(&self, cid: &Cid) -> bool { - let validated = self.validated_blocks.lock().contains(cid); + let validated = self.validated_blocks.get(cid).is_some(); if validated { trace!("Block {cid} was previously validated"); } @@ -350,13 +356,11 @@ impl ChainStore { /// Marks block as validated in the metadata file. pub fn mark_block_as_validated(&self, cid: &Cid) { - let mut file = self.validated_blocks.lock(); - file.insert(*cid); + self.validated_blocks.insert((*cid).into(), ()); } pub fn unmark_block_as_validated(&self, cid: &Cid) { - let mut file = self.validated_blocks.lock(); - let _did_work = file.remove(cid); + self.validated_blocks.remove(cid); } /// Retrieves ordered valid messages from a `Tipset`. This will only include diff --git a/src/chain_sync/chain_follower.rs b/src/chain_sync/chain_follower.rs index a9a854a75b6..4233145c7af 100644 --- a/src/chain_sync/chain_follower.rs +++ b/src/chain_sync/chain_follower.rs @@ -153,11 +153,7 @@ impl ChainFollower { pub fn reset(&self) { let start = Instant::now(); self.tasks.lock().clear(); - self.state_manager - .chain_store() - .validated_blocks - .lock() - .clear(); + self.state_manager.chain_store().validated_blocks.clear(); self.state_machine.lock().tipsets.clear(); if let Some(bad_blocks) = &self.bad_blocks { bad_blocks.clear();