Merge pull request #2 from LoopringSecondary/upstream-branch
Fixed misc small issues + split up work in multiple programs
This commit is contained in:
commit
5e26ad1cc2
@ -286,6 +286,7 @@ impl<E: Engine> Parameters<E> {
|
|||||||
|
|
||||||
pub fn read<R: Read>(
|
pub fn read<R: Read>(
|
||||||
mut reader: R,
|
mut reader: R,
|
||||||
|
disallow_points_at_infinity: bool,
|
||||||
checked: bool
|
checked: bool
|
||||||
) -> io::Result<Self>
|
) -> io::Result<Self>
|
||||||
{
|
{
|
||||||
@ -301,7 +302,7 @@ impl<E: Engine> Parameters<E> {
|
|||||||
.into_affine_unchecked()
|
.into_affine_unchecked()
|
||||||
}
|
}
|
||||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
|
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
|
||||||
.and_then(|e| if e.is_zero() {
|
.and_then(|e| if disallow_points_at_infinity && e.is_zero() {
|
||||||
Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity"))
|
Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity"))
|
||||||
} else {
|
} else {
|
||||||
Ok(e)
|
Ok(e)
|
||||||
@ -320,7 +321,7 @@ impl<E: Engine> Parameters<E> {
|
|||||||
.into_affine_unchecked()
|
.into_affine_unchecked()
|
||||||
}
|
}
|
||||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
|
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
|
||||||
.and_then(|e| if e.is_zero() {
|
.and_then(|e| if disallow_points_at_infinity && e.is_zero() {
|
||||||
Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity"))
|
Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity"))
|
||||||
} else {
|
} else {
|
||||||
Ok(e)
|
Ok(e)
|
||||||
|
@ -12,11 +12,16 @@ repository = "https://github.com/ebfull/phase2"
|
|||||||
rand = "0.4"
|
rand = "0.4"
|
||||||
bellman_ce = { path = "../bellman" }
|
bellman_ce = { path = "../bellman" }
|
||||||
byteorder = "1"
|
byteorder = "1"
|
||||||
|
exitcode = "1.1.2"
|
||||||
num_cpus = "1"
|
num_cpus = "1"
|
||||||
crossbeam = "0.3"
|
crossbeam = "0.3"
|
||||||
blake2-rfc = "0.2"
|
blake2-rfc = "0.2"
|
||||||
|
blake2 = "0.6.1"
|
||||||
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-bigint = "0.2.3"
|
||||||
num-traits = "0.2.8"
|
num-traits = "0.2.8"
|
||||||
|
itertools = "0.8.1"
|
||||||
|
rust-crypto = "0.2"
|
||||||
|
hex = "0.4.0"
|
||||||
|
94
phase2/src/bin/beacon.rs
Normal file
94
phase2/src/bin/beacon.rs
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
extern crate rand;
|
||||||
|
extern crate phase2;
|
||||||
|
extern crate memmap;
|
||||||
|
extern crate num_bigint;
|
||||||
|
extern crate num_traits;
|
||||||
|
extern crate blake2;
|
||||||
|
extern crate byteorder;
|
||||||
|
extern crate exitcode;
|
||||||
|
extern crate itertools;
|
||||||
|
extern crate crypto;
|
||||||
|
extern crate hex;
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
use std::fs::File;
|
||||||
|
use std::fs::OpenOptions;
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args: Vec<String> = std::env::args().collect();
|
||||||
|
if args.len() != 5 {
|
||||||
|
println!("Usage: \n<in_params.params> <in_beacon_hash> <in_num_iterations_exp> <out_params.params>");
|
||||||
|
std::process::exit(exitcode::USAGE);
|
||||||
|
}
|
||||||
|
let in_params_filename = &args[1];
|
||||||
|
let beacon_hash = &args[2];
|
||||||
|
let num_iterations_exp = &args[3].parse::<usize>().unwrap();
|
||||||
|
let out_params_filename = &args[4];
|
||||||
|
|
||||||
|
let disallow_points_at_infinity = false;
|
||||||
|
|
||||||
|
// Create an RNG based on the outcome of the random beacon
|
||||||
|
let mut rng = {
|
||||||
|
use byteorder::{ReadBytesExt, BigEndian};
|
||||||
|
use rand::{SeedableRng};
|
||||||
|
use rand::chacha::ChaChaRng;
|
||||||
|
use crypto::sha2::Sha256;
|
||||||
|
use crypto::digest::Digest;
|
||||||
|
|
||||||
|
// The hash used for the beacon
|
||||||
|
let mut cur_hash = hex::decode(beacon_hash).unwrap();
|
||||||
|
// Performs 2^n hash iterations over it
|
||||||
|
let n: usize = *num_iterations_exp;
|
||||||
|
|
||||||
|
for i in 0..(1u64<<n) {
|
||||||
|
// Print 1024 of the interstitial states
|
||||||
|
// so that verification can be
|
||||||
|
// parallelized
|
||||||
|
|
||||||
|
if i % (1u64<<(n-10)) == 0 {
|
||||||
|
print!("{}: ", i);
|
||||||
|
for b in cur_hash.iter() {
|
||||||
|
print!("{:02x}", b);
|
||||||
|
}
|
||||||
|
println!("");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut h = Sha256::new();
|
||||||
|
h.input(&cur_hash);
|
||||||
|
h.result(&mut cur_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
print!("Final result of beacon: ");
|
||||||
|
for b in cur_hash.iter() {
|
||||||
|
print!("{:02x}", b);
|
||||||
|
}
|
||||||
|
println!("");
|
||||||
|
|
||||||
|
let mut digest = &cur_hash[..];
|
||||||
|
|
||||||
|
let mut seed = [0u32; 8];
|
||||||
|
for i in 0..8 {
|
||||||
|
seed[i] = digest.read_u32::<BigEndian>().expect("digest is large enough for this to work");
|
||||||
|
}
|
||||||
|
|
||||||
|
ChaChaRng::from_seed(&seed)
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("Done creating a beacon RNG");
|
||||||
|
|
||||||
|
let reader = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.open(in_params_filename)
|
||||||
|
.expect("unable to open.");
|
||||||
|
let mut params = phase2::MPCParameters::read(reader, disallow_points_at_infinity, true).expect("unable to read params");
|
||||||
|
|
||||||
|
println!("Contributing to {}...", in_params_filename);
|
||||||
|
let hash = params.contribute(&mut rng);
|
||||||
|
println!("Contribution hash: 0x{:02x}", hash.iter().format(""));
|
||||||
|
|
||||||
|
println!("Writing parameters to {}.", out_params_filename);
|
||||||
|
let mut f = File::create(out_params_filename).unwrap();
|
||||||
|
params.write(&mut f).expect("failed to write updated parameters");
|
||||||
|
}
|
@ -1,409 +0,0 @@
|
|||||||
extern crate bellman_ce;
|
|
||||||
extern crate rand;
|
|
||||||
extern crate phase2;
|
|
||||||
extern crate memmap;
|
|
||||||
extern crate num_bigint;
|
|
||||||
extern crate num_traits;
|
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate serde;
|
|
||||||
extern crate serde_json;
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use num_bigint::BigUint;
|
|
||||||
use num_traits::Num;
|
|
||||||
|
|
||||||
// For randomness (during paramgen and proof generation)
|
|
||||||
use rand::{thread_rng, ChaChaRng, Rng};
|
|
||||||
|
|
||||||
// For benchmarking
|
|
||||||
use std::time::{Duration, Instant};
|
|
||||||
use std::str;
|
|
||||||
|
|
||||||
use std::fs::File;
|
|
||||||
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
|
|
||||||
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,
|
|
||||||
Variable,
|
|
||||||
Index,
|
|
||||||
LinearCombination,
|
|
||||||
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::collections::BTreeMap;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
struct CircuitJson {
|
|
||||||
pub constraints: Vec<Vec<BTreeMap<String, String>>>,
|
|
||||||
#[serde(rename = "nPubInputs")]
|
|
||||||
pub num_inputs: usize,
|
|
||||||
#[serde(rename = "nOutputs")]
|
|
||||||
pub num_outputs: usize,
|
|
||||||
#[serde(rename = "nVars")]
|
|
||||||
pub num_variables: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CircomCircuit<'a> {
|
|
||||||
pub file_name: &'a str,
|
|
||||||
pub witness: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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 CircomCircuit<'a> {
|
|
||||||
fn synthesize<CS: ConstraintSystem<E>>(
|
|
||||||
self,
|
|
||||||
cs: &mut CS
|
|
||||||
) -> Result<(), SynthesisError>
|
|
||||||
{
|
|
||||||
let mmap = unsafe { memmap::Mmap::map(&File::open(self.file_name)?) }?;
|
|
||||||
let content = str::from_utf8(&mmap).unwrap();
|
|
||||||
let circuit_json: CircuitJson = serde_json::from_str(&content).unwrap();
|
|
||||||
let num_public_inputs = circuit_json.num_inputs + circuit_json.num_outputs + 1;
|
|
||||||
println!("num public inputs: {}", num_public_inputs);
|
|
||||||
for i in 1..circuit_json.num_variables {
|
|
||||||
if i < num_public_inputs {
|
|
||||||
//println!("allocating public input {}", i);
|
|
||||||
cs.alloc_input(|| format!("variable {}", i), || {
|
|
||||||
println!("variable {}: {}", i, &self.witness[i]);
|
|
||||||
Ok(E::Fr::from_str(&self.witness[i]).unwrap())
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
//println!("allocating private input {}", i);
|
|
||||||
cs.alloc(|| format!("variable {}", i), || {
|
|
||||||
println!("variable {}: {}", i, &self.witness[i]);
|
|
||||||
Ok(E::Fr::from_str(&self.witness[i]).unwrap())
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let mut constrained: BTreeMap<usize, bool> = BTreeMap::new();
|
|
||||||
let mut constraint_num = 0;
|
|
||||||
for (i, constraint) in circuit_json.constraints.iter().enumerate() {
|
|
||||||
let mut lcs = vec![];
|
|
||||||
for lc_description in constraint {
|
|
||||||
let mut lc = LinearCombination::<E>::zero();
|
|
||||||
//println!("lc_description: {:?}, i: {}, len: {}", lc_description, i, constraint.len());
|
|
||||||
for (var_index_str, coefficient_str) in lc_description {
|
|
||||||
//println!("var_index_str: {}, coefficient_str: {}", var_index_str, coefficient_str);
|
|
||||||
let var_index_num: usize = var_index_str.parse().unwrap();
|
|
||||||
let var_index = if var_index_num < num_public_inputs {
|
|
||||||
Index::Input(var_index_num)
|
|
||||||
} else {
|
|
||||||
Index::Aux(var_index_num - num_public_inputs)
|
|
||||||
};
|
|
||||||
constrained.insert(var_index_num, true);
|
|
||||||
if i == 2 {
|
|
||||||
lc = lc + (E::Fr::from_str(coefficient_str).unwrap(), Variable::new_unchecked(var_index));
|
|
||||||
} else {
|
|
||||||
lc = lc + (E::Fr::from_str(coefficient_str).unwrap(), Variable::new_unchecked(var_index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lcs.push(lc);
|
|
||||||
}
|
|
||||||
cs.enforce(|| format!("constraint {}", constraint_num), |_| lcs[0].clone(), |_| lcs[1].clone(), |_| lcs[2].clone());
|
|
||||||
constraint_num += 1;
|
|
||||||
}
|
|
||||||
println!("contraints: {}", circuit_json.constraints.len());
|
|
||||||
let mut unconstrained: BTreeMap<usize, bool> = BTreeMap::new();
|
|
||||||
for i in 0..circuit_json.num_variables {
|
|
||||||
if !constrained.contains_key(&i) {
|
|
||||||
unconstrained.insert(i, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (i, _) in unconstrained {
|
|
||||||
println!("variable {} is unconstrained", i);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
// This may not be cryptographically safe, use
|
|
||||||
// `OsRng` (for example) in production software.
|
|
||||||
//let rng = &mut thread_rng();
|
|
||||||
let mut rng = ChaChaRng::new_unseeded();
|
|
||||||
rng.set_counter(0u64, 1234567890u64);
|
|
||||||
let rng = &mut rng;
|
|
||||||
|
|
||||||
|
|
||||||
println!("Creating parameters...");
|
|
||||||
|
|
||||||
let should_filter_points_at_infinity = false;
|
|
||||||
|
|
||||||
let file_name = "circuit.json";
|
|
||||||
|
|
||||||
let mmap = unsafe { memmap::Mmap::map(&File::open("witness.json").unwrap()) }.unwrap();
|
|
||||||
let content = str::from_utf8(&mmap).unwrap();
|
|
||||||
|
|
||||||
let witness: Vec<String> = serde_json::from_str(&content).unwrap();
|
|
||||||
// Create parameters for our circuit
|
|
||||||
let mut params = {
|
|
||||||
let c = CircomCircuit {
|
|
||||||
file_name,
|
|
||||||
witness: witness.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
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(CircomCircuit {
|
|
||||||
file_name,
|
|
||||||
witness: witness.clone(),
|
|
||||||
}, 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("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_alfabeta_12 = vk_alfa_1.pairing_with(&vk_beta_2);
|
|
||||||
//println!("vk_alfabeta_12: {}", vk_alfabeta_12);
|
|
||||||
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 = 1;
|
|
||||||
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 {
|
|
||||||
proof_vec.truncate(0);
|
|
||||||
|
|
||||||
let start = Instant::now();
|
|
||||||
{
|
|
||||||
// Create an instance of our circuit (with the
|
|
||||||
// witness)
|
|
||||||
let c = CircomCircuit {
|
|
||||||
file_name,
|
|
||||||
witness: witness.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create a groth16 proof with our parameters.
|
|
||||||
let proof = create_random_proof(c, params, rng).unwrap();
|
|
||||||
println!("proof: {:?}", proof);
|
|
||||||
|
|
||||||
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,
|
|
||||||
&[]
|
|
||||||
).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);
|
|
||||||
*/
|
|
||||||
}
|
|
74
phase2/src/bin/contribute.rs
Normal file
74
phase2/src/bin/contribute.rs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
extern crate rand;
|
||||||
|
extern crate phase2;
|
||||||
|
extern crate memmap;
|
||||||
|
extern crate num_bigint;
|
||||||
|
extern crate num_traits;
|
||||||
|
extern crate blake2;
|
||||||
|
extern crate byteorder;
|
||||||
|
extern crate exitcode;
|
||||||
|
extern crate itertools;
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
use std::fs::File;
|
||||||
|
use std::fs::OpenOptions;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args: Vec<String> = std::env::args().collect();
|
||||||
|
if args.len() != 4 {
|
||||||
|
println!("Usage: \n<in_params.params> <in_str_entropy> <out_params.params>");
|
||||||
|
std::process::exit(exitcode::USAGE);
|
||||||
|
}
|
||||||
|
let in_params_filename = &args[1];
|
||||||
|
let entropy = &args[2];
|
||||||
|
let out_params_filename = &args[3];
|
||||||
|
|
||||||
|
let disallow_points_at_infinity = false;
|
||||||
|
|
||||||
|
// Create an RNG based on a mixture of system randomness and user provided randomness
|
||||||
|
let mut rng = {
|
||||||
|
use byteorder::{ReadBytesExt, BigEndian};
|
||||||
|
use blake2::{Blake2b, Digest};
|
||||||
|
use rand::{SeedableRng, Rng, OsRng};
|
||||||
|
use rand::chacha::ChaChaRng;
|
||||||
|
|
||||||
|
let h = {
|
||||||
|
let mut system_rng = OsRng::new().unwrap();
|
||||||
|
let mut h = Blake2b::default();
|
||||||
|
|
||||||
|
// Gather 1024 bytes of entropy from the system
|
||||||
|
for _ in 0..1024 {
|
||||||
|
let r: u8 = system_rng.gen();
|
||||||
|
h.input(&[r]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash it all up to make a seed
|
||||||
|
h.input(&entropy.as_bytes());
|
||||||
|
h.result()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut digest = &h[..];
|
||||||
|
|
||||||
|
// Interpret the first 32 bytes of the digest as 8 32-bit words
|
||||||
|
let mut seed = [0u32; 8];
|
||||||
|
for i in 0..8 {
|
||||||
|
seed[i] = digest.read_u32::<BigEndian>().expect("digest is large enough for this to work");
|
||||||
|
}
|
||||||
|
|
||||||
|
ChaChaRng::from_seed(&seed)
|
||||||
|
};
|
||||||
|
|
||||||
|
let reader = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.open(in_params_filename)
|
||||||
|
.expect("unable to open.");
|
||||||
|
let mut params = phase2::MPCParameters::read(reader, disallow_points_at_infinity, true).expect("unable to read params");
|
||||||
|
|
||||||
|
println!("Contributing to {}...", in_params_filename);
|
||||||
|
let hash = params.contribute(&mut rng);
|
||||||
|
println!("Contribution hash: 0x{:02x}", hash.iter().format(""));
|
||||||
|
|
||||||
|
println!("Writing parameters to {}.", out_params_filename);
|
||||||
|
let mut f = File::create(out_params_filename).unwrap();
|
||||||
|
params.write(&mut f).expect("failed to write updated parameters");
|
||||||
|
}
|
219
phase2/src/bin/export_keys.rs
Normal file
219
phase2/src/bin/export_keys.rs
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
extern crate bellman_ce;
|
||||||
|
extern crate rand;
|
||||||
|
extern crate phase2;
|
||||||
|
extern crate memmap;
|
||||||
|
extern crate num_bigint;
|
||||||
|
extern crate num_traits;
|
||||||
|
extern crate exitcode;
|
||||||
|
|
||||||
|
extern crate serde;
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use num_bigint::BigUint;
|
||||||
|
use num_traits::Num;
|
||||||
|
|
||||||
|
use std::fs::OpenOptions;
|
||||||
|
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
|
||||||
|
use bellman_ce::pairing::{
|
||||||
|
Engine,
|
||||||
|
CurveAffine,
|
||||||
|
ff::PrimeField,
|
||||||
|
};
|
||||||
|
|
||||||
|
// We're going to use the BLS12-381 pairing-friendly elliptic curve.
|
||||||
|
use bellman_ce::pairing::bn256::{
|
||||||
|
Bn256,
|
||||||
|
};
|
||||||
|
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct CircuitJson {
|
||||||
|
pub constraints: Vec<Vec<BTreeMap<String, String>>>,
|
||||||
|
#[serde(rename = "nPubInputs")]
|
||||||
|
pub num_inputs: usize,
|
||||||
|
#[serde(rename = "nOutputs")]
|
||||||
|
pub num_outputs: usize,
|
||||||
|
#[serde(rename = "nVars")]
|
||||||
|
pub num_variables: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args: Vec<String> = std::env::args().collect();
|
||||||
|
if args.len() != 4 {
|
||||||
|
println!("Usage: \n<in_params.params> <out_vk.json> <out_pk.json>");
|
||||||
|
std::process::exit(exitcode::USAGE);
|
||||||
|
}
|
||||||
|
let params_filename = &args[1];
|
||||||
|
let vk_filename = &args[2];
|
||||||
|
let pk_filename = &args[3];
|
||||||
|
|
||||||
|
let disallow_points_at_infinity = false;
|
||||||
|
|
||||||
|
println!("Exporting {}...", params_filename);
|
||||||
|
|
||||||
|
let reader = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.open(params_filename)
|
||||||
|
.expect("unable to open.");
|
||||||
|
let params = phase2::MPCParameters::read(reader, disallow_points_at_infinity, true).expect("unable to read params");
|
||||||
|
let params = params.get_params();
|
||||||
|
|
||||||
|
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![];
|
||||||
|
//println!("test: {}", p.get_x().into_repr());
|
||||||
|
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 pk_file = OpenOptions::new().read(true).write(true).create_new(true).open(pk_filename).unwrap();
|
||||||
|
let pk_json = serde_json::to_string(&proving_key).unwrap();
|
||||||
|
pk_file.set_len(pk_json.len() as u64).expect("unable to write pk file");
|
||||||
|
let mut mmap = unsafe { memmap::Mmap::map(&pk_file) }.unwrap().make_mut().unwrap();
|
||||||
|
mmap.deref_mut().write_all(pk_json.as_bytes()).unwrap();
|
||||||
|
|
||||||
|
let vk_file = OpenOptions::new().read(true).write(true).create_new(true).open(vk_filename).unwrap();
|
||||||
|
let vk_json = serde_json::to_string(&verification_key).unwrap();
|
||||||
|
vk_file.set_len(vk_json.len() as u64).expect("unable to write vk file");
|
||||||
|
let mut mmap = unsafe { memmap::Mmap::map(&vk_file) }.unwrap().make_mut().unwrap();
|
||||||
|
mmap.deref_mut().write_all(vk_json.as_bytes()).unwrap();
|
||||||
|
|
||||||
|
println!("Created {} and {}.", pk_filename, vk_filename);
|
||||||
|
}
|
30
phase2/src/bin/new.rs
Normal file
30
phase2/src/bin/new.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
extern crate rand;
|
||||||
|
extern crate phase2;
|
||||||
|
extern crate exitcode;
|
||||||
|
|
||||||
|
use std::fs::File;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args: Vec<String> = std::env::args().collect();
|
||||||
|
if args.len() != 3 {
|
||||||
|
println!("Usage: \n<in_circuit.json> <out_params.params>");
|
||||||
|
std::process::exit(exitcode::USAGE);
|
||||||
|
}
|
||||||
|
let circuit_filename = &args[1];
|
||||||
|
let params_filename = &args[2];
|
||||||
|
|
||||||
|
let should_filter_points_at_infinity = false;
|
||||||
|
|
||||||
|
// Import the circuit and create the initial parameters using phase 1
|
||||||
|
println!("Creating initial parameters for {}...", circuit_filename);
|
||||||
|
let params = {
|
||||||
|
let c = phase2::CircomCircuit {
|
||||||
|
file_name: &circuit_filename,
|
||||||
|
};
|
||||||
|
phase2::MPCParameters::new(c, should_filter_points_at_infinity).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("Writing initial parameters to {}.", params_filename);
|
||||||
|
let mut f = File::create(params_filename).unwrap();
|
||||||
|
params.write(&mut f).expect("unable to write params");
|
||||||
|
}
|
39
phase2/src/bin/verify_contribution.rs
Normal file
39
phase2/src/bin/verify_contribution.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
extern crate phase2;
|
||||||
|
extern crate exitcode;
|
||||||
|
|
||||||
|
use std::fs::OpenOptions;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args: Vec<String> = std::env::args().collect();
|
||||||
|
if args.len() != 4 {
|
||||||
|
println!("Usage: \n<in_circuit.json> <in_old_params.params> <in_new_params.params>");
|
||||||
|
std::process::exit(exitcode::USAGE);
|
||||||
|
}
|
||||||
|
let circuit_filename = &args[1];
|
||||||
|
let old_params_filename = &args[2];
|
||||||
|
let new_params_filename = &args[3];
|
||||||
|
|
||||||
|
let disallow_points_at_infinity = false;
|
||||||
|
|
||||||
|
let old_reader = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.open(old_params_filename)
|
||||||
|
.expect("unable to open old params");
|
||||||
|
let old_params = phase2::MPCParameters::read(old_reader, disallow_points_at_infinity, true).expect("unable to read old params");
|
||||||
|
|
||||||
|
let new_reader = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.open(new_params_filename)
|
||||||
|
.expect("unable to open new params");
|
||||||
|
let new_params = phase2::MPCParameters::read(new_reader, disallow_points_at_infinity, true).expect("unable to read new params");
|
||||||
|
|
||||||
|
println!("Checking contribution {}...", new_params_filename);
|
||||||
|
let contribution = phase2::verify_contribution(&old_params, &new_params).expect("should verify");
|
||||||
|
|
||||||
|
let should_filter_points_at_infinity = false;
|
||||||
|
let verification_result = new_params.verify(phase2::CircomCircuit {
|
||||||
|
file_name: &circuit_filename,
|
||||||
|
}, should_filter_points_at_infinity).unwrap();
|
||||||
|
assert!(phase2::contains_contribution(&verification_result, &contribution));
|
||||||
|
println!("Contribution {} verified.", new_params_filename);
|
||||||
|
}
|
@ -269,6 +269,14 @@ use rand::{
|
|||||||
SeedableRng
|
SeedableRng
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde;
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
/// This is our assembly structure that we'll use to synthesize the
|
/// This is our assembly structure that we'll use to synthesize the
|
||||||
/// circuit into a QAP.
|
/// circuit into a QAP.
|
||||||
struct KeypairAssembly<E: Engine> {
|
struct KeypairAssembly<E: Engine> {
|
||||||
@ -438,8 +446,8 @@ impl MPCParameters {
|
|||||||
m *= 2;
|
m *= 2;
|
||||||
exp += 1;
|
exp += 1;
|
||||||
|
|
||||||
// Powers of Tau ceremony can't support more than 2^21
|
// Powers of Tau ceremony can't support more than 2^28
|
||||||
if exp > 21 {
|
if exp > 28 {
|
||||||
return Err(SynthesisError::PolynomialDegreeTooLarge)
|
return Err(SynthesisError::PolynomialDegreeTooLarge)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -511,8 +519,8 @@ impl MPCParameters {
|
|||||||
let alpha_coeffs_g1 = Arc::new(alpha_coeffs_g1);
|
let alpha_coeffs_g1 = Arc::new(alpha_coeffs_g1);
|
||||||
let beta_coeffs_g1 = Arc::new(beta_coeffs_g1);
|
let beta_coeffs_g1 = Arc::new(beta_coeffs_g1);
|
||||||
|
|
||||||
let mut h = Vec::with_capacity(m);
|
let mut h = Vec::with_capacity(m-1);
|
||||||
for i in 0..m {
|
for _ in 0..m-1 {
|
||||||
h.push(read_g1(f)?);
|
h.push(read_g1(f)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -947,10 +955,11 @@ impl MPCParameters {
|
|||||||
/// checks.
|
/// checks.
|
||||||
pub fn read<R: Read>(
|
pub fn read<R: Read>(
|
||||||
mut reader: R,
|
mut reader: R,
|
||||||
|
disallow_points_at_infinity: bool,
|
||||||
checked: bool
|
checked: bool
|
||||||
) -> io::Result<MPCParameters>
|
) -> io::Result<MPCParameters>
|
||||||
{
|
{
|
||||||
let params = Parameters::read(&mut reader, checked)?;
|
let params = Parameters::read(&mut reader, disallow_points_at_infinity, checked)?;
|
||||||
|
|
||||||
let mut cs_hash = [0u8; 64];
|
let mut cs_hash = [0u8; 64];
|
||||||
reader.read_exact(&mut cs_hash)?;
|
reader.read_exact(&mut cs_hash)?;
|
||||||
@ -1399,3 +1408,88 @@ pub fn contains_contribution(
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct CircuitJson {
|
||||||
|
pub constraints: Vec<Vec<BTreeMap<String, String>>>,
|
||||||
|
#[serde(rename = "nPubInputs")]
|
||||||
|
pub num_inputs: usize,
|
||||||
|
#[serde(rename = "nOutputs")]
|
||||||
|
pub num_outputs: usize,
|
||||||
|
#[serde(rename = "nVars")]
|
||||||
|
pub num_variables: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CircomCircuit<'a> {
|
||||||
|
pub file_name: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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 CircomCircuit<'a> {
|
||||||
|
fn synthesize<CS: ConstraintSystem<E>>(
|
||||||
|
self,
|
||||||
|
cs: &mut CS
|
||||||
|
) -> Result<(), SynthesisError>
|
||||||
|
{
|
||||||
|
let mmap = unsafe { memmap::Mmap::map(&File::open(self.file_name)?) }?;
|
||||||
|
let content = str::from_utf8(&mmap).unwrap();
|
||||||
|
let circuit_json: CircuitJson = serde_json::from_str(&content).unwrap();
|
||||||
|
let num_public_inputs = circuit_json.num_inputs + circuit_json.num_outputs + 1;
|
||||||
|
//println!("num public inputs: {}", num_public_inputs);
|
||||||
|
for i in 1..circuit_json.num_variables {
|
||||||
|
if i < num_public_inputs {
|
||||||
|
//println!("allocating public input {}", i);
|
||||||
|
cs.alloc_input(|| format!("variable {}", i), || {
|
||||||
|
//println!("variable {}: {}", i, &self.witness[i]);
|
||||||
|
Ok(E::Fr::from_str("1").unwrap())
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
//println!("allocating private input {}", i);
|
||||||
|
cs.alloc(|| format!("variable {}", i), || {
|
||||||
|
//println!("variable {}: {}", i, &self.witness[i]);
|
||||||
|
Ok(E::Fr::from_str("1").unwrap())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut constrained: BTreeMap<usize, bool> = BTreeMap::new();
|
||||||
|
let mut constraint_num = 0;
|
||||||
|
for (i, constraint) in circuit_json.constraints.iter().enumerate() {
|
||||||
|
let mut lcs = vec![];
|
||||||
|
for lc_description in constraint {
|
||||||
|
let mut lc = LinearCombination::<E>::zero();
|
||||||
|
//println!("lc_description: {:?}, i: {}, len: {}", lc_description, i, constraint.len());
|
||||||
|
for (var_index_str, coefficient_str) in lc_description {
|
||||||
|
//println!("var_index_str: {}, coefficient_str: {}", var_index_str, coefficient_str);
|
||||||
|
let var_index_num: usize = var_index_str.parse().unwrap();
|
||||||
|
let var_index = if var_index_num < num_public_inputs {
|
||||||
|
Index::Input(var_index_num)
|
||||||
|
} else {
|
||||||
|
Index::Aux(var_index_num - num_public_inputs)
|
||||||
|
};
|
||||||
|
constrained.insert(var_index_num, true);
|
||||||
|
if i == 2 {
|
||||||
|
lc = lc + (E::Fr::from_str(coefficient_str).unwrap(), Variable::new_unchecked(var_index));
|
||||||
|
} else {
|
||||||
|
lc = lc + (E::Fr::from_str(coefficient_str).unwrap(), Variable::new_unchecked(var_index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lcs.push(lc);
|
||||||
|
}
|
||||||
|
cs.enforce(|| format!("constraint {}", constraint_num), |_| lcs[0].clone(), |_| lcs[1].clone(), |_| lcs[2].clone());
|
||||||
|
constraint_num += 1;
|
||||||
|
}
|
||||||
|
println!("constraints: {}", circuit_json.constraints.len());
|
||||||
|
let mut unconstrained: BTreeMap<usize, bool> = BTreeMap::new();
|
||||||
|
for i in 0..circuit_json.num_variables {
|
||||||
|
if !constrained.contains_key(&i) {
|
||||||
|
unconstrained.insert(i, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i, _) in unconstrained {
|
||||||
|
println!("variable {} is unconstrained", i);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
48
phase2/tools/vk2ethsnarks.py
Normal file
48
phase2/tools/vk2ethsnarks.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import sys
|
||||||
|
import json
|
||||||
|
|
||||||
|
def to_hex(d):
|
||||||
|
return hex(int(d)).rstrip('L')
|
||||||
|
return d
|
||||||
|
|
||||||
|
class vk_ethsnarks(object):
|
||||||
|
def to_json(self):
|
||||||
|
return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4)
|
||||||
|
|
||||||
|
if len(sys.argv) != 3:
|
||||||
|
print("Usage: ")
|
||||||
|
print("<input_vk.json> <ethsnarks_vk.json>")
|
||||||
|
|
||||||
|
f = json.load(open(sys.argv[1]))
|
||||||
|
|
||||||
|
vk = vk_ethsnarks()
|
||||||
|
# alpha
|
||||||
|
vk.alpha = []
|
||||||
|
for i in range(2):
|
||||||
|
vk.alpha.append(to_hex(f["vk_alfa_1"][i]))
|
||||||
|
# beta
|
||||||
|
vk.beta = [[], []]
|
||||||
|
for i in range(2):
|
||||||
|
for j in range(2):
|
||||||
|
vk.beta[i].append(to_hex(f["vk_beta_2"][i][1-j]))
|
||||||
|
# gamma
|
||||||
|
vk.gamma = [[], []]
|
||||||
|
for i in range(2):
|
||||||
|
for j in range(2):
|
||||||
|
vk.gamma[i].append(to_hex(f["vk_gamma_2"][i][1-j]))
|
||||||
|
# delta
|
||||||
|
vk.delta = [[], []]
|
||||||
|
for i in range(2):
|
||||||
|
for j in range(2):
|
||||||
|
vk.delta[i].append(to_hex(f["vk_delta_2"][i][1-j]))
|
||||||
|
# gammaABC
|
||||||
|
vk.gammaABC = [[], []]
|
||||||
|
for i in range(2):
|
||||||
|
for j in range(2):
|
||||||
|
vk.gammaABC[i].append(to_hex(f["IC"][i][j]))
|
||||||
|
|
||||||
|
f3 = open(sys.argv[2], 'w')
|
||||||
|
f3.write(vk.to_json())
|
||||||
|
f3.close()
|
||||||
|
|
||||||
|
print("vk file created: " + str(sys.argv[2]))
|
4
powersoftau/Cargo.lock
generated
4
powersoftau/Cargo.lock
generated
@ -19,7 +19,7 @@ dependencies = [
|
|||||||
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pairing_ce 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pairing_ce 0.18.0",
|
||||||
"rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -296,7 +296,6 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "pairing_ce"
|
name = "pairing_ce"
|
||||||
version = "0.18.0"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ff_ce 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ff_ce 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -511,7 +510,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
|
"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
|
||||||
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
||||||
"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba"
|
"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba"
|
||||||
"checksum pairing_ce 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f075a9c570e2026111cb6dddf6a320e5163c42aa32500b315ec34acbcf7c9b36"
|
|
||||||
"checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8"
|
"checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8"
|
||||||
"checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a"
|
"checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a"
|
||||||
"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
|
"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
|
||||||
|
@ -29,7 +29,7 @@ fn log_2(x: u64) -> u32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Try to load `./transcript` from disk.
|
// Try to load `./response` from disk.
|
||||||
let reader = OpenOptions::new()
|
let reader = OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
.open("response")
|
.open("response")
|
||||||
@ -47,7 +47,7 @@ fn main() {
|
|||||||
|
|
||||||
// Create the parameters for various 2^m circuit depths.
|
// Create the parameters for various 2^m circuit depths.
|
||||||
let max_degree = log_2(current_accumulator.tau_powers_g2.len() as u64);
|
let max_degree = log_2(current_accumulator.tau_powers_g2.len() as u64);
|
||||||
for m in 0..max_degree {
|
for m in 0..max_degree+1 {
|
||||||
let paramname = format!("phase1radix2m{}", m);
|
let paramname = format!("phase1radix2m{}", m);
|
||||||
println!("Creating {}", paramname);
|
println!("Creating {}", paramname);
|
||||||
|
|
||||||
|
@ -25,6 +25,13 @@ use std::io::{self, Read, BufWriter, Write};
|
|||||||
|
|
||||||
use memmap::*;
|
use memmap::*;
|
||||||
|
|
||||||
|
const fn num_bits<T>() -> usize { std::mem::size_of::<T>() * 8 }
|
||||||
|
|
||||||
|
fn log_2(x: u64) -> u32 {
|
||||||
|
assert!(x > 0);
|
||||||
|
num_bits::<u64>() as u32 - x.leading_zeros() - 1
|
||||||
|
}
|
||||||
|
|
||||||
// Computes the hash of the challenge file for the player,
|
// Computes the hash of the challenge file for the player,
|
||||||
// given the current state of the accumulator and the last
|
// given the current state of the accumulator and the last
|
||||||
// response file hash.
|
// response file hash.
|
||||||
@ -268,7 +275,8 @@ fn main() {
|
|||||||
let worker = &Worker::new();
|
let worker = &Worker::new();
|
||||||
|
|
||||||
// Create the parameters for various 2^m circuit depths.
|
// Create the parameters for various 2^m circuit depths.
|
||||||
for m in 0..22 {
|
let max_degree = log_2(current_accumulator.tau_powers_g2.len() as u64);
|
||||||
|
for m in 0..max_degree+1 {
|
||||||
let paramname = format!("phase1radix2m{}", m);
|
let paramname = format!("phase1radix2m{}", m);
|
||||||
println!("Creating {}", paramname);
|
println!("Creating {}", paramname);
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ pub struct Bn256CeremonyParameters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PowersOfTauParameters for Bn256CeremonyParameters {
|
impl PowersOfTauParameters for Bn256CeremonyParameters {
|
||||||
const REQUIRED_POWER: usize = 12; // generate to have roughly 2 million constraints
|
const REQUIRED_POWER: usize = 28;
|
||||||
|
|
||||||
// This ceremony is based on the BN256 elliptic curve construction.
|
// This ceremony is based on the BN256 elliptic curve construction.
|
||||||
const G1_UNCOMPRESSED_BYTE_SIZE: usize = 64;
|
const G1_UNCOMPRESSED_BYTE_SIZE: usize = 64;
|
||||||
|
Loading…
Reference in New Issue
Block a user