diff --git a/benches/sha256.rs b/benches/sha256.rs index c09d7967f6..c6796eaaa1 100644 --- a/benches/sha256.rs +++ b/benches/sha256.rs @@ -18,7 +18,7 @@ use lurk::{ eval::lang::Lang, field::LurkField, lem::{ - eval::{evaluate, make_eval_step_from_config, EvalConfig}, + eval::{evaluate, make_cprocs_funcs_from_lang, make_eval_step_from_config, EvalConfig}, multiframe::MultiFrame, pointers::Ptr, store::Store, @@ -134,7 +134,7 @@ fn sha256_ivc_prove( let prover = NovaProver::new(prove_params.reduction_count, lang_rc.clone()); - let frames = &evaluate(Some((&lurk_step, &lang)), ptr, store, limit).unwrap(); + let frames = &evaluate(Some((&lurk_step, &[], &lang)), ptr, store, limit).unwrap(); b.iter_batched( || frames, @@ -215,7 +215,7 @@ fn sha256_ivc_prove_compressed( let prover = NovaProver::new(prove_params.reduction_count, lang_rc.clone()); - let frames = &evaluate(Some((&lurk_step, &lang)), ptr, store, limit).unwrap(); + let frames = &evaluate(Some((&lurk_step, &[], &lang)), ptr, store, limit).unwrap(); b.iter_batched( || frames, @@ -274,6 +274,7 @@ fn sha256_nivc_prove( let lang_rc = Arc::new(lang.clone()); let lurk_step = make_eval_step_from_config(&EvalConfig::new_ivc(&lang)); + let cprocs = make_cprocs_funcs_from_lang(&lang); // use cached public params let instance = Instance::new( @@ -298,7 +299,7 @@ fn sha256_nivc_prove( let prover = SuperNovaProver::new(prove_params.reduction_count, lang_rc.clone()); - let frames = &evaluate(Some((&lurk_step, &lang)), ptr, store, limit).unwrap(); + let frames = &evaluate(Some((&lurk_step, &cprocs, &lang)), ptr, store, limit).unwrap(); b.iter_batched( || frames, diff --git a/examples/sha256_nivc.rs b/examples/sha256_nivc.rs index 71392dfa67..5cbfce91ab 100644 --- a/examples/sha256_nivc.rs +++ b/examples/sha256_nivc.rs @@ -8,7 +8,7 @@ use lurk::{ eval::lang::Lang, field::LurkField, lem::{ - eval::{evaluate, make_eval_step_from_config, EvalConfig}, + eval::{evaluate, make_cprocs_funcs_from_lang, make_eval_step_from_config, EvalConfig}, multiframe::MultiFrame, pointers::Ptr, store::Store, @@ -77,7 +77,8 @@ fn main() { let lang_rc = Arc::new(lang.clone()); let lurk_step = make_eval_step_from_config(&EvalConfig::new_nivc(&lang)); - let frames = evaluate(Some((&lurk_step, &lang)), call, store, 1000).unwrap(); + let cprocs = make_cprocs_funcs_from_lang(&lang); + let frames = evaluate(Some((&lurk_step, &cprocs, &lang)), call, store, 1000).unwrap(); let supernova_prover = SuperNovaProver::, MultiFrame<'_, _, _>>::new( REDUCTION_COUNT, diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 43ae1c9fd7..13c6765398 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -22,7 +22,7 @@ use std::{ }; use crate::{ - eval::lang::Coproc, + eval::lang::{Coproc, Lang}, field::{LanguageField, LurkField}, lem::{multiframe::MultiFrame, store::Store}, public_parameters::disk_cache::public_params_dir, @@ -94,7 +94,7 @@ struct LoadArgs { #[clap(long, value_enum)] backend: Option, - /// Arithmetic field (defaults to the backend's standard field) + /// Arithmetic field (defaults to "Pallas") #[clap(long, value_enum)] field: Option, @@ -207,7 +207,7 @@ struct ReplArgs { #[clap(long, value_enum)] backend: Option, - /// Arithmetic field (defaults to the backend's standard field) + /// Arithmetic field (defaults to "Pallas") #[clap(long, value_enum)] field: Option, @@ -305,7 +305,9 @@ fn get_store serde::de::Deserialize<'a>>( macro_rules! new_repl { ( $cli: expr, $rc: expr, $limit: expr, $field: path, $backend: expr ) => {{ let store = get_store(&$cli.zstore).with_context(|| "reading store from file")?; - Repl::<$field>::new(store, $rc, $limit, $backend) + // TODO: pick a predefined `Lang` according to a CLI parameter + let lang = Lang::new(); + Repl::<$field, Coproc<$field>>::new(store, lang, $rc, $limit, $backend) }}; } @@ -420,6 +422,10 @@ struct VerifyArgs { #[clap(value_parser)] proof_key: String, + /// Arithmetic field (defaults to "Pallas") + #[clap(long, value_enum)] + field: Option, + /// Path to public parameters directory #[clap(long, value_parser)] public_params_dir: Option, @@ -439,6 +445,10 @@ struct InspectArgs { #[clap(value_parser)] proof_key: String, + /// Arithmetic field (defaults to "Pallas") + #[clap(long, value_enum)] + field: Option, + /// Flag to show the entire proof meta-data #[arg(long)] full: bool, @@ -593,9 +603,20 @@ impl Cli { } cli_config(verify_args.config.as_ref(), Some(&cli_settings)); - LurkProof::<_, _, MultiFrame<'_, _, Coproc>>::verify_proof( - &verify_args.proof_key, - ) + // TODO: pick a predefined `Lang` according to a CLI parameter + match verify_args.field.unwrap_or_default() { + LanguageField::BN256 => { + LurkProof::<_, _, MultiFrame<'_, _, Coproc>>::verify_proof( + &verify_args.proof_key, + ) + } + LanguageField::Pallas => { + LurkProof::<_, _, MultiFrame<'_, _, Coproc>>::verify_proof( + &verify_args.proof_key, + ) + } + _ => unreachable!(), + } } #[allow(unused_variables)] Command::Inspect(inspect_args) => { @@ -606,11 +627,19 @@ impl Cli { } cli_config(None, Some(&cli_settings)); - LurkProofMeta::::inspect_proof( - &inspect_args.proof_key, - None, - inspect_args.full, - ) + match inspect_args.field.unwrap_or_default() { + LanguageField::BN256 => LurkProofMeta::::inspect_proof( + &inspect_args.proof_key, + None, + inspect_args.full, + ), + LanguageField::Pallas => LurkProofMeta::::inspect_proof( + &inspect_args.proof_key, + None, + inspect_args.full, + ), + _ => unreachable!(), + } } Command::Circom(circom_args) => { use crate::cli::circom::create_circom_gadget; diff --git a/src/cli/repl/meta_cmd.rs b/src/cli/repl/meta_cmd.rs index e38fa3b2d0..fdb727ee3f 100644 --- a/src/cli/repl/meta_cmd.rs +++ b/src/cli/repl/meta_cmd.rs @@ -14,7 +14,6 @@ use crate::{ zstore::ZDag, }, coprocessor::Coprocessor, - eval::lang::Coproc, field::LurkField, lem::{ eval::evaluate_with_env_and_cont, @@ -36,21 +35,24 @@ use crate::{ use super::Repl; -pub(super) struct MetaCmd { +pub(super) struct MetaCmd + Serialize + DeserializeOwned> { name: &'static str, summary: &'static str, format: &'static str, description: &'static [&'static str], example: &'static [&'static str], - pub(super) run: fn(repl: &mut Repl, args: &Ptr) -> Result<()>, + pub(super) run: fn(repl: &mut Repl, args: &Ptr) -> Result<()>, } -impl MetaCmd +impl< + F: CurveCycleEquipped + Serialize + DeserializeOwned, + C: Coprocessor + Serialize + DeserializeOwned + 'static, + > MetaCmd where ::Repr: Abomonation, <<::E2 as Engine>::Scalar as PrimeField>::Repr: Abomonation, { - const LOAD: MetaCmd = MetaCmd { + const LOAD: MetaCmd = MetaCmd { name: "load", summary: "Load lurk expressions from a file.", format: "!(load )", @@ -66,7 +68,7 @@ where }, }; - const DEF: MetaCmd = MetaCmd { + const DEF: MetaCmd = MetaCmd { name: "def", summary: "Extends env with a non-recursive binding.", format: "!(def )", @@ -75,7 +77,7 @@ where "The state's env is set to the result.", ], example: &["!(def foo (lambda () 123))"], - run: |repl: &mut Repl, args: &Ptr| { + run: |repl: &mut Repl, args: &Ptr| { let (first, second) = repl.peek2(args)?; let new_name = first.fmt_to_string(&repl.store, &repl.state.borrow()); let l = repl.store.intern_lurk_symbol("let"); @@ -91,7 +93,7 @@ where }, }; - const DEFREC: MetaCmd = MetaCmd { + const DEFREC: MetaCmd = MetaCmd { name: "defrec", summary: "Extends the env with a recursive binding.", format: "!(defrec )", @@ -119,7 +121,7 @@ where }, }; - const ASSERT: MetaCmd = MetaCmd { + const ASSERT: MetaCmd = MetaCmd { name: "assert", summary: "Assert that an expression evaluates to true.", format: "!(assert )", @@ -139,7 +141,7 @@ where }, }; - const ASSERT_EQ: MetaCmd = MetaCmd { + const ASSERT_EQ: MetaCmd = MetaCmd { name: "assert-eq", summary: "Assert that two expressions evaluate to the same value.", format: "!(assert-eq )", @@ -168,7 +170,7 @@ where }, }; - const ASSERT_EMITTED: MetaCmd = MetaCmd { + const ASSERT_EMITTED: MetaCmd = MetaCmd { name: "assert-emitted", summary: @@ -205,7 +207,7 @@ where }, }; - const ASSERT_ERROR: MetaCmd = MetaCmd { + const ASSERT_ERROR: MetaCmd = MetaCmd { name: "assert-error", summary: "Assert that a evaluation of fails.", format: "!(assert-error )", @@ -225,7 +227,7 @@ where }, }; - const COMMIT: MetaCmd = MetaCmd { + const COMMIT: MetaCmd = MetaCmd { name: "commit", summary: @@ -244,7 +246,7 @@ where } }; - const HIDE: MetaCmd = MetaCmd { + const HIDE: MetaCmd = MetaCmd { name: "hide", summary: "Return and persist the commitment of using secret .", format: "!(hide )", @@ -274,7 +276,7 @@ where }, }; - const FETCH: MetaCmd = MetaCmd { + const FETCH: MetaCmd = MetaCmd { name: "fetch", summary: "Add data from a commitment to the repl store.", format: "!(fetch )", @@ -289,7 +291,7 @@ where }, }; - const OPEN: MetaCmd = MetaCmd { + const OPEN: MetaCmd = MetaCmd { name: "open", summary: "Open a commitment.", format: "!(open )", @@ -304,7 +306,7 @@ where }, }; - const CLEAR: MetaCmd = MetaCmd { + const CLEAR: MetaCmd = MetaCmd { name: "clear", summary: "Reset the current environment to be empty.", format: "!(clear)", @@ -316,7 +318,7 @@ where }, }; - const SET_ENV: MetaCmd = MetaCmd { + const SET_ENV: MetaCmd = MetaCmd { name: "set-env", summary: "Set the env to the result of evaluating the first argument.", format: "!(set-env )", @@ -330,7 +332,7 @@ where }, }; - const PROVE: MetaCmd = MetaCmd { + const PROVE: MetaCmd = MetaCmd { name: "prove", summary: @@ -354,7 +356,7 @@ where } }; - const VERIFY: MetaCmd = MetaCmd { + const VERIFY: MetaCmd = MetaCmd { name: "verify", summary: "Verify a proof", format: "!(verify )", @@ -367,13 +369,13 @@ where run: |repl, args| { let first = repl.peek1(args)?; let proof_id = repl.get_string(&first)?; - LurkProof::<_, _, MultiFrame<'_, _, Coproc>>::verify_proof( + LurkProof::<_, _, MultiFrame<'_, _, C>>::verify_proof( &proof_id, ) } }; - const DEFPACKAGE: MetaCmd = MetaCmd { + const DEFPACKAGE: MetaCmd = MetaCmd { name: "defpackage", summary: "Add a package to the state.", format: "!(defpackage )", @@ -394,7 +396,7 @@ where }, }; - const IMPORT: MetaCmd = MetaCmd { + const IMPORT: MetaCmd = MetaCmd { name: "import", summary: "Import a single or several packages.", format: "!(import ...)", @@ -425,7 +427,7 @@ where }, }; - const IN_PACKAGE: MetaCmd = MetaCmd { + const IN_PACKAGE: MetaCmd = MetaCmd { name: "in-package", summary: "set the current package.", format: "!(in-package )", @@ -459,7 +461,7 @@ where }, }; - const HELP: MetaCmd = MetaCmd { + const HELP: MetaCmd = MetaCmd { name: "help", summary: "Print help message.", format: "!(help )", @@ -483,7 +485,7 @@ where Tag::Expr(ExprTag::Nil) => { use itertools::Itertools; println!("Available commands:"); - for (_, i) in MetaCmd::::cmds().iter().sorted_by_key(|x| x.0) { + for (_, i) in MetaCmd::::cmds().iter().sorted_by_key(|x| x.0) { println!(" {} - {}", i.name, i.summary); } } @@ -494,7 +496,7 @@ where }; fn meta_help(cmd: &str) { - match MetaCmd::::cmds().get(cmd) { + match MetaCmd::::cmds().get(cmd) { Some(i) => { println!("{} - {}", i.name, i.summary); for &e in i.description.iter() { @@ -512,7 +514,7 @@ where } } - fn call(repl: &mut Repl, args: &Ptr) -> Result<()> { + fn call(repl: &mut Repl, args: &Ptr) -> Result<()> { let (hash_ptr, args) = repl.store.car_cdr(args)?; let hash_expr = match hash_ptr.tag() { Tag::Expr(ExprTag::Cons) => hash_ptr, @@ -534,7 +536,7 @@ where repl.handle_non_meta(repl.store.list(expr_vec)) } - const CALL: MetaCmd = MetaCmd { + const CALL: MetaCmd = MetaCmd { name: "call", summary: "Open a functional commitment then apply arguments to it", format: "!(call )", @@ -546,7 +548,7 @@ where run: Self::call, }; - const CHAIN: MetaCmd = MetaCmd { + const CHAIN: MetaCmd = MetaCmd { name: "chain", summary: "Chain a functional commitment by applying the provided arguments to it", format: "!(chain )", @@ -562,7 +564,7 @@ where (add 0)))", "!(chain 0x14cb06e2d3c594af90d5b670e73595791d7462b20442c24cd56ba2919947d769 1)", ], - run: |repl: &mut Repl, args: &Ptr| { + run: |repl: &mut Repl, args: &Ptr| { Self::call(repl, args)?; let ev = repl .get_evaluation() @@ -585,7 +587,7 @@ where }, }; - fn inspect(repl: &mut Repl, args: &Ptr, full: bool) -> Result<()> { + fn inspect(repl: &mut Repl, args: &Ptr, full: bool) -> Result<()> { let first = repl.peek1(args)?; let proof_id = repl.get_string(&first)?; LurkProofMeta::::inspect_proof( @@ -595,7 +597,7 @@ where ) } - const INSPECT: MetaCmd = MetaCmd { + const INSPECT: MetaCmd = MetaCmd { name: "inspect", summary: "Print part of a proof claim", format: "!(inspect )", @@ -609,7 +611,7 @@ where } }; - const INSPECT_FULL: MetaCmd = MetaCmd { + const INSPECT_FULL: MetaCmd = MetaCmd { name: "inspect-full", summary: "Print a proof claim", format: "!(inspect-full )", @@ -623,7 +625,7 @@ where } }; - const DUMP_DATA: MetaCmd = MetaCmd { + const DUMP_DATA: MetaCmd = MetaCmd { name: "dump-data", summary: "Write Lurk data to the file system", format: "!(dump-data )", @@ -641,7 +643,7 @@ where }, }; - const DEF_LOAD_DATA: MetaCmd = MetaCmd { + const DEF_LOAD_DATA: MetaCmd = MetaCmd { name: "def-load-data", summary: "Read Lurk data from the file system and bind it to a symbol", format: "!(def-load-data )", @@ -664,7 +666,7 @@ where }, }; - const DEFPROTOCOL: MetaCmd = MetaCmd { + const DEFPROTOCOL: MetaCmd = MetaCmd { name: "defprotocol", summary: "Defines a protocol", format: "!(defprotocol options...)", @@ -725,7 +727,7 @@ where let prop_map = repl.get_properties(&props, &["rc", "lang", "description"])?; - let get_prop = |key, accepts: fn(&Ptr) -> bool, def: fn(&Repl) -> Ptr| -> Result { + let get_prop = |key, accepts: fn(&Ptr) -> bool, def: fn(&Repl) -> Ptr| -> Result { match prop_map.get(key) { Some(val) => { if accepts(val) { @@ -770,7 +772,7 @@ where /// # Errors /// * If the protocol evaluation fails /// * If the reduction count is not a number or can't be converted to `u64` - fn get_fun_and_rc(repl: &Repl, ptcl: Ptr) -> Result<(Ptr, usize)> { + fn get_fun_and_rc(repl: &Repl, ptcl: Ptr) -> Result<(Ptr, usize)> { let (io, ..) = repl .eval_expr(ptcl) .with_context(|| "evaluating protocol")?; @@ -791,7 +793,7 @@ where /// /// # Errors /// Errors if the the list of arguments is not proper - fn get_args_vec(repl: &Repl, args: &Ptr) -> Result> { + fn get_args_vec(repl: &Repl, args: &Ptr) -> Result> { let Some((args_vec, None)) = repl.store.fetch_list(args) else { bail!("Protocol arguments must be a list") }; @@ -809,7 +811,7 @@ where /// * If the proof input can't be built (first component of the pair is nil) /// * If the proof input is not a list with length 6 fn get_cek_io_and_post_verify_fn( - repl: &Repl, + repl: &Repl, fun: Ptr, args: Ptr, ) -> Result<(Vec, Ptr)> { @@ -851,7 +853,7 @@ where /// * If the predicate is not a function /// * If the predicate evaluation fails /// * If the predicate rejects the proof (evaluation returns nil) - fn post_verify_check(repl: &Repl, post_verify: Ptr) -> Result<()> { + fn post_verify_check(repl: &Repl, post_verify: Ptr) -> Result<()> { if !post_verify.is_nil() { let call = repl.store.list(vec![post_verify]); let (io, ..) = repl @@ -869,7 +871,7 @@ where /// /// # Errors /// Errors if the continuation specifier does not represent a valid continuation - fn get_cont_ptr(repl: &Repl, cont_key: &Ptr) -> Result { + fn get_cont_ptr(repl: &Repl, cont_key: &Ptr) -> Result { let store = &repl.store; if cont_key == &store.key("outermost") { Ok(store.cont_outermost()) @@ -885,7 +887,7 @@ where } } - const PROVE_PROTOCOL: MetaCmd = MetaCmd { + const PROVE_PROTOCOL: MetaCmd = MetaCmd { name: "prove-protocol", summary: "Creates a proof for a protocol", format: "!(prove-protocol args...)", @@ -932,8 +934,8 @@ where Self::post_verify_check(repl, post_verify)?; - let frames = evaluate_with_env_and_cont::>( - None, + let frames = evaluate_with_env_and_cont::( + Some(repl.lang_setup()), cek_io[0], cek_io[1], Self::get_cont_ptr(repl, &cek_io[2])?, @@ -958,9 +960,7 @@ where let mut z_dag = ZDag::default(); let z_ptr = z_dag.populate_with(&args, &repl.store, &mut Default::default()); let args = LurkData { z_ptr, z_dag }; - match load::>>>(&proof_path( - &proof_key, - ))? { + match load::>>(&proof_path(&proof_key))? { LurkProof::Nova { proof, .. } => { dump(ProtocolProof::Nova { args, proof }, &path)?; println!("Protocol proof saved at {path}"); @@ -970,7 +970,7 @@ where }, }; - const VERIFY_PROTOCOL: MetaCmd = MetaCmd { + const VERIFY_PROTOCOL: MetaCmd = MetaCmd { name: "verify-protocol", summary: "Verifies a proof for a protocol", format: "!(verify-protocol )", @@ -990,7 +990,7 @@ where let (fun, proto_rc) = Self::get_fun_and_rc(repl, ptcl)?; - match load::>>>(&path)? { + match load::>>(&path)? { ProtocolProof::Nova { args: LurkData { z_ptr, z_dag }, proof, @@ -1024,7 +1024,7 @@ where }, }; - const CMDS: [MetaCmd; 28] = [ + const CMDS: [MetaCmd; 28] = [ MetaCmd::LOAD, MetaCmd::DEF, MetaCmd::DEFREC, @@ -1055,7 +1055,7 @@ where MetaCmd::VERIFY_PROTOCOL, ]; - pub(super) fn cmds() -> std::collections::HashMap<&'static str, MetaCmd> { + pub(super) fn cmds() -> std::collections::HashMap<&'static str, MetaCmd> { HashMap::from(Self::CMDS.map(|x| (x.name, x))) } } @@ -1076,7 +1076,10 @@ impl HasFieldModulus for LurkData { /// /// # Errors /// Errors if a string can't be fetched with the pointer -fn get_path(repl: &Repl, path: &Ptr) -> Result { +fn get_path + Serialize + DeserializeOwned>( + repl: &Repl, + path: &Ptr, +) -> Result { let Some(path) = repl.store.fetch_string(path) else { bail!( "Path must be a string. Got {}", diff --git a/src/cli/repl/mod.rs b/src/cli/repl/mod.rs index 34840012bd..381cb8ecc5 100644 --- a/src/cli/repl/mod.rs +++ b/src/cli/repl/mod.rs @@ -24,15 +24,19 @@ use std::{ use tracing::info; use crate::{ - eval::lang::{Coproc, Lang}, + coprocessor::Coprocessor, + eval::lang::Lang, field::LurkField, lem::{ - eval::{evaluate_simple_with_env, evaluate_with_env}, + eval::{ + evaluate_simple_with_env, evaluate_with_env, make_cprocs_funcs_from_lang, + make_eval_step_from_config, EvalConfig, + }, interpreter::Frame, multiframe::MultiFrame, pointers::Ptr, store::Store, - Tag, + Func, Tag, }, parser, proof::{ @@ -84,17 +88,19 @@ impl Evaluation { } #[allow(dead_code)] -pub(crate) struct Repl { +pub(crate) struct Repl + Serialize + DeserializeOwned> { store: Store, state: Rc>, + lang: Arc>, + lurk_step: Func, + cprocs: Vec, env: Ptr, - lang: Arc>>, rc: usize, limit: usize, backend: Backend, evaluation: Option, pwd_path: Utf8PathBuf, - meta: HashMap<&'static str, MetaCmd>, + meta: HashMap<&'static str, MetaCmd>, apply_fn: OnceCell, } @@ -113,7 +119,7 @@ fn pad(a: usize, m: usize) -> usize { (a + m - 1) / m * m } -impl Repl { +impl + Serialize + DeserializeOwned> Repl { fn get_evaluation(&self) -> &Option { &self.evaluation } @@ -156,12 +162,21 @@ impl Repl { } } -impl Repl +impl< + F: CurveCycleEquipped + Serialize + DeserializeOwned, + C: Coprocessor + Serialize + DeserializeOwned + 'static, + > Repl where ::Repr: Abomonation, <<::E2 as Engine>::Scalar as PrimeField>::Repr: Abomonation, { - pub(crate) fn new(store: Store, rc: usize, limit: usize, backend: Backend) -> Repl { + pub(crate) fn new( + store: Store, + lang: Lang, + rc: usize, + limit: usize, + backend: Backend, + ) -> Repl { let limit = pad(limit, rc); info!( "Launching REPL with backend {backend}, field {}, rc {rc} and limit {limit}", @@ -171,11 +186,15 @@ where let pwd_path = Utf8PathBuf::from_path_buf(current_dir).expect("path contains invalid Unicode"); let env = store.intern_nil(); + let lurk_step = make_eval_step_from_config(&EvalConfig::new_ivc(&lang)); + let cprocs = make_cprocs_funcs_from_lang(&lang); Repl { store, state: State::init_lurk_state().rccell(), + lang: Arc::new(lang), + lurk_step, + cprocs, env, - lang: Arc::new(Lang::new()), rc, limit, backend, @@ -186,6 +205,10 @@ where } } + fn lang_setup(&self) -> (&Func, &[Func], &Lang) { + (&self.lurk_step, &self.cprocs, &self.lang) + } + fn get_apply_fn(&self) -> &Ptr { self.apply_fn.get_or_init(|| { let ptr = self @@ -307,7 +330,7 @@ where z_dag, }; - if LurkProof::<_, _, MultiFrame<'_, _, Coproc>>::is_cached(&proof_key) { + if LurkProof::<_, _, MultiFrame<'_, _, C>>::is_cached(&proof_key) { info!("Proof already cached"); } else { info!("Proof not cached. Loading public parameters"); @@ -315,10 +338,8 @@ where Instance::new(self.rc, self.lang.clone(), true, Kind::NovaPublicParams); let pp = public_params(&instance)?; - let prover = NovaProver::<_, _, MultiFrame<'_, F, Coproc>>::new( - self.rc, - self.lang.clone(), - ); + let prover = + NovaProver::<_, _, MultiFrame<'_, F, C>>::new(self.rc, self.lang.clone()); info!("Proving"); let (proof, public_inputs, public_outputs, num_steps) = @@ -396,8 +417,13 @@ where } fn eval_expr_with_env(&self, expr: Ptr, env: Ptr) -> Result<(Vec, usize, Vec)> { - let (ptrs, iterations, emitted) = - evaluate_simple_with_env::>(None, expr, env, &self.store, self.limit)?; + let (ptrs, iterations, emitted) = evaluate_simple_with_env::( + Some(self.lang_setup()), + expr, + env, + &self.store, + self.limit, + )?; match ptrs[2].tag() { Tag::Cont(ContTag::Terminal) => Ok((ptrs, iterations, emitted)), t => { @@ -420,8 +446,8 @@ where &mut self, expr_ptr: Ptr, ) -> Result<(Vec, usize, Vec)> { - let (ptrs, iterations, emitted) = evaluate_simple_with_env::>( - None, + let (ptrs, iterations, emitted) = evaluate_simple_with_env::( + Some(self.lang_setup()), expr_ptr, self.env, &self.store, @@ -438,8 +464,13 @@ where } fn eval_expr_and_memoize(&mut self, expr_ptr: Ptr) -> Result<(Vec, usize)> { - let frames = - evaluate_with_env::>(None, expr_ptr, self.env, &self.store, self.limit)?; + let frames = evaluate_with_env::( + Some(self.lang_setup()), + expr_ptr, + self.env, + &self.store, + self.limit, + )?; let iterations = frames.len(); let output = frames .last() diff --git a/src/lem/eval.rs b/src/lem/eval.rs index ce64d6cd89..93607b0cad 100644 --- a/src/lem/eval.rs +++ b/src/lem/eval.rs @@ -58,7 +58,7 @@ fn get_pc>( fn compute_frame>( lurk_step: &Func, - cprocs_run: &[Func], + cprocs: &[Func], input: &[Ptr], store: &Store, lang: &Lang, @@ -68,9 +68,7 @@ fn compute_frame>( let func = if pc == 0 { lurk_step } else { - cprocs_run - .get(pc - 1) - .expect("Program counter outside range") + cprocs.get(pc - 1).expect("Program counter outside range") }; assert_eq!(func.input_params.len(), input.len()); let preimages = Hints::new_from_func(func); @@ -86,7 +84,7 @@ fn build_frames< LogFmt: Fn(usize, &[Ptr], &[Ptr], &Store) -> String, >( lurk_step: &Func, - cprocs_run: &[Func], + cprocs: &[Func], mut input: Vec, store: &Store, limit: usize, @@ -100,7 +98,7 @@ fn build_frames< for _ in 0..limit { let mut emitted = vec![]; let (frame, must_break) = - compute_frame(lurk_step, cprocs_run, &input, store, lang, &mut emitted, pc)?; + compute_frame(lurk_step, cprocs, &input, store, lang, &mut emitted, pc)?; iterations += 1; input = frame.output.clone(); @@ -119,7 +117,7 @@ fn build_frames< /// Faster version of `build_frames` that doesn't accumulate frames fn traverse_frames>( lurk_step: &Func, - cprocs_run: &[Func], + cprocs: &[Func], mut input: Vec, store: &Store, limit: usize, @@ -130,7 +128,7 @@ fn traverse_frames>( let mut emitted = vec![]; for _ in 0..limit { let (frame, must_break) = - compute_frame(lurk_step, cprocs_run, &input, store, lang, &mut emitted, pc)?; + compute_frame(lurk_step, cprocs, &input, store, lang, &mut emitted, pc)?; iterations += 1; input = frame.output.clone(); @@ -144,7 +142,7 @@ fn traverse_frames>( } pub fn evaluate_with_env_and_cont>( - func_lang: Option<(&Func, &Lang)>, + lang_setup: Option<(&Func, &[Func], &Lang)>, expr: Ptr, env: Ptr, cont: Ptr, @@ -167,38 +165,37 @@ pub fn evaluate_with_env_and_cont>( let input = vec![expr, env, cont]; - match func_lang { + match lang_setup { None => { let lang: Lang = Lang::new(); build_frames(eval_step(), &[], input, store, limit, &lang, log_fmt) } - Some((func, lang)) => { - let funcs = make_cprocs_funcs_from_lang(lang); - build_frames(func, &funcs, input, store, limit, lang, log_fmt) + Some((lurk_step, cprocs, lang)) => { + build_frames(lurk_step, cprocs, input, store, limit, lang, log_fmt) } } } #[inline] pub fn evaluate_with_env>( - func_lang: Option<(&Func, &Lang)>, + lang_setup: Option<(&Func, &[Func], &Lang)>, expr: Ptr, env: Ptr, store: &Store, limit: usize, ) -> Result> { - evaluate_with_env_and_cont(func_lang, expr, env, store.cont_outermost(), store, limit) + evaluate_with_env_and_cont(lang_setup, expr, env, store.cont_outermost(), store, limit) } #[inline] pub fn evaluate>( - func_lang: Option<(&Func, &Lang)>, + lang_setup: Option<(&Func, &[Func], &Lang)>, expr: Ptr, store: &Store, limit: usize, ) -> Result> { evaluate_with_env_and_cont( - func_lang, + lang_setup, expr, store.intern_nil(), store.cont_outermost(), @@ -208,33 +205,32 @@ pub fn evaluate>( } pub fn evaluate_simple_with_env>( - func_lang: Option<(&Func, &Lang)>, + lang_setup: Option<(&Func, &[Func], &Lang)>, expr: Ptr, env: Ptr, store: &Store, limit: usize, ) -> Result<(Vec, usize, Vec)> { let input = vec![expr, env, store.cont_outermost()]; - match func_lang { + match lang_setup { None => { let lang: Lang = Lang::new(); traverse_frames(eval_step(), &[], input, store, limit, &lang) } - Some((func, lang)) => { - let funcs = make_cprocs_funcs_from_lang(lang); - traverse_frames(func, &funcs, input, store, limit, lang) + Some((lurk_step, cprocs, lang)) => { + traverse_frames(lurk_step, cprocs, input, store, limit, lang) } } } #[inline] pub fn evaluate_simple>( - func_lang: Option<(&Func, &Lang)>, + lang_setup: Option<(&Func, &[Func], &Lang)>, expr: Ptr, store: &Store, limit: usize, ) -> Result<(Vec, usize, Vec)> { - evaluate_simple_with_env(func_lang, expr, store.intern_nil(), store, limit) + evaluate_simple_with_env(lang_setup, expr, store.intern_nil(), store, limit) } pub struct EvalConfig<'a, F: LurkField, C: Coprocessor> { @@ -456,7 +452,7 @@ fn run_cproc(cproc_sym: Symbol, arity: usize) -> Func { /// coprocessor in the `Lang` will have its own specialized `Func` pub fn make_cprocs_funcs_from_lang>( lang: &Lang, -) -> std::sync::Arc<[Func]> { +) -> Vec { lang.coprocessors() .iter() .map(|(name, c)| run_cproc(name.clone(), c.arity())) diff --git a/src/lem/multiframe.rs b/src/lem/multiframe.rs index f8c4e2640c..17dfb9b265 100644 --- a/src/lem/multiframe.rs +++ b/src/lem/multiframe.rs @@ -500,7 +500,7 @@ impl<'a, F: LurkField, C: Coprocessor + 'a> MultiFrameTrait<'a, F, C> for Mul ), FoldingConfig::NIVC(lang, rc) => ( Arc::new(make_eval_step_from_config(&EvalConfig::new_nivc(lang))), - Some(make_cprocs_funcs_from_lang(lang)), + Some(make_cprocs_funcs_from_lang(lang).into()), *rc, ), }; @@ -572,7 +572,7 @@ impl<'a, F: LurkField, C: Coprocessor + 'a> MultiFrameTrait<'a, F, C> for Mul } FoldingConfig::NIVC(lang, _) => { let lurk_step = Arc::new(make_eval_step_from_config(&EvalConfig::new_nivc(lang))); - let cprocs = make_cprocs_funcs_from_lang(lang); + let cprocs: Arc<[Func]> = make_cprocs_funcs_from_lang(lang).into(); let mut chunk_start_idx = 0; while chunk_start_idx < frames.len() { let first_frame = &frames[chunk_start_idx]; @@ -669,8 +669,17 @@ impl<'a, F: LurkField, C: Coprocessor + 'a> MultiFrameTrait<'a, F, C> for Mul ) -> Result, ProofError> { let cont = store.cont_outermost(); let lurk_step = make_eval_step_from_config(ec); - evaluate_with_env_and_cont(Some((&lurk_step, ec.lang())), expr, env, cont, store, limit) - .map_err(|e| ProofError::Reduction(ReductionError::Misc(e.to_string()))) + let lang = ec.lang(); + let cprocs = make_cprocs_funcs_from_lang(lang); + evaluate_with_env_and_cont( + Some((&lurk_step, &cprocs, lang)), + expr, + env, + cont, + store, + limit, + ) + .map_err(|e| ProofError::Reduction(ReductionError::Misc(e.to_string()))) } fn significant_frame_count(frames: &[Self::EvalFrame]) -> usize { diff --git a/src/lem/tests/eval_tests.rs b/src/lem/tests/eval_tests.rs index 83e752eb6f..311f614891 100644 --- a/src/lem/tests/eval_tests.rs +++ b/src/lem/tests/eval_tests.rs @@ -6,7 +6,9 @@ use crate::{ coprocessor::Coprocessor, eval::lang::{Coproc, Lang}, lem::{ - eval::{evaluate_simple, make_eval_step_from_config, EvalConfig}, + eval::{ + evaluate_simple, make_cprocs_funcs_from_lang, make_eval_step_from_config, EvalConfig, + }, pointers::Ptr, store::Store, Tag, @@ -114,7 +116,8 @@ fn do_test>( evaluate_simple::(None, *expr, s, limit).unwrap() } else { let func = make_eval_step_from_config(&EvalConfig::new_ivc(lang)); - evaluate_simple(Some((&func, lang)), *expr, s, limit).unwrap() + let cprocs = make_cprocs_funcs_from_lang(lang); + evaluate_simple(Some((&func, &cprocs, lang)), *expr, s, limit).unwrap() }; let new_expr = output[0]; let new_env = output[1]; diff --git a/src/lem/tests/nivc_steps.rs b/src/lem/tests/nivc_steps.rs index 64b3e11ba4..ced53bf819 100644 --- a/src/lem/tests/nivc_steps.rs +++ b/src/lem/tests/nivc_steps.rs @@ -31,7 +31,7 @@ fn test_nivc_steps() { // 9^2 + 8 = 89 let expr = store.read_with_default_state("(cproc-dumb 9 8)").unwrap(); - let frames = evaluate(Some((&lurk_step, &lang)), expr, &store, 10).unwrap(); + let frames = evaluate(Some((&lurk_step, &cprocs, &lang)), expr, &store, 10).unwrap(); // Iteration 1: evaluate first argument // Iteration 2: evaluate second argument