openvm_deferral_circuit/canonicity/
trace.rs

1use std::array::from_fn;
2
3use openvm_stark_backend::p3_field::{PrimeCharacteristicRing, PrimeField32};
4
5use super::CanonicityAuxCols;
6use crate::utils::F_NUM_BYTES;
7
8/// Tracegen helper for canonicity sub-AIR auxiliary columns
9pub struct CanonicityTraceGen;
10
11impl CanonicityTraceGen {
12    pub fn generate_subrow<F: PrimeField32>(
13        x_le: &[F; F_NUM_BYTES],
14        aux: &mut CanonicityAuxCols<F>,
15    ) -> u32 {
16        aux.diff_marker.fill(F::ZERO);
17        aux.diff_val = F::ZERO;
18        let x_be: [F; F_NUM_BYTES] = from_fn(|i| x_le[F_NUM_BYTES - 1 - i]);
19        let order_be = F::ORDER_U32.to_le_bytes().into_iter().rev();
20
21        let mut found = false;
22        let mut to_range_check = 0u32;
23
24        for (i, (&x, y)) in x_be.iter().zip(order_be).enumerate() {
25            let x_u32 = x.as_canonical_u32();
26            if !found && x_u32 != y as u32 {
27                debug_assert!(x_u32 < 256);
28                debug_assert!(y as u32 > x_u32);
29                let diff = y as u32 - x_u32;
30                aux.diff_marker[i] = F::ONE;
31                aux.diff_val = F::from_u32(diff);
32                to_range_check = diff - 1;
33                found = true;
34            }
35        }
36        debug_assert!(found);
37        to_range_check
38    }
39
40    pub fn clear_aux<F: PrimeCharacteristicRing>(aux: &mut CanonicityAuxCols<F>) {
41        aux.diff_marker.fill(F::ZERO);
42        aux.diff_val = F::ZERO;
43    }
44}