diff --git a/halo2_proofs/src/plonk.rs b/halo2_proofs/src/plonk.rs index 05f932b98b..af9aac3f87 100644 --- a/halo2_proofs/src/plonk.rs +++ b/halo2_proofs/src/plonk.rs @@ -100,6 +100,16 @@ impl VerifyingKeyV2 { vk } + + /// Hashes a verification key into a transcript. + pub fn hash_into, T: Transcript>( + &self, + transcript: &mut T, + ) -> io::Result<()> { + transcript.common_scalar(self.transcript_repr)?; + + Ok(()) + } } /// This is a verifying key which allows for the verification of proofs for a @@ -389,6 +399,21 @@ pub struct ProvingKeyV2 { ev: Evaluator, } +// impl ProvingKeyV2 +// where +// C::Scalar: FromUniformBytes<64>, +// { +// /// Hashes a verification key into a transcript. +// pub fn hash_into, T: Transcript>( +// &self, +// transcript: &mut T, +// ) -> io::Result<()> { +// transcript.common_scalar(self.transcript_repr)?; +// +// Ok(()) +// } +// } + /// This is a proving key which allows for the creation of proofs for a /// particular circuit. #[derive(Clone, Debug)] diff --git a/halo2_proofs/src/plonk/prover.rs b/halo2_proofs/src/plonk/prover.rs index cd0d7306a9..91b44356dd 100644 --- a/halo2_proofs/src/plonk/prover.rs +++ b/halo2_proofs/src/plonk/prover.rs @@ -8,11 +8,11 @@ use std::{collections::HashMap, iter}; use super::{ circuit::{ sealed::{self}, - Advice, Any, Assignment, Challenge, Circuit, Column, ConstraintSystem, Fixed, FloorPlanner, - Instance, Selector, + Advice, Any, Assignment, Challenge, Circuit, Column, CompiledCircuitV2, ConstraintSystem, + Fixed, FloorPlanner, Instance, Selector, }, lookup, permutation, shuffle, vanishing, ChallengeBeta, ChallengeGamma, ChallengeTheta, - ChallengeX, ChallengeY, Error, ProvingKey, + ChallengeX, ChallengeY, Error, ProvingKey, ProvingKeyV2, }; use crate::{ @@ -30,6 +30,117 @@ use crate::{ }; use group::prime::PrimeCurveAffine; +struct InstanceSingle { + pub instance_values: Vec>, + pub instance_polys: Vec>, +} + +pub struct ProverV2< + 'params, + Scheme: CommitmentScheme, + P: Prover<'params, Scheme>, + E: EncodedChallenge, + R: RngCore, + T: TranscriptWrite, +> { + params: &'params Scheme::ParamsProver, + instance: Vec>, + _marker: std::marker::PhantomData<(Scheme, P, E, R, T)>, +} + +impl< + 'params, + Scheme: CommitmentScheme, + P: Prover<'params, Scheme>, + E: EncodedChallenge, + R: RngCore, + T: TranscriptWrite, + > ProverV2<'params, Scheme, P, E, R, T> +{ + pub fn new( + params: &'params Scheme::ParamsProver, + pk: &ProvingKeyV2, + circuit: &CompiledCircuitV2, + instance: &[&[Scheme::Scalar]], + mut rng: R, + mut transcript: T, + ) -> Result + where + Scheme::Scalar: WithSmallOrderMulGroup<3> + FromUniformBytes<64>, + { + if instance.len() != pk.vk.cs.num_instance_columns { + return Err(Error::InvalidInstances); + } + + // Hash verification key into transcript + pk.vk.hash_into(&mut transcript)?; + + let meta = &circuit.cs; + + let domain = &pk.vk.domain; + + let instance: Vec> = iter::once(instance) + .map(|instance| -> Result, Error> { + let instance_values = instance + .iter() + .map(|values| { + let mut poly = domain.empty_lagrange(); + assert_eq!(poly.len(), params.n() as usize); + if values.len() > (poly.len() - (meta.blinding_factors() + 1)) { + return Err(Error::InstanceTooLarge); + } + for (poly, value) in poly.iter_mut().zip(values.iter()) { + if !P::QUERY_INSTANCE { + transcript.common_scalar(*value)?; + } + *poly = *value; + } + Ok(poly) + }) + .collect::, _>>()?; + + if P::QUERY_INSTANCE { + let instance_commitments_projective: Vec<_> = instance_values + .iter() + .map(|poly| params.commit_lagrange(poly, Blind::default())) + .collect(); + let mut instance_commitments = + vec![Scheme::Curve::identity(); instance_commitments_projective.len()]; + ::CurveExt::batch_normalize( + &instance_commitments_projective, + &mut instance_commitments, + ); + let instance_commitments = instance_commitments; + drop(instance_commitments_projective); + + for commitment in &instance_commitments { + transcript.common_point(*commitment)?; + } + } + + let instance_polys: Vec<_> = instance_values + .iter() + .map(|poly| { + let lagrange_vec = domain.lagrange_from_vec(poly.to_vec()); + domain.lagrange_to_coeff(lagrange_vec) + }) + .collect(); + + Ok(InstanceSingle { + instance_values, + instance_polys, + }) + }) + .collect::, _>>()?; + + Ok(ProverV2 { + params, + instance, + _marker: std::marker::PhantomData {}, + }) + } +} + /// This creates a proof for the provided `circuit` when given the public /// parameters `params` and the proving key [`ProvingKey`] that was /// generated previously for the same circuit. The provided `instances`