1use crate::{
9 circuit::plonk_verifier::{BatchProofVar, ProofEvaluationsVar},
10 errors::{
11 PlonkError,
12 SnarkError::{self, ParameterError, SnarkLookupUnsupported},
13 },
14};
15use ark_ec::{
16 pairing::Pairing,
17 scalar_mul::variable_base::VariableBaseMSM,
18 short_weierstrass::{Affine, SWCurveConfig},
19 CurveGroup,
20};
21use ark_ff::{FftField, Field, Fp2, Fp2Config, PrimeField, Zero};
22use ark_poly::univariate::DensePolynomial;
23use ark_serialize::*;
24use ark_std::{format, string::ToString, vec, vec::Vec};
25use derive_where::derive_where;
26use espresso_systems_common::jellyfish::tag;
27use hashbrown::HashMap;
28use jf_pcs::prelude::{
29 Commitment, UnivariateProverParam, UnivariateUniversalParams, UnivariateVerifierParam,
30};
31use jf_relation::{
32 constants::{compute_coset_representatives, GATE_WIDTH, N_TURBO_PLONK_SELECTORS},
33 gadgets::{
34 ecc::{SWToTEConParam, TEPoint},
35 ultraplonk::mod_arith::FpElemVar,
36 },
37 PlonkCircuit,
38};
39use jf_rescue::RescueParameter;
40use jf_utils::{field_switching, fq_to_fr, fr_to_fq};
41use tagged_base64::tagged;
42
43pub type UniversalSrs<E> = UnivariateUniversalParams<E>;
45pub type CommitKey<E> = UnivariateProverParam<E>;
47pub type OpenKey<E> = UnivariateVerifierParam<E>;
49
50#[tagged(tag::PROOF)]
52#[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
53#[derive_where(Hash; E: Pairing)]
54pub struct Proof<E: Pairing> {
55 pub wires_poly_comms: Vec<Commitment<E>>,
57
58 pub prod_perm_poly_comm: Commitment<E>,
60
61 pub split_quot_poly_comms: Vec<Commitment<E>>,
63
64 pub opening_proof: Commitment<E>,
66
67 pub shifted_opening_proof: Commitment<E>,
70
71 pub poly_evals: ProofEvaluations<E::ScalarField>,
73
74 pub plookup_proof: Option<PlookupProof<E>>,
76}
77
78impl<E, P> TryFrom<Vec<E::BaseField>> for Proof<E>
79where
80 E: Pairing<G1Affine = Affine<P>>,
81 P: SWCurveConfig<BaseField = E::BaseField, ScalarField = E::ScalarField>,
82{
83 type Error = SnarkError;
84
85 fn try_from(value: Vec<E::BaseField>) -> Result<Self, Self::Error> {
86 const TURBO_PLONK_LEN: usize = (GATE_WIDTH + 1) * 2 * 2 + 2 * 3 + (GATE_WIDTH + 1) * 2;
92 if value.len() == TURBO_PLONK_LEN {
93 let mut ptr = 0;
95 let wires_poly_comms: Vec<Commitment<E>> = value[ptr..ptr + (GATE_WIDTH + 1) * 2]
96 .chunks_exact(2)
97 .map(|chunk| {
98 if chunk.len() == 2 {
99 Commitment(Affine::new(chunk[0], chunk[1]))
100 } else {
101 unreachable!("Internal error");
102 }
103 })
104 .collect();
105 ptr += (GATE_WIDTH + 1) * 2;
106
107 let split_quot_poly_comms = value[ptr..ptr + (GATE_WIDTH + 1) * 2]
108 .chunks_exact(2)
109 .map(|chunk| {
110 if chunk.len() == 2 {
111 Commitment(Affine::new(chunk[0], chunk[1]))
112 } else {
113 unreachable!("Internal error");
114 }
115 })
116 .collect();
117 ptr += (GATE_WIDTH + 1) * 2;
118
119 let prod_perm_poly_comm = Commitment(Affine::new(value[ptr], value[ptr + 1]));
120 ptr += 2;
121
122 let opening_proof = Commitment(Affine::new(value[ptr], value[ptr + 1]));
123 ptr += 2;
124
125 let shifted_opening_proof = Commitment(Affine::new(value[ptr], value[ptr + 1]));
126 ptr += 2;
127
128 let poly_evals_scalars: Vec<E::ScalarField> = value[ptr..]
129 .iter()
130 .map(|f| fq_to_fr::<E::BaseField, P>(f))
131 .collect();
132 let poly_evals = poly_evals_scalars.try_into()?;
133
134 Ok(Self {
135 wires_poly_comms,
136 prod_perm_poly_comm,
137 split_quot_poly_comms,
138 opening_proof,
139 shifted_opening_proof,
140 poly_evals,
141 plookup_proof: None,
142 })
143 } else {
144 Err(SnarkError::ParameterError(
145 "Wrong number of scalars for proof, only support TurboPlonk for now".to_string(),
146 ))
147 }
148 }
149}
150
151fn group1_to_fields<E, P>(p: Affine<P>) -> Vec<E::BaseField>
153where
154 E: Pairing<G1Affine = Affine<P>>,
155 P: SWCurveConfig<BaseField = E::BaseField>,
156{
157 vec![p.x, p.y]
159}
160
161fn group2_to_fields<E, F, P>(p: Affine<P>) -> Vec<E::BaseField>
162where
163 E: Pairing<G2Affine = Affine<P>>,
164 F: Fp2Config<Fp = E::BaseField>,
165 P: SWCurveConfig<BaseField = Fp2<F>>,
166{
167 vec![p.x.c0, p.x.c1, p.y.c0, p.y.c1]
169}
170
171impl<E, P> From<Proof<E>> for Vec<E::BaseField>
172where
173 E: Pairing<G1Affine = Affine<P>>,
174 P: SWCurveConfig<BaseField = E::BaseField, ScalarField = E::ScalarField>,
175{
176 fn from(proof: Proof<E>) -> Self {
177 if proof.plookup_proof.is_some() {
178 panic!("Only support TurboPlonk for now.");
179 }
180 let poly_evals_scalars: Vec<E::ScalarField> = proof.poly_evals.into();
181
182 [
184 proof
185 .wires_poly_comms
186 .iter()
187 .map(|cm| group1_to_fields::<E, _>(cm.0))
188 .collect::<Vec<_>>()
189 .concat(),
190 proof
191 .split_quot_poly_comms
192 .iter()
193 .map(|cm| group1_to_fields::<E, _>(cm.0))
194 .collect::<Vec<_>>()
195 .concat(),
196 group1_to_fields::<E, _>(proof.prod_perm_poly_comm.0),
197 group1_to_fields::<E, _>(proof.opening_proof.0),
198 group1_to_fields::<E, _>(proof.shifted_opening_proof.0),
199 poly_evals_scalars
200 .iter()
201 .map(|s| fr_to_fq::<E::BaseField, P>(s))
202 .collect::<Vec<_>>(),
203 ]
204 .concat()
205 }
206}
207
208#[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
210#[derive_where(Hash; E: Pairing)]
211pub struct PlookupProof<E: Pairing> {
212 pub(crate) h_poly_comms: Vec<Commitment<E>>,
215
216 pub(crate) prod_lookup_poly_comm: Commitment<E>,
218
219 pub(crate) poly_evals: PlookupEvaluations<E::ScalarField>,
221}
222
223#[tagged(tag::BATCHPROOF)]
225#[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
226#[derive_where(Hash; E: Pairing)]
227pub struct BatchProof<E: Pairing> {
228 pub(crate) wires_poly_comms_vec: Vec<Vec<Commitment<E>>>,
230
231 pub(crate) prod_perm_poly_comms_vec: Vec<Commitment<E>>,
233
234 pub(crate) poly_evals_vec: Vec<ProofEvaluations<E::ScalarField>>,
236
237 pub(crate) plookup_proofs_vec: Vec<Option<PlookupProof<E>>>,
239
240 pub(crate) split_quot_poly_comms: Vec<Commitment<E>>,
242
243 pub(crate) opening_proof: Commitment<E>,
245
246 pub(crate) shifted_opening_proof: Commitment<E>,
249}
250
251impl<E: Pairing> BatchProof<E> {
252 pub fn len(&self) -> usize {
254 self.prod_perm_poly_comms_vec.len()
255 }
256 pub fn is_empty(&self) -> bool {
258 self.prod_perm_poly_comms_vec.is_empty()
259 }
260 pub fn dummy(n: usize) -> Self {
262 let num_wire_types = GATE_WIDTH + 1;
263 Self {
264 wires_poly_comms_vec: vec![vec![Commitment::default(); num_wire_types]; n],
265 prod_perm_poly_comms_vec: vec![Commitment::default(); n],
266 poly_evals_vec: vec![ProofEvaluations::default(); n],
267 plookup_proofs_vec: vec![None; n],
268 split_quot_poly_comms: vec![Commitment::default(); num_wire_types],
269 opening_proof: Commitment::default(),
270 shifted_opening_proof: Commitment::default(),
271 }
272 }
273}
274
275impl<E: Pairing> From<Proof<E>> for BatchProof<E> {
276 fn from(proof: Proof<E>) -> Self {
277 Self {
278 wires_poly_comms_vec: vec![proof.wires_poly_comms],
279 prod_perm_poly_comms_vec: vec![proof.prod_perm_poly_comm],
280 poly_evals_vec: vec![proof.poly_evals],
281 plookup_proofs_vec: vec![proof.plookup_proof],
282 split_quot_poly_comms: proof.split_quot_poly_comms,
283 opening_proof: proof.opening_proof,
284 shifted_opening_proof: proof.shifted_opening_proof,
285 }
286 }
287}
288
289impl<T: PrimeField> ProofEvaluations<T> {
290 pub(crate) fn create_variables<F>(
294 &self,
295 circuit: &mut PlonkCircuit<F>,
296 m: usize,
297 two_power_m: Option<F>,
298 ) -> Result<ProofEvaluationsVar<F>, PlonkError>
299 where
300 F: RescueParameter + SWToTEConParam,
301 {
302 if T::MODULUS_BIT_SIZE >= F::MODULUS_BIT_SIZE {
303 return Err(PlonkError::InvalidParameters(format!(
304 "circuit field size {} is not greater than Plookup Evaluation field size {}",
305 F::MODULUS_BIT_SIZE,
306 T::MODULUS_BIT_SIZE
307 )));
308 }
309 let wires_evals = self
310 .wires_evals
311 .iter()
312 .map(|x| {
313 FpElemVar::new_from_field_element(circuit, &field_switching(x), m, two_power_m)
314 })
315 .collect::<Result<Vec<_>, _>>()?;
316 let wire_sigma_evals = self
317 .wire_sigma_evals
318 .iter()
319 .map(|x| {
320 FpElemVar::new_from_field_element(circuit, &field_switching(x), m, two_power_m)
321 })
322 .collect::<Result<Vec<_>, _>>()?;
323 Ok(ProofEvaluationsVar {
324 wires_evals,
325 wire_sigma_evals,
326 perm_next_eval: FpElemVar::new_from_field_element(
327 circuit,
328 &field_switching(&self.perm_next_eval),
329 m,
330 two_power_m,
331 )?,
332 })
333 }
334}
335
336impl<E: Pairing> BatchProof<E> {
337 pub fn create_variables<F, P>(
339 &self,
340 circuit: &mut PlonkCircuit<F>,
341 m: usize,
342 two_power_m: Option<F>,
343 ) -> Result<BatchProofVar<F>, PlonkError>
344 where
345 E: Pairing<BaseField = F, G1Affine = Affine<P>>,
346 F: RescueParameter + SWToTEConParam,
347 P: SWCurveConfig<BaseField = F>,
348 {
349 let mut wires_poly_comms_vec = Vec::new();
350 for e in self.wires_poly_comms_vec.iter() {
351 let mut tmp = Vec::new();
352 for f in e.iter() {
353 let p: TEPoint<F> = f.0.into();
354 tmp.push(circuit.create_point_variable(p)?);
355 }
356 wires_poly_comms_vec.push(tmp);
357 }
358 let mut prod_perm_poly_comms_vec = Vec::new();
359 for e in self.prod_perm_poly_comms_vec.iter() {
360 let p: TEPoint<F> = e.0.into();
361 prod_perm_poly_comms_vec.push(circuit.create_point_variable(p)?);
362 }
363
364 let poly_evals_vec = self
365 .poly_evals_vec
366 .iter()
367 .map(|x| x.create_variables(circuit, m, two_power_m))
368 .collect::<Result<Vec<_>, _>>()?;
369
370 let mut split_quot_poly_comms = Vec::new();
371 for e in self.split_quot_poly_comms.iter() {
372 let p: TEPoint<F> = e.0.into();
373 split_quot_poly_comms.push(circuit.create_point_variable(p)?);
374 }
375
376 let p: TEPoint<F> = self.opening_proof.0.into();
377 let opening_proof = circuit.create_point_variable(p)?;
378
379 let p: TEPoint<F> = self.shifted_opening_proof.0.into();
380 let shifted_opening_proof = circuit.create_point_variable(p)?;
381
382 Ok(BatchProofVar {
383 wires_poly_comms_vec,
384 prod_perm_poly_comms_vec,
385 poly_evals_vec,
386 split_quot_poly_comms,
387 opening_proof,
388 shifted_opening_proof,
389 })
390 }
391}
392
393#[derive(Debug, Clone, PartialEq, Eq, Hash, CanonicalSerialize, CanonicalDeserialize)]
395pub struct ProofEvaluations<F: Field> {
396 pub wires_evals: Vec<F>,
398
399 pub wire_sigma_evals: Vec<F>,
402
403 pub perm_next_eval: F,
405}
406
407impl<F: Field> TryFrom<Vec<F>> for ProofEvaluations<F> {
408 type Error = SnarkError;
409
410 fn try_from(value: Vec<F>) -> Result<Self, Self::Error> {
411 const TURBO_PLONK_EVAL_LEN: usize = (GATE_WIDTH + 1) * 2;
415 const ULTRA_PLONK_EVAL_LEN: usize = (GATE_WIDTH + 2) * 2;
416
417 if value.len() == TURBO_PLONK_EVAL_LEN || value.len() == ULTRA_PLONK_EVAL_LEN {
418 let l = value.len();
419 let wires_evals = value[..l / 2].to_vec();
420 let wire_sigma_evals = value[l / 2..l - 1].to_vec();
421 let perm_next_eval = value[l - 1];
422 Ok(Self {
423 wires_evals,
424 wire_sigma_evals,
425 perm_next_eval,
426 })
427 } else {
428 Err(SnarkError::ParameterError(
429 "Wrong number of scalars for proof evals.".to_string(),
430 ))
431 }
432 }
433}
434
435impl<F: Field> From<ProofEvaluations<F>> for Vec<F> {
436 fn from(evals: ProofEvaluations<F>) -> Self {
437 [
438 evals.wires_evals,
439 evals.wire_sigma_evals,
440 vec![evals.perm_next_eval],
441 ]
442 .concat()
443 }
444}
445
446impl<F> Default for ProofEvaluations<F>
447where
448 F: Field,
449{
450 fn default() -> Self {
451 let num_wire_types = GATE_WIDTH + 1;
452 Self {
453 wires_evals: vec![F::zero(); num_wire_types],
454 wire_sigma_evals: vec![F::zero(); num_wire_types - 1],
455 perm_next_eval: F::zero(),
456 }
457 }
458}
459
460#[derive(Debug, Clone, PartialEq, Eq, Hash, CanonicalSerialize, CanonicalDeserialize)]
462pub struct PlookupEvaluations<F: Field> {
463 pub(crate) range_table_eval: F,
465
466 pub(crate) key_table_eval: F,
468
469 pub(crate) table_dom_sep_eval: F,
471
472 pub(crate) q_dom_sep_eval: F,
474
475 pub(crate) h_1_eval: F,
477
478 pub(crate) q_lookup_eval: F,
480
481 pub(crate) prod_next_eval: F,
483
484 pub(crate) range_table_next_eval: F,
486
487 pub(crate) key_table_next_eval: F,
489
490 pub(crate) table_dom_sep_next_eval: F,
492
493 pub(crate) h_1_next_eval: F,
495
496 pub(crate) h_2_next_eval: F,
498
499 pub(crate) q_lookup_next_eval: F,
501
502 pub(crate) w_3_next_eval: F,
504
505 pub(crate) w_4_next_eval: F,
507}
508
509impl<F: Field> PlookupEvaluations<F> {
510 pub(crate) fn evals_vec(&self) -> Vec<F> {
512 vec![
513 self.range_table_eval,
514 self.key_table_eval,
515 self.h_1_eval,
516 self.q_lookup_eval,
517 self.table_dom_sep_eval,
518 self.q_dom_sep_eval,
519 ]
520 }
521
522 pub(crate) fn next_evals_vec(&self) -> Vec<F> {
524 vec![
525 self.prod_next_eval,
526 self.range_table_next_eval,
527 self.key_table_next_eval,
528 self.h_1_next_eval,
529 self.h_2_next_eval,
530 self.q_lookup_next_eval,
531 self.w_3_next_eval,
532 self.w_4_next_eval,
533 self.table_dom_sep_next_eval,
534 ]
535 }
536}
537
538#[derive(Debug, Clone, PartialEq, Eq, CanonicalSerialize, CanonicalDeserialize)]
541pub struct ProvingKey<E: Pairing> {
542 pub(crate) sigmas: Vec<DensePolynomial<E::ScalarField>>,
544
545 pub(crate) selectors: Vec<DensePolynomial<E::ScalarField>>,
547
548 pub(crate) commit_key: CommitKey<E>,
550
551 pub vk: VerifyingKey<E>,
553
554 pub(crate) plookup_pk: Option<PlookupProvingKey<E>>,
556}
557
558#[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
561pub struct PlookupProvingKey<E: Pairing> {
562 pub(crate) range_table_poly: DensePolynomial<E::ScalarField>,
564
565 pub(crate) key_table_poly: DensePolynomial<E::ScalarField>,
567
568 pub(crate) table_dom_sep_poly: DensePolynomial<E::ScalarField>,
570
571 pub(crate) q_dom_sep_poly: DensePolynomial<E::ScalarField>,
573}
574
575impl<E: Pairing> ProvingKey<E> {
576 pub(crate) fn domain_size(&self) -> usize {
578 self.vk.domain_size
579 }
580 #[allow(dead_code)]
582 pub(crate) fn num_inputs(&self) -> usize {
583 self.vk.num_inputs
584 }
585 pub(crate) fn k(&self) -> &[E::ScalarField] {
587 &self.vk.k
588 }
589
590 pub(crate) fn q_lookup_poly(&self) -> Result<&DensePolynomial<E::ScalarField>, PlonkError> {
592 if self.plookup_pk.is_none() {
593 return Err(SnarkLookupUnsupported.into());
594 }
595 Ok(self.selectors.last().unwrap())
596 }
597
598 #[allow(dead_code)]
604 pub(crate) fn merge(&self, other_pk: &Self) -> Result<Self, PlonkError> {
605 if self.domain_size() != other_pk.domain_size() {
606 return Err(ParameterError(format!(
607 "mismatched domain size ({} vs {}) when merging proving keys",
608 self.domain_size(),
609 other_pk.domain_size()
610 ))
611 .into());
612 }
613 if self.num_inputs() != other_pk.num_inputs() {
614 return Err(ParameterError(
615 "mismatched number of public inputs when merging proving keys".to_string(),
616 )
617 .into());
618 }
619 if self.plookup_pk.is_some() || other_pk.plookup_pk.is_some() {
620 return Err(ParameterError("cannot merge UltraPlonk proving keys".to_string()).into());
621 }
622 let sigmas: Vec<DensePolynomial<E::ScalarField>> = self
623 .sigmas
624 .iter()
625 .zip(other_pk.sigmas.iter())
626 .map(|(poly1, poly2)| poly1 + poly2)
627 .collect();
628 let selectors: Vec<DensePolynomial<E::ScalarField>> = self
629 .selectors
630 .iter()
631 .zip(other_pk.selectors.iter())
632 .map(|(poly1, poly2)| poly1 + poly2)
633 .collect();
634
635 Ok(Self {
636 sigmas,
637 selectors,
638 commit_key: self.commit_key.clone(),
639 vk: self.vk.merge(&other_pk.vk)?,
640 plookup_pk: None,
641 })
642 }
643}
644
645#[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
648pub struct VerifyingKey<E: Pairing> {
649 pub domain_size: usize,
651
652 pub num_inputs: usize,
654
655 pub sigma_comms: Vec<Commitment<E>>,
657
658 pub selector_comms: Vec<Commitment<E>>,
660
661 pub k: Vec<E::ScalarField>,
664
665 pub open_key: OpenKey<E>,
667
668 pub is_merged: bool,
670
671 pub plookup_vk: Option<PlookupVerifyingKey<E>>,
673}
674
675impl<E, F, P1, P2> From<VerifyingKey<E>> for Vec<E::BaseField>
676where
677 E: Pairing<G1Affine = Affine<P1>, G2Affine = Affine<P2>, TargetField = Fp2<F>>,
678 F: Fp2Config<Fp = E::BaseField>,
679 P1: SWCurveConfig<BaseField = E::BaseField, ScalarField = E::ScalarField>,
680 P2: SWCurveConfig<BaseField = E::TargetField, ScalarField = E::ScalarField>,
681{
682 fn from(vk: VerifyingKey<E>) -> Self {
683 if vk.plookup_vk.is_some() {
684 panic!("Only support TurboPlonk VerifyingKey for now.");
685 }
686
687 [
688 vec![E::BaseField::from(vk.domain_size as u64)],
689 vec![E::BaseField::from(vk.num_inputs as u64)],
690 vk.sigma_comms
691 .iter()
692 .map(|cm| group1_to_fields::<E, _>(cm.0))
693 .collect::<Vec<_>>()
694 .concat(),
695 vk.selector_comms
696 .iter()
697 .map(|cm| group1_to_fields::<E, _>(cm.0))
698 .collect::<Vec<_>>()
699 .concat(),
700 vk.k.iter()
701 .map(|fr| fr_to_fq::<E::BaseField, P1>(fr))
702 .collect(),
703 group1_to_fields::<E, P1>(vk.open_key.g),
705 group2_to_fields::<E, F, P2>(vk.open_key.h),
706 group2_to_fields::<E, F, P2>(vk.open_key.beta_h),
707 ]
708 .concat()
709 }
710}
711
712impl<E, F, P> VerifyingKey<E>
713where
714 E: Pairing<BaseField = F, G1Affine = Affine<P>>,
715 F: SWToTEConParam,
716 P: SWCurveConfig<BaseField = F>,
717{
718 pub fn convert_te_coordinates_to_scalars(&self) -> Vec<F> {
721 let mut res = vec![];
722 for sigma_comm in self.sigma_comms.iter() {
723 let point: TEPoint<F> = sigma_comm.0.into();
724 res.push(point.get_x());
725 res.push(point.get_y());
726 }
727 for selector_comm in self.selector_comms.iter() {
728 let point: TEPoint<F> = selector_comm.0.into();
729 res.push(point.get_x());
730 res.push(point.get_y());
731 }
732 res
733 }
734}
735
736#[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
739pub struct PlookupVerifyingKey<E: Pairing> {
740 pub(crate) range_table_comm: Commitment<E>,
742
743 pub(crate) key_table_comm: Commitment<E>,
745
746 pub(crate) table_dom_sep_comm: Commitment<E>,
749
750 pub(crate) q_dom_sep_comm: Commitment<E>,
753}
754
755impl<E: Pairing> VerifyingKey<E> {
756 pub fn dummy(num_inputs: usize, domain_size: usize) -> Self {
759 let num_wire_types = GATE_WIDTH + 1;
760 Self {
761 domain_size,
762 num_inputs,
763 sigma_comms: vec![Commitment::default(); num_wire_types],
764 selector_comms: vec![Commitment::default(); N_TURBO_PLONK_SELECTORS],
765 k: compute_coset_representatives(num_wire_types, Some(domain_size)),
766 open_key: OpenKey::default(),
767 is_merged: false,
768 plookup_vk: None,
769 }
770 }
771 pub(crate) fn merge(&self, other_vk: &Self) -> Result<Self, PlonkError> {
777 if self.is_merged || other_vk.is_merged {
778 return Err(ParameterError("cannot merge a merged key again".to_string()).into());
779 }
780 if self.domain_size != other_vk.domain_size {
781 return Err(ParameterError(
782 "mismatched domain size when merging verifying keys".to_string(),
783 )
784 .into());
785 }
786 if self.num_inputs != other_vk.num_inputs {
787 return Err(ParameterError(
788 "mismatched number of public inputs when merging verifying keys".to_string(),
789 )
790 .into());
791 }
792 if self.plookup_vk.is_some() || other_vk.plookup_vk.is_some() {
793 return Err(
794 ParameterError("cannot merge UltraPlonk verifying keys".to_string()).into(),
795 );
796 }
797 let sigma_comms: Vec<Commitment<E>> = self
798 .sigma_comms
799 .iter()
800 .zip(other_vk.sigma_comms.iter())
801 .map(|(com1, com2)| Commitment((com1.0 + com2.0).into_affine()))
802 .collect();
803 let selector_comms: Vec<Commitment<E>> = self
804 .selector_comms
805 .iter()
806 .zip(other_vk.selector_comms.iter())
807 .map(|(com1, com2)| Commitment((com1.0 + com2.0).into_affine()))
808 .collect();
809
810 Ok(Self {
811 domain_size: self.domain_size,
812 num_inputs: self.num_inputs + other_vk.num_inputs,
813 sigma_comms,
814 selector_comms,
815 k: self.k.clone(),
816 open_key: self.open_key.clone(),
817 plookup_vk: None,
818 is_merged: true,
819 })
820 }
821
822 pub(crate) fn q_lookup_comm(&self) -> Result<&Commitment<E>, PlonkError> {
824 if self.plookup_vk.is_none() {
825 return Err(SnarkLookupUnsupported.into());
826 }
827 Ok(self.selector_comms.last().unwrap())
828 }
829}
830
831#[derive(Debug, Default)]
833pub(crate) struct Challenges<F: Field> {
834 pub(crate) tau: Option<F>,
835 pub(crate) alpha: F,
836 pub(crate) beta: F,
837 pub(crate) gamma: F,
838 pub(crate) zeta: F,
839 pub(crate) v: F,
840 pub(crate) u: F,
841}
842
843#[derive(Debug, Default, Clone)]
845pub(crate) struct Oracles<F: FftField> {
846 pub(crate) wire_polys: Vec<DensePolynomial<F>>,
847 pub(crate) pub_inp_poly: DensePolynomial<F>,
848 pub(crate) prod_perm_poly: DensePolynomial<F>,
849 pub(crate) plookup_oracles: PlookupOracles<F>,
850}
851
852#[derive(Debug, Default, Clone)]
854pub(crate) struct PlookupOracles<F: FftField> {
855 pub(crate) h_polys: Vec<DensePolynomial<F>>,
856 pub(crate) prod_lookup_poly: DensePolynomial<F>,
857}
858
859#[derive(Debug)]
861pub(crate) struct ScalarsAndBases<E: Pairing> {
862 pub(crate) base_scalar_map: HashMap<E::G1Affine, E::ScalarField>,
863}
864
865impl<E: Pairing> ScalarsAndBases<E> {
866 pub(crate) fn new() -> Self {
867 Self {
868 base_scalar_map: HashMap::new(),
869 }
870 }
871 pub(crate) fn push(&mut self, scalar: E::ScalarField, base: E::G1Affine) {
873 let entry_scalar = self
874 .base_scalar_map
875 .entry(base)
876 .or_insert_with(E::ScalarField::zero);
877 *entry_scalar += scalar;
878 }
879
880 pub(crate) fn merge(&mut self, c: E::ScalarField, scalars_and_bases: &Self) {
883 for (base, scalar) in &scalars_and_bases.base_scalar_map {
884 self.push(c * scalar, *base);
885 }
886 }
887 pub(crate) fn multi_scalar_mul(&self) -> E::G1 {
889 let mut bases = vec![];
890 let mut scalars = vec![];
891 for (base, scalar) in &self.base_scalar_map {
892 bases.push(*base);
893 scalars.push(scalar.into_bigint());
894 }
895 VariableBaseMSM::msm_bigint(&bases, &scalars)
896 }
897}
898
899#[inline]
901pub(crate) fn eval_merged_table<E: Pairing>(
902 tau: E::ScalarField,
903 range_eval: E::ScalarField,
904 key_eval: E::ScalarField,
905 q_lookup_eval: E::ScalarField,
906 w3_eval: E::ScalarField,
907 w4_eval: E::ScalarField,
908 table_dom_sep_eval: E::ScalarField,
909) -> E::ScalarField {
910 range_eval
911 + q_lookup_eval
912 * tau
913 * (table_dom_sep_eval + tau * (key_eval + tau * (w3_eval + tau * w4_eval)))
914}
915
916#[inline]
918pub(crate) fn eval_merged_lookup_witness<E: Pairing>(
919 tau: E::ScalarField,
920 w_range_eval: E::ScalarField,
921 w_0_eval: E::ScalarField,
922 w_1_eval: E::ScalarField,
923 w_2_eval: E::ScalarField,
924 q_lookup_eval: E::ScalarField,
925 q_dom_sep_eval: E::ScalarField,
926) -> E::ScalarField {
927 w_range_eval
928 + q_lookup_eval
929 * tau
930 * (q_dom_sep_eval + tau * (w_0_eval + tau * (w_1_eval + tau * w_2_eval)))
931}
932
933#[cfg(test)]
934mod test {
935 use super::*;
936 use ark_bn254::{g1::Config, Bn254, Fq};
937 use ark_ec::AffineRepr;
938
939 #[test]
940 fn test_group_to_field() {
941 let g1 = <Bn254 as Pairing>::G1Affine::generator();
942 let f1: Vec<Fq> = group1_to_fields::<Bn254, Config>(g1);
943 assert_eq!(f1.len(), 2);
944 let g2 = <Bn254 as Pairing>::G2Affine::generator();
945 let f2: Vec<Fq> = group2_to_fields::<Bn254, _, _>(g2);
946 assert_eq!(f2.len(), 4);
947 }
948}