From d671a77659923055dc978d60213c7049e53a0b9e Mon Sep 17 00:00:00 2001 From: querolita Date: Fri, 19 Jan 2024 13:01:02 +0100 Subject: [PATCH 1/3] first skeleton for witness accumulation, some errors with iterators and types --- optimism/src/keccak/column.rs | 30 +++++------ optimism/src/keccak/environment.rs | 2 +- optimism/src/main.rs | 81 ++++++++++++++++++++++++++++-- 3 files changed, 93 insertions(+), 20 deletions(-) diff --git a/optimism/src/keccak/column.rs b/optimism/src/keccak/column.rs index 633b06af22..72cacb4c28 100644 --- a/optimism/src/keccak/column.rs +++ b/optimism/src/keccak/column.rs @@ -59,21 +59,21 @@ pub enum KeccakColumn { #[derive(Clone, Debug, Eq, PartialEq)] pub struct KeccakColumns { - pub(crate) hash_index: T, - pub(crate) step_index: T, - pub(crate) flag_round: T, // Coeff Round = 0 | 1 .. 24 - pub(crate) flag_absorb: T, // Coeff Absorb = 0 | 1 - pub(crate) flag_squeeze: T, // Coeff Squeeze = 0 | 1 - pub(crate) flag_root: T, // Coeff Root = 0 | 1 - pub(crate) flag_pad: T, // Coeff Pad = 0 | 1 - pub(crate) flag_length: T, // Coeff Length 0 | 1 .. 136 - pub(crate) two_to_pad: T, // 2^PadLength - pub(crate) inverse_round: T, // Round^-1 - pub(crate) flags_bytes: [T; RATE_IN_BYTES], // 136 boolean values - pub(crate) pad_suffix: [T; 5], // 5 values with padding suffix - pub(crate) round_constants: [T; QUARTERS], // Round constants - pub(crate) curr: [T; ZKVM_KECCAK_COLS_CURR], // Curr[0..1965) - pub(crate) next: [T; ZKVM_KECCAK_COLS_NEXT], // Next[0..100) + pub hash_index: T, + pub step_index: T, + pub flag_round: T, // Coeff Round = 0 | 1 .. 24 + pub flag_absorb: T, // Coeff Absorb = 0 | 1 + pub flag_squeeze: T, // Coeff Squeeze = 0 | 1 + pub flag_root: T, // Coeff Root = 0 | 1 + pub flag_pad: T, // Coeff Pad = 0 | 1 + pub flag_length: T, // Coeff Length 0 | 1 .. 136 + pub two_to_pad: T, // 2^PadLength + pub inverse_round: T, // Round^-1 + pub flags_bytes: [T; RATE_IN_BYTES], // 136 boolean values + pub pad_suffix: [T; 5], // 5 values with padding suffix + pub round_constants: [T; QUARTERS], // Round constants + pub curr: [T; ZKVM_KECCAK_COLS_CURR], // Curr[0..1965) + pub next: [T; ZKVM_KECCAK_COLS_NEXT], // Next[0..100) } impl KeccakColumns { diff --git a/optimism/src/keccak/environment.rs b/optimism/src/keccak/environment.rs index 8f44cfe903..6fd638b038 100644 --- a/optimism/src/keccak/environment.rs +++ b/optimism/src/keccak/environment.rs @@ -19,7 +19,7 @@ pub struct KeccakEnv { pub(crate) lookups: Vec>>, /// The full state of the Keccak gate (witness) - pub(crate) keccak_state: KeccakColumns>, + pub keccak_state: KeccakColumns>, /// What step of the hash is being executed (or None, if just ended) pub keccak_step: Option, diff --git a/optimism/src/main.rs b/optimism/src/main.rs index db98ebafc8..bd7034d3cf 100644 --- a/optimism/src/main.rs +++ b/optimism/src/main.rs @@ -1,13 +1,20 @@ +use ark_bn254::FrParameters; use ark_ec::bn::Bn; -use ark_ff::{UniformRand, Zero}; +use ark_ff::{Fp256, UniformRand, Zero}; use kimchi_optimism::{ cannon::{self, Meta, Start, State}, cannon_cli, - keccak::interpreter::KeccakInterpreter, - mips::{proof, witness}, + keccak::{ + column::KeccakColumns, + environment::KeccakEnv, + interpreter::KeccakInterpreter, + proof::{self as keccak_proof, KeccakProofInputs}, + }, + mips::{proof, witness as mips_witness}, preimage_oracle::PreImageOracle, }; use poly_commitment::pairing_proof::PairingProof; +use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, IntoParallelRefMutIterator}; use std::{fs::File, io::BufReader, process::ExitCode}; use kimchi_optimism::DOMAIN_SIZE; @@ -70,7 +77,7 @@ pub fn main() -> ExitCode { srs }; - let mut env = witness::Env::::create(cannon::PAGE_SIZE as usize, state, po); + let mut env = mips_witness::Env::::create(cannon::PAGE_SIZE as usize, state, po); let mut folded_witness = proof::ProofInputs::< ark_ec::short_weierstrass_jacobian::GroupAffine, @@ -94,6 +101,54 @@ pub fn main() -> ExitCode { error: Vec::with_capacity(domain_size), }; + // The keccak environment is extracted inside the loop + + let mut keccak_folded_witness = KeccakProofInputs::< + ark_ec::short_weierstrass_jacobian::GroupAffine, + >::default(); + + let keccak_reset_pre_folding_witness = + |keccak_columns: &mut KeccakColumns>>| { + // Resize without deallocating + keccak_columns.hash_index.clear(); + keccak_columns.step_index.clear(); + keccak_columns.flag_round.clear(); + keccak_columns.flag_absorb.clear(); + keccak_columns.flag_squeeze.clear(); + keccak_columns.flag_root.clear(); + keccak_columns.flag_pad.clear(); + keccak_columns.flag_length.clear(); + keccak_columns.two_to_pad.clear(); + keccak_columns.inverse_round.clear(); + keccak_columns.flags_bytes.iter_mut().for_each(Vec::clear); + keccak_columns.pad_suffix.iter_mut().for_each(Vec::clear); + keccak_columns + .round_constants + .iter_mut() + .for_each(Vec::clear); + keccak_columns.curr.iter_mut().for_each(Vec::clear); + keccak_columns.next.iter_mut().for_each(Vec::clear); + }; + + let mut keccak_current_pre_folding_witness: KeccakColumns>> = + KeccakColumns { + hash_index: Vec::with_capacity(domain_size), + step_index: Vec::with_capacity(domain_size), + flag_round: Vec::with_capacity(domain_size), + flag_absorb: Vec::with_capacity(domain_size), + flag_squeeze: Vec::with_capacity(domain_size), + flag_root: Vec::with_capacity(domain_size), + flag_pad: Vec::with_capacity(domain_size), + flag_length: Vec::with_capacity(domain_size), + two_to_pad: Vec::with_capacity(domain_size), + inverse_round: Vec::with_capacity(domain_size), + flags_bytes: std::array::from_fn(|_| Vec::with_capacity(domain_size)), + pad_suffix: std::array::from_fn(|_| Vec::with_capacity(domain_size)), + round_constants: std::array::from_fn(|_| Vec::with_capacity(domain_size)), + curr: std::array::from_fn(|_| Vec::with_capacity(domain_size)), + next: std::array::from_fn(|_| Vec::with_capacity(domain_size)), + }; + while !env.halt { env.step(&configuration, &meta, &start); @@ -104,6 +159,24 @@ pub fn main() -> ExitCode { } // TODO: update the witness with the Keccak step columns before resetting the environment + for (env_wit, pre_fold_wit) in keccak_env + .keccak_state + .into_iter() + .zip(keccak_current_pre_folding_witness.par_iter_mut()) + { + pre_fold_wit.push(env_wit); + } + + if keccak_current_pre_folding_witness.step_index.len() == DOMAIN_SIZE { + keccak_proof::fold::<_, OpeningProof, BaseSponge, ScalarSponge>( + domain, + &srs, + &mut keccak_folded_witness, + &keccak_current_pre_folding_witness, + ); + keccak_reset_pre_folding_witness(&mut keccak_current_pre_folding_witness); + } + // TODO: create READ lookup tables // When the Keccak interpreter is finished, we can reset the environment From 8fed2e3e46be0ad2ceb3a7d066c388f6198782f8 Mon Sep 17 00:00:00 2001 From: querolita Date: Mon, 22 Jan 2024 15:55:31 +0100 Subject: [PATCH 2/3] update witness with current step data --- optimism/src/main.rs | 72 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/optimism/src/main.rs b/optimism/src/main.rs index 43f92380af..13a060a00b 100644 --- a/optimism/src/main.rs +++ b/optimism/src/main.rs @@ -6,7 +6,6 @@ use kimchi_optimism::{ cannon_cli, keccak::{ column::KeccakColumns, - environment::KeccakEnv, interpreter::KeccakInterpreter, proof::{self as keccak_proof, KeccakProofInputs}, }, @@ -14,7 +13,6 @@ use kimchi_optimism::{ preimage_oracle::PreImageOracle, }; use poly_commitment::pairing_proof::PairingProof; -use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, IntoParallelRefMutIterator}; use std::{fs::File, io::BufReader, process::ExitCode}; use kimchi_optimism::DOMAIN_SIZE; @@ -158,13 +156,75 @@ pub fn main() -> ExitCode { keccak_env.step(); } - // TODO: update the witness with the Keccak step columns before resetting the environment + // Update the witness with the Keccak step columns before resetting the environment + keccak_current_pre_folding_witness + .hash_index + .push(keccak_env.keccak_witness.hash_index); + keccak_current_pre_folding_witness + .step_index + .push(keccak_env.keccak_witness.step_index); + keccak_current_pre_folding_witness + .flag_round + .push(keccak_env.keccak_witness.flag_round); + keccak_current_pre_folding_witness + .flag_absorb + .push(keccak_env.keccak_witness.flag_absorb); + keccak_current_pre_folding_witness + .flag_squeeze + .push(keccak_env.keccak_witness.flag_squeeze); + keccak_current_pre_folding_witness + .flag_root + .push(keccak_env.keccak_witness.flag_root); + keccak_current_pre_folding_witness + .flag_pad + .push(keccak_env.keccak_witness.flag_pad); + keccak_current_pre_folding_witness + .flag_length + .push(keccak_env.keccak_witness.flag_length); + keccak_current_pre_folding_witness + .two_to_pad + .push(keccak_env.keccak_witness.two_to_pad); + keccak_current_pre_folding_witness + .inverse_round + .push(keccak_env.keccak_witness.inverse_round); for (env_wit, pre_fold_wit) in keccak_env .keccak_witness - .into_iter() - .zip(keccak_current_pre_folding_witness.par_iter_mut()) + .flags_bytes + .iter() + .zip(keccak_current_pre_folding_witness.flags_bytes.iter_mut()) { - pre_fold_wit.push(env_wit); + pre_fold_wit.push(*env_wit); + } + for (env_wit, pre_fold_wit) in keccak_env + .keccak_witness + .pad_suffix + .iter() + .zip(keccak_current_pre_folding_witness.pad_suffix.iter_mut()) + { + pre_fold_wit.push(*env_wit); + } + for (env_wit, pre_fold_wit) in keccak_env.keccak_witness.round_constants.iter().zip( + keccak_current_pre_folding_witness + .round_constants + .iter_mut(), + ) { + pre_fold_wit.push(*env_wit); + } + for (env_wit, pre_fold_wit) in keccak_env + .keccak_witness + .curr + .iter() + .zip(keccak_current_pre_folding_witness.curr.iter_mut()) + { + pre_fold_wit.push(*env_wit); + } + for (env_wit, pre_fold_wit) in keccak_env + .keccak_witness + .next + .iter() + .zip(keccak_current_pre_folding_witness.next.iter_mut()) + { + pre_fold_wit.push(*env_wit); } if keccak_current_pre_folding_witness.step_index.len() == DOMAIN_SIZE { From 4d64c618122de748139b3a168a6dc057cc828dba Mon Sep 17 00:00:00 2001 From: querolita Date: Mon, 22 Jan 2024 15:58:50 +0100 Subject: [PATCH 3/3] add proof verification at the end --- optimism/src/main.rs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/optimism/src/main.rs b/optimism/src/main.rs index 13a060a00b..d53079f424 100644 --- a/optimism/src/main.rs +++ b/optimism/src/main.rs @@ -157,6 +157,7 @@ pub fn main() -> ExitCode { } // Update the witness with the Keccak step columns before resetting the environment + // TODO: simplify the contents of the KeccakColumns or create an iterator for it keccak_current_pre_folding_witness .hash_index .push(keccak_env.keccak_witness.hash_index); @@ -287,15 +288,36 @@ pub fn main() -> ExitCode { } { + // MIPS let proof = proof::prove::<_, OpeningProof, BaseSponge, ScalarSponge>(domain, &srs, folded_witness); println!("Generated a proof:\n{:?}", proof); let verifies = proof::verify::<_, OpeningProof, BaseSponge, ScalarSponge>(domain, &srs, &proof); if verifies { - println!("The proof verifies") + println!("The MIPS proof verifies") } else { - println!("The proof doesn't verify") + println!("The MIPS proof doesn't verify") + } + } + + { + // KECCAK + let keccak_proof = keccak_proof::prove::<_, OpeningProof, BaseSponge, ScalarSponge>( + domain, + &srs, + keccak_folded_witness, + ); + println!("Generated a proof:\n{:?}", keccak_proof); + let verifies = keccak_proof::verify::<_, OpeningProof, BaseSponge, ScalarSponge>( + domain, + &srs, + &keccak_proof, + ); + if verifies { + println!("The KECCAK proof verifies") + } else { + println!("The KECCAK proof doesn't verify") } }