Modify MSM and Guard structs and methods

This commit is contained in:
therealyingtong 2020-09-11 13:42:11 +08:00
parent 7255e085a4
commit d41fcf842b
No known key found for this signature in database
GPG Key ID: 179F32A1503D607E
4 changed files with 128 additions and 129 deletions

View File

@ -70,10 +70,6 @@ where
} }
/// This is a 128-bit verifier challenge. /// This is a 128-bit verifier challenge.
///
/// The verifier samples its challenge here as u^2, i.e. the square of the
/// actual challenge. This is an optimisation that is documented in Section 6.3
/// of the [Halo](https://eprint.iacr.org/2019/1021) paper.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct Challenge(pub(crate) u128); pub struct Challenge(pub(crate) u128);

View File

@ -264,11 +264,12 @@ impl<C: CurveAffine> Proof<C> {
} }
// Verify the opening proof // Verify the opening proof
let (challenges, mut guard) = self let default_msm = MSM::default(&params);
let (challenges, guard) = self
.opening .opening
.verify( .verify(
params, params,
&mut MSM::default(&params), default_msm,
&mut transcript, &mut transcript,
x_6, x_6,
&f_commitment.to_affine(), &f_commitment.to_affine(),
@ -276,8 +277,8 @@ impl<C: CurveAffine> Proof<C> {
) )
.unwrap(); .unwrap();
let msm: MSM<C> = guard.use_challenges(challenges).unwrap(); let msm: &MSM<C> = &guard.use_challenges(params, challenges).unwrap();
msm.is_zero() msm.is_zero(params)
} }
} }

View File

