Skip to content

Commit be0d0db

Browse files
authored
refactor: no Arc wrapper around ChainIndex and ZstdFrameCache (#6889)
1 parent b7d0075 commit be0d0db

36 files changed

Lines changed: 314 additions & 187 deletions

File tree

src/blocks/tipset.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::{
1313
networks::{calibnet, mainnet},
1414
shim::clock::ChainEpoch,
1515
utils::{
16+
ShallowClone,
1617
cid::CidCborExt,
1718
db::{CborStoreExt, car_stream::CarBlock},
1819
get_size::nunny_vec_heap_size_helper,
@@ -195,6 +196,15 @@ pub struct Tipset {
195196
key: Arc<OnceLock<TipsetKey>>,
196197
}
197198

199+
impl ShallowClone for Tipset {
200+
fn shallow_clone(&self) -> Self {
201+
Self {
202+
headers: self.headers.shallow_clone(),
203+
key: self.key.shallow_clone(),
204+
}
205+
}
206+
}
207+
198208
impl From<RawBlockHeader> for Tipset {
199209
fn from(value: RawBlockHeader) -> Self {
200210
Self::from(CachingBlockHeader::from(value))

src/chain/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::cid_collections::CidHashSet;
1515
use crate::db::car::forest::{self, ForestCarFrame, finalize_frame};
1616
use crate::db::{SettingsStore, SettingsStoreExt};
1717
use crate::ipld::stream_chain;
18+
use crate::utils::ShallowClone as _;
1819
use crate::utils::db::car_stream::{CarBlock, CarBlockWrite};
1920
use crate::utils::io::{AsyncWriterWithChecksum, Checksum};
2021
use crate::utils::multihash::MultihashCode;
@@ -167,8 +168,8 @@ async fn export_to_forest_car<D: Digest>(
167168
// block size is between 1kb and 2kb.
168169
1024,
169170
stream_chain(
170-
Arc::clone(db),
171-
tipset.clone().chain_owned(Arc::clone(db)),
171+
db.shallow_clone(),
172+
tipset.shallow_clone().chain_owned(db.shallow_clone()),
172173
stateroot_lookup_limit,
173174
)
174175
.with_seen(seen)

src/chain/store/chain_store.rs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::networks::{ChainConfig, Height};
1111
use crate::rpc::eth::{eth_tx_from_signed_eth_message, types::EthHash};
1212
use crate::shim::clock::ChainEpoch;
1313
use crate::shim::{executor::Receipt, message::Message, version::NetworkVersion};
14+
use crate::utils::ShallowClone;
1415
use crate::utils::db::{BlockstoreExt, CborStoreExt};
1516
use crate::{
1617
blocks::{CachingBlockHeader, Tipset, TipsetKey, TxMeta},
@@ -76,7 +77,7 @@ pub struct ChainStore<DB> {
7677
f3_finalized_tipset: Arc<RwLock<Option<Tipset>>>,
7778

7879
/// Used as a cache for tipset `lookbacks`.
79-
chain_index: Arc<ChainIndex<Arc<DB>>>,
80+
chain_index: ChainIndex<DB>,
8081

8182
/// Tracks blocks for the purpose of forming tipsets.
8283
tipset_tracker: TipsetTracker<DB>,
@@ -144,22 +145,20 @@ where
144145
};
145146
let heaviest_tipset = Arc::new(RwLock::new(head));
146147
let f3_finalized_tipset: Arc<RwLock<Option<Tipset>>> = Default::default();
147-
let chain_index = Arc::new(
148-
ChainIndex::new(db.clone()).with_is_tipset_finalized(Box::new({
149-
let chain_finality = chain_config.policy.chain_finality;
150-
let heaviest_tipset = heaviest_tipset.clone();
151-
let f3_finalized_tipset = f3_finalized_tipset.clone();
152-
move |ts| {
153-
let finalized = f3_finalized_tipset
154-
.read()
155-
.as_ref()
156-
.map(|ts| ts.epoch())
157-
.unwrap_or_default()
158-
.max(heaviest_tipset.read().epoch() - chain_finality);
159-
ts.epoch() <= finalized
160-
}
161-
})),
162-
);
148+
let chain_index = ChainIndex::new(db.clone()).with_is_tipset_finalized(Arc::new({
149+
let chain_finality = chain_config.policy.chain_finality;
150+
let heaviest_tipset = heaviest_tipset.clone();
151+
let f3_finalized_tipset = f3_finalized_tipset.clone();
152+
move |ts| {
153+
let finalized = f3_finalized_tipset
154+
.read()
155+
.as_ref()
156+
.map(|ts| ts.epoch())
157+
.unwrap_or_default()
158+
.max(heaviest_tipset.read().epoch() - chain_finality);
159+
ts.epoch() <= finalized
160+
}
161+
}));
163162
let cs = Self {
164163
head_changes_tx: publisher,
165164
chain_index,
@@ -290,7 +289,7 @@ where
290289
}
291290

292291
/// Returns the chain index
293-
pub fn chain_index(&self) -> &Arc<ChainIndex<Arc<DB>>> {
292+
pub fn chain_index(&self) -> &ChainIndex<DB> {
294293
&self.chain_index
295294
}
296295

@@ -393,7 +392,7 @@ where
393392
/// is usually 900. The `heaviest_tipset` is a reference point in the
394393
/// blockchain. It must be a child of the look-back tipset.
395394
pub fn get_lookback_tipset_for_round(
396-
chain_index: &Arc<ChainIndex<Arc<DB>>>,
395+
chain_index: &ChainIndex<DB>,
397396
chain_config: &Arc<ChainConfig>,
398397
heaviest_tipset: &Tipset,
399398
round: ChainEpoch,
@@ -417,8 +416,8 @@ where
417416
let beacon = Arc::new(chain_config.get_beacon_schedule(genesis_timestamp));
418417
let ExecutedTipset { state_root, .. } = crate::state_manager::apply_block_messages(
419418
genesis_timestamp,
420-
Arc::clone(chain_index),
421-
Arc::clone(chain_config),
419+
chain_index.shallow_clone(),
420+
chain_config.shallow_clone(),
422421
beacon,
423422
// Using shared WASM engine here as creating new WASM engines is expensive
424423
// (takes seconds to minutes). It's only acceptable here because this situation is

src/chain/store/index.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
// Copyright 2019-2026 ChainSafe Systems
22
// SPDX-License-Identifier: Apache-2.0, MIT
33

4-
use std::num::NonZeroUsize;
4+
use std::{num::NonZeroUsize, sync::Arc};
55

66
use crate::beacon::{BeaconEntry, IGNORE_DRAND};
77
use crate::blocks::{Tipset, TipsetKey};
88
use crate::chain::Error;
99
use crate::metrics;
1010
use crate::shim::clock::ChainEpoch;
11+
use crate::utils::ShallowClone;
1112
use crate::utils::cache::SizeTrackingLruCache;
1213
use fvm_ipld_blockstore::Blockstore;
1314
use itertools::Itertools;
@@ -20,7 +21,7 @@ type TipsetCache = SizeTrackingLruCache<TipsetKey, Tipset>;
2021

2122
type TipsetHeightCache = SizeTrackingLruCache<ChainEpoch, TipsetKey>;
2223

23-
type IsTipsetFinalizedFn = Box<dyn Fn(&Tipset) -> bool + Send + Sync>;
24+
type IsTipsetFinalizedFn = Arc<dyn Fn(&Tipset) -> bool + Send + Sync>;
2425

2526
/// Keeps look-back tipsets in cache at a given interval `skip_length` and can
2627
/// be used to look-back at the chain to retrieve an old tipset.
@@ -30,11 +31,22 @@ pub struct ChainIndex<DB> {
3031
/// epoch to tipset key mappings.
3132
ts_height_cache: TipsetHeightCache,
3233
/// `Blockstore` pointer needed to load tipsets from cold storage.
33-
db: DB,
34+
db: Arc<DB>,
3435
/// check whether a tipset is finalized
3536
is_tipset_finalized: Option<IsTipsetFinalizedFn>,
3637
}
3738

39+
impl<DB> ShallowClone for ChainIndex<DB> {
40+
fn shallow_clone(&self) -> Self {
41+
Self {
42+
ts_cache: self.ts_cache.shallow_clone(),
43+
ts_height_cache: self.ts_height_cache.shallow_clone(),
44+
db: self.db.shallow_clone(),
45+
is_tipset_finalized: self.is_tipset_finalized.clone(),
46+
}
47+
}
48+
}
49+
3850
#[derive(Debug, Clone, Copy)]
3951
/// Methods for resolving fetches of null tipsets.
4052
/// Imagine epoch 10 is null but epoch 9 and 11 exist. If epoch we request epoch
@@ -45,7 +57,7 @@ pub enum ResolveNullTipset {
4557
}
4658

4759
impl<DB: Blockstore> ChainIndex<DB> {
48-
pub fn new(db: DB) -> Self {
60+
pub fn new(db: Arc<DB>) -> Self {
4961
let ts_cache =
5062
SizeTrackingLruCache::new_with_metrics("tipset".into(), DEFAULT_TIPSET_CACHE_SIZE);
5163
let ts_height_cache: SizeTrackingLruCache<ChainEpoch, TipsetKey> =
@@ -68,7 +80,7 @@ impl<DB: Blockstore> ChainIndex<DB> {
6880
self
6981
}
7082

71-
pub fn db(&self) -> &DB {
83+
pub fn db(&self) -> &Arc<DB> {
7284
&self.db
7385
}
7486

src/chain_sync/bad_block_cache.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::num::NonZeroUsize;
66
use cid::Cid;
77
use nonzero_ext::nonzero;
88

9-
use crate::utils::{cache::SizeTrackingLruCache, get_size};
9+
use crate::utils::{ShallowClone, cache::SizeTrackingLruCache, get_size};
1010

1111
/// Default capacity for CID caches (32768 entries).
1212
/// That's about 4 MiB.
@@ -47,11 +47,19 @@ impl BadBlockCache {
4747

4848
/// Thread-safe LRU cache for tracking recently seen gossip block CIDs.
4949
/// Used to de-duplicate gossip blocks before expensive message fetching.
50-
#[derive(Debug, Clone)]
50+
#[derive(Debug)]
5151
pub struct SeenBlockCache {
5252
cache: SizeTrackingLruCache<get_size::CidWrapper, ()>,
5353
}
5454

55+
impl ShallowClone for SeenBlockCache {
56+
fn shallow_clone(&self) -> Self {
57+
Self {
58+
cache: self.cache.shallow_clone(),
59+
}
60+
}
61+
}
62+
5563
impl Default for SeenBlockCache {
5664
fn default() -> Self {
5765
Self::new(DEFAULT_CID_CACHE_CAPACITY)

src/chain_sync/chain_follower.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use crate::{
3232
networks::calculate_expected_epoch,
3333
shim::clock::ChainEpoch,
3434
state_manager::StateManager,
35+
utils::ShallowClone as _,
3536
};
3637
use ahash::{HashMap, HashSet};
3738
use chrono::Utc;
@@ -153,12 +154,12 @@ pub async fn chain_follower<DB: Blockstore + Sync + Send + 'static>(
153154

154155
// Increment metrics, update peer information, and forward tipsets to the state machine.
155156
set.spawn({
156-
let state_manager = state_manager.clone();
157-
let state_changed = state_changed.clone();
158-
let state_machine = state_machine.clone();
159-
let network = network.clone();
160-
let bad_block_cache = bad_block_cache.clone();
161-
let seen_block_cache = seen_block_cache.clone();
157+
let state_manager = state_manager.shallow_clone();
158+
let state_changed = state_changed.shallow_clone();
159+
let state_machine = state_machine.shallow_clone();
160+
let network = network.shallow_clone();
161+
let bad_block_cache = bad_block_cache.shallow_clone();
162+
let seen_block_cache = seen_block_cache.shallow_clone();
162163
async move {
163164
while let Ok(event) = network_rx.recv_async().await {
164165
inc_gossipsub_event_metrics(&event);
@@ -272,10 +273,10 @@ pub async fn chain_follower<DB: Blockstore + Sync + Send + 'static>(
272273
let new = tasks_set.insert(task.clone());
273274
if new {
274275
let action = task.clone().execute(
275-
network.clone(),
276-
state_manager.clone(),
276+
network.shallow_clone(),
277+
state_manager.shallow_clone(),
277278
stateless_mode,
278-
bad_block_cache.clone(),
279+
bad_block_cache.shallow_clone(),
279280
);
280281
tokio::spawn({
281282
let tasks = tasks.clone();
@@ -389,7 +390,7 @@ fn update_peer_info<DB: Blockstore + Sync + Send + 'static>(
389390
let genesis_cid = *genesis.block_headers().first().cid();
390391
// Spawn and immediately move on to the next event
391392
tokio::task::spawn(handle_peer_connected_event(
392-
network.clone(),
393+
network.shallow_clone(),
393394
chain_store,
394395
*peer_id,
395396
genesis_cid,

src/chain_sync/network_context.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use crate::{
2222
rpc::RequestResponseError,
2323
},
2424
utils::{
25+
ShallowClone,
2526
misc::{AdaptiveValueProvider, ExponentialAdaptiveValueProvider},
2627
stats::Stats,
2728
},
@@ -66,12 +67,12 @@ pub struct SyncNetworkContext<DB> {
6667
db: Arc<DB>,
6768
}
6869

69-
impl<DB> Clone for SyncNetworkContext<DB> {
70-
fn clone(&self) -> Self {
70+
impl<DB> ShallowClone for SyncNetworkContext<DB> {
71+
fn shallow_clone(&self) -> Self {
7172
Self {
7273
network_send: self.network_send.clone(),
73-
peer_manager: self.peer_manager.clone(),
74-
db: self.db.clone(),
74+
peer_manager: self.peer_manager.shallow_clone(),
75+
db: self.db.shallow_clone(),
7576
}
7677
}
7778
}

src/chain_sync/tipset_syncer.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::shim::{
1313
};
1414
use crate::state_manager::ExecutedTipset;
1515
use crate::state_manager::{Error as StateManagerError, StateManager, utils::is_valid_for_sending};
16+
use crate::utils::ShallowClone as _;
1617
use crate::{
1718
blocks::{Block, CachingBlockHeader, Error as ForestBlockError, FullTipset, Tipset},
1819
fil_cns::{self, FilecoinConsensus, FilecoinConsensusError},
@@ -224,17 +225,17 @@ async fn validate_block<DB: Blockstore + Sync + Send + 'static>(
224225

225226
// Check block messages
226227
validations.spawn(check_block_messages(
227-
state_manager.clone(),
228-
block.clone(),
229-
base_tipset.clone(),
228+
state_manager.shallow_clone(),
229+
block.shallow_clone(),
230+
base_tipset.shallow_clone(),
230231
));
231232

232233
// Base fee check
233234
validations.spawn_blocking({
234235
let smoke_height = state_manager.chain_config().epoch(Height::Smoke);
235-
let base_tipset = base_tipset.clone();
236+
let base_tipset = base_tipset.shallow_clone();
236237
let block_store = state_manager.blockstore_owned();
237-
let block = Arc::clone(&block);
238+
let block = block.shallow_clone();
238239
move || {
239240
let base_fee = crate::chain::compute_base_fee(&block_store, &base_tipset, smoke_height)
240241
.map_err(|e| {
@@ -253,7 +254,7 @@ async fn validate_block<DB: Blockstore + Sync + Send + 'static>(
253254
// Parent weight calculation check
254255
validations.spawn_blocking({
255256
let block_store = state_manager.blockstore_owned();
256-
let base_tipset = base_tipset.clone();
257+
let base_tipset = base_tipset.shallow_clone();
257258
let weight = header.weight.clone();
258259
move || {
259260
let calc_weight = fil_cns::weight(&block_store, &base_tipset).map_err(|e| {

src/cli/subcommands/chain_cmd/list.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::{
1717
},
1818
},
1919
shim::econ::{BLOCK_GAS_LIMIT, TokenAmount},
20+
utils::ShallowClone as _,
2021
};
2122

2223
/// View a segment of the chain
@@ -43,7 +44,7 @@ impl ChainListCommand {
4344
};
4445
let mut tipsets = Vec::with_capacity(count);
4546
loop {
46-
tipsets.push(ts.clone());
47+
tipsets.push(ts.shallow_clone());
4748
if ts.epoch() == 0 || tipsets.len() >= count {
4849
break;
4950
}

src/daemon/db_util.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::networks::ChainConfig;
1010
use crate::rpc::sync::SnapshotProgressTracker;
1111
use crate::shim::clock::ChainEpoch;
1212
use crate::state_manager::StateManager;
13+
use crate::utils::ShallowClone as _;
1314
use crate::utils::db::car_stream::CarStream;
1415
use crate::utils::io::EitherMmapOrRandomAccessFile;
1516
use crate::utils::net::{DownloadFileOption, download_to};
@@ -390,7 +391,7 @@ where
390391
match spec {
391392
RangeSpec::To(to_epoch) => {
392393
for ts in head_ts
393-
.clone()
394+
.shallow_clone()
394395
.chain(&state_manager.chain_store().blockstore())
395396
.take_while(|ts| ts.epoch() >= to_epoch)
396397
{
@@ -400,7 +401,7 @@ where
400401
}
401402
RangeSpec::NumTipsets(n_tipsets) => {
402403
for ts in head_ts
403-
.clone()
404+
.shallow_clone()
404405
.chain(&state_manager.chain_store().blockstore())
405406
.take(n_tipsets)
406407
{

0 commit comments

Comments
 (0)