From 75bf89407960e1950e51f4b3aa3653e8f2cb1067 Mon Sep 17 00:00:00 2001 From: DoHoonKim Date: Tue, 31 Oct 2023 17:39:31 +0900 Subject: [PATCH] Remove plonkish_backend/src/accumulation --- plonkish_backend/src/accumulation.rs | 262 ------- .../src/accumulation/protostar.rs | 310 --------- .../src/accumulation/protostar/hyperplonk.rs | 654 ------------------ .../protostar/hyperplonk/preprocessor.rs | 406 ----------- .../protostar/hyperplonk/prover.rs | 334 --------- plonkish_backend/src/accumulation/sangria.rs | 20 - .../src/accumulation/sangria/hyperplonk.rs | 59 -- plonkish_backend/src/lib.rs | 1 - 8 files changed, 2046 deletions(-) delete mode 100644 plonkish_backend/src/accumulation.rs delete mode 100644 plonkish_backend/src/accumulation/protostar.rs delete mode 100644 plonkish_backend/src/accumulation/protostar/hyperplonk.rs delete mode 100644 plonkish_backend/src/accumulation/protostar/hyperplonk/preprocessor.rs delete mode 100644 plonkish_backend/src/accumulation/protostar/hyperplonk/prover.rs delete mode 100644 plonkish_backend/src/accumulation/sangria.rs delete mode 100644 plonkish_backend/src/accumulation/sangria/hyperplonk.rs diff --git a/plonkish_backend/src/accumulation.rs b/plonkish_backend/src/accumulation.rs deleted file mode 100644 index 12ca8ca..0000000 --- a/plonkish_backend/src/accumulation.rs +++ /dev/null @@ -1,262 +0,0 @@ -use crate::{ - backend::{PlonkishCircuit, PlonkishCircuitInfo}, - pcs::{CommitmentChunk, PolynomialCommitmentScheme}, - util::{ - arithmetic::Field, - transcript::{TranscriptRead, TranscriptWrite}, - DeserializeOwned, Serialize, - }, - Error, -}; -use rand::RngCore; -use std::{borrow::BorrowMut, fmt::Debug}; - -pub mod protostar; -pub mod sangria; - -pub trait AccumulationScheme: Clone + Debug { - type Pcs: PolynomialCommitmentScheme; - type ProverParam: Debug + Serialize + DeserializeOwned; - type VerifierParam: Debug + Serialize + DeserializeOwned; - type Accumulator: Debug + AsRef; - type AccumulatorInstance: Clone + Debug + Serialize + DeserializeOwned; - - fn setup( - circuit_info: &PlonkishCircuitInfo, - rng: impl RngCore, - ) -> Result<>::Param, Error>; - - fn preprocess( - param: &>::Param, - circuit_info: &PlonkishCircuitInfo, - ) -> Result<(Self::ProverParam, Self::VerifierParam), Error>; - - fn init_accumulator(pp: &Self::ProverParam) -> Result; - - fn init_accumulator_from_nark( - pp: &Self::ProverParam, - nark: PlonkishNark, - ) -> Result; - - fn prove_nark( - pp: &Self::ProverParam, - circuit: &impl PlonkishCircuit, - transcript: &mut impl TranscriptWrite, F>, - rng: impl RngCore, - ) -> Result, Error>; - - fn prove_accumulation( - pp: &Self::ProverParam, - accumulator: impl BorrowMut, - incoming: &Self::Accumulator, - transcript: &mut impl TranscriptWrite, F>, - rng: impl RngCore, - ) -> Result<(), Error>; - - fn prove_accumulation_from_nark( - pp: &Self::ProverParam, - accumulator: impl BorrowMut, - circuit: &impl PlonkishCircuit, - transcript: &mut impl TranscriptWrite, F>, - mut rng: impl RngCore, - ) -> Result<(), Error> { - let nark = Self::prove_nark(pp, circuit, transcript, &mut rng)?; - let incoming = Self::init_accumulator_from_nark(pp, nark)?; - Self::prove_accumulation::(pp, accumulator, &incoming, transcript, &mut rng)?; - Ok(()) - } - - fn verify_accumulation_from_nark( - vp: &Self::VerifierParam, - accumulator: impl BorrowMut, - instances: &[Vec], - transcript: &mut impl TranscriptRead, F>, - rng: impl RngCore, - ) -> Result<(), Error>; - - fn prove_decider( - pp: &Self::ProverParam, - accumulator: &Self::Accumulator, - transcript: &mut impl TranscriptWrite, F>, - rng: impl RngCore, - ) -> Result<(), Error>; - - fn prove_decider_with_last_nark( - pp: &Self::ProverParam, - mut accumulator: impl BorrowMut, - circuit: &impl PlonkishCircuit, - transcript: &mut impl TranscriptWrite, F>, - mut rng: impl RngCore, - ) -> Result<(), Error> { - Self::prove_accumulation_from_nark( - pp, - accumulator.borrow_mut(), - circuit, - transcript, - &mut rng, - )?; - Self::prove_decider(pp, accumulator.borrow(), transcript, &mut rng)?; - Ok(()) - } - - fn verify_decider( - vp: &Self::VerifierParam, - accumulator: &Self::AccumulatorInstance, - transcript: &mut impl TranscriptRead, F>, - rng: impl RngCore, - ) -> Result<(), Error>; - - fn verify_decider_with_last_nark( - vp: &Self::VerifierParam, - mut accumulator: impl BorrowMut, - instances: &[Vec], - transcript: &mut impl TranscriptRead, F>, - mut rng: impl RngCore, - ) -> Result<(), Error> { - Self::verify_accumulation_from_nark( - vp, - accumulator.borrow_mut(), - instances, - transcript, - &mut rng, - )?; - Self::verify_decider(vp, accumulator.borrow(), transcript, &mut rng)?; - Ok(()) - } -} - -#[derive(Clone, Debug)] -pub struct PlonkishNark -where - F: Field, - Pcs: PolynomialCommitmentScheme, -{ - instance: PlonkishNarkInstance, - witness_polys: Vec, -} - -impl PlonkishNark -where - F: Field, - Pcs: PolynomialCommitmentScheme, -{ - fn new( - instances: Vec>, - challenges: Vec, - witness_comms: Vec, - witness_polys: Vec, - ) -> Self { - Self { - instance: PlonkishNarkInstance::new(instances, challenges, witness_comms), - witness_polys, - } - } -} - -#[derive(Clone, Debug)] -pub struct PlonkishNarkInstance { - instances: Vec>, - challenges: Vec, - witness_comms: Vec, -} - -impl PlonkishNarkInstance { - fn new(instances: Vec>, challenges: Vec, witness_comms: Vec) -> Self { - Self { - instances, - challenges, - witness_comms, - } - } -} - -#[cfg(test)] -pub(crate) mod test { - use crate::{ - accumulation::AccumulationScheme, - backend::{PlonkishCircuit, PlonkishCircuitInfo}, - pcs::PolynomialCommitmentScheme, - util::{ - arithmetic::PrimeField, - end_timer, start_timer, - test::seeded_std_rng, - transcript::{InMemoryTranscript, TranscriptRead, TranscriptWrite}, - DeserializeOwned, Serialize, - }, - }; - use std::{hash::Hash, ops::Range}; - - pub(crate) fn run_accumulation_scheme( - num_vars_range: Range, - circuit_fn: impl Fn(usize) -> (PlonkishCircuitInfo, Vec), - ) where - F: PrimeField + Hash + Serialize + DeserializeOwned, - Fs: AccumulationScheme, - T: TranscriptRead<>::CommitmentChunk, F> - + TranscriptWrite<>::CommitmentChunk, F> - + InMemoryTranscript, - C: PlonkishCircuit, - { - for num_vars in num_vars_range { - let (circuit_info, circuits) = circuit_fn(num_vars); - let last_circuit = circuits.last().unwrap(); - - let timer = start_timer(|| format!("setup-{num_vars}")); - let param = Fs::setup(&circuit_info, seeded_std_rng()).unwrap(); - end_timer(timer); - - let timer = start_timer(|| format!("preprocess-{num_vars}")); - let (pp, vp) = Fs::preprocess(¶m, &circuit_info).unwrap(); - end_timer(timer); - - let (accumulator_before_last, proof) = { - let mut accumulator = Fs::init_accumulator(&pp).unwrap(); - for circuit in circuits[..circuits.len() - 1].iter() { - let timer = start_timer(|| format!("prove_accumulation_from_nark-{num_vars}")); - Fs::prove_accumulation_from_nark( - &pp, - &mut accumulator, - circuit, - &mut T::new(()), - seeded_std_rng(), - ) - .unwrap(); - end_timer(timer); - } - - let accumulator_before_last = accumulator.as_ref().clone(); - - let timer = start_timer(|| format!("prove_decider_with_last_nark-{num_vars}")); - let proof = { - let mut transcript = T::new(()); - Fs::prove_decider_with_last_nark( - &pp, - &mut accumulator, - last_circuit, - &mut transcript, - seeded_std_rng(), - ) - .unwrap(); - transcript.into_proof() - }; - end_timer(timer); - - (accumulator_before_last, proof) - }; - - let timer = start_timer(|| format!("verify_decider_with_last_nark-{num_vars}")); - let result = { - let mut transcript = T::from_proof((), proof.as_slice()); - Fs::verify_decider_with_last_nark( - &vp, - accumulator_before_last, - last_circuit.instances(), - &mut transcript, - seeded_std_rng(), - ) - }; - assert!(matches!(result, Ok(_))); - end_timer(timer); - } - } -} diff --git a/plonkish_backend/src/accumulation/protostar.rs b/plonkish_backend/src/accumulation/protostar.rs deleted file mode 100644 index 04adf87..0000000 --- a/plonkish_backend/src/accumulation/protostar.rs +++ /dev/null @@ -1,310 +0,0 @@ -use crate::{ - accumulation::{ - protostar::ProtostarStrategy::{Compressing, NoCompressing}, - PlonkishNark, PlonkishNarkInstance, - }, - backend::PlonkishBackend, - pcs::{AdditiveCommitment, PolynomialCommitmentScheme}, - poly::Polynomial, - util::{ - arithmetic::{inner_product, powers, Field}, - chain, - expression::Expression, - izip, izip_eq, - transcript::Transcript, - Deserialize, Itertools, Serialize, - }, - Error, -}; -use std::{iter, marker::PhantomData}; - -pub mod hyperplonk; - -#[derive(Clone, Debug)] -pub struct Protostar(PhantomData); - -#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)] -pub enum ProtostarStrategy { - // As known as Sangria - NoCompressing = 0, - // Compressing verification as described in 2023/620 section 3.5 but without square-root optimization - #[default] - Compressing = 1, - // TODO: - // Compressing verification with square-root optimization applied as described in 2023/620 section 3.5 - // CompressingWithSqrtPowers = 3, -} - -impl From for ProtostarStrategy { - fn from(strategy: usize) -> Self { - [NoCompressing, Compressing][strategy] - } -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ProtostarProverParam -where - F: Field, - Pb: PlonkishBackend, -{ - pp: Pb::ProverParam, - strategy: ProtostarStrategy, - num_theta_primes: usize, - num_alpha_primes: usize, - num_folding_witness_polys: usize, - num_folding_challenges: usize, - cross_term_expressions: Vec>, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ProtostarVerifierParam -where - F: Field, - Pb: PlonkishBackend, -{ - vp: Pb::VerifierParam, - strategy: ProtostarStrategy, - num_theta_primes: usize, - num_alpha_primes: usize, - num_folding_witness_polys: usize, - num_folding_challenges: usize, - num_cross_terms: usize, -} - -#[derive(Clone, Debug)] -pub struct ProtostarAccumulator -where - F: Field, - Pcs: PolynomialCommitmentScheme, -{ - instance: ProtostarAccumulatorInstance, - witness_polys: Vec, - e_poly: Pcs::Polynomial, - _marker: PhantomData, -} - -impl AsRef> - for ProtostarAccumulator -where - F: Field, - Pcs: PolynomialCommitmentScheme, -{ - fn as_ref(&self) -> &ProtostarAccumulatorInstance { - &self.instance - } -} - -impl ProtostarAccumulator -where - F: Field, - Pcs: PolynomialCommitmentScheme, -{ - fn init( - strategy: ProtostarStrategy, - k: usize, - num_instances: &[usize], - num_witness_polys: usize, - num_challenges: usize, - ) -> Self { - let zero_poly = Pcs::Polynomial::from_evals(vec![F::ZERO; 1 << k]); - Self { - instance: ProtostarAccumulatorInstance::init( - strategy, - num_instances, - num_witness_polys, - num_challenges, - ), - witness_polys: iter::repeat_with(|| zero_poly.clone()) - .take(num_witness_polys) - .collect(), - e_poly: zero_poly, - _marker: PhantomData, - } - } - - fn from_nark(strategy: ProtostarStrategy, k: usize, nark: PlonkishNark) -> Self { - let witness_polys = nark.witness_polys; - Self { - instance: ProtostarAccumulatorInstance::from_nark(strategy, nark.instance), - witness_polys, - e_poly: Pcs::Polynomial::from_evals(vec![F::ZERO; 1 << k]), - _marker: PhantomData, - } - } - - fn fold_uncompressed( - &mut self, - rhs: &Self, - cross_term_polys: &[Pcs::Polynomial], - cross_term_comms: &[Pcs::Commitment], - r: &F, - ) where - Pcs::Commitment: AdditiveCommitment, - { - self.instance - .fold_uncompressed(&rhs.instance, cross_term_comms, r); - izip_eq!(&mut self.witness_polys, &rhs.witness_polys) - .for_each(|(lhs, rhs)| *lhs += (r, rhs)); - izip!(powers(*r).skip(1), chain![cross_term_polys, [&rhs.e_poly]]) - .for_each(|(power_of_r, poly)| self.e_poly += (&power_of_r, poly)); - } - - fn fold_compressed( - &mut self, - rhs: &Self, - zeta_cross_term_poly: &Pcs::Polynomial, - zeta_cross_term_comm: &Pcs::Commitment, - compressed_cross_term_sums: &[F], - r: &F, - ) where - Pcs::Commitment: AdditiveCommitment, - { - self.instance.fold_compressed( - &rhs.instance, - zeta_cross_term_comm, - compressed_cross_term_sums, - r, - ); - izip_eq!(&mut self.witness_polys, &rhs.witness_polys) - .for_each(|(lhs, rhs)| *lhs += (r, rhs)); - izip!(powers(*r).skip(1), [zeta_cross_term_poly, &rhs.e_poly]) - .for_each(|(power_of_r, poly)| self.e_poly += (&power_of_r, poly)); - } - - pub fn instance(&self) -> &ProtostarAccumulatorInstance { - &self.instance - } -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ProtostarAccumulatorInstance { - instances: Vec>, - witness_comms: Vec, - challenges: Vec, - u: F, - e_comm: C, - compressed_e_sum: Option, -} - -impl ProtostarAccumulatorInstance { - fn instances(&self) -> &[Vec] { - &self.instances - } -} - -impl ProtostarAccumulatorInstance -where - F: Field, - C: Default, -{ - fn init( - strategy: ProtostarStrategy, - num_instances: &[usize], - num_witness_polys: usize, - num_challenges: usize, - ) -> Self { - Self { - instances: num_instances.iter().map(|n| vec![F::ZERO; *n]).collect(), - witness_comms: iter::repeat_with(C::default) - .take(num_witness_polys) - .collect(), - challenges: vec![F::ZERO; num_challenges], - u: F::ZERO, - e_comm: C::default(), - compressed_e_sum: match strategy { - NoCompressing => None, - Compressing => Some(F::ZERO), - }, - } - } - - fn claimed_sum(&self) -> F { - self.compressed_e_sum.unwrap_or(F::ZERO) - } - - fn absorb_into( - &self, - transcript: &mut impl Transcript, - ) -> Result<(), Error> - where - C: AsRef<[CommitmentChunk]>, - { - self.instances - .iter() - .try_for_each(|instances| transcript.common_field_elements(instances))?; - self.witness_comms - .iter() - .try_for_each(|comm| transcript.common_commitments(comm.as_ref()))?; - transcript.common_field_elements(&self.challenges)?; - transcript.common_field_element(&self.u)?; - transcript.common_commitments(self.e_comm.as_ref())?; - if let Some(compressed_e_sum) = self.compressed_e_sum.as_ref() { - transcript.common_field_element(compressed_e_sum)?; - } - Ok(()) - } - - fn from_nark(strategy: ProtostarStrategy, nark: PlonkishNarkInstance) -> Self { - Self { - instances: nark.instances, - witness_comms: nark.witness_comms, - challenges: nark.challenges, - u: F::ONE, - e_comm: C::default(), - compressed_e_sum: match strategy { - NoCompressing => None, - Compressing => Some(F::ZERO), - }, - } - } - - fn fold_uncompressed(&mut self, rhs: &Self, cross_term_comms: &[C], r: &F) - where - C: AdditiveCommitment, - { - let one = F::ONE; - let powers_of_r = powers(*r).take(cross_term_comms.len() + 2).collect_vec(); - izip_eq!(&mut self.instances, &rhs.instances) - .for_each(|(lhs, rhs)| izip_eq!(lhs, rhs).for_each(|(lhs, rhs)| *lhs += &(*rhs * r))); - izip_eq!(&mut self.witness_comms, &rhs.witness_comms) - .for_each(|(lhs, rhs)| *lhs = C::sum_with_scalar([&one, r], [lhs, rhs])); - izip_eq!(&mut self.challenges, &rhs.challenges).for_each(|(lhs, rhs)| *lhs += &(*rhs * r)); - self.u += &(rhs.u * r); - self.e_comm = { - let comms = chain![[&self.e_comm], cross_term_comms, [&rhs.e_comm]]; - C::sum_with_scalar(&powers_of_r, comms) - }; - } - - fn fold_compressed( - &mut self, - rhs: &Self, - zeta_cross_term_comm: &C, - compressed_cross_term_sums: &[F], - r: &F, - ) where - C: AdditiveCommitment, - { - let one = F::ONE; - let powers_of_r = powers(*r) - .take(compressed_cross_term_sums.len().max(1) + 2) - .collect_vec(); - izip_eq!(&mut self.instances, &rhs.instances) - .for_each(|(lhs, rhs)| izip_eq!(lhs, rhs).for_each(|(lhs, rhs)| *lhs += &(*rhs * r))); - izip_eq!(&mut self.witness_comms, &rhs.witness_comms) - .for_each(|(lhs, rhs)| *lhs = C::sum_with_scalar([&one, r], [lhs, rhs])); - izip_eq!(&mut self.challenges, &rhs.challenges).for_each(|(lhs, rhs)| *lhs += &(*rhs * r)); - self.u += &(rhs.u * r); - self.e_comm = { - let comms = [&self.e_comm, zeta_cross_term_comm, &rhs.e_comm]; - C::sum_with_scalar(&powers_of_r[..3], comms) - }; - *self.compressed_e_sum.as_mut().unwrap() += &inner_product( - &powers_of_r[1..], - chain![ - compressed_cross_term_sums, - [rhs.compressed_e_sum.as_ref().unwrap()] - ], - ); - } -} diff --git a/plonkish_backend/src/accumulation/protostar/hyperplonk.rs b/plonkish_backend/src/accumulation/protostar/hyperplonk.rs deleted file mode 100644 index 541dfc1..0000000 --- a/plonkish_backend/src/accumulation/protostar/hyperplonk.rs +++ /dev/null @@ -1,654 +0,0 @@ -use crate::{ - accumulation::{ - protostar::{ - hyperplonk::{ - preprocessor::{batch_size, preprocess}, - prover::{ - evaluate_compressed_cross_term_sums, evaluate_cross_term_polys, - evaluate_zeta_cross_term_poly, lookup_h_polys, powers_of_zeta_poly, - }, - }, - Protostar, ProtostarAccumulator, ProtostarAccumulatorInstance, ProtostarProverParam, - ProtostarStrategy::{Compressing, NoCompressing}, - ProtostarVerifierParam, - }, - AccumulationScheme, PlonkishNark, PlonkishNarkInstance, - }, - backend::{ - hyperplonk::{ - prover::{ - instance_polys, lookup_compressed_polys, lookup_m_polys, permutation_z_polys, - prove_sum_check, - }, - verifier::verify_sum_check, - HyperPlonk, - }, - PlonkishCircuit, PlonkishCircuitInfo, - }, - pcs::{AdditiveCommitment, CommitmentChunk, PolynomialCommitmentScheme}, - poly::multilinear::MultilinearPolynomial, - util::{ - arithmetic::{powers, PrimeField}, - end_timer, start_timer, - transcript::{TranscriptRead, TranscriptWrite}, - DeserializeOwned, Itertools, Serialize, - }, - Error, -}; -use rand::RngCore; -use std::{borrow::BorrowMut, hash::Hash, iter}; - -mod preprocessor; -mod prover; - -impl AccumulationScheme for Protostar, STRATEGY> -where - F: PrimeField + Hash + Serialize + DeserializeOwned, - Pcs: PolynomialCommitmentScheme>, - Pcs::Commitment: AdditiveCommitment, - Pcs::CommitmentChunk: AdditiveCommitment, -{ - type Pcs = Pcs; - type ProverParam = ProtostarProverParam>; - type VerifierParam = ProtostarVerifierParam>; - type Accumulator = ProtostarAccumulator; - type AccumulatorInstance = ProtostarAccumulatorInstance; - - fn setup( - circuit_info: &PlonkishCircuitInfo, - rng: impl RngCore, - ) -> Result { - assert!(circuit_info.is_well_formed()); - - let num_vars = circuit_info.k; - let poly_size = 1 << num_vars; - let batch_size = batch_size(circuit_info, STRATEGY.into()); - Pcs::setup(poly_size, batch_size, rng) - } - - fn preprocess( - param: &Pcs::Param, - circuit_info: &PlonkishCircuitInfo, - ) -> Result<(Self::ProverParam, Self::VerifierParam), Error> { - assert!(circuit_info.is_well_formed()); - - preprocess(param, circuit_info, STRATEGY.into()) - } - - fn init_accumulator(pp: &Self::ProverParam) -> Result { - Ok(ProtostarAccumulator::init( - pp.strategy, - pp.pp.num_vars, - &pp.pp.num_instances, - pp.num_folding_witness_polys, - pp.num_folding_challenges, - )) - } - - fn init_accumulator_from_nark( - pp: &Self::ProverParam, - nark: PlonkishNark, - ) -> Result { - Ok(ProtostarAccumulator::from_nark( - pp.strategy, - pp.pp.num_vars, - nark, - )) - } - - fn prove_nark( - pp: &Self::ProverParam, - circuit: &impl PlonkishCircuit, - transcript: &mut impl TranscriptWrite, F>, - _: impl RngCore, - ) -> Result, Error> { - let ProtostarProverParam { - pp, - strategy, - num_theta_primes, - num_alpha_primes, - .. - } = pp; - - let instances = circuit.instances(); - for (num_instances, instances) in pp.num_instances.iter().zip_eq(instances) { - assert_eq!(instances.len(), *num_instances); - for instance in instances.iter() { - transcript.common_field_element(instance)?; - } - } - - // Round 0..n - - let mut witness_polys = Vec::with_capacity(pp.num_witness_polys.iter().sum()); - let mut witness_comms = Vec::with_capacity(witness_polys.len()); - let mut challenges = Vec::with_capacity(pp.num_challenges.iter().sum()); - for (round, (num_witness_polys, num_challenges)) in pp - .num_witness_polys - .iter() - .zip_eq(pp.num_challenges.iter()) - .enumerate() - { - let timer = start_timer(|| format!("witness_collector-{round}")); - let polys = circuit - .synthesize(round, &challenges)? - .into_iter() - .map(MultilinearPolynomial::new) - .collect_vec(); - assert_eq!(polys.len(), *num_witness_polys); - end_timer(timer); - - witness_comms.extend(Pcs::batch_commit_and_write(&pp.pcs, &polys, transcript)?); - witness_polys.extend(polys); - challenges.extend(transcript.squeeze_challenges(*num_challenges)); - } - - // Round n - - let theta_primes = powers(transcript.squeeze_challenge()) - .skip(1) - .take(*num_theta_primes) - .collect_vec(); - - let timer = start_timer(|| format!("lookup_compressed_polys-{}", pp.lookups.len())); - let lookup_compressed_polys = { - let instance_polys = instance_polys(pp.num_vars, instances); - let polys = iter::empty() - .chain(instance_polys.iter()) - .chain(pp.preprocess_polys.iter()) - .chain(witness_polys.iter()) - .collect_vec(); - let thetas = iter::empty() - .chain(Some(F::ONE)) - .chain(theta_primes.iter().cloned()) - .collect_vec(); - lookup_compressed_polys(&pp.lookups, &polys, &challenges, &thetas) - }; - end_timer(timer); - - let timer = start_timer(|| format!("lookup_m_polys-{}", pp.lookups.len())); - let lookup_m_polys = lookup_m_polys(&lookup_compressed_polys)?; - end_timer(timer); - - let lookup_m_comms = Pcs::batch_commit_and_write(&pp.pcs, &lookup_m_polys, transcript)?; - - // Round n+1 - - let beta_prime = transcript.squeeze_challenge(); - - let timer = start_timer(|| format!("lookup_h_polys-{}", pp.lookups.len())); - let lookup_h_polys = lookup_h_polys(&lookup_compressed_polys, &lookup_m_polys, &beta_prime); - end_timer(timer); - - let lookup_h_comms = { - let polys = lookup_h_polys.iter().flatten(); - Pcs::batch_commit_and_write(&pp.pcs, polys, transcript)? - }; - - // Round n+2 - - let (zeta, powers_of_zeta_poly, powers_of_zeta_comm) = match strategy { - NoCompressing => (None, None, None), - Compressing => { - let zeta = transcript.squeeze_challenge(); - - let timer = start_timer(|| "powers_of_zeta_poly"); - let powers_of_zeta_poly = powers_of_zeta_poly(pp.num_vars, zeta); - end_timer(timer); - - let powers_of_zeta_comm = - Pcs::commit_and_write(&pp.pcs, &powers_of_zeta_poly, transcript)?; - - ( - Some(zeta), - Some(powers_of_zeta_poly), - Some(powers_of_zeta_comm), - ) - } - }; - - // Round n+3 - - let alpha_primes = powers(transcript.squeeze_challenge()) - .skip(1) - .take(*num_alpha_primes) - .collect_vec(); - - Ok(PlonkishNark::new( - instances.to_vec(), - iter::empty() - .chain(challenges) - .chain(theta_primes) - .chain(Some(beta_prime)) - .chain(zeta) - .chain(alpha_primes) - .collect(), - iter::empty() - .chain(witness_comms) - .chain(lookup_m_comms) - .chain(lookup_h_comms) - .chain(powers_of_zeta_comm) - .collect(), - iter::empty() - .chain(witness_polys) - .chain(lookup_m_polys) - .chain(lookup_h_polys.into_iter().flatten()) - .chain(powers_of_zeta_poly) - .collect(), - )) - } - - fn prove_accumulation( - pp: &Self::ProverParam, - mut accumulator: impl BorrowMut, - incoming: &Self::Accumulator, - transcript: &mut impl TranscriptWrite, F>, - _: impl RngCore, - ) -> Result<(), Error> { - let ProtostarProverParam { - pp, - strategy, - num_alpha_primes, - cross_term_expressions, - .. - } = pp; - let accumulator = accumulator.borrow_mut(); - - accumulator.instance.absorb_into(transcript)?; - if !IS_INCOMING_ABSORBED { - incoming.instance.absorb_into(transcript)?; - } - - match strategy { - NoCompressing => { - let timer = start_timer(|| { - format!("evaluate_cross_term_polys-{}", cross_term_expressions.len()) - }); - let cross_term_polys = evaluate_cross_term_polys( - cross_term_expressions, - pp.num_vars, - &pp.preprocess_polys, - accumulator, - incoming, - ); - end_timer(timer); - - let cross_term_comms = - Pcs::batch_commit_and_write(&pp.pcs, &cross_term_polys, transcript)?; - - // Round 0 - - let r = transcript.squeeze_challenge(); - - let timer = start_timer(|| "fold_uncompressed"); - accumulator.fold_uncompressed(incoming, &cross_term_polys, &cross_term_comms, &r); - end_timer(timer); - } - Compressing => { - let timer = start_timer(|| "evaluate_zeta_cross_term_poly"); - let zeta_cross_term_poly = evaluate_zeta_cross_term_poly( - pp.num_vars, - *num_alpha_primes, - accumulator, - incoming, - ); - end_timer(timer); - - let timer = start_timer(|| { - let len = cross_term_expressions.len(); - format!("evaluate_compressed_cross_term_sums-{len}") - }); - let compressed_cross_term_sums = evaluate_compressed_cross_term_sums( - cross_term_expressions, - pp.num_vars, - &pp.preprocess_polys, - accumulator, - incoming, - ); - end_timer(timer); - - let zeta_cross_term_comm = - Pcs::commit_and_write(&pp.pcs, &zeta_cross_term_poly, transcript)?; - transcript.write_field_elements(&compressed_cross_term_sums)?; - - // Round 0 - - let r = transcript.squeeze_challenge(); - - let timer = start_timer(|| "fold_compressed"); - accumulator.fold_compressed( - incoming, - &zeta_cross_term_poly, - &zeta_cross_term_comm, - &compressed_cross_term_sums, - &r, - ); - end_timer(timer); - } - } - - Ok(()) - } - - fn verify_accumulation_from_nark( - vp: &Self::VerifierParam, - mut accumulator: impl BorrowMut, - instances: &[Vec], - transcript: &mut impl TranscriptRead, F>, - _: impl RngCore, - ) -> Result<(), Error> { - let ProtostarVerifierParam { - vp, - strategy, - num_theta_primes, - num_alpha_primes, - num_cross_terms, - .. - } = vp; - let accumulator = accumulator.borrow_mut(); - - for (num_instances, instances) in vp.num_instances.iter().zip_eq(instances) { - assert_eq!(instances.len(), *num_instances); - for instance in instances.iter() { - transcript.common_field_element(instance)?; - } - } - - // Round 0..n - - let mut witness_comms = Vec::with_capacity(vp.num_witness_polys.iter().sum()); - let mut challenges = Vec::with_capacity(vp.num_challenges.iter().sum()); - for (num_polys, num_challenges) in - vp.num_witness_polys.iter().zip_eq(vp.num_challenges.iter()) - { - witness_comms.extend(Pcs::read_commitments(&vp.pcs, *num_polys, transcript)?); - challenges.extend(transcript.squeeze_challenges(*num_challenges)); - } - - // Round n - - let theta_primes = powers(transcript.squeeze_challenge()) - .skip(1) - .take(*num_theta_primes) - .collect_vec(); - - let lookup_m_comms = Pcs::read_commitments(&vp.pcs, vp.num_lookups, transcript)?; - - // Round n+1 - - let beta_prime = transcript.squeeze_challenge(); - - let lookup_h_comms = Pcs::read_commitments(&vp.pcs, 2 * vp.num_lookups, transcript)?; - - // Round n+2 - - let (zeta, powers_of_zeta_comm) = match strategy { - NoCompressing => (None, None), - Compressing => { - let zeta = transcript.squeeze_challenge(); - - let powers_of_zeta_comm = Pcs::read_commitment(&vp.pcs, transcript)?; - - (Some(zeta), Some(powers_of_zeta_comm)) - } - }; - - // Round n+3 - - let alpha_primes = powers(transcript.squeeze_challenge()) - .skip(1) - .take(*num_alpha_primes) - .collect_vec(); - - let nark = PlonkishNarkInstance::new( - instances.to_vec(), - iter::empty() - .chain(challenges) - .chain(theta_primes) - .chain(Some(beta_prime)) - .chain(zeta) - .chain(alpha_primes) - .collect(), - iter::empty() - .chain(witness_comms) - .chain(lookup_m_comms) - .chain(lookup_h_comms) - .chain(powers_of_zeta_comm) - .collect(), - ); - let incoming = ProtostarAccumulatorInstance::from_nark(*strategy, nark); - accumulator.absorb_into(transcript)?; - - match strategy { - NoCompressing => { - let cross_term_comms = - Pcs::read_commitments(&vp.pcs, *num_cross_terms, transcript)?; - - // Round n+4 - - let r = transcript.squeeze_challenge(); - - accumulator.fold_uncompressed(&incoming, &cross_term_comms, &r); - } - Compressing => { - let zeta_cross_term_comm = Pcs::read_commitment(&vp.pcs, transcript)?; - let compressed_cross_term_sums = - transcript.read_field_elements(*num_cross_terms)?; - - // Round n+4 - - let r = transcript.squeeze_challenge(); - - accumulator.fold_compressed( - &incoming, - &zeta_cross_term_comm, - &compressed_cross_term_sums, - &r, - ); - } - }; - - Ok(()) - } - - fn prove_decider( - pp: &Self::ProverParam, - accumulator: &Self::Accumulator, - transcript: &mut impl TranscriptWrite, F>, - _: impl RngCore, - ) -> Result<(), Error> { - let ProtostarProverParam { pp, .. } = pp; - - accumulator.instance.absorb_into(transcript)?; - - // Round 0 - - let beta = transcript.squeeze_challenge(); - let gamma = transcript.squeeze_challenge(); - - let timer = start_timer(|| format!("permutation_z_polys-{}", pp.permutation_polys.len())); - let builtin_witness_poly_offset = pp.num_witness_polys.iter().sum::(); - let instance_polys = instance_polys(pp.num_vars, &accumulator.instance.instances); - let polys = iter::empty() - .chain(&instance_polys) - .chain(&pp.preprocess_polys) - .chain(&accumulator.witness_polys[..builtin_witness_poly_offset]) - .chain(pp.permutation_polys.iter().map(|(_, poly)| poly)) - .collect_vec(); - let permutation_z_polys = permutation_z_polys( - pp.num_permutation_z_polys, - &pp.permutation_polys, - &polys, - &beta, - &gamma, - ); - end_timer(timer); - - let permutation_z_comms = - Pcs::batch_commit_and_write(&pp.pcs, &permutation_z_polys, transcript)?; - - // Round 1 - - let alpha = transcript.squeeze_challenge(); - let y = transcript.squeeze_challenges(pp.num_vars); - - let polys = iter::empty() - .chain(polys) - .chain(&accumulator.witness_polys[builtin_witness_poly_offset..]) - .chain(permutation_z_polys.iter()) - .chain(Some(&accumulator.e_poly)) - .collect_vec(); - let challenges = iter::empty() - .chain(accumulator.instance.challenges.iter().copied()) - .chain([accumulator.instance.u]) - .chain([beta, gamma, alpha]) - .collect(); - let (points, evals) = { - prove_sum_check( - pp.num_instances.len(), - &pp.expression, - accumulator.instance.claimed_sum(), - &polys, - challenges, - y, - transcript, - )? - }; - - // PCS open - - let dummy_comm = Pcs::Commitment::default(); - let comms = iter::empty() - .chain(iter::repeat(&dummy_comm).take(pp.num_instances.len())) - .chain(&pp.preprocess_comms) - .chain(&accumulator.instance.witness_comms[..builtin_witness_poly_offset]) - .chain(&pp.permutation_comms) - .chain(&accumulator.instance.witness_comms[builtin_witness_poly_offset..]) - .chain(&permutation_z_comms) - .chain(Some(&accumulator.instance.e_comm)) - .collect_vec(); - let timer = start_timer(|| format!("pcs_batch_open-{}", evals.len())); - Pcs::batch_open(&pp.pcs, polys, comms, &points, &evals, transcript)?; - end_timer(timer); - - Ok(()) - } - - fn verify_decider( - vp: &Self::VerifierParam, - accumulator: &Self::AccumulatorInstance, - transcript: &mut impl TranscriptRead, F>, - _: impl RngCore, - ) -> Result<(), Error> { - let ProtostarVerifierParam { vp, .. } = vp; - - accumulator.absorb_into(transcript)?; - - // Round 0 - - let beta = transcript.squeeze_challenge(); - let gamma = transcript.squeeze_challenge(); - - let permutation_z_comms = - Pcs::read_commitments(&vp.pcs, vp.num_permutation_z_polys, transcript)?; - - // Round 1 - - let alpha = transcript.squeeze_challenge(); - let y = transcript.squeeze_challenges(vp.num_vars); - - let challenges = iter::empty() - .chain(accumulator.challenges.iter().copied()) - .chain([accumulator.u]) - .chain([beta, gamma, alpha]) - .collect_vec(); - let (points, evals) = { - verify_sum_check( - vp.num_vars, - &vp.expression, - accumulator.claimed_sum(), - accumulator.instances(), - &challenges, - &y, - transcript, - )? - }; - - // PCS verify - - let builtin_witness_poly_offset = vp.num_witness_polys.iter().sum::(); - let dummy_comm = Pcs::Commitment::default(); - let comms = iter::empty() - .chain(iter::repeat(&dummy_comm).take(vp.num_instances.len())) - .chain(&vp.preprocess_comms) - .chain(&accumulator.witness_comms[..builtin_witness_poly_offset]) - .chain(vp.permutation_comms.iter().map(|(_, comm)| comm)) - .chain(&accumulator.witness_comms[builtin_witness_poly_offset..]) - .chain(&permutation_z_comms) - .chain(Some(&accumulator.e_comm)) - .collect_vec(); - Pcs::batch_verify(&vp.pcs, comms, &points, &evals, transcript)?; - - Ok(()) - } -} - -#[cfg(test)] -pub(crate) mod test { - use crate::{ - accumulation::{protostar::Protostar, test::run_accumulation_scheme}, - backend::hyperplonk::{ - util::{rand_vanilla_plonk_circuit, rand_vanilla_plonk_with_lookup_circuit}, - HyperPlonk, - }, - pcs::{ - multilinear::{Gemini, MultilinearIpa, MultilinearKzg, Zeromorph}, - univariate::UnivariateKzg, - }, - util::{ - test::{seeded_std_rng, std_rng}, - transcript::Keccak256Transcript, - Itertools, - }, - }; - use halo2_curves::{bn256::Bn256, grumpkin}; - use std::iter; - - macro_rules! tests { - ($name:ident, $pcs:ty, $num_vars_range:expr) => { - paste::paste! { - #[test] - fn [<$name _protostar_hyperplonk_vanilla_plonk>]() { - run_accumulation_scheme::<_, Protostar>, Keccak256Transcript<_>, _>($num_vars_range, |num_vars| { - let (circuit_info, _) = rand_vanilla_plonk_circuit(num_vars, std_rng(), seeded_std_rng()); - let circuits = iter::repeat_with(|| { - let (_, circuit) = rand_vanilla_plonk_circuit(num_vars, std_rng(), seeded_std_rng()); - circuit - }).take(3).collect_vec(); - (circuit_info, circuits) - }); - } - - #[test] - fn [<$name _protostar_hyperplonk_vanilla_plonk_with_lookup>]() { - run_accumulation_scheme::<_, Protostar>, Keccak256Transcript<_>, _>($num_vars_range, |num_vars| { - let (circuit_info, _) = rand_vanilla_plonk_with_lookup_circuit(num_vars, std_rng(), seeded_std_rng()); - let circuits = iter::repeat_with(|| { - let (_, circuit) = rand_vanilla_plonk_with_lookup_circuit(num_vars, std_rng(), seeded_std_rng()); - circuit - }).take(3).collect_vec(); - (circuit_info, circuits) - }); - } - } - }; - ($name:ident, $pcs:ty) => { - tests!($name, $pcs, 2..16); - }; - } - - tests!(ipa, MultilinearIpa); - tests!(kzg, MultilinearKzg); - tests!(gemini_kzg, Gemini>); - tests!(zeromorph_kzg, Zeromorph>); -} diff --git a/plonkish_backend/src/accumulation/protostar/hyperplonk/preprocessor.rs b/plonkish_backend/src/accumulation/protostar/hyperplonk/preprocessor.rs deleted file mode 100644 index 1ca692c..0000000 --- a/plonkish_backend/src/accumulation/protostar/hyperplonk/preprocessor.rs +++ /dev/null @@ -1,406 +0,0 @@ -use crate::{ - accumulation::protostar::{ - ProtostarProverParam, ProtostarStrategy, - ProtostarStrategy::{Compressing, NoCompressing}, - ProtostarVerifierParam, - }, - backend::{ - hyperplonk::{preprocessor::permutation_constraints, HyperPlonk}, - PlonkishBackend, PlonkishCircuitInfo, - }, - pcs::PolynomialCommitmentScheme, - poly::multilinear::MultilinearPolynomial, - util::{ - arithmetic::{div_ceil, PrimeField}, - chain, - expression::{ - relaxed::{cross_term_expressions, products, relaxed_expression, PolynomialSet}, - Expression, Query, Rotation, - }, - DeserializeOwned, Itertools, Serialize, - }, - Error, -}; -use std::{array, borrow::Cow, collections::BTreeSet, hash::Hash, iter}; - -pub(crate) fn batch_size( - circuit_info: &PlonkishCircuitInfo, - strategy: ProtostarStrategy, -) -> usize { - let num_lookups = circuit_info.lookups.len(); - let num_permutation_polys = circuit_info.permutation_polys().len(); - chain![ - [circuit_info.preprocess_polys.len() + circuit_info.permutation_polys().len()], - circuit_info.num_witness_polys.clone(), - [num_lookups], - match strategy { - NoCompressing => { - vec![] - } - Compressing => { - vec![1] - } - }, - [2 * num_lookups + div_ceil(num_permutation_polys, max_degree(circuit_info, None) - 1)], - [1], - ] - .sum() -} - -#[allow(clippy::type_complexity)] -pub(super) fn preprocess( - param: &Pcs::Param, - circuit_info: &PlonkishCircuitInfo, - strategy: ProtostarStrategy, -) -> Result< - ( - ProtostarProverParam>, - ProtostarVerifierParam>, - ), - Error, -> -where - F: PrimeField + Hash + Serialize + DeserializeOwned, - Pcs: PolynomialCommitmentScheme>, -{ - let challenge_offset = circuit_info.num_challenges.iter().sum::(); - let max_lookup_width = circuit_info.lookups.iter().map(Vec::len).max().unwrap_or(0); - let num_theta_primes = max_lookup_width.checked_sub(1).unwrap_or_default(); - let theta_primes = (challenge_offset..) - .take(num_theta_primes) - .map(Expression::::Challenge) - .collect_vec(); - let beta_prime = &Expression::::Challenge(challenge_offset + num_theta_primes); - - let (lookup_constraints, lookup_zero_checks) = - lookup_constraints(circuit_info, &theta_primes, beta_prime); - - let max_degree = max_degree(circuit_info, Some(&lookup_constraints)); - - let num_constraints = circuit_info.constraints.len() + lookup_constraints.len(); - let num_alpha_primes = num_constraints.checked_sub(1).unwrap_or_default(); - - let witness_poly_offset = - circuit_info.num_instances.len() + circuit_info.preprocess_polys.len(); - let num_witness_polys = circuit_info.num_witness_polys.iter().sum::(); - let num_permutation_z_polys = div_ceil(circuit_info.permutation_polys().len(), max_degree - 1); - - let ( - num_builtin_witness_polys, - alpha_prime_offset, - cross_term_expressions, - sum_check, - zero_check_on_every_row, - ) = match strategy { - NoCompressing => { - let alpha_prime_offset = challenge_offset + num_theta_primes + 1; - let num_builtin_witness_polys = 3 * circuit_info.lookups.len(); - let builtin_witness_poly_offset = - witness_poly_offset + num_witness_polys + circuit_info.permutation_polys().len(); - - let poly_set = PolynomialSet { - preprocess: iter::empty() - .chain( - (circuit_info.num_instances.len()..) - .take(circuit_info.preprocess_polys.len()), - ) - .collect(), - folding: iter::empty() - .chain(0..circuit_info.num_instances.len()) - .chain((witness_poly_offset..).take(num_witness_polys)) - .chain((builtin_witness_poly_offset..).take(num_builtin_witness_polys)) - .collect(), - }; - - let products = { - let mut constraints = iter::empty() - .chain(circuit_info.constraints.iter()) - .chain(lookup_constraints.iter()) - .collect_vec(); - let folding_degrees = constraints - .iter() - .map(|constraint| folding_degree(&poly_set.preprocess, constraint)) - .enumerate() - .sorted_by(|a, b| b.1.cmp(&a.1)) - .collect_vec(); - if let &[a, b, ..] = &folding_degrees[..] { - if a.1 != b.1 { - constraints.swap(0, a.0); - } - } - let compressed_constraint = iter::empty() - .chain(constraints.first().cloned().cloned()) - .chain( - constraints - .into_iter() - .skip(1) - .zip((alpha_prime_offset..).map(Expression::Challenge)) - .map(|(constraint, challenge)| constraint * challenge), - ) - .sum::>(); - products(&poly_set.preprocess, &compressed_constraint) - }; - - let num_folding_challenges = alpha_prime_offset + num_alpha_primes; - let cross_term_expressions = - cross_term_expressions(&poly_set, &products, num_folding_challenges); - - let u = num_folding_challenges; - let relexed_constraint = { - let e = builtin_witness_poly_offset - + circuit_info.lookups.len() * 3 - + num_permutation_z_polys; - relaxed_expression(&products, u) - - Expression::Polynomial(Query::new(e, Rotation::cur())) - }; - - ( - num_builtin_witness_polys, - alpha_prime_offset, - cross_term_expressions, - None, - relexed_constraint, - ) - } - Compressing => { - let zeta = challenge_offset + num_theta_primes + 1; - let alpha_prime_offset = zeta + 1; - let num_builtin_witness_polys = 3 * circuit_info.lookups.len() + 1; - let builtin_witness_poly_offset = - witness_poly_offset + num_witness_polys + circuit_info.permutation_polys().len(); - - let poly_set = PolynomialSet { - preprocess: iter::empty() - .chain( - (circuit_info.num_instances.len()..) - .take(circuit_info.preprocess_polys.len()), - ) - .collect(), - folding: iter::empty() - .chain(0..circuit_info.num_instances.len()) - .chain((witness_poly_offset..).take(num_witness_polys)) - .chain((builtin_witness_poly_offset..).take(num_builtin_witness_polys)) - .collect(), - }; - - let powers_of_zeta = builtin_witness_poly_offset + circuit_info.lookups.len() * 3; - let compressed_products = { - let mut constraints = iter::empty() - .chain(circuit_info.constraints.iter()) - .chain(lookup_constraints.iter()) - .collect_vec(); - let folding_degrees = constraints - .iter() - .map(|constraint| folding_degree(&poly_set.preprocess, constraint)) - .enumerate() - .sorted_by(|a, b| b.1.cmp(&a.1)) - .collect_vec(); - if let &[a, b, ..] = &folding_degrees[..] { - if a.1 != b.1 { - constraints.swap(0, a.0); - } - } - let powers_of_zeta = - Expression::::Polynomial(Query::new(powers_of_zeta, Rotation::cur())); - let compressed_constraint = iter::empty() - .chain(constraints.first().cloned().cloned()) - .chain( - constraints - .into_iter() - .skip(1) - .zip((alpha_prime_offset..).map(Expression::Challenge)) - .map(|(constraint, challenge)| constraint * challenge), - ) - .sum::>() - * powers_of_zeta; - products(&poly_set.preprocess, &compressed_constraint) - }; - let powers_of_zeta_constraint = powers_of_zeta_constraint(zeta, powers_of_zeta); - let zeta_products = products(&poly_set.preprocess, &powers_of_zeta_constraint); - - let num_folding_challenges = alpha_prime_offset + num_alpha_primes; - let cross_term_expressions = - cross_term_expressions(&poly_set, &compressed_products, num_folding_challenges); - - let u = num_folding_challenges; - let relexed_compressed_constraint = relaxed_expression(&compressed_products, u); - let relexed_zeta_constraint = { - let e = powers_of_zeta + num_permutation_z_polys + 1; - relaxed_expression(&zeta_products, u) - - Expression::Polynomial(Query::new(e, Rotation::cur())) - }; - - ( - num_builtin_witness_polys, - alpha_prime_offset, - cross_term_expressions, - Some(relexed_compressed_constraint), - relexed_zeta_constraint, - ) - } - }; - - let num_folding_witness_polys = num_witness_polys + num_builtin_witness_polys; - let num_folding_challenges = alpha_prime_offset + num_alpha_primes; - - let [beta, gamma, alpha] = - &array::from_fn(|idx| Expression::::Challenge(num_folding_challenges + 1 + idx)); - let (_, permutation_constraints) = permutation_constraints( - circuit_info, - max_degree, - beta, - gamma, - num_builtin_witness_polys, - ); - - let expression = { - let zero_check_on_every_row = Expression::distribute_powers( - iter::empty() - .chain(Some(&zero_check_on_every_row)) - .chain(&permutation_constraints), - alpha, - ) * Expression::eq_xy(0); - Expression::distribute_powers( - iter::empty() - .chain(&sum_check) - .chain(lookup_zero_checks.iter()) - .chain(Some(&zero_check_on_every_row)), - alpha, - ) - }; - - let (pp, vp) = { - let (mut pp, mut vp) = HyperPlonk::preprocess(param, circuit_info)?; - let batch_size = batch_size(circuit_info, strategy); - let (pcs_pp, pcs_vp) = Pcs::trim(param, 1 << circuit_info.k, batch_size)?; - pp.pcs = pcs_pp; - vp.pcs = pcs_vp; - pp.num_permutation_z_polys = num_permutation_z_polys; - vp.num_permutation_z_polys = num_permutation_z_polys; - pp.expression = expression.clone(); - vp.expression = expression; - (pp, vp) - }; - - let num_cross_terms = cross_term_expressions.len(); - - Ok(( - ProtostarProverParam { - pp, - strategy, - num_theta_primes, - num_alpha_primes, - num_folding_witness_polys, - num_folding_challenges, - cross_term_expressions, - }, - ProtostarVerifierParam { - vp, - strategy, - num_theta_primes, - num_alpha_primes, - num_folding_witness_polys, - num_folding_challenges, - num_cross_terms, - }, - )) -} - -pub(crate) fn max_degree( - circuit_info: &PlonkishCircuitInfo, - lookup_constraints: Option<&[Expression]>, -) -> usize { - let lookup_constraints = lookup_constraints.map(Cow::Borrowed).unwrap_or_else(|| { - let n = circuit_info.lookups.iter().map(Vec::len).max().unwrap_or(1); - let dummy_challenges = vec![Expression::zero(); n]; - Cow::Owned( - self::lookup_constraints(circuit_info, &dummy_challenges, &dummy_challenges[0]).0, - ) - }); - iter::empty() - .chain(circuit_info.constraints.iter().map(Expression::degree)) - .chain(lookup_constraints.iter().map(Expression::degree)) - .chain(circuit_info.max_degree) - .chain(Some(2)) - .max() - .unwrap() -} - -pub(crate) fn folding_degree( - preprocess_polys: &BTreeSet, - expression: &Expression, -) -> usize { - expression.evaluate( - &|_| 0, - &|_| 0, - &|query| (!preprocess_polys.contains(&query.poly())) as usize, - &|_| 1, - &|a| a, - &|a, b| a.max(b), - &|a, b| a + b, - &|a, _| a, - ) -} - -pub(crate) fn lookup_constraints( - circuit_info: &PlonkishCircuitInfo, - theta_primes: &[Expression], - beta_prime: &Expression, -) -> (Vec>, Vec>) { - let one = &Expression::one(); - let m_offset = circuit_info.num_poly() + circuit_info.permutation_polys().len(); - let h_offset = m_offset + circuit_info.lookups.len(); - let constraints = circuit_info - .lookups - .iter() - .zip(m_offset..) - .zip((h_offset..).step_by(2)) - .flat_map(|((lookup, m), h)| { - let [m, h_input, h_table] = &[m, h, h + 1] - .map(|poly| Query::new(poly, Rotation::cur())) - .map(Expression::::Polynomial); - let (inputs, tables) = lookup - .iter() - .map(|(input, table)| (input, table)) - .unzip::<_, _, Vec<_>, Vec<_>>(); - let [input, table] = &[inputs, tables].map(|exprs| { - iter::empty() - .chain(exprs.first().cloned().cloned()) - .chain( - exprs - .into_iter() - .skip(1) - .zip(theta_primes) - .map(|(expr, theta_prime)| expr * theta_prime), - ) - .sum::>() - }); - [ - h_input * (input + beta_prime) - one, - h_table * (table + beta_prime) - m, - ] - }) - .collect_vec(); - let sum_check = (h_offset..) - .step_by(2) - .take(circuit_info.lookups.len()) - .map(|h| { - let [h_input, h_table] = &[h, h + 1] - .map(|poly| Query::new(poly, Rotation::cur())) - .map(Expression::::Polynomial); - h_input - h_table - }) - .collect_vec(); - (constraints, sum_check) -} - -fn powers_of_zeta_constraint(zeta: usize, powers_of_zeta: usize) -> Expression { - let l_0 = &Expression::::lagrange(0); - let l_last = &Expression::::lagrange(-1); - let one = &Expression::one(); - let zeta = &Expression::Challenge(zeta); - let [powers_of_zeta, powers_of_zeta_next] = &[Rotation::cur(), Rotation::next()] - .map(|rotation| Expression::Polynomial(Query::new(powers_of_zeta, rotation))); - - powers_of_zeta_next - (l_0 + l_last * zeta + (one - (l_0 + l_last)) * powers_of_zeta * zeta) -} diff --git a/plonkish_backend/src/accumulation/protostar/hyperplonk/prover.rs b/plonkish_backend/src/accumulation/protostar/hyperplonk/prover.rs deleted file mode 100644 index 6fcf02b..0000000 --- a/plonkish_backend/src/accumulation/protostar/hyperplonk/prover.rs +++ /dev/null @@ -1,334 +0,0 @@ -use crate::{ - accumulation::protostar::ProtostarAccumulator, - backend::hyperplonk::prover::instance_polys, - pcs::PolynomialCommitmentScheme, - poly::multilinear::MultilinearPolynomial, - util::{ - arithmetic::{div_ceil, powers, sum, BatchInvert, BooleanHypercube, PrimeField}, - expression::{evaluator::ExpressionRegistry, Expression, Rotation}, - izip, izip_eq, - parallel::{num_threads, par_map_collect, parallelize, parallelize_iter}, - Itertools, - }, -}; -use std::{borrow::Cow, hash::Hash, iter}; - -pub(crate) fn lookup_h_polys( - compressed_polys: &[[MultilinearPolynomial; 2]], - m_polys: &[MultilinearPolynomial], - beta: &F, -) -> Vec<[MultilinearPolynomial; 2]> { - compressed_polys - .iter() - .zip(m_polys.iter()) - .map(|(compressed_polys, m_poly)| lookup_h_poly(compressed_polys, m_poly, beta)) - .collect() -} - -fn lookup_h_poly( - compressed_polys: &[MultilinearPolynomial; 2], - m_poly: &MultilinearPolynomial, - beta: &F, -) -> [MultilinearPolynomial; 2] { - let [input, table] = compressed_polys; - let mut h_input = vec![F::ZERO; 1 << input.num_vars()]; - let mut h_table = vec![F::ZERO; 1 << input.num_vars()]; - - parallelize(&mut h_input, |(h_input, start)| { - for (h_input, input) in h_input.iter_mut().zip(input[start..].iter()) { - *h_input = *beta + input; - } - }); - parallelize(&mut h_table, |(h_table, start)| { - for (h_table, table) in h_table.iter_mut().zip(table[start..].iter()) { - *h_table = *beta + table; - } - }); - - let chunk_size = div_ceil(2 * h_input.len(), num_threads()); - parallelize_iter( - iter::empty() - .chain(h_input.chunks_mut(chunk_size)) - .chain(h_table.chunks_mut(chunk_size)), - |h| { - h.iter_mut().batch_invert(); - }, - ); - - parallelize(&mut h_table, |(h_table, start)| { - for (h_table, m) in h_table.iter_mut().zip(m_poly[start..].iter()) { - *h_table *= m; - } - }); - - if cfg!(feature = "sanity-check") { - assert_eq!(sum::(&h_input), sum::(&h_table)); - } - - [ - MultilinearPolynomial::new(h_input), - MultilinearPolynomial::new(h_table), - ] -} - -pub(super) fn powers_of_zeta_poly( - num_vars: usize, - zeta: F, -) -> MultilinearPolynomial { - let powers_of_zeta = powers(zeta).take(1 << num_vars).collect_vec(); - let nth_map = BooleanHypercube::new(num_vars).nth_map(); - MultilinearPolynomial::new(par_map_collect(&nth_map, |b| powers_of_zeta[*b])) -} - -pub(crate) fn evaluate_cross_term_polys( - cross_term_expressions: &[Expression], - num_vars: usize, - preprocess_polys: &[MultilinearPolynomial], - accumulator: &ProtostarAccumulator, - incoming: &ProtostarAccumulator, -) -> Vec> -where - F: PrimeField, - Pcs: PolynomialCommitmentScheme>, -{ - if cross_term_expressions.is_empty() { - return Vec::new(); - } - - let ev = init_hadamard_evaluator( - cross_term_expressions, - num_vars, - preprocess_polys, - accumulator, - incoming, - ); - - let size = 1 << ev.num_vars; - let chunk_size = div_ceil(size, num_threads()); - let num_cross_terms = ev.reg.indexed_outputs().len(); - - let mut outputs = vec![F::ZERO; num_cross_terms * size]; - parallelize_iter( - outputs - .chunks_mut(chunk_size * num_cross_terms) - .zip((0..).step_by(chunk_size)), - |(outputs, start)| { - let mut data = ev.cache(); - let bs = start..(start + chunk_size).min(size); - izip!(bs, outputs.chunks_mut(num_cross_terms)) - .for_each(|(b, outputs)| ev.evaluate(outputs, &mut data, b)); - }, - ); - - (0..num_cross_terms) - .map(|offset| par_map_collect(0..size, |idx| outputs[idx * num_cross_terms + offset])) - .map(MultilinearPolynomial::new) - .collect_vec() -} - -pub(super) fn evaluate_compressed_cross_term_sums( - cross_term_expressions: &[Expression], - num_vars: usize, - preprocess_polys: &[MultilinearPolynomial], - accumulator: &ProtostarAccumulator, - incoming: &ProtostarAccumulator, -) -> Vec -where - F: PrimeField, - Pcs: PolynomialCommitmentScheme>, -{ - if cross_term_expressions.is_empty() { - return Vec::new(); - } - - let ev = init_hadamard_evaluator( - cross_term_expressions, - num_vars, - preprocess_polys, - accumulator, - incoming, - ); - - let size = 1 << ev.num_vars; - let num_threads = num_threads(); - let chunk_size = div_ceil(size, num_threads); - let num_cross_terms = ev.reg.indexed_outputs().len(); - - let mut partial_sums = vec![vec![F::ZERO; num_cross_terms]; num_threads]; - parallelize_iter( - partial_sums.iter_mut().zip((0..).step_by(chunk_size)), - |(partial_sums, start)| { - let mut data = ev.cache(); - (start..(start + chunk_size).min(size)) - .for_each(|b| ev.evaluate_and_sum(partial_sums, &mut data, b)) - }, - ); - - partial_sums - .into_iter() - .reduce(|mut sums, partial_sums| { - izip_eq!(&mut sums, &partial_sums).for_each(|(sum, partial_sum)| *sum += partial_sum); - sums - }) - .unwrap() -} - -pub(crate) fn evaluate_zeta_cross_term_poly( - num_vars: usize, - zeta_nth_back: usize, - accumulator: &ProtostarAccumulator, - incoming: &ProtostarAccumulator, -) -> MultilinearPolynomial -where - F: PrimeField, - Pcs: PolynomialCommitmentScheme>, -{ - let [(acc_pow, acc_zeta, acc_u), (incoming_pow, incoming_zeta, incoming_u)] = - [accumulator, incoming].map(|witness| { - let pow = witness.witness_polys.last().unwrap(); - let zeta = witness - .instance - .challenges - .iter() - .nth_back(zeta_nth_back) - .unwrap(); - (pow, zeta, witness.instance.u) - }); - assert_eq!(incoming_u, F::ONE); - - let size = 1 << num_vars; - let mut cross_term = vec![F::ZERO; size]; - - let bh = BooleanHypercube::new(num_vars); - let next_map = bh.rotation_map(Rotation::next()); - parallelize(&mut cross_term, |(cross_term, start)| { - cross_term - .iter_mut() - .zip(start..) - .for_each(|(cross_term, b)| { - *cross_term = acc_pow[next_map[b]] + acc_u * incoming_pow[next_map[b]] - - (acc_pow[b] * incoming_zeta + incoming_pow[b] * acc_zeta); - }) - }); - let b_0 = 0; - let b_last = bh.rotate(1, Rotation::prev()); - cross_term[b_0] += acc_pow[b_0] * incoming_zeta + incoming_pow[b_0] * acc_zeta - acc_u.double(); - cross_term[b_last] += acc_pow[b_last] * incoming_zeta + incoming_pow[b_last] * acc_zeta - - acc_u * incoming_zeta - - acc_zeta; - - MultilinearPolynomial::new(cross_term) -} - -fn init_hadamard_evaluator<'a, F, Pcs>( - expressions: &[Expression], - num_vars: usize, - preprocess_polys: &'a [MultilinearPolynomial], - accumulator: &'a ProtostarAccumulator, - incoming: &'a ProtostarAccumulator, -) -> HadamardEvaluator<'a, F> -where - F: PrimeField, - Pcs: PolynomialCommitmentScheme>, -{ - assert!(!expressions.is_empty()); - - let acc_instance_polys = instance_polys(num_vars, &accumulator.instance.instances); - let incoming_instance_polys = instance_polys(num_vars, &incoming.instance.instances); - let polys = iter::empty() - .chain(preprocess_polys.iter().map(Cow::Borrowed)) - .chain(acc_instance_polys.into_iter().map(Cow::Owned)) - .chain(accumulator.witness_polys.iter().map(Cow::Borrowed)) - .chain(incoming_instance_polys.into_iter().map(Cow::Owned)) - .chain(incoming.witness_polys.iter().map(Cow::Borrowed)) - .collect_vec(); - let challenges = iter::empty() - .chain(accumulator.instance.challenges.iter().cloned()) - .chain(Some(accumulator.instance.u)) - .chain(incoming.instance.challenges.iter().cloned()) - .chain(Some(incoming.instance.u)) - .collect_vec(); - - let expressions = expressions - .iter() - .map(|expression| { - expression - .simplified(Some(&challenges)) - .unwrap_or_else(Expression::zero) - }) - .collect_vec(); - - HadamardEvaluator::new(num_vars, &expressions, polys) -} - -#[derive(Clone, Debug)] -pub(crate) struct HadamardEvaluator<'a, F: PrimeField> { - pub(crate) num_vars: usize, - pub(crate) reg: ExpressionRegistry, - lagranges: Vec, - polys: Vec>>, -} - -impl<'a, F: PrimeField> HadamardEvaluator<'a, F> { - pub(crate) fn new( - num_vars: usize, - expressions: &[Expression], - polys: Vec>>, - ) -> Self { - let mut reg = ExpressionRegistry::new(); - for expression in expressions.iter() { - reg.register(expression); - } - assert!(reg.eq_xys().is_empty()); - - let bh = BooleanHypercube::new(num_vars).iter().collect_vec(); - let lagranges = reg - .lagranges() - .iter() - .map(|i| bh[i.rem_euclid(1 << num_vars) as usize]) - .collect_vec(); - - Self { - num_vars, - reg, - lagranges, - polys, - } - } - - pub(crate) fn cache(&self) -> Vec { - self.reg.cache() - } - - pub(crate) fn evaluate(&self, evals: &mut [F], cache: &mut [F], b: usize) { - self.evaluate_calculations(cache, b); - izip_eq!(evals, self.reg.indexed_outputs()).for_each(|(eval, idx)| *eval = cache[*idx]) - } - - pub(crate) fn evaluate_and_sum(&self, sums: &mut [F], cache: &mut [F], b: usize) { - self.evaluate_calculations(cache, b); - izip_eq!(sums, self.reg.indexed_outputs()).for_each(|(sum, idx)| *sum += cache[*idx]) - } - - fn evaluate_calculations(&self, cache: &mut [F], b: usize) { - let bh = BooleanHypercube::new(self.num_vars); - if self.reg.has_identity() { - cache[self.reg.offsets().identity()] = F::from(b as u64); - } - cache[self.reg.offsets().lagranges()..] - .iter_mut() - .zip(&self.lagranges) - .for_each(|(value, i)| *value = if &b == i { F::ONE } else { F::ZERO }); - cache[self.reg.offsets().polys()..] - .iter_mut() - .zip(self.reg.polys()) - .for_each(|(value, (query, _))| { - *value = self.polys[query.poly()][bh.rotate(b, query.rotation())] - }); - self.reg - .indexed_calculations() - .iter() - .zip(self.reg.offsets().calculations()..) - .for_each(|(calculation, idx)| calculation.calculate(cache, idx)); - } -} diff --git a/plonkish_backend/src/accumulation/sangria.rs b/plonkish_backend/src/accumulation/sangria.rs deleted file mode 100644 index 83c4118..0000000 --- a/plonkish_backend/src/accumulation/sangria.rs +++ /dev/null @@ -1,20 +0,0 @@ -use crate::{ - accumulation::protostar::{ - Protostar, ProtostarAccumulator, ProtostarAccumulatorInstance, ProtostarProverParam, - ProtostarStrategy::NoCompressing, ProtostarVerifierParam, - }, - pcs::PolynomialCommitmentScheme, -}; - -mod hyperplonk; - -pub type Sangria = Protostar; - -pub type SangriaProverParam = ProtostarProverParam; - -pub type SangriaVerifierParam = ProtostarVerifierParam; - -pub type SangriaAccumulator = ProtostarAccumulator; - -pub type SangriaAccumulatorInstance = - ProtostarAccumulatorInstance>::Commitment>; diff --git a/plonkish_backend/src/accumulation/sangria/hyperplonk.rs b/plonkish_backend/src/accumulation/sangria/hyperplonk.rs deleted file mode 100644 index 314b2f7..0000000 --- a/plonkish_backend/src/accumulation/sangria/hyperplonk.rs +++ /dev/null @@ -1,59 +0,0 @@ -#[cfg(test)] -pub(crate) mod test { - use crate::{ - accumulation::{sangria::Sangria, test::run_accumulation_scheme}, - backend::hyperplonk::{ - util::{rand_vanilla_plonk_circuit, rand_vanilla_plonk_with_lookup_circuit}, - HyperPlonk, - }, - pcs::{ - multilinear::{Gemini, MultilinearIpa, MultilinearKzg, Zeromorph}, - univariate::UnivariateKzg, - }, - util::{ - test::{seeded_std_rng, std_rng}, - transcript::Keccak256Transcript, - Itertools, - }, - }; - use halo2_curves::{bn256::Bn256, grumpkin}; - use std::iter; - - macro_rules! tests { - ($name:ident, $pcs:ty, $num_vars_range:expr) => { - paste::paste! { - #[test] - fn [<$name _sangria_hyperplonk_vanilla_plonk>]() { - run_accumulation_scheme::<_, Sangria>, Keccak256Transcript<_>, _>($num_vars_range, |num_vars| { - let (circuit_info, _) = rand_vanilla_plonk_circuit(num_vars, std_rng(), seeded_std_rng()); - let circuits = iter::repeat_with(|| { - let (_, circuit) = rand_vanilla_plonk_circuit(num_vars, std_rng(), seeded_std_rng()); - circuit - }).take(3).collect_vec(); - (circuit_info, circuits) - }); - } - - #[test] - fn [<$name _sangria_hyperplonk_vanilla_plonk_with_lookup>]() { - run_accumulation_scheme::<_, Sangria>, Keccak256Transcript<_>, _>($num_vars_range, |num_vars| { - let (circuit_info, _) = rand_vanilla_plonk_with_lookup_circuit(num_vars, std_rng(), seeded_std_rng()); - let circuits = iter::repeat_with(|| { - let (_, circuit) = rand_vanilla_plonk_with_lookup_circuit(num_vars, std_rng(), seeded_std_rng()); - circuit - }).take(3).collect_vec(); - (circuit_info, circuits) - }); - } - } - }; - ($name:ident, $pcs:ty) => { - tests!($name, $pcs, 2..16); - }; - } - - tests!(ipa, MultilinearIpa); - tests!(kzg, MultilinearKzg); - tests!(gemini_kzg, Gemini>); - tests!(zeromorph_kzg, Zeromorph>); -} diff --git a/plonkish_backend/src/lib.rs b/plonkish_backend/src/lib.rs index 1cd59ee..054488d 100644 --- a/plonkish_backend/src/lib.rs +++ b/plonkish_backend/src/lib.rs @@ -1,6 +1,5 @@ #![allow(clippy::op_ref)] -pub mod accumulation; pub mod backend; pub mod frontend; pub mod pcs;