lisp.rs 18 KB

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