Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added a new option --validate-tipsets in forest-cli validate command #3167

Merged
merged 43 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
3f7dd03
Added snapshot validate in forest-cli
sudo-shashank Jul 11, 2023
9cbded2
fix chain store init
sudo-shashank Jul 11, 2023
0126282
handle validate options
sudo-shashank Jul 11, 2023
5173f47
make snapshot an option not arg to validate cmd
sudo-shashank Jul 11, 2023
3c6ed92
fmt
sudo-shashank Jul 11, 2023
8fa4d7f
fmt
sudo-shashank Jul 12, 2023
4e925ee
Update changelog.md
sudo-shashank Jul 12, 2023
d904676
update changelog
sudo-shashank Jul 12, 2023
87c9695
fmt
sudo-shashank Jul 12, 2023
08ac01b
Merge branch 'main' into shashank/cli-validate
sudo-shashank Jul 12, 2023
0b18cff
refactor to validate_tipset_range
sudo-shashank Jul 12, 2023
fe4ab34
fix forest-cli test
sudo-shashank Jul 12, 2023
d93e0e9
Merge branch 'main' into shashank/cli-validate
sudo-shashank Jul 12, 2023
5ee781e
fix error handling
sudo-shashank Jul 12, 2023
610fceb
Use snapshot for validating
sudo-shashank Jul 12, 2023
b83aed1
Merge branch 'main' into shashank/cli-validate
sudo-shashank Jul 12, 2023
09154d4
fix error handling
sudo-shashank Jul 12, 2023
744cfdd
update cli check script
sudo-shashank Jul 12, 2023
740dbaa
Merge branch 'main' into shashank/cli-validate
sudo-shashank Jul 12, 2023
242279d
Merge branch 'main' into shashank/cli-validate
sudo-shashank Jul 13, 2023
9414812
added ensure params download
sudo-shashank Jul 13, 2023
fc583f0
fmt
sudo-shashank Jul 13, 2023
529f4e6
Merge branch 'main' into shashank/cli-validate
sudo-shashank Jul 13, 2023
5c355ff
Remove use of import chain
sudo-shashank Jul 13, 2023
8e1f79c
Use a progress bar to indicate status
sudo-shashank Jul 13, 2023
8239955
fmt
sudo-shashank Jul 13, 2023
b8fe557
cleanup
sudo-shashank Jul 13, 2023
44c511f
remove progressbar and other cleanup
sudo-shashank Jul 14, 2023
7bd3d22
Add chain method in Tipset
sudo-shashank Jul 14, 2023
6971ab7
Merge branch 'main' into shashank/cli-validate
sudo-shashank Jul 14, 2023
51700e2
chain to consume self
sudo-shashank Jul 14, 2023
27bd174
Remove Arc from chain method
sudo-shashank Jul 14, 2023
1419e83
remove more Arc
sudo-shashank Jul 14, 2023
20719e3
Cleanup
sudo-shashank Jul 14, 2023
65c3c1e
minor improvements
sudo-shashank Jul 14, 2023
40da2ec
fmt
sudo-shashank Jul 14, 2023
26bd1a2
fix error handling
sudo-shashank Jul 14, 2023
1b3d6dc
fix clippy error
sudo-shashank Jul 14, 2023
5510b61
Merge branch 'main' into shashank/cli-validate
sudo-shashank Jul 14, 2023
133789d
cleanup
sudo-shashank Jul 14, 2023
950b99d
fmt
sudo-shashank Jul 14, 2023
5ead43a
minor corrections
sudo-shashank Jul 14, 2023
721da03
Remove reference
sudo-shashank Jul 14, 2023
File filter

Filter by extension

Filter by extension

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

### Added

