mirror of https://github.com/zcash/halo2.git
Merge pull request #242 from zcash/challenge-space
Add support for full-field challenge space
This commit is contained in:
commit
870a2f1e8a
|
@ -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};
|
||||
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::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::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,7 +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::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());
|
||||
|
|
|
@ -8,7 +8,7 @@ use halo2::{
|
|||
Error, VerifyingKey,
|
||||
},
|
||||
poly::commitment::Params,
|
||||
transcript::{Blake2bRead, Blake2bWrite},
|
||||
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::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<u8> = transcript.finalize();
|
||||
|
@ -145,7 +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::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());
|
||||
|
|
|
@ -12,7 +12,7 @@ use crate::poly::{
|
|||
commitment::Params, Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff,
|
||||
PinnedEvaluationDomain, Polynomial,
|
||||
};
|
||||
use crate::transcript::{ChallengeScalar, Transcript};
|
||||
use crate::transcript::{ChallengeScalar, EncodedChallenge, Transcript};
|
||||
|
||||
mod circuit;
|
||||
mod keygen;
|
||||
|
@ -79,7 +79,10 @@ impl<C: CurveAffine> VerifyingKey<C> {
|
|||
}
|
||||
|
||||
/// Hashes a verification key into a transcript.
|
||||
pub fn hash_into<T: Transcript<C>>(&self, transcript: &mut T) -> io::Result<()> {
|
||||
pub fn hash_into<E: EncodedChallenge<C>, T: Transcript<C, E>>(
|
||||
&self,
|
||||
transcript: &mut T,
|
||||
) -> io::Result<()> {
|
||||
let mut hasher = Blake2bParams::new()
|
||||
.hash_length(64)
|
||||
.personal(b"Halo2-Verify-Key")
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
multiopen::ProverQuery,
|
||||
Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial, Rotation,
|
||||
},
|
||||
transcript::TranscriptWrite,
|
||||
transcript::{EncodedChallenge, TranscriptWrite},
|
||||
};
|
||||
use ff::Field;
|
||||
use group::Curve;
|
||||
|
@ -72,7 +72,12 @@ impl<F: FieldExt> Argument<F> {
|
|||
/// - constructs Permuted<C> struct using permuted_input_value = A', and
|
||||
/// permuted_table_expression = S'.
|
||||
/// The Permuted<C> struct is used to update the Lookup, and is then returned.
|
||||
pub(in crate::plonk) fn commit_permuted<'a, C, T: TranscriptWrite<C>>(
|
||||
pub(in crate::plonk) fn commit_permuted<
|
||||
'a,
|
||||
C,
|
||||
E: EncodedChallenge<C>,
|
||||
T: TranscriptWrite<C, E>,
|
||||
>(
|
||||
&self,
|
||||
pk: &ProvingKey<C>,
|
||||
params: &Params<C>,
|
||||
|
@ -244,7 +249,7 @@ impl<C: CurveAffine> Permuted<C> {
|
|||
/// grand product polynomial over the lookup. The grand product polynomial
|
||||
/// is used to populate the Product<C> struct. The Product<C> struct is
|
||||
/// added to the Lookup and finally returned by the method.
|
||||
pub(in crate::plonk) fn commit_product<T: TranscriptWrite<C>>(
|
||||
pub(in crate::plonk) fn commit_product<E: EncodedChallenge<C>, T: TranscriptWrite<C, E>>(
|
||||
self,
|
||||
pk: &ProvingKey<C>,
|
||||
params: &Params<C>,
|
||||
|
@ -488,7 +493,7 @@ impl<'a, C: CurveAffine> Committed<C> {
|
|||
}
|
||||
|
||||
impl<C: CurveAffine> Constructed<C> {
|
||||
pub(in crate::plonk) fn evaluate<T: TranscriptWrite<C>>(
|
||||
pub(in crate::plonk) fn evaluate<E: EncodedChallenge<C>, T: TranscriptWrite<C, E>>(
|
||||
self,
|
||||
pk: &ProvingKey<C>,
|
||||
x: ChallengeX<C>,
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
use std::iter;
|
||||
|
||||
use super::super::circuit::Expression;
|
||||
use super::super::{
|
||||
circuit::Expression, ChallengeBeta, ChallengeGamma, ChallengeTheta, ChallengeX,
|
||||
};
|
||||
use super::Argument;
|
||||
use crate::{
|
||||
arithmetic::{CurveAffine, FieldExt},
|
||||
plonk::{ChallengeBeta, ChallengeGamma, ChallengeTheta, ChallengeX, Error, VerifyingKey},
|
||||
plonk::{Error, VerifyingKey},
|
||||
poly::{multiopen::VerifierQuery, Rotation},
|
||||
transcript::TranscriptRead,
|
||||
transcript::{EncodedChallenge, TranscriptRead},
|
||||
};
|
||||
use ff::Field;
|
||||
|
||||
|
@ -30,7 +32,11 @@ pub struct Evaluated<C: CurveAffine> {
|
|||
}
|
||||
|
||||
impl<F: FieldExt> Argument<F> {
|
||||
pub(in crate::plonk) fn read_permuted_commitments<C: CurveAffine, T: TranscriptRead<C>>(
|
||||
pub(in crate::plonk) fn read_permuted_commitments<
|
||||
C: CurveAffine,
|
||||
E: EncodedChallenge<C>,
|
||||
T: TranscriptRead<C, E>,
|
||||
>(
|
||||
&self,
|
||||
transcript: &mut T,
|
||||
) -> Result<PermutationCommitments<C>, Error> {
|
||||
|
@ -49,7 +55,10 @@ impl<F: FieldExt> Argument<F> {
|
|||
}
|
||||
|
||||
impl<C: CurveAffine> PermutationCommitments<C> {
|
||||
pub(in crate::plonk) fn read_product_commitment<T: TranscriptRead<C>>(
|
||||
pub(in crate::plonk) fn read_product_commitment<
|
||||
E: EncodedChallenge<C>,
|
||||
T: TranscriptRead<C, E>,
|
||||
>(
|
||||
self,
|
||||
transcript: &mut T,
|
||||
) -> Result<Committed<C>, Error> {
|
||||
|
@ -65,7 +74,7 @@ impl<C: CurveAffine> PermutationCommitments<C> {
|
|||
}
|
||||
|
||||
impl<C: CurveAffine> Committed<C> {
|
||||
pub(crate) fn evaluate<T: TranscriptRead<C>>(
|
||||
pub(crate) fn evaluate<E: EncodedChallenge<C>, T: TranscriptRead<C, E>>(
|
||||
self,
|
||||
transcript: &mut T,
|
||||
) -> Result<Evaluated<C>, Error> {
|
||||
|
|
|
@ -2,17 +2,17 @@ use ff::Field;
|
|||
use group::Curve;
|
||||
use std::iter;
|
||||
|
||||
use super::super::circuit::Any;
|
||||
use super::super::{circuit::Any, ChallengeBeta, ChallengeGamma, ChallengeX};
|
||||
use super::{Argument, ProvingKey};
|
||||
use crate::{
|
||||
arithmetic::{eval_polynomial, parallelize, BatchInvert, CurveAffine, FieldExt},
|
||||
plonk::{self, ChallengeBeta, ChallengeGamma, ChallengeX, Error},
|
||||
plonk::{self, Error},
|
||||
poly::{
|
||||
commitment::{Blind, Params},
|
||||
multiopen::ProverQuery,
|
||||
Coeff, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial, Rotation,
|
||||
},
|
||||
transcript::TranscriptWrite,
|
||||
transcript::{EncodedChallenge, TranscriptWrite},
|
||||
};
|
||||
|
||||
pub(crate) struct Committed<C: CurveAffine> {
|
||||
|
@ -32,7 +32,11 @@ pub(crate) struct Evaluated<C: CurveAffine> {
|
|||
}
|
||||
|
||||
impl Argument {
|
||||
pub(in crate::plonk) fn commit<C: CurveAffine, T: TranscriptWrite<C>>(
|
||||
pub(in crate::plonk) fn commit<
|
||||
C: CurveAffine,
|
||||
E: EncodedChallenge<C>,
|
||||
T: TranscriptWrite<C, E>,
|
||||
>(
|
||||
&self,
|
||||
params: &Params<C>,
|
||||
pk: &plonk::ProvingKey<C>,
|
||||
|
@ -253,7 +257,7 @@ impl<C: CurveAffine> super::ProvingKey<C> {
|
|||
}
|
||||
|
||||
impl<C: CurveAffine> Constructed<C> {
|
||||
pub(in crate::plonk) fn evaluate<T: TranscriptWrite<C>>(
|
||||
pub(in crate::plonk) fn evaluate<E: EncodedChallenge<C>, T: TranscriptWrite<C, E>>(
|
||||
self,
|
||||
pk: &plonk::ProvingKey<C>,
|
||||
pkey: &ProvingKey<C>,
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use ff::Field;
|
||||
use std::iter;
|
||||
|
||||
use super::super::circuit::Any;
|
||||
use super::super::{circuit::Any, ChallengeBeta, ChallengeGamma, ChallengeX};
|
||||
use super::{Argument, VerifyingKey};
|
||||
use crate::{
|
||||
arithmetic::{CurveAffine, FieldExt},
|
||||
plonk::{self, ChallengeBeta, ChallengeGamma, ChallengeX, Error},
|
||||
plonk::{self, Error},
|
||||
poly::{multiopen::VerifierQuery, Rotation},
|
||||
transcript::TranscriptRead,
|
||||
transcript::{EncodedChallenge, TranscriptRead},
|
||||
};
|
||||
|
||||
pub struct Committed<C: CurveAffine> {
|
||||
|
@ -22,7 +22,11 @@ pub struct Evaluated<C: CurveAffine> {
|
|||
}
|
||||
|
||||
impl Argument {
|
||||
pub(crate) fn read_product_commitment<C: CurveAffine, T: TranscriptRead<C>>(
|
||||
pub(crate) fn read_product_commitment<
|
||||
C: CurveAffine,
|
||||
E: EncodedChallenge<C>,
|
||||
T: TranscriptRead<C, E>,
|
||||
>(
|
||||
&self,
|
||||
transcript: &mut T,
|
||||
) -> Result<Committed<C>, Error> {
|
||||
|
@ -37,7 +41,7 @@ impl Argument {
|
|||
}
|
||||
|
||||
impl<C: CurveAffine> Committed<C> {
|
||||
pub(crate) fn evaluate<T: TranscriptRead<C>>(
|
||||
pub(crate) fn evaluate<E: EncodedChallenge<C>, T: TranscriptRead<C, E>>(
|
||||
self,
|
||||
vkey: &VerifyingKey<C>,
|
||||
transcript: &mut T,
|
||||
|
|
|
@ -13,12 +13,17 @@ use crate::poly::{
|
|||
multiopen::{self, ProverQuery},
|
||||
Coeff, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial,
|
||||
};
|
||||
use crate::transcript::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, T: TranscriptWrite<C>, ConcreteCircuit: Circuit<C::Scalar>>(
|
||||
pub fn create_proof<
|
||||
C: CurveAffine,
|
||||
E: EncodedChallenge<C>,
|
||||
T: TranscriptWrite<C, E>,
|
||||
ConcreteCircuit: Circuit<C::Scalar>,
|
||||
>(
|
||||
params: &Params<C>,
|
||||
pk: &ProvingKey<C>,
|
||||
circuits: &[ConcreteCircuit],
|
||||
|
@ -241,7 +246,7 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circ
|
|||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
// Sample theta challenge for keeping lookup columns linearly independent
|
||||
let theta = ChallengeTheta::get(transcript);
|
||||
let theta: ChallengeTheta<_> = transcript.squeeze_challenge_scalar();
|
||||
|
||||
let lookups: Vec<Vec<lookup::prover::Permuted<C>>> = instance
|
||||
.iter()
|
||||
|
@ -272,10 +277,10 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circ
|
|||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
// Sample beta challenge
|
||||
let beta = ChallengeBeta::get(transcript);
|
||||
let beta: ChallengeBeta<_> = transcript.squeeze_challenge_scalar();
|
||||
|
||||
// Sample gamma challenge
|
||||
let gamma = ChallengeGamma::get(transcript);
|
||||
let gamma: ChallengeGamma<_> = transcript.squeeze_challenge_scalar();
|
||||
|
||||
let permutations: Vec<Vec<permutation::prover::Committed<C>>> = instance
|
||||
.iter()
|
||||
|
@ -316,7 +321,7 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circ
|
|||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
// Obtain challenge for keeping all separate gates linearly independent
|
||||
let y = ChallengeY::get(transcript);
|
||||
let y: ChallengeY<_> = transcript.squeeze_challenge_scalar();
|
||||
|
||||
let (permutations, permutation_expressions): (Vec<Vec<_>>, Vec<Vec<_>>) = permutations
|
||||
.into_iter()
|
||||
|
@ -389,7 +394,7 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>, ConcreteCircuit: Circ
|
|||
// Construct the vanishing argument
|
||||
let vanishing = vanishing::Argument::construct(params, domain, expressions, y, transcript)?;
|
||||
|
||||
let x = ChallengeX::get(transcript);
|
||||
let x: ChallengeX<_> = transcript.squeeze_challenge_scalar();
|
||||
|
||||
// Compute and hash instance evals for each circuit instance
|
||||
for instance in instance.iter() {
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
use group::Curve;
|
||||
|
||||
use super::super::{ChallengeX, ChallengeY};
|
||||
use super::Argument;
|
||||
use crate::{
|
||||
arithmetic::{eval_polynomial, CurveAffine, FieldExt},
|
||||
plonk::{ChallengeX, ChallengeY, Error},
|
||||
plonk::Error,
|
||||
poly::{
|
||||
commitment::{Blind, Params},
|
||||
multiopen::ProverQuery,
|
||||
Coeff, EvaluationDomain, ExtendedLagrangeCoeff, Polynomial,
|
||||
},
|
||||
transcript::TranscriptWrite,
|
||||
transcript::{EncodedChallenge, TranscriptWrite},
|
||||
};
|
||||
|
||||
pub(in crate::plonk) struct Constructed<C: CurveAffine> {
|
||||
|
@ -22,7 +23,7 @@ pub(in crate::plonk) struct Evaluated<C: CurveAffine> {
|
|||
}
|
||||
|
||||
impl<C: CurveAffine> Argument<C> {
|
||||
pub(in crate::plonk) fn construct<T: TranscriptWrite<C>>(
|
||||
pub(in crate::plonk) fn construct<E: EncodedChallenge<C>, T: TranscriptWrite<C, E>>(
|
||||
params: &Params<C>,
|
||||
domain: &EvaluationDomain<C::Scalar>,
|
||||
expressions: impl Iterator<Item = Polynomial<C::Scalar, ExtendedLagrangeCoeff>>,
|
||||
|
@ -68,7 +69,7 @@ impl<C: CurveAffine> Argument<C> {
|
|||
}
|
||||
|
||||
impl<C: CurveAffine> Constructed<C> {
|
||||
pub(in crate::plonk) fn evaluate<T: TranscriptWrite<C>>(
|
||||
pub(in crate::plonk) fn evaluate<E: EncodedChallenge<C>, T: TranscriptWrite<C, E>>(
|
||||
self,
|
||||
x: ChallengeX<C>,
|
||||
transcript: &mut T,
|
||||
|
|
|
@ -2,11 +2,12 @@ use ff::Field;
|
|||
|
||||
use crate::{
|
||||
arithmetic::CurveAffine,
|
||||
plonk::{ChallengeX, ChallengeY, Error, VerifyingKey},
|
||||
plonk::{Error, VerifyingKey},
|
||||
poly::multiopen::VerifierQuery,
|
||||
transcript::{read_n_points, read_n_scalars, TranscriptRead},
|
||||
transcript::{read_n_points, read_n_scalars, EncodedChallenge, TranscriptRead},
|
||||
};
|
||||
|
||||
use super::super::{ChallengeX, ChallengeY};
|
||||
use super::Argument;
|
||||
|
||||
pub struct Committed<C: CurveAffine> {
|
||||
|
@ -19,7 +20,7 @@ pub struct Evaluated<C: CurveAffine> {
|
|||
}
|
||||
|
||||
impl<C: CurveAffine> Argument<C> {
|
||||
pub(in crate::plonk) fn read_commitments<T: TranscriptRead<C>>(
|
||||
pub(in crate::plonk) fn read_commitments<E: EncodedChallenge<C>, T: TranscriptRead<C, E>>(
|
||||
vk: &VerifyingKey<C>,
|
||||
transcript: &mut T,
|
||||
) -> Result<Committed<C>, Error> {
|
||||
|
@ -32,7 +33,7 @@ impl<C: CurveAffine> Argument<C> {
|
|||
}
|
||||
|
||||
impl<C: CurveAffine> Committed<C> {
|
||||
pub(in crate::plonk) fn evaluate<T: TranscriptRead<C>>(
|
||||
pub(in crate::plonk) fn evaluate<E: EncodedChallenge<C>, T: TranscriptRead<C, E>>(
|
||||
self,
|
||||
transcript: &mut T,
|
||||
) -> Result<Evaluated<C>, Error> {
|
||||
|
|
|
@ -10,16 +10,16 @@ use crate::poly::{
|
|||
commitment::{Guard, Params, MSM},
|
||||
multiopen::{self, VerifierQuery},
|
||||
};
|
||||
use crate::transcript::{read_n_points, read_n_scalars, 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, T: TranscriptRead<C>>(
|
||||
pub fn verify_proof<'a, C: CurveAffine, E: EncodedChallenge<C>, T: TranscriptRead<C, E>>(
|
||||
params: &'a Params<C>,
|
||||
vk: &VerifyingKey<C>,
|
||||
msm: MSM<'a, C>,
|
||||
instance_commitments: &[&[C]],
|
||||
transcript: &mut T,
|
||||
) -> Result<Guard<'a, C>, Error> {
|
||||
) -> Result<Guard<'a, C, E>, 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 {
|
||||
|
@ -50,7 +50,7 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
|||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
// Sample theta challenge for keeping lookup columns linearly independent
|
||||
let theta = ChallengeTheta::get(transcript);
|
||||
let theta: ChallengeTheta<_> = transcript.squeeze_challenge_scalar();
|
||||
|
||||
let lookups_permuted = (0..num_proofs)
|
||||
.map(|_| -> Result<Vec<_>, _> {
|
||||
|
@ -64,10 +64,10 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
|||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
// Sample beta challenge
|
||||
let beta = ChallengeBeta::get(transcript);
|
||||
let beta: ChallengeBeta<_> = transcript.squeeze_challenge_scalar();
|
||||
|
||||
// Sample gamma challenge
|
||||
let gamma = ChallengeGamma::get(transcript);
|
||||
let gamma: ChallengeGamma<_> = transcript.squeeze_challenge_scalar();
|
||||
|
||||
let permutations_committed = (0..num_proofs)
|
||||
.map(|_| -> Result<Vec<_>, _> {
|
||||
|
@ -92,14 +92,12 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
|||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
// Sample y challenge, which keeps the gates linearly independent.
|
||||
let y = ChallengeY::get(transcript);
|
||||
|
||||
let y: ChallengeY<_> = transcript.squeeze_challenge_scalar();
|
||||
let vanishing = vanishing::Argument::read_commitments(vk, transcript)?;
|
||||
|
||||
// Sample x challenge, which is used to ensure the circuit is
|
||||
// satisfied with high probability.
|
||||
let x = ChallengeX::get(transcript);
|
||||
|
||||
let x: ChallengeX<_> = transcript.squeeze_challenge_scalar();
|
||||
let instance_evals = (0..num_proofs)
|
||||
.map(|_| -> Result<Vec<_>, _> {
|
||||
read_n_scalars(transcript, vk.cs.instance_queries.len())
|
||||
|
|
|
@ -306,7 +306,7 @@ fn test_opening_proof() {
|
|||
use crate::arithmetic::{eval_polynomial, FieldExt};
|
||||
use crate::pasta::{EpAffine, Fq};
|
||||
use crate::transcript::{
|
||||
Blake2bRead, Blake2bWrite, ChallengeScalar, Transcript, TranscriptRead, TranscriptWrite,
|
||||
Blake2bRead, Blake2bWrite, Challenge255, Transcript, TranscriptRead, TranscriptWrite,
|
||||
};
|
||||
|
||||
let params = Params::<EpAffine>::new(K);
|
||||
|
@ -326,9 +326,9 @@ fn test_opening_proof() {
|
|||
|
||||
let p = params.commit(&px, blind).to_affine();
|
||||
|
||||
let mut transcript = Blake2bWrite::<Vec<u8>, EpAffine>::init(vec![]);
|
||||
let mut transcript = Blake2bWrite::<Vec<u8>, EpAffine, Challenge255<EpAffine>>::init(vec![]);
|
||||
transcript.write_point(p).unwrap();
|
||||
let x = ChallengeScalar::<_, ()>::get(&mut transcript);
|
||||
let x = transcript.squeeze_challenge_scalar::<()>();
|
||||
// Evaluate the polynomial
|
||||
let v = eval_polynomial(&px, *x);
|
||||
transcript.write_scalar(v).unwrap();
|
||||
|
@ -340,10 +340,10 @@ fn test_opening_proof() {
|
|||
};
|
||||
|
||||
// Verify the opening proof
|
||||
let mut transcript = Blake2bRead::<&[u8], EpAffine>::init(&proof[..]);
|
||||
let mut transcript = Blake2bRead::<&[u8], EpAffine, Challenge255<EpAffine>>::init(&proof[..]);
|
||||
let p_prime = transcript.read_point().unwrap();
|
||||
assert_eq!(p, p_prime);
|
||||
let x_prime = ChallengeScalar::<_, ()>::get(&mut transcript);
|
||||
let x_prime = transcript.squeeze_challenge_scalar::<()>();
|
||||
assert_eq!(*x, *x_prime);
|
||||
let v_prime = transcript.read_scalar().unwrap();
|
||||
assert_eq!(v, v_prime);
|
||||
|
@ -352,7 +352,7 @@ fn test_opening_proof() {
|
|||
commitment_msm.append_term(Field::one(), p);
|
||||
let guard = verify_proof(¶ms, commitment_msm, &mut transcript, *x, v).unwrap();
|
||||
let ch_verifier = transcript.squeeze_challenge();
|
||||
assert_eq!(ch_prover, ch_verifier);
|
||||
assert_eq!(*ch_prover, *ch_verifier);
|
||||
|
||||
// Test guard behavior prior to checking another proof
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@ use super::{Blind, Params};
|
|||
use crate::arithmetic::{
|
||||
best_multiexp, compute_inner_product, eval_polynomial, parallelize, CurveAffine, FieldExt,
|
||||
};
|
||||
use crate::transcript::{Challenge, ChallengeScalar, 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<C: CurveAffine, T: TranscriptWrite<C>>(
|
||||
pub fn create_proof<C: CurveAffine, E: EncodedChallenge<C>, T: TranscriptWrite<C, E>>(
|
||||
params: &Params<C>,
|
||||
transcript: &mut T,
|
||||
px: &Polynomial<C::Scalar, Coeff>,
|
||||
|
@ -53,11 +53,11 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>>(
|
|||
// Challenge that will ensure that the prover cannot change P but can only
|
||||
// witness a random polynomial commitment that agrees with P at x, with high
|
||||
// probability.
|
||||
let iota = *ChallengeScalar::<C, ()>::get(transcript);
|
||||
let iota = *transcript.squeeze_challenge_scalar::<()>();
|
||||
|
||||
// Challenge that ensures that the prover did not interfere with the U term
|
||||
// in their commitments.
|
||||
let z = *ChallengeScalar::<C, ()>::get(transcript);
|
||||
let z = *transcript.squeeze_challenge_scalar::<()>();
|
||||
|
||||
// We'll be opening `s_poly_commitment * iota + P - [v] G_0` to ensure it
|
||||
// has a root at zero.
|
||||
|
@ -110,8 +110,7 @@ pub fn create_proof<C: CurveAffine, T: TranscriptWrite<C>>(
|
|||
transcript.write_point(l)?;
|
||||
transcript.write_point(r)?;
|
||||
|
||||
let challenge_packed = Challenge::get(transcript);
|
||||
let challenge = *ChallengeScalar::<C, ()>::from(challenge_packed);
|
||||
let challenge = *transcript.squeeze_challenge_scalar::<()>();
|
||||
let challenge_inv = challenge.invert().unwrap(); // TODO, bubble this up
|
||||
|
||||
// Collapse `a` and `b`.
|
||||
|
|
|
@ -3,31 +3,31 @@ use group::Curve;
|
|||
|
||||
use super::super::Error;
|
||||
use super::{Params, MSM};
|
||||
use crate::transcript::{Challenge, ChallengeScalar, 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> {
|
||||
pub struct Guard<'a, C: CurveAffine, E: EncodedChallenge<C>> {
|
||||
msm: MSM<'a, C>,
|
||||
neg_a: C::Scalar,
|
||||
challenges: Vec<C::Scalar>,
|
||||
challenges_packed: Vec<Challenge>,
|
||||
challenges_packed: Vec<E>,
|
||||
}
|
||||
|
||||
/// An accumulator instance consisting of an evaluation claim and a proof.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Accumulator<C: CurveAffine> {
|
||||
pub struct Accumulator<C: CurveAffine, E: EncodedChallenge<C>> {
|
||||
/// 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<Challenge>,
|
||||
pub challenges_packed: Vec<E>,
|
||||
}
|
||||
|
||||
impl<'a, C: CurveAffine> Guard<'a, C> {
|
||||
impl<'a, C: CurveAffine, E: EncodedChallenge<C>> Guard<'a, C, 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,7 +40,7 @@ impl<'a, C: CurveAffine> Guard<'a, C> {
|
|||
|
||||
/// 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<C>) {
|
||||
pub fn use_g(mut self, g: C) -> (MSM<'a, C>, Accumulator<C, E>) {
|
||||
self.msm.append_term(self.neg_a, g);
|
||||
|
||||
let accumulator = Accumulator {
|
||||
|
@ -64,13 +64,13 @@ impl<'a, C: CurveAffine> Guard<'a, C> {
|
|||
/// 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, T: TranscriptRead<C>>(
|
||||
pub fn verify_proof<'a, C: CurveAffine, E: EncodedChallenge<C>, T: TranscriptRead<C, E>>(
|
||||
params: &'a Params<C>,
|
||||
mut msm: MSM<'a, C>,
|
||||
transcript: &mut T,
|
||||
x: C::Scalar,
|
||||
v: C::Scalar,
|
||||
) -> Result<Guard<'a, C>, Error> {
|
||||
) -> Result<Guard<'a, C, E>, Error> {
|
||||
let k = params.k as usize;
|
||||
|
||||
// P - [v] G_0 + S * iota
|
||||
|
@ -78,10 +78,11 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
|||
msm.add_constant_term(-v);
|
||||
let s_poly_commitment = transcript.read_point().map_err(|_| Error::OpeningError)?;
|
||||
|
||||
let iota = *ChallengeScalar::<C, ()>::get(transcript);
|
||||
let iota = *transcript.squeeze_challenge_scalar::<()>();
|
||||
|
||||
msm.append_term(iota, s_poly_commitment);
|
||||
|
||||
let z = *ChallengeScalar::<C, ()>::get(transcript);
|
||||
let z = *transcript.squeeze_challenge_scalar::<()>();
|
||||
|
||||
let mut rounds = vec![];
|
||||
for _ in 0..k {
|
||||
|
@ -89,8 +90,8 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
|||
let l = transcript.read_point().map_err(|_| Error::OpeningError)?;
|
||||
let r = transcript.read_point().map_err(|_| Error::OpeningError)?;
|
||||
|
||||
let challenge_packed = Challenge::get(transcript);
|
||||
let challenge = *ChallengeScalar::<C, ()>::from(challenge_packed);
|
||||
let challenge_packed = transcript.squeeze_challenge();
|
||||
let challenge = *challenge_packed.as_challenge_scalar::<()>();
|
||||
|
||||
rounds.push((
|
||||
l,
|
||||
|
@ -107,7 +108,7 @@ pub fn verify_proof<'a, C: CurveAffine, T: TranscriptRead<C>>(
|
|||
.batch_invert();
|
||||
|
||||
let mut challenges = Vec::with_capacity(k);
|
||||
let mut challenges_packed: Vec<Challenge> = Vec::with_capacity(k);
|
||||
let mut challenges_packed: Vec<E> = 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);
|
||||
|
|
|
@ -211,6 +211,7 @@ fn test_roundtrip() {
|
|||
use super::commitment::{Blind, Params};
|
||||
use crate::arithmetic::{eval_polynomial, FieldExt};
|
||||
use crate::pasta::{EqAffine, Fp};
|
||||
use crate::transcript::Challenge255;
|
||||
|
||||
const K: u32 = 4;
|
||||
|
||||
|
@ -244,7 +245,7 @@ fn test_roundtrip() {
|
|||
let bvx = eval_polynomial(&bx, x);
|
||||
let cvy = eval_polynomial(&cx, y);
|
||||
|
||||
let mut transcript = crate::transcript::Blake2bWrite::init(vec![]);
|
||||
let mut transcript = crate::transcript::Blake2bWrite::<_, _, Challenge255<_>>::init(vec![]);
|
||||
create_proof(
|
||||
¶ms,
|
||||
&mut transcript,
|
||||
|
@ -270,7 +271,8 @@ fn test_roundtrip() {
|
|||
|
||||
{
|
||||
let mut proof = &proof[..];
|
||||
let mut transcript = crate::transcript::Blake2bRead::init(&mut proof);
|
||||
let mut transcript =
|
||||
crate::transcript::Blake2bRead::<_, _, Challenge255<_>>::init(&mut proof);
|
||||
let msm = params.empty_msm();
|
||||
|
||||
let guard = verify_proof(
|
||||
|
@ -303,7 +305,8 @@ fn test_roundtrip() {
|
|||
{
|
||||
let mut proof = &proof[..];
|
||||
|
||||
let mut transcript = crate::transcript::Blake2bRead::init(&mut proof);
|
||||
let mut transcript =
|
||||
crate::transcript::Blake2bRead::<_, _, Challenge255<_>>::init(&mut proof);
|
||||
let msm = params.empty_msm();
|
||||
|
||||
let guard = verify_proof(
|
||||
|
|
|
@ -8,7 +8,7 @@ use super::{
|
|||
};
|
||||
|
||||
use crate::arithmetic::{eval_polynomial, kate_division, CurveAffine, FieldExt};
|
||||
use crate::transcript::TranscriptWrite;
|
||||
use crate::transcript::{EncodedChallenge, TranscriptWrite};
|
||||
|
||||
use ff::Field;
|
||||
use group::Curve;
|
||||
|
@ -24,7 +24,7 @@ struct CommitmentData<C: CurveAffine> {
|
|||
}
|
||||
|
||||
/// Create a multi-opening proof
|
||||
pub fn create_proof<'a, I, C: CurveAffine, T: TranscriptWrite<C>>(
|
||||
pub fn create_proof<'a, I, C: CurveAffine, E: EncodedChallenge<C>, T: TranscriptWrite<C, E>>(
|
||||
params: &Params<C>,
|
||||
transcript: &mut T,
|
||||
queries: I,
|
||||
|
@ -32,8 +32,8 @@ pub fn create_proof<'a, I, C: CurveAffine, T: TranscriptWrite<C>>(
|
|||
where
|
||||
I: IntoIterator<Item = ProverQuery<'a, C>> + Clone,
|
||||
{
|
||||
let x_1 = ChallengeX1::get(transcript);
|
||||
let x_2 = ChallengeX2::get(transcript);
|
||||
let x_1: ChallengeX1<_> = transcript.squeeze_challenge_scalar();
|
||||
let x_2: ChallengeX2<_> = transcript.squeeze_challenge_scalar();
|
||||
|
||||
let (poly_map, point_sets) = construct_intermediate_sets(queries);
|
||||
|
||||
|
@ -91,7 +91,7 @@ where
|
|||
|
||||
transcript.write_point(f_commitment)?;
|
||||
|
||||
let x_3 = ChallengeX3::get(transcript);
|
||||
let x_3: ChallengeX3<_> = transcript.squeeze_challenge_scalar();
|
||||
|
||||
let q_evals: Vec<C::Scalar> = q_polys
|
||||
.iter()
|
||||
|
@ -102,7 +102,7 @@ where
|
|||
transcript.write_scalar(*eval)?;
|
||||
}
|
||||
|
||||
let x_4 = ChallengeX4::get(transcript);
|
||||
let x_4: ChallengeX4<_> = transcript.squeeze_challenge_scalar();
|
||||
|
||||
let (f_poly, f_blind_try) = q_polys.iter().zip(q_blinds.iter()).fold(
|
||||
(f_poly, f_blind),
|
||||
|
|
|
@ -9,7 +9,7 @@ use super::{
|
|||
VerifierQuery,
|
||||
};
|
||||
use crate::arithmetic::{eval_polynomial, lagrange_interpolate, CurveAffine, FieldExt};
|
||||
use crate::transcript::TranscriptRead;
|
||||
use crate::transcript::{EncodedChallenge, TranscriptRead};
|
||||
#[derive(Debug, Clone)]
|
||||
struct CommitmentData<C: CurveAffine> {
|
||||
set_index: usize,
|
||||
|
@ -18,12 +18,19 @@ struct CommitmentData<C: CurveAffine> {
|
|||
}
|
||||
|
||||
/// Verify a multi-opening proof
|
||||
pub fn verify_proof<'b, 'a: 'b, I, C: CurveAffine, T: TranscriptRead<C>>(
|
||||
pub fn verify_proof<
|
||||
'b,
|
||||
'a: 'b,
|
||||
I,
|
||||
C: CurveAffine,
|
||||
E: EncodedChallenge<C>,
|
||||
T: TranscriptRead<C, E>,
|
||||
>(
|
||||
params: &'a Params<C>,
|
||||
transcript: &mut T,
|
||||
queries: I,
|
||||
mut msm: MSM<'a, C>,
|
||||
) -> Result<Guard<'a, C>, Error>
|
||||
) -> Result<Guard<'a, C, E>, Error>
|
||||
where
|
||||
I: IntoIterator<Item = VerifierQuery<'b, C>> + Clone,
|
||||
{
|
||||
|
@ -33,11 +40,11 @@ where
|
|||
msm.scale(C::Scalar::rand());
|
||||
|
||||
// Sample x_1 for compressing openings at the same point sets together
|
||||
let x_1 = ChallengeX1::get(transcript);
|
||||
let x_1: ChallengeX1<_> = transcript.squeeze_challenge_scalar();
|
||||
|
||||
// Sample a challenge x_2 for keeping the multi-point quotient
|
||||
// polynomial terms linearly independent.
|
||||
let x_2 = ChallengeX2::get(transcript);
|
||||
let x_2: ChallengeX2<_> = transcript.squeeze_challenge_scalar();
|
||||
|
||||
let (commitment_map, point_sets) = construct_intermediate_sets(queries);
|
||||
|
||||
|
@ -77,7 +84,7 @@ where
|
|||
|
||||
// Sample a challenge x_3 for checking that f(X) was committed to
|
||||
// correctly.
|
||||
let x_3 = ChallengeX3::get(transcript);
|
||||
let x_3: ChallengeX3<_> = transcript.squeeze_challenge_scalar();
|
||||
|
||||
let mut q_evals = Vec::with_capacity(q_eval_sets.len());
|
||||
for _ in 0..q_eval_sets.len() {
|
||||
|
@ -104,7 +111,7 @@ where
|
|||
|
||||
// Sample a challenge x_4 that we will use to collapse the openings of
|
||||
// the various remaining polynomials at x_3 together.
|
||||
let x_4 = ChallengeX4::get(transcript);
|
||||
let x_4: ChallengeX4<_> = transcript.squeeze_challenge_scalar();
|
||||
|
||||
// Compute the final commitment that has to be opened
|
||||
msm.append_term(C::Scalar::one(), f_commitment);
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
//! transcripts.
|
||||
|
||||
use blake2b_simd::{Params as Blake2bParams, State as Blake2bState};
|
||||
use ff::Field;
|
||||
use std::convert::TryInto;
|
||||
use std::ops::Deref;
|
||||
|
||||
use crate::arithmetic::{Coordinates, CurveAffine, FieldExt};
|
||||
|
||||
|
@ -12,9 +10,17 @@ use std::io::{self, Read, Write};
|
|||
use std::marker::PhantomData;
|
||||
|
||||
/// Generic transcript view (from either the prover or verifier's perspective)
|
||||
pub trait Transcript<C: CurveAffine> {
|
||||
/// Squeeze a challenge (in the base field) from the transcript.
|
||||
fn squeeze_challenge(&mut self) -> C::Base;
|
||||
pub trait Transcript<C: CurveAffine, E: EncodedChallenge<C>> {
|
||||
/// Squeeze an encoded verifier challenge from the transcript.
|
||||
fn squeeze_challenge(&mut self) -> E;
|
||||
|
||||
/// Squeeze a typed challenge (in the scalar field) from the transcript.
|
||||
fn squeeze_challenge_scalar<T>(&mut self) -> ChallengeScalar<C, T> {
|
||||
ChallengeScalar {
|
||||
inner: self.squeeze_challenge().get_scalar(),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Writing the point to the transcript without writing it to the proof,
|
||||
/// treating it as a common input.
|
||||
|
@ -27,7 +33,7 @@ pub trait Transcript<C: CurveAffine> {
|
|||
|
||||
/// 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<C: CurveAffine>: Transcript<C> {
|
||||
pub trait TranscriptRead<C: CurveAffine, E: EncodedChallenge<C>>: Transcript<C, E> {
|
||||
/// Read a curve point from the prover.
|
||||
fn read_point(&mut self) -> io::Result<C>;
|
||||
|
||||
|
@ -37,7 +43,7 @@ pub trait TranscriptRead<C: CurveAffine>: Transcript<C> {
|
|||
|
||||
/// 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<C: CurveAffine>: Transcript<C> {
|
||||
pub trait TranscriptWrite<C: CurveAffine, E: EncodedChallenge<C>>: Transcript<C, E> {
|
||||
/// Write a curve point to the proof and the transcript.
|
||||
fn write_point(&mut self, point: C) -> io::Result<()>;
|
||||
|
||||
|
@ -47,13 +53,14 @@ pub trait TranscriptWrite<C: CurveAffine>: Transcript<C> {
|
|||
|
||||
/// We will replace BLAKE2b with an algebraic hash function in a later version.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Blake2bRead<R: Read, C: CurveAffine> {
|
||||
pub struct Blake2bRead<R: Read, C: CurveAffine, E: EncodedChallenge<C>> {
|
||||
state: Blake2bState,
|
||||
reader: R,
|
||||
_marker: PhantomData<C>,
|
||||
_marker_c: PhantomData<C>,
|
||||
_marker_e: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<R: Read, C: CurveAffine> Blake2bRead<R, C> {
|
||||
impl<R: Read, C: CurveAffine, E: EncodedChallenge<C>> Blake2bRead<R, C, E> {
|
||||
/// Initialize a transcript given an input buffer and a key.
|
||||
pub fn init(reader: R) -> Self {
|
||||
Blake2bRead {
|
||||
|
@ -62,12 +69,15 @@ impl<R: Read, C: CurveAffine> Blake2bRead<R, C> {
|
|||
.personal(b"Halo2-Transcript")
|
||||
.to_state(),
|
||||
reader,
|
||||
_marker: PhantomData,
|
||||
_marker_c: PhantomData,
|
||||
_marker_e: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read, C: CurveAffine> TranscriptRead<C> for Blake2bRead<R, C> {
|
||||
impl<R: Read, C: CurveAffine> TranscriptRead<C, Challenge255<C>>
|
||||
for Blake2bRead<R, C, Challenge255<C>>
|
||||
{
|
||||
fn read_point(&mut self) -> io::Result<C> {
|
||||
let mut compressed = C::Repr::default();
|
||||
self.reader.read_exact(compressed.as_mut())?;
|
||||
|
@ -94,7 +104,16 @@ impl<R: Read, C: CurveAffine> TranscriptRead<C> for Blake2bRead<R, C> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<R: Read, C: CurveAffine> Transcript<C> for Blake2bRead<R, C> {
|
||||
impl<R: Read, C: CurveAffine> Transcript<C, Challenge255<C>>
|
||||
for Blake2bRead<R, C, Challenge255<C>>
|
||||
{
|
||||
fn squeeze_challenge(&mut self) -> Challenge255<C> {
|
||||
let hasher = self.state.clone();
|
||||
let result: [u8; 64] = hasher.finalize().as_bytes().try_into().unwrap();
|
||||
self.state.update(&result[..]);
|
||||
Challenge255::<C>::new(&result)
|
||||
}
|
||||
|
||||
fn common_point(&mut self, point: C) -> io::Result<()> {
|
||||
let coords: Coordinates<C> = Option::from(point.coordinates()).ok_or_else(|| {
|
||||
io::Error::new(
|
||||
|
@ -113,24 +132,18 @@ impl<R: Read, C: CurveAffine> Transcript<C> for Blake2bRead<R, C> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn squeeze_challenge(&mut self) -> C::Base {
|
||||
let hasher = self.state.clone();
|
||||
let result: [u8; 64] = hasher.finalize().as_bytes().try_into().unwrap();
|
||||
self.state.update(&result[..]);
|
||||
C::Base::from_bytes_wide(&result)
|
||||
}
|
||||
}
|
||||
|
||||
/// We will replace BLAKE2b with an algebraic hash function in a later version.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Blake2bWrite<W: Write, C: CurveAffine> {
|
||||
pub struct Blake2bWrite<W: Write, C: CurveAffine, E: EncodedChallenge<C>> {
|
||||
state: Blake2bState,
|
||||
writer: W,
|
||||
_marker: PhantomData<C>,
|
||||
_marker_c: PhantomData<C>,
|
||||
_marker_e: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<W: Write, C: CurveAffine> Blake2bWrite<W, C> {
|
||||
impl<W: Write, C: CurveAffine, E: EncodedChallenge<C>> Blake2bWrite<W, C, E> {
|
||||
/// Initialize a transcript given an output buffer and a key.
|
||||
pub fn init(writer: W) -> Self {
|
||||
Blake2bWrite {
|
||||
|
@ -139,7 +152,8 @@ impl<W: Write, C: CurveAffine> Blake2bWrite<W, C> {
|
|||
.personal(b"Halo2-Transcript")
|
||||
.to_state(),
|
||||
writer,
|
||||
_marker: PhantomData,
|
||||
_marker_c: PhantomData,
|
||||
_marker_e: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,7 +164,9 @@ impl<W: Write, C: CurveAffine> Blake2bWrite<W, C> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<W: Write, C: CurveAffine> TranscriptWrite<C> for Blake2bWrite<W, C> {
|
||||
impl<W: Write, C: CurveAffine> TranscriptWrite<C, Challenge255<C>>
|
||||
for Blake2bWrite<W, C, Challenge255<C>>
|
||||
{
|
||||
fn write_point(&mut self, point: C) -> io::Result<()> {
|
||||
self.common_point(point)?;
|
||||
let compressed = point.to_bytes();
|
||||
|
@ -163,7 +179,16 @@ impl<W: Write, C: CurveAffine> TranscriptWrite<C> for Blake2bWrite<W, C> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<W: Write, C: CurveAffine> Transcript<C> for Blake2bWrite<W, C> {
|
||||
impl<W: Write, C: CurveAffine> Transcript<C, Challenge255<C>>
|
||||
for Blake2bWrite<W, C, Challenge255<C>>
|
||||
{
|
||||
fn squeeze_challenge(&mut self) -> Challenge255<C> {
|
||||
let hasher = self.state.clone();
|
||||
let result: [u8; 64] = hasher.finalize().as_bytes().try_into().unwrap();
|
||||
self.state.update(&result[..]);
|
||||
Challenge255::<C>::new(&result)
|
||||
}
|
||||
|
||||
fn common_point(&mut self, point: C) -> io::Result<()> {
|
||||
let coords: Coordinates<C> = Option::from(point.coordinates()).ok_or_else(|| {
|
||||
io::Error::new(
|
||||
|
@ -182,24 +207,6 @@ impl<W: Write, C: CurveAffine> Transcript<C> for Blake2bWrite<W, C> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn squeeze_challenge(&mut self) -> C::Base {
|
||||
let hasher = self.state.clone();
|
||||
let result: [u8; 64] = hasher.finalize().as_bytes().try_into().unwrap();
|
||||
self.state.update(&result[..]);
|
||||
C::Base::from_bytes_wide(&result)
|
||||
}
|
||||
}
|
||||
|
||||
/// This is a 128-bit verifier challenge.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Challenge(pub(crate) u128);
|
||||
|
||||
impl Challenge {
|
||||
/// Obtains a new challenge from the transcript.
|
||||
pub fn get<C: CurveAffine, T: Transcript<C>>(transcript: &mut T) -> Challenge {
|
||||
Challenge(transcript.squeeze_challenge().get_lower_128())
|
||||
}
|
||||
}
|
||||
|
||||
/// The scalar representation of a verifier challenge.
|
||||
|
@ -207,63 +214,77 @@ impl Challenge {
|
|||
/// The `Type` type can be used to scope the challenge to a specific context, or
|
||||
/// set to `()` if no context is required.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ChallengeScalar<C: CurveAffine, Type> {
|
||||
pub struct ChallengeScalar<C: CurveAffine, T> {
|
||||
inner: C::Scalar,
|
||||
_marker: PhantomData<Type>,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<C: CurveAffine, Type> From<Challenge> for ChallengeScalar<C, Type> {
|
||||
/// This algorithm applies the mapping of Algorithm 1 from the
|
||||
/// [Halo](https://eprint.iacr.org/2019/1021) paper.
|
||||
fn from(challenge: Challenge) -> Self {
|
||||
let mut acc = (C::Scalar::ZETA + &C::Scalar::one()).double();
|
||||
impl<C: CurveAffine, T> std::ops::Deref for ChallengeScalar<C, T> {
|
||||
type Target = C::Scalar;
|
||||
|
||||
for i in (0..64).rev() {
|
||||
let should_negate = ((challenge.0 >> ((i << 1) + 1)) & 1) == 1;
|
||||
let should_endo = ((challenge.0 >> (i << 1)) & 1) == 1;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
let q = if should_negate {
|
||||
-C::Scalar::one()
|
||||
} else {
|
||||
C::Scalar::one()
|
||||
};
|
||||
let q = if should_endo { q * &C::Scalar::ZETA } else { q };
|
||||
acc = acc + &q + &acc;
|
||||
}
|
||||
/// `EncodedChallenge<C>` defines a challenge encoding with a [`Self::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<C: CurveAffine> {
|
||||
/// The Input type used to derive the challenge encoding. For example,
|
||||
/// an input from the Poseidon hash would be a base field element;
|
||||
/// an input from the Blake2b hash would be a [u8; 64].
|
||||
type Input;
|
||||
|
||||
/// Get an encoded challenge from a given input challenge.
|
||||
fn new(challenge_input: &Self::Input) -> Self;
|
||||
|
||||
/// Get a scalar field element from an encoded challenge.
|
||||
fn get_scalar(&self) -> C::Scalar;
|
||||
|
||||
/// Cast an encoded challenge as a typed `ChallengeScalar`.
|
||||
fn as_challenge_scalar<T>(&self) -> ChallengeScalar<C, T> {
|
||||
ChallengeScalar {
|
||||
inner: acc,
|
||||
inner: self.get_scalar(),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: CurveAffine, Type> ChallengeScalar<C, Type> {
|
||||
/// Obtains a new challenge from the transcript.
|
||||
pub fn get<T: Transcript<C>>(transcript: &mut T) -> Self
|
||||
where
|
||||
C: CurveAffine,
|
||||
{
|
||||
Challenge::get(transcript).into()
|
||||
/// A 255-bit challenge.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Challenge255<C: CurveAffine>([u8; 32], PhantomData<C>);
|
||||
|
||||
impl<C: CurveAffine> std::ops::Deref for Challenge255<C> {
|
||||
type Target = [u8; 32];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: CurveAffine, Type> Deref for ChallengeScalar<C, Type> {
|
||||
type Target = C::Scalar;
|
||||
impl<C: CurveAffine> EncodedChallenge<C> for Challenge255<C> {
|
||||
type Input = [u8; 64];
|
||||
|
||||
fn deref(&self) -> &C::Scalar {
|
||||
&self.inner
|
||||
fn new(challenge_input: &[u8; 64]) -> Self {
|
||||
Challenge255(
|
||||
C::Scalar::from_bytes_wide(challenge_input).to_bytes(),
|
||||
PhantomData,
|
||||
)
|
||||
}
|
||||
fn get_scalar(&self) -> C::Scalar {
|
||||
C::Scalar::from_bytes(&self.0).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn read_n_points<C: CurveAffine, T: TranscriptRead<C>>(
|
||||
pub(crate) fn read_n_points<C: CurveAffine, E: EncodedChallenge<C>, T: TranscriptRead<C, E>>(
|
||||
transcript: &mut T,
|
||||
n: usize,
|
||||
) -> io::Result<Vec<C>> {
|
||||
(0..n).map(|_| transcript.read_point()).collect()
|
||||
}
|
||||
|
||||
pub(crate) fn read_n_scalars<C: CurveAffine, T: TranscriptRead<C>>(
|
||||
pub(crate) fn read_n_scalars<C: CurveAffine, E: EncodedChallenge<C>, T: TranscriptRead<C, E>>(
|
||||
transcript: &mut T,
|
||||
n: usize,
|
||||
) -> io::Result<Vec<C::Scalar>> {
|
||||
|
|
|
@ -13,7 +13,7 @@ use halo2::poly::{
|
|||
commitment::{Blind, Params},
|
||||
Rotation,
|
||||
};
|
||||
use halo2::transcript::{Blake2bRead, Blake2bWrite};
|
||||
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::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::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::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::<EqAffine>::read::<_, MyCircuit<Fp>>(&mut &vk_buffer[..], ¶ms)
|
||||
|
|
Loading…
Reference in New Issue