From ddef2300dec97a6122a2adeaebbfeb6a9c1cc71a Mon Sep 17 00:00:00 2001 From: FiveMovesAhead Date: Tue, 25 Nov 2025 13:37:03 +0000 Subject: [PATCH] Account for binary quality. --- tig-protocol/src/contracts/benchmarks.rs | 48 ++++++++++++++++++------ tig-protocol/src/contracts/opow.rs | 4 +- tig-structs/src/config.rs | 18 ++++++++- tig-structs/src/core.rs | 16 +------- 4 files changed, 58 insertions(+), 28 deletions(-) diff --git a/tig-protocol/src/contracts/benchmarks.rs b/tig-protocol/src/contracts/benchmarks.rs index 4efb3fa9..56a0631c 100644 --- a/tig-protocol/src/contracts/benchmarks.rs +++ b/tig-protocol/src/contracts/benchmarks.rs @@ -61,10 +61,11 @@ pub async fn submit_precommit( } let track_config = &challenge_config.active_tracks[&settings.track_id]; - if num_bundles == 0 { + if num_bundles < track_config.min_num_bundles { return Err(anyhow!( - "Invalid num_bundles '{}'. Must at least 1", + "Invalid num_bundles '{}'. Must be at least {}", num_bundles, + track_config.min_num_bundles, )); } @@ -173,6 +174,8 @@ pub async fn submit_benchmark( } // random sample nonces + let challenge_config = &ctx.get_config().await.challenges[&settings.challenge_id]; + let track_config = &challenge_config.active_tracks[&settings.track_id]; let mut rng = StdRng::seed_from_u64(seed); let mut nonce_quality = solution_quality .iter() @@ -200,19 +203,42 @@ pub async fn submit_benchmark( let group = &mut nonce_quality[start_idx..end_idx]; group.sort_unstable_by_key(|&(_, quality)| quality); - average_quality_by_group.push(group[num_nonces_per_group / 2].1); - sampled_nonces.extend( - group - .iter() - .skip(num_nonces_per_group / 2) - .map(|&(idx, _)| idx as u64), - ); + match challenge_config.quality_type { + QualityType::Continuous => { + let median = group[num_nonces_per_group / 2].1; + average_quality_by_group.push(median); + if median >= track_config.min_active_quality { + sampled_nonces.extend( + group + .iter() + .skip(num_nonces_per_group / 2) + .map(|&(idx, _)| idx as u64), + ); + } + } + QualityType::Binary => { + let mean = + (group.iter().map(|&(_, q)| q as i64).sum::() / group.len() as i64) as i32; + average_quality_by_group.push(mean); + if mean >= track_config.min_active_quality { + sampled_nonces.extend( + group + .iter() + .filter(|&(_, quality)| *quality != 0) + .map(|&(idx, _)| idx as u64), + ); + } + } + } } - let max_samples = ctx.get_config().await.challenges[&settings.challenge_id].max_samples; + for i in 0..sampled_nonces.len().min(challenge_config.max_samples) { + let j = rng.gen_range(i..sampled_nonces.len()); + sampled_nonces.swap(i, j); + } let sampled_nonces = sampled_nonces .into_iter() - .take(max_samples) + .take(challenge_config.max_samples) .collect::>(); ctx.add_benchmark_to_mempool( diff --git a/tig-protocol/src/contracts/opow.rs b/tig-protocol/src/contracts/opow.rs index 51135fe1..3fabb0c4 100644 --- a/tig-protocol/src/contracts/opow.rs +++ b/tig-protocol/src/contracts/opow.rs @@ -55,7 +55,7 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { .entry(settings.challenge_id.clone()) .or_default() += average_quality_by_bundle .iter() - .filter(|&&x| x >= track_config.min_quality_threshold) + .filter(|&&x| x >= track_config.min_active_quality) .count() as u64; } } @@ -142,7 +142,7 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { .enumerate() .flat_map(|(i, x)| { x.1.iter() - .filter(|&&quality| quality >= track_config.min_quality_threshold) + .filter(|&&quality| quality >= track_config.min_active_quality) .map(move |&quality| (i, quality)) }) .collect::>(); diff --git a/tig-structs/src/config.rs b/tig-structs/src/config.rs index 6772b44b..f5fd7021 100644 --- a/tig-structs/src/config.rs +++ b/tig-structs/src/config.rs @@ -63,15 +63,31 @@ serializable_struct_with_getters! { min_topup_amount: PreciseNumber, } } +#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)] +#[serde(rename_all = "lowercase")] +pub enum ChallengeType { + CPU, + GPU, +} +#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)] +#[serde(rename_all = "snake_case")] +pub enum QualityType { + Continuous, + Binary, +} serializable_struct_with_getters! { TrackConfig { num_nonces_per_bundle: u64, + min_num_bundles: u64, runtime_config_limits: RuntimeConfig, - min_quality_threshold: i32, + min_active_quality: i32, } } serializable_struct_with_getters! { ChallengeConfig { + name: String, + r#type: ChallengeType, + quality_type: QualityType, submission_delay_multiplier: f64, max_samples: usize, lifespan_period: u32, diff --git a/tig-structs/src/core.rs b/tig-structs/src/core.rs index 03699241..4261e18c 100644 --- a/tig-structs/src/core.rs +++ b/tig-structs/src/core.rs @@ -1,5 +1,5 @@ use crate::{ - config::{ProtocolConfig, RuntimeConfig}, + config::{ChallengeConfig, ProtocolConfig, RuntimeConfig}, serializable_struct_with_getters, }; use serde::{Deserialize, Serialize}; @@ -42,7 +42,7 @@ serializable_struct_with_getters! { serializable_struct_with_getters! { Challenge { id: String, - details: ChallengeDetails, + config: ChallengeConfig, state: ChallengeState, block_data: Option, } @@ -271,18 +271,6 @@ serializable_struct_with_getters! { } // Challenge child structs -#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)] -#[serde(rename_all = "lowercase")] -pub enum ChallengeType { - CPU, - GPU, -} -serializable_struct_with_getters! { - ChallengeDetails { - name: String, - r#type: ChallengeType, - } -} serializable_struct_with_getters! { ChallengeState { round_active: u32,