Skip to content

[precompile] part2 integrate keccak precompile into e2e flow #980

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 34 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
f87d5b3
wip integration
hero78119 Jul 4, 2025
8052834
refactor keccak opcode and gkr iop interface
hero78119 Jul 7, 2025
3214d5f
simplify interface to only pass memory read/write expression to gkr-iop
hero78119 Jul 7, 2025
a9596e0
lookup keccak switch to unify circuit builder
hero78119 Jul 7, 2025
558fe58
wip
hero78119 Jul 8, 2025
f768108
wip
hero78119 Jul 8, 2025
e61de90
build + clippy pass
hero78119 Jul 8, 2025
45e98d8
fix namespace format
hero78119 Jul 8, 2025
fb08066
chores: fix runtime error
hero78119 Jul 8, 2025
ed03656
Add fixed_witness_group in ProtocolWitnessGenerator<E>
dreamATD Jul 2, 2025
9a39498
Fix according to the comments
dreamATD Jul 4, 2025
884626e
temporarily partial fix MerkleRootMismatch failed on verifier
hero78119 Jul 9, 2025
9dd5207
witness assignment
hero78119 Jul 9, 2025
a58c9a1
integrate gkr iop into main prover logic
hero78119 Jul 9, 2025
d488a47
chores: add gkr-iop proof and move rc to witiness
hero78119 Jul 10, 2025
a794995
add keccak bench
hero78119 Jul 10, 2025
aa72c7e
move proof size info before verify
hero78119 Jul 10, 2025
7b3fd66
benchmark 100 keccak
hero78119 Jul 10, 2025
46a1c05
chores: rename ceno_rt_keccak
hero78119 Jul 10, 2025
57dea65
fix verifier sigma logic
hero78119 Jul 10, 2025
58c26b3
refactor mock prover
hero78119 Jul 10, 2025
5eb65e0
fix padding formula
hero78119 Jul 10, 2025
af125ce
retain debug mechanism
hero78119 Jul 10, 2025
03127b5
clippy fix
hero78119 Jul 10, 2025
41efaf6
fix witness assignment across round; fix eq to structural witin
hero78119 Jul 11, 2025
99f3bc6
migrate precompile circuit to ceno_zkvm
hero78119 Jul 13, 2025
d9e114f
add structural witness to opcode circuit
hero78119 Jul 14, 2025
528bef0
clean debug log
hero78119 Jul 14, 2025
7eddec6
fix structural witin logic
hero78119 Jul 14, 2025
75ebf0b
define semantic equal in standard way
hero78119 Jul 15, 2025
cb278cc
clippy happy
hero78119 Jul 15, 2025
03aafe8
Merge branch 'master' into feat/gkr_iop_integration
hero78119 Jul 15, 2025
2bbcb92
retain structural_witness in layer witness to prepare for opcode comp…
hero78119 Jul 15, 2025
cd30ab1
align non_zero record order with ceno zkvm
hero78119 Jul 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ceno_cli/src/commands/common_args/ceno.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ impl CenoOptions {

fn run_elf_inner<
E: ExtensionField + LkMultiplicityKey,
PCS: PolynomialCommitmentScheme<E> + 'static,
PCS: PolynomialCommitmentScheme<E> + Serialize + 'static,
P: AsRef<Path>,
>(
options: &CenoOptions,
Expand Down
6 changes: 3 additions & 3 deletions ceno_host/tests/test_elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,13 +231,13 @@ fn test_hashing() -> Result<()> {
}

#[test]
fn test_ceno_rt_keccak() -> Result<()> {
let program_elf = ceno_examples::ceno_rt_keccak;
fn test_keccak_syscall() -> Result<()> {
let program_elf = ceno_examples::keccak_syscall;
let mut state = VMState::new_from_elf(unsafe_platform(), program_elf)?;
let steps = run(&mut state)?;

// Expect the program to have written successive states between Keccak permutations.
const ITERATIONS: usize = 4;
const ITERATIONS: usize = 100;
let keccak_outs = sample_keccak_f(ITERATIONS);

let all_messages = read_all_messages(&state);
Expand Down
14 changes: 14 additions & 0 deletions ceno_zkvm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ ceno_host = { path = "../ceno_host" }
either.workspace = true
ff_ext = { path = "../ff_ext" }
gkr_iop = { path = "../gkr_iop" }
keccakf = "0.1.2"
mpcs = { path = "../mpcs" }
multilinear_extensions = { version = "0", path = "../multilinear_extensions" }
p3.workspace = true
Expand All @@ -29,6 +30,7 @@ transcript = { path = "../transcript" }
witness = { path = "../witness" }

itertools.workspace = true
ndarray.workspace = true
num-traits.workspace = true
paste.workspace = true
poseidon.workspace = true
Expand Down Expand Up @@ -101,3 +103,15 @@ name = "quadratic_sorting"
[[bench]]
harness = false
name = "is_prime"

[[bench]]
harness = false
name = "keccak"

[[bench]]
harness = false
name = "bitwise_keccakf"

[[bench]]
harness = false
name = "lookup_keccakf"
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::time::Duration;

use ceno_zkvm::precompiles::{run_bitwise_keccakf, setup_bitwise_keccak_gkr_circuit};
use criterion::*;
use ff_ext::GoldilocksExt2;
use gkr_iop::precompiles::{run_bitwise_keccakf, setup_bitwise_keccak_gkr_circuit};
use itertools::Itertools;
use mpcs::BasefoldDefault;
use rand::{RngCore, SeedableRng};
Expand Down Expand Up @@ -36,7 +36,7 @@ fn keccak_f_fn(c: &mut Criterion) {

#[allow(clippy::unit_arg)]
run_bitwise_keccakf::<GoldilocksExt2, BasefoldDefault<GoldilocksExt2>>(
setup_bitwise_keccak_gkr_circuit(),
setup_bitwise_keccak_gkr_circuit().expect("setup circuit error"),
black_box(states),
false,
false,
Expand Down
107 changes: 107 additions & 0 deletions ceno_zkvm/benches/keccak.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
use std::time::Duration;

use ceno_emul::{Platform, Program};
use ceno_host::CenoStdin;
use ceno_zkvm::{
self,
e2e::{Checkpoint, Preset, run_e2e_with_checkpoint, setup_platform},
scheme::constants::MAX_NUM_VARIABLES,
};
mod alloc;
use criterion::*;

use ff_ext::GoldilocksExt2;
use mpcs::{BasefoldDefault, SecurityLevel};

criterion_group! {
name = keccak_prove_group;
config = Criterion::default().warm_up_time(Duration::from_millis(20000));
targets = keccak_prove,
}

criterion_main!(keccak_prove_group);

const NUM_SAMPLES: usize = 10;

type Pcs = BasefoldDefault<E>;
type E = GoldilocksExt2;

// Relevant init data for keccak run
fn setup() -> (Program, Platform) {
let stack_size = 32768;
let heap_size = 2097152;
let pub_io_size = 16;
let program = Program::load_elf(ceno_examples::keccak_syscall, u32::MAX).unwrap();
let platform = setup_platform(Preset::Ceno, &program, stack_size, heap_size, pub_io_size);
(program, platform)
}

fn keccak_prove(c: &mut Criterion) {
let (program, platform) = setup();
// retrive 1 << 20th keccak element >> max_steps
let mut hints = CenoStdin::default();
let _ = hints.write(&vec![1, 2, 3]);
let max_steps = usize::MAX;
// estimate proof size data first
// let result = run_e2e_with_checkpoint::<E, Pcs>(
// program.clone(),
// platform.clone(),
// &Vec::from(&hints),
// &[],
// max_steps,
// MAX_NUM_VARIABLES,
// SecurityLevel::default(),
// Checkpoint::Complete,
// );
// let proof = result.proof.expect("PrepSanityCheck do not provide proof");
// let vk = result.vk.expect("PrepSanityCheck do not provide verifier");

// println!("e2e proof {}", proof);
// let transcript = BasicTranscript::new(b"riscv");
// let verifier = ZKVMVerifier::<E, Pcs>::new(vk);
// assert!(
// verifier
// .verify_proof_halt(proof, transcript, false)
// .expect("verify proof return with error"),
// );
// println!();
// println!("max_steps = {}", max_steps);

// expand more input size once runtime is acceptable
let mut group = c.benchmark_group(format!("keccak_max_steps_{}", max_steps));
group.sample_size(NUM_SAMPLES);

// Benchmark the proving time
group.bench_function(
BenchmarkId::new("prove_keccak", format!("keccak_max_steps_{}", max_steps)),
|b| {
b.iter_custom(|iters| {
let mut time = Duration::new(0, 0);
for _ in 0..iters {
let result = run_e2e_with_checkpoint::<E, Pcs>(
program.clone(),
platform.clone(),
&Vec::from(&hints),
&[],
max_steps,
MAX_NUM_VARIABLES,
SecurityLevel::default(),
Checkpoint::PrepE2EProving,
);
let instant = std::time::Instant::now();
result.next_step();
let elapsed = instant.elapsed();
println!(
"Keccak::create_proof, max_steps = {}, time = {}",
max_steps,
elapsed.as_secs_f64()
);
time += elapsed;
}
time
});
},
);

group.finish();
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::time::Duration;

use ceno_zkvm::precompiles::{run_faster_keccakf, setup_lookup_keccak_gkr_circuit};
use criterion::*;
use ff_ext::GoldilocksExt2;
use gkr_iop::precompiles::{run_faster_keccakf, setup_lookup_keccak_gkr_circuit};

use itertools::Itertools;
use mpcs::BasefoldDefault;
Expand Down Expand Up @@ -38,7 +38,8 @@ fn keccak_f_fn(c: &mut Criterion) {

let instant = std::time::Instant::now();

let circuit = setup_lookup_keccak_gkr_circuit();
let circuit =
setup_lookup_keccak_gkr_circuit().expect("setup circuit error");
#[allow(clippy::unit_arg)]
let _ =
run_faster_keccakf::<GoldilocksExt2, BasefoldDefault<GoldilocksExt2>>(
Expand Down
4 changes: 2 additions & 2 deletions ceno_zkvm/benches/riscv_add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ const NUM_SAMPLES: usize = 10;
fn bench_add(c: &mut Criterion) {
type Pcs = BasefoldDefault<E>;
let mut zkvm_cs = ZKVMConstraintSystem::default();
let _ = zkvm_cs.register_opcode_circuit::<AddInstruction<E>>();
let config = zkvm_cs.register_opcode_circuit::<AddInstruction<E>>();
let mut zkvm_fixed_traces = ZKVMFixedTraces::default();
zkvm_fixed_traces.register_opcode_circuit::<AddInstruction<E>>(&zkvm_cs);
zkvm_fixed_traces.register_opcode_circuit::<AddInstruction<E>>(&zkvm_cs, &config);

let param = Pcs::setup(1 << MAX_NUM_VARIABLES, SecurityLevel::default()).unwrap();
let (pp, vp) = Pcs::trim(param, 1 << MAX_NUM_VARIABLES).unwrap();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use ceno_zkvm::precompiles::{run_bitwise_keccakf, setup_bitwise_keccak_gkr_circuit};
use clap::{Parser, command};
use ff_ext::GoldilocksExt2;
use gkr_iop::precompiles::{run_bitwise_keccakf, setup_bitwise_keccak_gkr_circuit};
use itertools::Itertools;
use mpcs::BasefoldDefault;
use rand::{RngCore, SeedableRng};
Expand Down Expand Up @@ -70,5 +70,10 @@ fn main() {
let states: Vec<[u64; 25]> = (0..num_instance)
.map(|_| std::array::from_fn(|_| rng.next_u64()))
.collect_vec();
run_bitwise_keccakf::<E, Pcs>(setup_bitwise_keccak_gkr_circuit(), states, false, false);
run_bitwise_keccakf::<E, Pcs>(
setup_bitwise_keccak_gkr_circuit().expect("setup circuit error"),
states,
false,
false,
);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use ceno_zkvm::precompiles::{run_faster_keccakf, setup_lookup_keccak_gkr_circuit};
use clap::{Parser, command};
use ff_ext::GoldilocksExt2;
use gkr_iop::precompiles::{run_faster_keccakf, setup_lookup_keccak_gkr_circuit};
use itertools::Itertools;
use mpcs::BasefoldDefault;
use rand::{RngCore, SeedableRng};
Expand Down Expand Up @@ -71,7 +71,12 @@ fn main() {
.map(|_| std::array::from_fn(|_| rng.next_u64()))
.collect_vec();
let circuit_setup = setup_lookup_keccak_gkr_circuit();
let proof =
run_faster_keccakf::<E, Pcs>(circuit_setup, states, true, true).expect("generate proof");
let proof = run_faster_keccakf::<E, Pcs>(
circuit_setup.expect("setup circuit error"),
states,
true,
true,
)
.expect("generate proof");
tracing::info!("lookup keccak proof stat: {}", proof);
}
Loading
Loading