implemented parallelized kate division, with a lot of TODOs
This commit is contained in:
parent
6e784deda8
commit
2173354b1f
@ -32,8 +32,8 @@ git = "https://github.com/gtank/blake2-rfc"
|
|||||||
rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9"
|
rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["multicore"]
|
#default = ["multicore"]
|
||||||
#default = ["multicore", "gm17", "sonic"]
|
default = ["multicore", "gm17", "sonic"]
|
||||||
#default = ["singlecore"]
|
#default = ["singlecore"]
|
||||||
multicore = ["futures-cpupool", "num_cpus", "crossbeam"]
|
multicore = ["futures-cpupool", "num_cpus", "crossbeam"]
|
||||||
sonic = ["tiny-keccak"]
|
sonic = ["tiny-keccak"]
|
||||||
|
@ -20,8 +20,14 @@ Initial SONIC proof system integration using the code from the [original impleme
|
|||||||
- [x] Basic Ethereum smart-contract
|
- [x] Basic Ethereum smart-contract
|
||||||
- [x] Add blinding factors
|
- [x] Add blinding factors
|
||||||
- [ ] Implement unhelped version
|
- [ ] Implement unhelped version
|
||||||
- [x] Implement a part of S poly precomputation (S2)
|
- [x] Implement a part of S poly precomputation (S_2)
|
||||||
- [x] Implement a "well formed" argument
|
- [x] Implement a "well formed" argument
|
||||||
- [x] Implement a coefficients product argument
|
- [x] Implement a coefficients product argument
|
||||||
- [ ] Implement a premutation argument
|
- [x] Implement a premutation argument
|
||||||
- [ ] Implement synthesizer for proper form of S polynomial
|
- [ ] Implement synthesizer for proper form of S polynomial
|
||||||
|
- [ ] Finer tuning
|
||||||
|
- [x] Parallelized evaluation of S polynomial
|
||||||
|
- [ ] Parallelize some polynomial operations in the protocol itself
|
||||||
|
- [x] Parallelized kate division
|
||||||
|
- [ ] Implement specialized version of polynomial multiplication by degree 1 polynomial
|
||||||
|
- [ ] Non-assigning variant of the "adaptor" (may require a change of SONIC CS trait)
|
@ -209,50 +209,6 @@ impl SynthesisDriver for Basic {
|
|||||||
|
|
||||||
circuit.synthesize(&mut tmp)?;
|
circuit.synthesize(&mut tmp)?;
|
||||||
|
|
||||||
// let blindings_to_add = 6;
|
|
||||||
|
|
||||||
// for i in 0..blindings_to_add {
|
|
||||||
|
|
||||||
// match tmp.current_variable.take() {
|
|
||||||
// Some(index) => {
|
|
||||||
// let var_a = Variable::A(index);
|
|
||||||
// let var_b = Variable::B(index);
|
|
||||||
// let var_c = Variable::C(index);
|
|
||||||
|
|
||||||
// let mut product = None;
|
|
||||||
|
|
||||||
// let value_a = tmp.backend.get_var(var_a);
|
|
||||||
|
|
||||||
// tmp.backend.set_var(var_b, || {
|
|
||||||
// let value_b = E::Fr::one();
|
|
||||||
// product = Some(value_a.ok_or(SynthesisError::AssignmentMissing)?);
|
|
||||||
// product.as_mut().map(|product| product.mul_assign(&value_b));
|
|
||||||
|
|
||||||
// Ok(value_b)
|
|
||||||
// })?;
|
|
||||||
|
|
||||||
// tmp.backend.set_var(var_c, || {
|
|
||||||
// product.ok_or(SynthesisError::AssignmentMissing)
|
|
||||||
// })?;
|
|
||||||
|
|
||||||
// tmp.current_variable = None;
|
|
||||||
// },
|
|
||||||
// None => {
|
|
||||||
// self.n += 1;
|
|
||||||
// let index = self.n ;
|
|
||||||
// tmp.backend.new_multiplication_gate();
|
|
||||||
|
|
||||||
// let var_a = Variable::A(index);
|
|
||||||
|
|
||||||
// tmp.backend.set_var(var_a, value)?;
|
|
||||||
|
|
||||||
// tmp.current_variable = Some(index);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// TODO: add blinding factors so we actually get zero-knowledge
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -357,10 +313,6 @@ impl SynthesisDriver for Nonassigning {
|
|||||||
|
|
||||||
circuit.synthesize(&mut tmp)?;
|
circuit.synthesize(&mut tmp)?;
|
||||||
|
|
||||||
// TODO: add blinding factors so we actually get zero-knowledge
|
|
||||||
|
|
||||||
// println!("n = {}", tmp.n);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -383,7 +383,6 @@ pub fn generate_parameters<E, C>(
|
|||||||
{
|
{
|
||||||
let circuit_parameters = get_circuit_parameters::<E, C>(circuit)?;
|
let circuit_parameters = get_circuit_parameters::<E, C>(circuit)?;
|
||||||
let min_d = circuit_parameters.n * 4 + 2*NUM_BLINDINGS;
|
let min_d = circuit_parameters.n * 4 + 2*NUM_BLINDINGS;
|
||||||
println!{"Mid d = {}", min_d};
|
|
||||||
|
|
||||||
let srs = generate_srs(alpha, x, min_d)?;
|
let srs = generate_srs(alpha, x, min_d)?;
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ pub fn create_aggregate_on_srs<E: Engine, C: Circuit<E>, S: SynthesisDriver>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut tmp = CountN{n:0,q:0};
|
let mut tmp = CountN{n:0, q:0};
|
||||||
S::synthesize(&mut tmp, circuit).unwrap(); // TODO
|
S::synthesize(&mut tmp, circuit).unwrap(); // TODO
|
||||||
|
|
||||||
(tmp.n, tmp.q)
|
(tmp.n, tmp.q)
|
||||||
@ -139,23 +139,28 @@ pub fn create_aggregate_on_srs_using_information<E: Engine, C: Circuit<E>, S: Sy
|
|||||||
// Let's open up C to every y.
|
// Let's open up C to every y.
|
||||||
fn compute_value<E: Engine>(y: &E::Fr, poly_positive: &[E::Fr], poly_negative: &[E::Fr]) -> E::Fr {
|
fn compute_value<E: Engine>(y: &E::Fr, poly_positive: &[E::Fr], poly_negative: &[E::Fr]) -> E::Fr {
|
||||||
let mut value = E::Fr::zero();
|
let mut value = E::Fr::zero();
|
||||||
|
|
||||||
let yinv = y.inverse().unwrap(); // TODO
|
let yinv = y.inverse().unwrap(); // TODO
|
||||||
let mut tmp = yinv;
|
|
||||||
for &coeff in poly_negative {
|
|
||||||
let mut coeff = coeff;
|
|
||||||
coeff.mul_assign(&tmp);
|
|
||||||
value.add_assign(&coeff);
|
|
||||||
tmp.mul_assign(&yinv);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut tmp = *y;
|
let positive_powers_contrib = evaluate_at_consequitive_powers(poly_positive, *y, *y);
|
||||||
for &coeff in poly_positive {
|
let negative_powers_contrib = evaluate_at_consequitive_powers(poly_negative, yinv, yinv);
|
||||||
let mut coeff = coeff;
|
value.add_assign(&positive_powers_contrib);
|
||||||
coeff.mul_assign(&tmp);
|
value.add_assign(&negative_powers_contrib);
|
||||||
value.add_assign(&coeff);
|
|
||||||
tmp.mul_assign(&y);
|
// let mut tmp = yinv;
|
||||||
}
|
// for &coeff in poly_negative {
|
||||||
|
// let mut coeff = coeff;
|
||||||
|
// coeff.mul_assign(&tmp);
|
||||||
|
// value.add_assign(&coeff);
|
||||||
|
// tmp.mul_assign(&yinv);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let mut tmp = *y;
|
||||||
|
// for &coeff in poly_positive {
|
||||||
|
// let mut coeff = coeff;
|
||||||
|
// coeff.mul_assign(&tmp);
|
||||||
|
// value.add_assign(&coeff);
|
||||||
|
// tmp.mul_assign(&y);
|
||||||
|
// }
|
||||||
|
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ use std::marker::PhantomData;
|
|||||||
|
|
||||||
use crate::sonic::cs::{Backend};
|
use crate::sonic::cs::{Backend};
|
||||||
use crate::sonic::cs::{Coeff, Variable, LinearCombination};
|
use crate::sonic::cs::{Coeff, Variable, LinearCombination};
|
||||||
|
use crate::sonic::util::*;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
s(X, Y) = \sum\limits_{i=1}^N u_i(Y) X^{-i}
|
s(X, Y) = \sum\limits_{i=1}^N u_i(Y) X^{-i}
|
||||||
@ -71,26 +72,33 @@ impl<E: Engine> SxEval<E> {
|
|||||||
pub fn finalize(self, x: E::Fr) -> E::Fr {
|
pub fn finalize(self, x: E::Fr) -> E::Fr {
|
||||||
let x_inv = x.inverse().unwrap(); // TODO
|
let x_inv = x.inverse().unwrap(); // TODO
|
||||||
|
|
||||||
let mut tmp = x_inv;
|
|
||||||
|
|
||||||
let mut acc = E::Fr::zero();
|
let mut acc = E::Fr::zero();
|
||||||
for mut u in self.u {
|
|
||||||
u.mul_assign(&tmp);
|
|
||||||
acc.add_assign(&u);
|
|
||||||
tmp.mul_assign(&x_inv);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
let mut tmp = x_inv;
|
||||||
|
acc.add_assign(&evaluate_at_consequitive_powers(& self.u[..], tmp, tmp));
|
||||||
let mut tmp = x;
|
let mut tmp = x;
|
||||||
for mut v in self.v {
|
acc.add_assign(&evaluate_at_consequitive_powers(& self.v[..], tmp, tmp));
|
||||||
v.mul_assign(&tmp);
|
let mut tmp = x.pow(&[(self.v.len()+1) as u64]);
|
||||||
acc.add_assign(&v);
|
acc.add_assign(&evaluate_at_consequitive_powers(& self.w[..], tmp, x));
|
||||||
tmp.mul_assign(&x);
|
|
||||||
}
|
// let mut tmp = x_inv;
|
||||||
for mut w in self.w {
|
// for mut u in self.u {
|
||||||
w.mul_assign(&tmp);
|
// u.mul_assign(&tmp);
|
||||||
acc.add_assign(&w);
|
// acc.add_assign(&u);
|
||||||
tmp.mul_assign(&x);
|
// tmp.mul_assign(&x_inv);
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
// let mut tmp = x;
|
||||||
|
// for mut v in self.v {
|
||||||
|
// v.mul_assign(&tmp);
|
||||||
|
// acc.add_assign(&v);
|
||||||
|
// tmp.mul_assign(&x);
|
||||||
|
// }
|
||||||
|
// for mut w in self.w {
|
||||||
|
// w.mul_assign(&tmp);
|
||||||
|
// acc.add_assign(&w);
|
||||||
|
// tmp.mul_assign(&x);
|
||||||
|
// }
|
||||||
|
|
||||||
acc
|
acc
|
||||||
}
|
}
|
||||||
@ -209,20 +217,26 @@ impl<E: Engine> SyEval<E> {
|
|||||||
|
|
||||||
pub fn finalize(self, y: E::Fr) -> E::Fr {
|
pub fn finalize(self, y: E::Fr) -> E::Fr {
|
||||||
let mut acc = E::Fr::zero();
|
let mut acc = E::Fr::zero();
|
||||||
|
|
||||||
let mut tmp = y;
|
|
||||||
for mut coeff in self.positive_coeffs {
|
|
||||||
coeff.mul_assign(&tmp);
|
|
||||||
acc.add_assign(&coeff);
|
|
||||||
tmp.mul_assign(&y);
|
|
||||||
}
|
|
||||||
let yinv = y.inverse().unwrap(); // TODO
|
let yinv = y.inverse().unwrap(); // TODO
|
||||||
let mut tmp = yinv;
|
|
||||||
for mut coeff in self.negative_coeffs {
|
let positive_powers_contrib = evaluate_at_consequitive_powers(& self.positive_coeffs[..], y, y);
|
||||||
coeff.mul_assign(&tmp);
|
let negative_powers_contrib = evaluate_at_consequitive_powers(& self.negative_coeffs[..], yinv, yinv);
|
||||||
acc.add_assign(&coeff);
|
acc.add_assign(&positive_powers_contrib);
|
||||||
tmp.mul_assign(&yinv);
|
acc.add_assign(&negative_powers_contrib);
|
||||||
}
|
|
||||||
|
// let mut tmp = y;
|
||||||
|
// for mut coeff in self.positive_coeffs {
|
||||||
|
// coeff.mul_assign(&tmp);
|
||||||
|
// acc.add_assign(&coeff);
|
||||||
|
// tmp.mul_assign(&y);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let mut tmp = yinv;
|
||||||
|
// for mut coeff in self.negative_coeffs {
|
||||||
|
// coeff.mul_assign(&tmp);
|
||||||
|
// acc.add_assign(&coeff);
|
||||||
|
// tmp.mul_assign(&yinv);
|
||||||
|
// }
|
||||||
|
|
||||||
acc
|
acc
|
||||||
}
|
}
|
||||||
|
@ -310,23 +310,6 @@ pub fn create_proof_on_srs<E: Engine, C: Circuit<E>, S: SynthesisDriver>(
|
|||||||
evaluate_at_consequitive_powers(&rx1, tmp, z)
|
evaluate_at_consequitive_powers(&rx1, tmp, z)
|
||||||
};
|
};
|
||||||
|
|
||||||
// {
|
|
||||||
// rx1[(2 * n + NUM_BLINDINGS)].sub_assign(&rz);
|
|
||||||
|
|
||||||
// let opening = polynomial_commitment_opening(
|
|
||||||
// 2 * n + NUM_BLINDINGS,
|
|
||||||
// n,
|
|
||||||
// rx1.iter(),
|
|
||||||
// z,
|
|
||||||
// srs
|
|
||||||
// );
|
|
||||||
|
|
||||||
// let valid_rz_commitment = check_polynomial_commitment(&r, &z, &rz, &opening, n, &srs);
|
|
||||||
// assert!(valid_rz_commitment);
|
|
||||||
|
|
||||||
// rx1[(2 * n + NUM_BLINDINGS)].add_assign(&rz);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// rzy is evaluation of r(X, Y) at z, y
|
// rzy is evaluation of r(X, Y) at z, y
|
||||||
let rzy = {
|
let rzy = {
|
||||||
let tmp = z_inv.pow(&[(2*n + NUM_BLINDINGS) as u64]);
|
let tmp = z_inv.pow(&[(2*n + NUM_BLINDINGS) as u64]);
|
||||||
@ -385,11 +368,6 @@ pub fn create_proof_on_srs<E: Engine, C: Circuit<E>, S: SynthesisDriver>(
|
|||||||
srs)
|
srs)
|
||||||
};
|
};
|
||||||
|
|
||||||
// let mut zy = z;
|
|
||||||
// zy.mul_assign(&y);
|
|
||||||
// let valid_rzy_commitment = check_polynomial_commitment(&r, &zy, &rzy, &zy_opening, n, &srs);
|
|
||||||
// assert!(valid_rzy_commitment);
|
|
||||||
|
|
||||||
Ok(Proof {
|
Ok(Proof {
|
||||||
r, rz, rzy, t, z_opening, zy_opening
|
r, rz, rzy, t, z_opening, zy_opening
|
||||||
})
|
})
|
||||||
|
1
src/sonic/tests/mod.rs
Normal file
1
src/sonic/tests/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
mod sonics;
|
@ -1,5 +1,3 @@
|
|||||||
extern crate bellman;
|
|
||||||
extern crate pairing;
|
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
|
|
||||||
// For randomness (during paramgen and proof generation)
|
// For randomness (during paramgen and proof generation)
|
||||||
@ -27,23 +25,131 @@ use pairing::bn256::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
// We'll use these interfaces to construct our circuit.
|
// We'll use these interfaces to construct our circuit.
|
||||||
use bellman::{
|
use crate::{
|
||||||
Circuit,
|
Circuit,
|
||||||
ConstraintSystem,
|
ConstraintSystem,
|
||||||
SynthesisError
|
SynthesisError
|
||||||
};
|
};
|
||||||
|
|
||||||
// We're going to use the Groth16 proving system.
|
|
||||||
use bellman::groth16::{
|
|
||||||
Proof,
|
|
||||||
generate_random_parameters,
|
|
||||||
prepare_verifying_key,
|
|
||||||
create_random_proof,
|
|
||||||
verify_proof,
|
|
||||||
};
|
|
||||||
|
|
||||||
const MIMC_ROUNDS: usize = 322;
|
const MIMC_ROUNDS: usize = 322;
|
||||||
|
|
||||||
|
fn mimc<E: Engine>(
|
||||||
|
mut xl: E::Fr,
|
||||||
|
mut xr: E::Fr,
|
||||||
|
constants: &[E::Fr]
|
||||||
|
) -> E::Fr
|
||||||
|
{
|
||||||
|
assert_eq!(constants.len(), MIMC_ROUNDS);
|
||||||
|
|
||||||
|
for i in 0..MIMC_ROUNDS {
|
||||||
|
let mut tmp1 = xl;
|
||||||
|
tmp1.add_assign(&constants[i]);
|
||||||
|
let mut tmp2 = tmp1;
|
||||||
|
tmp2.square();
|
||||||
|
tmp2.mul_assign(&tmp1);
|
||||||
|
tmp2.add_assign(&xr);
|
||||||
|
xr = xl;
|
||||||
|
xl = tmp2;
|
||||||
|
}
|
||||||
|
|
||||||
|
xl
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is our demo circuit for proving knowledge of the
|
||||||
|
/// preimage of a MiMC hash invocation.
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct MiMCDemo<'a, E: Engine> {
|
||||||
|
xl: Option<E::Fr>,
|
||||||
|
xr: Option<E::Fr>,
|
||||||
|
constants: &'a [E::Fr]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Our demo circuit implements this `Circuit` trait which
|
||||||
|
/// is used during paramgen and proving in order to
|
||||||
|
/// synthesize the constraint system.
|
||||||
|
impl<'a, E: Engine> Circuit<E> for MiMCDemo<'a, E> {
|
||||||
|
fn synthesize<CS: ConstraintSystem<E>>(
|
||||||
|
self,
|
||||||
|
cs: &mut CS
|
||||||
|
) -> Result<(), SynthesisError>
|
||||||
|
{
|
||||||
|
assert_eq!(self.constants.len(), MIMC_ROUNDS);
|
||||||
|
|
||||||
|
// Allocate the first component of the preimage.
|
||||||
|
let mut xl_value = self.xl;
|
||||||
|
let mut xl = cs.alloc(|| "preimage xl", || {
|
||||||
|
xl_value.ok_or(SynthesisError::AssignmentMissing)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// Allocate the second component of the preimage.
|
||||||
|
let mut xr_value = self.xr;
|
||||||
|
let mut xr = cs.alloc(|| "preimage xr", || {
|
||||||
|
xr_value.ok_or(SynthesisError::AssignmentMissing)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
for i in 0..MIMC_ROUNDS {
|
||||||
|
// xL, xR := xR + (xL + Ci)^3, xL
|
||||||
|
let cs = &mut cs.namespace(|| format!("round {}", i));
|
||||||
|
|
||||||
|
// tmp = (xL + Ci)^2
|
||||||
|
let tmp_value = xl_value.map(|mut e| {
|
||||||
|
e.add_assign(&self.constants[i]);
|
||||||
|
e.square();
|
||||||
|
e
|
||||||
|
});
|
||||||
|
let tmp = cs.alloc(|| "tmp", || {
|
||||||
|
tmp_value.ok_or(SynthesisError::AssignmentMissing)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
cs.enforce(
|
||||||
|
|| "tmp = (xL + Ci)^2",
|
||||||
|
|lc| lc + xl + (self.constants[i], CS::one()),
|
||||||
|
|lc| lc + xl + (self.constants[i], CS::one()),
|
||||||
|
|lc| lc + tmp
|
||||||
|
);
|
||||||
|
|
||||||
|
// new_xL = xR + (xL + Ci)^3
|
||||||
|
// new_xL = xR + tmp * (xL + Ci)
|
||||||
|
// new_xL - xR = tmp * (xL + Ci)
|
||||||
|
let new_xl_value = xl_value.map(|mut e| {
|
||||||
|
e.add_assign(&self.constants[i]);
|
||||||
|
e.mul_assign(&tmp_value.unwrap());
|
||||||
|
e.add_assign(&xr_value.unwrap());
|
||||||
|
e
|
||||||
|
});
|
||||||
|
|
||||||
|
let new_xl = if i == (MIMC_ROUNDS-1) {
|
||||||
|
// This is the last round, xL is our image and so
|
||||||
|
// we allocate a public input.
|
||||||
|
cs.alloc_input(|| "image", || {
|
||||||
|
new_xl_value.ok_or(SynthesisError::AssignmentMissing)
|
||||||
|
})?
|
||||||
|
} else {
|
||||||
|
cs.alloc(|| "new_xl", || {
|
||||||
|
new_xl_value.ok_or(SynthesisError::AssignmentMissing)
|
||||||
|
})?
|
||||||
|
};
|
||||||
|
|
||||||
|
cs.enforce(
|
||||||
|
|| "new_xL = xR + (xL + Ci)^3",
|
||||||
|
|lc| lc + tmp,
|
||||||
|
|lc| lc + xl + (self.constants[i], CS::one()),
|
||||||
|
|lc| lc + new_xl - xr
|
||||||
|
);
|
||||||
|
|
||||||
|
// xR = xL
|
||||||
|
xr = xl;
|
||||||
|
xr_value = xl_value;
|
||||||
|
|
||||||
|
// xL = new_xL
|
||||||
|
xl = new_xl;
|
||||||
|
xl_value = new_xl_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// This is our demo circuit for proving knowledge of the
|
/// This is our demo circuit for proving knowledge of the
|
||||||
/// preimage of a MiMC hash invocation.
|
/// preimage of a MiMC hash invocation.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -147,7 +253,7 @@ fn test_sonic_mimc() {
|
|||||||
use pairing::{Engine, CurveAffine, CurveProjective};
|
use pairing::{Engine, CurveAffine, CurveProjective};
|
||||||
use pairing::bls12_381::{Bls12, Fr};
|
use pairing::bls12_381::{Bls12, Fr};
|
||||||
use std::time::{Instant};
|
use std::time::{Instant};
|
||||||
use bellman::sonic::srs::SRS;
|
use crate::sonic::srs::SRS;
|
||||||
|
|
||||||
let srs_x = Fr::from_str("23923").unwrap();
|
let srs_x = Fr::from_str("23923").unwrap();
|
||||||
let srs_alpha = Fr::from_str("23728792").unwrap();
|
let srs_alpha = Fr::from_str("23728792").unwrap();
|
||||||
@ -178,11 +284,11 @@ fn test_sonic_mimc() {
|
|||||||
constants: &constants
|
constants: &constants
|
||||||
};
|
};
|
||||||
|
|
||||||
use bellman::sonic::cs::Basic;
|
use crate::sonic::cs::Basic;
|
||||||
use bellman::sonic::sonic::AdaptorCircuit;
|
use crate::sonic::sonic::AdaptorCircuit;
|
||||||
use bellman::sonic::helped::prover::{create_advice_on_srs, create_proof_on_srs};
|
use crate::sonic::helped::prover::{create_advice_on_srs, create_proof_on_srs};
|
||||||
use bellman::sonic::helped::{MultiVerifier, get_circuit_parameters};
|
use crate::sonic::helped::{MultiVerifier, get_circuit_parameters};
|
||||||
use bellman::sonic::helped::helper::{create_aggregate_on_srs};
|
use crate::sonic::helped::helper::{create_aggregate_on_srs};
|
||||||
|
|
||||||
println!("creating proof");
|
println!("creating proof");
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
@ -252,7 +358,7 @@ fn test_inputs_into_sonic_mimc() {
|
|||||||
use pairing::bn256::{Bn256, Fr};
|
use pairing::bn256::{Bn256, Fr};
|
||||||
// use pairing::bls12_381::{Bls12, Fr};
|
// use pairing::bls12_381::{Bls12, Fr};
|
||||||
use std::time::{Instant};
|
use std::time::{Instant};
|
||||||
use bellman::sonic::srs::SRS;
|
use crate::sonic::srs::SRS;
|
||||||
|
|
||||||
let srs_x = Fr::from_str("23923").unwrap();
|
let srs_x = Fr::from_str("23923").unwrap();
|
||||||
let srs_alpha = Fr::from_str("23728792").unwrap();
|
let srs_alpha = Fr::from_str("23728792").unwrap();
|
||||||
@ -282,11 +388,11 @@ fn test_inputs_into_sonic_mimc() {
|
|||||||
constants: &constants
|
constants: &constants
|
||||||
};
|
};
|
||||||
|
|
||||||
use bellman::sonic::cs::Basic;
|
use crate::sonic::cs::Basic;
|
||||||
use bellman::sonic::sonic::AdaptorCircuit;
|
use crate::sonic::sonic::AdaptorCircuit;
|
||||||
use bellman::sonic::helped::prover::{create_advice_on_srs, create_proof_on_srs};
|
use crate::sonic::helped::prover::{create_advice_on_srs, create_proof_on_srs};
|
||||||
use bellman::sonic::helped::{MultiVerifier, get_circuit_parameters};
|
use crate::sonic::helped::{MultiVerifier, get_circuit_parameters};
|
||||||
use bellman::sonic::helped::helper::{create_aggregate_on_srs};
|
use crate::sonic::helped::helper::{create_aggregate_on_srs};
|
||||||
|
|
||||||
let info = get_circuit_parameters::<Bn256, _>(circuit.clone()).expect("Must get circuit info");
|
let info = get_circuit_parameters::<Bn256, _>(circuit.clone()).expect("Must get circuit info");
|
||||||
println!("{:?}", info);
|
println!("{:?}", info);
|
||||||
@ -356,7 +462,7 @@ fn test_inputs_into_sonic_mimc() {
|
|||||||
fn test_high_level_sonic_api() {
|
fn test_high_level_sonic_api() {
|
||||||
use pairing::bn256::{Bn256};
|
use pairing::bn256::{Bn256};
|
||||||
use std::time::{Instant};
|
use std::time::{Instant};
|
||||||
use bellman::sonic::helped::{
|
use crate::sonic::helped::{
|
||||||
generate_random_parameters,
|
generate_random_parameters,
|
||||||
verify_aggregate,
|
verify_aggregate,
|
||||||
verify_proofs,
|
verify_proofs,
|
||||||
|
@ -123,10 +123,12 @@ pub fn polynomial_commitment_opening<
|
|||||||
) -> E::G1Affine
|
) -> E::G1Affine
|
||||||
where I::IntoIter: DoubleEndedIterator + ExactSizeIterator,
|
where I::IntoIter: DoubleEndedIterator + ExactSizeIterator,
|
||||||
{
|
{
|
||||||
let poly = kate_divison(
|
let poly = parallel_kate_divison::<E, _>(polynomial_coefficients, point);
|
||||||
polynomial_coefficients,
|
|
||||||
point,
|
// let poly = kate_divison(
|
||||||
);
|
// polynomial_coefficients,
|
||||||
|
// point,
|
||||||
|
// );
|
||||||
|
|
||||||
let negative_poly = poly[0..largest_negative_power].iter().rev();
|
let negative_poly = poly[0..largest_negative_power].iter().rev();
|
||||||
let positive_poly = poly[largest_negative_power..].iter();
|
let positive_poly = poly[largest_negative_power..].iter();
|
||||||
@ -400,6 +402,75 @@ where
|
|||||||
q
|
q
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Divides polynomial `a` in `x` by `x - b` with
|
||||||
|
/// no remainder using fft.
|
||||||
|
pub fn parallel_kate_divison<'a, E: Engine, I: IntoIterator<Item = &'a E::Fr>>(a: I, mut b: E::Fr) -> Vec<E::Fr>
|
||||||
|
where
|
||||||
|
I::IntoIter: DoubleEndedIterator + ExactSizeIterator,
|
||||||
|
{
|
||||||
|
// this implementation is only for division by `x - b` form polynomail,
|
||||||
|
// so we can manuall calculate the reciproical poly of the form `x^2/(x-b)`
|
||||||
|
// and the reminder
|
||||||
|
|
||||||
|
// x^2 /(x - b) = x + b*x/(x - b) = (x + b) + b^2/(x - b)
|
||||||
|
|
||||||
|
let reciproical = vec![b, E::Fr::one()]; // x + b
|
||||||
|
|
||||||
|
// and remainder b^2
|
||||||
|
let mut b_squared = b;
|
||||||
|
b_squared.square();
|
||||||
|
|
||||||
|
let mut b_neg = b;
|
||||||
|
b_neg.negate();
|
||||||
|
|
||||||
|
let divisor = vec![b_neg, E::Fr::one()];
|
||||||
|
|
||||||
|
let poly: Vec<E::Fr> = a.into_iter().map(|el| el.clone()).collect();
|
||||||
|
|
||||||
|
let (q, _) = kate_divison_inner::<E>(poly, divisor, reciproical, b_squared);
|
||||||
|
|
||||||
|
// assert_eq!(r.len(), 0);
|
||||||
|
|
||||||
|
q
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kate_divison_inner<E: Engine>(
|
||||||
|
poly: Vec<E::Fr>,
|
||||||
|
divisor: Vec<E::Fr>,
|
||||||
|
reciproical: Vec<E::Fr>,
|
||||||
|
remainder: E::Fr
|
||||||
|
) -> (Vec<E::Fr>, Vec<E::Fr>) {
|
||||||
|
if poly.len() == 1 {
|
||||||
|
return (vec![], poly);
|
||||||
|
}
|
||||||
|
// TODO: Change generic multiplications by multiplications by degree 1 polynomial
|
||||||
|
let poly_degree = poly.len() - 1;
|
||||||
|
let mut q = multiply_polynomials::<E>(poly.clone(), reciproical.clone());
|
||||||
|
q.drain(0..2);
|
||||||
|
// recursion step
|
||||||
|
if poly_degree > 2 {
|
||||||
|
let mut rec_step = poly.clone();
|
||||||
|
mul_polynomial_by_scalar(&mut rec_step[..], remainder);
|
||||||
|
// truncate low order terms
|
||||||
|
rec_step.drain(0..2);
|
||||||
|
let (q2, _) = kate_divison_inner::<E>(rec_step, divisor.clone(), reciproical, remainder);
|
||||||
|
// length of q2 is smaller
|
||||||
|
add_polynomials(&mut q[..q2.len()], &q2[..]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// although r must be zero, calculate it for now
|
||||||
|
if q.len() == 0 {
|
||||||
|
return (q, poly);
|
||||||
|
}
|
||||||
|
|
||||||
|
// r = u - v*q
|
||||||
|
let mut poly = poly;
|
||||||
|
let tmp = multiply_polynomials::<E>(divisor, q.clone());
|
||||||
|
sub_polynomials(&mut poly[..], &tmp[..]);
|
||||||
|
|
||||||
|
return (q, poly);
|
||||||
|
}
|
||||||
|
|
||||||
/// Convenience function to check polynomail commitment
|
/// Convenience function to check polynomail commitment
|
||||||
pub fn check_polynomial_commitment<E: Engine>(
|
pub fn check_polynomial_commitment<E: Engine>(
|
||||||
commitment: &E::G1Affine,
|
commitment: &E::G1Affine,
|
||||||
@ -524,6 +595,90 @@ pub fn multiply_polynomials<E: Engine>(a: Vec<E::Fr>, b: Vec<E::Fr>) -> Vec<E::F
|
|||||||
mul_result
|
mul_result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// alternative implementation that does not require an `Evaluation domain` struct
|
||||||
|
pub fn multiply_polynomials_fft<E: Engine>(a: Vec<E::Fr>, b: Vec<E::Fr>) -> Vec<E::Fr> {
|
||||||
|
use crate::multicore::Worker;
|
||||||
|
use crate::domain::{best_fft, Scalar};
|
||||||
|
use crate::group::Group;
|
||||||
|
|
||||||
|
let result_len = a.len() + b.len() - 1;
|
||||||
|
|
||||||
|
// m is a size of domain where Z polynomial does NOT vanish
|
||||||
|
// in normal domain Z is in a form of (X-1)(X-2)...(X-N)
|
||||||
|
let mut m = 1;
|
||||||
|
let mut exp = 0;
|
||||||
|
let mut omega = E::Fr::root_of_unity();
|
||||||
|
let max_degree = (1 << E::Fr::S) - 1;
|
||||||
|
|
||||||
|
if result_len > max_degree {
|
||||||
|
panic!("multiplication result degree is too large");
|
||||||
|
}
|
||||||
|
|
||||||
|
while m < result_len {
|
||||||
|
m *= 2;
|
||||||
|
exp += 1;
|
||||||
|
|
||||||
|
// The pairing-friendly curve may not be able to support
|
||||||
|
// large enough (radix2) evaluation domains.
|
||||||
|
if exp > E::Fr::S {
|
||||||
|
panic!("multiplication result degree is too large");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If full domain is not needed - limit it,
|
||||||
|
// e.g. if (2^N)th power is not required, just double omega and get 2^(N-1)th
|
||||||
|
// Compute omega, the 2^exp primitive root of unity
|
||||||
|
for _ in exp..E::Fr::S {
|
||||||
|
omega.square();
|
||||||
|
}
|
||||||
|
|
||||||
|
let omegainv = omega.inverse().unwrap();
|
||||||
|
let minv = E::Fr::from_str(&format!("{}", m)).unwrap().inverse().unwrap();
|
||||||
|
|
||||||
|
let worker = Worker::new();
|
||||||
|
|
||||||
|
let mut scalars_a: Vec<Scalar<E>> = a.into_iter().map(|e| Scalar::<E>(e)).collect();
|
||||||
|
let mut scalars_b: Vec<Scalar<E>> = b.into_iter().map(|e| Scalar::<E>(e)).collect();
|
||||||
|
scalars_a.resize(m, Scalar::<E>(E::Fr::zero()));
|
||||||
|
scalars_b.resize(m, Scalar::<E>(E::Fr::zero()));
|
||||||
|
|
||||||
|
|
||||||
|
best_fft(&mut scalars_a[..], &worker, &omega, exp);
|
||||||
|
best_fft(&mut scalars_b[..], &worker, &omega, exp);
|
||||||
|
|
||||||
|
// do the convolution
|
||||||
|
worker.scope(scalars_a.len(), |scope, chunk| {
|
||||||
|
for (a, b) in scalars_a.chunks_mut(chunk).zip(scalars_b.chunks(chunk)) {
|
||||||
|
scope.spawn(move |_| {
|
||||||
|
for (a, b) in a.iter_mut().zip(b.iter()) {
|
||||||
|
a.group_mul_assign(&b.0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// no longer need it
|
||||||
|
drop(scalars_b);
|
||||||
|
|
||||||
|
best_fft(&mut scalars_a[..], &worker, &omegainv, exp);
|
||||||
|
worker.scope(scalars_a.len(), |scope, chunk| {
|
||||||
|
for v in scalars_a.chunks_mut(chunk) {
|
||||||
|
scope.spawn(move |_| {
|
||||||
|
for v in v {
|
||||||
|
v.group_mul_assign(&minv);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut mul_result: Vec<E::Fr> = scalars_a.into_iter().map(|e| e.0).collect();
|
||||||
|
|
||||||
|
mul_result.truncate(result_len);
|
||||||
|
|
||||||
|
mul_result
|
||||||
|
}
|
||||||
|
|
||||||
pub fn multiply_polynomials_serial<E: Engine>(mut a: Vec<E::Fr>, mut b: Vec<E::Fr>) -> Vec<E::Fr> {
|
pub fn multiply_polynomials_serial<E: Engine>(mut a: Vec<E::Fr>, mut b: Vec<E::Fr>) -> Vec<E::Fr> {
|
||||||
let result_len = a.len() + b.len() - 1;
|
let result_len = a.len() + b.len() - 1;
|
||||||
|
|
||||||
@ -574,6 +729,7 @@ pub fn multiply_polynomials_serial<E: Engine>(mut a: Vec<E::Fr>, mut b: Vec<E::F
|
|||||||
a
|
a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add polynomails in coefficient form
|
||||||
pub fn add_polynomials<F: Field>(a: &mut [F], b: &[F]) {
|
pub fn add_polynomials<F: Field>(a: &mut [F], b: &[F]) {
|
||||||
use crate::multicore::Worker;
|
use crate::multicore::Worker;
|
||||||
use crate::domain::{EvaluationDomain, Scalar};
|
use crate::domain::{EvaluationDomain, Scalar};
|
||||||
@ -594,6 +750,28 @@ pub fn add_polynomials<F: Field>(a: &mut [F], b: &[F]) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// subtract polynomails in coefficient form
|
||||||
|
pub fn sub_polynomials<F: Field>(a: &mut [F], b: &[F]) {
|
||||||
|
use crate::multicore::Worker;
|
||||||
|
use crate::domain::{EvaluationDomain, Scalar};
|
||||||
|
|
||||||
|
let worker = Worker::new();
|
||||||
|
|
||||||
|
assert_eq!(a.len(), b.len());
|
||||||
|
|
||||||
|
worker.scope(a.len(), |scope, chunk| {
|
||||||
|
for (a, b) in a.chunks_mut(chunk).zip(b.chunks(chunk))
|
||||||
|
{
|
||||||
|
scope.spawn(move |_| {
|
||||||
|
for (a, b) in a.iter_mut().zip(b.iter()) {
|
||||||
|
a.sub_assign(b);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// multiply coefficients of the polynomial by the scalar
|
||||||
pub fn mul_polynomial_by_scalar<F: Field>(a: &mut [F], b: F) {
|
pub fn mul_polynomial_by_scalar<F: Field>(a: &mut [F], b: F) {
|
||||||
use crate::multicore::Worker;
|
use crate::multicore::Worker;
|
||||||
use crate::domain::{EvaluationDomain, Scalar};
|
use crate::domain::{EvaluationDomain, Scalar};
|
||||||
@ -612,6 +790,8 @@ pub fn mul_polynomial_by_scalar<F: Field>(a: &mut [F], b: F) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// elementwise add coeffs of one polynomial with coeffs of other, that are
|
||||||
|
// first multiplied by a scalar
|
||||||
pub fn mul_add_polynomials<F: Field>(a: &mut [F], b: &[F], c: F) {
|
pub fn mul_add_polynomials<F: Field>(a: &mut [F], b: &[F], c: F) {
|
||||||
use crate::multicore::Worker;
|
use crate::multicore::Worker;
|
||||||
use crate::domain::{EvaluationDomain, Scalar};
|
use crate::domain::{EvaluationDomain, Scalar};
|
||||||
@ -693,7 +873,6 @@ impl<T> OptionExt<T> for Option<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
||||||
fn test_mul() {
|
fn test_mul() {
|
||||||
use rand::{self, Rand};
|
use rand::{self, Rand};
|
||||||
use pairing::bls12_381::Bls12;
|
use pairing::bls12_381::Bls12;
|
||||||
@ -804,4 +983,119 @@ fn test_mut_distribute_powers() {
|
|||||||
mut_distribute_consequitive_powers(&mut b[..], first_power, x);
|
mut_distribute_consequitive_powers(&mut b[..], first_power, x);
|
||||||
|
|
||||||
assert!(a == b);
|
assert!(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_trivial_parallel_kate_division() {
|
||||||
|
use pairing::ff::PrimeField;
|
||||||
|
use pairing::bls12_381::{Bls12, Fr};
|
||||||
|
|
||||||
|
let mut minus_one = Fr::one();
|
||||||
|
minus_one.negate();
|
||||||
|
|
||||||
|
let z = Fr::one();
|
||||||
|
|
||||||
|
// this is x^2 - 1
|
||||||
|
let poly = vec![
|
||||||
|
minus_one,
|
||||||
|
Fr::from_str("0").unwrap(),
|
||||||
|
Fr::from_str("1").unwrap(),
|
||||||
|
];
|
||||||
|
|
||||||
|
let quotient_poly = kate_divison(&poly, z);
|
||||||
|
|
||||||
|
let parallel_q_poly = parallel_kate_divison::<Bls12, _>(&poly, z);
|
||||||
|
|
||||||
|
assert_eq!(quotient_poly, parallel_q_poly);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_less_trivial_parallel_kate_division() {
|
||||||
|
use pairing::ff::PrimeField;
|
||||||
|
use pairing::bls12_381::{Bls12, Fr};
|
||||||
|
|
||||||
|
let z = Fr::one();
|
||||||
|
|
||||||
|
let mut poly = vec![
|
||||||
|
Fr::from_str("328947234").unwrap(),
|
||||||
|
Fr::from_str("3545623451111").unwrap(),
|
||||||
|
Fr::from_str("5").unwrap(),
|
||||||
|
Fr::from_str("55555").unwrap(),
|
||||||
|
Fr::from_str("1235685").unwrap(),
|
||||||
|
];
|
||||||
|
|
||||||
|
fn eval(poly: &[Fr], point: Fr) -> Fr {
|
||||||
|
let mut acc = Fr::zero();
|
||||||
|
let mut tmp = Fr::one();
|
||||||
|
for p in &poly[..] {
|
||||||
|
let mut t = *p;
|
||||||
|
t.mul_assign(&tmp);
|
||||||
|
acc.add_assign(&t);
|
||||||
|
tmp.mul_assign(&point);
|
||||||
|
}
|
||||||
|
|
||||||
|
acc
|
||||||
|
}
|
||||||
|
|
||||||
|
let p_at_z = eval(&poly, z);
|
||||||
|
|
||||||
|
// poly = poly(X) - poly(z)
|
||||||
|
poly[0].sub_assign(&p_at_z);
|
||||||
|
|
||||||
|
let quotient_poly = kate_divison(&poly, z);
|
||||||
|
|
||||||
|
let parallel_q_poly = parallel_kate_divison::<Bls12, _>(&poly, z);
|
||||||
|
|
||||||
|
assert_eq!(quotient_poly, parallel_q_poly);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parallel_kate_division() {
|
||||||
|
use pairing::ff::PrimeField;
|
||||||
|
use pairing::bls12_381::{Bls12, Fr};
|
||||||
|
|
||||||
|
let mut poly = vec![
|
||||||
|
Fr::from_str("328947234").unwrap(),
|
||||||
|
Fr::from_str("3545623451111").unwrap(),
|
||||||
|
Fr::from_str("0").unwrap(),
|
||||||
|
Fr::from_str("55555").unwrap(),
|
||||||
|
Fr::from_str("1235685").unwrap(),
|
||||||
|
];
|
||||||
|
|
||||||
|
fn eval(poly: &[Fr], point: Fr) -> Fr {
|
||||||
|
let point_inv = point.inverse().unwrap();
|
||||||
|
|
||||||
|
let mut acc = Fr::zero();
|
||||||
|
let mut tmp = Fr::one();
|
||||||
|
for p in &poly[2..] {
|
||||||
|
let mut t = *p;
|
||||||
|
t.mul_assign(&tmp);
|
||||||
|
acc.add_assign(&t);
|
||||||
|
tmp.mul_assign(&point);
|
||||||
|
}
|
||||||
|
let mut tmp = point_inv;
|
||||||
|
for p in poly[0..2].iter().rev() {
|
||||||
|
let mut t = *p;
|
||||||
|
t.mul_assign(&tmp);
|
||||||
|
acc.add_assign(&t);
|
||||||
|
tmp.mul_assign(&point_inv);
|
||||||
|
}
|
||||||
|
|
||||||
|
acc
|
||||||
|
}
|
||||||
|
|
||||||
|
let z = Fr::from_str("2000").unwrap();
|
||||||
|
|
||||||
|
let p_at_z = eval(&poly, z);
|
||||||
|
|
||||||
|
// poly = poly(X) - poly(z)
|
||||||
|
poly[2].sub_assign(&p_at_z);
|
||||||
|
|
||||||
|
let quotient_poly = kate_divison(&poly, z);
|
||||||
|
|
||||||
|
let parallel_q_poly = parallel_kate_divison::<Bls12, _>(&poly, z);
|
||||||
|
|
||||||
|
assert_eq!(quotient_poly, parallel_q_poly);
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user