1#[cfg(feature = "profile")]
2use ark_std::{end_timer, start_timer};
3use ff::{Field, WithSmallOrderMulGroup};
4use group::Curve;
5use rand_core::RngCore;
6
7use std::hash::Hash;
8use std::marker::PhantomData;
9use std::ops::RangeTo;
10
11#[cfg(feature = "multicore")]
12use crate::multicore::IndexedParallelIterator;
13use crate::multicore::{IntoParallelIterator, ParallelIterator};
14use std::{collections::HashMap, iter};
15
16use super::{
17 circuit::{
18 sealed::{self},
19 Advice, Any, Assignment, Challenge, Circuit, Column, ConstraintSystem, Fixed, FloorPlanner,
20 Instance, Selector,
21 },
22 lookup, permutation, vanishing, ChallengeBeta, ChallengeGamma, ChallengeTheta, ChallengeX,
23 ChallengeY, Error, ProvingKey,
24};
25
26use crate::{
27 arithmetic::{eval_polynomial, CurveAffine},
28 circuit::Value,
29 plonk::Assigned,
30 poly::{
31 commitment::{Blind, CommitmentScheme, Params, Prover},
32 Basis, Coeff, LagrangeCoeff, Polynomial, ProverQuery,
33 },
34};
35use crate::{
36 poly::batch_invert_assigned,
37 transcript::{EncodedChallenge, TranscriptWrite},
38};
39
40pub fn create_proof<
45 'params,
46 'a,
47 Scheme: CommitmentScheme,
48 P: Prover<'params, Scheme>,
49 E: EncodedChallenge<Scheme::Curve>,
50 R: RngCore + 'a,
51 T: TranscriptWrite<Scheme::Curve, E>,
52 ConcreteCircuit: Circuit<Scheme::Scalar>,
53>(
54 params: &'params Scheme::ParamsProver,
55 pk: &ProvingKey<Scheme::Curve>,
56 circuits: &[ConcreteCircuit],
57 instances: &[&[&'a [Scheme::Scalar]]],
58 mut rng: R,
59 mut transcript: &'a mut T,
60) -> Result<(), Error>
61where
62 Scheme::Scalar: Hash + WithSmallOrderMulGroup<3>,
63 <Scheme as CommitmentScheme>::ParamsProver: Sync,
64{
65 if circuits.len() != instances.len() {
66 return Err(Error::InvalidInstances);
67 }
68
69 for instance in instances.iter() {
70 if instance.len() != pk.vk.cs.num_instance_columns {
71 return Err(Error::InvalidInstances);
72 }
73 }
74
75 pk.vk.hash_into(transcript)?;
77
78 let domain = &pk.vk.domain;
79 let mut meta = ConstraintSystem::default();
80 #[cfg(feature = "circuit-params")]
81 let config = ConcreteCircuit::configure_with_params(&mut meta, circuits[0].params());
82 #[cfg(not(feature = "circuit-params"))]
83 let config = ConcreteCircuit::configure(&mut meta);
84
85 let meta = &pk.vk.cs;
88
89 struct InstanceSingle<C: CurveAffine> {
90 pub instance_values: Vec<Polynomial<C::Scalar, LagrangeCoeff>>,
91 pub instance_polys: Vec<Polynomial<C::Scalar, Coeff>>,
92 }
93
94 let instance: Vec<InstanceSingle<Scheme::Curve>> = instances
95 .iter()
96 .map(|instance| -> InstanceSingle<Scheme::Curve> {
97 let instance_values = instance
98 .iter()
99 .map(|values| {
100 let mut poly = domain.empty_lagrange();
101 assert_eq!(poly.len(), params.n() as usize);
102 if values.len() > (poly.len() - (meta.blinding_factors() + 1)) {
103 panic!("Error::InstanceTooLarge");
104 }
105 for (poly, value) in poly.iter_mut().zip(values.iter()) {
106 *poly = *value;
107 }
108 poly
109 })
110 .collect::<Vec<_>>();
111
112 let instance_polys: Vec<_> = instance_values
113 .iter()
114 .map(|poly| {
115 let lagrange_vec = domain.lagrange_from_vec(poly.to_vec());
116 domain.lagrange_to_coeff(lagrange_vec)
117 })
118 .collect();
119
120 InstanceSingle {
121 instance_values,
122 instance_polys,
123 }
124 })
125 .collect();
126
127 #[derive(Clone)]
128 struct AdviceSingle<C: CurveAffine, B: Basis> {
129 pub advice_polys: Vec<Polynomial<C::Scalar, B>>,
130 pub advice_blinds: Vec<Blind<C::Scalar>>,
131 }
132
133 struct WitnessCollection<'params, 'a, 'b, Scheme, P, C, E, R, T>
134 where
135 Scheme: CommitmentScheme<Curve = C>,
136 P: Prover<'params, Scheme>,
137 C: CurveAffine,
138 E: EncodedChallenge<C>,
139 R: RngCore + 'a,
140 T: TranscriptWrite<C, E>,
141 {
142 params: &'params Scheme::ParamsProver,
143 current_phase: sealed::Phase,
144 advice: Vec<Polynomial<Assigned<C::Scalar>, LagrangeCoeff>>,
145 challenges: &'b mut HashMap<usize, C::Scalar>,
146 instances: &'b [&'a [C::Scalar]],
147 usable_rows: RangeTo<usize>,
148 advice_single: AdviceSingle<C, LagrangeCoeff>,
149 instance_single: &'b InstanceSingle<C>,
150 rng: &'b mut R,
151 transcript: &'b mut &'a mut T,
152 column_indices: [Vec<usize>; 3],
153 challenge_indices: [Vec<usize>; 3],
154 unusable_rows_start: usize,
155 _marker: PhantomData<(P, E)>,
156 }
157
158 impl<'params, 'a, 'b, F, Scheme, P, C, E, R, T> Assignment<F>
159 for WitnessCollection<'params, 'a, 'b, Scheme, P, C, E, R, T>
160 where
161 F: Field,
162 Scheme: CommitmentScheme<Curve = C>,
163 P: Prover<'params, Scheme>,
164 C: CurveAffine<ScalarExt = F>,
165 E: EncodedChallenge<C>,
166 R: RngCore,
167 T: TranscriptWrite<C, E>,
168 <Scheme as CommitmentScheme>::ParamsProver: Sync,
169 {
170 fn enter_region<NR, N>(&mut self, _: N)
171 where
172 NR: Into<String>,
173 N: FnOnce() -> NR,
174 {
175 }
177
178 fn exit_region(&mut self) {
179 }
181
182 fn enable_selector<A, AR>(&mut self, _: A, _: &Selector, _: usize) -> Result<(), Error>
183 where
184 A: FnOnce() -> AR,
185 AR: Into<String>,
186 {
187 Ok(())
190 }
191
192 fn annotate_column<A, AR>(&mut self, _annotation: A, _column: Column<Any>)
193 where
194 A: FnOnce() -> AR,
195 AR: Into<String>,
196 {
197 }
199
200 fn query_instance(&self, column: Column<Instance>, row: usize) -> Result<Value<F>, Error> {
201 if !self.usable_rows.contains(&row) {
202 return Err(Error::not_enough_rows_available(self.params.k()));
203 }
204
205 self.instances
206 .get(column.index())
207 .and_then(|column| column.get(row))
208 .map(|v| Value::known(*v))
209 .ok_or(Error::BoundsFailure)
210 }
211
212 fn assign_advice<'v>(
213 &mut self,
215 column: Column<Advice>,
217 row: usize,
218 to: Value<Assigned<F>>,
219 ) -> Value<&'v Assigned<F>> {
220 debug_assert!(
223 self.usable_rows.contains(&row),
224 "{:?}",
225 Error::not_enough_rows_available(self.params.k())
226 );
227
228 let advice_get_mut = self
229 .advice
230 .get_mut(column.index())
231 .expect("Not enough advice columns")
232 .get_mut(row)
233 .expect("Not enough rows");
234 *advice_get_mut = to
243 .assign()
244 .expect("No Value::unknown() in advice column allowed during create_proof");
245 let immutable_raw_ptr = advice_get_mut as *const Assigned<F>;
246 Value::known(unsafe { &*immutable_raw_ptr })
247 }
248
249 fn assign_fixed(&mut self, _: Column<Fixed>, _: usize, _: Assigned<F>) {
250 }
252
253 fn copy(&mut self, _: Column<Any>, _: usize, _: Column<Any>, _: usize) {
254 }
256
257 fn fill_from_row(
258 &mut self,
259 _: Column<Fixed>,
260 _: usize,
261 _: Value<Assigned<F>>,
262 ) -> Result<(), Error> {
263 Ok(())
264 }
265
266 fn get_challenge(&self, challenge: Challenge) -> Value<F> {
267 self.challenges
268 .get(&challenge.index())
269 .cloned()
270 .map(Value::known)
271 .unwrap_or_else(Value::unknown)
272 }
273
274 fn push_namespace<NR, N>(&mut self, _: N)
275 where
276 NR: Into<String>,
277 N: FnOnce() -> NR,
278 {
279 }
281
282 fn pop_namespace(&mut self, _: Option<String>) {
283 }
285
286 fn next_phase(&mut self) {
287 let phase = self.current_phase.to_u8() as usize;
288 #[cfg(feature = "profile")]
289 let start1 = start_timer!(|| format!("Phase {phase} inversion and MSM commitment"));
290 if phase == 0 {
291 if !P::QUERY_INSTANCE {
295 for values in self.instances.iter() {
296 for value in values.iter() {
297 self.transcript
298 .common_scalar(*value)
299 .expect("Absorbing instance value to transcript failed");
300 }
301 }
302 } else {
303 let instance_commitments_projective: Vec<_> =
304 (&self.instance_single.instance_values)
305 .into_par_iter()
306 .map(|poly| self.params.commit_lagrange(poly, Blind::default()))
307 .collect();
308 let mut instance_commitments =
309 vec![C::identity(); instance_commitments_projective.len()];
310 C::CurveExt::batch_normalize(
311 &instance_commitments_projective,
312 &mut instance_commitments,
313 );
314 let instance_commitments = instance_commitments;
315 drop(instance_commitments_projective);
316
317 for commitment in &instance_commitments {
318 self.transcript
319 .common_point(*commitment)
320 .expect("Absorbing instance commitment to transcript failed");
321 }
322 }
323 }
324 let mut advice_values = batch_invert_assigned(
326 self.column_indices
327 .get(phase)
328 .expect("The API only supports 3 phases right now")
329 .iter()
330 .map(|column_index| &self.advice[*column_index][..])
331 .collect(),
332 );
333 for advice_values in &mut advice_values {
335 for cell in &mut advice_values[self.unusable_rows_start..] {
336 *cell = F::random(&mut self.rng);
337 }
338 }
339 let blinds: Vec<_> = advice_values
341 .iter()
342 .map(|_| Blind(F::random(&mut self.rng)))
343 .collect();
344 let advice_commitments_projective: Vec<_> = (&advice_values)
345 .into_par_iter()
346 .zip((&blinds).into_par_iter())
347 .map(|(poly, blind)| self.params.commit_lagrange(poly, *blind))
348 .collect();
349 let mut advice_commitments = vec![C::identity(); advice_commitments_projective.len()];
350 C::CurveExt::batch_normalize(&advice_commitments_projective, &mut advice_commitments);
351 let advice_commitments = advice_commitments;
352 drop(advice_commitments_projective);
353
354 for commitment in &advice_commitments {
355 self.transcript
356 .write_point(*commitment)
357 .expect("Absorbing advice commitment to transcript failed");
358 }
359 for ((column_index, advice_poly), blind) in self.column_indices[phase]
360 .iter()
361 .zip(advice_values)
362 .zip(blinds)
363 {
364 self.advice_single.advice_polys[*column_index] = advice_poly;
365 self.advice_single.advice_blinds[*column_index] = blind;
366 }
367 for challenge_index in self.challenge_indices[phase].iter() {
368 let existing = self.challenges.insert(
369 *challenge_index,
370 *self.transcript.squeeze_challenge_scalar::<()>(),
371 );
372 assert!(existing.is_none());
373 }
374 self.current_phase = self.current_phase.next();
375 #[cfg(feature = "profile")]
376 end_timer!(start1);
377 }
378 }
379
380 let mut column_indices = [(); 3].map(|_| vec![]);
381 for (index, phase) in meta.advice_column_phase.iter().enumerate() {
382 column_indices[phase.to_u8() as usize].push(index);
383 }
384 let mut challenge_indices = [(); 3].map(|_| vec![]);
385 for (index, phase) in meta.challenge_phase.iter().enumerate() {
386 challenge_indices[phase.to_u8() as usize].push(index);
387 }
388
389 #[cfg(feature = "profile")]
390 let phase1_time = start_timer!(|| "Phase 1: Witness assignment and MSM commitments");
391 let (advice, challenges) = {
392 let mut advice = Vec::with_capacity(instances.len());
393 let mut challenges = HashMap::<usize, Scheme::Scalar>::with_capacity(meta.num_challenges);
394
395 let unusable_rows_start = params.n() as usize - (meta.blinding_factors() + 1);
396 let phases = pk.vk.cs.phases().collect::<Vec<_>>();
397 let num_phases = phases.len();
398 if num_phases > 1 {
402 assert_eq!(
403 circuits.len(),
404 1,
405 "New challenge API doesn't work with multiple circuits yet"
406 );
407 }
408 for ((circuit, instances), instance_single) in
409 circuits.iter().zip(instances).zip(instance.iter())
410 {
411 let mut witness: WitnessCollection<Scheme, P, _, E, _, _> = WitnessCollection {
412 params,
413 current_phase: phases[0],
414 advice: vec![domain.empty_lagrange_assigned(); meta.num_advice_columns],
415 instances,
416 challenges: &mut challenges,
417 usable_rows: ..unusable_rows_start,
422 advice_single: AdviceSingle::<Scheme::Curve, LagrangeCoeff> {
423 advice_polys: vec![domain.empty_lagrange(); meta.num_advice_columns],
424 advice_blinds: vec![Blind::default(); meta.num_advice_columns],
425 },
426 instance_single,
427 rng: &mut rng,
428 transcript: &mut transcript,
429 column_indices: column_indices.clone(),
430 challenge_indices: challenge_indices.clone(),
431 unusable_rows_start,
432 _marker: PhantomData,
433 };
434
435 while witness.current_phase.to_u8() < num_phases as u8 {
438 #[cfg(feature = "profile")]
439 let syn_time = start_timer!(|| format!(
440 "Synthesize time starting from phase {} (synthesize may cross multiple phases)",
441 witness.current_phase.to_u8()
442 ));
443 ConcreteCircuit::FloorPlanner::synthesize(
445 &mut witness,
446 circuit,
447 config.clone(),
448 meta.constants.clone(),
449 )
450 .unwrap();
451 #[cfg(feature = "profile")]
452 end_timer!(syn_time);
453 if witness.current_phase.to_u8() < num_phases as u8 {
454 witness.next_phase();
455 }
456 }
457 advice.push(witness.advice_single);
458 }
459
460 assert_eq!(challenges.len(), meta.num_challenges);
461 let challenges = (0..meta.num_challenges)
462 .map(|index| challenges.remove(&index).unwrap())
463 .collect::<Vec<_>>();
464
465 (advice, challenges)
466 };
467 #[cfg(feature = "profile")]
468 end_timer!(phase1_time);
469
470 #[cfg(feature = "profile")]
471 let phase2_time = start_timer!(|| "Phase 2: Lookup commit permuted");
472 let theta: ChallengeTheta<_> = transcript.squeeze_challenge_scalar();
474
475 let lookups: Vec<Vec<lookup::prover::Permuted<Scheme::Curve>>> = instance
476 .iter()
477 .zip(advice.iter())
478 .map(|(instance, advice)| -> Vec<_> {
479 pk.vk
481 .cs
482 .lookups
483 .iter()
484 .map(|lookup| {
485 lookup
486 .commit_permuted(
487 pk,
488 params,
489 domain,
490 theta,
491 &advice.advice_polys,
492 &pk.fixed_values,
493 &instance.instance_values,
494 &challenges,
495 &mut rng,
496 transcript,
497 )
498 .unwrap()
499 })
500 .collect()
501 })
502 .collect();
503 #[cfg(feature = "profile")]
504 end_timer!(phase2_time);
505
506 #[cfg(feature = "profile")]
507 let phase3a_time = start_timer!(|| "Phase 3a: Commit to permutations");
508
509 let beta: ChallengeBeta<_> = transcript.squeeze_challenge_scalar();
511
512 let gamma: ChallengeGamma<_> = transcript.squeeze_challenge_scalar();
514
515 let permutations: Vec<permutation::prover::Committed<Scheme::Curve>> = instance
517 .iter()
518 .zip(advice.iter())
519 .map(|(instance, advice)| {
520 pk.vk
521 .cs
522 .permutation
523 .commit(
524 params,
525 pk,
526 &pk.permutation,
527 &advice.advice_polys,
528 &pk.fixed_values,
529 &instance.instance_values,
530 beta,
531 gamma,
532 &mut rng,
533 transcript,
534 )
535 .unwrap()
536 })
537 .collect::<Vec<_>>();
538 #[cfg(feature = "profile")]
539 end_timer!(phase3a_time);
540
541 #[cfg(feature = "profile")]
542 let phase3b_time = start_timer!(|| "Phase 3b: Lookup commit product");
543 let lookups: Vec<Vec<lookup::prover::Committed<Scheme::Curve>>> = lookups
544 .into_iter()
545 .map(|lookups| -> Vec<_> {
546 lookups
548 .into_iter()
549 .map(|lookup| {
550 lookup
551 .commit_product(pk, params, beta, gamma, &mut rng, transcript)
552 .unwrap()
553 })
554 .collect()
555 })
556 .collect();
557 #[cfg(feature = "profile")]
558 end_timer!(phase3b_time);
559
560 #[cfg(feature = "profile")]
561 let vanishing_time = start_timer!(|| "Commit to vanishing argument's random poly");
562 let vanishing = vanishing::Argument::commit(params, domain, &mut rng, transcript).unwrap();
564
565 let y: ChallengeY<_> = transcript.squeeze_challenge_scalar();
567
568 #[cfg(feature = "profile")]
569 end_timer!(vanishing_time);
570 #[cfg(feature = "profile")]
571 let fft_time = start_timer!(|| "Calculate advice polys (fft)");
572
573 let advice: Vec<AdviceSingle<Scheme::Curve, Coeff>> = advice
575 .into_iter()
576 .map(
577 |AdviceSingle {
578 advice_polys,
579 advice_blinds,
580 }| {
581 AdviceSingle {
582 advice_polys: advice_polys
583 .into_iter()
584 .map(|poly| domain.lagrange_to_coeff(poly))
585 .collect::<Vec<_>>(),
586 advice_blinds,
587 }
588 },
589 )
590 .collect();
591 #[cfg(feature = "profile")]
592 end_timer!(fft_time);
593
594 #[cfg(feature = "profile")]
595 let phase4_time = start_timer!(|| "Phase 4: Evaluate h(X)");
596 let h_poly = pk.ev.evaluate_h(
598 pk,
599 &advice
600 .iter()
601 .map(|a| a.advice_polys.as_slice())
602 .collect::<Vec<_>>(),
603 &instance
604 .iter()
605 .map(|i| i.instance_polys.as_slice())
606 .collect::<Vec<_>>(),
607 &challenges,
608 *y,
609 *beta,
610 *gamma,
611 *theta,
612 &lookups,
613 &permutations,
614 );
615 #[cfg(feature = "profile")]
616 end_timer!(phase4_time);
617
618 #[cfg(feature = "profile")]
619 let timer = start_timer!(|| "Commit to vanishing argument's h(X) commitments");
620 let vanishing = vanishing.construct(params, domain, h_poly, &mut rng, transcript)?;
622 #[cfg(feature = "profile")]
623 end_timer!(timer);
624 #[cfg(feature = "profile")]
625 let eval_time = start_timer!(|| "Commit to vanishing argument's h(X) commitments");
626
627 let x: ChallengeX<_> = transcript.squeeze_challenge_scalar();
628 let xn = x.pow([params.n()]);
629
630 if P::QUERY_INSTANCE {
631 for instance in instance.iter() {
633 let instance_evals: Vec<_> = meta
635 .instance_queries
636 .iter()
637 .map(|&(column, at)| {
638 eval_polynomial(
639 &instance.instance_polys[column.index()],
640 domain.rotate_omega(*x, at),
641 )
642 })
643 .collect();
644
645 for eval in instance_evals.iter() {
647 transcript.write_scalar(*eval)?;
648 }
649 }
650 }
651
652 for advice in advice.iter() {
654 let advice_evals: Vec<_> = meta
656 .advice_queries
657 .iter()
658 .map(|&(column, at)| {
659 eval_polynomial(
660 &advice.advice_polys[column.index()],
661 domain.rotate_omega(*x, at),
662 )
663 })
664 .collect();
665
666 for eval in advice_evals.iter() {
668 transcript.write_scalar(*eval)?;
669 }
670 }
671
672 let fixed_evals: Vec<_> = meta
674 .fixed_queries
675 .iter()
676 .map(|&(column, at)| {
677 eval_polynomial(&pk.fixed_polys[column.index()], domain.rotate_omega(*x, at))
678 })
679 .collect();
680
681 for eval in fixed_evals.iter() {
683 transcript.write_scalar(*eval)?;
684 }
685
686 let vanishing = vanishing.evaluate(x, xn, domain, transcript)?;
687
688 pk.permutation.evaluate(x, transcript)?;
690
691 let permutations: Vec<permutation::prover::Evaluated<Scheme::Curve>> = permutations
693 .into_iter()
694 .map(|permutation| permutation.construct().evaluate(pk, x, transcript).unwrap())
695 .collect();
696
697 let lookups: Vec<Vec<lookup::prover::Evaluated<Scheme::Curve>>> = lookups
699 .into_iter()
700 .map(|lookups| -> Vec<_> {
701 lookups
702 .into_iter()
703 .map(|p| p.evaluate(pk, x, transcript).unwrap())
704 .collect()
705 })
706 .collect();
707 #[cfg(feature = "profile")]
708 end_timer!(eval_time);
709
710 let instances = instance
711 .iter()
712 .zip(advice.iter())
713 .zip(permutations.iter())
714 .zip(lookups.iter())
715 .flat_map(|(((instance, advice), permutation), lookups)| {
716 iter::empty()
717 .chain(
718 P::QUERY_INSTANCE
719 .then_some(pk.vk.cs.instance_queries.iter().map(move |&(column, at)| {
720 ProverQuery {
721 point: domain.rotate_omega(*x, at),
722 poly: &instance.instance_polys[column.index()],
723 blind: Blind::default(),
724 }
725 }))
726 .into_iter()
727 .flatten(),
728 )
729 .chain(
730 pk.vk
731 .cs
732 .advice_queries
733 .iter()
734 .map(move |&(column, at)| ProverQuery {
735 point: domain.rotate_omega(*x, at),
736 poly: &advice.advice_polys[column.index()],
737 blind: advice.advice_blinds[column.index()],
738 }),
739 )
740 .chain(permutation.open(pk, x))
741 .chain(lookups.iter().flat_map(move |p| p.open(pk, x)))
742 })
743 .chain(
744 pk.vk
745 .cs
746 .fixed_queries
747 .iter()
748 .map(|&(column, at)| ProverQuery {
749 point: domain.rotate_omega(*x, at),
750 poly: &pk.fixed_polys[column.index()],
751 blind: Blind::default(),
752 }),
753 )
754 .chain(pk.permutation.open(x))
755 .chain(vanishing.open(x));
757
758 #[cfg(feature = "profile")]
759 let multiopen_time = start_timer!(|| "Phase 5: multiopen");
760 let prover = P::new(params);
761 #[allow(clippy::let_and_return)]
762 let multiopen_res = prover
763 .create_proof(&mut rng, transcript, instances)
764 .map_err(|_| Error::ConstraintSystemFailure);
765 #[cfg(feature = "profile")]
766 end_timer!(multiopen_time);
767 multiopen_res
768}
769
770#[test]
771fn test_create_proof() {
772 use crate::{
773 circuit::SimpleFloorPlanner,
774 plonk::{keygen_pk, keygen_vk},
775 poly::kzg::{
776 commitment::{KZGCommitmentScheme, ParamsKZG},
777 multiopen::ProverSHPLONK,
778 },
779 transcript::{Blake2bWrite, Challenge255, TranscriptWriterBuffer},
780 };
781 use halo2curves::bn256::Bn256;
782 use rand_core::OsRng;
783
784 #[derive(Clone, Copy)]
785 struct MyCircuit;
786
787 impl<F: Field> Circuit<F> for MyCircuit {
788 type Config = ();
789 type FloorPlanner = SimpleFloorPlanner;
790 #[cfg(feature = "circuit-params")]
791 type Params = ();
792
793 fn without_witnesses(&self) -> Self {
794 *self
795 }
796
797 fn configure(_meta: &mut ConstraintSystem<F>) -> Self::Config {}
798
799 fn synthesize(
800 &self,
801 _config: Self::Config,
802 _layouter: impl crate::circuit::Layouter<F>,
803 ) -> Result<(), Error> {
804 Ok(())
805 }
806 }
807
808 let params: ParamsKZG<Bn256> = ParamsKZG::setup(3, OsRng);
809 let vk = keygen_vk(¶ms, &MyCircuit).expect("keygen_vk should not fail");
810 let pk = keygen_pk(¶ms, vk, &MyCircuit).expect("keygen_pk should not fail");
811 let mut transcript = Blake2bWrite::<_, _, Challenge255<_>>::init(vec![]);
812
813 let proof = create_proof::<KZGCommitmentScheme<_>, ProverSHPLONK<_>, _, _, _, _>(
815 ¶ms,
816 &pk,
817 &[MyCircuit, MyCircuit],
818 &[],
819 OsRng,
820 &mut transcript,
821 );
822 assert!(matches!(proof.unwrap_err(), Error::InvalidInstances));
823
824 create_proof::<KZGCommitmentScheme<_>, ProverSHPLONK<_>, _, _, _, _>(
826 ¶ms,
827 &pk,
828 &[MyCircuit, MyCircuit],
829 &[&[], &[]],
830 OsRng,
831 &mut transcript,
832 )
833 .expect("proof generation should not fail");
834}