diff --git a/src/beacon/drand.rs b/src/beacon/drand.rs index a0e525aa24cf..af229e616a28 100644 --- a/src/beacon/drand.rs +++ b/src/beacon/drand.rs @@ -13,16 +13,15 @@ use super::{ PublicKeyOnG1, PublicKeyOnG2, SignatureOnG1, SignatureOnG2, verify_messages_chained, }, }; +use crate::prelude::*; use crate::shim::clock::ChainEpoch; use crate::shim::version::NetworkVersion; use crate::utils::cache::SizeTrackingLruCache; use crate::utils::misc::env::is_env_truthy; use crate::utils::net::global_http_client; use ambassador::{Delegate, delegatable_trait}; -use anyhow::Context as _; use backon::{ExponentialBuilder, Retryable}; use bls_signatures::Serialize as _; -use itertools::Itertools as _; use nonzero_ext::nonzero; use serde::{Deserialize as SerdeDeserialize, Serialize as SerdeSerialize}; use tracing::debug; diff --git a/src/blocks/chain4u.rs b/src/blocks/chain4u.rs index 2d4a0b55c496..735df2e56e03 100644 --- a/src/blocks/chain4u.rs +++ b/src/blocks/chain4u.rs @@ -11,21 +11,21 @@ use crate::{ blocks::*, db::{MemoryDB, car::PlainCar}, networks, + prelude::*, shim::{ address::Address, clock::ChainEpoch, crypto::Signature, econ::TokenAmount, sector::PoStProof, }, }; use chain4u::header::{FILECOIN_GENESIS_BLOCK, FILECOIN_GENESIS_CID, GENESIS_BLOCK_PARENTS}; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::CborStore; -use itertools::Itertools as _; use num_bigint::BigInt; use petgraph::Direction; -use std::{borrow::Borrow, fmt::Debug, hash::Hash}; use std::{ + borrow::Borrow, collections::hash_map::Entry::{Occupied, Vacant}, + fmt::Debug, + hash::Hash, iter, }; @@ -173,6 +173,11 @@ impl Chain4U { inner: Default::default(), } } + + pub fn blockstore(&self) -> &T { + &self.blockstore + } + pub fn get(&self, ident: &Q) -> Option where String: Borrow, @@ -180,9 +185,11 @@ impl Chain4U { { self.inner.lock().ident2header.get(ident).cloned() } + pub fn tipset(&self, of: &[&str]) -> Tipset { Tipset::new(of.iter().map(|it| self.get(*it).unwrap())).unwrap() } + /// Insert a header. /// Header fields (epoch etc) will be set accordingly. pub fn insert( @@ -206,16 +213,6 @@ impl Chain4U { } } -impl Blockstore for Chain4U { - fn get(&self, k: &Cid) -> anyhow::Result>> { - self.blockstore.get(k) - } - - fn put_keyed(&self, k: &Cid, block: &[u8]) -> anyhow::Result<()> { - self.blockstore.put_keyed(k, block) - } -} - #[derive(Default)] struct Chain4UInner { ident2header: ahash::HashMap, @@ -693,7 +690,11 @@ fn test_chain4u() { itertools::assert_equal( iter::successors(Some(t3.clone()), |t| match t.epoch() { 0 => None, - _ => Some(Tipset::load(&c4u, t.parents()).unwrap().unwrap()), + _ => Some( + Tipset::load(c4u.blockstore(), t.parents()) + .unwrap() + .unwrap(), + ), }), [t3, t2, t1, t0], ); diff --git a/src/blocks/tipset.rs b/src/blocks/tipset.rs index a1a89a2c9465..7ce9451aec0b 100644 --- a/src/blocks/tipset.rs +++ b/src/blocks/tipset.rs @@ -11,9 +11,9 @@ use crate::{ chain_sync::TipsetValidator, cid_collections::SmallCidNonEmptyVec, networks::{calibnet, mainnet}, + prelude::*, shim::clock::ChainEpoch, utils::{ - ShallowClone, cid::CidCborExt, db::{CborStoreExt, car_stream::CarBlock}, get_size::nunny_vec_heap_size_helper, @@ -21,12 +21,8 @@ use crate::{ }, }; use ahash::HashMap; -use anyhow::Context as _; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::CborStore; use get_size2::GetSize; -use itertools::Itertools as _; use multihash_derive::MultihashDigest as _; use num::BigInt; use nunny::{Vec as NonEmpty, vec as nonempty}; diff --git a/src/chain/mod.rs b/src/chain/mod.rs index 85c73464bee9..cc54ecd823bb 100644 --- a/src/chain/mod.rs +++ b/src/chain/mod.rs @@ -15,7 +15,7 @@ use crate::cid_collections::CidHashSetLike; use crate::db::car::forest::{self, ForestCarFrame, finalize_frame}; use crate::db::{SettingsStore, SettingsStoreExt}; use crate::ipld::stream_chain; -use crate::utils::ShallowClone as _; +use crate::prelude::*; use crate::utils::db::car_stream::{CarBlock, CarBlockWrite}; use crate::utils::io::{AsyncWriterWithChecksum, Checksum}; use crate::utils::multihash::MultihashCode; @@ -23,13 +23,11 @@ use crate::utils::stream::par_buffer; use anyhow::Context as _; use cid::Cid; use futures::StreamExt as _; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::DAG_CBOR; use multihash_derive::MultihashDigest as _; use nunny::Vec as NonEmpty; use sha2::digest::{self, Digest}; use std::io::{Read, Seek, SeekFrom}; -use std::sync::Arc; use tokio::io::{AsyncWrite, AsyncWriteExt, BufWriter}; pub struct ExportOptions { @@ -53,7 +51,7 @@ impl Default for ExportOptions { } pub async fn export_from_head( - db: &Arc, + db: &(impl Blockstore + ShallowClone + SettingsStore + Unpin + Send + Sync + 'static), lookup_depth: ChainEpochDelta, writer: impl AsyncWrite + Unpin, options: ExportOptions, @@ -68,7 +66,7 @@ pub async fn export_from_head pub async fn export( - db: &Arc, + db: &(impl Blockstore + ShallowClone + Unpin + Send + Sync + 'static), tipset: &Tipset, lookup_depth: ChainEpochDelta, writer: impl AsyncWrite + Unpin, @@ -81,7 +79,7 @@ pub async fn export( /// Exports a Filecoin snapshot in v2 format /// See pub async fn export_v2( - db: &Arc, + db: &(impl Blockstore + ShallowClone + Unpin + Send + Sync + 'static), mut f3: Option<(Cid, F)>, tipset: &Tipset, lookup_depth: ChainEpochDelta, @@ -148,7 +146,7 @@ pub async fn export_v2( roots: NonEmpty, prefix_data_frames: Option>>, - db: &Arc, + db: &(impl Blockstore + ShallowClone + Unpin + Send + Sync + 'static), tipset: &Tipset, lookup_depth: ChainEpochDelta, writer: impl AsyncWrite + Unpin, diff --git a/src/chain/snapshot_format.rs b/src/chain/snapshot_format.rs index 996f0e28c99e..2d13540ee9ff 100644 --- a/src/chain/snapshot_format.rs +++ b/src/chain/snapshot_format.rs @@ -2,8 +2,7 @@ // SPDX-License-Identifier: Apache-2.0, MIT use crate::lotus_json::lotus_json_with_self; -use cid::Cid; -use itertools::Itertools as _; +use crate::prelude::*; use num::FromPrimitive as _; use num_derive::FromPrimitive; use nunny::Vec as NonEmpty; diff --git a/src/chain/store/chain_store.rs b/src/chain/store/chain_store.rs index 518a1e1917ec..8554c9c44a24 100644 --- a/src/chain/store/chain_store.rs +++ b/src/chain/store/chain_store.rs @@ -6,41 +6,31 @@ use super::{ index::{ChainIndex, ResolveNullTipset}, tipset_tracker::TipsetTracker, }; -use crate::message::{ChainMessage, SignedMessage}; use crate::networks::{ChainConfig, Height}; +use crate::prelude::*; use crate::rpc::eth::{eth_tx_from_signed_eth_message, types::EthHash}; use crate::shim::clock::ChainEpoch; use crate::shim::{executor::Receipt, message::Message, version::NetworkVersion}; -use crate::utils::ShallowClone; +use crate::state_manager::ExecutedTipset; use crate::utils::db::{BlockstoreExt, CborStoreExt}; use crate::{ blocks::{CachingBlockHeader, Tipset, TipsetKey, TxMeta}, - db::HeaviestTipsetKeyProvider, -}; -use crate::{ - db::{EthMappingsStore, EthMappingsStoreExt}, - rpc::chain::PathChange, + db::{DbImpl, HeaviestTipsetKeyProvider}, + message::{ChainMessage, SignedMessage}, }; +use crate::{db::EthMappingsStoreExt, rpc::chain::PathChange}; use crate::{fil_cns, utils::cache::SizeTrackingLruCache}; use crate::{ interpreter::{BlockMessages, VMTrace}, rpc::chain::PathChanges, }; -use crate::{ - libp2p_bitswap::{BitswapStoreRead, BitswapStoreReadWrite}, - state_manager::ExecutedTipset, -}; use ahash::{HashMap, HashSet}; -use anyhow::Context as _; -use cid::Cid; use fil_actors_shared::fvm_ipld_amt::Amtv0 as Amt; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::CborStore; -use itertools::Itertools; use nonzero_ext::nonzero; use parking_lot::{Mutex, RwLock}; use serde::{Serialize, de::DeserializeOwned}; -use std::{num::NonZeroUsize, sync::Arc}; +use std::num::NonZeroUsize; use tokio::sync::broadcast; use tracing::{debug, error, trace, warn}; @@ -60,16 +50,10 @@ pub type HeadChanges = PathChanges; /// Stores chain data such as heaviest tipset and cached tipset info at each /// epoch. This structure is thread-safe, and all caches are wrapped in a mutex /// to allow a consistent `ChainStore` to be shared across tasks. -pub struct ChainStore { +pub struct ChainStore { /// Publisher for head change events head_changes_tx: broadcast::Sender, - /// key-value `datastore`. - db: Arc, - - /// Heaviest tipset key provider - heaviest_tipset_key_provider: Arc, - /// Heaviest tipset cache heaviest_tipset: Arc>, @@ -77,18 +61,15 @@ pub struct ChainStore { f3_finalized_tipset: Arc>>, /// Used as a cache for tipset `lookbacks`. - chain_index: ChainIndex, + chain_index: ChainIndex, /// Tracks blocks for the purpose of forming tipsets. - tipset_tracker: TipsetTracker, + tipset_tracker: TipsetTracker, - genesis_block_header: CachingBlockHeader, + genesis_block_header: Arc, /// validated blocks - pub(crate) validated_blocks: Mutex>, - - /// Ethereum mappings store - eth_mappings: Arc, + pub(crate) validated_blocks: Arc>>, /// Needed by the Ethereum mapping. chain_config: Arc, @@ -97,44 +78,31 @@ pub struct ChainStore { messages_in_tipset_cache: MessagesInTipsetCache, } -impl BitswapStoreRead for ChainStore -where - DB: BitswapStoreRead, -{ - fn contains(&self, cid: &Cid) -> anyhow::Result { - self.db.contains(cid) - } - - fn get(&self, cid: &Cid) -> anyhow::Result>> { - self.db.get(cid) - } -} - -impl BitswapStoreReadWrite for ChainStore -where - DB: BitswapStoreReadWrite, -{ - type Hashes = ::Hashes; - - fn insert(&self, block: &crate::libp2p_bitswap::Block64) -> anyhow::Result<()> { - self.db.insert(block) +impl ShallowClone for ChainStore { + fn shallow_clone(&self) -> Self { + Self { + head_changes_tx: self.head_changes_tx.clone(), + heaviest_tipset: self.heaviest_tipset.shallow_clone(), + f3_finalized_tipset: self.f3_finalized_tipset.shallow_clone(), + chain_index: self.chain_index.shallow_clone(), + tipset_tracker: self.tipset_tracker.shallow_clone(), + genesis_block_header: self.genesis_block_header.shallow_clone(), + validated_blocks: self.validated_blocks.shallow_clone(), + chain_config: self.chain_config.shallow_clone(), + messages_in_tipset_cache: self.messages_in_tipset_cache.shallow_clone(), + } } } -impl ChainStore -where - DB: Blockstore, -{ +impl ChainStore { pub fn new( - db: Arc, - heaviest_tipset_key_provider: Arc, - eth_mappings: Arc, + db: impl Into, chain_config: Arc, genesis_block_header: CachingBlockHeader, ) -> anyhow::Result { + let db = db.into(); let (publisher, _) = broadcast::channel(SINK_CAP); - let validated_blocks = Mutex::new(HashSet::default()); - let head = if let Some(head_tsk) = heaviest_tipset_key_provider + let head = if let Some(head_tsk) = db .heaviest_tipset_key() .context("failed to load head tipset key")? { @@ -145,7 +113,7 @@ where }; let heaviest_tipset = Arc::new(RwLock::new(head)); let f3_finalized_tipset: Arc>> = Default::default(); - let chain_index = ChainIndex::new(db.clone()).with_is_tipset_finalized(Arc::new({ + let chain_index = ChainIndex::new(db.shallow_clone()).with_is_tipset_finalized(Arc::new({ let chain_finality = chain_config.policy.chain_finality; let heaviest_tipset = heaviest_tipset.clone(); let f3_finalized_tipset = f3_finalized_tipset.clone(); @@ -162,14 +130,11 @@ where let cs = Self { head_changes_tx: publisher, chain_index, - tipset_tracker: TipsetTracker::new(Arc::clone(&db), chain_config.clone()), - db, - heaviest_tipset_key_provider, + tipset_tracker: TipsetTracker::new(db, chain_config.clone()), heaviest_tipset, f3_finalized_tipset, - genesis_block_header, - validated_blocks, - eth_mappings, + genesis_block_header: genesis_block_header.into(), + validated_blocks: Default::default(), chain_config, messages_in_tipset_cache: Default::default(), }; @@ -194,9 +159,8 @@ where /// Sets heaviest tipset pub fn set_heaviest_tipset(&self, head: Tipset) -> Result<(), Error> { - head.key().save(self.blockstore())?; - self.heaviest_tipset_key_provider - .set_heaviest_tipset_key(head.key())?; + head.key().save(self.db())?; + self.db().set_heaviest_tipset_key(head.key())?; let old_head = std::mem::replace(&mut *self.heaviest_tipset.write(), head.clone()); if crate::utils::broadcast::has_subscribers(&self.head_changes_tx) { @@ -231,7 +195,7 @@ where /// Writes tipset block headers to data store and updates heaviest tipset /// with other compatible tracked headers. pub fn put_tipset(&self, ts: &Tipset) -> Result<(), Error> { - persist_objects(self.blockstore(), ts.block_headers().iter())?; + persist_objects(self.db(), ts.block_headers().iter())?; // Expand tipset to include other compatible blocks at the epoch. let expanded = self.expand_tipset(ts.min_ticket_block().clone())?; @@ -241,21 +205,18 @@ where /// Reads the `TipsetKey` from the blockstore for `EthAPI` queries. pub fn get_required_tipset_key(&self, hash: &EthHash) -> Result { - Ok(TipsetKey::load(self.blockstore(), &hash.to_cid())?) + Ok(TipsetKey::load(self.db(), &hash.to_cid())?) } /// Writes with timestamp the `Hash` to `Cid` mapping to the blockstore for `EthAPI` queries. pub fn put_mapping(&self, k: EthHash, v: Cid, timestamp: u64) -> Result<(), Error> { - self.eth_mappings.write_obj(&k, &(v, timestamp))?; + self.db().write_obj(&k, &(v, timestamp))?; Ok(()) } /// Reads the `Cid` from the blockstore for `EthAPI` queries. pub fn get_mapping(&self, hash: &EthHash) -> Result, Error> { - Ok(self - .eth_mappings - .read_obj::<(Cid, u64)>(hash)? - .map(|(cid, _)| cid)) + Ok(self.db().read_obj::<(Cid, u64)>(hash)?.map(|(cid, _)| cid)) } /// Expands tipset to tipset with all other headers in the same epoch using @@ -283,13 +244,18 @@ where self.head_changes_tx.subscribe() } - /// Returns key-value store instance. - pub fn blockstore(&self) -> &Arc { - &self.db + /// Returns a borrowed key-value store instance. + pub fn db(&self) -> &DbImpl { + self.chain_index().db() + } + + /// Returns an owned key-value store instance. + pub fn db_owned(&self) -> DbImpl { + self.chain_index().db_owned() } /// Returns the chain index - pub fn chain_index(&self) -> &ChainIndex { + pub fn chain_index(&self) -> &ChainIndex { &self.chain_index } @@ -315,10 +281,7 @@ where /// Returns [`None`] when `ts` has no known child on the current heaviest chain /// (e.g. `ts` is the chain head). Blockstore errors are returned as [`Err`]. - pub fn load_child_tipset(&self, ts: &Tipset) -> Result, Error> - where - DB: EthMappingsStore, - { + pub fn load_child_tipset(&self, ts: &Tipset) -> Result, Error> { let head = self.heaviest_tipset(); if head.parents() == ts.key() { Ok(Some(head)) @@ -340,9 +303,9 @@ where /// tipset fn update_heaviest(&self, ts: Tipset) -> Result<(), Error> { // Calculate heaviest weight before matching to avoid deadlock with mutex - let heaviest_weight = fil_cns::weight(self.blockstore(), &self.heaviest_tipset())?; + let heaviest_weight = fil_cns::weight(self.db(), &self.heaviest_tipset())?; - let new_weight = fil_cns::weight(self.blockstore(), &ts)?; + let new_weight = fil_cns::weight(self.db(), &ts)?; let curr_weight = heaviest_weight; if new_weight > curr_weight { @@ -377,7 +340,7 @@ where Ok(self .messages_in_tipset_cache() .get_or_insert_with(ts.key(), || { - let bmsgs = BlockMessages::for_tipset(&self.db, ts)?; + let bmsgs = BlockMessages::for_tipset(self.db(), ts)?; Ok(bmsgs.into_iter().flat_map(|bm| bm.messages).collect_vec()) })?) } @@ -391,14 +354,11 @@ where /// is usually 900. The `heaviest_tipset` is a reference point in the /// blockchain. It must be a child of the look-back tipset. pub fn get_lookback_tipset_for_round( - chain_index: &ChainIndex, + chain_index: &ChainIndex, chain_config: &Arc, heaviest_tipset: &Tipset, round: ChainEpoch, - ) -> Result<(Tipset, Cid), Error> - where - DB: EthMappingsStore + Send + Sync + 'static, - { + ) -> Result<(Tipset, Cid), Error> { let version = chain_config.network_version(round); let lb = if version <= NetworkVersion::V3 { ChainEpoch::from(10) @@ -453,10 +413,7 @@ where } /// Filter [`SignedMessage`]'s to keep only the most recent ones, then write corresponding entries to the Ethereum mapping. - pub fn process_signed_messages(&self, messages: &[(SignedMessage, u64)]) -> anyhow::Result<()> - where - DB: fvm_ipld_blockstore::Blockstore, - { + pub fn process_signed_messages(&self, messages: &[(SignedMessage, u64)]) -> anyhow::Result<()> { let eth_txs: Vec<(EthHash, Cid, u64, usize)> = messages .iter() .enumerate() @@ -490,10 +447,7 @@ where pub fn headers_delegated_messages<'a>( &self, headers: impl Iterator, - ) -> anyhow::Result> - where - DB: fvm_ipld_blockstore::Blockstore, - { + ) -> anyhow::Result> { let mut delegated_messages = vec![]; // Hygge is the start of Ethereum support in the FVM (through the FEVM actor). @@ -502,7 +456,7 @@ where headers.filter(|bh| bh.epoch >= self.chain_config.epoch(Height::Hygge)); for bh in filtered_headers { - if let Ok((_, secp_cids)) = block_messages(self.blockstore(), bh) { + if let Ok((_, secp_cids)) = block_messages(self.db(), bh) { let mut messages: Vec<_> = secp_cids .into_iter() .filter(|msg| msg.is_delegated()) @@ -689,6 +643,14 @@ impl Default for MessagesInTipsetCache { } } +impl ShallowClone for MessagesInTipsetCache { + fn shallow_clone(&self) -> Self { + Self { + cache: self.cache.shallow_clone(), + } + } +} + /// Returns messages from key-value store based on a slice of [`Cid`]s. pub fn messages_from_cids(db: &DB, keys: &[Cid]) -> Result, Error> where @@ -726,7 +688,6 @@ mod tests { use super::*; use crate::utils::multihash::prelude::*; use crate::{blocks::RawBlockHeader, shim::address::Address}; - use cid::Cid; use fvm_ipld_encoding::DAG_CBOR; #[test] @@ -743,22 +704,21 @@ mod tests { message_receipts: Cid::new_v1(DAG_CBOR, MultihashCode::Identity.digest(&[])), ..Default::default() }); - let cs = - ChainStore::new(db.clone(), db.clone(), db, chain_config, gen_block.clone()).unwrap(); + let cs = ChainStore::new(db, chain_config, gen_block.clone()).unwrap(); assert_eq!(cs.genesis_block_header(), &gen_block); } #[test] fn block_validation_cache_basic() { - let db = Arc::new(crate::db::MemoryDB::default()); + let db = DbImpl::from(Arc::new(crate::db::MemoryDB::default())); let chain_config = Arc::new(ChainConfig::default()); let gen_block = CachingBlockHeader::new(RawBlockHeader { miner_address: Address::new_id(0), ..Default::default() }); - let cs = ChainStore::new(db.clone(), db.clone(), db, chain_config, gen_block).unwrap(); + let cs = ChainStore::new(db, chain_config, gen_block).unwrap(); let cid = Cid::new_v1(DAG_CBOR, MultihashCode::Blake2b256.digest(&[1, 2, 3])); assert!(!cs.is_block_validated(&cid)); diff --git a/src/chain/store/index.rs b/src/chain/store/index.rs index 6dc9d202b718..f9ca19d2a30b 100644 --- a/src/chain/store/index.rs +++ b/src/chain/store/index.rs @@ -1,18 +1,16 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use std::{num::NonZeroUsize, sync::Arc}; +use std::num::NonZeroUsize; use crate::beacon::{BeaconEntry, IGNORE_DRAND}; use crate::blocks::{Tipset, TipsetKey}; use crate::chain::Error; -use crate::db::EthMappingsStore; +use crate::db::{DbImpl, EthMappingsStore as _}; use crate::metrics; +use crate::prelude::*; use crate::shim::clock::ChainEpoch; -use crate::utils::ShallowClone; use crate::utils::cache::SizeTrackingLruCache; -use fvm_ipld_blockstore::Blockstore; -use itertools::Itertools; use nonzero_ext::nonzero; use num::Integer; @@ -24,16 +22,16 @@ type IsTipsetFinalizedFn = Arc bool + Send + Sync>; /// Keeps look-back tipsets in cache at a given interval `skip_length` and can /// be used to look-back at the chain to retrieve an old tipset. -pub struct ChainIndex { +pub struct ChainIndex { /// tipset key to tipset mappings. ts_cache: TipsetCache, /// `Blockstore` pointer needed to load tipsets from cold storage. - db: Arc, + db: DbImpl, /// check whether a tipset is finalized is_tipset_finalized: Option, } -impl ShallowClone for ChainIndex { +impl ShallowClone for ChainIndex { fn shallow_clone(&self) -> Self { Self { ts_cache: self.ts_cache.shallow_clone(), @@ -52,8 +50,9 @@ pub enum ResolveNullTipset { TakeOlder, } -impl ChainIndex { - pub fn new(db: Arc) -> Self { +impl ChainIndex { + pub fn new(db: impl Into) -> Self { + let db = db.into(); let ts_cache = SizeTrackingLruCache::new_with_metrics("tipset".into(), DEFAULT_TIPSET_CACHE_SIZE); Self { @@ -68,10 +67,14 @@ impl ChainIndex { self } - pub fn db(&self) -> &Arc { + pub fn db(&self) -> &DbImpl { &self.db } + pub fn db_owned(&self) -> DbImpl { + self.db().shallow_clone() + } + /// Loads a tipset from memory given the tipset keys and cache. Semantically /// identical to [`Tipset::load`] but the result is cached. pub fn load_tipset(&self, tsk: &TipsetKey) -> Result, Error> { @@ -152,10 +155,7 @@ impl ChainIndex { to: ChainEpoch, mut from: Tipset, resolve: ResolveNullTipset, - ) -> Result, Error> - where - DB: EthMappingsStore, - { + ) -> Result, Error> { use crate::shim::policy::policy_constants::CHAIN_FINALITY; // use `20` as checkpoint interval to match Lotus: @@ -233,10 +233,7 @@ impl ChainIndex { to: ChainEpoch, from: Tipset, resolve: ResolveNullTipset, - ) -> Result - where - DB: EthMappingsStore, - { + ) -> Result { self.tipset_by_height(to, from, resolve)? .ok_or_else(|| Error::NotFound(format!("tipset at epoch {to}").into())) } @@ -266,15 +263,14 @@ impl ChainIndex { #[cfg(test)] mod tests { - use std::sync::{ - Arc, - atomic::{AtomicU64, Ordering}, - }; - use super::*; use crate::blocks::{CachingBlockHeader, RawBlockHeader}; use crate::db::MemoryDB; use crate::utils::db::CborStoreExt; + use std::sync::{ + Arc, + atomic::{AtomicU64, Ordering}, + }; fn persist_tipset(tipset: &Tipset, db: &impl Blockstore) { for block in tipset.block_headers() { diff --git a/src/chain/store/tipset_tracker.rs b/src/chain/store/tipset_tracker.rs index 10d372c6ba98..7ec088f13e41 100644 --- a/src/chain/store/tipset_tracker.rs +++ b/src/chain/store/tipset_tracker.rs @@ -1,14 +1,13 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use std::{collections::BTreeMap, sync::Arc}; +use std::collections::BTreeMap; use super::Error; use crate::blocks::{CachingBlockHeader, Tipset}; use crate::networks::ChainConfig; +use crate::prelude::*; use crate::shim::clock::ChainEpoch; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; use nunny::vec as nonempty; use parking_lot::Mutex; use tracing::{debug, warn}; @@ -16,13 +15,23 @@ use tracing::{debug, warn}; /// Tracks blocks by their height for the purpose of forming tipsets. #[derive(Default)] pub(in crate::chain) struct TipsetTracker { - entries: Mutex>>, - db: Arc, + entries: Arc>>>, + db: DB, chain_config: Arc, } +impl ShallowClone for TipsetTracker { + fn shallow_clone(&self) -> Self { + Self { + entries: self.entries.shallow_clone(), + db: self.db.shallow_clone(), + chain_config: self.chain_config.shallow_clone(), + } + } +} + impl TipsetTracker { - pub fn new(db: Arc, chain_config: Arc) -> Self { + pub fn new(db: DB, chain_config: Arc) -> Self { Self { entries: Default::default(), db, @@ -114,10 +123,8 @@ impl TipsetTracker { #[cfg(test)] mod test { - use crate::db::MemoryDB; - use itertools::Itertools as _; - use super::*; + use crate::db::MemoryDB; #[test] fn ensure_tipset_is_bounded() { @@ -136,7 +143,7 @@ mod test { let tipset_tracker = TipsetTracker { db: Arc::new(db), chain_config: chain_config.clone(), - entries: Mutex::new(entries), + entries: Arc::new(Mutex::new(entries)), }; tipset_tracker.prune_entries(head_epoch); diff --git a/src/chain/tests.rs b/src/chain/tests.rs index 3bdcf051957b..5cecd44d15fd 100644 --- a/src/chain/tests.rs +++ b/src/chain/tests.rs @@ -10,6 +10,7 @@ use crate::{ }; use sha2::{Digest as _, Sha256}; use std::fs::File; +use std::sync::Arc; #[test] fn test_snapshot_version_cbor_serde() { diff --git a/src/chain_sync/bad_block_cache.rs b/src/chain_sync/bad_block_cache.rs index 4d89a67a52dd..cd4aea139b9d 100644 --- a/src/chain_sync/bad_block_cache.rs +++ b/src/chain_sync/bad_block_cache.rs @@ -3,10 +3,10 @@ use std::num::NonZeroUsize; -use cid::Cid; use nonzero_ext::nonzero; -use crate::utils::{ShallowClone, cache::SizeTrackingLruCache, get_size}; +use crate::prelude::*; +use crate::utils::{cache::SizeTrackingLruCache, get_size}; /// Default capacity for CID caches (32768 entries). /// That's about 4 MiB. @@ -26,6 +26,14 @@ impl Default for BadBlockCache { } } +impl ShallowClone for BadBlockCache { + fn shallow_clone(&self) -> Self { + Self { + cache: self.cache.shallow_clone(), + } + } +} + impl BadBlockCache { pub fn new(cap: NonZeroUsize) -> Self { Self { diff --git a/src/chain_sync/chain_follower.rs b/src/chain_sync/chain_follower.rs index cd887b466205..bc03040218a8 100644 --- a/src/chain_sync/chain_follower.rs +++ b/src/chain_sync/chain_follower.rs @@ -27,40 +27,36 @@ use crate::{ tipset_syncer::{TipsetSyncerError, validate_tipset}, validation::GossipBlockValidator, }, - db::EthMappingsStore, libp2p::{NetworkEvent, PubsubMessage, hello::HelloRequest}, message_pool::MessagePool, networks::calculate_expected_epoch, + prelude::*, shim::clock::ChainEpoch, state_manager::StateManager, - utils::ShallowClone as _, }; use ahash::{HashMap, HashSet}; use chrono::Utc; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; -use itertools::Itertools; use libp2p::PeerId; use parking_lot::{Mutex, RwLock}; -use std::{sync::Arc, time::Instant}; +use std::time::Instant; use tokio::{sync::Notify, task::JoinSet}; use tracing::{debug, error, info, trace, warn}; -pub struct ChainFollower { +pub struct ChainFollower { /// Tasks tasks: Arc>>, /// State machine - state_machine: Arc>>, + state_machine: Arc>, /// Syncing status of the chain pub sync_status: SyncStatus, /// manages retrieving and updates state objects - pub state_manager: Arc>, + pub state_manager: StateManager, /// Context to be able to send requests to P2P network - pub network: SyncNetworkContext, + pub network: SyncNetworkContext, /// Genesis tipset genesis: Tipset, @@ -68,16 +64,16 @@ pub struct ChainFollower { /// Bad blocks cache, updates based on invalid state transitions. /// Will mark any invalid blocks and all children as bad in this bounded /// cache - pub bad_blocks: Option>, + pub bad_blocks: Option, /// Incoming network events to be handled by synchronizer - net_handler: flume::Receiver, + net_handler: Arc>, /// Tipset channel sender pub tipset_sender: flume::Sender, /// Tipset channel receiver - tipset_receiver: flume::Receiver, + tipset_receiver: Arc>, /// When `stateless_mode` is true, forest connects to the P2P network but /// does not execute any state transitions. This drastically reduces the @@ -86,17 +82,36 @@ pub struct ChainFollower { stateless_mode: bool, /// Message pool - mem_pool: Arc>>>, + mem_pool: MessagePool, } -impl ChainFollower { +impl ShallowClone for ChainFollower { + fn shallow_clone(&self) -> Self { + Self { + tasks: self.tasks.shallow_clone(), + state_machine: self.state_machine.shallow_clone(), + sync_status: self.sync_status.shallow_clone(), + state_manager: self.state_manager.shallow_clone(), + network: self.network.shallow_clone(), + genesis: self.genesis.shallow_clone(), + bad_blocks: self.bad_blocks.shallow_clone(), + net_handler: self.net_handler.shallow_clone(), + tipset_sender: self.tipset_sender.clone(), + tipset_receiver: self.tipset_receiver.shallow_clone(), + stateless_mode: self.stateless_mode, + mem_pool: self.mem_pool.shallow_clone(), + } + } +} + +impl ChainFollower { pub fn new( - state_manager: Arc>, - network: SyncNetworkContext, + state_manager: StateManager, + network: SyncNetworkContext, genesis: Tipset, net_handler: flume::Receiver, stateless_mode: bool, - mem_pool: Arc>>>, + mem_pool: MessagePool, ) -> Self { crate::def_is_env_truthy!(cache_disabled, "FOREST_DISABLE_BAD_BLOCK_CACHE"); let (tipset_sender, tipset_receiver) = flume::bounded(20); @@ -108,8 +123,8 @@ impl ChainFollower { Some(Default::default()) }; let state_machine = Arc::new(Mutex::new(SyncStateMachine::new( - state_manager.chain_store().clone(), - bad_blocks.clone(), + state_manager.chain_store().shallow_clone(), + bad_blocks.shallow_clone(), stateless_mode, ))); Self { @@ -120,9 +135,9 @@ impl ChainFollower { network, genesis, bad_blocks, - net_handler, + net_handler: net_handler.into(), tipset_sender, - tipset_receiver, + tipset_receiver: tipset_receiver.into(), stateless_mode, mem_pool, } @@ -147,17 +162,14 @@ impl ChainFollower { ); } - pub async fn run(&self) -> anyhow::Result<()> - where - DB: EthMappingsStore, - { + pub async fn run(&self) -> anyhow::Result<()> { chain_follower( &self.tasks, &self.state_machine, &self.state_manager, - self.bad_blocks.clone(), - self.net_handler.clone(), - self.tipset_receiver.clone(), + self.bad_blocks.shallow_clone(), + self.net_handler.shallow_clone(), + self.tipset_receiver.shallow_clone(), &self.network, &self.mem_pool, &self.sync_status, @@ -170,15 +182,15 @@ impl ChainFollower { #[allow(clippy::too_many_arguments)] // We receive new full tipsets from the p2p swarm, and from miners that use Forest as their frontend. -async fn chain_follower( +async fn chain_follower( tasks: &Arc>>, - state_machine: &Arc>>, - state_manager: &Arc>, - bad_block_cache: Option>, - network_rx: flume::Receiver, - tipset_receiver: flume::Receiver, - network: &SyncNetworkContext, - mem_pool: &Arc>>>, + state_machine: &Arc>, + state_manager: &StateManager, + bad_block_cache: Option, + network_rx: Arc>, + tipset_receiver: Arc>, + network: &SyncNetworkContext, + mem_pool: &MessagePool, sync_status: &SyncStatus, genesis: &Tipset, stateless_mode: bool, @@ -206,7 +218,7 @@ async fn chain_follower match message { PubsubMessage::Block(b) => { @@ -231,7 +243,7 @@ async fn chain_follower( +fn update_peer_info( event: &NetworkEvent, - network: &SyncNetworkContext, - chain_store: Arc>, + network: &SyncNetworkContext, + chain_store: ChainStore, genesis: &Tipset, ) { match event { @@ -444,9 +456,9 @@ fn update_peer_info( } } -async fn handle_peer_connected_event( - network: SyncNetworkContext, - chain_store: Arc>, +async fn handle_peer_connected_event( + network: SyncNetworkContext, + chain_store: ChainStore, peer_id: PeerId, genesis_block_cid: Cid, ) { @@ -482,17 +494,14 @@ async fn handle_peer_connected_event( } } -fn handle_peer_disconnected_event( - network: &SyncNetworkContext, - peer_id: PeerId, -) { +fn handle_peer_disconnected_event(network: &SyncNetworkContext, peer_id: PeerId) { network.peer_manager().remove_peer(&peer_id); network.peer_manager().unmark_peer_bad(&peer_id); } -pub async fn get_full_tipset( - network: &SyncNetworkContext, - chain_store: &ChainStore, +pub async fn get_full_tipset( + network: &SyncNetworkContext, + chain_store: &ChainStore, peer_id: Option, tipset_keys: &TipsetKey, ) -> anyhow::Result { @@ -505,14 +514,14 @@ pub async fn get_full_tipset( .chain_exchange_full_tipset(peer_id, tipset_keys) .await .map_err(|e| anyhow::anyhow!(e))?; - tipset.persist(chain_store.blockstore())?; + tipset.persist(chain_store.db())?; Ok(tipset) } -async fn get_full_tipset_batch( - network: &SyncNetworkContext, - chain_store: &ChainStore, +async fn get_full_tipset_batch( + network: &SyncNetworkContext, + chain_store: &ChainStore, peer_id: Option, tipset_keys: &TipsetKey, ) -> anyhow::Result> { @@ -527,14 +536,14 @@ async fn get_full_tipset_batch( .map_err(|e| anyhow::anyhow!(e))?; for tipset in tipsets.iter() { - tipset.persist(chain_store.blockstore())?; + tipset.persist(chain_store.db())?; } Ok(tipsets) } -pub fn load_full_tipset( - chain_store: &ChainStore, +pub fn load_full_tipset( + chain_store: &ChainStore, tipset_keys: &TipsetKey, ) -> anyhow::Result { // Retrieve tipset from store based on passed in TipsetKey @@ -545,8 +554,7 @@ pub fn load_full_tipset( .block_headers() .iter() .map(|header| -> anyhow::Result { - let (bls_msgs, secp_msgs) = - crate::chain::block_messages(chain_store.blockstore(), header)?; + let (bls_msgs, secp_msgs) = crate::chain::block_messages(chain_store.db(), header)?; Ok(Block { header: header.clone(), bls_messages: bls_msgs, @@ -596,18 +604,18 @@ impl std::fmt::Display for SyncEvent { } } -struct SyncStateMachine { - cs: Arc>, - bad_block_cache: Option>, +struct SyncStateMachine { + cs: ChainStore, + bad_block_cache: Option, // Map from TipsetKey to FullTipset tipsets: HashMap, stateless_mode: bool, } -impl SyncStateMachine { +impl SyncStateMachine { pub fn new( - cs: Arc>, - bad_block_cache: Option>, + cs: ChainStore, + bad_block_cache: Option, stateless_mode: bool, ) -> Self { Self { @@ -648,7 +656,7 @@ impl SyncStateMachine { } fn is_parent_validated(&self, tipset: &FullTipset) -> bool { - let db = self.cs.blockstore(); + let db = self.cs.db(); self.stateless_mode || db.has(tipset.parent_state()).unwrap_or(false) } @@ -675,13 +683,10 @@ impl SyncStateMachine { } } - fn add_full_tipset(&mut self, tipset: FullTipset) - where - DB: EthMappingsStore, - { + fn add_full_tipset(&mut self, tipset: FullTipset) { if let Err(why) = TipsetValidator(&tipset).validate( &self.cs, - self.bad_block_cache.as_ref().map(AsRef::as_ref), + self.bad_block_cache.as_ref(), &self.cs.genesis_tipset(), self.cs.chain_config().block_delay_secs, ) { @@ -806,10 +811,7 @@ impl SyncStateMachine { } } - pub fn update(&mut self, event: SyncEvent) - where - DB: EthMappingsStore, - { + pub fn update(&mut self, event: SyncEvent) { tracing::trace!("update: {event}"); match event { SyncEvent::NewFullTipsets(tipsets) => { @@ -903,12 +905,12 @@ impl std::fmt::Display for SyncTask { } impl SyncTask { - async fn execute( + async fn execute( self, - network: SyncNetworkContext, - state_manager: Arc>, + network: SyncNetworkContext, + state_manager: StateManager, stateless_mode: bool, - bad_block_cache: Option>, + bad_block_cache: Option, ) -> Option { tracing::trace!("SyncTask::execute {self}"); match self { @@ -967,7 +969,7 @@ mod tests { use tracing::level_filters::LevelFilter; use tracing_subscriber::EnvFilter; - fn setup() -> (Arc>, Chain4U>) { + fn setup() -> (ChainStore, Chain4U>) { // Initialize test logger let _ = tracing_subscriber::fmt() .without_time() @@ -998,16 +1000,7 @@ mod tests { [genesis_header = dummy_node(&db, 0)] }; - let cs = Arc::new( - ChainStore::new( - db.clone(), - db.clone(), - db.clone(), - Default::default(), - genesis_header.clone().into(), - ) - .unwrap(), - ); + let cs = ChainStore::new(db, Default::default(), genesis_header.clone().into()).unwrap(); cs.set_heaviest_tipset(cs.genesis_tipset()).unwrap(); @@ -1030,7 +1023,7 @@ mod tests { #[test] fn test_state_machine_validation_order() { let (cs, c4u) = setup(); - let db = cs.blockstore().clone(); + let db = cs.db_owned(); chain4u! { from [genesis_header] in c4u; @@ -1038,7 +1031,7 @@ mod tests { }; // Create the state machine - let mut state_machine = SyncStateMachine::new(cs, Default::default(), true); + let mut state_machine = SyncStateMachine::new(cs.shallow_clone(), Default::default(), true); // Insert tipsets in random order let tipsets = vec![e, b, d, c, a]; @@ -1094,18 +1087,18 @@ mod tests { #[test] fn test_sync_state_machine_chain_fragments() { let (cs, c4u) = setup(); - let db = cs.blockstore().clone(); + let db = cs.db(); // Create a forked chain // genesis -> a -> b // \--> c chain4u! { in c4u; - [a = dummy_node(&db, 1)] -> [b = dummy_node(&db, 2)] + [a = dummy_node(db, 1)] -> [b = dummy_node(db, 2)] }; chain4u! { from [a] in c4u; - [c = dummy_node(&db, 3)] + [c = dummy_node(db, 3)] }; // Create the state machine diff --git a/src/chain_sync/network_context.rs b/src/chain_sync/network_context.rs index f351e55079db..1eef364f0a78 100644 --- a/src/chain_sync/network_context.rs +++ b/src/chain_sync/network_context.rs @@ -13,6 +13,7 @@ use std::{ use crate::{ blocks::{FullTipset, Tipset, TipsetKey, TipsetLike}, + db::DbImpl, libp2p::{ NetworkMessage, PeerId, PeerManager, chain_exchange::{ @@ -21,14 +22,13 @@ use crate::{ hello::{HelloRequest, HelloResponse}, rpc::RequestResponseError, }, + prelude::*, utils::{ - ShallowClone, misc::{AdaptiveValueProvider, ExponentialAdaptiveValueProvider}, stats::Stats, }, }; use anyhow::Context as _; -use fvm_ipld_blockstore::Blockstore; use nonzero_ext::nonzero; use parking_lot::Mutex; use std::future::Future; @@ -58,16 +58,16 @@ static MAX_CONCURRENT_CHAIN_EXCHANGE_REQUESTS: LazyLock = LazyLock /// This contains the peer manager, P2P service interface, and [`Blockstore`] /// required to make network requests. #[derive(derive_more::Constructor)] -pub struct SyncNetworkContext { +pub struct SyncNetworkContext { /// Channel to send network messages through P2P service network_send: flume::Sender, /// Manages peers to send requests to and updates request stats for the /// respective peers. peer_manager: Arc, - db: Arc, + db: DbImpl, } -impl ShallowClone for SyncNetworkContext { +impl ShallowClone for SyncNetworkContext { fn shallow_clone(&self) -> Self { Self { network_send: self.network_send.clone(), @@ -125,10 +125,7 @@ where } } -impl SyncNetworkContext -where - DB: Blockstore, -{ +impl SyncNetworkContext { /// Returns a reference to the peer manager of the network context. pub fn peer_manager(&self) -> &PeerManager { self.peer_manager.as_ref() diff --git a/src/chain_sync/sync_status.rs b/src/chain_sync/sync_status.rs index 12fb5f7530ad..28aa2ceb8468 100644 --- a/src/chain_sync/sync_status.rs +++ b/src/chain_sync/sync_status.rs @@ -6,7 +6,6 @@ use crate::networks::calculate_expected_epoch; use crate::shim::clock::ChainEpoch; use crate::state_manager::StateManager; use chrono::{DateTime, Utc}; -use fvm_ipld_blockstore::Blockstore; use parking_lot::RwLock; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -140,9 +139,9 @@ impl SyncStatusReport { /// Updates the sync status report based on the current state of the node and network. /// This does not modify the existing report but returns a new one with updated information. - pub(crate) fn update( + pub(crate) fn update( &self, - state_manager: &StateManager, + state_manager: &StateManager, active_forks: Vec, stateless_mode: bool, ) -> Self { diff --git a/src/chain_sync/tipset_syncer.rs b/src/chain_sync/tipset_syncer.rs index 4ea1a0dd2592..cb915b1e6f14 100644 --- a/src/chain_sync/tipset_syncer.rs +++ b/src/chain_sync/tipset_syncer.rs @@ -1,20 +1,19 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use std::sync::Arc; - use crate::chain_sync::BadBlockCache; -use crate::db::EthMappingsStore; +use crate::db::DbImpl; use crate::networks::Height; +use crate::prelude::*; use crate::shim::clock::ALLOWABLE_CLOCK_DRIFT; use crate::shim::crypto::SignatureType; +use crate::shim::message::Message; use crate::shim::{ address::Address, crypto::verify_bls_aggregate, econ::BLOCK_GAS_LIMIT, - gas::price_list_by_network_version, message::Message, state_tree::StateTree, + gas::price_list_by_network_version, state_tree::StateTree, }; use crate::state_manager::ExecutedTipset; use crate::state_manager::{Error as StateManagerError, StateManager, utils::is_valid_for_sending}; -use crate::utils::ShallowClone as _; use crate::{ blocks::{Block, CachingBlockHeader, Error as ForestBlockError, FullTipset, Tipset}, fil_cns::{self, FilecoinConsensus, FilecoinConsensusError}, @@ -28,11 +27,8 @@ use crate::{ message::{MessageRead as _, valid_for_block_inclusion}, }; use ahash::HashMap; -use cid::Cid; use futures::TryFutureExt; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::to_vec; -use itertools::Itertools; use nunny::Vec as NonEmpty; use thiserror::Error; use tokio::task::JoinSet; @@ -96,10 +92,10 @@ impl TipsetSyncerError { /// executed), adding the successful ones to the tipset tracker, and the failed /// ones to the bad block cache, depending on strategy. Any bad block fails /// validation. -pub async fn validate_tipset( - state_manager: &Arc>, +pub async fn validate_tipset( + state_manager: &StateManager, full_tipset: FullTipset, - bad_block_cache: Option>, + bad_block_cache: Option, ) -> Result<(), TipsetSyncerError> { if full_tipset .key() @@ -118,7 +114,7 @@ pub async fn validate_tipset { // Do not mark block as bad if the parent state tree does not exist - if StateTree::new_from_root(state_manager.blockstore_owned(), &parent_state) - .is_ok() + if StateTree::new_from_root(state_manager.db(), &parent_state).is_ok() && let Some(bad_block_cache) = bad_block_cache { bad_block_cache.push(cid); @@ -174,8 +169,8 @@ pub async fn validate_tipset( - state_manager: Arc>, +async fn validate_block( + state_manager: StateManager, block: Arc, ) -> Result, (Cid, TipsetSyncerError)> { let consensus = FilecoinConsensus::new(state_manager.beacon_schedule().clone()); @@ -185,7 +180,7 @@ async fn validate_block( - state_manager: Arc>, +async fn check_block_messages( + state_manager: StateManager, block: Arc, base_tipset: Tipset, ) -> Result<(), TipsetSyncerError> { @@ -383,7 +378,7 @@ async fn check_block_messages, - tree: &StateTree| + tree: &StateTree| -> anyhow::Result<()> { // Phase 1: Syntactic validation let min_gas = price_list.on_chain_message(to_vec(msg).unwrap().len()); @@ -458,12 +453,11 @@ async fn check_block_messages for TipsetValidationError { pub struct TipsetValidator<'a>(pub &'a FullTipset); impl TipsetValidator<'_> { - pub fn validate( + pub fn validate( &self, - chainstore: &ChainStore, + chainstore: &ChainStore, bad_block_cache: Option<&BadBlockCache>, genesis_tipset: &Tipset, block_delay: u32, @@ -98,7 +98,7 @@ impl TipsetValidator<'_> { // matches the mst root in the block header 2. Ensuring it has not // previously been seen in the bad blocks cache for block in self.0.blocks() { - Self::validate_msg_root(chainstore.blockstore(), block)?; + Self::validate_msg_root(chainstore.db(), block)?; if let Some(bad_block_cache) = bad_block_cache && bad_block_cache.peek(block.cid()).is_some() { diff --git a/src/cli/humantoken.rs b/src/cli/humantoken.rs index 110d5b2d6d2f..8daa562d16b1 100644 --- a/src/cli/humantoken.rs +++ b/src/cli/humantoken.rs @@ -104,10 +104,10 @@ mod si { mod parse { // ENHANCE(aatifsyed): could accept pairs like "1 nano 1 atto" + use crate::prelude::*; use crate::shim::econ::TokenAmount; use anyhow::{anyhow, bail}; use bigdecimal::{BigDecimal, ParseBigDecimalError}; - use itertools::Itertools as _; use nom::{ IResult, Parser, bytes::complete::tag, diff --git a/src/cli/subcommands/chain_cmd/list.rs b/src/cli/subcommands/chain_cmd/list.rs index b865785cebe0..ac877cce17d7 100644 --- a/src/cli/subcommands/chain_cmd/list.rs +++ b/src/cli/subcommands/chain_cmd/list.rs @@ -3,12 +3,11 @@ use std::num::NonZeroUsize; -use anyhow::Context as _; -use itertools::Itertools; use nonzero_ext::nonzero; use num::{BigInt, Zero as _}; use crate::{ + prelude::*, rpc::{ self, RpcMethodExt as _, chain::{ @@ -17,7 +16,6 @@ use crate::{ }, }, shim::econ::{BLOCK_GAS_LIMIT, TokenAmount}, - utils::ShallowClone as _, }; /// View a segment of the chain diff --git a/src/cli/subcommands/f3_cmd.rs b/src/cli/subcommands/f3_cmd.rs index ddea7f3beb5a..3d0380575487 100644 --- a/src/cli/subcommands/f3_cmd.rs +++ b/src/cli/subcommands/f3_cmd.rs @@ -13,6 +13,7 @@ use std::{ use crate::{ blocks::{Tipset, TipsetKey}, lotus_json::HasLotusJson as _, + prelude::*, rpc::{ self, f3::{ @@ -24,10 +25,8 @@ use crate::{ shim::fvm_shared_latest::ActorID, }; use ahash::HashSet; -use cid::Cid; use clap::{Subcommand, ValueEnum}; use indicatif::{ProgressBar, ProgressStyle}; -use itertools::Itertools as _; use serde::{Deserialize, Serialize}; use serde_with::{DisplayFromStr, serde_as}; use tera::Tera; diff --git a/src/daemon/context.rs b/src/daemon/context.rs index 345b046ae3fd..6d7a66d2e1af 100644 --- a/src/daemon/context.rs +++ b/src/daemon/context.rs @@ -8,13 +8,14 @@ use crate::cli_shared::cli::CliOpts; use crate::daemon::asyncify; use crate::daemon::bundle::load_actor_bundles; use crate::daemon::db_util::load_all_forest_cars_with_cleanup; +use crate::db::CAR_DB_DIR_NAME; use crate::db::car::ManyCar; use crate::db::db_engine::db_root; use crate::db::parity_db::{GarbageCollectableParityDb, ParityDb}; -use crate::db::{CAR_DB_DIR_NAME, DummyStore, EthMappingsStore}; use crate::genesis::read_genesis_header; use crate::libp2p::{Keypair, PeerId}; use crate::networks::ChainConfig; +use crate::prelude::*; use crate::rpc::sync::SnapshotProgressTracker; use crate::shim::address::CurrentNetwork; use crate::state_manager::StateManager; @@ -31,12 +32,14 @@ use std::path::PathBuf; use std::sync::Arc; use tracing::{info, warn}; +type DbType = Arc>>; + pub struct AppContext { pub net_keypair: Keypair, pub p2p_peer_id: PeerId, - pub db: Arc, + pub db: DbType, pub db_meta_data: DbMetadata, - pub state_manager: Arc>, + pub state_manager: StateManager, pub keystore: Arc>, pub admin_jwt: String, pub snapshot_progress_tracker: SnapshotProgressTracker, @@ -70,7 +73,7 @@ impl AppContext { self.state_manager.chain_config() } - pub fn chain_store(&self) -> &Arc> { + pub fn chain_store(&self) -> &ChainStore { self.state_manager.chain_store() } } @@ -182,8 +185,6 @@ fn maybe_migrate_db(config: &Config) { } } -pub type DbType = ManyCar>; - pub(crate) struct DbMetadata { db_root_dir: PathBuf, forest_car_db_dir: PathBuf, @@ -204,7 +205,7 @@ impl DbMetadata { /// - load parity-db /// - load CAR database /// - load actor bundles -async fn setup_db(opts: &CliOpts, config: &Config) -> anyhow::Result<(Arc, DbMetadata)> { +async fn setup_db(opts: &CliOpts, config: &Config) -> anyhow::Result<(DbType, DbMetadata)> { maybe_migrate_db(config); let chain_data_path = chain_path(config); let db_root_dir = db_root(&chain_data_path)?; @@ -229,9 +230,9 @@ async fn setup_db(opts: &CliOpts, config: &Config) -> anyhow::Result<(Arc, + db: &DbType, chain_config: &Arc, -) -> anyhow::Result>> { +) -> anyhow::Result { // Read Genesis file // * When snapshot command implemented, this genesis does not need to be // initialized @@ -242,23 +243,14 @@ async fn create_state_manager( ) .await?; - let eth_mappings: Arc = - if config.chain_indexer.enable_indexer { - db.writer().clone() - } else { - Arc::new(DummyStore {}) - }; - let chain_store = Arc::new(ChainStore::new( - Arc::clone(db), - Arc::new(db.clone()), - eth_mappings, - chain_config.clone(), - genesis_header.clone(), - )?); + let chain_store = ChainStore::new( + db.shallow_clone(), + chain_config.shallow_clone(), + genesis_header, + )?; // Initialize StateManager - let state_manager = Arc::new(StateManager::new(Arc::clone(&chain_store))?); - + let state_manager = StateManager::new(chain_store)?; Ok(state_manager) } diff --git a/src/daemon/db_util.rs b/src/daemon/db_util.rs index e78e39d94ca6..cfb314af1458 100644 --- a/src/daemon/db_util.rs +++ b/src/daemon/db_util.rs @@ -6,12 +6,11 @@ use crate::db::car::forest::{ FOREST_CAR_FILE_EXTENSION, TEMP_FOREST_CAR_FILE_EXTENSION, new_forest_car_temp_path_in, }; use crate::db::car::{ForestCar, ManyCar}; -use crate::db::{Blockstore, EthMappingsStore}; use crate::networks::ChainConfig; +use crate::prelude::*; use crate::rpc::sync::SnapshotProgressTracker; use crate::shim::clock::ChainEpoch; use crate::state_manager::StateManager; -use crate::utils::ShallowClone as _; use crate::utils::db::car_stream::CarStream; use crate::utils::io::EitherMmapOrRandomAccessFile; use crate::utils::net::{DownloadFileOption, download_to}; @@ -22,7 +21,6 @@ use std::{ ffi::OsStr, fs, path::{Path, PathBuf}, - sync::Arc, time, }; use tokio::io::AsyncWriteExt; @@ -329,14 +327,11 @@ async fn transcode_into_forest_car(from: &Path, to: &Path) -> anyhow::Result<()> Ok(()) } -async fn process_ts( +async fn process_ts( ts: &Tipset, - state_manager: &Arc>, + state_manager: &StateManager, delegated_messages: &mut Vec<(crate::message::SignedMessage, u64)>, -) -> anyhow::Result<()> -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +) -> anyhow::Result<()> { let epoch = ts.epoch(); let tsk = ts.key().clone(); @@ -348,7 +343,7 @@ where .headers_delegated_messages(ts.block_headers().iter())?, ); tracing::trace!("Indexing tipset @{}: {}", epoch, &tsk); - tsk.save(state_manager.blockstore())?; + tsk.save(state_manager.db())?; Ok(()) } @@ -375,14 +370,11 @@ impl std::fmt::Display for RangeSpec { /// - [`struct@EthHash`] -> Delegated message [`Cid`]. /// /// This function traverses the chain store and populates these columns accordingly. -pub async fn backfill_db( - state_manager: &Arc>, +pub async fn backfill_db( + state_manager: &StateManager, head_ts: &Tipset, spec: RangeSpec, -) -> anyhow::Result<()> -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +) -> anyhow::Result<()> { tracing::info!("Starting index backfill..."); let mut delegated_messages = vec![]; @@ -393,7 +385,7 @@ where RangeSpec::To(to_epoch) => { for ts in head_ts .shallow_clone() - .chain(&state_manager.chain_store().blockstore()) + .chain(&state_manager.chain_store().db()) .take_while(|ts| ts.epoch() >= to_epoch) { process_ts(&ts, state_manager, &mut delegated_messages).await?; @@ -403,7 +395,7 @@ where RangeSpec::NumTipsets(n_tipsets) => { for ts in head_ts .shallow_clone() - .chain(&state_manager.chain_store().blockstore()) + .chain(&state_manager.chain_store().db()) .take(n_tipsets) { process_ts(&ts, state_manager, &mut delegated_messages).await?; diff --git a/src/daemon/mod.rs b/src/daemon/mod.rs index cbb8f7758b30..670dd30a6a25 100644 --- a/src/daemon/mod.rs +++ b/src/daemon/mod.rs @@ -16,15 +16,13 @@ use crate::cli_shared::{ chain_path, cli::{CliOpts, Config}, }; -use crate::daemon::{ - context::{AppContext, DbType}, - db_util::import_chain_as_forest_car, -}; +use crate::daemon::{context::AppContext, db_util::import_chain_as_forest_car}; use crate::db::gc::SnapshotGarbageCollector; use crate::db::ttl::EthMappingCollector; use crate::libp2p::{Libp2pService, PeerManager}; use crate::message_pool::{MessagePool, MpoolConfig, MpoolLocker, NonceTracker}; use crate::networks::{self, ChainConfig}; +use crate::prelude::*; use crate::rpc::RPCState; use crate::rpc::eth::filter::EthEventHandler; use crate::rpc::start_rpc; @@ -32,7 +30,7 @@ use crate::shim::clock::ChainEpoch; use crate::shim::state_tree::StateTree; use crate::shim::version::NetworkVersion; use crate::utils::misc::env::is_env_truthy; -use crate::utils::{self, ShallowClone as _}; +use crate::utils::{self}; use crate::utils::{proofs_api::ensure_proof_params_downloaded, version::FOREST_VERSION_STRING}; use anyhow::{Context as _, bail}; use backon::{ExponentialBuilder, Retryable}; @@ -53,7 +51,7 @@ use tokio::{ }; use tracing::{debug, info, warn}; -pub static GLOBAL_SNAPSHOT_GC: OnceLock>> = OnceLock::new(); +pub static GLOBAL_SNAPSHOT_GC: OnceLock> = OnceLock::new(); /// Increase the file descriptor limit to a reasonable number. /// This prevents the node from failing if the default soft limit is too low. @@ -181,7 +179,7 @@ async fn maybe_import_snapshot( let validation_range = validation_range(current_height, validate_from)?; // `validate_range` is CPU-bound (drives rayon-parallel VM execution) and // can run for minutes. Safer to spawn it on a blocking thread. - let state_manager = ctx.state_manager.clone(); + let state_manager = ctx.state_manager.shallow_clone(); tokio::task::spawn_blocking(move || state_manager.validate_range(validation_range)) .await??; } @@ -235,30 +233,21 @@ async fn maybe_start_metrics_service( let db = ctx.db.writer().clone(); let get_chain_head_height = Arc::new({ - // Use `Weak` to not dead lock GC. - let chain_store = Arc::downgrade(ctx.state_manager.chain_store()); - move || { - chain_store - .upgrade() - .map(|cs| cs.heaviest_tipset().epoch()) - .unwrap_or_default() - } + let cs = ctx.state_manager.chain_store().shallow_clone(); + move || cs.heaviest_tipset().epoch() }); let get_chain_head_actor_version = Arc::new({ - // Use `Weak` to not dead lock GC. - let chain_store = Arc::downgrade(ctx.state_manager.chain_store()); + let cs = ctx.state_manager.chain_store().shallow_clone(); move || { - if let Some(cs) = chain_store.upgrade() - && let Ok(state) = StateTree::new_from_root( - cs.blockstore().clone(), - cs.heaviest_tipset().parent_state(), - ) + if let Ok(state) = + StateTree::new_from_root(cs.db(), cs.heaviest_tipset().parent_state()) && let Ok(bundle_meta) = state.get_actor_bundle_metadata() && let Ok(actor_version) = bundle_meta.actor_major_version() { - return actor_version; + actor_version + } else { + 0 } - 0 } }); services.spawn({ @@ -296,7 +285,7 @@ async fn create_p2p_service( services: &mut JoinSet>, config: &mut Config, ctx: &AppContext, -) -> anyhow::Result> { +) -> anyhow::Result { // if bootstrap peers are not set, set them if config.network.bootstrap_peers.is_empty() { config.network.bootstrap_peers = ctx.state_manager.chain_config().bootstrap_peers.clone(); @@ -307,7 +296,7 @@ async fn create_p2p_service( // Libp2p service setup let p2p_service = Libp2pService::new( config.network.clone(), - Arc::clone(ctx.state_manager.chain_store()), + ctx.state_manager.chain_store().shallow_clone(), peer_manager.clone(), ctx.net_keypair.clone(), config.chain.genesis_name(), @@ -319,41 +308,40 @@ async fn create_p2p_service( fn create_mpool( services: &mut JoinSet>, - p2p_service: &Libp2pService, + p2p_service: &Libp2pService, ctx: &AppContext, -) -> anyhow::Result>>>> { +) -> anyhow::Result> { Ok(MessagePool::new( - ctx.state_manager.chain_store().clone(), + ctx.state_manager.chain_store().shallow_clone(), p2p_service.network_sender().clone(), MpoolConfig::load_config(ctx.db.writer().as_ref())?, ctx.state_manager.chain_config().clone(), services, - ) - .map(Arc::new)?) + )?) } fn create_chain_follower( opts: &CliOpts, - p2p_service: &Libp2pService, - mpool: Arc>>>, + p2p_service: &Libp2pService, + mpool: MessagePool, ctx: &AppContext, -) -> anyhow::Result>> { +) -> anyhow::Result { let network_send = p2p_service.network_sender().clone(); let peer_manager = p2p_service.peer_manager().clone(); - let network = SyncNetworkContext::new(network_send, peer_manager, ctx.db.clone()); - Ok(Arc::new(ChainFollower::new( - ctx.state_manager.clone(), + let network = SyncNetworkContext::new(network_send, peer_manager, ctx.db.clone().into()); + Ok(ChainFollower::new( + ctx.state_manager.shallow_clone(), network, Tipset::from(ctx.state_manager.chain_store().genesis_block_header()), p2p_service.network_receiver(), opts.stateless, mpool, - ))) + )) } fn start_chain_follower_service( services: &mut JoinSet>, - chain_follower: Arc>, + chain_follower: ChainFollower, ) { services.spawn(async move { chain_follower.run().await }); } @@ -361,8 +349,8 @@ fn start_chain_follower_service( async fn maybe_start_health_check_service( services: &mut JoinSet>, config: &Config, - p2p_service: &Libp2pService, - chain_follower: &ChainFollower, + p2p_service: &Libp2pService, + chain_follower: &ChainFollower, ctx: &AppContext, ) -> anyhow::Result<()> { if config.client.enable_health_check { @@ -395,7 +383,7 @@ fn maybe_start_gc_service( services: &mut JoinSet>, opts: &CliOpts, config: &Config, - chain_follower: Arc>, + chain_follower: ChainFollower, ) -> anyhow::Result<()> { // If the node is stateless, GC shouldn't get triggered even on demand. if opts.stateless { @@ -435,8 +423,8 @@ fn maybe_start_gc_service( fn maybe_start_rpc_service( services: &mut JoinSet>, config: &Config, - mpool: Arc>>>, - chain_follower: &ChainFollower, + mpool: MessagePool, + chain_follower: &ChainFollower, start_time: chrono::DateTime, shutdown: mpsc::Sender<()>, rpc_stop_handle: jsonrpsee::server::StopHandle, @@ -552,7 +540,7 @@ fn maybe_start_f3_service(opts: &CliOpts, config: &Config, ctx: &AppContext) -> } }); tokio::task::spawn({ - let chain_store = ctx.chain_store().clone(); + let chain_store = ctx.chain_store().shallow_clone(); async move { // wait 1s to let F3 RPC server start tokio::time::sleep(Duration::from_secs(1)).await; @@ -605,7 +593,7 @@ fn maybe_start_indexer_service( && !ctx.state_manager.chain_config().is_devnet() { let mut head_changes_rx = ctx.state_manager.chain_store().subscribe_head_changes(); - let chain_store = ctx.state_manager.chain_store().clone(); + let chain_store = ctx.state_manager.chain_store().shallow_clone(); services.spawn(async move { tracing::info!("Starting indexer service"); @@ -630,12 +618,12 @@ fn maybe_start_indexer_service( // Run the collector only if chain indexer is enabled if let Some(retention_epochs) = config.chain_indexer.gc_retention_epochs { - let chain_store = ctx.state_manager.chain_store().clone(); + let chain_store = ctx.state_manager.chain_store().shallow_clone(); let chain_config = ctx.state_manager.chain_config().clone(); services.spawn(async move { tracing::info!("Starting collector for eth_mappings"); let mut collector = EthMappingCollector::new( - chain_store.blockstore().clone(), + chain_store.db_owned(), chain_config.eth_chain_id, retention_epochs.into(), ); @@ -690,12 +678,12 @@ pub(super) async fn start_services( let p2p_service = create_p2p_service(&mut services, &mut config, &ctx).await?; let mpool = create_mpool(&mut services, &p2p_service, &ctx)?; - let chain_follower = create_chain_follower(opts, &p2p_service, mpool.clone(), &ctx)?; + let chain_follower = create_chain_follower(opts, &p2p_service, mpool.shallow_clone(), &ctx)?; maybe_start_rpc_service( &mut services, &config, - mpool.clone(), + mpool.shallow_clone(), &chain_follower, start_time, shutdown_send.clone(), @@ -711,7 +699,7 @@ pub(super) async fn start_services( } warmup_in_background(&ctx); - maybe_start_gc_service(&mut services, opts, &config, chain_follower.clone())?; + maybe_start_gc_service(&mut services, opts, &config, chain_follower.shallow_clone())?; maybe_start_metrics_service(&mut services, &config, &ctx).await?; maybe_start_f3_service(opts, &config, &ctx)?; maybe_start_health_check_service(&mut services, &config, &p2p_service, &chain_follower, &ctx) @@ -731,7 +719,7 @@ pub(super) async fn start_services( fn warmup_in_background(ctx: &AppContext) { // Populate `tipset_by_height` cache - let cs = ctx.chain_store().clone(); + let cs = ctx.chain_store().shallow_clone(); tokio::task::spawn_blocking(move || { let start = Instant::now(); match cs.chain_index().tipset_by_height( diff --git a/src/db/blockstore_with_write_buffer.rs b/src/db/blockstore_with_write_buffer.rs index e4cc9677e7a1..2f050ef383bb 100644 --- a/src/db/blockstore_with_write_buffer.rs +++ b/src/db/blockstore_with_write_buffer.rs @@ -1,10 +1,8 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT +use crate::prelude::*; use ahash::{HashMap, HashMapExt}; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; -use itertools::Itertools; use parking_lot::RwLock; pub struct BlockstoreWithWriteBuffer { diff --git a/src/db/car/any.rs b/src/db/car/any.rs index d6cd962d931a..f8c9851adc7d 100644 --- a/src/db/car/any.rs +++ b/src/db/car/any.rs @@ -11,9 +11,8 @@ use super::{CacheKey, RandomAccessFileReader, ZstdFrameCache}; use crate::blocks::{Tipset, TipsetKey}; use crate::chain::FilecoinSnapshotMetadata; +use crate::prelude::*; use crate::utils::io::EitherMmapOrRandomAccessFile; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; use itertools::Either; use positioned_io::ReadAt; use std::{ diff --git a/src/db/car/many.rs b/src/db/car/many.rs index 8e373dc54806..22a53841a3dc 100644 --- a/src/db/car/many.rs +++ b/src/db/car/many.rs @@ -16,9 +16,9 @@ use crate::db::{ SettingsStoreExt, }; use crate::libp2p_bitswap::BitswapStoreReadWrite; +use crate::prelude::*; use crate::rpc::eth::types::EthHash; use crate::shim::clock::ChainEpoch; -use crate::utils::ShallowClone as _; use crate::utils::io::EitherMmapOrRandomAccessFile; use crate::utils::multihash::prelude::*; use crate::{blocks::Tipset, libp2p_bitswap::BitswapStoreRead}; @@ -325,7 +325,9 @@ impl super::super::HeaviestTipsetKeyProvider for } impl BlockstoreWriteOpsSubscribable for ManyCar { - fn subscribe_write_ops(&self) -> tokio::sync::broadcast::Receiver> { + fn subscribe_write_ops( + &self, + ) -> anyhow::Result>> { self.writer().subscribe_write_ops() } diff --git a/src/db/car/mod.rs b/src/db/car/mod.rs index 37236fee93e9..2f2293149b36 100644 --- a/src/db/car/mod.rs +++ b/src/db/car/mod.rs @@ -12,17 +12,17 @@ pub use many::{ManyCar, ReloadableManyCar}; pub use plain::PlainCar; use bytes::Bytes; -use cid::Cid; use positioned_io::{ReadAt, Size}; use std::{ num::NonZeroUsize, sync::{ - Arc, LazyLock, + LazyLock, atomic::{AtomicUsize, Ordering}, }, }; -use crate::utils::{ShallowClone, cache::SizeTrackingLruCache, get_size::CidWrapper}; +use crate::prelude::*; +use crate::utils::{cache::SizeTrackingLruCache, get_size::CidWrapper}; pub trait RandomAccessFileReader: ReadAt + Size + Send + Sync + 'static {} impl RandomAccessFileReader for X {} diff --git a/src/db/db_impl.rs b/src/db/db_impl.rs new file mode 100644 index 000000000000..2936e195c7f6 --- /dev/null +++ b/src/db/db_impl.rs @@ -0,0 +1,129 @@ +// Copyright 2019-2026 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +use super::{ + car::ManyCar, + parity_db::{GarbageCollectableDb, GarbageCollectableParityDb, ParityDb}, + *, +}; +use crate::{ + db::car::ReloadableManyCar, libp2p_bitswap::*, prelude::*, + tool::subcommands::api_cmd::generate_test_snapshot::ReadOpsTrackingStore, +}; +use ambassador::Delegate; +use spire_enum::prelude::delegated_enum; +use std::path::PathBuf; + +#[derive(Delegate)] +#[delegate(SettingsStore)] +#[delegate(EthMappingsStore)] +#[delegate(HeaviestTipsetKeyProvider)] +#[delegate(BitswapStoreRead)] +#[delegate(BitswapStoreReadWrite)] +#[delegated_enum(impl_conversions)] +pub enum DbImpl { + ManyCarWithGarbageCollectableParityDb(Arc>>), + ManyCarWithMemoryDB(Arc>), + ManyCarParityDb(Arc>), + Memory(Arc), + ReadOpsTrackingManyCarParityDb(Arc>>), +} + +impl ShallowClone for DbImpl { + fn shallow_clone(&self) -> Self { + delegate_db_impl!(self.shallow_clone().into()) + } +} + +impl Blockstore for DbImpl { + fn get(&self, k: &Cid) -> anyhow::Result>> { + delegate_db_impl!(self => |i| Blockstore::get(i, k)) + } + + fn put_keyed(&self, k: &Cid, block: &[u8]) -> anyhow::Result<()> { + delegate_db_impl!(self => |i| Blockstore::put_keyed(i, k, block)) + } + + fn has(&self, k: &Cid) -> anyhow::Result { + delegate_db_impl!(self => |i| Blockstore::has(i, k)) + } + + #[allow(clippy::disallowed_types)] + fn put( + &self, + mh_code: multihash_codetable::Code, + block: &fvm_ipld_blockstore::Block, + ) -> anyhow::Result + where + Self: Sized, + D: AsRef<[u8]>, + { + delegate_db_impl!(self => |i| Blockstore::put(i, mh_code, block)) + } + + #[allow(clippy::disallowed_types)] + fn put_many(&self, blocks: I) -> anyhow::Result<()> + where + Self: Sized, + D: AsRef<[u8]>, + I: IntoIterator)>, + { + delegate_db_impl!(self => |i| Blockstore::put_many(i, blocks)) + } + + fn put_many_keyed(&self, blocks: I) -> anyhow::Result<()> + where + Self: Sized, + D: AsRef<[u8]>, + I: IntoIterator, + { + delegate_db_impl!(self => |i| Blockstore::put_many_keyed(i, blocks)) + } +} + +impl GarbageCollectableDb for DbImpl { + fn reset_gc_columns(&self) -> anyhow::Result<()> { + match self { + Self::ManyCarWithGarbageCollectableParityDb(db) => db.reset_gc_columns(), + _ => anyhow::bail!("db is not garbage collectable"), + } + } +} + +impl BlockstoreWriteOpsSubscribable for DbImpl { + fn subscribe_write_ops( + &self, + ) -> anyhow::Result>> { + if let Self::ManyCarWithGarbageCollectableParityDb(db) = self { + db.subscribe_write_ops() + } else { + anyhow::bail!("not supported") + } + } + + fn unsubscribe_write_ops(&self) { + if let Self::ManyCarWithGarbageCollectableParityDb(db) = self { + db.unsubscribe_write_ops(); + } + } +} + +impl ReloadableManyCar for DbImpl { + fn clear_and_reload_cars(&self, files: impl Iterator) -> anyhow::Result<()> { + match self { + Self::ManyCarWithGarbageCollectableParityDb(db) => db.clear_and_reload_cars(files), + Self::ManyCarWithMemoryDB(db) => db.clear_and_reload_cars(files), + Self::ManyCarParityDb(db) => db.clear_and_reload_cars(files), + _ => anyhow::bail!("not supported"), + } + } + + fn heaviest_car_tipset(&self) -> anyhow::Result { + match self { + Self::ManyCarWithGarbageCollectableParityDb(db) => db.heaviest_car_tipset(), + Self::ManyCarWithMemoryDB(db) => db.heaviest_car_tipset(), + Self::ManyCarParityDb(db) => db.heaviest_car_tipset(), + _ => anyhow::bail!("not supported"), + } + } +} diff --git a/src/db/db_mode.rs b/src/db/db_mode.rs index 6de989ccc7ec..fe770701faf9 100644 --- a/src/db/db_mode.rs +++ b/src/db/db_mode.rs @@ -6,9 +6,9 @@ use std::{ path::{Path, PathBuf}, }; -use anyhow::Context as _; use semver::Version; +use crate::prelude::*; use crate::utils::version::FOREST_VERSION; /// Environment variable used to set the development mode @@ -92,8 +92,6 @@ impl DbMode { #[cfg(test)] mod tests { - use itertools::Itertools; - use super::*; use std::env; diff --git a/src/db/either.rs b/src/db/either.rs index 3757b21f334b..dffafc815b7f 100644 --- a/src/db/either.rs +++ b/src/db/either.rs @@ -2,18 +2,25 @@ // SPDX-License-Identifier: Apache-2.0, MIT use super::*; +use spire_enum::prelude::delegated_enum; +#[delegated_enum] pub enum Either { Left(A), Right(B), } impl Blockstore for Either { + fn get(&self, k: &Cid) -> anyhow::Result>> { + delegate_either!(self.get(k)) + } + + fn put_keyed(&self, k: &Cid, block: &[u8]) -> anyhow::Result<()> { + delegate_either!(self.put_keyed(k, block)) + } + fn has(&self, k: &Cid) -> anyhow::Result { - match self { - Self::Left(v) => v.has(k), - Self::Right(v) => v.has(k), - } + delegate_either!(self.has(k)) } #[allow(clippy::disallowed_types)] @@ -26,10 +33,7 @@ impl Blockstore for Either { Self: Sized, D: AsRef<[u8]>, { - match self { - Self::Left(v) => v.put(mh_code, block), - Self::Right(v) => v.put(mh_code, block), - } + delegate_either!(self.put(mh_code, block)) } #[allow(clippy::disallowed_types)] @@ -39,10 +43,7 @@ impl Blockstore for Either { D: AsRef<[u8]>, I: IntoIterator)>, { - match self { - Self::Left(v) => v.put_many(blocks), - Self::Right(v) => v.put_many(blocks), - } + delegate_either!(self.put_many(blocks)) } fn put_many_keyed(&self, blocks: I) -> anyhow::Result<()> @@ -51,23 +52,6 @@ impl Blockstore for Either { D: AsRef<[u8]>, I: IntoIterator, { - match self { - Self::Left(v) => v.put_many_keyed(blocks), - Self::Right(v) => v.put_many_keyed(blocks), - } - } - - fn get(&self, k: &Cid) -> anyhow::Result>> { - match self { - Self::Left(v) => v.get(k), - Self::Right(v) => v.get(k), - } - } - - fn put_keyed(&self, k: &Cid, block: &[u8]) -> anyhow::Result<()> { - match self { - Self::Left(v) => v.put_keyed(k, block), - Self::Right(v) => v.put_keyed(k, block), - } + delegate_either!(self.put_many_keyed(blocks)) } } diff --git a/src/db/gc/snapshot.rs b/src/db/gc/snapshot.rs index 5b27b74242ef..3718d3c31e5d 100644 --- a/src/db/gc/snapshot.rs +++ b/src/db/gc/snapshot.rs @@ -41,12 +41,14 @@ use crate::chain::{ChainStore, ExportOptions}; use crate::chain_sync::ChainFollower; use crate::cid_collections::FileBackedCidHashSet; use crate::cli_shared::chain_path; +use crate::db::DbImpl; use crate::db::{ - BlockstoreWriteOpsSubscribable, CAR_DB_DIR_NAME, HeaviestTipsetKeyProvider, SettingsStore, + BlockstoreWriteOpsSubscribable, CAR_DB_DIR_NAME, HeaviestTipsetKeyProvider, car::{ForestCar, ReloadableManyCar, forest::new_forest_car_temp_path_in}, db_engine::db_root, parity_db::GarbageCollectableDb, }; +use crate::prelude::*; use crate::shim::clock::EPOCHS_IN_DAY; use crate::utils::io::EitherMmapOrRandomAccessFile; use ahash::HashMap; @@ -57,21 +59,18 @@ use parking_lot::RwLock; use sha2::Sha256; use std::{ path::PathBuf, - sync::{ - Arc, - atomic::{AtomicBool, Ordering}, - }, + sync::atomic::{AtomicBool, Ordering}, time::{Duration, Instant}, }; use tokio::task::JoinSet; -pub struct SnapshotGarbageCollector { +pub struct SnapshotGarbageCollector { chain_tmp_root: PathBuf, car_db_dir: PathBuf, recent_state_roots: i64, running: AtomicBool, blessed_lite_snapshot: RwLock>, - chain_follower: Arc>, + chain_follower: ChainFollower, // On mainnet, it takes ~50MiB-200MiB RAM, depending on the time cost of snapshot export memory_db: RwLock>>, memory_db_head_key: RwLock>, @@ -81,22 +80,8 @@ pub struct SnapshotGarbageCollector { progress_tx: RwLock>>, } -impl SnapshotGarbageCollector -where - DB: Blockstore - + GarbageCollectableDb - + ReloadableManyCar - + SettingsStore - + HeaviestTipsetKeyProvider - + BlockstoreWriteOpsSubscribable - + Send - + Sync - + 'static, -{ - pub fn new( - chain_follower: Arc>, - config: &crate::Config, - ) -> anyhow::Result { +impl SnapshotGarbageCollector { + pub fn new(chain_follower: ChainFollower, config: &crate::Config) -> anyhow::Result { let chain_data_path = chain_path(config); let chain_tmp_root = chain_data_path.join("tmp"); std::fs::create_dir_all(&chain_tmp_root)?; @@ -231,7 +216,7 @@ where ); let temp_path = new_forest_car_temp_path_in(&self.car_db_dir)?; let file = tokio::fs::File::create(&temp_path).await?; - let mut db_write_ops_rx = db.subscribe_write_ops(); + let mut db_write_ops_rx = db.subscribe_write_ops()?; let mut joinset = JoinSet::new(); joinset.spawn(async move { let mut map = HashMap::default(); @@ -306,7 +291,7 @@ where // Reset parity-db columns tokio::task::spawn_blocking({ - let db = db.clone(); + let db = db.shallow_clone(); move || db.reset_gc_columns() }) .await??; @@ -396,12 +381,12 @@ where Ok(()) } - fn cs(&self) -> &Arc> { + fn cs(&self) -> &ChainStore { self.chain_follower.state_manager.chain_store() } - fn db(&self) -> &Arc { - self.chain_follower.state_manager.blockstore() + fn db(&self) -> &DbImpl { + self.chain_follower.state_manager.db() } fn sync_status(&self) -> &crate::chain_sync::SyncStatus { diff --git a/src/db/memory.rs b/src/db/memory.rs index bce48b362353..c72baee39b27 100644 --- a/src/db/memory.rs +++ b/src/db/memory.rs @@ -5,15 +5,12 @@ use super::{EthMappingsStore, SettingsStore, SettingsStoreExt}; use crate::blocks::{Tipset, TipsetKey}; use crate::db::PersistentStore; use crate::libp2p_bitswap::{BitswapStoreRead, BitswapStoreReadWrite}; +use crate::prelude::*; use crate::rpc::eth::types::EthHash; use crate::shim::clock::ChainEpoch; use crate::utils::db::car_stream::CarBlock; use crate::utils::multihash::prelude::*; use ahash::HashMap; -use anyhow::Context as _; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; -use itertools::Itertools; use nunny::Vec as NonEmpty; use parking_lot::RwLock; diff --git a/src/db/mod.rs b/src/db/mod.rs index a5aad69b7d1c..78518517cdc6 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -4,25 +4,28 @@ mod blockstore_with_read_cache; mod blockstore_with_write_buffer; pub mod car; +mod db_impl; +mod db_mode; +mod either; +pub mod gc; mod memory; +pub mod migration; pub mod parity_db; pub mod parity_db_config; - -pub mod gc; pub mod ttl; + pub use blockstore_with_read_cache::*; pub use blockstore_with_write_buffer::BlockstoreWithWriteBuffer; -pub use memory::MemoryDB; -mod db_mode; -mod either; -pub mod migration; +pub use db_impl::DbImpl; pub use either::Either; +pub use fvm_ipld_blockstore::{Blockstore, MemoryBlockstore}; +pub use memory::MemoryDB; use crate::blocks::{Tipset, TipsetKey}; use crate::rpc::eth::types::EthHash; -use anyhow::{Context as _, bail}; +use ambassador::delegatable_trait; +use anyhow::Context as _; use cid::Cid; -pub use fvm_ipld_blockstore::{Blockstore, MemoryBlockstore}; use serde::Serialize; use serde::de::DeserializeOwned; @@ -38,6 +41,7 @@ pub mod setting_keys { /// Interface used to store and retrieve settings from the database. /// To store IPLD blocks, use the `BlockStore` trait. #[auto_impl::auto_impl(&, Arc)] +#[delegatable_trait] pub trait SettingsStore { /// Reads binary field from the Settings store. This should be used for /// non-serializable data. For serializable data, use [`SettingsStoreExt::read_obj`]. @@ -89,6 +93,7 @@ impl SettingsStoreExt for T { /// Interface used to store and retrieve Ethereum mappings from the database. /// To store IPLD blocks, use the `BlockStore` trait. #[auto_impl::auto_impl(&, Arc)] +#[delegatable_trait] pub trait EthMappingsStore { /// Reads binary field from the `EthMappings` store. This should be used for /// non-serializable data. For serializable data, use [`EthMappingsStoreExt::read_obj`]. @@ -115,41 +120,6 @@ pub trait EthMappingsStore { fn set_tipset_key_at_epoch(&self, ts: &Tipset) -> anyhow::Result<()>; } -pub struct DummyStore {} - -const INDEXER_ERROR: &str = - "indexer disabled, enable with chain_indexer.enable_indexer / FOREST_CHAIN_INDEXER_ENABLED"; - -impl EthMappingsStore for DummyStore { - fn read_bin(&self, _key: &EthHash) -> anyhow::Result>> { - bail!(INDEXER_ERROR) - } - - fn write_bin(&self, _key: &EthHash, _value: &[u8]) -> anyhow::Result<()> { - bail!(INDEXER_ERROR) - } - - fn exists(&self, _key: &EthHash) -> anyhow::Result { - bail!(INDEXER_ERROR) - } - - fn get_message_cids(&self) -> anyhow::Result> { - bail!(INDEXER_ERROR) - } - - fn delete(&self, _keys: Vec) -> anyhow::Result<()> { - bail!(INDEXER_ERROR) - } - - fn tipset_key_by_epoch(&self, _epoch: i64) -> anyhow::Result> { - bail!(INDEXER_ERROR) - } - - fn set_tipset_key_at_epoch(&self, _ts: &Tipset) -> anyhow::Result<()> { - bail!(INDEXER_ERROR) - } -} - pub trait EthMappingsStoreExt { fn read_obj(&self, key: &EthHash) -> anyhow::Result>; fn write_obj(&self, key: &EthHash, value: &V) -> anyhow::Result<()>; @@ -200,6 +170,7 @@ impl PersistentStore for MemoryBlockstore { } #[auto_impl::auto_impl(&, Arc)] +#[delegatable_trait] pub trait HeaviestTipsetKeyProvider { /// Returns the currently tracked heaviest tipset. fn heaviest_tipset_key(&self) -> anyhow::Result>; @@ -210,7 +181,9 @@ pub trait HeaviestTipsetKeyProvider { #[auto_impl::auto_impl(&, Arc)] pub trait BlockstoreWriteOpsSubscribable { - fn subscribe_write_ops(&self) -> tokio::sync::broadcast::Receiver>; + fn subscribe_write_ops( + &self, + ) -> anyhow::Result>>; fn unsubscribe_write_ops(&self); } diff --git a/src/db/parity_db.rs b/src/db/parity_db.rs index eed482a0fed0..12d913e35063 100644 --- a/src/db/parity_db.rs +++ b/src/db/parity_db.rs @@ -8,12 +8,10 @@ use super::{EthMappingsStore, PersistentStore, SettingsStore}; use crate::blocks::{Tipset, TipsetKey}; use crate::db::{DBStatistics, parity_db_config::ParityDbConfig}; use crate::libp2p_bitswap::{BitswapStoreRead, BitswapStoreReadWrite}; +use crate::prelude::*; use crate::rpc::eth::types::EthHash; use crate::utils::{broadcast::has_subscribers, multihash::prelude::*}; -use anyhow::Context as _; use bytes::Bytes; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::DAG_CBOR; use parity_db::{CompressionType, Db, Operation, Options}; use parking_lot::RwLock; @@ -388,15 +386,20 @@ impl ParityDb { } impl super::BlockstoreWriteOpsSubscribable for ParityDb { - fn subscribe_write_ops(&self) -> tokio::sync::broadcast::Receiver> { - let tx_lock = self.write_ops_broadcast_tx.read(); - if let Some(tx) = &*tx_lock { - return tx.subscribe(); + fn subscribe_write_ops( + &self, + ) -> anyhow::Result>> { + // Use double checks to avoid concurrent first-time subscribers to create duplicate channels + if let Some(tx) = self.write_ops_broadcast_tx.read().as_ref() { + return Ok(tx.subscribe()); + } + let mut tx_lock = self.write_ops_broadcast_tx.write(); + if let Some(tx) = tx_lock.as_ref() { + return Ok(tx.subscribe()); } - drop(tx_lock); let (tx, rx) = tokio::sync::broadcast::channel(65536); - *self.write_ops_broadcast_tx.write() = Some(tx); - rx + *tx_lock = Some(tx); + Ok(rx) } fn unsubscribe_write_ops(&self) { @@ -409,7 +412,6 @@ mod test { use super::*; use crate::db::{BlockstoreWriteOpsSubscribable, tests::db_utils::parity::TempParityDB}; use fvm_ipld_encoding::IPLD_RAW; - use itertools::Itertools as _; use nom::AsBytes; use std::ops::Deref; @@ -563,8 +565,8 @@ mod test { Cid::new_v1(IPLD_RAW, MultihashCode::Blake2b256.digest(&data[1])), ]; - let mut rx1 = db.subscribe_write_ops(); - let mut rx2 = db.subscribe_write_ops(); + let mut rx1 = db.subscribe_write_ops().unwrap(); + let mut rx2 = db.subscribe_write_ops().unwrap(); assert!(has_subscribers( db.write_ops_broadcast_tx.read().as_ref().unwrap() diff --git a/src/db/parity_db/gc.rs b/src/db/parity_db/gc.rs index df09fe887786..f7b49468f419 100644 --- a/src/db/parity_db/gc.rs +++ b/src/db/parity_db/gc.rs @@ -192,7 +192,9 @@ impl DBStatistics for GarbageCollectableParityDb { } impl BlockstoreWriteOpsSubscribable for GarbageCollectableParityDb { - fn subscribe_write_ops(&self) -> tokio::sync::broadcast::Receiver> { + fn subscribe_write_ops( + &self, + ) -> anyhow::Result>> { BlockstoreWriteOpsSubscribable::subscribe_write_ops(&*self.db.read()) } diff --git a/src/db/ttl/mod.rs b/src/db/ttl/mod.rs index d3c80644dd4c..40d1b3e35744 100644 --- a/src/db/ttl/mod.rs +++ b/src/db/ttl/mod.rs @@ -6,13 +6,12 @@ use crate::message::ChainMessage; use crate::rpc::eth::{eth_tx_from_signed_eth_message, types::EthHash}; use crate::shim::clock::{ChainEpoch, EPOCH_DURATION_SECONDS}; use fvm_ipld_blockstore::Blockstore; -use std::sync::Arc; use std::time::Duration; use super::EthMappingsStore; pub struct EthMappingCollector { - db: Arc, + db: DB, eth_chain_id: EthChainId, ttl: std::time::Duration, } @@ -20,7 +19,7 @@ pub struct EthMappingCollector { impl EthMappingCollector { /// Creates a `TTL` collector for the Ethereum mapping. /// - pub fn new(db: Arc, eth_chain_id: EthChainId, retention_epochs: ChainEpoch) -> Self { + pub fn new(db: DB, eth_chain_id: EthChainId, retention_epochs: ChainEpoch) -> Self { // Convert retention_epochs to number of seconds let secs = EPOCH_DURATION_SECONDS * retention_epochs; Self { @@ -41,7 +40,7 @@ impl EthMappingCollec duration.saturating_sub(Duration::from_secs(*timestamp)) > self.ttl }) .filter_map(|(cid, _)| { - let message = crate::chain::get_chain_message(self.db.as_ref(), cid); + let message = crate::chain::get_chain_message(&self.db, cid); if let Ok(ChainMessage::Signed(smsg)) = message { let result = eth_tx_from_signed_eth_message(&smsg, self.eth_chain_id); if let Ok((_, tx)) = result { @@ -72,7 +71,6 @@ impl EthMappingCollec pub async fn run(&mut self) -> anyhow::Result<()> { loop { tokio::time::sleep(self.ttl).await; - let duration = Duration::from_secs(chrono::Utc::now().timestamp() as u64); self.ttl_workflow(duration)?; } @@ -82,6 +80,7 @@ impl EthMappingCollec #[cfg(test)] mod test { use std::convert::TryFrom; + use std::sync::Arc; use chrono::{DateTime, TimeZone, Utc}; use cid::Cid; diff --git a/src/dev/subcommands/export_state_tree_cmd.rs b/src/dev/subcommands/export_state_tree_cmd.rs index 67360d175456..b133ba78495a 100644 --- a/src/dev/subcommands/export_state_tree_cmd.rs +++ b/src/dev/subcommands/export_state_tree_cmd.rs @@ -75,13 +75,7 @@ impl ExportStateTreeCommand { let genesis_header = read_genesis_header(None, chain_config.genesis_bytes(&db).await?.as_deref(), &db) .await?; - let chain_store = Arc::new(ChainStore::new( - db.clone(), - db.clone(), - db.clone(), - chain_config, - genesis_header, - )?); + let chain_store = ChainStore::new(db.clone(), chain_config, genesis_header)?; let start_ts = chain_store.chain_index().load_required_tipset_by_height( from, diff --git a/src/dev/subcommands/export_tipset_lookup_cmd.rs b/src/dev/subcommands/export_tipset_lookup_cmd.rs index 6e1593c5969c..69593b624d9c 100644 --- a/src/dev/subcommands/export_tipset_lookup_cmd.rs +++ b/src/dev/subcommands/export_tipset_lookup_cmd.rs @@ -69,20 +69,14 @@ impl ExportTipsetLookupCommand { let genesis_header = read_genesis_header(None, chain_config.genesis_bytes(&db).await?.as_deref(), &db) .await?; - let chain_store = Arc::new(ChainStore::new( - db.clone(), - db.clone(), - db.clone(), - chain_config, - genesis_header, - )?); + let chain_store = ChainStore::new(db.clone(), chain_config, genesis_header)?; let head = chain_store.heaviest_tipset(); let amt_db = Arc::new(MemoryDB::default()); let mut amt = Amt::new(&amt_db); let start = Instant::now(); - for ts in head.chain(chain_store.blockstore()) { + for ts in head.chain(chain_store.db()) { if let Some(from) = from && ts.epoch() > from { diff --git a/src/dev/subcommands/state_cmd.rs b/src/dev/subcommands/state_cmd.rs index c6f739a3aa83..48961c6067cd 100644 --- a/src/dev/subcommands/state_cmd.rs +++ b/src/dev/subcommands/state_cmd.rs @@ -9,15 +9,14 @@ use crate::{ genesis::read_genesis_header, interpreter::VMTrace, networks::{ChainConfig, NetworkChain}, + prelude::*, shim::clock::ChainEpoch, state_manager::{ExecutedTipset, StateManager}, tool::subcommands::api_cmd::generate_test_snapshot, - utils::ShallowClone as _, }; -use anyhow::Context as _; use human_repr::HumanCount as _; use nonzero_ext::nonzero; -use std::{num::NonZeroUsize, path::PathBuf, sync::Arc, time::Instant}; +use std::{num::NonZeroUsize, path::PathBuf, time::Instant}; /// Interact with Filecoin chain state #[derive(Debug, clap::Subcommand)] @@ -76,13 +75,7 @@ impl ComputeCommand { let genesis_header = read_genesis_header(None, chain_config.genesis_bytes(&db).await?.as_deref(), &db) .await?; - let chain_store = Arc::new(ChainStore::new( - db.clone(), - db.clone(), - db.clone(), - chain_config, - genesis_header, - )?); + let chain_store = ChainStore::new(db.clone(), chain_config, genesis_header)?; let chain_index = chain_store.chain_index(); let (ts, ts_next) = { // We don't want to track all entries that are visited by `tipset_by_height` @@ -111,7 +104,7 @@ impl ComputeCommand { ) }; let epoch = ts.epoch(); - let state_manager = Arc::new(StateManager::new(chain_store)?); + let state_manager = StateManager::new(chain_store)?; let ExecutedTipset { state_root, @@ -212,13 +205,7 @@ impl ValidateCommand { let genesis_header = read_genesis_header(None, chain_config.genesis_bytes(&db).await?.as_deref(), &db) .await?; - let chain_store = Arc::new(ChainStore::new( - db.clone(), - db.clone(), - db.clone(), - chain_config, - genesis_header, - )?); + let chain_store = ChainStore::new(db.clone(), chain_config, genesis_header)?; let chain_index = chain_store.chain_index(); let ts = { // We don't want to track all entries that are visited by `tipset_by_height` @@ -235,7 +222,7 @@ impl ValidateCommand { }; let epoch = ts.epoch(); let fts = load_full_tipset(&chain_store, ts.key())?; - let state_manager = Arc::new(StateManager::new(chain_store)?); + let state_manager = StateManager::new(chain_store)?; validate_tipset(&state_manager, fts, None).await?; let mut db_snapshot = vec![]; db.export_forest_car(&mut db_snapshot).await?; diff --git a/src/fil_cns/mod.rs b/src/fil_cns/mod.rs index d465b66d992e..20e50220fe04 100644 --- a/src/fil_cns/mod.rs +++ b/src/fil_cns/mod.rs @@ -1,14 +1,13 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use std::{fmt::Debug, sync::Arc}; +use std::fmt::Debug; use crate::beacon::BeaconSchedule; use crate::blocks::{Block, Tipset}; use crate::chain::{Error as ChainStoreError, Weight}; -use crate::db::EthMappingsStore; +use crate::prelude::*; use crate::state_manager::{Error as StateManagerError, StateManager}; use anyhow::anyhow; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::Error as ForestEncodingError; use nunny::Vec as NonEmpty; use thiserror::Error; @@ -69,12 +68,12 @@ pub struct FilecoinConsensus { } impl FilecoinConsensus { - pub async fn validate_block( + pub async fn validate_block( &self, - state_manager: Arc>, + state_manager: StateManager, block: Arc, ) -> Result<(), NonEmpty> { - validation::validate_block::<_>(state_manager, self.beacon.clone(), block).await + validation::validate_block(state_manager, self.beacon.clone(), block).await } } @@ -88,7 +87,7 @@ impl Debug for FilecoinConsensus { pub fn weight(db: &DB, ts: &Tipset) -> anyhow::Result where - DB: Blockstore, + DB: Blockstore + ShallowClone, { - weight::weight(&Arc::new(db), ts).map_err(|s| anyhow!(s)) + weight::weight(db, ts).map_err(|s| anyhow!(s)) } diff --git a/src/fil_cns/validation.rs b/src/fil_cns/validation.rs index 18f91e511252..109246b35c4d 100644 --- a/src/fil_cns/validation.rs +++ b/src/fil_cns/validation.rs @@ -1,14 +1,14 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use std::{collections::BTreeMap, sync::Arc}; +use std::collections::BTreeMap; use crate::beacon::{BeaconEntry, BeaconSchedule, IGNORE_DRAND}; use crate::blocks::{Block, CachingBlockHeader, Tipset}; use crate::chain::ChainStore; use crate::chain_sync::collect_errs; -use crate::db::EthMappingsStore; use crate::networks::{ChainConfig, Height}; +use crate::prelude::*; use crate::shim::actors::PowerActorStateLoad as _; use crate::shim::actors::power; use crate::shim::crypto::{ @@ -22,14 +22,10 @@ use crate::shim::{ version::NetworkVersion, }; use crate::state_manager::StateManager; -use crate::utils::ShallowClone; use crate::utils::encoding::prover_id_from_u64; -use cid::Cid; use fil_actors_shared::filecoin_proofs_api::{PublicReplicaInfo, SectorId, post}; use fil_actors_shared::v10::runtime::DomainSeparationTag; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::{bytes_32, to_vec}; -use itertools::Itertools; use nunny::Vec as NonEmpty; use tokio::task::JoinSet; @@ -47,14 +43,12 @@ fn to_errs>(e: E) -> NonEmpty( - state_manager: Arc>, +pub(in crate::fil_cns) async fn validate_block( + state_manager: StateManager, beacon_schedule: Arc, block: Arc, ) -> Result<(), NonEmpty> { - let chain_store = state_manager.chain_store().clone(); + let chain_store = state_manager.chain_store().shallow_clone(); let header = block.header(); block_sanity_checks(header).map_err(to_errs)?; @@ -97,9 +91,9 @@ pub(in crate::fil_cns) async fn validate_block< // Miner validations validations.spawn_blocking({ - let state_manager = state_manager.clone(); + let state_manager = state_manager.shallow_clone(); let base_tipset = base_tipset.shallow_clone(); - let block = block.clone(); + let block = block.shallow_clone(); move || { validate_miner( &state_manager, @@ -111,11 +105,11 @@ pub(in crate::fil_cns) async fn validate_block< // Winner election PoSt validations validations.spawn_blocking({ - let block = block.clone(); - let prev_beacon = prev_beacon.clone(); + let block = block.shallow_clone(); + let prev_beacon = prev_beacon.shallow_clone(); let base_tipset = base_tipset.shallow_clone(); - let state_manager = state_manager.clone(); - let lookback_state = lookback_state.clone(); + let state_manager = state_manager.shallow_clone(); + let lookback_state = lookback_state.shallow_clone(); move || { validate_winner_election( block.header(), @@ -163,7 +157,7 @@ pub(in crate::fil_cns) async fn validate_block< // Winning PoSt proof validation validations.spawn_blocking(move || { - verify_winning_post_proof::<_>( + verify_winning_post_proof( &state_manager, win_p_nv, block.header(), @@ -222,8 +216,8 @@ fn block_timestamp_checks( // Check that the miner power can be loaded. // Doesn't check that the miner actually has any power. -fn validate_miner( - state_manager: &StateManager, +fn validate_miner( + state_manager: &StateManager, miner_addr: &Address, tipset_state: &Cid, ) -> Result<(), FilecoinConsensusError> { @@ -232,24 +226,24 @@ fn validate_miner( .map_err(|_| FilecoinConsensusError::PowerActorUnavailable)? .ok_or(FilecoinConsensusError::PowerActorUnavailable)?; - let state = power::State::load(state_manager.blockstore(), actor.code, actor.state) + let state = power::State::load(state_manager.db(), actor.code, actor.state) .map_err(|err| FilecoinConsensusError::MinerPowerUnavailable(err.to_string()))?; state - .miner_power(state_manager.blockstore(), miner_addr) + .miner_power(state_manager.db(), miner_addr) .map_err(|err| FilecoinConsensusError::MinerPowerUnavailable(err.to_string()))?; Ok(()) } -fn validate_winner_election( +fn validate_winner_election( header: &CachingBlockHeader, base_tipset: &Tipset, lookback_tipset: &Tipset, lookback_state: &Cid, prev_beacon: &BeaconEntry, work_addr: &Address, - state_manager: &StateManager, + state_manager: &StateManager, ) -> Result<(), FilecoinConsensusError> { // Safe to unwrap because checked to `Some` in sanity check let election_proof = header.election_proof.as_ref().unwrap(); @@ -343,8 +337,8 @@ fn verify_election_post_vrf( verify_bls_sig(evrf, rand, worker).map_err(FilecoinConsensusError::VrfValidation) } -fn verify_winning_post_proof( - state_manager: &StateManager, +fn verify_winning_post_proof( + state_manager: &StateManager, network_version: NetworkVersion, header: &CachingBlockHeader, prev_beacon_entry: &BeaconEntry, diff --git a/src/fil_cns/weight.rs b/src/fil_cns/weight.rs index 563df969f49e..bbf8fd790357 100644 --- a/src/fil_cns/weight.rs +++ b/src/fil_cns/weight.rs @@ -1,13 +1,11 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use crate::blocks::Tipset; use crate::shim::actors::power; use crate::shim::state_tree::StateTree; -use fvm_ipld_blockstore::Blockstore; +use crate::{blocks::Tipset, prelude::*}; use num::{BigInt, Integer}; use num_traits::Zero; -use std::sync::Arc; // constants for Weight calculation /// The ratio of weight contributed by short-term vs long-term factors in a @@ -20,11 +18,11 @@ const BLOCKS_PER_EPOCH: u64 = 5; /// Returns the weight of provided [Tipset]. This function will load power actor /// state and calculate the total weight of the [Tipset]. -pub(in crate::fil_cns) fn weight(db: &Arc, ts: &Tipset) -> Result +pub(in crate::fil_cns) fn weight(db: &DB, ts: &Tipset) -> Result where - DB: Blockstore, + DB: Blockstore + ShallowClone, { - let state_tree = StateTree::new_from_tipset(Arc::clone(db), ts).map_err(|e| e.to_string())?; + let state_tree = StateTree::new_from_tipset(db, ts).map_err(|e| e.to_string())?; let state: power::State = state_tree.get_actor_state().map_err(|e| e.to_string())?; let tpow = state.into_total_quality_adj_power(); diff --git a/src/interpreter/fvm2.rs b/src/interpreter/fvm2.rs index def6978345b5..2917915ebd01 100644 --- a/src/interpreter/fvm2.rs +++ b/src/interpreter/fvm2.rs @@ -6,7 +6,6 @@ use std::{cell::Ref, sync::Arc}; use crate::blocks::{CachingBlockHeader, Tipset}; use crate::chain::{index::ChainIndex, store::ChainStore}; -use crate::db::EthMappingsStore; use crate::interpreter::errors::Error; use crate::interpreter::resolve_to_key_addr; use crate::networks::ChainConfig; @@ -20,10 +19,7 @@ use crate::shim::{ use crate::utils::encoding::from_slice_with_fallback; use anyhow::bail; use cid::Cid; -use fvm_ipld_blockstore::{ - Blockstore, - tracking::{BSStats, TrackingBlockstore}, -}; +use fvm_ipld_blockstore::tracking::{BSStats, TrackingBlockstore}; use fvm_shared2::{ address::Address, clock::ChainEpoch, @@ -31,23 +27,23 @@ use fvm_shared2::{ }; use fvm2::externs::{Consensus, Externs, Rand}; -pub struct ForestExternsV2 { +pub struct ForestExternsV2 { rand: Box, heaviest_tipset: Tipset, epoch: ChainEpoch, root: Cid, - chain_index: ChainIndex, + chain_index: ChainIndex, chain_config: Arc, bail: AtomicBool, } -impl ForestExternsV2 { +impl ForestExternsV2 { pub fn new( rand: impl Rand + 'static, heaviest_tipset: Tipset, epoch: ChainEpoch, root: Cid, - chain_index: ChainIndex, + chain_index: ChainIndex, chain_config: Arc, ) -> Self { ForestExternsV2 { @@ -61,10 +57,7 @@ impl ForestExternsV2 { } } - fn get_lookback_tipset_state_root_for_round(&self, height: ChainEpoch) -> anyhow::Result - where - DB: EthMappingsStore, - { + fn get_lookback_tipset_state_root_for_round(&self, height: ChainEpoch) -> anyhow::Result { let (_, st) = ChainStore::get_lookback_tipset_for_round( &self.chain_index, &self.chain_config, @@ -78,10 +71,7 @@ impl ForestExternsV2 { &self, miner_addr: &Address, height: ChainEpoch, - ) -> anyhow::Result<(Address, i64)> - where - DB: EthMappingsStore, - { + ) -> anyhow::Result<(Address, i64)> { if height < self.epoch - self.chain_config.policy.chain_finality { bail!( "cannot get worker key (current epoch: {}, height: {})", @@ -91,11 +81,11 @@ impl ForestExternsV2 { } let prev_root = self.get_lookback_tipset_state_root_for_round(height)?; - let lb_state = StateTree::new_from_root(Arc::clone(self.chain_index.db()), &prev_root)?; + let lb_state = StateTree::new_from_root(self.chain_index.db(), &prev_root)?; let actor = lb_state .get_actor(&miner_addr.into())? - .ok_or_else(|| anyhow::anyhow!("actor not found {:?}", miner_addr))?; + .ok_or_else(|| anyhow::anyhow!("actor not found {miner_addr}"))?; let tbs = TrackingBlockstore::new(self.chain_index.db()); @@ -103,7 +93,7 @@ impl ForestExternsV2 { let worker = ms.info(&tbs)?.worker; - let state = StateTree::new_from_root(Arc::clone(self.chain_index.db()), &self.root)?; + let state = StateTree::new_from_root(self.chain_index.db(), &self.root)?; let addr = resolve_to_key_addr(&state, &tbs, &worker)?; @@ -113,10 +103,7 @@ impl ForestExternsV2 { Ok((addr.into(), gas_used.round_up() as i64)) } - fn verify_block_signature(&self, bh: &CachingBlockHeader) -> anyhow::Result - where - DB: EthMappingsStore, - { + fn verify_block_signature(&self, bh: &CachingBlockHeader) -> anyhow::Result { let (worker_addr, gas_used) = self.worker_key_at_lookback(&bh.miner_address.into(), bh.epoch)?; @@ -130,9 +117,9 @@ impl ForestExternsV2 { } } -impl Externs for ForestExternsV2 {} +impl Externs for ForestExternsV2 {} -impl Rand for ForestExternsV2 { +impl Rand for ForestExternsV2 { fn get_chain_randomness(&self, round: ChainEpoch) -> anyhow::Result<[u8; 32]> { self.rand.get_chain_randomness(round) } @@ -142,7 +129,7 @@ impl Rand for ForestExternsV2 { } } -impl Consensus for ForestExternsV2 { +impl Consensus for ForestExternsV2 { // See https://github.com/filecoin-project/lotus/blob/v1.18.0/chain/vm/fvm.go#L102-L216 for reference implementation fn verify_consensus_fault( &self, diff --git a/src/interpreter/fvm3.rs b/src/interpreter/fvm3.rs index 13618876dc82..98703a7d7717 100644 --- a/src/interpreter/fvm3.rs +++ b/src/interpreter/fvm3.rs @@ -9,7 +9,6 @@ use crate::chain::{ ChainStore, index::{ChainIndex, ResolveNullTipset}, }; -use crate::db::EthMappingsStore; use crate::interpreter::errors::Error; use crate::interpreter::resolve_to_key_addr; use crate::networks::ChainConfig; @@ -22,10 +21,7 @@ use crate::shim::{ use crate::utils::encoding::from_slice_with_fallback; use anyhow::{Context as _, bail}; use cid::Cid; -use fvm_ipld_blockstore::{ - Blockstore, - tracking::{BSStats, TrackingBlockstore}, -}; +use fvm_ipld_blockstore::tracking::{BSStats, TrackingBlockstore}; use fvm_shared3::{ clock::ChainEpoch, consensus::{ConsensusFault, ConsensusFaultType}, @@ -35,23 +31,23 @@ use fvm3::{ gas::{Gas, GasTracker}, }; -pub struct ForestExterns { +pub struct ForestExterns { rand: Box, heaviest_tipset: Tipset, epoch: ChainEpoch, root: Cid, - chain_index: ChainIndex, + chain_index: ChainIndex, chain_config: Arc, bail: AtomicBool, } -impl ForestExterns { +impl ForestExterns { pub fn new( rand: impl Rand + 'static, heaviest_tipset: Tipset, epoch: ChainEpoch, root: Cid, - chain_index: ChainIndex, + chain_index: ChainIndex, chain_config: Arc, ) -> Self { ForestExterns { @@ -65,10 +61,7 @@ impl ForestExterns { } } - fn get_lookback_tipset_state_root_for_round(&self, height: ChainEpoch) -> anyhow::Result - where - DB: EthMappingsStore, - { + fn get_lookback_tipset_state_root_for_round(&self, height: ChainEpoch) -> anyhow::Result { let (_, st) = ChainStore::get_lookback_tipset_for_round( &self.chain_index, &self.chain_config, @@ -82,10 +75,7 @@ impl ForestExterns { &self, miner_addr: &Address, height: ChainEpoch, - ) -> anyhow::Result<(Address, i64)> - where - DB: EthMappingsStore, - { + ) -> anyhow::Result<(Address, i64)> { if height < self.epoch - self.chain_config.policy.chain_finality { bail!( "cannot get worker key (current epoch: {}, height: {})", @@ -95,7 +85,7 @@ impl ForestExterns { } let prev_root = self.get_lookback_tipset_state_root_for_round(height)?; - let lb_state = StateTree::new_from_root(Arc::clone(self.chain_index.db()), &prev_root)?; + let lb_state = StateTree::new_from_root(self.chain_index.db(), &prev_root)?; let actor = lb_state .get_actor(miner_addr)? @@ -107,7 +97,7 @@ impl ForestExterns { let worker = ms.info(&tbs)?.worker; - let state = StateTree::new_from_root(Arc::clone(self.chain_index.db()), &self.root)?; + let state = StateTree::new_from_root(self.chain_index.db(), &self.root)?; let addr = resolve_to_key_addr(&state, &tbs, &worker)?; @@ -117,10 +107,7 @@ impl ForestExterns { Ok((addr, gas_used.round_up() as i64)) } - fn verify_block_signature(&self, bh: &CachingBlockHeader) -> anyhow::Result - where - DB: EthMappingsStore, - { + fn verify_block_signature(&self, bh: &CachingBlockHeader) -> anyhow::Result { let (worker_addr, gas_used) = self.worker_key_at_lookback(&bh.miner_address, bh.epoch)?; bh.verify_signature_against(&worker_addr)?; @@ -137,9 +124,9 @@ impl ForestExterns { } } -impl Externs for ForestExterns {} +impl Externs for ForestExterns {} -impl Chain for ForestExterns { +impl Chain for ForestExterns { fn get_tipset_cid(&self, epoch: ChainEpoch) -> anyhow::Result { let ts = self .chain_index @@ -153,7 +140,7 @@ impl Chain for ForestExterns { } } -impl Rand for ForestExterns { +impl Rand for ForestExterns { fn get_chain_randomness(&self, round: ChainEpoch) -> anyhow::Result<[u8; 32]> { self.rand.get_chain_randomness(round) } @@ -163,7 +150,7 @@ impl Rand for ForestExterns { } } -impl Consensus for ForestExterns { +impl Consensus for ForestExterns { // See https://github.com/filecoin-project/lotus/blob/v1.18.0/chain/vm/fvm.go#L102-L216 for reference implementation fn verify_consensus_fault( &self, diff --git a/src/interpreter/fvm4.rs b/src/interpreter/fvm4.rs index f24213fbd9a0..306260649bea 100644 --- a/src/interpreter/fvm4.rs +++ b/src/interpreter/fvm4.rs @@ -9,7 +9,6 @@ use crate::chain::{ ChainStore, index::{ChainIndex, ResolveNullTipset}, }; -use crate::db::EthMappingsStore; use crate::interpreter::errors::Error; use crate::interpreter::resolve_to_key_addr; use crate::networks::{ChainConfig, Height, NetworkChain}; @@ -22,10 +21,7 @@ use crate::shim::{ use crate::utils::encoding::from_slice_with_fallback; use anyhow::{Context as _, bail}; use cid::Cid; -use fvm_ipld_blockstore::{ - Blockstore, - tracking::{BSStats, TrackingBlockstore}, -}; +use fvm_ipld_blockstore::tracking::{BSStats, TrackingBlockstore}; use fvm_shared4::{ clock::ChainEpoch, consensus::{ConsensusFault, ConsensusFaultType}, @@ -35,23 +31,23 @@ use fvm4::{ gas::{Gas, GasTracker}, }; -pub struct ForestExterns { +pub struct ForestExterns { rand: Box, heaviest_tipset: Tipset, epoch: ChainEpoch, root: Cid, - chain_index: ChainIndex, + chain_index: ChainIndex, chain_config: Arc, bail: AtomicBool, } -impl ForestExterns { +impl ForestExterns { pub fn new( rand: impl Rand + 'static, heaviest_tipset: Tipset, epoch: ChainEpoch, root: Cid, - chain_index: ChainIndex, + chain_index: ChainIndex, chain_config: Arc, ) -> Self { ForestExterns { @@ -65,10 +61,7 @@ impl ForestExterns { } } - fn get_lookback_tipset_state_root_for_round(&self, height: ChainEpoch) -> anyhow::Result - where - DB: EthMappingsStore, - { + fn get_lookback_tipset_state_root_for_round(&self, height: ChainEpoch) -> anyhow::Result { let (_, st) = ChainStore::get_lookback_tipset_for_round( &self.chain_index, &self.chain_config, @@ -82,10 +75,7 @@ impl ForestExterns { &self, miner_addr: &Address, height: ChainEpoch, - ) -> anyhow::Result<(Address, i64)> - where - DB: EthMappingsStore, - { + ) -> anyhow::Result<(Address, i64)> { if height < self.epoch - self.chain_config.policy.chain_finality { bail!( "cannot get worker key (current epoch: {}, height: {height}, miner address: {miner_addr})", @@ -94,7 +84,7 @@ impl ForestExterns { } let prev_root = self.get_lookback_tipset_state_root_for_round(height)?; - let lb_state = StateTree::new_from_root(Arc::clone(self.chain_index.db()), &prev_root)?; + let lb_state = StateTree::new_from_root(self.chain_index.db(), &prev_root)?; let actor = lb_state .get_actor(miner_addr)? @@ -106,7 +96,7 @@ impl ForestExterns { let worker = ms.info(&tbs)?.worker; - let state = StateTree::new_from_root(Arc::clone(self.chain_index.db()), &self.root)?; + let state = StateTree::new_from_root(self.chain_index.db(), &self.root)?; let addr = resolve_to_key_addr(&state, &tbs, &worker)?; @@ -116,10 +106,7 @@ impl ForestExterns { Ok((addr, gas_used.round_up() as i64)) } - fn verify_block_signature(&self, bh: &CachingBlockHeader) -> anyhow::Result - where - DB: EthMappingsStore, - { + fn verify_block_signature(&self, bh: &CachingBlockHeader) -> anyhow::Result { let (worker_addr, gas_used) = self.worker_key_at_lookback(&bh.miner_address, bh.epoch)?; bh.verify_signature_against(&worker_addr)?; @@ -136,9 +123,9 @@ impl ForestExterns { } } -impl Externs for ForestExterns {} +impl Externs for ForestExterns {} -impl Chain for ForestExterns { +impl Chain for ForestExterns { fn get_tipset_cid(&self, epoch: ChainEpoch) -> anyhow::Result { let ts = self .chain_index @@ -152,7 +139,7 @@ impl Chain for ForestExterns { } } -impl Rand for ForestExterns { +impl Rand for ForestExterns { fn get_chain_randomness(&self, round: ChainEpoch) -> anyhow::Result<[u8; 32]> { self.rand.get_chain_randomness(round) } @@ -162,7 +149,7 @@ impl Rand for ForestExterns { } } -impl Consensus for ForestExterns { +impl Consensus for ForestExterns { // See https://github.com/filecoin-project/lotus/blob/v1.18.0/chain/vm/fvm.go#L102-L216 for reference implementation fn verify_consensus_fault( &self, diff --git a/src/interpreter/vm.rs b/src/interpreter/vm.rs index 25b76910333e..f009ee563e0e 100644 --- a/src/interpreter/vm.rs +++ b/src/interpreter/vm.rs @@ -7,7 +7,7 @@ use crate::blocks::Tipset; use crate::chain::block_messages; use crate::chain::index::ChainIndex; use crate::chain::store::Error; -use crate::db::EthMappingsStore; +use crate::db::DbImpl; use crate::interpreter::{ fvm2::ForestExternsV2, fvm3::ForestExterns as ForestExternsV3, fvm4::ForestExterns as ForestExternsV4, @@ -15,6 +15,7 @@ use crate::interpreter::{ use crate::message::ChainMessage; use crate::message::MessageRead as _; use crate::networks::{ChainConfig, NetworkChain}; +use crate::prelude::*; use crate::shim::actors::{AwardBlockRewardParams, cron, reward}; use crate::shim::{ address::Address, @@ -28,8 +29,6 @@ use crate::shim::{ }; use ahash::{HashMap, HashMapExt, HashSet}; use anyhow::bail; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::{RawBytes, to_vec}; use fvm_shared2::clock::ChainEpoch; use fvm2::{ @@ -57,24 +56,19 @@ use num::Zero; use spire_enum::prelude::delegated_enum; use std::time::{Duration, Instant}; -pub(in crate::interpreter) type ForestMachineV2 = - DefaultMachine_v2, ForestExternsV2>; -pub(in crate::interpreter) type ForestMachineV3 = - DefaultMachine_v3, ForestExternsV3>; -pub(in crate::interpreter) type ForestMachineV4 = - DefaultMachine_v4, ForestExternsV4>; - -type ForestKernelV2 = - fvm2::DefaultKernel>>; -type ForestKernelV3 = - fvm3::DefaultKernel>>; -type ForestKernelV4 = fvm4::kernel::filecoin::DefaultFilecoinKernel< - fvm4::call_manager::DefaultCallManager>, +pub(in crate::interpreter) type ForestMachineV2 = DefaultMachine_v2; +pub(in crate::interpreter) type ForestMachineV3 = DefaultMachine_v3; +pub(in crate::interpreter) type ForestMachineV4 = DefaultMachine_v4; + +type ForestKernelV2 = fvm2::DefaultKernel>; +type ForestKernelV3 = fvm3::DefaultKernel>; +type ForestKernelV4 = fvm4::kernel::filecoin::DefaultFilecoinKernel< + fvm4::call_manager::DefaultCallManager, >; -type ForestExecutorV2 = DefaultExecutor_v2>; -type ForestExecutorV3 = DefaultExecutor_v3>; -type ForestExecutorV4 = DefaultExecutor_v4>; +type ForestExecutorV2 = DefaultExecutor_v2; +type ForestExecutorV3 = DefaultExecutor_v3; +type ForestExecutorV4 = DefaultExecutor_v4; pub type ApplyResult = anyhow::Result<(ApplyRet, Duration)>; @@ -139,13 +133,13 @@ impl BlockMessages { /// Interpreter which handles execution of state transitioning messages and /// returns receipts from the VM execution. #[delegated_enum(impl_conversions)] -pub enum VM { - VM2(ForestExecutorV2), - VM3(ForestExecutorV3), - VM4(ForestExecutorV4), +pub enum VM { + VM2(ForestExecutorV2), + VM3(ForestExecutorV3), + VM4(ForestExecutorV4), } -pub struct ExecutionContext { +pub struct ExecutionContext { // This tipset identifies of the blockchain. It functions as a starting // point when searching for ancestors. It may be any tipset as long as its // epoch is at or higher than the epoch in `epoch`. @@ -163,15 +157,12 @@ pub struct ExecutionContext { // The chain config is used to determine which consensus rules to use. pub chain_config: Arc, // Caching interface to the DB - pub chain_index: ChainIndex, + pub chain_index: ChainIndex, // UNIX timestamp for epoch pub timestamp: u64, } -impl VM -where - DB: Blockstore + EthMappingsStore + Send + Sync, -{ +impl VM { pub fn new( ExecutionContext { heaviest_tipset, @@ -183,7 +174,7 @@ where chain_config, chain_index, timestamp, - }: ExecutionContext, + }: ExecutionContext, multi_engine: &MultiEngine, enable_tracing: VMTrace, ) -> anyhow::Result { @@ -202,9 +193,9 @@ where context.set_circulating_supply(circ_supply.into()); context.tracing = enable_tracing.is_traced(); - let fvm: ForestMachineV4 = ForestMachineV4::new( + let fvm = ForestMachineV4::new( &context, - Arc::clone(chain_index.db()), + chain_index.db().shallow_clone(), ForestExternsV4::new( RandWrapper::from(rand), heaviest_tipset, @@ -214,7 +205,7 @@ where chain_config, ), )?; - let exec: ForestExecutorV4 = DefaultExecutor_v4::new(engine, fvm)?; + let exec = DefaultExecutor_v4::new(engine, fvm)?; Ok(VM::VM4(exec)) } else if network_version >= NetworkVersion::V18 { let mut config = NetworkConfig_v3::new(network_version.into()); @@ -230,9 +221,9 @@ where context.set_circulating_supply(circ_supply.into()); context.tracing = enable_tracing.is_traced(); - let fvm: ForestMachineV3 = ForestMachineV3::new( + let fvm = ForestMachineV3::new( &context, - Arc::clone(chain_index.db()), + chain_index.db().shallow_clone(), ForestExternsV3::new( RandWrapper::from(rand), heaviest_tipset, @@ -242,7 +233,7 @@ where chain_config, ), )?; - let exec: ForestExecutorV3 = DefaultExecutor_v3::new(engine, fvm)?; + let exec = DefaultExecutor_v3::new(engine, fvm)?; Ok(VM::VM3(exec)) } else { let config = NetworkConfig_v2::new(network_version.into()); @@ -252,10 +243,10 @@ where context.set_circulating_supply(circ_supply.into()); context.tracing = enable_tracing.is_traced(); - let fvm: ForestMachineV2 = ForestMachineV2::new( + let fvm = ForestMachineV2::new( &engine, &context, - Arc::clone(chain_index.db()), + chain_index.db().shallow_clone(), ForestExternsV2::new( RandWrapper::from(rand), heaviest_tipset, @@ -265,7 +256,7 @@ where chain_config, ), )?; - let exec: ForestExecutorV2 = DefaultExecutor_v2::new(fvm); + let exec = DefaultExecutor_v2::new(fvm); Ok(VM::VM2(exec)) } } diff --git a/src/lib.rs b/src/lib.rs index e083dfd83f1b..98315827ac1d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -75,6 +75,14 @@ mod tool; mod utils; mod wallet; +mod prelude { + pub use crate::{db::Blockstore, utils::ShallowClone}; + pub use anyhow::Context as _; + pub use cid::Cid; + pub use itertools::Itertools as _; + pub use std::sync::Arc; +} + /// These items are semver-exempt, and exist for forest author use only // We want to have doctests, but don't want our internals to be public because: // - We don't want to be concerned with library compat diff --git a/src/libp2p/chain_exchange/provider.rs b/src/libp2p/chain_exchange/provider.rs index 906f39edae33..55a6f8758b2a 100644 --- a/src/libp2p/chain_exchange/provider.rs +++ b/src/libp2p/chain_exchange/provider.rs @@ -4,9 +4,6 @@ use std::{io, num::NonZeroUsize, sync::LazyLock}; use ahash::{HashMap, HashMapExt}; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; -use itertools::Itertools; use nonzero_ext::nonzero; use super::{ @@ -16,6 +13,7 @@ use super::{ use crate::{ blocks::{Tipset, TipsetKey}, chain::{ChainStore, Error as ChainError}, + prelude::*, utils::misc::env::env_or_default_logged, }; @@ -51,13 +49,10 @@ fn encoded_size(value: &T) -> Result { } /// Builds chain exchange response out of chain data. -pub fn make_chain_exchange_response( - cs: &ChainStore, +pub fn make_chain_exchange_response( + cs: &ChainStore, request: &ChainExchangeRequest, -) -> ChainExchangeResponse -where - DB: Blockstore + Send + Sync + 'static, -{ +) -> ChainExchangeResponse { make_chain_exchange_response_with_cap( cs, request, @@ -65,14 +60,11 @@ where ) } -fn make_chain_exchange_response_with_cap( - cs: &ChainStore, +fn make_chain_exchange_response_with_cap( + cs: &ChainStore, request: &ChainExchangeRequest, max_bytes: usize, -) -> ChainExchangeResponse -where - DB: Blockstore + Send + Sync + 'static, -{ +) -> ChainExchangeResponse { if !request.is_options_valid() || !request.is_request_len_valid() { return ChainExchangeResponse { chain: Default::default(), @@ -99,10 +91,10 @@ where let mut chain: Vec = Vec::with_capacity(request.request_len as usize); let mut accumulated: usize = 0; - for tipset in root.chain(cs.blockstore()).take(request.request_len as _) { + for tipset in root.chain(cs.db()).take(request.request_len as _) { let mut tipset_bundle: TipsetBundle = TipsetBundle::default(); if request.include_messages() { - tipset_bundle.messages = Some(compact_messages(cs.blockstore(), &tipset)?); + tipset_bundle.messages = Some(compact_messages(cs.db(), &tipset)?); } if request.include_blocks() { tipset_bundle.blocks = tipset.block_headers().iter().cloned().collect_vec(); @@ -214,7 +206,7 @@ mod tests { use nunny::Vec as NonEmpty; use std::{io::Cursor, sync::Arc}; - async fn populate_chain_store() -> (NonEmpty, ChainStore) { + async fn populate_chain_store() -> (NonEmpty, ChainStore) { let db = Arc::new(MemoryDB::default()); // The cids are the tipset cids of the most recent tipset (39th). let header = load_car(&db, Cursor::new(EXPORT_SR_40)).await.unwrap(); @@ -222,14 +214,7 @@ mod tests { miner_address: Address::new_id(0), ..Default::default() }); - let cs = ChainStore::new( - db.clone(), - db.clone(), - db, - Arc::new(ChainConfig::default()), - gen_block, - ) - .unwrap(); + let cs = ChainStore::new(db, Arc::new(ChainConfig::default()), gen_block).unwrap(); (header.roots, cs) } diff --git a/src/libp2p/service.rs b/src/libp2p/service.rs index 2901759f7190..cd8810fd182a 100644 --- a/src/libp2p/service.rs +++ b/src/libp2p/service.rs @@ -1,26 +1,20 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use std::{ - sync::Arc, - time::{Duration, SystemTime, UNIX_EPOCH}, -}; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; +use crate::prelude::*; use crate::{blocks::GossipBlock, rpc::net::NetInfoResult}; use crate::{chain::ChainStore, utils::encoding::from_slice_with_fallback}; use crate::{ - libp2p_bitswap::{ - BitswapStoreRead, BitswapStoreReadWrite, request_manager::BitswapRequestManager, - }, + libp2p_bitswap::{BitswapStoreReadWrite, request_manager::BitswapRequestManager}, utils::flume::FlumeSenderExt as _, }; use crate::{message::SignedMessage, networks::GenesisNetworkName}; use ahash::{HashMap, HashSet}; use anyhow::Context as _; -use cid::Cid; use flume::Sender; use futures::{select, stream::StreamExt as _}; -use fvm_ipld_blockstore::Blockstore; pub use libp2p::gossipsub::{IdentTopic, Topic}; use libp2p::{ PeerId, Swarm, SwarmBuilder, @@ -164,10 +158,10 @@ pub enum NetRPCMethods { } /// The `Libp2pService` listens to events from the libp2p swarm. -pub struct Libp2pService { +pub struct Libp2pService { swarm: Swarm, bootstrap_peers: HashMap, - cs: Arc>, + cs: ChainStore, peer_manager: Arc, network_receiver_in: flume::Receiver, network_sender_in: Sender, @@ -177,13 +171,10 @@ pub struct Libp2pService { genesis_cid: Cid, } -impl Libp2pService -where - DB: Blockstore + BitswapStoreReadWrite + Sync + Send + 'static, -{ +impl Libp2pService { pub async fn new( config: Libp2pConfig, - cs: Arc>, + cs: ChainStore, peer_manager: Arc, net_keypair: Keypair, network_name: GenesisNetworkName, @@ -339,8 +330,8 @@ where Some(message) => { handle_network_message( swarm_stream.get_mut(), - self.cs.clone(), - bitswap_request_manager.clone(), + self.cs.db_owned(), + bitswap_request_manager.shallow_clone(), message, &self.network_sender_out, &self.peer_manager).await; @@ -435,7 +426,7 @@ fn handle_peer_ops( async fn handle_network_message( swarm: &mut Swarm, - store: Arc, + store: impl BitswapStoreReadWrite + ShallowClone, bitswap_request_manager: Arc, message: NetworkMessage, network_sender_out: &Sender, @@ -791,19 +782,17 @@ async fn handle_ping_event(ping_event: ping::Event) { } } -async fn handle_chain_exchange_event( +async fn handle_chain_exchange_event( chain_exchange: &mut ChainExchangeBehaviour, ce_event: request_response::Event, - db: &Arc>, + db: &ChainStore, network_sender_out: &Sender, cx_response_tx: Sender<( request_response::InboundRequestId, request_response::ResponseChannel, ChainExchangeResponse, )>, -) where - DB: Blockstore + Sync + Send + 'static, -{ +) { match ce_event { request_response::Event::Message { peer, message, .. } => match message { request_response::Message::Request { @@ -837,7 +826,7 @@ async fn handle_chain_exchange_event( ) .await; - let db = db.clone(); + let db = db.shallow_clone(); tokio::task::spawn(async move { let _per_peer_permit = per_peer_permit; let _global_permit = global_permit; @@ -886,12 +875,12 @@ async fn handle_chain_exchange_event( } #[allow(clippy::too_many_arguments)] -async fn handle_forest_behaviour_event( +async fn handle_forest_behaviour_event( swarm: &mut Swarm, bitswap_request_manager: &Arc, peer_manager: &PeerManager, event: ForestBehaviourEvent, - db: &Arc>, + db: &ChainStore, genesis_cid: &Cid, network_sender_out: &Sender, cx_response_tx: Sender<( @@ -901,9 +890,7 @@ async fn handle_forest_behaviour_event( )>, pubsub_block_str: &str, pubsub_msg_str: &str, -) where - DB: Blockstore + BitswapStoreRead + Sync + Send + 'static, -{ +) { match event { ForestBehaviourEvent::Discovery(discovery_out) => { handle_discovery_event( @@ -932,7 +919,7 @@ async fn handle_forest_behaviour_event( ForestBehaviourEvent::Bitswap(event) => { if let Err(e) = bitswap_request_manager.handle_event( &mut swarm.behaviour_mut().bitswap, - db.blockstore(), + db.db(), event, ) { warn!("bitswap: {e:#}"); diff --git a/src/libp2p_bitswap/request_manager.rs b/src/libp2p_bitswap/request_manager.rs index 0c990fea633d..ea0847078905 100644 --- a/src/libp2p_bitswap/request_manager.rs +++ b/src/libp2p_bitswap/request_manager.rs @@ -10,8 +10,8 @@ use std::{ }; use crate::cid_collections::CidHashMap; +use crate::prelude::*; use ahash::{HashSet, HashSetExt}; -use cid::Cid; use flume::TryRecvError; use futures::StreamExt; use libp2p::PeerId; @@ -118,20 +118,20 @@ impl BitswapRequestManager { #[cfg(not(target_arch = "wasm32"))] pub fn get_block( self: Arc, - store: Arc, + store: impl BitswapStoreReadWrite + ShallowClone, cid: Cid, timeout: Duration, responder: Option>, validate_peer: Option>, ) { let start = Instant::now(); - let store_cloned = store.clone(); task::spawn(async move { let mut success = store.contains(&cid).unwrap_or_default(); if !success { let deadline = start.checked_add(timeout).expect("Infallible"); - success = task::spawn_blocking(move || { - self.get_block_sync(store_cloned, cid, deadline, validate_peer) + success = task::spawn_blocking({ + let store = store.shallow_clone(); + move || self.get_block_sync(&store, cid, deadline, validate_peer) }) .await .unwrap_or_default(); @@ -161,7 +161,7 @@ impl BitswapRequestManager { fn get_block_sync( &self, - store: Arc, + store: &impl BitswapStoreReadWrite, cid: Cid, deadline: Instant, validate_peer: Option>, diff --git a/src/libp2p_bitswap/store.rs b/src/libp2p_bitswap/store.rs index b41847c8d46b..6c894def5474 100644 --- a/src/libp2p_bitswap/store.rs +++ b/src/libp2p_bitswap/store.rs @@ -2,12 +2,14 @@ // SPDX-License-Identifier: Apache-2.0, MIT use super::*; +use ambassador::delegatable_trait; use multihash_derive::MultihashDigest; use std::marker::PhantomData; use std::ops::Deref; /// Trait implemented by a block store for reading. #[auto_impl::auto_impl(&, Arc)] +#[delegatable_trait] pub trait BitswapStoreRead { /// A have query needs to know if the block store contains the block. fn contains(&self, cid: &Cid) -> anyhow::Result; @@ -18,6 +20,7 @@ pub trait BitswapStoreRead { /// Trait implemented by a block store for reading and writing. #[auto_impl::auto_impl(&, Arc)] +#[delegatable_trait] pub trait BitswapStoreReadWrite: BitswapStoreRead + Send + Sync + 'static { /// The hashes parameters. type Hashes: MultihashDigest<64>; diff --git a/src/message_pool/msgpool/mod.rs b/src/message_pool/msgpool/mod.rs index c05331124e87..a81b6240a7ae 100644 --- a/src/message_pool/msgpool/mod.rs +++ b/src/message_pool/msgpool/mod.rs @@ -21,13 +21,12 @@ use crate::blocks::Tipset; use crate::libp2p::{NetworkMessage, PUBSUB_MSG_STR, Topic}; use crate::message::{MessageRead as _, SignedMessage}; use crate::networks::ChainConfig; +use crate::prelude::*; use crate::shim::{address::Address, crypto::Signature}; use crate::state_manager::IdToAddressCache; -use crate::utils::ShallowClone as _; use crate::utils::cache::SizeTrackingLruCache; use crate::utils::get_size::CidWrapper; use ahash::{HashMap, HashMapExt, HashSet, HashSetExt}; -use cid::Cid; use fvm_ipld_encoding::to_vec; use parking_lot::RwLock as SyncRwLock; use tracing::error; diff --git a/src/message_pool/msgpool/msg_pool.rs b/src/message_pool/msgpool/msg_pool.rs index 26e53ed67f89..e642767519a4 100644 --- a/src/message_pool/msgpool/msg_pool.rs +++ b/src/message_pool/msgpool/msg_pool.rs @@ -6,7 +6,7 @@ // inclusion in the chain. Messages are added either directly for locally // published messages or through pubsub propagation. -use std::{num::NonZeroUsize, sync::Arc, time::Duration}; +use std::{num::NonZeroUsize, time::Duration}; use crate::blocks::{CachingBlockHeader, Tipset, TipsetKey}; use crate::chain::{HeadChanges, MINIMUM_BASE_FEE}; @@ -16,6 +16,7 @@ use crate::eth::is_valid_eth_tx_for_sending; use crate::libp2p::{NetworkMessage, PUBSUB_MSG_STR, Topic}; use crate::message::{ChainMessage, MessageRead as _, SignedMessage, valid_for_block_inclusion}; use crate::networks::{ChainConfig, NEWEST_NETWORK_VERSION}; +use crate::prelude::*; use crate::rpc::eth::types::EthAddress; use crate::shim::{ address::{Address, Protocol}, @@ -25,16 +26,12 @@ use crate::shim::{ }; use crate::state_manager::IdToAddressCache; use crate::state_manager::utils::is_valid_for_sending; -use crate::utils::ShallowClone as _; use crate::utils::cache::SizeTrackingLruCache; use crate::utils::get_size::CidWrapper; use ahash::{HashSet, HashSetExt}; -use anyhow::Context as _; -use cid::Cid; use futures::StreamExt; use fvm_ipld_encoding::to_vec; use get_size2::GetSize; -use itertools::Itertools; use nonzero_ext::nonzero; use parking_lot::RwLock as SyncRwLock; use tokio::{ @@ -114,11 +111,32 @@ pub struct MessagePool { pub repub_trigger: flume::Sender<()>, local_msgs: Arc>>, /// Configurable parameters of the message pool - pub config: MpoolConfig, + pub config: Arc, /// Chain configuration pub chain_config: Arc, } +impl ShallowClone for MessagePool { + fn shallow_clone(&self) -> Self { + Self { + local_addrs: self.local_addrs.shallow_clone(), + pending_store: self.pending_store.shallow_clone(), + cur_tipset: self.cur_tipset.shallow_clone(), + api: self.api.shallow_clone(), + network_sender: self.network_sender.clone(), + bls_sig_cache: self.bls_sig_cache.shallow_clone(), + sig_val_cache: self.sig_val_cache.shallow_clone(), + key_cache: self.key_cache.shallow_clone(), + state_nonce_cache: self.state_nonce_cache.shallow_clone(), + republished: self.republished.shallow_clone(), + repub_trigger: self.repub_trigger.clone(), + local_msgs: self.local_msgs.clone(), + config: self.config.shallow_clone(), + chain_config: self.chain_config.shallow_clone(), + } + } +} + /// Resolve an address to its key form, checking the cache first. /// Non-ID addresses are returned unchanged. pub(in crate::message_pool) fn resolve_to_key( @@ -500,7 +518,7 @@ where ) -> Result<(), Error> { cfg.save_config(db) .map_err(|e| Error::Other(e.to_string()))?; - self.config = cfg; + self.config = cfg.into(); Ok(()) } @@ -575,7 +593,7 @@ where state_nonce_cache, local_msgs, republished, - config, + config: config.into(), network_sender, repub_trigger, chain_config: Arc::clone(&chain_config), @@ -733,7 +751,7 @@ fn verify_msg_before_add( mod tests { use crate::blocks::RawBlockHeader; use crate::chain::ChainStore; - use crate::db::MemoryDB; + use crate::db::{DbImpl, MemoryDB}; use crate::message_pool::provider::Provider; use crate::message_pool::test_provider::TestApi; use crate::networks::ChainConfig; @@ -1052,7 +1070,7 @@ mod tests { #[test] fn resolve_to_key_uses_finality_lookback() { - let db = Arc::new(MemoryDB::default()); + let db: DbImpl = Arc::new(MemoryDB::default()).into(); let mut cfg = ChainConfig::default(); cfg.policy.chain_finality = 1; @@ -1062,7 +1080,7 @@ mod tests { let bls_b = Address::new_bls(&[9u8; 48]).unwrap(); // root_a: only contains f0300 - let mut st_a = StateTree::new(db.clone(), StateTreeVersion::V5).unwrap(); + let mut st_a = StateTree::new(&db, StateTreeVersion::V5).unwrap(); st_a.set_actor( &Address::new_id(300), ActorState::new_empty(Cid::default(), Some(bls_a)), @@ -1071,7 +1089,7 @@ mod tests { let root_a = st_a.flush().unwrap(); // root_b: only contains f0400 - let mut st_b = StateTree::new(db.clone(), StateTreeVersion::V5).unwrap(); + let mut st_b = StateTree::new(&db, StateTreeVersion::V5).unwrap(); st_b.set_actor( &Address::new_id(400), ActorState::new_empty(Cid::default(), Some(bls_b)), @@ -1104,14 +1122,7 @@ mod tests { })); db.put_cbor_default(head.block_headers().first()).unwrap(); - let cs = ChainStore::new( - db.clone(), - db.clone(), - db, - cfg, - genesis.block_headers().first().clone(), - ) - .unwrap(); + let cs = ChainStore::new(db, cfg, genesis.block_headers().first().clone()).unwrap(); // f0300 exists in lookback state (root_a) → resolves successfully. let result = Provider::resolve_to_deterministic_address_at_finality( diff --git a/src/message_pool/msgpool/pending_store.rs b/src/message_pool/msgpool/pending_store.rs index 80666b3fea7a..76c70202cd60 100644 --- a/src/message_pool/msgpool/pending_store.rs +++ b/src/message_pool/msgpool/pending_store.rs @@ -3,8 +3,6 @@ //! Pending message storage and event broadcast. -use std::sync::Arc; - use ahash::{HashMap, HashMapExt}; use parking_lot::RwLock as SyncRwLock; use tokio::sync::broadcast; @@ -14,8 +12,8 @@ use crate::message_pool::errors::Error; use crate::message_pool::msgpool::events::{MPOOL_UPDATE_CHANNEL_CAPACITY, MpoolUpdate}; use crate::message_pool::msgpool::msg_pool::TrustPolicy; use crate::message_pool::msgpool::msg_set::{MsgSet, MsgSetLimits, StrictnessPolicy}; +use crate::prelude::*; use crate::shim::address::Address; -use crate::utils::ShallowClone; use crate::utils::broadcast::has_subscribers; /// Owns the per-actor [`MsgSet`] map and the [`MpoolUpdate`] broadcast @@ -24,6 +22,14 @@ pub(in crate::message_pool) struct PendingStore { inner: Arc, } +impl ShallowClone for PendingStore { + fn shallow_clone(&self) -> Self { + Self { + inner: self.inner.shallow_clone(), + } + } +} + struct Inner { /// Per-resolved-address pending messages. pending: SyncRwLock>, @@ -33,14 +39,6 @@ struct Inner { limits: MsgSetLimits, } -impl ShallowClone for PendingStore { - fn shallow_clone(&self) -> Self { - Self { - inner: self.inner.shallow_clone(), - } - } -} - impl PendingStore { /// Construct an empty store with the given per-actor limits. pub(in crate::message_pool) fn new(limits: MsgSetLimits) -> Self { diff --git a/src/message_pool/msgpool/provider.rs b/src/message_pool/msgpool/provider.rs index 2b1683537cd1..9b14426698fa 100644 --- a/src/message_pool/msgpool/provider.rs +++ b/src/message_pool/msgpool/provider.rs @@ -4,7 +4,6 @@ use crate::blocks::{CachingBlockHeader, Tipset, TipsetKey}; use crate::chain::index::ResolveNullTipset; use crate::chain::{ChainStore, HeadChanges}; -use crate::db::EthMappingsStore; use crate::message::{ChainMessage, SignedMessage}; use crate::message_pool::errors::Error; use crate::message_pool::msg_pool::{ @@ -20,7 +19,6 @@ use crate::shim::{ use crate::utils::db::CborStoreExt; use auto_impl::auto_impl; use cid::Cid; -use fvm_ipld_blockstore::Blockstore; use std::sync::Arc; use tokio::sync::broadcast; @@ -68,7 +66,7 @@ pub trait Provider { } } -impl Provider for ChainStore { +impl Provider for ChainStore { fn subscribe_head_changes(&self) -> broadcast::Receiver { self.subscribe_head_changes() } @@ -79,14 +77,14 @@ impl Provider for ChainStore { fn put_message(&self, msg: &ChainMessage) -> Result { let cid = self - .blockstore() + .db() .put_cbor_default(msg) .map_err(|err| Error::Other(err.to_string()))?; Ok(cid) } fn get_actor_after(&self, addr: &Address, ts: &Tipset) -> Result { - let state = StateTree::new_from_root(self.blockstore().clone(), ts.parent_state()) + let state = StateTree::new_from_root(self.db(), ts.parent_state()) .map_err(|e| Error::Other(e.to_string()))?; Ok(state.get_required_actor(addr)?) } @@ -95,7 +93,7 @@ impl Provider for ChainStore { &self, h: &CachingBlockHeader, ) -> Result<(Vec, Vec), Error> { - crate::chain::block_messages(self.blockstore(), h).map_err(|err| err.into()) + crate::chain::block_messages(self.db(), h).map_err(|err| err.into()) } fn load_tipset(&self, tsk: &TipsetKey) -> Result { @@ -105,7 +103,7 @@ impl Provider for ChainStore { fn chain_compute_base_fee(&self, ts: &Tipset) -> Result { let smoke_height = self.chain_config().epoch(Height::Smoke); let firehorse_height = self.chain_config().epoch(Height::FireHorse); - crate::chain::compute_base_fee(self.blockstore(), ts, smoke_height, firehorse_height) + crate::chain::compute_base_fee(self.db(), ts, smoke_height, firehorse_height) .map_err(|err| err.into()) } @@ -133,11 +131,10 @@ impl Provider for ChainStore { ts.clone() }; - let state = - StateTree::new_from_root(self.blockstore().clone(), lookback_ts.parent_state()) - .map_err(|e| Error::Other(e.to_string()))?; + let state = StateTree::new_from_root(self.db(), lookback_ts.parent_state()) + .map_err(|e| Error::Other(e.to_string()))?; state - .resolve_to_deterministic_addr(self.blockstore(), *addr) + .resolve_to_deterministic_addr(self.db(), *addr) .map_err(|e| Error::Other(e.to_string())) } } diff --git a/src/rpc/auth_layer.rs b/src/rpc/auth_layer.rs index b0cf4952800c..280354d96ca6 100644 --- a/src/rpc/auth_layer.rs +++ b/src/rpc/auth_layer.rs @@ -3,6 +3,7 @@ use crate::auth::{JWT_IDENTIFIER, verify_token}; use crate::key_management::KeyStore; +use crate::prelude::*; use crate::rpc::{CANCEL_METHOD_NAME, Permission, RpcMethod as _, chain}; use ahash::{HashMap, HashMapExt as _}; use futures::future::Either; @@ -10,14 +11,13 @@ use http::{ HeaderMap, header::{AUTHORIZATION, HeaderValue}, }; -use itertools::Itertools as _; use jsonrpsee::MethodResponse; use jsonrpsee::core::middleware::{Batch, BatchEntry, BatchEntryErr, Notification}; use jsonrpsee::server::middleware::rpc::RpcServiceT; use jsonrpsee::types::Id; use jsonrpsee::types::{ErrorObject, error::ErrorCode}; use parking_lot::RwLock; -use std::sync::{Arc, LazyLock}; +use std::sync::LazyLock; use tower::Layer; use tracing::debug; diff --git a/src/rpc/methods/auth.rs b/src/rpc/methods/auth.rs index 154902ee651d..a14d1497bcb0 100644 --- a/src/rpc/methods/auth.rs +++ b/src/rpc/methods/auth.rs @@ -10,7 +10,6 @@ use crate::{ use anyhow::Result; use chrono::Duration; use enumflags2::BitFlags; -use fvm_ipld_blockstore::Blockstore; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_with::{DurationSeconds, serde_as}; @@ -39,7 +38,7 @@ impl RpcMethod<2> for AuthNew { type Params = (Vec, Option); type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (permissions, expiration_secs): Self::Params, _: &http::Extensions, ) -> Result { @@ -64,7 +63,7 @@ impl RpcMethod<1> for AuthVerify { type Params = (String,); type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (header_raw,): Self::Params, _: &http::Extensions, ) -> Result { diff --git a/src/rpc/methods/beacon.rs b/src/rpc/methods/beacon.rs index 12ba6ff3a94a..9b47056f3097 100644 --- a/src/rpc/methods/beacon.rs +++ b/src/rpc/methods/beacon.rs @@ -6,7 +6,6 @@ use crate::rpc::{ApiPaths, Ctx, Permission, RpcMethod, ServerError}; use crate::{beacon::BeaconEntry, shim::clock::ChainEpoch}; use anyhow::Result; use enumflags2::{BitFlags, make_bitflags}; -use fvm_ipld_blockstore::Blockstore; /// `BeaconGetEntry` returns the beacon entry for the given Filecoin epoch. If /// the entry has not yet been produced, the call will block until the entry @@ -22,7 +21,7 @@ impl RpcMethod<1> for BeaconGetEntry { type Ok = BeaconEntry; async fn handle( - ctx: Ctx, + ctx: Ctx, (first,): Self::Params, _: &http::Extensions, ) -> Result { diff --git a/src/rpc/methods/chain.rs b/src/rpc/methods/chain.rs index 16f7a0f37be0..322a397ce3b1 100644 --- a/src/rpc/methods/chain.rs +++ b/src/rpc/methods/chain.rs @@ -11,13 +11,13 @@ use crate::chain::index::ResolveNullTipset; use crate::chain::{ChainStore, ExportOptions, FilecoinSnapshotVersion, HeadChange}; use crate::chain_sync::{get_full_tipset, load_full_tipset}; use crate::cid_collections::{CidHashSet, FileBackedCidHashSet}; -use crate::db::EthMappingsStore; use crate::ipld::DfsIter; use crate::ipld::{CHAIN_EXPORT_STATUS, cancel_export, end_export, start_export}; use crate::lotus_json::{HasLotusJson, LotusJson, lotus_json_with_self}; #[cfg(test)] use crate::lotus_json::{assert_all_snapshots, assert_unchanged_via_json}; use crate::message::{ChainMessage, SignedMessage}; +use crate::prelude::*; use crate::rpc::eth::Block as EthBlock; use crate::rpc::eth::{ EthLog, TxInfo, eth_logs_with_filter, types::ApiHeaders, types::EthFilterSpec, @@ -29,18 +29,14 @@ use crate::shim::clock::ChainEpoch; use crate::shim::error::ExitCode; use crate::shim::executor::Receipt; use crate::shim::message::Message; -use crate::utils::ShallowClone; use crate::utils::db::CborStoreExt as _; use crate::utils::io::VoidAsyncWriter; use crate::utils::misc::env::is_env_truthy; use anyhow::{Context as _, Result}; -use cid::Cid; use enumflags2::{BitFlags, make_bitflags}; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::{CborStore, RawBytes}; use hex::ToHex; use ipld_core::ipld::Ipld; -use itertools::Itertools as _; use jsonrpsee::types::Params; use jsonrpsee::types::error::ErrorObjectOwned; use num::BigInt; @@ -48,7 +44,6 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use sha2::Sha256; use std::fs::File; -use std::sync::Arc; use std::{collections::VecDeque, path::PathBuf, sync::LazyLock}; use tokio::sync::{ Mutex, @@ -83,9 +78,7 @@ static CHAIN_EXPORT_LOCK: LazyLock>> = /// /// Spawns an internal `tokio` task that can be aborted anytime via the returned `JoinHandle`, /// allowing manual cleanup if needed. -pub(crate) fn new_heads( - data: Ctx, -) -> (Subscriber, JoinHandle<()>) { +pub(crate) fn new_heads(data: Ctx) -> (Subscriber, JoinHandle<()>) { let (sender, receiver) = broadcast::channel(HEAD_CHANNEL_CAPACITY); let mut head_changes_rx = data.chain_store().subscribe_head_changes(); @@ -119,8 +112,8 @@ pub(crate) fn new_heads( - ctx: &Ctx, +pub(crate) fn logs( + ctx: &Ctx, filter: Option, ) -> (Subscriber>, JoinHandle<()>) { let (sender, receiver) = broadcast::channel(HEAD_CHANNEL_CAPACITY); @@ -166,7 +159,7 @@ impl RpcMethod<0> for ChainGetFinalizedTipset { type Ok = Tipset; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -186,12 +179,12 @@ impl RpcMethod<1> for ChainGetMessage { type Ok = Message; async fn handle( - ctx: Ctx, + ctx: Ctx, (message_cid,): Self::Params, _: &http::Extensions, ) -> Result { let chain_message: ChainMessage = ctx - .store() + .db() .get_cbor(&message_cid)? .with_context(|| format!("can't find message with cid {message_cid}"))?; let message = match chain_message { @@ -217,7 +210,7 @@ impl RpcMethod<1> for ChainGetEvents { type Params = (Cid,); type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (root_cid,): Self::Params, _: &http::Extensions, ) -> Result { @@ -239,11 +232,11 @@ impl RpcMethod<1> for ChainGetParentMessages { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (block_cid,): Self::Params, _: &http::Extensions, ) -> Result { - let store = ctx.store(); + let store = ctx.db(); let block_header: CachingBlockHeader = store .get_cbor(&block_cid)? .with_context(|| format!("can't find block header with cid {block_cid}"))?; @@ -271,11 +264,11 @@ impl RpcMethod<1> for ChainGetParentReceipts { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (block_cid,): Self::Params, _: &http::Extensions, ) -> Result { - let store = ctx.store(); + let store = ctx.db(); let block_header: CachingBlockHeader = store .get_cbor(&block_cid)? .with_context(|| format!("can't find block header with cid {block_cid}"))?; @@ -317,7 +310,7 @@ impl RpcMethod<1> for ChainGetMessagesInTipset { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (ApiTipsetKey(tipset_key),): Self::Params, _: &http::Extensions, ) -> Result { @@ -339,7 +332,7 @@ impl RpcMethod<1> for ChainPruneSnapshot { type Ok = (); async fn handle( - _ctx: Ctx, + _ctx: Ctx, (blocking,): Self::Params, _: &http::Extensions, ) -> Result { @@ -364,7 +357,7 @@ impl RpcMethod<1> for ForestChainExport { type Ok = ApiExportResult; async fn handle( - ctx: Ctx, + ctx: Ctx, (params,): Self::Params, _: &http::Extensions, ) -> Result { @@ -414,7 +407,7 @@ impl RpcMethod<1> for ForestChainExport { }; let result = match version { FilecoinSnapshotVersion::V1 => { - let db = ctx.store_owned(); + let db = ctx.db_owned(); let chain_export = crate::chain::export::( &db, @@ -436,7 +429,7 @@ impl RpcMethod<1> for ForestChainExport { } } FilecoinSnapshotVersion::V2 => { - let db = ctx.store_owned(); + let db = ctx.db_owned(); let f3_snap_tmp_path = { let mut f3_snap_dir = output_path.clone(); @@ -503,7 +496,7 @@ impl RpcMethod<0> for ForestChainExportStatus { type Ok = ApiExportStatus; async fn handle( - _ctx: Ctx, + _ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -544,7 +537,7 @@ impl RpcMethod<0> for ForestChainExportCancel { type Ok = bool; async fn handle( - _ctx: Ctx, + _ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -568,7 +561,7 @@ impl RpcMethod<1> for ForestChainExportDiff { type Ok = (); async fn handle( - ctx: Ctx, + ctx: Ctx, (params,): Self::Params, _: &http::Extensions, ) -> Result { @@ -601,7 +594,7 @@ impl RpcMethod<1> for ForestChainExportDiff { )?; crate::tool::subcommands::archive_cmd::do_export( - &ctx.store_owned(), + ctx.chain_index().db(), start_ts, output_path, None, @@ -627,7 +620,7 @@ impl RpcMethod<1> for ChainExport { type Ok = ApiExportResult; async fn handle( - ctx: Ctx, + ctx: Ctx, (ChainExportParams { epoch, recent_roots, @@ -672,12 +665,12 @@ impl RpcMethod<1> for ChainReadObj { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (cid,): Self::Params, _: &http::Extensions, ) -> Result { let bytes = ctx - .store() + .db() .get(&cid)? .with_context(|| format!("can't find object with cid={cid}"))?; Ok(bytes) @@ -697,11 +690,11 @@ impl RpcMethod<1> for ChainHasObj { type Ok = bool; async fn handle( - ctx: Ctx, + ctx: Ctx, (cid,): Self::Params, _: &http::Extensions, ) -> Result { - Ok(ctx.store().get(&cid)?.is_some()) + Ok(ctx.db().get(&cid)?.is_some()) } } @@ -718,7 +711,7 @@ impl RpcMethod<2> for ChainStatObj { type Ok = ObjStat; async fn handle( - ctx: Ctx, + ctx: Ctx, (obj_cid, base_cid): Self::Params, _: &http::Extensions, ) -> Result { @@ -731,7 +724,7 @@ impl RpcMethod<2> for ChainStatObj { if !seen.insert(link_cid) { continue; } - let data = ctx.store().get(&link_cid)?; + let data = ctx.db().get(&link_cid)?; if let Some(data) = data { if collect { stats.links += 1; @@ -772,14 +765,14 @@ impl RpcMethod<1> for ChainGetBlockMessages { type Ok = BlockMessages; async fn handle( - ctx: Ctx, + ctx: Ctx, (block_cid,): Self::Params, _: &http::Extensions, ) -> Result { - let blk: CachingBlockHeader = ctx.store().get_cbor_required(&block_cid)?; - let (unsigned_cids, signed_cids) = crate::chain::read_msg_cids(ctx.store(), &blk)?; + let blk: CachingBlockHeader = ctx.db().get_cbor_required(&block_cid)?; + let (unsigned_cids, signed_cids) = crate::chain::read_msg_cids(ctx.db(), &blk)?; let (bls_msg, secp_msg) = - crate::chain::block_messages_from_cids(ctx.store(), &unsigned_cids, &signed_cids)?; + crate::chain::block_messages_from_cids(ctx.db(), &unsigned_cids, &signed_cids)?; let cids = unsigned_cids.into_iter().chain(signed_cids).collect(); let ret = BlockMessages { @@ -804,7 +797,7 @@ impl RpcMethod<2> for ChainGetPath { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (from, to): Self::Params, _: &http::Extensions, ) -> Result { @@ -830,7 +823,7 @@ impl RpcMethod<2> for ChainGetPath { /// /// Exposes errors from the [`Blockstore`], and returns an error if there is no common ancestor. pub fn chain_get_path( - chain_store: &ChainStore, + chain_store: &ChainStore, from: &TipsetKey, to: &TipsetKey, ) -> anyhow::Result { @@ -888,7 +881,7 @@ impl RpcMethod<2> for ChainGetTipSetByHeight { type Ok = Tipset; async fn handle( - ctx: Ctx, + ctx: Ctx, (height, ApiTipsetKey(tipset_key)): Self::Params, _: &http::Extensions, ) -> Result { @@ -920,7 +913,7 @@ impl RpcMethod<2> for ChainGetTipSetAfterHeight { type Ok = Tipset; async fn handle( - ctx: Ctx, + ctx: Ctx, (height, ApiTipsetKey(tipset_key)): Self::Params, _: &http::Extensions, ) -> Result { @@ -947,7 +940,7 @@ impl RpcMethod<0> for ChainGetGenesis { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -968,7 +961,7 @@ impl RpcMethod<0> for ChainHead { type Ok = Tipset; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -989,11 +982,11 @@ impl RpcMethod<1> for ChainGetBlock { type Ok = CachingBlockHeader; async fn handle( - ctx: Ctx, + ctx: Ctx, (block_cid,): Self::Params, _: &http::Extensions, ) -> Result { - let blk: CachingBlockHeader = ctx.store().get_cbor_required(&block_cid)?; + let blk: CachingBlockHeader = ctx.db().get_cbor_required(&block_cid)?; Ok(blk) } } @@ -1011,7 +1004,7 @@ impl RpcMethod<1> for ChainGetTipSet { type Ok = Tipset; async fn handle( - ctx: Ctx, + ctx: Ctx, (ApiTipsetKey(tsk),): Self::Params, _: &http::Extensions, ) -> Result { @@ -1032,7 +1025,7 @@ pub enum ChainGetTipSetV2 {} impl ChainGetTipSetV2 { pub async fn get_tipset_by_anchor( - ctx: &Ctx, + ctx: &Ctx, anchor: Option<&TipsetAnchor>, ) -> anyhow::Result { if let Some(anchor) = anchor { @@ -1052,10 +1045,7 @@ impl ChainGetTipSetV2 { } } - pub async fn get_tipset_by_tag( - ctx: &Ctx, - tag: TipsetTag, - ) -> anyhow::Result { + pub async fn get_tipset_by_tag(ctx: &Ctx, tag: TipsetTag) -> anyhow::Result { match tag { TipsetTag::Latest => Ok(ctx.state_manager.heaviest_tipset()), TipsetTag::Finalized => Self::get_latest_finalized_tipset(ctx).await, @@ -1063,9 +1053,7 @@ impl ChainGetTipSetV2 { } } - pub async fn get_latest_safe_tipset( - ctx: &Ctx, - ) -> anyhow::Result { + pub async fn get_latest_safe_tipset(ctx: &Ctx) -> anyhow::Result { let finalized = Self::get_latest_finalized_tipset(ctx).await?; let head = ctx.chain_store().heaviest_tipset(); let safe_height = (head.epoch() - SAFE_HEIGHT_DISTANCE).max(0); @@ -1080,18 +1068,13 @@ impl ChainGetTipSetV2 { } } - pub async fn get_latest_finalized_tipset( - ctx: &Ctx, - ) -> anyhow::Result { + pub async fn get_latest_finalized_tipset(ctx: &Ctx) -> anyhow::Result { ChainGetTipSetFinalityStatus::get_finality_status(ctx)? .finalized_tip_set .context("failed to resolve finalized tipset") } - pub async fn get_tipset( - ctx: &Ctx, - selector: &TipsetSelector, - ) -> anyhow::Result { + pub async fn get_tipset(ctx: &Ctx, selector: &TipsetSelector) -> anyhow::Result { selector.validate()?; // Get tipset by key. if let ApiTipsetKey(Some(tsk)) = &selector.key { @@ -1128,7 +1111,7 @@ impl RpcMethod<1> for ChainGetTipSetV2 { type Ok = Tipset; async fn handle( - ctx: Ctx, + ctx: Ctx, (selector,): Self::Params, _: &http::Extensions, ) -> Result { @@ -1139,9 +1122,7 @@ impl RpcMethod<1> for ChainGetTipSetV2 { pub enum ChainGetTipSetFinalityStatus {} impl ChainGetTipSetFinalityStatus { - pub fn get_finality_status( - ctx: &Ctx, - ) -> anyhow::Result { + pub fn get_finality_status(ctx: &Ctx) -> anyhow::Result { let head = ctx.chain_store().heaviest_tipset(); let (ec_finality_threshold_depth, ec_finalized_tip_set) = Self::get_ec_finality_threshold_depth_and_tipset_with_cache(ctx, head.shallow_clone())?; @@ -1168,7 +1149,7 @@ impl ChainGetTipSetFinalityStatus { } pub fn get_ec_finality_threshold_depth_and_tipset_with_cache( - ctx: &Ctx, + ctx: &Ctx, head: Tipset, ) -> anyhow::Result<(i64, Option)> { static CACHE: parking_lot::Mutex)>> = @@ -1187,7 +1168,7 @@ impl ChainGetTipSetFinalityStatus { } fn get_ec_finality_threshold_depth_and_tipset( - ctx: &Ctx, + ctx: &Ctx, head: Tipset, ) -> anyhow::Result<(i64, Option)> { use crate::chain::ec_finality::calculator::{ @@ -1272,7 +1253,7 @@ impl RpcMethod<0> for ChainGetTipSetFinalityStatus { type Ok = ChainFinalityStatus; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -1291,7 +1272,7 @@ impl RpcMethod<1> for ChainSetHead { type Ok = (); async fn handle( - ctx: Ctx, + ctx: Ctx, (tsk,): Self::Params, _: &http::Extensions, ) -> Result { @@ -1324,7 +1305,7 @@ impl RpcMethod<1> for ChainGetMinBaseFee { type Ok = String; async fn handle( - ctx: Ctx, + ctx: Ctx, (lookback,): Self::Params, _: &http::Extensions, ) -> Result { @@ -1355,14 +1336,14 @@ impl RpcMethod<1> for ChainTipSetWeight { type Ok = BigInt; async fn handle( - ctx: Ctx, + ctx: Ctx, (ApiTipsetKey(tipset_key),): Self::Params, _: &http::Extensions, ) -> Result { let ts = ctx .chain_store() .load_required_tipset_or_heaviest(&tipset_key)?; - let weight = crate::fil_cns::weight(ctx.store(), &ts)?; + let weight = crate::fil_cns::weight(ctx.db(), &ts)?; Ok(weight) } } @@ -1378,23 +1359,23 @@ impl RpcMethod<1> for ChainGetTipsetByParentState { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (parent_state,): Self::Params, _: &http::Extensions, ) -> Result { Ok(ctx .chain_store() .heaviest_tipset() - .chain(ctx.store()) + .chain(ctx.db()) .find(|ts| ts.parent_state() == &parent_state) .shallow_clone()) } } pub const CHAIN_NOTIFY: &str = "Filecoin.ChainNotify"; -pub(crate) fn chain_notify( +pub(crate) fn chain_notify( _params: Params<'_>, - data: &crate::rpc::RPCState, + data: &crate::rpc::RPCState, ) -> Subscriber> { let (sender, receiver) = broadcast::channel(HEAD_CHANNEL_CAPACITY); @@ -1424,8 +1405,8 @@ pub(crate) fn chain_notify( receiver } -async fn load_api_messages_from_tipset( - ctx: &crate::rpc::RPCState, +async fn load_api_messages_from_tipset( + ctx: &crate::rpc::RPCState, tipset_keys: &TipsetKey, ) -> Result, ServerError> { static SHOULD_BACKFILL: LazyLock = LazyLock::new(|| { @@ -1725,40 +1706,42 @@ mod tests { #[test] fn revert_to_ancestor_linear() { - let store = ChainStore::calibnet(); + let cs = ChainStore::calibnet(); + let db = Chain4U::with_blockstore(cs.db_owned()); chain4u! { - in store.blockstore(); - [_genesis = store.genesis_block_header()] + in db; + [_genesis = cs.genesis_block_header()] -> [a] -> [b] -> [c, d] -> [e] }; // simple - assert_path_change(&store, b, a, [Revert(&[b])]); + assert_path_change(&cs, b, a, [Revert(&[b])]); // from multi-member tipset - assert_path_change(&store, [c, d], a, [Revert(&[c, d][..]), Revert(&[b])]); + assert_path_change(&cs, [c, d], a, [Revert(&[c, d][..]), Revert(&[b])]); // to multi-member tipset - assert_path_change(&store, e, [c, d], [Revert(e)]); + assert_path_change(&cs, e, [c, d], [Revert(e)]); // over multi-member tipset - assert_path_change(&store, e, b, [Revert(&[e][..]), Revert(&[c, d])]); + assert_path_change(&cs, e, b, [Revert(&[e][..]), Revert(&[c, d])]); } /// Mirror how lotus handles passing an incomplete `TipsetKey`s. /// Tested on lotus `1.23.2` #[test] fn incomplete_tipsets() { - let store = ChainStore::calibnet(); + let cs = ChainStore::calibnet(); + let db = Chain4U::with_blockstore(cs.db_owned()); chain4u! { - in store.blockstore(); - [_genesis = store.genesis_block_header()] + in db; + [_genesis = cs.genesis_block_header()] -> [a, b] -> [c] -> [d, _e] // this pattern 2 -> 1 -> 2 can be found at calibnet epoch 1369126 }; // apply to descendant with incomplete `from` assert_path_change( - &store, + &cs, a, c, [ @@ -1769,14 +1752,14 @@ mod tests { ); // apply to descendant with incomplete `to` - assert_path_change(&store, c, d, [Apply(d)]); + assert_path_change(&cs, c, d, [Apply(d)]); // revert to ancestor with incomplete `from` - assert_path_change(&store, d, c, [Revert(d)]); + assert_path_change(&cs, d, c, [Revert(d)]); // revert to ancestor with incomplete `to` assert_path_change( - &store, + &cs, c, a, [ @@ -1789,64 +1772,59 @@ mod tests { #[test] fn apply_to_descendant_linear() { - let store = ChainStore::calibnet(); + let cs = ChainStore::calibnet(); + let db = Chain4U::with_blockstore(cs.db_owned()); chain4u! { - in store.blockstore(); - [_genesis = store.genesis_block_header()] + in db; + [_genesis = cs.genesis_block_header()] -> [a] -> [b] -> [c, d] -> [e] }; // simple - assert_path_change(&store, a, b, [Apply(&[b])]); + assert_path_change(&cs, a, b, [Apply(&[b])]); // from multi-member tipset - assert_path_change(&store, [c, d], e, [Apply(e)]); + assert_path_change(&cs, [c, d], e, [Apply(e)]); // to multi-member tipset - assert_path_change(&store, b, [c, d], [Apply([c, d])]); + assert_path_change(&cs, b, [c, d], [Apply([c, d])]); // over multi-member tipset - assert_path_change(&store, b, e, [Apply(&[c, d][..]), Apply(&[e])]); + assert_path_change(&cs, b, e, [Apply(&[c, d][..]), Apply(&[e])]); } #[test] fn cross_fork_simple() { - let store = ChainStore::calibnet(); + let cs = ChainStore::calibnet(); + let db = Chain4U::with_blockstore(cs.db_owned()); chain4u! { - in store.blockstore(); - [_genesis = store.genesis_block_header()] + in db; + [_genesis = cs.genesis_block_header()] -> [a] -> [b1] -> [c1] }; chain4u! { - from [a] in store.blockstore(); + from [a] in db; [b2] -> [c2] }; // same height - assert_path_change(&store, b1, b2, [Revert(b1), Apply(b2)]); + assert_path_change(&cs, b1, b2, [Revert(b1), Apply(b2)]); // different height - assert_path_change(&store, b1, c2, [Revert(b1), Apply(b2), Apply(c2)]); + assert_path_change(&cs, b1, c2, [Revert(b1), Apply(b2), Apply(c2)]); let _ = (a, c1); } - impl ChainStore> { + impl ChainStore { fn _load(genesis_car: &'static [u8], genesis_cid: Cid) -> Self { - let db = Arc::new(Chain4U::with_blockstore( + let db = Arc::new( ManyCar::new(MemoryDB::default()) .with_read_only(AnyCar::new(genesis_car).unwrap()) .unwrap(), - )); + ); let genesis_block_header = db.get_cbor(&genesis_cid).unwrap().unwrap(); - ChainStore::new( - db, - Arc::new(MemoryDB::default()), - Arc::new(MemoryDB::default()), - Arc::new(ChainConfig::calibnet()), - genesis_block_header, - ) - .unwrap() + ChainStore::new(db, Arc::new(ChainConfig::calibnet()), genesis_block_header).unwrap() } pub fn calibnet() -> Self { Self::_load( @@ -1887,7 +1865,7 @@ mod tests { #[track_caller] fn assert_path_change( - store: &ChainStore, + store: &ChainStore, from: impl MakeTipset, to: impl MakeTipset, expected: impl IntoIterator>, diff --git a/src/rpc/methods/common.rs b/src/rpc/methods/common.rs index ff74190e2879..5c1aee3e41a4 100644 --- a/src/rpc/methods/common.rs +++ b/src/rpc/methods/common.rs @@ -5,10 +5,8 @@ use crate::lotus_json::lotus_json_with_self; use crate::rpc::error::ServerError; use crate::rpc::{ApiPaths, Ctx, Permission, RpcMethod}; use enumflags2::BitFlags; -use fvm_ipld_blockstore::Blockstore; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use std::any::Any; use std::sync::LazyLock; use uuid::Uuid; @@ -25,11 +23,7 @@ impl RpcMethod<0> for Session { type Params = (); type Ok = Uuid; - async fn handle( - _: Ctx, - (): Self::Params, - _: &http::Extensions, - ) -> Result { + async fn handle(_: Ctx, (): Self::Params, _: &http::Extensions) -> Result { Ok(*SESSION_UUID) } } @@ -45,7 +39,7 @@ impl RpcMethod<0> for Version { type Ok = PublicVersion; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -71,7 +65,7 @@ impl RpcMethod<0> for Shutdown { type Ok = (); async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -91,7 +85,7 @@ impl RpcMethod<0> for StartTime { type Ok = chrono::DateTime; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { diff --git a/src/rpc/methods/eth.rs b/src/rpc/methods/eth.rs index a30edce82efc..06c645a928ff 100644 --- a/src/rpc/methods/eth.rs +++ b/src/rpc/methods/eth.rs @@ -21,7 +21,7 @@ use crate::blocks::{Tipset, TipsetKey}; use crate::chain::{ChainStore, compute_base_fee, index::ResolveNullTipset}; use crate::chain_sync::NodeSyncStatus; use crate::cid_collections::CidHashSet; -use crate::db::EthMappingsStore; +use crate::db::DbImpl; use crate::eth::{ EAMMethod, EVMMethod, EthChainId as EthChainIdType, EthEip1559TxArgs, EthLegacyEip155TxArgs, EthLegacyHomesteadTxArgs, parse_eth_transaction, @@ -29,6 +29,7 @@ use crate::eth::{ use crate::lotus_json::{HasLotusJson, lotus_json_with_self}; use crate::message::{ChainMessage, MessageRead as _, MessageReadWrite as _, SignedMessage}; use crate::networks::Height; +use crate::prelude::*; use crate::rpc::{ ApiPaths, Ctx, EthEventHandler, LOOKBACK_NO_LIMIT, Permission, RpcMethod, RpcMethodExt as _, error::ServerError, @@ -54,7 +55,6 @@ use crate::shim::message::Message; use crate::shim::trace::{CallReturn, ExecutionEvent}; use crate::shim::{clock::ChainEpoch, state_tree::StateTree}; use crate::state_manager::{ExecutedMessage, ExecutedTipset, TipsetState, VMFlush}; -use crate::utils::ShallowClone as _; use crate::utils::cache::SizeTrackingLruCache; use crate::utils::db::BlockstoreExt as _; use crate::utils::encoding::from_slice_with_fallback; @@ -62,15 +62,12 @@ use crate::utils::get_size::{CidWrapper, big_int_heap_size_helper}; use crate::utils::misc::env::env_or_default; use crate::utils::multihash::prelude::*; use ahash::HashSet; -use anyhow::{Context, Error, Result, anyhow, bail, ensure}; -use cid::Cid; +use anyhow::{Error, Result, anyhow, bail, ensure}; use enumflags2::{BitFlags, make_bitflags}; use filter::{ParsedFilter, ParsedFilterTipsets}; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::{CBOR, DAG_CBOR, IPLD_RAW, RawBytes}; use get_size2::GetSize; use ipld_core::ipld::Ipld; -use itertools::Itertools; use nonzero_ext::nonzero; use num::{BigInt, Zero as _}; use nunny::Vec as NonEmpty; @@ -79,7 +76,7 @@ use serde::{Deserialize, Serialize}; use std::num::NonZeroUsize; use std::ops::RangeInclusive; use std::str::FromStr; -use std::sync::{Arc, LazyLock, OnceLock}; +use std::sync::{LazyLock, OnceLock}; use utils::{decode_payload, lookup_eth_address}; static FOREST_TRACE_FILTER_MAX_RESULT: LazyLock = @@ -476,8 +473,8 @@ impl Block { /// Creates a new Ethereum block from a Filecoin tipset, executing transactions if requested. /// /// Reference: - pub async fn from_filecoin_tipset( - ctx: Ctx, + pub async fn from_filecoin_tipset( + ctx: Ctx, tipset: crate::blocks::Tipset, tx_info: TxInfo, ) -> Result { @@ -769,7 +766,7 @@ impl RpcMethod<0> for Web3ClientVersion { type Ok = Arc; async fn handle( - _: Ctx, + _: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -798,7 +795,7 @@ impl RpcMethod<0> for EthAccounts { type Ok = Vec; async fn handle( - _: Ctx, + _: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -821,7 +818,7 @@ impl RpcMethod<0> for EthBaseFee { type Ok = EthBigInt; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -835,7 +832,7 @@ impl RpcMethod<0> for EthBaseFee { .get(&Height::FireHorse) .context("Missing FireHorse height")? .epoch; - let base_fee = compute_base_fee(ctx.store(), &ts, smoke_height, firehorse_height) + let base_fee = compute_base_fee(ctx.db(), &ts, smoke_height, firehorse_height) .context("failed to compute base fee for eth_baseFee")?; Ok(EthBigInt(base_fee.atto().clone())) } @@ -853,7 +850,7 @@ impl RpcMethod<0> for EthBlockNumber { type Ok = EthUint64; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -889,7 +886,7 @@ impl RpcMethod<0> for EthChainId { type Ok = Arc; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -914,7 +911,7 @@ impl RpcMethod<0> for EthGasPrice { type Ok = GasPriceResult; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -945,7 +942,7 @@ impl RpcMethod<2> for EthGetBalance { type Ok = EthBigInt; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, block_param): Self::Params, ext: &http::Extensions, ) -> Result { @@ -958,11 +955,7 @@ impl RpcMethod<2> for EthGetBalance { } } -async fn eth_get_balance( - ctx: &Ctx, - address: &EthAddress, - ts: &Tipset, -) -> Result { +async fn eth_get_balance(ctx: &Ctx, address: &EthAddress, ts: &Tipset) -> Result { let fil_addr = address.to_filecoin_address()?; let TipsetState { state_root, .. } = ctx.state_manager.load_tipset_state(ts).await?; let state_tree = ctx.state_manager.get_state_tree(&state_root)?; @@ -972,16 +965,13 @@ async fn eth_get_balance( - chain_store: &ChainStore, - block_hash: &EthHash, -) -> anyhow::Result { +fn get_tipset_from_hash(chain_store: &ChainStore, block_hash: &EthHash) -> anyhow::Result { let tsk = chain_store.get_required_tipset_key(block_hash)?; Ok(chain_store.chain_index().load_required_tipset(&tsk)?) } -fn resolve_block_number_tipset( - chain: &ChainStore, +fn resolve_block_number_tipset( + chain: &ChainStore, block_number: EthInt64, resolve: ResolveNullTipset, ) -> anyhow::Result { @@ -995,8 +985,8 @@ fn resolve_block_number_tipset( .load_required_tipset_by_height(height, head, resolve)?) } -fn resolve_block_hash_tipset( - chain: &ChainStore, +fn resolve_block_hash_tipset( + chain: &ChainStore, block_hash: &EthHash, require_canonical: bool, resolve: ResolveNullTipset, @@ -1210,8 +1200,8 @@ pub fn new_eth_tx_from_signed_message( /// Creates an Ethereum transaction from Filecoin message lookup. If `None` is passed for `tx_index`, /// it looks up the transaction index of the message in the tipset. /// Otherwise, it uses some index passed into the function. -fn new_eth_tx_from_message_lookup( - ctx: &Ctx, +fn new_eth_tx_from_message_lookup( + ctx: &Ctx, message_lookup: &MessageLookup, tx_index: Option, ) -> Result { @@ -1250,9 +1240,9 @@ fn new_eth_tx_from_message_lookup( }) } -fn new_eth_tx( - ctx: &Ctx, - state: &StateTree, +fn new_eth_tx( + ctx: &Ctx, + state: &StateTree, block_height: ChainEpoch, msg_tipset_cid: &Cid, msg_cid: &Cid, @@ -1269,8 +1259,8 @@ fn new_eth_tx( }) } -async fn new_eth_tx_receipt( - ctx: &Ctx, +async fn new_eth_tx_receipt( + ctx: &Ctx, tipset: &Tipset, tx: &ApiEthTx, msg_cid: Cid, @@ -1337,10 +1327,8 @@ async fn new_eth_tx_receipt( - ctx: &Ctx, +pub async fn eth_logs_for_block_and_transaction( + ctx: &Ctx, ts: &Tipset, block_hash: &EthHash, msg_cid: &Cid, @@ -1367,8 +1355,8 @@ pub async fn eth_logs_for_block_and_transaction< eth_filter_logs_from_events(ctx, &events) } -pub async fn eth_logs_with_filter( - ctx: &Ctx, +pub async fn eth_logs_with_filter( + ctx: &Ctx, ts: &Tipset, spec: Option, ) -> anyhow::Result> { @@ -1384,13 +1372,13 @@ pub async fn eth_logs_with_filter(ctx: &Ctx, message_cid: Cid) -> Result { +fn get_signed_message(ctx: &Ctx, message_cid: Cid) -> Result { let result: Result = - crate::chain::message_from_cid(ctx.store(), &message_cid); + crate::chain::message_from_cid(ctx.db(), &message_cid); result.or_else(|_| { // We couldn't find the signed message, it might be a BLS message, so search for a regular message. - let msg: Message = crate::chain::message_from_cid(ctx.store(), &message_cid) + let msg: Message = crate::chain::message_from_cid(ctx.db(), &message_cid) .with_context(|| format!("failed to find msg {message_cid}"))?; Ok(SignedMessage::new_unchecked( msg, @@ -1411,7 +1399,7 @@ impl RpcMethod<2> for EthGetBlockByHash { type Ok = Block; async fn handle( - ctx: Ctx, + ctx: Ctx, (block_hash, full_tx_info): Self::Params, ext: &http::Extensions, ) -> Result { @@ -1439,7 +1427,7 @@ impl RpcMethod<2> for EthGetBlockByNumber { type Ok = Block; async fn handle( - ctx: Ctx, + ctx: Ctx, (block_param, full_tx_info): Self::Params, ext: &http::Extensions, ) -> Result { @@ -1453,8 +1441,8 @@ impl RpcMethod<2> for EthGetBlockByNumber { } } -async fn get_block_receipts( - ctx: &Ctx, +async fn get_block_receipts( + ctx: &Ctx, ts: Tipset, limit: Option, ) -> Result> { @@ -1518,7 +1506,7 @@ impl RpcMethod<1> for EthGetBlockReceipts { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (block_param,): Self::Params, ext: &http::Extensions, ) -> Result { @@ -1547,7 +1535,7 @@ impl RpcMethod<2> for EthGetBlockReceiptsLimited { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (block_param, limit): Self::Params, ext: &http::Extensions, ) -> Result { @@ -1573,7 +1561,7 @@ impl RpcMethod<1> for EthGetBlockTransactionCountByHash { type Ok = EthUint64; async fn handle( - ctx: Ctx, + ctx: Ctx, (block_hash,): Self::Params, _: &http::Extensions, ) -> Result { @@ -1583,7 +1571,7 @@ impl RpcMethod<1> for EthGetBlockTransactionCountByHash { if ts.epoch() > head.epoch() { return Err(anyhow::anyhow!("requested a future epoch (beyond \"latest\")").into()); } - let count = count_messages_in_tipset(ctx.store(), &ts)?; + let count = count_messages_in_tipset(ctx.db(), &ts)?; Ok(EthUint64(count as _)) } } @@ -1603,7 +1591,7 @@ impl RpcMethod<1> for EthGetBlockTransactionCountByNumber { type Ok = EthUint64; async fn handle( - ctx: Ctx, + ctx: Ctx, (block_number,): Self::Params, ext: &http::Extensions, ) -> Result { @@ -1611,7 +1599,7 @@ impl RpcMethod<1> for EthGetBlockTransactionCountByNumber { let ts = resolver .tipset_by_block_number_or_hash(block_number, ResolveNullTipset::TakeOlder) .await?; - let count = count_messages_in_tipset(ctx.store(), &ts)?; + let count = count_messages_in_tipset(ctx.db(), &ts)?; Ok(EthUint64(count as _)) } } @@ -1628,7 +1616,7 @@ impl RpcMethod<1> for EthGetMessageCidByTransactionHash { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (tx_hash,): Self::Params, _: &http::Extensions, ) -> Result { @@ -1645,14 +1633,14 @@ impl RpcMethod<1> for EthGetMessageCidByTransactionHash { let cid = tx_hash.to_cid(); let result: Result, crate::chain::Error> = - crate::chain::messages_from_cids(ctx.store(), &[cid]); + crate::chain::messages_from_cids(ctx.db(), &[cid]); if result.is_ok() { // This is an Eth Tx, Secp message, Or BLS message in the mpool return Ok(Some(cid)); } let result: Result, crate::chain::Error> = - crate::chain::messages_from_cids(ctx.store(), &[cid]); + crate::chain::messages_from_cids(ctx.db(), &[cid]); if result.is_ok() { // This is a BLS message return Ok(Some(cid)); @@ -1689,7 +1677,7 @@ impl RpcMethod<0> for EthSyncing { type Ok = EthSyncingResult; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, ext: &http::Extensions, ) -> Result { @@ -1736,7 +1724,7 @@ impl RpcMethod<2> for EthEstimateGas { type Ok = EthUint64; async fn handle( - ctx: Ctx, + ctx: Ctx, (tx, block_param): Self::Params, ext: &http::Extensions, ) -> Result { @@ -1752,14 +1740,11 @@ impl RpcMethod<2> for EthEstimateGas { } } -async fn eth_estimate_gas( - ctx: &Ctx, +async fn eth_estimate_gas( + ctx: &Ctx, tx: EthCallMessage, tipset: Tipset, -) -> Result -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +) -> Result { let mut msg = Message::try_from(tx)?; // Set the gas limit to the zero sentinel value, which makes // gas estimation actually run. @@ -1794,14 +1779,11 @@ where } } -async fn apply_message( - ctx: &Ctx, +async fn apply_message( + ctx: &Ctx, tipset: Option, msg: Message, -) -> Result -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +) -> Result { let (invoc_res, _) = ctx .state_manager .apply_on_state_with_gas(tipset, msg, VMFlush::Skip) @@ -1829,14 +1811,7 @@ where Ok(invoc_res) } -pub async fn eth_gas_search( - data: &Ctx, - msg: Message, - tsk: &ApiTipsetKey, -) -> anyhow::Result -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +pub async fn eth_gas_search(data: &Ctx, msg: Message, tsk: &ApiTipsetKey) -> anyhow::Result { let (_invoc_res, apply_ret, prior_messages, ts) = gas::GasEstimateGasLimit::estimate_call_with_gas(data, msg.clone(), tsk).await?; if apply_ret.msg_receipt().exit_code().is_success() { @@ -1869,28 +1844,22 @@ where /// message with. It first finds a high gas limit that allows the message to execute /// by doubling the previous gas limit until it succeeds then does a binary /// search till it gets within a range of 1% -async fn gas_search( - data: &Ctx, +async fn gas_search( + data: &Ctx, msg: &Message, prior_messages: &[ChainMessage], ts: Tipset, -) -> anyhow::Result -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +) -> anyhow::Result { let mut high = msg.gas_limit; let mut low = msg.gas_limit; - async fn can_succeed( - data: &Ctx, + async fn can_succeed( + data: &Ctx, mut msg: Message, prior_messages: &[ChainMessage], ts: Tipset, limit: u64, - ) -> anyhow::Result - where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, - { + ) -> anyhow::Result { msg.gas_limit = limit; let (_invoc_res, apply_ret, _, _) = data .state_manager @@ -1943,7 +1912,7 @@ impl RpcMethod<3> for EthFeeHistory { type Ok = EthFeeHistoryResult; async fn handle( - ctx: Ctx, + ctx: Ctx, (EthUint64(block_count), newest_block_number, reward_percentiles): Self::Params, ext: &http::Extensions, ) -> Result { @@ -1955,8 +1924,8 @@ impl RpcMethod<3> for EthFeeHistory { } } -async fn eth_fee_history( - ctx: Ctx, +async fn eth_fee_history( + ctx: Ctx, tipset: Tipset, block_count: u64, reward_percentiles: Option>, @@ -1979,7 +1948,7 @@ async fn eth_fee_history 0) .take(block_count as _) { @@ -2092,7 +2061,7 @@ impl RpcMethod<2> for EthGetCode { type Ok = EthBytes; async fn handle( - ctx: Ctx, + ctx: Ctx, (eth_address, block_param): Self::Params, ext: &http::Extensions, ) -> Result { @@ -2104,14 +2073,11 @@ impl RpcMethod<2> for EthGetCode { } } -async fn eth_get_code( - ctx: &Ctx, +async fn eth_get_code( + ctx: &Ctx, ts: &Tipset, eth_address: &EthAddress, -) -> Result -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +) -> Result { let to_address = FilecoinAddress::try_from(eth_address)?; let TipsetState { state_root, .. } = ctx.state_manager.load_tipset_state(ts).await?; let state_tree = ctx.state_manager.get_state_tree(&state_root)?; @@ -2137,7 +2103,7 @@ where }; let api_invoc_result = 'invoc: { - for ts in ts.shallow_clone().chain(ctx.store()) { + for ts in ts.shallow_clone().chain(ctx.db()) { match ctx .state_manager .call_on_state(state_root, &message, Some(ts)) @@ -2165,7 +2131,7 @@ where let get_bytecode_return: GetBytecodeReturn = fvm_ipld_encoding::from_slice(msg_rct.return_data().as_slice())?; if let Some(cid) = get_bytecode_return.0 { - Ok(EthBytes(ctx.store().get_required(&cid)?)) + Ok(EthBytes(ctx.db().get_required(&cid)?)) } else { Ok(Default::default()) } @@ -2187,7 +2153,7 @@ impl RpcMethod<3> for EthGetStorageAt { type Ok = EthBytes; async fn handle( - ctx: Ctx, + ctx: Ctx, (eth_address, position, block_number_or_hash): Self::Params, ext: &http::Extensions, ) -> Result { @@ -2199,8 +2165,8 @@ impl RpcMethod<3> for EthGetStorageAt { } } -async fn get_storage_at( - ctx: &Ctx, +async fn get_storage_at( + ctx: &Ctx, ts: Tipset, eth_address: EthAddress, position: EthBytes, @@ -2230,7 +2196,7 @@ async fn get_storage_at, + ctx: Ctx, (sender, block_param): Self::Params, ext: &http::Extensions, ) -> Result { @@ -2296,14 +2262,11 @@ impl RpcMethod<2> for EthGetTransactionCount { } } -async fn eth_get_transaction_count( - ctx: &Ctx, +async fn eth_get_transaction_count( + ctx: &Ctx, ts: &Tipset, addr: FilecoinAddress, -) -> Result -where - B: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +) -> Result { let TipsetState { state_root, .. } = ctx.state_manager.load_tipset_state(ts).await?; let state_tree = ctx.state_manager.get_state_tree(&state_root)?; @@ -2313,7 +2276,7 @@ where }; if is_evm_actor(&actor.code) { - let evm_state = evm::State::load(ctx.store(), actor.code, actor.state)?; + let evm_state = evm::State::load(ctx.db(), actor.code, actor.state)?; if !evm_state.is_alive() { return Ok(EthUint64(0)); } @@ -2335,7 +2298,7 @@ impl RpcMethod<0> for EthMaxPriorityFeePerGas { type Ok = EthBigInt; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -2358,7 +2321,7 @@ impl RpcMethod<0> for EthProtocolVersion { type Ok = EthUint64; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -2382,7 +2345,7 @@ impl RpcMethod<2> for EthGetTransactionByBlockNumberAndIndex { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (block_param, tx_index): Self::Params, ext: &http::Extensions, ) -> Result { @@ -2394,14 +2357,11 @@ impl RpcMethod<2> for EthGetTransactionByBlockNumberAndIndex { } } -fn eth_tx_by_block_num_and_idx( - ctx: &Ctx, +fn eth_tx_by_block_num_and_idx( + ctx: &Ctx, ts: &Tipset, tx_index: EthUint64, -) -> Result, ServerError> -where - B: Blockstore + Send + Sync + 'static, -{ +) -> Result, ServerError> { let messages = ctx.chain_store().messages_for_tipset(ts)?; let EthUint64(index) = tx_index; @@ -2433,7 +2393,7 @@ impl RpcMethod<2> for EthGetTransactionByBlockHashAndIndex { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (block_hash, tx_index): Self::Params, _: &http::Extensions, ) -> Result { @@ -2477,7 +2437,7 @@ impl RpcMethod<1> for EthGetTransactionByHash { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (tx_hash,): Self::Params, _: &http::Extensions, ) -> Result { @@ -2497,7 +2457,7 @@ impl RpcMethod<2> for EthGetTransactionByHashLimited { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (tx_hash, limit): Self::Params, _: &http::Extensions, ) -> Result { @@ -2506,7 +2466,7 @@ impl RpcMethod<2> for EthGetTransactionByHashLimited { } async fn get_eth_transaction_by_hash( - ctx: &Ctx, + ctx: &Ctx, tx_hash: &EthHash, limit: Option, ) -> Result, ServerError> { @@ -2571,12 +2531,12 @@ impl RpcMethod<1> for EthGetTransactionHashByCid { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (cid,): Self::Params, _: &http::Extensions, ) -> Result { let smsgs_result: Result, crate::chain::Error> = - crate::chain::messages_from_cids(ctx.store(), &[cid]); + crate::chain::messages_from_cids(ctx.db(), &[cid]); if let Ok(smsgs) = smsgs_result && let Some(smsg) = smsgs.first() { @@ -2592,7 +2552,7 @@ impl RpcMethod<1> for EthGetTransactionHashByCid { return Ok(Some(hash)); } - let msg_result = crate::chain::get_chain_message(ctx.store(), &cid); + let msg_result = crate::chain::get_chain_message(ctx.db(), &cid); if let Ok(msg) = msg_result { return Ok(Some(msg.cid().into())); } @@ -2612,7 +2572,7 @@ impl RpcMethod<2> for EthCall { type Params = (EthCallMessage, BlockNumberOrHash); type Ok = EthBytes; async fn handle( - ctx: Ctx, + ctx: Ctx, (tx, block_param): Self::Params, ext: &http::Extensions, ) -> Result { @@ -2624,14 +2584,7 @@ impl RpcMethod<2> for EthCall { } } -async fn eth_call( - ctx: &Ctx, - tx: EthCallMessage, - ts: Tipset, -) -> Result -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +async fn eth_call(ctx: &Ctx, tx: EthCallMessage, ts: Tipset) -> Result { let msg = Message::try_from(tx)?; let invoke_result = apply_message(ctx, Some(ts), msg.clone()).await?; @@ -2661,7 +2614,7 @@ impl RpcMethod<1> for EthNewFilter { type Ok = FilterID; async fn handle( - ctx: Ctx, + ctx: Ctx, (filter_spec,): Self::Params, _: &http::Extensions, ) -> Result { @@ -2683,7 +2636,7 @@ impl RpcMethod<0> for EthNewPendingTransactionFilter { type Ok = FilterID; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -2704,7 +2657,7 @@ impl RpcMethod<0> for EthNewBlockFilter { type Ok = FilterID; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -2726,7 +2679,7 @@ impl RpcMethod<1> for EthUninstallFilter { type Ok = bool; async fn handle( - ctx: Ctx, + ctx: Ctx, (filter_id,): Self::Params, _: &http::Extensions, ) -> Result { @@ -2754,7 +2707,7 @@ impl RpcMethod<0> for EthUnsubscribe { // We still need to implement the [`RpcMethod`] trait to expose method metadata // like [`NAME`](Self::NAME), [`NAME_ALIAS`](Self::NAME_ALIAS), [`PERMISSION`](Self::PERMISSION), etc.. async fn handle( - _: Ctx, + _: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -2780,7 +2733,7 @@ impl RpcMethod<0> for EthSubscribe { // We still need to implement the [`RpcMethod`] trait to expose method metadata // like [`NAME`](Self::NAME), [`NAME_ALIAS`](Self::NAME_ALIAS), [`PERMISSION`](Self::PERMISSION), etc.. async fn handle( - _: Ctx, + _: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -2799,7 +2752,7 @@ impl RpcMethod<1> for EthAddressToFilecoinAddress { type Params = (EthAddress,); type Ok = FilecoinAddress; async fn handle( - _ctx: Ctx, + _ctx: Ctx, (eth_address,): Self::Params, _: &http::Extensions, ) -> Result { @@ -2819,7 +2772,7 @@ impl RpcMethod<2> for FilecoinAddressToEthAddress { type Params = (FilecoinAddress, Option); type Ok = EthAddress; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, block_param): Self::Params, ext: &http::Extensions, ) -> Result { @@ -2840,7 +2793,7 @@ impl RpcMethod<2> for FilecoinAddressToEthAddress { } async fn get_eth_transaction_receipt( - ctx: Ctx, + ctx: Ctx, tx_hash: EthHash, limit: Option, ) -> Result, ServerError> { @@ -2914,7 +2867,7 @@ impl RpcMethod<1> for EthGetTransactionReceipt { type Params = (EthHash,); type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (tx_hash,): Self::Params, _: &http::Extensions, ) -> Result { @@ -2933,7 +2886,7 @@ impl RpcMethod<2> for EthGetTransactionReceiptLimited { type Params = (EthHash, ChainEpoch); type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (tx_hash, limit): Self::Params, _: &http::Extensions, ) -> Result { @@ -2953,13 +2906,13 @@ impl RpcMethod<1> for EthSendRawTransaction { type Ok = EthHash; async fn handle( - ctx: Ctx, + ctx: Ctx, (raw_tx,): Self::Params, _: &http::Extensions, ) -> Result { let tx_args = parse_eth_transaction(&raw_tx.0)?; let smsg = tx_args.get_signed_message(ctx.chain_config().eth_chain_id)?; - let cid = ctx.mpool.as_ref().push(smsg).await?; + let cid = ctx.mpool.push(smsg).await?; Ok(cid.into()) } } @@ -2976,13 +2929,13 @@ impl RpcMethod<1> for EthSendRawTransactionUntrusted { type Ok = EthHash; async fn handle( - ctx: Ctx, + ctx: Ctx, (raw_tx,): Self::Params, _: &http::Extensions, ) -> Result { let tx_args = parse_eth_transaction(&raw_tx.0)?; let smsg = tx_args.get_signed_message(ctx.chain_config().eth_chain_id)?; - let cid = ctx.mpool.as_ref().push_untrusted(smsg).await?; + let cid = ctx.mpool.push_untrusted(smsg).await?; Ok(cid.into()) } } @@ -3112,15 +3065,15 @@ fn eth_filter_logs_from_tipsets(events: &[CollectedEvent]) -> anyhow::Result( - ctx: &Ctx, +fn eth_filter_logs_from_messages( + ctx: &Ctx, events: &[CollectedEvent], ) -> anyhow::Result> { events .iter() .filter_map(|event| { match eth_tx_hash_from_message_cid( - ctx.store(), + ctx.db(), &event.msg_cid, ctx.state_manager.chain_config().eth_chain_id, ) { @@ -3135,8 +3088,8 @@ fn eth_filter_logs_from_messages( .collect() } -fn eth_filter_logs_from_events( - ctx: &Ctx, +fn eth_filter_logs_from_events( + ctx: &Ctx, events: &[CollectedEvent], ) -> anyhow::Result> { use ahash::AHashMap as HashMap; @@ -3159,7 +3112,7 @@ fn eth_filter_logs_from_events( let transaction_hash = if let Some(h) = tx_hash_by_msg.get(&event.msg_cid) { *h } else { - match eth_tx_hash_from_message_cid(ctx.store(), &event.msg_cid, chain_id)? { + match eth_tx_hash_from_message_cid(ctx.db(), &event.msg_cid, chain_id)? { Some(h) => { tx_hash_by_msg.insert(event.msg_cid, h); h @@ -3202,8 +3155,8 @@ fn eth_filter_logs_from_events( Ok(logs) } -fn eth_filter_result_from_events( - ctx: &Ctx, +fn eth_filter_result_from_events( + ctx: &Ctx, events: &[CollectedEvent], ) -> anyhow::Result { Ok(EthFilterResult::Logs(eth_filter_logs_from_events( @@ -3217,8 +3170,8 @@ fn eth_filter_result_from_tipsets(events: &[CollectedEvent]) -> anyhow::Result( - ctx: &Ctx, +fn eth_filter_result_from_messages( + ctx: &Ctx, events: &[CollectedEvent], ) -> anyhow::Result { Ok(EthFilterResult::Hashes(eth_filter_logs_from_messages( @@ -3237,7 +3190,7 @@ impl RpcMethod<1> for EthGetLogs { type Params = (EthFilterSpec,); type Ok = EthFilterResult; async fn handle( - ctx: Ctx, + ctx: Ctx, (eth_filter,): Self::Params, _: &http::Extensions, ) -> Result { @@ -3272,7 +3225,7 @@ impl RpcMethod<1> for EthGetFilterLogs { type Params = (FilterID,); type Ok = EthFilterResult; async fn handle( - ctx: Ctx, + ctx: Ctx, (filter_id,): Self::Params, _: &http::Extensions, ) -> Result { @@ -3323,7 +3276,7 @@ impl RpcMethod<1> for EthGetFilterChanges { type Params = (FilterID,); type Ok = EthFilterResult; async fn handle( - ctx: Ctx, + ctx: Ctx, (filter_id,): Self::Params, _: &http::Extensions, ) -> Result { @@ -3437,7 +3390,7 @@ impl RpcMethod<1> for EthTraceBlock { type Params = (BlockNumberOrHash,); type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (block_param,): Self::Params, ext: &http::Extensions, ) -> Result { @@ -3450,16 +3403,13 @@ impl RpcMethod<1> for EthTraceBlock { } /// Replays a tipset and resolves every non-system transaction into a [`trace::TipsetTraceEntry`]. -async fn execute_tipset_traces( - ctx: &Ctx, +async fn execute_tipset_traces( + ctx: &Ctx, ts: &Tipset, ext: &http::Extensions, -) -> Result<(StateTree, Vec), ServerError> -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +) -> Result<(StateTree, Vec), ServerError> { let (state_root, raw_traces) = { - let sm = ctx.state_manager.clone(); + let sm = ctx.state_manager.shallow_clone(); let ts = ts.shallow_clone(); tokio::task::spawn_blocking(move || sm.execution_trace(&ts)) .await @@ -3496,14 +3446,11 @@ fn non_system_traces_with_positions( .map(|(idx, ir)| (idx as i64, ir)) } -async fn eth_trace_block( - ctx: &Ctx, +async fn eth_trace_block( + ctx: &Ctx, ts: &Tipset, ext: &http::Extensions, -) -> Result, ServerError> -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +) -> Result, ServerError> { let (state, entries) = execute_tipset_traces(ctx, ts, ext).await?; let block_hash: EthHash = ts.key().cid()?.into(); let mut all_traces = vec![]; @@ -3537,7 +3484,7 @@ impl RpcMethod<2> for EthDebugTraceTransaction { type Ok = GethTrace; async fn handle( - ctx: Ctx, + ctx: Ctx, (tx_hash, opts): Self::Params, ext: &http::Extensions, ) -> Result { @@ -3546,16 +3493,13 @@ impl RpcMethod<2> for EthDebugTraceTransaction { } } -async fn debug_trace_transaction( - ctx: Ctx, +async fn debug_trace_transaction( + ctx: Ctx, ext: &http::Extensions, api_path: ApiPaths, tx_hash: String, opts: GethDebugTracingOptions, -) -> Result -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +) -> Result { let tracer = match &opts.tracer { Some(t) => t.clone(), None => { @@ -3617,11 +3561,11 @@ where touched.insert(addr); } - let pre_state = StateTree::new_from_root(ctx.store_owned(), &pre_root)?; - let post_state = StateTree::new_from_root(ctx.store_owned(), &post_root)?; + let pre_state = StateTree::new_from_root(ctx.db(), &pre_root)?; + let post_state = StateTree::new_from_root(ctx.db(), &post_root)?; let frame = trace::build_prestate_frame( - ctx.store(), + ctx.db(), &pre_state, &post_state, &touched, @@ -3696,7 +3640,7 @@ impl RpcMethod<3> for EthTraceCall { ); type Ok = EthTraceResults; async fn handle( - ctx: Ctx, + ctx: Ctx, (tx, trace_types, block_param): Self::Params, ext: &http::Extensions, ) -> Result { @@ -3715,7 +3659,7 @@ impl RpcMethod<3> for EthTraceCall { .load_tipset_state(&ts) .await .context("failed to get tipset state")?; - let pre_state = StateTree::new_from_root(ctx.store_owned(), &pre_state_root)?; + let pre_state = StateTree::new_from_root(ctx.db(), &pre_state_root)?; let (invoke_result, post_state_root) = ctx .state_manager @@ -3724,7 +3668,7 @@ impl RpcMethod<3> for EthTraceCall { .context("failed to apply message")?; let post_state_root = post_state_root.context("post-execution state root required for trace call")?; - let post_state = StateTree::new_from_root(ctx.store_owned(), &post_state_root)?; + let post_state = StateTree::new_from_root(ctx.db(), &post_state_root)?; let mut trace_results = EthTraceResults { output: get_trace_output(&msg, &invoke_result)?, @@ -3760,7 +3704,7 @@ impl RpcMethod<3> for EthTraceCall { } let state_diff = - trace::build_state_diff(ctx.store(), &pre_state, &post_state, &all_touched)?; + trace::build_state_diff(ctx.db(), &pre_state, &post_state, &all_touched)?; trace_results.state_diff = Some(state_diff); } @@ -3819,7 +3763,7 @@ impl RpcMethod<1> for EthTraceTransaction { type Params = (String,); type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (tx_hash,): Self::Params, ext: &http::Extensions, ) -> Result { @@ -3858,7 +3802,7 @@ impl RpcMethod<2> for EthTraceReplayBlockTransactions { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (block_param, trace_types): Self::Params, ext: &http::Extensions, ) -> Result { @@ -3878,14 +3822,11 @@ impl RpcMethod<2> for EthTraceReplayBlockTransactions { } } -async fn eth_trace_replay_block_transactions( - ctx: &Ctx, +async fn eth_trace_replay_block_transactions( + ctx: &Ctx, ts: &Tipset, ext: &http::Extensions, -) -> Result, ServerError> -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +) -> Result, ServerError> { let (state, entries) = execute_tipset_traces(ctx, ts, ext).await?; let mut all_traces = vec![]; @@ -3901,10 +3842,8 @@ where Ok(all_traces) } -async fn get_eth_block_number_from_string< - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, ->( - ctx: &Ctx, +async fn get_eth_block_number_from_string( + ctx: &Ctx, block: Option<&str>, resolve: ResolveNullTipset, api_path: ApiPaths, @@ -3936,7 +3875,7 @@ impl RpcMethod<1> for EthTraceFilter { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (filter,): Self::Params, ext: &http::Extensions, ) -> Result { @@ -3972,7 +3911,7 @@ impl RpcMethod<1> for EthTraceFilter { } async fn trace_filter( - ctx: Ctx, + ctx: Ctx, filter: EthTraceFilterCriteria, from_block: EthUint64, to_block: EthUint64, diff --git a/src/rpc/methods/eth/filter/mod.rs b/src/rpc/methods/eth/filter/mod.rs index 2670a38b3dc0..d61661ba52ee 100644 --- a/src/rpc/methods/eth/filter/mod.rs +++ b/src/rpc/methods/eth/filter/mod.rs @@ -28,7 +28,6 @@ use crate::blocks::Tipset; use crate::blocks::TipsetKey; use crate::chain::index::ResolveNullTipset; use crate::cli_shared::cli::EventsConfig; -use crate::db::EthMappingsStore; use crate::rpc::eth::EVM_WORD_LENGTH; use crate::rpc::eth::errors::EthErrors; use crate::rpc::eth::filter::event::*; @@ -47,7 +46,6 @@ use ahash::AHashMap as HashMap; use anyhow::{Context, Error, anyhow, bail, ensure}; use cid::Cid; use futures::{TryStreamExt as _, stream::FuturesOrdered}; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::IPLD_RAW; use serde::*; use std::ops::RangeInclusive; @@ -277,9 +275,9 @@ impl EthEventHandler { } } - pub fn parse_eth_filter_spec( + pub fn parse_eth_filter_spec( &self, - ctx: &Ctx, + ctx: &Ctx, filter_spec: &EthFilterSpec, ) -> anyhow::Result { EthFilterSpec::parse_eth_filter_spec( @@ -289,10 +287,8 @@ impl EthEventHandler { ) } - pub async fn collect_events_for_tipsets< - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, - >( - ctx: &Ctx, + pub async fn collect_events_for_tipsets( + ctx: &Ctx, tipsets: impl Iterator, spec: Option<&impl Matcher>, skip_event: SkipEvent, @@ -322,8 +318,8 @@ impl EthEventHandler { Ok(()) } - pub async fn collect_events( - ctx: &Ctx, + pub async fn collect_events( + ctx: &Ctx, tipset: &Tipset, spec: Option<&impl Matcher>, skip_event: SkipEvent, @@ -422,27 +418,21 @@ impl EthEventHandler { } /// Gets events by event root. - pub fn get_events_by_event_root( - ctx: &Ctx, - events_root: &Cid, - ) -> anyhow::Result> { - let state_events = - match StampedEvent::get_events(ctx.chain_store().blockstore(), events_root) { - Ok(e) => e, - Err(e) => { - return Err(anyhow::anyhow!("load events amt: {}", e)); - } - }; + pub fn get_events_by_event_root(ctx: &Ctx, events_root: &Cid) -> anyhow::Result> { + let state_events = match StampedEvent::get_events(ctx.chain_store().db(), events_root) { + Ok(e) => e, + Err(e) => { + return Err(anyhow::anyhow!("load events amt: {}", e)); + } + }; let chain_events: Vec = state_events.into_iter().map(Into::into).collect(); Ok(chain_events) } - pub async fn get_events_for_parsed_filter< - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, - >( + pub async fn get_events_for_parsed_filter( &self, - ctx: &Ctx, + ctx: &Ctx, pf: &ParsedFilter, skip_event: SkipEvent, ) -> anyhow::Result> { @@ -477,7 +467,7 @@ impl EthEventHandler { ResolveNullTipset::TakeOlder, )?; let tipsets = max_tipset - .chain(ctx.store()) + .chain(ctx.db()) .take_while(|ts| ts.epoch() >= *range.start()); Self::collect_events_for_tipsets( ctx, diff --git a/src/rpc/methods/eth/pubsub.rs b/src/rpc/methods/eth/pubsub.rs index 9e01a1d6274c..8c81a284b0fe 100644 --- a/src/rpc/methods/eth/pubsub.rs +++ b/src/rpc/methods/eth/pubsub.rs @@ -59,27 +59,22 @@ //! ``` //! -use crate::db::EthMappingsStore; use crate::rpc::eth::pubsub_trait::{ EthPubSubApiServer, LogFilter, SubscriptionKind, SubscriptionParams, }; use crate::rpc::{RPCState, chain}; -use fvm_ipld_blockstore::Blockstore; use jsonrpsee::PendingSubscriptionSink; use jsonrpsee::core::{SubscriptionError, SubscriptionResult}; use std::sync::Arc; use tokio::sync::broadcast::{Receiver as Subscriber, error::RecvError}; #[derive(derive_more::Constructor)] -pub struct EthPubSub { - ctx: Arc>, +pub struct EthPubSub { + ctx: Arc, } #[async_trait::async_trait] -impl EthPubSubApiServer for EthPubSub -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +impl EthPubSubApiServer for EthPubSub { async fn subscribe( &self, pending: PendingSubscriptionSink, @@ -110,14 +105,11 @@ where } } -impl EthPubSub -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +impl EthPubSub { async fn handle_new_heads_subscription( &self, accepted_sink: jsonrpsee::SubscriptionSink, - ctx: Arc>, + ctx: Arc, ) { let (subscriber, handle) = chain::new_heads(ctx); tokio::spawn(async move { @@ -128,7 +120,7 @@ where async fn handle_logs_subscription( &self, accepted_sink: jsonrpsee::SubscriptionSink, - ctx: Arc>, + ctx: Arc, filter_spec: Option, ) { let filter_spec = filter_spec.map(Into::into); diff --git a/src/rpc/methods/eth/tipset_resolver.rs b/src/rpc/methods/eth/tipset_resolver.rs index f3e0f3e68292..4fc6b64c1bfd 100644 --- a/src/rpc/methods/eth/tipset_resolver.rs +++ b/src/rpc/methods/eth/tipset_resolver.rs @@ -2,26 +2,17 @@ // SPDX-License-Identifier: Apache-2.0, MIT use super::*; -use crate::{ - db::EthMappingsStore, - rpc::chain::{ChainGetTipSetFinalityStatus, SAFE_HEIGHT_DISTANCE}, -}; +use crate::rpc::chain::{ChainGetTipSetFinalityStatus, SAFE_HEIGHT_DISTANCE}; use anyhow::Context as _; -pub struct TipsetResolver<'a, DB> -where - DB: Blockstore + Send + Sync + 'static, -{ - ctx: &'a Ctx, +pub struct TipsetResolver<'a> { + ctx: &'a Ctx, api_version: ApiPaths, } -impl<'a, DB> TipsetResolver<'a, DB> -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +impl<'a> TipsetResolver<'a> { /// Creates a TipsetResolver that holds a reference to the given chain context and the API version to use for tipset resolution. - pub fn new(ctx: &'a Ctx, api_version: ApiPaths) -> Self { + pub fn new(ctx: &'a Ctx, api_version: ApiPaths) -> Self { Self { ctx, api_version } } diff --git a/src/rpc/methods/eth/trace/mod.rs b/src/rpc/methods/eth/trace/mod.rs index 8dba2abfb735..532cffc55489 100644 --- a/src/rpc/methods/eth/trace/mod.rs +++ b/src/rpc/methods/eth/trace/mod.rs @@ -25,12 +25,12 @@ pub(crate) use state_diff::build_state_diff; use super::lookup_eth_address; use super::types::EthAddress; -use anyhow::Context; -use fvm_ipld_blockstore::Blockstore; +use crate::{ + prelude::*, + shim::{address::Address, state_tree::StateTree}, +}; use types::EthTrace; -use crate::shim::{address::Address, state_tree::StateTree}; - /// Shared mutable context threaded through recursive trace building. /// /// Used by both Parity-style and Geth-style trace constructors to track @@ -44,7 +44,7 @@ pub(super) struct Environment { pub(super) last_byte_code: Option, } -pub(super) fn base_environment( +pub(super) fn base_environment( state: &StateTree, from: &Address, ) -> anyhow::Result { diff --git a/src/rpc/methods/eth/trace/parity.rs b/src/rpc/methods/eth/trace/parity.rs index 3889cc65891e..a958a601406e 100644 --- a/src/rpc/methods/eth/trace/parity.rs +++ b/src/rpc/methods/eth/trace/parity.rs @@ -17,6 +17,7 @@ use super::types::{ }; use super::utils::trace_to_address; use crate::eth::{EAMMethod, EVMMethod}; +use crate::prelude::*; use crate::rpc::methods::state::ExecutionTrace; use crate::shim::fvm_shared_latest::METHOD_CONSTRUCTOR; use crate::shim::{actors::is_evm_actor, address::Address, error::ExitCode, state_tree::StateTree}; @@ -608,7 +609,7 @@ pub struct TipsetTraceEntry { impl TipsetTraceEntry { /// Builds Parity-style traces for this entry using the given state tree. - pub fn build_parity_traces( + pub fn build_parity_traces( &self, state: &StateTree, ) -> Result, crate::rpc::error::ServerError> { diff --git a/src/rpc/methods/eth/trace/state_diff.rs b/src/rpc/methods/eth/trace/state_diff.rs index d963283a2add..1033c67e5cde 100644 --- a/src/rpc/methods/eth/trace/state_diff.rs +++ b/src/rpc/methods/eth/trace/state_diff.rs @@ -465,8 +465,8 @@ mod tests { #[test] fn test_build_state_diff_multiple_addresses() { let store = Arc::new(MemoryDB::default()); - let mut pre_state = StateTree::new(store.clone(), StateTreeVersion::V5).unwrap(); - let mut post_state = StateTree::new(store.clone(), StateTreeVersion::V5).unwrap(); + let mut pre_state = StateTree::new(&store, StateTreeVersion::V5).unwrap(); + let mut post_state = StateTree::new(&store, StateTreeVersion::V5).unwrap(); // Actor 1: balance increase let addr1 = FilecoinAddress::new_id(2001); @@ -620,8 +620,8 @@ mod tests { create_evm_actor_with_bytecode(&store, bal, 0, nonce, code) }); - let mut pre_state = StateTree::new(store.clone(), StateTreeVersion::V5).unwrap(); - let mut post_state = StateTree::new(store.clone(), StateTreeVersion::V5).unwrap(); + let mut pre_state = StateTree::new(&store, StateTreeVersion::V5).unwrap(); + let mut post_state = StateTree::new(&store, StateTreeVersion::V5).unwrap(); let addr = FilecoinAddress::new_id(actor_id); if let Some(actor) = pre_actor { diff --git a/src/rpc/methods/eth/trace/test_helpers.rs b/src/rpc/methods/eth/trace/test_helpers.rs index 421bff698402..91c39f493f05 100644 --- a/src/rpc/methods/eth/trace/test_helpers.rs +++ b/src/rpc/methods/eth/trace/test_helpers.rs @@ -94,15 +94,15 @@ pub fn create_masked_id_eth_address(actor_id: u64) -> EthAddress { pub struct TestStateTrees { pub store: Arc, - pub pre_state: StateTree, - pub post_state: StateTree, + pub pre_state: StateTree>, + pub post_state: StateTree>, } impl TestStateTrees { pub fn new() -> anyhow::Result { let store = Arc::new(MemoryDB::default()); - let pre_state = StateTree::new(store.clone(), StateTreeVersion::V5)?; - let post_state = StateTree::new(store.clone(), StateTreeVersion::V5)?; + let pre_state = StateTree::new(&store, StateTreeVersion::V5)?; + let post_state = StateTree::new(&store, StateTreeVersion::V5)?; Ok(Self { store, pre_state, @@ -117,8 +117,8 @@ impl TestStateTrees { post_actor: ActorState, ) -> anyhow::Result { let store = Arc::new(MemoryDB::default()); - let mut pre_state = StateTree::new(store.clone(), StateTreeVersion::V5)?; - let mut post_state = StateTree::new(store.clone(), StateTreeVersion::V5)?; + let mut pre_state = StateTree::new(&store, StateTreeVersion::V5)?; + let mut post_state = StateTree::new(&store, StateTreeVersion::V5)?; let addr = FilecoinAddress::new_id(actor_id); pre_state.set_actor(&addr, pre_actor)?; post_state.set_actor(&addr, post_actor)?; @@ -132,8 +132,8 @@ impl TestStateTrees { /// Create state trees with actor only in post (creation scenario). pub fn with_created_actor(actor_id: u64, post_actor: ActorState) -> anyhow::Result { let store = Arc::new(MemoryDB::default()); - let pre_state = StateTree::new(store.clone(), StateTreeVersion::V5)?; - let mut post_state = StateTree::new(store.clone(), StateTreeVersion::V5)?; + let pre_state = StateTree::new(&store, StateTreeVersion::V5)?; + let mut post_state = StateTree::new(&store, StateTreeVersion::V5)?; let addr = FilecoinAddress::new_id(actor_id); post_state.set_actor(&addr, post_actor)?; Ok(Self { @@ -146,8 +146,8 @@ impl TestStateTrees { /// Create state trees with actor only in pre (deletion scenario). pub fn with_deleted_actor(actor_id: u64, pre_actor: ActorState) -> anyhow::Result { let store = Arc::new(MemoryDB::default()); - let mut pre_state = StateTree::new(store.clone(), StateTreeVersion::V5)?; - let post_state = StateTree::new(store.clone(), StateTreeVersion::V5)?; + let mut pre_state = StateTree::new(&store, StateTreeVersion::V5)?; + let post_state = StateTree::new(&store, StateTreeVersion::V5)?; let addr = FilecoinAddress::new_id(actor_id); pre_state.set_actor(&addr, pre_actor)?; Ok(Self { diff --git a/src/rpc/methods/f3.rs b/src/rpc/methods/f3.rs index 0e02d469f1c3..174db788d935 100644 --- a/src/rpc/methods/f3.rs +++ b/src/rpc/methods/f3.rs @@ -21,10 +21,11 @@ use crate::{ chain_sync::TipsetValidator, db::{ BlockstoreReadCacheStats as _, BlockstoreWithReadCache, DefaultBlockstoreReadCacheStats, - EthMappingsStore, LruBlockstoreReadCache, + LruBlockstoreReadCache, }, libp2p::{NetRPCMethods, NetworkMessage}, lotus_json::{HasLotusJson as _, LotusJson}, + prelude::*, rpc::{ApiPaths, Ctx, Permission, RpcMethod, ServerError, types::ApiTipsetKey}, shim::{ actors::{miner, power}, @@ -32,13 +33,11 @@ use crate::{ clock::ChainEpoch, crypto::Signature, }, - utils::{ShallowClone, misc::env::is_env_set_and_truthy}, + utils::misc::env::is_env_set_and_truthy, }; use ahash::{HashMap, HashSet}; use anyhow::Context as _; -use cid::Cid; use enumflags2::BitFlags; -use fvm_ipld_blockstore::Blockstore; use jsonrpsee::core::{client::ClientT as _, params::ArrayParams}; use libp2p::PeerId; use nonzero_ext::nonzero; @@ -49,7 +48,7 @@ use std::{ borrow::Cow, fmt::Display, str::FromStr as _, - sync::{Arc, LazyLock, OnceLock}, + sync::{LazyLock, OnceLock}, }; pub static F3_LEASE_MANAGER: OnceLock = OnceLock::new(); @@ -66,7 +65,7 @@ impl RpcMethod<0> for GetRawNetworkName { type Ok = Arc; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -91,7 +90,7 @@ impl RpcMethod<1> for GetTipsetByEpoch { type Ok = F3TipSet; async fn handle( - ctx: Ctx, + ctx: Ctx, (epoch,): Self::Params, _: &http::Extensions, ) -> Result { @@ -115,7 +114,7 @@ impl RpcMethod<1> for GetTipset { type Ok = F3TipSet; async fn handle( - ctx: Ctx, + ctx: Ctx, (f3_tsk,): Self::Params, _: &http::Extensions, ) -> Result { @@ -136,7 +135,7 @@ impl RpcMethod<0> for GetHead { type Ok = F3TipSet; async fn handle( - ctx: Ctx, + ctx: Ctx, _: Self::Params, _: &http::Extensions, ) -> Result { @@ -155,7 +154,7 @@ impl RpcMethod<1> for GetParent { type Ok = F3TipSet; async fn handle( - ctx: Ctx, + ctx: Ctx, (f3_tsk,): Self::Params, _: &http::Extensions, ) -> Result { @@ -169,17 +168,14 @@ impl RpcMethod<1> for GetParent { pub enum GetPowerTable {} impl GetPowerTable { - async fn compute( - ctx: &Ctx, - ts: &Tipset, - ) -> anyhow::Result> { + async fn compute(ctx: &Ctx, ts: &Tipset) -> anyhow::Result> { // The RAM overhead on mainnet is ~14MiB const BLOCKSTORE_CACHE_CAP: NonZeroUsize = nonzero!(65536_usize); static BLOCKSTORE_CACHE: LazyLock = LazyLock::new(|| { LruBlockstoreReadCache::new_with_metrics("get_powertable".into(), BLOCKSTORE_CACHE_CAP) }); let db = BlockstoreWithReadCache::new( - ctx.store_owned(), + ctx.db_owned(), BLOCKSTORE_CACHE.shallow_clone(), Some(DefaultBlockstoreReadCacheStats::default()), ); @@ -447,7 +443,7 @@ impl RpcMethod<1> for GetPowerTable { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (f3_tsk,): Self::Params, _: &http::Extensions, ) -> Result { @@ -471,7 +467,7 @@ impl RpcMethod<1> for ProtectPeer { type Ok = bool; async fn handle( - ctx: Ctx, + ctx: Ctx, (peer_id,): Self::Params, _: &http::Extensions, ) -> Result { @@ -499,7 +495,7 @@ impl RpcMethod<0> for GetParticipatingMinerIDs { type Ok = Vec; async fn handle( - _: Ctx, + _: Ctx, _: Self::Params, _: &http::Extensions, ) -> Result { @@ -523,7 +519,7 @@ impl RpcMethod<1> for Finalize { type Ok = (); async fn handle( - ctx: Ctx, + ctx: Ctx, (f3_tsk,): Self::Params, _: &http::Extensions, ) -> Result { @@ -560,7 +556,7 @@ impl RpcMethod<1> for Finalize { finalized_ts.epoch() ); if !head - .chain(ctx.store()) + .chain(ctx.db()) .take_while(|ts| ts.epoch() >= finalized_ts.epoch()) .any(|ts| ts == finalized_ts) { @@ -573,7 +569,7 @@ impl RpcMethod<1> for Finalize { .sync_network_context .chain_exchange_full_tipset(None, &tsk) .await?; - fts.persist(ctx.store())?; + fts.persist(ctx.db())?; let validator = TipsetValidator(&fts); validator.validate( ctx.chain_store(), @@ -603,7 +599,7 @@ impl RpcMethod<2> for SignMessage { type Ok = Signature; async fn handle( - ctx: Ctx, + ctx: Ctx, (pubkey, message): Self::Params, ext: &http::Extensions, ) -> Result { @@ -639,7 +635,7 @@ impl RpcMethod<1> for F3ExportLatestSnapshot { type Ok = Cid; async fn handle( - _ctx: Ctx, + _ctx: Ctx, (path,): Self::Params, _: &http::Extensions, ) -> Result { @@ -659,7 +655,7 @@ impl RpcMethod<1> for F3GetCertificate { type Ok = FinalityCertificate; async fn handle( - _: Ctx, + _: Ctx, (instance,): Self::Params, _: &http::Extensions, ) -> Result { @@ -695,7 +691,7 @@ impl RpcMethod<0> for F3GetLatestCertificate { type Ok = FinalityCertificate; async fn handle( - _: Ctx, + _: Ctx, _: Self::Params, _: &http::Extensions, ) -> Result { @@ -714,7 +710,7 @@ impl RpcMethod<1> for F3GetECPowerTable { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (ApiTipsetKey(tsk_opt),): Self::Params, ext: &http::Extensions, ) -> Result { @@ -734,7 +730,7 @@ impl RpcMethod<1> for F3GetF3PowerTable { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (ApiTipsetKey(tsk_opt),): Self::Params, _: &http::Extensions, ) -> Result { @@ -762,7 +758,7 @@ impl RpcMethod<1> for F3GetF3PowerTableByInstance { type Ok = Vec; async fn handle( - _ctx: Ctx, + _ctx: Ctx, (instance,): Self::Params, _: &http::Extensions, ) -> Result { @@ -794,7 +790,7 @@ impl RpcMethod<0> for F3IsRunning { type Ok = bool; async fn handle( - _: Ctx, + _: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -824,7 +820,7 @@ impl RpcMethod<0> for F3GetProgress { type Ok = F3InstanceProgress; async fn handle( - _: Ctx, + _: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -854,7 +850,7 @@ impl RpcMethod<0> for F3GetManifest { type Ok = F3Manifest; async fn handle( - _: Ctx, + _: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -874,7 +870,7 @@ impl RpcMethod<0> for F3ListParticipants { type Ok = Vec; async fn handle( - _: Ctx, + _: Ctx, _: Self::Params, _: &http::Extensions, ) -> Result { @@ -908,7 +904,7 @@ impl RpcMethod<3> for F3GetOrRenewParticipationTicket { type Ok = Vec; async fn handle( - _: Ctx, + _: Ctx, (miner, previous_lease_ticket, instances): Self::Params, _: &http::Extensions, ) -> Result { @@ -944,7 +940,7 @@ impl RpcMethod<1> for F3Participate { type Ok = F3ParticipationLease; async fn handle( - _: Ctx, + _: Ctx, (lease_ticket,): Self::Params, _: &http::Extensions, ) -> Result { diff --git a/src/rpc/methods/gas.rs b/src/rpc/methods/gas.rs index d7c04340ebb2..a42b85dbe7c0 100644 --- a/src/rpc/methods/gas.rs +++ b/src/rpc/methods/gas.rs @@ -4,8 +4,8 @@ use super::state::InvocResult; use crate::blocks::Tipset; use crate::chain::{BASE_FEE_MAX_CHANGE_DENOM, BLOCK_GAS_TARGET}; -use crate::db::EthMappingsStore; use crate::message::{ChainMessage, MessageRead as _, MessageReadWrite as _, SignedMessage}; +use crate::prelude::*; use crate::rpc::{ApiPaths, Ctx, Permission, RpcMethod, error::ServerError, types::*}; use crate::shim::executor::ApplyRet; use crate::shim::{ @@ -15,11 +15,8 @@ use crate::shim::{ message::Message, }; use crate::state_manager::VMFlush; -use crate::utils::ShallowClone as _; -use anyhow::{Context, Result}; +use anyhow::Result; use enumflags2::BitFlags; -use fvm_ipld_blockstore::Blockstore; -use itertools::Itertools as _; use num::BigInt; use num_traits::{FromPrimitive, Zero}; use rand_distr::{Distribution, Normal}; @@ -43,7 +40,7 @@ impl RpcMethod<3> for GasEstimateFeeCap { type Ok = String; async fn handle( - ctx: Ctx, + ctx: Ctx, (msg, max_queue_blks, tsk): Self::Params, _: &http::Extensions, ) -> Result { @@ -51,8 +48,8 @@ impl RpcMethod<3> for GasEstimateFeeCap { } } -fn estimate_fee_cap( - data: &Ctx, +fn estimate_fee_cap( + data: &Ctx, msg: &Message, max_queue_blks: i64, ApiTipsetKey(ts_key): &ApiTipsetKey, @@ -91,7 +88,7 @@ impl RpcMethod<4> for GasEstimateGasPremium { type Ok = String; async fn handle( - ctx: Ctx, + ctx: Ctx, (nblocksincl, _sender, _gas_limit, tsk): Self::Params, _: &http::Extensions, ) -> Result { @@ -107,8 +104,8 @@ struct GasMeta { pub limit: u64, } -pub async fn estimate_gas_premium( - ctx: &Ctx, +pub async fn estimate_gas_premium( + ctx: &Ctx, nblocksincl: u64, ApiTipsetKey(ts_key): &ApiTipsetKey, ) -> Result { @@ -205,7 +202,7 @@ impl RpcMethod<2> for GasEstimateGasLimit { type Ok = i64; async fn handle( - ctx: Ctx, + ctx: Ctx, (msg, tsk): Self::Params, _: &http::Extensions, ) -> Result { @@ -214,14 +211,11 @@ impl RpcMethod<2> for GasEstimateGasLimit { } impl GasEstimateGasLimit { - pub async fn estimate_call_with_gas( - data: &Ctx, + pub async fn estimate_call_with_gas( + data: &Ctx, mut msg: Message, ApiTipsetKey(tsk): &ApiTipsetKey, - ) -> anyhow::Result<(InvocResult, ApplyRet, Vec, Tipset)> - where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, - { + ) -> anyhow::Result<(InvocResult, ApplyRet, Vec, Tipset)> { msg.set_gas_limit(BLOCK_GAS_LIMIT); msg.set_gas_fee_cap(TokenAmount::from_atto(0)); msg.set_gas_premium(TokenAmount::from_atto(0)); @@ -268,14 +262,7 @@ impl GasEstimateGasLimit { Ok((invoc_res, apply_ret, prior_messages, ts)) } - pub async fn estimate_gas_limit( - data: &Ctx, - msg: Message, - tsk: &ApiTipsetKey, - ) -> Result - where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, - { + pub async fn estimate_gas_limit(data: &Ctx, msg: Message, tsk: &ApiTipsetKey) -> Result { let (res, ..) = Self::estimate_call_with_gas(data, msg, tsk) .await .context("gas estimation failed")?; @@ -308,7 +295,7 @@ impl RpcMethod<3> for GasEstimateMessageGas { type Ok = Message; async fn handle( - ctx: Ctx, + ctx: Ctx, (msg, spec, tsk): Self::Params, _: &http::Extensions, ) -> Result { @@ -317,15 +304,12 @@ impl RpcMethod<3> for GasEstimateMessageGas { } } -pub async fn estimate_message_gas( - data: &Ctx, +pub async fn estimate_message_gas( + data: &Ctx, mut msg: Message, msg_spec: Option, tsk: ApiTipsetKey, -) -> Result -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +) -> Result { if msg.gas_limit == 0 { let gl = GasEstimateGasLimit::estimate_gas_limit(data, msg.clone(), &tsk).await?; let gl = gl as f64 * data.mpool.config.gas_limit_overestimation; diff --git a/src/rpc/methods/market.rs b/src/rpc/methods/market.rs index ff362dd79c4c..4bb936d4cf22 100644 --- a/src/rpc/methods/market.rs +++ b/src/rpc/methods/market.rs @@ -1,14 +1,12 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use crate::db::EthMappingsStore; use crate::rpc::error::ServerError; use crate::rpc::mpool::MpoolPushMessage; use crate::rpc::{ApiPaths, Ctx, Permission, RpcMethod}; use crate::shim::{address::Address, message::Message, message::MethodNum}; use cid::Cid; use enumflags2::BitFlags; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::RawBytes; use num_bigint::BigInt; @@ -25,7 +23,7 @@ impl RpcMethod<3> for MarketAddBalance { type Ok = Cid; async fn handle( - ctx: Ctx, + ctx: Ctx, (wallet, address, amount): Self::Params, ext: &http::Extensions, ) -> Result { diff --git a/src/rpc/methods/miner.rs b/src/rpc/methods/miner.rs index 2c6c7897cd4b..3b41408eb84f 100644 --- a/src/rpc/methods/miner.rs +++ b/src/rpc/methods/miner.rs @@ -2,46 +2,35 @@ // SPDX-License-Identifier: Apache-2.0, MIT use crate::beacon::BeaconEntry; -use crate::blocks::{CachingBlockHeader, Ticket, TipsetKey}; -use crate::blocks::{ElectionProof, RawBlockHeader}; - +use crate::blocks::{CachingBlockHeader, ElectionProof, RawBlockHeader, Ticket, TipsetKey}; use crate::chain::{ChainStore, compute_base_fee}; - -use crate::db::EthMappingsStore; use crate::fil_cns::weight; use crate::interpreter::VMTrace; use crate::key_management::{Key, KeyStore}; -use crate::lotus_json::lotus_json_with_self; - use crate::lotus_json::LotusJson; +use crate::lotus_json::lotus_json_with_self; use crate::message::SignedMessage; use crate::networks::Height; - +use crate::prelude::*; use crate::rpc::reflect::Permission; use crate::rpc::types::{ApiTipsetKey, MiningBaseInfo}; use crate::rpc::{ApiPaths, Ctx, RpcMethod, ServerError}; use crate::shim::address::Address; use crate::shim::clock::ChainEpoch; +use crate::shim::crypto::BLS_SIG_LEN; use crate::shim::crypto::{Signature, SignatureType}; -use crate::state_manager::ExecutedTipset; -use enumflags2::BitFlags; - use crate::shim::sector::PoStProof; +use crate::state_manager::ExecutedTipset; use crate::utils::db::CborStoreExt; - -use crate::shim::crypto::BLS_SIG_LEN; -use anyhow::{Context as _, Result}; +use anyhow::Result; use bls_signatures::Serialize as _; -use cid::Cid; +use enumflags2::BitFlags; use fil_actors_shared::fvm_ipld_amt::Amtv0 as Amt; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::tuple::*; use group::prime::PrimeCurveAffine as _; -use itertools::Itertools; use parking_lot::RwLock; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; - use std::sync::Arc; #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, JsonSchema)] @@ -112,11 +101,11 @@ impl RpcMethod<1> for MinerCreateBlock { type Ok = BlockMessage; async fn handle( - ctx: Ctx, + ctx: Ctx, (block_template,): Self::Params, _: &http::Extensions, ) -> Result { - let store = ctx.store(); + let store = ctx.db(); let parent_tipset = ctx .chain_index() .load_required_tipset(&block_template.parents)?; @@ -171,14 +160,14 @@ impl RpcMethod<1> for MinerCreateBlock { for msg in block_template.messages { match msg.signature().signature_type() { SignatureType::Bls => { - let cid = ctx.store().put_cbor_default(&msg.message)?; + let cid = ctx.db().put_cbor_default(&msg.message)?; bls_msg_cids.push(cid); bls_sigs.push(msg.signature); bls_messages.push(msg.message); } SignatureType::Secp256k1 | SignatureType::Delegated => { if msg.signature.is_valid_secpk_sig_type(network_version) { - let cid = ctx.store().put_cbor_default(&msg)?; + let cid = ctx.db().put_cbor_default(&msg)?; secpk_msg_cids.push(cid); secpk_messages.push(msg); } else { @@ -191,7 +180,7 @@ impl RpcMethod<1> for MinerCreateBlock { } } - let store = ctx.store(); + let store = ctx.db(); let mut message_array = Amt::::new(store); for (i, cid) in bls_msg_cids.iter().enumerate() { message_array.set(i as u64, *cid)?; @@ -295,7 +284,7 @@ impl RpcMethod<3> for MinerGetBaseInfo { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (miner_address, epoch, ApiTipsetKey(tipset_key)): Self::Params, _: &http::Extensions, ) -> Result { diff --git a/src/rpc/methods/misc.rs b/src/rpc/methods/misc.rs index 3f2d3f4ee63a..e456009c5204 100644 --- a/src/rpc/methods/misc.rs +++ b/src/rpc/methods/misc.rs @@ -5,11 +5,9 @@ use std::collections::BTreeMap; use cid::Cid; use enumflags2::BitFlags; -use fvm_ipld_blockstore::Blockstore; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::db::EthMappingsStore; use crate::rpc::eth::CollectedEvent; use crate::rpc::eth::filter::{ParsedFilter, SkipEvent}; use crate::{ @@ -32,7 +30,7 @@ impl RpcMethod<1> for GetActorEventsRaw { type Params = (Option,); type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (filter,): Self::Params, _: &http::Extensions, ) -> Result { diff --git a/src/rpc/methods/mpool.rs b/src/rpc/methods/mpool.rs index d6b53cb46ac4..db157acc8678 100644 --- a/src/rpc/methods/mpool.rs +++ b/src/rpc/methods/mpool.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0, MIT use super::gas::estimate_message_gas; -use crate::db::EthMappingsStore; use crate::lotus_json::NotNullVec; use crate::message::SignedMessage; use crate::rpc::error::ServerError; @@ -15,7 +14,6 @@ use crate::shim::{ use ahash::{HashSet, HashSetExt as _}; use cid::Cid; use enumflags2::BitFlags; -use fvm_ipld_blockstore::Blockstore; /// Gets next nonce for the specified sender. pub enum MpoolGetNonce {} @@ -31,7 +29,7 @@ impl RpcMethod<1> for MpoolGetNonce { type Ok = u64; async fn handle( - ctx: Ctx, + ctx: Ctx, (address,): Self::Params, _: &http::Extensions, ) -> Result { @@ -53,7 +51,7 @@ impl RpcMethod<1> for MpoolPending { type Ok = NotNullVec; async fn handle( - ctx: Ctx, + ctx: Ctx, (ApiTipsetKey(tipset_key),): Self::Params, _: &http::Extensions, ) -> Result { @@ -79,20 +77,14 @@ impl RpcMethod<1> for MpoolPending { } // mpts has different blocks than ts - let have = ctx - .mpool - .as_ref() - .messages_for_blocks(ts.block_headers().iter())?; + let have = ctx.mpool.messages_for_blocks(ts.block_headers().iter())?; for sm in have { have_cids.insert(sm.cid()); } } - let msgs = ctx - .mpool - .as_ref() - .messages_for_blocks(ts.block_headers().iter())?; + let msgs = ctx.mpool.messages_for_blocks(ts.block_headers().iter())?; for m in msgs { if have_cids.contains(&m.cid()) { @@ -127,7 +119,7 @@ impl RpcMethod<2> for MpoolSelect { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (ApiTipsetKey(tipset_key), ticket_quality): Self::Params, _: &http::Extensions, ) -> Result { @@ -151,11 +143,11 @@ impl RpcMethod<1> for MpoolPush { type Ok = Cid; async fn handle( - ctx: Ctx, + ctx: Ctx, (message,): Self::Params, _: &http::Extensions, ) -> Result { - let cid = ctx.mpool.as_ref().push(message).await?; + let cid = ctx.mpool.push(message).await?; Ok(cid) } } @@ -174,13 +166,13 @@ impl RpcMethod<1> for MpoolBatchPush { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (messages,): Self::Params, _: &http::Extensions, ) -> Result { let mut cids = vec![]; for msg in messages { - cids.push(ctx.mpool.as_ref().push(msg).await?); + cids.push(ctx.mpool.push(msg).await?); } Ok(cids) } @@ -200,14 +192,14 @@ impl RpcMethod<1> for MpoolPushUntrusted { type Ok = Cid; async fn handle( - ctx: Ctx, + ctx: Ctx, (message,): Self::Params, _: &http::Extensions, ) -> Result { // Lotus implements a few extra sanity checks that we skip. We skip them // because those checks aren't used for messages received from peers and // therefore aren't safety critical. - let cid = ctx.mpool.as_ref().push_untrusted(message).await?; + let cid = ctx.mpool.push_untrusted(message).await?; Ok(cid) } } @@ -226,7 +218,7 @@ impl RpcMethod<1> for MpoolBatchPushUntrusted { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (messages,): Self::Params, ext: &http::Extensions, ) -> Result { @@ -249,7 +241,7 @@ impl RpcMethod<2> for MpoolPushMessage { type Ok = SignedMessage; async fn handle( - ctx: Ctx, + ctx: Ctx, (message, send_spec): Self::Params, extensions: &http::Extensions, ) -> Result { @@ -301,7 +293,7 @@ impl RpcMethod<2> for MpoolPushMessage { let smsg = ctx .nonce_tracker - .sign_and_push(ctx.mpool.as_ref(), message, &key, eth_chain_id) + .sign_and_push(&ctx.mpool, message, &key, eth_chain_id) .await?; Ok(smsg) diff --git a/src/rpc/methods/msig.rs b/src/rpc/methods/msig.rs index c6d5b51be4eb..ff1719cff82e 100644 --- a/src/rpc/methods/msig.rs +++ b/src/rpc/methods/msig.rs @@ -9,7 +9,6 @@ use crate::shim::actors::MultisigActorStateLoad as _; use crate::shim::actors::multisig; use crate::shim::{address::Address, econ::TokenAmount}; use enumflags2::BitFlags; -use fvm_ipld_blockstore::Blockstore; use num_bigint::BigInt; pub enum MsigGetAvailableBalance {} @@ -24,7 +23,7 @@ impl RpcMethod<2> for MsigGetAvailableBalance { type Ok = TokenAmount; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -34,7 +33,7 @@ impl RpcMethod<2> for MsigGetAvailableBalance { .state_manager .get_required_actor(&address, *ts.parent_state())?; let actor_balance = TokenAmount::from(&actor.balance); - let ms = multisig::State::load(ctx.store(), actor.code, actor.state)?; + let ms = multisig::State::load(ctx.db(), actor.code, actor.state)?; let locked_balance = ms.locked_balance(height)?; let avail_balance = &actor_balance - locked_balance; Ok(avail_balance) @@ -53,7 +52,7 @@ impl RpcMethod<2> for MsigGetPending { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -62,7 +61,7 @@ impl RpcMethod<2> for MsigGetPending { .state_manager .get_actor_state_from_address(&ts, &address)?; let txns = ms - .get_pending_txn(ctx.store())? + .get_pending_txn(ctx.db())? .into_iter() .map(|txn| Transaction { id: txn.id, @@ -88,7 +87,7 @@ impl RpcMethod<3> for MsigGetVested { type Ok = BigInt; async fn handle( - ctx: Ctx, + ctx: Ctx, (addr, ApiTipsetKey(start_tsk), ApiTipsetKey(end_tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -128,7 +127,7 @@ impl RpcMethod<2> for MsigGetVestingSchedule { type Ok = MsigVesting; async fn handle( - ctx: Ctx, + ctx: Ctx, (addr, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { diff --git a/src/rpc/methods/net.rs b/src/rpc/methods/net.rs index dc045bc531c7..8dc798f46dfa 100644 --- a/src/rpc/methods/net.rs +++ b/src/rpc/methods/net.rs @@ -4,21 +4,19 @@ mod types; pub use types::*; -use std::any::Any; use std::num::NonZeroU64; use std::str::FromStr; -use std::sync::{Arc, OnceLock}; +use std::sync::OnceLock; use std::time::Instant; use crate::libp2p::chain_exchange::TipsetBundle; use crate::libp2p::{NetRPCMethods, NetworkMessage, PeerId}; +use crate::prelude::*; use crate::rpc::types::ApiTipsetKey; use crate::rpc::{ApiPaths, Ctx, Permission, RpcMethod, ServerError}; -use anyhow::{Context as _, Result}; +use anyhow::Result; use cid::multibase; use enumflags2::BitFlags; -use fvm_ipld_blockstore::Blockstore; -use itertools::Itertools as _; pub enum NetAddrsListen {} impl RpcMethod<0> for NetAddrsListen { @@ -33,7 +31,7 @@ impl RpcMethod<0> for NetAddrsListen { type Ok = AddrInfo; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -61,7 +59,7 @@ impl RpcMethod<0> for NetPeers { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -93,7 +91,7 @@ impl RpcMethod<1> for NetFindPeer { type Ok = AddrInfo; async fn handle( - ctx: Ctx, + ctx: Ctx, (peer_id,): Self::Params, _: &http::Extensions, ) -> Result { @@ -124,7 +122,7 @@ impl RpcMethod<0> for NetListening { type Ok = bool; async fn handle( - _: Ctx, + _: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -143,7 +141,7 @@ impl RpcMethod<0> for NetInfo { type Ok = NetInfoResult; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -169,7 +167,7 @@ impl RpcMethod<1> for NetConnect { type Ok = (); async fn handle( - ctx: Ctx, + ctx: Ctx, (AddrInfo { id, addrs },): Self::Params, _: &http::Extensions, ) -> Result { @@ -204,7 +202,7 @@ impl RpcMethod<1> for NetDisconnect { type Ok = (); async fn handle( - ctx: Ctx, + ctx: Ctx, (peer_id,): Self::Params, _: &http::Extensions, ) -> Result { @@ -234,7 +232,7 @@ impl RpcMethod<1> for NetAgentVersion { type Ok = String; async fn handle( - ctx: Ctx, + ctx: Ctx, (peer_id,): Self::Params, _: &http::Extensions, ) -> Result { @@ -260,7 +258,7 @@ impl RpcMethod<0> for NetAutoNatStatus { type Ok = NatStatusResult; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -286,7 +284,7 @@ impl RpcMethod<0> for NetVersion { type Ok = Arc; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -316,7 +314,7 @@ impl RpcMethod<1> for NetProtectAdd { // in go. However it would be nice to investigate connection limiting options in Rust. // See: . async fn handle( - ctx: Ctx, + ctx: Ctx, (peer_ids,): Self::Params, _: &http::Extensions, ) -> Result { @@ -347,7 +345,7 @@ impl RpcMethod<0> for NetProtectList { type Params = (); type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -375,7 +373,7 @@ impl RpcMethod<1> for NetProtectRemove { // Similar to NetProtectAdd async fn handle( - ctx: Ctx, + ctx: Ctx, (peer_ids,): Self::Params, _: &http::Extensions, ) -> Result { @@ -407,7 +405,7 @@ impl RpcMethod<3> for NetChainExchange { type Ok = String; async fn handle( - ctx: Ctx, + ctx: Ctx, (tsk, request_len, options): Self::Params, _: &http::Extensions, ) -> Result { diff --git a/src/rpc/methods/node.rs b/src/rpc/methods/node.rs index ef9dd8de0bda..f406cf666ee5 100644 --- a/src/rpc/methods/node.rs +++ b/src/rpc/methods/node.rs @@ -8,7 +8,6 @@ use crate::{ rpc::{ApiPaths, Ctx, Permission, RpcMethod, ServerError}, }; use enumflags2::BitFlags; -use fvm_ipld_blockstore::Blockstore; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -23,7 +22,7 @@ impl RpcMethod<0> for NodeStatus { type Ok = NodeStatusResult; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { diff --git a/src/rpc/methods/state.rs b/src/rpc/methods/state.rs index a338cd37d3ca..e16367ba31f9 100644 --- a/src/rpc/methods/state.rs +++ b/src/rpc/methods/state.rs @@ -10,12 +10,12 @@ use crate::beacon::Beacon as _; use crate::blocks::{Tipset, TipsetKey}; use crate::chain::index::ResolveNullTipset; use crate::cid_collections::CidHashSet; -use crate::db::EthMappingsStore; use crate::eth::EthChainId; use crate::interpreter::{MessageCallbackCtx, VMTrace}; use crate::libp2p::NetworkMessage; use crate::lotus_json::{LotusJson, lotus_json_with_self}; use crate::networks::ChainConfig; +use crate::prelude::*; use crate::rpc::registry::actors_reg::load_and_serialize_actor_state; use crate::shim::actors::market::DealState; use crate::shim::actors::market::ext::MarketStateExt as _; @@ -46,23 +46,19 @@ use crate::state_manager::{ExecutedTipset, NO_CALLBACK}; use crate::state_manager::{ MarketBalance, StateManager, circulating_supply::GenesisInfo, utils::structured, }; -use crate::utils::ShallowClone as _; use crate::utils::db::car_stream::{CarBlock, CarWriter}; use crate::{ beacon::BeaconEntry, rpc::{ApiPaths, Ctx, Permission, RpcMethod, ServerError, types::*}, }; use ahash::{HashMap, HashMapExt, HashSet}; -use anyhow::Context; use anyhow::Result; -use cid::Cid; use enumflags2::{BitFlags, make_bitflags}; use fil_actor_miner_state::v10::{qa_power_for_weight, qa_power_max}; use fil_actor_verifreg_state::v13::ClaimID; use fil_actors_shared::fvm_ipld_amt::Amt; use fil_actors_shared::fvm_ipld_bitfield::BitField; use futures::{StreamExt as _, TryStreamExt as _}; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::{CborStore, DAG_CBOR}; pub use fvm_shared3::sector::StoragePower; use ipld_core::ipld::Ipld; @@ -76,7 +72,7 @@ use serde::{Deserialize, Serialize}; use std::num::NonZeroUsize; use std::ops::Mul; use std::path::PathBuf; -use std::{sync::Arc, time::Duration}; +use std::time::Duration; use tokio::task::JoinSet; const INITIAL_PLEDGE_NUM: u64 = 110; @@ -85,8 +81,8 @@ const INITIAL_PLEDGE_DEN: u64 = 100; pub enum StateCall {} impl StateCall { - pub fn run( - state_manager: &StateManager, + pub fn run( + state_manager: &StateManager, message: &Message, tsk: Option, ) -> anyhow::Result { @@ -110,7 +106,7 @@ impl RpcMethod<2> for StateCall { type Ok = ApiInvocResult; async fn handle( - ctx: Ctx, + ctx: Ctx, (message, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -134,7 +130,7 @@ impl RpcMethod<2> for StateReplay { /// returns the result of executing the indicated message, assuming it was /// executed in the indicated tipset. async fn handle( - ctx: Ctx, + ctx: Ctx, (ApiTipsetKey(tsk), message_cid): Self::Params, _: &http::Extensions, ) -> Result { @@ -154,7 +150,7 @@ impl RpcMethod<0> for StateNetworkName { type Ok = String; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -179,7 +175,7 @@ impl RpcMethod<1> for StateNetworkVersion { type Ok = NetworkVersion; async fn handle( - ctx: Ctx, + ctx: Ctx, (ApiTipsetKey(tsk),): Self::Params, _: &http::Extensions, ) -> Result { @@ -204,7 +200,7 @@ impl RpcMethod<2> for StateAccountKey { type Ok = Address; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -232,7 +228,7 @@ impl RpcMethod<2> for StateLookupID { type Ok = Address; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -256,7 +252,7 @@ impl RpcMethod<1> for StateVerifiedRegistryRootKey { type Ok = Address; async fn handle( - ctx: Ctx, + ctx: Ctx, (ApiTipsetKey(tsk),): Self::Params, _: &http::Extensions, ) -> Result { @@ -281,14 +277,14 @@ impl RpcMethod<2> for StateVerifierStatus { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { let ts = ctx.chain_store().load_required_tipset_or_heaviest(&tsk)?; let aid = ctx.state_manager.lookup_required_id(&address, &ts)?; let verifreg_state: verifreg::State = ctx.state_manager.get_actor_state(&ts)?; - Ok(verifreg_state.verifier_data_cap(ctx.store(), aid)?) + Ok(verifreg_state.verifier_data_cap(ctx.db(), aid)?) } } @@ -306,7 +302,7 @@ impl RpcMethod<2> for StateGetActor { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -330,7 +326,7 @@ impl RpcMethod<2> for StateGetActorV2 { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, selector): Self::Params, _: &http::Extensions, ) -> Result { @@ -353,7 +349,7 @@ impl RpcMethod<2> for StateGetID { type Ok = Address; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, selector): Self::Params, _: &http::Extensions, ) -> Result { @@ -390,13 +386,13 @@ impl RpcMethod<2> for StateLookupRobustAddress { type Ok = Address; async fn handle( - ctx: Ctx, + ctx: Ctx, (addr, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { let ts = ctx.chain_store().load_required_tipset_or_heaviest(&tsk)?; - let store = ctx.store(); - let state_tree = StateTree::new_from_root(ctx.store_owned(), ts.parent_state())?; + let store = ctx.db(); + let state_tree = StateTree::new_from_root(ctx.db(), ts.parent_state())?; if let &Payload::ID(id_addr_decoded) = addr.payload() { let init_state: init::State = state_tree.get_actor_state()?; let mut robust_addr = Address::default(); @@ -561,7 +557,7 @@ impl RpcMethod<2> for StateMarketBalance { type Ok = MarketBalance; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -586,15 +582,15 @@ impl RpcMethod<1> for StateMarketDeals { type Ok = HashMap; async fn handle( - ctx: Ctx, + ctx: Ctx, (ApiTipsetKey(tsk),): Self::Params, _: &http::Extensions, ) -> Result { let ts = ctx.chain_store().load_required_tipset_or_heaviest(&tsk)?; let market_state: market::State = ctx.state_manager.get_actor_state(&ts)?; - let da = market_state.proposals(ctx.store())?; - let sa = market_state.states(ctx.store())?; + let da = market_state.proposals(ctx.db())?; + let sa = market_state.states(ctx.db())?; let mut out = HashMap::new(); da.for_each(|deal_id, d| { @@ -634,7 +630,7 @@ impl RpcMethod<2> for StateMinerInfo { type Ok = MinerInfo; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -657,7 +653,7 @@ impl RpcMethod<2> for StateMinerActiveSectors { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -668,14 +664,14 @@ impl RpcMethod<2> for StateMinerActiveSectors { .get_actor_state_from_address(&ts, &address)?; // Collect active sectors from each partition in each deadline. let mut active_sectors = vec![]; - miner_state.for_each_deadline(policy, ctx.store(), |_dlidx, deadline| { - deadline.for_each(ctx.store(), |_partidx, partition| { + miner_state.for_each_deadline(policy, ctx.db(), |_dlidx, deadline| { + deadline.for_each(ctx.db(), |_partidx, partition| { active_sectors.push(partition.active_sectors()); Ok(()) }) })?; let sectors = - miner_state.load_sectors_ext(ctx.store(), Some(&BitField::union(&active_sectors)))?; + miner_state.load_sectors_ext(ctx.db(), Some(&BitField::union(&active_sectors)))?; Ok(sectors) } } @@ -696,7 +692,7 @@ impl RpcMethod<2> for StateMinerAllocated { type Ok = BitField; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -704,7 +700,7 @@ impl RpcMethod<2> for StateMinerAllocated { let miner_state: miner::State = ctx .state_manager .get_actor_state_from_address(&ts, &address)?; - Ok(miner_state.load_allocated_sector_numbers(ctx.store())?) + Ok(miner_state.load_allocated_sector_numbers(ctx.db())?) } } @@ -723,7 +719,7 @@ impl RpcMethod<3> for StateMinerPartitions { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, dl_idx, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -732,9 +728,9 @@ impl RpcMethod<3> for StateMinerPartitions { let miner_state: miner::State = ctx .state_manager .get_actor_state_from_address(&ts, &address)?; - let deadline = miner_state.load_deadline(policy, ctx.store(), dl_idx)?; + let deadline = miner_state.load_deadline(policy, ctx.db(), dl_idx)?; let mut all_partitions = Vec::new(); - deadline.for_each(ctx.store(), |_partidx, partition| { + deadline.for_each(ctx.db(), |_partidx, partition| { all_partitions.push(MinerPartitions::new( partition.all_sectors(), partition.faulty_sectors(), @@ -763,7 +759,7 @@ impl RpcMethod<3> for StateMinerSectors { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, sectors, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -771,7 +767,7 @@ impl RpcMethod<3> for StateMinerSectors { let miner_state: miner::State = ctx .state_manager .get_actor_state_from_address(&ts, &address)?; - Ok(miner_state.load_sectors_ext(ctx.store(), sectors.as_ref())?) + Ok(miner_state.load_sectors_ext(ctx.db(), sectors.as_ref())?) } } @@ -790,7 +786,7 @@ impl RpcMethod<2> for StateMinerSectorCount { type Ok = MinerSectors; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -803,8 +799,8 @@ impl RpcMethod<2> for StateMinerSectorCount { let mut live_count = 0; let mut active_count = 0; let mut faulty_count = 0; - miner_state.for_each_deadline(policy, ctx.store(), |_dlidx, deadline| { - deadline.for_each(ctx.store(), |_partidx, partition| { + miner_state.for_each_deadline(policy, ctx.db(), |_dlidx, deadline| { + deadline.for_each(ctx.db(), |_partidx, partition| { live_count += partition.live_sectors().len(); active_count += partition.active_sectors().len(); faulty_count += partition.faulty_sectors().len(); @@ -830,7 +826,7 @@ impl RpcMethod<3> for StateMinerSectorAllocated { type Ok = bool; async fn handle( - ctx: Ctx, + ctx: Ctx, (miner_address, sector_number, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -839,7 +835,7 @@ impl RpcMethod<3> for StateMinerSectorAllocated { .state_manager .get_actor_state_from_address(&ts, &miner_address)?; let allocated_sector_numbers: BitField = - miner_state.load_allocated_sector_numbers(ctx.store())?; + miner_state.load_allocated_sector_numbers(ctx.db())?; Ok(allocated_sector_numbers.get(sector_number)) } } @@ -858,7 +854,7 @@ impl RpcMethod<2> for StateMinerPower { type Ok = MinerPower; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -883,7 +879,7 @@ impl RpcMethod<2> for StateMinerDeadlines { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -893,10 +889,10 @@ impl RpcMethod<2> for StateMinerDeadlines { .state_manager .get_actor_state_from_address(&ts, &address)?; let mut res = Vec::new(); - state.for_each_deadline(policy, ctx.store(), |_idx, deadline| { + state.for_each_deadline(policy, ctx.db(), |_idx, deadline| { res.push(ApiDeadline { post_submissions: deadline.partitions_posted(), - disputable_proof_count: deadline.disputable_proof_count(ctx.store())?, + disputable_proof_count: deadline.disputable_proof_count(ctx.db())?, daily_fee: deadline.daily_fee(), }); Ok(()) @@ -920,7 +916,7 @@ impl RpcMethod<2> for StateMinerProvingDeadline { type Ok = ApiDeadlineInfo; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -952,7 +948,7 @@ impl RpcMethod<2> for StateMinerFaults { type Ok = BitField; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -977,7 +973,7 @@ impl RpcMethod<2> for StateMinerRecoveries { type Ok = BitField; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -1002,7 +998,7 @@ impl RpcMethod<2> for StateMinerAvailableBalance { type Ok = TokenAmount; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -1010,51 +1006,51 @@ impl RpcMethod<2> for StateMinerAvailableBalance { let actor = ctx .state_manager .get_required_actor(&address, *ts.parent_state())?; - let state = miner::State::load(ctx.store(), actor.code, actor.state)?; + let state = miner::State::load(ctx.db(), actor.code, actor.state)?; let actor_balance: TokenAmount = actor.balance.clone().into(); let (vested, available): (TokenAmount, TokenAmount) = match &state { miner::State::V18(s) => ( - s.check_vested_funds(ctx.store(), ts.epoch())?.into(), + s.check_vested_funds(ctx.db(), ts.epoch())?.into(), s.get_available_balance(&actor_balance.into())?.into(), ), miner::State::V17(s) => ( - s.check_vested_funds(ctx.store(), ts.epoch())?.into(), + s.check_vested_funds(ctx.db(), ts.epoch())?.into(), s.get_available_balance(&actor_balance.into())?.into(), ), miner::State::V16(s) => ( - s.check_vested_funds(ctx.store(), ts.epoch())?.into(), + s.check_vested_funds(ctx.db(), ts.epoch())?.into(), s.get_available_balance(&actor_balance.into())?.into(), ), miner::State::V15(s) => ( - s.check_vested_funds(ctx.store(), ts.epoch())?.into(), + s.check_vested_funds(ctx.db(), ts.epoch())?.into(), s.get_available_balance(&actor_balance.into())?.into(), ), miner::State::V14(s) => ( - s.check_vested_funds(ctx.store(), ts.epoch())?.into(), + s.check_vested_funds(ctx.db(), ts.epoch())?.into(), s.get_available_balance(&actor_balance.into())?.into(), ), miner::State::V13(s) => ( - s.check_vested_funds(ctx.store(), ts.epoch())?.into(), + s.check_vested_funds(ctx.db(), ts.epoch())?.into(), s.get_available_balance(&actor_balance.into())?.into(), ), miner::State::V12(s) => ( - s.check_vested_funds(ctx.store(), ts.epoch())?.into(), + s.check_vested_funds(ctx.db(), ts.epoch())?.into(), s.get_available_balance(&actor_balance.into())?.into(), ), miner::State::V11(s) => ( - s.check_vested_funds(ctx.store(), ts.epoch())?.into(), + s.check_vested_funds(ctx.db(), ts.epoch())?.into(), s.get_available_balance(&actor_balance.into())?.into(), ), miner::State::V10(s) => ( - s.check_vested_funds(ctx.store(), ts.epoch())?.into(), + s.check_vested_funds(ctx.db(), ts.epoch())?.into(), s.get_available_balance(&actor_balance.into())?.into(), ), miner::State::V9(s) => ( - s.check_vested_funds(ctx.store(), ts.epoch())?.into(), + s.check_vested_funds(ctx.db(), ts.epoch())?.into(), s.get_available_balance(&actor_balance.into())?.into(), ), miner::State::V8(s) => ( - s.check_vested_funds(ctx.store(), ts.epoch())?.into(), + s.check_vested_funds(ctx.db(), ts.epoch())?.into(), s.get_available_balance(&actor_balance.into())?.into(), ), }; @@ -1077,7 +1073,7 @@ impl RpcMethod<3> for StateMinerInitialPledgeCollateral { type Ok = TokenAmount; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, pci, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -1090,7 +1086,7 @@ impl RpcMethod<3> for StateMinerInitialPledgeCollateral { let market_state: market::State = ctx.state_manager.get_actor_state(&ts)?; let (w, vw) = market_state.verify_deals_for_activation( - ctx.store(), + ctx.db(), address, pci.deal_ids, ts.epoch(), @@ -1108,7 +1104,7 @@ impl RpcMethod<3> for StateMinerInitialPledgeCollateral { let genesis_info = GenesisInfo::from_chain_config(ctx.chain_config().clone()); let circ_supply = genesis_info.get_vm_circulating_supply_detailed( ts.epoch(), - &Arc::new(ctx.store()), + ctx.db(), ts.parent_state(), )?; let initial_pledge = reward_state.initial_pledge_for_power( @@ -1139,7 +1135,7 @@ impl RpcMethod<3> for StateMinerPreCommitDepositForPower { type Ok = TokenAmount; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, pci, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -1152,7 +1148,7 @@ impl RpcMethod<3> for StateMinerPreCommitDepositForPower { let market_state: market::State = ctx.state_manager.get_actor_state(&ts)?; let (w, vw) = market_state.verify_deals_for_activation( - ctx.store(), + ctx.db(), address, pci.deal_ids, ts.epoch(), @@ -1191,7 +1187,7 @@ impl RpcMethod<2> for StateGetReceipt { type Ok = Receipt; async fn handle( - ctx: Ctx, + ctx: Ctx, (cid, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -1216,7 +1212,7 @@ impl RpcMethod<2> for StateWaitMsgV0 { type Ok = MessageLookup; async fn handle( - ctx: Ctx, + ctx: Ctx, (message_cid, confidence): Self::Params, _: &http::Extensions, ) -> Result { @@ -1255,7 +1251,7 @@ impl RpcMethod<4> for StateWaitMsg { type Ok = MessageLookup; async fn handle( - ctx: Ctx, + ctx: Ctx, (message_cid, confidence, look_back_limit, allow_replaced): Self::Params, _: &http::Extensions, ) -> Result { @@ -1299,7 +1295,7 @@ impl RpcMethod<4> for StateSearchMsg { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (ApiTipsetKey(tsk), message_cid, look_back_limit, allow_replaced): Self::Params, _: &http::Extensions, ) -> Result { @@ -1344,7 +1340,7 @@ impl RpcMethod<2> for StateSearchMsgLimited { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (message_cid, look_back_limit): Self::Params, _: &http::Extensions, ) -> Result { @@ -1392,12 +1388,12 @@ impl RpcMethod<2> for StateFetchRoot { type Ok = String; async fn handle( - ctx: Ctx, + ctx: Ctx, (root_cid, save_to_file): Self::Params, _: &http::Extensions, ) -> Result { let network_send = ctx.network_send().clone(); - let db = ctx.store_owned(); + let db = ctx.db_owned(); let (car_tx, car_handle) = if let Some(save_to_file) = save_to_file { let (car_tx, car_rx) = flume::bounded(100); @@ -1495,7 +1491,7 @@ impl RpcMethod<2> for StateFetchRoot { } task_set.spawn_blocking({ let network_send = network_send.clone(); - let db = db.clone(); + let db = db.shallow_clone(); let dfs_vec = Arc::clone(&dfs); let car_tx = car_tx.clone(); move || { @@ -1567,7 +1563,7 @@ impl RpcMethod<3> for ForestStateCompute { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (from_epoch, n_epochs, force_recompute): Self::Params, _: &http::Extensions, ) -> Result { @@ -1593,10 +1589,10 @@ impl RpcMethod<3> for ForestStateCompute { let mut futures = FuturesOrdered::new(); for ts in to_ts - .chain(ctx.store()) + .chain(ctx.db()) .take_while(|ts| ts.epoch() >= from_ts.epoch()) { - let chain_store = ctx.chain_store().clone(); + let chain_store = ctx.chain_store().shallow_clone(); let network_context = ctx.sync_network_context.shallow_clone(); futures.push_front(async move { if crate::chain_sync::load_full_tipset(&chain_store, ts.key()).is_err() { @@ -1613,7 +1609,7 @@ impl RpcMethod<3> for ForestStateCompute { anyhow::bail!("unreachable chain exchange error in ForestStateCompute") } .with_context(|| format!("failed to download messages@{}", ts.epoch()))?; - fts.persist(chain_store.blockstore())?; + fts.persist(chain_store.db())?; } anyhow::Ok(ts) }); @@ -1627,7 +1623,7 @@ impl RpcMethod<3> for ForestStateCompute { let ExecutedTipset { state_root, .. } = ctx.state_manager.load_executed_tipset(&ts).await?; // Verify the state tree is loadable as the root CID could present due to some bad or wrong diff snapshot import - if StateTree::new_from_root(ctx.store_owned(), &state_root).is_ok() { + if StateTree::new_from_root(ctx.db(), &state_root).is_ok() { results.push(ForestComputeStateOutput { state_root, epoch, @@ -1642,7 +1638,7 @@ impl RpcMethod<3> for ForestStateCompute { .compute_tipset_state(ts, NO_CALLBACK, VMTrace::NotTraced) .await?; // Verify the result state tree - StateTree::new_from_root(ctx.store_owned(), &state_root).with_context(|| format!("failed to load the result state tree, root: {state_root}, epoch: {epoch}, tipset key: {tipset_key}"))?; + StateTree::new_from_root(ctx.db(), &state_root).with_context(|| format!("failed to load the result state tree, root: {state_root}, epoch: {epoch}, tipset key: {tipset_key}"))?; results.push(ForestComputeStateOutput { state_root, epoch, @@ -1667,7 +1663,7 @@ impl RpcMethod<3> for StateCompute { type Ok = ComputeStateOutput; async fn handle( - ctx: Ctx, + ctx: Ctx, (height, messages, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -1721,7 +1717,7 @@ impl RpcMethod<4> for StateGetRandomnessFromTickets { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (personalization, rand_epoch, entropy, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -1751,7 +1747,7 @@ impl RpcMethod<2> for StateGetRandomnessDigestFromTickets { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (rand_epoch, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -1778,7 +1774,7 @@ impl RpcMethod<4> for StateGetRandomnessFromBeacon { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (personalization, rand_epoch, entropy, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -1808,7 +1804,7 @@ impl RpcMethod<2> for StateGetRandomnessDigestFromBeacon { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (rand_epoch, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -1833,7 +1829,7 @@ impl RpcMethod<2> for StateReadState { type Ok = ApiActorState; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -1841,7 +1837,7 @@ impl RpcMethod<2> for StateReadState { let actor = ctx .state_manager .get_required_actor(&address, *ts.parent_state())?; - let state_json = load_and_serialize_actor_state(ctx.store(), &actor.code, &actor.state) + let state_json = load_and_serialize_actor_state(ctx.db(), &actor.code, &actor.state) .map_err(|e| anyhow::anyhow!("Failed to load actor state: {}", e))?; Ok(ApiActorState { balance: actor.balance.clone().into(), @@ -1863,7 +1859,7 @@ impl RpcMethod<4> for StateDecodeParams { type Ok = serde_json::Value; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, method, params, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -1895,7 +1891,7 @@ impl RpcMethod<1> for StateCirculatingSupply { type Ok = TokenAmount; async fn handle( - ctx: Ctx, + ctx: Ctx, (ApiTipsetKey(tsk),): Self::Params, _: &http::Extensions, ) -> Result { @@ -1903,8 +1899,7 @@ impl RpcMethod<1> for StateCirculatingSupply { let height = ts.epoch(); let root = ts.parent_state(); let genesis_info = GenesisInfo::from_chain_config(ctx.chain_config().clone()); - let supply = - genesis_info.get_state_circulating_supply(height - 1, &ctx.store_owned(), root)?; + let supply = genesis_info.get_state_circulating_supply(height - 1, ctx.db(), root)?; Ok(supply) } } @@ -1924,7 +1919,7 @@ impl RpcMethod<2> for StateVerifiedClientStatus { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -1948,7 +1943,7 @@ impl RpcMethod<1> for StateVMCirculatingSupplyInternal { type Ok = CirculatingSupply; async fn handle( - ctx: Ctx, + ctx: Ctx, (ApiTipsetKey(tsk),): Self::Params, _: &http::Extensions, ) -> Result { @@ -1956,7 +1951,7 @@ impl RpcMethod<1> for StateVMCirculatingSupplyInternal { let genesis_info = GenesisInfo::from_chain_config(ctx.chain_config().clone()); Ok(genesis_info.get_vm_circulating_supply_detailed( ts.epoch(), - &ctx.store_owned(), + ctx.db(), ts.parent_state(), )?) } @@ -1976,13 +1971,13 @@ impl RpcMethod<1> for StateListMiners { type Ok = Vec
; async fn handle( - ctx: Ctx, + ctx: Ctx, (ApiTipsetKey(tsk),): Self::Params, _: &http::Extensions, ) -> Result { let ts = ctx.chain_store().load_required_tipset_or_heaviest(&tsk)?; let state: power::State = ctx.state_manager.get_actor_state(&ts)?; - let miners = state.list_all_miners(ctx.store())?; + let miners = state.list_all_miners(ctx.db())?; Ok(miners) } } @@ -2001,7 +1996,7 @@ impl RpcMethod<1> for StateListActors { type Ok = Vec
; async fn handle( - ctx: Ctx, + ctx: Ctx, (ApiTipsetKey(tsk),): Self::Params, _: &http::Extensions, ) -> Result { @@ -2029,11 +2024,11 @@ impl RpcMethod<2> for StateMarketStorageDeal { type Ok = ApiMarketDeal; async fn handle( - ctx: Ctx, + ctx: Ctx, (deal_id, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { - let store = ctx.store(); + let store = ctx.db(); let ts = ctx.chain_store().load_required_tipset_or_heaviest(&tsk)?; let market_state: market::State = ctx.state_manager.get_actor_state(&ts)?; let proposals = market_state.proposals(store)?; @@ -2060,14 +2055,14 @@ impl RpcMethod<1> for StateMarketParticipants { type Ok = HashMap; async fn handle( - ctx: Ctx, + ctx: Ctx, (ApiTipsetKey(tsk),): Self::Params, _: &http::Extensions, ) -> Result { let ts = ctx.chain_store().load_required_tipset_or_heaviest(&tsk)?; let market_state = ctx.state_manager.market_state(&ts)?; - let escrow_table = market_state.escrow_table(ctx.store())?; - let locked_table = market_state.locked_table(ctx.store())?; + let escrow_table = market_state.escrow_table(ctx.db())?; + let locked_table = market_state.locked_table(ctx.db())?; let mut result = HashMap::new(); escrow_table.for_each(|address, escrow| { let locked = locked_table.get(address)?; @@ -2099,7 +2094,7 @@ impl RpcMethod<3> for StateDealProviderCollateralBounds { type Ok = DealCollateralBounds; async fn handle( - ctx: Ctx, + ctx: Ctx, (size, verified, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -2116,11 +2111,8 @@ impl RpcMethod<3> for StateDealProviderCollateralBounds { let genesis_info = GenesisInfo::from_chain_config(ctx.chain_config().clone()); - let supply = genesis_info.get_vm_circulating_supply( - ts.epoch(), - &ctx.store_owned(), - ts.parent_state(), - )?; + let supply = + genesis_info.get_vm_circulating_supply(ts.epoch(), ctx.db(), ts.parent_state())?; let power_claim = power_state.total_power(); @@ -2162,7 +2154,7 @@ impl RpcMethod<1> for StateGetBeaconEntry { type Ok = BeaconEntry; async fn handle( - ctx: Ctx, + ctx: Ctx, (epoch,): Self::Params, _: &http::Extensions, ) -> Result { @@ -2200,7 +2192,7 @@ impl RpcMethod<3> for StateSectorPreCommitInfoV0 { type Ok = SectorPreCommitOnChainInfo; async fn handle( - ctx: Ctx, + ctx: Ctx, (miner_address, sector_number, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -2209,7 +2201,7 @@ impl RpcMethod<3> for StateSectorPreCommitInfoV0 { .state_manager .get_actor_state_from_address(&ts, &miner_address)?; Ok(state - .load_precommit_on_chain_info(ctx.store(), sector_number)? + .load_precommit_on_chain_info(ctx.db(), sector_number)? .context("precommit info does not exist")?) } } @@ -2229,7 +2221,7 @@ impl RpcMethod<3> for StateSectorPreCommitInfo { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (miner_address, sector_number, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -2237,18 +2229,18 @@ impl RpcMethod<3> for StateSectorPreCommitInfo { let state: miner::State = ctx .state_manager .get_actor_state_from_address(&ts, &miner_address)?; - Ok(state.load_precommit_on_chain_info(ctx.store(), sector_number)?) + Ok(state.load_precommit_on_chain_info(ctx.db(), sector_number)?) } } impl StateSectorPreCommitInfo { pub fn get_sectors( - store: &Arc, + store: &(impl Blockstore + ShallowClone), miner_address: &Address, tipset: &Tipset, ) -> anyhow::Result> { let mut sectors = vec![]; - let state_tree = StateTree::new_from_root(store.clone(), tipset.parent_state())?; + let state_tree = StateTree::new_from_root(store, tipset.parent_state())?; let state: miner::State = state_tree.get_actor_state_from_address(miner_address)?; match &state { miner::State::V8(s) => { @@ -2399,12 +2391,12 @@ impl StateSectorPreCommitInfo { } pub fn get_sector_pre_commit_infos( - store: &Arc, + store: &(impl Blockstore + ShallowClone), miner_address: &Address, tipset: &Tipset, ) -> anyhow::Result> { let mut infos = vec![]; - let state_tree = StateTree::new_from_root(store.clone(), tipset.parent_state())?; + let state_tree = StateTree::new_from_root(store, tipset.parent_state())?; let state: miner::State = state_tree.get_actor_state_from_address(miner_address)?; match &state { miner::State::V8(s) => { @@ -2570,7 +2562,7 @@ impl RpcMethod<3> for StateSectorGetInfo { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (miner_address, sector_number, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -2585,11 +2577,11 @@ impl RpcMethod<3> for StateSectorGetInfo { impl StateSectorGetInfo { pub fn get_sectors( - store: &Arc, + store: &(impl Blockstore + ShallowClone), miner_address: &Address, tipset: &Tipset, ) -> anyhow::Result> { - let state_tree = StateTree::new_from_root(store.clone(), tipset.parent_state())?; + let state_tree = StateTree::new_from_root(store, tipset.parent_state())?; let state: miner::State = state_tree.get_actor_state_from_address(miner_address)?; Ok(state .load_sectors(store, None)? @@ -2613,11 +2605,11 @@ impl RpcMethod<3> for StateSectorExpiration { type Ok = SectorExpiration; async fn handle( - ctx: Ctx, + ctx: Ctx, (miner_address, sector_number, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { - let store = ctx.store(); + let store = ctx.db(); let policy = &ctx.chain_config().policy; let ts = ctx.chain_store().load_required_tipset_or_heaviest(&tsk)?; let state: miner::State = ctx @@ -2674,7 +2666,7 @@ impl RpcMethod<3> for StateSectorPartition { type Ok = SectorLocation; async fn handle( - ctx: Ctx, + ctx: Ctx, (miner_address, sector_number, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -2683,7 +2675,7 @@ impl RpcMethod<3> for StateSectorPartition { .state_manager .get_actor_state_from_address(&ts, &miner_address)?; let (deadline, partition) = - state.find_sector(ctx.store(), sector_number, &ctx.chain_config().policy)?; + state.find_sector(ctx.db(), sector_number, &ctx.chain_config().policy)?; Ok(SectorLocation { deadline, partition, @@ -2706,7 +2698,7 @@ impl RpcMethod<3> for StateListMessages { type Ok = Vec; async fn handle( - ctx: Ctx, + ctx: Ctx, (from_to, ApiTipsetKey(tsk), max_height): Self::Params, _: &http::Extensions, ) -> Result { @@ -2768,7 +2760,7 @@ impl RpcMethod<3> for StateGetClaim { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, claim_id, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -2790,22 +2782,22 @@ impl RpcMethod<2> for StateGetClaims { type Ok = HashMap; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { let ts = ctx.chain_store().load_required_tipset_or_heaviest(&tsk)?; - Ok(Self::get_claims(&ctx.store_owned(), &address, &ts)?) + Ok(Self::get_claims(ctx.db(), &address, &ts)?) } } impl StateGetClaims { pub fn get_claims( - store: &Arc, + store: &(impl Blockstore + ShallowClone), address: &Address, tipset: &Tipset, ) -> anyhow::Result> { - let state_tree = StateTree::new_from_tipset(store.clone(), tipset)?; + let state_tree = StateTree::new_from_tipset(store, tipset)?; let state: verifreg::State = state_tree.get_actor_state()?; let actor_id = state_tree.lookup_required_id(address)?; let actor_id_address = Address::new_id(actor_id); @@ -2827,7 +2819,7 @@ impl RpcMethod<1> for StateGetAllClaims { type Ok = HashMap; async fn handle( - ctx: Ctx, + ctx: Ctx, (ApiTipsetKey(tsk),): Self::Params, _: &http::Extensions, ) -> Result { @@ -2850,7 +2842,7 @@ impl RpcMethod<3> for StateGetAllocation { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, allocation_id, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -2874,23 +2866,23 @@ impl RpcMethod<2> for StateGetAllocations { type Ok = HashMap; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { let ts = ctx.chain_store().load_required_tipset_or_heaviest(&tsk)?; - Ok(Self::get_allocations(&ctx.store_owned(), &address, &ts)?) + Ok(Self::get_allocations(ctx.db(), &address, &ts)?) } } impl StateGetAllocations { // For testing pub fn get_valid_actor_addresses<'a>( - store: &'a Arc, + store: &'a (impl Blockstore + ShallowClone), tipset: &'a Tipset, ) -> anyhow::Result + 'a> { let mut addresses = HashSet::default(); - let state_tree = StateTree::new_from_tipset(store.clone(), tipset)?; + let state_tree = StateTree::new_from_tipset(store, tipset)?; let verifreg_state: verifreg::State = state_tree.get_actor_state()?; match verifreg_state { verifreg::State::V13(s) => { @@ -3046,11 +3038,11 @@ impl StateGetAllocations { } pub fn get_allocations( - store: &Arc, + store: &(impl Blockstore + ShallowClone), address: &Address, tipset: &Tipset, ) -> anyhow::Result> { - let state_tree = StateTree::new_from_tipset(store.clone(), tipset)?; + let state_tree = StateTree::new_from_tipset(store, tipset)?; let state: verifreg::State = state_tree.get_actor_state()?; state.get_allocations(store, address) } @@ -3070,7 +3062,7 @@ impl RpcMethod<1> for crate::rpc::prelude::StateGetAllAllocations { type Ok = HashMap; async fn handle( - ctx: Ctx, + ctx: Ctx, (ApiTipsetKey(tsk),): Self::Params, _: &http::Extensions, ) -> Result { @@ -3093,23 +3085,23 @@ impl RpcMethod<2> for StateGetAllocationIdForPendingDeal { type Ok = AllocationID; async fn handle( - ctx: Ctx, + ctx: Ctx, (deal_id, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { let ts = ctx.chain_store().load_required_tipset_or_heaviest(&tsk)?; - let state_tree = StateTree::new_from_tipset(ctx.store_owned(), &ts)?; + let state_tree = StateTree::new_from_tipset(ctx.db(), &ts)?; let market_state: market::State = state_tree.get_actor_state()?; - Ok(market_state.get_allocation_id_for_pending_deal(ctx.store(), &deal_id)?) + Ok(market_state.get_allocation_id_for_pending_deal(ctx.db(), &deal_id)?) } } impl StateGetAllocationIdForPendingDeal { pub fn get_allocations_for_pending_deals( - store: &Arc, + store: &(impl Blockstore + ShallowClone), tipset: &Tipset, ) -> anyhow::Result> { - let state_tree = StateTree::new_from_tipset(store.clone(), tipset)?; + let state_tree = StateTree::new_from_tipset(store, tipset)?; let state: market::State = state_tree.get_actor_state()?; state.get_allocations_for_pending_deals(store) } @@ -3130,7 +3122,7 @@ impl RpcMethod<2> for StateGetAllocationForPendingDeal { type Ok = Option; async fn handle( - ctx: Ctx, + ctx: Ctx, (deal_id, tsk): Self::Params, ext: &http::Extensions, ) -> Result { @@ -3159,7 +3151,7 @@ impl RpcMethod<0> for StateGetNetworkParams { type Ok = NetworkParams; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -3310,7 +3302,7 @@ impl RpcMethod<4> for StateMinerInitialPledgeForSector { type Ok = TokenAmount; async fn handle( - ctx: Ctx, + ctx: Ctx, (sector_duration, sector_size, verified_size, ApiTipsetKey(tsk)): Self::Params, _: &http::Extensions, ) -> Result { @@ -3334,7 +3326,7 @@ impl RpcMethod<4> for StateMinerInitialPledgeForSector { let genesis_info = GenesisInfo::from_chain_config(ctx.chain_config().clone()); let circ_supply = genesis_info.get_vm_circulating_supply_detailed( ts.epoch(), - &ctx.store_owned(), + ctx.db(), ts.parent_state(), )?; @@ -3364,7 +3356,7 @@ impl RpcMethod<4> for StateMinerInitialPledgeForSector { } fn get_pledge_ramp_params( - ctx: &Ctx, + ctx: &Ctx, height: ChainEpoch, ts: &Tipset, ) -> anyhow::Result<(ChainEpoch, u64)> { @@ -3441,17 +3433,17 @@ impl RpcMethod<0> for StateActorInfo { type Ok = StateActorCodeCidsOutput; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { let ts = ctx.chain_store().load_required_tipset_or_heaviest(None)?; - let state_tree = StateTree::new_from_tipset(ctx.store_owned(), &ts)?; + let state_tree = StateTree::new_from_tipset(ctx.db(), &ts)?; let bundle = state_tree.get_actor_bundle_metadata()?; let system_state: system::State = state_tree.get_actor_state()?; let actors = system_state.builtin_actors_cid(); - let current_manifest = BuiltinActorManifest::load_v1_actor_list(ctx.store(), actors)?; + let current_manifest = BuiltinActorManifest::load_v1_actor_list(ctx.db(), actors)?; // Sanity check: the command would normally be used only for diagnostics, so we want to be // sure the data is consistent. diff --git a/src/rpc/methods/sync.rs b/src/rpc/methods/sync.rs index 218e863d7067..f0e45d05fc5f 100644 --- a/src/rpc/methods/sync.rs +++ b/src/rpc/methods/sync.rs @@ -4,18 +4,16 @@ mod types; use crate::blocks::{Block, FullTipset, GossipBlock}; +use crate::chain; +use crate::chain_sync::{NodeSyncStatus, SyncStatusReport, TipsetValidator}; use crate::libp2p::{IdentTopic, NetworkMessage, PUBSUB_BLOCK_STR}; +use crate::prelude::*; use crate::rpc::{ApiPaths, Ctx, Permission, RpcMethod, ServerError}; -use anyhow::{Context as _, anyhow}; -use cid::Cid; +use anyhow::anyhow; use enumflags2::BitFlags; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::to_vec; pub use types::*; -use crate::chain; -use crate::chain_sync::{NodeSyncStatus, SyncStatusReport, TipsetValidator}; - pub enum SyncCheckBad {} impl RpcMethod<1> for SyncCheckBad { const NAME: &'static str = "Filecoin.SyncCheckBad"; @@ -27,7 +25,7 @@ impl RpcMethod<1> for SyncCheckBad { type Ok = String; async fn handle( - ctx: Ctx, + ctx: Ctx, (cid,): Self::Params, _: &http::Extensions, ) -> Result { @@ -52,7 +50,7 @@ impl RpcMethod<1> for SyncMarkBad { type Ok = (); async fn handle( - ctx: Ctx, + ctx: Ctx, (cid,): Self::Params, _: &http::Extensions, ) -> Result { @@ -77,7 +75,7 @@ impl RpcMethod<0> for SyncSnapshotProgress { type Ok = SnapshotProgressState; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -97,7 +95,7 @@ impl RpcMethod<0> for SyncStatus { type Ok = SyncStatusReport; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -120,7 +118,7 @@ impl RpcMethod<1> for SyncSubmitBlock { // NOTE: This currently skips all the sanity-checks and directly passes the message onto the // swarm. async fn handle( - ctx: Ctx, + ctx: Ctx, (block_msg,): Self::Params, _: &http::Extensions, ) -> Result { @@ -131,7 +129,7 @@ impl RpcMethod<1> for SyncSubmitBlock { let encoded_message = to_vec(&block_msg)?; let pubsub_block_str = format!("{PUBSUB_BLOCK_STR}/{genesis_network_name}"); let (bls_messages, secp_messages) = - chain::store::block_messages(ctx.store(), &block_msg.header)?; + chain::store::block_messages(ctx.db(), &block_msg.header)?; let block = Block { header: block_msg.header.clone(), bls_messages, @@ -143,7 +141,7 @@ impl RpcMethod<1> for SyncSubmitBlock { TipsetValidator(&ts) .validate( ctx.chain_store(), - ctx.bad_blocks.as_ref().map(AsRef::as_ref), + ctx.bad_blocks.as_ref(), &genesis_ts, ctx.chain_config().block_delay_secs, ) @@ -170,7 +168,7 @@ mod tests { use crate::blocks::{CachingBlockHeader, Tipset}; use crate::chain::ChainStore; use crate::chain_sync::network_context::SyncNetworkContext; - use crate::db::MemoryDB; + use crate::db::{Blockstore as _, MemoryDB}; use crate::key_management::{KeyStore, KeyStoreConfig}; use crate::libp2p::{NetworkMessage, PeerManager}; use crate::message_pool::{MessagePool, MpoolLocker, NonceTracker}; @@ -184,7 +182,7 @@ mod tests { use tokio::sync::mpsc; use tokio::task::JoinSet; - fn ctx() -> (Arc>, flume::Receiver) { + fn ctx() -> (Arc, flume::Receiver) { let (network_send, network_rx) = flume::bounded(5); let (tipset_send, _) = flume::bounded(5); let mut services = JoinSet::new(); @@ -197,18 +195,15 @@ mod tests { ..Default::default() }); - let cs_arc = Arc::new( - ChainStore::new(db.clone(), db.clone(), db, chain_config, genesis_header).unwrap(), - ); - - let state_manager = Arc::new(StateManager::new(cs_arc.clone()).unwrap()); - let cs_for_test = &cs_arc; + let cs = ChainStore::new(db, chain_config, genesis_header).unwrap(); + let state_manager = StateManager::new(cs.shallow_clone()).unwrap(); + let cs_for_test = &cs; let mpool_network_send = network_send.clone(); - let pool = { + let mpool = { let bz = hex::decode("904300e80781586082cb7477a801f55c1f2ea5e5d1167661feea60a39f697e1099af132682b81cc5047beacf5b6e80d5f52b9fd90323fb8510a5396416dd076c13c85619e176558582744053a3faef6764829aa02132a1571a76aabdc498a638ea0054d3bb57f41d82015860812d2396cc4592cdf7f829374b01ffd03c5469a4b0a9acc5ccc642797aa0a5498b97b28d90820fedc6f79ff0a6005f5c15dbaca3b8a45720af7ed53000555667207a0ccb50073cd24510995abd4c4e45c1e9e114905018b2da9454190499941e818201582012dd0a6a7d0e222a97926da03adb5a7768d31cc7c5c2bd6828e14a7d25fa3a608182004b76616c69642070726f6f6681d82a5827000171a0e4022030f89a8b0373ad69079dbcbc5addfe9b34dce932189786e50d3eb432ede3ba9c43000f0001d82a5827000171a0e4022052238c7d15c100c1b9ebf849541810c9e3c2d86e826512c6c416d2318fcd496dd82a5827000171a0e40220e5658b3d18cd06e1db9015b4b0ec55c123a24d5be1ea24d83938c5b8397b4f2fd82a5827000171a0e4022018d351341c302a21786b585708c9873565a0d07c42521d4aaf52da3ff6f2e461586102c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a5f2c5439586102b5cd48724dce0fec8799d77fd6c5113276e7f470c8391faa0b5a6033a3eaf357d635705c36abe10309d73592727289680515afd9d424793ba4796b052682d21b03c5c8a37d94827fecc59cdc5750e198fdf20dee012f4d627c6665132298ab95004500053724e0").unwrap(); let header = from_slice_with_fallback::(&bz).unwrap(); let ts = Tipset::from(header); - let db = cs_for_test.blockstore(); + let db = cs_for_test.db(); let tsk = ts.key(); cs_for_test.set_heaviest_tipset(ts.clone()).unwrap(); @@ -218,7 +213,7 @@ mod tests { } MessagePool::new( - cs_arc, + cs, mpool_network_send, Default::default(), state_manager.chain_config().clone(), @@ -230,12 +225,12 @@ mod tests { let peer_manager = Arc::new(PeerManager::default()); let sync_network_context = - SyncNetworkContext::new(network_send, peer_manager, state_manager.blockstore_owned()); + SyncNetworkContext::new(network_send, peer_manager, state_manager.db_owned()); let nonce_tracker = NonceTracker::new(); let state = Arc::new(RPCState { state_manager, keystore: Arc::new(RwLock::new(KeyStore::new(KeyStoreConfig::Memory).unwrap())), - mpool: Arc::new(pool), + mpool, bad_blocks: Some(Default::default()), sync_status: Arc::new(RwLock::new(SyncStatusReport::default())), eth_event_handler: Arc::new(EthEventHandler::new()), diff --git a/src/rpc/methods/wallet.rs b/src/rpc/methods/wallet.rs index 4f65221eb3dc..6a82b214c595 100644 --- a/src/rpc/methods/wallet.rs +++ b/src/rpc/methods/wallet.rs @@ -1,9 +1,6 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use std::any::Any; - -use crate::db::EthMappingsStore; use crate::key_management::{Key, KeyInfo}; use crate::message::SignedMessage; use crate::rpc::{ApiPaths, Ctx, Permission, RpcMethod, ServerError}; @@ -15,7 +12,6 @@ use crate::shim::{ state_tree::StateTree, }; use enumflags2::BitFlags; -use fvm_ipld_blockstore::Blockstore; pub enum WalletBalance {} impl RpcMethod<1> for WalletBalance { @@ -29,14 +25,14 @@ impl RpcMethod<1> for WalletBalance { type Ok = TokenAmount; async fn handle( - ctx: Ctx, + ctx: Ctx, (address,): Self::Params, _: &http::Extensions, ) -> Result { let heaviest_ts = ctx.chain_store().heaviest_tipset(); let cid = heaviest_ts.parent_state(); - Ok(StateTree::new_from_root(ctx.store_owned(), cid)? + Ok(StateTree::new_from_root(ctx.db(), cid)? .get_actor(&address)? .map(|it| it.balance.clone().into()) .unwrap_or_default()) @@ -54,7 +50,7 @@ impl RpcMethod<0> for WalletDefaultAddress { type Ok = Option
; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -74,7 +70,7 @@ impl RpcMethod<1> for WalletExport { type Ok = KeyInfo; async fn handle( - ctx: Ctx, + ctx: Ctx, (address,): Self::Params, _: &http::Extensions, ) -> Result { @@ -97,7 +93,7 @@ impl RpcMethod<1> for WalletHas { type Ok = bool; async fn handle( - ctx: Ctx, + ctx: Ctx, (address,): Self::Params, _: &http::Extensions, ) -> Result { @@ -117,7 +113,7 @@ impl RpcMethod<1> for WalletImport { type Ok = Address; async fn handle( - ctx: Ctx, + ctx: Ctx, (key_info,): Self::Params, _: &http::Extensions, ) -> Result { @@ -141,7 +137,7 @@ impl RpcMethod<0> for WalletList { type Ok = Vec
; async fn handle( - ctx: Ctx, + ctx: Ctx, (): Self::Params, _: &http::Extensions, ) -> Result { @@ -161,7 +157,7 @@ impl RpcMethod<1> for WalletNew { type Ok = Address; async fn handle( - ctx: Ctx, + ctx: Ctx, (signature_type,): Self::Params, _: &http::Extensions, ) -> Result { @@ -189,7 +185,7 @@ impl RpcMethod<1> for WalletSetDefault { type Ok = (); async fn handle( - ctx: Ctx, + ctx: Ctx, (address,): Self::Params, _: &http::Extensions, ) -> Result { @@ -215,7 +211,7 @@ impl RpcMethod<2> for WalletSign { type Ok = Signature; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, message): Self::Params, _: &http::Extensions, ) -> Result { @@ -249,7 +245,7 @@ impl RpcMethod<2> for WalletSignMessage { type Ok = SignedMessage; async fn handle( - ctx: Ctx, + ctx: Ctx, (address, message): Self::Params, _: &http::Extensions, ) -> Result { @@ -277,7 +273,7 @@ impl RpcMethod<1> for WalletValidateAddress { type Ok = Address; async fn handle( - _: Ctx, + _: Ctx, (s,): Self::Params, _: &http::Extensions, ) -> Result { @@ -296,7 +292,7 @@ impl RpcMethod<3> for WalletVerify { type Ok = bool; async fn handle( - _: Ctx, + _: Ctx, (address, message, signature): Self::Params, _: &http::Extensions, ) -> Result { @@ -315,7 +311,7 @@ impl RpcMethod<1> for WalletDelete { type Ok = (); async fn handle( - ctx: Ctx, + ctx: Ctx, (address,): Self::Params, _: &http::Extensions, ) -> Result { diff --git a/src/rpc/mod.rs b/src/rpc/mod.rs index 8325157cdca7..f5af90855161 100644 --- a/src/rpc/mod.rs +++ b/src/rpc/mod.rs @@ -1,7 +1,7 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use crate::db::EthMappingsStore; +use crate::db::DbImpl; use crate::rpc::methods::eth::pubsub_trait::EthPubSubApiServer; mod auth_layer; mod channel; @@ -435,7 +435,6 @@ use crate::{chain_sync::network_context::SyncNetworkContext, key_management::Key use crate::blocks::FullTipset; use crate::utils::misc::env::env_or_default; -use fvm_ipld_blockstore::Blockstore; use jsonrpsee::{ Methods, core::middleware::RpcServiceBuilder, @@ -489,14 +488,14 @@ static MAX_RESPONSE_BODY_SIZE: LazyLock = /// This is where you store persistent data, or at least access to stateful /// data. -pub struct RPCState { +pub struct RPCState { pub keystore: Arc>, - pub state_manager: Arc>, - pub mpool: Arc>>>, - pub bad_blocks: Option>, + pub state_manager: crate::state_manager::StateManager, + pub mpool: crate::message_pool::MessagePool, + pub bad_blocks: Option, pub sync_status: crate::chain_sync::SyncStatus, pub eth_event_handler: Arc, - pub sync_network_context: SyncNetworkContext, + pub sync_network_context: SyncNetworkContext, pub tipset_send: flume::Sender, pub start_time: chrono::DateTime, pub snapshot_progress_tracker: SnapshotProgressTracker, @@ -506,16 +505,16 @@ pub struct RPCState { pub temp_dir: Arc, } -impl RPCState { +impl RPCState { pub fn beacon(&self) -> &Arc { self.state_manager.beacon_schedule() } - pub fn chain_store(&self) -> &Arc> { + pub fn chain_store(&self) -> &crate::chain::ChainStore { self.state_manager.chain_store() } - pub fn chain_index(&self) -> &crate::chain::index::ChainIndex { + pub fn chain_index(&self) -> &crate::chain::index::ChainIndex { self.chain_store().chain_index() } @@ -523,12 +522,12 @@ impl RPCState { self.state_manager.chain_config() } - pub fn store(&self) -> &Arc { - self.chain_store().blockstore() + pub fn db(&self) -> &DbImpl { + self.state_manager.db() } - pub fn store_owned(&self) -> Arc { - self.state_manager.blockstore_owned() + pub fn db_owned(&self) -> DbImpl { + self.state_manager.db_owned() } pub fn network_send(&self) -> &flume::Sender { @@ -547,15 +546,12 @@ struct PerConnection { keystore: Arc>, } -pub async fn start_rpc( - state: RPCState, +pub async fn start_rpc( + state: RPCState, rpc_listener: tokio::net::TcpListener, stop_handle: StopHandle, filter_list: Option, -) -> anyhow::Result<()> -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +) -> anyhow::Result<()> { let filter_list = filter_list.unwrap_or_default(); // `Arc` is needed because we will share the state between two modules let state = Arc::new(state); @@ -705,10 +701,7 @@ where Ok(()) } -fn create_modules(state: Arc>) -> HashMap>> -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +fn create_modules(state: Arc) -> HashMap> { let mut modules = HashMap::default(); for api_version in ApiPaths::value_variants() { modules.insert(*api_version, RpcModule::from_arc(state.clone())); diff --git a/src/rpc/reflect/mod.rs b/src/rpc/reflect/mod.rs index 3a4c75083267..1882a35cebf8 100644 --- a/src/rpc/reflect/mod.rs +++ b/src/rpc/reflect/mod.rs @@ -21,14 +21,13 @@ pub mod jsonrpc_types; mod parser; mod util; -use crate::{db::EthMappingsStore, lotus_json::HasLotusJson}; +use crate::lotus_json::HasLotusJson; use self::{jsonrpc_types::RequestParameters, util::Optional as _}; use super::error::ServerError as Error; use ahash::HashMap; use anyhow::Context as _; use enumflags2::{BitFlags, bitflags, make_bitflags}; -use fvm_ipld_blockstore::Blockstore; use http::{Extensions, Uri}; use jsonrpsee::RpcModule; use openrpc_types::{ContentDescriptor, Method, ParamStructure, ReferenceOr}; @@ -42,7 +41,7 @@ use std::{future::Future, str::FromStr, sync::Arc}; use strum::EnumString; /// Type to be used by [`RpcMethod::handle`]. -pub type Ctx = Arc>; +pub type Ctx = Arc; /// A definition of an RPC method handler which: /// - can be [registered](RpcMethodExt::register) with an [`RpcModule`]. @@ -78,7 +77,7 @@ pub trait RpcMethod { type Ok: HasLotusJson; /// Logic for this method. fn handle( - ctx: Ctx, + ctx: Ctx, params: Self::Params, ext: &Extensions, ) -> impl Future> + Send; @@ -247,12 +246,7 @@ pub trait RpcMethodExt: RpcMethod { /// Register a method with an [`RpcModule`]. fn register( - modules: &mut HashMap< - ApiPaths, - RpcModule< - crate::rpc::RPCState, - >, - >, + modules: &mut HashMap>, calling_convention: ParamStructure, ) -> Result<(), jsonrpsee::core::RegisterMethodError> where diff --git a/src/shim/machine/manifest.rs b/src/shim/machine/manifest.rs index f105c04fe292..346d518267b7 100644 --- a/src/shim/machine/manifest.rs +++ b/src/shim/machine/manifest.rs @@ -7,12 +7,10 @@ use std::collections::BTreeMap; use crate::{ networks::{ACTOR_BUNDLES_METADATA, ActorBundleMetadata}, + prelude::*, utils::db::CborStoreExt as _, }; -use anyhow::{Context as _, ensure}; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; -use itertools::Itertools as _; +use anyhow::ensure; use num::FromPrimitive; use serde::{Deserialize, Serialize}; diff --git a/src/shim/state_tree.rs b/src/shim/state_tree.rs index 2921ee40cc71..215e72a30854 100644 --- a/src/shim/state_tree.rs +++ b/src/shim/state_tree.rs @@ -4,15 +4,14 @@ use super::actors::LoadActorStateFromBlockstore; pub use super::fvm_shared_latest::{ActorID, state::StateRoot}; use crate::{ blocks::Tipset, + prelude::*, shim::{actors::AccountActorStateLoad as _, address::Address, econ::TokenAmount}, }; use crate::{ networks::{ACTOR_BUNDLES_METADATA, ActorBundleMetadata}, shim::actors::account, }; -use anyhow::{Context as _, bail}; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; +use anyhow::bail; use fvm_ipld_encoding::{ CborStore as _, repr::{Deserialize_repr, Serialize_repr}, @@ -29,7 +28,6 @@ use num::FromPrimitive; use num_derive::FromPrimitive; use serde::{Deserialize, Serialize}; use spire_enum::prelude::delegated_enum; -use std::sync::Arc; #[derive( Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Serialize_repr, Deserialize_repr, FromPrimitive, @@ -136,40 +134,42 @@ impl TryFrom for StateTreeVersionV4 { #[delegated_enum(impl_conversions)] pub enum StateTree { // Version 0 is used to parse the genesis block. - V0(super::state_tree_v0::StateTreeV0>), + V0(super::state_tree_v0::StateTreeV0), // fvm-2 support state tree versions 3 and 4. - FvmV2(StateTreeV2>), + FvmV2(StateTreeV2), // fvm-3 support state tree versions 5. - FvmV3(StateTreeV3>), + FvmV3(StateTreeV3), // fvm-4 support state tree versions *. - FvmV4(StateTreeV4>), + FvmV4(StateTreeV4), } impl StateTree where - S: Blockstore, + S: Blockstore + ShallowClone, { /// Constructor for a HAMT state tree given an IPLD store - pub fn new(store: Arc, version: StateTreeVersion) -> anyhow::Result { - if let Ok(st) = StateTreeV4::new(store.clone(), version.try_into()?) { + pub fn new(store: &S, version: StateTreeVersion) -> anyhow::Result { + if let Ok(st) = StateTreeV4::new(store.shallow_clone(), version.try_into()?) { Ok(StateTree::FvmV4(st)) - } else if let Ok(st) = StateTreeV3::new(store.clone(), version.try_into()?) { + } else if let Ok(st) = StateTreeV3::new(store.shallow_clone(), version.try_into()?) { Ok(StateTree::FvmV3(st)) - } else if let Ok(st) = StateTreeV2::new(store, version.try_into()?) { + } else if let Ok(st) = StateTreeV2::new(store.shallow_clone(), version.try_into()?) { Ok(StateTree::FvmV2(st)) } else { bail!("Can't create a valid state tree for the given version."); } } - pub fn new_from_root(store: Arc, c: &Cid) -> anyhow::Result { - if let Ok(st) = StateTreeV4::new_from_root(store.clone(), c) { + pub fn new_from_root(store: &S, c: &Cid) -> anyhow::Result { + if let Ok(st) = StateTreeV4::new_from_root(store.shallow_clone(), c) { Ok(StateTree::FvmV4(st)) - } else if let Ok(st) = StateTreeV3::new_from_root(store.clone(), c) { + } else if let Ok(st) = StateTreeV3::new_from_root(store.shallow_clone(), c) { Ok(StateTree::FvmV3(st)) - } else if let Ok(st) = StateTreeV2::new_from_root(store.clone(), c) { + } else if let Ok(st) = StateTreeV2::new_from_root(store.shallow_clone(), c) { Ok(StateTree::FvmV2(st)) - } else if let Ok(st) = super::state_tree_v0::StateTreeV0::new_from_root(store.clone(), c) { + } else if let Ok(st) = + super::state_tree_v0::StateTreeV0::new_from_root(store.shallow_clone(), c) + { Ok(StateTree::V0(st)) } else if !store.has(c)? { bail!("No state tree exists for the root {c}.") @@ -184,10 +184,15 @@ where } } - pub fn new_from_tipset(store: Arc, ts: &Tipset) -> anyhow::Result { + pub fn new_from_tipset(store: &S, ts: &Tipset) -> anyhow::Result { Self::new_from_root(store, ts.parent_state()) } +} +impl StateTree +where + S: Blockstore, +{ /// Get required actor state from an address. Will be resolved to ID address. pub fn get_required_actor(&self, addr: &Address) -> anyhow::Result { self.get_actor(addr)? @@ -527,12 +532,11 @@ mod tests { // refactored from `StateManager::get_network_name` fn get_network_name(car: &'static [u8], genesis_cid: Cid) -> String { - let forest_car = AnyCar::new(car).unwrap(); + let forest_car = Arc::new(AnyCar::new(car).unwrap()); let genesis_block = CachingBlockHeader::load(&forest_car, genesis_cid) .unwrap() .unwrap(); - let state_tree = - StateTree::new_from_root(Arc::new(&forest_car), &genesis_block.state_root).unwrap(); + let state_tree = StateTree::new_from_root(&forest_car, &genesis_block.state_root).unwrap(); let state: init::State = state_tree.get_actor_state().unwrap(); state.into_network_name() } diff --git a/src/state_manager/actor_queries.rs b/src/state_manager/actor_queries.rs index 5c901c20b43a..e1513f1dc82f 100644 --- a/src/state_manager/actor_queries.rs +++ b/src/state_manager/actor_queries.rs @@ -10,14 +10,11 @@ use fil_actor_verifreg_state::v12::DataCap; use fil_actor_verifreg_state::v13::ClaimID; use fil_actors_shared::fvm_ipld_bitfield::BitField; -impl StateManager -where - DB: Blockstore + Send + Sync + 'static, -{ +impl StateManager { /// Retrieves market state pub fn market_state(&self, ts: &Tipset) -> Result { let actor = self.get_required_actor(&Address::MARKET_ACTOR, *ts.parent_state())?; - let market_state = market::State::load(self.blockstore(), actor.code, actor.state)?; + let market_state = market::State::load(self.db(), actor.code, actor.state)?; Ok(market_state) } @@ -26,16 +23,8 @@ where let market_state = self.market_state(ts)?; let new_addr = self.lookup_required_id(addr, ts)?; let out = MarketBalance { - escrow: { - market_state - .escrow_table(self.blockstore())? - .get(&new_addr)? - }, - locked: { - market_state - .locked_table(self.blockstore())? - .get(&new_addr)? - }, + escrow: { market_state.escrow_table(self.db())?.get(&new_addr)? }, + locked: { market_state.locked_table(self.db())?.get(&new_addr)? }, }; Ok(out) @@ -49,9 +38,9 @@ where ts.epoch() )) })?; - let state = miner::State::load(self.blockstore(), actor.code, actor.state)?; + let state = miner::State::load(self.db(), actor.code, actor.state)?; - Ok(state.info(self.blockstore())?) + Ok(state.info(self.db())?) } /// Retrieves miner faults. @@ -77,20 +66,16 @@ where )) })?; - let state = miner::State::load(self.blockstore(), actor.code, actor.state)?; + let state = miner::State::load(self.db(), actor.code, actor.state)?; let mut partitions = Vec::new(); - state.for_each_deadline( - &self.chain_config().policy, - self.blockstore(), - |_, deadline| { - deadline.for_each(self.blockstore(), |_, partition| { - partitions.push(get_sector(partition)); - Ok(()) - }) - }, - )?; + state.for_each_deadline(&self.chain_config().policy, self.db(), |_, deadline| { + deadline.for_each(self.db(), |_, partition| { + partitions.push(get_sector(partition)); + Ok(()) + }) + })?; Ok(BitField::union(partitions.iter())) } @@ -120,7 +105,7 @@ where .get_actor(&Address::VERIFIED_REGISTRY_ACTOR, *ts.parent_state()) .map_err(Error::state)? .ok_or_else(|| Error::state("actor not found"))?; - verifreg::State::load(self.blockstore(), act.code, act.state) + verifreg::State::load(self.db(), act.code, act.state) } pub fn get_claim( &self, @@ -130,12 +115,12 @@ where ) -> anyhow::Result> { let id_address = self.lookup_required_id(addr, ts)?; let state = self.get_verified_registry_actor_state(ts)?; - state.get_claim(self.blockstore(), id_address, claim_id) + state.get_claim(self.db(), id_address, claim_id) } pub fn get_all_claims(&self, ts: &Tipset) -> anyhow::Result> { let state = self.get_verified_registry_actor_state(ts)?; - state.get_all_claims(self.blockstore()) + state.get_all_claims(self.db()) } pub fn get_allocation( @@ -146,7 +131,7 @@ where ) -> anyhow::Result> { let id_address = self.lookup_required_id(addr, ts)?; let state = self.get_verified_registry_actor_state(ts)?; - state.get_allocation(self.blockstore(), id_address.id()?, allocation_id) + state.get_allocation(self.db(), id_address.id()?, allocation_id) } pub fn get_all_allocations( @@ -154,7 +139,7 @@ where ts: &Tipset, ) -> anyhow::Result> { let state = self.get_verified_registry_actor_state(ts)?; - state.get_all_allocations(self.blockstore()) + state.get_all_allocations(self.db()) } pub fn verified_client_status( @@ -170,7 +155,7 @@ where // Original: https://github.com/filecoin-project/lotus/blob/5e76b05b17771da6939c7b0bf65127c3dc70ee23/node/impl/full/state.go#L1627-L1664. if (u32::from(network_version.0)) < 17 { let state = self.get_verified_registry_actor_state(ts)?; - return state.verified_client_data_cap(self.blockstore(), id); + return state.verified_client_data_cap(self.db(), id); } let act = self @@ -183,8 +168,8 @@ where )) })?; - let state = datacap::State::load(self.blockstore(), act.code, act.state)?; + let state = datacap::State::load(self.db(), act.code, act.state)?; - state.verified_client_data_cap(self.blockstore(), id) + state.verified_client_data_cap(self.db(), id) } } diff --git a/src/state_manager/address_resolution.rs b/src/state_manager/address_resolution.rs index 1f83390f1660..2dd0aa884fc2 100644 --- a/src/state_manager/address_resolution.rs +++ b/src/state_manager/address_resolution.rs @@ -2,23 +2,19 @@ // SPDX-License-Identifier: Apache-2.0, MIT use super::*; -use crate::db::EthMappingsStore; +use crate::prelude::*; use crate::shim::address::{Payload, Protocol}; -use anyhow::Context as _; use bls_signatures::{PublicKey as BlsPublicKey, Serialize as _}; -impl StateManager -where - DB: Blockstore + Send + Sync + 'static, -{ +impl StateManager { /// Returns a BLS public key from provided address pub fn get_bls_public_key( - db: &Arc, + db: &(impl Blockstore + ShallowClone), addr: &Address, state_cid: Cid, ) -> Result { - let state = StateTree::new_from_root(Arc::clone(db), &state_cid) - .map_err(|e| Error::Other(e.to_string()))?; + let state = + StateTree::new_from_root(db, &state_cid).map_err(|e| Error::Other(e.to_string()))?; let kaddr = resolve_to_key_addr(&state, db, addr).context("Failed to resolve key address")?; @@ -34,8 +30,8 @@ where /// Looks up ID [Address] from the state at the given [Tipset]. pub fn lookup_id(&self, addr: &Address, ts: &Tipset) -> Result, Error> { - let state_tree = StateTree::new_from_root(self.blockstore_owned(), ts.parent_state()) - .map_err(|e| format!("{e:?}"))?; + let state_tree = + StateTree::new_from_root(self.db(), ts.parent_state()).map_err(|e| format!("{e:?}"))?; Ok(state_tree .lookup_id(addr) .map_err(|e| Error::Other(e.to_string()))? @@ -51,13 +47,10 @@ where /// Similar to `resolve_to_key_addr` in the `forest_vm` [`crate::state_manager`] but does not /// allow `Actor` type of addresses. Uses `ts` to generate the VM state. pub async fn resolve_to_key_addr( - self: &Arc, + &self, addr: &Address, ts: &Tipset, - ) -> anyhow::Result
- where - DB: EthMappingsStore, - { + ) -> anyhow::Result
{ match addr.protocol() { Protocol::BLS | Protocol::Secp256k1 | Protocol::Delegated => return Ok(*addr), Protocol::Actor => { @@ -71,28 +64,25 @@ where // First try to resolve the actor in the parent state, so we don't have to // compute anything. - let state = StateTree::new_from_root(self.blockstore_owned(), ts.parent_state())?; - if let Ok(addr) = resolve_to_key_addr(&state, self.blockstore(), addr) { + let state = StateTree::new_from_root(self.db(), ts.parent_state())?; + if let Ok(addr) = resolve_to_key_addr(&state, self.db(), addr) { return Ok(addr); } // If that fails, compute the tip-set and try again. let TipsetState { state_root, .. } = self.load_tipset_state(ts).await?; - let state = StateTree::new_from_root(self.blockstore_owned(), &state_root)?; + let state = StateTree::new_from_root(self.db(), &state_root)?; - resolve_to_key_addr(&state, self.blockstore(), addr) + resolve_to_key_addr(&state, self.db(), addr) } /// Similar to [`StateTree::resolve_to_deterministic_addr`] but does not allow [`crate::shim::address::Protocol::Actor`] type of addresses. /// Uses the [`Tipset`] `ts` to generate the VM state. pub async fn resolve_to_deterministic_address( - self: &Arc, + &self, address: Address, ts: &Tipset, - ) -> anyhow::Result
- where - DB: EthMappingsStore, - { + ) -> anyhow::Result
{ use crate::shim::address::Protocol::*; match address.protocol() { BLS | Secp256k1 | Delegated => Ok(address), @@ -104,16 +94,16 @@ where } // First try to resolve the actor in the parent state, so we don't have to compute anything. let resolved = if let Ok(state) = - StateTree::new_from_root(self.blockstore_owned(), ts.parent_state()) - && let Ok(address) = state - .resolve_to_deterministic_addr(self.chain_store().blockstore(), address) + StateTree::new_from_root(self.db(), ts.parent_state()) + && let Ok(address) = + state.resolve_to_deterministic_addr(self.chain_store().db(), address) { address } else { // If that fails, compute the tip-set and try again. let TipsetState { state_root, .. } = self.load_tipset_state(ts).await?; - let state = StateTree::new_from_root(self.blockstore_owned(), &state_root)?; - state.resolve_to_deterministic_addr(self.chain_store().blockstore(), address)? + let state = StateTree::new_from_root(self.db(), &state_root)?; + state.resolve_to_deterministic_addr(self.chain_store().db(), address)? }; self.id_to_deterministic_address_cache.push(id, resolved); Ok(resolved) diff --git a/src/state_manager/cache.rs b/src/state_manager/cache.rs index 0e98bde266a1..13371a67d5ec 100644 --- a/src/state_manager/cache.rs +++ b/src/state_manager/cache.rs @@ -1,14 +1,13 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT use crate::blocks::TipsetKey; +use crate::prelude::*; use crate::state_manager::DEFAULT_TIPSET_CACHE_SIZE; -use crate::utils::ShallowClone; use crate::utils::cache::{LruValueConstraints, SizeTrackingLruCache}; use ahash::{HashMap, HashMapExt as _}; use parking_lot::RwLock as SyncRwLock; use std::future::Future; use std::num::NonZeroUsize; -use std::sync::Arc; use tokio::sync::Mutex as TokioMutex; struct TipsetStateCacheInner { @@ -37,6 +36,14 @@ pub(crate) struct TipsetStateCache { cache: Arc>>, } +impl ShallowClone for TipsetStateCache { + fn shallow_clone(&self) -> Self { + Self { + cache: self.cache.shallow_clone(), + } + } +} + enum CacheLookupStatus { Exist(V), Empty(Arc>), diff --git a/src/state_manager/chain_rand.rs b/src/state_manager/chain_rand.rs index ce5c01186aea..8b798e1275d2 100644 --- a/src/state_manager/chain_rand.rs +++ b/src/state_manager/chain_rand.rs @@ -1,32 +1,30 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use std::{io::Write, sync::Arc}; +use std::io::Write; use crate::beacon::{Beacon as _, BeaconEntry, BeaconSchedule}; use crate::blocks::Tipset; use crate::chain::index::{ChainIndex, ResolveNullTipset}; -use crate::db::EthMappingsStore; use crate::networks::ChainConfig; +use crate::prelude::*; use crate::shim::clock::ChainEpoch; use crate::shim::externs::Rand; -use crate::utils::ShallowClone; use crate::utils::encoding::blake2b_256; -use anyhow::{Context as _, bail}; +use anyhow::bail; use blake2b_simd::Params; use byteorder::{BigEndian, WriteBytesExt}; -use fvm_ipld_blockstore::Blockstore; /// Allows for deriving the randomness from a particular tipset. #[derive(derive_more::Constructor)] -pub struct ChainRand { +pub struct ChainRand { chain_config: Arc, tipset: Tipset, - chain_index: ChainIndex, + chain_index: ChainIndex, beacon: Arc, } -impl ShallowClone for ChainRand { +impl ShallowClone for ChainRand { fn shallow_clone(&self) -> Self { ChainRand { chain_config: self.chain_config.shallow_clone(), @@ -37,10 +35,7 @@ impl ShallowClone for ChainRand { } } -impl ChainRand -where - DB: Blockstore + EthMappingsStore, -{ +impl ChainRand { /// Gets 32 bytes of randomness for `ChainRand` parameterized by the /// `DomainSeparationTag`, `ChainEpoch`, Entropy from the ticket chain. pub fn get_chain_randomness( @@ -156,10 +151,7 @@ where } } -impl Rand for ChainRand -where - DB: Blockstore + EthMappingsStore, -{ +impl Rand for ChainRand { fn get_chain_randomness(&self, round: ChainEpoch) -> anyhow::Result<[u8; 32]> { self.get_chain_randomness_v2(round) } diff --git a/src/state_manager/circulating_supply.rs b/src/state_manager/circulating_supply.rs index b6e6c9bbd5cd..d68a64fffa73 100644 --- a/src/state_manager/circulating_supply.rs +++ b/src/state_manager/circulating_supply.rs @@ -1,10 +1,9 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use std::sync::Arc; - use crate::chain::*; use crate::networks::{ChainConfig, Height}; +use crate::prelude::*; use crate::rpc::types::CirculatingSupply; use crate::shim::actors::{ MarketActorStateLoad as _, MinerActorStateLoad as _, MultisigActorStateLoad as _, @@ -19,9 +18,7 @@ use crate::shim::{ econ::{TOTAL_FILECOIN, TokenAmount}, state_tree::{ActorState, StateTree}, }; -use anyhow::{Context as _, bail}; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; +use anyhow::bail; use num_traits::Zero; const EPOCHS_IN_YEAR: ChainEpoch = 365 * EPOCHS_IN_DAY; @@ -68,26 +65,25 @@ impl GenesisInfo { /// /// IMPORTANT: Easy to mistake for [`GenesisInfo::get_state_circulating_supply`], that's being /// calculated differently. - pub fn get_vm_circulating_supply( + pub fn get_vm_circulating_supply( &self, height: ChainEpoch, - db: &Arc, + db: &DB, root: &Cid, ) -> anyhow::Result { let detailed = self.get_vm_circulating_supply_detailed(height, db, root)?; - Ok(detailed.fil_circulating) } /// Calculate total FIL circulating supply based on Genesis configuration and state of particular /// actors at a given height and state root. - pub fn get_vm_circulating_supply_detailed( + pub fn get_vm_circulating_supply_detailed( &self, height: ChainEpoch, - db: &Arc, + db: &DB, root: &Cid, ) -> anyhow::Result { - let state_tree = StateTree::new_from_root(Arc::clone(db), root)?; + let state_tree = StateTree::new_from_root(db, root)?; let fil_vested = get_fil_vested(self, height); let fil_mined = get_fil_mined(&state_tree)?; @@ -119,16 +115,16 @@ impl GenesisInfo { /// /// IMPORTANT: Easy to mistake for [`GenesisInfo::get_vm_circulating_supply`], that's being /// calculated differently. - pub fn get_state_circulating_supply( + pub fn get_state_circulating_supply( &self, height: ChainEpoch, - db: &Arc, + db: &(impl Blockstore + ShallowClone), root: &Cid, ) -> anyhow::Result { let mut circ = TokenAmount::default(); let mut un_circ = TokenAmount::default(); - let state_tree = StateTree::new_from_root(Arc::clone(db), root)?; + let state_tree = StateTree::new_from_root(db, root)?; state_tree.for_each(|addr: Address, actor: &ActorState| { let actor_balance = TokenAmount::from(actor.balance.clone()); diff --git a/src/state_manager/execution.rs b/src/state_manager/execution.rs index ca6eafa0ef98..e86a2d13f419 100644 --- a/src/state_manager/execution.rs +++ b/src/state_manager/execution.rs @@ -6,28 +6,20 @@ use super::utils::structured; use super::*; use crate::interpreter::{CalledAt, VMTrace}; use crate::rpc::state::{ApiInvocResult, MessageGasCost}; -use crate::utils::ShallowClone as _; use anyhow::{Context as _, bail}; use num_traits::identities::Zero; use std::ops::RangeInclusive; -impl StateManager -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +impl StateManager { /// Replays the given message and returns the result of executing the /// indicated message, assuming it was executed in the indicated tipset. - pub async fn replay(self: &Arc, ts: Tipset, mcid: Cid) -> Result { - let this = Arc::clone(self); + pub async fn replay(&self, ts: Tipset, mcid: Cid) -> Result { + let this = self.shallow_clone(); tokio::task::spawn_blocking(move || this.replay_blocking(ts, mcid)).await? } /// Blocking version of `replay` - pub fn replay_blocking( - self: &Arc, - ts: Tipset, - mcid: Cid, - ) -> Result { + pub fn replay_blocking(&self, ts: Tipset, mcid: Cid) -> Result { const REPLAY_HALT: &str = "replay_halt"; let mut api_invoc_result = None; @@ -65,11 +57,11 @@ where /// Replays a tipset up to a target message, capturing the state root before /// and after execution. pub async fn replay_for_prestate( - self: &Arc, + &self, ts: Tipset, target_message_cid: Cid, ) -> Result<(Cid, ApiInvocResult, Cid), Error> { - let this = Arc::clone(self); + let this = self.shallow_clone(); tokio::task::spawn_blocking(move || { this.replay_for_prestate_blocking(ts, target_message_cid) }) @@ -78,7 +70,7 @@ where } fn replay_for_prestate_blocking( - self: &Arc, + &self, ts: Tipset, target_msg_cid: Cid, ) -> Result<(Cid, ApiInvocResult, Cid), Error> { @@ -207,7 +199,7 @@ where // lookup tipset parents as we go along, iterating DOWN from `end` let tipsets = end - .chain(self.blockstore()) + .chain(self.db()) .take_while(|ts| ts.epoch() >= *epochs.start()); self.validate_tipsets(tipsets) diff --git a/src/state_manager/message_search.rs b/src/state_manager/message_search.rs index ac52b093ae6a..c8231a80c093 100644 --- a/src/state_manager/message_search.rs +++ b/src/state_manager/message_search.rs @@ -4,17 +4,13 @@ use super::*; use crate::blocks::TipsetKey; use crate::message::MessageRead as _; -use crate::utils::ShallowClone as _; use ahash::{HashMap, HashMapExt as _}; use anyhow::Context as _; use futures::{FutureExt, channel::oneshot, select}; use tokio::sync::{RwLock, broadcast::error::RecvError}; use tracing::warn; -impl StateManager -where - DB: Blockstore + Send + Sync + 'static, -{ +impl StateManager { /// Check if tipset had executed the message, by loading the receipt based /// on the index of the message in the block. fn tipset_executed_message( @@ -62,7 +58,7 @@ where } else { let block_header = tipset.block_headers().first(); crate::chain::get_parent_receipt( - self.blockstore(), + self.db(), block_header, index, ) @@ -150,7 +146,7 @@ where /// Returns a message receipt from a given tipset and message CID. pub fn get_receipt(&self, tipset: Tipset, msg: Cid) -> Result { - let m = crate::chain::get_chain_message(self.blockstore(), &msg) + let m = crate::chain::get_chain_message(self.db(), &msg) .map_err(|e| Error::Other(e.to_string()))?; let message_receipt = self.tipset_executed_message(&tipset, &m, true)?; if let Some(receipt) = message_receipt { @@ -171,7 +167,7 @@ where /// guarantees that the message has been on chain for at least /// confidence epochs without being reverted before returning. pub async fn wait_for_message( - self: &Arc, + &self, msg_cid: Cid, confidence: i64, look_back_limit: Option, @@ -179,7 +175,7 @@ where ) -> Result<(Option, Option), Error> { let mut head_changes_rx = self.cs.subscribe_head_changes(); let (sender, mut receiver) = oneshot::channel::<()>(); - let message = crate::chain::get_chain_message(self.blockstore(), &msg_cid) + let message = crate::chain::get_chain_message(self.db(), &msg_cid) .map_err(|err| Error::Other(format!("failed to load message {err:}")))?; let current_tipset = self.heaviest_tipset(); let maybe_message_receipt = @@ -210,7 +206,7 @@ where let reverts: Arc>> = Arc::new(RwLock::new(HashMap::new())); let block_revert = reverts.clone(); - let sm_cloned = Arc::clone(self); + let sm_cloned = self.shallow_clone(); // Wait for message to be included in head change. let mut subscriber_poll = tokio::task::spawn(async move { @@ -310,7 +306,7 @@ where allow_replaced: Option, ) -> Result, Error> { let from = from.unwrap_or_else(|| self.heaviest_tipset()); - let message = crate::chain::get_chain_message(self.blockstore(), &msg_cid) + let message = crate::chain::get_chain_message(self.db(), &msg_cid) .map_err(|err| Error::Other(format!("failed to load message {err}")))?; let current_tipset = self.heaviest_tipset(); let maybe_message_receipt = diff --git a/src/state_manager/message_simulation.rs b/src/state_manager/message_simulation.rs index 4f3c20ad8e71..637c73169793 100644 --- a/src/state_manager/message_simulation.rs +++ b/src/state_manager/message_simulation.rs @@ -4,7 +4,6 @@ use super::circulating_supply::GenesisInfo; use super::utils::structured; use super::*; -use crate::db::EthMappingsStore; use crate::interpreter::{ExecutionContext, IMPLICIT_MESSAGE_GAS_LIMIT, VM, VMTrace}; use crate::message::{MessageRead as _, MessageReadWrite as _, SignedMessage}; use crate::rpc::state::{ApiInvocResult, InvocResult, MessageGasCost}; @@ -12,26 +11,19 @@ use crate::shim::address::Protocol; use crate::shim::crypto::{Signature, SignatureType}; use crate::shim::executor::ApplyRet; use crate::shim::message::Message; -use crate::utils::ShallowClone as _; use fvm_shared4::crypto::signature::SECP_SIG_LEN; use std::time::Duration; use tracing::instrument; -impl StateManager -where - DB: Blockstore + Send + Sync + 'static, -{ +impl StateManager { #[instrument(skip(self, rand))] fn call_raw( &self, state_cid: Option, msg: &Message, - rand: ChainRand, + rand: ChainRand, tipset: &Tipset, - ) -> Result - where - DB: EthMappingsStore, - { + ) -> Result { let mut msg = msg.clone(); let state_cid = state_cid.unwrap_or(*tipset.parent_state()); @@ -58,7 +50,7 @@ where base_fee: tipset.block_headers().first().parent_base_fee.clone(), circ_supply: genesis_info.get_vm_circulating_supply( height, - self.blockstore(), + self.db(), &state_cid, )?, chain_config: self.chain_config().shallow_clone(), @@ -77,7 +69,7 @@ where // This is needed to get the correct nonce from the actor state to match the VM let state_cid = vm.flush()?; - let state = StateTree::new_from_root(self.blockstore_owned(), &state_cid)?; + let state = StateTree::new_from_root(self.db(), &state_cid)?; let from_actor = state .get_actor(&msg.from())? @@ -103,10 +95,7 @@ where /// runs the given message and returns its result without any persisted /// changes. - pub fn call(&self, message: &Message, tipset: Option) -> Result - where - DB: EthMappingsStore, - { + pub fn call(&self, message: &Message, tipset: Option) -> Result { let ts = tipset.unwrap_or_else(|| self.heaviest_tipset()); let chain_rand = self.chain_rand(ts.shallow_clone()); self.call_raw(None, message, chain_rand, &ts) @@ -119,24 +108,18 @@ where state_cid: Cid, message: &Message, tipset: Option, - ) -> Result - where - DB: EthMappingsStore, - { + ) -> Result { let ts = tipset.unwrap_or_else(|| self.cs.heaviest_tipset()); let chain_rand = self.chain_rand(ts.shallow_clone()); self.call_raw(Some(state_cid), message, chain_rand, &ts) } pub async fn apply_on_state_with_gas( - self: &Arc, + &self, tipset: Option, msg: Message, vm_flush: VMFlush, - ) -> anyhow::Result<(ApiInvocResult, Option)> - where - DB: EthMappingsStore, - { + ) -> anyhow::Result<(ApiInvocResult, Option)> { let ts = tipset.unwrap_or_else(|| self.heaviest_tipset()); let from_a = self.resolve_to_key_addr(&msg.from, &ts).await?; @@ -182,15 +165,12 @@ where /// Computes message on the given [Tipset] state, after applying other /// messages and returns the values computed in the VM. pub async fn call_with_gas( - self: &Arc, + &self, message: &mut ChainMessage, prior_messages: &[ChainMessage], tipset: Option, vm_flush: VMFlush, - ) -> Result<(InvocResult, ApplyRet, Duration, Option), Error> - where - DB: EthMappingsStore, - { + ) -> Result<(InvocResult, ApplyRet, Duration, Option), Error> { let ts = tipset.unwrap_or_else(|| self.heaviest_tipset()); let TipsetState { state_root, .. } = self .load_tipset_state(&ts) @@ -214,7 +194,7 @@ where base_fee: ts.block_headers().first().parent_base_fee.clone(), circ_supply: genesis_info.get_vm_circulating_supply( epoch, - self.blockstore(), + self.chain_index().db(), &state_root, )?, chain_config: self.chain_config().shallow_clone(), diff --git a/src/state_manager/mining.rs b/src/state_manager/mining.rs index a0af8f4dabc1..6e3498be8f49 100644 --- a/src/state_manager/mining.rs +++ b/src/state_manager/mining.rs @@ -4,7 +4,6 @@ use super::chain_rand::draw_randomness; use super::*; use crate::beacon::BeaconEntry; -use crate::db::EthMappingsStore; use crate::rpc::types::MiningBaseInfo; use crate::shim::randomness::Randomness; use crate::shim::runtime::Policy; @@ -13,10 +12,8 @@ use fil_actors_shared::v12::runtime::DomainSeparationTag; use fvm_ipld_encoding::to_vec; use num::BigInt; use num_traits::identities::Zero; -impl StateManager -where - DB: Blockstore + Send + Sync + 'static, -{ + +impl StateManager { /// Checks the eligibility of the miner. This is used in the validation that /// a block's miner has the requirements to mine a block. pub fn eligible_to_mine( @@ -41,17 +38,17 @@ where .get_actor(&Address::POWER_ACTOR, *base_tipset.parent_state())? .ok_or_else(|| Error::state("Power actor address could not be resolved"))?; - let power_state = power::State::load(self.blockstore(), actor.code, actor.state)?; + let power_state = power::State::load(self.db(), actor.code, actor.state)?; let actor = self .get_actor(address, *base_tipset.parent_state())? .ok_or_else(|| Error::state("Miner actor address could not be resolved"))?; - let miner_state = miner::State::load(self.blockstore(), actor.code, actor.state)?; + let miner_state = miner::State::load(self.db(), actor.code, actor.state)?; // Non-empty power claim. let claim = power_state - .miner_power(self.blockstore(), address)? + .miner_power(self.db(), address)? .ok_or_else(|| Error::Other("Could not get claim".to_string()))?; if claim.quality_adj_power <= BigInt::zero() { return Ok(false); @@ -63,7 +60,7 @@ where } // No active consensus faults. - let info = miner_state.info(self.blockstore())?; + let info = miner_state.info(self.db())?; if base_tipset.epoch() <= info.consensus_fault_elapsed { return Ok(false); } @@ -72,15 +69,12 @@ where } pub async fn miner_get_base_info( - self: &Arc, + &self, beacon_schedule: &BeaconSchedule, tipset: Tipset, addr: Address, epoch: ChainEpoch, - ) -> anyhow::Result> - where - DB: EthMappingsStore, - { + ) -> anyhow::Result> { let prev_beacon = self .chain_store() .chain_index() @@ -113,7 +107,7 @@ where return Ok(None); } - let miner_state = miner::State::load(self.blockstore(), actor.code, actor.state)?; + let miner_state = miner::State::load(self.db(), actor.code, actor.state)?; let addr_buf = to_vec(&addr)?; let rand = draw_randomness( @@ -139,7 +133,7 @@ where .get_power(&lb_state_root, Some(&addr))? .context("failed to get power")?; - let info = miner_state.info(self.blockstore())?; + let info = miner_state.info(self.db())?; let worker_key = self .resolve_to_deterministic_address(info.worker, &tipset) @@ -169,8 +163,8 @@ where let actor = self .get_actor(&Address::POWER_ACTOR, *ts.parent_state())? .ok_or_else(|| Error::state("Power actor address could not be resolved"))?; - let ps = power::State::load(self.blockstore(), actor.code, actor.state)?; + let ps = power::State::load(self.db(), actor.code, actor.state)?; - ps.miner_nominal_power_meets_consensus_minimum(policy, self.blockstore(), addr) + ps.miner_nominal_power_meets_consensus_minimum(policy, self.db(), addr) } } diff --git a/src/state_manager/mod.rs b/src/state_manager/mod.rs index 28f39447fa11..ffdaaf37c692 100644 --- a/src/state_manager/mod.rs +++ b/src/state_manager/mod.rs @@ -25,12 +25,13 @@ use crate::chain::{ ChainStore, index::{ChainIndex, ResolveNullTipset}, }; -use crate::db::EthMappingsStore; +use crate::db::DbImpl; use crate::interpreter::MessageCallbackCtx; use crate::interpreter::resolve_to_key_addr; use crate::lotus_json::{LotusJson, lotus_json_with_self}; use crate::message::ChainMessage; use crate::networks::ChainConfig; +use crate::prelude::*; use crate::rpc::types::SectorOnChainInfo; use crate::shim::actors::init::{self, State}; use crate::shim::actors::*; @@ -48,17 +49,14 @@ use crate::shim::{ version::NetworkVersion, }; use crate::state_manager::cache::TipsetStateCache; -use crate::utils::ShallowClone as _; use crate::utils::cache::SizeTrackingLruCache; use crate::utils::get_size::{GetSize, vec_heap_size_helper}; use anyhow::Context as _; use chain_rand::ChainRand; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; use nonzero_ext::nonzero; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use std::{num::NonZeroUsize, sync::Arc}; +use std::num::NonZeroUsize; use tracing::warn; const DEFAULT_TIPSET_CACHE_SIZE: NonZeroUsize = nonzero!(1024usize); @@ -165,9 +163,9 @@ lotus_json_with_self!(MarketBalance); /// handles chain data, to allow for interactions with the underlying state of /// the chain. The state manager not only allows interfacing with state, but /// also is used when performing state transitions. -pub struct StateManager { +pub struct StateManager { /// Chain store - cs: Arc>, + cs: ChainStore, /// This is a cache which indexes tipsets to their calculated state output (state root, receipt root). cache: TipsetStateCache, id_to_deterministic_address_cache: IdToAddressCache, @@ -175,6 +173,20 @@ pub struct StateManager { engine: Arc, } +impl ShallowClone for StateManager { + fn shallow_clone(&self) -> Self { + Self { + cs: self.cs.shallow_clone(), + cache: self.cache.shallow_clone(), + id_to_deterministic_address_cache: self + .id_to_deterministic_address_cache + .shallow_clone(), + beacon: self.beacon.shallow_clone(), + engine: self.engine.shallow_clone(), + } + } +} + #[allow(clippy::type_complexity)] pub const NO_CALLBACK: Option) -> anyhow::Result<()>> = None; @@ -186,18 +198,12 @@ pub enum VMFlush { Skip, } -impl StateManager -where - DB: Blockstore, -{ - pub fn new(cs: Arc>) -> anyhow::Result { +impl StateManager { + pub fn new(cs: ChainStore) -> anyhow::Result { Self::new_with_engine(cs, GLOBAL_MULTI_ENGINE.clone()) } - pub fn new_with_engine( - cs: Arc>, - engine: Arc, - ) -> anyhow::Result { + pub fn new_with_engine(cs: ChainStore, engine: Arc) -> anyhow::Result { let genesis = cs.genesis_block_header(); let beacon = Arc::new(cs.chain_config().get_beacon_schedule(genesis.timestamp)); @@ -222,25 +228,19 @@ where /// A valid head has /// - state tree in the blockstore /// - actor bundle version in the state tree that matches chain configuration - pub fn maybe_rewind_heaviest_tipset(&self) -> anyhow::Result<()> - where - DB: EthMappingsStore, - { + pub fn maybe_rewind_heaviest_tipset(&self) -> anyhow::Result<()> { while self.maybe_rewind_heaviest_tipset_once()? {} Ok(()) } - fn maybe_rewind_heaviest_tipset_once(&self) -> anyhow::Result - where - DB: EthMappingsStore, - { + fn maybe_rewind_heaviest_tipset_once(&self) -> anyhow::Result { let head = self.heaviest_tipset(); if let Some(info) = self .chain_config() .network_height_with_actor_bundle(head.epoch()) { let expected_height_info = info.info; - let expected_bundle = info.manifest(self.blockstore())?; + let expected_bundle = info.manifest(self.db())?; let expected_bundle_metadata = expected_bundle.metadata()?; let state = self.get_state_tree(head.parent_state())?; let bundle_metadata = state.get_actor_bundle_metadata()?; @@ -258,7 +258,7 @@ where tracing::warn!( "rewinding chain head from {current_epoch} to {target_epoch}, actor bundle: {bundle_version}, expected: {expected_bundle_version}" ); - if self.blockstore().has(target_head.parent_state())? { + if self.db().has(target_head.parent_state())? { self.chain_store().set_heaviest_tipset(target_head)?; return Ok(true); } else { @@ -283,8 +283,8 @@ where } /// Gets the state tree - pub fn get_state_tree(&self, state_cid: &Cid) -> anyhow::Result> { - StateTree::new_from_root(self.blockstore_owned(), state_cid) + pub fn get_state_tree(&self, state_cid: &Cid) -> anyhow::Result> { + StateTree::new_from_root(self.chain_index().db(), state_cid) } /// Gets actor from given [`Cid`], if it exists. @@ -321,21 +321,21 @@ where } /// Returns a reference to the state manager's [`Blockstore`]. - pub fn blockstore(&self) -> &Arc { - self.cs.blockstore() + pub fn db(&self) -> &DbImpl { + self.cs.db() } - pub fn blockstore_owned(&self) -> Arc { - self.blockstore().clone() + pub fn db_owned(&self) -> DbImpl { + self.cs.db_owned() } /// Returns reference to the state manager's [`ChainStore`]. - pub fn chain_store(&self) -> &Arc> { + pub fn chain_store(&self) -> &ChainStore { &self.cs } /// Returns reference to the state manager's [`ChainIndex`]. - pub fn chain_index(&self) -> &ChainIndex { + pub fn chain_index(&self) -> &ChainIndex { self.cs.chain_index() } @@ -344,7 +344,7 @@ where self.cs.chain_config() } - pub fn chain_rand(&self, tipset: Tipset) -> ChainRand { + pub fn chain_rand(&self, tipset: Tipset) -> ChainRand { ChainRand::new( self.chain_config().shallow_clone(), tipset, @@ -361,11 +361,9 @@ where let init_act = self .get_actor(&init::ADDRESS.into(), state_cid)? .ok_or_else(|| Error::state("Init actor address could not be resolved"))?; - Ok( - State::load(self.blockstore(), init_act.code, init_act.state)? - .into_network_name() - .into(), - ) + Ok(State::load(self.db(), init_act.code, init_act.state)? + .into_network_name() + .into()) } /// Returns true if miner has been slashed or is considered invalid. @@ -374,18 +372,17 @@ where .get_actor(&Address::POWER_ACTOR, *state_cid)? .ok_or_else(|| Error::state("Power actor address could not be resolved"))?; - let spas = power::State::load(self.blockstore(), actor.code, actor.state)?; + let spas = power::State::load(self.db(), actor.code, actor.state)?; - Ok(spas.miner_power(self.blockstore(), addr)?.is_none()) + Ok(spas.miner_power(self.db(), addr)?.is_none()) } /// Returns raw work address of a miner given the state root. pub fn get_miner_work_addr(&self, state_cid: Cid, addr: &Address) -> Result { - let state = - StateTree::new_from_root(self.blockstore_owned(), &state_cid).map_err(Error::other)?; + let state = StateTree::new_from_root(self.db(), &state_cid).map_err(Error::other)?; let ms: miner::State = state.get_actor_state_from_address(addr)?; - let info = ms.info(self.blockstore()).map_err(|e| e.to_string())?; - let addr = resolve_to_key_addr(&state, self.blockstore(), &info.worker())?; + let info = ms.info(self.db()).map_err(|e| e.to_string())?; + let addr = resolve_to_key_addr(&state, self.db(), &info.worker())?; Ok(addr) } @@ -400,18 +397,18 @@ where .get_actor(&Address::POWER_ACTOR, *state_cid)? .ok_or_else(|| Error::state("Power actor address could not be resolved"))?; - let spas = power::State::load(self.blockstore(), actor.code, actor.state)?; + let spas = power::State::load(self.db(), actor.code, actor.state)?; let t_pow = spas.total_power(); if let Some(maddr) = addr { let m_pow = spas - .miner_power(self.blockstore(), maddr)? + .miner_power(self.db(), maddr)? .ok_or_else(|| Error::state(format!("Miner for address {maddr} not found")))?; let min_pow = spas.miner_nominal_power_meets_consensus_minimum( &self.chain_config().policy, - self.blockstore(), + self.db(), maddr, )?; if min_pow { @@ -431,7 +428,7 @@ where let actor = self .get_actor(addr, *ts.parent_state())? .ok_or_else(|| Error::state(format!("Miner actor {addr} not found")))?; - let state = miner::State::load(self.blockstore(), actor.code, actor.state)?; - state.load_sectors_ext(self.blockstore(), None) + let state = miner::State::load(self.db(), actor.code, actor.state)?; + state.load_sectors_ext(self.db(), None) } } diff --git a/src/state_manager/state_computation.rs b/src/state_manager/state_computation.rs index 6e03070288db..b69de7159e4c 100644 --- a/src/state_manager/state_computation.rs +++ b/src/state_manager/state_computation.rs @@ -3,22 +3,17 @@ use super::circulating_supply::GenesisInfo; use super::*; -use crate::db::EthMappingsStore; use crate::interpreter::{BlockMessages, ExecutionContext, VM, VMTrace}; +use crate::prelude::*; use crate::shim::message::Message; use crate::state_migration::run_state_migrations; -use crate::utils::ShallowClone as _; -use anyhow::{Context as _, bail, ensure}; +use anyhow::{bail, ensure}; use fil_actors_shared::fvm_ipld_amt::{Amt, Amtv0}; -use itertools::Itertools as _; use tracing::{error, info, instrument}; -impl StateManager -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +impl StateManager { /// Load the state of a tipset, including state root, message receipts - pub async fn load_tipset_state(self: &Arc, ts: &Tipset) -> anyhow::Result { + pub async fn load_tipset_state(&self, ts: &Tipset) -> anyhow::Result { if let Some(state) = self.cache.get_map(ts.key(), |et| et.into()) { Ok(state) } else { @@ -33,15 +28,12 @@ where } /// Load an executed tipset, including state root, message receipts and events with caching. - pub async fn load_executed_tipset( - self: &Arc, - ts: &Tipset, - ) -> anyhow::Result { + pub async fn load_executed_tipset(&self, ts: &Tipset) -> anyhow::Result { // validate the existence of state trees for post-chain-head-epoch tipsets in case chain head is reset(e.g. manually or via GC). if ts.epoch() >= self.heaviest_tipset().epoch() && let Some(cached) = self.cache.get(ts.key()) { - if StateTree::new_from_root(self.blockstore_owned(), &cached.state_root).is_ok() { + if StateTree::new_from_root(self.db(), &cached.state_root).is_ok() { return Ok(cached); } else { self.cache.remove(ts.key()); @@ -57,7 +49,7 @@ where } async fn load_executed_tipset_inner( - self: &Arc, + &self, msg_ts: &Tipset, // when `msg_ts` is the current head, `receipt_ts` is `None` receipt_ts: Option<&Tipset>, @@ -71,7 +63,7 @@ where let mut recomputed = false; let (state_root, receipt_root, receipts) = match receipt_ts.and_then(|ts| { let receipt_root = *ts.parent_message_receipts(); - Receipt::get_receipts(self.cs.blockstore(), receipt_root) + Receipt::get_receipts(self.cs.db(), receipt_root) .ok() .map(|r| (*ts.parent_state(), receipt_root, r)) }) { @@ -84,7 +76,7 @@ where ( state_output.state_root, state_output.receipt_root, - Receipt::get_receipts(self.cs.blockstore(), state_output.receipt_root)?, + Receipt::get_receipts(self.cs.db(), state_output.receipt_root)?, ) } }; @@ -99,22 +91,20 @@ where let mut executed_messages = Vec::with_capacity(messages.len()); for (message, receipt) in messages.iter().cloned().zip(receipts) { let events = if let Some(events_root) = receipt.events_root() { - Some( - match StampedEvent::get_events(self.cs.blockstore(), &events_root) { - Ok(events) => events, - Err(e) if recomputed => return Err(e), - Err(_) => { - self.compute_tipset_state( - msg_ts.shallow_clone(), - NO_CALLBACK, - VMTrace::NotTraced, - ) - .await?; - recomputed = true; - StampedEvent::get_events(self.cs.blockstore(), &events_root)? - } - }, - ) + Some(match StampedEvent::get_events(self.cs.db(), &events_root) { + Ok(events) => events, + Err(e) if recomputed => return Err(e), + Err(_) => { + self.compute_tipset_state( + msg_ts.shallow_clone(), + NO_CALLBACK, + VMTrace::NotTraced, + ) + .await?; + recomputed = true; + StampedEvent::get_events(self.cs.db(), &events_root)? + } + }) } else { None }; @@ -153,12 +143,12 @@ where /// For details, see the documentation for [`apply_block_messages`]. /// pub async fn compute_tipset_state( - self: &Arc, + &self, tipset: Tipset, callback: Option) -> anyhow::Result<()> + Send + 'static>, enable_tracing: VMTrace, ) -> Result { - let this = Arc::clone(self); + let this = self.shallow_clone(); tokio::task::spawn_blocking(move || { this.compute_tipset_state_blocking(tipset, callback, enable_tracing) }) @@ -200,14 +190,14 @@ where #[instrument(skip_all)] pub async fn compute_state( - self: &Arc, + &self, height: ChainEpoch, messages: Vec, tipset: Tipset, callback: Option) -> anyhow::Result<()> + Send + 'static>, enable_tracing: VMTrace, ) -> Result { - let this = Arc::clone(self); + let this = self.shallow_clone(); tokio::task::spawn_blocking(move || { this.compute_state_blocking(height, messages, tipset, callback, enable_tracing) }) @@ -239,16 +229,15 @@ where } } -pub fn validate_tipsets( +pub fn validate_tipsets( genesis_timestamp: u64, - chain_index: &ChainIndex, + chain_index: &ChainIndex, chain_config: &Arc, beacon: &Arc, engine: &MultiEngine, tipsets: T, ) -> anyhow::Result<()> where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, T: Iterator + Send, { // Validate one tipset at a time. Parallelizing the outer loop across tipsets @@ -293,18 +282,18 @@ where /// /// Encapsulates randomness source, genesis info, VM construction, /// null-epoch cron handling, and state migrations. -pub(in crate::state_manager) struct TipsetExecutor<'a, DB: Blockstore + Send + Sync + 'static> { +pub(in crate::state_manager) struct TipsetExecutor<'a> { tipset: Tipset, - rand: ChainRand, + rand: ChainRand, chain_config: Arc, - chain_index: ChainIndex, + chain_index: ChainIndex, genesis_info: GenesisInfo, engine: &'a MultiEngine, } -impl<'a, DB: Blockstore + Send + Sync + 'static> TipsetExecutor<'a, DB> { +impl<'a> TipsetExecutor<'a> { pub(in crate::state_manager) fn new( - chain_index: ChainIndex, + chain_index: ChainIndex, chain_config: Arc, beacon: Arc, engine: &'a MultiEngine, @@ -333,10 +322,7 @@ impl<'a, DB: Blockstore + Send + Sync + 'static> TipsetExecutor<'a, DB> { epoch: ChainEpoch, timestamp: u64, trace: VMTrace, - ) -> anyhow::Result> - where - DB: EthMappingsStore, - { + ) -> anyhow::Result { let circ_supply = self.genesis_info.get_vm_circulating_supply( epoch, self.chain_index.db(), @@ -368,7 +354,6 @@ impl<'a, DB: Blockstore + Send + Sync + 'static> TipsetExecutor<'a, DB> { cron_callback: &mut Option, ) -> anyhow::Result<(Cid, ChainEpoch, Vec)> where - DB: EthMappingsStore, F: FnMut(MessageCallbackCtx<'_>) -> anyhow::Result<()>, { use crate::shim::clock::EPOCH_DURATION_SECONDS; @@ -485,19 +470,16 @@ impl<'a, DB: Blockstore + Send + Sync + 'static> TipsetExecutor<'a, DB> { /// Scanning the blockchain to find past tipsets and state-trees may be slow. /// The `ChainStore` caches recent tipsets to make these scans faster. #[allow(clippy::too_many_arguments)] -pub fn apply_block_messages( +pub fn apply_block_messages( genesis_timestamp: u64, - chain_index: ChainIndex, + chain_index: ChainIndex, chain_config: Arc, beacon: Arc, engine: &MultiEngine, tipset: Tipset, mut callback: Option) -> anyhow::Result<()>>, enable_tracing: VMTrace, -) -> anyhow::Result -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +) -> anyhow::Result { // This function will: // 1. handle the genesis block as a special case // 2. run 'cron' for any null-tipsets between the current tipset and our parent tipset @@ -595,21 +577,18 @@ where } #[allow(clippy::too_many_arguments)] -pub(in crate::state_manager) fn compute_state( +pub(in crate::state_manager) fn compute_state( _height: ChainEpoch, messages: Vec, tipset: Tipset, genesis_timestamp: u64, - chain_index: ChainIndex, + chain_index: ChainIndex, chain_config: Arc, beacon: Arc, engine: &MultiEngine, callback: Option) -> anyhow::Result<()>>, enable_tracing: VMTrace, -) -> anyhow::Result -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +) -> anyhow::Result { if !messages.is_empty() { anyhow::bail!("Applying messages is not yet implemented."); } diff --git a/src/state_manager/utils.rs b/src/state_manager/utils.rs index 8881732e7ff3..d6528a7eb767 100644 --- a/src/state_manager/utils.rs +++ b/src/state_manager/utils.rs @@ -16,13 +16,9 @@ use crate::utils::encoding::prover_id_from_u64; use cid::Cid; use fil_actors_shared::filecoin_proofs_api::post; use fil_actors_shared::fvm_ipld_bitfield::BitField; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::bytes_32; -impl StateManager -where - DB: Blockstore, -{ +impl StateManager { /// Retrieves and generates a vector of sector info for the winning `PoSt` /// verification. pub fn get_sectors_for_winning_post( @@ -32,12 +28,12 @@ where miner_address: &Address, rand: Randomness, ) -> anyhow::Result> { - let store = self.blockstore(); + let store = self.db(); let actor = self .get_actor(miner_address, *st)? .ok_or_else(|| Error::state("Miner actor address could not be resolved"))?; - let mas = miner::State::load(self.blockstore(), actor.code, actor.state)?; + let mas = miner::State::load(self.db(), actor.code, actor.state)?; let proving_sectors = { let mut proving_sectors = BitField::new(); @@ -271,7 +267,7 @@ pub mod state_compute { pub async fn prepare_state_compute( chain: &NetworkChain, snapshot: &Path, - ) -> anyhow::Result<(Arc>, Tipset, Tipset)> { + ) -> anyhow::Result<(StateManager, Tipset, Tipset)> { let snap_car = AnyCar::try_from(snapshot)?; let ts_next = snap_car.heaviest_tipset()?; let db = Arc::new(ManyCar::new(MemoryDB::default()).with_read_only(snap_car)?); @@ -280,28 +276,22 @@ pub mod state_compute { let genesis_header = read_genesis_header(None, chain_config.genesis_bytes(&db).await?.as_deref(), &db) .await?; - let chain_store = Arc::new(ChainStore::new( - db.clone(), - db.clone(), - db.clone(), - chain_config, - genesis_header, - )?); - let state_manager = Arc::new(StateManager::new(chain_store.clone())?); + let chain_store = ChainStore::new(db, chain_config, genesis_header)?; + let state_manager = StateManager::new(chain_store)?; Ok((state_manager, ts, ts_next)) } pub async fn prepare_state_validate( chain: &NetworkChain, snapshot: &Path, - ) -> anyhow::Result<(Arc>, FullTipset)> { + ) -> anyhow::Result<(StateManager, FullTipset)> { let (sm, _, ts) = prepare_state_compute(chain, snapshot).await?; let fts = load_full_tipset(sm.chain_store(), ts.key())?; Ok((sm, fts)) } pub async fn state_compute( - state_manager: &Arc>, + state_manager: &StateManager, ts: Tipset, ts_next: &Tipset, ) -> anyhow::Result<()> { diff --git a/src/state_migration/mod.rs b/src/state_migration/mod.rs index 0d1eb5ab7b3f..7b807c60b227 100644 --- a/src/state_migration/mod.rs +++ b/src/state_migration/mod.rs @@ -1,17 +1,13 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use std::sync::{ - Arc, - atomic::{self, AtomicBool}, -}; +use std::sync::atomic::{self, AtomicBool}; use crate::db::BlockstoreWithWriteBuffer; use crate::networks::{ChainConfig, Height, NetworkChain}; +use crate::prelude::*; use crate::shim::clock::ChainEpoch; use crate::shim::state_tree::StateRoot; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::CborStore; pub(in crate::state_migration) mod common; @@ -31,11 +27,11 @@ mod nv27; mod nv28; mod type_migrations; -type RunMigration = fn(&ChainConfig, &Arc, &Cid, ChainEpoch) -> anyhow::Result; +type RunMigration = fn(&ChainConfig, &DB, &Cid, ChainEpoch) -> anyhow::Result; pub fn get_migrations(chain: &NetworkChain) -> Vec<(Height, RunMigration)> where - DB: Blockstore + Send + Sync, + DB: Blockstore + ShallowClone + Send + Sync, { match chain { NetworkChain::Mainnet => { @@ -94,11 +90,11 @@ where pub fn run_state_migrations( epoch: ChainEpoch, chain_config: &ChainConfig, - db: &Arc, + db: &DB, parent_state: &Cid, ) -> anyhow::Result> where - DB: Blockstore + Send + Sync, + DB: Blockstore + ShallowClone + Send + Sync, { // ~10MB RAM per 10k buffer let db_write_buffer = match std::env::var("FOREST_STATE_MIGRATION_DB_WRITE_BUFFER") { @@ -130,7 +126,7 @@ where tracing::info!("Running {height} migration at epoch {epoch}"); let start_time = std::time::Instant::now(); let db = Arc::new(BlockstoreWithWriteBuffer::new_with_capacity( - db.clone(), + db.shallow_clone(), db_write_buffer, )); let new_state = migrate(chain_config, &db, parent_state, epoch)?; diff --git a/src/state_migration/nv17/migration.rs b/src/state_migration/nv17/migration.rs index 65eb857cb1a9..fe1b2308fc5f 100644 --- a/src/state_migration/nv17/migration.rs +++ b/src/state_migration/nv17/migration.rs @@ -1,9 +1,8 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use std::sync::Arc; - use crate::networks::{ChainConfig, Height, NetworkChain}; +use crate::prelude::*; use crate::shim::{ address::Address, clock::ChainEpoch, @@ -12,8 +11,6 @@ use crate::shim::{ }; use crate::utils::db::CborStoreExt as _; use anyhow::anyhow; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::CborStore as _; use super::super::common::{ @@ -25,10 +22,10 @@ use super::{ verifier::Verifier, verifreg_market::VerifregMarketPostMigrator, }; -impl StateMigration { +impl StateMigration { pub fn add_nv17_migrations( &mut self, - store: &Arc, + store: &BS, actors_in: &mut StateTree, new_manifest: &BuiltinActorManifest, prior_epoch: ChainEpoch, @@ -124,12 +121,12 @@ impl StateMigration { /// Runs the migration for `NV17`. Returns the new state root. pub fn run_migration( chain_config: &ChainConfig, - blockstore: &Arc, + blockstore: &DB, state: &Cid, epoch: ChainEpoch, ) -> anyhow::Result where - DB: Blockstore + Send + Sync, + DB: Blockstore + ShallowClone + Send + Sync, { let new_manifest_cid = chain_config .height_infos @@ -148,12 +145,12 @@ where let new_manifest = BuiltinActorManifest::load_manifest(blockstore, new_manifest_cid)?; - let mut actors_in = StateTree::new_from_root(blockstore.clone(), state)?; + let mut actors_in = StateTree::new_from_root(blockstore, state)?; // Add migration specification verification let verifier = Arc::new(Verifier::default()); - let mut migration = StateMigration::::new(Some(verifier)); + let mut migration = StateMigration::new(Some(verifier)); migration.add_nv17_migrations( blockstore, &mut actors_in, @@ -162,7 +159,7 @@ where chain_config.network.clone(), )?; - let actors_out = StateTree::new(blockstore.clone(), StateTreeVersion::V4)?; + let actors_out = StateTree::new(blockstore, StateTreeVersion::V4)?; let new_state = migration.migrate_state_tree(blockstore, epoch, actors_in, actors_out)?; diff --git a/src/state_migration/nv17/miner.rs b/src/state_migration/nv17/miner.rs index f4fc39fc0ba5..a37fb4817638 100644 --- a/src/state_migration/nv17/miner.rs +++ b/src/state_migration/nv17/miner.rs @@ -4,26 +4,23 @@ //! This module contains the migration logic for the `NV17` upgrade for the miner //! actor. -use std::sync::Arc; - +use super::super::common::{ + ActorMigration, ActorMigrationInput, ActorMigrationOutput, TypeMigration, TypeMigrator, +}; use crate::networks::NetworkChain; +use crate::prelude::*; use crate::shim::{address::Address, piece::PieceInfo}; use crate::utils::db::CborStoreExt; use crate::{make_calibnet_policy, make_mainnet_policy}; use ahash::HashMap; use anyhow::Context as _; -use cid::{Cid, multibase::Base}; +use cid::multibase::Base; use fil_actor_miner_state::{ v8::State as MinerStateOld, v9::{State as MinerStateNew, util::sector_key}, }; use fil_actors_shared::abi::commp::compute_unsealed_sector_cid_v2; use fil_actors_shared::fvm_ipld_amt; -use fvm_ipld_blockstore::Blockstore; - -use super::super::common::{ - ActorMigration, ActorMigrationInput, ActorMigrationOutput, TypeMigration, TypeMigrator, -}; pub struct MinerMigrator { chain: NetworkChain, @@ -37,12 +34,12 @@ pub struct MinerMigrator { pub(super) fn miner_migrator( out_code: Cid, - store: &Arc, + store: &BS, market_proposals: Cid, chain: NetworkChain, ) -> anyhow::Result + Send + Sync>> where - BS: Blockstore + Send + Sync, + BS: Blockstore + ShallowClone + Send + Sync, { let empty_deadline_v8: fil_actor_miner_state::v8::Deadline = fil_actor_miner_state::v8::Deadline::new(store)?; @@ -654,8 +651,10 @@ mod tests { ); } - fn make_input_tree(store: &Arc) -> (StateTree, BuiltinActorManifest) { - let mut tree = StateTree::new(store.clone(), StateTreeVersion::V4).unwrap(); + fn make_input_tree( + store: &BS, + ) -> (StateTree, BuiltinActorManifest) { + let mut tree = StateTree::new(store, StateTreeVersion::V4).unwrap(); let (_manifest_cid, manifest) = make_test_manifest(&store, "fil/8/"); let account_cid = manifest.get(BuiltinActor::Account).unwrap(); diff --git a/src/state_migration/nv17/verifreg_market.rs b/src/state_migration/nv17/verifreg_market.rs index bafc4ac464f3..d89ac0a14197 100644 --- a/src/state_migration/nv17/verifreg_market.rs +++ b/src/state_migration/nv17/verifreg_market.rs @@ -4,6 +4,8 @@ //! This module contains the migration logic for the `NV17` upgrade for the `verifreg` and `market` //! actor. +use super::super::ChainEpoch; +use super::super::common::PostMigrator; use crate::shim::{ address::Address, deal::DealID, @@ -16,9 +18,6 @@ use cid::Cid; use fil_actors_shared::fvm_ipld_hamt::BytesKey; use fvm_ipld_blockstore::Blockstore; -use super::super::ChainEpoch; -use super::super::common::PostMigrator; - pub(super) struct VerifregMarketPostMigrator { pub prior_epoch: ChainEpoch, pub init_state_v8: fil_actor_init_state::v8::State, diff --git a/src/state_migration/nv18/eam.rs b/src/state_migration/nv18/eam.rs index 16da6868ec54..ab546fbb3e39 100644 --- a/src/state_migration/nv18/eam.rs +++ b/src/state_migration/nv18/eam.rs @@ -1,18 +1,16 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT +use super::SystemStateNew; use crate::shim::{ address::Address, machine::{BuiltinActor, BuiltinActorManifest}, state_tree::{ActorState, StateTree}, }; +use crate::state_migration::common::PostMigrator; use crate::utils::db::CborStoreExt as _; use fvm_ipld_blockstore::Blockstore; -use crate::state_migration::common::PostMigrator; - -use super::SystemStateNew; - pub struct EamPostMigrator; impl PostMigrator for EamPostMigrator { diff --git a/src/state_migration/nv18/migration.rs b/src/state_migration/nv18/migration.rs index 36926e714d75..a6343867bbe0 100644 --- a/src/state_migration/nv18/migration.rs +++ b/src/state_migration/nv18/migration.rs @@ -1,33 +1,29 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use std::sync::Arc; - +use super::{ + SystemStateOld, eam::EamPostMigrator, eth_account::EthAccountPostMigrator, init, system, + verifier::Verifier, +}; use crate::networks::{ChainConfig, Height}; +use crate::prelude::*; use crate::shim::machine::BuiltinActorManifest; use crate::shim::{ address::Address, clock::ChainEpoch, state_tree::{StateTree, StateTreeVersion}, }; +use crate::state_migration::common::{StateMigration, migrators::nil_migrator}; use anyhow::anyhow; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::CborStore as _; - -use super::{ - SystemStateOld, eam::EamPostMigrator, eth_account::EthAccountPostMigrator, init, system, - verifier::Verifier, -}; -use crate::state_migration::common::{StateMigration, migrators::nil_migrator}; -impl StateMigration { +impl StateMigration { pub fn add_nv18_migrations( &mut self, - store: Arc, + store: BS, state: &Cid, new_manifest: &Cid, ) -> anyhow::Result<()> { - let state_tree = StateTree::new_from_root(store.clone(), state)?; + let state_tree = StateTree::new_from_root(&store, state)?; let system_actor = state_tree .get_actor(&Address::new_id(0))? .ok_or_else(|| anyhow!("system actor not found"))?; @@ -67,12 +63,12 @@ impl StateMigration { /// Runs the migration for `NV18`. Returns the new state root. pub fn run_migration( chain_config: &ChainConfig, - blockstore: &Arc, + blockstore: &DB, state: &Cid, epoch: ChainEpoch, ) -> anyhow::Result where - DB: Blockstore + Send + Sync, + DB: Blockstore + ShallowClone + Send + Sync, { let new_manifest_cid = chain_config .height_infos @@ -92,11 +88,11 @@ where // Add migration specification verification let verifier = Arc::new(Verifier::default()); - let mut migration = StateMigration::::new(Some(verifier)); - migration.add_nv18_migrations(blockstore.clone(), state, new_manifest_cid)?; + let mut migration = StateMigration::new(Some(verifier)); + migration.add_nv18_migrations(blockstore.shallow_clone(), state, new_manifest_cid)?; - let actors_in = StateTree::new_from_root(blockstore.clone(), state)?; - let actors_out = StateTree::new(blockstore.clone(), StateTreeVersion::V5)?; + let actors_in = StateTree::new_from_root(blockstore, state)?; + let actors_out = StateTree::new(blockstore, StateTreeVersion::V5)?; let new_state = migration.migrate_state_tree(blockstore, epoch, actors_in, actors_out)?; Ok(new_state) diff --git a/src/state_migration/nv19/migration.rs b/src/state_migration/nv19/migration.rs index 716459a38ddd..c634af76baae 100644 --- a/src/state_migration/nv19/migration.rs +++ b/src/state_migration/nv19/migration.rs @@ -1,31 +1,27 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use std::sync::Arc; - +use super::{SystemStateOld, miner, power, system, verifier::Verifier}; use crate::networks::{ChainConfig, Height}; +use crate::prelude::*; use crate::shim::{ address::Address, clock::ChainEpoch, machine::{BuiltinActor, BuiltinActorManifest}, state_tree::{StateTree, StateTreeVersion}, }; +use crate::state_migration::common::{StateMigration, migrators::nil_migrator}; use anyhow::anyhow; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::CborStore as _; -use super::{SystemStateOld, miner, power, system, verifier::Verifier}; -use crate::state_migration::common::{StateMigration, migrators::nil_migrator}; - -impl StateMigration { +impl StateMigration { pub fn add_nv19_migrations( &mut self, - store: &Arc, + store: &BS, state: &Cid, new_manifest: &Cid, ) -> anyhow::Result<()> { - let state_tree = StateTree::new_from_root(store.clone(), state)?; + let state_tree = StateTree::new_from_root(store, state)?; let system_actor = state_tree .get_actor(&Address::new_id(0))? .ok_or_else(|| anyhow!("system actor not found"))?; @@ -66,12 +62,12 @@ impl StateMigration { /// Runs the migration for `NV19`. Returns the new state root. pub fn run_migration( chain_config: &ChainConfig, - blockstore: &Arc, + blockstore: &DB, state: &Cid, epoch: ChainEpoch, ) -> anyhow::Result where - DB: Blockstore + Send + Sync, + DB: Blockstore + ShallowClone + Send + Sync, { let new_manifest_cid = chain_config .height_infos @@ -94,8 +90,8 @@ where let mut migration = StateMigration::::new(Some(verifier)); migration.add_nv19_migrations(blockstore, state, new_manifest_cid)?; - let actors_in = StateTree::new_from_root(blockstore.clone(), state)?; - let actors_out = StateTree::new(blockstore.clone(), StateTreeVersion::V5)?; + let actors_in = StateTree::new_from_root(blockstore, state)?; + let actors_out = StateTree::new(blockstore, StateTreeVersion::V5)?; let new_state = migration.migrate_state_tree(blockstore, epoch, actors_in, actors_out)?; Ok(new_state) diff --git a/src/state_migration/nv21/migration.rs b/src/state_migration/nv21/migration.rs index d39da54f6de5..62d6cc16142c 100644 --- a/src/state_migration/nv21/migration.rs +++ b/src/state_migration/nv21/migration.rs @@ -1,10 +1,9 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use std::sync::Arc; - use super::{SystemStateOld, miner, system, verifier::Verifier}; use crate::networks::{ChainConfig, Height, NetworkChain}; +use crate::prelude::*; use crate::shim::{ address::Address, clock::ChainEpoch, @@ -15,19 +14,16 @@ use crate::shim::{ use crate::state_migration::common::{StateMigration, migrators::nil_migrator}; use crate::utils::db::CborStoreExt as _; use crate::{make_butterfly_policy, make_calibnet_policy, make_devnet_policy, make_mainnet_policy}; -use anyhow::Context as _; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; -impl StateMigration { +impl StateMigration { pub fn add_nv21_migrations( &mut self, - store: &Arc, + store: &BS, state: &Cid, new_manifest: &BuiltinActorManifest, chain_config: &ChainConfig, ) -> anyhow::Result<()> { - let state_tree = StateTree::new_from_root(store.clone(), state)?; + let state_tree = StateTree::new_from_root(store, state)?; let system_actor = state_tree.get_required_actor(&Address::new_id(0))?; let system_actor_state = store.get_cbor_required::(&system_actor.state)?; @@ -69,12 +65,12 @@ impl StateMigration { /// Runs the migration for `NV21`. Returns the new state root. pub fn run_migration( chain_config: &ChainConfig, - blockstore: &Arc, + blockstore: &DB, state: &Cid, epoch: ChainEpoch, ) -> anyhow::Result where - DB: Blockstore + Send + Sync, + DB: Blockstore + ShallowClone + Send + Sync, { let new_manifest_cid = chain_config .height_infos @@ -95,8 +91,8 @@ where let mut migration = StateMigration::::new(Some(verifier)); migration.add_nv21_migrations(blockstore, state, &new_manifest, chain_config)?; - let actors_in = StateTree::new_from_root(blockstore.clone(), state)?; - let actors_out = StateTree::new(blockstore.clone(), StateTreeVersion::V5)?; + let actors_in = StateTree::new_from_root(blockstore, state)?; + let actors_out = StateTree::new(blockstore, StateTreeVersion::V5)?; let new_state = migration.migrate_state_tree(blockstore, epoch, actors_in, actors_out)?; Ok(new_state) diff --git a/src/state_migration/nv21/miner.rs b/src/state_migration/nv21/miner.rs index ca50b37f124b..198c4f3a9c85 100644 --- a/src/state_migration/nv21/miner.rs +++ b/src/state_migration/nv21/miner.rs @@ -4,6 +4,7 @@ //! This module contains the migration logic for the `NV21` upgrade for the //! Miner actor. +use crate::prelude::*; use crate::shim::econ::TokenAmount; use crate::state_migration::common::{ ActorMigration, ActorMigrationInput, ActorMigrationOutput, TypeMigration, TypeMigrator, @@ -11,8 +12,7 @@ use crate::state_migration::common::{ use crate::{ shim::address::Address, state_migration::common::MigrationCache, utils::db::CborStoreExt, }; -use anyhow::Context as _; -use cid::{Cid, multibase::Base}; +use cid::multibase::Base; use fil_actor_miner_state::{ v11::Deadline as DeadlineOld, v11::Deadlines as DeadlinesOld, v11::State as MinerStateOld, v12::Deadline as DeadlineNew, v12::Deadlines as DeadlinesNew, v12::State as MinerStateNew, @@ -20,8 +20,6 @@ use fil_actor_miner_state::{ use fil_actors_shared::fvm_ipld_amt; use fil_actors_shared::v11::{Array as ArrayOld, runtime::Policy as PolicyOld}; use fil_actors_shared::v12::{Array as ArrayNew, runtime::Policy as PolicyNew}; -use fvm_ipld_blockstore::Blockstore; -use std::sync::Arc; pub struct MinerMigrator { empty_deadline_v11: Cid, @@ -35,7 +33,7 @@ pub struct MinerMigrator { pub(in crate::state_migration) fn miner_migrator( policy_old: &PolicyOld, policy_new: &PolicyNew, - store: &Arc, + store: &BS, out_cid: Cid, ) -> anyhow::Result + Send + Sync>> { let empty_deadline_v11 = DeadlineOld::new(store)?; @@ -366,7 +364,7 @@ mod tests { assert_eq!(new_state_cid, new_state_cid2); - let new_state_tree = StateTree::new_from_root(store.clone(), &new_state_cid).unwrap(); + let new_state_tree = StateTree::new_from_root(&store, &new_state_cid).unwrap(); let new_miner_state_cid = new_state_tree.get_required_actor(&addr).unwrap().state; let new_miner_state: fil_actor_miner_state::v12::State = store.get_cbor_required(&new_miner_state_cid).unwrap(); @@ -394,8 +392,10 @@ mod tests { .unwrap(); } - fn make_input_tree(store: &Arc) -> (StateTree, BuiltinActorManifest) { - let mut tree = StateTree::new(store.clone(), StateTreeVersion::V5).unwrap(); + fn make_input_tree( + store: &BS, + ) -> (StateTree, BuiltinActorManifest) { + let mut tree = StateTree::new(store, StateTreeVersion::V5).unwrap(); let (_manifest_cid, manifest) = make_test_manifest(&store, "fil/11/"); let system_cid = manifest.get_system(); diff --git a/src/state_migration/nv21fix/migration.rs b/src/state_migration/nv21fix/migration.rs index 4585a4ddc701..5a958e242010 100644 --- a/src/state_migration/nv21fix/migration.rs +++ b/src/state_migration/nv21fix/migration.rs @@ -1,9 +1,9 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use std::sync::Arc; - +use super::{SystemStateOld, system, verifier::Verifier}; use crate::networks::{ChainConfig, Height}; +use crate::prelude::*; use crate::shim::{ address::Address, clock::ChainEpoch, @@ -11,22 +11,18 @@ use crate::shim::{ state_tree::{StateTree, StateTreeVersion}, }; use crate::state_migration::common::PostMigrationCheck; -use crate::utils::db::CborStoreExt as _; -use anyhow::{Context, bail}; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; - -use super::{SystemStateOld, system, verifier::Verifier}; use crate::state_migration::common::{StateMigration, migrators::nil_migrator}; +use crate::utils::db::CborStoreExt as _; +use anyhow::bail; -impl StateMigration { +impl StateMigration { pub fn add_nv21fix_migrations( &mut self, - store: &Arc, + store: &BS, state: &Cid, new_manifest: &BuiltinActorManifest, ) -> anyhow::Result<()> { - let state_tree = StateTree::new_from_root(store.clone(), state)?; + let state_tree = StateTree::new_from_root(store, state)?; let system_actor = state_tree.get_required_actor(&Address::new_id(0))?; let system_actor_state = store.get_cbor_required::(&system_actor.state)?; @@ -54,9 +50,9 @@ struct PostMigrationVerifier { state_pre: Cid, } -impl PostMigrationCheck for PostMigrationVerifier { +impl PostMigrationCheck for PostMigrationVerifier { fn post_migrate_check(&self, store: &BS, actors_out: &StateTree) -> anyhow::Result<()> { - let actors_in = StateTree::new_from_root(Arc::new(store), &self.state_pre)?; + let actors_in = StateTree::new_from_root(store, &self.state_pre)?; let system_actor = actors_in.get_required_actor(&Address::new_id(0))?; let system_actor_state = store.get_cbor_required::(&system_actor.state)?; @@ -113,12 +109,12 @@ impl PostMigrationCheck for PostMigrationVerifier { /// Runs the light-weight patch for the `NV21` calibration network. Returns the new state root. pub fn run_migration( chain_config: &ChainConfig, - blockstore: &Arc, + blockstore: &DB, state: &Cid, epoch: ChainEpoch, ) -> anyhow::Result where - DB: Blockstore + Send + Sync, + DB: Blockstore + ShallowClone + Send + Sync, { assert!( chain_config.network.is_testnet(), @@ -147,8 +143,8 @@ where migration.add_nv21fix_migrations(blockstore, state, &new_manifest)?; migration.add_post_migration_check(Arc::new(PostMigrationVerifier { state_pre: *state })); - let actors_in = StateTree::new_from_root(blockstore.clone(), state)?; - let actors_out = StateTree::new(blockstore.clone(), StateTreeVersion::V5)?; + let actors_in = StateTree::new_from_root(blockstore, state)?; + let actors_out = StateTree::new(blockstore, StateTreeVersion::V5)?; let new_state = migration.migrate_state_tree(blockstore, epoch, actors_in, actors_out)?; Ok(new_state) diff --git a/src/state_migration/nv21fix2/migration.rs b/src/state_migration/nv21fix2/migration.rs index 90437c958b57..a11c9f9b8401 100644 --- a/src/state_migration/nv21fix2/migration.rs +++ b/src/state_migration/nv21fix2/migration.rs @@ -1,9 +1,9 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use std::sync::Arc; - +use super::{SystemStateOld, system, verifier::Verifier}; use crate::networks::{ChainConfig, Height}; +use crate::prelude::*; use crate::shim::{ address::Address, clock::ChainEpoch, @@ -11,22 +11,18 @@ use crate::shim::{ state_tree::{StateTree, StateTreeVersion}, }; use crate::state_migration::common::PostMigrationCheck; -use crate::utils::db::CborStoreExt as _; -use anyhow::{Context, bail}; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; - -use super::{SystemStateOld, system, verifier::Verifier}; use crate::state_migration::common::{StateMigration, migrators::nil_migrator}; +use crate::utils::db::CborStoreExt as _; +use anyhow::bail; -impl StateMigration { +impl StateMigration { pub fn add_nv21fix2_migrations( &mut self, - store: &Arc, + store: &BS, state: &Cid, new_manifest: &BuiltinActorManifest, ) -> anyhow::Result<()> { - let state_tree = StateTree::new_from_root(store.clone(), state)?; + let state_tree = StateTree::new_from_root(store, state)?; let system_actor = state_tree.get_required_actor(&Address::new_id(0))?; let system_actor_state = store.get_cbor_required::(&system_actor.state)?; @@ -54,9 +50,9 @@ struct PostMigrationVerifier { state_pre: Cid, } -impl PostMigrationCheck for PostMigrationVerifier { +impl PostMigrationCheck for PostMigrationVerifier { fn post_migrate_check(&self, store: &BS, actors_out: &StateTree) -> anyhow::Result<()> { - let actors_in = StateTree::new_from_root(Arc::new(store), &self.state_pre)?; + let actors_in = StateTree::new_from_root(store, &self.state_pre)?; let system_actor = actors_in.get_required_actor(&Address::new_id(0))?; let system_actor_state = store.get_cbor_required::(&system_actor.state)?; @@ -113,12 +109,12 @@ impl PostMigrationCheck for PostMigrationVerifier { /// Runs the light-weight patch for the `NV21` calibration network. Returns the new state root. pub fn run_migration( chain_config: &ChainConfig, - blockstore: &Arc, + blockstore: &DB, state: &Cid, epoch: ChainEpoch, ) -> anyhow::Result where - DB: Blockstore + Send + Sync, + DB: Blockstore + ShallowClone + Send + Sync, { assert!( chain_config.network.is_testnet(), @@ -144,8 +140,8 @@ where migration.add_nv21fix2_migrations(blockstore, state, &new_manifest)?; migration.add_post_migration_check(Arc::new(PostMigrationVerifier { state_pre: *state })); - let actors_in = StateTree::new_from_root(blockstore.clone(), state)?; - let actors_out = StateTree::new(blockstore.clone(), StateTreeVersion::V5)?; + let actors_in = StateTree::new_from_root(blockstore, state)?; + let actors_out = StateTree::new(blockstore, StateTreeVersion::V5)?; let new_state = migration.migrate_state_tree(blockstore, epoch, actors_in, actors_out)?; Ok(new_state) diff --git a/src/state_migration/nv22/migration.rs b/src/state_migration/nv22/migration.rs index 6684ec31b7c4..242dae0ec145 100644 --- a/src/state_migration/nv22/migration.rs +++ b/src/state_migration/nv22/migration.rs @@ -5,28 +5,22 @@ //! comes from the //! [FIP-0076](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0076.md#migration). -use std::sync::Arc; - +use super::{SystemStateOld, market, miner, system, verifier::Verifier}; use crate::networks::{ChainConfig, Height}; +use crate::prelude::*; use crate::shim::{ address::Address, clock::ChainEpoch, machine::{BuiltinActor, BuiltinActorManifest}, state_tree::{StateTree, StateTreeVersion}, }; -use crate::utils::db::CborStoreExt as _; -use anyhow::Context as _; -use cid::Cid; - -use fvm_ipld_blockstore::Blockstore; - -use super::{SystemStateOld, market, miner, system, verifier::Verifier}; use crate::state_migration::common::{StateMigration, migrators::nil_migrator}; +use crate::utils::db::CborStoreExt as _; -impl StateMigration { +impl StateMigration { pub fn add_nv22_migrations( &mut self, - store: &Arc, + store: &BS, state: &Cid, new_manifest: &BuiltinActorManifest, chain_config: &ChainConfig, @@ -37,7 +31,7 @@ impl StateMigration { .context("no height info for network version NV22")? .epoch; - let state_tree = StateTree::new_from_root(store.clone(), state)?; + let state_tree = StateTree::new_from_root(store, state)?; let system_actor = state_tree.get_required_actor(&Address::new_id(0))?; let system_actor_state = store.get_cbor_required::(&system_actor.state)?; @@ -81,12 +75,12 @@ impl StateMigration { /// Runs the migration for `NV22`. Returns the new state root. pub fn run_migration( chain_config: &ChainConfig, - blockstore: &Arc, + blockstore: &DB, state: &Cid, epoch: ChainEpoch, ) -> anyhow::Result where - DB: Blockstore + Send + Sync, + DB: Blockstore + ShallowClone + Send + Sync, { let new_manifest_cid = chain_config .height_infos @@ -107,8 +101,8 @@ where let mut migration = StateMigration::::new(Some(verifier)); migration.add_nv22_migrations(blockstore, state, &new_manifest, chain_config)?; - let actors_in = StateTree::new_from_root(blockstore.clone(), state)?; - let actors_out = StateTree::new(blockstore.clone(), StateTreeVersion::V5)?; + let actors_in = StateTree::new_from_root(blockstore, state)?; + let actors_out = StateTree::new(blockstore, StateTreeVersion::V5)?; let new_state = migration.migrate_state_tree(blockstore, epoch, actors_in, actors_out)?; Ok(new_state) diff --git a/src/state_migration/nv22fix/migration.rs b/src/state_migration/nv22fix/migration.rs index 79d96b5cf8cc..d7b89f1edcec 100644 --- a/src/state_migration/nv22fix/migration.rs +++ b/src/state_migration/nv22fix/migration.rs @@ -3,10 +3,10 @@ // //! This module contains the migration logic for the `NV22fix` upgrade. //! Corresponding -use std::sync::Arc; use super::{SystemStateOld, system, verifier::Verifier}; use crate::networks::{ChainConfig, Height, NetworkChain}; +use crate::prelude::*; use crate::shim::{ address::Address, clock::ChainEpoch, @@ -16,18 +16,16 @@ use crate::shim::{ use crate::state_migration::common::PostMigrationCheck; use crate::state_migration::common::{StateMigration, migrators::nil_migrator}; use crate::utils::db::CborStoreExt as _; -use anyhow::{Context, bail}; -use cid::Cid; -use fvm_ipld_blockstore::Blockstore; +use anyhow::bail; -impl StateMigration { +impl StateMigration { pub fn add_nv22fix_migrations( &mut self, - store: &Arc, + store: &BS, state: &Cid, new_manifest: &BuiltinActorManifest, ) -> anyhow::Result<()> { - let state_tree = StateTree::new_from_root(store.clone(), state)?; + let state_tree = StateTree::new_from_root(store, state)?; let system_actor = state_tree.get_required_actor(&Address::new_id(0))?; let system_actor_state = store.get_cbor_required::(&system_actor.state)?; @@ -55,9 +53,9 @@ struct PostMigrationVerifier { state_pre: Cid, } -impl PostMigrationCheck for PostMigrationVerifier { +impl PostMigrationCheck for PostMigrationVerifier { fn post_migrate_check(&self, store: &BS, actors_out: &StateTree) -> anyhow::Result<()> { - let actors_in = StateTree::new_from_root(Arc::new(store), &self.state_pre)?; + let actors_in = StateTree::new_from_root(store, &self.state_pre)?; let system_actor = actors_in.get_required_actor(&Address::new_id(0))?; let system_actor_state = store.get_cbor_required::(&system_actor.state)?; @@ -114,12 +112,12 @@ impl PostMigrationCheck for PostMigrationVerifier { /// Runs the migration for `NV22`. Returns the new state root. pub fn run_migration( chain_config: &ChainConfig, - blockstore: &Arc, + blockstore: &DB, state: &Cid, epoch: ChainEpoch, ) -> anyhow::Result where - DB: Blockstore + Send + Sync, + DB: Blockstore + ShallowClone + Send + Sync, { assert_eq!( chain_config.network, @@ -147,8 +145,8 @@ where migration.add_nv22fix_migrations(blockstore, state, &new_manifest)?; migration.add_post_migration_check(Arc::new(PostMigrationVerifier { state_pre: *state })); - let actors_in = StateTree::new_from_root(blockstore.clone(), state)?; - let actors_out = StateTree::new(blockstore.clone(), StateTreeVersion::V5)?; + let actors_in = StateTree::new_from_root(blockstore, state)?; + let actors_out = StateTree::new(blockstore, StateTreeVersion::V5)?; let new_state = migration.migrate_state_tree(blockstore, epoch, actors_in, actors_out)?; Ok(new_state) diff --git a/src/state_migration/nv23/migration.rs b/src/state_migration/nv23/migration.rs index 5b93ce8e4f16..399fe7d0278f 100644 --- a/src/state_migration/nv23/migration.rs +++ b/src/state_migration/nv23/migration.rs @@ -3,34 +3,28 @@ // //! This module contains the migration logic for the `NV23` upgrade. -use std::sync::Arc; - +use super::mining_reserve::MiningReservePostMigrator; +use super::{SystemStateOld, system, verifier::Verifier}; use crate::networks::{ChainConfig, Height}; +use crate::prelude::*; use crate::shim::{ address::Address, clock::ChainEpoch, machine::{BuiltinActor, BuiltinActorManifest}, state_tree::{StateTree, StateTreeVersion}, }; -use crate::utils::db::CborStoreExt as _; -use anyhow::Context as _; -use cid::Cid; - -use fvm_ipld_blockstore::Blockstore; - -use super::mining_reserve::MiningReservePostMigrator; -use super::{SystemStateOld, system, verifier::Verifier}; use crate::state_migration::common::{StateMigration, migrators::nil_migrator}; +use crate::utils::db::CborStoreExt as _; -impl StateMigration { +impl StateMigration { pub fn add_nv23_migrations( &mut self, - store: &Arc, + store: &BS, state: &Cid, new_manifest: &BuiltinActorManifest, _chain_config: &ChainConfig, ) -> anyhow::Result<()> { - let state_tree = StateTree::new_from_root(store.clone(), state)?; + let state_tree = StateTree::new_from_root(store, state)?; let system_actor = state_tree.get_required_actor(&Address::SYSTEM_ACTOR)?; let system_actor_state = store.get_cbor_required::(&system_actor.state)?; @@ -61,12 +55,12 @@ impl StateMigration { /// Runs the migration for `NV23`. Returns the new state root. pub fn run_migration( chain_config: &ChainConfig, - blockstore: &Arc, + blockstore: &DB, state: &Cid, epoch: ChainEpoch, ) -> anyhow::Result where - DB: Blockstore + Send + Sync, + DB: Blockstore + ShallowClone + Send + Sync, { let new_manifest_cid = chain_config .height_infos @@ -87,8 +81,8 @@ where let mut migration = StateMigration::::new(Some(verifier)); migration.add_nv23_migrations(blockstore, state, &new_manifest, chain_config)?; - let actors_in = StateTree::new_from_root(blockstore.clone(), state)?; - let actors_out = StateTree::new(blockstore.clone(), StateTreeVersion::V5)?; + let actors_in = StateTree::new_from_root(blockstore, state)?; + let actors_out = StateTree::new(blockstore, StateTreeVersion::V5)?; let new_state = migration.migrate_state_tree(blockstore, epoch, actors_in, actors_out)?; Ok(new_state) diff --git a/src/state_migration/nv24/migration.rs b/src/state_migration/nv24/migration.rs index f1d89766c3d6..50bc3c47e560 100644 --- a/src/state_migration/nv24/migration.rs +++ b/src/state_migration/nv24/migration.rs @@ -3,33 +3,27 @@ // //! This module contains the migration logic for the `NV24` upgrade. -use std::sync::Arc; - +use super::{SystemStateOld, power, system, verifier::Verifier}; use crate::networks::{ChainConfig, Height}; +use crate::prelude::*; use crate::shim::{ address::Address, clock::ChainEpoch, machine::{BuiltinActor, BuiltinActorManifest}, state_tree::{StateTree, StateTreeVersion}, }; -use crate::utils::db::CborStoreExt as _; -use anyhow::Context as _; -use cid::Cid; - -use fvm_ipld_blockstore::Blockstore; - -use super::{SystemStateOld, power, system, verifier::Verifier}; use crate::state_migration::common::{StateMigration, migrators::nil_migrator}; +use crate::utils::db::CborStoreExt as _; -impl StateMigration { +impl StateMigration { pub fn add_nv24_migrations( &mut self, - store: &Arc, + store: &BS, state: &Cid, new_manifest: &BuiltinActorManifest, chain_config: &ChainConfig, ) -> anyhow::Result<()> { - let state_tree = StateTree::new_from_root(store.clone(), state)?; + let state_tree = StateTree::new_from_root(store, state)?; let system_actor = state_tree.get_required_actor(&Address::SYSTEM_ACTOR)?; let system_actor_state = store.get_cbor_required::(&system_actor.state)?; @@ -70,12 +64,12 @@ impl StateMigration { #[allow(dead_code)] pub fn run_migration( chain_config: &ChainConfig, - blockstore: &Arc, + blockstore: &DB, state: &Cid, epoch: ChainEpoch, ) -> anyhow::Result where - DB: Blockstore + Send + Sync, + DB: Blockstore + ShallowClone + Send + Sync, { let new_manifest_cid = chain_config .height_infos @@ -96,8 +90,8 @@ where let mut migration = StateMigration::::new(Some(verifier)); migration.add_nv24_migrations(blockstore, state, &new_manifest, chain_config)?; - let actors_in = StateTree::new_from_root(blockstore.clone(), state)?; - let actors_out = StateTree::new(blockstore.clone(), StateTreeVersion::V5)?; + let actors_in = StateTree::new_from_root(blockstore, state)?; + let actors_out = StateTree::new(blockstore, StateTreeVersion::V5)?; let new_state = migration.migrate_state_tree(blockstore, epoch, actors_in, actors_out)?; Ok(new_state) diff --git a/src/state_migration/nv25/migration.rs b/src/state_migration/nv25/migration.rs index 206e3465c72f..cea8e97a3e00 100644 --- a/src/state_migration/nv25/migration.rs +++ b/src/state_migration/nv25/migration.rs @@ -3,34 +3,28 @@ // //! This module contains the migration logic for the `NV25` upgrade. -use std::sync::Arc; - +use super::evm::EvmMigrator; +use super::miner::MinerMigrator; +use super::{SystemStateOld, system, verifier::Verifier}; use crate::networks::{ChainConfig, Height}; +use crate::prelude::*; use crate::shim::{ address::Address, clock::ChainEpoch, machine::{BuiltinActor, BuiltinActorManifest}, state_tree::{StateTree, StateTreeVersion}, }; -use crate::utils::db::CborStoreExt as _; -use anyhow::Context as _; -use cid::Cid; - -use fvm_ipld_blockstore::Blockstore; - -use super::evm::EvmMigrator; -use super::miner::MinerMigrator; -use super::{SystemStateOld, system, verifier::Verifier}; use crate::state_migration::common::{StateMigration, migrators::nil_migrator}; +use crate::utils::db::CborStoreExt as _; -impl StateMigration { +impl StateMigration { pub fn add_nv25_migrations( &mut self, - store: &Arc, + store: &BS, state: &Cid, new_manifest: &BuiltinActorManifest, ) -> anyhow::Result<()> { - let state_tree = StateTree::new_from_root(store.clone(), state)?; + let state_tree = StateTree::new_from_root(store, state)?; let system_actor = state_tree.get_required_actor(&Address::SYSTEM_ACTOR)?; let system_actor_state = store.get_cbor_required::(&system_actor.state)?; @@ -68,12 +62,12 @@ impl StateMigration { /// Runs the migration for `NV25`. Returns the new state root. pub fn run_migration( chain_config: &ChainConfig, - blockstore: &Arc, + blockstore: &DB, state: &Cid, epoch: ChainEpoch, ) -> anyhow::Result where - DB: Blockstore + Send + Sync, + DB: Blockstore + ShallowClone + Send + Sync, { let new_manifest_cid = chain_config .height_infos @@ -94,8 +88,8 @@ where let mut migration = StateMigration::::new(Some(verifier)); migration.add_nv25_migrations(blockstore, state, &new_manifest)?; - let actors_in = StateTree::new_from_root(blockstore.clone(), state)?; - let actors_out = StateTree::new(blockstore.clone(), StateTreeVersion::V5)?; + let actors_in = StateTree::new_from_root(blockstore, state)?; + let actors_out = StateTree::new(blockstore, StateTreeVersion::V5)?; let new_state = migration.migrate_state_tree(blockstore, epoch, actors_in, actors_out)?; Ok(new_state) diff --git a/src/state_migration/nv26fix/migration.rs b/src/state_migration/nv26fix/migration.rs index 3325ce388d19..e6748d7749df 100644 --- a/src/state_migration/nv26fix/migration.rs +++ b/src/state_migration/nv26fix/migration.rs @@ -4,32 +4,27 @@ //! This module contains the migration logic for the `nv26fix` upgrade. See the parent module for //! details on the fix. -use std::sync::Arc; - +use super::{SystemStateOld, system, verifier::Verifier}; use crate::networks::{ChainConfig, Height}; +use crate::prelude::*; use crate::shim::{ address::Address, clock::ChainEpoch, machine::BuiltinActorManifest, state_tree::{StateTree, StateTreeVersion}, }; -use crate::utils::db::CborStoreExt as _; -use anyhow::{Context as _, ensure}; -use cid::Cid; - -use fvm_ipld_blockstore::Blockstore; - -use super::{SystemStateOld, system, verifier::Verifier}; use crate::state_migration::common::{StateMigration, migrators::nil_migrator}; +use crate::utils::db::CborStoreExt as _; +use anyhow::ensure; -impl StateMigration { +impl StateMigration { pub fn add_nv26fix_migrations( &mut self, - store: &Arc, + store: &BS, state: &Cid, new_manifest: &BuiltinActorManifest, ) -> anyhow::Result<()> { - let state_tree = StateTree::new_from_root(store.clone(), state)?; + let state_tree = StateTree::new_from_root(store, state)?; let system_actor = state_tree.get_required_actor(&Address::SYSTEM_ACTOR)?; let system_actor_state = store.get_cbor_required::(&system_actor.state)?; @@ -55,12 +50,12 @@ impl StateMigration { /// Runs the migration for `nv26fix`. Returns the new state root. pub fn run_migration( chain_config: &ChainConfig, - blockstore: &Arc, + blockstore: &DB, state: &Cid, epoch: ChainEpoch, ) -> anyhow::Result where - DB: Blockstore + Send + Sync, + DB: Blockstore + ShallowClone + Send + Sync, { // Technically the manifest for this just won't be there for mainnet, but better safe than // sorry. @@ -87,8 +82,8 @@ where let mut migration = StateMigration::::new(Some(verifier)); migration.add_nv26fix_migrations(blockstore, state, &new_manifest)?; - let actors_in = StateTree::new_from_root(blockstore.clone(), state)?; - let actors_out = StateTree::new(blockstore.clone(), StateTreeVersion::V5)?; + let actors_in = StateTree::new_from_root(blockstore, state)?; + let actors_out = StateTree::new(blockstore, StateTreeVersion::V5)?; let new_state = migration.migrate_state_tree(blockstore, epoch, actors_in, actors_out)?; Ok(new_state) diff --git a/src/state_migration/nv27/migration.rs b/src/state_migration/nv27/migration.rs index e541e1af492c..142bf7ef127e 100644 --- a/src/state_migration/nv27/migration.rs +++ b/src/state_migration/nv27/migration.rs @@ -3,32 +3,26 @@ // //! This module contains the migration logic for the `NV27` upgrade. -use std::sync::Arc; - +use super::{SystemStateOld, system, verifier::Verifier}; use crate::networks::{ChainConfig, Height}; +use crate::prelude::*; use crate::shim::{ address::Address, clock::ChainEpoch, machine::BuiltinActorManifest, state_tree::{StateTree, StateTreeVersion}, }; -use crate::utils::db::CborStoreExt as _; -use anyhow::Context as _; -use cid::Cid; - -use fvm_ipld_blockstore::Blockstore; - -use super::{SystemStateOld, system, verifier::Verifier}; use crate::state_migration::common::{StateMigration, migrators::nil_migrator}; +use crate::utils::db::CborStoreExt as _; -impl StateMigration { +impl StateMigration { pub fn add_nv27_migrations( &mut self, - store: &Arc, + store: &BS, state: &Cid, new_manifest: &BuiltinActorManifest, ) -> anyhow::Result<()> { - let state_tree = StateTree::new_from_root(store.clone(), state)?; + let state_tree = StateTree::new_from_root(store, state)?; let system_actor = state_tree.get_required_actor(&Address::SYSTEM_ACTOR)?; let system_actor_state = store.get_cbor_required::(&system_actor.state)?; @@ -54,12 +48,12 @@ impl StateMigration { /// Runs the migration for `NV27`. Returns the new state root. pub fn run_migration( chain_config: &ChainConfig, - blockstore: &Arc, + blockstore: &DB, state: &Cid, epoch: ChainEpoch, ) -> anyhow::Result where - DB: Blockstore + Send + Sync, + DB: Blockstore + ShallowClone + Send + Sync, { let new_manifest_cid = chain_config .height_infos @@ -80,8 +74,8 @@ where let mut migration = StateMigration::::new(Some(verifier)); migration.add_nv27_migrations(blockstore, state, &new_manifest)?; - let actors_in = StateTree::new_from_root(blockstore.clone(), state)?; - let actors_out = StateTree::new(blockstore.clone(), StateTreeVersion::V5)?; + let actors_in = StateTree::new_from_root(blockstore, state)?; + let actors_out = StateTree::new(blockstore, StateTreeVersion::V5)?; let new_state = migration.migrate_state_tree(blockstore, epoch, actors_in, actors_out)?; Ok(new_state) diff --git a/src/state_migration/nv28/migration.rs b/src/state_migration/nv28/migration.rs index 39511fc1897c..390bf5083038 100644 --- a/src/state_migration/nv28/migration.rs +++ b/src/state_migration/nv28/migration.rs @@ -3,32 +3,26 @@ // //! This module contains the migration logic for the `NV28` upgrade. -use std::sync::Arc; - +use super::{SystemStateOld, system, verifier::Verifier}; use crate::networks::{ChainConfig, Height}; +use crate::prelude::*; use crate::shim::{ address::Address, clock::ChainEpoch, machine::BuiltinActorManifest, state_tree::{StateTree, StateTreeVersion}, }; -use crate::utils::db::CborStoreExt as _; -use anyhow::Context as _; -use cid::Cid; - -use fvm_ipld_blockstore::Blockstore; - -use super::{SystemStateOld, system, verifier::Verifier}; use crate::state_migration::common::{StateMigration, migrators::nil_migrator}; +use crate::utils::db::CborStoreExt as _; -impl StateMigration { +impl StateMigration { pub fn add_nv28_migrations( &mut self, - store: &Arc, + store: &BS, state: &Cid, new_manifest: &BuiltinActorManifest, ) -> anyhow::Result<()> { - let state_tree = StateTree::new_from_root(store.clone(), state)?; + let state_tree = StateTree::new_from_root(store, state)?; let system_actor = state_tree.get_required_actor(&Address::SYSTEM_ACTOR)?; let system_actor_state = store.get_cbor_required::(&system_actor.state)?; @@ -54,12 +48,12 @@ impl StateMigration { /// Runs the migration for `NV28`. Returns the new state root. pub fn run_migration( chain_config: &ChainConfig, - blockstore: &Arc, + blockstore: &DB, state: &Cid, epoch: ChainEpoch, ) -> anyhow::Result where - DB: Blockstore + Send + Sync, + DB: Blockstore + ShallowClone + Send + Sync, { let new_manifest_cid = chain_config .height_infos @@ -80,8 +74,8 @@ where let mut migration = StateMigration::::new(Some(verifier)); migration.add_nv28_migrations(blockstore, state, &new_manifest)?; - let actors_in = StateTree::new_from_root(blockstore.clone(), state)?; - let actors_out = StateTree::new(blockstore.clone(), StateTreeVersion::V5)?; + let actors_in = StateTree::new_from_root(blockstore, state)?; + let actors_out = StateTree::new(blockstore, StateTreeVersion::V5)?; let new_state = migration.migrate_state_tree(blockstore, epoch, actors_in, actors_out)?; Ok(new_state) diff --git a/src/statediff/mod.rs b/src/statediff/mod.rs index 65d0ad636e78..d67098a0acb7 100644 --- a/src/statediff/mod.rs +++ b/src/statediff/mod.rs @@ -6,15 +6,8 @@ mod resolve; use std::{ fmt::Write as FmtWrite, io::{Write, stdout}, - sync::Arc, }; -use crate::shim::actors::{ - account::State as AccountState, cron::State as CronState, datacap::State as DatacapState, - evm::State as EvmState, init::State as InitState, market::State as MarketState, - miner::State as MinerState, multisig::State as MultiSigState, power::State as PowerState, - reward::State as RewardState, system::State as SystemState, -}; use crate::{ lotus_json::HasLotusJson as _, shim::{ @@ -23,12 +16,19 @@ use crate::{ state_tree::{ActorState, StateTree}, }, }; +use crate::{ + prelude::*, + shim::actors::{ + account::State as AccountState, cron::State as CronState, datacap::State as DatacapState, + evm::State as EvmState, init::State as InitState, market::State as MarketState, + miner::State as MinerState, multisig::State as MultiSigState, power::State as PowerState, + reward::State as RewardState, system::State as SystemState, + }, +}; use ahash::HashMap; -use cid::Cid; use colored::*; use fvm_ipld_blockstore::Blockstore; use ipld_core::ipld::Ipld; -use itertools::Itertools as _; use resolve::resolve_cids_recursive; use serde::{Deserialize, Serialize}; use similar::{ChangeTag, TextDiff}; @@ -58,12 +58,12 @@ fn actor_to_resolved( } } -fn root_to_state_map( - bs: &Arc, +fn root_to_state_map( + bs: &BS, root: &Cid, ) -> anyhow::Result> { let mut actors = HashMap::default(); - let state_tree = StateTree::new_from_root(bs.clone(), root)?; + let state_tree = StateTree::new_from_root(bs, root)?; state_tree.for_each(|addr: Address, actor: &ActorState| { actors.insert(addr, actor.clone()); Ok(()) @@ -76,8 +76,8 @@ fn root_to_state_map( /// The actors HAMT is hard to parse in a diff, so this attempts to remedy this. /// This function will only print the actors that are added, removed, or changed /// so it can be used on large state trees. -fn try_print_actor_states( - bs: &Arc, +fn try_print_actor_states( + bs: &BS, root: &Cid, expected_root: &Cid, depth: Option, @@ -87,7 +87,7 @@ fn try_print_actor_states( let mut e_state = root_to_state_map(bs, expected_root)?; // Compare state with expected - let state_tree = StateTree::new_from_root(bs.clone(), root)?; + let state_tree = StateTree::new_from_root(bs, root)?; state_tree.for_each(|addr: Address, actor| { if let Some(other) = e_state.remove(&addr) { diff --git a/src/tool/offline_server/server.rs b/src/tool/offline_server/server.rs index 04e7d7e33838..b315025dc00e 100644 --- a/src/tool/offline_server/server.rs +++ b/src/tool/offline_server/server.rs @@ -7,16 +7,14 @@ use crate::chain_sync::SyncStatusReport; use crate::chain_sync::network_context::SyncNetworkContext; use crate::cli_shared::cli::EventsConfig; use crate::cli_shared::snapshot::TrustedVendor; -use crate::daemon::db_util::RangeSpec; -use crate::daemon::db_util::backfill_db; -use crate::db::{ - EthMappingsStore, HeaviestTipsetKeyProvider, MemoryDB, SettingsStore, car::ManyCar, -}; +use crate::daemon::db_util::{RangeSpec, backfill_db}; +use crate::db::{DbImpl, MemoryDB, car::ManyCar}; use crate::genesis::read_genesis_header; use crate::key_management::{KeyStore, KeyStoreConfig}; use crate::libp2p::PeerManager; use crate::message_pool::{MessagePool, MpoolLocker, NonceTracker}; use crate::networks::{ChainConfig, NetworkChain}; +use crate::prelude::*; use crate::rpc::eth::filter::EthEventHandler; use crate::rpc::{RPCState, start_rpc}; use crate::shim::address::{CurrentNetwork, Network}; @@ -24,15 +22,12 @@ use crate::state_manager::StateManager; use crate::utils::net::{DownloadFileOption, download_to}; use crate::utils::proofs_api::{self, ensure_proof_params_downloaded}; use crate::{Config, JWT_IDENTIFIER}; -use anyhow::Context as _; -use fvm_ipld_blockstore::Blockstore; use jsonrpsee::server::stop_channel; use parking_lot::RwLock; use std::{ mem::discriminant, net::{IpAddr, Ipv4Addr, SocketAddr}, path::{Path, PathBuf}, - sync::Arc, }; use tokio::{ signal::{ @@ -46,22 +41,14 @@ use tracing::{info, warn}; /// Builds offline RPC state and returns it with a shutdown receiver. /// The receiver is notified when RPC shutdown is requested. -pub async fn offline_rpc_state( +pub async fn offline_rpc_state( chain: NetworkChain, - db: Arc, + db: impl Into, genesis_fp: Option<&Path>, save_jwt_token: Option<&Path>, services: &mut JoinSet>, -) -> anyhow::Result<(RPCState, mpsc::Receiver<()>)> -where - DB: Blockstore - + SettingsStore - + HeaviestTipsetKeyProvider - + EthMappingsStore - + Send - + Sync - + 'static, -{ +) -> anyhow::Result<(RPCState, mpsc::Receiver<()>)> { + let db = db.into(); let chain_config = Arc::new(handle_chain_config(&chain)?); let events_config = Arc::new(EventsConfig::default()); let genesis_header = read_genesis_header( @@ -71,19 +58,13 @@ where ) .await?; // let head_ts = db.heaviest_tipset()?; - let chain_store = Arc::new(ChainStore::new( - db.clone(), - db.clone(), - db.clone(), - chain_config, - genesis_header.clone(), - )?); - let state_manager = Arc::new(StateManager::new(chain_store.clone())?); + let chain_store = ChainStore::new(db.shallow_clone(), chain_config, genesis_header.clone())?; + let state_manager = StateManager::new(chain_store.shallow_clone())?; let (network_send, _) = flume::bounded(5); let (tipset_send, _) = flume::bounded(5); let message_pool = MessagePool::new( - chain_store.clone(), + chain_store, network_send.clone(), Default::default(), state_manager.chain_config().clone(), @@ -113,13 +94,13 @@ where let peer_manager = Arc::new(PeerManager::default()); let sync_network_context = - SyncNetworkContext::new(network_send, peer_manager, state_manager.blockstore_owned()); + SyncNetworkContext::new(network_send, peer_manager, state_manager.db_owned()); let nonce_tracker = NonceTracker::new(); Ok(( RPCState { state_manager, keystore: Arc::new(RwLock::new(keystore)), - mpool: Arc::new(message_pool), + mpool: message_pool, bad_blocks: Default::default(), sync_status: Arc::new(RwLock::new(SyncStatusReport::init())), eth_event_handler: Arc::new(EthEventHandler::from_config(&events_config)), @@ -212,7 +193,7 @@ pub async fn start_offline_server( if validate_until_epoch <= head_ts.epoch() { state_manager.validate_tipsets( head_ts - .chain(rpc_state.store()) + .chain(rpc_state.db()) .take_while(|ts| ts.epoch() >= validate_until_epoch), )?; } @@ -222,14 +203,11 @@ pub async fn start_offline_server( Ok(()) } -async fn start_offline_rpc( - state: RPCState, +async fn start_offline_rpc( + state: RPCState, rpc_port: u16, mut shutdown_recv: mpsc::Receiver<()>, -) -> anyhow::Result<()> -where - DB: Blockstore + EthMappingsStore + Send + Sync + 'static, -{ +) -> anyhow::Result<()> { info!("Starting offline RPC Server"); let rpc_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), rpc_port); let rpc_listener = diff --git a/src/tool/subcommands/api_cmd/api_compare_tests.rs b/src/tool/subcommands/api_cmd/api_compare_tests.rs index 1319fafd73ab..529539524b5c 100644 --- a/src/tool/subcommands/api_cmd/api_compare_tests.rs +++ b/src/tool/subcommands/api_cmd/api_compare_tests.rs @@ -8,6 +8,7 @@ use crate::db::car::ManyCar; use crate::eth::EthChainId as EthChainIdType; use crate::lotus_json::HasLotusJson; use crate::message::{MessageRead as _, SignedMessage}; +use crate::prelude::*; use crate::rpc::auth::AuthNewParams; use crate::rpc::beacon::BeaconGetEntry; use crate::rpc::eth::{ @@ -498,8 +499,8 @@ fn chain_tests(offline: bool) -> Vec { ] } -fn chain_tests_with_tipset( - store: &Arc, +fn chain_tests_with_tipset( + store: &DB, offline: bool, tipset: &Tipset, ) -> anyhow::Result> { @@ -715,8 +716,8 @@ fn node_tests() -> Vec { ] } -fn event_tests_with_tipset( - _store: &Arc, +fn event_tests_with_tipset( + _store: &DB, tipset: &Tipset, ) -> anyhow::Result> { let epoch = tipset.epoch(); @@ -791,8 +792,8 @@ fn event_tests_with_tipset( ]) } -fn miner_tests_with_tipset( - store: &Arc, +fn miner_tests_with_tipset( + store: &DB, tipset: &Tipset, miner_address: Option
, ) -> anyhow::Result> { @@ -863,8 +864,8 @@ fn miner_create_block_no_messages_test(miner: Address, tipset: &Tipset) -> RpcTe RpcTest::identity(MinerCreateBlock::request((block_template,)).unwrap()) } -fn state_tests_with_tipset( - store: &Arc, +fn state_tests_with_tipset( + store: &DB, tipset: &Tipset, ) -> anyhow::Result> { let mut tests = vec![ @@ -1019,7 +1020,7 @@ fn state_tests_with_tipset( // Get deals let (deals, deals_map) = { - let state = StateTree::new_from_root(store.clone(), tipset.parent_state())?; + let state = StateTree::new_from_root(store, tipset.parent_state())?; let actor = state.get_required_actor(&Address::MARKET_ACTOR)?; let market_state = market::State::load(&store, actor.code, actor.state)?; let proposals = market_state.proposals(&store)?; @@ -1580,8 +1581,8 @@ fn eth_call_api_err_tests(epoch: i64) -> Vec { tests } -fn eth_tests_with_tipset( - store: &Arc, +fn eth_tests_with_tipset( + store: &DB, shared_tipset: &Tipset, ) -> anyhow::Result> { let block_cid = shared_tipset.key().cid()?; @@ -2290,16 +2291,15 @@ fn read_state_api_tests(tipset: &Tipset) -> anyhow::Result> { Ok(tests) } -fn eth_state_tests_with_tipset( - store: &Arc, +fn eth_state_tests_with_tipset( + store: &DB, shared_tipset: &Tipset, eth_chain_id: EthChainIdType, ) -> anyhow::Result> { let mut tests = vec![]; for block in shared_tipset.block_headers() { - let state = StateTree::new_from_root(store.clone(), shared_tipset.parent_state())?; - + let state = StateTree::new_from_root(store, shared_tipset.parent_state())?; let (bls_messages, secp_messages) = crate::chain::store::block_messages(store, block)?; for smsg in sample_signed_messages(bls_messages.iter(), secp_messages.iter()) { let tx = new_eth_tx_from_signed_message(&smsg, &state, eth_chain_id)?; @@ -2574,14 +2574,8 @@ async fn revalidate_chain(db: Arc, n_ts_to_validate: usize) -> anyhow:: &db, ) .await?; - let chain_store = Arc::new(ChainStore::new( - db.clone(), - db.clone(), - db.clone(), - chain_config, - genesis_header.clone(), - )?); - let state_manager = Arc::new(StateManager::new(chain_store.clone())?); + let chain_store = ChainStore::new(db.clone(), chain_config, genesis_header.clone())?; + let state_manager = StateManager::new(chain_store)?; let head_ts = db.heaviest_tipset()?; // Set proof parameter data dir and make sure the proofs are available. Otherwise, diff --git a/src/tool/subcommands/api_cmd/generate_test_snapshot.rs b/src/tool/subcommands/api_cmd/generate_test_snapshot.rs index b1747c9abe93..ec15584c6896 100644 --- a/src/tool/subcommands/api_cmd/generate_test_snapshot.rs +++ b/src/tool/subcommands/api_cmd/generate_test_snapshot.rs @@ -2,12 +2,11 @@ // SPDX-License-Identifier: Apache-2.0, MIT use super::*; -use crate::chain_sync::SyncStatusReport; use crate::{ KeyStore, KeyStoreConfig, blocks::{Tipset, TipsetKey}, chain::ChainStore, - chain_sync::network_context::SyncNetworkContext, + chain_sync::{SyncStatusReport, network_context::SyncNetworkContext}, daemon::{bundle::load_actor_bundles, db_util::load_all_forest_cars}, db::{ CAR_DB_DIR_NAME, EthMappingsStore, HeaviestTipsetKeyProvider, MemoryDB, SettingsStore, @@ -18,6 +17,7 @@ use crate::{ libp2p_bitswap::{BitswapStoreRead, BitswapStoreReadWrite, Block64}, message_pool::{MessagePool, MpoolLocker, NonceTracker}, networks::ChainConfig, + prelude::*, shim::address::CurrentNetwork, state_manager::StateManager, }; @@ -109,7 +109,7 @@ async fn ctx( db: Arc>>, chain_config: Arc, ) -> anyhow::Result<( - Arc>>>, + Arc, flume::Receiver, tokio::sync::mpsc::Receiver<()>, )> { @@ -117,21 +117,10 @@ async fn ctx( let (tipset_send, _) = flume::bounded(5); let genesis_header = read_genesis_header(None, chain_config.genesis_bytes(&db).await?.as_deref(), &db).await?; - - let chain_store = Arc::new( - ChainStore::new( - db.clone(), - db.clone(), - db.clone(), - chain_config, - genesis_header, - ) - .unwrap(), - ); - - let state_manager = Arc::new(StateManager::new(chain_store.clone()).unwrap()); + let chain_store = ChainStore::new(db.clone(), chain_config, genesis_header)?; + let state_manager = StateManager::new(chain_store.shallow_clone())?; let message_pool = MessagePool::new( - chain_store.clone(), + chain_store, network_send.clone(), Default::default(), state_manager.chain_config().clone(), @@ -140,13 +129,13 @@ async fn ctx( let peer_manager = Arc::new(PeerManager::default()); let sync_network_context = - SyncNetworkContext::new(network_send, peer_manager, state_manager.blockstore_owned()); + SyncNetworkContext::new(network_send, peer_manager, state_manager.db_owned()); let (shutdown, shutdown_recv) = mpsc::channel(1); let nonce_tracker = NonceTracker::new(); let rpc_state = Arc::new(RPCState { state_manager, keystore: Arc::new(RwLock::new(KeyStore::new(KeyStoreConfig::Memory)?)), - mpool: Arc::new(message_pool), + mpool: message_pool, bad_blocks: Default::default(), sync_status: Arc::new(RwLock::new(SyncStatusReport::init())), eth_event_handler: Arc::new(EthEventHandler::new()), diff --git a/src/tool/subcommands/api_cmd/test_snapshot.rs b/src/tool/subcommands/api_cmd/test_snapshot.rs index 28653564c66a..4149f33dba8b 100644 --- a/src/tool/subcommands/api_cmd/test_snapshot.rs +++ b/src/tool/subcommands/api_cmd/test_snapshot.rs @@ -14,6 +14,7 @@ use crate::{ lotus_json::HasLotusJson, message_pool::{MessagePool, MpoolLocker, NonceTracker}, networks::{ChainConfig, NetworkChain}, + prelude::*, rpc::{ ApiPaths, RPCState, RpcMethod, RpcMethodExt as _, eth::{filter::EthEventHandler, types::EthHash}, @@ -133,7 +134,7 @@ async fn ctx( db: Arc>, chain_config: Arc, ) -> anyhow::Result<( - Arc>>, + Arc, flume::Receiver, tokio::sync::mpsc::Receiver<()>, )> { @@ -141,16 +142,10 @@ async fn ctx( let (tipset_send, _) = flume::bounded(5); let genesis_header = read_genesis_header(None, chain_config.genesis_bytes(&db).await?.as_deref(), &db).await?; - let chain_store = Arc::new(ChainStore::new( - db.clone(), - db.clone(), - db, - chain_config, - genesis_header.clone(), - )?); - let state_manager = Arc::new(StateManager::new(chain_store.clone()).unwrap()); + let chain_store = ChainStore::new(db, chain_config, genesis_header.clone())?; + let state_manager = StateManager::new(chain_store.shallow_clone()).unwrap(); let message_pool = MessagePool::new( - chain_store.clone(), + chain_store, network_send.clone(), Default::default(), state_manager.chain_config().clone(), @@ -159,13 +154,13 @@ async fn ctx( let peer_manager = Arc::new(PeerManager::default()); let sync_network_context = - SyncNetworkContext::new(network_send, peer_manager, state_manager.blockstore_owned()); + SyncNetworkContext::new(network_send, peer_manager, state_manager.db_owned()); let (shutdown, shutdown_recv) = mpsc::channel(1); let nonce_tracker = NonceTracker::new(); let rpc_state = Arc::new(RPCState { state_manager, keystore: Arc::new(RwLock::new(KeyStore::new(KeyStoreConfig::Memory)?)), - mpool: Arc::new(message_pool), + mpool: message_pool, bad_blocks: Default::default(), sync_status: Arc::new(RwLock::new(SyncStatusReport::init())), eth_event_handler: Arc::new(EthEventHandler::new()), diff --git a/src/tool/subcommands/archive_cmd.rs b/src/tool/subcommands/archive_cmd.rs index 6d11cff1aa2e..e2d56d95a7fd 100644 --- a/src/tool/subcommands/archive_cmd.rs +++ b/src/tool/subcommands/archive_cmd.rs @@ -35,12 +35,13 @@ use crate::cid_collections::CidHashSet; use crate::cid_collections::FileBackedCidHashSet; use crate::cli_shared::{snapshot, snapshot::TrustedVendor}; use crate::daemon::bundle::load_actor_bundles; -use crate::db::EthMappingsStore; +use crate::db::DbImpl; use crate::db::car::{AnyCar, ManyCar, forest::DEFAULT_FOREST_CAR_COMPRESSION_LEVEL}; use crate::f3::snapshot::F3SnapshotHeader; use crate::interpreter::VMTrace; use crate::ipld::{stream_chain, stream_graph}; use crate::networks::{ChainConfig, NetworkChain, butterflynet, calibnet, mainnet}; +use crate::prelude::*; use crate::shim::address::CurrentNetwork; use crate::shim::clock::{ChainEpoch, EPOCH_DURATION_SECONDS, EPOCHS_IN_DAY}; use crate::shim::executor::{Receipt, StampedEvent}; @@ -48,16 +49,13 @@ use crate::shim::fvm_shared_latest::address::Network; use crate::shim::machine::GLOBAL_MULTI_ENGINE; use crate::state_manager::{ExecutedTipset, NO_CALLBACK, apply_block_messages}; use crate::tool::subcommands::api_cmd::generate_test_snapshot::ReadOpsTrackingStore; -use crate::utils::ShallowClone as _; use crate::utils::db::car_stream::{CarBlock, CarBlockWrite as _, CarStream}; use crate::utils::multihash::MultihashCode; use anyhow::{Context as _, bail}; use chrono::DateTime; -use cid::Cid; use clap::{Subcommand, ValueEnum}; use dialoguer::{Confirm, theme::ColorfulTheme}; use futures::{StreamExt as _, TryStreamExt as _}; -use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::DAG_CBOR; use human_repr::HumanCount as _; use indicatif::{ProgressBar, ProgressIterator, ProgressStyle}; @@ -68,7 +66,6 @@ use std::fs::File; use std::io::{BufReader, Seek as _, SeekFrom}; use std::ops::Range; use std::path::PathBuf; -use std::sync::Arc; use tokio::io::{AsyncWriteExt, BufWriter}; use tracing::info; @@ -265,10 +262,10 @@ impl ArchiveCommands { diff_depth, force, } => { - let store = ManyCar::try_from(snapshot_files)?; + let store = Arc::new(ManyCar::try_from(snapshot_files)?); let heaviest_tipset = store.heaviest_tipset()?; do_export( - &store.into(), + &store, heaviest_tipset, output_path, epoch, @@ -552,8 +549,8 @@ fn build_output_path( } #[allow(clippy::too_many_arguments)] -pub async fn do_export( - store: &Arc, +pub async fn do_export( + store: &DB, root: Tipset, output_path: PathBuf, epoch_option: Option, @@ -561,7 +558,10 @@ pub async fn do_export( diff: Option, diff_depth: Option, force: bool, -) -> anyhow::Result<()> { +) -> anyhow::Result<()> +where + DB: Blockstore + ShallowClone + Into + Unpin + Send + Sync + 'static, +{ let ts = root; let genesis = ts.genesis(store)?; @@ -579,7 +579,7 @@ pub async fn do_export( info!("looking up a tipset by epoch: {}", epoch); - let index = ChainIndex::new(store.clone()); + let index = ChainIndex::new(store.shallow_clone()); let ts = index .load_required_tipset_by_height(epoch, ts, ResolveNullTipset::TakeOlder) @@ -591,9 +591,10 @@ pub async fn do_export( .context("diff epoch must be smaller than target epoch")?; let diff_ts: &Tipset = &diff_ts; let diff_limit = diff_depth.map(|depth| diff_ts.epoch() - depth).unwrap_or(0); + let store = Arc::new(store.shallow_clone()); let mut stream = stream_chain( - store.clone(), - diff_ts.clone().chain_owned(store.clone()), + store.shallow_clone(), + diff_ts.clone().chain_owned(store.shallow_clone()), diff_limit, FileBackedCidHashSet::new_in_temp_dir()?, ); @@ -1021,13 +1022,16 @@ fn upload_to_forest_bucket(path: PathBuf, network: &str, tag: &str) -> anyhow::R } /// Given a block store, export a lite snapshot for a given epoch. -async fn export_lite_snapshot( - store: Arc, +async fn export_lite_snapshot( + store: DB, root: Tipset, network: &str, genesis_timestamp: u64, epoch: ChainEpoch, -) -> anyhow::Result { +) -> anyhow::Result +where + DB: Blockstore + ShallowClone + Into + Unpin + Send + Sync + 'static, +{ let output_path: PathBuf = format_lite_snapshot(network, genesis_timestamp, epoch)?.into(); // Skip if file already exists @@ -1054,13 +1058,16 @@ async fn export_lite_snapshot( } /// Given a block store, export a diff snapshot for a given epoch. -async fn export_diff_snapshot( - store: Arc, +async fn export_diff_snapshot( + store: DB, root: Tipset, network: &str, genesis_timestamp: u64, epoch: ChainEpoch, -) -> anyhow::Result { +) -> anyhow::Result +where + DB: Blockstore + ShallowClone + Into + Unpin + Send + Sync + 'static, +{ let output_path: PathBuf = format_diff_snapshot(network, genesis_timestamp, epoch)?.into(); // Skip if file already exists @@ -1212,13 +1219,15 @@ mod tests { #[tokio::test] async fn export() { let output_path = TempDir::new().unwrap(); - let store: ManyCar = AnyCar::try_from(calibnet::DEFAULT_GENESIS) - .unwrap() - .try_into() - .unwrap(); + let store: Arc = Arc::new( + AnyCar::try_from(calibnet::DEFAULT_GENESIS) + .unwrap() + .try_into() + .unwrap(), + ); let heaviest_tipset = store.heaviest_tipset().unwrap(); do_export( - &store.into(), + &store, heaviest_tipset, output_path.path().into(), Some(0), diff --git a/src/tool/subcommands/index_cmd.rs b/src/tool/subcommands/index_cmd.rs index d1775f8cbfaa..1d6d2c4cde3c 100644 --- a/src/tool/subcommands/index_cmd.rs +++ b/src/tool/subcommands/index_cmd.rs @@ -16,6 +16,7 @@ use crate::db::car::ManyCar; use crate::db::db_engine::{db_root, open_db}; use crate::genesis::read_genesis_header; use crate::networks::NetworkChain; +use crate::prelude::*; use crate::shim::clock::ChainEpoch; use crate::state_manager::StateManager; use crate::tool::offline_server::server::handle_chain_config; @@ -66,8 +67,8 @@ impl IndexCommands { let chain_data_path = chain_path(&config); let db_root_dir = db_root(&chain_data_path)?; - let db_writer = Arc::new(open_db(db_root_dir.clone(), config.db_config())?); - let db = Arc::new(ManyCar::new(db_writer.clone())); + let db_writer = open_db(db_root_dir.clone(), config.db_config())?; + let db = Arc::new(ManyCar::new(db_writer)); let forest_car_db_dir = db_root_dir.join(CAR_DB_DIR_NAME); load_all_forest_cars(&db, &forest_car_db_dir)?; @@ -80,15 +81,9 @@ impl IndexCommands { ) .await?; - let chain_store = Arc::new(ChainStore::new( - db.clone(), - db.clone(), - db.clone(), - chain_config, - genesis_header.clone(), - )?); + let chain_store = ChainStore::new(db, chain_config, genesis_header.clone())?; - let state_manager = Arc::new(StateManager::new(chain_store.clone())?); + let state_manager = StateManager::new(chain_store.shallow_clone())?; let head_ts = chain_store.heaviest_tipset(); diff --git a/src/tool/subcommands/snapshot_cmd.rs b/src/tool/subcommands/snapshot_cmd.rs index a96f4b4a61f4..c114e89f05a2 100644 --- a/src/tool/subcommands/snapshot_cmd.rs +++ b/src/tool/subcommands/snapshot_cmd.rs @@ -9,7 +9,7 @@ use crate::cli_shared::snapshot; use crate::daemon::bundle::load_actor_bundles; use crate::db::car::forest::DEFAULT_FOREST_CAR_FRAME_SIZE; use crate::db::car::{AnyCar, ManyCar}; -use crate::db::{EthMappingsStore, MemoryDB, PersistentStore}; +use crate::db::{DbImpl, MemoryDB, PersistentStore}; use crate::interpreter::{MessageCallbackCtx, VMTrace}; use crate::ipld::stream_chain; use crate::networks::{ChainConfig, NetworkChain, butterflynet, calibnet, mainnet}; @@ -297,7 +297,8 @@ async fn validate_with_blockstore( check_stateroots: u32, ) -> anyhow::Result<()> where - BlockstoreT: PersistentStore + EthMappingsStore + Send + Sync + 'static, + BlockstoreT: PersistentStore + Send + Sync + 'static, + Arc: Into, { if check_links != 0 { validate_ipld_links(root.clone(), &store, check_links).await?; @@ -399,7 +400,8 @@ async fn validate_stateroots( epochs: u32, ) -> anyhow::Result<()> where - DB: PersistentStore + EthMappingsStore + Send + Sync + 'static, + DB: PersistentStore + Send + Sync + 'static, + Arc: Into, { let chain_config = Arc::new(ChainConfig::from_chain(&network)); let genesis = ts.genesis(db)?; diff --git a/src/utils/cache/lru.rs b/src/utils/cache/lru.rs index ea866f0e5e3a..913bcde4fba8 100644 --- a/src/utils/cache/lru.rs +++ b/src/utils/cache/lru.rs @@ -22,7 +22,7 @@ use prometheus_client::{ registry::Unit, }; -use crate::utils::ShallowClone; +use crate::prelude::*; pub trait KeyConstraints: GetSize + Debug + Send + Sync + Hash + PartialEq + Eq + Clone + 'static diff --git a/src/utils/db/car_util.rs b/src/utils/db/car_util.rs index 9a38eb5a910a..7b7002c9a93c 100644 --- a/src/utils/db/car_util.rs +++ b/src/utils/db/car_util.rs @@ -1,8 +1,8 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT +use crate::prelude::*; use futures::{Stream, StreamExt as _, TryStreamExt as _}; -use fvm_ipld_blockstore::Blockstore; use tokio::io::{AsyncBufRead, AsyncSeek, BufReader}; use crate::cid_collections::CidHashSet; @@ -46,11 +46,9 @@ mod tests { use crate::utils::multihash::prelude::*; use ahash::HashSet; use async_compression::tokio::write::ZstdEncoder; - use cid::Cid; use futures::executor::block_on_stream; use futures::{StreamExt, TryStreamExt}; use fvm_ipld_encoding::DAG_CBOR; - use itertools::Itertools; use nunny::{Vec as NonEmpty, vec as nonempty}; use pretty_assertions::assert_eq; use quickcheck::Arbitrary;