Skip to main content

u280_hardware_promoter/
policy.rs

1//! Integer-only percentile and throughput policy.
2
3use crate::model::{
4    BASELINE_CLOCK_HZ, MAXIMUM_CAPTURE_CYCLES_PER_RESULT, MINIMUM_MEASURED_SAMPLES,
5    MINIMUM_SIGNATURES_PER_SECOND, PERFORMANCE_BATCH,
6};
7use crate::{FailureCode, PromotionError, PromotionResult};
8use serde::Serialize;
9use u280_evidence_oracle::VerifiedPerformanceObservations;
10
11const MAXIMUM_MEASURED_SAMPLES: usize = 1_000_000;
12
13/// Exact accepted p95 arithmetic. No floating-point or rounded rate is part
14/// of the decision.
15#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize)]
16pub struct PerformanceAssessment {
17    sample_count: usize,
18    p95_rank: usize,
19    p95_capture_interval_cycles: u64,
20    capture_results_denominator: u32,
21    p95_whole_kernel_nanoseconds: u64,
22    whole_kernel_results_denominator: u32,
23    actual_routed_hz: u64,
24}
25
26impl PerformanceAssessment {
27    /// Number of measured samples in the p95 population.
28    #[must_use]
29    pub const fn sample_count(self) -> usize {
30        self.sample_count
31    }
32
33    /// One-based nearest-rank p95 position in the measured population.
34    #[must_use]
35    pub const fn p95_rank(self) -> usize {
36        self.p95_rank
37    }
38
39    /// p95 raw capture/core interval numerator in cycles.
40    #[must_use]
41    pub const fn p95_capture_interval_cycles(self) -> u64 {
42        self.p95_capture_interval_cycles
43    }
44
45    /// Number of inter-result intervals represented by the capture numerator.
46    #[must_use]
47    pub const fn capture_results_denominator(self) -> u32 {
48        self.capture_results_denominator
49    }
50
51    /// p95 raw whole-kernel elapsed numerator in nanoseconds.
52    #[must_use]
53    pub const fn p95_whole_kernel_nanoseconds(self) -> u64 {
54        self.p95_whole_kernel_nanoseconds
55    }
56
57    /// Number of results represented by the whole-kernel numerator.
58    #[must_use]
59    pub const fn whole_kernel_results_denominator(self) -> u32 {
60        self.whole_kernel_results_denominator
61    }
62
63    /// Exact accepted routed clock in hertz.
64    #[must_use]
65    pub const fn actual_routed_hz(self) -> u64 {
66        self.actual_routed_hz
67    }
68}
69
70/// Independently applies the fixed performance policy to the oracle's opaque
71/// verified sample population.
72///
73/// Capture/core cost is represented as `C95 / 16_383`; whole-kernel cost is
74/// represented as `T95 / 16_384`. Every comparison uses cross-multiplied
75/// `u128` arithmetic, so neither division nor floating-point rounding can turn
76/// a failure into a pass.
77///
78/// `actual_routed_hz` must come from the eventual accepted-route proof. This
79/// crate-private function rejects it unless it exactly matches the oracle's
80/// typed declaration, that declaration carries a route-evidence binding, and
81/// the actual routed clock is at least the fixed 250 MHz baseline.
82///
83/// # Errors
84///
85/// Returns [`FailureCode::PerformancePopulation`] for an incomplete or
86/// inconsistent population, [`FailureCode::IdentityJoin`] for a routed-clock
87/// mismatch, or [`FailureCode::PerformanceThreshold`] for an actual routed
88/// clock below 250 MHz or any failed exact inequality.
89#[allow(dead_code)] // Called only by the future accepted-route adapter.
90pub(crate) fn evaluate_performance(
91    observations: &VerifiedPerformanceObservations,
92    actual_routed_hz: u64,
93) -> PromotionResult<PerformanceAssessment> {
94    let required_samples = usize::try_from(MINIMUM_MEASURED_SAMPLES).expect("u32 fits usize");
95    if observations.required_batch() != PERFORMANCE_BATCH
96        || observations.minimum_measured_samples() != required_samples
97        || observations.normalized_clock_hz() != BASELINE_CLOCK_HZ
98        || observations.minimum_signatures_per_second() != MINIMUM_SIGNATURES_PER_SECOND
99        || observations.maximum_capture_cycles_per_result() != MAXIMUM_CAPTURE_CYCLES_PER_RESULT
100        || !observations.required_batch_requested()
101    {
102        return Err(PromotionError::new(
103            FailureCode::PerformancePopulation,
104            "typed oracle observations do not contain the fixed promoter performance policy",
105        ));
106    }
107
108    let measured = observations
109        .samples()
110        .iter()
111        .filter(|sample| sample.phase() == "measured" && sample.batch() == PERFORMANCE_BATCH)
112        .collect::<Vec<_>>();
113    if measured.len() != observations.observed_measured_samples() {
114        return Err(PromotionError::new(
115            FailureCode::PerformancePopulation,
116            "typed oracle measured-sample count disagrees with its retained raw population",
117        ));
118    }
119
120    let clock = observations.clock();
121    if !clock.supports_hardware_rate_claim()
122        || clock.routed_clock_evidence().is_none()
123        || clock.declared_routed_hz() != Some(actual_routed_hz)
124    {
125        return Err(PromotionError::new(
126            FailureCode::IdentityJoin,
127            "accepted route clock does not match the oracle's bound routed-clock declaration",
128        ));
129    }
130
131    let capture = measured
132        .iter()
133        .map(|sample| sample.capture_core_interval_cycles())
134        .collect::<Vec<_>>();
135    let whole = measured
136        .iter()
137        .map(|sample| sample.whole_kernel_nanoseconds())
138        .collect::<Vec<_>>();
139    let assessment = assess_exact_population(actual_routed_hz, capture, whole)?;
140    if observations.p95_rank() != Some(assessment.p95_rank())
141        || observations.p95_capture_interval_cycles()
142            != Some(assessment.p95_capture_interval_cycles())
143        || observations.capture_results_denominator() != assessment.capture_results_denominator()
144        || observations.p95_whole_kernel_nanoseconds()
145            != Some(assessment.p95_whole_kernel_nanoseconds())
146        || observations.whole_kernel_results_denominator()
147            != assessment.whole_kernel_results_denominator()
148    {
149        return Err(PromotionError::new(
150            FailureCode::PerformancePopulation,
151            "typed oracle p95 summary disagrees with independent promoter recomputation",
152        ));
153    }
154
155    Ok(assessment)
156}
157
158fn assess_exact_population(
159    actual_routed_hz: u64,
160    capture: Vec<u64>,
161    whole: Vec<u64>,
162) -> PromotionResult<PerformanceAssessment> {
163    let required_samples = usize::try_from(MINIMUM_MEASURED_SAMPLES).expect("u32 fits usize");
164    if capture.len() != whole.len()
165        || capture.len() < required_samples
166        || capture.len() > MAXIMUM_MEASURED_SAMPLES
167        || actual_routed_hz == 0
168        || capture.iter().any(|value| *value == 0)
169        || whole.iter().any(|value| *value == 0)
170    {
171        return Err(PromotionError::new(
172            FailureCode::PerformancePopulation,
173            "performance population must contain 30..=1000000 paired positive raw samples and a nonzero routed clock",
174        ));
175    }
176    if actual_routed_hz < BASELINE_CLOCK_HZ {
177        return Err(PromotionError::new(
178            FailureCode::PerformanceThreshold,
179            format!(
180                "actual routed clock {actual_routed_hz} Hz is below the required {BASELINE_CLOCK_HZ} Hz baseline"
181            ),
182        ));
183    }
184
185    let sample_count = capture.len();
186    let (capture_rank, capture_p95) = nearest_rank_p95(capture)?;
187    let (whole_rank, whole_p95) = nearest_rank_p95(whole)?;
188    if capture_rank != whole_rank {
189        return Err(PromotionError::new(
190            FailureCode::PerformancePopulation,
191            "capture and whole-kernel populations produced different p95 ranks",
192        ));
193    }
194
195    let capture_denominator = u128::from(PERFORMANCE_BATCH - 1);
196    let whole_denominator = u128::from(PERFORMANCE_BATCH);
197    let capture_p95_u128 = u128::from(capture_p95);
198    let whole_p95_u128 = u128::from(whole_p95);
199    let minimum_rate = u128::from(MINIMUM_SIGNATURES_PER_SECOND);
200
201    let capture_cap_passes =
202        capture_p95_u128 <= u128::from(MAXIMUM_CAPTURE_CYCLES_PER_RESULT) * capture_denominator;
203    let normalized_rate_passes =
204        u128::from(BASELINE_CLOCK_HZ) * capture_denominator >= minimum_rate * capture_p95_u128;
205    let routed_rate_passes =
206        u128::from(actual_routed_hz) * capture_denominator >= minimum_rate * capture_p95_u128;
207    let whole_kernel_rate_passes =
208        1_000_000_000_u128 * whole_denominator >= minimum_rate * whole_p95_u128;
209    if !(capture_cap_passes
210        && normalized_rate_passes
211        && routed_rate_passes
212        && whole_kernel_rate_passes)
213    {
214        return Err(PromotionError::new(
215            FailureCode::PerformanceThreshold,
216            format!(
217                "exact p95 threshold failed (C95={capture_p95}/16383 cycles/result, T95={whole_p95}/16384 ns/result, actual_hz={actual_routed_hz})"
218            ),
219        ));
220    }
221
222    Ok(PerformanceAssessment {
223        sample_count,
224        p95_rank: capture_rank,
225        p95_capture_interval_cycles: capture_p95,
226        capture_results_denominator: PERFORMANCE_BATCH - 1,
227        p95_whole_kernel_nanoseconds: whole_p95,
228        whole_kernel_results_denominator: PERFORMANCE_BATCH,
229        actual_routed_hz,
230    })
231}
232
233fn nearest_rank_p95(mut values: Vec<u64>) -> PromotionResult<(usize, u64)> {
234    if values.is_empty() || values.len() > MAXIMUM_MEASURED_SAMPLES {
235        return Err(PromotionError::new(
236            FailureCode::PerformancePopulation,
237            "p95 population is empty or exceeds its memory bound",
238        ));
239    }
240    values.sort_unstable();
241    let scaled = values.len().checked_mul(95).ok_or_else(|| {
242        PromotionError::new(
243            FailureCode::PerformancePopulation,
244            "p95 rank arithmetic overflowed",
245        )
246    })?;
247    // One-based ceil(95*n/100); the sorted vector uses rank - 1.
248    let rank = scaled.div_ceil(100);
249    Ok((rank, values[rank - 1]))
250}
251
252#[cfg(test)]
253mod tests {
254    use super::{assess_exact_population, nearest_rank_p95};
255    use crate::FailureCode;
256
257    #[test]
258    fn nearest_rank_p95_uses_ceil_rank_not_interpolation() {
259        let values = (1_u64..=30).collect::<Vec<_>>();
260        assert_eq!(nearest_rank_p95(values).unwrap(), (29, 29));
261    }
262
263    #[test]
264    fn exact_threshold_boundary_passes_without_rounding() {
265        let accepted = assess_exact_population(
266            250_000_000,
267            vec![500 * 16_383; 30],
268            vec![2_000 * 16_384; 30],
269        )
270        .unwrap();
271        assert_eq!(accepted.p95_capture_interval_cycles(), 500 * 16_383);
272        assert_eq!(accepted.p95_whole_kernel_nanoseconds(), 2_000 * 16_384);
273    }
274
275    #[test]
276    fn routed_clock_below_250mhz_fails_even_when_rate_inequalities_pass() {
277        let below_baseline = assess_exact_population(249_999_999, vec![1; 30], vec![1; 30]);
278        assert_eq!(
279            below_baseline.unwrap_err().code(),
280            FailureCode::PerformanceThreshold
281        );
282    }
283
284    #[test]
285    fn one_unit_beyond_either_exact_boundary_fails() {
286        let slow_capture =
287            assess_exact_population(250_000_000, vec![500 * 16_383 + 1; 30], vec![1; 30]);
288        assert_eq!(
289            slow_capture.unwrap_err().code(),
290            FailureCode::PerformanceThreshold
291        );
292
293        let slow_wall =
294            assess_exact_population(250_000_000, vec![1; 30], vec![2_000 * 16_384 + 1; 30]);
295        assert_eq!(
296            slow_wall.unwrap_err().code(),
297            FailureCode::PerformanceThreshold
298        );
299    }
300}