-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Impl ldt test with MerkleTree. * Refact kzg. * Add commit-and-open by index for MerkleTree in ldt. * bugfix for MerkleTree.
- Loading branch information
1 parent
4b812f3
commit b1968fd
Showing
29 changed files
with
1,742 additions
and
501 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
mod param; | ||
mod prover; | ||
mod verifier; | ||
|
||
use bls12_381::Scalar; | ||
use ff::Field; | ||
use pairing::Engine; | ||
|
||
pub struct KZGProof<E: Engine> { | ||
cm: E::G1, // commit of p(x) | ||
eval: E::Fr, // eval for p(z) | ||
pi: E::G1, // aka.π, commit of q(x), q = p(x)-p(z)/x-z | ||
} | ||
|
||
impl<E: Engine> KZGProof<E> { | ||
fn new(cm: E::G1, eval: E::Fr, pi: E::G1) -> Self { | ||
Self { cm, eval, pi } | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use super::*; | ||
use crate::kzg::param::ParamKzg; | ||
use crate::kzg::prover::Prover; | ||
use crate::kzg::verifier::Verifier; | ||
use crate::poly::Polynomial; | ||
use bls12_381::Bls12; | ||
use ff::PrimeField; | ||
|
||
#[test] | ||
fn test_kzg_protocol() { | ||
let k = 4; | ||
let poly = Polynomial::random(3); | ||
|
||
// setup | ||
let param = ParamKzg::<Bls12>::setup(k); | ||
|
||
// prove | ||
let prover = Prover::init(param.clone()); | ||
let proof = prover.prover(&poly); | ||
|
||
// verify | ||
let verifier = Verifier::init(param); | ||
verifier.verify(proof); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
use crate::msm::small_multiexp; | ||
use crate::poly::Polynomial; | ||
use ff::{Field, PrimeField}; | ||
use group::prime::PrimeCurveAffine; | ||
use pairing::Engine; | ||
use rand_core::OsRng; | ||
use std::fmt::Debug; | ||
|
||
// The SRS | ||
#[derive(Clone)] | ||
pub struct ParamKzg<E: Engine> { | ||
pub(crate) k: usize, | ||
pub(crate) n: usize, | ||
pub pow_tau_g1: Vec<E::G1>, | ||
pub pow_tau_g2: Vec<E::G2>, | ||
} | ||
|
||
impl<E: Engine + Debug> ParamKzg<E> | ||
where | ||
E::Fr: PrimeField, | ||
{ | ||
fn new(k: usize) -> Self { | ||
Self::setup(k) | ||
} | ||
|
||
// Generate the SRS | ||
pub fn setup(k: usize) -> Self { | ||
let n = 1 << k; | ||
|
||
let tau = E::Fr::random(OsRng); | ||
|
||
// obtain: s, ..., s^i,..., s^n | ||
let powers_of_tau: Vec<E::Fr> = (0..n) | ||
.into_iter() | ||
.scan(E::Fr::ONE, |acc, _| { | ||
let v = *acc; | ||
*acc *= tau; | ||
Some(v) | ||
}) | ||
.collect(); | ||
|
||
// obtain [s]1 | ||
let pow_tau_g1: Vec<E::G1> = powers_of_tau | ||
.iter() | ||
.map(|tau_pow| E::G1Affine::generator() * tau_pow) | ||
.collect(); | ||
|
||
// obtain [s]2 | ||
let pow_tau_g2: Vec<E::G2> = powers_of_tau | ||
.iter() | ||
.map(|tau_pow| E::G2Affine::generator() * tau_pow) | ||
.collect(); | ||
|
||
Self { | ||
k, | ||
n, | ||
pow_tau_g1, | ||
pow_tau_g2, | ||
} | ||
} | ||
|
||
// unify ti with commit_lagrange | ||
pub fn eval_at_tau_g1(&self, poly: &Polynomial<E::Fr>) -> E::G1 { | ||
let mut scalars = Vec::with_capacity(poly.len()); | ||
scalars.extend(poly.coeffs().iter()); | ||
let bases = &self.pow_tau_g1; | ||
let size = scalars.len(); | ||
assert!(bases.len() >= size); | ||
small_multiexp(&scalars, &bases[0..size]) | ||
} | ||
|
||
pub fn eval_at_tau_g2(&self, poly: &Polynomial<E::Fr>) -> E::G2 { | ||
let mut scalars = Vec::with_capacity(poly.len()); | ||
scalars.extend(poly.coeffs().iter()); | ||
let bases = &self.pow_tau_g2; | ||
let size = scalars.len(); | ||
assert!(bases.len() >= size); | ||
small_multiexp(&scalars, &bases[0..size]) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
use crate::kzg::param::ParamKzg; | ||
use crate::kzg::KZGProof; | ||
use crate::poly::Polynomial; | ||
use crate::transcript::default::Keccak256Transcript; | ||
use crate::transcript::Transcript; | ||
use ff::{BitViewSized, Field, PrimeField}; | ||
use pairing::Engine; | ||
use std::ops::{MulAssign, SubAssign}; | ||
|
||
pub struct Prover<E: Engine> { | ||
param: ParamKzg<E>, | ||
} | ||
|
||
impl<E: Engine> Prover<E> { | ||
pub fn init(param: ParamKzg<E>) -> Self { | ||
Self { param } | ||
} | ||
|
||
pub fn prover(&self, poly: &Polynomial<E::Fr>) -> KZGProof<E> { | ||
// 1. commit | ||
let cm = self.commit(poly); | ||
|
||
// 2. challenge z. | ||
let mut transcript_1 = Keccak256Transcript::<E::Fr>::default(); | ||
let z = transcript_1.challenge(); | ||
// 3. eval z. | ||
let eval = poly.evaluate(z.clone()); | ||
|
||
// 4. open | ||
let pi = self.open(poly, &z); | ||
|
||
KZGProof::new(cm, eval, pi) | ||
} | ||
|
||
// return the commit of p | ||
fn commit(&self, poly: &Polynomial<E::Fr>) -> E::G1 { | ||
self.param.eval_at_tau_g1(poly) | ||
} | ||
|
||
// return the commit of q, aka.pi, the proof. | ||
fn open(&self, poly: &Polynomial<E::Fr>, z: &E::Fr) -> E::G1 { | ||
// q = ( p(x) - p(z) ) / x-z | ||
let q_coeff = Self::kate_division(&poly.coeffs(), z.clone()); | ||
let q = Polynomial::from_coeffs(q_coeff); | ||
// the proof is evaluating the Q at tau in G1 | ||
self.commit(&q) | ||
} | ||
|
||
// Divides polynomial `a` in `X` by `X - b` with no remainder. | ||
// q(x) = f(x)-f(z)/x-z | ||
fn kate_division(a: &Vec<E::Fr>, z: E::Fr) -> Vec<E::Fr> { | ||
let b = -z; | ||
let a = a.into_iter(); | ||
|
||
let mut q = vec![E::Fr::ZERO; a.len() - 1]; | ||
|
||
let mut tmp: E::Fr = E::Fr::ZERO; | ||
for (q, r) in q.iter_mut().rev().zip(a.rev()) { | ||
let mut lead_coeff = *r; | ||
lead_coeff.sub_assign(&tmp); | ||
*q = lead_coeff; | ||
tmp = lead_coeff; | ||
tmp.mul_assign(&b); | ||
} | ||
q | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use super::*; | ||
use crate::kzg::param::ParamKzg; | ||
use crate::kzg::prover::Prover; | ||
use crate::kzg::verifier::Verifier; | ||
use crate::poly::Polynomial; | ||
use bls12_381::{Bls12, Scalar}; | ||
use ff::{Field, PrimeField}; | ||
|
||
#[test] | ||
fn test_div() { | ||
// division: -2+x+x^2 = (x-1)(x+2) | ||
let division = vec![Scalar::from_u128(2).neg(), Scalar::ONE, Scalar::ONE]; | ||
|
||
// dividor: 2+x | ||
// dividor: -1+x | ||
let coeffs = vec![Scalar::ONE.neg(), Scalar::ONE]; | ||
let dividor = Polynomial::from_coeffs(coeffs); | ||
|
||
// target: | ||
// quotient poly: 2+x | ||
// remainder poly: 0 | ||
let target_qoutient = vec![Scalar::from_u128(2), Scalar::ONE]; | ||
|
||
// q(x) = f(x)-f(z)/x-z | ||
let z = Scalar::ONE; | ||
let actual_qoutient = Prover::<Bls12>::kate_division(&division, z); | ||
|
||
assert_eq!(actual_qoutient, target_qoutient); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// Verifies that `points` exists in `proof` | ||
|
||
use crate::kzg::param::ParamKzg; | ||
use crate::kzg::KZGProof; | ||
use crate::poly::Polynomial; | ||
use crate::transcript::default::Keccak256Transcript; | ||
use crate::transcript::Transcript; | ||
use bls12_381::Scalar; | ||
use ff::{Field, PrimeField}; | ||
use group::prime::PrimeCurveAffine; | ||
use group::Curve; | ||
use pairing::Engine; | ||
use std::fmt::Debug; | ||
use std::ops::Neg; | ||
|
||
pub struct Verifier<E: Engine> { | ||
param: ParamKzg<E>, | ||
} | ||
|
||
impl<E: Engine> Verifier<E> { | ||
pub fn init(param: ParamKzg<E>) -> Self { | ||
Self { param } | ||
} | ||
|
||
// verify proof by pairing: | ||
// check e(π, [x−z]_2 ) = e(cm−[p(z)]_1, g2) | ||
// => e(g1, g2)^{q(x)*(x-z)} = e(g1, g2)^{p(x)-p(z)} | ||
// => q(x)*(x-z) = p(x)-p(z) | ||
// -> same as Prove::open. | ||
pub fn verify(&self, proof: KZGProof<E>) { | ||
let vanish_poly = |z: E::Fr| { | ||
let coeffs = vec![z.neg(), E::Fr::ONE]; | ||
Polynomial::from_coeffs(coeffs) | ||
}; | ||
|
||
// 1. challenge z. | ||
let mut transcript_1 = Keccak256Transcript::<E::Fr>::default(); | ||
let z = transcript_1.challenge(); | ||
|
||
// 2. prepare poly for pairing. | ||
// compute: x-z | ||
let vanish_poly = vanish_poly(z); | ||
let eval_poly = Polynomial::from_coeffs(vec![proof.eval]); | ||
|
||
// 3.pairing | ||
// e(pi, [x-z]2) | ||
let e1 = E::pairing( | ||
&proof.pi.to_affine(), | ||
&self.param.eval_at_tau_g2(&vanish_poly).to_affine(), | ||
); | ||
// e(cm-[p(z)]1, g2) | ||
let e2 = E::pairing( | ||
&(proof.cm - self.param.eval_at_tau_g1(&eval_poly)).to_affine(), | ||
&E::G2Affine::generator(), | ||
); | ||
assert_eq!(e1, e2, "Verify: failed for pairing."); | ||
} | ||
} |
Oops, something went wrong.