diff --git a/.gitignore b/.gitignore
index 4f653b47..54acb129 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,8 +12,7 @@ Cargo.lock
**/proptest-regressions
/output.txt
flamegraph.svg
-**/*.trace
-**/*.memory
+dhat-heap.json
**/.DS_Store
**/*.swp
diff --git a/Cargo.toml b/Cargo.toml
index 84bc3f20..8acbd135 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -23,6 +23,7 @@ rayon = { version = "1.7.0", optional = true }
giza-core = { git = "https://github.com/lambdaclass/giza", branch = "remove_prints", optional = true }
giza-prover = { git = "https://github.com/lambdaclass/giza", branch = "remove_prints", optional = true }
giza-runner = { git = "https://github.com/lambdaclass/giza", branch = "remove_prints", optional = true }
+dhat = { version = "0.3.2", optional = true }
[dev-dependencies]
proptest = "1.2.0"
@@ -39,21 +40,23 @@ instruments = [] # This enables timing prints in prover and ve
metal = ["lambdaworks-math/metal"]
parallel = ["dep:rayon"]
giza = ["dep:giza-core", "dep:giza-prover", "dep:giza-runner"]
+heap_profiling = ["dep:dhat"]
[[bench]]
name = "criterion_prover"
harness = false
-metal = ["lambdaworks-math/metal"]
[[bench]]
name = "criterion_prover_70k"
harness = false
-metal = ["lambdaworks-math/metal"]
+
+[[bench]]
+name = "criterion_prover_security"
+harness = false
[[bench]]
name = "criterion_verifier"
harness = false
-metal = ["lambdaworks-math/metal"]
[[bench]]
name = "criterion_verifier_70k"
@@ -63,11 +66,24 @@ harness = false
name = "criterion_giza"
harness = false
+[[bench]]
+name = "criterion_verifier_security"
+harness = false
+
+[[bench]]
+name = "criterion_table"
+harness = false
+
+[[bench]]
+name = "dhat_prover"
+harness = false
+required-features = ["heap_profiling"]
[profile.release]
lto = true
opt-level = 3
codegen-units = 1
+debug = 1
[profile.test]
lto = "thin"
diff --git a/Makefile b/Makefile
index c60c63f9..981b783d 100644
--- a/Makefile
+++ b/Makefile
@@ -19,10 +19,10 @@ build:
cargo build --release
prove: build
- cargo run --release prove $(PROGRAM_PATH) $(PROOF_PATH)
+ cargo run --release prove $(PROGRAM_PATH) $(PROOF_PATH) -s
verify: build
- cargo run --release verify $(PROOF_PATH)
+ cargo run --release verify $(PROOF_PATH) -s
run_all: build
cargo run --release prove_and_verify $(PROGRAM_PATH)
@@ -43,12 +43,21 @@ clippy:
cargo clippy --workspace --all-targets -- -D warnings
benchmarks_sequential: $(COMPILED_CAIRO0_PROGRAMS)
- cargo bench
+ cargo bench --bench criterion_prover
+ cargo bench --bench criterion_verifier
benchmarks_parallel: $(COMPILED_CAIRO0_PROGRAMS)
cargo bench -F parallel --bench criterion_prover
cargo bench -F parallel --bench criterion_verifier
+benchmarks_security: $(COMPILED_CAIRO0_PROGRAMS)
+ cargo bench -F parallel --bench criterion_prover_security
+ cargo bench -F parallel --bench criterion_verifier_security
+
+benchmarks_table: $(COMPILED_CAIRO0_PROGRAMS)
+ cargo bench -F parallel --bench criterion_table
+ cargo bench --bench dhat_prover
+
benchmarks_parallel_all: $(COMPILED_CAIRO0_PROGRAMS)
cargo bench -F parallel
diff --git a/README.md b/README.md
index c4038daa..8b70f391 100644
--- a/README.md
+++ b/README.md
@@ -140,3 +140,138 @@ if you donĀ“t have the tools for fuzzing installed use
make fuzzer_tools
```
+## Benchmarks
+
+To get the results of the table below, run
+
+```
+make benchmarks_table
+```
+
+The results shown are from the execution of a Fibonacci program.
+
+Bits of security are used to ensure that the proof satisfies a certain conjuecturable security level.
+
+First table has the results that are independent of the hardware used.
+
+| n | Trace length | Prover RAM | Proof size 80 bit security | Proof size 128 bit security |
+|-----|--------------|------------|----------------------------|-----------------------------|
+| 100 | 2^10 | 18.5 MB | 270 KB | 476 KB |
+| 500 | 2^12 | 75.5 MB | 335 KB | 591 KB |
+| 2k | 2^14 | 302.1 MB | 407 KB | 719 KB |
+| 5k | 2^16 | 1.2 GB | 488 KB | 862 KB |
+| 20k | 2^18 | 4.7 GB | 576 KB | 1 MB |
+
+Second table has the results of the execution on an Apple M1 with 4 E and 4 P cores and 16 GB of RAM:
+
+
+
+ Trace length |
+ Trace time |
+ 80 bit security |
+ 128 bit security |
+
+
+ Prover time |
+ Verifier time |
+ Prover time |
+ Verifier time |
+
+
+ 2^10 |
+ 0.9 ms |
+ 1.1 s |
+ 3.1 ms |
+ 1.1 s |
+ 4.7 ms |
+
+
+ 2^12 |
+ 5.3 ms |
+ 335.5 ms |
+ 7.6 ms |
+ 336.4 ms |
+ 9.5 ms |
+
+
+ 2^14 |
+ 24.7 ms |
+ 1.41 s |
+ 26.4 ms |
+ 1.42 s |
+ 29 ms |
+
+
+ 2^16 |
+ 77.2 ms |
+ 5.8 s |
+ 108.8 ms |
+ 5.8 s |
+ 113.9 ms |
+
+
+ 2^18 |
+ 312 ms |
+ 24.3 s |
+ 477.4 ms |
+ 24.3 s |
+ 481.7 ms |
+
+
+
+Third table has the results of the execution on an Intel Xeon Platinum with 4 cores and 16 GB of RAM:
+
+
+
+ Trace length |
+ Trace time |
+ 80 bit security |
+ 128 bit security |
+
+
+ Prover time |
+ Verifier time |
+ Prover time |
+ Verifier time |
+
+
+ 2^10 |
+ 1.4 ms |
+ 2.5 s |
+ 6.3 ms |
+ 2.5 s |
+ 9.8 ms |
+
+
+ 2^12 |
+ 8 ms |
+ 709 ms |
+ 13.3 ms |
+ 710.5 ms |
+ 17.7 ms |
+
+
+ 2^14 |
+ 44.9 ms |
+ 3 s |
+ 41.1 ms |
+ 3 s |
+ 46.5 ms |
+
+
+ 2^16 |
+ 140.8 s |
+ 12.2 s |
+ 160.6 ms |
+ 12.2 s |
+ 168 ms |
+
+
+ 2^18 |
+ 700 ms |
+ 50.5 s |
+ 692.9 ms |
+ 50.5 s |
+ 702.6 ms |
+
+
diff --git a/benches/criterion_giza.rs b/benches/criterion_giza.rs
index 9160623a..307b4447 100644
--- a/benches/criterion_giza.rs
+++ b/benches/criterion_giza.rs
@@ -10,6 +10,8 @@ use lambdaworks_stark::{
starks::proof::options::{self, SecurityLevel},
};
#[cfg(feature = "giza")]
+pub mod criterion_utils;
+#[cfg(feature = "giza")]
pub mod functions;
#[cfg(not(feature = "giza"))]
diff --git a/benches/criterion_prover.rs b/benches/criterion_prover.rs
index 5842ea02..8b251909 100644
--- a/benches/criterion_prover.rs
+++ b/benches/criterion_prover.rs
@@ -1,14 +1,11 @@
use criterion::{
- black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion,
-};
-use lambdaworks_stark::{
- cairo::{
- air::generate_cairo_proof,
- runner::run::{generate_prover_args, CairoVersion},
- },
- starks::proof::options::{ProofOptions, SecurityLevel},
+ criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion,
};
+use criterion_utils::utils::run_cairo_bench_with_security_level;
+use functions::path::cairo0_program_path;
+use lambdaworks_stark::starks::proof::options::SecurityLevel;
+pub mod criterion_utils;
pub mod functions;
fn cairo_benches(c: &mut Criterion) {
@@ -39,25 +36,13 @@ fn cairo_benches(c: &mut Criterion) {
);
}
-fn cairo0_program_path(program_name: &str) -> String {
- const CARGO_DIR: &str = env!("CARGO_MANIFEST_DIR");
- const PROGRAM_BASE_REL_PATH: &str = "/cairo_programs/cairo0/";
- let program_base_path = CARGO_DIR.to_string() + PROGRAM_BASE_REL_PATH;
- program_base_path + program_name
-}
-
fn run_cairo_bench(group: &mut BenchmarkGroup<'_, WallTime>, benchname: &str, program_path: &str) {
- let program_content = std::fs::read(program_path).unwrap();
- let proof_options = ProofOptions::new_secure(SecurityLevel::Provable80Bits, 3);
- let (main_trace, pub_inputs) =
- generate_prover_args(&program_content, &CairoVersion::V0, &None).unwrap();
- println!("Generated main trace with {} rows", main_trace.n_rows());
-
- group.bench_function(benchname, |bench| {
- bench.iter(|| {
- black_box(generate_cairo_proof(&main_trace, &pub_inputs, &proof_options).unwrap())
- });
- });
+ run_cairo_bench_with_security_level(
+ group,
+ benchname,
+ program_path,
+ SecurityLevel::Conjecturable80Bits,
+ );
}
criterion_group!(benches, cairo_benches);
diff --git a/benches/criterion_prover_70k.rs b/benches/criterion_prover_70k.rs
index 63a8044f..839f46af 100644
--- a/benches/criterion_prover_70k.rs
+++ b/benches/criterion_prover_70k.rs
@@ -1,15 +1,11 @@
use criterion::{
- black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion,
- SamplingMode,
-};
-use lambdaworks_stark::{
- cairo::{
- air::generate_cairo_proof,
- runner::run::{generate_prover_args, CairoVersion},
- },
- starks::proof::options::{ProofOptions, SecurityLevel},
+ criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion, SamplingMode,
};
+use criterion_utils::utils::run_cairo_bench_with_security_level;
+use functions::path::cairo0_program_path;
+use lambdaworks_stark::starks::proof::options::SecurityLevel;
+pub mod criterion_utils;
pub mod functions;
fn fibo_70k_bench(c: &mut Criterion) {
@@ -36,24 +32,13 @@ fn fibo_70k_bench(c: &mut Criterion) {
);
}
-fn cairo0_program_path(program_name: &str) -> String {
- const CARGO_DIR: &str = env!("CARGO_MANIFEST_DIR");
- const PROGRAM_BASE_REL_PATH: &str = "/cairo_programs/cairo0/";
- let program_base_path = CARGO_DIR.to_string() + PROGRAM_BASE_REL_PATH;
- program_base_path + program_name
-}
-
fn run_cairo_bench(group: &mut BenchmarkGroup<'_, WallTime>, benchname: &str, program_path: &str) {
- let program_content = std::fs::read(program_path).unwrap();
- let proof_options = ProofOptions::new_secure(SecurityLevel::Provable80Bits, 3);
- let (main_trace, pub_inputs) =
- generate_prover_args(&program_content, &CairoVersion::V0, &None).unwrap();
-
- group.bench_function(benchname, |bench| {
- bench.iter(|| {
- black_box(generate_cairo_proof(&main_trace, &pub_inputs, &proof_options).unwrap())
- });
- });
+ run_cairo_bench_with_security_level(
+ group,
+ benchname,
+ program_path,
+ SecurityLevel::Provable128Bits,
+ );
}
criterion_group!(benches, fibo_70k_bench);
diff --git a/benches/criterion_prover_security.rs b/benches/criterion_prover_security.rs
new file mode 100644
index 00000000..d04ac152
--- /dev/null
+++ b/benches/criterion_prover_security.rs
@@ -0,0 +1,55 @@
+use criterion::{
+ criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion,
+};
+use criterion_utils::utils::run_cairo_bench_with_security_level;
+use functions::path::cairo0_program_path;
+use lambdaworks_stark::starks::proof::options::SecurityLevel;
+
+pub mod criterion_utils;
+pub mod functions;
+
+fn cairo_benches(c: &mut Criterion) {
+ #[cfg(feature = "parallel")]
+ {
+ let num_threads: usize = std::env::var("NUM_THREADS")
+ .unwrap_or("8".to_string())
+ .parse()
+ .unwrap();
+ println!("Running benchmarks using {} threads", num_threads);
+ rayon::ThreadPoolBuilder::new()
+ .num_threads(num_threads)
+ .build_global()
+ .unwrap();
+ };
+
+ let mut group = c.benchmark_group("CAIRO");
+ group.sample_size(10);
+ run_cairo_bench(
+ &mut group,
+ "fibonacci/500",
+ &cairo0_program_path("fibonacci_500.json"),
+ );
+ run_cairo_bench(
+ &mut group,
+ "fibonacci/1000",
+ &cairo0_program_path("fibonacci_1000.json"),
+ );
+}
+
+fn run_cairo_bench(group: &mut BenchmarkGroup<'_, WallTime>, benchname: &str, program_path: &str) {
+ run_cairo_bench_with_security_level(
+ group,
+ &format!("80_bits/{benchname}"),
+ program_path,
+ SecurityLevel::Conjecturable80Bits,
+ );
+ run_cairo_bench_with_security_level(
+ group,
+ &format!("128_bits/{benchname}"),
+ program_path,
+ SecurityLevel::Conjecturable128Bits,
+ );
+}
+
+criterion_group!(benches, cairo_benches);
+criterion_main!(benches);
diff --git a/benches/criterion_table.rs b/benches/criterion_table.rs
new file mode 100644
index 00000000..f01d92d0
--- /dev/null
+++ b/benches/criterion_table.rs
@@ -0,0 +1,101 @@
+use criterion::{
+ criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion,
+};
+use criterion_utils::utils::{
+ run_cairo_bench_and_measure_proof, run_trace_bench, run_verifier_bench_with_security_level,
+};
+use functions::path::{cairo0_program_path, cairo0_proof_path};
+use lambdaworks_stark::starks::proof::options::SecurityLevel;
+
+pub mod criterion_utils;
+pub mod functions;
+
+fn table_benches(c: &mut Criterion) {
+ #[cfg(feature = "parallel")]
+ {
+ let num_threads: usize = std::env::var("NUM_THREADS")
+ .unwrap_or("8".to_string())
+ .parse()
+ .unwrap();
+ println!("Running benchmarks using {} threads", num_threads);
+ rayon::ThreadPoolBuilder::new()
+ .num_threads(num_threads)
+ .build_global()
+ .unwrap();
+ };
+
+ let mut group = c.benchmark_group("TABLE");
+ group.sample_size(10);
+ run_table_bench(
+ &mut group,
+ "fibonacci/100",
+ &cairo0_program_path("fibonacci_100.json"),
+ &cairo0_proof_path("fibonacci_100.proof"),
+ &cairo0_proof_path("fibonacci_100_sec.proof"),
+ );
+ run_table_bench(
+ &mut group,
+ "fibonacci/500",
+ &cairo0_program_path("fibonacci_500.json"),
+ &cairo0_proof_path("fibonacci_500.proof"),
+ &cairo0_proof_path("fibonacci_500_sec.proof"),
+ );
+ run_table_bench(
+ &mut group,
+ "fibonacci/2000",
+ &cairo0_program_path("fibonacci_2000.json"),
+ &cairo0_proof_path("fibonacci_2000.proof"),
+ &cairo0_proof_path("fibonacci_2000_sec.proof"),
+ );
+ run_table_bench(
+ &mut group,
+ "fibonacci/5000",
+ &cairo0_program_path("fibonacci_5000.json"),
+ &cairo0_proof_path("fibonacci_5000.proof"),
+ &cairo0_proof_path("fibonacci_5000_sec.proof"),
+ );
+ run_table_bench(
+ &mut group,
+ "fibonacci/20000",
+ &cairo0_program_path("fibonacci_20000.json"),
+ &cairo0_proof_path("fibonacci_20000.proof"),
+ &cairo0_proof_path("fibonacci_20000_sec.proof"),
+ );
+}
+
+fn run_table_bench(
+ group: &mut BenchmarkGroup<'_, WallTime>,
+ benchname: &str,
+ program_path: &str,
+ proof_path: &str,
+ sec_proof_path: &str,
+) {
+ run_trace_bench(group, &format!("trace/{benchname}"), program_path);
+ run_cairo_bench_and_measure_proof(
+ group,
+ &format!("prover/80_bits/{benchname}"),
+ program_path,
+ SecurityLevel::Conjecturable80Bits,
+ );
+ run_verifier_bench_with_security_level(
+ group,
+ &format!("verifier/80_bits/{benchname}"),
+ proof_path,
+ SecurityLevel::Conjecturable80Bits,
+ );
+ run_cairo_bench_and_measure_proof(
+ group,
+ &format!("prover/128_bits/{benchname}"),
+ program_path,
+ SecurityLevel::Conjecturable128Bits,
+ );
+ run_verifier_bench_with_security_level(
+ group,
+ &format!("verifier/128_bits/{benchname}"),
+ sec_proof_path,
+ SecurityLevel::Conjecturable128Bits,
+ );
+}
+
+criterion_group!(benches, table_benches);
+criterion_main!(benches);
diff --git a/benches/criterion_utils/mod.rs b/benches/criterion_utils/mod.rs
new file mode 100644
index 00000000..b5614dd8
--- /dev/null
+++ b/benches/criterion_utils/mod.rs
@@ -0,0 +1 @@
+pub mod utils;
diff --git a/benches/criterion_utils/utils.rs b/benches/criterion_utils/utils.rs
new file mode 100644
index 00000000..ffdea9f2
--- /dev/null
+++ b/benches/criterion_utils/utils.rs
@@ -0,0 +1,118 @@
+use criterion::{black_box, measurement::WallTime, BenchmarkGroup};
+use lambdaworks_math::{
+ field::fields::fft_friendly::stark_252_prime_field::Stark252PrimeField,
+ traits::{Deserializable, Serializable},
+};
+use lambdaworks_stark::{
+ cairo::{
+ air::{generate_cairo_proof, verify_cairo_proof, PublicInputs},
+ cairo_layout::CairoLayout,
+ execution_trace::build_main_trace,
+ runner::run::{build_pub_inputs, run_program, CairoVersion},
+ },
+ starks::proof::{
+ options::{ProofOptions, SecurityLevel},
+ stark::StarkProof,
+ },
+};
+
+use crate::functions::stark::generate_prover_args_with_options;
+
+pub fn run_cairo_bench_with_security_level(
+ group: &mut BenchmarkGroup<'_, WallTime>,
+ benchname: &str,
+ program_path: &str,
+ security_level: SecurityLevel,
+) {
+ let (proof_options, main_trace, pub_inputs) =
+ generate_prover_args_with_options(program_path, security_level);
+
+ group.bench_function(benchname, |bench| {
+ bench.iter(|| {
+ black_box(generate_cairo_proof(&main_trace, &pub_inputs, &proof_options).unwrap())
+ });
+ });
+}
+
+pub fn run_cairo_bench_and_measure_proof(
+ group: &mut BenchmarkGroup<'_, WallTime>,
+ benchname: &str,
+ program_path: &str,
+ security_level: SecurityLevel,
+) {
+ let (proof_options, main_trace, pub_inputs) =
+ generate_prover_args_with_options(program_path, security_level);
+
+ let proof_size = generate_cairo_proof(&main_trace, &pub_inputs, &proof_options)
+ .unwrap()
+ .serialize()
+ .len();
+ println!("Proof size: {} bytes", proof_size);
+ println!("Trace length: {} rows", main_trace.n_rows());
+
+ group.bench_function(benchname, |bench| {
+ bench.iter(|| {
+ black_box(generate_cairo_proof(&main_trace, &pub_inputs, &proof_options).unwrap())
+ });
+ });
+}
+
+pub fn run_verifier_bench_with_security_level(
+ group: &mut BenchmarkGroup<'_, WallTime>,
+ benchname: &str,
+ program_path: &str,
+ security_level: SecurityLevel,
+) {
+ let (proof, pub_inputs) = load_proof_and_pub_inputs(program_path);
+ let proof_options = ProofOptions::new_secure(security_level, 3);
+ group.bench_function(benchname, |bench| {
+ bench.iter(|| {
+ black_box(assert!(verify_cairo_proof(
+ &proof,
+ &pub_inputs,
+ &proof_options
+ )))
+ });
+ });
+}
+
+fn load_proof_and_pub_inputs(input_path: &str) -> (StarkProof, PublicInputs) {
+ let program_content = std::fs::read(input_path).unwrap();
+ let mut bytes = program_content.as_slice();
+ let proof_len = usize::from_be_bytes(bytes[0..8].try_into().unwrap());
+ bytes = &bytes[8..];
+ let proof = StarkProof::::deserialize(&bytes[0..proof_len]).unwrap();
+ bytes = &bytes[proof_len..];
+
+ let public_inputs = PublicInputs::deserialize(bytes).unwrap();
+
+ (proof, public_inputs)
+}
+
+pub fn run_trace_bench(
+ group: &mut BenchmarkGroup<'_, WallTime>,
+ benchname: &str,
+ program_path: &str,
+) {
+ let program_content = std::fs::read(program_path).unwrap();
+
+ let (register_states, memory, program_size, range_check_builtin_range) = run_program(
+ None,
+ CairoLayout::Small,
+ &program_content,
+ &CairoVersion::V0,
+ )
+ .unwrap();
+
+ let mut pub_inputs = build_pub_inputs(
+ range_check_builtin_range,
+ &None,
+ ®ister_states,
+ &memory,
+ program_size,
+ );
+
+ group.bench_function(benchname, |bench| {
+ bench.iter(|| black_box(build_main_trace(®ister_states, &memory, &mut pub_inputs)));
+ });
+}
diff --git a/benches/criterion_verifier.rs b/benches/criterion_verifier.rs
index bb283a04..51d17a72 100644
--- a/benches/criterion_verifier.rs
+++ b/benches/criterion_verifier.rs
@@ -1,31 +1,13 @@
use criterion::{
- black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion,
+ criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion,
};
-use lambdaworks_math::{
- field::fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, traits::Deserializable,
-};
-use lambdaworks_stark::{
- cairo::air::{verify_cairo_proof, PublicInputs},
- starks::proof::{
- options::{ProofOptions, SecurityLevel},
- stark::StarkProof,
- },
-};
-
-pub mod functions;
-
-fn load_proof_and_pub_inputs(input_path: &str) -> (StarkProof, PublicInputs) {
- let program_content = std::fs::read(input_path).unwrap();
- let mut bytes = program_content.as_slice();
- let proof_len = usize::from_be_bytes(bytes[0..8].try_into().unwrap());
- bytes = &bytes[8..];
- let proof = StarkProof::::deserialize(&bytes[0..proof_len]).unwrap();
- bytes = &bytes[proof_len..];
+use criterion_utils::utils::run_verifier_bench_with_security_level;
+use functions::path::cairo0_proof_path;
- let public_inputs = PublicInputs::deserialize(bytes).unwrap();
+use lambdaworks_stark::starks::proof::options::SecurityLevel;
- (proof, public_inputs)
-}
+pub mod criterion_utils;
+pub mod functions;
fn verifier_benches(c: &mut Criterion) {
#[cfg(feature = "parallel")]
@@ -54,23 +36,17 @@ fn verifier_benches(c: &mut Criterion) {
);
}
-fn cairo0_proof_path(program_name: &str) -> String {
- const CARGO_DIR: &str = env!("CARGO_MANIFEST_DIR");
- const PROGRAM_BASE_REL_PATH: &str = "/benches/proofs/";
- let program_base_path = CARGO_DIR.to_string() + PROGRAM_BASE_REL_PATH;
- program_base_path + program_name
-}
-
fn run_verifier_bench(
group: &mut BenchmarkGroup<'_, WallTime>,
benchname: &str,
program_path: &str,
) {
- let (proof, pub_inputs) = load_proof_and_pub_inputs(program_path);
- let proof_options = ProofOptions::new_secure(SecurityLevel::Provable80Bits, 3);
- group.bench_function(benchname, |bench| {
- bench.iter(|| black_box(verify_cairo_proof(&proof, &pub_inputs, &proof_options)));
- });
+ run_verifier_bench_with_security_level(
+ group,
+ benchname,
+ program_path,
+ SecurityLevel::Conjecturable80Bits,
+ );
}
criterion_group!(benches, verifier_benches);
diff --git a/benches/criterion_verifier_70k.rs b/benches/criterion_verifier_70k.rs
index 12f3ccd5..63ad4196 100644
--- a/benches/criterion_verifier_70k.rs
+++ b/benches/criterion_verifier_70k.rs
@@ -1,32 +1,13 @@
use criterion::{
- black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion,
- SamplingMode,
+ criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion, SamplingMode,
};
-use lambdaworks_math::{
- field::fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, traits::Deserializable,
-};
-use lambdaworks_stark::{
- cairo::air::{verify_cairo_proof, PublicInputs},
- starks::proof::{
- options::{ProofOptions, SecurityLevel},
- stark::StarkProof,
- },
-};
-
-pub mod functions;
-
-fn load_proof_and_pub_inputs(input_path: &str) -> (StarkProof, PublicInputs) {
- let program_content = std::fs::read(input_path).unwrap();
- let mut bytes = program_content.as_slice();
- let proof_len = usize::from_be_bytes(bytes[0..8].try_into().unwrap());
- bytes = &bytes[8..];
- let proof = StarkProof::::deserialize(&bytes[0..proof_len]).unwrap();
- bytes = &bytes[proof_len..];
+use criterion_utils::utils::run_verifier_bench_with_security_level;
+use functions::path::cairo0_proof_path;
- let public_inputs = PublicInputs::deserialize(bytes).unwrap();
+use lambdaworks_stark::starks::proof::options::SecurityLevel;
- (proof, public_inputs)
-}
+pub mod criterion_utils;
+pub mod functions;
fn verifier_benches(c: &mut Criterion) {
#[cfg(feature = "parallel")]
@@ -48,27 +29,21 @@ fn verifier_benches(c: &mut Criterion) {
run_verifier_bench(
&mut group,
"fibonacci/70000",
- &cairo0_proof_path("fibonacci_70000.proof"),
+ &cairo0_proof_path("fibonacci_70000_sec.proof"),
);
}
-fn cairo0_proof_path(program_name: &str) -> String {
- const CARGO_DIR: &str = env!("CARGO_MANIFEST_DIR");
- const PROGRAM_BASE_REL_PATH: &str = "/benches/proofs/";
- let program_base_path = CARGO_DIR.to_string() + PROGRAM_BASE_REL_PATH;
- program_base_path + program_name
-}
-
fn run_verifier_bench(
group: &mut BenchmarkGroup<'_, WallTime>,
benchname: &str,
program_path: &str,
) {
- let (proof, pub_inputs) = load_proof_and_pub_inputs(program_path);
- let proof_options = ProofOptions::new_secure(SecurityLevel::Provable80Bits, 3);
- group.bench_function(benchname, |bench| {
- bench.iter(|| black_box(verify_cairo_proof(&proof, &pub_inputs, &proof_options)));
- });
+ run_verifier_bench_with_security_level(
+ group,
+ benchname,
+ program_path,
+ SecurityLevel::Conjecturable128Bits,
+ );
}
criterion_group!(benches, verifier_benches);
diff --git a/benches/criterion_verifier_security.rs b/benches/criterion_verifier_security.rs
new file mode 100644
index 00000000..7a6b327f
--- /dev/null
+++ b/benches/criterion_verifier_security.rs
@@ -0,0 +1,68 @@
+use criterion::{
+ criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion,
+};
+
+use criterion_utils::utils::run_verifier_bench_with_security_level;
+use lambdaworks_stark::starks::proof::options::SecurityLevel;
+
+pub mod criterion_utils;
+pub mod functions;
+
+fn verifier_benches(c: &mut Criterion) {
+ #[cfg(feature = "parallel")]
+ {
+ let num_threads: usize = std::env::var("NUM_THREADS")
+ .unwrap_or("8".to_string())
+ .parse()
+ .unwrap();
+ println!("Running benchmarks using {} threads", num_threads);
+ rayon::ThreadPoolBuilder::new()
+ .num_threads(num_threads)
+ .build_global()
+ .unwrap();
+ };
+
+ let mut group = c.benchmark_group("VERIFIER");
+ run_verifier_bench(
+ &mut group,
+ "fibonacci/500",
+ &cairo0_proof_path("fibonacci_500.proof"),
+ &cairo0_proof_path("fibonacci_500_sec.proof"),
+ );
+ run_verifier_bench(
+ &mut group,
+ "fibonacci/1000",
+ &cairo0_proof_path("fibonacci_1000.proof"),
+ &cairo0_proof_path("fibonacci_1000_sec.proof"),
+ );
+}
+
+fn cairo0_proof_path(program_name: &str) -> String {
+ const CARGO_DIR: &str = env!("CARGO_MANIFEST_DIR");
+ const PROGRAM_BASE_REL_PATH: &str = "/benches/proofs/";
+ let program_base_path = CARGO_DIR.to_string() + PROGRAM_BASE_REL_PATH;
+ program_base_path + program_name
+}
+
+fn run_verifier_bench(
+ group: &mut BenchmarkGroup<'_, WallTime>,
+ benchname: &str,
+ proof_path: &str,
+ sec_proof_path: &str,
+) {
+ run_verifier_bench_with_security_level(
+ group,
+ &format!("80_bits/{benchname}"),
+ proof_path,
+ SecurityLevel::Conjecturable80Bits,
+ );
+ run_verifier_bench_with_security_level(
+ group,
+ &format!("128_bits/{benchname}"),
+ sec_proof_path,
+ SecurityLevel::Conjecturable128Bits,
+ );
+}
+
+criterion_group!(benches, verifier_benches);
+criterion_main!(benches);
diff --git a/benches/dhat_prover.rs b/benches/dhat_prover.rs
new file mode 100644
index 00000000..8ef5b1be
--- /dev/null
+++ b/benches/dhat_prover.rs
@@ -0,0 +1,48 @@
+use functions::path::cairo0_program_path;
+use lambdaworks_stark::{cairo::air::generate_cairo_proof, starks::proof::options::SecurityLevel};
+
+use crate::functions::stark::generate_prover_args_with_options;
+
+pub mod functions;
+
+#[global_allocator]
+static ALLOC: dhat::Alloc = dhat::Alloc;
+
+pub fn main() {
+ let _profiler = dhat::Profiler::new_heap();
+ println!("\nMeasuring prover RAM usage\n");
+
+ run_prover(
+ &cairo0_program_path("fibonacci_100.json"),
+ SecurityLevel::Conjecturable80Bits,
+ );
+ run_prover(
+ &cairo0_program_path("fibonacci_500.json"),
+ SecurityLevel::Conjecturable80Bits,
+ );
+ run_prover(
+ &cairo0_program_path("fibonacci_2000.json"),
+ SecurityLevel::Conjecturable80Bits,
+ );
+ run_prover(
+ &cairo0_program_path("fibonacci_5000.json"),
+ SecurityLevel::Conjecturable80Bits,
+ );
+ run_prover(
+ &cairo0_program_path("fibonacci_20000.json"),
+ SecurityLevel::Conjecturable80Bits,
+ );
+}
+
+fn run_prover(program_path: &str, security_level: SecurityLevel) {
+ println!("Generating proof for {}", program_path);
+
+ let (proof_options, main_trace, pub_inputs) =
+ generate_prover_args_with_options(program_path, security_level);
+
+ let _proof_size = generate_cairo_proof(&main_trace, &pub_inputs, &proof_options);
+ println!(
+ "Prover RAM usage: {} bytes",
+ dhat::HeapStats::get().max_bytes
+ );
+}
diff --git a/benches/functions/mod.rs b/benches/functions/mod.rs
index c3514ea0..323c9dae 100644
--- a/benches/functions/mod.rs
+++ b/benches/functions/mod.rs
@@ -1,2 +1,2 @@
-pub mod cairo;
+pub mod path;
pub mod stark;
diff --git a/benches/functions/cairo.rs b/benches/functions/path.rs
similarity index 50%
rename from benches/functions/cairo.rs
rename to benches/functions/path.rs
index fe7e4f1e..4d570d43 100644
--- a/benches/functions/cairo.rs
+++ b/benches/functions/path.rs
@@ -4,3 +4,10 @@ pub fn cairo0_program_path(program_name: &str) -> String {
let program_base_path = CARGO_DIR.to_string() + PROGRAM_BASE_REL_PATH;
program_base_path + program_name
}
+
+pub fn cairo0_proof_path(program_name: &str) -> String {
+ const CARGO_DIR: &str = env!("CARGO_MANIFEST_DIR");
+ const PROGRAM_BASE_REL_PATH: &str = "/benches/proofs/";
+ let program_base_path = CARGO_DIR.to_string() + PROGRAM_BASE_REL_PATH;
+ program_base_path + program_name
+}
diff --git a/benches/functions/stark.rs b/benches/functions/stark.rs
index 0f475018..44437366 100644
--- a/benches/functions/stark.rs
+++ b/benches/functions/stark.rs
@@ -1,4 +1,16 @@
-use lambdaworks_stark::cairo::{cairo_mem::CairoMemory, register_states::RegisterStates};
+use lambdaworks_math::field::fields::fft_friendly::stark_252_prime_field::Stark252PrimeField;
+use lambdaworks_stark::{
+ cairo::{
+ air::PublicInputs,
+ cairo_mem::CairoMemory,
+ register_states::RegisterStates,
+ runner::run::{generate_prover_args, CairoVersion},
+ },
+ starks::{
+ proof::options::{ProofOptions, SecurityLevel},
+ trace::TraceTable,
+ },
+};
pub fn generate_cairo_trace(filename: &str) -> (RegisterStates, CairoMemory) {
let base_dir = env!("CARGO_MANIFEST_DIR").to_string() + "/src/cairo_vm/test_data/";
@@ -12,3 +24,14 @@ pub fn generate_cairo_trace(filename: &str) -> (RegisterStates, CairoMemory) {
(register_states, memory)
}
+
+pub fn generate_prover_args_with_options(
+ program_path: &str,
+ security_level: SecurityLevel,
+) -> (ProofOptions, TraceTable, PublicInputs) {
+ let program_content = std::fs::read(program_path).unwrap();
+ let proof_options = ProofOptions::new_secure(security_level, 3);
+ let (main_trace, pub_inputs) =
+ generate_prover_args(&program_content, &CairoVersion::V0, &None).unwrap();
+ (proof_options, main_trace, pub_inputs)
+}
diff --git a/benches/proofs/fibonacci_100.proof b/benches/proofs/fibonacci_100.proof
new file mode 100644
index 00000000..53426696
Binary files /dev/null and b/benches/proofs/fibonacci_100.proof differ
diff --git a/benches/proofs/fibonacci_1000.proof b/benches/proofs/fibonacci_1000.proof
index f2696069..94d7f60c 100644
Binary files a/benches/proofs/fibonacci_1000.proof and b/benches/proofs/fibonacci_1000.proof differ
diff --git a/benches/proofs/fibonacci_10000.proof b/benches/proofs/fibonacci_10000.proof
new file mode 100644
index 00000000..1b6d821d
Binary files /dev/null and b/benches/proofs/fibonacci_10000.proof differ
diff --git a/benches/proofs/fibonacci_1000_sec.proof b/benches/proofs/fibonacci_1000_sec.proof
new file mode 100644
index 00000000..59ea2961
Binary files /dev/null and b/benches/proofs/fibonacci_1000_sec.proof differ
diff --git a/benches/proofs/fibonacci_100_sec.proof b/benches/proofs/fibonacci_100_sec.proof
new file mode 100644
index 00000000..d5b15bc7
Binary files /dev/null and b/benches/proofs/fibonacci_100_sec.proof differ
diff --git a/benches/proofs/fibonacci_2000.proof b/benches/proofs/fibonacci_2000.proof
new file mode 100644
index 00000000..776cc0df
Binary files /dev/null and b/benches/proofs/fibonacci_2000.proof differ
diff --git a/benches/proofs/fibonacci_20000.proof b/benches/proofs/fibonacci_20000.proof
new file mode 100644
index 00000000..a625aa0f
Binary files /dev/null and b/benches/proofs/fibonacci_20000.proof differ
diff --git a/benches/proofs/fibonacci_20000_sec.proof b/benches/proofs/fibonacci_20000_sec.proof
new file mode 100644
index 00000000..0cf38bf7
Binary files /dev/null and b/benches/proofs/fibonacci_20000_sec.proof differ
diff --git a/benches/proofs/fibonacci_2000_sec.proof b/benches/proofs/fibonacci_2000_sec.proof
new file mode 100644
index 00000000..f4ce0de7
Binary files /dev/null and b/benches/proofs/fibonacci_2000_sec.proof differ
diff --git a/benches/proofs/fibonacci_500.proof b/benches/proofs/fibonacci_500.proof
index e934ef66..79ef3792 100644
Binary files a/benches/proofs/fibonacci_500.proof and b/benches/proofs/fibonacci_500.proof differ
diff --git a/benches/proofs/fibonacci_5000.proof b/benches/proofs/fibonacci_5000.proof
new file mode 100644
index 00000000..5a4b0799
Binary files /dev/null and b/benches/proofs/fibonacci_5000.proof differ
diff --git a/benches/proofs/fibonacci_5000_sec.proof b/benches/proofs/fibonacci_5000_sec.proof
new file mode 100644
index 00000000..293bf1db
Binary files /dev/null and b/benches/proofs/fibonacci_5000_sec.proof differ
diff --git a/benches/proofs/fibonacci_500_sec.proof b/benches/proofs/fibonacci_500_sec.proof
new file mode 100644
index 00000000..e1f7eca9
Binary files /dev/null and b/benches/proofs/fibonacci_500_sec.proof differ
diff --git a/benches/proofs/fibonacci_70000.proof b/benches/proofs/fibonacci_70000.proof
deleted file mode 100644
index 99813bb8..00000000
Binary files a/benches/proofs/fibonacci_70000.proof and /dev/null differ
diff --git a/benches/proofs/fibonacci_70000_sec.proof b/benches/proofs/fibonacci_70000_sec.proof
new file mode 100644
index 00000000..f2e71f6e
Binary files /dev/null and b/benches/proofs/fibonacci_70000_sec.proof differ
diff --git a/cairo_programs/cairo0/.gitignore b/cairo_programs/cairo0/.gitignore
index a6c57f5f..790706e7 100644
--- a/cairo_programs/cairo0/.gitignore
+++ b/cairo_programs/cairo0/.gitignore
@@ -1 +1,3 @@
*.json
+*.trace
+*.memory
diff --git a/cairo_programs/cairo0/fibonacci_2000.cairo b/cairo_programs/cairo0/fibonacci_2000.cairo
new file mode 100644
index 00000000..73e1c207
--- /dev/null
+++ b/cairo_programs/cairo0/fibonacci_2000.cairo
@@ -0,0 +1,19 @@
+func main() {
+ // Call fib(1, 1, 2000).
+ let result: felt = fib(1, 1, 2000);
+
+ // Make sure the 2000th Fibonacci number is 2488789449880543025993160600549605444069072274860741457936217360575764513035.
+ assert result = 2488789449880543025993160600549605444069072274860741457936217360575764513035;
+ ret;
+}
+
+func fib(first_element, second_element, n) -> (res: felt) {
+ jmp fib_body if n != 0;
+ tempvar result = second_element;
+ return (second_element,);
+
+ fib_body:
+ tempvar y = first_element + second_element;
+ return fib(second_element, y, n - 1);
+}
+
diff --git a/cairo_programs/cairo0/fibonacci_20000.cairo b/cairo_programs/cairo0/fibonacci_20000.cairo
new file mode 100644
index 00000000..cf10f9c9
--- /dev/null
+++ b/cairo_programs/cairo0/fibonacci_20000.cairo
@@ -0,0 +1,19 @@
+func main() {
+ // Call fib(1, 1, 20000).
+ let result: felt = fib(1, 1, 20000);
+
+ // Make sure the 20000th Fibonacci number is 2466807170979865163394825981097502788813037637400933247258687309819819983611.
+ assert result = 2466807170979865163394825981097502788813037637400933247258687309819819983611;
+ ret;
+}
+
+func fib(first_element, second_element, n) -> (res: felt) {
+ jmp fib_body if n != 0;
+ tempvar result = second_element;
+ return (second_element,);
+
+ fib_body:
+ tempvar y = first_element + second_element;
+ return fib(second_element, y, n - 1);
+}
+
diff --git a/cairo_programs/cairo0/fibonacci_5000.cairo b/cairo_programs/cairo0/fibonacci_5000.cairo
new file mode 100644
index 00000000..a36e4db8
--- /dev/null
+++ b/cairo_programs/cairo0/fibonacci_5000.cairo
@@ -0,0 +1,19 @@
+func main() {
+ // Call fib(1, 1, 5000).
+ let result: felt = fib(1, 1, 5000);
+
+ // Make sure the 5000th Fibonacci number is 529451847554265076639542422726571337094129671408026182306040934618673389596.
+ assert result = 529451847554265076639542422726571337094129671408026182306040934618673389596;
+ ret;
+}
+
+func fib(first_element, second_element, n) -> (res: felt) {
+ jmp fib_body if n != 0;
+ tempvar result = second_element;
+ return (second_element,);
+
+ fib_body:
+ tempvar y = first_element + second_element;
+ return fib(second_element, y, n - 1);
+}
+
diff --git a/cairo_programs/cairo1/.gitignore b/cairo_programs/cairo1/.gitignore
new file mode 100644
index 00000000..992dfe5a
--- /dev/null
+++ b/cairo_programs/cairo1/.gitignore
@@ -0,0 +1,2 @@
+*.json
+*.sierra
diff --git a/src/cairo/runner/run.rs b/src/cairo/runner/run.rs
index 22bfc5b0..a6e8e90a 100644
--- a/src/cairo/runner/run.rs
+++ b/src/cairo/runner/run.rs
@@ -252,16 +252,31 @@ pub fn generate_prover_args(
let (register_states, memory, program_size, range_check_builtin_range) =
run_program(None, cairo_layout, program_content, cairo_version)?;
- let memory_segments = create_memory_segment_map(range_check_builtin_range, output_range);
-
- let mut pub_inputs =
- PublicInputs::from_regs_and_mem(®ister_states, &memory, program_size, &memory_segments);
+ let mut pub_inputs = build_pub_inputs(
+ range_check_builtin_range,
+ output_range,
+ ®ister_states,
+ &memory,
+ program_size,
+ );
let main_trace = build_main_trace(®ister_states, &memory, &mut pub_inputs);
Ok((main_trace, pub_inputs))
}
+pub fn build_pub_inputs(
+ range_check_builtin_range: Option>,
+ output_range: &Option>,
+ register_states: &RegisterStates,
+ memory: &CairoMemory,
+ program_size: usize,
+) -> PublicInputs {
+ let memory_segments = create_memory_segment_map(range_check_builtin_range, output_range);
+
+ PublicInputs::from_regs_and_mem(register_states, memory, program_size, &memory_segments)
+}
+
fn create_memory_segment_map(
range_check_builtin_range: Option>,
output_range: &Option>,
diff --git a/src/main.rs b/src/main.rs
index 1f952024..87f92337 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,7 +2,7 @@ use lambdaworks_math::field::fields::fft_friendly::stark_252_prime_field::Stark2
use lambdaworks_math::traits::{Deserializable, Serializable};
use lambdaworks_stark::cairo::air::{generate_cairo_proof, verify_cairo_proof, PublicInputs};
use lambdaworks_stark::cairo::runner::run::{generate_prover_args, CairoVersion};
-use lambdaworks_stark::starks::proof::options::ProofOptions;
+use lambdaworks_stark::starks::proof::options::{ProofOptions, SecurityLevel};
use lambdaworks_stark::starks::proof::stark::StarkProof;
use std::env;
use std::time::Instant;
@@ -32,7 +32,8 @@ fn generate_proof(
return None;
};
- println!(" Time spent: {:?} \n", timer.elapsed());
+ println!(" Time spent: {:?}", timer.elapsed());
+ println!(" Generated main trace with {} rows\n", main_trace.n_rows());
let timer = Instant::now();
println!("Making proof ...");
@@ -44,7 +45,10 @@ fn generate_proof(
}
};
- println!("Time spent in proving: {:?} \n", timer.elapsed());
+ println!("Time spent in proving: {:?}", timer.elapsed());
+
+ let proof_size = proof.serialize().len();
+ println!("Proof size: {} bytes\n", proof_size);
Some((proof, pub_inputs))
}
@@ -69,9 +73,29 @@ fn verify_proof(
proof_verified
}
-fn main() {
- let proof_options = ProofOptions::default_test_options();
+fn get_proof_options(arg: Option<&String>) -> Option {
+ let default_coset_offset = ProofOptions::default_test_options().coset_offset;
+
+ match arg {
+ Some(arg) => {
+ if arg == "-s" {
+ println!("Using secure proof options");
+ Some(ProofOptions::new_secure(
+ SecurityLevel::Conjecturable128Bits,
+ default_coset_offset,
+ ))
+ } else {
+ None
+ }
+ }
+ None => Some(ProofOptions::new_secure(
+ SecurityLevel::Conjecturable80Bits,
+ default_coset_offset,
+ )),
+ }
+}
+fn main() {
let args: Vec = env::args().collect();
if args.len() < 2 {
@@ -84,12 +108,13 @@ fn main() {
match command.as_str() {
"prove" => {
if args.len() < 4 {
- println!("Usage: cargo run prove ");
+ println!("Usage: cargo run prove [-s]");
return;
}
let input_path = &args[2];
let output_path = &args[3];
+ let Some(proof_options) = get_proof_options(args.get(4)) else { return; };
let Some((proof, pub_inputs)) = generate_proof(input_path, &proof_options) else {
return;
@@ -109,11 +134,13 @@ fn main() {
}
"verify" => {
if args.len() < 3 {
- println!("Usage: cargo run verify ");
+ println!("Usage: cargo run verify [-s]");
return;
}
let input_path = &args[2];
+ let Some(proof_options) = get_proof_options(args.get(3)) else { return; };
+
let Ok(program_content) = std::fs::read(input_path) else {
println!("Error opening {input_path} file");
return;
@@ -144,11 +171,13 @@ fn main() {
}
"prove_and_verify" => {
if args.len() < 3 {
- println!("Usage: cargo run prove_and_verify ");
+ println!("Usage: cargo run prove_and_verify [-s]");
return;
}
let input_path = &args[2];
+ let Some(proof_options) = get_proof_options(args.get(3)) else { return; };
+
let Some((proof, pub_inputs)) = generate_proof(input_path, &proof_options) else {
return;
};