Skip to content

Commit

Permalink
proofs api refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
LesnyRumcajs committed Apr 10, 2024
1 parent 6637e24 commit caa81b3
Show file tree
Hide file tree
Showing 8 changed files with 238 additions and 153 deletions.
3 changes: 3 additions & 0 deletions .config/forest.dic
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ CARv2/SM
CBOR
CID/SM
CIDs
ChainSafe
CLI
Cloudflare
clonable
Expand Down Expand Up @@ -73,6 +74,7 @@ param/SM
ParityDb
ParityDB
parsable
performant
PoC
pointer/SM
PoSt
Expand All @@ -99,6 +101,7 @@ tipset/SM
tipsetkey/S
TOML
trie
truthy
TTY
uncompress
unrepresentable
Expand Down
18 changes: 10 additions & 8 deletions documentation/src/environment_variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ Besides CLI options and the configuration values in the configuration file,
there are some environment variables that control the behaviour of a `forest`
process.

| Environment variable | Value | Default | Description |
| ------------------------------- | -------------------------------- | ------- | ------------------------------------------------------------------------- |
| FOREST_KEYSTORE_PHRASE | any text | empty | The passphrase for the encrypted keystore |
| FOREST_CAR_LOADER_FILE_IO | 1 or true | false | Load CAR files with `RandomAccessFile` instead of `Mmap` |
| FOREST_DB_DEV_MODE | [see here](#-forest_db_dev_mode) | current | The database to use in development mode |
| FOREST_ACTOR_BUNDLE_PATH | file path | empty | Path to the local actor bundle, download from remote servers when not set |
| FIL_PROOFS_PARAMETER_CACHE | dir path | empty | Path to folder that caches fil proof parameter files |
| FOREST_PROOFS_ONLY_IPFS_GATEWAY | 1 or true | false | Use only IPFS gateway for proofs parameters download |
| Environment variable | Value | Default | Description |
| ------------------------------- | -------------------------------- | -------------------------------- | ------------------------------------------------------------------------- |
| FOREST_KEYSTORE_PHRASE | any text | empty | The passphrase for the encrypted keystore |
| FOREST_CAR_LOADER_FILE_IO | 1 or true | false | Load CAR files with `RandomAccessFile` instead of `Mmap` |
| FOREST_DB_DEV_MODE | [see here](#-forest_db_dev_mode) | current | The database to use in development mode |
| FOREST_ACTOR_BUNDLE_PATH | file path | empty | Path to the local actor bundle, download from remote servers when not set |
| FIL_PROOFS_PARAMETER_CACHE | dir path | empty | Path to folder that caches fil proof parameter files |
| FOREST_PROOFS_ONLY_IPFS_GATEWAY | 1 or true | false | Use only IPFS gateway for proofs parameters download |
| TRUST_PARAMS | 1 or true | false | Trust the parameters downloaded from the Cloudflare/IPFS |
| IPFS_GATEWAY | URL | https://proofs.filecoin.io/ipfs/ | The IPFS gateway to use for downloading proofs parameters |

### FOREST_DB_DEV_MODE

Expand Down
6 changes: 2 additions & 4 deletions src/daemon/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use crate::shim::clock::ChainEpoch;
use crate::shim::version::NetworkVersion;
use crate::state_manager::StateManager;
use crate::utils::{
monitoring::MemStatsTracker, proofs_api::paramfetch::ensure_params_downloaded,
monitoring::MemStatsTracker, proofs_api::ensure_params_downloaded,
version::FOREST_VERSION_STRING,
};
use anyhow::{bail, Context as _};
Expand Down Expand Up @@ -380,9 +380,7 @@ pub(super) async fn start(

// Sets proof parameter file download path early, the files will be checked and
// downloaded later right after snapshot import step
crate::utils::proofs_api::paramfetch::set_proofs_parameter_cache_dir_env(
&config.client.data_dir,
);
crate::utils::proofs_api::set_proofs_parameter_cache_dir_env(&config.client.data_dir);

// Sets the latest snapshot if needed for downloading later
let mut config = config;
Expand Down
2 changes: 1 addition & 1 deletion src/tool/subcommands/fetch_params_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use std::path::PathBuf;

use crate::shim::sector::SectorSize;
use crate::utils::proofs_api::paramfetch::{get_params_default, SectorSizeOpt};
use crate::utils::proofs_api::{get_params_default, SectorSizeOpt};

use crate::cli::subcommands::cli_error_and_die;
use crate::cli_shared::read_config;
Expand Down
4 changes: 2 additions & 2 deletions src/tool/subcommands/snapshot_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::shim::fvm_shared_latest::address::Network;
use crate::shim::machine::MultiEngine;
use crate::state_manager::apply_block_messages;
use crate::utils::db::car_stream::CarStream;
use crate::utils::proofs_api::paramfetch::ensure_params_downloaded;
use crate::utils::proofs_api::ensure_params_downloaded;
use anyhow::{bail, Context as _};
use cid::Cid;
use clap::Subcommand;
Expand Down Expand Up @@ -354,7 +354,7 @@ where
load_actor_bundles(&db, &network).await?;

// Set proof parameter data dir and make sure the proofs are available
crate::utils::proofs_api::paramfetch::set_proofs_parameter_cache_dir_env(
crate::utils::proofs_api::set_proofs_parameter_cache_dir_env(
&Config::default().client.data_dir,
);

Expand Down
14 changes: 13 additions & 1 deletion src/utils/proofs_api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
// Copyright 2019-2024 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

pub mod paramfetch;
mod parameters;
mod paramfetch;

pub use parameters::set_proofs_parameter_cache_dir_env;
pub use paramfetch::{ensure_params_downloaded, get_params_default, SectorSizeOpt};

/// Check if the given environment variable is set to truthy value.
fn is_env_truthy(env: &str) -> bool {
match std::env::var(env) {
Ok(var) => matches!(var.to_lowercase().as_str(), "1" | "true"),
_ => false,
}
}
156 changes: 156 additions & 0 deletions src/utils/proofs_api/parameters.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// Copyright 2019-2024 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT
//! This module contains the logic for storing and verifying the proofs parameters.
//!
//! The parameters are fetched from the network and stored in the cache directory. The cache directory can be set
//! using the [`PROOFS_PARAMETER_CACHE_ENV`] environment variable. If not set, the default directory is used.

use std::{
fs::File as SyncFile,
io::{self, copy as sync_copy, BufReader as SyncBufReader},
path::{Path, PathBuf},
};

use ahash::HashMap;
use anyhow::{bail, Context};
use blake2b_simd::{Hash, State as Blake2b};
use cid::Cid;
use serde::{Deserialize, Serialize};
use tracing::{debug, warn};

use super::is_env_truthy;

const PROOF_DIGEST_LEN: usize = 16;

/// Environment variable that allows skipping checksum verification of the parameter files.
const TRUST_PARAMS_ENV: &str = "TRUST_PARAMS";

/// Environment variable to set the directory where proofs parameters are stored. Defaults to
/// [`PARAM_DIR`] in the data directory.
pub(super) const PROOFS_PARAMETER_CACHE_ENV: &str = "FIL_PROOFS_PARAMETER_CACHE";

/// Default directory name for storing proofs parameters.
const PARAM_DIR: &str = "filecoin-proof-parameters";

/// Default parameters, as outlined in Lotus `v1.26.2`.
/// <https://github.com/filecoin-project/filecoin-ffi/blob/b715c9403faf919e95fdc702cd651e842f18d890/parameters.json>
pub(super) const DEFAULT_PARAMETERS: &str = include_str!("./parameters.json");

/// Map of parameter data, to be deserialized from the parameter file.
pub(super) type ParameterMap = HashMap<String, ParameterData>;

/// Data structure for retrieving the proof parameter data from provided JSON.
#[derive(Debug, Deserialize, Serialize, Clone)]
pub(super) struct ParameterData {
#[serde(with = "crate::lotus_json::stringify")]
pub cid: Cid,
#[serde(with = "hex::serde")]
pub digest: [u8; PROOF_DIGEST_LEN],
pub sector_size: u64,
}

/// Ensures the parameter file is downloaded and has the correct checksum.
/// This behavior can be disabled by setting the [`TRUST_PARAMS_ENV`] environment variable to 1.
pub(super) async fn check_parameter_file(path: &Path, info: &ParameterData) -> anyhow::Result<()> {
if is_env_truthy(TRUST_PARAMS_ENV) {
warn!("Assuming parameter files are okay. Do not use in production!");
return Ok(());
}

let hash = tokio::task::spawn_blocking({
let file = SyncFile::open(path)?;
move || -> Result<Hash, io::Error> {
let mut reader = SyncBufReader::new(file);
let mut hasher = Blake2b::new();
sync_copy(&mut reader, &mut hasher)?;
Ok(hasher.finalize())
}
})
.await??;

let hash_chunk = hash
.as_bytes()
.get(..PROOF_DIGEST_LEN)
.context("invalid digest length")?;
if info.digest == hash_chunk {
debug!("Parameter file {:?} is ok", path);
Ok(())
} else {
bail!(
"Checksum mismatch in param file {:?}. ({:x?} != {:x?})",
path,
hash_chunk,
info.digest,
)
}
}

// Proof parameter file directory. Defaults to
// %DATA_DIR/filecoin-proof-parameters unless the FIL_PROOFS_PARAMETER_CACHE
// environment variable is set.
pub(super) fn param_dir(data_dir: &Path) -> PathBuf {
std::env::var(PathBuf::from(PROOFS_PARAMETER_CACHE_ENV))
.map(PathBuf::from)
.unwrap_or_else(|_| data_dir.join(PARAM_DIR))
}

/// Forest uses a set of external crates for verifying the proofs generated by
/// the miners. These external crates require a specific set of parameter files
/// to be located at in a specific folder. By default, it is
/// `/var/tmp/filecoin-proof-parameters` but it can be overridden by the
/// `FIL_PROOFS_PARAMETER_CACHE` environment variable. Forest will automatically
/// download the parameter files from Cloudflare/IPFS and verify their validity. For
/// consistency, Forest will prefer to download the files it's local data
/// directory. To this end, the `FIL_PROOFS_PARAMETER_CACHE` environment
/// variable is updated before the parameters are downloaded.
///
/// More information available here: <https://github.com/filecoin-project/rust-fil-proofs#parameter-file-location>
pub fn set_proofs_parameter_cache_dir_env(data_dir: &Path) {
std::env::set_var(PROOFS_PARAMETER_CACHE_ENV, param_dir(data_dir));
}

#[cfg(test)]
mod tests {
use super::*;

#[tokio::test]
async fn test_proof_file_check() {
let tempfile = tempfile::Builder::new().tempfile().unwrap();
let path = tempfile.path();

let data = b"Cthulhu fhtagn!";
std::fs::write(path, data).unwrap();

let mut hasher = Blake2b::new();
hasher.update(data);
let digest = hasher
.finalize()
.as_bytes()
.get(..PROOF_DIGEST_LEN)
.unwrap()
.to_owned();

let param_data = ParameterData {
cid: Cid::default(),
digest: digest.try_into().unwrap(),
sector_size: 32,
};

check_parameter_file(path, &param_data).await.unwrap()
}

#[tokio::test]
async fn test_proof_file_check_no_file() {
let param_data = ParameterData {
cid: Cid::default(),
digest: [0; PROOF_DIGEST_LEN],
sector_size: 32,
};

let path = Path::new("cthulhuazathoh.dagon");
let ret = check_parameter_file(path, &param_data).await;
assert!(
ret.unwrap_err().downcast_ref::<io::Error>().unwrap().kind() == io::ErrorKind::NotFound
);
}
}
Loading

0 comments on commit caa81b3

Please sign in to comment.