diff --git a/.github/workflows/bench-deploy.yml b/.github/workflows/bench-deploy.yml index 2e0b68dd1e..0f760a3d5e 100644 --- a/.github/workflows/bench-deploy.yml +++ b/.github/workflows/bench-deploy.yml @@ -35,7 +35,7 @@ jobs: - name: Install criterion run: cargo install cargo-criterion - name: Run benchmarks - run: just --dotenv-filename bench.env gpu-bench fibonacci_lem + run: just --dotenv-filename bench.env gpu-bench fibonacci working-directory: ${{ github.workspace }}/benches # TODO: Prettify labels for easier viewing # Compress the benchmark file and metadata for later analysis diff --git a/.github/workflows/bench-pr-comment.yml b/.github/workflows/bench-pr-comment.yml index 8078cb662c..4a63bd79cb 100644 --- a/.github/workflows/bench-pr-comment.yml +++ b/.github/workflows/bench-pr-comment.yml @@ -35,7 +35,7 @@ jobs: - uses: boa-dev/criterion-compare-action@v3 with: # Optional. Compare only this benchmark target - benchName: "fibonacci_lem" + benchName: "fibonacci" # Needed. The name of the branch to compare with branchName: ${{ github.ref_name }} @@ -83,7 +83,7 @@ jobs: - uses: boa-dev/criterion-compare-action@v3 with: # Optional. Compare only this benchmark target - benchName: "fibonacci_lem" + benchName: "fibonacci" # Optional. Features activated in the benchmark features: "cuda" # Needed. The name of the branch to compare with diff --git a/.github/workflows/merge-tests.yml b/.github/workflows/merge-tests.yml index 975bac6294..b48e79c36c 100644 --- a/.github/workflows/merge-tests.yml +++ b/.github/workflows/merge-tests.yml @@ -102,7 +102,7 @@ jobs: run: echo "BASE_REF=$(git rev-parse HEAD)" | tee -a $GITHUB_ENV working-directory: ${{ github.workspace }}/master - name: Run GPU bench on base branch - run: just --dotenv-filename bench.env gpu-bench fibonacci_lem + run: just --dotenv-filename bench.env gpu-bench fibonacci working-directory: ${{ github.workspace }}/master/benches - name: Copy bench output to PR branch run: | @@ -110,7 +110,7 @@ jobs: cp -r master/target/criterion target cp master/${{ env.BASE_REF }}.json . - name: Run GPU bench on PR branch - run: just --dotenv-filename bench.env gpu-bench fibonacci_lem + run: just --dotenv-filename bench.env gpu-bench fibonacci working-directory: ${{ github.workspace }}/benches # Create a `criterion-table` and write in commit comment - name: Run `criterion-table` diff --git a/Cargo.toml b/Cargo.toml index c1010eb136..113c46023d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -167,34 +167,18 @@ debug-assertions = false name = "end2end" harness = false -[[bench]] -name = "end2end_lem" -harness = false - [[bench]] name = "fibonacci" harness = false -[[bench]] -name = "fibonacci_lem" -harness = false - [[bench]] name = "synthesis" harness = false -[[bench]] -name = "synthesis_lem" -harness = false - [[bench]] name = "sha256" harness = false -[[bench]] -name = "sha256_lem" -harness = false - [[bench]] name = "public_params" harness = false diff --git a/benches/end2end.rs b/benches/end2end.rs index 2c10459093..c4e2956d4f 100644 --- a/benches/end2end.rs +++ b/benches/end2end.rs @@ -1,28 +1,26 @@ use criterion::{ black_box, criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion, SamplingMode, }; +use pasta_curves::pallas::Scalar as Fr; use pasta_curves::pallas::Scalar as Fq; +use std::{cell::RefCell, rc::Rc, sync::Arc, time::Duration}; use lurk::{ - circuit::circuit_frame::MultiFrame, - eval::{ - empty_sym_env, - lang::{Coproc, Lang}, - Evaluator, - }, + eval::lang::{Coproc, Lang}, field::LurkField, - proof::Prover, - proof::{nova::NovaProver, MultiFrameTrait}, - ptr::Ptr, + lem::{ + eval::{evaluate, evaluate_simple}, + multiframe::MultiFrame, + pointers::Ptr, + store::Store, + }, + proof::{nova::NovaProver, Prover}, public_parameters::{ self, instance::{Instance, Kind}, }, state::State, - store::Store, }; -use std::time::Duration; -use std::{cell::RefCell, rc::Rc, sync::Arc}; mod common; use common::set_bench_config; @@ -45,7 +43,7 @@ fn go_base(store: &Store, state: Rc>, a: u64, b: "# ); - store.read_with_state(state, &program).unwrap() + store.read(state, &program).unwrap() } /// To run these benchmarks, do `cargo criterion end2end_benchmark`. @@ -60,14 +58,15 @@ fn end2end_benchmark(c: &mut Criterion) { set_bench_config(); let limit = 1_000_000_000; - let lang_pallas = Lang::>::new(); - let lang_pallas_rc = Arc::new(lang_pallas.clone()); let reduction_count = DEFAULT_REDUCTION_COUNT; // setup + let lang_pallas = Lang::>::new(); + let lang_pallas_rc = Arc::new(lang_pallas.clone()); + let store = Store::default(); - let env = empty_sym_env(&store); - let prover = NovaProver::new(reduction_count, lang_pallas); + let prover: NovaProver<'_, Fq, Coproc, MultiFrame<'_, Fq, Coproc>> = + NovaProver::new(reduction_count, (*lang_pallas_rc).clone()); // use cached public params let instance = Instance::new( @@ -86,9 +85,8 @@ fn end2end_benchmark(c: &mut Criterion) { group.bench_with_input(benchmark_id, &size, |b, &s| { b.iter(|| { let ptr = go_base::(&store, state.clone(), s.0, s.1); - let _result = prover - .evaluate_and_prove(&pp, ptr, env, &store, limit, &lang_pallas_rc) - .unwrap(); + let (frames, _) = evaluate::>(None, ptr, &store, limit).unwrap(); + let _result = prover.prove(&pp, &frames, &store, &lang_pallas_rc).unwrap(); }) }); @@ -104,15 +102,24 @@ fn store_benchmark(c: &mut Criterion) { .measurement_time(Duration::from_secs(5)) .sample_size(60); + let bls12_store = Store::::default(); let pallas_store = Store::::default(); let state = State::init_lurk_state().rccell(); // todo!() rfc out into more flexible test cases - let sizes = vec![(10, 16), (10, 160)]; + let sizes = [(10, 16), (10, 160)]; for size in sizes { let parameter_string = format!("_{}_{}", size.0, size.1); + let bls12_id = BenchmarkId::new("store_go_base_bls12", ¶meter_string); + group.bench_with_input(bls12_id, &size, |b, &s| { + b.iter(|| { + let result = go_base::(&bls12_store, state.clone(), s.0, s.1); + black_box(result) + }) + }); + let pasta_id = BenchmarkId::new("store_go_base_pallas", ¶meter_string); group.bench_with_input(pasta_id, &size, |b, &s| { b.iter(|| { @@ -134,20 +141,29 @@ fn hydration_benchmark(c: &mut Criterion) { .measurement_time(Duration::from_secs(5)) .sample_size(60); + let bls12_store = Store::::default(); let pallas_store = Store::::default(); let state = State::init_lurk_state().rccell(); // todo!() rfc out into more flexible test cases - let sizes = vec![(10, 16), (10, 160)]; + let sizes = [(10, 16), (10, 160)]; for size in sizes { let parameter_string = format!("_{}_{}", size.0, size.1); + { + let benchmark_id = BenchmarkId::new("hydration_go_base_bls12", ¶meter_string); + group.bench_with_input(benchmark_id, &size, |b, &s| { + let _ptr = go_base::(&bls12_store, state.clone(), s.0, s.1); + b.iter(|| bls12_store.hydrate_z_cache()) + }); + } + { let benchmark_id = BenchmarkId::new("hydration_go_base_pallas", ¶meter_string); group.bench_with_input(benchmark_id, &size, |b, &s| { let _ptr = go_base::(&pallas_store, state.clone(), s.0, s.1); - b.iter(|| pallas_store.hydrate_scalar_cache()) + b.iter(|| pallas_store.hydrate_z_cache()) }); } } @@ -165,30 +181,29 @@ fn eval_benchmark(c: &mut Criterion) { .sample_size(60); let limit = 1_000_000_000; - let lang_pallas = Lang::>::new(); - let pallas_store = Store::::default(); + let bls12_store = Store::default(); + let pallas_store = Store::default(); let state = State::init_lurk_state().rccell(); // todo!() rfc out into more flexible test cases - let sizes = vec![(10, 16), (10, 160)]; + let sizes = [(10, 16), (10, 160)]; for size in sizes { let parameter_string = format!("_{}_{}", size.0, size.1); + { + let benchmark_id = BenchmarkId::new("eval_go_base_bls12", ¶meter_string); + group.bench_with_input(benchmark_id, &size, |b, &s| { + let ptr = go_base::(&bls12_store, state.clone(), s.0, s.1); + b.iter(|| evaluate_simple::>(None, ptr, &bls12_store, limit)) + }); + } + { let benchmark_id = BenchmarkId::new("eval_go_base_pallas", ¶meter_string); group.bench_with_input(benchmark_id, &size, |b, &s| { let ptr = go_base::(&pallas_store, state.clone(), s.0, s.1); - b.iter(|| { - Evaluator::new( - ptr, - empty_sym_env(&pallas_store), - &pallas_store, - limit, - &lang_pallas, - ) - .eval() - }) + b.iter(|| evaluate_simple::>(None, ptr, &pallas_store, limit)) }); } } @@ -204,15 +219,15 @@ fn eval_benchmark(c: &mut Criterion) { // let limit = 1_000_000_000; // let _lang_bls = Lang::>::new(); -// let _lang_pallas = Lang::>::new(); -// let lang_pallas = Lang::>::new(); +// let _lang_pallas = Lang::>::new(); +// let lang_pallas = Lang::>::new(); // let reduction_count = DEFAULT_REDUCTION_COUNT; // group.bench_function("circuit_generation_go_base_10_16_nova", |b| { // let mut store = Store::default(); // let env = empty_sym_env(&store); -// let ptr = go_base::(&mut store, black_box(10), black_box(16)); +// let ptr = go_base::(&mut store, black_box(10), black_box(16)); // let prover = NovaProver::new(reduction_count, lang_pallas.clone()); // let pp = public_parameters::public_params(reduction_count).unwrap(); @@ -241,16 +256,18 @@ fn prove_benchmark(c: &mut Criterion) { set_bench_config(); let limit = 1_000_000_000; - let lang_pallas = Lang::>::new(); - let lang_pallas_rc = Arc::new(lang_pallas.clone()); - let store = Store::default(); let reduction_count = DEFAULT_REDUCTION_COUNT; + let store = Store::default(); + let size = (10, 0); let benchmark_id = BenchmarkId::new("prove_go_base_nova", format!("_{}_{}", size.0, size.1)); let state = State::init_lurk_state().rccell(); + let lang_pallas = Lang::>::new(); + let lang_pallas_rc = Arc::new(lang_pallas.clone()); + // use cached public params let instance = Instance::new( reduction_count, @@ -262,16 +279,9 @@ fn prove_benchmark(c: &mut Criterion) { group.bench_with_input(benchmark_id, &size, |b, &s| { let ptr = go_base::(&store, state.clone(), s.0, s.1); - let prover = NovaProver::new(reduction_count, lang_pallas.clone()); - let frames = MultiFrame::get_evaluation_frames( - |count| prover.needs_frame_padding(count), - ptr, - empty_sym_env(&store), - &store, - limit, - &lang_pallas, - ) - .unwrap(); + let prover: NovaProver<'_, Fq, Coproc, MultiFrame<'_, Fq, Coproc>> = + NovaProver::new(reduction_count, Lang::new()); + let (frames, _) = evaluate::>(None, ptr, &store, limit).unwrap(); b.iter(|| { let result = prover.prove(&pp, &frames, &store, &lang_pallas_rc).unwrap(); @@ -292,8 +302,6 @@ fn prove_compressed_benchmark(c: &mut Criterion) { set_bench_config(); let limit = 1_000_000_000; - let lang_pallas = Lang::>::new(); - let lang_pallas_rc = Arc::new(lang_pallas.clone()); let store = Store::default(); let reduction_count = DEFAULT_REDUCTION_COUNT; @@ -305,6 +313,9 @@ fn prove_compressed_benchmark(c: &mut Criterion) { let state = State::init_lurk_state().rccell(); + let lang_pallas = Lang::>::new(); + let lang_pallas_rc = Arc::new(lang_pallas.clone()); + // use cached public params let instance = Instance::new( reduction_count, @@ -316,16 +327,8 @@ fn prove_compressed_benchmark(c: &mut Criterion) { group.bench_with_input(benchmark_id, &size, |b, &s| { let ptr = go_base::(&store, state.clone(), s.0, s.1); - let prover = NovaProver::new(reduction_count, lang_pallas.clone()); - let frames = prover - .get_evaluation_frames( - ptr, - empty_sym_env(&store), - &store, - limit, - lang_pallas_rc.clone(), - ) - .unwrap(); + let prover = NovaProver::new(reduction_count, Lang::new()); + let (frames, _) = evaluate::>(None, ptr, &store, limit).unwrap(); b.iter(|| { let (proof, _, _, _) = prover.prove(&pp, &frames, &store, &lang_pallas_rc).unwrap(); @@ -347,13 +350,14 @@ fn verify_benchmark(c: &mut Criterion) { set_bench_config(); let limit = 1_000_000_000; - let lang_pallas = Lang::>::new(); - let lang_pallas_rc = Arc::new(lang_pallas.clone()); let store = Store::default(); let reduction_count = DEFAULT_REDUCTION_COUNT; let state = State::init_lurk_state().rccell(); + let lang_pallas = Lang::>::new(); + let lang_pallas_rc = Arc::new(lang_pallas.clone()); + // use cached public params let instance = Instance::new( reduction_count, @@ -363,25 +367,16 @@ fn verify_benchmark(c: &mut Criterion) { ); let pp = public_parameters::public_params::<_, _, MultiFrame<'_, _, _>>(&instance).unwrap(); - let sizes = vec![(10, 0)]; + let sizes = [(10, 0)]; for size in sizes { let parameter_string = format!("_{}_{}", size.0, size.1); let benchmark_id = BenchmarkId::new("verify_go_base_nova", ¶meter_string); group.bench_with_input(benchmark_id, &size, |b, &s| { let ptr = go_base(&store, state.clone(), s.0, s.1); - let prover = NovaProver::new(reduction_count, lang_pallas.clone()); - let frames = prover - .get_evaluation_frames( - ptr, - empty_sym_env(&store), - &store, - limit, - lang_pallas_rc.clone(), - ) - .unwrap(); - let (proof, z0, zi, num_steps) = prover - .prove(&pp, &frames, &store, &lang_pallas_rc.clone()) - .unwrap(); + let prover = NovaProver::new(reduction_count, Lang::new()); + let (frames, _) = evaluate::>(None, ptr, &store, limit).unwrap(); + let (proof, z0, zi, num_steps) = + prover.prove(&pp, &frames, &store, &lang_pallas_rc).unwrap(); b.iter_batched( || z0.clone(), @@ -408,13 +403,14 @@ fn verify_compressed_benchmark(c: &mut Criterion) { set_bench_config(); let limit = 1_000_000_000; - let lang_pallas = Lang::>::new(); - let lang_pallas_rc = Arc::new(lang_pallas.clone()); let store = Store::default(); let reduction_count = DEFAULT_REDUCTION_COUNT; let state = State::init_lurk_state().rccell(); + let lang_pallas = Lang::>::new(); + let lang_pallas_rc = Arc::new(lang_pallas.clone()); + // use cached public params let instance = Instance::new( reduction_count, @@ -424,22 +420,14 @@ fn verify_compressed_benchmark(c: &mut Criterion) { ); let pp = public_parameters::public_params::<_, _, MultiFrame<'_, _, _>>(&instance).unwrap(); - let sizes = vec![(10, 0)]; + let sizes = [(10, 0)]; for size in sizes { let parameter_string = format!("_{}_{}", size.0, size.1); let benchmark_id = BenchmarkId::new("verify_compressed_go_base_nova", ¶meter_string); group.bench_with_input(benchmark_id, &size, |b, &s| { let ptr = go_base(&store, state.clone(), s.0, s.1); - let prover = NovaProver::new(reduction_count, lang_pallas.clone()); - let frames = prover - .get_evaluation_frames( - ptr, - empty_sym_env(&store), - &store, - limit, - lang_pallas_rc.clone(), - ) - .unwrap(); + let prover = NovaProver::new(reduction_count, Lang::new()); + let (frames, _) = evaluate::>(None, ptr, &store, limit).unwrap(); let (proof, z0, zi, num_steps) = prover.prove(&pp, &frames, &store, &lang_pallas_rc).unwrap(); @@ -472,7 +460,6 @@ cfg_if::cfg_if! { criterion_group! { name = benches; config = Criterion::default() - .with_profiler(pprof::criterion::PProfProfiler::new(100, pprof::criterion::Output::Flamegraph(None))); targets = end2end_benchmark, diff --git a/benches/end2end_lem.rs b/benches/end2end_lem.rs deleted file mode 100644 index 4a7d4cf804..0000000000 --- a/benches/end2end_lem.rs +++ /dev/null @@ -1,497 +0,0 @@ -use criterion::{ - black_box, criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion, SamplingMode, -}; -use pasta_curves::pallas::Scalar as Fr; -use pasta_curves::pallas::Scalar as Fq; -use std::{cell::RefCell, rc::Rc, sync::Arc, time::Duration}; - -use lurk::{ - eval::lang::{Coproc, Lang}, - field::LurkField, - lem::{ - eval::{evaluate, evaluate_simple}, - multiframe::MultiFrame, - pointers::Ptr, - store::Store, - }, - proof::{nova::NovaProver, Prover}, - public_parameters::{ - self, - instance::{Instance, Kind}, - }, - state::State, -}; - -mod common; -use common::set_bench_config; - -const DEFAULT_REDUCTION_COUNT: usize = 10; - -fn go_base(store: &Store, state: Rc>, a: u64, b: u64) -> Ptr { - let program = format!( - r#" -(let ((foo (lambda (a b) - (letrec ((aux (lambda (i a x) - (if (= i b) - x - (let ((x (+ x a)) - (a (+ a (* b 2)))) - (aux (+ i 1) a x)))))) - (let ((x (+ (* a b) 4))) - (aux 0 a x)))))) - (foo {a} {b})) -"# - ); - - store.read(state, &program).unwrap() -} - -/// To run these benchmarks, do `cargo criterion end2end_benchmark_lem`. -/// For flamegraphs, run: -/// ```cargo criterion end2end_benchmark_lem --features flamegraph -- --profile-time ``` -fn end2end_benchmark_lem(c: &mut Criterion) { - let mut group = c.benchmark_group("end2end_benchmark"); - group - .sampling_mode(SamplingMode::Flat) - .measurement_time(Duration::from_secs(120)) - .sample_size(10); - - set_bench_config(); - let limit = 1_000_000_000; - let reduction_count = DEFAULT_REDUCTION_COUNT; - - // setup - let lang_pallas = Lang::>::new(); - let lang_pallas_rc = Arc::new(lang_pallas.clone()); - - let store = Store::default(); - let prover: NovaProver<'_, Fq, Coproc, MultiFrame<'_, Fq, Coproc>> = - NovaProver::new(reduction_count, (*lang_pallas_rc).clone()); - - // use cached public params - let instance = Instance::new( - reduction_count, - lang_pallas_rc.clone(), - true, - Kind::NovaPublicParams, - ); - let pp = public_parameters::public_params::<_, _, MultiFrame<'_, _, _>>(&instance).unwrap(); - - let size = (10, 0); - let benchmark_id = BenchmarkId::new("end2end_go_base_nova", format!("_{}_{}", size.0, size.1)); - - let state = State::init_lurk_state().rccell(); - - group.bench_with_input(benchmark_id, &size, |b, &s| { - b.iter(|| { - let ptr = go_base::(&store, state.clone(), s.0, s.1); - let (frames, _) = evaluate::>(None, ptr, &store, limit).unwrap(); - let _result = prover.prove(&pp, &frames, &store, &lang_pallas_rc).unwrap(); - }) - }); - - group.finish(); -} - -/// To run these benchmarks, do `cargo criterion store_benchmark_lem`. -/// For flamegraphs, run: -/// ```cargo criterion store_benchmark_lem --features flamegraph -- --profile-time ``` -fn store_benchmark_lem(c: &mut Criterion) { - let mut group = c.benchmark_group("store_benchmark"); - group - .measurement_time(Duration::from_secs(5)) - .sample_size(60); - - let bls12_store = Store::::default(); - let pallas_store = Store::::default(); - - let state = State::init_lurk_state().rccell(); - - // todo!() rfc out into more flexible test cases - let sizes = [(10, 16), (10, 160)]; - for size in sizes { - let parameter_string = format!("_{}_{}", size.0, size.1); - - let bls12_id = BenchmarkId::new("store_go_base_bls12", ¶meter_string); - group.bench_with_input(bls12_id, &size, |b, &s| { - b.iter(|| { - let result = go_base::(&bls12_store, state.clone(), s.0, s.1); - black_box(result) - }) - }); - - let pasta_id = BenchmarkId::new("store_go_base_pallas", ¶meter_string); - group.bench_with_input(pasta_id, &size, |b, &s| { - b.iter(|| { - let result = go_base::(&pallas_store, state.clone(), s.0, s.1); - black_box(result) - }) - }); - } - - group.finish(); -} - -/// To run these benchmarks, do `cargo criterion hydration_benchmark_lem`. -/// For flamegraphs, run: -/// ```cargo criterion hydration_benchmark_lem --features flamegraph -- --profile-time ``` -fn hydration_benchmark_lem(c: &mut Criterion) { - let mut group = c.benchmark_group("hydration_benchmark"); - group - .measurement_time(Duration::from_secs(5)) - .sample_size(60); - - let bls12_store = Store::::default(); - let pallas_store = Store::::default(); - - let state = State::init_lurk_state().rccell(); - - // todo!() rfc out into more flexible test cases - let sizes = [(10, 16), (10, 160)]; - for size in sizes { - let parameter_string = format!("_{}_{}", size.0, size.1); - - { - let benchmark_id = BenchmarkId::new("hydration_go_base_bls12", ¶meter_string); - group.bench_with_input(benchmark_id, &size, |b, &s| { - let _ptr = go_base::(&bls12_store, state.clone(), s.0, s.1); - b.iter(|| bls12_store.hydrate_z_cache()) - }); - } - - { - let benchmark_id = BenchmarkId::new("hydration_go_base_pallas", ¶meter_string); - group.bench_with_input(benchmark_id, &size, |b, &s| { - let _ptr = go_base::(&pallas_store, state.clone(), s.0, s.1); - b.iter(|| pallas_store.hydrate_z_cache()) - }); - } - } - - group.finish(); -} - -/// To run these benchmarks, do `cargo criterion eval_benchmark_lem`. -/// For flamegraphs, run: -/// ```cargo criterion eval_benchmark_lem --features flamegraph -- --profile-time ``` -fn eval_benchmark_lem(c: &mut Criterion) { - let mut group = c.benchmark_group("eval_benchmark"); - group - .measurement_time(Duration::from_secs(5)) - .sample_size(60); - - let limit = 1_000_000_000; - let bls12_store = Store::default(); - let pallas_store = Store::default(); - - let state = State::init_lurk_state().rccell(); - - // todo!() rfc out into more flexible test cases - let sizes = [(10, 16), (10, 160)]; - for size in sizes { - let parameter_string = format!("_{}_{}", size.0, size.1); - - { - let benchmark_id = BenchmarkId::new("eval_go_base_bls12", ¶meter_string); - group.bench_with_input(benchmark_id, &size, |b, &s| { - let ptr = go_base::(&bls12_store, state.clone(), s.0, s.1); - b.iter(|| evaluate_simple::>(None, ptr, &bls12_store, limit)) - }); - } - - { - let benchmark_id = BenchmarkId::new("eval_go_base_pallas", ¶meter_string); - group.bench_with_input(benchmark_id, &size, |b, &s| { - let ptr = go_base::(&pallas_store, state.clone(), s.0, s.1); - b.iter(|| evaluate_simple::>(None, ptr, &pallas_store, limit)) - }); - } - } - - group.finish(); -} - -// todo!(): come back to this later when we know what to do with circuit generation -// fn circuit_generation_benchmark(c: &mut Criterion) { -// let mut group = c.benchmark_group("eval_benchmark"); -// group.measurement_time(Duration::from_secs(5)) -// .sample_size(60); - -// let limit = 1_000_000_000; -// let _lang_bls = Lang::>::new(); -// let _lang_pallas = Lang::>::new(); -// let lang_pallas = Lang::>::new(); - -// let reduction_count = DEFAULT_REDUCTION_COUNT; - -// group.bench_function("circuit_generation_go_base_10_16_nova", |b| { -// let mut store = Store::default(); -// let env = empty_sym_env(&store); -// let ptr = go_base::(&mut store, black_box(10), black_box(16)); -// let prover = NovaProver::new(reduction_count, lang_pallas.clone()); - -// let pp = public_parameters::public_params(reduction_count).unwrap(); -// let frames = prover -// .get_evaluation_frames(ptr, env, &mut store, limit, &lang_pallas) -// .unwrap(); - -// b.iter(|| { -// let result = prover -// .prove(&pp, frames.clone(), &mut store, &lang_pallas) -// .unwrap(); -// black_box(result); -// }) -// }); -// } - -/// To run these benchmarks, do `cargo criterion prove_benchmark_lem`. -/// For flamegraphs, run: -/// ```cargo criterion prove_benchmark_lem --features flamegraph -- --profile-time ``` -fn prove_benchmark_lem(c: &mut Criterion) { - let mut group = c.benchmark_group("prove_benchmark"); - group - .sampling_mode(SamplingMode::Flat) - .measurement_time(Duration::from_secs(120)) - .sample_size(10); - - set_bench_config(); - let limit = 1_000_000_000; - let reduction_count = DEFAULT_REDUCTION_COUNT; - - let store = Store::default(); - - let size = (10, 0); - let benchmark_id = BenchmarkId::new("prove_go_base_nova", format!("_{}_{}", size.0, size.1)); - - let state = State::init_lurk_state().rccell(); - - let lang_pallas = Lang::>::new(); - let lang_pallas_rc = Arc::new(lang_pallas.clone()); - - // use cached public params - let instance = Instance::new( - reduction_count, - lang_pallas_rc.clone(), - true, - Kind::NovaPublicParams, - ); - let pp = public_parameters::public_params::<_, _, MultiFrame<'_, _, _>>(&instance).unwrap(); - - group.bench_with_input(benchmark_id, &size, |b, &s| { - let ptr = go_base::(&store, state.clone(), s.0, s.1); - let prover: NovaProver<'_, Fq, Coproc, MultiFrame<'_, Fq, Coproc>> = - NovaProver::new(reduction_count, Lang::new()); - let (frames, _) = evaluate::>(None, ptr, &store, limit).unwrap(); - - b.iter(|| { - let result = prover.prove(&pp, &frames, &store, &lang_pallas_rc).unwrap(); - black_box(result); - }) - }); -} - -/// To run these benchmarks, do `cargo criterion prove_compressed_benchmark_lem`. -/// For flamegraphs, run: -/// ```cargo criterion prove_compressed_benchmark_lem --features flamegraph -- --profile-time ``` -fn prove_compressed_benchmark_lem(c: &mut Criterion) { - let mut group = c.benchmark_group("prove_compressed_benchmark"); - group - .sampling_mode(SamplingMode::Flat) - .measurement_time(Duration::from_secs(120)) - .sample_size(10); - - set_bench_config(); - let limit = 1_000_000_000; - let store = Store::default(); - let reduction_count = DEFAULT_REDUCTION_COUNT; - - let size = (10, 0); - let benchmark_id = BenchmarkId::new( - "prove_compressed_go_base_nova", - format!("_{}_{}", size.0, size.1), - ); - - let state = State::init_lurk_state().rccell(); - - let lang_pallas = Lang::>::new(); - let lang_pallas_rc = Arc::new(lang_pallas.clone()); - - // use cached public params - let instance = Instance::new( - reduction_count, - lang_pallas_rc.clone(), - true, - Kind::NovaPublicParams, - ); - let pp = public_parameters::public_params::<_, _, MultiFrame<'_, _, _>>(&instance).unwrap(); - - group.bench_with_input(benchmark_id, &size, |b, &s| { - let ptr = go_base::(&store, state.clone(), s.0, s.1); - let prover = NovaProver::new(reduction_count, Lang::new()); - let (frames, _) = evaluate::>(None, ptr, &store, limit).unwrap(); - - b.iter(|| { - let (proof, _, _, _) = prover.prove(&pp, &frames, &store, &lang_pallas_rc).unwrap(); - - let compressed_result = proof.compress(&pp).unwrap(); - black_box(compressed_result); - }) - }); -} - -/// To run these benchmarks, do `cargo criterion verify_benchmark_lem`. -/// For flamegraphs, run: -/// ```cargo criterion verify_benchmark_lem --features flamegraph -- --profile-time ``` -fn verify_benchmark_lem(c: &mut Criterion) { - let mut group = c.benchmark_group("verify_benchmark"); - group - .measurement_time(Duration::from_secs(10)) - .sample_size(10); - - set_bench_config(); - let limit = 1_000_000_000; - let store = Store::default(); - let reduction_count = DEFAULT_REDUCTION_COUNT; - - let state = State::init_lurk_state().rccell(); - - let lang_pallas = Lang::>::new(); - let lang_pallas_rc = Arc::new(lang_pallas.clone()); - - // use cached public params - let instance = Instance::new( - reduction_count, - lang_pallas_rc.clone(), - true, - Kind::NovaPublicParams, - ); - let pp = public_parameters::public_params::<_, _, MultiFrame<'_, _, _>>(&instance).unwrap(); - - let sizes = [(10, 0)]; - for size in sizes { - let parameter_string = format!("_{}_{}", size.0, size.1); - let benchmark_id = BenchmarkId::new("verify_go_base_nova", ¶meter_string); - group.bench_with_input(benchmark_id, &size, |b, &s| { - let ptr = go_base(&store, state.clone(), s.0, s.1); - let prover = NovaProver::new(reduction_count, Lang::new()); - let (frames, _) = evaluate::>(None, ptr, &store, limit).unwrap(); - let (proof, z0, zi, num_steps) = - prover.prove(&pp, &frames, &store, &lang_pallas_rc).unwrap(); - - b.iter_batched( - || z0.clone(), - |z0| { - let result = proof.verify(&pp, num_steps, &z0, &zi[..]).unwrap(); - black_box(result); - }, - BatchSize::LargeInput, - ) - }); - } - - group.finish(); -} - -/// To run these benchmarks, do `cargo criterion verify_compressed_benchmark_lem`. -/// For flamegraphs, run: -/// ```cargo criterion verify_compressed_benchmark_lem --features flamegraph -- --profile-time ``` -fn verify_compressed_benchmark_lem(c: &mut Criterion) { - let mut group = c.benchmark_group("verify_compressed_benchmark"); - group - .measurement_time(Duration::from_secs(10)) - .sample_size(10); - - set_bench_config(); - let limit = 1_000_000_000; - let store = Store::default(); - let reduction_count = DEFAULT_REDUCTION_COUNT; - - let state = State::init_lurk_state().rccell(); - - let lang_pallas = Lang::>::new(); - let lang_pallas_rc = Arc::new(lang_pallas.clone()); - - // use cached public params - let instance = Instance::new( - reduction_count, - lang_pallas_rc.clone(), - true, - Kind::NovaPublicParams, - ); - let pp = public_parameters::public_params::<_, _, MultiFrame<'_, _, _>>(&instance).unwrap(); - - let sizes = [(10, 0)]; - for size in sizes { - let parameter_string = format!("_{}_{}", size.0, size.1); - let benchmark_id = BenchmarkId::new("verify_compressed_go_base_nova", ¶meter_string); - group.bench_with_input(benchmark_id, &size, |b, &s| { - let ptr = go_base(&store, state.clone(), s.0, s.1); - let prover = NovaProver::new(reduction_count, Lang::new()); - let (frames, _) = evaluate::>(None, ptr, &store, limit).unwrap(); - let (proof, z0, zi, num_steps) = - prover.prove(&pp, &frames, &store, &lang_pallas_rc).unwrap(); - - let compressed_proof = proof.compress(&pp).unwrap(); - - b.iter_batched( - || z0.clone(), - |z0| { - let result = compressed_proof - .verify(&pp, num_steps, &z0, &zi[..]) - .unwrap(); - black_box(result); - }, - BatchSize::LargeInput, - ) - }); - } - - group.finish(); -} - -cfg_if::cfg_if! { - - if #[cfg(feature = "flamegraph")] { - // In order to collect a flamegraph, you need to indicate a profile time, see - // https://github.com/tikv/pprof-rs#integrate-with-criterion - // Example usage : - // cargo criterion --bench fibonacci --features flamegraph -- --profile-time 5 - // Warning: it is not recommended to run this on an M1 Mac, as making pprof work well there is hard. - criterion_group! { - name = benches; - config = Criterion::default() - .with_profiler(pprof::criterion::PProfProfiler::new(100, pprof::criterion::Output::Flamegraph(None))); - targets = - end2end_benchmark_lem, - store_benchmark_lem, - hydration_benchmark_lem, - eval_benchmark_lem, - // circuit_generation_benchmark, - prove_benchmark_lem, - prove_compressed_benchmark_lem, - verify_benchmark_lem, - verify_compressed_benchmark_lem - } - } else { - criterion_group! { - name = benches; - config = Criterion::default(); - targets = - end2end_benchmark_lem, - store_benchmark_lem, - hydration_benchmark_lem, - eval_benchmark_lem, - // circuit_generation_benchmark, - prove_benchmark_lem, - prove_compressed_benchmark_lem, - verify_benchmark_lem, - verify_compressed_benchmark_lem - } - } -} - -// To run these benchmarks, first download `criterion` with `cargo install cargo-criterion`. -// Then `cargo criterion --bench end2end_lem`. The results are located in `target/criterion/data/`. -// For flamegraphs, run `cargo criterion --bench end2end_lem --features flamegraph -- --profile-time `. -// The results are located in `target/criterion/profile/`. -criterion_main!(benches); diff --git a/benches/fibonacci.rs b/benches/fibonacci.rs index d0621bd575..e1c9507c04 100644 --- a/benches/fibonacci.rs +++ b/benches/fibonacci.rs @@ -1,5 +1,6 @@ use std::{cell::RefCell, rc::Rc, sync::Arc, time::Duration}; +use anyhow::anyhow; use criterion::{ black_box, criterion_group, criterion_main, measurement, BatchSize, BenchmarkGroup, BenchmarkId, Criterion, SamplingMode, @@ -8,21 +9,16 @@ use criterion::{ use pasta_curves::pallas; use lurk::{ - circuit::circuit_frame::MultiFrame, - eval::{ - empty_sym_env, - lang::{Coproc, Lang}, - }, + eval::lang::{Coproc, Lang}, field::LurkField, + lem::{eval::evaluate, multiframe::MultiFrame, pointers::Ptr, store::Store}, proof::nova::NovaProver, proof::Prover, - ptr::Ptr, public_parameters::{ instance::{Instance, Kind}, public_params, }, state::State, - store::Store, }; mod common; @@ -35,7 +31,7 @@ fn fib(store: &Store, state: Rc>, _a: u64) -> Pt (fib)) "#; - store.read_with_state(state, program).unwrap() + store.read(state, program).unwrap() } // The env output in the `fib_frame`th frame of the above, infinite Fibonacci computation will contain a binding of the @@ -105,7 +101,6 @@ fn fibo_prove( |b, prove_params| { let store = Store::default(); - let env = empty_sym_env(&store); let ptr = fib::( &store, state.clone(), @@ -113,9 +108,10 @@ fn fibo_prove( ); let prover = NovaProver::new(prove_params.reduction_count, lang_pallas.clone()); - let frames = &prover - .get_evaluation_frames(ptr, env, &store, limit, lang_rc.clone()) - .unwrap(); + let frames = + &evaluate::>(None, ptr, &store, limit) + .unwrap() + .0; b.iter_batched( || (frames, lang_rc.clone()), @@ -129,14 +125,42 @@ fn fibo_prove( ); } +fn rc_env() -> anyhow::Result> { + std::env::var("LURK_RC") + .map_err(|e| anyhow!("Reduction count env var isn't set: {e}")) + .and_then(|rc| { + let vec: anyhow::Result> = rc + .split(',') + .map(|rc| { + rc.parse::() + .map_err(|e| anyhow!("Failed to parse RC: {e}")) + }) + .collect(); + vec + }) +} + +fn noise_threshold_env() -> anyhow::Result { + std::env::var("LURK_BENCH_NOISE_THRESHOLD") + .map_err(|e| anyhow!("Noise threshold env var isn't set: {e}")) + .and_then(|nt| { + nt.parse::() + .map_err(|e| anyhow!("Failed to parse noise threshold: {e}")) + }) +} + fn fibonacci_prove(c: &mut Criterion) { + tracing_subscriber::fmt::init(); set_bench_config(); tracing::debug!("{:?}", lurk::config::LURK_CONFIG); - let reduction_counts = [100, 600, 700, 800, 900]; + + let reduction_counts = rc_env().unwrap_or_else(|_| vec![100]); let batch_sizes = [100, 200]; - let mut group: BenchmarkGroup<'_, _> = c.benchmark_group("Prove"); + let mut group: BenchmarkGroup<'_, _> = c.benchmark_group("LEM Prove"); group.sampling_mode(SamplingMode::Flat); // This can take a *while* group.sample_size(10); + group.noise_threshold(noise_threshold_env().unwrap_or(0.05)); + let state = State::init_lurk_state().rccell(); for fib_n in batch_sizes.iter() { diff --git a/benches/fibonacci_lem.rs b/benches/fibonacci_lem.rs deleted file mode 100644 index e1c9507c04..0000000000 --- a/benches/fibonacci_lem.rs +++ /dev/null @@ -1,202 +0,0 @@ -use std::{cell::RefCell, rc::Rc, sync::Arc, time::Duration}; - -use anyhow::anyhow; -use criterion::{ - black_box, criterion_group, criterion_main, measurement, BatchSize, BenchmarkGroup, - BenchmarkId, Criterion, SamplingMode, -}; - -use pasta_curves::pallas; - -use lurk::{ - eval::lang::{Coproc, Lang}, - field::LurkField, - lem::{eval::evaluate, multiframe::MultiFrame, pointers::Ptr, store::Store}, - proof::nova::NovaProver, - proof::Prover, - public_parameters::{ - instance::{Instance, Kind}, - public_params, - }, - state::State, -}; - -mod common; -use common::set_bench_config; - -fn fib(store: &Store, state: Rc>, _a: u64) -> Ptr { - let program = r#" -(letrec ((next (lambda (a b) (next b (+ a b)))) - (fib (next 0 1))) - (fib)) -"#; - - store.read(state, program).unwrap() -} - -// The env output in the `fib_frame`th frame of the above, infinite Fibonacci computation will contain a binding of the -// nth Fibonacci number to `a`. -// means of computing it.] -fn fib_frame(n: usize) -> usize { - 11 + 16 * n -} - -// Set the limit so the last step will be filled exactly, since Lurk currently only pads terminal/error continuations. -fn fib_limit(n: usize, rc: usize) -> usize { - let frame = fib_frame(n); - rc * (frame / rc + usize::from(frame % rc != 0)) -} - -#[derive(Clone, Debug, Copy)] -struct ProveParams { - fib_n: usize, - reduction_count: usize, - date: &'static str, - sha: &'static str, -} - -impl ProveParams { - fn name(&self) -> String { - format!("Fibonacci-rc={}", self.reduction_count) - } -} - -fn fibo_prove( - prove_params: ProveParams, - c: &mut BenchmarkGroup<'_, M>, - state: &Rc>, -) { - let ProveParams { - fib_n, - reduction_count, - date, - sha, - } = prove_params; - - let limit = fib_limit(fib_n, reduction_count); - let lang_pallas = Lang::>::new(); - let lang_rc = Arc::new(lang_pallas.clone()); - - // use cached public params - let instance = Instance::new( - reduction_count, - lang_rc.clone(), - true, - Kind::NovaPublicParams, - ); - let pp = public_params::<_, _, MultiFrame<'_, _, _>>(&instance).unwrap(); - - // Track the number of `Lurk frames / sec` - let rc = reduction_count as u64; - c.throughput(criterion::Throughput::Elements( - rc * u64::div_ceil((11 + 16 * fib_n) as u64, rc), - )); - - c.bench_with_input( - BenchmarkId::new( - prove_params.name(), - format!("num-{}/{sha}-{date}", prove_params.fib_n), - ), - &prove_params, - |b, prove_params| { - let store = Store::default(); - - let ptr = fib::( - &store, - state.clone(), - black_box(prove_params.fib_n as u64), - ); - let prover = NovaProver::new(prove_params.reduction_count, lang_pallas.clone()); - - let frames = - &evaluate::>(None, ptr, &store, limit) - .unwrap() - .0; - - b.iter_batched( - || (frames, lang_rc.clone()), - |(frames, lang_rc)| { - let result = prover.prove(&pp, frames, &store, &lang_rc); - let _ = black_box(result); - }, - BatchSize::LargeInput, - ) - }, - ); -} - -fn rc_env() -> anyhow::Result> { - std::env::var("LURK_RC") - .map_err(|e| anyhow!("Reduction count env var isn't set: {e}")) - .and_then(|rc| { - let vec: anyhow::Result> = rc - .split(',') - .map(|rc| { - rc.parse::() - .map_err(|e| anyhow!("Failed to parse RC: {e}")) - }) - .collect(); - vec - }) -} - -fn noise_threshold_env() -> anyhow::Result { - std::env::var("LURK_BENCH_NOISE_THRESHOLD") - .map_err(|e| anyhow!("Noise threshold env var isn't set: {e}")) - .and_then(|nt| { - nt.parse::() - .map_err(|e| anyhow!("Failed to parse noise threshold: {e}")) - }) -} - -fn fibonacci_prove(c: &mut Criterion) { - tracing_subscriber::fmt::init(); - set_bench_config(); - tracing::debug!("{:?}", lurk::config::LURK_CONFIG); - - let reduction_counts = rc_env().unwrap_or_else(|_| vec![100]); - let batch_sizes = [100, 200]; - let mut group: BenchmarkGroup<'_, _> = c.benchmark_group("LEM Prove"); - group.sampling_mode(SamplingMode::Flat); // This can take a *while* - group.sample_size(10); - group.noise_threshold(noise_threshold_env().unwrap_or(0.05)); - - let state = State::init_lurk_state().rccell(); - - for fib_n in batch_sizes.iter() { - for reduction_count in reduction_counts.iter() { - let prove_params = ProveParams { - fib_n: *fib_n, - reduction_count: *reduction_count, - date: env!("VERGEN_GIT_COMMIT_DATE"), - sha: env!("VERGEN_GIT_SHA"), - }; - fibo_prove(prove_params, &mut group, &state); - } - } -} - -cfg_if::cfg_if! { - if #[cfg(feature = "flamegraph")] { - criterion_group! { - name = benches; - config = Criterion::default() - .measurement_time(Duration::from_secs(120)) - .sample_size(10) - .with_profiler(pprof::criterion::PProfProfiler::new(100, pprof::criterion::Output::Flamegraph(None))); - targets = - fibonacci_prove, - } - } else { - criterion_group! { - name = benches; - config = Criterion::default() - .measurement_time(Duration::from_secs(120)) - .sample_size(10); - targets = - fibonacci_prove, - } - } -} - -criterion_main!(benches); diff --git a/benches/sha256.rs b/benches/sha256.rs index db8afe625c..9e622bc2d1 100644 --- a/benches/sha256.rs +++ b/benches/sha256.rs @@ -5,6 +5,7 @@ //! //! Note: The example [example/sha256_ivc.rs] is this same benchmark but as an example //! that's easier to play with and run. + use criterion::{ black_box, criterion_group, criterion_main, measurement, BatchSize, BenchmarkGroup, BenchmarkId, Criterion, SamplingMode, @@ -13,18 +14,21 @@ use pasta_curves::pallas::Scalar as Fr; use std::{cell::RefCell, rc::Rc, sync::Arc, time::Duration}; use lurk::{ - circuit::circuit_frame::MultiFrame, coprocessor::sha256::{Sha256Coproc, Sha256Coprocessor}, - eval::{empty_sym_env, lang::Lang}, + eval::lang::Lang, field::LurkField, + lem::{ + eval::{evaluate, make_eval_step_from_lang}, + multiframe::MultiFrame, + pointers::Ptr, + store::Store, + }, proof::{nova::NovaProver, supernova::SuperNovaProver, Prover}, - ptr::Ptr, public_parameters::{ instance::{Instance, Kind}, public_params, supernova_public_params, }, state::{user_sym, State}, - store::Store, }; mod common; @@ -35,7 +39,7 @@ fn sha256_ivc( state: Rc>, arity: usize, n: usize, - input: &[usize], + input: &Vec, ) -> Ptr { assert_eq!(n, input.len()); let input = input @@ -46,7 +50,7 @@ fn sha256_ivc( let input = format!("'({input})"); let program = format!( r#" -(letrec ((encode-1 (lambda (term) +(letrec ((encode-1 (lambda (term) (let ((type (car term)) (value (cdr term))) (if (eq 'sha256 type) @@ -57,17 +61,17 @@ fn sha256_ivc( value)))))) (encode (lambda (input) (if input - (cons + (cons (encode-1 (car input)) (encode (cdr input))))))) (encode '((lurk . 5) (id . 15) {input}))) "# ); - store.read_with_state(state, &program).unwrap() + store.read(state, &program).unwrap() } -#[derive(Clone, Debug, Copy)] +#[derive(Clone, Copy, Debug)] struct ProveParams { arity: usize, n: usize, @@ -98,22 +102,17 @@ fn sha256_ivc_prove( let limit = 10000; - let store = &mut Store::::new(); + let store = &Store::::default(); let cproc_sym = user_sym(&format!("sha256_ivc_{arity}")); - let lang = Lang::>::new_with_bindings( - store, - vec![(cproc_sym, Sha256Coprocessor::new(arity).into())], - ); + let mut lang = Lang::>::new(); + lang.add_coprocessor_lem(cproc_sym, Sha256Coprocessor::new(arity), store); let lang_rc = Arc::new(lang.clone()); + let lurk_step = make_eval_step_from_lang(&lang, true); + // use cached public params - let instance: Instance< - '_, - pasta_curves::Fq, - Sha256Coproc, - MultiFrame<'_, _, _>, - > = Instance::new( + let instance: Instance<'_, Fr, Sha256Coproc, MultiFrame<'_, _, _>> = Instance::new( reduction_count, lang_rc.clone(), true, @@ -125,20 +124,19 @@ fn sha256_ivc_prove( BenchmarkId::new(prove_params.name(), arity), &prove_params, |b, prove_params| { - let env = empty_sym_env(store); let ptr = sha256_ivc( store, state.clone(), black_box(prove_params.arity), black_box(prove_params.n), - &(0..prove_params.n).collect::>(), + &(0..prove_params.n).collect(), ); let prover = NovaProver::new(prove_params.reduction_count, lang.clone()); - let frames = &prover - .get_evaluation_frames(ptr, env, store, limit, lang_rc.clone()) - .unwrap(); + let frames = &evaluate(Some((&lurk_step, &lang)), ptr, store, limit) + .unwrap() + .0; b.iter_batched( || (frames, lang_rc.clone()), @@ -187,15 +185,15 @@ fn sha256_ivc_prove_compressed( let limit = 10000; - let store = &mut Store::::new(); + let store = &Store::::default(); let cproc_sym = user_sym(&format!("sha256_ivc_{arity}")); - let lang = Lang::>::new_with_bindings( - store, - vec![(cproc_sym, Sha256Coprocessor::new(arity).into())], - ); + let mut lang = Lang::>::new(); + lang.add_coprocessor_lem(cproc_sym, Sha256Coprocessor::new(arity), store); let lang_rc = Arc::new(lang.clone()); + let lurk_step = make_eval_step_from_lang(&lang, true); + // use cached public params let instance = Instance::new( reduction_count, @@ -209,20 +207,19 @@ fn sha256_ivc_prove_compressed( BenchmarkId::new(prove_params.name(), arity), &prove_params, |b, prove_params| { - let env = empty_sym_env(store); let ptr = sha256_ivc( store, state.clone(), black_box(prove_params.arity), black_box(prove_params.n), - &(0..prove_params.n).collect::>(), + &(0..prove_params.n).collect(), ); let prover = NovaProver::new(prove_params.reduction_count, lang.clone()); - let frames = &prover - .get_evaluation_frames(ptr, env, store, limit, lang_rc.clone()) - .unwrap(); + let frames = &evaluate(Some((&lurk_step, &lang)), ptr, store, limit) + .unwrap() + .0; b.iter_batched( || (frames, lang_rc.clone()), @@ -273,15 +270,15 @@ fn sha256_nivc_prove( let limit = 10000; - let store = &mut Store::::new(); + let store = &Store::::default(); let cproc_sym = user_sym(&format!("sha256_ivc_{arity}")); - let lang = Lang::>::new_with_bindings( - store, - vec![(cproc_sym, Sha256Coprocessor::new(arity).into())], - ); + let mut lang = Lang::>::new(); + lang.add_coprocessor_lem(cproc_sym, Sha256Coprocessor::new(arity), store); let lang_rc = Arc::new(lang.clone()); + let lurk_step = make_eval_step_from_lang(&lang, false); + // use cached public params let instance = Instance::new( reduction_count, @@ -295,20 +292,19 @@ fn sha256_nivc_prove( BenchmarkId::new(prove_params.name(), arity), &prove_params, |b, prove_params| { - let env = empty_sym_env(store); let ptr = sha256_ivc( store, state.clone(), black_box(prove_params.arity), black_box(prove_params.n), - &(0..prove_params.n).collect::>(), + &(0..prove_params.n).collect(), ); let prover = SuperNovaProver::new(prove_params.reduction_count, lang.clone()); - let frames = &prover - .get_evaluation_frames(ptr, env, store, limit, lang_rc.clone()) - .unwrap(); + let frames = &evaluate(Some((&lurk_step, &lang)), ptr, store, limit) + .unwrap() + .0; b.iter_batched( || (frames, lang_rc.clone()), diff --git a/benches/sha256_lem.rs b/benches/sha256_lem.rs deleted file mode 100644 index 9e622bc2d1..0000000000 --- a/benches/sha256_lem.rs +++ /dev/null @@ -1,391 +0,0 @@ -//! This benchmark measures the IVC performance of coprocessors, by adding a `sha256` -//! circuit alongside the lurk primary circuit. When supernova is integrated as a backend, -//! then NIVC performance can also be tested. This benchmark serves as a baseline for that -//! performance. -//! -//! Note: The example [example/sha256_ivc.rs] is this same benchmark but as an example -//! that's easier to play with and run. - -use criterion::{ - black_box, criterion_group, criterion_main, measurement, BatchSize, BenchmarkGroup, - BenchmarkId, Criterion, SamplingMode, -}; -use pasta_curves::pallas::Scalar as Fr; -use std::{cell::RefCell, rc::Rc, sync::Arc, time::Duration}; - -use lurk::{ - coprocessor::sha256::{Sha256Coproc, Sha256Coprocessor}, - eval::lang::Lang, - field::LurkField, - lem::{ - eval::{evaluate, make_eval_step_from_lang}, - multiframe::MultiFrame, - pointers::Ptr, - store::Store, - }, - proof::{nova::NovaProver, supernova::SuperNovaProver, Prover}, - public_parameters::{ - instance::{Instance, Kind}, - public_params, supernova_public_params, - }, - state::{user_sym, State}, -}; - -mod common; -use common::set_bench_config; - -fn sha256_ivc( - store: &Store, - state: Rc>, - arity: usize, - n: usize, - input: &Vec, -) -> Ptr { - assert_eq!(n, input.len()); - let input = input - .iter() - .map(|i| format!("(sha256 . {i})")) - .collect::>() - .join(" "); - let input = format!("'({input})"); - let program = format!( - r#" -(letrec ((encode-1 (lambda (term) - (let ((type (car term)) - (value (cdr term))) - (if (eq 'sha256 type) - (eval (cons 'sha256_ivc_{arity} value)) - (if (eq 'lurk type) - (commit value) - (if (eq 'id type) - value)))))) - (encode (lambda (input) - (if input - (cons - (encode-1 (car input)) - (encode (cdr input))))))) - (encode '((lurk . 5) (id . 15) {input}))) -"# - ); - - store.read(state, &program).unwrap() -} - -#[derive(Clone, Copy, Debug)] -struct ProveParams { - arity: usize, - n: usize, - reduction_count: usize, -} - -impl ProveParams { - fn name(&self) -> String { - let date = env!("VERGEN_GIT_COMMIT_DATE"); - let sha = env!("VERGEN_GIT_SHA"); - format!( - "{date}:{sha}:rc={}:sha256_ivc_{}", - self.reduction_count, self.arity - ) - } -} - -fn sha256_ivc_prove( - prove_params: ProveParams, - c: &mut BenchmarkGroup<'_, M>, - state: &Rc>, -) { - let ProveParams { - arity, - n: _, - reduction_count, - } = prove_params; - - let limit = 10000; - - let store = &Store::::default(); - let cproc_sym = user_sym(&format!("sha256_ivc_{arity}")); - - let mut lang = Lang::>::new(); - lang.add_coprocessor_lem(cproc_sym, Sha256Coprocessor::new(arity), store); - let lang_rc = Arc::new(lang.clone()); - - let lurk_step = make_eval_step_from_lang(&lang, true); - - // use cached public params - let instance: Instance<'_, Fr, Sha256Coproc, MultiFrame<'_, _, _>> = Instance::new( - reduction_count, - lang_rc.clone(), - true, - Kind::NovaPublicParams, - ); - let pp = public_params::<_, _, MultiFrame<'_, _, _>>(&instance).unwrap(); - - c.bench_with_input( - BenchmarkId::new(prove_params.name(), arity), - &prove_params, - |b, prove_params| { - let ptr = sha256_ivc( - store, - state.clone(), - black_box(prove_params.arity), - black_box(prove_params.n), - &(0..prove_params.n).collect(), - ); - - let prover = NovaProver::new(prove_params.reduction_count, lang.clone()); - - let frames = &evaluate(Some((&lurk_step, &lang)), ptr, store, limit) - .unwrap() - .0; - - b.iter_batched( - || (frames, lang_rc.clone()), - |(frames, lang_rc)| { - let result = prover.prove(&pp, frames, store, &lang_rc); - let _ = black_box(result); - }, - BatchSize::LargeInput, - ) - }, - ); -} - -fn ivc_prove_benchmarks(c: &mut Criterion) { - set_bench_config(); - tracing::debug!("{:?}", &lurk::config::LURK_CONFIG); - let reduction_counts = [10, 100]; - let batch_sizes = [1, 2, 5, 10, 20]; - let mut group: BenchmarkGroup<'_, _> = c.benchmark_group("prove"); - group.sampling_mode(SamplingMode::Flat); // This can take a *while* - group.sample_size(10); - let state = State::init_lurk_state().rccell(); - - for &n in batch_sizes.iter() { - for &reduction_count in reduction_counts.iter() { - let prove_params = ProveParams { - arity: 1, - n, - reduction_count, - }; - sha256_ivc_prove(prove_params, &mut group, &state); - } - } -} - -fn sha256_ivc_prove_compressed( - prove_params: ProveParams, - c: &mut BenchmarkGroup<'_, M>, - state: &Rc>, -) { - let ProveParams { - arity, - n: _, - reduction_count, - } = prove_params; - - let limit = 10000; - - let store = &Store::::default(); - let cproc_sym = user_sym(&format!("sha256_ivc_{arity}")); - - let mut lang = Lang::>::new(); - lang.add_coprocessor_lem(cproc_sym, Sha256Coprocessor::new(arity), store); - let lang_rc = Arc::new(lang.clone()); - - let lurk_step = make_eval_step_from_lang(&lang, true); - - // use cached public params - let instance = Instance::new( - reduction_count, - lang_rc.clone(), - true, - Kind::NovaPublicParams, - ); - let pp = public_params::<_, _, MultiFrame<'_, _, _>>(&instance).unwrap(); - - c.bench_with_input( - BenchmarkId::new(prove_params.name(), arity), - &prove_params, - |b, prove_params| { - let ptr = sha256_ivc( - store, - state.clone(), - black_box(prove_params.arity), - black_box(prove_params.n), - &(0..prove_params.n).collect(), - ); - - let prover = NovaProver::new(prove_params.reduction_count, lang.clone()); - - let frames = &evaluate(Some((&lurk_step, &lang)), ptr, store, limit) - .unwrap() - .0; - - b.iter_batched( - || (frames, lang_rc.clone()), - |(frames, lang_rc)| { - let (proof, _, _, _) = prover.prove(&pp, frames, store, &lang_rc).unwrap(); - let compressed_result = proof.compress(&pp).unwrap(); - - let _ = black_box(compressed_result); - }, - BatchSize::LargeInput, - ) - }, - ); -} - -fn ivc_prove_compressed_benchmarks(c: &mut Criterion) { - set_bench_config(); - tracing::debug!("{:?}", &lurk::config::LURK_CONFIG); - let reduction_counts = [10, 100]; - let batch_sizes = [1, 2, 5, 10, 20]; - let mut group: BenchmarkGroup<'_, _> = c.benchmark_group("prove_compressed"); - group.sampling_mode(SamplingMode::Flat); // This can take a *while* - group.sample_size(10); - let state = State::init_lurk_state().rccell(); - - for &n in batch_sizes.iter() { - for &reduction_count in reduction_counts.iter() { - let prove_params = ProveParams { - arity: 1, - n, - reduction_count, - }; - sha256_ivc_prove_compressed(prove_params, &mut group, &state); - } - } -} - -fn sha256_nivc_prove( - prove_params: ProveParams, - c: &mut BenchmarkGroup<'_, M>, - state: &Rc>, -) { - let ProveParams { - arity, - n: _, - reduction_count, - } = prove_params; - - let limit = 10000; - - let store = &Store::::default(); - let cproc_sym = user_sym(&format!("sha256_ivc_{arity}")); - - let mut lang = Lang::>::new(); - lang.add_coprocessor_lem(cproc_sym, Sha256Coprocessor::new(arity), store); - let lang_rc = Arc::new(lang.clone()); - - let lurk_step = make_eval_step_from_lang(&lang, false); - - // use cached public params - let instance = Instance::new( - reduction_count, - lang_rc.clone(), - true, - Kind::SuperNovaAuxParams, - ); - let pp = supernova_public_params::<_, _, MultiFrame<'_, _, _>>(&instance).unwrap(); - - c.bench_with_input( - BenchmarkId::new(prove_params.name(), arity), - &prove_params, - |b, prove_params| { - let ptr = sha256_ivc( - store, - state.clone(), - black_box(prove_params.arity), - black_box(prove_params.n), - &(0..prove_params.n).collect(), - ); - - let prover = SuperNovaProver::new(prove_params.reduction_count, lang.clone()); - - let frames = &evaluate(Some((&lurk_step, &lang)), ptr, store, limit) - .unwrap() - .0; - - b.iter_batched( - || (frames, lang_rc.clone()), - |(frames, lang_rc)| { - let result = prover.prove(&pp, frames, store, lang_rc); - let _ = black_box(result); - }, - BatchSize::LargeInput, - ) - }, - ); -} - -fn nivc_prove_benchmarks(c: &mut Criterion) { - set_bench_config(); - tracing::debug!("{:?}", &lurk::config::LURK_CONFIG); - let reduction_counts = [10, 100]; - let batch_sizes = [1, 2, 5, 10, 20]; - let mut group: BenchmarkGroup<'_, _> = c.benchmark_group("prove"); - group.sampling_mode(SamplingMode::Flat); // This can take a *while* - group.sample_size(10); - let state = State::init_lurk_state().rccell(); - - for &n in batch_sizes.iter() { - for &reduction_count in reduction_counts.iter() { - let prove_params = ProveParams { - arity: 1, - n, - reduction_count, - }; - sha256_nivc_prove(prove_params, &mut group, &state); - } - } -} - -cfg_if::cfg_if! { - if #[cfg(feature = "flamegraph")] { - criterion_group! { - name = ivc_benches; - config = Criterion::default() - .measurement_time(Duration::from_secs(120)) - .sample_size(10) - .with_profiler(pprof::criterion::PProfProfiler::new(100, pprof::criterion::Output::Flamegraph(None))); - targets = - ivc_prove_benchmarks, - ivc_prove_compressed_benchmarks - } - criterion_group! { - name = nivc_benches; - config = Criterion::default() - .measurement_time(Duration::from_secs(120)) - .sample_size(10) - .with_profiler(pprof::criterion::PProfProfiler::new(100, pprof::criterion::Output::Flamegraph(None))); - targets = - nivc_prove_benchmarks - // TODO: Add when compressed SNARK is implemented for SuperNova - // https://github.com/lurk-lab/arecibo/issues/27https://github.com/lurk-lab/arecibo/issues/27 - // nivc_prove_compressed_benchmarks - } - } else { - criterion_group! { - name = ivc_benches; - config = Criterion::default() - .measurement_time(Duration::from_secs(120)) - .sample_size(10); - targets = - ivc_prove_benchmarks, - ivc_prove_compressed_benchmarks - } - criterion_group! { - name = nivc_benches; - config = Criterion::default() - .measurement_time(Duration::from_secs(120)) - .sample_size(10); - targets = - nivc_prove_benchmarks - // TODO: Add when compressed SNARK is implemented for SuperNova - // https://github.com/lurk-lab/arecibo/issues/27https://github.com/lurk-lab/arecibo/issues/27 - // nivc_prove_compressed_benchmarks - } - } -} - -criterion_main!(ivc_benches, nivc_benches); diff --git a/benches/synthesis.rs b/benches/synthesis.rs index 1b4005bdf4..9a10e570a8 100644 --- a/benches/synthesis.rs +++ b/benches/synthesis.rs @@ -6,20 +6,14 @@ use criterion::{ black_box, criterion_group, criterion_main, measurement, BatchSize, BenchmarkGroup, BenchmarkId, Criterion, SamplingMode, }; +use pasta_curves::Fq; use lurk::{ - circuit::circuit_frame::MultiFrame, - eval::{ - empty_sym_env, - lang::{Coproc, Lang}, - }, + eval::lang::{Coproc, Lang}, field::LurkField, - proof::nova::NovaProver, - proof::supernova::FoldingConfig, - proof::Prover, - ptr::Ptr, + lem::{eval::evaluate, multiframe::MultiFrame, pointers::Ptr, store::Store}, + proof::{supernova::FoldingConfig, MultiFrameTrait}, state::State, - store::Store, }; fn fib(store: &Store, state: Rc>, a: u64) -> Ptr { @@ -37,7 +31,7 @@ fn fib(store: &Store, state: Rc>, a: u64) -> Ptr "# ); - store.read_with_state(state, &program).unwrap() + store.read(state, &program).unwrap() } fn synthesize( @@ -46,8 +40,7 @@ fn synthesize( c: &mut BenchmarkGroup<'_, M>, ) { let limit = 1_000_000; - let lang_pallas = Lang::>::new(); - let lang_rc = Arc::new(lang_pallas.clone()); + let lang_rc = Arc::new(Lang::>::new()); let state = State::init_lurk_state().rccell(); c.bench_with_input( @@ -55,17 +48,10 @@ fn synthesize( &reduction_count, |b, reduction_count| { let store = Store::default(); - let env = empty_sym_env(&store); let fib_n = (reduction_count / 3) as u64; // Heuristic, since one fib is 35 iterations. let ptr = fib::(&store, state.clone(), black_box(fib_n)); - let prover = NovaProver::<_, _, MultiFrame<'_, _, _>>::new( - *reduction_count, - lang_pallas.clone(), - ); + let (frames, _) = evaluate::>(None, ptr, &store, limit).unwrap(); - let frames = prover - .get_evaluation_frames(ptr, env, &store, limit, lang_rc.clone()) - .unwrap(); let folding_config = Arc::new(FoldingConfig::new_ivc(lang_rc.clone(), *reduction_count)); diff --git a/benches/synthesis_lem.rs b/benches/synthesis_lem.rs deleted file mode 100644 index 9a10e570a8..0000000000 --- a/benches/synthesis_lem.rs +++ /dev/null @@ -1,109 +0,0 @@ -use std::{cell::RefCell, rc::Rc, sync::Arc, time::Duration}; - -use bellpepper::util_cs::witness_cs::WitnessCS; -use bellpepper_core::{Circuit, ConstraintSystem}; -use criterion::{ - black_box, criterion_group, criterion_main, measurement, BatchSize, BenchmarkGroup, - BenchmarkId, Criterion, SamplingMode, -}; -use pasta_curves::Fq; - -use lurk::{ - eval::lang::{Coproc, Lang}, - field::LurkField, - lem::{eval::evaluate, multiframe::MultiFrame, pointers::Ptr, store::Store}, - proof::{supernova::FoldingConfig, MultiFrameTrait}, - state::State, -}; - -fn fib(store: &Store, state: Rc>, a: u64) -> Ptr { - let program = format!( - r#" -(let ((fib (lambda (target) - (letrec ((next (lambda (a b target) - (if (= 0 target) - a - (next b - (+ a b) - (- target 1)))))) - (next 0 1 target))))) - (fib {a})) -"# - ); - - store.read(state, &program).unwrap() -} - -fn synthesize( - name: &str, - reduction_count: usize, - c: &mut BenchmarkGroup<'_, M>, -) { - let limit = 1_000_000; - let lang_rc = Arc::new(Lang::>::new()); - let state = State::init_lurk_state().rccell(); - - c.bench_with_input( - BenchmarkId::new(name.to_string(), reduction_count), - &reduction_count, - |b, reduction_count| { - let store = Store::default(); - let fib_n = (reduction_count / 3) as u64; // Heuristic, since one fib is 35 iterations. - let ptr = fib::(&store, state.clone(), black_box(fib_n)); - let (frames, _) = evaluate::>(None, ptr, &store, limit).unwrap(); - - let folding_config = - Arc::new(FoldingConfig::new_ivc(lang_rc.clone(), *reduction_count)); - - let multiframe = - MultiFrame::from_frames(*reduction_count, &frames, &store, &folding_config)[0] - .clone(); - - b.iter_batched( - || (multiframe.clone()), // avoid cloning the frames in the benchmark - |multiframe| { - let mut cs = WitnessCS::new(); - let result = multiframe.synthesize(&mut cs); - let _ = black_box(result); - }, - BatchSize::LargeInput, - ) - }, - ); -} - -fn fibonacci_synthesize(c: &mut Criterion) { - let batch_sizes = [5, 10, 100, 200]; - let mut group: BenchmarkGroup<'_, _> = c.benchmark_group("synthesis"); - group.sampling_mode(SamplingMode::Flat); // This can take a *while* - group.sample_size(10); - - for size in batch_sizes.iter() { - synthesize("Synthesis-rc", *size, &mut group); - } -} - -cfg_if::cfg_if! { - if #[cfg(feature = "flamegraph")] { - criterion_group! { - name = benches; - config = Criterion::default() - .measurement_time(Duration::from_secs(120)) - .sample_size(10) - .with_profiler(pprof::criterion::PProfProfiler::new(100, pprof::criterion::Output::Flamegraph(None))); - targets = - fibonacci_synthesize - } - } else { - criterion_group! { - name = benches; - config = Criterion::default() - .measurement_time(Duration::from_secs(120)) - .sample_size(10); - targets = - fibonacci_synthesize, - } - } -} - -criterion_main!(benches); diff --git a/examples/sha256_ivc.rs b/examples/sha256_ivc.rs index b5fd4ea28d..c62932489a 100644 --- a/examples/sha256_ivc.rs +++ b/examples/sha256_ivc.rs @@ -4,18 +4,16 @@ use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry}; use tracing_texray::TeXRayLayer; use lurk::{ - circuit::circuit_frame::MultiFrame, coprocessor::sha256::{Sha256Coproc, Sha256Coprocessor}, - eval::{empty_sym_env, lang::Lang}, + eval::lang::Lang, field::LurkField, + lem::{multiframe::MultiFrame, pointers::Ptr, store::Store}, proof::{nova::NovaProver, Prover}, - ptr::Ptr, public_parameters::{ instance::{Instance, Kind}, public_params, }, state::user_sym, - store::Store, }; const REDUCTION_COUNT: usize = 10; @@ -48,7 +46,7 @@ fn sha256_ivc(store: &Store, n: usize, input: &[usize]) -> Ptr< "# ); - store.read(&program).unwrap() + store.read_with_default_state(&program).unwrap() } /// Run the example in this file with @@ -62,17 +60,15 @@ fn main() { tracing::subscriber::set_global_default(subscriber).unwrap(); let args = std::env::args().collect::>(); - let n = args[1].parse().unwrap(); + let n = args.get(1).unwrap_or(&"1".into()).parse().unwrap(); - let store = &mut Store::::new(); + let store = &Store::::default(); let cproc_sym = user_sym(&format!("sha256_ivc_{n}")); let call = sha256_ivc(store, n, &(0..n).collect::>()); - let lang = Lang::>::new_with_bindings( - store, - vec![(cproc_sym, Sha256Coprocessor::new(n).into())], - ); + let mut lang = Lang::>::new(); + lang.add_coprocessor_lem(cproc_sym, Sha256Coprocessor::new(n), store); let lang_rc = Arc::new(lang.clone()); let nova_prover = @@ -97,7 +93,7 @@ fn main() { let (proof, z0, zi, num_steps) = tracing_texray::examine(tracing::info_span!("bang!")) .in_scope(|| { nova_prover - .evaluate_and_prove(&pp, call, empty_sym_env(store), store, 10000, &lang_rc) + .evaluate_and_prove(&pp, call, store.intern_nil(), store, 10000, &lang_rc) .unwrap() }); let proof_end = proof_start.elapsed(); @@ -114,7 +110,7 @@ fn main() { if res { println!( - "Congratulations! You proved and verified a SHA256 hash calculation in {:?} time!", + "Congratulations! You proved and verified a LEM IVC SHA256 hash calculation in {:?} time!", pp_end + proof_end + verify_end ); } diff --git a/examples/sha256_ivc_lem.rs b/examples/sha256_ivc_lem.rs deleted file mode 100644 index 85df409d10..0000000000 --- a/examples/sha256_ivc_lem.rs +++ /dev/null @@ -1,117 +0,0 @@ -use pasta_curves::pallas::Scalar as Fr; -use std::{sync::Arc, time::Instant}; -use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry}; -use tracing_texray::TeXRayLayer; - -use lurk::{ - coprocessor::sha256::{Sha256Coproc, Sha256Coprocessor}, - eval::lang::Lang, - field::LurkField, - lem::{multiframe::MultiFrame, pointers::Ptr, store::Store}, - proof::{nova::NovaProver, Prover}, - public_parameters::{ - instance::{Instance, Kind}, - public_params, - }, - state::user_sym, -}; - -const REDUCTION_COUNT: usize = 10; - -fn sha256_ivc(store: &Store, n: usize, input: &[usize]) -> Ptr { - assert_eq!(n, input.len()); - let input = input - .iter() - .map(|i| i.to_string()) - .collect::>() - .join(" "); - let input = format!("'({input})"); - let program = format!( - r#" -(letrec ((encode-1 (lambda (term) - (let ((type (car term)) - (value (cdr term))) - (if (eq 'sha256 type) - (eval (cons 'sha256_ivc_{n} value)) - (if (eq 'lurk type) - (commit value) - (if (eq 'id type) - value)))))) - (encode (lambda (input) - (if input - (cons - (encode-1 (car input)) - (encode (cdr input))))))) - (encode '((sha256 . {input})))) -"# - ); - - store.read_with_default_state(&program).unwrap() -} - -/// Run the example in this file with -/// `cargo run --release --example sha256_ivc_lem ` -/// where `n` is the needed arity -fn main() { - let subscriber = Registry::default() - .with(fmt::layer().pretty()) - .with(EnvFilter::from_default_env()) - .with(TeXRayLayer::new()); - tracing::subscriber::set_global_default(subscriber).unwrap(); - - let args = std::env::args().collect::>(); - let n = args.get(1).unwrap_or(&"1".into()).parse().unwrap(); - - let store = &Store::::default(); - let cproc_sym = user_sym(&format!("sha256_ivc_{n}")); - - let call = sha256_ivc(store, n, &(0..n).collect::>()); - - let mut lang = Lang::>::new(); - lang.add_coprocessor_lem(cproc_sym, Sha256Coprocessor::new(n), store); - let lang_rc = Arc::new(lang.clone()); - - let nova_prover = - NovaProver::, MultiFrame<'_, _, _>>::new(REDUCTION_COUNT, lang); - - println!("Setting up public parameters (rc = {REDUCTION_COUNT})..."); - - let pp_start = Instant::now(); - let instance = Instance::new( - REDUCTION_COUNT, - lang_rc.clone(), - true, - Kind::NovaPublicParams, - ); - // see the documentation on `with_public_params` - let pp = public_params(&instance).unwrap(); - let pp_end = pp_start.elapsed(); - println!("Public parameters took {:?}", pp_end); - - println!("Beginning proof step..."); - let proof_start = Instant::now(); - let (proof, z0, zi, num_steps) = tracing_texray::examine(tracing::info_span!("bang!")) - .in_scope(|| { - nova_prover - .evaluate_and_prove(&pp, call, store.intern_nil(), store, 10000, &lang_rc) - .unwrap() - }); - let proof_end = proof_start.elapsed(); - - println!("Proofs took {:?}", proof_end); - - println!("Verifying proof..."); - - let verify_start = Instant::now(); - let res = proof.verify(&pp, num_steps, &z0, &zi).unwrap(); - let verify_end = verify_start.elapsed(); - - println!("Verify took {:?}", verify_end); - - if res { - println!( - "Congratulations! You proved and verified a LEM IVC SHA256 hash calculation in {:?} time!", - pp_end + proof_end + verify_end - ); - } -} diff --git a/examples/sha256_nivc.rs b/examples/sha256_nivc.rs index d259def011..f0bcb84a84 100644 --- a/examples/sha256_nivc.rs +++ b/examples/sha256_nivc.rs @@ -4,23 +4,26 @@ use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry}; use tracing_texray::TeXRayLayer; use lurk::{ - circuit::circuit_frame::MultiFrame, coprocessor::sha256::{Sha256Coproc, Sha256Coprocessor}, - eval::{empty_sym_env, lang::Lang}, + eval::lang::Lang, field::LurkField, + lem::{ + eval::{evaluate, make_eval_step_from_lang}, + multiframe::MultiFrame, + pointers::Ptr, + store::Store, + }, proof::{supernova::SuperNovaProver, Prover}, - ptr::Ptr, public_parameters::{ instance::{Instance, Kind}, supernova_public_params, }, state::user_sym, - store::Store, }; const REDUCTION_COUNT: usize = 10; -fn sha256_nivc(store: &mut Store, n: usize, input: &[usize]) -> Ptr { +fn sha256_nivc(store: &Store, n: usize, input: &[usize]) -> Ptr { assert_eq!(n, input.len()); let input = input .iter() @@ -48,7 +51,7 @@ fn sha256_nivc(store: &mut Store, n: usize, input: &[usize]) -> "# ); - store.read(&program).unwrap() + store.read_with_default_state(&program).unwrap() } /// Run the example in this file with @@ -64,17 +67,18 @@ fn main() { let args = std::env::args().collect::>(); let n = args.get(1).unwrap_or(&"1".into()).parse().unwrap(); - let store = &mut Store::::new(); + let store = &Store::::default(); let cproc_sym = user_sym(&format!("sha256_nivc_{n}")); let call = sha256_nivc(store, n, &(0..n).collect::>()); - let lang = Lang::>::new_with_bindings( - store, - vec![(cproc_sym, Sha256Coprocessor::new(n).into())], - ); + let mut lang = Lang::>::new(); + lang.add_coprocessor_lem(cproc_sym, Sha256Coprocessor::new(n), store); let lang_rc = Arc::new(lang.clone()); + let lurk_step = make_eval_step_from_lang(&lang, false); + let (frames, _) = evaluate(Some((&lurk_step, &lang)), call, store, 1000).unwrap(); + let supernova_prover = SuperNovaProver::, MultiFrame<'_, _, _>>::new(REDUCTION_COUNT, lang); @@ -97,7 +101,7 @@ fn main() { let (proof, z0, zi, num_steps, last_circuit_index) = tracing_texray::examine(tracing::info_span!("bang!")).in_scope(|| { supernova_prover - .evaluate_and_prove(&pp, call, empty_sym_env(store), store, 10000, lang_rc) + .prove(&pp, &frames, store, lang_rc) .unwrap() }); let proof_end = proof_start.elapsed(); @@ -116,7 +120,7 @@ fn main() { if res { println!( - "Congratulations! You proved and verified a NIVC SHA256 hash calculation in {:?} time!", + "Congratulations! You proved and verified a LEM NIVC SHA256 hash calculation in {:?} time!", pp_end + proof_end + verify_end ); } diff --git a/examples/sha256_nivc_lem.rs b/examples/sha256_nivc_lem.rs deleted file mode 100644 index c6fa5b1a1b..0000000000 --- a/examples/sha256_nivc_lem.rs +++ /dev/null @@ -1,127 +0,0 @@ -use pasta_curves::pallas::Scalar as Fr; -use std::{sync::Arc, time::Instant}; -use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry}; -use tracing_texray::TeXRayLayer; - -use lurk::{ - coprocessor::sha256::{Sha256Coproc, Sha256Coprocessor}, - eval::lang::Lang, - field::LurkField, - lem::{ - eval::{evaluate, make_eval_step_from_lang}, - multiframe::MultiFrame, - pointers::Ptr, - store::Store, - }, - proof::{supernova::SuperNovaProver, Prover}, - public_parameters::{ - instance::{Instance, Kind}, - supernova_public_params, - }, - state::user_sym, -}; - -const REDUCTION_COUNT: usize = 10; - -fn sha256_nivc(store: &Store, n: usize, input: &[usize]) -> Ptr { - assert_eq!(n, input.len()); - let input = input - .iter() - .map(|i| i.to_string()) - .collect::>() - .join(" "); - let input = format!("({})", input); - let program = format!( - r#" -(letrec ((encode-1 (lambda (term) - (let ((type (car term)) - (value (cdr term))) - (if (eq 'sha256 type) - (eval (cons 'sha256_nivc_{n} value)) - (if (eq 'lurk type) - (commit value) - (if (eq 'id type) - value)))))) - (encode (lambda (input) - (if input - (cons - (encode-1 (car input)) - (encode (cdr input))))))) - (encode '((sha256 . {input})))) -"# - ); - - store.read_with_default_state(&program).unwrap() -} - -/// Run the example in this file with -/// `cargo run --release --example sha256_nivc_lem ` -/// where `n` is the needed arity (default is 1) -fn main() { - let subscriber = Registry::default() - .with(fmt::layer().pretty()) - .with(EnvFilter::from_default_env()) - .with(TeXRayLayer::new()); - tracing::subscriber::set_global_default(subscriber).unwrap(); - - let args = std::env::args().collect::>(); - let n = args.get(1).unwrap_or(&"1".into()).parse().unwrap(); - - let store = &Store::::default(); - let cproc_sym = user_sym(&format!("sha256_nivc_{n}")); - - let call = sha256_nivc(store, n, &(0..n).collect::>()); - - let mut lang = Lang::>::new(); - lang.add_coprocessor_lem(cproc_sym, Sha256Coprocessor::new(n), store); - let lang_rc = Arc::new(lang.clone()); - - let lurk_step = make_eval_step_from_lang(&lang, false); - let (frames, _) = evaluate(Some((&lurk_step, &lang)), call, store, 1000).unwrap(); - - let supernova_prover = - SuperNovaProver::, MultiFrame<'_, _, _>>::new(REDUCTION_COUNT, lang); - - println!("Setting up running claim parameters (rc = {REDUCTION_COUNT})..."); - let pp_start = Instant::now(); - - let instance_primary = Instance::new( - REDUCTION_COUNT, - lang_rc.clone(), - true, - Kind::SuperNovaAuxParams, - ); - let pp = supernova_public_params::<_, _, MultiFrame<'_, _, _>>(&instance_primary).unwrap(); - - let pp_end = pp_start.elapsed(); - println!("Running claim parameters took {:?}", pp_end); - - println!("Beginning proof step..."); - let proof_start = Instant::now(); - let (proof, z0, zi, num_steps, last_circuit_index) = - tracing_texray::examine(tracing::info_span!("bang!")).in_scope(|| { - supernova_prover - .prove(&pp, &frames, store, lang_rc) - .unwrap() - }); - let proof_end = proof_start.elapsed(); - - println!("Proofs took {:?}", proof_end); - - println!("Verifying proof..."); - - let verify_start = Instant::now(); - let res = proof - .verify(&pp, last_circuit_index, num_steps, &z0, &zi) - .unwrap(); - let verify_end = verify_start.elapsed(); - - println!("Verify took {:?}", verify_end); - - if res { - println!( - "Congratulations! You proved and verified a LEM NIVC SHA256 hash calculation in {:?} time!", - pp_end + proof_end + verify_end - ); - } -} diff --git a/tests/lurk-nivc-test.rs b/tests/lurk-nivc-test.rs index f6cd24380a..1036a77bc1 100644 --- a/tests/lurk-nivc-test.rs +++ b/tests/lurk-nivc-test.rs @@ -1,22 +1,12 @@ use assert_cmd::prelude::*; use std::process::Command; -/// TODO: replace this test for more granular ones, specific for the NIVC -/// pipeline steps -#[test] -#[ignore] -fn test_sha256_nivc() { - let mut cmd = Command::new("cargo"); - cmd.args(["run", "--release", "--example", "sha256_nivc"]); - cmd.assert().success(); -} - /// TODO: replace this test for more granular ones, specific for the NIVC /// pipeline steps #[test] #[ignore] fn test_sha256_nivc_lem() { let mut cmd = Command::new("cargo"); - cmd.args(["run", "--release", "--example", "sha256_nivc_lem"]); + cmd.args(["run", "--release", "--example", "sha256_nivc"]); cmd.assert().success(); }