lisp.rs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. #![allow(non_snake_case)]
  2. use crate::groth16::VerifyingKey;
  3. use crate::types::LispCircuit;
  4. use crate::MalVal::Enforce;
  5. use crate::MalVal::Zk;
  6. use bellman::groth16::PreparedVerifyingKey;
  7. use sapvi::bls_extensions::BlsStringConversion;
  8. use sapvi::{ZKVMCircuit, ZKVirtualMachine};
  9. use simplelog::*;
  10. use bellman::{gadgets::Assignment, groth16, Circuit, ConstraintSystem, SynthesisError};
  11. use bls12_381::Bls12;
  12. use bls12_381::Scalar;
  13. use ff::{Field, PrimeField};
  14. use rand::rngs::OsRng;
  15. use std::time::Instant;
  16. use std::{borrow::BorrowMut, rc::Rc};
  17. use std::{
  18. cell::RefCell,
  19. ops::{AddAssign, MulAssign, SubAssign},
  20. };
  21. use types::EnforceAllocation;
  22. //use std::collections::HashMap;
  23. use fnv::FnvHashMap;
  24. use itertools::Itertools;
  25. use MalVal::ZKScalar;
  26. #[macro_use]
  27. extern crate clap;
  28. #[macro_use]
  29. extern crate lazy_static;
  30. extern crate fnv;
  31. extern crate itertools;
  32. extern crate regex;
  33. #[macro_use]
  34. mod types;
  35. use crate::types::MalErr::{ErrMalVal, ErrString};
  36. use crate::types::MalVal::{Bool, Func, Hash, List, MalFunc, Nil, Str, Sym, Vector};
  37. use crate::types::{error, format_error, Allocation, MalArgs, MalErr, MalRet, MalVal};
  38. mod env;
  39. mod printer;
  40. mod reader;
  41. use crate::env::{env_bind, env_find, env_get, env_new, env_set, env_sets, Env};
  42. #[macro_use]
  43. mod core;
  44. pub const ZK_CIRCUIT_ENV_KEY: &str = "ZKC";
  45. // read
  46. fn read(str: &str) -> MalRet {
  47. reader::read_str(str.to_string())
  48. }
  49. // eval
  50. fn qq_iter(elts: &MalArgs) -> MalVal {
  51. let mut acc = list![];
  52. for elt in elts.iter().rev() {
  53. if let List(v, _) = elt {
  54. if v.len() == 2 {
  55. if let Sym(ref s) = v[0] {
  56. if s == "splice-unquote" {
  57. acc = list![Sym("concat".to_string()), v[1].clone(), acc];
  58. continue;
  59. }
  60. }
  61. }
  62. }
  63. acc = list![Sym("cons".to_string()), quasiquote(&elt), acc];
  64. }
  65. return acc;
  66. }
  67. fn quasiquote(ast: &MalVal) -> MalVal {
  68. match ast {
  69. List(v, _) => {
  70. if v.len() == 2 {
  71. if let Sym(ref s) = v[0] {
  72. if s == "unquote" {
  73. return v[1].clone();
  74. }
  75. }
  76. }
  77. return qq_iter(&v);
  78. }
  79. Vector(v, _) => return list![Sym("vec".to_string()), qq_iter(&v)],
  80. Hash(_, _) | Sym(_) => return list![Sym("quote".to_string()), ast.clone()],
  81. _ => ast.clone(),
  82. }
  83. }
  84. fn is_macro_call(ast: &MalVal, env: &Env) -> Option<(MalVal, MalArgs)> {
  85. match ast {
  86. List(v, _) => match v[0] {
  87. Sym(ref s) => match env_find(env, s) {
  88. Some(e) => match env_get(&e, &v[0]) {
  89. Ok(f @ MalFunc { is_macro: true, .. }) => Some((f, v[1..].to_vec())),
  90. _ => None,
  91. },
  92. _ => None,
  93. },
  94. _ => None,
  95. },
  96. _ => None,
  97. }
  98. }
  99. fn macroexpand(mut ast: MalVal, env: &Env) -> (bool, MalRet) {
  100. let mut was_expanded = false;
  101. while let Some((mf, args)) = is_macro_call(&ast, env) {
  102. //println!("macroexpand 1: {:?}", ast);
  103. ast = match mf.apply(args) {
  104. Err(e) => return (false, Err(e)),
  105. Ok(a) => a,
  106. };
  107. //println!("macroexpand 2: {:?}", ast);
  108. was_expanded = true;
  109. }
  110. (was_expanded, Ok(ast))
  111. }
  112. fn eval_ast(ast: &MalVal, env: &Env) -> MalRet {
  113. match ast {
  114. Sym(_) => Ok(env_get(&env, &ast)?),
  115. List(v, _) => {
  116. let mut lst: MalArgs = vec![];
  117. for a in v.iter() {
  118. lst.push(eval(a.clone(), env.clone())?)
  119. }
  120. Ok(list!(lst))
  121. }
  122. Vector(v, _) => {
  123. let mut lst: MalArgs = vec![];
  124. for a in v.iter() {
  125. lst.push(eval(a.clone(), env.clone())?)
  126. }
  127. Ok(vector!(lst))
  128. }
  129. Hash(hm, _) => {
  130. let mut new_hm: FnvHashMap<String, MalVal> = FnvHashMap::default();
  131. for (k, v) in hm.iter() {
  132. new_hm.insert(k.to_string(), eval(v.clone(), env.clone())?);
  133. }
  134. Ok(Hash(Rc::new(new_hm), Rc::new(Nil)))
  135. }
  136. _ => Ok(ast.clone()),
  137. }
  138. }
  139. fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
  140. let ret: MalRet;
  141. 'tco: loop {
  142. ret = match ast.clone() {
  143. List(l, _) => {
  144. if l.len() == 0 {
  145. return Ok(ast);
  146. }
  147. match macroexpand(ast.clone(), &env) {
  148. (true, Ok(new_ast)) => {
  149. ast = new_ast;
  150. continue 'tco;
  151. }
  152. (_, Err(e)) => return Err(e),
  153. _ => (),
  154. }
  155. if l.len() == 0 {
  156. return Ok(ast);
  157. }
  158. let a0 = &l[0];
  159. match a0 {
  160. Sym(ref a0sym) if a0sym == "def!" => {
  161. env_set(&env, l[1].clone(), eval(l[2].clone(), env.clone())?)
  162. }
  163. Sym(ref a0sym) if a0sym == "let*" => {
  164. env = env_new(Some(env.clone()));
  165. let (a1, a2) = (l[1].clone(), l[2].clone());
  166. match a1 {
  167. List(ref binds, _) | Vector(ref binds, _) => {
  168. for (b, e) in binds.iter().tuples() {
  169. match b {
  170. Sym(_) => {
  171. let _ = env_set(
  172. &env,
  173. b.clone(),
  174. eval(e.clone(), env.clone())?,
  175. );
  176. }
  177. _ => {
  178. return error("let* with non-Sym binding");
  179. }
  180. }
  181. }
  182. }
  183. _ => {
  184. return error("let* with non-List bindings");
  185. }
  186. };
  187. ast = a2;
  188. continue 'tco;
  189. }
  190. Sym(ref a0sym) if a0sym == "quote" => Ok(l[1].clone()),
  191. Sym(ref a0sym) if a0sym == "quasiquoteexpand" => Ok(quasiquote(&l[1])),
  192. Sym(ref a0sym) if a0sym == "quasiquote" => {
  193. ast = quasiquote(&l[1]);
  194. continue 'tco;
  195. }
  196. Sym(ref a0sym) if a0sym == "defmacro!" => {
  197. let (a1, a2) = (l[1].clone(), l[2].clone());
  198. let r = eval(a2, env.clone())?;
  199. match r {
  200. MalFunc {
  201. eval,
  202. ast,
  203. env,
  204. params,
  205. ..
  206. } => Ok(env_set(
  207. &env,
  208. a1.clone(),
  209. MalFunc {
  210. eval: eval,
  211. ast: ast.clone(),
  212. env: env.clone(),
  213. params: params.clone(),
  214. is_macro: true,
  215. meta: Rc::new(Nil),
  216. },
  217. )?),
  218. _ => error("set_macro on non-function"),
  219. }
  220. }
  221. Sym(ref a0sym) if a0sym == "macroexpand" => {
  222. match macroexpand(l[1].clone(), &env) {
  223. (_, Ok(new_ast)) => Ok(new_ast),
  224. (_, e) => return e,
  225. }
  226. }
  227. Sym(ref a0sym) if a0sym == "try*" => match eval(l[1].clone(), env.clone()) {
  228. Err(ref e) if l.len() >= 3 => {
  229. let exc = match e {
  230. ErrMalVal(mv) => mv.clone(),
  231. ErrString(s) => Str(s.to_string()),
  232. };
  233. match l[2].clone() {
  234. List(c, _) => {
  235. let catch_env = env_bind(
  236. Some(env.clone()),
  237. list!(vec![c[1].clone()]),
  238. vec![exc],
  239. )?;
  240. eval(c[2].clone(), catch_env)
  241. }
  242. _ => error("invalid catch block"),
  243. }
  244. }
  245. res => res,
  246. },
  247. Sym(ref a0sym) if a0sym == "do" => {
  248. match eval_ast(&list!(l[1..l.len() - 1].to_vec()), &env)? {
  249. List(_, _) => {
  250. ast = l.last().unwrap_or(&Nil).clone();
  251. continue 'tco;
  252. }
  253. _ => error("invalid do form"),
  254. }
  255. }
  256. Sym(ref a0sym) if a0sym == "if" => {
  257. let cond = eval(l[1].clone(), env.clone())?;
  258. match cond {
  259. Bool(false) | Nil if l.len() >= 4 => {
  260. ast = l[3].clone();
  261. continue 'tco;
  262. }
  263. Bool(false) | Nil => Ok(Nil),
  264. _ if l.len() >= 3 => {
  265. ast = l[2].clone();
  266. continue 'tco;
  267. }
  268. _ => Ok(Nil),
  269. }
  270. }
  271. Sym(ref a0sym) if a0sym == "fn*" => {
  272. let (a1, a2) = (l[1].clone(), l[2].clone());
  273. Ok(MalFunc {
  274. eval: eval,
  275. ast: Rc::new(a2),
  276. env: env,
  277. params: Rc::new(a1),
  278. is_macro: false,
  279. meta: Rc::new(Nil),
  280. })
  281. }
  282. Sym(ref a0sym) if a0sym == "eval" => {
  283. ast = eval(l[1].clone(), env.clone())?;
  284. while let Some(ref e) = env.clone().outer {
  285. env = e.clone();
  286. }
  287. continue 'tco;
  288. }
  289. Sym(ref a0sym) if a0sym == "setup" => {
  290. let a1 = l[1].clone();
  291. let pvk = setup(a1.clone(), env.clone())?;
  292. ast = eval(a1.clone(), env.clone())?;
  293. continue 'tco;
  294. }
  295. Sym(ref a0sym) if a0sym == "prove" => {
  296. let a1 = l[0].clone();
  297. println!("prove {:?}", a1);
  298. prove(a1.clone(), env.clone())
  299. }
  300. Sym(ref a0sym) if a0sym == "alloc-input" => {
  301. let a1 = l[1].clone();
  302. let value = eval(l[2].clone(), env.clone())?;
  303. let result = eval(value.clone(), env.clone())?;
  304. // let symbol = MalVal::Sym(a1.pr_str(false));
  305. // env_set(&env, Sym(a1.pr_str(false)), result.clone());
  306. if let Hash(allocs, _) = get_allocations(&env, "AllocationsInput")? {
  307. let mut new_hm: FnvHashMap<String, MalVal> = FnvHashMap::default();
  308. for (k, v) in allocs.iter() {
  309. new_hm.insert(k.to_string(), eval(v.clone(), env.clone())?);
  310. }
  311. new_hm.insert(a1.pr_str(false), result);
  312. env_set(
  313. &env,
  314. Sym("AllocationsInput".to_string()),
  315. Hash(Rc::new(new_hm), Rc::new(Nil)),
  316. )?;
  317. };
  318. Ok(Nil)
  319. }
  320. Sym(ref a0sym) if a0sym == "alloc" => {
  321. let a1 = l[1].clone();
  322. let value = eval(l[2].clone(), env.clone())?;
  323. let result = eval(value.clone(), env.clone())?;
  324. if let Hash(allocs, _) = get_allocations(&env, "Allocations")? {
  325. let mut new_hm: FnvHashMap<String, MalVal> = FnvHashMap::default();
  326. for (k, v) in allocs.iter() {
  327. new_hm.insert(k.to_string(), eval(v.clone(), env.clone())?);
  328. }
  329. new_hm.insert(a1.pr_str(false), result);
  330. env_set(
  331. &env,
  332. Sym("Allocations".to_string()),
  333. Hash(Rc::new(new_hm), Rc::new(Nil)),
  334. )?;
  335. };
  336. Ok(Nil)
  337. }
  338. //Sym(ref a0sym) if a0sym == "verify" => {
  339. Sym(ref a0sym) if a0sym == "enforce" => {
  340. // here i'm considering that we always have tuple with only two elements
  341. // also it's important to keep in mind for the sake of brevity of this v0
  342. // we will not allow calculation or any lisp evaluations inside the enforce
  343. // it means that every symbol will be on allocations and we will do the
  344. // find/replace on the bellman circuit, it's nasty v0
  345. let left = match l[1].clone() {
  346. List(v, _) | Vector(v, _) => {
  347. println!("v {:?}", v.to_vec());
  348. (v[0].pr_str(false), v[1].pr_str(false))
  349. }
  350. _ => ("".to_string(), "".to_string()),
  351. };
  352. let right = match l[1].clone() {
  353. List(v, _) | Vector(v, _) => {
  354. println!("v {:?}", v.to_vec());
  355. (v[0].pr_str(false), v[1].pr_str(false))
  356. }
  357. _ => ("".to_string(), "".to_string()),
  358. };
  359. let output = match l[1].clone() {
  360. List(v, _) | Vector(v, _) => (v[0].pr_str(false), v[1].pr_str(false)),
  361. _ => ("".to_string(), "".to_string()),
  362. };
  363. /*
  364. let enforce = EnforceAllocation {
  365. left: left,
  366. right: right,
  367. output: output,
  368. };
  369. let mut new_vec: Vec<EnforceAllocation> = vec![enforce];
  370. match get_enforce_allocs(&env)? {
  371. Vector(v, _) => {
  372. for value in v.iter() {
  373. println!("VALUES {:?} \n", value);
  374. match value {
  375. Enforce(v) => {
  376. println!("{:?}", v);
  377. },
  378. _ => {}
  379. };
  380. }
  381. }
  382. v => {
  383. println!("something wrong. {:?}", v)
  384. }
  385. };
  386. env_set(
  387. &env,
  388. Sym("AllocationsEnforce".to_string()),
  389. vector![vec![Enforce(Rc::new(new_vec))]],
  390. );
  391. */
  392. // println!("allocations {:?}", get_allocations(&env, "Allocations"));
  393. // println!("allocations input {:?}", get_allocations(&env, "AllocationsInput"));
  394. //println!("allocations enforce {:?}", get_enforce_allocs(&env));
  395. Ok(vector![vec![]])
  396. }
  397. _ => match eval_ast(&ast, &env)? {
  398. List(ref el, _) => {
  399. let ref f = el[0].clone();
  400. let args = el[1..].to_vec();
  401. match f {
  402. Func(_, _) => f.apply(args),
  403. MalFunc {
  404. ast: mast,
  405. env: menv,
  406. params,
  407. ..
  408. } => {
  409. let a = &**mast;
  410. let p = &**params;
  411. env = env_bind(Some(menv.clone()), p.clone(), args)?;
  412. ast = a.clone();
  413. continue 'tco;
  414. }
  415. _ => {
  416. Ok(vector![el.to_vec()])
  417. //error("call non-function")
  418. }
  419. }
  420. }
  421. _ => error("expected a list"),
  422. },
  423. }
  424. }
  425. _ => eval_ast(&ast, &env),
  426. };
  427. break;
  428. } // end 'tco loop
  429. ret
  430. }
  431. pub fn get_enforce_allocs(env: &Env) -> MalRet {
  432. let found = match env_find(env, "AllocationsEnforce") {
  433. Some(e) => match env_get(&e, &Sym("AllocationsEnforce".to_string())) {
  434. Ok(f) => {
  435. println!("Found {:?}", f);
  436. Ok(f)
  437. }
  438. _ => Ok(vector![vec![]]),
  439. },
  440. _ => Ok(vector![vec![]]),
  441. };
  442. found
  443. }
  444. pub fn get_allocations(env: &Env, key: &str) -> MalRet {
  445. let alloc_hm: FnvHashMap<String, MalVal> = FnvHashMap::default();
  446. match env_find(env, key) {
  447. Some(e) => match env_get(&e, &Sym(key.to_string())) {
  448. Ok(f) => Ok(f),
  449. _ => Ok(Hash(Rc::new(alloc_hm), Rc::new(Nil))),
  450. },
  451. _ => Ok(Hash(Rc::new(alloc_hm), Rc::new(Nil))),
  452. }
  453. }
  454. pub fn setup(ast: MalVal, env: Env) -> Result<PreparedVerifyingKey<Bls12>, MalErr> {
  455. let start = Instant::now();
  456. // Create parameters for our circuit. In a production deployment these would
  457. // be generated securely using a multiparty computation.
  458. // get all allocs from env
  459. let c = LispCircuit {
  460. params: vec![],
  461. allocs: vec![],
  462. alloc_inputs: vec![],
  463. constraints: vec![],
  464. env: env.clone(),
  465. };
  466. // TODO move to another fn
  467. let random_parameters =
  468. groth16::generate_random_parameters::<Bls12, _, _>(c, &mut OsRng).unwrap();
  469. let pvk = groth16::prepare_verifying_key(&random_parameters.vk);
  470. println!("Setup: [{:?}]", start.elapsed());
  471. Ok(pvk)
  472. }
  473. pub fn prove(ast: MalVal, env: Env) -> MalRet {
  474. // TODO remove it
  475. let quantity = bls12_381::Scalar::from(3);
  476. // Create an instance of our circuit (with the preimage as a witness).
  477. let params = {
  478. let c = LispCircuit {
  479. params: vec![],
  480. allocs: vec![],
  481. alloc_inputs: vec![],
  482. constraints: vec![],
  483. env: env.clone(),
  484. };
  485. groth16::generate_random_parameters::<Bls12, _, _>(c, &mut OsRng).unwrap()
  486. };
  487. let circuit = LispCircuit {
  488. params: vec![],
  489. allocs: vec![],
  490. alloc_inputs: vec![],
  491. constraints: vec![],
  492. env: env.clone(),
  493. };
  494. let start = Instant::now();
  495. // Create a Groth16 proof with our parameters.
  496. let proof = groth16::create_random_proof(circuit, &params, &mut OsRng).unwrap();
  497. println!("Prove: [{:?}]", start.elapsed());
  498. Ok(MalVal::Nil)
  499. }
  500. pub fn verify(ast: &MalVal) -> MalRet {
  501. let public_input = vec![bls12_381::Scalar::from(27)];
  502. let start = Instant::now();
  503. // Check the proof!
  504. //assert!(groth16::verify_proof(&pvk, &proof, &public_input).is_ok());
  505. println!("Verify: [{:?}]", start.elapsed());
  506. Ok(MalVal::Nil)
  507. }
  508. // print
  509. fn print(ast: &MalVal) -> String {
  510. ast.pr_str(true)
  511. }
  512. fn rep(str: &str, env: &Env) -> Result<String, MalErr> {
  513. let ast = read(str)?;
  514. let exp = eval(ast, env.clone())?;
  515. Ok(print(&exp))
  516. }
  517. fn main() -> Result<(), ()> {
  518. let matches = clap_app!(zklisp =>
  519. (version: "0.1.0")
  520. (author: "mileschet <miles.chet@gmail.com>")
  521. (about: "A Lisp Interpreter for Zero Knowledge Virtual Machine")
  522. (@subcommand load =>
  523. (about: "Load the file into the interpreter")
  524. (@arg FILE: +required "Lisp Contract filename")
  525. )
  526. )
  527. .get_matches();
  528. CombinedLogger::init(vec![TermLogger::new(
  529. LevelFilter::Debug,
  530. Config::default(),
  531. TerminalMode::Mixed,
  532. )
  533. .unwrap()])
  534. .unwrap();
  535. match matches.subcommand() {
  536. Some(("load", matches)) => {
  537. let file: String = matches.value_of("FILE").unwrap().parse().unwrap();
  538. repl_load(file)?;
  539. }
  540. _ => {
  541. eprintln!("error: Invalid subcommand invoked");
  542. std::process::exit(-1);
  543. }
  544. }
  545. Ok(())
  546. }
  547. fn repl_load(file: String) -> Result<(), ()> {
  548. let repl_env = env_new(None);
  549. for (k, v) in core::ns() {
  550. env_sets(&repl_env, k, v);
  551. }
  552. let _ = rep("(def! not (fn* (a) (if a false true)))", &repl_env);
  553. let _ = rep(
  554. "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\nnil)\")))))",
  555. &repl_env,
  556. );
  557. //let _ = rep("(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))", &repl_env);
  558. match rep(&format!("(load-file \"{}\")", file), &repl_env) {
  559. Ok(_) => std::process::exit(0),
  560. Err(e) => {
  561. println!("Error: {}", format_error(e));
  562. std::process::exit(1);
  563. }
  564. }
  565. Ok(())
  566. }