mirror of
https://github.com/tig-foundation/tig-monorepo.git
synced 2026-02-21 10:27:49 +08:00
Apply min_num_nonces and min_solution_ratio to filter qualifiers.
Some checks are pending
Test Workspace / Test Workspace (push) Waiting to run
Some checks are pending
Test Workspace / Test Workspace (push) Waiting to run
This commit is contained in:
parent
cc568d9523
commit
43ef0f1856
@ -40,15 +40,6 @@ pub async fn submit_precommit<T: Context>(
|
||||
return Err(anyhow!("Invalid challenge '{}'", settings.challenge_id));
|
||||
}
|
||||
|
||||
// verify min nonces
|
||||
let min_nonces = config.benchmarks.min_nonces[&settings.challenge_id];
|
||||
if num_nonces < min_nonces {
|
||||
return Err(anyhow!(
|
||||
"Invalid num_nonces. Must be at least {}",
|
||||
min_nonces
|
||||
));
|
||||
}
|
||||
|
||||
// verify algorithm is active
|
||||
if !ctx
|
||||
.get_algorithm_state(&settings.algorithm_id)
|
||||
|
||||
@ -128,111 +128,129 @@ pub(crate) async fn update(cache: &mut AddBlockCache) {
|
||||
frontier_indexes.insert(point, frontier_index);
|
||||
}
|
||||
}
|
||||
solutions.sort_by(|(a_settings, _, _), (b_settings, _, _)| {
|
||||
let a_index = frontier_indexes[&a_settings.difficulty];
|
||||
let b_index = frontier_indexes[&b_settings.difficulty];
|
||||
a_index.cmp(&b_index)
|
||||
});
|
||||
let mut solutions_by_frontier_idx =
|
||||
HashMap::<usize, Vec<(&BenchmarkSettings, &u32, &u32)>>::new();
|
||||
for &x in solutions.iter() {
|
||||
solutions_by_frontier_idx
|
||||
.entry(frontier_indexes[&x.0.difficulty])
|
||||
.or_default()
|
||||
.push(x);
|
||||
}
|
||||
|
||||
let mut max_qualifiers_by_player = max_qualifiers_by_player.clone();
|
||||
let mut curr_frontier_index = 0;
|
||||
let challenge_data = active_challenges_block_data.get_mut(challenge_id).unwrap();
|
||||
let prev_solution_ratio = active_challenges_prev_block_data
|
||||
.get(challenge_id)
|
||||
.map(|x| x.average_solution_ratio)
|
||||
.unwrap_or_default();
|
||||
let min_solution_ratio = prev_solution_ratio * config.opow.min_solution_ratio_factor;
|
||||
for (settings, &num_solutions, &num_nonces) in solutions.iter() {
|
||||
let BenchmarkSettings {
|
||||
player_id,
|
||||
algorithm_id,
|
||||
challenge_id,
|
||||
difficulty,
|
||||
..
|
||||
} = settings;
|
||||
let min_num_nonces = config.opow.min_num_nonces;
|
||||
let mut player_algorithm_solutions = HashMap::<String, HashMap<String, u32>>::new();
|
||||
let mut player_solutions = HashMap::<String, u32>::new();
|
||||
let mut player_nonces = HashMap::<String, u32>::new();
|
||||
|
||||
if curr_frontier_index != frontier_indexes[difficulty]
|
||||
&& challenge_data.num_qualifiers > config.opow.total_qualifiers_threshold
|
||||
for frontier_idx in 0..solutions_by_frontier_idx.len() {
|
||||
for (settings, &num_solutions, &num_nonces) in
|
||||
solutions_by_frontier_idx[&frontier_idx].iter()
|
||||
{
|
||||
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();
|
||||
if (0..difficulty.len())
|
||||
.into_iter()
|
||||
.any(|i| difficulty[i] < min_difficulty[i] || difficulty[i] > max_difficulty[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
*player_algorithm_solutions
|
||||
.entry(player_id.clone())
|
||||
.or_default()
|
||||
.entry(algorithm_id.clone())
|
||||
.or_default() += num_solutions;
|
||||
*player_solutions.entry(player_id.clone()).or_default() += num_solutions;
|
||||
*player_nonces.entry(player_id.clone()).or_default() += num_nonces;
|
||||
|
||||
challenge_data
|
||||
.qualifier_difficulties
|
||||
.insert(difficulty.clone());
|
||||
}
|
||||
|
||||
// check if we have enough qualifiers
|
||||
let player_solution_ratio: HashMap<String, f64> = player_solutions
|
||||
.keys()
|
||||
.map(|player_id| {
|
||||
(
|
||||
player_id.clone(),
|
||||
player_solutions[player_id] as f64 / player_nonces[player_id] as f64,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let player_qualifiers: HashMap<String, u32> = player_solution_ratio
|
||||
.keys()
|
||||
.map(|player_id| {
|
||||
(
|
||||
player_id.clone(),
|
||||
if player_nonces[player_id] >= min_num_nonces
|
||||
&& player_solution_ratio[player_id] >= min_solution_ratio
|
||||
{
|
||||
max_qualifiers_by_player[player_id].min(player_solutions[player_id])
|
||||
} else {
|
||||
0
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let num_qualifiers = player_qualifiers.values().sum::<u32>();
|
||||
if num_qualifiers >= config.opow.total_qualifiers_threshold
|
||||
|| frontier_idx == solutions_by_frontier_idx.len() - 1
|
||||
{
|
||||
let mut sum_weighted_solution_ratio = 0.0;
|
||||
for player_id in player_qualifiers.keys() {
|
||||
let opow_data = active_opow_block_data.get_mut(player_id).unwrap();
|
||||
opow_data
|
||||
.num_qualifiers_by_challenge
|
||||
.insert(challenge_id.clone(), player_qualifiers[player_id]);
|
||||
opow_data
|
||||
.solution_ratio_by_challenge
|
||||
.insert(challenge_id.clone(), player_solution_ratio[player_id]);
|
||||
|
||||
sum_weighted_solution_ratio +=
|
||||
player_solution_ratio[player_id] * player_qualifiers[player_id] as f64;
|
||||
|
||||
if player_qualifiers[player_id] > 0 {
|
||||
for algorithm_id in player_algorithm_solutions[player_id].keys() {
|
||||
let algorithm_data =
|
||||
active_algorithms_block_data.get_mut(algorithm_id).unwrap();
|
||||
|
||||
algorithm_data.num_qualifiers_by_player.insert(
|
||||
player_id.clone(),
|
||||
(player_qualifiers[player_id] as f64
|
||||
* player_algorithm_solutions[player_id][algorithm_id] as f64
|
||||
/ player_solutions[player_id] as f64)
|
||||
.ceil() as u32,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
challenge_data.num_qualifiers = num_qualifiers;
|
||||
challenge_data.average_solution_ratio = if num_qualifiers == 0 {
|
||||
0.0
|
||||
} else {
|
||||
sum_weighted_solution_ratio / num_qualifiers as f64
|
||||
};
|
||||
break;
|
||||
}
|
||||
let difficulty_parameters = &config.challenges.difficulty_parameters[challenge_id];
|
||||
let min_difficulty = difficulty_parameters.min_difficulty();
|
||||
let max_difficulty = difficulty_parameters.max_difficulty();
|
||||
if (0..difficulty.len())
|
||||
.into_iter()
|
||||
.any(|i| difficulty[i] < min_difficulty[i] || difficulty[i] > max_difficulty[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
curr_frontier_index = frontier_indexes[difficulty];
|
||||
let player_data = active_opow_block_data.get_mut(player_id).unwrap();
|
||||
let algorithm_data = active_algorithms_block_data.get_mut(algorithm_id).unwrap();
|
||||
|
||||
let max_qualifiers = max_qualifiers_by_player.get(player_id).unwrap().clone();
|
||||
let solution_ratio = num_solutions as f64 / num_nonces as f64;
|
||||
let num_qualifiers = if solution_ratio >= min_solution_ratio {
|
||||
num_solutions.min(max_qualifiers)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
max_qualifiers_by_player.insert(player_id.clone(), max_qualifiers - num_qualifiers);
|
||||
|
||||
if num_qualifiers > 0 {
|
||||
*player_data
|
||||
.num_qualifiers_by_challenge
|
||||
.entry(challenge_id.clone())
|
||||
.or_default() += num_qualifiers;
|
||||
*algorithm_data
|
||||
.num_qualifiers_by_player
|
||||
.entry(player_id.clone())
|
||||
.or_default() += num_qualifiers;
|
||||
challenge_data.num_qualifiers += num_qualifiers;
|
||||
}
|
||||
challenge_data
|
||||
.qualifier_difficulties
|
||||
.insert(difficulty.clone());
|
||||
}
|
||||
}
|
||||
|
||||
// update reliability
|
||||
for challenge_id in active_challenge_ids.iter() {
|
||||
if !solutions_by_challenge.contains_key(challenge_id) {
|
||||
continue;
|
||||
}
|
||||
let solutions = solutions_by_challenge.get(challenge_id).unwrap();
|
||||
let challenge_data = active_challenges_block_data.get_mut(challenge_id).unwrap();
|
||||
|
||||
let mut total_solutions = HashMap::<String, u32>::new();
|
||||
let mut total_nonces = HashMap::<String, u32>::new();
|
||||
for (settings, num_solutions, num_nonces) in solutions.iter() {
|
||||
if !challenge_data
|
||||
.qualifier_difficulties
|
||||
.contains(&settings.difficulty)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
*total_solutions
|
||||
.entry(settings.player_id.clone())
|
||||
.or_default() += *num_solutions;
|
||||
*total_nonces.entry(settings.player_id.clone()).or_default() += *num_nonces;
|
||||
}
|
||||
|
||||
let mut sum_weighted_solution_ratio = 0.0;
|
||||
for player_id in total_solutions.keys() {
|
||||
let solution_ratio = total_solutions[player_id] as f64 / total_nonces[player_id] as f64;
|
||||
let opow_data = active_opow_block_data.get_mut(player_id).unwrap();
|
||||
if let Some(&num_qualifiers) = opow_data.num_qualifiers_by_challenge.get(challenge_id) {
|
||||
sum_weighted_solution_ratio += solution_ratio * num_qualifiers as f64;
|
||||
}
|
||||
opow_data
|
||||
.solution_ratio_by_challenge
|
||||
.insert(challenge_id.clone(), solution_ratio);
|
||||
}
|
||||
challenge_data.average_solution_ratio =
|
||||
sum_weighted_solution_ratio / challenge_data.num_qualifiers as f64;
|
||||
}
|
||||
|
||||
// update frontiers
|
||||
for challenge_id in active_challenge_ids.iter() {
|
||||
let challenge_data = active_challenges_block_data.get_mut(challenge_id).unwrap();
|
||||
|
||||
@ -68,7 +68,6 @@ serializable_struct_with_getters! {
|
||||
min_per_nonce_fee: PreciseNumber,
|
||||
min_base_fee: PreciseNumber,
|
||||
runtime_configs: HashMap<AlgorithmType, RuntimeConfig>,
|
||||
min_nonces: HashMap<String, u32>,
|
||||
}
|
||||
}
|
||||
serializable_struct_with_getters! {
|
||||
@ -114,6 +113,7 @@ serializable_struct_with_getters! {
|
||||
max_coinbase_outputs: usize,
|
||||
coinbase_update_period: u32,
|
||||
min_solution_ratio_factor: f64,
|
||||
min_num_nonces: u32,
|
||||
}
|
||||
}
|
||||
serializable_struct_with_getters! {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user