mirror of https://github.com/zcash/halo2.git
Merge pull request #43 from zcash/transcript-merge
Make transcript generic over curve point
This commit is contained in:
commit
e8bf35d853
18
src/plonk.rs
18
src/plonk.rs
|
@ -9,7 +9,6 @@ use crate::arithmetic::CurveAffine;
|
|||
use crate::poly::{
|
||||
multiopen, Coeff, EvaluationDomain, ExtendedLagrangeCoeff, LagrangeCoeff, Polynomial,
|
||||
};
|
||||
use crate::transcript::Hasher;
|
||||
|
||||
mod circuit;
|
||||
mod keygen;
|
||||
|
@ -78,6 +77,8 @@ pub enum Error {
|
|||
BoundsFailure,
|
||||
/// Opening error
|
||||
OpeningError,
|
||||
/// Transcript error
|
||||
TranscriptError,
|
||||
}
|
||||
|
||||
impl<C: CurveAffine> ProvingKey<C> {
|
||||
|
@ -94,21 +95,6 @@ impl<C: CurveAffine> VerifyingKey<C> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Hash a point into transcript
|
||||
pub fn hash_point<C: CurveAffine, H: Hasher<C::Base>>(
|
||||
transcript: &mut H,
|
||||
point: &C,
|
||||
) -> Result<(), Error> {
|
||||
let tmp = point.get_xy();
|
||||
if bool::from(tmp.is_none()) {
|
||||
return Err(Error::SynthesisError);
|
||||
};
|
||||
let tmp = tmp.unwrap();
|
||||
transcript.absorb(tmp.0);
|
||||
transcript.absorb(tmp.1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_proving() {
|
||||
use crate::arithmetic::{Curve, Field};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::{
|
||||
circuit::{Advice, Assignment, Circuit, Column, ConstraintSystem, Fixed},
|
||||
hash_point, Error, Proof, ProvingKey,
|
||||
Error, Proof, ProvingKey,
|
||||
};
|
||||
use crate::arithmetic::{
|
||||
eval_polynomial, get_challenge_scalar, parallelize, BatchInvert, Challenge, Curve, CurveAffine,
|
||||
|
@ -11,7 +11,7 @@ use crate::poly::{
|
|||
multiopen::{self, ProverQuery},
|
||||
LagrangeCoeff, Polynomial, Rotation,
|
||||
};
|
||||
use crate::transcript::Hasher;
|
||||
use crate::transcript::{Hasher, Transcript};
|
||||
|
||||
impl<C: CurveAffine> Proof<C> {
|
||||
/// This creates a proof for the provided `circuit` when given the public
|
||||
|
@ -92,7 +92,7 @@ impl<C: CurveAffine> Proof<C> {
|
|||
let witness = witness;
|
||||
|
||||
// Create a transcript for obtaining Fiat-Shamir challenges.
|
||||
let mut transcript = HBase::init(C::Base::one());
|
||||
let mut transcript = Transcript::<C, HBase, HScalar>::new();
|
||||
|
||||
// Compute commitments to aux column polynomials
|
||||
let aux_commitments_projective: Vec<_> = aux
|
||||
|
@ -105,7 +105,9 @@ impl<C: CurveAffine> Proof<C> {
|
|||
drop(aux_commitments_projective);
|
||||
|
||||
for commitment in &aux_commitments {
|
||||
hash_point(&mut transcript, commitment)?;
|
||||
transcript
|
||||
.absorb_point(commitment)
|
||||
.map_err(|_| Error::TranscriptError)?;
|
||||
}
|
||||
|
||||
let aux_polys: Vec<_> = aux
|
||||
|
@ -143,7 +145,9 @@ impl<C: CurveAffine> Proof<C> {
|
|||
drop(advice_commitments_projective);
|
||||
|
||||
for commitment in &advice_commitments {
|
||||
hash_point(&mut transcript, commitment)?;
|
||||
transcript
|
||||
.absorb_point(commitment)
|
||||
.map_err(|_| Error::TranscriptError)?;
|
||||
}
|
||||
|
||||
let advice_polys: Vec<_> = witness
|
||||
|
@ -277,7 +281,9 @@ impl<C: CurveAffine> Proof<C> {
|
|||
|
||||
// Hash each permutation product commitment
|
||||
for c in &permutation_product_commitments {
|
||||
hash_point(&mut transcript, c)?;
|
||||
transcript
|
||||
.absorb_point(c)
|
||||
.map_err(|_| Error::TranscriptError)?;
|
||||
}
|
||||
|
||||
// Obtain challenge for keeping all separate gates linearly independent
|
||||
|
@ -385,7 +391,9 @@ impl<C: CurveAffine> Proof<C> {
|
|||
|
||||
// Hash each h(X) piece
|
||||
for c in h_commitments.iter() {
|
||||
hash_point(&mut transcript, c)?;
|
||||
transcript
|
||||
.absorb_point(c)
|
||||
.map_err(|_| Error::TranscriptError)?;
|
||||
}
|
||||
|
||||
let x_3: C::Scalar = get_challenge_scalar(Challenge(transcript.squeeze().get_lower_128()));
|
||||
|
@ -444,10 +452,6 @@ impl<C: CurveAffine> Proof<C> {
|
|||
.map(|poly| eval_polynomial(poly, x_3))
|
||||
.collect();
|
||||
|
||||
// We set up a second transcript on the scalar field to hash in openings of
|
||||
// our polynomial commitments.
|
||||
let mut transcript_scalar = HScalar::init(C::Scalar::one());
|
||||
|
||||
// Hash each advice evaluation
|
||||
for eval in advice_evals
|
||||
.iter()
|
||||
|
@ -458,13 +462,9 @@ impl<C: CurveAffine> Proof<C> {
|
|||
.chain(permutation_product_inv_evals.iter())
|
||||
.chain(permutation_evals.iter().flat_map(|evals| evals.iter()))
|
||||
{
|
||||
transcript_scalar.absorb(*eval);
|
||||
transcript.absorb_scalar(*eval);
|
||||
}
|
||||
|
||||
let transcript_scalar_point =
|
||||
C::Base::from_bytes(&(transcript_scalar.squeeze()).to_bytes()).unwrap();
|
||||
transcript.absorb(transcript_scalar_point);
|
||||
|
||||
let mut instances: Vec<ProverQuery<C>> = Vec::new();
|
||||
|
||||
for (query_index, &(column, at)) in pk.vk.cs.advice_queries.iter().enumerate() {
|
||||
|
@ -558,9 +558,8 @@ impl<C: CurveAffine> Proof<C> {
|
|||
}
|
||||
}
|
||||
|
||||
let multiopening =
|
||||
multiopen::Proof::create(params, &mut transcript, &mut transcript_scalar, instances)
|
||||
.map_err(|_| Error::OpeningError)?;
|
||||
let multiopening = multiopen::Proof::create(params, &mut transcript, instances)
|
||||
.map_err(|_| Error::OpeningError)?;
|
||||
|
||||
Ok(Proof {
|
||||
advice_commitments,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use super::{hash_point, Error, Proof, VerifyingKey};
|
||||
use super::{Error, Proof, VerifyingKey};
|
||||
use crate::arithmetic::{get_challenge_scalar, Challenge, CurveAffine, Field};
|
||||
use crate::poly::{
|
||||
commitment::{Guard, Params, MSM},
|
||||
multiopen::VerifierQuery,
|
||||
Rotation,
|
||||
};
|
||||
use crate::transcript::Hasher;
|
||||
use crate::transcript::{Hasher, Transcript};
|
||||
|
||||
impl<'a, C: CurveAffine> Proof<C> {
|
||||
/// Returns a boolean indicating whether or not the proof is valid
|
||||
|
@ -27,16 +27,20 @@ impl<'a, C: CurveAffine> Proof<C> {
|
|||
}
|
||||
|
||||
// Create a transcript for obtaining Fiat-Shamir challenges.
|
||||
let mut transcript = HBase::init(C::Base::one());
|
||||
let mut transcript = Transcript::<C, HBase, HScalar>::new();
|
||||
|
||||
// Hash the aux (external) commitments into the transcript
|
||||
for commitment in aux_commitments {
|
||||
hash_point(&mut transcript, commitment)?;
|
||||
transcript
|
||||
.absorb_point(commitment)
|
||||
.map_err(|_| Error::TranscriptError)?;
|
||||
}
|
||||
|
||||
// Hash the prover's advice commitments into the transcript
|
||||
for commitment in &self.advice_commitments {
|
||||
hash_point(&mut transcript, commitment)?;
|
||||
transcript
|
||||
.absorb_point(commitment)
|
||||
.map_err(|_| Error::TranscriptError)?;
|
||||
}
|
||||
|
||||
// Sample x_0 challenge
|
||||
|
@ -47,7 +51,9 @@ impl<'a, C: CurveAffine> Proof<C> {
|
|||
|
||||
// Hash each permutation product commitment
|
||||
for c in &self.permutation_product_commitments {
|
||||
hash_point(&mut transcript, c)?;
|
||||
transcript
|
||||
.absorb_point(c)
|
||||
.map_err(|_| Error::TranscriptError)?;
|
||||
}
|
||||
|
||||
// Sample x_2 challenge, which keeps the gates linearly independent.
|
||||
|
@ -55,7 +61,9 @@ impl<'a, C: CurveAffine> Proof<C> {
|
|||
|
||||
// Obtain a commitment to h(X) in the form of multiple pieces of degree n - 1
|
||||
for c in &self.h_commitments {
|
||||
hash_point(&mut transcript, c)?;
|
||||
transcript
|
||||
.absorb_point(c)
|
||||
.map_err(|_| Error::TranscriptError)?;
|
||||
}
|
||||
|
||||
// Sample x_3 challenge, which is used to ensure the circuit is
|
||||
|
@ -66,10 +74,6 @@ impl<'a, C: CurveAffine> Proof<C> {
|
|||
// commitments open to the correct values.
|
||||
self.check_hx(params, vk, x_0, x_1, x_2, x_3)?;
|
||||
|
||||
// Hash together all the openings provided by the prover into a new
|
||||
// transcript on the scalar field.
|
||||
let mut transcript_scalar = HScalar::init(C::Scalar::one());
|
||||
|
||||
for eval in self
|
||||
.advice_evals
|
||||
.iter()
|
||||
|
@ -80,13 +84,9 @@ impl<'a, C: CurveAffine> Proof<C> {
|
|||
.chain(self.permutation_product_inv_evals.iter())
|
||||
.chain(self.permutation_evals.iter().flat_map(|evals| evals.iter()))
|
||||
{
|
||||
transcript_scalar.absorb(*eval);
|
||||
transcript.absorb_scalar(*eval);
|
||||
}
|
||||
|
||||
let transcript_scalar_point =
|
||||
C::Base::from_bytes(&(transcript_scalar.squeeze()).to_bytes()).unwrap();
|
||||
transcript.absorb(transcript_scalar_point);
|
||||
|
||||
let mut queries: Vec<VerifierQuery<'a, C>> = Vec::new();
|
||||
|
||||
for (query_index, &(column, at)) in vk.cs.advice_queries.iter().enumerate() {
|
||||
|
@ -180,13 +180,7 @@ impl<'a, C: CurveAffine> Proof<C> {
|
|||
// We are now convinced the circuit is satisfied so long as the
|
||||
// polynomial commitments open to the correct values.
|
||||
self.multiopening
|
||||
.verify(
|
||||
params,
|
||||
&mut transcript,
|
||||
&mut transcript_scalar,
|
||||
queries,
|
||||
msm,
|
||||
)
|
||||
.verify(params, &mut transcript, queries, msm)
|
||||
.map_err(|_| Error::OpeningError)
|
||||
}
|
||||
|
||||
|
|
|
@ -248,8 +248,10 @@ fn test_opening_proof() {
|
|||
commitment::{Blind, Params},
|
||||
EvaluationDomain,
|
||||
};
|
||||
use crate::arithmetic::{eval_polynomial, get_challenge_scalar, Challenge, Curve, Field};
|
||||
use crate::transcript::{DummyHash, Hasher};
|
||||
use crate::arithmetic::{
|
||||
eval_polynomial, get_challenge_scalar, Challenge, Curve, CurveAffine, Field,
|
||||
};
|
||||
use crate::transcript::{DummyHash, Hasher, Transcript};
|
||||
use crate::tweedle::{EpAffine, Fp, Fq};
|
||||
|
||||
let params = Params::<EpAffine>::new::<DummyHash<Fp>>(K);
|
||||
|
@ -265,17 +267,18 @@ fn test_opening_proof() {
|
|||
|
||||
let p = params.commit(&px, blind).to_affine();
|
||||
|
||||
let mut transcript = DummyHash::init(Field::one());
|
||||
let mut hasher = DummyHash::init(Field::one());
|
||||
let (p_x, p_y) = p.get_xy().unwrap();
|
||||
transcript.absorb(p_x);
|
||||
transcript.absorb(p_y);
|
||||
let x_packed = transcript.squeeze().get_lower_128();
|
||||
hasher.absorb(p_x);
|
||||
hasher.absorb(p_y);
|
||||
let x_packed = hasher.squeeze().get_lower_128();
|
||||
let x: Fq = get_challenge_scalar(Challenge(x_packed));
|
||||
|
||||
// Evaluate the polynomial
|
||||
let v = eval_polynomial(&px, x);
|
||||
|
||||
transcript.absorb(Fp::from_bytes(&v.to_bytes()).unwrap()); // unlikely to fail since p ~ q
|
||||
hasher.absorb(Fp::from_bytes(&v.to_bytes()).unwrap()); // unlikely to fail since p ~ q
|
||||
let scalar_hasher = DummyHash::init(Fq::one());
|
||||
let mut transcript = Transcript::init_with_hashers(&hasher, &scalar_hasher);
|
||||
|
||||
loop {
|
||||
let transcript_dup = transcript.clone();
|
||||
|
@ -283,7 +286,7 @@ fn test_opening_proof() {
|
|||
let opening_proof = Proof::create(¶ms, &mut transcript, &px, blind, x);
|
||||
if opening_proof.is_err() {
|
||||
transcript = transcript_dup;
|
||||
transcript.absorb(Field::one());
|
||||
transcript.absorb_base(Field::one());
|
||||
} else {
|
||||
let opening_proof = opening_proof.unwrap();
|
||||
// Verify the opening proof
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::arithmetic::{
|
|||
best_multiexp, compute_inner_product, get_challenge_scalar, parallelize, small_multiexp,
|
||||
Challenge, Curve, CurveAffine, Field,
|
||||
};
|
||||
use crate::transcript::Hasher;
|
||||
use crate::transcript::{Hasher, Transcript};
|
||||
|
||||
impl<C: CurveAffine> Proof<C> {
|
||||
/// Create a polynomial commitment opening proof for the polynomial defined
|
||||
|
@ -20,13 +20,17 @@ impl<C: CurveAffine> Proof<C> {
|
|||
/// opening v, and the point x. It's probably also nice for the transcript
|
||||
/// to have seen the elliptic curve description and the SRS, if you want to
|
||||
/// be rigorous.
|
||||
pub fn create<H: Hasher<C::Base>>(
|
||||
pub fn create<HBase, HScalar>(
|
||||
params: &Params<C>,
|
||||
transcript: &mut H,
|
||||
transcript: &mut Transcript<C, HBase, HScalar>,
|
||||
px: &Polynomial<C::Scalar, Coeff>,
|
||||
blind: Blind<C::Scalar>,
|
||||
x: C::Scalar,
|
||||
) -> Result<Self, Error> {
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
HBase: Hasher<C::Base>,
|
||||
HScalar: Hasher<C::Scalar>,
|
||||
{
|
||||
let mut blind = blind.0;
|
||||
|
||||
// We're limited to polynomials of degree n - 1.
|
||||
|
@ -90,15 +94,14 @@ impl<C: CurveAffine> Proof<C> {
|
|||
// until the challenge is a square.
|
||||
let mut transcript = transcript.clone();
|
||||
|
||||
// Feed L and R into the cloned transcript.
|
||||
// We expect these to not be points at infinity due to the randomness.
|
||||
let (l_x, l_y) = l.get_xy().unwrap();
|
||||
let (r_x, r_y) = r.get_xy().unwrap();
|
||||
|
||||
// Feed L and R into the cloned transcript...
|
||||
transcript.absorb(l_x);
|
||||
transcript.absorb(l_y);
|
||||
transcript.absorb(r_x);
|
||||
transcript.absorb(r_y);
|
||||
transcript
|
||||
.absorb_point(&l)
|
||||
.map_err(|_| Error::SamplingError)?;
|
||||
transcript
|
||||
.absorb_point(&r)
|
||||
.map_err(|_| Error::SamplingError)?;
|
||||
|
||||
// ... and get the squared challenge.
|
||||
let challenge_sq_packed = transcript.squeeze().get_lower_128();
|
||||
|
@ -122,12 +125,12 @@ impl<C: CurveAffine> Proof<C> {
|
|||
let challenge_sq = challenge.square();
|
||||
|
||||
// Feed L and R into the real transcript
|
||||
let (l_x, l_y) = l.get_xy().unwrap();
|
||||
let (r_x, r_y) = r.get_xy().unwrap();
|
||||
transcript.absorb(l_x);
|
||||
transcript.absorb(l_y);
|
||||
transcript.absorb(r_x);
|
||||
transcript.absorb(r_y);
|
||||
transcript
|
||||
.absorb_point(&l)
|
||||
.map_err(|_| Error::SamplingError)?;
|
||||
transcript
|
||||
.absorb_point(&r)
|
||||
.map_err(|_| Error::SamplingError)?;
|
||||
|
||||
// And obtain the challenge, even though we already have it, since
|
||||
// squeezing affects the transcript.
|
||||
|
@ -172,11 +175,10 @@ impl<C: CurveAffine> Proof<C> {
|
|||
|
||||
let delta = best_multiexp(&[d, d * &b, s], &[g, u, params.h]).to_affine();
|
||||
|
||||
let (delta_x, delta_y) = delta.get_xy().unwrap();
|
||||
|
||||
// Feed delta into the transcript
|
||||
transcript.absorb(delta_x);
|
||||
transcript.absorb(delta_y);
|
||||
transcript
|
||||
.absorb_point(&delta)
|
||||
.map_err(|_| Error::SamplingError)?;
|
||||
|
||||
// Obtain the challenge c.
|
||||
let c_packed = transcript.squeeze().get_lower_128();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::super::Error;
|
||||
use super::{Params, Proof, MSM};
|
||||
use crate::transcript::Hasher;
|
||||
use crate::transcript::{Hasher, Transcript};
|
||||
|
||||
use crate::arithmetic::{
|
||||
best_multiexp, get_challenge_scalar, Challenge, Curve, CurveAffine, Field,
|
||||
|
@ -65,15 +65,19 @@ impl<C: CurveAffine> Proof<C> {
|
|||
/// Checks to see if an [`Proof`] is valid given the current `transcript`,
|
||||
/// and a point `x` that the polynomial commitment `p` opens purportedly to
|
||||
/// the value `v`.
|
||||
pub fn verify<'a, H: Hasher<C::Base>>(
|
||||
pub fn verify<'a, HBase, HScalar>(
|
||||
&self,
|
||||
params: &'a Params<C>,
|
||||
mut msm: MSM<'a, C>,
|
||||
transcript: &mut H,
|
||||
transcript: &mut Transcript<C, HBase, HScalar>,
|
||||
x: C::Scalar,
|
||||
mut commitment_msm: MSM<'a, C>,
|
||||
v: C::Scalar,
|
||||
) -> Result<Guard<'a, C>, Error> {
|
||||
) -> Result<Guard<'a, C>, Error>
|
||||
where
|
||||
HBase: Hasher<C::Base>,
|
||||
HScalar: Hasher<C::Scalar>,
|
||||
{
|
||||
// Check for well-formedness
|
||||
if self.rounds.len() != params.k as usize {
|
||||
return Err(Error::OpeningError);
|
||||
|
@ -105,17 +109,14 @@ impl<C: CurveAffine> Proof<C> {
|
|||
|
||||
for round in &self.rounds {
|
||||
// Feed L and R into the transcript.
|
||||
let l = round.0.get_xy();
|
||||
let r = round.1.get_xy();
|
||||
if bool::from(l.is_none() | r.is_none()) {
|
||||
return Err(Error::OpeningError);
|
||||
}
|
||||
let l = l.unwrap();
|
||||
let r = r.unwrap();
|
||||
transcript.absorb(l.0);
|
||||
transcript.absorb(l.1);
|
||||
transcript.absorb(r.0);
|
||||
transcript.absorb(r.1);
|
||||
let l = round.0;
|
||||
let r = round.1;
|
||||
transcript
|
||||
.absorb_point(&l)
|
||||
.map_err(|_| Error::OpeningError)?;
|
||||
transcript
|
||||
.absorb_point(&r)
|
||||
.map_err(|_| Error::OpeningError)?;
|
||||
let challenge_sq_packed = transcript.squeeze().get_lower_128();
|
||||
let challenge_sq: C::Scalar = get_challenge_scalar(Challenge(challenge_sq_packed));
|
||||
|
||||
|
@ -148,15 +149,10 @@ impl<C: CurveAffine> Proof<C> {
|
|||
challenges_sq_packed.push(Challenge(challenge_sq_packed));
|
||||
}
|
||||
|
||||
let delta = self.delta.get_xy();
|
||||
if bool::from(delta.is_none()) {
|
||||
return Err(Error::OpeningError);
|
||||
}
|
||||
let delta = delta.unwrap();
|
||||
|
||||
// Feed delta into the transcript
|
||||
transcript.absorb(delta.0);
|
||||
transcript.absorb(delta.1);
|
||||
transcript
|
||||
.absorb_point(&self.delta)
|
||||
.map_err(|_| Error::OpeningError)?;
|
||||
|
||||
// Get the challenge `c`
|
||||
let c_packed = transcript.squeeze().get_lower_128();
|
||||
|
|
|
@ -8,8 +8,7 @@ use crate::arithmetic::{
|
|||
eval_polynomial, get_challenge_scalar, kate_division, lagrange_interpolate, Challenge, Curve,
|
||||
CurveAffine, Field,
|
||||
};
|
||||
use crate::plonk::hash_point;
|
||||
use crate::transcript::Hasher;
|
||||
use crate::transcript::{Hasher, Transcript};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -24,8 +23,7 @@ impl<C: CurveAffine> Proof<C> {
|
|||
/// Create a multi-opening proof
|
||||
pub fn create<'a, I, HBase: Hasher<C::Base>, HScalar: Hasher<C::Scalar>>(
|
||||
params: &Params<C>,
|
||||
transcript: &mut HBase,
|
||||
transcript_scalar: &mut HScalar,
|
||||
transcript: &mut Transcript<C, HBase, HScalar>,
|
||||
queries: I,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
|
@ -110,8 +108,9 @@ impl<C: CurveAffine> Proof<C> {
|
|||
|
||||
let (opening, q_evals) = loop {
|
||||
let mut transcript = transcript.clone();
|
||||
let mut transcript_scalar = transcript_scalar.clone();
|
||||
hash_point(&mut transcript, &f_commitment).unwrap();
|
||||
transcript
|
||||
.absorb_point(&f_commitment)
|
||||
.map_err(|_| Error::SamplingError)?;
|
||||
|
||||
let x_6: C::Scalar =
|
||||
get_challenge_scalar(Challenge(transcript.squeeze().get_lower_128()));
|
||||
|
@ -122,13 +121,9 @@ impl<C: CurveAffine> Proof<C> {
|
|||
.collect();
|
||||
|
||||
for eval in q_evals.iter() {
|
||||
transcript_scalar.absorb(*eval);
|
||||
transcript.absorb_scalar(*eval);
|
||||
}
|
||||
|
||||
let transcript_scalar_point =
|
||||
C::Base::from_bytes(&(transcript_scalar.squeeze()).to_bytes()).unwrap();
|
||||
transcript.absorb(transcript_scalar_point);
|
||||
|
||||
let x_7: C::Scalar =
|
||||
get_challenge_scalar(Challenge(transcript.squeeze().get_lower_128()));
|
||||
|
||||
|
|
|
@ -6,8 +6,7 @@ use super::{construct_intermediate_sets, Proof, Query, VerifierQuery};
|
|||
use crate::arithmetic::{
|
||||
eval_polynomial, get_challenge_scalar, lagrange_interpolate, Challenge, CurveAffine, Field,
|
||||
};
|
||||
use crate::plonk::hash_point;
|
||||
use crate::transcript::Hasher;
|
||||
use crate::transcript::{Hasher, Transcript};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct CommitmentData<C: CurveAffine> {
|
||||
|
@ -21,8 +20,7 @@ impl<C: CurveAffine> Proof<C> {
|
|||
pub fn verify<'a, I, HBase: Hasher<C::Base>, HScalar: Hasher<C::Scalar>>(
|
||||
&self,
|
||||
params: &'a Params<C>,
|
||||
transcript: &mut HBase,
|
||||
transcript_scalar: &mut HScalar,
|
||||
transcript: &mut Transcript<C, HBase, HScalar>,
|
||||
queries: I,
|
||||
mut msm: MSM<'a, C>,
|
||||
) -> Result<Guard<'a, C>, Error>
|
||||
|
@ -75,20 +73,18 @@ impl<C: CurveAffine> Proof<C> {
|
|||
}
|
||||
|
||||
// Obtain the commitment to the multi-point quotient polynomial f(X).
|
||||
hash_point(transcript, &self.f_commitment).unwrap();
|
||||
transcript
|
||||
.absorb_point(&self.f_commitment)
|
||||
.map_err(|_| Error::SamplingError)?;
|
||||
|
||||
// Sample a challenge x_6 for checking that f(X) was committed to
|
||||
// correctly.
|
||||
let x_6: C::Scalar = get_challenge_scalar(Challenge(transcript.squeeze().get_lower_128()));
|
||||
|
||||
for eval in self.q_evals.iter() {
|
||||
transcript_scalar.absorb(*eval);
|
||||
transcript.absorb_scalar(*eval);
|
||||
}
|
||||
|
||||
let transcript_scalar_point =
|
||||
C::Base::from_bytes(&(transcript_scalar.squeeze()).to_bytes()).unwrap();
|
||||
transcript.absorb(transcript_scalar_point);
|
||||
|
||||
// We can compute the expected msm_eval at x_6 using the q_evals provided
|
||||
// by the prover and from x_5
|
||||
let msm_eval = point_sets
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
//! This module contains utilities and traits for dealing with Fiat-Shamir
|
||||
//! transcripts.
|
||||
|
||||
use crate::arithmetic::Field;
|
||||
use crate::arithmetic::{CurveAffine, Field};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// This is a generic interface for a sponge function that can be used for
|
||||
/// Fiat-Shamir transformations.
|
||||
|
@ -23,9 +24,9 @@ pub struct DummyHash<F: Field> {
|
|||
}
|
||||
|
||||
impl<F: Field> Hasher<F> for DummyHash<F> {
|
||||
fn init(value: F) -> Self {
|
||||
fn init(key: F) -> Self {
|
||||
DummyHash {
|
||||
power: F::ZETA + F::one() + value,
|
||||
power: F::ZETA + F::one() + key,
|
||||
state: F::ZETA,
|
||||
}
|
||||
}
|
||||
|
@ -43,3 +44,91 @@ impl<F: Field> Hasher<F> for DummyHash<F> {
|
|||
tmp
|
||||
}
|
||||
}
|
||||
|
||||
/// A transcript that can absorb points from both the base field and scalar
|
||||
/// field of a curve
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Transcript<C: CurveAffine, HBase, HScalar>
|
||||
where
|
||||
HBase: Hasher<C::Base>,
|
||||
HScalar: Hasher<C::Scalar>,
|
||||
{
|
||||
// Hasher over the base field
|
||||
base_hasher: HBase,
|
||||
// Hasher over the scalar field
|
||||
scalar_hasher: HScalar,
|
||||
// Indicates if scalar(s) has been hashed but not squeezed
|
||||
scalar_needs_squeezing: bool,
|
||||
// PhantomData
|
||||
_marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<C: CurveAffine, HBase: Hasher<C::Base>, HScalar: Hasher<C::Scalar>>
|
||||
Transcript<C, HBase, HScalar>
|
||||
{
|
||||
/// Initialise a new transcript with Field::one() as keys
|
||||
/// in both the base_hasher and scalar_hasher
|
||||
pub fn new() -> Self {
|
||||
let base_hasher = HBase::init(C::Base::one());
|
||||
let scalar_hasher = HScalar::init(C::Scalar::one());
|
||||
Transcript {
|
||||
base_hasher,
|
||||
scalar_hasher,
|
||||
scalar_needs_squeezing: false,
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialise a new transcript with some given base_hasher and
|
||||
/// scalar_hasher
|
||||
#[cfg(test)]
|
||||
pub(crate) fn init_with_hashers(base_hasher: &HBase, scalar_hasher: &HScalar) -> Self {
|
||||
Transcript {
|
||||
base_hasher: base_hasher.clone(),
|
||||
scalar_hasher: scalar_hasher.clone(),
|
||||
scalar_needs_squeezing: false,
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn conditional_scalar_squeeze(&mut self) {
|
||||
if self.scalar_needs_squeezing {
|
||||
let transcript_scalar_point =
|
||||
C::Base::from_bytes(&(self.scalar_hasher.squeeze()).to_bytes()).unwrap();
|
||||
self.base_hasher.absorb(transcript_scalar_point);
|
||||
self.scalar_needs_squeezing = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Absorb a curve point into the transcript by absorbing
|
||||
/// its x and y coordinates
|
||||
pub fn absorb_point(&mut self, point: &C) -> Result<(), ()> {
|
||||
self.conditional_scalar_squeeze();
|
||||
let tmp = point.get_xy();
|
||||
if bool::from(tmp.is_none()) {
|
||||
return Err(());
|
||||
};
|
||||
let tmp = tmp.unwrap();
|
||||
self.base_hasher.absorb(tmp.0);
|
||||
self.base_hasher.absorb(tmp.1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Absorb a base into the base_hasher
|
||||
pub fn absorb_base(&mut self, base: C::Base) {
|
||||
self.conditional_scalar_squeeze();
|
||||
self.base_hasher.absorb(base);
|
||||
}
|
||||
|
||||
/// Absorb a scalar into the scalar_hasher
|
||||
pub fn absorb_scalar(&mut self, scalar: C::Scalar) {
|
||||
self.scalar_hasher.absorb(scalar);
|
||||
self.scalar_needs_squeezing = true;
|
||||
}
|
||||
|
||||
/// Squeeze the transcript to obtain a C::Base value.
|
||||
pub fn squeeze(&mut self) -> C::Base {
|
||||
self.conditional_scalar_squeeze();
|
||||
self.base_hasher.squeeze()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue