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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ env:
FOREST_F3_SIDECAR_FFI_BUILD_OPT_OUT: 1
FIL_PROOFS_PARAMETER_CACHE: /var/tmp/filecoin-proof-parameters
RUST_LOG: error
FOREST_ACTOR_BUNDLE_PATH: /var/tmp/forest_actor_bundle.car.zst

jobs:
codecov:
Expand All @@ -53,7 +54,7 @@ jobs:
- uses: taiki-e/install-action@nextest
- name: Fetch proof params and RPC test snapshots
run: |
cargo run --bin forest-dev --no-default-features --profile quick -- fetch-rpc-tests
cargo run --bin forest-dev --no-default-features --profile quick -- fetch-test-snapshots --actor-bundle $FOREST_ACTOR_BUNDLE_PATH
ls -ahl $FIL_PROOFS_PARAMETER_CACHE
- name: Generate code coverage
run: mise codecov
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ jobs:
uses: taiki-e/install-action@nextest
- name: Fetch proof params and RPC test snapshots
run: |
cargo run --bin forest-dev --no-default-features --profile quick -- fetch-rpc-tests
cargo run --bin forest-dev --no-default-features --profile quick -- fetch-test-snapshots
ls -ahl $FIL_PROOFS_PARAMETER_CACHE
- uses: jdx/mise-action@v3
- run: |
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/users/reference/cli.sh
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ generate_markdown_section "forest-tool" "index backfill"

generate_markdown_section "forest-dev" ""

generate_markdown_section "forest-dev" "fetch-rpc-tests"
generate_markdown_section "forest-dev" "fetch-test-snapshots"

