diff --git a/circuits/src/hash/poseidon/poseidon_chip.rs b/circuits/src/hash/poseidon/poseidon_chip.rs index 94fcafa1..2c46a3bf 100644 --- a/circuits/src/hash/poseidon/poseidon_chip.rs +++ b/circuits/src/hash/poseidon/poseidon_chip.rs @@ -179,7 +179,7 @@ impl ComposableChip for PoseidonChip { let constant_cols = shared_res.1; let q_full_round = meta.selector(); - let q_partial_round = meta.complex_selector(); + let q_partial_round = meta.selector(); register_cols[..WIDTH].iter().for_each(|col| meta.enable_equality(*col)); @@ -253,7 +253,7 @@ impl ComposableChip for PoseidonChip { .chain(input_pow_constraints) .chain(once(output_pow_constraint)) .collect::>(); - Constraints::with_additive_selector(q_partial_round, constraints) + Constraints::with_selector(q_partial_round, constraints) }); PoseidonConfig { diff --git a/circuits/src/verifier/accumulator.rs b/circuits/src/verifier/accumulator.rs index 51166fac..bce0c298 100644 --- a/circuits/src/verifier/accumulator.rs +++ b/circuits/src/verifier/accumulator.rs @@ -121,6 +121,12 @@ impl Accumulator { self.rhs.collapse(); } + /// Evaluates the variable and fixed parts of the Accumulator collapsing + /// each side to a single point. + pub fn fully_collapse(&self, fixed_bases: &BTreeMap) -> (S::C, S::C) { + (self.lhs.eval(fixed_bases), self.rhs.eval(fixed_bases)) + } + /// Accumulates several accumulators together. The resulting acc will /// satisfy the invariant iff all the accumulators individually do. pub fn accumulate(accs: &[Self]) -> Self { @@ -293,6 +299,21 @@ impl AssignedAccumulator { self.rhs.collapse(layouter, curve_chip, scalar_chip) } + /// Evaluates the variable and fixed parts of the AssignedAccumulator + /// collapsing each side to a single point. + /// + /// This will likely be an expensive in-circuit operation. + pub fn fully_collapse( + &self, + layouter: &mut impl Layouter, + curve_chip: &S::CurveChip, + fixed_bases: &BTreeMap, + ) -> Result<(S::AssignedPoint, S::AssignedPoint), Error> { + let lhs_pt = self.lhs.eval(layouter, curve_chip, fixed_bases)?; + let rhs_pt = self.rhs.eval(layouter, curve_chip, fixed_bases)?; + Ok((lhs_pt, rhs_pt)) + } + /// Accumulates several accumulators together. The resulting acc will /// satisfy the invariant iff all the accumulators individually do. pub fn accumulate( diff --git a/circuits/src/verifier/msm.rs b/circuits/src/verifier/msm.rs index 6ef520bc..8edb5463 100644 --- a/circuits/src/verifier/msm.rs +++ b/circuits/src/verifier/msm.rs @@ -485,6 +485,34 @@ impl AssignedMsm { Ok(()) } + /// Evaluates the variable and fixed base parts of the AssignedMsm + /// collapsing it to a single point. + /// + /// The fixed bases are constrained in-circuit to be fixed. + pub fn eval( + &self, + layouter: &mut impl Layouter, + curve_chip: &S::CurveChip, + fixed_bases: &BTreeMap, + ) -> Result { + let mut bases = self.bases.clone(); + let mut scalars = self.scalars.clone(); + + for (key, scalar) in self.fixed_base_scalars.iter() { + let base = fixed_bases.get(key).expect("Base not provided: {key}"); + let fixed_base = curve_chip.assign_fixed(layouter, *base)?; + bases.push(fixed_base); + scalars.push(scalar.clone()); + } + + let scalar_tuples = scalars + .iter() + .map(|s| (s.scalar.clone(), s.bound.bits() as usize)) + .collect::>(); + + S::msm(layouter, curve_chip, &scalar_tuples, &bases) + } + /// Scales all the scalars of the AssignedMsm by the given factor r. /// /// This function mutates self. diff --git a/circuits/src/verifier/verifier_gadget.rs b/circuits/src/verifier/verifier_gadget.rs index df8ffcf7..ea1b84de 100644 --- a/circuits/src/verifier/verifier_gadget.rs +++ b/circuits/src/verifier/verifier_gadget.rs @@ -201,6 +201,31 @@ impl VerifierGadget { Ok(assigned_vk) } + + /// Assigns a verifying key to a fixed/constant `transcript_repr` value. + pub fn assign_vk_to_fixed( + &self, + layouter: &mut impl Layouter, + vk_name: &str, + domain: &EvaluationDomain, + cs: &ConstraintSystem, + transcript_repr_constant: S::F, + ) -> Result, Error> { + let transcript_repr = self.scalar_chip.assign_fixed(layouter, transcript_repr_constant)?; + // We expect a finalized cs with no selectors, i.e. whose selectors have been + // converted into fixed columns. + let selectors = vec![vec![false]; cs.num_selectors()]; + let (processed_cs, _) = cs.clone().directly_convert_selectors_to_fixed(selectors); + + let assigned_vk = AssignedVk { + vk_name: vk_name.to_string(), + domain: domain.clone(), + cs: processed_cs, + transcript_repr, + }; + + Ok(assigned_vk) + } } impl VerifierGadget {