diff --git a/lisp/core.rs b/lisp/core.rs index 3ab3d5ce6..76a4b2d57 100644 --- a/lisp/core.rs +++ b/lisp/core.rs @@ -13,7 +13,7 @@ use crate::types::MalVal::{ use crate::types::{MalArgs, MalRet, MalVal, _assoc, _dissoc, atom, error, func, hash_map}; use bls12_381; -use ff::{Field, PrimeField}; +use ff::PrimeField; use sapvi::bls_extensions::BlsStringConversion; @@ -323,7 +323,7 @@ fn scalar_one(a: MalArgs) -> MalRet { } } -fn cs_one(a: MalArgs) -> MalRet { +fn cs_one(_a: MalArgs) -> MalRet { Ok(vector![vec![Sym("cs::one".to_string())]]) } diff --git a/lisp/lisp.rs b/lisp/lisp.rs index dcdad6f33..cbee39a35 100644 --- a/lisp/lisp.rs +++ b/lisp/lisp.rs @@ -1,11 +1,8 @@ #![allow(non_snake_case)] -use crate::MalVal::Enforce; -use crate::groth16::VerifyingKey; use crate::types::LispCircuit; use crate::MalVal::Zk; use bellman::groth16::PreparedVerifyingKey; -use sapvi::bls_extensions::BlsStringConversion; use sapvi::{ZKVMCircuit, ZKVirtualMachine}; use simplelog::*; @@ -13,19 +10,17 @@ use simplelog::*; use bellman::{gadgets::Assignment, groth16, Circuit, ConstraintSystem, SynthesisError}; use bls12_381::Bls12; use bls12_381::Scalar; -use ff::{Field, PrimeField}; +use ff::PrimeField; +use fnv::FnvHashMap; +use itertools::Itertools; use rand::rngs::OsRng; -use types::EnforceAllocation; -use std::{borrow::BorrowMut, rc::Rc}; use std::time::Instant; +use std::{borrow::BorrowMut, rc::Rc}; use std::{ cell::RefCell, ops::{AddAssign, MulAssign, SubAssign}, }; - -//use std::collections::HashMap; -use fnv::FnvHashMap; -use itertools::Itertools; +use types::EnforceAllocation; use MalVal::ZKScalar; #[macro_use] @@ -39,8 +34,8 @@ extern crate regex; #[macro_use] mod types; use crate::types::MalErr::{ErrMalVal, ErrString}; -use crate::types::MalVal::{Bool, Func, Hash, List, MalFunc, Nil, Str, Sym, Vector}; -use crate::types::{error, format_error, Allocation, MalArgs, MalErr, MalRet, MalVal}; +use crate::types::MalVal::{Bool, Enforce, Func, Hash, List, MalFunc, Nil, Str, Sym, Vector}; +use crate::types::{error, format_error, MalArgs, MalErr, MalRet, MalVal}; mod env; mod printer; mod reader; @@ -306,8 +301,9 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { } Sym(ref a0sym) if a0sym == "setup" => { let a1 = l[1].clone(); - let pvk = setup(a1.clone(), env.clone())?; + // todo ast = eval(a1.clone(), env.clone())?; + let _pvk = setup(a1.clone(), env.clone())?; continue 'tco; } Sym(ref a0sym) if a0sym == "prove" => { @@ -319,86 +315,120 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { let a1 = l[1].clone(); let value = eval(l[2].clone(), env.clone())?; let result = eval(value.clone(), env.clone())?; - // let symbol = MalVal::Sym(a1.pr_str(false)); - // env_set(&env, Sym(a1.pr_str(false)), result.clone()); - if let Hash(allocs, _) = get_allocations(&env, "AllocationsInput")? { - let mut new_hm: FnvHashMap = FnvHashMap::default(); - for (k, v) in allocs.iter() { - new_hm.insert(k.to_string(), eval(v.clone(), env.clone())?); - } - new_hm.insert(a1.pr_str(false), result); - env_set( - &env, - Sym("AllocationsInput".to_string()), - Hash(Rc::new(new_hm), Rc::new(Nil)), - ); - }; + let allocs = get_allocations(&env, "AllocationsInput"); + let mut new_hm: FnvHashMap = FnvHashMap::default(); + for (k, v) in allocs.iter() { + new_hm.insert(k.to_string(), eval(v.clone(), env.clone())?); + } + new_hm.insert(a1.pr_str(false), result); + env_set( + &env, + Sym("AllocationsInput".to_string()), + Hash(Rc::new(new_hm), Rc::new(Nil)), + )?; Ok(Nil) } Sym(ref a0sym) if a0sym == "alloc" => { let a1 = l[1].clone(); let value = eval(l[2].clone(), env.clone())?; let result = eval(value.clone(), env.clone())?; - if let Hash(allocs, _) = get_allocations(&env, "Allocations")? { - let mut new_hm: FnvHashMap = FnvHashMap::default(); - for (k, v) in allocs.iter() { - new_hm.insert(k.to_string(), eval(v.clone(), env.clone())?); - } - new_hm.insert(a1.pr_str(false), result); - env_set( - &env, - Sym("Allocations".to_string()), - Hash(Rc::new(new_hm), Rc::new(Nil)), - ); - }; + let allocs = get_allocations(&env, "Allocations"); + let mut new_hm: FnvHashMap = FnvHashMap::default(); + for (k, v) in allocs.iter() { + new_hm.insert(k.to_string(), eval(v.clone(), env.clone())?); + } + new_hm.insert(a1.pr_str(false), result); + env_set( + &env, + Sym("Allocations".to_string()), + Hash(Rc::new(new_hm), Rc::new(Nil)), + )?; Ok(Nil) } //Sym(ref a0sym) if a0sym == "verify" => { Sym(ref a0sym) if a0sym == "enforce" => { // here i'm considering that we always have tuple with only two elements // also it's important to keep in mind for the sake of brevity of this v0 - // we will not allow calculation or any lisp evaluations inside the enforce - // it means that every symbol will be on allocations and we will do the + // we will not allow calculation or any lisp evaluations inside the enforce + // it means that every symbol will be on allocations and we will do the // find/replace on the bellman circuit, it's nasty v0 - let left = match l[1].clone() { - List(v, _) | Vector(v, _) => { - (v[0].pr_str(false), v[1].pr_str(false)) - } - _ => {("".to_string(), "".to_string())} - }; - let right = match l[1].clone() { - List(v, _) | Vector(v, _) => { - (v[0].pr_str(false), v[1].pr_str(false)) - } - _ => {("".to_string(), "".to_string())} - }; - let output = match l[1].clone() { - List(v, _) | Vector(v, _) => { - (v[0].pr_str(false), v[1].pr_str(false)) - } - _ => {("".to_string(), "".to_string())} - }; - let enforce = EnforceAllocation{left : left, right : right, output : output}; - let mut new_vec: Vec = vec![enforce]; - match get_enforce_allocs(&env)? { - Enforce(v) => { - println!("---> {:?}", v); - for value in v.iter() { - new_vec.push(value.to_owned()); + let mut left_vec = vec![]; + let mut right_vec = vec![]; + let mut out_vec = vec![]; + // todo extract a macro for this + match l[1].clone() { + List(v, _) | Vector(v, _) => { + if let List(_, _) = &v.to_vec()[0] { + for ele in v.to_vec().iter() { + if let List(ele_vec, _) = ele { + left_vec.push(( + ele_vec[0].pr_str(false), + ele_vec[1].pr_str(false), + )); + } + } + } else { + left_vec.push((v[0].pr_str(false), v[1].pr_str(false))); } - }, - _ => {} + } + _ => {} }; + match l[2].clone() { + List(v, _) | Vector(v, _) => { + if let List(_, _) = &v.to_vec()[0] { + for ele in v.to_vec().iter() { + if let List(ele_vec, _) = ele { + right_vec.push(( + ele_vec[0].pr_str(false), + ele_vec[1].pr_str(false), + )); + } + } + } else { + right_vec.push((v[0].pr_str(false), v[1].pr_str(false))); + } + } + _ => {} + }; + match l[3].clone() { + List(v, _) | Vector(v, _) => { + if let List(_, _) = &v.to_vec()[0] { + for ele in v.to_vec().iter() { + if let List(ele_vec, _) = ele { + out_vec.push(( + ele_vec[0].pr_str(false), + ele_vec[1].pr_str(false), + )); + } + } + } else { + out_vec.push((v[0].pr_str(false), v[1].pr_str(false))); + } + } + _ => {} + }; + let enforce = EnforceAllocation { + left: left_vec, + right: right_vec, + output: out_vec, + }; + let mut new_vec: Vec = vec![enforce]; + for value in get_enforce_allocs(&env).iter() { + new_vec.push(value.clone()); + } env_set( &env, Sym("AllocationsEnforce".to_string()), vector![vec![Enforce(Rc::new(new_vec))]], ); - - // println!("allocations {:?}", get_allocations(&env, "Allocations")); - // println!("allocations input {:?}", get_allocations(&env, "AllocationsInput")); - println!("allocations enforce {:?}", get_enforce_allocs(&env)); - + /* + println!("\n\nallocations {:?}", get_allocations(&env, "Allocations")); + println!( + "\n\nallocations input {:?}", + get_allocations(&env, "AllocationsInput") + ); + println!("\n\nallocations enforce {:?}", get_enforce_allocs(&env)); + */ Ok(vector![vec![]]) } _ => match eval_ast(&ast, &env)? { @@ -439,39 +469,56 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { ret } -pub fn get_enforce_allocs(env: &Env) -> MalRet { - let found = match env_find(env, "AllocationsEnforce") { +pub fn get_enforce_allocs(env: &Env) -> Vec { + // todo need some cleanup + match env_find(env, "AllocationsEnforce") { Some(e) => match env_get(&e, &Sym("AllocationsEnforce".to_string())) { - Ok(f) => Ok(f), - _ => Ok(vector![vec![]]) + Ok(f) => { + if let Vector(val, _) = f { + if let Enforce(ret) = &val[0] { + ret.to_vec() + } else { + vec![] + } + } else { + vec![] + } + } + _ => vec![], }, - _ => Ok(vector![vec![]]) - }; - found + _ => vec![], + } } -pub fn get_allocations(env: &Env, key: &str) -> MalRet { - let mut alloc_hm: FnvHashMap = FnvHashMap::default(); +pub fn get_allocations(env: &Env, key: &str) -> Rc> { + let alloc_hm: Rc> = Rc::new(FnvHashMap::default()); match env_find(env, key) { Some(e) => match env_get(&e, &Sym(key.to_string())) { - Ok(f) => Ok(f), - _ => Ok(Hash(Rc::new(alloc_hm), Rc::new(Nil))), + Ok(f) => { + if let Hash(allocs, _) = f { + allocs + } else { + alloc_hm + } + } + _ => alloc_hm, }, - _ => Ok(Hash(Rc::new(alloc_hm), Rc::new(Nil))), + _ => alloc_hm, } } -pub fn setup(ast: MalVal, mut env: Env) -> Result, MalErr> { +pub fn setup(_ast: MalVal, env: Env) -> Result, MalErr> { let start = Instant::now(); // Create parameters for our circuit. In a production deployment these would // be generated securely using a multiparty computation. + let allocs_input = get_allocations(&env, "AllocationsInput"); + let allocs = get_allocations(&env, "Allocations"); + let enforce_allocs = get_enforce_allocs(&env); - // get all allocs from env - - let mut c = LispCircuit { + let c = LispCircuit { params: vec![], - allocs: vec![], - alloc_inputs: vec![], - constraints: vec![], + allocs: allocs.as_ref().clone(), + alloc_inputs: allocs_input.as_ref().clone(), + constraints: enforce_allocs, env: env.clone(), }; // TODO move to another fn @@ -483,16 +530,16 @@ pub fn setup(ast: MalVal, mut env: Env) -> Result, M Ok(pvk) } -pub fn prove(mut ast: MalVal, mut env: Env) -> MalRet { +pub fn prove(_ast: MalVal, env: Env) -> MalRet { // TODO remove it - let quantity = bls12_381::Scalar::from(3); + let _quantity = bls12_381::Scalar::from(3); // Create an instance of our circuit (with the preimage as a witness). let params = { let c = LispCircuit { params: vec![], - allocs: vec![], - alloc_inputs: vec![], + allocs: FnvHashMap::default(), + alloc_inputs: FnvHashMap::default(), constraints: vec![], env: env.clone(), }; @@ -501,20 +548,20 @@ pub fn prove(mut ast: MalVal, mut env: Env) -> MalRet { let circuit = LispCircuit { params: vec![], - allocs: vec![], - alloc_inputs: vec![], + allocs: FnvHashMap::default(), + alloc_inputs: FnvHashMap::default(), constraints: vec![], env: env.clone(), }; let start = Instant::now(); // Create a Groth16 proof with our parameters. - let proof = groth16::create_random_proof(circuit, ¶ms, &mut OsRng).unwrap(); + let _proof = groth16::create_random_proof(circuit, ¶ms, &mut OsRng).unwrap(); println!("Prove: [{:?}]", start.elapsed()); Ok(MalVal::Nil) } -pub fn verify(ast: &MalVal) -> MalRet { - let public_input = vec![bls12_381::Scalar::from(27)]; +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()); @@ -556,7 +603,7 @@ fn main() -> Result<(), ()> { match matches.subcommand() { Some(("load", matches)) => { let file: String = matches.value_of("FILE").unwrap().parse().unwrap(); - repl_load(file); + repl_load(file)?; } _ => { eprintln!("error: Invalid subcommand invoked"); @@ -585,5 +632,4 @@ fn repl_load(file: String) -> Result<(), ()> { std::process::exit(1); } } - Ok(()) } diff --git a/lisp/new-cs.lisp b/lisp/new-cs.lisp index e1839bfd2..a077a5f00 100644 --- a/lisp/new-cs.lisp +++ b/lisp/new-cs.lisp @@ -10,7 +10,10 @@ ;; (enforce left right output) ( (enforce - (scalar::one x) + ( + (scalar::one x) + (scalar::one x2) + ) ;;(scalar::one::neg x) (scalar::one x) (scalar::one x2) diff --git a/lisp/printer.rs b/lisp/printer.rs index 293d1d353..1a9047c0e 100644 --- a/lisp/printer.rs +++ b/lisp/printer.rs @@ -1,5 +1,5 @@ use crate::types::MalVal; -use crate::types::MalVal::{Atom, Bool, Func, Hash, Int, List, MalFunc, Nil, Str, Sym, Vector, Zk}; +use crate::types::MalVal::{Atom, Bool, Func, Hash, Int, List, MalFunc, Nil, Str, Sym, Vector}; fn escape_str(s: &str) -> String { s.chars() diff --git a/lisp/types.rs b/lisp/types.rs index 6c485e126..8c3c91963 100644 --- a/lisp/types.rs +++ b/lisp/types.rs @@ -1,20 +1,16 @@ -use bellman::groth16::PreparedVerifyingKey; use bellman::Circuit; use bellman::ConstraintSystem; use bellman::SynthesisError; -use bls12_381::Bls12; use std::cell::RefCell; use std::rc::Rc; //use std::collections::HashMap; use fnv::FnvHashMap; use itertools::Itertools; -use crate::env; 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 bls12_381::Scalar; -use sapvi::{BlsStringConversion, ConstraintInstruction}; #[derive(Debug, Clone)] pub struct Allocation { @@ -24,29 +20,27 @@ pub struct Allocation { #[derive(Debug, Clone)] pub struct EnforceAllocation { - pub left: (String, String), - pub right: (String, String), - pub output: (String, String) + pub left: Vec<(String, String)>, + pub right: Vec<(String, String)>, + pub output: Vec<(String, String)>, } #[derive(Debug, Clone)] pub struct LispCircuit { - // TODO refactor to vec pub params: Vec>, - pub allocs: Vec>, - pub alloc_inputs: Vec>, - pub constraints: Vec>, + pub allocs: FnvHashMap, + pub alloc_inputs: FnvHashMap, + pub constraints: Vec, pub env: Env, } impl Circuit for LispCircuit { fn synthesize>( self, - cs: &mut CS, + _cs: &mut CS, ) -> Result<(), SynthesisError> { + println!("something called this"); for alloc_value in &self.allocs { - // let var = cs.alloc(|| "private alloc", ||)?; - // TODO use env println!("{:?}", alloc_value); }