lisp.rs 18 KB

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