- [#3167](https://github.com/ChainSafe/forest/pull/3167): Added a new option
`--validate-tipsets` for `forest-cli snapshot validate`.
- [#3166](https://github.com/ChainSafe/forest/issues/3166): Add
`forest-cli archive info` command for inspecting archives.
- [#3159](https://github.com/ChainSafe/forest/issues/3159): Add
Expand Down
2 changes: 1 addition & 1 deletion scripts/tests/forest_cli_check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pushd "$(mktemp --directory)"

validate_me=$(find . -type f | head -1)
: : validating under calibnet chain should succeed
"$FOREST_CLI_PATH" --chain calibnet snapshot validate "$validate_me"
"$FOREST_CLI_PATH" --chain calibnet snapshot validate "$validate_me" --validate-tipsets=-1000

: : validating under mainnet chain should fail
if "$FOREST_CLI_PATH" --chain mainnet snapshot validate "$validate_me"; then
Expand Down
9 changes: 9 additions & 0 deletions src/blocks/tipset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,15 @@ impl Tipset {
}
broken
}
/// Returns an iterator of all tipsets
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of all ancestor tipsets

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since it includes itself also, @lemmih suggested we keep it to Returns an iterator of all tipsets

pub fn chain(self, store: impl Blockstore) -> impl Iterator<Item = Tipset> {
itertools::unfold(Some(self), move |tipset| {
tipset.take().map(|child| {
*tipset = Tipset::load(&store, child.parents()).ok().flatten();
child
})
})
}
}

/// `FullTipset` is an expanded version of a tipset that contains all the blocks
Expand Down
60 changes: 48 additions & 12 deletions src/cli/subcommands/snapshot_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ use crate::car_backed_blockstore::{
use crate::chain::ChainStore;
use crate::cli::subcommands::{cli_error_and_die, handle_rpc_err};
use crate::cli_shared::snapshot::{self, TrustedVendor};
use crate::fil_cns::composition as cns;
use crate::genesis::read_genesis_header;
use crate::ipld::{recurse_links_hash, CidHashSet};
use crate::networks::NetworkChain;
use crate::rpc_api::{chain_api::ChainExportParams, progress_api::GetProgressType};
use crate::rpc_client::{chain_ops::*, progress_ops::get_progress};
use crate::shim::clock::ChainEpoch;
use crate::utils::io::ProgressBar;
use anyhow::bail;
use crate::state_manager::StateManager;
use crate::utils::{io::ProgressBar, proofs_api::paramfetch::ensure_params_downloaded};
use anyhow::{bail, Context};
use chrono::Utc;
use clap::Subcommand;
use fvm_ipld_blockstore::Blockstore;
Expand Down Expand Up @@ -56,6 +58,10 @@ pub enum SnapshotCommands {
/// Number of block headers to validate from the tip
#[arg(long, default_value = "2000")]
recent_stateroots: i64,
/// Validate already computed tipsets at given EPOCH,
/// use a negative value -N to validate the last N EPOCH(s) starting at HEAD.
#[arg(long)]
validate_tipsets: Option<i64>,
/// Path to a snapshot CAR, which may be zstd compressed
snapshot: PathBuf,
},
Expand Down Expand Up @@ -157,6 +163,7 @@ impl SnapshotCommands {
}
Self::Validate {
recent_stateroots,
validate_tipsets,
snapshot,
} => {
// this is all blocking...
Expand All @@ -168,6 +175,7 @@ impl SnapshotCommands {
store.roots(),
Arc::new(store),
recent_stateroots,
*validate_tipsets,
)
.await
}
Expand All @@ -187,6 +195,7 @@ impl SnapshotCommands {
store.roots(),
Arc::new(store),
recent_stateroots,
*validate_tipsets,
)
.await
}
Expand Down Expand Up @@ -240,42 +249,71 @@ async fn validate_with_blockstore<BlockstoreT>(
roots: Vec<Cid>,
store: Arc<BlockstoreT>,
recent_stateroots: &i64,
) -> Result<(), anyhow::Error>
validate_tipsets: Option<i64>,
) -> anyhow::Result<()>
where
BlockstoreT: Blockstore + Send + Sync,
BlockstoreT: Blockstore + Send + Sync + 'static,
{
let genesis = read_genesis_header(
config.client.genesis_file.as_ref(),
config.chain.genesis_bytes(),
&store,
)
.await?;

let chain_data_root = TempDir::new()?;
let chain_store = Arc::new(ChainStore::new(
store,
Arc::clone(&store),
config.chain.clone(),
&genesis,
TempDir::new()?.path(),
chain_data_root.path(),
)?);

let ts = chain_store.tipset_from_keys(&TipsetKeys::new(roots))?;
let ts = Tipset::load(&store, &TipsetKeys::new(roots))?.context("missing root tipset")?;

validate_links_and_genesis_traversal(
&chain_store,
ts,
&ts,
chain_store.blockstore(),
*recent_stateroots,
&Tipset::from(genesis),
&config.chain.network,
)
.await?;

if let Some(validate_from) = validate_tipsets {
let last_epoch = match validate_from.is_negative() {
true => ts.epoch() + validate_from,
false => validate_from,
};
// Set proof parameter data dir
if cns::FETCH_PARAMS {
crate::utils::proofs_api::paramfetch::set_proofs_parameter_cache_dir_env(
&config.client.data_dir,
);
}
// Initialize StateManager
let state_manager = Arc::new(StateManager::new(
chain_store,
Arc::clone(&config.chain),
Arc::new(crate::interpreter::RewardActorMessageCalc),
)?);
ensure_params_downloaded().await?;
// Prepare tipset stream to validate
let tipsets = ts
.chain(&store)
.map(|ts| Arc::clone(&Arc::new(ts)))
.take_while(|tipset| tipset.epoch() >= last_epoch);

state_manager.validate_tipsets(tipsets)?
}

println!("Snapshot is valid");
Ok(())
}

