diff --git a/lisp/core.rs b/lisp/core.rs index 3a721c265..20b015f72 100644 --- a/lisp/core.rs +++ b/lisp/core.rs @@ -283,7 +283,6 @@ fn sub_scalar(a: MalArgs) -> MalRet { } fn mul_scalar(a: MalArgs) -> MalRet { - println!("{:?}", a); match (a[0].clone(), a[1].clone()) { (Func(_, _), ZKScalar(a1)) => { if let Vector(ref values, _) = a[0].apply(vec![]).unwrap() { @@ -306,7 +305,6 @@ fn mul_scalar(a: MalArgs) -> MalRet { } fn div_scalar(a: MalArgs) -> MalRet { - println!("{:?}", a); match (a[0].clone(), a[1].clone()) { (ZKScalar(s0), ZKScalar(s1)) => { let ret = s1.invert().map(|other| *&s0 * other); @@ -390,7 +388,6 @@ fn scalar_from(a: MalArgs) -> MalRet { Ok(ZKScalar(s0)) } Int(a0) => { - println!("{:?}", a0); let s0 = bls12_381::Scalar::from(a0 as u64); Ok(ZKScalar(s0)) } diff --git a/lisp/inverse.lisp b/lisp/inverse.lisp index 34aa17c42..8a58096bc 100644 --- a/lisp/inverse.lisp +++ b/lisp/inverse.lisp @@ -4,7 +4,7 @@ x (alloc "x" aux) x2 (alloc "x2" (* aux aux)) x3 (alloc "x3" (* aux (* aux aux))) - input (alloc-input "input" (scalar 3)) + input (alloc-input "input" (scalar 27)) ] (prove (setup diff --git a/lisp/lisp-cheat-sheet.png b/lisp/lisp-cheat-sheet.png deleted file mode 100644 index ed929becf..000000000 Binary files a/lisp/lisp-cheat-sheet.png and /dev/null differ diff --git a/lisp/lisp.rs b/lisp/lisp.rs index be133575e..18978f082 100644 --- a/lisp/lisp.rs +++ b/lisp/lisp.rs @@ -29,6 +29,7 @@ extern crate regex; mod types; use crate::types::MalErr::{ErrMalVal, ErrString}; use crate::types::MalVal::{Bool, Enforce, Func, Hash, List, MalFunc, Nil, Str, Sym, Vector}; +use crate::types::VerifyKeyParams; use crate::types::{error, format_error, MalArgs, MalErr, MalRet, MalVal}; mod env; mod printer; @@ -297,7 +298,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { let a1 = l[1].clone(); // todo ast = eval(a1.clone(), env.clone())?; - let _pvk = setup(a1.clone(), env.clone())?; + // let _pvk = setup(a1.clone(), env.clone())?; continue 'tco; } Sym(ref a0sym) if a0sym == "prove" => { @@ -517,69 +518,75 @@ pub fn get_allocations(env: &Env, key: &str) -> Rc> { } } -pub fn setup(_ast: MalVal, env: Env) -> Result, MalErr> { +pub fn setup(_ast: MalVal, env: Env) -> Result { let start = Instant::now(); - // Create parameters for our circuit. In a production deployment these would - // be generated securely using a multiparty computation. - let c = LispCircuit { - params: None, - allocs: None, - alloc_inputs: None, - constraints: None, + params: FnvHashMap::default(), + allocs: FnvHashMap::default(), + alloc_inputs: FnvHashMap::default(), + constraints: Vec::new(), }; - // TODO move to another fn let random_parameters = groth16::generate_random_parameters::(c, &mut OsRng).unwrap(); let pvk = groth16::prepare_verifying_key(&random_parameters.vk); println!("Setup: [{:?}]", start.elapsed()); - Ok(pvk) + Ok(VerifyKeyParams { + verifying_key: pvk, + random_params: random_parameters, + }) } pub fn prove(_ast: MalVal, env: Env) -> MalRet { + let start = Instant::now(); let allocs_input = get_allocations(&env, "AllocationsInput"); let allocs = get_allocations(&env, "Allocations"); let enforce_allocs = get_enforce_allocs(&env); let allocs_const = get_allocations(&env, "AllocationsConst"); - let start = Instant::now(); + // todo some refactor to improve this + let params = Some({ +// todo check if we do need to pass everything like this, its important to +// remember that this function runs after the evaluation, we have all allocs in memory now with all enfores let circuit = LispCircuit { - params: Some(allocs_const.as_ref().clone()), - allocs: Some(allocs.as_ref().clone()), - alloc_inputs: Some(allocs_input.as_ref().clone()), - constraints: Some(enforce_allocs), + params: allocs_const.as_ref().clone(), + allocs: allocs.as_ref().clone(), + alloc_inputs: allocs_input.as_ref().clone(), + constraints: enforce_allocs.clone(), }; - let params = { - let c = circuit.clone(); - groth16::generate_random_parameters::(c, &mut OsRng).unwrap() + groth16::generate_random_parameters::(circuit, &mut OsRng)? + }); + let verifying_key = Some(groth16::prepare_verifying_key(¶ms.as_ref().unwrap().vk)); + + let circuit = LispCircuit { + params: allocs_const.as_ref().clone(), + allocs: allocs.as_ref().clone(), + alloc_inputs: allocs_input.as_ref().clone(), + constraints: enforce_allocs.clone(), }; - let proof = groth16::create_random_proof(circuit, ¶ms, &mut OsRng).unwrap(); - let mut buf = File::create("proof.output").unwrap(); - proof.write(buf); - println!("Prove: [{:?}]", start.elapsed()); - let proof_file = File::open("proof.output").unwrap(); - let reader = std::io::BufReader::new(proof_file); - let proof_read: groth16::Proof = groth16::Proof::read(reader).unwrap(); + let proof = groth16::create_random_proof(circuit, params.as_ref().unwrap(), &mut OsRng)?; +// todo save the proof and keys on a file let mut vec_input = vec![]; for (k, val) in allocs_input.iter() { if let MalVal::ZKScalar(v) = val { vec_input.push(*v); } } - let pvk = setup(_ast.clone(), env.clone()).unwrap(); - println!("{:?}", vec_input); - let verify_result = groth16::verify_proof(&pvk, &proof, &vec_input.as_slice()); - println!("{:?}", verify_result); + println!("vec input {:?}", vec_input); + let result = groth16::verify_proof( + verifying_key.as_ref().unwrap(), + &proof, + vec_input.as_slice(), + ); + println!("{:?}", result); + Ok(MalVal::Nil) } pub fn verify(_ast: &MalVal) -> MalRet { let _public_input = vec![bls12_381::Scalar::from(27)]; let start = Instant::now(); - // Check the proof! - //assert!(groth16::verify_proof(&pvk, &proof, &public_input).is_ok()); println!("Verify: [{:?}]", start.elapsed()); Ok(MalVal::Nil) } diff --git a/lisp/types.rs b/lisp/types.rs index 129fad361..2753cdb83 100644 --- a/lisp/types.rs +++ b/lisp/types.rs @@ -11,6 +11,7 @@ use crate::env::{env_bind, Env}; use crate::types::MalErr::{ErrMalVal, ErrString}; use crate::types::MalVal::{Atom, Bool, Func, Hash, Int, List, MalFunc, Nil, Str, Sym, Vector}; use bellman::Variable; +use bls12_381::Bls12; use bls12_381::Scalar; #[derive(Debug, Clone)] @@ -26,124 +27,18 @@ pub struct EnforceAllocation { pub output: Vec<(String, String)>, } -#[derive(Debug, Clone)] -pub struct LispCircuit { - pub params: Option>, - pub allocs: Option>, - pub alloc_inputs: Option>, - pub constraints: Option>, +pub struct VerifyKeyParams { + pub random_params: groth16::Parameters, + pub verifying_key: groth16::PreparedVerifyingKey, } -impl Circuit for LispCircuit { - fn synthesize>( - self, - cs: &mut CS, - ) -> Result<(), SynthesisError> { - let mut variables: FnvHashMap = FnvHashMap::default(); - let mut params_const = self.params.unwrap_or(FnvHashMap::default()); - - println!("Allocations\n"); - for (k, v) in &self.allocs.unwrap_or(FnvHashMap::default()) { - println!("k {:?} v {:?}", k, v); - match v { - MalVal::ZKScalar(val) => { - let var = cs.alloc(|| "alloc", || Ok(*val))?; - variables.insert(k.to_string(), var); - } - MalVal::Str(val) => { - let val_scalar = bls12_381::Scalar::from_string(&*val); - let var = cs.alloc(|| "alloc", || Ok(val_scalar))?; - variables.insert(k.to_string(), var); - } - _ => { - println!("not allocated k {:?} v {:?}", k, v); - } - } - } - - println!("Allocations Input\n"); - for (k, v) in &self.alloc_inputs.unwrap_or(FnvHashMap::default()) { - println!("k {:?} v {:?}", k, v); - match v { - MalVal::ZKScalar(val) => { - let var = cs.alloc_input(|| "alloc", || Ok(*val))?; - variables.insert(k.to_string(), var); - } - MalVal::Str(val) => { - let val_scalar = bls12_381::Scalar::from_string(&*val); - let var = cs.alloc_input(|| "alloc", || Ok(val_scalar))?; - variables.insert(k.to_string(), var); - } - _ => { - println!("not allocated k {:?} v {:?}", k, v); - } - } - } - - println!("Enforce Allocations\n"); - // we need to keep order - for alloc_value in self.constraints.unwrap_or(Vec::::new()).iter() { - let coeff = bls12_381::Scalar::one(); - let mut left = bellman::LinearCombination::::zero(); - let mut right = bellman::LinearCombination::::zero(); - let mut output = bellman::LinearCombination::::zero(); - for values in alloc_value.left.iter() { - let (a, b) = values; - println!("a {:?} b {:?}", a, b); - let mut val_b = CS::one(); - if b != "cs::one" { - val_b = *variables.get(b).unwrap(); - } - if a == "scalar::one" { - left = left + (coeff, val_b); - } else if a == "scalar::one::neg" { - left = left + (coeff.neg(), val_b); - } else { - if let Some(value) = params_const.get(a) { - if let MalVal::ZKScalar(val) = value { - left = left + (*val, val_b); - } - } - } - } - - for values in alloc_value.right.iter() { - let (a, b) = values; - let mut val_b = CS::one(); - if b != "cs::one" { - val_b = *variables.get(b).unwrap(); - } - if a == "scalar::one" { - right = right + (coeff, val_b); - } else if a == "scalar::one::neg" { - right = right + (coeff.neg(), val_b); - } - } - - for values in alloc_value.output.iter() { - let (a, b) = values; - let mut val_b = CS::one(); - if b != "cs::one" { - val_b = *variables.get(b).unwrap(); - } - if a == "scalar::one" { - output = output + (coeff, val_b); - } else if a == "scalar::one::neg" { - output = output + (coeff.neg(), val_b); - } - } - - cs.enforce( - || "constraint", - |_| left.clone(), - |_| right.clone(), - |_| output.clone(), - ); - - } - - Ok(()) - } +#[derive(Debug, Clone)] +pub struct LispCircuit { + pub params: FnvHashMap, + pub allocs: FnvHashMap, + pub alloc_inputs: FnvHashMap, +// todo change this for a ordered data structure so enforce + pub constraints: Vec, } #[derive(Debug, Clone)] @@ -171,12 +66,132 @@ pub enum MalVal { ZKScalar(bls12_381::Scalar), } +impl Circuit for LispCircuit { + fn synthesize>( + self, + cs: &mut CS, + ) -> Result<(), SynthesisError> { + let mut variables: FnvHashMap = FnvHashMap::default(); + let mut params_const = self.params; + + println!("Allocations\n"); + for (k, v) in &self.allocs { + println!("k {:?} v {:?}", k, v); + match v { + MalVal::ZKScalar(val) => { + let var = cs.alloc(|| k, || Ok(*val))?; + variables.insert(k.to_string(), var); + } + MalVal::Str(val) => { + let val_scalar = bls12_381::Scalar::from_string(&*val); + let var = cs.alloc(|| k, || Ok(val_scalar))?; + variables.insert(k.to_string(), var); + } + _ => { + println!("not allocated k {:?} v {:?}", k, v); + } + } + } + + println!("Allocations Input\n"); + for (k, v) in &self.alloc_inputs { + println!("k {:?} v {:?}", k, v); + match v { + MalVal::ZKScalar(val) => { + let var = cs.alloc_input(|| k, || Ok(*val))?; + variables.insert(k.to_string(), var); + } + MalVal::Str(val) => { + let val_scalar = bls12_381::Scalar::from_string(&*val); + let var = cs.alloc_input(|| k, || Ok(val_scalar))?; + variables.insert(k.to_string(), var); + } + _ => { + println!("not allocated k {:?} v {:?}", k, v); + } + } + } + + println!("Enforce Allocations\n"); + // we need to keep order + for alloc_value in self.constraints.iter() { + let coeff = bls12_381::Scalar::one(); + let mut left = bellman::LinearCombination::::zero(); + let mut right = bellman::LinearCombination::::zero(); + let mut output = bellman::LinearCombination::::zero(); + for values in alloc_value.left.iter() { + let (a, b) = values; + let mut val_b = CS::one(); + if b != "cs::one" { + val_b = *variables.get(b).unwrap(); + } + if a == "scalar::one" { + left = left + (coeff, val_b); + } else if a == "scalar::one::neg" { + left = left + (coeff.neg(), val_b); + } else { + if let Some(value) = params_const.get(a) { + if let MalVal::ZKScalar(val) = value { + left = left + (*val, val_b); + } + } + } + println!("left: a {:?} b {:?} val_b: {:?}", a, b, val_b); + } + + for values in alloc_value.right.iter() { + let (a, b) = values; + let mut val_b = CS::one(); + if b != "cs::one" { + val_b = *variables.get(b).unwrap(); + } + if a == "scalar::one" { + right = right + (coeff, val_b); + } else if a == "scalar::one::neg" { + right = right + (coeff.neg(), val_b); + } + println!("right: a {:?} b {:?} val_b: {:?}", a, b, val_b); + } + + for values in alloc_value.output.iter() { + let (a, b) = values; + let mut val_b = CS::one(); + if b != "cs::one" { + val_b = *variables.get(b).unwrap(); + } + if a == "scalar::one" { + output = output + (coeff, val_b); + } else if a == "scalar::one::neg" { + output = output + (coeff.neg(), val_b); + } + println!("output: a {:?} b {:?} val_b: {:?}", a, b, val_b); + } + + println!("Enforcing ..."); + cs.enforce( + || "constraint", + |_| left.clone(), + |_| right.clone(), + |_| output.clone(), + ); + } + + Ok(()) + } +} + #[derive(Debug)] pub enum MalErr { ErrString(String), ErrMalVal(MalVal), } +impl From for MalErr { + fn from(err: SynthesisError) -> MalErr { + ErrString(err.to_string()) + } +} + pub type MalArgs = Vec; pub type MalRet = Result;