Rework config so more settings are challenge specific.

This commit is contained in:
FiveMovesAhead 2025-08-27 14:56:29 +01:00
parent 127235e1b5
commit 9f89fc02a8
4 changed files with 47 additions and 59 deletions

View File

@ -51,16 +51,19 @@ pub async fn submit_precommit<T: Context>(
// 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<T: Context>(
// 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();

View File

@ -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;
}
}

View File

@ -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::<String, HashMap<String, u32>>::new();
let mut player_solutions = HashMap::<String, u32>::new();
let mut player_discarded_solutions = HashMap::<String, u32>::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::<u32>();
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(

View File

@ -7,8 +7,7 @@ use tig_utils::PreciseNumber;
serializable_struct_with_getters! {
ProtocolConfig {
advances: AdvancesConfig,
benchmarks: BenchmarksConfig,
challenges: ChallengesConfig,
challenges: HashMap<String, ChallengeConfig>,
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<String, Vec<DifficultyParameter>>,
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<DifficultyParameter> {
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<String>,
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! {