mirror of https://github.com/zcash/halo2.git
Merge pull request #21 from zcash/incorporate-msm
Incorporate MSM/Guard into PLONK verifier API and arithmetic
This commit is contained in:
commit
76f95b08e9
32
src/plonk.rs
32
src/plonk.rs
|
@ -71,6 +71,8 @@ pub enum Error {
|
|||
ConstraintSystemFailure,
|
||||
/// Out of bounds index passed to a backend
|
||||
BoundsFailure,
|
||||
/// Opening error
|
||||
OpeningError,
|
||||
}
|
||||
|
||||
fn hash_point<C: CurveAffine, H: Hasher<C::Base>>(
|
||||
|
@ -345,10 +347,32 @@ fn test_proving() {
|
|||
let proof = Proof::create::<DummyHash<Fq>, DummyHash<Fp>, _>(¶ms, &srs, &circuit)
|
||||
.expect("proof generation should not fail");
|
||||
|
||||
let msm_default = params.empty_msm();
|
||||
let msm = proof
|
||||
.verify::<DummyHash<Fq>, DummyHash<Fp>>(¶ms, &srs, msm_default)
|
||||
let msm = params.empty_msm();
|
||||
let guard = proof
|
||||
.verify::<DummyHash<Fq>, DummyHash<Fp>>(¶ms, &srs, msm)
|
||||
.unwrap();
|
||||
assert!(msm.is_zero())
|
||||
{
|
||||
let msm = guard.clone().use_challenges();
|
||||
assert!(msm.is_zero());
|
||||
}
|
||||
{
|
||||
let g = guard.compute_g();
|
||||
let (msm, _) = guard.clone().use_g(g);
|
||||
assert!(msm.is_zero());
|
||||
}
|
||||
let msm = guard.clone().use_challenges();
|
||||
assert!(msm.clone().is_zero());
|
||||
let guard = proof
|
||||
.verify::<DummyHash<Fq>, DummyHash<Fp>>(¶ms, &srs, msm)
|
||||
.unwrap();
|
||||
{
|
||||
let msm = guard.clone().use_challenges();
|
||||
assert!(msm.is_zero());
|
||||
}
|
||||
{
|
||||
let g = guard.compute_g();
|
||||
let (msm, _) = guard.clone().use_g(g);
|
||||
assert!(msm.is_zero());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use super::{hash_point, Error, Proof, SRS};
|
||||
use crate::arithmetic::{get_challenge_scalar, Challenge, Curve, CurveAffine, Field};
|
||||
use crate::arithmetic::{get_challenge_scalar, Challenge, CurveAffine, Field};
|
||||
use crate::poly::{
|
||||
commitment::{Params, MSM},
|
||||
commitment::{Guard, Params, MSM},
|
||||
Rotation,
|
||||
};
|
||||
use crate::transcript::Hasher;
|
||||
|
@ -12,8 +12,13 @@ impl<'a, C: CurveAffine> Proof<C> {
|
|||
&self,
|
||||
params: &'a Params<C>,
|
||||
srs: &SRS<C>,
|
||||
msm: MSM<'a, C>,
|
||||
) -> Result<MSM<'a, C>, Error> {
|
||||
mut msm: MSM<'a, C>,
|
||||
) -> Result<Guard<'a, C>, Error> {
|
||||
// Scale the MSM by a random factor to ensure that if the existing MSM
|
||||
// has is_zero() == false then this argument won't be able to interfere
|
||||
// with it to make it true, with high probability.
|
||||
msm.scale(C::Scalar::random());
|
||||
|
||||
// Create a transcript for obtaining Fiat-Shamir challenges.
|
||||
let mut transcript = HBase::init(C::Base::one());
|
||||
|
||||
|
@ -148,17 +153,12 @@ impl<'a, C: CurveAffine> Proof<C> {
|
|||
|
||||
// Compress the commitments and expected evaluations at x_3 together
|
||||
// using the challenge x_4
|
||||
let mut q_commitments: Vec<Option<C::Projective>> = vec![None; srs.cs.rotations.len()];
|
||||
let mut q_commitments: Vec<_> = vec![params.empty_msm(); srs.cs.rotations.len()];
|
||||
let mut q_evals: Vec<_> = vec![C::Scalar::zero(); srs.cs.rotations.len()];
|
||||
{
|
||||
let mut accumulate = |point_index: usize, new_commitment, eval| {
|
||||
q_commitments[point_index] = q_commitments[point_index]
|
||||
.map(|mut commitment| {
|
||||
commitment *= x_4;
|
||||
commitment += new_commitment;
|
||||
commitment
|
||||
})
|
||||
.or_else(|| Some(new_commitment.to_projective()));
|
||||
q_commitments[point_index].scale(x_4);
|
||||
q_commitments[point_index].add_term(C::Scalar::one(), new_commitment);
|
||||
q_evals[point_index] *= &x_4;
|
||||
q_evals[point_index] += &eval;
|
||||
};
|
||||
|
@ -256,29 +256,18 @@ impl<'a, C: CurveAffine> Proof<C> {
|
|||
let x_7: C::Scalar = get_challenge_scalar(Challenge(transcript.squeeze().get_lower_128()));
|
||||
|
||||
// Compute the final commitment that has to be opened
|
||||
let mut f_commitment: C::Projective = self.f_commitment.to_projective();
|
||||
let mut commitment_msm = params.empty_msm();
|
||||
commitment_msm.add_term(C::Scalar::one(), self.f_commitment);
|
||||
for (_, &point_index) in srs.cs.rotations.iter() {
|
||||
f_commitment *= x_7;
|
||||
f_commitment = f_commitment + &q_commitments[point_index.0].as_ref().unwrap();
|
||||
commitment_msm.scale(x_7);
|
||||
commitment_msm.add_msm(&q_commitments[point_index.0]);
|
||||
f_eval *= &x_7;
|
||||
f_eval += &self.q_evals[point_index.0];
|
||||
}
|
||||
|
||||
// Verify the opening proof
|
||||
let guard = self
|
||||
.opening
|
||||
.verify(
|
||||
params,
|
||||
msm,
|
||||
&mut transcript,
|
||||
x_6,
|
||||
&f_commitment.to_affine(),
|
||||
f_eval,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let msm_challenges = guard.use_challenges();
|
||||
|
||||
Ok(msm_challenges)
|
||||
self.opening
|
||||
.verify(params, msm, &mut transcript, x_6, commitment_msm, f_eval)
|
||||
.map_err(|_| Error::OpeningError)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,20 @@ pub struct MSM<'a, C: CurveAffine> {
|
|||
}
|
||||
|
||||
impl<'a, C: CurveAffine> MSM<'a, C> {
|
||||
/// Add another multiexp into this one
|
||||
pub fn add_msm(&mut self, other: &Self) {
|
||||
self.other_scalars.extend(other.other_scalars.iter());
|
||||
self.other_bases.extend(other.other_bases.iter());
|
||||
|
||||
if let Some(g_scalars) = &other.g_scalars {
|
||||
self.add_to_g(&g_scalars);
|
||||
}
|
||||
|
||||
if let Some(h_scalar) = &other.h_scalar {
|
||||
self.add_to_h(*h_scalar);
|
||||
}
|
||||
}
|
||||
|
||||
/// Add arbitrary term (the scalar and the point)
|
||||
pub fn add_term(&mut self, scalar: C::Scalar, point: C) {
|
||||
&self.other_scalars.push(scalar);
|
||||
|
@ -423,13 +437,15 @@ fn test_opening_proof() {
|
|||
} else {
|
||||
let opening_proof = opening_proof.unwrap();
|
||||
// Verify the opening proof
|
||||
let mut commitment_msm = params.empty_msm();
|
||||
commitment_msm.add_term(Field::one(), p);
|
||||
let guard = opening_proof
|
||||
.verify(
|
||||
¶ms,
|
||||
params.empty_msm(),
|
||||
&mut transcript_dup.clone(),
|
||||
x,
|
||||
&p,
|
||||
commitment_msm,
|
||||
v,
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -448,8 +464,17 @@ fn test_opening_proof() {
|
|||
|
||||
// Check another proof to populate `msm.g_scalars`
|
||||
let msm = guard.use_challenges();
|
||||
let mut commitment_msm = params.empty_msm();
|
||||
commitment_msm.add_term(Field::one(), p);
|
||||
let guard = opening_proof
|
||||
.verify(¶ms, msm, &mut transcript_dup.clone(), x, &p, v)
|
||||
.verify(
|
||||
¶ms,
|
||||
msm,
|
||||
&mut transcript_dup.clone(),
|
||||
x,
|
||||
commitment_msm,
|
||||
v,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Test use_challenges()
|
||||
|
|
|
@ -14,7 +14,7 @@ impl<C: CurveAffine> OpeningProof<C> {
|
|||
mut msm: MSM<'a, C>,
|
||||
transcript: &mut H,
|
||||
x: C::Scalar,
|
||||
p: &C,
|
||||
mut commitment_msm: MSM<'a, C>,
|
||||
v: C::Scalar,
|
||||
) -> Result<Guard<'a, C>, Error> {
|
||||
// Check for well-formedness
|
||||
|
@ -111,11 +111,13 @@ impl<C: CurveAffine> OpeningProof<C> {
|
|||
// [c] P + [c * v] U + [c] sum(L_i * u_i^2) + [c] sum(R_i * u_i^-2) + delta - [z1] G - [z1 * b] U - [z2] H
|
||||
// = 0
|
||||
|
||||
// Scale the MSM by a random factor to ensure that if the existing MSM
|
||||
// has is_zero() == false then this argument won't be able to interfere
|
||||
// with it to make it true. It's a way of keeping the MSM's linearly
|
||||
// independent.
|
||||
msm.scale(C::Scalar::random());
|
||||
let b = compute_b(x, &challenges, &challenges_inv);
|
||||
|
||||
let neg_z1 = -self.z1;
|
||||
|
||||
// [c] P
|
||||
commitment_msm.scale(c);
|
||||
msm.add_msm(&commitment_msm);
|
||||
|
||||
for scalar in &mut extra_scalars {
|
||||
*scalar *= &c;
|
||||
|
@ -125,13 +127,6 @@ impl<C: CurveAffine> OpeningProof<C> {
|
|||
msm.add_term(*scalar, *base);
|
||||
}
|
||||
|
||||
let b = compute_b(x, &challenges, &challenges_inv);
|
||||
|
||||
let neg_z1 = -self.z1;
|
||||
|
||||
// [c] P
|
||||
msm.add_term(c, *p);
|
||||
|
||||
// [c * v] U - [z1 * b] U
|
||||
msm.add_term((c * &v) + &(neg_z1 * &b), u);
|
||||
|
||||
|
|
Loading…
Reference in New Issue