generate_markdown_section "forest-dev" "state"
generate_markdown_section "forest-dev" "state compute"
Expand Down
34 changes: 22 additions & 12 deletions src/benchmark_private/tipset_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,39 @@ pub fn bench_tipset_validation(c: &mut Criterion) {
let mut group = c.benchmark_group("tipset_validation");

group
.bench_function("calibnet@3111900", |b| {
.bench_function("calibnet@3408952", |b| {
let chain = NetworkChain::Calibnet;
let epoch = 3111900;
let (state_manager, ts) = rt
let epoch = 3408952;
let (state_manager, ts, ts_next) = rt
.block_on(async {
let snapshot = get_state_compute_snapshot(&chain, epoch).await?;
prepare_state_compute(&chain, &snapshot, true).await
prepare_state_compute(&chain, &snapshot).await
})
.unwrap();
b.to_async(&rt)
.iter(|| state_compute(black_box(state_manager.clone()), black_box(ts.clone())))
b.to_async(&rt).iter(|| {
state_compute(
black_box(&state_manager),
black_box(ts.clone()),
black_box(&ts_next),
)
})
})
.bench_function("mainnet@5427431", |b| {
.bench_function("mainnet@5709604", |b| {
let chain = NetworkChain::Mainnet;
let epoch = 5427431;
let (state_manager, ts) = rt
let epoch = 5709604;
let (state_manager, ts, ts_next) = rt
.block_on(async {
let snapshot = get_state_compute_snapshot(&chain, epoch).await?;
prepare_state_compute(&chain, &snapshot, true).await
prepare_state_compute(&chain, &snapshot).await
})
.unwrap();
b.to_async(&rt)
.iter(|| state_compute(black_box(state_manager.clone()), black_box(ts.clone())))
b.to_async(&rt).iter(|| {
state_compute(
black_box(&state_manager),
black_box(ts.clone()),
black_box(&ts_next),
)
})
});

group.finish();
Expand Down
4 changes: 4 additions & 0 deletions src/blocks/tipset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,10 @@ impl Tipset {
pub fn parent_state(&self) -> &Cid {
&self.min_ticket_block().state_root
}
/// Returns the message receipt root for the tipset parent.
pub fn parent_message_receipts(&self) -> &Cid {
&self.min_ticket_block().message_receipts
}
/// Returns the tipset's calculated weight
pub fn weight(&self) -> &BigInt {
&self.min_ticket_block().weight
Expand Down
5 changes: 3 additions & 2 deletions src/chain_sync/tipset_syncer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::shim::{
address::Address, crypto::verify_bls_aggregate, econ::BLOCK_GAS_LIMIT,
gas::price_list_by_network_version, message::Message, state_tree::StateTree,
};
use crate::state_manager::StateLookupPolicy;
use crate::state_manager::{Error as StateManagerError, StateManager, utils::is_valid_for_sending};
use crate::{
blocks::{Block, CachingBlockHeader, Error as ForestBlockError, FullTipset, Tipset},
Expand Down Expand Up @@ -278,7 +279,7 @@ async fn validate_block<DB: Blockstore + Sync + Send + 'static>(
async move {
let header = block.header();
let (state_root, receipt_root) = state_manager
.tipset_state(&base_tipset)
.tipset_state(&base_tipset, StateLookupPolicy::Disabled)
.await
.map_err(|e| {
TipsetSyncerError::Calculation(format!("Failed to calculate state: {e}"))
Expand Down Expand Up @@ -439,7 +440,7 @@ async fn check_block_messages<DB: Blockstore + Send + Sync + 'static>(

let mut account_sequences: HashMap<Address, u64> = HashMap::default();
let (state_root, _) = state_manager
.tipset_state(&base_tipset)
.tipset_state(&base_tipset, StateLookupPolicy::Disabled)
.await
.map_err(|e| TipsetSyncerError::Calculation(format!("Could not update state: {e}")))?;
let tree =
Expand Down
26 changes: 22 additions & 4 deletions src/dev/subcommands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
mod state_cmd;

use crate::cli_shared::cli::HELP_MESSAGE;
use crate::networks::generate_actor_bundle;
use crate::rpc::Client;
use crate::utils::net::{DownloadFileOption, download_file_with_cache};
use crate::utils::proofs_api::ensure_proof_params_downloaded;
Expand All @@ -30,26 +31,43 @@ pub struct Cli {
/// forest-dev sub-commands
#[derive(clap::Subcommand)]
pub enum Subcommand {
/// Fetch RPC test snapshots to the local cache
FetchRpcTests,
/// Fetch test snapshots to the local cache
FetchTestSnapshots {
// Save actor bundle to
#[arg(long)]
actor_bundle: Option<PathBuf>,
},
#[command(subcommand)]
State(state_cmd::StateCommand),
}

impl Subcommand {
pub async fn run(self, _client: Client) -> anyhow::Result<()> {
match self {
Self::FetchRpcTests => fetch_rpc_tests().await,
Self::FetchTestSnapshots { actor_bundle } => fetch_test_snapshots(actor_bundle).await,
Self::State(cmd) => cmd.run().await,
}
}
}

async fn fetch_rpc_tests() -> anyhow::Result<()> {
async fn fetch_test_snapshots(actor_bundle: Option<PathBuf>) -> anyhow::Result<()> {
// Prepare proof parameter files
crate::utils::proofs_api::maybe_set_proofs_parameter_cache_dir_env(
&crate::Config::default().client.data_dir,
);
ensure_proof_params_downloaded().await?;

// Prepare actor bundles
if let Some(actor_bundle) = actor_bundle {
generate_actor_bundle(&actor_bundle).await?;
println!("Wrote the actors bundle to {}", actor_bundle.display());
}

// Prepare RPC test snapshots
fetch_rpc_tests().await
}

async fn fetch_rpc_tests() -> anyhow::Result<()> {
let tests = include_str!("../../tool/subcommands/api_cmd/test_snapshots.txt")
.lines()
.map(|i| {
Expand Down
98 changes: 39 additions & 59 deletions src/dev/subcommands/state_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ use crate::{
chain::{ChainStore, index::ResolveNullTipset},
chain_sync::{load_full_tipset, tipset_syncer::validate_tipset},
cli_shared::{chain_path, read_config},
db::{
MemoryDB, SettingsStoreExt,
car::{AnyCar, ManyCar},
db_engine::db_root,
},
db::{SettingsStoreExt, db_engine::db_root},
genesis::read_genesis_header,
interpreter::VMTrace,
networks::{ChainConfig, NetworkChain},
Expand Down Expand Up @@ -73,7 +69,7 @@ impl ComputeCommand {
let (_, config) = read_config(None, Some(chain.clone()))?;
db_root(&chain_path(&config))?
};
let db = generate_test_snapshot::load_db(&db_root_path)?;
let db = generate_test_snapshot::load_db(&db_root_path, Some(&chain)).await?;
let chain_config = Arc::new(ChainConfig::from_chain(&chain));
let genesis_header =
read_genesis_header(None, chain_config.genesis_bytes(&db).await?.as_deref(), &db)
Expand All @@ -85,18 +81,30 @@ impl ComputeCommand {
chain_config,
genesis_header,
)?);
let ts = {
let (ts, ts_next) = {
// We don't want to track all entries that are visited by `tipset_by_height`
db.pause_tracking();
let ts = chain_store.chain_index().tipset_by_height(
epoch,
chain_store.heaviest_tipset(),
ResolveNullTipset::TakeOlder,
)?;
let ts_next = chain_store.chain_index().tipset_by_height(
epoch + 1,
chain_store.heaviest_tipset(),
ResolveNullTipset::TakeNewer,
)?;
db.resume_tracking();
SettingsStoreExt::write_obj(&db.tracker, crate::db::setting_keys::HEAD_KEY, ts.key())?;
// Only track the desired tipset
Tipset::load_required(&db, ts.key())?
SettingsStoreExt::write_obj(
&db.tracker,
crate::db::setting_keys::HEAD_KEY,
ts_next.key(),
)?;
// Only track the desired tipsets
(
Tipset::load_required(&db, ts.key())?,
Tipset::load_required(&db, ts_next.key())?,
)
};
let epoch = ts.epoch();
let state_manager = Arc::new(StateManager::new(chain_store)?);
Expand All @@ -114,6 +122,16 @@ impl ComputeCommand {
"epoch: {epoch}, state_root: {state_root}, receipt_root: {receipt_root}, db_snapshot_size: {}",
human_bytes::human_bytes(db_snapshot.len() as f64)
);
let expected_state_root = *ts_next.parent_state();
let expected_receipt_root = *ts_next.parent_message_receipts();
anyhow::ensure!(
state_root == expected_state_root,
"state root mismatch, state_root: {state_root}, expected_state_root: {expected_state_root}"
);
anyhow::ensure!(
receipt_root == expected_receipt_root,
"receipt root mismatch, receipt_root: {receipt_root}, expected_receipt_root: {expected_receipt_root}"
);
if let Some(export_db_to) = export_db_to {
std::fs::write(export_db_to, db_snapshot)?;
}
Expand All @@ -138,39 +156,12 @@ pub struct ReplayComputeCommand {
impl ReplayComputeCommand {
pub async fn run(self) -> anyhow::Result<()> {
let Self { snapshot, chain, n } = self;
let snap_car = AnyCar::try_from(&snapshot)?;
let ts = snap_car.heaviest_tipset()?;
let epoch = ts.epoch();
let db = Arc::new(ManyCar::new(MemoryDB::default()).with_read_only(snap_car)?);
let chain_config = Arc::new(ChainConfig::from_chain(&chain));
let genesis_header =
read_genesis_header(None, chain_config.genesis_bytes(&db).await?.as_deref(), &db)
let (sm, ts, ts_next) =
crate::state_manager::utils::state_compute::prepare_state_compute(&chain, &snapshot)
.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)?);
for _ in 0..n.get() {
let start = Instant::now();
let StateOutput {
state_root,
receipt_root,
..
} = state_manager
.compute_tipset_state(
ts.clone(),
crate::state_manager::NO_CALLBACK,
VMTrace::NotTraced,
)
crate::state_manager::utils::state_compute::state_compute(&sm, ts.clone(), &ts_next)
.await?;
println!(
"epoch: {epoch}, state_root: {state_root}, receipt_root: {receipt_root}, took {}.",
humantime::format_duration(start.elapsed())
);
}
Ok(())
}
Expand Down Expand Up @@ -208,7 +199,7 @@ impl ValidateCommand {
let (_, config) = read_config(None, Some(chain.clone()))?;
db_root(&chain_path(&config))?
};
let db = generate_test_snapshot::load_db(&db_root_path)?;
let db = generate_test_snapshot::load_db(&db_root_path, Some(&chain)).await?;
let chain_config = Arc::new(ChainConfig::from_chain(&chain));
let genesis_header =
read_genesis_header(None, chain_config.genesis_bytes(&db).await?.as_deref(), &db)
Expand Down Expand Up @@ -267,27 +258,14 @@ pub struct ReplayValidateCommand {
impl ReplayValidateCommand {
pub async fn run(self) -> anyhow::Result<()> {
let Self { snapshot, chain, n } = self;
let snap_car = AnyCar::try_from(&snapshot)?;
let ts = snap_car.heaviest_tipset()?;
let epoch = ts.epoch();
let db = Arc::new(ManyCar::new(MemoryDB::default()).with_read_only(snap_car)?);
let chain_config = Arc::new(ChainConfig::from_chain(&chain));
let genesis_header =
read_genesis_header(None, chain_config.genesis_bytes(&db).await?.as_deref(), &db)
let (sm, fts) =
crate::state_manager::utils::state_compute::prepare_state_validate(&chain, &snapshot)
.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)?);
let fts = load_full_tipset(state_manager.chain_store(), ts.key())?;
let epoch = fts.epoch();
for _ in 0..n.get() {
let fts = fts.clone();
let start = Instant::now();
validate_tipset(&state_manager, fts, None).await?;
validate_tipset(&sm, fts, None).await?;
println!(
"epoch: {epoch}, took {}.",
humantime::format_duration(start.elapsed())
Expand All @@ -298,5 +276,7 @@ impl ReplayValidateCommand {
}

fn disable_tipset_cache() {
unsafe { std::env::set_var("FOREST_TIPSET_CACHE_DISABLED", "1") };
unsafe {
std::env::set_var("FOREST_TIPSET_CACHE_DISABLED", "1");
}
}
Loading
Loading