Skip to content
Open
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
24 changes: 23 additions & 1 deletion src/dev/subcommands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ mod state_cmd;
use crate::cli_shared::cli::HELP_MESSAGE;
use crate::networks::generate_actor_bundle;
use crate::rpc::Client;
use crate::state_manager::utils::state_compute::{
get_state_snapshot_file, list_state_snapshot_files,
};
use crate::utils::net::{DownloadFileOption, download_file_with_cache};
use crate::utils::proofs_api::ensure_proof_params_downloaded;
use crate::utils::version::FOREST_VERSION_STRING;
Expand Down Expand Up @@ -63,8 +66,27 @@ async fn fetch_test_snapshots(actor_bundle: Option<PathBuf>) -> anyhow::Result<(
println!("Wrote the actors bundle to {}", actor_bundle.display());
}

// Prepare state computation and validation snapshots
fetch_state_tests().await?;

// Prepare RPC test snapshots
fetch_rpc_tests().await
fetch_rpc_tests().await?;

Ok(())
}

pub async fn fetch_state_tests() -> anyhow::Result<()> {
let files = list_state_snapshot_files().await?;
let mut joinset = JoinSet::new();
for file in files {
joinset.spawn(async move { get_state_snapshot_file(&file).await });
}
for result in joinset.join_all().await {
if let Err(e) = result {
tracing::warn!("{e}");
}
}
Ok(())
}

async fn fetch_rpc_tests() -> anyhow::Result<()> {
Expand Down
60 changes: 52 additions & 8 deletions src/state_manager/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,11 @@ pub mod state_compute {
sync::{Arc, LazyLock},
time::{Duration, Instant},
};
use tokio::io::AsyncReadExt;
use url::Url;

const DO_SPACE_ROOT: &str = "https://forest-snapshots.fra1.cdn.digitaloceanspaces.com/";

#[allow(dead_code)]
pub async fn get_state_compute_snapshot(
chain: &NetworkChain,
Expand All @@ -209,12 +212,25 @@ pub mod state_compute {
get_state_snapshot(chain, "state_compute", epoch).await
}

#[allow(dead_code)]
async fn get_state_validate_snapshot(
chain: &NetworkChain,
epoch: i64,
) -> anyhow::Result<PathBuf> {
get_state_snapshot(chain, "state_validate", epoch).await
}

#[allow(dead_code)]
pub async fn get_state_snapshot(
chain: &NetworkChain,
bucket: &str,
epoch: i64,
) -> anyhow::Result<PathBuf> {
let file = format!("{bucket}/{chain}_{epoch}.forest.car.zst");
get_state_snapshot_file(&file).await
}

pub async fn get_state_snapshot_file(file: &str) -> anyhow::Result<PathBuf> {
static SNAPSHOT_CACHE_DIR: LazyLock<PathBuf> = LazyLock::new(|| {
let project_dir = ProjectDirs::from("com", "ChainSafe", "Forest");
project_dir
Expand All @@ -223,9 +239,7 @@ pub mod state_compute {
.join("state_compute_snapshots")
});

let url = Url::parse(&format!(
"https://forest-snapshots.fra1.cdn.digitaloceanspaces.com/{bucket}/{chain}_{epoch}.forest.car.zst"
))?;
let url = Url::parse(&format!("{DO_SPACE_ROOT}{file}"))?;
Ok(crate::utils::retry(
crate::utils::RetryArgs {
timeout: Some(Duration::from_secs(30)),
Expand Down Expand Up @@ -307,6 +321,35 @@ pub mod state_compute {
Ok(())
}

pub async fn list_state_snapshot_files() -> anyhow::Result<Vec<String>> {
let url = Url::parse(&format!("{DO_SPACE_ROOT}?format=json&prefix=state_"))?;
let mut json_str = String::new();
crate::utils::net::reader(url.as_str(), DownloadFileOption::NonResumable, None)
.await?
.read_to_string(&mut json_str)
.await?;
if let justjson::Value::Object(obj) = justjson::Value::from_json(&json_str)? {
let files = obj
.iter()
.filter_map(|i| {
if i.key.as_str() == Some("Contents")
&& let justjson::Value::Array(arr) = &i.value
&& let Some(justjson::Value::String(s)) = arr.first()
&& let Some(file) = s.as_str()
&& file.ends_with(".car.zst")
{
Some(file.to_string())
} else {
None
}
})
.collect();
Ok(files)
} else {
Ok(vec![])
}
}

#[cfg(test)]
mod tests {
//!
Expand All @@ -316,11 +359,12 @@ pub mod state_compute {
use super::*;
use crate::chain_sync::tipset_syncer::validate_tipset;

async fn get_state_validate_snapshot(
chain: &NetworkChain,
epoch: i64,
) -> anyhow::Result<PathBuf> {
get_state_snapshot(chain, "state_validate", epoch).await
#[tokio::test(flavor = "multi_thread")]
async fn test_list_state_snapshot_files() {
let files = list_state_snapshot_files().await.unwrap();
println!("{files:?}");
assert!(!files.is_empty());
get_state_snapshot_file(&files[0]).await.unwrap();
}

// FVM@4
Expand Down
Loading