diff --git a/Cargo.toml b/Cargo.toml index d3ff3076..dfdff654 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,6 @@ members = [ "tools/tui", "config", "config/serde_wrapper", - "prover", "network", "network/rpc/common", "network/rpc/server", @@ -21,7 +20,6 @@ members = [ default-members = [ "vm", "tools", - "prover", "network", "nova", "spartan", diff --git a/api/Cargo.toml b/api/Cargo.toml index 051a2e1f..b87c8cf7 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -10,6 +10,38 @@ keywords = { workspace = true } categories = { workspace = true } [dependencies] -nexus-config = { path = "../config" } +anyhow = "1.0" + +zstd = { version = "0.12", default-features = false } + +nexus-config = { path = "../config", features = ["clap_derive"] } nexus-vm = { path = "../vm" } -nexus-prover = { path = "../prover" } +nexus-jolt = { path = "../jolt", optional = true } +spartan = { path = "../spartan", package = "ark-spartan", optional = true } +nexus-nova = { path = "../nova", optional = true } + +tracing = "0.1" + +ark-ff.workspace = true +ark-ec.workspace = true +ark-std.workspace = true +ark-crypto-primitives.workspace = true +ark-relations.workspace = true +ark-r1cs-std.workspace = true +ark-serialize.workspace = true + +ark-bn254.workspace = true +ark-grumpkin.workspace = true + +[features] +default = ["parallel", "prover_nova"] +parallel = [ + "ark-ff/parallel", + "ark-ec/parallel", + "ark-std/parallel", + "ark-crypto-primitives/parallel", + "ark-r1cs-std/parallel", + "nexus-nova/parallel", +] +prover_nova = ["dep:nexus-nova", "dep:spartan", "nexus-nova/spartan"] +prover_jolt = ["dep:nexus-jolt"] \ No newline at end of file diff --git a/api/examples/prover_run.rs b/api/examples/prover_run.rs index 898b7369..4ec36fac 100644 --- a/api/examples/prover_run.rs +++ b/api/examples/prover_run.rs @@ -1,11 +1,11 @@ // An example of loading and running the NVM. +use nexus_api::config::vm::NovaImpl; use nexus_api::{ config::vm::{ProverImpl, VmConfig}, nvm::{self, memory::MerkleTrie, NexusVM}, prover::{self}, }; -use nexus_config::vm::NovaImpl; use std::path::PathBuf; const CONFIG: VmConfig = VmConfig { @@ -21,7 +21,7 @@ fn main() { println!("Setting up public parameters..."); let public_params = - prover::setup::gen_vm_pp(CONFIG.k, &()).expect("error generating public parameters"); + prover::nova::pp::gen_vm_pp(CONFIG.k, &()).expect("error generating public parameters"); println!("Reading and translating vm..."); let mut vm: NexusVM = @@ -40,7 +40,8 @@ fn main() { println!("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); println!("Proving execution of length {}...", trace.blocks.len()); - let proof = prover::prove::prove_seq(&public_params, trace).expect("error proving execution"); + let proof = + nexus_api::prover::nova::prove_seq(&public_params, trace).expect("error proving execution"); print!("Verifying execution..."); proof diff --git a/api/src/lib.rs b/api/src/lib.rs index 6d139dd5..fbf6de8f 100644 --- a/api/src/lib.rs +++ b/api/src/lib.rs @@ -4,34 +4,24 @@ /// Configurations pub mod config { + pub use nexus_config::{Config, MiscConfig}; pub mod vm { pub use nexus_config::vm::*; } + pub mod network { + pub use nexus_config::network::*; + } } /// RISC-V processing pub mod nvm { pub mod interactive { - pub use nexus_vm::{eval, load_elf, parse_elf, trace::trace}; + pub use nexus_vm::{eval, load_elf, parse_elf, trace::trace, trace::Trace}; } pub use nexus_vm::{error::NexusVMError, eval::NexusVM, run_vm, trace_vm, VMOpts}; pub mod memory { - pub use nexus_vm::memory::{paged::Paged, trie::MerkleTrie}; + pub use nexus_vm::memory::{paged::Paged, path::Path, trie::MerkleTrie}; } } -/// Nova-based provers -pub mod prover { - pub use nexus_prover::error::ProofError; - pub mod setup { - pub use nexus_prover::pp::{gen_or_load, gen_pp, gen_to_file, gen_vm_pp, load_pp, save_pp}; - } - pub mod prove { - pub use nexus_prover::{ - compress, load_proof, prove_par, prove_par_com, prove_seq, run, save_proof, - }; - } - pub mod verify { - pub use nexus_prover::verify_compressed; - } -} +pub mod prover; diff --git a/api/src/prover/jolt/mod.rs b/api/src/prover/jolt/mod.rs new file mode 100644 index 00000000..c6cee71e --- /dev/null +++ b/api/src/prover/jolt/mod.rs @@ -0,0 +1,3 @@ +pub use nexus_jolt::{parse, preprocess, prove, trace, verify, VM}; + +pub mod types; diff --git a/api/src/prover/jolt/types.rs b/api/src/prover/jolt/types.rs new file mode 100644 index 00000000..a08e4937 --- /dev/null +++ b/api/src/prover/jolt/types.rs @@ -0,0 +1,3 @@ +//! Default types and traits for use by zkVM + Jolt pipeline + +pub use nexus_jolt::{JoltCommitments, JoltPreprocessing, JoltProof, F, PCS}; diff --git a/api/src/prover/mod.rs b/api/src/prover/mod.rs new file mode 100644 index 00000000..b2bd03c3 --- /dev/null +++ b/api/src/prover/mod.rs @@ -0,0 +1,4 @@ +#[cfg(feature = "prover_jolt")] +pub mod jolt; +#[cfg(feature = "prover_nova")] +pub mod nova; diff --git a/prover/src/circuit.rs b/api/src/prover/nova/circuit.rs similarity index 77% rename from prover/src/circuit.rs rename to api/src/prover/nova/circuit.rs index 849b3038..25c58e2a 100644 --- a/prover/src/circuit.rs +++ b/api/src/prover/nova/circuit.rs @@ -15,16 +15,16 @@ pub use ark_relations::{ use nexus_vm::{ circuit::{build_constraints, ARITY}, machines::nop_vm, - memory::{path::Path, trie::MerkleTrie}, + memory::Memory, trace::{trace, Trace}, }; -use crate::error::*; -use crate::types::*; +use super::error::*; +use super::types::*; -pub struct Tr(pub Trace); +pub struct Tr(pub Trace); -impl Tr { +impl Tr { pub fn steps(&self) -> usize { self.0.blocks.len() } @@ -38,13 +38,16 @@ impl Tr { } } -pub fn nop_circuit(k: usize) -> Result { - let mut vm = nop_vm::(1); +pub fn nop_circuit(k: usize) -> Result, ProofError> { + let mut vm = nop_vm::(1); let trace = trace(&mut vm, k, false)?; Ok(Tr(trace)) } -impl StepCircuit for Tr { +impl StepCircuit for Tr +where + M::Proof: Send + Sync, +{ const ARITY: usize = ARITY; fn generate_constraints( diff --git a/prover/src/error.rs b/api/src/prover/nova/error.rs similarity index 100% rename from prover/src/error.rs rename to api/src/prover/nova/error.rs diff --git a/api/src/prover/nova/key.rs b/api/src/prover/nova/key.rs new file mode 100644 index 00000000..b0aa8dec --- /dev/null +++ b/api/src/prover/nova/key.rs @@ -0,0 +1,52 @@ +use std::fs::File; +use zstd::stream::{Decoder, Encoder}; + +pub use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; +use nexus_nova::nova::pcd::compression::SNARK; + +use super::error::*; +use super::types::*; +use super::LOG_TARGET; + +pub fn gen_key(pp: &ComPP, srs: &SRS) -> Result { + tracing::info!( + target: LOG_TARGET, + "Generating Spartan key parameters", + ); + + let key = SNARK::setup(pp, srs)?; + Ok(key) +} + +pub fn save_key(key: SpartanKey, file: &str) -> Result<(), ProofError> { + tracing::info!( + target: LOG_TARGET, + pp_file =?file, + "Saving Spartan key parameters", + ); + + let f = File::create(file)?; + let mut enc = Encoder::new(&f, 0)?; + key.serialize_compressed(&mut enc)?; + enc.finish()?; + f.sync_all()?; + Ok(()) +} + +pub fn load_key(file: &str) -> Result { + tracing::info!( + target: LOG_TARGET, + pp_file =?file, + "Loading Spartan key parameters", + ); + + let f = File::open(file)?; + let mut dec = Decoder::new(&f)?; + let key = SpartanKey::deserialize_compressed_unchecked(&mut dec)?; + Ok(key) +} + +pub fn gen_key_to_file(pp: &ComPP, srs: &SRS, key_file: &str) -> Result<(), ProofError> { + let key: SpartanKey = gen_key(pp, srs)?; + save_key(key, key_file) +} diff --git a/api/src/prover/nova/mod.rs b/api/src/prover/nova/mod.rs new file mode 100644 index 00000000..68c8c55c --- /dev/null +++ b/api/src/prover/nova/mod.rs @@ -0,0 +1,208 @@ +pub mod circuit; +pub mod error; +pub mod key; +pub mod pp; +pub mod srs; + +pub mod types; + +use std::path::Path; + +use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; + +use nexus_vm::{ + memory::{trie::MerkleTrie, Memory}, + VMOpts, +}; + +use nexus_nova::nova::pcd::compression::SNARK; + +use crate::prover::nova::{ + circuit::Tr, + error::ProofError, + types::{ComPCDNode, ComPP, ComProof, IVCProof, PCDNode, ParPP, SeqPP, SpartanKey, SC}, +}; + +pub const LOG_TARGET: &str = "nexus-prover"; + +pub fn save_proof(proof: P, path: &Path) -> anyhow::Result<()> { + tracing::info!( + target: LOG_TARGET, + path = %path.display(), + "Saving the proof", + ); + + let mut buf = Vec::new(); + + proof.serialize_compressed(&mut buf)?; + std::fs::write(path, buf)?; + + Ok(()) +} + +pub fn load_proof(path: &Path) -> Result { + tracing::info!( + target: LOG_TARGET, + path = %path.display(), + "Loading the proof", + ); + + let file = std::fs::File::open(path)?; + let reader = std::io::BufReader::new(file); + + let proof: P = P::deserialize_compressed(reader)?; + + Ok(proof) +} + +type Trace = nexus_vm::trace::Trace<::Proof>; + +pub fn run(opts: &VMOpts, pow: bool) -> Result { + Ok(nexus_vm::trace_vm::(opts, pow, false)?) +} + +pub fn init_circuit_trace(trace: Trace) -> Result { + let tr = Tr::(trace); + Ok(tr) +} + +pub fn prove_seq(pp: &SeqPP, trace: Trace) -> Result { + let tr = init_circuit_trace(trace)?; + + let mut proof = prove_seq_step(None, pp, &tr)?; + for _ in 1..tr.steps() { + proof = prove_seq_step(Some(proof), pp, &tr)?; + } + + Ok(proof) +} + +pub fn prove_seq_step( + proof: Option, + pp: &SeqPP, + tr: &SC, +) -> Result { + let mut pr; + + if proof.is_none() { + let z_0 = tr.input(0)?; + pr = IVCProof::new(&z_0); + } else { + pr = proof.unwrap(); + } + + pr = IVCProof::prove_step(pr, pp, tr)?; + Ok(pr) +} + +macro_rules! prove_par_impl { + ( $pp_type:ty, $node_type:ty, $name:ident, $leaf_step_name:ident, $parent_step_name:ident) => { + pub fn $name(pp: &$pp_type, trace: Trace) -> Result<$node_type, ProofError> { + let tr = init_circuit_trace(trace)?; + let num_steps = tr.steps(); + + assert!((tr.steps() + 1).is_power_of_two()); + + let mut vs = (0..num_steps) + .step_by(2) + .map(|i| { + // todo: replace with concat_idents once stable + let v = $leaf_step_name(pp, &tr, i)?; + Ok(v) + }) + .collect::, ProofError>>()?; + + loop { + if vs.len() == 1 { + break; + } + + vs = vs + .chunks(2) + .map(|ab| { + // todo: replace with concat_idents once stable + let c = $parent_step_name(pp, &tr, &ab[0], &ab[1])?; + Ok(c) + }) + .collect::, ProofError>>()?; + } + + Ok(vs.into_iter().next().unwrap()) + } + }; +} + +macro_rules! prove_par_leaf_step_impl { + ( $pp_type:ty, $node_type:ty, $name:ident ) => { + pub fn $name(pp: &$pp_type, tr: &SC, i: usize) -> Result<$node_type, ProofError> { + assert!((tr.steps() + 1).is_power_of_two()); + + let v = <$node_type>::prove_leaf(pp, tr, i, &tr.input(i)?)?; + Ok(v) + } + }; +} + +macro_rules! prove_par_parent_step_impl { + ( $pp_type:ty, $node_type:ty, $name:ident ) => { + pub fn $name( + pp: &$pp_type, + tr: &SC, + ab0: &$node_type, + ab1: &$node_type, + ) -> Result<$node_type, ProofError> { + assert!((tr.steps() + 1).is_power_of_two()); + + let c = <$node_type>::prove_parent(pp, tr, ab0, ab1)?; + Ok(c) + } + }; +} + +prove_par_leaf_step_impl!(ParPP, PCDNode, prove_par_leaf_step); +prove_par_leaf_step_impl!(ComPP, ComPCDNode, prove_par_com_leaf_step); +prove_par_parent_step_impl!(ParPP, PCDNode, prove_par_parent_step); +prove_par_parent_step_impl!(ComPP, ComPCDNode, prove_par_com_parent_step); +prove_par_impl!( + ParPP, + PCDNode, + prove_par, + prove_par_leaf_step, + prove_par_parent_step +); +prove_par_impl!( + ComPP, + ComPCDNode, + prove_par_com, + prove_par_com_leaf_step, + prove_par_com_parent_step +); + +pub fn compress( + compression_pp: &ComPP, + key: &SpartanKey, + node: ComPCDNode, +) -> Result { + tracing::info!( + target: LOG_TARGET, + "Compressing the proof", + ); + + let compressed_pcd_proof = SNARK::compress(compression_pp, key, node)?; + + Ok(compressed_pcd_proof) +} + +pub fn verify_compressed( + key: &SpartanKey, + params: &ComPP, + proof: &ComProof, +) -> Result<(), ProofError> { + tracing::info!( + target: LOG_TARGET, + "Verifying the compressed proof", + ); + + SNARK::verify(key, params, proof)?; + Ok(()) +} diff --git a/api/src/prover/nova/pp.rs b/api/src/prover/nova/pp.rs new file mode 100644 index 00000000..be3137a1 --- /dev/null +++ b/api/src/prover/nova/pp.rs @@ -0,0 +1,86 @@ +use std::fs::File; +use zstd::stream::{Decoder, Encoder}; + +pub use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; + +use super::circuit::nop_circuit; +use super::error::*; +use super::types::*; +use super::LOG_TARGET; + +pub fn gen_pp(circuit: &SC, aux: &C::SetupAux) -> Result, ProofError> +where + C: CommitmentScheme, + SP: SetupParams, +{ + tracing::info!( + target: LOG_TARGET, + "Generating public parameters", + ); + + Ok(SP::setup(ro_config(), circuit, aux, &())?) +} + +pub fn save_pp(pp: &PP, file: &str) -> Result<(), ProofError> +where + C: CommitmentScheme, + SC: StepCircuit, + SP: SetupParams, +{ + tracing::info!( + target: LOG_TARGET, + path = ?file, + "Saving public parameters", + ); + + let f = File::create(file)?; + let mut enc = Encoder::new(&f, 0)?; + pp.serialize_compressed(&mut enc)?; + enc.finish()?; + f.sync_all()?; + Ok(()) +} + +pub fn load_pp(file: &str) -> Result, ProofError> +where + C: CommitmentScheme, + SC: StepCircuit + Sync, + SP: SetupParams + Sync, +{ + tracing::info!( + target: LOG_TARGET, + path = ?file, + "Loading public parameters", + ); + + let f = File::open(file)?; + let mut dec = Decoder::new(&f)?; + let pp = PP::::deserialize_compressed(&mut dec)?; + Ok(pp) +} + +pub fn gen_vm_pp(k: usize, aux: &C::SetupAux) -> Result, ProofError> +where + SP: SetupParams, + C: CommitmentScheme, +{ + let tr = nop_circuit(k)?; + gen_pp(&tr, aux) +} + +pub fn show_pp(pp: &PP) +where + SP: SetupParams, + C: CommitmentScheme, +{ + tracing::debug!( + target: LOG_TARGET, + "Primary circuit {}", + pp.shape, + ); + tracing::debug!( + target: LOG_TARGET, + "Secondary circuit {}", + pp.shape_secondary, + ); +} diff --git a/prover/src/srs.rs b/api/src/prover/nova/srs.rs similarity index 95% rename from prover/src/srs.rs rename to api/src/prover/nova/srs.rs index b779ed8a..e308675f 100644 --- a/prover/src/srs.rs +++ b/api/src/prover/nova/srs.rs @@ -1,7 +1,7 @@ use std::fs::File; use zstd::stream::Decoder; -use crate::{ +use crate::prover::nova::{ error::ProofError, pp::gen_vm_pp, types::{ParPP, SpartanKey, SRS}, @@ -34,7 +34,7 @@ pub mod test_srs { use ark_std::test_rng; use zstd::stream::Encoder; - use crate::types::{PolyCommitmentScheme, PC}; + use crate::prover::nova::types::{PolyCommitmentScheme, PC}; /// This function should only be used for testing, as it is insescure: /// the SRS should be generated by a trusted setup ceremony. pub fn gen_test_srs(num_vars: usize) -> Result { diff --git a/prover/src/types.rs b/api/src/prover/nova/types.rs similarity index 93% rename from prover/src/types.rs rename to api/src/prover/nova/types.rs index 1a9f2e9e..6bcb673b 100644 --- a/prover/src/types.rs +++ b/api/src/prover/nova/types.rs @@ -1,4 +1,4 @@ -//! Concrete types and traits used by zkVM +//! Default types and traits for use by zkVM pub use std::marker::PhantomData; @@ -26,6 +26,7 @@ pub use nexus_nova::{ r1cs::{R1CSShape, R1CSWitness}, StepCircuit, }; +use nexus_vm::memory::trie::MerkleTrie; // concrete constraint system pub type CS = ConstraintSystemRef; @@ -46,7 +47,7 @@ pub type PVC1 = com::PolyVectorCommitment; // structured reference string for polynomial commitment scheme pub type SRS = >::SRS; -pub type SC = crate::circuit::Tr; +pub type SC = crate::prover::nova::circuit::Tr; // concrete public parameters pub type PP = PublicParams; diff --git a/network/Cargo.toml b/network/Cargo.toml index 424c83e1..f6840065 100644 --- a/network/Cargo.toml +++ b/network/Cargo.toml @@ -34,9 +34,7 @@ ark-ff.workspace = true ark-ec.workspace = true ark-serialize.workspace = true -nexus-config = { path = "../config" } -nexus-vm = { path = "../vm" } -nexus-prover = { path = "../prover" } +nexus-api = { path = "../api" } hex = { workspace = true } [features] diff --git a/network/rpc/server/Cargo.toml b/network/rpc/server/Cargo.toml index 27e11ac6..db210beb 100644 --- a/network/rpc/server/Cargo.toml +++ b/network/rpc/server/Cargo.toml @@ -21,9 +21,7 @@ path = "src/bin/client.rs" [dependencies] nexus-rpc-traits = { path = "../traits", features = ["server"] } nexus-rpc-common = { path = "../common" } -nexus-prover = { path = "../../../prover" } -nexus-vm = { path = "../../../vm" } -nexus-config = { path = "../../../config" } +nexus-api = { path = "../../../api" } ark-serialize = { workspace = true } jsonrpsee = { workspace = true } diff --git a/network/rpc/server/src/bin/client.rs b/network/rpc/server/src/bin/client.rs index eda7910c..7d339d84 100644 --- a/network/rpc/server/src/bin/client.rs +++ b/network/rpc/server/src/bin/client.rs @@ -11,7 +11,7 @@ use std::env; use std::time::Duration; use jsonrpsee::ws_client::{WsClient, WsClientBuilder}; -use nexus_prover::types::IVCProof; +use nexus_api::prover::nova::types::IVCProof; use nexus_rpc_common::{ArkWrapper, ElfBytes}; use nexus_rpc_traits::RpcClient; diff --git a/network/rpc/server/src/bin/server.rs b/network/rpc/server/src/bin/server.rs index 64115ed5..03bd5a9b 100644 --- a/network/rpc/server/src/bin/server.rs +++ b/network/rpc/server/src/bin/server.rs @@ -1,4 +1,4 @@ -use nexus_config::{network::rpc::RpcConfig, Config}; +use nexus_api::config::{network::rpc::RpcConfig, Config}; use tracing::{level_filters::LevelFilter, Level}; use tracing_subscriber::{ diff --git a/network/rpc/server/src/error.rs b/network/rpc/server/src/error.rs index 99322635..9fbcfcaa 100644 --- a/network/rpc/server/src/error.rs +++ b/network/rpc/server/src/error.rs @@ -1,5 +1,5 @@ use jsonrpsee::types::ErrorObjectOwned; -use nexus_prover::error::ProofError; +use nexus_api::prover::nova::error::ProofError; use thiserror::Error; use tokio::sync::oneshot::error::RecvError; @@ -8,7 +8,7 @@ pub enum Error { #[error("program hash is unknown")] UnknownHash, #[error(transparent)] - Vm(#[from] nexus_vm::NexusVMError), + Vm(#[from] nexus_api::nvm::NexusVMError), #[error("Nova error")] Nova(ProofError), diff --git a/network/rpc/server/src/lib.rs b/network/rpc/server/src/lib.rs index aa561c23..29b9a60c 100644 --- a/network/rpc/server/src/lib.rs +++ b/network/rpc/server/src/lib.rs @@ -17,7 +17,7 @@ pub use nova::load_params; type RocksDB = storage::RocksDb<::Proof>; -pub async fn run(config: nexus_config::network::rpc::RpcConfig) { +pub async fn run(config: nexus_api::config::network::rpc::RpcConfig) { tracing::info!( target: rpc::LOG_TARGET, "RPC config: {config:?}", diff --git a/network/rpc/server/src/nova.rs b/network/rpc/server/src/nova.rs index e3d3ca8e..643d7ddc 100644 --- a/network/rpc/server/src/nova.rs +++ b/network/rpc/server/src/nova.rs @@ -1,12 +1,15 @@ use std::path::PathBuf; -use nexus_config::{ +use nexus_api::config::{ vm::{NovaImpl, ProverImpl, VmConfig}, Config, MiscConfig, }; -use nexus_prover::types::{IVCProof, SeqPP}; +use nexus_api::nvm::{ + interactive::{parse_elf, trace}, + memory::MerkleTrie, +}; +use nexus_api::prover::nova::types::{IVCProof, SeqPP}; use nexus_rpc_common::ElfBytes; -use nexus_vm::{init_vm, memory::trie::MerkleTrie, parse_elf_bytes, trace::trace}; use super::{Error, ProverT}; @@ -25,11 +28,10 @@ impl ProverT for NovaProver { type Params = SeqPP; fn prove(pp: &SeqPP, elf_bytes: ElfBytes) -> Result { - let elf = parse_elf_bytes(&elf_bytes)?; - let mut vm = init_vm(&elf, &elf_bytes)?; + let mut vm = parse_elf(&elf_bytes)?; let trace = trace::(&mut vm, CONFIG.k, false)?; - let proof = nexus_prover::prove_seq(pp, trace).map_err(Error::Nova)?; + let proof = nexus_api::prover::nova::prove_seq(pp, trace).map_err(Error::Nova)?; Ok(proof) } @@ -48,7 +50,7 @@ pub fn load_params() -> SeqPP { let path_str = path.to_str().expect("cache path is not valid utf8"); if path.exists() { - nexus_prover::pp::load_pp(path_str).expect("failed to load params") + nexus_api::prover::nova::pp::load_pp(path_str).expect("failed to load params") } else { let _span = tracing::info_span!( target: LOG_TARGET, @@ -58,9 +60,9 @@ pub fn load_params() -> SeqPP { ) .entered(); - let pp: SeqPP = - nexus_prover::pp::gen_vm_pp(CONFIG.k, &()).expect("failed to gen parameters"); - nexus_prover::pp::save_pp(&pp, path_str).expect("failed to save parameters"); + let pp: SeqPP = nexus_api::prover::nova::pp::gen_vm_pp(CONFIG.k, &()) + .expect("failed to gen parameters"); + nexus_api::prover::nova::pp::save_pp(&pp, path_str).expect("failed to save parameters"); pp } } diff --git a/network/src/bin/pcdnode/main.rs b/network/src/bin/pcdnode/main.rs index f3bffe7b..e9056331 100644 --- a/network/src/bin/pcdnode/main.rs +++ b/network/src/bin/pcdnode/main.rs @@ -18,8 +18,6 @@ use hyper::{ }; use tracing_subscriber::EnvFilter; -use nexus_prover::pp::gen_or_load; - use nexus_network::*; use post::*; use workers::*; @@ -86,7 +84,13 @@ async fn main() -> Result<()> { let opts = Opts::parse(); - let pp = gen_or_load(false, 0, &opts.pp_file, None)?; + tracing::info!( + target: LOG_TARGET, + path = ?opts.pp_file, + "Loading public parameters", + ); + + let pp = nexus_api::prover::nova::pp::load_pp(&opts.pp_file)?; let state = WorkerState::new(pp); start_local_workers(state.clone())?; diff --git a/network/src/bin/pcdnode/post.rs b/network/src/bin/pcdnode/post.rs index f48d19ea..7a7a9303 100644 --- a/network/src/bin/pcdnode/post.rs +++ b/network/src/bin/pcdnode/post.rs @@ -18,7 +18,11 @@ use crate::{ api::NexusAPI::{Error, NexusProof, Program, Query}, request_work, WorkerState, LOG_TARGET, }; -use nexus_vm::{eval::NexusVM, memory::trie::MerkleTrie, parse_elf, trace::trace}; +use nexus_api::nvm::{ + interactive::{parse_elf, trace}, + memory::MerkleTrie, + NexusVM, +}; pub fn manage_proof( mut state: WorkerState, diff --git a/network/src/bin/pcdnode/workers.rs b/network/src/bin/pcdnode/workers.rs index 39643762..c5d16a78 100644 --- a/network/src/bin/pcdnode/workers.rs +++ b/network/src/bin/pcdnode/workers.rs @@ -11,7 +11,7 @@ use hyper::upgrade::Upgraded; use async_channel::{unbounded, Receiver, Sender}; -use nexus_prover::{circuit::Tr, error::ProofError, types::*}; +use nexus_api::prover::nova::{circuit::Tr, error::ProofError, types::*}; use nexus_network::pcd::*; use nexus_network::*; diff --git a/network/src/pcd.rs b/network/src/pcd.rs index 0e7e66fc..175e6367 100644 --- a/network/src/pcd.rs +++ b/network/src/pcd.rs @@ -2,11 +2,11 @@ use std::net::SocketAddr; use serde::{Deserialize, Serialize}; -use nexus_prover::types::*; +use nexus_api::prover::nova::types::*; use crate::Result; -pub type Trace = nexus_vm::trace::Trace; +pub type Trace = nexus_api::nvm::interactive::Trace; #[allow(clippy::large_enum_variant)] #[derive(Serialize, Deserialize)] @@ -188,8 +188,9 @@ mod test { use super::*; use ark_ff::fields::AdditiveGroup; - use nexus_prover::circuit::nop_circuit; - use nexus_prover::pp::gen_pp; + use nexus_api::nvm::memory::MerkleTrie; + use nexus_api::prover::nova::circuit::nop_circuit; + use nexus_api::prover::nova::pp::gen_pp; fn round_trip(msg: &NexusMsg) { let v = encode_lz4(msg).unwrap(); @@ -209,14 +210,14 @@ mod test { #[test] fn round_trip_leaf() { - let t = nop_circuit(3).unwrap().0; + let t = nop_circuit::(3).unwrap().0; round_trip(&LeafReq(t)); } #[test] #[ignore] fn round_trip_node() { - let circuit = nop_circuit(3).unwrap(); + let circuit = nop_circuit::(3).unwrap(); let pp: ParPP = gen_pp(&circuit, &()).unwrap(); let n0 = PCDNode::prove_leaf(&pp, &circuit, 0, &circuit.input(0).unwrap()).unwrap(); let n2 = PCDNode::prove_leaf(&pp, &circuit, 2, &circuit.input(2).unwrap()).unwrap(); diff --git a/prover/Cargo.toml b/prover/Cargo.toml deleted file mode 100644 index 0b341341..00000000 --- a/prover/Cargo.toml +++ /dev/null @@ -1,56 +0,0 @@ -[package] -name = "nexus-prover" -authors = { workspace = true } -version = { workspace = true } -edition = { workspace = true } -homepage = { workspace = true } -repository = { workspace = true } -publish = { workspace = true } -keywords = { workspace = true } -categories = { workspace = true } - -[dependencies] -clap.workspace = true - -#rayon = "1.8" -snmalloc-rs = { version = "0.3.4", optional = true } - -anyhow = "1.0" - -zstd = { version = "0.12", default-features = false } - -nexus-vm = { path = "../vm" } -nexus-nova = { path = "../nova", features = ["spartan"] } -nexus-tui = { path = "../tools/tui" } -spartan = { path = "../spartan", package = "ark-spartan" } - -tracing = "0.1" -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } - -ark-ff.workspace = true -ark-ec.workspace = true -ark-std.workspace = true -ark-crypto-primitives.workspace = true -ark-relations.workspace = true -ark-r1cs-std.workspace = true -ark-serialize.workspace = true - -ark-bn254.workspace = true -ark-grumpkin.workspace = true - -[dev-dependencies] -nexus-config = { path = "../config" } - -[features] -default = ["parallel", "snmalloc"] -parallel = [ - "ark-ff/parallel", - "ark-ec/parallel", - "ark-std/parallel", - "ark-crypto-primitives/parallel", - "ark-r1cs-std/parallel", - "nexus-nova/parallel", -] -snmalloc = ["snmalloc-rs"] -# TODO: disable superconsole if not enabled -verbose = [] diff --git a/prover/examples/prove.rs b/prover/examples/prove.rs deleted file mode 100644 index 69900e03..00000000 --- a/prover/examples/prove.rs +++ /dev/null @@ -1,50 +0,0 @@ -//! Example of using `nexus-prover` API. -//! Run with `cargo run --release --example prove`. - -use nexus_config::{ - vm::{NovaImpl, ProverImpl}, - VmConfig, -}; -use nexus_vm::VMOpts; - -use tracing::level_filters::LevelFilter; -use tracing_subscriber::EnvFilter; - -const CONFIG: VmConfig = VmConfig { - k: 16, - prover: ProverImpl::Nova(nexus_config::vm::NovaImpl::Sequential), -}; - -fn main() -> anyhow::Result<()> { - let filter = EnvFilter::builder() - .with_default_directive(LevelFilter::DEBUG.into()) - .from_env() - .unwrap() - .add_directive("r1cs=off".parse().unwrap()); - tracing_subscriber::fmt() - .with_span_events(tracing_subscriber::fmt::format::FmtSpan::CLOSE) - .with_env_filter(filter) - .init(); - - tracing::info!("Setting up public parameters..."); - let public_params = nexus_prover::pp::gen_vm_pp(CONFIG.k, &())?; - - // Run the program. - let vm_opts = VMOpts { - k: CONFIG.k, - machine: Some(String::from("nop10")), - ..Default::default() - }; - let trace = nexus_prover::run( - &vm_opts, - matches!(CONFIG.prover, ProverImpl::Nova(NovaImpl::Parallel)), - )?; - - tracing::info!("Proving execution trace..."); - let proof = nexus_prover::prove_seq(&public_params, trace)?; - - tracing::info!("Verifying proof..."); - proof.verify(&public_params, proof.step_num() as _)?; - - Ok(()) -} diff --git a/prover/src/key.rs b/prover/src/key.rs deleted file mode 100644 index 268119fb..00000000 --- a/prover/src/key.rs +++ /dev/null @@ -1,146 +0,0 @@ -use std::fs::File; -use zstd::stream::{Decoder, Encoder}; - -pub use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; -use nexus_nova::nova::pcd::compression::SNARK; - -use crate::error::*; -use crate::pp::load_pp; -use crate::srs::load_srs; -use crate::types::*; -use crate::{LOG_TARGET, TERMINAL_MODE}; - -pub fn gen_key(pp: &ComPP, srs: &SRS) -> Result { - let key = SNARK::setup(pp, srs)?; - Ok(key) -} - -pub fn save_key(key: SpartanKey, file: &str) -> Result<(), ProofError> { - let f = File::create(file)?; - let mut enc = Encoder::new(&f, 0)?; - key.serialize_compressed(&mut enc)?; - enc.finish()?; - f.sync_all()?; - Ok(()) -} - -pub fn load_key(file: &str) -> Result { - let f = File::open(file)?; - let mut dec = Decoder::new(&f)?; - let key = SpartanKey::deserialize_compressed_unchecked(&mut dec)?; - Ok(key) -} - -pub fn gen_key_to_file(pp_file: &str, srs_file: &str, key_file: &str) -> Result<(), ProofError> { - tracing::info!( - target: LOG_TARGET, - path =?srs_file, - "Reading the SRS", - ); - let mut term = nexus_tui::TerminalHandle::new(TERMINAL_MODE); - let srs = { - let mut term_ctx = term.context("Loading").on_step(|_step| "SRS".into()); - let _guard = term_ctx.display_step(); - - load_srs(srs_file)? - }; - - tracing::info!( - target: LOG_TARGET, - path =?srs_file, - "SRS found for a maximum of {} variables", - srs.max_num_vars - ); - - tracing::info!( - target: LOG_TARGET, - pp_file =?pp_file, - "Reading the Nova public parameters", - ); - - let pp: ComPP = { - let mut term_ctx = term - .context("Loading") - .on_step(|_step| "Nova public parameters".into()); - let _guard = term_ctx.display_step(); - - load_pp(pp_file)? - }; - - tracing::info!( - target: LOG_TARGET, - key_file =?key_file, - "Generating Spartan key parameters", - ); - - let mut term_ctx = term - .context("Generating") - .on_step(|_step| "Spartan key".into()); - let _guard = term_ctx.display_step(); - - let key: SpartanKey = gen_key(&pp, &srs)?; - save_key(key, key_file) -} - -pub fn gen_or_load_key( - gen: bool, - key_file: &str, - pp_file: Option<&str>, - srs_file: Option<&str>, -) -> Result { - let mut term = nexus_tui::TerminalHandle::new(TERMINAL_MODE); - let key: SpartanKey = if gen { - tracing::info!( - target: LOG_TARGET, - key_file =?key_file, - "Generating Spartan key parameters", - ); - - let srs_file = srs_file.ok_or(ProofError::MissingSRS)?; - tracing::info!( - target: LOG_TARGET, - path =?srs_file, - "Reading the SRS", - ); - let srs = { - let mut term_ctx = term.context("Loading").on_step(|_step| "SRS".into()); - let _guard = term_ctx.display_step(); - load_srs(srs_file)? - }; - tracing::info!( - target: LOG_TARGET, - path =?srs_file, - "SRS found for a maximum of {} variables", - srs.max_num_vars - ); - - let pp_file = pp_file.ok_or(ProofError::InvalidPP)?; - tracing::info!( - target: LOG_TARGET, - path =?srs_file, - "Reading the Nova public parameters", - ); - - let mut term_ctx = term - .context("Setting up") - .on_step(|_step| "Spartan key".into()); - let _guard = term_ctx.display_step(); - - let pp: ComPP = load_pp(pp_file)?; - - gen_key(&pp, &srs)? - } else { - tracing::info!( - target: LOG_TARGET, - path = ?pp_file, - "Loading Spartan key", - ); - let mut term_ctx = term - .context("Loading") - .on_step(|_step| "Spartan key".into()); - let _guard = term_ctx.display_step(); - - load_key(key_file)? - }; - Ok(key) -} diff --git a/prover/src/lib.rs b/prover/src/lib.rs deleted file mode 100644 index cc4908f6..00000000 --- a/prover/src/lib.rs +++ /dev/null @@ -1,212 +0,0 @@ -pub mod circuit; -pub mod error; -pub mod key; -pub mod pp; -pub mod srs; - -pub mod types; - -use std::path::Path; - -use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; - -use nexus_vm::{memory::trie::MerkleTrie, VMOpts}; - -use nexus_nova::nova::pcd::compression::SNARK; - -use crate::{ - circuit::Tr, - error::ProofError, - types::{ComPCDNode, ComPP, ComProof, IVCProof, PCDNode, ParPP, SeqPP, SpartanKey}, -}; - -#[cfg(feature = "verbose")] -const TERMINAL_MODE: nexus_tui::Mode = nexus_tui::Mode::Enabled; -#[cfg(not(feature = "verbose"))] -const TERMINAL_MODE: nexus_tui::Mode = nexus_tui::Mode::Disabled; - -pub const LOG_TARGET: &str = "nexus-prover"; - -pub fn save_proof(proof: P, path: &Path) -> anyhow::Result<()> { - tracing::info!( - target: LOG_TARGET, - path = %path.display(), - "Saving the proof", - ); - - let mut term = nexus_tui::TerminalHandle::new(TERMINAL_MODE); - let mut context = term.context("Saving").on_step(|_step| "proof".into()); - let _guard = context.display_step(); - - let mut buf = Vec::new(); - - proof.serialize_compressed(&mut buf)?; - std::fs::write(path, buf)?; - - Ok(()) -} - -pub fn load_proof(path: &Path) -> Result { - let file = std::fs::File::open(path)?; - let reader = std::io::BufReader::new(file); - tracing::info!( - target: LOG_TARGET, - path = %path.display(), - "Loading the proof", - ); - - let mut term = nexus_tui::TerminalHandle::new(TERMINAL_MODE); - let mut context = term.context("Loading").on_step(|_step| "proof".into()); - let _guard = context.display_step(); - - let proof: P = P::deserialize_compressed(reader)?; - - Ok(proof) -} - -type Trace = nexus_vm::trace::Trace; - -pub fn run(opts: &VMOpts, pow: bool) -> Result { - Ok(nexus_vm::trace_vm::(opts, pow, false)?) -} - -pub fn prove_seq(pp: &SeqPP, trace: Trace) -> Result { - // let k = trace.k; - let tr = Tr(trace); - let icount = tr.instructions(); - let z_0 = tr.input(0)?; - let mut proof = IVCProof::new(&z_0); - - let num_steps = tr.steps(); - - let mut term = nexus_tui::TerminalHandle::new(TERMINAL_MODE); - let mut term_ctx = term - .context("Computing") - .on_step(|step| format!("step {step}")) - .num_steps(num_steps) - .with_loading_bar("Proving") - .completion_header("Proved") - .completion_stats(move |elapsed| { - format!( - "{num_steps} step(s) in {elapsed}; {:.2} instructions / second", - icount as f32 / elapsed.as_secs_f32() - ) - }); - - for _ in 0..num_steps { - let _guard = term_ctx.display_step(); - - proof = IVCProof::prove_step(proof, pp, &tr)?; - } - - Ok(proof) -} - -macro_rules! prove_par_impl { - ( $pp_type:ty, $node_type:ty, $name:ident ) => { - pub fn $name(pp: $pp_type, trace: Trace) -> Result<$node_type, ProofError> { - let k = trace.k; - let tr = Tr(trace); - - let num_steps = tr.steps(); - assert!((num_steps + 1).is_power_of_two()); - - let on_step = move |iter: usize| { - let b = (num_steps + 1).ilog2(); - let a = b - 1 - (num_steps - iter).ilog2(); - - let step = 2usize.pow(a + 1) * iter - (2usize.pow(a) - 1) * (2usize.pow(b + 1) - 1); - let step_type = if iter <= num_steps / 2 { - "leaf" - } else if iter == num_steps - 1 { - "root" - } else { - "node" - }; - format!("{step_type} {step}") - }; - - let mut term = nexus_tui::TerminalHandle::new(TERMINAL_MODE); - let mut term_ctx = term - .context("Computing") - .on_step(on_step) - .num_steps(num_steps) - .with_loading_bar("Proving") - .completion_header("Proved") - .completion_stats(move |elapsed| { - format!( - "tree root in {elapsed}; {:.2} instructions / second", - (k * num_steps) as f32 / elapsed.as_secs_f32() - ) - }); - - let mut vs = (0..num_steps) - .step_by(2) - .map(|i| { - let _guard = term_ctx.display_step(); - - let v = <$node_type>::prove_leaf(&pp, &tr, i, &tr.input(i)?)?; - Ok(v) - }) - .collect::, ProofError>>()?; - - loop { - if vs.len() == 1 { - break; - } - vs = vs - .chunks(2) - .map(|ab| { - let _guard = term_ctx.display_step(); - let c = <$node_type>::prove_parent(&pp, &tr, &ab[0], &ab[1])?; - Ok(c) - }) - .collect::, ProofError>>()?; - } - - Ok(vs.into_iter().next().unwrap()) - } - }; -} - -prove_par_impl!(ParPP, PCDNode, prove_par); -prove_par_impl!(ComPP, ComPCDNode, prove_par_com); - -pub fn compress( - compression_pp: &ComPP, - key: &SpartanKey, - node: ComPCDNode, -) -> Result { - tracing::info!( - target: LOG_TARGET, - "Compressing the proof", - ); - let mut term = nexus_tui::TerminalHandle::new(TERMINAL_MODE); - let mut term_ctx = term - .context("Compressing") - .on_step(|_step| "the proof".into()); - let _guard = term_ctx.display_step(); - - let compressed_pcd_proof = SNARK::compress(compression_pp, key, node)?; - - Ok(compressed_pcd_proof) -} - -pub fn verify_compressed( - key: &SpartanKey, - params: &ComPP, - proof: &ComProof, -) -> Result<(), ProofError> { - tracing::info!( - target: LOG_TARGET, - "Verifying the compressed proof", - ); - let mut term = nexus_tui::TerminalHandle::new(TERMINAL_MODE); - let mut term_ctx = term - .context("Verifying") - .on_step(|_step| "compressed proof".into()); - let _guard = term_ctx.display_step(); - - SNARK::verify(key, params, proof)?; - Ok(()) -} diff --git a/prover/src/main.rs b/prover/src/main.rs deleted file mode 100644 index ff20a718..00000000 --- a/prover/src/main.rs +++ /dev/null @@ -1,227 +0,0 @@ -#[cfg(feature = "snmalloc")] -#[global_allocator] -static ALLOC: snmalloc_rs::SnMalloc = snmalloc_rs::SnMalloc; - -use ark_std::path::Path; -use clap::{Parser, Subcommand}; -use tracing_subscriber::EnvFilter; - -use nexus_prover::{ - compress, - key::{gen_key_to_file, gen_or_load_key}, - load_proof, - pp::{gen_or_load, gen_to_file, load_pp}, - prove_par, prove_par_com, prove_seq, run, save_proof, - srs::load_srs, - types::{ComPCDNode, ComPP}, - LOG_TARGET, -}; -use nexus_vm::VMOpts; - -#[derive(Debug, Parser)] -#[command(author, version, about, long_about = None)] -struct Opts { - #[command(subcommand)] - command: Command, -} - -#[derive(Debug, Subcommand)] -enum Command { - /// Generate public parameters file - Gen { - /// instructions per step - #[arg(short, name = "k", default_value = "1")] - k: usize, - - /// use parallel Nova - #[arg(short = 'P', default_value = "false")] - par: bool, - - /// public parameters file - #[arg( - short = 'p', - long = "public-params", - default_value = "nexus-public.zst" - )] - pp_file: String, - - /// SRS file: if not provided, proofs will not be compressible. - #[arg(short = 's', long = "srs")] - srs_file: Option, - }, - - /// Prove execution of program - Prove { - /// generate public parameters (ignore files) - #[arg(short)] - gen: bool, - - /// use parallel Nova - #[arg(short = 'P', default_value = "false")] - par: bool, - - /// public parameters file - #[arg( - short = 'p', - long = "public-params", - default_value = "nexus-public.zst" - )] - pp_file: String, - - #[command(flatten)] - vm: VMOpts, - - /// SRS file: if supplied, compressible proof is generated - #[arg(short = 's', long = "srs")] - srs_file: Option, - - /// File to save the proof - #[arg(short = 'f', long = "proof_file")] - proof_file: String, - }, - /// Generate public parameters file - SpartanKeyGen { - /// public parameters file - #[arg( - short = 'p', - long = "public-params", - default_value = "nexus-public.zst" - )] - pp_file: String, - - /// SRS file - #[arg(short = 's', long = "srs")] - srs_file: String, - - /// Spartan key file - #[arg( - short = 'k', - long = "spartan-key", - default_value = "nexus-spartan-key.zst" - )] - key_file: String, - }, - - /// Compress a Nexus proof via supernova - Compress { - /// generate Spartan key (ignore files) - #[arg(short)] - gen: bool, - - /// Spartan key file - #[arg( - short = 'k', - long = "spartan-key", - default_value = "nexus-spartan-key.zst" - )] - key_file: String, - - /// public parameters file - #[arg( - short = 'p', - long = "public-params", - default_value = "nexus-public.zst" - )] - pp_file: String, - - /// srs file; only needed if `gen` is `false` - #[arg( - short = 's', - long = "structured-reference-string", - default_value = "nexus-srs.zst" - )] - srs_file: Option, - - /// File containing uncompressed proof - #[arg(short = 'f', long = "proof-file", default_value = "nexus-proof.json")] - proof_file: String, - - /// File to save compressed proof - #[arg( - short = 'c', - long = "compressed-proof-file", - default_value = "nexus-proof-compressed.json" - )] - compressed_proof_file: String, - }, -} -use Command::*; - -fn main() -> anyhow::Result<()> { - let filter = EnvFilter::from_default_env(); - tracing_subscriber::fmt() - .with_span_events(tracing_subscriber::fmt::format::FmtSpan::CLOSE) - .with_env_filter(filter) - .init(); - - let opts = Opts::parse(); - - match opts.command { - Gen { k, par, pp_file, srs_file } => { - gen_to_file(k, par, &pp_file, srs_file.as_deref())?; - Ok(()) - } - - SpartanKeyGen { pp_file, srs_file, key_file } => { - gen_key_to_file(&pp_file, &srs_file, &key_file)?; - Ok(()) - } - - Prove { - gen, - par, - pp_file, - vm, - srs_file, - proof_file, - } => { - let trace = run(&vm, par)?; - let path = Path::new(&proof_file); - if par { - if srs_file.is_some() { - let srs = load_srs(&srs_file.unwrap())?; - let proof = - prove_par_com(gen_or_load(gen, vm.k, &pp_file, Some(&(srs)))?, trace)?; - save_proof(proof, path) - } else { - let proof = prove_par(gen_or_load(gen, vm.k, &pp_file, Some(&()))?, trace)?; - save_proof(proof, path) - } - } else { - let proof = prove_seq(&gen_or_load(gen, vm.k, &pp_file, Some(&()))?, trace)?; - save_proof(proof, path) - } - } - - Compress { - gen, - key_file, - pp_file, - srs_file, - proof_file, - compressed_proof_file, - } => { - let key = gen_or_load_key(gen, &key_file, Some(&pp_file), srs_file.as_deref())?; - - tracing::info!( - target: LOG_TARGET, - path =?pp_file, - "Reading the Nova public parameters", - ); - - let pp: ComPP = load_pp(&pp_file)?; - - tracing::info!( - target: LOG_TARGET, - proof_file = %proof_file, - "Reading the proof", - ); - let proof_path = Path::new(&proof_file); - let node: ComPCDNode = load_proof(proof_path)?; - - let compressed_proof = compress(&pp, &key, node)?; - let compressed_proof_path = Path::new(&compressed_proof_file); - save_proof(compressed_proof, compressed_proof_path) - } - } -} diff --git a/prover/src/pp.rs b/prover/src/pp.rs deleted file mode 100644 index 43dfb1a6..00000000 --- a/prover/src/pp.rs +++ /dev/null @@ -1,202 +0,0 @@ -use std::fs::File; -use zstd::stream::{Decoder, Encoder}; - -pub use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; - -use super::srs::load_srs; -use crate::circuit::{nop_circuit, Tr}; -use crate::error::*; -use crate::types::*; -use crate::{LOG_TARGET, TERMINAL_MODE}; - -pub fn gen_pp(circuit: &SC, aux: &C::SetupAux) -> Result, ProofError> -where - C: CommitmentScheme, - SP: SetupParams, -{ - Ok(SP::setup(ro_config(), circuit, aux, &())?) -} - -pub fn save_pp(pp: &PP, file: &str) -> Result<(), ProofError> -where - C: CommitmentScheme, - SC: StepCircuit, - SP: SetupParams, -{ - let f = File::create(file)?; - let mut enc = Encoder::new(&f, 0)?; - pp.serialize_compressed(&mut enc)?; - enc.finish()?; - f.sync_all()?; - Ok(()) -} - -pub fn load_pp(file: &str) -> Result, ProofError> -where - C: CommitmentScheme, - SC: StepCircuit + Sync, - SP: SetupParams + Sync, -{ - let f = File::open(file)?; - let mut dec = Decoder::new(&f)?; - let pp = PP::::deserialize_compressed(&mut dec)?; - Ok(pp) -} - -pub fn gen_vm_pp(k: usize, aux: &C::SetupAux) -> Result, ProofError> -where - SP: SetupParams, - C: CommitmentScheme, -{ - let tr = nop_circuit(k)?; - gen_pp(&tr, aux) -} - -fn show_pp(pp: &PP) -where - SP: SetupParams, - C: CommitmentScheme, -{ - tracing::debug!( - target: LOG_TARGET, - "Primary circuit {}", - pp.shape, - ); - tracing::debug!( - target: LOG_TARGET, - "Secondary circuit {}", - pp.shape_secondary, - ); -} - -pub fn gen_to_file( - k: usize, - par: bool, - pp_file: &str, - srs_file_opt: Option<&str>, -) -> Result<(), ProofError> { - tracing::info!( - target: LOG_TARGET, - path = ?pp_file, - "Generating public parameters", - ); - let mut term = nexus_tui::TerminalHandle::new(TERMINAL_MODE); - - if par { - match srs_file_opt { - Some(srs_file) => { - tracing::info!( - target: LOG_TARGET, - path =?srs_file, - "Reading the SRS", - ); - let srs: SRS = { - let mut term_ctx = term.context("Loading").on_step(|_step| "SRS".into()); - let _guard = term_ctx.display_step(); - load_srs(srs_file)? - }; - tracing::info!( - target: LOG_TARGET, - path =?srs_file, - "SRS found for a maximum of {} variables", - srs.max_num_vars - ); - let pp: ComPP = { - tracing::info!( - target: LOG_TARGET, - "Generating compressible PCD public parameters", - ); - let mut term_ctx = term - .context("Setting up") - .on_step(|_step| "public parameters for PCD (compression enabled)".into()); - let _guard = term_ctx.display_step(); - gen_vm_pp(k, &srs)? - }; - - show_pp(&pp); - save_pp(&pp, pp_file) - } - None => { - tracing::info!( - target: LOG_TARGET, - "Generating non-compressible PCD public parameters", - ); - let pp: ParPP = { - let mut term_ctx = term - .context("Setting up") - .on_step(|_step| "public parameters for PCD (compression disabled)".into()); - let _guard = term_ctx.display_step(); - - gen_vm_pp(k, &())? - }; - show_pp(&pp); - save_pp(&pp, pp_file) - } - } - } else { - tracing::info!( - target: LOG_TARGET, - "Generating IVC public parameters", - ); - - let pp: SeqPP = { - let mut term_ctx = term - .context("Setting up") - .on_step(|_step| "public parameters for IVC".into()); - let _guard = term_ctx.display_step(); - gen_vm_pp(k, &())? - }; - show_pp(&pp); - save_pp(&pp, pp_file) - } -} - -pub fn gen_or_load( - gen: bool, - k: usize, - pp_file: &str, - aux_opt: Option<&C::SetupAux>, -) -> Result, ProofError> -where - SP: SetupParams + Sync, - C: CommitmentScheme, -{ - let mut term = nexus_tui::TerminalHandle::new(TERMINAL_MODE); - - let pp: PP = if gen { - tracing::info!( - target: LOG_TARGET, - "Generating public parameters", - ); - - let aux = if let Some(aux) = aux_opt { - aux - } else { - tracing::error!( - target: LOG_TARGET, - "Auxiliary setup parameters are not provided", - ); - return Err(ProofError::MissingSRS); - }; - let mut term_ctx = term - .context("Setting up") - .on_step(|_step| "public parameters".into()); - let _guard = term_ctx.display_step(); - gen_vm_pp(k, aux)? - } else { - tracing::info!( - target: LOG_TARGET, - path = ?pp_file, - "Loading public parameters", - ); - let mut term_ctx = term - .context("Loading") - .on_step(|_step| "public parameters".into()); - let _guard = term_ctx.display_step(); - - load_pp(pp_file)? - }; - - show_pp(&pp); - Ok(pp) -} diff --git a/tools/Cargo.toml b/tools/Cargo.toml index 5af90eeb..d46148ce 100644 --- a/tools/Cargo.toml +++ b/tools/Cargo.toml @@ -32,11 +32,7 @@ tracing-subscriber = { version = "0.3", default-features = false, features = [ cargo_metadata = "0.18.1" clap.workspace = true -nexus-config = { path = "../config", features = ["clap_derive"] } -nexus-vm = { path = "../vm" } -nexus-prover = { path = "../prover", features = ["verbose"] } -nexus-jolt = { path = "../jolt" } +nexus-api = { path = "../api", features = ["prover_jolt"] } nexus-tui = { path = "./tui" } -ark-spartan = { path = "../spartan" } ark-serialize.workspace = true diff --git a/tools/src/command/compress.rs b/tools/src/command/compress.rs index ceef8357..364a069d 100644 --- a/tools/src/command/compress.rs +++ b/tools/src/command/compress.rs @@ -3,9 +3,10 @@ use std::{io, path::PathBuf}; use anyhow::Context; use clap::Args; -use nexus_config::{vm as vm_config, Config}; +use nexus_api::config::{vm as vm_config, Config}; use super::{public_params::format_params_file, spartan_key::SetupArgs}; + use crate::{ command::{cache_path, spartan_key::spartan_setup}, LOG_TARGET, @@ -68,7 +69,7 @@ pub fn compress_proof(args: CompressArgs) -> anyhow::Result<()> { ); let pp_file_str = pp_file.to_str().context("path is not valid utf8")?; - let pp = nexus_prover::pp::load_pp(pp_file_str)?; + let pp = nexus_api::prover::nova::pp::load_pp(pp_file_str)?; let key_file = if let Some(path) = args.key_file { // return early if the path was explicitly specified and doesn't exist @@ -91,7 +92,7 @@ pub fn compress_proof(args: CompressArgs) -> anyhow::Result<()> { })? }; let key_file_str = key_file.to_str().context("path is not valid utf8")?; - let key = nexus_prover::key::gen_or_load_key(false, key_file_str, None, None)?; + let key = nexus_api::prover::nova::key::load_key(key_file_str)?; let proof_file = args.proof_file; if !proof_file.try_exists()? { @@ -102,14 +103,32 @@ pub fn compress_proof(args: CompressArgs) -> anyhow::Result<()> { ); return Err(io::Error::from(io::ErrorKind::NotFound).into()); }; - let proof = nexus_prover::load_proof(&proof_file)?; + + let mut term = nexus_tui::TerminalHandle::new_enabled(); + + let proof = { + let mut context = term.context("Loading").on_step(|_step| "proof".into()); + let _guard = context.display_step(); + + nexus_api::prover::nova::load_proof(&proof_file)? + }; let current_dir = std::env::current_dir()?; let compressed_proof_path = current_dir.join("nexus-proof-compressed"); - let compressed_proof = nexus_prover::compress(&pp, &key, proof)?; + let compressed_proof = { + let mut term_ctx = term + .context("Compressing") + .on_step(|_step| "the proof".into()); + let _guard = term_ctx.display_step(); + + nexus_api::prover::nova::compress(&pp, &key, proof)? + }; + + let mut context = term.context("Saving").on_step(|_step| "proof".into()); + let _guard = context.display_step(); - nexus_prover::save_proof(compressed_proof, &compressed_proof_path)?; + nexus_api::prover::nova::save_proof(compressed_proof, &compressed_proof_path)?; Ok(()) } diff --git a/tools/src/command/jolt.rs b/tools/src/command/jolt.rs index eb34ca1c..23dc25a1 100644 --- a/tools/src/command/jolt.rs +++ b/tools/src/command/jolt.rs @@ -2,8 +2,12 @@ use std::{fs::File, io::BufReader, path::Path}; -use nexus_jolt::{parse, preprocess, trace, JoltCommitments, JoltProof}; -use nexus_vm::memory::trie::MerkleTrie; +use nexus_api::nvm::memory::MerkleTrie; +use nexus_api::prover::jolt::{ + parse, trace, + types::{JoltCommitments, JoltProof}, + VM, +}; use anyhow::Context; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; @@ -15,7 +19,7 @@ type Proof = (JoltProof, JoltCommitments); pub fn prove(path: &Path) -> anyhow::Result<()> { let bytes = std::fs::read(path)?; - let vm: nexus_jolt::VM = parse::parse_elf(&bytes)?; + let vm: VM = parse::parse_elf(&bytes)?; let mut term = nexus_tui::TerminalHandle::new_enabled(); @@ -27,7 +31,7 @@ pub fn prove(path: &Path) -> anyhow::Result<()> { .completion_stats(move |elapsed| format!("in {elapsed}; bytecode size: {bytecode_size}")); let preprocessing = { let _guard = ctx.display_step(); - preprocess(&vm) + nexus_api::prover::jolt::preprocess(&vm) }; drop(term); @@ -49,7 +53,7 @@ pub fn prove(path: &Path) -> anyhow::Result<()> { .on_step(|_step| "program execution".into()); let (proof, commitments) = { let _guard = ctx.display_step(); - nexus_jolt::prove(trace, &preprocessing)? + nexus_api::prover::jolt::prove(trace, &preprocessing)? }; let proof = (proof, commitments); @@ -83,7 +87,7 @@ pub fn verify(proof_path: &Path, prove_args: CommonProveArgs) -> anyhow::Result< .context("proof is not in Jolt format")?; let bytes = std::fs::read(path)?; - let vm: nexus_jolt::VM = parse::parse_elf(&bytes)?; + let vm: VM = parse::parse_elf(&bytes)?; let mut term = nexus_tui::TerminalHandle::new_enabled(); @@ -95,7 +99,7 @@ pub fn verify(proof_path: &Path, prove_args: CommonProveArgs) -> anyhow::Result< .completion_stats(move |elapsed| format!("in {elapsed}; bytecode size: {bytecode_size}")); let preprocessing = { let _guard = ctx.display_step(); - preprocess(&vm) + nexus_api::prover::jolt::preprocess(&vm) }; // verify @@ -104,7 +108,7 @@ pub fn verify(proof_path: &Path, prove_args: CommonProveArgs) -> anyhow::Result< .on_step(move |_step| "proof".into()); let mut _guard = ctx.display_step(); - let result = nexus_jolt::verify(preprocessing, proof, commitments); + let result = nexus_api::prover::jolt::verify(preprocessing, proof, commitments); match result { Ok(_) => { diff --git a/tools/src/command/mod.rs b/tools/src/command/mod.rs index eb69a6fa..ed4b01a5 100644 --- a/tools/src/command/mod.rs +++ b/tools/src/command/mod.rs @@ -1,7 +1,7 @@ use clap::Subcommand; use std::path::PathBuf; -use nexus_config::{Config, MiscConfig}; +use nexus_api::config::{Config, MiscConfig}; use super::ENV; @@ -70,7 +70,7 @@ pub(crate) fn cache_path() -> anyhow::Result { #[cfg(test)] mod tests { use super::*; - use nexus_config::{Config, VmConfig}; + use nexus_api::config::{vm::VmConfig, Config}; #[test] fn env_config() { diff --git a/tools/src/command/prove.rs b/tools/src/command/prove.rs index fcd37c45..6ff2ad3a 100644 --- a/tools/src/command/prove.rs +++ b/tools/src/command/prove.rs @@ -6,7 +6,7 @@ use std::{ use anyhow::Context; use clap::Args; -use nexus_config::{vm as vm_config, Config}; +use nexus_api::config::{vm as vm_config, Config}; use crate::{ command::{ @@ -157,55 +157,185 @@ fn local_prove( }; let path_str = pp_file.to_str().context("path is not valid utf8")?; - let opts = nexus_vm::VMOpts { + let opts = nexus_api::nvm::VMOpts { k, machine: None, file: Some(path.into()), }; - let trace = nexus_prover::run(&opts, true)?; + let trace = nexus_api::prover::nova::run(&opts, true)?; + let k = trace.k; let current_dir = std::env::current_dir()?; let proof_path = current_dir.join("nexus-proof"); + let mut term = nexus_tui::TerminalHandle::new_enabled(); + + let tr = nexus_api::prover::nova::init_circuit_trace(trace)?; + let num_steps = tr.steps(); + + let on_step = move |iter: usize| match nova_impl { + vm_config::NovaImpl::Parallel | vm_config::NovaImpl::ParallelCompressible => { + let b = (num_steps + 1).ilog2(); + let a = b - 1 - (num_steps - iter).ilog2(); + + let step = 2usize.pow(a + 1) * iter - (2usize.pow(a) - 1) * (2usize.pow(b + 1) - 1); + let step_type = if iter <= num_steps / 2 { + "leaf" + } else if iter == num_steps - 1 { + "root" + } else { + "node" + }; + format!("{step_type} {step}") + } + _ => format!("step {iter}"), + }; + + let icount = { + match nova_impl { + vm_config::NovaImpl::Parallel | vm_config::NovaImpl::ParallelCompressible => { + k * num_steps + } + _ => tr.instructions(), + } + }; + + let mut term_ctx = term + .context("Computing") + .on_step(on_step) + .num_steps(num_steps) + .with_loading_bar("Proving") + .completion_header("Proved") + .completion_stats(move |elapsed| { + format!( + "{num_steps} step(s) in {elapsed}; {:.2} instructions / second", + icount as f32 / elapsed.as_secs_f32() + ) + }); + match nova_impl { vm_config::NovaImpl::Parallel => { - let state = nexus_prover::pp::gen_or_load(false, k, path_str, None)?; - let root = nexus_prover::prove_par(state, trace)?; - - nexus_prover::save_proof(root, &proof_path)?; + assert!((num_steps + 1).is_power_of_two()); + + let state = { + let mut iterm = nexus_tui::TerminalHandle::new_enabled(); + let mut term_ctx = iterm + .context("Loading") + .on_step(|_step| "public parameters".into()); + let _guard = term_ctx.display_step(); + + nexus_api::prover::nova::pp::load_pp(path_str)? + }; + + let mut vs = (0..num_steps) + .step_by(2) + .map(|i| { + let _guard = term_ctx.display_step(); + + let v = nexus_api::prover::nova::prove_par_leaf_step(&state, &tr, i)?; + Ok(v) + }) + .collect::>>()?; + + let root = { + loop { + if vs.len() == 1 { + break; + } + + vs = vs + .chunks(2) + .map(|ab| { + let _guard = term_ctx.display_step(); + let c = nexus_api::prover::nova::prove_par_parent_step( + &state, &tr, &ab[0], &ab[1], + )?; + Ok(c) + }) + .collect::>>()?; + } + + vs.into_iter().next().unwrap() + }; + + let mut context = term.context("Saving").on_step(|_step| "proof".into()); + let _guard = context.display_step(); + + nexus_api::prover::nova::save_proof(root, &proof_path)?; } vm_config::NovaImpl::ParallelCompressible => { - let state = nexus_prover::pp::gen_or_load(false, k, path_str, None)?; - let root = nexus_prover::prove_par_com(state, trace)?; - - nexus_prover::save_proof(root, &proof_path)?; + assert!((num_steps + 1).is_power_of_two()); + + let mut iterm = nexus_tui::TerminalHandle::new_enabled(); + let state = { + let mut term_ctx = iterm + .context("Loading") + .on_step(|_step| "public parameters".into()); + let _guard = term_ctx.display_step(); + + nexus_api::prover::nova::pp::load_pp(path_str)? + }; + + let mut vs = (0..num_steps) + .step_by(2) + .map(|i| { + let _guard = term_ctx.display_step(); + + let v = nexus_api::prover::nova::prove_par_com_leaf_step(&state, &tr, i)?; + Ok(v) + }) + .collect::>>()?; + + let root = { + loop { + if vs.len() == 1 { + break; + } + + vs = vs + .chunks(2) + .map(|ab| { + let _guard = term_ctx.display_step(); + let c = nexus_api::prover::nova::prove_par_com_parent_step( + &state, &tr, &ab[0], &ab[1], + )?; + Ok(c) + }) + .collect::>>()?; + } + + vs.into_iter().next().unwrap() + }; + + let mut context = term.context("Saving").on_step(|_step| "proof".into()); + let _guard = context.display_step(); + + nexus_api::prover::nova::save_proof(root, &proof_path)?; } vm_config::NovaImpl::Sequential => { - let state = nexus_prover::pp::gen_or_load(false, k, path_str, None)?; - let proof = nexus_prover::prove_seq(&state, trace)?; + let mut iterm = nexus_tui::TerminalHandle::new_enabled(); + let state = { + let mut term_ctx = iterm + .context("Loading") + .on_step(|_step| "public parameters".into()); + let _guard = term_ctx.display_step(); - nexus_prover::save_proof(proof, &proof_path)?; - } - } - - Ok(()) -} + nexus_api::prover::nova::pp::load_pp(path_str)? + }; -// fn save_proof(proof: P, path: &Path) -> anyhow::Result<()> { -// tracing::info!( -// target: LOG_TARGET, -// path = %path.display(), -// "Saving the proof", -// ); + let mut proof = nexus_api::prover::nova::prove_seq_step(None, &state, &tr)?; -// let mut term = nexus_tui::TerminalHandle::new_enabled(); -// let mut context = term.context("Saving").on_step(|_step| "proof".into()); -// let _guard = context.display_step(); + for _ in 1..num_steps { + let _guard = term_ctx.display_step(); + proof = nexus_api::prover::nova::prove_seq_step(Some(proof), &state, &tr)?; + } -// let mut buf = Vec::new(); + let mut context = term.context("Saving").on_step(|_step| "proof".into()); + let _guard = context.display_step(); -// proof.serialize_compressed(&mut buf)?; -// std::fs::write(path, buf)?; + nexus_api::prover::nova::save_proof(proof, &proof_path)?; + } + } -// Ok(()) -// } + Ok(()) +} diff --git a/tools/src/command/public_params.rs b/tools/src/command/public_params.rs index d6be57fe..e42f2ea7 100644 --- a/tools/src/command/public_params.rs +++ b/tools/src/command/public_params.rs @@ -5,11 +5,12 @@ use std::{ use anyhow::Context; -use nexus_config::{ +use nexus_api::config::{ vm::{self as vm_config, ProverImpl}, Config, }; -use nexus_prover::srs::{get_min_srs_size, test_srs::gen_test_srs_to_file}; +use nexus_api::prover::nova::srs::{get_min_srs_size, test_srs::gen_test_srs_to_file}; +use nexus_api::prover::nova::types::{ComPP, ParPP, SeqPP, SRS}; use crate::{command::cache_path, LOG_TARGET}; @@ -77,9 +78,37 @@ fn setup_params_to_file( srs_file: Option, ) -> anyhow::Result<()> { let path = path.to_str().context("path is not valid utf8")?; - match nova_impl { - vm_config::NovaImpl::Sequential => nexus_prover::pp::gen_to_file(k, false, path, None)?, - vm_config::NovaImpl::Parallel => nexus_prover::pp::gen_to_file(k, true, path, None)?, + + let mut term = nexus_tui::TerminalHandle::new_enabled(); + + let _ = match nova_impl { + vm_config::NovaImpl::Sequential => { + tracing::info!( + target: LOG_TARGET, + "Generating IVC public parameters", + ); + + let pp: SeqPP = { + let mut term_ctx = term + .context("Setting up") + .on_step(|_step| "public parameters for IVC".into()); + let _guard = term_ctx.display_step(); + + nexus_api::prover::nova::pp::gen_vm_pp(k, &())? + }; + nexus_api::prover::nova::pp::show_pp(&pp); + nexus_api::prover::nova::pp::save_pp(&pp, path) + } + vm_config::NovaImpl::Parallel => { + tracing::info!( + target: LOG_TARGET, + "Generating non-compressible PCD public parameters", + ); + let pp: ParPP = nexus_api::prover::nova::pp::gen_vm_pp(k, &())?; + + nexus_api::prover::nova::pp::show_pp(&pp); + nexus_api::prover::nova::pp::save_pp(&pp, path) + } vm_config::NovaImpl::ParallelCompressible => { let srs_file = match srs_file { None => { @@ -100,7 +129,32 @@ fn setup_params_to_file( return Err(io::Error::from(io::ErrorKind::NotFound).into()); } let srs_file_str = srs_file.to_str().context("path is not valid utf8")?; - nexus_prover::pp::gen_to_file(k, true, path, Some(srs_file_str))? + + tracing::info!( + target: LOG_TARGET, + path =?srs_file, + "Reading the SRS", + ); + let srs: SRS = nexus_api::prover::nova::srs::load_srs(srs_file_str)?; + + tracing::info!( + target: LOG_TARGET, + path =?srs_file, + "SRS found for a maximum of {} variables", + srs.max_num_vars + ); + + let pp: ComPP = { + tracing::info!( + target: LOG_TARGET, + "Generating compressible PCD public parameters", + ); + + nexus_api::prover::nova::pp::gen_vm_pp(k, &srs)? + }; + + nexus_api::prover::nova::pp::show_pp(&pp); + nexus_api::prover::nova::pp::save_pp(&pp, path) } }; Ok(()) diff --git a/tools/src/command/public_params/command_args.rs b/tools/src/command/public_params/command_args.rs index a8626eb2..b29262fb 100644 --- a/tools/src/command/public_params/command_args.rs +++ b/tools/src/command/public_params/command_args.rs @@ -1,7 +1,7 @@ use std::path::PathBuf; use clap::{Args, Subcommand}; -use nexus_config::vm as vm_config; +use nexus_api::config::vm as vm_config; #[derive(Debug, Args)] pub struct PublicParamsArgs { diff --git a/tools/src/command/run.rs b/tools/src/command/run.rs index b02a7338..34e9dc6d 100644 --- a/tools/src/command/run.rs +++ b/tools/src/command/run.rs @@ -35,11 +35,11 @@ fn run_vm(bin: Option, verbose: bool, profile: &str) -> anyhow::Result<( } pub fn run_vm_with_elf_file(path: &Path, verbose: bool) -> anyhow::Result<()> { - let opts = nexus_vm::VMOpts { + let opts = nexus_api::nvm::VMOpts { k: 1, machine: None, file: Some(path.into()), }; - nexus_vm::run_vm::(&opts, verbose).map_err(Into::into) + nexus_api::nvm::run_vm::(&opts, verbose).map_err(Into::into) } diff --git a/tools/src/command/spartan_key.rs b/tools/src/command/spartan_key.rs index 2359f9b5..1639aec4 100644 --- a/tools/src/command/spartan_key.rs +++ b/tools/src/command/spartan_key.rs @@ -6,8 +6,8 @@ use std::{ use anyhow::Context; -use nexus_config::{vm as vm_config, Config}; -use nexus_prover::srs::get_min_srs_size; +use nexus_api::config::{vm as vm_config, Config}; +use nexus_api::prover::nova::{srs::get_min_srs_size, types::ComPP}; use super::public_params::{format_params_file, format_srs_file}; use crate::{command::cache_path, LOG_TARGET}; @@ -129,7 +129,48 @@ fn spartan_setup_to_file(key_path: &Path, pp_path: &Path, srs_path: &Path) -> an let key_path = key_path.to_str().context("path is not valid utf8")?; let pp_path_str = pp_path.to_str().context("path is not valid utf8")?; let srs_path_str = srs_path.to_str().context("path is not valid utf8")?; - nexus_prover::key::gen_key_to_file(pp_path_str, srs_path_str, key_path)?; + + tracing::info!( + target: LOG_TARGET, + path =?srs_path_str, + "Reading the SRS", + ); + let mut term = nexus_tui::TerminalHandle::new_enabled(); + let srs = { + let mut term_ctx = term.context("Loading").on_step(|_step| "SRS".into()); + let _guard = term_ctx.display_step(); + + nexus_api::prover::nova::srs::load_srs(srs_path_str)? + }; + + tracing::info!( + target: LOG_TARGET, + path =?srs_path_str, + "SRS found for a maximum of {} variables", + srs.max_num_vars + ); + + tracing::info!( + target: LOG_TARGET, + pp_file =?pp_path_str, + "Reading the Nova public parameters", + ); + + let pp: ComPP = { + let mut term_ctx = term + .context("Loading") + .on_step(|_step| "Nova public parameters".into()); + let _guard = term_ctx.display_step(); + + nexus_api::prover::nova::pp::load_pp(pp_path_str)? + }; + + let mut term_ctx = term + .context("Generating") + .on_step(|_step| "Spartan key".into()); + let _guard = term_ctx.display_step(); + + nexus_api::prover::nova::key::gen_key_to_file(&pp, &srs, key_path)?; Ok(()) } diff --git a/tools/src/command/verify.rs b/tools/src/command/verify.rs index 5b548533..1e396301 100644 --- a/tools/src/command/verify.rs +++ b/tools/src/command/verify.rs @@ -8,12 +8,6 @@ use anyhow::Context; use ark_serialize::CanonicalDeserialize; use clap::Args; -use nexus_config::{ - vm::{NovaImpl, ProverImpl, VmConfig}, - Config, -}; -use nexus_prover::types::{ComPCDNode, ComPP, ComProof, IVCProof, PCDNode, ParPP, SeqPP}; - use super::{ jolt, prove::{CommonProveArgs, LocalProveArgs}, @@ -21,6 +15,11 @@ use super::{ spartan_key::format_key_file, }; use crate::{command::cache_path, LOG_TARGET}; +use nexus_api::config::{ + vm::{NovaImpl, ProverImpl, VmConfig}, + Config, +}; +use nexus_api::prover::nova::types::{ComPCDNode, ComProof, IVCProof, PCDNode}; #[derive(Debug, Args)] pub struct VerifyArgs { @@ -102,6 +101,15 @@ fn verify_proof_compressed( .to_owned(); let mut term = nexus_tui::TerminalHandle::new_enabled(); + let params = { + let mut ctx = term + .context("Loading") + .on_step(|_step| "public parameters".into()); + let _guard = ctx.display_step(); + + nexus_api::prover::nova::pp::load_pp(&pp_path)? + }; + let mut ctx = term .context("Verifying compressed") .on_step(move |_step| "proof".into()); @@ -109,11 +117,11 @@ fn verify_proof_compressed( let result = { let proof = ComProof::deserialize_compressed(reader)?; - let params = nexus_prover::pp::gen_or_load(false, k, &pp_path, None)?; - let key = nexus_prover::key::gen_or_load_key(false, &key_path, Some(&pp_path), None)?; + let key = nexus_api::prover::nova::key::load_key(&key_path)?; _guard = ctx.display_step(); - nexus_prover::verify_compressed(&key, ¶ms, &proof).map_err(anyhow::Error::from) + nexus_api::prover::nova::verify_compressed(&key, ¶ms, &proof) + .map_err(anyhow::Error::from) }; match result { @@ -183,22 +191,46 @@ fn verify_proof( let result = match nova_impl { NovaImpl::Parallel => { + let mut iterm = nexus_tui::TerminalHandle::new_enabled(); + let params = { + let mut term_ctx = iterm + .context("Loading") + .on_step(|_step| "public parameters".into()); + let _guard = term_ctx.display_step(); + + nexus_api::prover::nova::pp::load_pp(&path)? + }; let root = PCDNode::deserialize_compressed(reader)?; - let params: ParPP = nexus_prover::pp::gen_or_load(false, k, &path, None)?; _guard = ctx.display_step(); root.verify(¶ms).map_err(anyhow::Error::from) } NovaImpl::ParallelCompressible => { + let mut iterm = nexus_tui::TerminalHandle::new_enabled(); + let params = { + let mut term_ctx = iterm + .context("Loading") + .on_step(|_step| "public parameters".into()); + let _guard = term_ctx.display_step(); + + nexus_api::prover::nova::pp::load_pp(&path)? + }; let root = ComPCDNode::deserialize_compressed(reader)?; - let params: ComPP = nexus_prover::pp::gen_or_load(false, k, &path, None)?; _guard = ctx.display_step(); root.verify(¶ms).map_err(anyhow::Error::from) } NovaImpl::Sequential => { + let mut iterm = nexus_tui::TerminalHandle::new_enabled(); + let params = { + let mut term_ctx = iterm + .context("Loading") + .on_step(|_step| "public parameters".into()); + let _guard = term_ctx.display_step(); + + nexus_api::prover::nova::pp::load_pp(&path)? + }; let proof = IVCProof::deserialize_compressed(reader)?; - let params: SeqPP = nexus_prover::pp::gen_or_load(false, k, &path, None)?; _guard = ctx.display_step(); proof