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