@ -27,60 +27,89 @@ pub struct OpeningProof<C: CurveAffine> {
/// A multiscalar multiplication in the polynomial commitment scheme /// A multiscalar multiplication in the polynomial commitment scheme
#[derive(Debug)] #[derive(Debug)]
pub struct MSM<C: CurveAffine> { pub struct MSM<C: CurveAffine> {
/// Vector of random generators /// TODO: documentation
pub g: Vec<C>, pub g_scalars: Option<Vec<C::Scalar>>,
/// Random generator /// TODO: documentation
pub h: C, pub h_scalar: Option<C::Scalar>,
/// Scalars in the multiscalar multiplication /// TODO: documentation
pub scalars: Vec<C::Scalar>, pub other_scalars: Vec<C::Scalar>,
/// Points in the multiscalar multiplication /// TODO: documentation
pub bases: Vec<C>, pub other_bases: Vec<C>,
} }
impl<'a, C: CurveAffine> MSM<C> { impl<'a, C: CurveAffine> MSM<C> {
/// Empty MSM /// Empty MSM
pub fn default(params: &'a Params<C>) -> Self { pub fn default(params: &Params<C>) -> Self {
let scalars: Vec<C::Scalar> = let g_scalars = Some(vec![C::Scalar::one(); params.n as usize]);
Vec::with_capacity(params.k as usize * 2 + 4 + params.n as usize); let h_scalar = Some(C::Scalar::one());
let bases: Vec<C> = Vec::with_capacity(params.k as usize * 2 + 4 + params.n as usize); let other_scalars: Vec<C::Scalar> = Vec::with_capacity(params.k as usize * 2 + 3);
let other_bases: Vec<C> = Vec::with_capacity(params.k as usize * 2 + 3);
MSM { MSM {
g: params.g.clone(), g_scalars,
h: params.h.clone(), h_scalar,
scalars, other_scalars,
bases, other_bases,
} }
} }
/// Add arbitrary term (the scalar and the point) /// Add arbitrary term (the scalar and the point)
pub fn add_term(&mut self, scalar: C::Scalar, point: C) { pub fn add_term(&mut self, scalar: C::Scalar, point: C) {
&self.scalars.push(scalar); &self.other_scalars.push(scalar);
&self.bases.push(point); &self.other_bases.push(point);
} }
/// Add term to g /// Add a vector of scalars to `g_scalars`
pub fn add_to_g(&mut self, point: C) { pub fn add_to_g(&mut self, scalars: Vec<C::Scalar>) {
&self.g.push(point); for (g_scalar, scalar) in self
.g_scalars
.as_mut()
.unwrap()
.iter_mut()
.zip(scalars.iter())
{
*g_scalar += &scalar;
}
} }
/// Add term to h /// Add term to h
pub fn add_to_h(&mut self, point: C) { pub fn add_to_h(&mut self, scalar: C::Scalar) {
self.h = self.h.add(point).to_affine(); self.h_scalar = Some(self.h_scalar.unwrap() + &scalar);
} }
/// Scale by a random blinding factor /// Scale all scalars in the MSM by a random blinding factor
pub fn scale(&mut self, factor: C::Scalar) { pub fn scale(&mut self, factor: C::Scalar) {
for scalar in self.scalars.iter_mut() { for g_scalar in self.g_scalars.as_mut().unwrap().iter_mut() {
*scalar *= &factor; *g_scalar *= &factor;
} }
for other_scalar in self.other_scalars.iter_mut() {
*other_scalar *= &factor;
}
self.h_scalar = Some(self.h_scalar.unwrap() * &factor);
} }
/// Perform multiexp and check that it results in zero /// Perform multiexp and check that it results in zero
pub fn is_zero(&self) -> bool { pub fn is_zero(&self, params: &'a Params<C>) -> bool {
bool::from(best_multiexp(&self.scalars, &self.bases).is_zero()) let mut scalars: Vec<C::Scalar> = vec![];
let mut bases: Vec<C> = vec![];
scalars.extend(&self.other_scalars);
bases.extend(&self.other_bases);
if let Some(h_scalar) = self.h_scalar {
scalars.push(h_scalar);
bases.push(params.h);
}
if let Some(g_scalars) = &self.g_scalars {
scalars.extend(g_scalars);
bases.extend(params.g.iter());
}
bool::from(best_multiexp(&scalars, &bases).is_zero())
} }
} }
@ -219,90 +248,70 @@ impl<C: CurveAffine> Params<C> {
/// A guard returned by the verifier /// A guard returned by the verifier
#[derive(Debug)] #[derive(Debug)]
pub struct Guard<'a, C: CurveAffine> { pub struct Guard<C: CurveAffine> {
/// Vector of random generators /// MSM
pub g: Vec<C>, msm: MSM<C>,
/// Random generator
pub h: C,
/// Negation of z1 value in the OpeningProof /// Negation of z1 value in the OpeningProof
pub neg_z1: C::Scalar, neg_z1: C::Scalar,
/// Params that were used by the verifier allinv: C::Scalar,
pub params: &'a Params<C>,
/// Scalars produced by the verifier for multiscalar multiplication challenges_sq: Vec<C::Scalar>,
pub scalars: Vec<C::Scalar>,
/// Points produced by the verifier for multiscalar multiplication
pub bases: Vec<C>,
} }
impl<'a, C: CurveAffine> Guard<'a, C> { impl<C: CurveAffine> Guard<C> {
/// Lets caller supply the challenges and obtain an MSM with updated /// Lets caller supply the challenges and obtain an MSM with updated
/// scalars and points. /// scalars and points.
pub fn use_challenges( pub fn use_challenges(
&mut self, mut self,
params: &Params<C>,
challenges_sq_packed: Vec<Challenge>, challenges_sq_packed: Vec<Challenge>,
) -> Result<MSM<C>, Error> { ) -> Result<MSM<C>, Error> {
let mut scalars: Vec<C::Scalar> = vec![];
let mut bases: Vec<C> = vec![];
scalars.extend(&self.msm.other_scalars);
bases.extend(&self.msm.other_bases);
// - [z2] H
if let Some(h_scalar) = self.msm.h_scalar {
scalars.push(h_scalar);
bases.push(params.h);
}
// - [z1] G // - [z1] G
let mut allinv = C::Scalar::one(); let mut allinv = C::Scalar::one();
let mut challenges_sq = Vec::with_capacity(self.params.k as usize); let mut challenges_sq = Vec::with_capacity(params.k as usize);
for challenge_sq_packed in challenges_sq_packed { for challenge_sq_packed in challenges_sq_packed.iter() {
let challenge_sq: C::Scalar = get_challenge_scalar(challenge_sq_packed); let challenge_sq: C::Scalar = get_challenge_scalar(*challenge_sq_packed);
challenges_sq.push(challenge_sq); challenges_sq.push(challenge_sq);
let challenge = challenge_sq.deterministic_sqrt(); let challenge = challenge_sq.deterministic_sqrt();
if challenge.is_none() {
// We didn't sample a square.
return Err(Error::OpeningError);
}
let challenge = challenge.unwrap(); let challenge = challenge.unwrap();
let challenge_inv = challenge.invert(); let challenge_inv = challenge.invert();
if bool::from(challenge_inv.is_none()) {
// We sampled zero for some reason, unlikely to happen by
// chance.
return Err(Error::OpeningError);
}
let challenge_inv = challenge_inv.unwrap(); let challenge_inv = challenge_inv.unwrap();
allinv *= &challenge_inv; allinv *= &challenge_inv;
} }
self.bases.extend(&self.g); let s = compute_s(&challenges_sq, allinv * &self.neg_z1);
let mut s = compute_s(&challenges_sq, allinv); scalars.extend(&s);
// TODO: parallelize bases.extend(&params.g);
for s in &mut s {
*s *= &self.neg_z1;
}
self.scalars.extend(s);
Ok(MSM { self.msm.g_scalars = Some(s);
g: self.g.clone(),
h: self.h.clone(), Ok(self.msm)
scalars: self.scalars.clone(),
bases: self.bases.clone(),
})
} }
/// Lets caller supply the purported G point and simply appends it to /// Lets caller supply the purported G point and simply appends it to
/// return an updated MSM. /// return an updated MSM.
pub fn use_s(&mut self, g: Vec<C>, mut s: Vec<C::Scalar>) -> Result<MSM<C>, Error> { pub fn use_g(mut self, g: C) -> Result<MSM<C>, Error> {
// - [z1] G &self.msm.other_scalars.push(self.allinv * &self.neg_z1);
self.bases.extend(&g); &self.msm.other_bases.push(g);
for s in &mut s {
*s *= &self.neg_z1;
}
self.scalars.extend(s);
Ok(MSM { Ok(self.msm)
g: self.g.clone(),
h: self.h.clone(),
scalars: self.scalars.clone(),
bases: self.bases.clone(),
})
} }
} }
@ -426,20 +435,14 @@ fn test_opening_proof() {
} else { } else {
let opening_proof = opening_proof.unwrap(); let opening_proof = opening_proof.unwrap();
// Verify the opening proof // Verify the opening proof
let (challenges, mut guard) = opening_proof let msm = MSM::default(&params);
.verify( let (challenges, guard) = opening_proof
&params, .verify(&params, msm, &mut transcript_dup, x, &p, v)
&mut MSM::default(&params),
&mut transcript_dup,
x,
&p,
v,
)
.unwrap(); .unwrap();
let msm = guard.use_challenges(challenges).unwrap(); let msm = guard.use_challenges(&params, challenges).unwrap();
assert!(msm.is_zero()); assert!(msm.is_zero(&params));
break; break;
} }
} }

