diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 8a478d5a9..85a72ed7d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -70,6 +70,11 @@ jobs:
nixdo nice cargo --version
nixdo nice cargo clippy --version
nixdo nice cargo clippy --locked -- -D warnings
+
+ - name: cargo-clippy (mozakvm)
+ working-directory: sdk
+ run: |
+ nixdo nice cargo clippy --locked --all-features -- -D warnings
- name: cargo-clippy (native, examples)
working-directory: examples
@@ -77,11 +82,6 @@ jobs:
ARCH_TRIPLE="$(nixdo rustc --verbose --version | grep host | awk '{ print $2; }')"
nixdo nice cargo clippy --locked --all-features --target ${ARCH_TRIPLE} -- -D warnings
- - name: cargo-clippy (mozakvm)
- working-directory: sdk
- run: |
- nixdo nice cargo clippy --locked --all-features -- -D warnings
-
- name: cargo-clippy (native)
working-directory: sdk
run: |
diff --git a/.gitignore b/.gitignore
index 709b92e1c..c7a0d9a48 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,3 +36,6 @@ riscv-testdata/testdata/*.i
# Temporary scripts
*tmp.sh
examples/*/out/
+
+# self program ids
+*self_prog_id.txt
diff --git a/Cargo.lock b/Cargo.lock
index ab2637316..fa525dc0a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -199,6 +199,10 @@ dependencies = [
"generic-array",
]
+[[package]]
+name = "build_scripts"
+version = "0.1.0"
+
[[package]]
name = "bumpalo"
version = "3.16.0"
@@ -935,6 +939,7 @@ dependencies = [
"clap-verbosity-flag",
"clap_derive",
"clio",
+ "criterion",
"env_logger",
"itertools 0.13.0",
"log",
diff --git a/Cargo.toml b/Cargo.toml
index da1b4bea9..675078bc0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,6 +17,7 @@
[workspace]
exclude = ["sdk"]
members = [
+ "build_scripts",
"circuits",
"cli",
"examples-builder",
diff --git a/build_scripts/Cargo.toml b/build_scripts/Cargo.toml
new file mode 100644
index 000000000..fed0705ab
--- /dev/null
+++ b/build_scripts/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+categories = ["cryptography"]
+description = "Build scripts for mozak examples"
+edition = "2021"
+keywords = ["crypto", "zero-knowledge", "vm"]
+license = "All rights reserved"
+name = "build_scripts"
+readme = "README.md"
+repository = "https://github.com/0xmozak/mozak-vm"
+version = "0.1.0"
diff --git a/build_scripts/src/lib.rs b/build_scripts/src/lib.rs
new file mode 100644
index 000000000..42c8820cb
--- /dev/null
+++ b/build_scripts/src/lib.rs
@@ -0,0 +1 @@
+pub mod self_prog_id;
diff --git a/build_scripts/src/self_prog_id.rs b/build_scripts/src/self_prog_id.rs
new file mode 100644
index 000000000..7161df111
--- /dev/null
+++ b/build_scripts/src/self_prog_id.rs
@@ -0,0 +1,46 @@
+use std::fs::File;
+use std::io;
+use std::io::Write;
+use std::path::Path;
+use std::process::Command;
+
+const CARGO_MANIFEST_DIR: &str = env!("CARGO_MANIFEST_DIR");
+/// dumps the `ProgramIdentifier` of the input ELF
+/// in a file `self_prog_id.txt` lying in same directory.
+/// Note that the `ProgramIdentifier` is represented as
+/// a string, for example,
+/// `MZK-8279ede6d0459962efe306b82d6036c08d6b9e66ad8d89d9e297c5222b3f4572`
+pub fn dump_self_prog_id(out_elf_name: &str) {
+ let cargo_manifest_dir_path = Path::new(CARGO_MANIFEST_DIR);
+ let out_dir =
+ cargo_manifest_dir_path.join("../examples/target/riscv32im-mozak-mozakvm-elf/release/");
+ let out_elf_path = out_dir.join(out_elf_name);
+ let out_elf_path_str = out_elf_path.to_str().unwrap();
+ let cli_dir = cargo_manifest_dir_path.join("../cli");
+
+ let args = vec!["run", "--release", "--", "self-prog-id", out_elf_path_str];
+
+ // execute the cli command `self-prog-id` on the ELF
+ let output = Command::new("cargo")
+ .args(args)
+ .current_dir(cli_dir)
+ .env_clear()
+ .envs(std::env::vars().filter(|x| !x.0.starts_with("CARGO_")))
+ .output()
+ .expect("can't find mozak-cli. Please run cargo build --release --bin mozak-cli from project root");
+
+ if !output.status.success() {
+ io::stdout().write_all(&output.stdout).unwrap();
+ io::stderr().write_all(&output.stderr).unwrap();
+ panic!("cargo run -- self-prog-id {out_elf_path_str} failed");
+ }
+
+ let self_prog_id = String::from_utf8(output.stdout).unwrap();
+ let self_prog_id = self_prog_id.trim();
+
+ // write `self_prog_id` to a file
+ let mut self_prog_id_file =
+ File::create("self_prog_id.txt").expect("failed to create self_prog_id.txt");
+ write!(self_prog_id_file, "{}", self_prog_id).expect("failed to write self_prog_id.txt");
+ println!("cargo:rerun-if-changed={}", out_elf_path_str);
+}
diff --git a/cli/Cargo.toml b/cli/Cargo.toml
index a0fe3028e..571dcbe4d 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -29,7 +29,7 @@ clio = { version = "0.3", features = ["clap-parse"] }
env_logger = "0.11"
itertools = "0.13"
log = "0.4"
-mozak-examples = { path = "../examples-builder", features = ["mozak-sort"] }
+mozak-examples = { path = "../examples-builder", features = ["mozak-sort"], optional = true }
plonky2 = { workspace = true, default-features = false }
plonky2_maybe_rayon = { workspace = true, default-features = false }
rkyv = { version = "=0.8.0-alpha.1", default-features = false, features = ["pointer_width_32", "alloc"] }
@@ -40,10 +40,13 @@ starky = { workspace = true, default-features = false }
tempfile = "3"
[dev-dependencies]
+# Only as a workaround to be able to control criterion's rayon feature and optional dependency.
+criterion = { workspace = true, default-features = false }
mozak-circuits = { path = "../circuits", features = ["test"] }
mozak-runner = { path = "../runner", features = ["test"] }
proptest = "1.4"
[features]
+bench = ["mozak-examples"]
default = []
-parallel = ["plonky2/parallel", "starky/parallel", "mozak-circuits/parallel"]
+parallel = ["plonky2/parallel", "starky/parallel", "mozak-circuits/parallel", "criterion/rayon"]
diff --git a/cli/src/lib.rs b/cli/src/lib.rs
index e9c8fbe43..7828ba3c6 100644
--- a/cli/src/lib.rs
+++ b/cli/src/lib.rs
@@ -1,3 +1,4 @@
+#[cfg(feature = "bench")]
pub mod cli_benches;
pub mod runner;
#[cfg(test)]
diff --git a/cli/src/main.rs b/cli/src/main.rs
index 3d1237aca..428c36a7c 100644
--- a/cli/src/main.rs
+++ b/cli/src/main.rs
@@ -26,6 +26,7 @@ use mozak_circuits::stark::utils::trace_rows_to_poly_values;
use mozak_circuits::stark::verifier::verify_proof;
use mozak_circuits::storage_device::generation::generate_call_tape_trace;
use mozak_circuits::test_utils::{prove_and_verify_mozak_stark, C, D, F, S};
+#[cfg(feature = "bench")]
use mozak_cli::cli_benches::benches::BenchArgs;
use mozak_cli::runner::{
deserialize_system_tape, get_self_prog_id, load_program, raw_tapes_from_system_tape,
@@ -60,8 +61,6 @@ pub struct RunArgs {
elf: Input,
#[arg(long)]
system_tape: Option,
- #[arg(long)]
- self_prog_id: String,
}
#[derive(Clone, Debug, Args)]
@@ -72,8 +71,6 @@ pub struct ProveArgs {
batch_proof: Option