1#![cfg_attr(not(feature = "std"), no_std)]
16
17extern crate alloc;
31
32pub mod control_id;
33mod info;
34pub mod layout;
35mod poly_ext;
36#[cfg(feature = "prove")]
37pub mod prove;
38mod taps;
39
40use risc0_zkp::{
41 adapter::{CircuitCoreDef, TapsProvider},
42 field::baby_bear::BabyBear,
43 taps::TapSet,
44};
45
46pub const REGISTER_GROUP_ACCUM: usize = 0;
47pub const REGISTER_GROUP_CODE: usize = 1;
48pub const REGISTER_GROUP_CTRL: usize = 1;
49pub const REGISTER_GROUP_DATA: usize = 2;
50
51pub const GLOBAL_MIX: usize = 0;
52pub const GLOBAL_OUT: usize = 1;
53pub const CIRCUIT: CircuitImpl = CircuitImpl::new();
54
55pub struct CircuitImpl;
58
59#[allow(clippy::new_without_default)]
60impl CircuitImpl {
61 pub const fn new() -> Self {
62 CircuitImpl
63 }
64}
65
66impl TapsProvider for CircuitImpl {
67 fn get_taps(&self) -> &'static TapSet<'static> {
68 self::taps::TAPSET
69 }
70}
71
72impl CircuitCoreDef<BabyBear> for CircuitImpl {}
73
74#[cfg(feature = "test")]
75pub mod testutil {
76 use rand::Rng;
77 use risc0_zkp::{
78 adapter::{CircuitInfo, TapsProvider},
79 field::{
80 baby_bear::{BabyBearElem, BabyBearExtElem},
81 Elem, ExtElem,
82 },
83 hal::{Buffer, CircuitHal, Hal},
84 INV_RATE,
85 };
86
87 use crate::{CircuitImpl, REGISTER_GROUP_ACCUM, REGISTER_GROUP_CODE, REGISTER_GROUP_DATA};
88
89 pub struct EvalCheckParams {
90 pub po2: usize,
91 pub steps: usize,
92 pub domain: usize,
93 pub code: Vec<BabyBearElem>,
94 pub data: Vec<BabyBearElem>,
95 pub accum: Vec<BabyBearElem>,
96 pub mix: Vec<BabyBearElem>,
97 pub out: Vec<BabyBearElem>,
98 pub poly_mix: BabyBearExtElem,
99 }
100
101 impl EvalCheckParams {
102 pub fn new(po2: usize) -> Self {
103 let mut rng = rand::rng();
104 let steps = 1 << po2;
105 let domain = steps * INV_RATE;
106 let circuit = CircuitImpl::new();
107 let taps = circuit.get_taps();
108 let code_size = taps.group_size(REGISTER_GROUP_CODE);
109 let data_size = taps.group_size(REGISTER_GROUP_DATA);
110 let accum_size = taps.group_size(REGISTER_GROUP_ACCUM);
111 let code = random_fps(&mut rng, code_size * domain);
112 let data = random_fps(&mut rng, data_size * domain);
113 let accum = random_fps(&mut rng, accum_size * domain);
114 let mix = random_fps(&mut rng, CircuitImpl::MIX_SIZE);
115 let out = random_fps(&mut rng, CircuitImpl::OUTPUT_SIZE);
116 let poly_mix = BabyBearExtElem::random(&mut rng);
117 tracing::debug!("code: {} bytes", code.len() * 4);
118 tracing::debug!("data: {} bytes", data.len() * 4);
119 tracing::debug!("accum: {} bytes", accum.len() * 4);
120 tracing::debug!("mix: {} bytes", mix.len() * 4);
121 tracing::debug!("out: {} bytes", out.len() * 4);
122 Self {
123 po2,
124 steps,
125 domain,
126 code,
127 data,
128 accum,
129 mix,
130 out,
131 poly_mix,
132 }
133 }
134 }
135
136 fn random_fps<E: Elem>(rng: &mut impl Rng, size: usize) -> Vec<E> {
137 let mut ret = Vec::new();
138 for _ in 0..size {
139 ret.push(E::random(rng));
140 }
141 ret
142 }
143
144 #[allow(unused)]
145 pub(crate) fn eval_check<H1, H2, C1, C2>(hal1: &H1, eval1: C1, hal2: &H2, eval2: C2, po2: usize)
146 where
147 H1: Hal<Elem = BabyBearElem, ExtElem = BabyBearExtElem>,
148 H2: Hal<Elem = BabyBearElem, ExtElem = BabyBearExtElem>,
149 C1: CircuitHal<H1>,
150 C2: CircuitHal<H2>,
151 {
152 let params = EvalCheckParams::new(po2);
153 let check1 = eval_check_impl(¶ms, hal1, &eval1);
154 let check2 = eval_check_impl(¶ms, hal2, &eval2);
155 assert_eq!(check1, check2);
156 }
157
158 pub fn eval_check_impl<H, C>(params: &EvalCheckParams, hal: &H, eval: &C) -> Vec<H::Elem>
159 where
160 H: Hal<Elem = BabyBearElem, ExtElem = BabyBearExtElem>,
161 C: CircuitHal<H>,
162 {
163 let check = hal.alloc_elem("check", BabyBearExtElem::EXT_SIZE * params.domain);
164 let code = hal.copy_from_elem("code", ¶ms.code);
165 let data = hal.copy_from_elem("data", ¶ms.data);
166 let accum = hal.copy_from_elem("accum", ¶ms.accum);
167 let mix = hal.copy_from_elem("mix", ¶ms.mix);
168 let out = hal.copy_from_elem("out", ¶ms.out);
169 eval.eval_check(
170 &check,
171 &[&accum, &code, &data],
172 &[&mix, &out],
173 params.poly_mix,
174 params.po2,
175 params.steps,
176 );
177 let mut ret = vec![H::Elem::ZERO; check.size()];
178 check.view(|view| {
179 ret.clone_from_slice(view);
180 });
181 ret
182 }
183}