1use crate::{
3 expr::E, logup::LookupTableID, lookups::LookupTableIDs, proof::ProofInputs, prover::prove,
4 verifier::verify, witness::Witness, BaseSponge, Fp, OpeningProof, ScalarSponge, BN254,
5};
6use ark_ec::AffineRepr;
7use kimchi::circuits::domains::EvaluationDomains;
8use poly_commitment::kzg::PairingSRS;
9use rand::{CryptoRng, RngCore};
10
11pub fn test_completeness_generic_only_relation<const N_REL: usize, RNG>(
13 constraints: Vec<E<Fp>>,
14 evaluations: Witness<N_REL, Vec<Fp>>,
15 domain_size: usize,
16 rng: &mut RNG,
17) where
18 RNG: RngCore + CryptoRng,
19{
20 test_completeness_generic_no_lookups::<N_REL, N_REL, 0, 0, _>(
21 constraints,
22 Box::new([]),
23 evaluations,
24 domain_size,
25 rng,
26 )
27}
28
29pub fn test_completeness_generic_no_lookups<
30 const N_WIT: usize,
31 const N_REL: usize,
32 const N_DSEL: usize,
33 const N_FSEL: usize,
34 RNG,
35>(
36 constraints: Vec<E<Fp>>,
37 fixed_selectors: Box<[Vec<Fp>; N_FSEL]>,
38 evaluations: Witness<N_WIT, Vec<Fp>>,
39 domain_size: usize,
40 rng: &mut RNG,
41) where
42 RNG: RngCore + CryptoRng,
43{
44 let proof_inputs = ProofInputs {
45 evaluations,
46 logups: Default::default(),
47 };
48 test_completeness_generic::<N_WIT, N_REL, N_DSEL, N_FSEL, LookupTableIDs, _>(
49 constraints,
50 fixed_selectors,
51 proof_inputs,
52 domain_size,
53 rng,
54 )
55}
56
57pub fn test_completeness_generic<
60 const N_WIT: usize,
61 const N_REL: usize,
62 const N_DSEL: usize,
63 const N_FSEL: usize,
64 LT: LookupTableID,
65 RNG,
66>(
67 constraints: Vec<E<Fp>>,
68 fixed_selectors: Box<[Vec<Fp>; N_FSEL]>,
69 proof_inputs: ProofInputs<N_WIT, Fp, LT>,
70 domain_size: usize,
71 rng: &mut RNG,
72) where
73 RNG: RngCore + CryptoRng,
74{
75 let domain = EvaluationDomains::<Fp>::create(domain_size).unwrap();
76
77 let srs: PairingSRS<BN254> = crate::precomputed_srs::get_bn254_srs(domain);
78
79 let proof =
80 prove::<_, OpeningProof, BaseSponge, ScalarSponge, _, N_WIT, N_REL, N_DSEL, N_FSEL, LT>(
81 domain,
82 &srs,
83 &constraints,
84 fixed_selectors.clone(),
85 proof_inputs.clone(),
86 rng,
87 )
88 .unwrap();
89
90 {
91 (&proof.proof_comms.witness_comms)
99 .into_iter()
100 .for_each(|x| assert_eq!(x.len(), 1));
101 assert!(
103 (&proof.proof_comms.witness_comms)
104 .into_iter()
105 .fold(0, |acc, x| acc + x.len())
106 == N_WIT
107 );
108 (&proof.proof_comms.witness_comms)
110 .into_iter()
111 .for_each(|v| v.chunks.iter().for_each(|x| assert!(!x.is_zero())));
112
113 let max_degree = {
115 if proof_inputs.logups.is_empty() {
116 constraints
117 .iter()
118 .map(|expr| expr.degree(1, 0))
119 .max()
120 .unwrap_or(0)
121 } else {
122 8
123 }
124 };
125
126 if max_degree == 1 {
127 assert_eq!(proof.proof_comms.t_comm.len(), 1);
128 } else {
129 assert_eq!(proof.proof_comms.t_comm.len(), max_degree as usize - 1);
130 }
131 }
132
133 let verifies =
134 verify::<_, OpeningProof, BaseSponge, ScalarSponge, N_WIT, N_REL, N_DSEL, N_FSEL, 0, LT>(
135 domain,
136 &srs,
137 &constraints,
138 fixed_selectors,
139 &proof,
140 Witness::zero_vec(domain_size),
141 );
142 assert!(verifies)
143}
144
145pub fn test_soundness_generic<
146 const N_WIT: usize,
147 const N_REL: usize,
148 const N_DSEL: usize,
149 const N_FSEL: usize,
150 LT: LookupTableID,
151 RNG,
152>(
153 constraints: Vec<E<Fp>>,
154 fixed_selectors: Box<[Vec<Fp>; N_FSEL]>,
155 proof_inputs: ProofInputs<N_WIT, Fp, LT>,
156 proof_inputs_prime: ProofInputs<N_WIT, Fp, LT>,
157 domain_size: usize,
158 rng: &mut RNG,
159) where
160 RNG: RngCore + CryptoRng,
161{
162 let domain = EvaluationDomains::<Fp>::create(domain_size).unwrap();
163
164 let srs: PairingSRS<BN254> = crate::precomputed_srs::get_bn254_srs(domain);
165
166 let proof =
168 prove::<_, OpeningProof, BaseSponge, ScalarSponge, _, N_WIT, N_REL, N_DSEL, N_FSEL, LT>(
169 domain,
170 &srs,
171 &constraints,
172 fixed_selectors.clone(),
173 proof_inputs,
174 rng,
175 )
176 .unwrap();
177
178 let proof_prime =
180 prove::<_, OpeningProof, BaseSponge, ScalarSponge, _, N_WIT, N_REL, N_DSEL, N_FSEL, LT>(
181 domain,
182 &srs,
183 &constraints,
184 fixed_selectors.clone(),
185 proof_inputs_prime,
186 rng,
187 )
188 .unwrap();
189
190 {
192 let mut proof_clone = proof.clone();
193 proof_clone.opening_proof = proof_prime.opening_proof;
194 let verifies = verify::<
195 _,
196 OpeningProof,
197 BaseSponge,
198 ScalarSponge,
199 N_WIT,
200 N_REL,
201 N_DSEL,
202 N_FSEL,
203 0,
204 LT,
205 >(
206 domain,
207 &srs,
208 &constraints,
209 fixed_selectors.clone(),
210 &proof_clone,
211 Witness::zero_vec(domain_size),
212 );
213 assert!(!verifies, "Proof with a swapped opening must fail");
214 }
215
216 {
220 let mut proof_clone = proof.clone();
221 proof_clone.proof_comms = proof_prime.proof_comms;
222 let verifies = verify::<
223 _,
224 OpeningProof,
225 BaseSponge,
226 ScalarSponge,
227 N_WIT,
228 N_REL,
229 N_DSEL,
230 N_FSEL,
231 0,
232 LT,
233 >(
234 domain,
235 &srs,
236 &constraints,
237 fixed_selectors.clone(),
238 &proof_clone,
239 Witness::zero_vec(domain_size),
240 );
241 assert!(!verifies, "Proof with a swapped commitment must fail");
242 }
243
244 {
249 let mut proof_clone = proof.clone();
250 proof_clone.proof_evals.witness_evals = proof_prime.proof_evals.witness_evals;
251 let verifies = verify::<
252 _,
253 OpeningProof,
254 BaseSponge,
255 ScalarSponge,
256 N_WIT,
257 N_REL,
258 N_DSEL,
259 N_FSEL,
260 0,
261 LT,
262 >(
263 domain,
264 &srs,
265 &constraints,
266 fixed_selectors,
267 &proof_clone,
268 Witness::zero_vec(domain_size),
269 );
270 assert!(!verifies, "Proof with a swapped witness eval must fail");
271 }
272}