Generate proof
This commit is contained in:
parent
8f7f1f44f8
commit
d770eb36c6
64
phase2/src/bin/prove.rs
Normal file
64
phase2/src/bin/prove.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#![allow(unused_imports)]
|
||||||
|
|
||||||
|
extern crate phase2;
|
||||||
|
extern crate bellman_ce;
|
||||||
|
|
||||||
|
use phase2::circom_circuit::CircomCircuit;
|
||||||
|
use std::fs::OpenOptions;
|
||||||
|
use phase2::parameters::MPCParameters;
|
||||||
|
use bellman_ce::groth16::{Proof, generate_random_parameters, prepare_verifying_key, create_random_proof, verify_proof};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use bellman_ce::pairing::bn256::{
|
||||||
|
Bn256,
|
||||||
|
};
|
||||||
|
|
||||||
|
use bellman_ce::pairing::{
|
||||||
|
Engine,
|
||||||
|
CurveAffine,
|
||||||
|
ff::{
|
||||||
|
Field,
|
||||||
|
PrimeField,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
use bellman_ce::{
|
||||||
|
Circuit,
|
||||||
|
SynthesisError,
|
||||||
|
Variable,
|
||||||
|
Index,
|
||||||
|
ConstraintSystem,
|
||||||
|
LinearCombination,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let should_filter_points_at_infinity = false;
|
||||||
|
let rng = &mut rand::XorShiftRng::new_unseeded(); // TODO: change this unsafe unseeded random (!)
|
||||||
|
|
||||||
|
let mut c = CircomCircuit::from_json("circuit.json");
|
||||||
|
c.load_witness_json("witness.json");
|
||||||
|
let input = c.inputs.to_vec();
|
||||||
|
|
||||||
|
let reader = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.open("circom4.params")
|
||||||
|
.expect("unable to open.");
|
||||||
|
|
||||||
|
let mut params = MPCParameters::read(reader, should_filter_points_at_infinity, true).expect("unable to read params");
|
||||||
|
|
||||||
|
params.filter_params();
|
||||||
|
let params = params.get_params();
|
||||||
|
|
||||||
|
println!("Proving...");
|
||||||
|
let proof = create_random_proof(c, &*params, rng).unwrap();
|
||||||
|
|
||||||
|
println!("Checking proof");
|
||||||
|
let pvk = prepare_verifying_key(¶ms.vk);
|
||||||
|
let result = verify_proof(
|
||||||
|
&pvk,
|
||||||
|
&proof,
|
||||||
|
&input[1..]
|
||||||
|
).unwrap();
|
||||||
|
assert!(result, "Proof is correct");
|
||||||
|
println!("Done!")
|
||||||
|
}
|
@ -34,63 +34,99 @@ struct CircuitJson {
|
|||||||
pub num_variables: usize,
|
pub num_variables: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CircomCircuit<'a> {
|
#[derive(Clone)]
|
||||||
pub file_name: &'a str,
|
pub struct CircomCircuit<E: Engine> {
|
||||||
|
pub num_inputs: usize,
|
||||||
|
pub num_aux: usize,
|
||||||
|
pub num_constraints: usize,
|
||||||
|
pub inputs: Vec<E::Fr>,
|
||||||
|
pub aux: Vec<E::Fr>,
|
||||||
|
pub constraints: Vec<(
|
||||||
|
Vec<(usize, E::Fr)>,
|
||||||
|
Vec<(usize, E::Fr)>,
|
||||||
|
Vec<(usize, E::Fr)>,
|
||||||
|
)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, E: Engine> CircomCircuit<E> {
|
||||||
|
pub fn load_witness_json(&mut self, filename: &str) {
|
||||||
|
let witness: Vec<String> = serde_json::from_str(&fs::read_to_string(filename).unwrap()).unwrap();
|
||||||
|
let witness = witness.into_iter().map(|x| E::Fr::from_str(&x).unwrap()).collect::<Vec<E::Fr>>();
|
||||||
|
self.inputs = witness[..self.num_inputs].to_vec();
|
||||||
|
self.aux = witness[self.num_inputs..].to_vec();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_json(filename: &str) -> CircomCircuit::<E> {
|
||||||
|
let circuit_json: CircuitJson = serde_json::from_str(&fs::read_to_string(filename).unwrap()).unwrap();
|
||||||
|
|
||||||
|
let num_inputs = circuit_json.num_inputs + circuit_json.num_outputs + 1;
|
||||||
|
let num_aux = circuit_json.num_variables - num_inputs;
|
||||||
|
|
||||||
|
fn convert_constraint<EE: Engine>(lc: &BTreeMap<String, String>) -> Vec<(usize, EE::Fr)> {
|
||||||
|
let mut coeffs = vec![];
|
||||||
|
for (var_index_str, coefficient_str) in lc {
|
||||||
|
coeffs.push((var_index_str.parse().unwrap(), EE::Fr::from_str(coefficient_str).unwrap()));
|
||||||
|
}
|
||||||
|
return coeffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut constraints = vec![];
|
||||||
|
for constraint in circuit_json.constraints.iter() {
|
||||||
|
constraints.push((convert_constraint::<E>(&constraint[0]), convert_constraint::<E>(&constraint[1]), convert_constraint::<E>(&constraint[2])));
|
||||||
|
}
|
||||||
|
|
||||||
|
return CircomCircuit {
|
||||||
|
num_inputs: num_inputs,
|
||||||
|
num_aux: num_aux,
|
||||||
|
num_constraints: circuit_json.num_variables,
|
||||||
|
inputs: vec![],
|
||||||
|
aux: vec![],
|
||||||
|
constraints: constraints,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Our demo circuit implements this `Circuit` trait which
|
/// Our demo circuit implements this `Circuit` trait which
|
||||||
/// is used during paramgen and proving in order to
|
/// is used during paramgen and proving in order to
|
||||||
/// synthesize the constraint system.
|
/// synthesize the constraint system.
|
||||||
impl<'a, E: Engine> Circuit<E> for CircomCircuit<'a> {
|
impl<'a, E: Engine> Circuit<E> for CircomCircuit<E> {
|
||||||
fn synthesize<CS: ConstraintSystem<E>>(
|
fn synthesize<CS: ConstraintSystem<E>>(
|
||||||
self,
|
self,
|
||||||
cs: &mut CS
|
cs: &mut CS
|
||||||
) -> Result<(), SynthesisError>
|
) -> Result<(), SynthesisError>
|
||||||
{
|
{
|
||||||
let content = fs::read_to_string(self.file_name)?;
|
for i in 1..self.num_inputs {
|
||||||
let circuit_json: CircuitJson = serde_json::from_str(&content).unwrap();
|
cs.alloc_input(|| format!("variable {}", i),
|
||||||
let num_public_inputs = circuit_json.num_inputs + circuit_json.num_outputs + 1;
|
|| {
|
||||||
for i in 1..circuit_json.num_variables {
|
Ok(if self.inputs.len() > 0 { self.inputs[i] } else { E::Fr::from_str("1").unwrap() })
|
||||||
if i < num_public_inputs {
|
})?;
|
||||||
cs.alloc_input(|| format!("variable {}", i), || {
|
|
||||||
Ok(E::Fr::from_str("1").unwrap())
|
|
||||||
})?;
|
|
||||||
} else {
|
|
||||||
cs.alloc(|| format!("variable {}", i), || {
|
|
||||||
Ok(E::Fr::from_str("1").unwrap())
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let mut constrained: BTreeMap<usize, bool> = BTreeMap::new();
|
|
||||||
let mut constraint_num = 0;
|
for i in 0..self.num_aux {
|
||||||
for (_i, constraint) in circuit_json.constraints.iter().enumerate() {
|
cs.alloc(|| format!("aux {}", i),
|
||||||
let mut lcs = vec![];
|
|| {
|
||||||
for lc_description in constraint {
|
Ok(if self.aux.len() > 0 { self.aux[i] } else { E::Fr::from_str("1").unwrap() })
|
||||||
let mut lc = LinearCombination::<E>::zero();
|
})?;
|
||||||
for (var_index_str, coefficient_str) in lc_description {
|
|
||||||
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);
|
|
||||||
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();
|
fn make_lc<E: Engine>(lc_data: Vec<(usize, E::Fr)>, num_inputs: usize) -> LinearCombination<E> {
|
||||||
for i in 0..circuit_json.num_variables {
|
let mut lc = LinearCombination::<E>::zero();
|
||||||
if !constrained.contains_key(&i) {
|
for (index, coeff) in lc_data {
|
||||||
unconstrained.insert(i, true);
|
let var_index = if index < num_inputs {
|
||||||
|
Index::Input(index)
|
||||||
|
} else {
|
||||||
|
Index::Aux(index - num_inputs)
|
||||||
|
};
|
||||||
|
lc = lc + (coeff, Variable::new_unchecked(var_index))
|
||||||
}
|
}
|
||||||
|
return lc;
|
||||||
}
|
}
|
||||||
for (i, _) in unconstrained {
|
for (i, constraint) in self.constraints.iter().enumerate() {
|
||||||
println!("variable {} is unconstrained", i);
|
cs.enforce(|| format!("constraint {}", i),
|
||||||
|
|_| make_lc(constraint.0.clone(), self.num_inputs),
|
||||||
|
|_| make_lc(constraint.1.clone(), self.num_inputs),
|
||||||
|
|_| make_lc(constraint.2.clone(), self.num_inputs),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -401,6 +401,14 @@ impl MPCParameters {
|
|||||||
&self.params
|
&self.params
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn filter_params(&mut self) {
|
||||||
|
self.params.vk.ic = self.params.vk.ic.clone().into_iter().filter(|x| !x.is_zero()).collect::<Vec<_>>();
|
||||||
|
self.params.h = Arc::new((*self.params.h).clone().into_iter().filter(|x| !x.is_zero()).collect::<Vec<_>>());
|
||||||
|
self.params.a = Arc::new((*self.params.a).clone().into_iter().filter(|x| !x.is_zero()).collect::<Vec<_>>());
|
||||||
|
self.params.b_g1 = Arc::new((*self.params.b_g1).clone().into_iter().filter(|x| !x.is_zero()).collect::<Vec<_>>());
|
||||||
|
self.params.b_g2 = Arc::new((*self.params.b_g2).clone().into_iter().filter(|x| !x.is_zero()).collect::<Vec<_>>());
|
||||||
|
}
|
||||||
|
|
||||||
/// Contributes some randomness to the parameters. Only one
|
/// Contributes some randomness to the parameters. Only one
|
||||||
/// contributor needs to be honest for the parameters to be
|
/// contributor needs to be honest for the parameters to be
|
||||||
/// secure.
|
/// secure.
|
||||||
|
Loading…
Reference in New Issue
Block a user