diff --git a/tig-protocol/src/contracts/benchmarks.rs b/tig-protocol/src/contracts/benchmarks.rs index ebd480a7..9a19c700 100644 --- a/tig-protocol/src/contracts/benchmarks.rs +++ b/tig-protocol/src/contracts/benchmarks.rs @@ -51,16 +51,19 @@ pub async fn submit_precommit( // verify difficulty let difficulty = &settings.difficulty; - let difficulty_parameters = &config.challenges.difficulty_parameters[&settings.challenge_id]; - if difficulty.len() != difficulty_parameters.len() - || difficulty - .iter() - .zip(difficulty_parameters.iter()) - .any(|(d, p)| *d < p.min_value || *d > p.max_value) - { + let challenge_config = &config.challenges[&settings.challenge_id]; + if difficulty.len() != challenge_config.difficulty.parameter_names.len() { return Err(anyhow!("Invalid difficulty '{:?}'", difficulty)); } + if num_nonces < challenge_config.benchmarks.min_num_nonces { + return Err(anyhow!( + "Invalid num_nonces '{}'. Must be >= {}", + num_nonces, + challenge_config.benchmarks.min_num_nonces + )); + } + let challenge_data = ctx .get_challenge_block_data(&settings.challenge_id, &settings.block_id) .await @@ -143,7 +146,8 @@ pub async fn submit_benchmark( // random sample nonces let config = ctx.get_config().await; let mut rng = StdRng::seed_from_u64(seed); - let max_samples = config.benchmarks.max_samples; + let benchmark_config = &config.challenges[&settings.challenge_id].benchmarks; + let max_samples = benchmark_config.max_samples; // sample nonces from solutions let mut sampled_solution_nonces = HashSet::new(); diff --git a/tig-protocol/src/contracts/challenges.rs b/tig-protocol/src/contracts/challenges.rs index 00834ac5..bed907d1 100644 --- a/tig-protocol/src/contracts/challenges.rs +++ b/tig-protocol/src/contracts/challenges.rs @@ -9,8 +9,9 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { .. } = cache; - for challenge_data in active_challenges_block_data.values_mut() { - challenge_data.base_fee = config.benchmarks.min_base_fee; - challenge_data.per_nonce_fee = config.benchmarks.min_per_nonce_fee; + for (challenge_id, challenge_data) in active_challenges_block_data.iter_mut() { + let benchmarks_config = &config.challenges[challenge_id].benchmarks; + challenge_data.base_fee = benchmarks_config.min_base_fee; + challenge_data.per_nonce_fee = benchmarks_config.min_per_nonce_fee; } } diff --git a/tig-protocol/src/contracts/opow.rs b/tig-protocol/src/contracts/opow.rs index fef1fcff..91a53d7c 100644 --- a/tig-protocol/src/contracts/opow.rs +++ b/tig-protocol/src/contracts/opow.rs @@ -97,11 +97,12 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { // update hash threshold let denominator: u64 = 1_000_000_000_000_000; - let max_delta = U256::MAX / U256::from(denominator) - * U256::from( - (config.benchmarks.hash_threshold_max_percent_delta * denominator as f64) as u64, - ); for challenge_id in active_challenge_ids.iter() { + let difficulty_config = &config.challenges[challenge_id].difficulty; + let max_delta = U256::MAX / U256::from(denominator) + * U256::from( + (difficulty_config.hash_threshold_max_percent_delta * denominator as f64) as u64, + ); let prev_hash_threshold = active_challenges_prev_block_data .get(challenge_id) .map(|x| U256::from(x.hash_threshold.clone().0)) @@ -111,7 +112,7 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { U256::MAX } else { (prev_hash_threshold / U256::from(current_solution_rate)) - .saturating_mul(U256::from(config.benchmarks.target_solution_rate)) + .saturating_mul(U256::from(difficulty_config.target_solution_rate)) }; let diff = prev_hash_threshold.abs_diff(target_threshold); let delta = (diff / U256::from(100)).min(max_delta); @@ -149,6 +150,7 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { if !solutions_by_challenge.contains_key(challenge_id) { continue; } + let challenge_config = &config.challenges[challenge_id]; let solutions = solutions_by_challenge.get_mut(challenge_id).unwrap(); let points = solutions .iter() @@ -174,7 +176,6 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { } let challenge_data = active_challenges_block_data.get_mut(challenge_id).unwrap(); - let min_num_nonces = config.opow.min_num_nonces as u64; let mut player_code_solutions = HashMap::>::new(); let mut player_solutions = HashMap::::new(); let mut player_discarded_solutions = HashMap::::new(); @@ -187,14 +188,12 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { let BenchmarkSettings { player_id, algorithm_id, - challenge_id, difficulty, .. } = settings; - let difficulty_parameters = &config.challenges.difficulty_parameters[challenge_id]; - let min_difficulty = difficulty_parameters.min_difficulty(); - let max_difficulty = difficulty_parameters.max_difficulty(); + let min_difficulty = challenge_config.difficulty.min_difficulty.clone(); + let max_difficulty = challenge_config.difficulty.max_difficulty.clone(); if (0..difficulty.len()) .into_iter() .any(|i| difficulty[i] < min_difficulty[i] || difficulty[i] > max_difficulty[i]) @@ -234,17 +233,13 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { .map(|player_id| { ( player_id.clone(), - if player_nonces[player_id] >= min_num_nonces { - max_qualifiers_by_player[player_id].min(player_solutions[player_id]) - } else { - 0 - }, + max_qualifiers_by_player[player_id].min(player_solutions[player_id]), ) }) .collect(); let num_qualifiers = player_qualifiers.values().sum::(); - if num_qualifiers >= config.opow.total_qualifiers_threshold + if num_qualifiers >= challenge_config.difficulty.total_qualifiers_threshold || frontier_idx == solutions_by_frontier_idx.len() - 1 { let mut sum_weighted_solution_ratio = 0.0; @@ -287,11 +282,11 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { // update frontiers for challenge_id in active_challenge_ids.iter() { + let challenge_config = &config.challenges[challenge_id]; let challenge_data = active_challenges_block_data.get_mut(challenge_id).unwrap(); - let difficulty_parameters = &config.challenges.difficulty_parameters[challenge_id]; - let min_difficulty = difficulty_parameters.min_difficulty(); - let max_difficulty = difficulty_parameters.max_difficulty(); + let min_difficulty = challenge_config.difficulty.min_difficulty.clone(); + let max_difficulty = challenge_config.difficulty.max_difficulty.clone(); let points = challenge_data .qualifier_difficulties @@ -313,8 +308,8 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { base_frontier = extend_frontier(&base_frontier, &min_difficulty, &max_difficulty); let mut scaling_factor = (challenge_data.num_qualifiers as f64 - / config.opow.total_qualifiers_threshold as f64) - .min(config.challenges.max_scaling_factor); + / challenge_config.difficulty.total_qualifiers_threshold as f64) + .min(challenge_config.difficulty.max_scaling_factor); if scaling_factor < 1.0 { base_frontier = scale_frontier( @@ -324,7 +319,8 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { scaling_factor, ); base_frontier = extend_frontier(&base_frontier, &min_difficulty, &max_difficulty); - scaling_factor = (1.0 / scaling_factor).min(config.challenges.max_scaling_factor); + scaling_factor = + (1.0 / scaling_factor).min(challenge_config.difficulty.max_scaling_factor); } let mut scaled_frontier = scale_frontier( diff --git a/tig-structs/src/config.rs b/tig-structs/src/config.rs index 480b25dc..91694031 100644 --- a/tig-structs/src/config.rs +++ b/tig-structs/src/config.rs @@ -7,8 +7,7 @@ use tig_utils::PreciseNumber; serializable_struct_with_getters! { ProtocolConfig { advances: AdvancesConfig, - benchmarks: BenchmarksConfig, - challenges: ChallengesConfig, + challenges: HashMap, codes: CodesConfig, deposits: DepositsConfig, erc20: ERC20Config, @@ -61,15 +60,13 @@ serializable_struct_with_getters! { } serializable_struct_with_getters! { BenchmarksConfig { - min_num_solutions: u32, + min_num_nonces: u32, submission_delay_multiplier: f64, max_samples: usize, lifespan_period: u32, min_per_nonce_fee: PreciseNumber, min_base_fee: PreciseNumber, runtime_config: RuntimeConfig, - target_solution_rate: u32, - hash_threshold_max_percent_delta: f64, } } serializable_struct_with_getters! { @@ -79,28 +76,20 @@ serializable_struct_with_getters! { } } serializable_struct_with_getters! { - ChallengesConfig { - max_scaling_factor: f64, - difficulty_parameters: HashMap>, + ChallengeConfig { + benchmarks: BenchmarksConfig, + difficulty: DifficultyConfig, } } serializable_struct_with_getters! { - DifficultyParameter { - name: String, - min_value: i32, - max_value: i32, - } -} -pub trait MinMaxDifficulty { - fn min_difficulty(&self) -> Point; - fn max_difficulty(&self) -> Point; -} -impl MinMaxDifficulty for Vec { - fn min_difficulty(&self) -> Point { - self.iter().map(|p| p.min_value).collect() - } - fn max_difficulty(&self) -> Point { - self.iter().map(|p| p.max_value).collect() + DifficultyConfig { + parameter_names: Vec, + min_difficulty: Point, + max_difficulty: Point, + max_scaling_factor: f64, + total_qualifiers_threshold: u32, + target_solution_rate: u32, + hash_threshold_max_percent_delta: f64, } } serializable_struct_with_getters! { @@ -108,13 +97,11 @@ serializable_struct_with_getters! { imbalance_multiplier: f64, cutoff_phase_in_period: u32, cutoff_multiplier: f64, - total_qualifiers_threshold: u32, max_deposit_to_qualifier_ratio: f64, deposit_multiplier: f64, deposit_to_cutoff_ratio: f64, max_coinbase_outputs: usize, coinbase_update_period: u32, - min_num_nonces: u32, } } serializable_struct_with_getters! {