diff --git a/src/cli/backend.rs b/src/cli/backend.rs index 5090f633e0..6fb916834b 100644 --- a/src/cli/backend.rs +++ b/src/cli/backend.rs @@ -20,9 +20,11 @@ impl std::fmt::Display for Backend { impl Backend { fn compatible_fields(&self) -> Vec { - use LanguageField::{Pallas, Vesta}; + // TODO: does this compatibility check still make sense now that we have + // CurveCycleEquiped? + use LanguageField::{Grumpkin, Pallas, Vesta, BN256}; match self { - Self::Nova => vec![Pallas, Vesta], + Self::Nova => vec![Pallas, Vesta, BN256, Grumpkin], } } diff --git a/src/cli/mod.rs b/src/cli/mod.rs index bec951a1dc..8d124fb386 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -11,6 +11,7 @@ mod zstore; use anyhow::{bail, Context, Result}; use camino::Utf8PathBuf; use clap::{Args, Parser, Subcommand}; +use halo2curves::bn256; use pasta_curves::pallas; use std::{ @@ -354,9 +355,9 @@ impl ReplCli { backend.validate_field(field)?; match field { LanguageField::Pallas => repl!(rc, limit, pallas::Scalar, backend.clone()), - LanguageField::Vesta => todo!(), - LanguageField::BN256 => todo!(), - LanguageField::Grumpkin => todo!(), + LanguageField::Vesta => unimplemented!("Vesta field is not CurveCycleEquipped"), + LanguageField::BN256 => repl!(rc, limit, bn256::Fr, backend.clone()), + LanguageField::Grumpkin => unimplemented!("Grumpkin field is not CurveCycleEquipped"), } } } @@ -408,9 +409,9 @@ impl LoadCli { backend.validate_field(field)?; match field { LanguageField::Pallas => load!(rc, limit, pallas::Scalar, backend.clone()), - LanguageField::Vesta => todo!(), - LanguageField::BN256 => todo!(), - LanguageField::Grumpkin => todo!(), + LanguageField::Vesta => unimplemented!("Vesta field is not CurveCycleEquipped"), + LanguageField::BN256 => load!(rc, limit, bn256::Fr, backend.clone()), + LanguageField::Grumpkin => unimplemented!("Grumpkin field is not CurveCycleEquipped"), } } } diff --git a/src/cli/repl/meta_cmd.rs b/src/cli/repl/meta_cmd.rs index 3125c367b0..e38fa3b2d0 100644 --- a/src/cli/repl/meta_cmd.rs +++ b/src/cli/repl/meta_cmd.rs @@ -2,6 +2,7 @@ use ::nova::traits::Engine; use abomonation::Abomonation; use anyhow::{anyhow, bail, Context, Result}; use camino::Utf8PathBuf; +use ff::PrimeField; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use std::{collections::HashMap, process}; @@ -44,9 +45,11 @@ pub(super) struct MetaCmd { pub(super) run: fn(repl: &mut Repl, args: &Ptr) -> Result<()>, } -type F = pasta_curves::pallas::Scalar; // TODO: generalize this - -impl MetaCmd { +impl MetaCmd +where + ::Repr: Abomonation, + <<::E2 as Engine>::Scalar as PrimeField>::Repr: Abomonation, +{ const LOAD: MetaCmd = MetaCmd { name: "load", summary: "Load lurk expressions from a file.", @@ -62,9 +65,7 @@ impl MetaCmd { } }, }; -} -impl MetaCmd { const DEF: MetaCmd = MetaCmd { name: "def", summary: "Extends env with a non-recursive binding.", @@ -89,9 +90,7 @@ impl MetaCmd { Ok(()) }, }; -} -impl MetaCmd { const DEFREC: MetaCmd = MetaCmd { name: "defrec", summary: "Extends the env with a recursive binding.", @@ -119,9 +118,7 @@ impl MetaCmd { Ok(()) }, }; -} -impl MetaCmd { const ASSERT: MetaCmd = MetaCmd { name: "assert", summary: "Assert that an expression evaluates to true.", @@ -141,9 +138,7 @@ impl MetaCmd { Ok(()) }, }; -} -impl MetaCmd { const ASSERT_EQ: MetaCmd = MetaCmd { name: "assert-eq", summary: "Assert that two expressions evaluate to the same value.", @@ -172,9 +167,7 @@ impl MetaCmd { Ok(()) }, }; -} -impl MetaCmd { const ASSERT_EMITTED: MetaCmd = MetaCmd { name: "assert-emitted", @@ -211,9 +204,7 @@ impl MetaCmd { Ok(()) }, }; -} -impl MetaCmd { const ASSERT_ERROR: MetaCmd = MetaCmd { name: "assert-error", summary: "Assert that a evaluation of fails.", @@ -233,9 +224,7 @@ impl MetaCmd { Ok(()) }, }; -} -impl MetaCmd { const COMMIT: MetaCmd = MetaCmd { name: "commit", @@ -254,9 +243,7 @@ impl MetaCmd { repl.hide(F::NON_HIDING_COMMITMENT_SECRET, first_io[0]) } }; -} -impl MetaCmd { const HIDE: MetaCmd = MetaCmd { name: "hide", summary: "Return and persist the commitment of using secret .", @@ -286,9 +273,7 @@ impl MetaCmd { Ok(()) }, }; -} -impl MetaCmd { const FETCH: MetaCmd = MetaCmd { name: "fetch", summary: "Add data from a commitment to the repl store.", @@ -303,9 +288,7 @@ impl MetaCmd { repl.fetch(&hash, false) }, }; -} -impl MetaCmd { const OPEN: MetaCmd = MetaCmd { name: "open", summary: "Open a commitment.", @@ -320,9 +303,7 @@ impl MetaCmd { repl.fetch(&hash, true) }, }; -} -impl MetaCmd { const CLEAR: MetaCmd = MetaCmd { name: "clear", summary: "Reset the current environment to be empty.", @@ -334,9 +315,7 @@ impl MetaCmd { Ok(()) }, }; -} -impl MetaCmd { const SET_ENV: MetaCmd = MetaCmd { name: "set-env", summary: "Set the env to the result of evaluating the first argument.", @@ -350,9 +329,7 @@ impl MetaCmd { Ok(()) }, }; -} -impl MetaCmd { const PROVE: MetaCmd = MetaCmd { name: "prove", @@ -376,13 +353,7 @@ impl MetaCmd { Ok(()) } }; -} -impl MetaCmd -where - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, -{ const VERIFY: MetaCmd = MetaCmd { name: "verify", summary: "Verify a proof", @@ -401,9 +372,7 @@ where ) } }; -} -impl MetaCmd { const DEFPACKAGE: MetaCmd = MetaCmd { name: "defpackage", summary: "Add a package to the state.", @@ -424,9 +393,7 @@ impl MetaCmd { Ok(()) }, }; -} -impl MetaCmd { const IMPORT: MetaCmd = MetaCmd { name: "import", summary: "Import a single or several packages.", @@ -457,9 +424,7 @@ impl MetaCmd { Ok(()) }, }; -} -impl MetaCmd { const IN_PACKAGE: MetaCmd = MetaCmd { name: "in-package", summary: "set the current package.", @@ -493,9 +458,7 @@ impl MetaCmd { } }, }; -} -impl MetaCmd { const HELP: MetaCmd = MetaCmd { name: "help", summary: "Print help message.", @@ -520,7 +483,7 @@ impl MetaCmd { 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); } } @@ -531,7 +494,7 @@ impl MetaCmd { }; 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() { @@ -548,9 +511,7 @@ impl MetaCmd { None => println!("unknown command {}", cmd), } } -} -impl MetaCmd { fn call(repl: &mut Repl, args: &Ptr) -> Result<()> { let (hash_ptr, args) = repl.store.car_cdr(args)?; let hash_expr = match hash_ptr.tag() { @@ -584,9 +545,7 @@ impl MetaCmd { ], run: Self::call, }; -} -impl MetaCmd { const CHAIN: MetaCmd = MetaCmd { name: "chain", summary: "Chain a functional commitment by applying the provided arguments to it", @@ -625,9 +584,7 @@ impl MetaCmd { repl.hide(*secret, *fun) }, }; -} -impl MetaCmd { fn inspect(repl: &mut Repl, args: &Ptr, full: bool) -> Result<()> { let first = repl.peek1(args)?; let proof_id = repl.get_string(&first)?; @@ -651,9 +608,7 @@ impl MetaCmd { Self::inspect(repl, args, false) } }; -} -impl MetaCmd { const INSPECT_FULL: MetaCmd = MetaCmd { name: "inspect-full", summary: "Print a proof claim", @@ -667,35 +622,7 @@ impl MetaCmd { Self::inspect(repl, args, true) } }; -} - -#[derive(Serialize, Deserialize)] -struct LurkData { - z_ptr: ZPtr, - z_dag: ZDag, -} - -impl HasFieldModulus for LurkData { - fn field_modulus() -> String { - F::MODULUS.to_string() - } -} - -/// Returns a `Utf8PathBuf` from a pointer -/// -/// # Errors -/// Errors if a string can't be fetched with the pointer -fn get_path(repl: &Repl, path: &Ptr) -> Result { - let Some(path) = repl.store.fetch_string(path) else { - bail!( - "Path must be a string. Got {}", - path.fmt_to_string(&repl.store, &repl.state.borrow()) - ) - }; - Ok(Utf8PathBuf::from(path)) -} -impl MetaCmd { const DUMP_DATA: MetaCmd = MetaCmd { name: "dump-data", summary: "Write Lurk data to the file system", @@ -713,9 +640,7 @@ impl MetaCmd { dump(LurkData { z_ptr, z_dag }, &path) }, }; -} -impl 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", @@ -738,9 +663,7 @@ impl MetaCmd { Ok(()) }, }; -} -impl MetaCmd { const DEFPROTOCOL: MetaCmd = MetaCmd { name: "defprotocol", summary: "Defines a protocol", @@ -841,44 +764,7 @@ impl MetaCmd { Ok(()) }, }; -} -/// Contains the data needed for proof validation (according to some protocol) -/// and verification -#[non_exhaustive] -#[derive(Serialize, Deserialize)] -#[serde(bound(serialize = "F: Serialize", deserialize = "F: DeserializeOwned"))] -enum ProtocolProof< - 'a, - F: CurveCycleEquipped, - C: Coprocessor + Serialize + DeserializeOwned, - M: MultiFrameTrait<'a, F, C>, -> where - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, -{ - Nova { - args: LurkData, - proof: nova::Proof<'a, F, C, M>, - }, -} - -impl< - 'a, - F: CurveCycleEquipped, - C: Coprocessor + 'a + Serialize + DeserializeOwned, - M: MultiFrameTrait<'a, F, C>, - > HasFieldModulus for ProtocolProof<'a, F, C, M> -where - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, -{ - fn field_modulus() -> String { - F::MODULUS.to_owned() - } -} - -impl MetaCmd { /// Returns the protocol function and reduction count /// /// # Errors @@ -1083,9 +969,7 @@ impl MetaCmd { } }, }; -} -impl MetaCmd { const VERIFY_PROTOCOL: MetaCmd = MetaCmd { name: "verify-protocol", summary: "Verifies a proof for a protocol", @@ -1139,9 +1023,7 @@ impl MetaCmd { } }, }; -} -impl MetaCmd { const CMDS: [MetaCmd; 28] = [ MetaCmd::LOAD, MetaCmd::DEF, @@ -1177,3 +1059,64 @@ impl MetaCmd { HashMap::from(Self::CMDS.map(|x| (x.name, x))) } } + +#[derive(Serialize, Deserialize)] +struct LurkData { + z_ptr: ZPtr, + z_dag: ZDag, +} + +impl HasFieldModulus for LurkData { + fn field_modulus() -> String { + F::MODULUS.to_string() + } +} + +/// Returns a `Utf8PathBuf` from a pointer +/// +/// # Errors +/// Errors if a string can't be fetched with the pointer +fn get_path(repl: &Repl, path: &Ptr) -> Result { + let Some(path) = repl.store.fetch_string(path) else { + bail!( + "Path must be a string. Got {}", + path.fmt_to_string(&repl.store, &repl.state.borrow()) + ) + }; + Ok(Utf8PathBuf::from(path)) +} + +/// Contains the data needed for proof validation (according to some protocol) +/// and verification +#[non_exhaustive] +#[derive(Serialize, Deserialize)] +#[serde(bound(serialize = "F: Serialize", deserialize = "F: DeserializeOwned"))] +enum ProtocolProof< + 'a, + F: CurveCycleEquipped, + C: Coprocessor + Serialize + DeserializeOwned, + M: MultiFrameTrait<'a, F, C>, +> where + < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, + < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, +{ + Nova { + args: LurkData, + proof: nova::Proof<'a, F, C, M>, + }, +} + +impl< + 'a, + F: CurveCycleEquipped, + C: Coprocessor + 'a + Serialize + DeserializeOwned, + M: MultiFrameTrait<'a, F, C>, + > HasFieldModulus for ProtocolProof<'a, F, C, M> +where + < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, + < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, +{ + fn field_modulus() -> String { + F::MODULUS.to_owned() + } +} diff --git a/src/cli/repl/mod.rs b/src/cli/repl/mod.rs index 8facbf69a0..34840012bd 100644 --- a/src/cli/repl/mod.rs +++ b/src/cli/repl/mod.rs @@ -1,7 +1,10 @@ mod meta_cmd; +use abomonation::Abomonation; use anyhow::{anyhow, bail, Context, Result}; use camino::{Utf8Path, Utf8PathBuf}; +use ff::PrimeField; +use nova::traits::Engine; use rustyline::{ error::ReadlineError, history::DefaultHistory, @@ -9,6 +12,7 @@ use rustyline::{ Config, Editor, }; use rustyline_derive::{Completer, Helper, Highlighter, Hinter}; +use serde::{de::DeserializeOwned, Serialize}; use std::{ cell::{OnceCell, RefCell}, collections::HashMap, @@ -31,7 +35,10 @@ use crate::{ Tag, }, parser, - proof::{nova::NovaProver, Prover, RecursiveSNARKTrait}, + proof::{ + nova::{CurveCycleEquipped, NovaProver}, + Prover, RecursiveSNARKTrait, + }, public_parameters::{ instance::{Instance, Kind}, public_params, @@ -149,9 +156,11 @@ impl Repl { } } -type F = pasta_curves::pallas::Scalar; // TODO: generalize this - -impl Repl { +impl 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 { let limit = pad(limit, rc); info!(