kimchi_msm/test/test_circuit/
mod.rs

1pub mod columns;
2pub mod interpreter;
3pub mod lookups;
4
5#[cfg(test)]
6mod tests {
7    use crate::{
8        circuit_design::{ConstraintBuilderEnv, WitnessBuilderEnv},
9        logup::LookupTableID,
10        lookups::DummyLookupTable,
11        test::test_circuit::{
12            columns::{TestColumn, N_COL_TEST, N_FSEL_TEST},
13            interpreter as test_interpreter,
14            lookups::LookupTable as TestLookupTable,
15        },
16        Ff1, Fp,
17    };
18    use ark_ff::UniformRand;
19    use rand::{CryptoRng, Rng, RngCore};
20    use std::collections::BTreeMap;
21
22    type TestWitnessBuilderEnv<LT> = WitnessBuilderEnv<
23        Fp,
24        TestColumn,
25        { N_COL_TEST - N_FSEL_TEST },
26        { N_COL_TEST - N_FSEL_TEST },
27        0,
28        N_FSEL_TEST,
29        LT,
30    >;
31
32    fn build_test_fixed_sel_circuit<RNG: RngCore + CryptoRng, LT: LookupTableID>(
33        rng: &mut RNG,
34        domain_size: usize,
35    ) -> TestWitnessBuilderEnv<LT> {
36        let mut witness_env = WitnessBuilderEnv::create();
37
38        let fixed_selectors = test_interpreter::build_fixed_selectors(domain_size);
39        witness_env.set_fixed_selectors(fixed_selectors.to_vec());
40
41        for row_i in 0..domain_size {
42            let a: Fp = <Fp as UniformRand>::rand(rng);
43            test_interpreter::test_fixed_sel(&mut witness_env, a);
44
45            if row_i < domain_size - 1 {
46                witness_env.next_row();
47            }
48        }
49
50        witness_env
51    }
52
53    #[test]
54    pub fn test_build_test_fixed_sel_circuit() {
55        let mut rng = o1_utils::tests::make_test_rng(None);
56        build_test_fixed_sel_circuit::<_, DummyLookupTable>(&mut rng, 1 << 4);
57    }
58
59    #[test]
60    fn test_completeness_fixed_sel() {
61        let mut rng = o1_utils::tests::make_test_rng(None);
62
63        // Include tests for completeness for Logup as the random witness
64        // includes all arguments
65        let domain_size = 1 << 8;
66
67        let fixed_selectors = test_interpreter::build_fixed_selectors(domain_size);
68
69        let mut constraint_env = ConstraintBuilderEnv::<Fp, DummyLookupTable>::create();
70        test_interpreter::constrain_test_fixed_sel::<Fp, _>(&mut constraint_env);
71        // Don't use lookups for now
72        let constraints = constraint_env.get_relation_constraints();
73
74        let witness_env =
75            build_test_fixed_sel_circuit::<_, DummyLookupTable>(&mut rng, domain_size);
76        let relation_witness = witness_env.get_relation_witness(domain_size);
77
78        crate::test::test_completeness_generic_no_lookups::<
79            { N_COL_TEST - N_FSEL_TEST },
80            { N_COL_TEST - N_FSEL_TEST },
81            0,
82            N_FSEL_TEST,
83            _,
84        >(
85            constraints,
86            fixed_selectors,
87            relation_witness,
88            domain_size,
89            &mut rng,
90        );
91    }
92
93    fn build_test_fixed_sel_degree_7_circuit<RNG: RngCore + CryptoRng, LT: LookupTableID>(
94        rng: &mut RNG,
95        domain_size: usize,
96    ) -> TestWitnessBuilderEnv<LT> {
97        let mut witness_env = WitnessBuilderEnv::create();
98
99        let fixed_sel: Vec<Fp> = (0..domain_size).map(|i| Fp::from(i as u64)).collect();
100        witness_env.set_fixed_selector_cix(TestColumn::FixedSel1, fixed_sel);
101
102        for row_i in 0..domain_size {
103            let a: Fp = <Fp as UniformRand>::rand(rng);
104            test_interpreter::test_fixed_sel_degree_7(&mut witness_env, a);
105
106            if row_i < domain_size - 1 {
107                witness_env.next_row();
108            }
109        }
110
111        witness_env
112    }
113
114    #[test]
115    fn test_completeness_fixed_sel_degree_7() {
116        let mut rng = o1_utils::tests::make_test_rng(None);
117
118        // Include tests for completeness for Logup as the random witness
119        // includes all arguments
120        let domain_size = 1 << 8;
121
122        let fixed_selectors = test_interpreter::build_fixed_selectors(domain_size);
123
124        let mut constraint_env = ConstraintBuilderEnv::<Fp, DummyLookupTable>::create();
125        test_interpreter::constrain_test_fixed_sel_degree_7::<Fp, _>(&mut constraint_env);
126        // Don't use lookups for now
127        let constraints = constraint_env.get_relation_constraints();
128
129        let witness_env =
130            build_test_fixed_sel_degree_7_circuit::<_, DummyLookupTable>(&mut rng, domain_size);
131        let relation_witness = witness_env.get_relation_witness(domain_size);
132
133        crate::test::test_completeness_generic_no_lookups::<
134            { N_COL_TEST - N_FSEL_TEST },
135            { N_COL_TEST - N_FSEL_TEST },
136            0,
137            N_FSEL_TEST,
138            _,
139        >(
140            constraints,
141            fixed_selectors,
142            relation_witness,
143            domain_size,
144            &mut rng,
145        );
146    }
147
148    fn build_test_fixed_sel_degree_7_circuit_with_constants<
149        RNG: RngCore + CryptoRng,
150        LT: LookupTableID,
151    >(
152        rng: &mut RNG,
153        domain_size: usize,
154    ) -> TestWitnessBuilderEnv<LT> {
155        let mut witness_env = WitnessBuilderEnv::create();
156
157        let fixed_sel: Vec<Fp> = (0..domain_size).map(|i| Fp::from(i as u64)).collect();
158        witness_env.set_fixed_selector_cix(TestColumn::FixedSel1, fixed_sel);
159
160        for row_i in 0..domain_size {
161            let a: Fp = <Fp as UniformRand>::rand(rng);
162            test_interpreter::test_fixed_sel_degree_7_with_constants(&mut witness_env, a);
163
164            if row_i < domain_size - 1 {
165                witness_env.next_row();
166            }
167        }
168
169        witness_env
170    }
171
172    #[test]
173    fn test_completeness_fixed_sel_degree_7_with_constants() {
174        let mut rng = o1_utils::tests::make_test_rng(None);
175
176        // Include tests for completeness for Logup as the random witness
177        // includes all arguments
178        let domain_size = 1 << 8;
179
180        let fixed_selectors = test_interpreter::build_fixed_selectors(domain_size);
181
182        let mut constraint_env = ConstraintBuilderEnv::<Fp, DummyLookupTable>::create();
183        test_interpreter::constrain_test_fixed_sel_degree_7_with_constants::<Fp, _>(
184            &mut constraint_env,
185        );
186        // Don't use lookups for now
187        let constraints = constraint_env.get_relation_constraints();
188
189        let witness_env = build_test_fixed_sel_degree_7_circuit_with_constants::<_, DummyLookupTable>(
190            &mut rng,
191            domain_size,
192        );
193        let relation_witness = witness_env.get_relation_witness(domain_size);
194
195        crate::test::test_completeness_generic_no_lookups::<
196            { N_COL_TEST - N_FSEL_TEST },
197            { N_COL_TEST - N_FSEL_TEST },
198            0,
199            N_FSEL_TEST,
200            _,
201        >(
202            constraints,
203            fixed_selectors,
204            relation_witness,
205            domain_size,
206            &mut rng,
207        );
208    }
209
210    fn build_test_fixed_sel_degree_7_circuit_mul_witness<
211        RNG: RngCore + CryptoRng,
212        LT: LookupTableID,
213    >(
214        rng: &mut RNG,
215        domain_size: usize,
216    ) -> TestWitnessBuilderEnv<LT> {
217        let mut witness_env = WitnessBuilderEnv::create();
218
219        let fixed_selectors = test_interpreter::build_fixed_selectors(domain_size);
220        witness_env.set_fixed_selectors(fixed_selectors.to_vec());
221
222        for row_i in 0..domain_size {
223            let a: Fp = <Fp as UniformRand>::rand(rng);
224            test_interpreter::test_fixed_sel_degree_7_mul_witness(&mut witness_env, a);
225
226            if row_i < domain_size - 1 {
227                witness_env.next_row();
228            }
229        }
230
231        witness_env
232    }
233
234    #[test]
235    fn test_completeness_fixed_sel_degree_7_mul_witness() {
236        let mut rng = o1_utils::tests::make_test_rng(None);
237
238        // Include tests for completeness for Logup as the random witness
239        // includes all arguments
240        let domain_size = 1 << 8;
241
242        let fixed_selectors = test_interpreter::build_fixed_selectors(domain_size);
243
244        let mut constraint_env = ConstraintBuilderEnv::<Fp, DummyLookupTable>::create();
245        test_interpreter::constrain_test_fixed_sel_degree_7_mul_witness::<Fp, _>(
246            &mut constraint_env,
247        );
248        // Don't use lookups for now
249        let constraints = constraint_env.get_relation_constraints();
250
251        let witness_env = build_test_fixed_sel_degree_7_circuit_mul_witness::<_, DummyLookupTable>(
252            &mut rng,
253            domain_size,
254        );
255        let relation_witness = witness_env.get_relation_witness(domain_size);
256
257        crate::test::test_completeness_generic_no_lookups::<
258            { N_COL_TEST - N_FSEL_TEST },
259            { N_COL_TEST - N_FSEL_TEST },
260            0,
261            N_FSEL_TEST,
262            _,
263        >(
264            constraints,
265            fixed_selectors,
266            relation_witness,
267            domain_size,
268            &mut rng,
269        );
270    }
271
272    fn build_test_fixed_sel_degree_7_circuit_fixed_values<
273        RNG: RngCore + CryptoRng,
274        LT: LookupTableID,
275    >(
276        rng: &mut RNG,
277        domain_size: usize,
278    ) -> TestWitnessBuilderEnv<LT> {
279        let mut witness_env = WitnessBuilderEnv::create();
280
281        let fixed_selectors = test_interpreter::build_fixed_selectors(domain_size);
282        witness_env.set_fixed_selectors(fixed_selectors.to_vec());
283
284        for row_i in 0..domain_size {
285            let a: Fp = <Fp as UniformRand>::rand(rng);
286            test_interpreter::test_fixed_sel_degree_7(&mut witness_env, a);
287
288            if row_i < domain_size - 1 {
289                witness_env.next_row();
290            }
291        }
292
293        witness_env
294    }
295
296    #[test]
297    fn test_completeness_fixed_sel_degree_7_fixed_values() {
298        let mut rng = o1_utils::tests::make_test_rng(None);
299
300        // Include tests for completeness for Logup as the random witness
301        // includes all arguments
302        let domain_size = 1 << 8;
303
304        let fixed_selectors = test_interpreter::build_fixed_selectors(domain_size);
305
306        let mut constraint_env = ConstraintBuilderEnv::<Fp, DummyLookupTable>::create();
307        test_interpreter::constrain_test_fixed_sel_degree_7::<Fp, _>(&mut constraint_env);
308        // Don't use lookups for now
309        let constraints = constraint_env.get_relation_constraints();
310
311        let witness_env = build_test_fixed_sel_degree_7_circuit_fixed_values::<_, DummyLookupTable>(
312            &mut rng,
313            domain_size,
314        );
315        let relation_witness = witness_env.get_relation_witness(domain_size);
316
317        crate::test::test_completeness_generic_no_lookups::<
318            { N_COL_TEST - N_FSEL_TEST },
319            { N_COL_TEST - N_FSEL_TEST },
320            0,
321            N_FSEL_TEST,
322            _,
323        >(
324            constraints,
325            fixed_selectors,
326            relation_witness,
327            domain_size,
328            &mut rng,
329        );
330    }
331
332    fn build_test_const_circuit<RNG: RngCore + CryptoRng, LT: LookupTableID>(
333        rng: &mut RNG,
334        domain_size: usize,
335    ) -> (TestWitnessBuilderEnv<LT>, Fp) {
336        let mut witness_env = WitnessBuilderEnv::create();
337
338        // To support less rows than domain_size we need to have selectors.
339        //let row_num = rng.gen_range(0..domain_size);
340
341        let fixed_sel: Vec<Fp> = (0..domain_size).map(|i| Fp::from(i as u64)).collect();
342        witness_env.set_fixed_selector_cix(TestColumn::FixedSel1, fixed_sel);
343
344        let constant: Fp = <Fp as UniformRand>::rand(rng);
345        for row_i in 0..domain_size {
346            let a: Fp = <Fp as UniformRand>::rand(rng);
347            let b: Fp = constant / a;
348            assert!(a * b == constant);
349            test_interpreter::test_const(&mut witness_env, a, b, constant);
350
351            if row_i < domain_size - 1 {
352                witness_env.next_row();
353            }
354        }
355
356        (witness_env, constant)
357    }
358
359    #[test]
360    pub fn test_build_test_constant_circuit() {
361        let mut rng = o1_utils::tests::make_test_rng(None);
362        build_test_const_circuit::<_, DummyLookupTable>(&mut rng, 1 << 4);
363    }
364
365    #[test]
366    fn test_completeness_constant() {
367        let mut rng = o1_utils::tests::make_test_rng(None);
368
369        // Include tests for completeness for Logup as the random witness
370        // includes all arguments
371        let domain_size = 1 << 8;
372
373        let fixed_selectors = test_interpreter::build_fixed_selectors(domain_size);
374
375        let (witness_env, constant) =
376            build_test_const_circuit::<_, DummyLookupTable>(&mut rng, domain_size);
377        let relation_witness = witness_env.get_relation_witness(domain_size);
378
379        let mut constraint_env = ConstraintBuilderEnv::<Fp, DummyLookupTable>::create();
380        test_interpreter::constrain_test_const::<Fp, _>(&mut constraint_env, constant);
381        let constraints = constraint_env.get_relation_constraints();
382
383        crate::test::test_completeness_generic_no_lookups::<
384            { N_COL_TEST - N_FSEL_TEST },
385            { N_COL_TEST - N_FSEL_TEST },
386            0,
387            N_FSEL_TEST,
388            _,
389        >(
390            constraints,
391            fixed_selectors,
392            relation_witness,
393            domain_size,
394            &mut rng,
395        );
396    }
397
398    fn build_test_mul_circuit<RNG: RngCore + CryptoRng, LT: LookupTableID>(
399        rng: &mut RNG,
400        domain_size: usize,
401    ) -> TestWitnessBuilderEnv<LT> {
402        let mut witness_env = WitnessBuilderEnv::create();
403
404        // To support less rows than domain_size we need to have selectors.
405        //let row_num = rng.gen_range(0..domain_size);
406
407        let fixed_sel: Vec<Fp> = (0..domain_size).map(|i| Fp::from(i as u64)).collect();
408        witness_env.set_fixed_selector_cix(TestColumn::FixedSel1, fixed_sel);
409
410        let row_num = 10;
411        for row_i in 0..row_num {
412            let a: Ff1 = From::from(rng.gen_range(0..(1 << 16)));
413            let b: Ff1 = From::from(rng.gen_range(0..(1 << 16)));
414            test_interpreter::test_multiplication(&mut witness_env, a, b);
415            if row_i < domain_size - 1 {
416                witness_env.next_row();
417            }
418        }
419
420        witness_env
421    }
422
423    #[test]
424    /// Tests if the "test" circuit is valid without running the proof.
425    pub fn test_build_test_mul_circuit() {
426        let mut rng = o1_utils::tests::make_test_rng(None);
427        build_test_mul_circuit::<_, DummyLookupTable>(&mut rng, 1 << 4);
428    }
429
430    #[test]
431    fn test_completeness_lookups() {
432        let mut rng = o1_utils::tests::make_test_rng(None);
433
434        // Include tests for completeness for Logup as the random witness
435        // includes all arguments
436        let domain_size = 1 << 15;
437
438        let fixed_selectors = test_interpreter::build_fixed_selectors(domain_size);
439
440        let mut constraint_env = ConstraintBuilderEnv::<Fp, TestLookupTable>::create();
441        test_interpreter::constrain_lookups::<Fp, _>(&mut constraint_env);
442        let constraints = constraint_env.get_relation_constraints();
443
444        let mut witness_env: TestWitnessBuilderEnv<TestLookupTable> = WitnessBuilderEnv::create();
445        witness_env.set_fixed_selectors(fixed_selectors.to_vec());
446        test_interpreter::lookups_circuit(&mut witness_env, domain_size);
447        let runtime_tables: BTreeMap<_, Vec<Vec<Vec<_>>>> =
448            witness_env.get_runtime_tables(domain_size);
449
450        let mut lookup_tables_data: BTreeMap<TestLookupTable, Vec<Vec<Vec<Fp>>>> = BTreeMap::new();
451        for table_id in TestLookupTable::all_variants().into_iter() {
452            if table_id.is_fixed() {
453                lookup_tables_data.insert(
454                    table_id,
455                    vec![table_id
456                        .entries(domain_size as u64)
457                        .unwrap()
458                        .into_iter()
459                        .map(|x| vec![x])
460                        .collect()],
461                );
462            }
463        }
464        for (table_id, runtime_table) in runtime_tables.into_iter() {
465            lookup_tables_data.insert(table_id, runtime_table);
466        }
467
468        let proof_inputs = witness_env.get_proof_inputs(domain_size, lookup_tables_data);
469
470        crate::test::test_completeness_generic::<
471            { N_COL_TEST - N_FSEL_TEST },
472            { N_COL_TEST - N_FSEL_TEST },
473            0,
474            N_FSEL_TEST,
475            TestLookupTable,
476            _,
477        >(
478            constraints,
479            fixed_selectors,
480            proof_inputs,
481            domain_size,
482            &mut rng,
483        );
484    }
485
486    #[test]
487    fn test_completeness() {
488        let mut rng = o1_utils::tests::make_test_rng(None);
489
490        // Include tests for completeness for Logup as the random witness
491        // includes all arguments
492        let domain_size = 1 << 8;
493
494        let fixed_selectors = test_interpreter::build_fixed_selectors(domain_size);
495
496        let mut constraint_env = ConstraintBuilderEnv::<Fp, DummyLookupTable>::create();
497        test_interpreter::constrain_multiplication::<Fp, _>(&mut constraint_env);
498        // Don't use lookups for now
499        let constraints = constraint_env.get_relation_constraints();
500
501        let witness_env = build_test_mul_circuit::<_, DummyLookupTable>(&mut rng, domain_size);
502        let relation_witness = witness_env.get_relation_witness(domain_size);
503
504        crate::test::test_completeness_generic_no_lookups::<
505            { N_COL_TEST - N_FSEL_TEST },
506            { N_COL_TEST - N_FSEL_TEST },
507            0,
508            N_FSEL_TEST,
509            _,
510        >(
511            constraints,
512            fixed_selectors,
513            relation_witness,
514            domain_size,
515            &mut rng,
516        );
517    }
518
519    #[test]
520    fn test_soundness() {
521        let mut rng = o1_utils::tests::make_test_rng(None);
522
523        // We generate two different witness and two different proofs.
524        let domain_size: usize = 1 << 8;
525
526        let fixed_selectors = test_interpreter::build_fixed_selectors(domain_size);
527
528        let mut constraint_env = ConstraintBuilderEnv::<Fp, DummyLookupTable>::create();
529        test_interpreter::constrain_multiplication::<Fp, _>(&mut constraint_env);
530        let constraints = constraint_env.get_relation_constraints();
531
532        let lookup_tables_data = BTreeMap::new();
533        let witness_env = build_test_mul_circuit::<_, DummyLookupTable>(&mut rng, domain_size);
534        let mut proof_inputs =
535            witness_env.get_proof_inputs(domain_size, lookup_tables_data.clone());
536        proof_inputs.logups = Default::default();
537
538        let witness_env_prime =
539            build_test_mul_circuit::<_, DummyLookupTable>(&mut rng, domain_size);
540        let mut proof_inputs_prime =
541            witness_env_prime.get_proof_inputs(domain_size, lookup_tables_data.clone());
542        proof_inputs_prime.logups = Default::default();
543
544        crate::test::test_soundness_generic::<
545            { N_COL_TEST - N_FSEL_TEST },
546            { N_COL_TEST - N_FSEL_TEST },
547            0,
548            N_FSEL_TEST,
549            DummyLookupTable,
550            _,
551        >(
552            constraints,
553            fixed_selectors,
554            proof_inputs,
555            proof_inputs_prime,
556            domain_size,
557            &mut rng,
558        );
559    }
560}