diff --git a/src/circuit.rs b/src/circuit.rs index 7d9ba85..7876e54 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -1,8 +1,9 @@ use std::{rc::{Rc, Weak}, marker::PhantomData, iter::repeat_with, cell::RefCell}; use elsa::map::FrozenMap; use ff::PrimeField; +use itertools::Itertools; -use crate::{witness::CSWtns, gate::{Gatebb, Gate}, constraint_system::{Variable, ConstraintSystem, CommitKind, Visibility, CS, Constraint}, utils::poly_utils::check_poly, circuit::circuit_operations::{AttachedAdvice, AttachedPolynomialAdvice, AttachedAdvicePub}, external_interface::{RunIndex, RunAllocator} }; +use crate::{witness::{CSWtns, ProtostarWtns, ProtostarLhsWtns}, gate::{Gatebb, Gate}, constraint_system::{Variable, ConstraintSystem, CommitKind, Visibility, CS, Constraint}, utils::poly_utils::check_poly, circuit::circuit_operations::{AttachedAdvice, AttachedPolynomialAdvice, AttachedAdvicePub}, external_interface::{RunIndex, RunAllocator} }; use self::circuit_operations::CircuitOperation; @@ -367,6 +368,35 @@ where } } + pub fn end(&self, mut beta: F) -> ProtostarWtns<'constructed, 'circuit, F, G> { + let m = self.constructed.circuit.cs.constr_spec().num_nonlinear_constraints; + let mut p = 1; + let mut protostar_challenges = vec![]; + while p <= m { + protostar_challenges.push(beta); + beta = beta * beta; + p = p * 2; + } + + let mut pubs = vec![]; + let mut round_wtns = vec![]; + + for round in &self.cs.wtns { + round_wtns.push(round.privs.iter().map(|x| x.unwrap()).collect_vec()); + pubs.push(round.pubs.iter().map(|x| x.unwrap()).collect_vec()); + } + + ProtostarWtns { + lhs: ProtostarLhsWtns { + round_wtns, + pubs, + protostar_challenges, + circuit: self.constructed, + }, + error: F::ZERO, + } + } + pub fn set_ext(&mut self, ext: ExternalValue, value: F) -> () { self.cs.setext(ext, value); } diff --git a/src/folding/shape.rs b/src/folding/shape.rs index dd26dfc..b04e9bd 100644 --- a/src/folding/shape.rs +++ b/src/folding/shape.rs @@ -4,7 +4,7 @@ use ff::PrimeField; use halo2::halo2curves::CurveAffine; use itertools::Itertools; -use crate::{utils::arith_helper::{log2_ceil, ev}, constraint_system::{WitnessSpec, ConstraintSystem, CS, ConstrSpec}, gate::Gate}; +use crate::{utils::arith_helper::{log2_ceil, ev}, constraint_system::{WitnessSpec, ConstraintSystem, CS, ConstrSpec}, gate::Gate, witness::Module}; /// Encode value as field elements. pub trait FEncoding { @@ -44,20 +44,22 @@ impl> ProtostarLhs { assert_eq!(self.protostar_challenges.len(), log2_ceil(shape.cspec.num_nonlinear_constraints)); } +} - pub fn scale(&mut self, scale: F) { +impl> Module for ProtostarLhs { + fn scale(&mut self, scale: F) { self.round_commitments.iter_mut().map(|x| *x = (*x * scale).into()).count(); self.pubs.iter_mut().map(|rpubs| rpubs.iter_mut().map(|x| *x *= scale).count()).count(); self.protostar_challenges.iter_mut().map(|x| *x *= scale).count(); } - pub fn neg(&mut self) { + fn neg(&mut self) { self.round_commitments.iter_mut().map(|x| *x = -*x).count(); self.pubs.iter_mut().map(|rpubs| rpubs.iter_mut().map(|x| *x = -*x).count()).count(); self.protostar_challenges.iter_mut().map(|x| *x = -*x).count(); } - pub fn add_assign(&mut self, other: Self) { + fn add_assign(&mut self, other: Self) { self.round_commitments.iter_mut().zip_eq(other.round_commitments.iter()) .map(|(a, b)| *a = (*a + *b).into()).count(); self.pubs.iter_mut().zip_eq(other.pubs.iter()) diff --git a/src/witness.rs b/src/witness.rs index dd81e7f..63a8fff 100644 --- a/src/witness.rs +++ b/src/witness.rs @@ -2,9 +2,10 @@ use std::iter::repeat; use std::marker::PhantomData; use ff::PrimeField; -use halo2::halo2curves::CurveAffine; +use halo2::{halo2curves::CurveAffine, arithmetic::best_multiexp}; +use itertools::Itertools; -use crate::{gate::Gate, constraint_system::{ConstraintSystem, Variable, CS, Visibility, WitnessSpec}, commitment::{CommitmentKey, CkWtns, CtRound, ErrGroup, CkRelaxed}, circuit::ExternalValue}; +use crate::{gate::Gate, constraint_system::{ConstraintSystem, Variable, CS, Visibility, WitnessSpec}, commitment::{CommitmentKey, CkWtns, CtRound, ErrGroup, CkRelaxed}, circuit::{ExternalValue, ConstructedCircuit, PolyOp}, utils::field_precomp::FieldUtils, folding::shape::{ProtostarLhs, ProtostarInstance}}; #[derive(Clone)] pub struct RoundWtns { @@ -138,3 +139,95 @@ impl<'c, F: PrimeField, T: Gate<'c, F>, G:CurveAffine> CSSystemComm (ck.0.commit(&self.cs.wtns), ck.1.commit(&self.err)) } } + +pub trait Module { + fn add_assign(&mut self, other: Self) -> (); + fn neg(&mut self) -> (); + fn scale(&mut self, scale: F) -> (); +} + +pub struct ProtostarLhsWtns<'constructed, 'circuit, F: PrimeField, G: Gate<'circuit, F> + From>> { + pub round_wtns: Vec>, + pub pubs: Vec>, + pub protostar_challenges: Vec, + pub circuit: &'constructed ConstructedCircuit<'circuit, F, G>, +} + +impl<'constructed, 'circuit, F: PrimeField, G: Gate<'circuit, F> + From>> ProtostarLhsWtns<'constructed, 'circuit, F, G> { + pub fn commit> (&self, commitment_key: Vec>) -> ProtostarLhs { + ProtostarLhs { + round_commitments: self.round_wtns.iter().zip_eq(commitment_key).map(|(wtns, ck)| best_multiexp(&wtns, &ck).into()).collect_vec(), + pubs: self.pubs.clone(), + protostar_challenges: self.protostar_challenges.clone(), + } + } +} + +impl<'constructed, 'circuit, F: PrimeField, G: Gate<'circuit, F> + From>> Module for ProtostarLhsWtns<'constructed, 'circuit, F, G> { + fn add_assign(&mut self, other: Self) -> () { + self.round_wtns.iter_mut().zip_eq(other.round_wtns.iter()).map(|(s, o)| { + s.iter_mut().zip_eq(o.iter()).map(|(s, o)| *s = *s + o) + }).last(); + self.pubs.iter_mut().zip_eq(other.pubs.iter()).map(|(s, o)| { + s.iter_mut().zip_eq(o.iter()).map(|(s, o)| *s = *s + o) + }).last(); + self.protostar_challenges.iter_mut().zip_eq(other.protostar_challenges.iter()).map(|(s, o)| { + *s = *s + o + }).last(); + } + + fn neg(&mut self) -> () { + self.round_wtns.iter_mut().map(|s| { + s.iter_mut().map(|s| *s = -*s) + }).last(); + self.pubs.iter_mut().map(|s| { + s.iter_mut().map(|s| *s = -*s) + }).last(); + self.protostar_challenges.iter_mut().map(|s| { + *s = -*s + }).last(); + } + + fn scale(&mut self, scale: F) -> () { + self.round_wtns.iter_mut().map(|s| { + s.iter_mut().map(|s| *s = *s * scale) + }).last(); + self.pubs.iter_mut().map(|s| { + s.iter_mut().map(|s| *s = *s * scale) + }).last(); + self.protostar_challenges.iter_mut().map(|s| { + *s = *s * scale + }).last(); + } +} + +pub struct ProtostarWtns<'constructed, 'circuit, F: PrimeField, G: Gate<'circuit, F> + From>> { + pub lhs: ProtostarLhsWtns<'constructed, 'circuit, F, G>, + pub error: F +} + +impl<'constructed, 'circuit, F: PrimeField, G: Gate<'circuit, F> + From>> Module for ProtostarWtns<'constructed, 'circuit, F, G> { + fn add_assign(&mut self, other: Self) -> () { + self.error += other.error; + self.lhs.add_assign(other.lhs); + } + + fn neg(&mut self) -> () { + self.error = -self.error; + self.lhs.neg(); + } + + fn scale(&mut self, scale: F) -> () { + self.error *= scale; + self.lhs.scale(scale); + } +} + +impl<'constructed, 'circuit, F: PrimeField, G: Gate<'circuit, F> + From>> ProtostarWtns<'constructed, 'circuit, F, G> { + pub fn commit> (&self, commitment_key: Vec>) -> ProtostarInstance { + ProtostarInstance { + lhs: self.lhs.commit(commitment_key), + error: self.error, + } + } +} \ No newline at end of file