From 32f011d52da4d5d759de6c1487209dcac9dd395c Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Sat, 1 May 2021 09:28:50 +0800 Subject: [PATCH] Replace ChallengeSpace with EncodedChallenge API Co-authored-by: Sean Bowe --- benches/plonk.rs | 9 +- examples/sha256/benches.rs | 7 +- src/plonk.rs | 4 +- src/plonk/lookup/prover.rs | 18 ++- src/plonk/lookup/verifier.rs | 14 +- src/plonk/permutation/prover.rs | 9 +- src/plonk/permutation/verifier.rs | 9 +- src/plonk/prover.rs | 6 +- src/plonk/vanishing/prover.rs | 6 +- src/plonk/vanishing/verifier.rs | 10 +- src/plonk/verifier.rs | 11 +- src/poly/commitment.rs | 8 +- src/poly/commitment/prover.rs | 4 +- src/poly/commitment/verifier.rs | 33 +++-- src/poly/multiopen.rs | 11 +- src/poly/multiopen/prover.rs | 11 +- src/poly/multiopen/verifier.rs | 14 +- src/transcript.rs | 206 ++++++++++++++---------------- tests/plonk_api.rs | 8 +- 19 files changed, 214 insertions(+), 184 deletions(-) diff --git a/benches/plonk.rs b/benches/plonk.rs index 3677ba09..8af94dee 100644 --- a/benches/plonk.rs +++ b/benches/plonk.rs @@ -6,7 +6,7 @@ use halo2::arithmetic::FieldExt; use halo2::pasta::{EqAffine, Fp}; use halo2::plonk::*; use halo2::poly::{commitment::Params, Rotation}; -use halo2::transcript::{Blake2bRead, Blake2bWrite, ChallengeScalarEndo}; +use halo2::transcript::{Blake2bRead, Blake2bWrite, Challenge255}; use std::marker::PhantomData; @@ -256,7 +256,7 @@ fn bench_with_k(name: &str, k: u32, c: &mut Criterion) { }; // Create a proof - let mut transcript = Blake2bWrite::<_, _, ChallengeScalarEndo>::init(vec![]); + let mut transcript = Blake2bWrite::<_, _, Challenge255>::init(vec![]); create_proof(¶ms, &pk, &[circuit], &[&[]], &mut transcript) .expect("proof generation should not fail") }); @@ -268,7 +268,7 @@ fn bench_with_k(name: &str, k: u32, c: &mut Criterion) { }; // Create a proof - let mut transcript = Blake2bWrite::<_, _, ChallengeScalarEndo>::init(vec![]); + let mut transcript = Blake2bWrite::<_, _, Challenge255>::init(vec![]); create_proof(¶ms, &pk, &[circuit], &[&[]], &mut transcript) .expect("proof generation should not fail"); let proof = transcript.finalize(); @@ -276,8 +276,7 @@ fn bench_with_k(name: &str, k: u32, c: &mut Criterion) { c.bench_function(&verifier_name, |b| { b.iter(|| { let msm = params.empty_msm(); - let mut transcript = - Blake2bRead::<_, _, ChallengeScalarEndo>::init(&proof[..]); + let mut transcript = Blake2bRead::<_, _, Challenge255>::init(&proof[..]); let guard = verify_proof(¶ms, pk.get_vk(), msm, &[&[]], &mut transcript).unwrap(); let msm = guard.clone().use_challenges(); assert!(msm.eval()); diff --git a/examples/sha256/benches.rs b/examples/sha256/benches.rs index 07266975..25d2d68f 100644 --- a/examples/sha256/benches.rs +++ b/examples/sha256/benches.rs @@ -8,7 +8,7 @@ use halo2::{ Error, VerifyingKey, }, poly::commitment::Params, - transcript::{Blake2bRead, Blake2bWrite, ChallengeScalarEndo}, + transcript::{Blake2bRead, Blake2bWrite, Challenge255}, }; use std::{ @@ -128,7 +128,7 @@ fn bench(name: &str, k: u32, c: &mut Criterion) { // Create a proof let proof_path = Path::new("./benches/sha256_assets/sha256_proof"); if File::open(&proof_path).is_err() { - let mut transcript = Blake2bWrite::<_, _, ChallengeScalarEndo>::init(vec![]); + let mut transcript = Blake2bWrite::<_, _, Challenge255>::init(vec![]); create_proof(¶ms, &pk, &[circuit], &[], &mut transcript) .expect("proof generation should not fail"); let proof: Vec = transcript.finalize(); @@ -145,8 +145,7 @@ fn bench(name: &str, k: u32, c: &mut Criterion) { c.bench_function(&verifier_name, |b| { b.iter(|| { let msm = params.empty_msm(); - let mut transcript = - Blake2bRead::<_, _, ChallengeScalarEndo>::init(&proof[..]); + let mut transcript = Blake2bRead::<_, _, Challenge255>::init(&proof[..]); let guard = verify_proof(¶ms, pk.get_vk(), msm, &[], &mut transcript).unwrap(); let msm = guard.clone().use_challenges(); assert!(msm.eval()); diff --git a/src/plonk.rs b/src/plonk.rs index 0772cc8d..3be83ea2 100644 --- a/src/plonk.rs +++ b/src/plonk.rs @@ -12,7 +12,7 @@ use crate::poly::{ commitment::Params, Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff, PinnedEvaluationDomain, Polynomial, }; -use crate::transcript::{ChallengeScalar, ChallengeSpace, Transcript}; +use crate::transcript::{ChallengeScalar, EncodedChallenge, Transcript}; mod circuit; mod keygen; @@ -79,7 +79,7 @@ impl VerifyingKey { } /// Hashes a verification key into a transcript. - pub fn hash_into, T: Transcript>( + pub fn hash_into, T: Transcript>( &self, transcript: &mut T, ) -> io::Result<()> { diff --git a/src/plonk/lookup/prover.rs b/src/plonk/lookup/prover.rs index e1f1a737..fa2f1df4 100644 --- a/src/plonk/lookup/prover.rs +++ b/src/plonk/lookup/prover.rs @@ -10,7 +10,7 @@ use crate::{ multiopen::ProverQuery, Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial, Rotation, }, - transcript::{ChallengeSpace, TranscriptWrite}, + transcript::{EncodedChallenge, TranscriptWrite}, }; use ff::Field; use group::Curve; @@ -72,7 +72,13 @@ impl Argument { /// - constructs Permuted struct using permuted_input_value = A', and /// permuted_table_expression = S'. /// The Permuted struct is used to update the Lookup, and is then returned. - pub(in crate::plonk) fn commit_permuted<'a, C, S: ChallengeSpace, T: TranscriptWrite>( + pub(in crate::plonk) fn commit_permuted< + 'a, + C, + I, + E: EncodedChallenge, + T: TranscriptWrite, + >( &self, pk: &ProvingKey, params: &Params, @@ -244,7 +250,11 @@ impl Permuted { /// grand product polynomial over the lookup. The grand product polynomial /// is used to populate the Product struct. The Product struct is /// added to the Lookup and finally returned by the method. - pub(in crate::plonk) fn commit_product, T: TranscriptWrite>( + pub(in crate::plonk) fn commit_product< + I, + E: EncodedChallenge, + T: TranscriptWrite, + >( self, pk: &ProvingKey, params: &Params, @@ -488,7 +498,7 @@ impl<'a, C: CurveAffine> Committed { } impl Constructed { - pub(in crate::plonk) fn evaluate, T: TranscriptWrite>( + pub(in crate::plonk) fn evaluate, T: TranscriptWrite>( self, pk: &ProvingKey, x: ChallengeX, diff --git a/src/plonk/lookup/verifier.rs b/src/plonk/lookup/verifier.rs index fe23f834..44b542eb 100644 --- a/src/plonk/lookup/verifier.rs +++ b/src/plonk/lookup/verifier.rs @@ -8,7 +8,7 @@ use crate::{ arithmetic::{CurveAffine, FieldExt}, plonk::{Error, VerifyingKey}, poly::{multiopen::VerifierQuery, Rotation}, - transcript::{ChallengeSpace, TranscriptRead}, + transcript::{EncodedChallenge, TranscriptRead}, }; use ff::Field; @@ -34,8 +34,9 @@ pub struct Evaluated { impl Argument { pub(in crate::plonk) fn read_permuted_commitments< C: CurveAffine, - S: ChallengeSpace, - T: TranscriptRead, + I, + E: EncodedChallenge, + T: TranscriptRead, >( &self, transcript: &mut T, @@ -56,8 +57,9 @@ impl Argument { impl PermutationCommitments { pub(in crate::plonk) fn read_product_commitment< - S: ChallengeSpace, - T: TranscriptRead, + I, + E: EncodedChallenge, + T: TranscriptRead, >( self, transcript: &mut T, @@ -74,7 +76,7 @@ impl PermutationCommitments { } impl Committed { - pub(crate) fn evaluate, T: TranscriptRead>( + pub(crate) fn evaluate, T: TranscriptRead>( self, transcript: &mut T, ) -> Result, Error> { diff --git a/src/plonk/permutation/prover.rs b/src/plonk/permutation/prover.rs index 203ae120..bc338e8a 100644 --- a/src/plonk/permutation/prover.rs +++ b/src/plonk/permutation/prover.rs @@ -12,7 +12,7 @@ use crate::{ multiopen::ProverQuery, Coeff, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial, Rotation, }, - transcript::{ChallengeSpace, TranscriptWrite}, + transcript::{EncodedChallenge, TranscriptWrite}, }; pub(crate) struct Committed { @@ -34,8 +34,9 @@ pub(crate) struct Evaluated { impl Argument { pub(in crate::plonk) fn commit< C: CurveAffine, - S: ChallengeSpace, - T: TranscriptWrite, + I, + E: EncodedChallenge, + T: TranscriptWrite, >( &self, params: &Params, @@ -257,7 +258,7 @@ impl super::ProvingKey { } impl Constructed { - pub(in crate::plonk) fn evaluate, T: TranscriptWrite>( + pub(in crate::plonk) fn evaluate, T: TranscriptWrite>( self, pk: &plonk::ProvingKey, pkey: &ProvingKey, diff --git a/src/plonk/permutation/verifier.rs b/src/plonk/permutation/verifier.rs index 97fa7a24..7fd776fa 100644 --- a/src/plonk/permutation/verifier.rs +++ b/src/plonk/permutation/verifier.rs @@ -7,7 +7,7 @@ use crate::{ arithmetic::{CurveAffine, FieldExt}, plonk::{self, Error}, poly::{multiopen::VerifierQuery, Rotation}, - transcript::{ChallengeSpace, TranscriptRead}, + transcript::{EncodedChallenge, TranscriptRead}, }; pub struct Committed { @@ -24,8 +24,9 @@ pub struct Evaluated { impl Argument { pub(crate) fn read_product_commitment< C: CurveAffine, - S: ChallengeSpace, - T: TranscriptRead, + I, + E: EncodedChallenge, + T: TranscriptRead, >( &self, transcript: &mut T, @@ -41,7 +42,7 @@ impl Argument { } impl Committed { - pub(crate) fn evaluate, T: TranscriptRead>( + pub(crate) fn evaluate, T: TranscriptRead>( self, vkey: &VerifyingKey, transcript: &mut T, diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 1a2220b0..a4a81c6a 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -12,15 +12,15 @@ use crate::poly::{ multiopen::{self, ProverQuery}, Coeff, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial, }; -use crate::transcript::{ChallengeSpace, TranscriptWrite}; +use crate::transcript::{EncodedChallenge, TranscriptWrite}; /// 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. pub fn create_proof< C: CurveAffine, - S: ChallengeSpace, - T: TranscriptWrite, + E: EncodedChallenge, + T: TranscriptWrite, ConcreteCircuit: Circuit, >( params: &Params, diff --git a/src/plonk/vanishing/prover.rs b/src/plonk/vanishing/prover.rs index 9e6ab4cd..e2d67eb6 100644 --- a/src/plonk/vanishing/prover.rs +++ b/src/plonk/vanishing/prover.rs @@ -10,7 +10,7 @@ use crate::{ multiopen::ProverQuery, Coeff, EvaluationDomain, ExtendedLagrangeCoeff, Polynomial, }, - transcript::{ChallengeSpace, TranscriptWrite}, + transcript::{EncodedChallenge, TranscriptWrite}, }; pub(in crate::plonk) struct Constructed { @@ -23,7 +23,7 @@ pub(in crate::plonk) struct Evaluated { } impl Argument { - pub(in crate::plonk) fn construct, T: TranscriptWrite>( + pub(in crate::plonk) fn construct, T: TranscriptWrite>( params: &Params, domain: &EvaluationDomain, expressions: impl Iterator>, @@ -69,7 +69,7 @@ impl Argument { } impl Constructed { - pub(in crate::plonk) fn evaluate, T: TranscriptWrite>( + pub(in crate::plonk) fn evaluate, T: TranscriptWrite>( self, x: ChallengeX, transcript: &mut T, diff --git a/src/plonk/vanishing/verifier.rs b/src/plonk/vanishing/verifier.rs index fd49d222..9c2f5a44 100644 --- a/src/plonk/vanishing/verifier.rs +++ b/src/plonk/vanishing/verifier.rs @@ -4,7 +4,7 @@ use crate::{ arithmetic::CurveAffine, plonk::{Error, VerifyingKey}, poly::multiopen::VerifierQuery, - transcript::{read_n_points, read_n_scalars, ChallengeSpace, TranscriptRead}, + transcript::{read_n_points, read_n_scalars, EncodedChallenge, TranscriptRead}, }; use super::super::{ChallengeX, ChallengeY}; @@ -20,7 +20,11 @@ pub struct Evaluated { } impl Argument { - pub(in crate::plonk) fn read_commitments, T: TranscriptRead>( + pub(in crate::plonk) fn read_commitments< + I, + E: EncodedChallenge, + T: TranscriptRead, + >( vk: &VerifyingKey, transcript: &mut T, ) -> Result, Error> { @@ -33,7 +37,7 @@ impl Argument { } impl Committed { - pub(in crate::plonk) fn evaluate, T: TranscriptRead>( + pub(in crate::plonk) fn evaluate, T: TranscriptRead>( self, transcript: &mut T, ) -> Result, Error> { diff --git a/src/plonk/verifier.rs b/src/plonk/verifier.rs index eead6f5f..b255f747 100644 --- a/src/plonk/verifier.rs +++ b/src/plonk/verifier.rs @@ -7,16 +7,21 @@ use crate::poly::{ commitment::{Guard, Params, MSM}, multiopen::{self, VerifierQuery}, }; -use crate::transcript::{read_n_points, read_n_scalars, ChallengeSpace, TranscriptRead}; +use crate::transcript::{read_n_points, read_n_scalars, EncodedChallenge, TranscriptRead}; /// Returns a boolean indicating whether or not the proof is valid -pub fn verify_proof<'a, C: CurveAffine, S: ChallengeSpace, T: TranscriptRead>( +pub fn verify_proof< + 'a, + C: CurveAffine, + E: EncodedChallenge, + T: TranscriptRead, +>( params: &'a Params, vk: &VerifyingKey, msm: MSM<'a, C>, instance_commitments: &[&[C]], transcript: &mut T, -) -> Result, Error> { +) -> Result, Error> { // Check that instance_commitments matches the expected number of instance columns for instance_commitments in instance_commitments.iter() { if instance_commitments.len() != vk.cs.num_instance_columns { diff --git a/src/poly/commitment.rs b/src/poly/commitment.rs index dd03da90..74ee85e9 100644 --- a/src/poly/commitment.rs +++ b/src/poly/commitment.rs @@ -306,7 +306,7 @@ fn test_opening_proof() { use crate::arithmetic::{eval_polynomial, FieldExt}; use crate::pasta::{EpAffine, Fq}; use crate::transcript::{ - Blake2bRead, Blake2bWrite, ChallengeScalarEndo, Transcript, TranscriptRead, TranscriptWrite, + Blake2bRead, Blake2bWrite, Challenge255, Transcript, TranscriptRead, TranscriptWrite, }; let params = Params::::new(K); @@ -326,8 +326,7 @@ fn test_opening_proof() { let p = params.commit(&px, blind).to_affine(); - let mut transcript = - Blake2bWrite::, EpAffine, ChallengeScalarEndo>::init(vec![]); + let mut transcript = Blake2bWrite::, EpAffine, Challenge255>::init(vec![]); transcript.write_point(p).unwrap(); let x = transcript.squeeze_challenge_scalar::<()>(); // Evaluate the polynomial @@ -341,8 +340,7 @@ fn test_opening_proof() { }; // Verify the opening proof - let mut transcript = - Blake2bRead::<&[u8], EpAffine, ChallengeScalarEndo>::init(&proof[..]); + let mut transcript = Blake2bRead::<&[u8], EpAffine, Challenge255>::init(&proof[..]); let p_prime = transcript.read_point().unwrap(); assert_eq!(p, p_prime); let x_prime = transcript.squeeze_challenge_scalar::<()>(); diff --git a/src/poly/commitment/prover.rs b/src/poly/commitment/prover.rs index d039c301..cdc8daad 100644 --- a/src/poly/commitment/prover.rs +++ b/src/poly/commitment/prover.rs @@ -5,7 +5,7 @@ use super::{Blind, Params}; use crate::arithmetic::{ best_multiexp, compute_inner_product, eval_polynomial, parallelize, CurveAffine, FieldExt, }; -use crate::transcript::{ChallengeSpace, TranscriptWrite}; +use crate::transcript::{EncodedChallenge, TranscriptWrite}; use group::Curve; use std::io; @@ -23,7 +23,7 @@ use std::io; /// opening v, and the point x. It's probably also nice for the transcript /// to have seen the elliptic curve description and the URS, if you want to /// be rigorous. -pub fn create_proof, T: TranscriptWrite>( +pub fn create_proof, T: TranscriptWrite>( params: &Params, transcript: &mut T, px: &Polynomial, diff --git a/src/poly/commitment/verifier.rs b/src/poly/commitment/verifier.rs index 63e37b74..0448e75e 100644 --- a/src/poly/commitment/verifier.rs +++ b/src/poly/commitment/verifier.rs @@ -1,33 +1,36 @@ use ff::Field; use group::Curve; +use std::marker::PhantomData; use super::super::Error; use super::{Params, MSM}; -use crate::transcript::{ChallengeSpace, TranscriptRead}; +use crate::transcript::{EncodedChallenge, TranscriptRead}; use crate::arithmetic::{best_multiexp, BatchInvert, CurveAffine}; /// A guard returned by the verifier #[derive(Debug, Clone)] -pub struct Guard<'a, C: CurveAffine, S: ChallengeSpace> { +pub struct Guard<'a, C: CurveAffine, I, E: EncodedChallenge> { msm: MSM<'a, C>, neg_a: C::Scalar, challenges: Vec, - challenges_packed: Vec, + challenges_packed: Vec, + _marker: PhantomData, } /// An accumulator instance consisting of an evaluation claim and a proof. #[derive(Debug, Clone)] -pub struct Accumulator> { +pub struct Accumulator> { /// The claimed output of the linear-time polycommit opening protocol pub g: C, /// A vector of 128-bit challenges sampled by the verifier, to be used in /// computing g. - pub challenges_packed: Vec, + pub challenges_packed: Vec, + _marker: PhantomData, } -impl<'a, C: CurveAffine, S: ChallengeSpace> Guard<'a, C, S> { +impl<'a, C: CurveAffine, I, E: EncodedChallenge> Guard<'a, C, I, E> { /// Lets caller supply the challenges and obtain an MSM with updated /// scalars and points. pub fn use_challenges(mut self) -> MSM<'a, C> { @@ -40,12 +43,13 @@ impl<'a, C: CurveAffine, S: ChallengeSpace> Guard<'a, C, S> { /// Lets caller supply the purported G point and simply appends /// [-a] G to return an updated MSM. - pub fn use_g(mut self, g: C) -> (MSM<'a, C>, Accumulator) { + pub fn use_g(mut self, g: C) -> (MSM<'a, C>, Accumulator) { self.msm.append_term(self.neg_a, g); let accumulator = Accumulator { g, challenges_packed: self.challenges_packed, + _marker: PhantomData, }; (self.msm, accumulator) @@ -64,13 +68,19 @@ impl<'a, C: CurveAffine, S: ChallengeSpace> Guard<'a, C, S> { /// Checks to see if the proof represented within `transcript` is valid, and a /// point `x` that the polynomial commitment `P` opens purportedly to the value /// `v`. The provided `msm` should evaluate to the commitment `P` being opened. -pub fn verify_proof<'a, C: CurveAffine, S: ChallengeSpace, T: TranscriptRead>( +pub fn verify_proof< + 'a, + C: CurveAffine, + I, + E: EncodedChallenge, + T: TranscriptRead, +>( params: &'a Params, mut msm: MSM<'a, C>, transcript: &mut T, x: C::Scalar, v: C::Scalar, -) -> Result, Error> { +) -> Result, Error> { let k = params.k as usize; // P - [v] G_0 + S * iota @@ -91,7 +101,7 @@ pub fn verify_proof<'a, C: CurveAffine, S: ChallengeSpace, T: TranscriptRead< let r = transcript.read_point().map_err(|_| Error::OpeningError)?; let challenge_packed = transcript.squeeze_challenge(); - let challenge = *S::to_challenge_scalar::<()>(challenge_packed); + let challenge = *T::as_challenge_scalar::<()>(&challenge_packed); rounds.push(( l, @@ -108,7 +118,7 @@ pub fn verify_proof<'a, C: CurveAffine, S: ChallengeSpace, T: TranscriptRead< .batch_invert(); let mut challenges = Vec::with_capacity(k); - let mut challenges_packed: Vec = Vec::with_capacity(k); + let mut challenges_packed: Vec = Vec::with_capacity(k); for (l, r, challenge, challenge_inv, challenge_packed) in rounds { msm.append_term(challenge_inv, l); msm.append_term(challenge, r); @@ -143,6 +153,7 @@ pub fn verify_proof<'a, C: CurveAffine, S: ChallengeSpace, T: TranscriptRead< neg_a, challenges, challenges_packed, + _marker: PhantomData, }; Ok(guard) diff --git a/src/poly/multiopen.rs b/src/poly/multiopen.rs index 42207b92..78317db3 100644 --- a/src/poly/multiopen.rs +++ b/src/poly/multiopen.rs @@ -211,7 +211,7 @@ fn test_roundtrip() { use super::commitment::{Blind, Params}; use crate::arithmetic::{eval_polynomial, FieldExt}; use crate::pasta::{EqAffine, Fp}; - use crate::transcript::ChallengeScalarEndo; + use crate::transcript::Challenge255; const K: u32 = 4; @@ -245,8 +245,7 @@ fn test_roundtrip() { let bvx = eval_polynomial(&bx, x); let cvy = eval_polynomial(&cx, y); - let mut transcript = - crate::transcript::Blake2bWrite::<_, _, ChallengeScalarEndo>::init(vec![]); + let mut transcript = crate::transcript::Blake2bWrite::<_, _, Challenge255>::init(vec![]); create_proof( ¶ms, &mut transcript, @@ -272,8 +271,7 @@ fn test_roundtrip() { { let mut proof = &proof[..]; - let mut transcript = - crate::transcript::Blake2bRead::<_, _, ChallengeScalarEndo>::init(&mut proof); + let mut transcript = crate::transcript::Blake2bRead::<_, _, Challenge255>::init(&mut proof); let msm = params.empty_msm(); let guard = verify_proof( @@ -306,8 +304,7 @@ fn test_roundtrip() { { let mut proof = &proof[..]; - let mut transcript = - crate::transcript::Blake2bRead::<_, _, ChallengeScalarEndo>::init(&mut proof); + let mut transcript = crate::transcript::Blake2bRead::<_, _, Challenge255>::init(&mut proof); let msm = params.empty_msm(); let guard = verify_proof( diff --git a/src/poly/multiopen/prover.rs b/src/poly/multiopen/prover.rs index 75cf886b..4577f591 100644 --- a/src/poly/multiopen/prover.rs +++ b/src/poly/multiopen/prover.rs @@ -8,7 +8,7 @@ use super::{ }; use crate::arithmetic::{eval_polynomial, kate_division, CurveAffine, FieldExt}; -use crate::transcript::{ChallengeSpace, TranscriptWrite}; +use crate::transcript::{EncodedChallenge, TranscriptWrite}; use ff::Field; use group::Curve; @@ -24,7 +24,14 @@ struct CommitmentData { } /// Create a multi-opening proof -pub fn create_proof<'a, I, C: CurveAffine, S: ChallengeSpace, T: TranscriptWrite>( +pub fn create_proof< + 'a, + I, + IN, + C: CurveAffine, + E: EncodedChallenge, + T: TranscriptWrite, +>( params: &Params, transcript: &mut T, queries: I, diff --git a/src/poly/multiopen/verifier.rs b/src/poly/multiopen/verifier.rs index f33c99ec..7a1fcc87 100644 --- a/src/poly/multiopen/verifier.rs +++ b/src/poly/multiopen/verifier.rs @@ -9,7 +9,7 @@ use super::{ VerifierQuery, }; use crate::arithmetic::{eval_polynomial, lagrange_interpolate, CurveAffine, FieldExt}; -use crate::transcript::{ChallengeSpace, TranscriptRead}; +use crate::transcript::{EncodedChallenge, TranscriptRead}; #[derive(Debug, Clone)] struct CommitmentData { set_index: usize, @@ -18,12 +18,20 @@ struct CommitmentData { } /// Verify a multi-opening proof -pub fn verify_proof<'b, 'a: 'b, I, C: CurveAffine, S: ChallengeSpace, T: TranscriptRead>( +pub fn verify_proof< + 'b, + 'a: 'b, + I, + IN, + C: CurveAffine, + E: EncodedChallenge, + T: TranscriptRead, +>( params: &'a Params, transcript: &mut T, queries: I, mut msm: MSM<'a, C>, -) -> Result, Error> +) -> Result, Error> where I: IntoIterator> + Clone, { diff --git a/src/transcript.rs b/src/transcript.rs index 41365c16..ebe05749 100644 --- a/src/transcript.rs +++ b/src/transcript.rs @@ -11,14 +11,24 @@ use std::io::{self, Read, Write}; use std::marker::PhantomData; /// Generic transcript view (from either the prover or verifier's perspective) -pub trait Transcript> { - /// Squeeze a verifier challenge from the transcript. The length of the - /// challenge is determined by the `ChallengeSpace`. - fn squeeze_challenge(&mut self) -> S::Challenge; +pub trait Transcript> { + /// Squeeze an encoded verifier challenge from the transcript. + fn squeeze_challenge(&mut self) -> E; - /// Squeeze a challenge (in the scalar field) from the transcript. + /// Squeeze a typed challenge (in the scalar field) from the transcript. fn squeeze_challenge_scalar(&mut self) -> ChallengeScalar { - S::to_challenge_scalar(self.squeeze_challenge()) + ChallengeScalar { + inner: E::get_scalar(&self.squeeze_challenge()), + _marker: PhantomData, + } + } + + /// Cast an encoded challenge as a typed `ChallengeScalar`. + fn as_challenge_scalar(challenge: &E) -> ChallengeScalar { + ChallengeScalar { + inner: E::get_scalar(challenge), + _marker: PhantomData, + } } /// Writing the point to the transcript without writing it to the proof, @@ -32,7 +42,9 @@ pub trait Transcript> { /// Transcript view from the perspective of a verifier that has access to an /// input stream of data from the prover to the verifier. -pub trait TranscriptRead>: Transcript { +pub trait TranscriptRead>: + Transcript +{ /// Read a curve point from the prover. fn read_point(&mut self) -> io::Result; @@ -42,7 +54,9 @@ pub trait TranscriptRead>: Transcript /// Transcript view from the perspective of a prover that has access to an /// output stream of messages from the prover to the verifier. -pub trait TranscriptWrite>: Transcript { +pub trait TranscriptWrite>: + Transcript +{ /// Write a curve point to the proof and the transcript. fn write_point(&mut self, point: C) -> io::Result<()>; @@ -52,14 +66,14 @@ pub trait TranscriptWrite>: Transcript> { +pub struct Blake2bRead> { state: Blake2bState, reader: R, _marker: PhantomData, - _marker_s: PhantomData, + _marker_e: PhantomData, } -impl> Blake2bRead { +impl> Blake2bRead { /// Initialize a transcript given an input buffer and a key. pub fn init(reader: R) -> Self { Blake2bRead { @@ -69,12 +83,14 @@ impl> Blake2bRead { .to_state(), reader, _marker: PhantomData, - _marker_s: PhantomData, + _marker_e: PhantomData, } } } -impl> TranscriptRead for Blake2bRead { +impl> TranscriptRead + for Blake2bRead +{ fn read_point(&mut self) -> io::Result { let mut compressed = C::Repr::default(); self.reader.read_exact(compressed.as_mut())?; @@ -101,14 +117,14 @@ impl> TranscriptRead for Bla } } -impl> Transcript for Blake2bRead { - fn squeeze_challenge(&mut self) -> S::Challenge { +impl> Transcript + for Blake2bRead +{ + fn squeeze_challenge(&mut self) -> E { let hasher = self.state.clone(); - let mut result: [u8; 64] = hasher.finalize().as_bytes().try_into().unwrap(); - result[S::NUM_BYTES - 1] &= S::BYTE_MASK; - // self.state.update(&result[..S::NUM_BYTES]); + let result: [u8; 64] = hasher.finalize().as_bytes().try_into().unwrap(); self.state.update(&result[..]); - S::Challenge::new(&result[..S::NUM_BYTES]) + E::new(&result) } fn common_point(&mut self, point: C) -> io::Result<()> { @@ -133,14 +149,14 @@ impl> Transcript for Blake2b /// We will replace BLAKE2b with an algebraic hash function in a later version. #[derive(Debug, Clone)] -pub struct Blake2bWrite> { +pub struct Blake2bWrite> { state: Blake2bState, writer: W, _marker: PhantomData, - _marker_s: PhantomData, + _marker_e: PhantomData, } -impl> Blake2bWrite { +impl> Blake2bWrite { /// Initialize a transcript given an output buffer and a key. pub fn init(writer: W) -> Self { Blake2bWrite { @@ -150,7 +166,7 @@ impl> Blake2bWrite { .to_state(), writer, _marker: PhantomData, - _marker_s: PhantomData, + _marker_e: PhantomData, } } @@ -161,8 +177,8 @@ impl> Blake2bWrite { } } -impl> TranscriptWrite - for Blake2bWrite +impl> TranscriptWrite + for Blake2bWrite { fn write_point(&mut self, point: C) -> io::Result<()> { self.common_point(point)?; @@ -176,14 +192,14 @@ impl> TranscriptWrite } } -impl> Transcript for Blake2bWrite { - fn squeeze_challenge(&mut self) -> S::Challenge { +impl> Transcript + for Blake2bWrite +{ + fn squeeze_challenge(&mut self) -> E { let hasher = self.state.clone(); - let mut result: [u8; 64] = hasher.finalize().as_bytes().try_into().unwrap(); - result[S::NUM_BYTES - 1] &= S::BYTE_MASK; - // self.state.update(&result[..S::NUM_BYTES]); + let result: [u8; 64] = hasher.finalize().as_bytes().try_into().unwrap(); self.state.update(&result[..]); - S::Challenge::new(&result[..S::NUM_BYTES]) + E::new(&result) } fn common_point(&mut self, point: C) -> io::Result<()> { @@ -212,42 +228,6 @@ pub trait Challenge: Copy + Clone + std::fmt::Debug { fn new(challenge: &[u8]) -> Self; } -/// This is a 16-byte verifier challenge. -#[derive(Copy, Clone, Debug)] -pub struct Challenge16(pub(crate) [u8; 16]); - -impl Challenge for Challenge16 { - fn new(challenge: &[u8]) -> Self { - Self(challenge.try_into().unwrap()) - } -} - -impl std::ops::Deref for Challenge16 { - type Target = [u8; 16]; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -/// This is a 64-byte verifier challenge. -#[derive(Copy, Clone, Debug)] -pub struct Challenge64(pub(crate) [u8; 64]); - -impl Challenge for Challenge64 { - fn new(challenge: &[u8]) -> Self { - Self(challenge.try_into().unwrap()) - } -} - -impl std::ops::Deref for Challenge64 { - type Target = [u8; 64]; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - /// The scalar representation of a verifier challenge. /// /// The `Type` type can be used to scope the challenge to a specific context, or @@ -266,42 +246,41 @@ impl std::ops::Deref for ChallengeScalar { } } -/// The challenge space used to sample a scalar from a 512-bit challenge. -/// This protocol supports implementations for `ChallengeScalarEndo`, which -/// uses an endomorphism, and `ChallengeScalarFull`, which samples the -/// full-width field. -pub trait ChallengeSpace: Copy + Clone + std::fmt::Debug { - /// TODO - const NUM_BYTES: usize; - /// TODO - const BYTE_MASK: u8; - /// TODO - type Challenge: Challenge; +/// `EncodedChallenge` defines a challenge encoding where `I` is the input +/// that is used to derive the challenge encoding and `get_challenge` obtains +/// the _real_ `C::Scalar` that the challenge encoding represents. +pub trait EncodedChallenge { + /// Get an encoded challenge from a given input challenge. + fn new(challenge_input: &I) -> Self; - /// Derive a scalar from a challenge in a certain challenge space. - fn to_challenge_scalar(challenge: Self::Challenge) -> ChallengeScalar; + /// Get a scalar field element from an encoded challenge. + fn get_scalar(challenge: &Self) -> C::Scalar; } /// The scalar challenge space that applies the mapping of Algorithm 1 from the /// [Halo](https://eprint.iacr.org/2019/1021) paper. #[derive(Copy, Clone, Debug)] -pub struct ChallengeScalarEndo { - _marker: PhantomData, +pub struct Challenge128(u128); + +impl std::ops::Deref for Challenge128 { + type Target = u128; + + fn deref(&self) -> &Self::Target { + &self.0 + } } -impl ChallengeSpace for ChallengeScalarEndo { - const NUM_BYTES: usize = 16; - const BYTE_MASK: u8 = 0b11111111; - type Challenge = Challenge16; +impl EncodedChallenge for Challenge128 { + fn new(challenge_input: &C::Base) -> Self { + Challenge128(challenge_input.get_lower_128()) + } - fn to_challenge_scalar(challenge: Self::Challenge) -> ChallengeScalar { + fn get_scalar(challenge: &Self) -> C::Scalar { let mut acc = (C::Scalar::ZETA + &C::Scalar::one()).double(); - let challenge: u128 = u128::from_le_bytes(challenge.0); - for i in (0..64).rev() { - let should_negate = ((challenge >> ((i << 1) + 1)) & 1) == 1; - let should_endo = ((challenge >> (i << 1)) & 1) == 1; + let should_negate = ((challenge.0 >> ((i << 1) + 1)) & 1) == 1; + let should_endo = ((challenge.0 >> (i << 1)) & 1) == 1; let q = if should_negate { -C::Scalar::one() @@ -312,40 +291,49 @@ impl ChallengeSpace for ChallengeScalarEndo { acc = acc + &q + &acc; } - ChallengeScalar { - inner: acc, - _marker: PhantomData, - } + acc } } /// The scalar challenge space that samples from the full-width field. #[derive(Copy, Clone, Debug)] -pub struct ChallengeScalarFull { - _marker: PhantomData, -} +pub struct Challenge255([u8; 32]); -impl ChallengeSpace for ChallengeScalarFull { - const NUM_BYTES: usize = 64; - const BYTE_MASK: u8 = 0b111111; - type Challenge = Challenge64; +impl std::ops::Deref for Challenge255 { + type Target = [u8; 32]; - fn to_challenge_scalar(challenge: Self::Challenge) -> ChallengeScalar { - ChallengeScalar { - inner: C::Scalar::from_bytes_wide(&challenge.0), - _marker: PhantomData, - } + fn deref(&self) -> &Self::Target { + &self.0 } } -pub(crate) fn read_n_points, T: TranscriptRead>( +impl EncodedChallenge for Challenge255 { + fn new(challenge_input: &[u8; 64]) -> Self { + Challenge255(C::Scalar::from_bytes_wide(challenge_input).to_bytes()) + } + fn get_scalar(challenge: &Self) -> C::Scalar { + C::Scalar::from_bytes(&challenge.0).unwrap() + } +} + +pub(crate) fn read_n_points< + C: CurveAffine, + I, + E: EncodedChallenge, + T: TranscriptRead, +>( transcript: &mut T, n: usize, ) -> io::Result> { (0..n).map(|_| transcript.read_point()).collect() } -pub(crate) fn read_n_scalars, T: TranscriptRead>( +pub(crate) fn read_n_scalars< + C: CurveAffine, + I, + E: EncodedChallenge, + T: TranscriptRead, +>( transcript: &mut T, n: usize, ) -> io::Result> { diff --git a/tests/plonk_api.rs b/tests/plonk_api.rs index cd2d80df..b478a091 100644 --- a/tests/plonk_api.rs +++ b/tests/plonk_api.rs @@ -13,7 +13,7 @@ use halo2::poly::{ commitment::{Blind, Params}, Rotation, }; -use halo2::transcript::{Blake2bRead, Blake2bWrite, ChallengeScalarEndo}; +use halo2::transcript::{Blake2bRead, Blake2bWrite, Challenge255}; use std::marker::PhantomData; #[test] @@ -397,7 +397,7 @@ fn plonk_api() { assert_eq!(prover.verify(), Ok(())); for _ in 0..10 { - let mut transcript = Blake2bWrite::<_, _, ChallengeScalarEndo>::init(vec![]); + let mut transcript = Blake2bWrite::<_, _, Challenge255>::init(vec![]); // Create a proof create_proof( ¶ms, @@ -412,7 +412,7 @@ fn plonk_api() { let pubinput_slice = &[pubinput]; let pubinput_slice_copy = &[pubinput]; let msm = params.empty_msm(); - let mut transcript = Blake2bRead::<_, _, ChallengeScalarEndo>::init(&proof[..]); + let mut transcript = Blake2bRead::<_, _, Challenge255>::init(&proof[..]); let guard = verify_proof( ¶ms, pk.get_vk(), @@ -432,7 +432,7 @@ fn plonk_api() { } let msm = guard.clone().use_challenges(); assert!(msm.clone().eval()); - let mut transcript = Blake2bRead::<_, _, ChallengeScalarEndo>::init(&proof[..]); + let mut transcript = Blake2bRead::<_, _, Challenge255>::init(&proof[..]); let mut vk_buffer = vec![]; pk.get_vk().write(&mut vk_buffer).unwrap(); let vk = VerifyingKey::::read::<_, MyCircuit>(&mut &vk_buffer[..], ¶ms)