Browse Source

Merge pull request #15 from narodnik/feature/lisp

Feature/lisp
ada 5 years ago
parent
commit
be30eac9b4
6 changed files with 104 additions and 80 deletions
  1. 0 3
      lisp/core.rs
  2. 1 1
      lisp/inverse.lisp
  3. BIN
      lisp/lisp-cheat-sheet.png
  4. 42 33
      lisp/lisp.rs
  5. 2 2
      lisp/run.sh
  6. 59 41
      lisp/types.rs

+ 0 - 3
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))
         }

+ 1 - 1
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 

BIN
lisp/lisp-cheat-sheet.png


+ 42 - 33
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" => {
@@ -418,13 +419,15 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
                             }
                             _ => {}
                         };
+                        let enforce_vec = get_enforce_allocs(&env);
                         let enforce = EnforceAllocation {
+                            idx: enforce_vec.len() + 1,
                             left: left_vec,
                             right: right_vec,
                             output: out_vec,
                         };
                         let mut new_vec: Vec<EnforceAllocation> = vec![enforce];
-                        for value in get_enforce_allocs(&env).iter() {
+                        for value in enforce_vec.iter() { 
                             new_vec.push(value.clone());
                         }
                         env_set(
@@ -517,69 +520,75 @@ pub fn get_allocations(env: &Env, key: &str) -> Rc<FnvHashMap<String, MalVal>> {
     }
 }
 
-pub fn setup(_ast: MalVal, env: Env) -> Result<PreparedVerifyingKey<Bls12>, MalErr> {
+pub fn setup(_ast: MalVal, env: Env) -> Result<VerifyKeyParams, MalErr> {
     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::<Bls12, _, _>(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::<Bls12, _, _>(c, &mut OsRng).unwrap()
+        groth16::generate_random_parameters::<Bls12, _, _>(circuit, &mut OsRng)?
+    });
+    let verifying_key = Some(groth16::prepare_verifying_key(&params.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, &params, &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<bls12_381::Bls12> = 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)
 }

+ 2 - 2
lisp/run.sh

@@ -1,3 +1,3 @@
 export RUST_BACKTRACE=full
-#cargo run --bin lisp load jubjub-add.lisp
-cargo run --bin lisp load inverse.lisp
+cargo run --bin lisp load jubjub-add.lisp
+#cargo run --bin lisp load new-cs.lisp

+ 59 - 41
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)]
@@ -21,17 +22,49 @@ pub struct Allocation {
 
 #[derive(Debug, Clone)]
 pub struct EnforceAllocation {
+    pub idx: usize,
     pub left: Vec<(String, String)>,
     pub right: Vec<(String, String)>,
     pub output: Vec<(String, String)>,
 }
 
+pub struct VerifyKeyParams {
+    pub random_params: groth16::Parameters<Bls12>,
+    pub verifying_key: groth16::PreparedVerifyingKey<Bls12>,
+}
+
 #[derive(Debug, Clone)]
 pub struct LispCircuit {
-    pub params: Option<FnvHashMap<String, MalVal>>,
-    pub allocs: Option<FnvHashMap<String, MalVal>>,
-    pub alloc_inputs: Option<FnvHashMap<String, MalVal>>,
-    pub constraints: Option<Vec<EnforceAllocation>>,
+    pub params: FnvHashMap<String, MalVal>,
+    pub allocs: FnvHashMap<String, MalVal>,
+    pub alloc_inputs: FnvHashMap<String, MalVal>,
+//    todo change this for a ordered data structure so enforce 
+    pub constraints: Vec<EnforceAllocation>,
+}
+
+#[derive(Debug, Clone)]
+pub enum MalVal {
+    Nil,
+    Bool(bool),
+    Int(i64),
+    Str(String),
+    Sym(String),
+    List(Rc<Vec<MalVal>>, Rc<MalVal>),
+    Vector(Rc<Vec<MalVal>>, Rc<MalVal>),
+    Hash(Rc<FnvHashMap<String, MalVal>>, Rc<MalVal>),
+    Func(fn(MalArgs) -> MalRet, Rc<MalVal>),
+    MalFunc {
+        eval: fn(ast: MalVal, env: Env) -> MalRet,
+        ast: Rc<MalVal>,
+        env: Env,
+        params: Rc<MalVal>,
+        is_macro: bool,
+        meta: Rc<MalVal>,
+    },
+    Atom(Rc<RefCell<MalVal>>),
+    Zk(Rc<LispCircuit>), // TODO remote it
+    Enforce(Rc<Vec<EnforceAllocation>>),
+    ZKScalar(bls12_381::Scalar),
 }
 
 impl Circuit<bls12_381::Scalar> for LispCircuit {
@@ -40,19 +73,19 @@ impl Circuit<bls12_381::Scalar> for LispCircuit {
         cs: &mut CS,
     ) -> Result<(), SynthesisError> {
         let mut variables: FnvHashMap<String, Variable> = FnvHashMap::default();
-        let mut params_const = self.params.unwrap_or(FnvHashMap::default());
+        let mut params_const = self.params;
 
         println!("Allocations\n");
-        for (k, v) in &self.allocs.unwrap_or(FnvHashMap::default()) {
+        for (k, v) in &self.allocs {
             println!("k {:?} v {:?}", k, v);
             match v {
                 MalVal::ZKScalar(val) => {
-                    let var = cs.alloc(|| "alloc", || Ok(*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(|| "alloc", || Ok(val_scalar))?;
+                    let var = cs.alloc(|| k, || Ok(val_scalar))?;
                     variables.insert(k.to_string(), var);
                 }
                 _ => {
@@ -62,16 +95,16 @@ impl Circuit<bls12_381::Scalar> for LispCircuit {
         }
 
         println!("Allocations Input\n");
-        for (k, v) in &self.alloc_inputs.unwrap_or(FnvHashMap::default()) {
+        for (k, v) in &self.alloc_inputs {
             println!("k {:?} v {:?}", k, v);
             match v {
                 MalVal::ZKScalar(val) => {
-                    let var = cs.alloc_input(|| "alloc", || Ok(*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(|| "alloc", || Ok(val_scalar))?;
+                    let var = cs.alloc_input(|| k, || Ok(val_scalar))?;
                     variables.insert(k.to_string(), var);
                 }
                 _ => {
@@ -81,15 +114,16 @@ impl Circuit<bls12_381::Scalar> for LispCircuit {
         }
 
         println!("Enforce Allocations\n");
-        // we need to keep order 
-        for alloc_value in self.constraints.unwrap_or(Vec::<EnforceAllocation>::new()).iter() {
+        let mut enforce_sorted = self.constraints.clone();
+        enforce_sorted.sort_by(|a, b| a.idx.cmp(&b.idx)); 
+        for alloc_value in enforce_sorted.iter() {
+            println!("Enforce -> {:?}", alloc_value);
             let coeff = bls12_381::Scalar::one();
             let mut left = bellman::LinearCombination::<Scalar>::zero();
             let mut right = bellman::LinearCombination::<Scalar>::zero();
             let mut output = bellman::LinearCombination::<Scalar>::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();
@@ -103,8 +137,9 @@ impl Circuit<bls12_381::Scalar> for LispCircuit {
                         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() {
@@ -118,6 +153,7 @@ impl Circuit<bls12_381::Scalar> for LispCircuit {
                 } 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() {
@@ -131,52 +167,34 @@ impl Circuit<bls12_381::Scalar> for LispCircuit {
                 } 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, Clone)]
-pub enum MalVal {
-    Nil,
-    Bool(bool),
-    Int(i64),
-    Str(String),
-    Sym(String),
-    List(Rc<Vec<MalVal>>, Rc<MalVal>),
-    Vector(Rc<Vec<MalVal>>, Rc<MalVal>),
-    Hash(Rc<FnvHashMap<String, MalVal>>, Rc<MalVal>),
-    Func(fn(MalArgs) -> MalRet, Rc<MalVal>),
-    MalFunc {
-        eval: fn(ast: MalVal, env: Env) -> MalRet,
-        ast: Rc<MalVal>,
-        env: Env,
-        params: Rc<MalVal>,
-        is_macro: bool,
-        meta: Rc<MalVal>,
-    },
-    Atom(Rc<RefCell<MalVal>>),
-    Zk(Rc<LispCircuit>), // TODO remote it
-    Enforce(Rc<Vec<EnforceAllocation>>),
-    ZKScalar(bls12_381::Scalar),
-}
-
 #[derive(Debug)]
 pub enum MalErr {
     ErrString(String),
     ErrMalVal(MalVal),
 }
 
+impl From<SynthesisError> for MalErr {
+    fn from(err: SynthesisError) -> MalErr {
+        ErrString(err.to_string())
+    }
+}
+
 pub type MalArgs = Vec<MalVal>;
 pub type MalRet = Result<MalVal, MalErr>;