diff --git a/fil-proofs-tooling/src/bin/benchy/main.rs b/fil-proofs-tooling/src/bin/benchy/main.rs index 777e9ff62..f1123e105 100644 --- a/fil-proofs-tooling/src/bin/benchy/main.rs +++ b/fil-proofs-tooling/src/bin/benchy/main.rs @@ -5,9 +5,9 @@ use std::str::FromStr; use anyhow::Result; use byte_unit::Byte; -use clap::{Arg, Command}; +use clap::{builder::PossibleValuesParser, Arg, ArgMatches, Command}; -use storage_proofs_core::api_version::ApiVersion; +use storage_proofs_core::api_version::{ApiFeature, ApiVersion}; mod hash_fns; mod merkleproofs; @@ -16,6 +16,17 @@ mod window_post; mod window_post_fake; mod winning_post; +const API_FEATURES: [&str; 2] = ["synthetic-porep", "non-interactive-porep"]; + +fn parse_api_features(m: &ArgMatches) -> Result> { + match m.get_many::("api_features") { + Some(api_features) => api_features + .map(|api_feature| ApiFeature::from_str(api_feature)) + .collect::>(), + None => Ok(Vec::new()), + } +} + fn main() -> Result<()> { fil_logger::init(); @@ -87,10 +98,12 @@ fn main() -> Result<()> { .takes_value(true), ) .arg( - Arg::new("synthetic") - .long("synthetic") - .help("Use Synthetic PoRep (default: false)") - .takes_value(false), + Arg::new("api_features") + .long("api-features") + .value_delimiter(',') + .value_parser(PossibleValuesParser::new(API_FEATURES)) + .help("The api_features to use, comma separated (e.g. synthetic-porep)") + .takes_value(true), ) .arg( Arg::new("api_version") @@ -116,10 +129,12 @@ fn main() -> Result<()> { .takes_value(false), ) .arg( - Arg::new("synthetic") - .long("synthetic") - .help("Use Synthetic PoRep (default: false)") - .takes_value(false), + Arg::new("api_features") + .long("api-features") + .value_delimiter(',') + .value_parser(PossibleValuesParser::new(API_FEATURES)) + .help("The api_features to use, comma separated (e.g. synthetic-porep)") + .takes_value(true), ) .arg( Arg::new("api_version") @@ -145,10 +160,12 @@ fn main() -> Result<()> { .takes_value(false), ) .arg( - Arg::new("synthetic") - .long("synthetic") - .help("Use Synthetic PoRep (default: false)") - .takes_value(false), + Arg::new("api_features") + .long("api-features") + .value_delimiter(',') + .value_parser(PossibleValuesParser::new(API_FEATURES)) + .help("The api_features to use, comma separated (e.g. synthetic-porep)") + .takes_value(true), ) .arg( Arg::new("api_version") @@ -229,10 +246,12 @@ fn main() -> Result<()> { .takes_value(true), ) .arg( - Arg::new("synthetic") - .long("synthetic") - .help("Use Synthetic PoRep (default: false)") - .takes_value(false), + Arg::new("api_features") + .long("api-features") + .value_delimiter(',') + .value_parser(PossibleValuesParser::new(API_FEATURES)) + .help("The api_features to use, comma separated (e.g. synthetic-porep)") + .takes_value(true), ) .arg( Arg::new("api_version") @@ -291,7 +310,7 @@ fn main() -> Result<()> { let cache_dir = m.value_of_t::("cache")?; let sector_size = Byte::from_str(m.value_of_t::("size")?)?.get_bytes() as usize; let api_version = ApiVersion::from_str(&m.value_of_t::("api_version")?)?; - let use_synthetic = m.is_present("synthetic"); + let api_features = parse_api_features(m)?; let task_numbers = m.value_of_t::("task_numbers")?; if task_numbers == 1 { @@ -305,7 +324,7 @@ fn main() -> Result<()> { skip_commit_phase1, skip_commit_phase2, test_resume, - use_synthetic, + api_features, )?; } else { let cache_dir: Vec<&str> = cache_dir.split(',').collect(); @@ -315,6 +334,7 @@ fn main() -> Result<()> { let mut children = Vec::new(); for dir in cache_dir.iter().take(task_numbers) { let task_dir = String::from(*dir); + let api_features_clone = api_features.clone(); let t = std::thread::spawn(move || { window_post::run( sector_size, @@ -326,7 +346,7 @@ fn main() -> Result<()> { skip_commit_phase1, skip_commit_phase2, test_resume, - use_synthetic, + api_features_clone, ) .expect("window_post run error"); }); @@ -342,15 +362,15 @@ fn main() -> Result<()> { let sector_size = Byte::from_str(m.value_of_t::("size")?)?.get_bytes() as usize; let fake_replica = m.is_present("fake"); let api_version = ApiVersion::from_str(&m.value_of_t::("api_version")?)?; - let use_synthetic = m.is_present("synthetic"); - winning_post::run(sector_size, fake_replica, api_version, use_synthetic)?; + let api_features = parse_api_features(m)?; + winning_post::run(sector_size, fake_replica, api_version, api_features)?; } Some(("window-post-fake", m)) => { let sector_size = Byte::from_str(m.value_of_t::("size")?)?.get_bytes() as usize; let fake_replica = m.is_present("fake"); let api_version = ApiVersion::from_str(&m.value_of_t::("api_version")?)?; - let use_synthetic = m.is_present("synthetic"); - window_post_fake::run(sector_size, fake_replica, api_version, use_synthetic)?; + let api_features = parse_api_features(m)?; + window_post_fake::run(sector_size, fake_replica, api_version, api_features)?; } Some(("hash-constraints", _m)) => { hash_fns::run()?; @@ -372,11 +392,12 @@ fn main() -> Result<()> { let cache_dir = m.value_of_t::("cache")?; let sector_size = Byte::from_str(m.value_of_t::("size")?)?.get_bytes() as usize; let api_version = ApiVersion::from_str(&m.value_of_t::("api_version")?)?; - let use_synthetic = m.is_present("synthetic"); + let api_features = parse_api_features(m)?; porep::run( sector_size, api_version, + api_features, cache_dir, preserve_cache, skip_precommit_phase1, @@ -384,7 +405,6 @@ fn main() -> Result<()> { skip_commit_phase1, skip_commit_phase2, test_resume, - use_synthetic, )?; } _ => unreachable!(), diff --git a/fil-proofs-tooling/src/bin/benchy/porep.rs b/fil-proofs-tooling/src/bin/benchy/porep.rs index 9ca7f5e79..b81337559 100644 --- a/fil-proofs-tooling/src/bin/benchy/porep.rs +++ b/fil-proofs-tooling/src/bin/benchy/porep.rs @@ -314,6 +314,7 @@ fn run_pre_commit_phases( pub fn run_porep_bench( sector_size: u64, api_version: ApiVersion, + api_features: Vec, cache_dir: PathBuf, preserve_cache: bool, skip_precommit_phase1: bool, @@ -321,14 +322,7 @@ pub fn run_porep_bench( skip_commit_phase1: bool, skip_commit_phase2: bool, test_resume: bool, - use_synthetic: bool, ) -> anyhow::Result<()> { - let features = if use_synthetic { - vec![ApiFeature::SyntheticPoRep] - } else { - Vec::new() - }; - let ( (seal_pre_commit_phase1_cpu_time_ms, seal_pre_commit_phase1_wall_time_ms), ( @@ -348,7 +342,7 @@ pub fn run_porep_bench( skip_precommit_phase2, test_resume, false, // skip staging - features.clone(), + api_features.clone(), ) }?; @@ -384,7 +378,7 @@ pub fn run_porep_bench( let seed = [1u8; 32]; let sector_id = SectorId::from(SECTOR_ID); - let porep_config = shared::get_porep_config(sector_size, api_version, features); + let porep_config = shared::get_porep_config(sector_size, api_version, api_features); let sealed_file_path = cache_dir.join(SEALED_FILE); @@ -393,7 +387,7 @@ pub fn run_porep_bench( validate_cache_for_commit_wall_time_ms, seal_commit_phase1_cpu_time_ms, seal_commit_phase1_wall_time_ms, - ) = if skip_commit_phase1 && !use_synthetic { + ) = if skip_commit_phase1 && !porep_config.feature_enabled(ApiFeature::SyntheticPoRep) { // generate no-op measurements (0, 0, 0, 0) } else { @@ -535,6 +529,7 @@ pub fn run_porep_bench( pub fn run( sector_size: usize, api_version: ApiVersion, + api_features: Vec, cache: String, preserve_cache: bool, skip_precommit_phase1: bool, @@ -542,9 +537,13 @@ pub fn run( skip_commit_phase1: bool, skip_commit_phase2: bool, test_resume: bool, - use_synthetic: bool, ) -> anyhow::Result<()> { - info!("Benchy PoRep: sector-size={}, api_version={}, preserve_cache={}, skip_precommit_phase1={}, skip_precommit_phase2={}, skip_commit_phase1={}, skip_commit_phase2={}, test_resume={}, use_synthetic={}", sector_size, api_version, preserve_cache, skip_precommit_phase1, skip_precommit_phase2, skip_commit_phase1, skip_commit_phase2, test_resume, use_synthetic); + let api_features_str = api_features + .iter() + .map(|api_feature| api_feature.to_string()) + .collect::>() + .join(","); + info!("Benchy PoRep: sector-size={}, api_version={}, preserve_cache={}, skip_precommit_phase1={}, skip_precommit_phase2={}, skip_commit_phase1={}, skip_commit_phase2={}, test_resume={}, use_synthetic={}", sector_size, api_version, preserve_cache, skip_precommit_phase1, skip_precommit_phase2, skip_commit_phase1, skip_commit_phase2, test_resume, api_features_str); let cache_dir_specified = !cache.is_empty(); @@ -588,6 +587,7 @@ pub fn run( run_porep_bench, sector_size as u64, api_version, + api_features, cache_dir, preserve_cache, skip_precommit_phase1, @@ -595,6 +595,5 @@ pub fn run( skip_commit_phase1, skip_commit_phase2, test_resume, - use_synthetic, ) } diff --git a/fil-proofs-tooling/src/bin/benchy/window_post.rs b/fil-proofs-tooling/src/bin/benchy/window_post.rs index 768779f31..9fe2bc4f3 100644 --- a/fil-proofs-tooling/src/bin/benchy/window_post.rs +++ b/fil-proofs-tooling/src/bin/benchy/window_post.rs @@ -329,14 +329,8 @@ pub fn run_window_post_bench( skip_commit_phase1: bool, skip_commit_phase2: bool, test_resume: bool, - use_synthetic: bool, + api_features: Vec, ) -> anyhow::Result<()> { - let features = if use_synthetic { - vec![ApiFeature::SyntheticPoRep] - } else { - Vec::new() - }; - let ( (seal_pre_commit_phase1_cpu_time_ms, seal_pre_commit_phase1_wall_time_ms), ( @@ -356,7 +350,7 @@ pub fn run_window_post_bench( skip_precommit_phase2, test_resume, false, // skip staging - features.clone(), + api_features.clone(), ) }?; @@ -394,7 +388,7 @@ pub fn run_window_post_bench( let comm_r = seal_pre_commit_output.comm_r; let sector_id = SectorId::from(SECTOR_ID); - let porep_config = shared::get_porep_config(sector_size, api_version, features); + let porep_config = shared::get_porep_config(sector_size, api_version, api_features); let sealed_file_path = cache_dir.join(SEALED_FILE); @@ -603,9 +597,14 @@ pub fn run( skip_commit_phase1: bool, skip_commit_phase2: bool, test_resume: bool, - use_synthetic: bool, + api_features: Vec, ) -> anyhow::Result<()> { - info!("Benchy Window PoSt: sector-size={}, api_version={}, preserve_cache={}, skip_precommit_phase1={}, skip_precommit_phase2={}, skip_commit_phase1={}, skip_commit_phase2={}, test_resume={}, use_synthetic={}", sector_size, api_version, preserve_cache, skip_precommit_phase1, skip_precommit_phase2, skip_commit_phase1, skip_commit_phase2, test_resume, use_synthetic); + let api_features_str = api_features + .iter() + .map(|api_feature| api_feature.to_string()) + .collect::>() + .join(","); + info!("Benchy Window PoSt: sector-size={}, api_version={}, preserve_cache={}, skip_precommit_phase1={}, skip_precommit_phase2={}, skip_commit_phase1={}, skip_commit_phase2={}, test_resume={}, apu_features={}", sector_size, api_version, preserve_cache, skip_precommit_phase1, skip_precommit_phase2, skip_commit_phase1, skip_commit_phase2, test_resume, api_features_str); let cache_dir_specified = !cache.is_empty(); @@ -656,6 +655,6 @@ pub fn run( skip_commit_phase1, skip_commit_phase2, test_resume, - use_synthetic, + api_features, ) } diff --git a/fil-proofs-tooling/src/bin/benchy/window_post_fake.rs b/fil-proofs-tooling/src/bin/benchy/window_post_fake.rs index e7d34d5ed..029cb0722 100644 --- a/fil-proofs-tooling/src/bin/benchy/window_post_fake.rs +++ b/fil-proofs-tooling/src/bin/benchy/window_post_fake.rs @@ -127,19 +127,13 @@ pub fn run( sector_size: usize, fake_replica: bool, api_version: ApiVersion, - use_synthetic_porep: bool, + api_features: Vec, ) -> anyhow::Result<()> { info!( "Benchy Window PoSt Fake: sector-size={}, fake_replica={}, api_version={}", sector_size, fake_replica, api_version ); - let api_features = if use_synthetic_porep { - vec![ApiFeature::SyntheticPoRep] - } else { - Vec::new() - }; - with_shape!( sector_size as u64, run_window_post_bench, diff --git a/fil-proofs-tooling/src/bin/benchy/winning_post.rs b/fil-proofs-tooling/src/bin/benchy/winning_post.rs index 8d7984d09..fd2a713b9 100644 --- a/fil-proofs-tooling/src/bin/benchy/winning_post.rs +++ b/fil-proofs-tooling/src/bin/benchy/winning_post.rs @@ -140,19 +140,13 @@ pub fn run( sector_size: usize, fake_replica: bool, api_version: ApiVersion, - use_synthetic: bool, + api_features: Vec, ) -> anyhow::Result<()> { info!( "Benchy Winning PoSt: sector-size={}, fake_replica={}, api_version={}", sector_size, fake_replica, api_version ); - let api_features = if use_synthetic { - vec![ApiFeature::SyntheticPoRep] - } else { - Vec::new() - }; - with_shape!( sector_size as u64, run_fallback_post_bench, diff --git a/storage-proofs-core/src/api_version.rs b/storage-proofs-core/src/api_version.rs index 8dacfd745..b7d7434ad 100644 --- a/storage-proofs-core/src/api_version.rs +++ b/storage-proofs-core/src/api_version.rs @@ -114,6 +114,31 @@ impl ApiFeature { } } +/// Display is also used for command-line argument tooling. +impl Display for ApiFeature { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let api_feature_str = match self { + Self::SyntheticPoRep => "synthetic-porep", + Self::NonInteractivePoRep => "non-interactive-porep", + }; + write!(f, "{}", api_feature_str) + } +} + +impl FromStr for ApiFeature { + type Err = Error; + fn from_str(api_feature_str: &str) -> Result { + match api_feature_str { + "synthetic-porep" => Ok(ApiFeature::SyntheticPoRep), + "non-interactive-porep" => Ok(ApiFeature::NonInteractivePoRep), + _ => Err(format_err!( + "'{}' cannot be parsed as valid API feature", + api_feature_str + )), + } + } +} + #[test] fn test_fmt() { assert_eq!(format!("{}", ApiVersion::V1_0_0), "1.0.0"); @@ -143,6 +168,13 @@ fn test_api_version_order() { #[test] fn test_api_feature_synthetic_porep() { let feature = ApiFeature::SyntheticPoRep; + + assert_eq!(format!("{}", feature), "synthetic-porep"); + assert_eq!( + ApiFeature::from_str("synthetic-porep").expect("can be parsed"), + feature + ); + assert!(feature.first_supported_version() == ApiVersion::V1_2_0); assert!(feature.last_supported_version().is_none()); }