adds circom json exporters
This commit is contained in:
parent
e7a10f72d6
commit
fcdca6e890
@ -18,8 +18,8 @@ bit-vec = "0.4.4"
|
|||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
cfg-if = "0.1.7"
|
cfg-if = "0.1.7"
|
||||||
|
|
||||||
#pairing = {package = "pairing_ce", path = "../pairing" }
|
pairing = {package = "pairing_ce", path = "../pairing" }
|
||||||
pairing = {package = "pairing_ce", version = "0.18.0" }
|
#pairing = {package = "pairing_ce", version = "0.18.0" }
|
||||||
byteorder = "1"
|
byteorder = "1"
|
||||||
|
|
||||||
futures-cpupool = {version = "0.1", optional = true}
|
futures-cpupool = {version = "0.1", optional = true}
|
||||||
|
@ -383,7 +383,7 @@ impl<E: Engine> Parameters<E> {
|
|||||||
|
|
||||||
pub struct PreparedVerifyingKey<E: Engine> {
|
pub struct PreparedVerifyingKey<E: Engine> {
|
||||||
/// Pairing result of alpha*beta
|
/// Pairing result of alpha*beta
|
||||||
alpha_g1_beta_g2: E::Fqk,
|
pub alpha_g1_beta_g2: E::Fqk,
|
||||||
/// -gamma in G2
|
/// -gamma in G2
|
||||||
neg_gamma_g2: <E::G2Affine as CurveAffine>::Prepared,
|
neg_gamma_g2: <E::G2Affine as CurveAffine>::Prepared,
|
||||||
/// -delta in G2
|
/// -delta in G2
|
||||||
|
@ -85,6 +85,14 @@ macro_rules! curve_impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl $affine {
|
impl $affine {
|
||||||
|
pub fn get_x(&self) -> $basefield {
|
||||||
|
self.x.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_y(&self) -> $basefield {
|
||||||
|
self.y.clone()
|
||||||
|
}
|
||||||
|
|
||||||
fn mul_bits<S: AsRef<[u64]>>(&self, bits: BitIterator<S>) -> $projective {
|
fn mul_bits<S: AsRef<[u64]>>(&self, bits: BitIterator<S>) -> $projective {
|
||||||
let mut res = $projective::zero();
|
let mut res = $projective::zero();
|
||||||
for i in bits {
|
for i in bits {
|
||||||
|
@ -18,3 +18,5 @@ blake2-rfc = "0.2"
|
|||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
memmap = "0.7"
|
memmap = "0.7"
|
||||||
|
num-bigint = "0.2.3"
|
||||||
|
num-traits = "0.2.8"
|
||||||
|
@ -2,26 +2,62 @@ extern crate bellman_ce;
|
|||||||
extern crate rand;
|
extern crate rand;
|
||||||
extern crate phase2;
|
extern crate phase2;
|
||||||
extern crate memmap;
|
extern crate memmap;
|
||||||
|
extern crate num_bigint;
|
||||||
|
extern crate num_traits;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::str;
|
use num_bigint::BigUint;
|
||||||
|
use num_traits::Num;
|
||||||
|
|
||||||
// For randomness (during paramgen and proof generation)
|
// For randomness (during paramgen and proof generation)
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
|
|
||||||
// For benchmarking
|
// For benchmarking
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
use std::str;
|
||||||
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::fs::{OpenOptions, remove_file};
|
||||||
|
use std::io::Write;
|
||||||
|
use std::ops::DerefMut;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct ProvingKeyJson {
|
||||||
|
#[serde(rename = "A")]
|
||||||
|
pub a: Vec<Vec<String>>,
|
||||||
|
#[serde(rename = "B1")]
|
||||||
|
pub b1: Vec<Vec<String>>,
|
||||||
|
#[serde(rename = "B2")]
|
||||||
|
pub b2: Vec<Vec<Vec<String>>>,
|
||||||
|
#[serde(rename = "C")]
|
||||||
|
pub c: Vec<Option<Vec<String>>>,
|
||||||
|
pub vk_alfa_1: Vec<String>,
|
||||||
|
pub vk_beta_1: Vec<String>,
|
||||||
|
pub vk_delta_1: Vec<String>,
|
||||||
|
pub vk_beta_2: Vec<Vec<String>>,
|
||||||
|
pub vk_delta_2: Vec<Vec<String>>,
|
||||||
|
#[serde(rename = "hExps")]
|
||||||
|
pub h: Vec<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct VerifyingKeyJson {
|
||||||
|
#[serde(rename = "IC")]
|
||||||
|
pub ic: Vec<Vec<String>>,
|
||||||
|
pub vk_alfa_1: Vec<String>,
|
||||||
|
pub vk_beta_2: Vec<Vec<String>>,
|
||||||
|
pub vk_gamma_2: Vec<Vec<String>>,
|
||||||
|
pub vk_delta_2: Vec<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
// Bring in some tools for using pairing-friendly curves
|
// Bring in some tools for using pairing-friendly curves
|
||||||
use bellman_ce::pairing::{
|
use bellman_ce::pairing::{
|
||||||
Engine,
|
Engine,
|
||||||
|
CurveAffine,
|
||||||
ff::{Field, PrimeField},
|
ff::{Field, PrimeField},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -117,6 +153,8 @@ fn main() {
|
|||||||
|
|
||||||
println!("Creating parameters...");
|
println!("Creating parameters...");
|
||||||
|
|
||||||
|
let should_filter_points_at_infinity = false;
|
||||||
|
|
||||||
let file_name = "circuit.json";
|
let file_name = "circuit.json";
|
||||||
// Create parameters for our circuit
|
// Create parameters for our circuit
|
||||||
let mut params = {
|
let mut params = {
|
||||||
@ -124,7 +162,7 @@ fn main() {
|
|||||||
file_name,
|
file_name,
|
||||||
};
|
};
|
||||||
|
|
||||||
phase2::MPCParameters::new(c).unwrap()
|
phase2::MPCParameters::new(c, should_filter_points_at_infinity).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let old_params = params.clone();
|
let old_params = params.clone();
|
||||||
@ -139,13 +177,142 @@ fn main() {
|
|||||||
|
|
||||||
let verification_result = params.verify(CircomCircuit {
|
let verification_result = params.verify(CircomCircuit {
|
||||||
file_name,
|
file_name,
|
||||||
}).unwrap();
|
}, should_filter_points_at_infinity).unwrap();
|
||||||
|
|
||||||
assert!(phase2::contains_contribution(&verification_result, &first_contrib));
|
assert!(phase2::contains_contribution(&verification_result, &first_contrib));
|
||||||
assert!(phase2::contains_contribution(&verification_result, &second_contrib));
|
assert!(phase2::contains_contribution(&verification_result, &second_contrib));
|
||||||
|
|
||||||
let params = params.get_params();
|
let params = params.get_params();
|
||||||
|
|
||||||
|
let mut f = File::create("circom.params").unwrap();
|
||||||
|
params.write(&mut f);
|
||||||
|
|
||||||
|
let mut proving_key = ProvingKeyJson {
|
||||||
|
a: vec![],
|
||||||
|
b1: vec![],
|
||||||
|
b2: vec![],
|
||||||
|
c: vec![],
|
||||||
|
vk_alfa_1: vec![],
|
||||||
|
vk_beta_1: vec![],
|
||||||
|
vk_delta_1: vec![],
|
||||||
|
vk_beta_2: vec![],
|
||||||
|
vk_delta_2: vec![],
|
||||||
|
h: vec![],
|
||||||
|
};
|
||||||
|
let repr_to_big = |r| {
|
||||||
|
BigUint::from_str_radix(&format!("{}", r)[2..], 16).unwrap().to_str_radix(10)
|
||||||
|
};
|
||||||
|
|
||||||
|
let p1_to_vec = |p : &<Bn256 as Engine>::G1Affine| {
|
||||||
|
let mut v = vec![];
|
||||||
|
let x = repr_to_big(p.get_x().into_repr());
|
||||||
|
v.push(x);
|
||||||
|
let y = repr_to_big(p.get_y().into_repr());
|
||||||
|
v.push(y);
|
||||||
|
if p.is_zero() {
|
||||||
|
v.push("0".to_string());
|
||||||
|
} else {
|
||||||
|
v.push("1".to_string());
|
||||||
|
}
|
||||||
|
v
|
||||||
|
};
|
||||||
|
let p2_to_vec = |p : &<Bn256 as Engine>::G2Affine| {
|
||||||
|
let mut v = vec![];
|
||||||
|
let x = p.get_x();
|
||||||
|
let mut x_v = vec![];
|
||||||
|
x_v.push(repr_to_big(x.c0.into_repr()));
|
||||||
|
x_v.push(repr_to_big(x.c1.into_repr()));
|
||||||
|
v.push(x_v);
|
||||||
|
|
||||||
|
let y = p.get_y();
|
||||||
|
let mut y_v = vec![];
|
||||||
|
y_v.push(repr_to_big(y.c0.into_repr()));
|
||||||
|
y_v.push(repr_to_big(y.c1.into_repr()));
|
||||||
|
v.push(y_v);
|
||||||
|
|
||||||
|
if p.is_zero() {
|
||||||
|
v.push(["0".to_string(), "0".to_string()].to_vec());
|
||||||
|
} else {
|
||||||
|
v.push(["1".to_string(), "0".to_string()].to_vec());
|
||||||
|
}
|
||||||
|
|
||||||
|
v
|
||||||
|
};
|
||||||
|
let a = params.a.clone();
|
||||||
|
for e in a.iter() {
|
||||||
|
proving_key.a.push(p1_to_vec(e));
|
||||||
|
}
|
||||||
|
let b1 = params.b_g1.clone();
|
||||||
|
for e in b1.iter() {
|
||||||
|
proving_key.b1.push(p1_to_vec(e));
|
||||||
|
}
|
||||||
|
let b2 = params.b_g2.clone();
|
||||||
|
for e in b2.iter() {
|
||||||
|
proving_key.b2.push(p2_to_vec(e));
|
||||||
|
}
|
||||||
|
let c = params.l.clone();
|
||||||
|
for _ in 0..params.vk.ic.len() {
|
||||||
|
proving_key.c.push(None);
|
||||||
|
}
|
||||||
|
for e in c.iter() {
|
||||||
|
proving_key.c.push(Some(p1_to_vec(e)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let vk_alfa_1 = params.vk.alpha_g1.clone();
|
||||||
|
proving_key.vk_alfa_1 = p1_to_vec(&vk_alfa_1);
|
||||||
|
|
||||||
|
let vk_beta_1 = params.vk.beta_g1.clone();
|
||||||
|
proving_key.vk_beta_1 = p1_to_vec(&vk_beta_1);
|
||||||
|
|
||||||
|
let vk_delta_1 = params.vk.delta_g1.clone();
|
||||||
|
proving_key.vk_delta_1 = p1_to_vec(&vk_delta_1);
|
||||||
|
|
||||||
|
let vk_beta_2 = params.vk.beta_g2.clone();
|
||||||
|
proving_key.vk_beta_2 = p2_to_vec(&vk_beta_2);
|
||||||
|
|
||||||
|
let vk_delta_2 = params.vk.delta_g2.clone();
|
||||||
|
proving_key.vk_delta_2 = p2_to_vec(&vk_delta_2);
|
||||||
|
|
||||||
|
let h = params.h.clone();
|
||||||
|
for e in h.iter() {
|
||||||
|
proving_key.h.push(p1_to_vec(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let mut verification_key = VerifyingKeyJson {
|
||||||
|
ic: vec![],
|
||||||
|
vk_alfa_1: vec![],
|
||||||
|
vk_beta_2: vec![],
|
||||||
|
vk_gamma_2: vec![],
|
||||||
|
vk_delta_2: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let ic = params.vk.ic.clone();
|
||||||
|
for e in ic.iter() {
|
||||||
|
verification_key.ic.push(p1_to_vec(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
verification_key.vk_alfa_1 = p1_to_vec(&vk_alfa_1);
|
||||||
|
verification_key.vk_beta_2 = p2_to_vec(&vk_beta_2);
|
||||||
|
let vk_gamma_2 = params.vk.gamma_g2.clone();
|
||||||
|
verification_key.vk_gamma_2 = p2_to_vec(&vk_gamma_2);
|
||||||
|
verification_key.vk_delta_2 = p2_to_vec(&vk_delta_2);
|
||||||
|
|
||||||
|
let mut pk_file = OpenOptions::new().read(true).write(true).create_new(true).open("pk.json").unwrap();
|
||||||
|
let pk_json = serde_json::to_string(&proving_key).unwrap();
|
||||||
|
pk_file.set_len(pk_json.len() as u64);
|
||||||
|
let mut mmap = unsafe { memmap::Mmap::map(&pk_file) }.unwrap().make_mut().unwrap();
|
||||||
|
mmap.deref_mut().write_all(pk_json.as_bytes()).unwrap();
|
||||||
|
|
||||||
|
let mut vk_file = OpenOptions::new().read(true).write(true).create_new(true).open("vk.json").unwrap();
|
||||||
|
let vk_json = serde_json::to_string(&verification_key).unwrap();
|
||||||
|
vk_file.set_len(vk_json.len() as u64);
|
||||||
|
let mut mmap = unsafe { memmap::Mmap::map(&vk_file) }.unwrap().make_mut().unwrap();
|
||||||
|
mmap.deref_mut().write_all(vk_json.as_bytes()).unwrap();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
// Prepare the verification key (for proof verification)
|
// Prepare the verification key (for proof verification)
|
||||||
let pvk = prepare_verifying_key(¶ms.vk);
|
let pvk = prepare_verifying_key(¶ms.vk);
|
||||||
|
|
||||||
@ -199,4 +366,5 @@ fn main() {
|
|||||||
|
|
||||||
println!("Average proving time: {:?} seconds", proving_avg);
|
println!("Average proving time: {:?} seconds", proving_avg);
|
||||||
println!("Average verifying time: {:?} seconds", verifying_avg);
|
println!("Average verifying time: {:?} seconds", verifying_avg);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
445
phase2/src/bin/mimc.rs
Normal file
445
phase2/src/bin/mimc.rs
Normal file
@ -0,0 +1,445 @@
|
|||||||
|
extern crate bellman_ce;
|
||||||
|
extern crate rand;
|
||||||
|
extern crate phase2;
|
||||||
|
extern crate num_bigint;
|
||||||
|
extern crate num_traits;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde;
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
|
use num_bigint::BigUint;
|
||||||
|
use num_traits::Num;
|
||||||
|
use std::ops::DerefMut;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
// For randomness (during paramgen and proof generation)
|
||||||
|
use rand::{thread_rng, Rng};
|
||||||
|
|
||||||
|
// For benchmarking
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
|
// Bring in some tools for using pairing-friendly curves
|
||||||
|
use bellman_ce::pairing::{
|
||||||
|
Engine,
|
||||||
|
CurveAffine,
|
||||||
|
ff::{Field, PrimeField},
|
||||||
|
};
|
||||||
|
|
||||||
|
// We're going to use the BLS12-381 pairing-friendly elliptic curve.
|
||||||
|
use bellman_ce::pairing::bn256::{
|
||||||
|
Bn256
|
||||||
|
};
|
||||||
|
|
||||||
|
// We'll use these interfaces to construct our circuit.
|
||||||
|
use bellman_ce::{
|
||||||
|
Circuit,
|
||||||
|
ConstraintSystem,
|
||||||
|
SynthesisError
|
||||||
|
};
|
||||||
|
|
||||||
|
// We're going to use the Groth16 proving system.
|
||||||
|
use bellman_ce::groth16::{
|
||||||
|
Proof,
|
||||||
|
prepare_verifying_key,
|
||||||
|
create_random_proof,
|
||||||
|
verify_proof,
|
||||||
|
};
|
||||||
|
|
||||||
|
use std::fs::File;
|
||||||
|
use std::fs::{OpenOptions, remove_file};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct ProvingKeyJson {
|
||||||
|
#[serde(rename = "A")]
|
||||||
|
pub a: Vec<Vec<String>>,
|
||||||
|
#[serde(rename = "B1")]
|
||||||
|
pub b1: Vec<Vec<String>>,
|
||||||
|
#[serde(rename = "B2")]
|
||||||
|
pub b2: Vec<Vec<Vec<String>>>,
|
||||||
|
#[serde(rename = "C")]
|
||||||
|
pub c: Vec<Option<Vec<String>>>,
|
||||||
|
pub vk_alfa_1: Vec<String>,
|
||||||
|
pub vk_beta_1: Vec<String>,
|
||||||
|
pub vk_delta_1: Vec<String>,
|
||||||
|
pub vk_beta_2: Vec<Vec<String>>,
|
||||||
|
pub vk_delta_2: Vec<Vec<String>>,
|
||||||
|
#[serde(rename = "hExps")]
|
||||||
|
pub h: Vec<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct VerifyingKeyJson {
|
||||||
|
#[serde(rename = "IC")]
|
||||||
|
pub ic: Vec<Vec<String>>,
|
||||||
|
pub vk_alfa_1: Vec<String>,
|
||||||
|
pub vk_beta_2: Vec<Vec<String>>,
|
||||||
|
pub vk_gamma_2: Vec<Vec<String>>,
|
||||||
|
pub vk_delta_2: Vec<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
const MIMC_ROUNDS: usize = 322;
|
||||||
|
|
||||||
|
/// This is an implementation of MiMC, specifically a
|
||||||
|
/// variant named `LongsightF322p3` for BLS12-381.
|
||||||
|
/// See http://eprint.iacr.org/2016/492 for more
|
||||||
|
/// information about this construction.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// function LongsightF322p3(xL ⦂ Fp, xR ⦂ Fp) {
|
||||||
|
/// for i from 0 up to 321 {
|
||||||
|
/// xL, xR := xR + (xL + Ci)^3, xL
|
||||||
|
/// }
|
||||||
|
/// return xL
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
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.
|
||||||
|
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 mut tmp_value = xl_value.map(|mut e| {
|
||||||
|
e.add_assign(&self.constants[i]);
|
||||||
|
e.square();
|
||||||
|
e
|
||||||
|
});
|
||||||
|
let mut 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 mut 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 mut 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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// This may not be cryptographically safe, use
|
||||||
|
// `OsRng` (for example) in production software.
|
||||||
|
let rng = &mut thread_rng();
|
||||||
|
|
||||||
|
// Generate the MiMC round constants
|
||||||
|
let constants = (0..MIMC_ROUNDS).map(|_| rng.gen()).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
println!("Creating parameters...");
|
||||||
|
|
||||||
|
let should_filter_points_at_infinity = false;
|
||||||
|
|
||||||
|
// Create parameters for our circuit
|
||||||
|
let mut params = {
|
||||||
|
let c = MiMCDemo::<Bn256> {
|
||||||
|
xl: None,
|
||||||
|
xr: None,
|
||||||
|
constants: &constants
|
||||||
|
};
|
||||||
|
|
||||||
|
phase2::MPCParameters::new(c, should_filter_points_at_infinity).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
let old_params = params.clone();
|
||||||
|
params.contribute(rng);
|
||||||
|
|
||||||
|
let first_contrib = phase2::verify_contribution(&old_params, ¶ms).expect("should verify");
|
||||||
|
|
||||||
|
let old_params = params.clone();
|
||||||
|
params.contribute(rng);
|
||||||
|
|
||||||
|
let second_contrib = phase2::verify_contribution(&old_params, ¶ms).expect("should verify");
|
||||||
|
|
||||||
|
let verification_result = params.verify(MiMCDemo::<Bn256> {
|
||||||
|
xl: None,
|
||||||
|
xr: None,
|
||||||
|
constants: &constants
|
||||||
|
}, should_filter_points_at_infinity).unwrap();
|
||||||
|
|
||||||
|
assert!(phase2::contains_contribution(&verification_result, &first_contrib));
|
||||||
|
assert!(phase2::contains_contribution(&verification_result, &second_contrib));
|
||||||
|
|
||||||
|
let params = params.get_params();
|
||||||
|
|
||||||
|
let mut f = File::create("mimc.params").unwrap();
|
||||||
|
params.write(&mut f);
|
||||||
|
|
||||||
|
let mut proving_key = ProvingKeyJson {
|
||||||
|
a: vec![],
|
||||||
|
b1: vec![],
|
||||||
|
b2: vec![],
|
||||||
|
c: vec![],
|
||||||
|
vk_alfa_1: vec![],
|
||||||
|
vk_beta_1: vec![],
|
||||||
|
vk_delta_1: vec![],
|
||||||
|
vk_beta_2: vec![],
|
||||||
|
vk_delta_2: vec![],
|
||||||
|
h: vec![],
|
||||||
|
};
|
||||||
|
let repr_to_big = |r| {
|
||||||
|
BigUint::from_str_radix(&format!("{}", r)[2..], 16).unwrap().to_str_radix(10)
|
||||||
|
};
|
||||||
|
|
||||||
|
let p1_to_vec = |p : &<Bn256 as Engine>::G1Affine| {
|
||||||
|
let mut v = vec![];
|
||||||
|
let x = repr_to_big(p.get_x().into_repr());
|
||||||
|
v.push(x);
|
||||||
|
let y = repr_to_big(p.get_y().into_repr());
|
||||||
|
v.push(y);
|
||||||
|
if p.is_zero() {
|
||||||
|
v.push("0".to_string());
|
||||||
|
} else {
|
||||||
|
v.push("1".to_string());
|
||||||
|
}
|
||||||
|
v
|
||||||
|
};
|
||||||
|
let p2_to_vec = |p : &<Bn256 as Engine>::G2Affine| {
|
||||||
|
let mut v = vec![];
|
||||||
|
let x = p.get_x();
|
||||||
|
let mut x_v = vec![];
|
||||||
|
x_v.push(repr_to_big(x.c0.into_repr()));
|
||||||
|
x_v.push(repr_to_big(x.c1.into_repr()));
|
||||||
|
v.push(x_v);
|
||||||
|
|
||||||
|
let y = p.get_y();
|
||||||
|
let mut y_v = vec![];
|
||||||
|
y_v.push(repr_to_big(y.c0.into_repr()));
|
||||||
|
y_v.push(repr_to_big(y.c1.into_repr()));
|
||||||
|
v.push(y_v);
|
||||||
|
|
||||||
|
if p.is_zero() {
|
||||||
|
v.push(["0".to_string(), "0".to_string()].to_vec());
|
||||||
|
} else {
|
||||||
|
v.push(["1".to_string(), "0".to_string()].to_vec());
|
||||||
|
}
|
||||||
|
|
||||||
|
v
|
||||||
|
};
|
||||||
|
let a = params.a.clone();
|
||||||
|
for e in a.iter() {
|
||||||
|
proving_key.a.push(p1_to_vec(e));
|
||||||
|
}
|
||||||
|
let b1 = params.b_g1.clone();
|
||||||
|
for e in b1.iter() {
|
||||||
|
proving_key.b1.push(p1_to_vec(e));
|
||||||
|
}
|
||||||
|
let b2 = params.b_g2.clone();
|
||||||
|
for e in b2.iter() {
|
||||||
|
proving_key.b2.push(p2_to_vec(e));
|
||||||
|
}
|
||||||
|
let c = params.l.clone();
|
||||||
|
for _ in 0..params.vk.ic.len() {
|
||||||
|
proving_key.c.push(None);
|
||||||
|
}
|
||||||
|
for e in c.iter() {
|
||||||
|
proving_key.c.push(Some(p1_to_vec(e)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let vk_alfa_1 = params.vk.alpha_g1.clone();
|
||||||
|
proving_key.vk_alfa_1 = p1_to_vec(&vk_alfa_1);
|
||||||
|
|
||||||
|
let vk_beta_1 = params.vk.beta_g1.clone();
|
||||||
|
proving_key.vk_beta_1 = p1_to_vec(&vk_beta_1);
|
||||||
|
|
||||||
|
let vk_delta_1 = params.vk.delta_g1.clone();
|
||||||
|
proving_key.vk_delta_1 = p1_to_vec(&vk_delta_1);
|
||||||
|
|
||||||
|
let vk_beta_2 = params.vk.beta_g2.clone();
|
||||||
|
proving_key.vk_beta_2 = p2_to_vec(&vk_beta_2);
|
||||||
|
|
||||||
|
let vk_delta_2 = params.vk.delta_g2.clone();
|
||||||
|
proving_key.vk_delta_2 = p2_to_vec(&vk_delta_2);
|
||||||
|
|
||||||
|
let h = params.h.clone();
|
||||||
|
for e in h.iter() {
|
||||||
|
proving_key.h.push(p1_to_vec(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let mut verification_key = VerifyingKeyJson {
|
||||||
|
ic: vec![],
|
||||||
|
vk_alfa_1: vec![],
|
||||||
|
vk_beta_2: vec![],
|
||||||
|
vk_gamma_2: vec![],
|
||||||
|
vk_delta_2: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let ic = params.vk.ic.clone();
|
||||||
|
for e in ic.iter() {
|
||||||
|
verification_key.ic.push(p1_to_vec(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
verification_key.vk_alfa_1 = p1_to_vec(&vk_alfa_1);
|
||||||
|
verification_key.vk_beta_2 = p2_to_vec(&vk_beta_2);
|
||||||
|
let vk_gamma_2 = params.vk.gamma_g2.clone();
|
||||||
|
verification_key.vk_gamma_2 = p2_to_vec(&vk_gamma_2);
|
||||||
|
verification_key.vk_delta_2 = p2_to_vec(&vk_delta_2);
|
||||||
|
|
||||||
|
let mut pk_file = OpenOptions::new().read(true).write(true).create_new(true).open("pk.json").unwrap();
|
||||||
|
let pk_json = serde_json::to_string(&proving_key).unwrap();
|
||||||
|
pk_file.set_len(pk_json.len() as u64);
|
||||||
|
let mut mmap = unsafe { memmap::Mmap::map(&pk_file) }.unwrap().make_mut().unwrap();
|
||||||
|
mmap.deref_mut().write_all(pk_json.as_bytes()).unwrap();
|
||||||
|
|
||||||
|
let mut vk_file = OpenOptions::new().read(true).write(true).create_new(true).open("vk.json").unwrap();
|
||||||
|
let vk_json = serde_json::to_string(&verification_key).unwrap();
|
||||||
|
vk_file.set_len(vk_json.len() as u64);
|
||||||
|
let mut mmap = unsafe { memmap::Mmap::map(&vk_file) }.unwrap().make_mut().unwrap();
|
||||||
|
mmap.deref_mut().write_all(vk_json.as_bytes()).unwrap();
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Prepare the verification key (for proof verification)
|
||||||
|
let pvk = prepare_verifying_key(¶ms.vk);
|
||||||
|
println!("Creating proofs...");
|
||||||
|
|
||||||
|
// Let's benchmark stuff!
|
||||||
|
const SAMPLES: u32 = 50;
|
||||||
|
let mut total_proving = Duration::new(0, 0);
|
||||||
|
let mut total_verifying = Duration::new(0, 0);
|
||||||
|
|
||||||
|
// Just a place to put the proof data, so we can
|
||||||
|
// benchmark deserialization.
|
||||||
|
let mut proof_vec = vec![];
|
||||||
|
|
||||||
|
for _ in 0..SAMPLES {
|
||||||
|
// Generate a random preimage and compute the image
|
||||||
|
let xl = rng.gen();
|
||||||
|
let xr = rng.gen();
|
||||||
|
let image = mimc::<Bn256>(xl, xr, &constants);
|
||||||
|
|
||||||
|
proof_vec.truncate(0);
|
||||||
|
|
||||||
|
let start = Instant::now();
|
||||||
|
{
|
||||||
|
// Create an instance of our circuit (with the
|
||||||
|
// witness)
|
||||||
|
let c = MiMCDemo {
|
||||||
|
xl: Some(xl),
|
||||||
|
xr: Some(xr),
|
||||||
|
constants: &constants
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create a groth16 proof with our parameters.
|
||||||
|
let proof = create_random_proof(c, params, rng).unwrap();
|
||||||
|
|
||||||
|
proof.write(&mut proof_vec).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
total_proving += start.elapsed();
|
||||||
|
|
||||||
|
let start = Instant::now();
|
||||||
|
let proof = Proof::read(&proof_vec[..]).unwrap();
|
||||||
|
// Check the proof
|
||||||
|
assert!(verify_proof(
|
||||||
|
&pvk,
|
||||||
|
&proof,
|
||||||
|
&[image]
|
||||||
|
).unwrap());
|
||||||
|
total_verifying += start.elapsed();
|
||||||
|
}
|
||||||
|
let proving_avg = total_proving / SAMPLES;
|
||||||
|
let proving_avg = proving_avg.subsec_nanos() as f64 / 1_000_000_000f64
|
||||||
|
+ (proving_avg.as_secs() as f64);
|
||||||
|
|
||||||
|
let verifying_avg = total_verifying / SAMPLES;
|
||||||
|
let verifying_avg = verifying_avg.subsec_nanos() as f64 / 1_000_000_000f64
|
||||||
|
+ (verifying_avg.as_secs() as f64);
|
||||||
|
|
||||||
|
println!("Average proving time: {:?} seconds", proving_avg);
|
||||||
|
println!("Average verifying time: {:?} seconds", verifying_avg);
|
||||||
|
*/
|
||||||
|
}
|
@ -399,6 +399,7 @@ impl MPCParameters {
|
|||||||
/// until there are contributions (see `contribute()`).
|
/// until there are contributions (see `contribute()`).
|
||||||
pub fn new<C>(
|
pub fn new<C>(
|
||||||
circuit: C,
|
circuit: C,
|
||||||
|
should_filter_points_at_infinity: bool,
|
||||||
) -> Result<MPCParameters, SynthesisError>
|
) -> Result<MPCParameters, SynthesisError>
|
||||||
where C: Circuit<Bn256>
|
where C: Circuit<Bn256>
|
||||||
{
|
{
|
||||||
@ -655,7 +656,8 @@ impl MPCParameters {
|
|||||||
ic: ic.into_iter().map(|e| e.into_affine()).collect()
|
ic: ic.into_iter().map(|e| e.into_affine()).collect()
|
||||||
};
|
};
|
||||||
|
|
||||||
let params = Parameters {
|
let params = if should_filter_points_at_infinity {
|
||||||
|
Parameters {
|
||||||
vk: vk,
|
vk: vk,
|
||||||
h: Arc::new(h),
|
h: Arc::new(h),
|
||||||
l: Arc::new(l.into_iter().map(|e| e.into_affine()).collect()),
|
l: Arc::new(l.into_iter().map(|e| e.into_affine()).collect()),
|
||||||
@ -664,6 +666,16 @@ impl MPCParameters {
|
|||||||
a: Arc::new(a_g1.into_iter().filter(|e| !e.is_zero()).map(|e| e.into_affine()).collect()),
|
a: Arc::new(a_g1.into_iter().filter(|e| !e.is_zero()).map(|e| e.into_affine()).collect()),
|
||||||
b_g1: Arc::new(b_g1.into_iter().filter(|e| !e.is_zero()).map(|e| e.into_affine()).collect()),
|
b_g1: Arc::new(b_g1.into_iter().filter(|e| !e.is_zero()).map(|e| e.into_affine()).collect()),
|
||||||
b_g2: Arc::new(b_g2.into_iter().filter(|e| !e.is_zero()).map(|e| e.into_affine()).collect())
|
b_g2: Arc::new(b_g2.into_iter().filter(|e| !e.is_zero()).map(|e| e.into_affine()).collect())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Parameters {
|
||||||
|
vk: vk,
|
||||||
|
h: Arc::new(h),
|
||||||
|
l: Arc::new(l.into_iter().map(|e| e.into_affine()).collect()),
|
||||||
|
a: Arc::new(a_g1.into_iter().map(|e| e.into_affine()).collect()),
|
||||||
|
b_g1: Arc::new(b_g1.into_iter().map(|e| e.into_affine()).collect()),
|
||||||
|
b_g2: Arc::new(b_g2.into_iter().map(|e| e.into_affine()).collect())
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let h = {
|
let h = {
|
||||||
@ -783,10 +795,11 @@ impl MPCParameters {
|
|||||||
/// exist in the final parameters.
|
/// exist in the final parameters.
|
||||||
pub fn verify<C: Circuit<Bn256>>(
|
pub fn verify<C: Circuit<Bn256>>(
|
||||||
&self,
|
&self,
|
||||||
circuit: C
|
circuit: C,
|
||||||
|
should_filter_points_at_infinity: bool,
|
||||||
) -> Result<Vec<[u8; 64]>, ()>
|
) -> Result<Vec<[u8; 64]>, ()>
|
||||||
{
|
{
|
||||||
let initial_params = MPCParameters::new(circuit).map_err(|_| ())?;
|
let initial_params = MPCParameters::new(circuit, should_filter_points_at_infinity).map_err(|_| ())?;
|
||||||
|
|
||||||
// H/L will change, but should have same length
|
// H/L will change, but should have same length
|
||||||
if initial_params.params.h.len() != self.params.h.len() {
|
if initial_params.params.h.len() != self.params.h.len() {
|
||||||
|
Loading…
Reference in New Issue
Block a user