diff --git a/o1vm/src/cli/mod.rs b/o1vm/src/cli/mod.rs index 7f915aee74..e57a7a4a13 100644 --- a/o1vm/src/cli/mod.rs +++ b/o1vm/src/cli/mod.rs @@ -1,6 +1,7 @@ use clap::Parser; pub mod cannon; +pub mod riscv; #[derive(Parser, Debug, Clone)] #[command( @@ -10,5 +11,7 @@ pub mod cannon; )] pub enum Commands { #[command(subcommand)] - Cannon(cannon::Cannon), + Cannon(Box), + #[command(subcommand)] + RiscV(riscv::Command), } diff --git a/o1vm/src/cli/riscv.rs b/o1vm/src/cli/riscv.rs new file mode 100644 index 0000000000..29ab6174c6 --- /dev/null +++ b/o1vm/src/cli/riscv.rs @@ -0,0 +1,18 @@ +use clap::{arg, Parser, Subcommand}; + +#[derive(Parser, Debug, Clone)] +pub struct Elf { + #[arg( + short = 'e', + long, + value_name = "ELF_PATH", + help = "input ELF file path for riscv" + )] + pub path: String, +} + +#[derive(Subcommand, Clone, Debug)] +pub enum Command { + #[command(name = "elf")] + Run(Elf), +} diff --git a/o1vm/src/pickles/column_env.rs b/o1vm/src/pickles/column_env.rs index 61f72d05e1..3e7ddb608a 100644 --- a/o1vm/src/pickles/column_env.rs +++ b/o1vm/src/pickles/column_env.rs @@ -21,7 +21,12 @@ type Evals = Evaluations>; pub struct ColumnEnvironment<'a, F: FftField> { /// The witness column polynomials. Includes relation columns and dynamic /// selector columns. - pub witness: &'a WitnessColumns, [Evals; N_MIPS_SEL_COLS]>, + pub witness: &'a WitnessColumns< + Evals, + [Evals; N_MIPS_SEL_COLS], + SCRATCH_SIZE, + SCRATCH_SIZE_INVERSE, + >, /// The value `prod_{j != 1} (1 - ω^j)`, used for efficiently /// computing the evaluations of the unnormalized Lagrange basis /// polynomials. @@ -47,7 +52,7 @@ pub fn get_all_columns() -> Vec { cols } -impl WitnessColumns { +impl WitnessColumns { pub fn get_column(&self, col: &Column) -> Option<&G> { match *col { Column::Relation(i) => { diff --git a/o1vm/src/pickles/main.rs b/o1vm/src/pickles/main.rs index da9c858bce..976f4beb8f 100644 --- a/o1vm/src/pickles/main.rs +++ b/o1vm/src/pickles/main.rs @@ -10,11 +10,17 @@ use mina_poseidon::{ use o1vm::{ cannon::{self, Start, State}, cli, elf_loader, - interpreters::mips::{ - column::N_MIPS_REL_COLS, - constraints as mips_constraints, - witness::{self as mips_witness}, - Instruction, + interpreters::{ + mips::{ + column::{ + N_MIPS_REL_COLS, SCRATCH_SIZE as MIPS_SCRATCH_SIZE, + SCRATCH_SIZE_INVERSE as MIPS_SCRATCH_SIZE_INVERSE, + }, + constraints as mips_constraints, + witness::{self as mips_witness}, + Instruction, + }, + riscv32im::{witness::Env as RiscEnv, PAGE_SIZE}, }, pickles::{proof::ProofInputs, prover, verifier}, preimage_oracle::{NullPreImageOracle, PreImageOracle, PreImageOracleT}, @@ -78,7 +84,8 @@ pub fn cannon_main(args: cli::cannon::RunArgs) { let constraints = mips_constraints::get_all_constraints::(); - let mut curr_proof_inputs: ProofInputs = ProofInputs::new(DOMAIN_SIZE); + let mut curr_proof_inputs: ProofInputs = + ProofInputs::new(DOMAIN_SIZE); while !mips_wit_env.halt { let _instr: Instruction = mips_wit_env.step(&configuration, meta, &start); for (scratch, scratch_chunk) in mips_wit_env @@ -113,6 +120,8 @@ pub fn cannon_main(args: cli::cannon::RunArgs) { let proof = prover::prove::< Vesta, DefaultFqSponge, + MIPS_SCRATCH_SIZE, + MIPS_SCRATCH_SIZE_INVERSE, DefaultFrSponge, _, >(domain_fp, &srs, curr_proof_inputs, &constraints, &mut rng) @@ -154,7 +163,7 @@ pub fn main() -> ExitCode { env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); let args = cli::Commands::parse(); match args { - cli::Commands::Cannon(args) => match args { + cli::Commands::Cannon(args) => match *args { cli::cannon::Cannon::Run(args) => { cannon_main(args); } @@ -165,6 +174,18 @@ pub fn main() -> ExitCode { gen_state_json(args).expect("Error generating state.json"); } }, + cli::Commands::RiscV(args) => match args { + cli::riscv::Command::Run(args) => { + let path = Path::new(&args.path); + let state = elf_loader::parse_elf(elf_loader::Architecture::RiscV32, path) + .expect("Error parsing ELF file"); + + let mut witness = RiscEnv::::create(PAGE_SIZE.try_into().unwrap(), state); + while !witness.halt { + witness.step(); + } + } + }, } ExitCode::SUCCESS } diff --git a/o1vm/src/pickles/proof.rs b/o1vm/src/pickles/proof.rs index 40529a3409..39ab464e52 100644 --- a/o1vm/src/pickles/proof.rs +++ b/o1vm/src/pickles/proof.rs @@ -1,9 +1,8 @@ +use crate::interpreters::mips::column::{SCRATCH_SIZE, SCRATCH_SIZE_INVERSE}; use kimchi::{curve::KimchiCurve, proof::PointEvaluations}; use poly_commitment::{ipa::OpeningProof, PolyComm}; -use crate::interpreters::mips::column::{N_MIPS_SEL_COLS, SCRATCH_SIZE, SCRATCH_SIZE_INVERSE}; - -pub struct WitnessColumns { +pub struct WitnessColumns { pub scratch: [G; SCRATCH_SIZE], pub scratch_inverse: [G; SCRATCH_SIZE_INVERSE], pub instruction_counter: G, @@ -11,16 +10,22 @@ pub struct WitnessColumns { pub selector: S, } -pub struct ProofInputs { - pub evaluations: WitnessColumns, Vec>, +pub struct ProofInputs +{ + pub evaluations: WitnessColumns< + Vec, + Vec, + SCRATCH_SIZE, + SCRATCH_SIZE_INVERSE, + >, } -impl ProofInputs { +impl ProofInputs { pub fn new(domain_size: usize) -> Self { ProofInputs { evaluations: WitnessColumns { - scratch: std::array::from_fn(|_| Vec::with_capacity(domain_size)), - scratch_inverse: std::array::from_fn(|_| Vec::with_capacity(domain_size)), + scratch: std::array::from_fn(|_| Vec::with_capacity(SCRATCH_SIZE)), + scratch_inverse: std::array::from_fn(|_| Vec::with_capacity(SCRATCH_SIZE_INVERSE)), instruction_counter: Vec::with_capacity(domain_size), error: Vec::with_capacity(domain_size), selector: Vec::with_capacity(domain_size), @@ -30,10 +35,25 @@ impl ProofInputs { } // FIXME: should we blind the commitment? -pub struct Proof { - pub commitments: WitnessColumns, [PolyComm; N_MIPS_SEL_COLS]>, - pub zeta_evaluations: WitnessColumns, - pub zeta_omega_evaluations: WitnessColumns, +pub struct Proof { + pub commitments: WitnessColumns< + PolyComm, + [PolyComm; INSTRUCTION_SET_SIZE], + SCRATCH_SIZE, + SCRATCH_SIZE_INVERSE, + >, + pub zeta_evaluations: WitnessColumns< + G::ScalarField, + [G::ScalarField; INSTRUCTION_SET_SIZE], + SCRATCH_SIZE, + SCRATCH_SIZE_INVERSE, + >, + pub zeta_omega_evaluations: WitnessColumns< + G::ScalarField, + [G::ScalarField; INSTRUCTION_SET_SIZE], + SCRATCH_SIZE, + SCRATCH_SIZE_INVERSE, + >, pub quotient_commitment: PolyComm, pub quotient_evaluations: PointEvaluations>, /// IPA opening proof diff --git a/o1vm/src/pickles/prover.rs b/o1vm/src/pickles/prover.rs index d9aa9416cf..35caa85fd9 100644 --- a/o1vm/src/pickles/prover.rs +++ b/o1vm/src/pickles/prover.rs @@ -30,7 +30,13 @@ use super::{ proof::{Proof, ProofInputs, WitnessColumns}, DEGREE_QUOTIENT_POLYNOMIAL, }; -use crate::{interpreters::mips::column::N_MIPS_SEL_COLS, E}; +use crate::{ + interpreters::mips::column::{ + N_MIPS_SEL_COLS, SCRATCH_SIZE as MIPS_SCRATCH_SIZE, + SCRATCH_SIZE_INVERSE as MIPS_SCRATCH_SIZE_INVERSE, + }, + E, +}; use thiserror::Error; /// Errors that can arise when creating a proof @@ -55,15 +61,17 @@ pub enum ProverError { pub fn prove< G: KimchiCurve, EFqSponge: FqSponge + Clone, + const SCRATCH_SIZE: usize, + const SCRATCH_SIZE_INVERSE: usize, EFrSponge: FrSponge, RNG, >( domain: EvaluationDomains, srs: &SRS, - inputs: ProofInputs, + inputs: ProofInputs, constraints: &[E], rng: &mut RNG, -) -> Result, ProverError> +) -> Result, ProverError> where G::BaseField: PrimeField, RNG: RngCore + CryptoRng, @@ -82,6 +90,8 @@ where let polys: WitnessColumns< DensePolynomial, [DensePolynomial; N_MIPS_SEL_COLS], + SCRATCH_SIZE, + SCRATCH_SIZE_INVERSE, > = { let WitnessColumns { scratch, @@ -130,7 +140,12 @@ where }; debug!("Prover: committing to all columns, including the selectors"); - let commitments: WitnessColumns, [PolyComm; N_MIPS_SEL_COLS]> = { + let commitments: WitnessColumns< + PolyComm, + [PolyComm; N_MIPS_SEL_COLS], + MIPS_SCRATCH_SIZE, + MIPS_SCRATCH_SIZE_INVERSE, + > = { let WitnessColumns { scratch, scratch_inverse, @@ -331,12 +346,20 @@ where } }; // All evaluations at ζ - let zeta_evaluations: WitnessColumns = - evals(&zeta); + let zeta_evaluations: WitnessColumns< + G::ScalarField, + [G::ScalarField; N_MIPS_SEL_COLS], + MIPS_SCRATCH_SIZE, + MIPS_SCRATCH_SIZE_INVERSE, + > = evals(&zeta); // All evaluations at ζω - let zeta_omega_evaluations: WitnessColumns = - evals(&zeta_omega); + let zeta_omega_evaluations: WitnessColumns< + G::ScalarField, + [G::ScalarField; N_MIPS_SEL_COLS], + MIPS_SCRATCH_SIZE, + MIPS_SCRATCH_SIZE_INVERSE, + > = evals(&zeta_omega); let chunked_quotient = quotient_poly .to_chunked_polynomial(DEGREE_QUOTIENT_POLYNOMIAL as usize, domain.d1.size as usize); diff --git a/o1vm/src/pickles/tests.rs b/o1vm/src/pickles/tests.rs index b4bb102dc7..46fdc8a0d7 100644 --- a/o1vm/src/pickles/tests.rs +++ b/o1vm/src/pickles/tests.rs @@ -1,18 +1,18 @@ use std::time::Instant; -use super::{ - super::interpreters::mips::column::SCRATCH_SIZE, - proof::{ProofInputs, WitnessColumns}, - prover::prove, -}; use crate::{ interpreters::mips::{ - column::SCRATCH_SIZE_INVERSE, + column::{SCRATCH_SIZE, SCRATCH_SIZE_INVERSE}, constraints as mips_constraints, interpreter::{self, InterpreterEnv}, Instruction, }, - pickles::{verifier::verify, MAXIMUM_DEGREE_CONSTRAINTS, TOTAL_NUMBER_OF_CONSTRAINTS}, + pickles::{ + proof::{ProofInputs, WitnessColumns}, + prover::prove, + verifier::verify, + MAXIMUM_DEGREE_CONSTRAINTS, TOTAL_NUMBER_OF_CONSTRAINTS, + }, }; use ark_ff::{Field, One, UniformRand, Zero}; use kimchi::circuits::{domains::EvaluationDomains, expr::Expr, gate::CurrOrNext}; @@ -63,7 +63,7 @@ fn zero_to_n_minus_one(n: usize) -> Vec { fn test_small_circuit() { let domain = EvaluationDomains::::create(8).unwrap(); let srs = SRS::create(8); - let proof_input = ProofInputs:: { + let proof_input = ProofInputs:: { evaluations: WitnessColumns { scratch: std::array::from_fn(|_| zero_to_n_minus_one(8)), scratch_inverse: std::array::from_fn(|_| (0..8).map(|_| Fq::zero()).collect()), @@ -86,7 +86,7 @@ fn test_small_circuit() { type BaseSponge = DefaultFqSponge; type ScalarSponge = DefaultFrSponge; - let proof = prove::( + let proof = prove::( domain, &srs, proof_input, diff --git a/o1vm/src/pickles/verifier.rs b/o1vm/src/pickles/verifier.rs index fbbaa912eb..33b11d8cfb 100644 --- a/o1vm/src/pickles/verifier.rs +++ b/o1vm/src/pickles/verifier.rs @@ -27,11 +27,16 @@ use super::{ column_env::get_all_columns, proof::{Proof, WitnessColumns}, }; -use crate::{interpreters::mips::column::N_MIPS_SEL_COLS, E}; +use crate::{ + interpreters::mips::column::{N_MIPS_SEL_COLS, SCRATCH_SIZE, SCRATCH_SIZE_INVERSE}, + E, +}; use kimchi_msm::columns::Column; -type CommitmentColumns = WitnessColumns, [PolyComm; N_MIPS_SEL_COLS]>; -type EvaluationColumns = WitnessColumns; +type CommitmentColumns = + WitnessColumns, [PolyComm; N_MIPS_SEL_COLS], SCRATCH_SIZE, SCRATCH_SIZE_INVERSE>; +type EvaluationColumns = + WitnessColumns; struct ColumnEval<'a, G: AffineRepr> { commitment: &'a CommitmentColumns, @@ -70,7 +75,7 @@ pub fn verify< domain: EvaluationDomains, srs: & as OpenProof>::SRS, constraints: &[E], - proof: &Proof, + proof: &Proof, ) -> bool where ::BaseField: PrimeField,