async fn validate_links_and_genesis_traversal<DB>(
chain_store: &ChainStore<DB>,
ts: Arc<Tipset>,
ts: &Tipset,
db: &DB,
recent_stateroots: ChainEpoch,
genesis_tipset: &Tipset,
Expand Down Expand Up @@ -340,7 +378,5 @@ where

drop(pb);

println!("Snapshot is valid");

Ok(())
}
6 changes: 4 additions & 2 deletions src/daemon/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,10 @@ pub(super) async fn start(
assert!(current_height.is_positive());
match validate_from.is_negative() {
// allow --height=-1000 to scroll back from the current head
true => state_manager.validate((current_height + validate_from)..=current_height)?,
false => state_manager.validate(validate_from..=current_height)?,
true => {
state_manager.validate_range((current_height + validate_from)..=current_height)?
}
false => state_manager.validate_range(validate_from..=current_height)?,
}
}

Expand Down
16 changes: 11 additions & 5 deletions src/state_manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1250,9 +1250,7 @@ where
/// This function is blocking, but we do observe threads waiting and synchronizing.
/// This is suspected to be due something in the VM or its `WASM` runtime.
#[tracing::instrument(skip(self))]
pub fn validate(self: &Arc<Self>, epochs: RangeInclusive<i64>) -> anyhow::Result<()> {
use rayon::iter::ParallelIterator as _;

pub fn validate_range(self: &Arc<Self>, epochs: RangeInclusive<i64>) -> anyhow::Result<()> {
let heaviest = self.cs.heaviest_tipset();
let heaviest_epoch = heaviest.epoch();
let end = self
Expand All @@ -1269,10 +1267,18 @@ where
// if this has parents, unfold them in the next iteration
*tipset = self.cs.tipset_from_keys(child.parents()).ok();
Some(child)
});
})
.take_while(|tipset| tipset.epoch() >= *epochs.start());

self.validate_tipsets(tipsets)
}

pub fn validate_tipsets<T>(self: &Arc<Self>, tipsets: T) -> anyhow::Result<()>
where
T: Iterator<Item = Arc<Tipset>> + Send,
{
use rayon::iter::ParallelIterator as _;
tipsets
.take_while(|tipset| tipset.epoch() >= *epochs.start())
.tuple_windows()
.par_bridge()
.try_for_each(|(child, parent)| {
Expand Down