View File

@ -11,12 +11,12 @@ impl<C: CurveAffine> OpeningProof<C> {
pub fn verify<'a, H: Hasher<C::Base>>( pub fn verify<'a, H: Hasher<C::Base>>(
&self, &self,
params: &'a Params<C>, params: &'a Params<C>,
msm: &mut MSM<C>, mut msm: MSM<C>,
transcript: &mut H, transcript: &mut H,
x: C::Scalar, x: C::Scalar,
p: &C, p: &C,
v: C::Scalar, v: C::Scalar,
) -> Result<(Vec<Challenge>, Guard<'a, C>), Error> { ) -> Result<(Vec<Challenge>, Guard<C>), Error> {
// Check for well-formedness // Check for well-formedness
if self.rounds.len() != params.k as usize { if self.rounds.len() != params.k as usize {
return Err(Error::OpeningError); return Err(Error::OpeningError);
@ -43,6 +43,7 @@ impl<C: CurveAffine> OpeningProof<C> {
let mut challenges_inv = Vec::with_capacity(self.rounds.len()); let mut challenges_inv = Vec::with_capacity(self.rounds.len());
let mut challenges_sq = Vec::with_capacity(self.rounds.len()); let mut challenges_sq = Vec::with_capacity(self.rounds.len());
let mut challenges_sq_packed: Vec<Challenge> = Vec::with_capacity(self.rounds.len()); let mut challenges_sq_packed: Vec<Challenge> = Vec::with_capacity(self.rounds.len());
let mut allinv = C::Scalar::one();
for round in &self.rounds { for round in &self.rounds {
// Feed L and R into the transcript. // Feed L and R into the transcript.
@ -74,13 +75,14 @@ impl<C: CurveAffine> OpeningProof<C> {
return Err(Error::OpeningError); return Err(Error::OpeningError);
} }
let challenge_inv = challenge_inv.unwrap(); let challenge_inv = challenge_inv.unwrap();
allinv *= &challenge_inv;
let challenge_sq_inv = challenge_inv.square(); let challenge_sq_inv = challenge_inv.square();
msm.scalars.push(challenge_sq); msm.other_scalars.push(challenge_sq);
msm.bases.push(round.0); msm.other_bases.push(round.0);
msm.scalars.push(challenge_sq_inv); msm.other_scalars.push(challenge_sq_inv);
msm.bases.push(round.1); msm.other_bases.push(round.1);
challenges.push(challenge); challenges.push(challenge);
challenges_inv.push(challenge_inv); challenges_inv.push(challenge_inv);
@ -106,7 +108,7 @@ 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 // [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 // = 0
for scalar in &mut msm.scalars { for scalar in &mut msm.other_scalars {
*scalar *= &c; *scalar *= &c;
} }
@ -115,28 +117,25 @@ impl<C: CurveAffine> OpeningProof<C> {
let neg_z1 = -self.z1; let neg_z1 = -self.z1;
// [c] P // [c] P
msm.bases.push(*p); msm.other_bases.push(*p);
msm.scalars.push(c); msm.other_scalars.push(c);
// [c * v] U - [z1 * b] U // [c * v] U - [z1 * b] U
msm.bases.push(u); msm.other_bases.push(u);
msm.scalars.push((c * &v) + &(neg_z1 * &b)); msm.other_scalars.push((c * &v) + &(neg_z1 * &b));
// delta // delta
msm.bases.push(self.delta); msm.other_bases.push(self.delta);
msm.scalars.push(Field::one()); msm.other_scalars.push(Field::one());
// - [z2] H // z2
msm.bases.push(msm.h); msm.h_scalar = Some(-self.z2);
msm.scalars.push(-self.z2);
let guard = Guard::<'a, _> { let guard = Guard {
g: msm.g.clone(), msm,
h: msm.h.clone(),
neg_z1, neg_z1,
params, allinv,
scalars: msm.scalars.clone(), challenges_sq,
bases: msm.bases.clone(),
}; };
Ok((challenges_sq_packed, guard)) Ok((challenges_sq_packed, guard))