From e9aa0d397f7105db523f3ee41c13381f46d9534a Mon Sep 17 00:00:00 2001 From: Ginika-Chinonso Date: Thu, 3 Jul 2025 10:20:07 +0100 Subject: [PATCH 1/6] wip --- Cargo.lock | 27 +++++++++++++++++++-------- README.md | 7 ++++--- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc22ef9..f59299b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,7 +23,7 @@ checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "circuits" version = "0.1.0" -source = "git+https://github.com/sublinearlabs/sl-core.git#fc79d9c6b30791b97868e48f8934bfed68e4b011" +source = "git+https://github.com/sublinearlabs/sl-core.git#f6ca2101de0e3734c389a4021e6012cdc052d5eb" dependencies = [ "p3-field", "p3-goldilocks", @@ -33,9 +33,9 @@ dependencies = [ [[package]] name = "crunchy" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "either" @@ -43,6 +43,15 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "fields" +version = "0.1.0" +source = "git+https://github.com/sublinearlabs/sl-core.git#f6ca2101de0e3734c389a4021e6012cdc052d5eb" +dependencies = [ + "p3-field", + "p3-mersenne-31", +] + [[package]] name = "gcd" version = "2.3.0" @@ -312,8 +321,9 @@ checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "poly" version = "0.1.0" -source = "git+https://github.com/sublinearlabs/sl-core.git#fc79d9c6b30791b97868e48f8934bfed68e4b011" +source = "git+https://github.com/sublinearlabs/sl-core.git#f6ca2101de0e3734c389a4021e6012cdc052d5eb" dependencies = [ + "fields", "p3-challenger", "p3-field", "p3-goldilocks", @@ -407,7 +417,7 @@ checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" [[package]] name = "sum_check" version = "0.1.0" -source = "git+https://github.com/sublinearlabs/sl-core.git#fc79d9c6b30791b97868e48f8934bfed68e4b011" +source = "git+https://github.com/sublinearlabs/sl-core.git#f6ca2101de0e3734c389a4021e6012cdc052d5eb" dependencies = [ "anyhow", "p3-challenger", @@ -420,9 +430,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.103" +version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ "proc-macro2", "quote", @@ -472,8 +482,9 @@ dependencies = [ [[package]] name = "transcript" version = "0.1.0" -source = "git+https://github.com/sublinearlabs/sl-core.git#fc79d9c6b30791b97868e48f8934bfed68e4b011" +source = "git+https://github.com/sublinearlabs/sl-core.git#f6ca2101de0e3734c389a4021e6012cdc052d5eb" dependencies = [ + "fields", "p3-challenger", "p3-field", "p3-keccak", diff --git a/README.md b/README.md index 8de00e1..64f7139 100644 --- a/README.md +++ b/README.md @@ -117,10 +117,11 @@ cargo test test_libra_protocol ## Performance The Libra protocol provides: -- **Prover time**: O(C log C) where C is circuit size -- **Verifier time**: O(log C) -- **Proof size**: O(log C) +- **Prover time**: O(C) +- **Verifier time**: O(d log C) +- **Proof size**: O(d log C) - **Memory usage**: Linear in circuit size +where C is circuit size and d is the circuit depth ## Contributing From a07cc6125c41301f2fa4ba222669031d75643ab0 Mon Sep 17 00:00:00 2001 From: Ginika-Chinonso Date: Fri, 4 Jul 2025 11:33:47 +0100 Subject: [PATCH 2/6] refac: update transcript and new poly creation --- src/prover.rs | 88 +++++++++++++++++-------------------- src/tests.rs | 114 ++++++++++++------------------------------------ src/utils.rs | 27 +++++++----- src/verifier.rs | 49 ++++++++------------- 4 files changed, 101 insertions(+), 177 deletions(-) diff --git a/src/prover.rs b/src/prover.rs index dba07db..5a8a5b0 100644 --- a/src/prover.rs +++ b/src/prover.rs @@ -26,18 +26,14 @@ pub fn prove>( let mut wcs = vec![]; // Get the output vector - let mut output_evals: Vec> = output.layers[circuit.layers.len()] + let output_evals: Vec> = output.layers[circuit.layers.len()] .iter() .map(|val| Fields::::Base(*val)) .collect(); - if output_evals.len() == 1 { - output_evals.push(Fields::Base(F::zero())); - } - // Build the output polynomial let output_mle = - MultilinearPoly::new_from_vec((output_evals.len() as f64).log2() as usize, output_evals); + MultilinearPoly::new_extend_to_power_of_two(output_evals, Fields::Base(F::zero())); // Adds the output to the transcript transcript.observe_base_element(&output.layers[circuit.layers.len()]); @@ -46,20 +42,20 @@ pub fn prove>( let (add_i, mul_i) = LibraGKRLayeredCircuitTr::::add_and_mul_mle(circuit, circuit.layers.len() - 1); + let w_i_plus_one_eval = output.layers[circuit.layers.len() - 1] + .iter() + .map(|val| Fields::Base(*val)) + .collect::>>(); + // Gets w_i+1 - let mut w_i_plus_one_poly = MultilinearPoly::new_from_vec( - (output.layers[circuit.layers.len() - 1].len() as f64).log2() as usize, - output.layers[circuit.layers.len() - 1] - .iter() - .map(|val| Fields::Base(*val)) - .collect::>>(), - ); + let mut w_i_plus_one_poly = + MultilinearPoly::new_extend_to_power_of_two(w_i_plus_one_eval, Fields::Base(F::zero())); // Sample random challenge for the first round let g = transcript .sample_n_challenges(output_mle.num_vars()) - .iter() - .map(|val| Fields::Extension(*val)) + .into_iter() + .map(Fields::Extension) .collect::>>(); let mut igz = generate_eq(&g); @@ -91,20 +87,18 @@ pub fn prove>( ); // Add messages to the transcript - transcript.observe_ext_element(&[wb.to_extension_field()]); - transcript.observe_ext_element(&[wc.to_extension_field()]); - transcript.observe_ext_element(&[sumcheck_proof.claimed_sum.to_extension_field()]); - transcript.observe_ext_element(&sumcheck_proof.round_polynomials.iter().fold( - vec![], - |mut acc, val| { - acc.extend( - val.iter() - .map(|val| val.to_extension_field()) - .collect::>(), - ); - acc - }, - )); + transcript.observe(&[wb]); + transcript.observe(&[wc]); + transcript.observe(&[sumcheck_proof.claimed_sum]); + transcript.observe( + &sumcheck_proof + .round_polynomials + .iter() + .fold(vec![], |mut acc, val| { + acc.extend(val); + acc + }), + ); // Adds messages to the proof sumcheck_proofs.push(sumcheck_proof); @@ -114,8 +108,8 @@ pub fn prove>( // Samples alpha and beta for folding let mut alpha_n_beta = transcript .sample_n_challenges(2) - .iter() - .map(|val| Fields::Extension(*val)) + .into_iter() + .map(Fields::Extension) .collect::>>(); for i in (1..circuit.layers.len()).rev() { @@ -125,14 +119,14 @@ pub fn prove>( claimed_sum = alpha_n_beta[0] * w_i_plus_one_poly.evaluate(&rb) + alpha_n_beta[1] * w_i_plus_one_poly.evaluate(&rc); + let w_i_plus_one_eval = output.layers[i - 1] + .iter() + .map(|val| Fields::::Base(*val)) + .collect(); + // Gets w_i+1 - w_i_plus_one_poly = MultilinearPoly::new_from_vec( - (output.layers[i - 1].len() as f64).log2() as usize, - output.layers[i - 1] - .iter() - .map(|val| Fields::::Base(*val)) - .collect(), - ); + w_i_plus_one_poly = + MultilinearPoly::new_extend_to_power_of_two(w_i_plus_one_eval, Fields::Base(F::zero())); // Fold Igz for rb and rc using alpha and beta igz = igz_n_to_1_fold(&[&rb, &rc], &alpha_n_beta); @@ -162,17 +156,13 @@ pub fn prove>( ); // Adds the messages to the transcript - transcript.observe_ext_element(&[wb.to_extension_field()]); - transcript.observe_ext_element(&[wc.to_extension_field()]); - transcript.observe_ext_element(&[sumcheck_proof.claimed_sum.to_extension_field()]); - transcript.observe_ext_element(&sumcheck_proof.round_polynomials.iter().fold( + transcript.observe(&[wb]); + transcript.observe(&[wc]); + transcript.observe(&[sumcheck_proof.claimed_sum]); + transcript.observe(&sumcheck_proof.round_polynomials.iter().fold( vec![], |mut acc, val| { - acc.extend( - val.iter() - .map(|val| val.to_extension_field()) - .collect::>(), - ); + acc.extend(val); acc }, )); @@ -185,8 +175,8 @@ pub fn prove>( // Sample alpha and beta alpha_n_beta = transcript .sample_n_challenges(2) - .iter() - .map(|val| Fields::Extension(*val)) + .into_iter() + .map(Fields::Extension) .collect::>>(); } diff --git a/src/tests.rs b/src/tests.rs index 909f8b6..7018cec 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -48,13 +48,12 @@ fn test_libra_protocol() { let input = [1, 2, 3, 2, 1, 2, 4, 1] .into_iter() - .map(Mersenne31::from_canonical_usize) - .collect::>(); + .map(F::from_canonical_usize) + .collect::>(); let output = circuit.excecute(&input); - let proof: LibraProof> = - prove(&circuit, output); + let proof: LibraProof = prove(&circuit, output); let verify = verify(&circuit, proof, input); @@ -339,30 +338,14 @@ fn test_precompute() { let precomputed = generate_eq(&challenges); let expected = [ - Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_usize(0), - )), - Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_usize(0), - )), - Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_usize(0), - )), - Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_usize(0), - )), - Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_usize(8), - )), - -Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_usize(10), - )), - -Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_usize(12), - )), - Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_usize(15), - )), + Fields::Extension(E::from_base(F::from_canonical_usize(0))), + Fields::Extension(E::from_base(F::from_canonical_usize(0))), + Fields::Extension(E::from_base(F::from_canonical_usize(0))), + Fields::Extension(E::from_base(F::from_canonical_usize(0))), + Fields::Extension(E::from_base(F::from_canonical_usize(8))), + -Fields::Extension(E::from_base(F::from_canonical_usize(10))), + -Fields::Extension(E::from_base(F::from_canonical_usize(12))), + Fields::Extension(E::from_base(F::from_canonical_usize(15))), ]; assert_eq!(precomputed, expected); @@ -393,44 +376,19 @@ fn test_build_ahg() { // f(out, left, right) in the sparse form let f1 = vec![(0, 0, 1), (1, 2, 3), (2, 4, 5), (3, 6, 7)]; - let f3 = vec![ - Fields::from_u32(3), - Fields::from_u32(4), - Fields::from_u32(5), - Fields::from_u32(6), - Fields::from_u32(7), - Fields::from_u32(8), - Fields::from_u32(9), - Fields::from_u32(10), - ]; + let f3 = Fields::::from_u32_vec(vec![3, 4, 5, 6, 7, 8, 9, 10]); let ahg = initialize_phase_one(&igz, &f1, &f3); let expected = [ - Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_u32(32), - )), - Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_u32(0), - )), - -Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_u32(60), - )), - Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_u32(0), - )), - -Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_u32(96), - )), - Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_u32(0), - )), - Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_u32(150), - )), - Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_u32(0), - )), + Fields::Extension(E::from_base(F::from_canonical_u32(32))), + Fields::Extension(E::from_base(F::from_canonical_u32(0))), + -Fields::Extension(E::from_base(F::from_canonical_u32(60))), + Fields::Extension(E::from_base(F::from_canonical_u32(0))), + -Fields::Extension(E::from_base(F::from_canonical_u32(96))), + Fields::Extension(E::from_base(F::from_canonical_u32(0))), + Fields::Extension(E::from_base(F::from_canonical_u32(150))), + Fields::Extension(E::from_base(F::from_canonical_u32(0))), ]; assert_eq!(ahg, expected); @@ -485,30 +443,14 @@ fn test_build_af1() { let af1 = initialize_phase_two(&igz, &iux, &f1); let expected = [ - Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_usize(0), - )), - -Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_usize(288), - )), - Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_usize(0), - )), - -Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_usize(420), - )), - Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_usize(0), - )), - -Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_usize(576), - )), - Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_usize(0), - )), - -Fields::Extension(BinomialExtensionField::from_base( - Mersenne31::from_canonical_usize(840), - )), + Fields::Extension(E::from_base(F::from_canonical_usize(0))), + -Fields::Extension(E::from_base(F::from_canonical_usize(288))), + Fields::Extension(E::from_base(F::from_canonical_usize(0))), + -Fields::Extension(E::from_base(F::from_canonical_usize(420))), + Fields::Extension(E::from_base(F::from_canonical_usize(0))), + -Fields::Extension(E::from_base(F::from_canonical_usize(576))), + Fields::Extension(E::from_base(F::from_canonical_usize(0))), + -Fields::Extension(E::from_base(F::from_canonical_usize(840))), ]; assert_eq!(af1, expected); diff --git a/src/utils.rs b/src/utils.rs index c4fcc4e..27dfa2d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,6 +1,6 @@ use circuits::layered_circuit::utils::get_gate_properties; use p3_field::{ExtensionField, Field}; -use poly::{Fields, MultilinearExtension, mle::MultilinearPoly, utils::generate_eq, vpoly::VPoly}; +use poly::{Fields, mle::MultilinearPoly, utils::generate_eq, vpoly::VPoly}; use std::rc::Rc; use sum_check::primitives::SumCheckProof; @@ -123,13 +123,13 @@ pub fn build_phase_one_libra_sumcheck_poly>( add_c_ahg: &[Fields], w_i_plus_one_poly: &MultilinearPoly, ) -> VPoly { - let n_vars = w_i_plus_one_poly.num_vars(); + let padding = Fields::Extension(E::zero()); VPoly::new( vec![ - MultilinearPoly::new_from_vec(n_vars, mul_ahg.to_vec()), - MultilinearPoly::new_from_vec(n_vars, add_b_ahg.to_vec()), - MultilinearPoly::new_from_vec(n_vars, add_c_ahg.to_vec()), + MultilinearPoly::new_extend_to_power_of_two(mul_ahg.to_vec(), padding), + MultilinearPoly::new_extend_to_power_of_two(add_b_ahg.to_vec(), padding), + MultilinearPoly::new_extend_to_power_of_two(add_c_ahg.to_vec(), padding), w_i_plus_one_poly.clone(), ], 2, @@ -159,13 +159,20 @@ pub fn build_phase_two_libra_sumcheck_poly>( wb: &Fields, w_i_plus_one_poly: &MultilinearPoly, ) -> VPoly { - let n_vars = w_i_plus_one_poly.num_vars(); - VPoly::new( vec![ - MultilinearPoly::new_from_vec(n_vars, mul_af1.to_vec()), - MultilinearPoly::new_from_vec(n_vars, add_af1.to_vec()), - MultilinearPoly::new_from_vec(n_vars, vec![*wb; w_i_plus_one_poly.evaluations.len()]), + MultilinearPoly::new_extend_to_power_of_two( + mul_af1.to_vec(), + Fields::Extension(E::zero()), + ), + MultilinearPoly::new_extend_to_power_of_two( + add_af1.to_vec(), + Fields::Extension(E::zero()), + ), + MultilinearPoly::new_extend_to_power_of_two( + vec![*wb; w_i_plus_one_poly.evaluations.len()], + Fields::Extension(E::zero()), + ), w_i_plus_one_poly.clone(), ], 2, diff --git a/src/verifier.rs b/src/verifier.rs index 48ccd50..925a7c5 100644 --- a/src/verifier.rs +++ b/src/verifier.rs @@ -26,13 +26,7 @@ pub fn verify>( let mut transcript = Transcript::::init(); // Adds output to the transcript - transcript.observe_base_element( - &proofs - .circuit_output - .iter() - .map(|val| val.to_base_field().unwrap()) - .collect::>(), - ); + transcript.observe(&proofs.circuit_output); // Gets output vector let mut output: Vec> = proofs.circuit_output; @@ -47,8 +41,8 @@ pub fn verify>( // Samples challenge for round one let g = transcript .sample_n_challenges(output_mle.num_vars()) - .iter() - .map(|val| Fields::Extension(*val)) + .into_iter() + .map(Fields::Extension) .collect::>>(); // Gets claimed sum by evaluating output polynomial at random challenge @@ -78,17 +72,13 @@ pub fn verify>( let mut rc = rb_n_rc[(rb_n_rc.len() / 2)..].to_vec(); // Add messages to the transcript - transcript.observe_ext_element(&[proofs.wbs[0].to_extension_field()]); - transcript.observe_ext_element(&[proofs.wcs[0].to_extension_field()]); - transcript.observe_ext_element(&[proofs.sumcheck_proofs[0].claimed_sum.to_extension_field()]); - transcript.observe_ext_element(&proofs.sumcheck_proofs[0].round_polynomials.iter().fold( + transcript.observe(&[proofs.wbs[0]]); + transcript.observe(&[proofs.wcs[0]]); + transcript.observe(&[proofs.sumcheck_proofs[0].claimed_sum]); + transcript.observe(&proofs.sumcheck_proofs[0].round_polynomials.iter().fold( vec![], |mut acc, val| { - acc.extend( - val.iter() - .map(|val| val.to_extension_field()) - .collect::>(), - ); + acc.extend(val); acc }, )); @@ -110,8 +100,8 @@ pub fn verify>( // Get alpha and beta let mut alpha_n_beta = transcript .sample_n_challenges(2) - .iter() - .map(|val| Fields::Extension(*val)) + .into_iter() + .map(Fields::Extension) .collect::>>(); // Get claimed sum for the next round by calculating: (alpha * wb) + (beta * wc) @@ -163,18 +153,13 @@ pub fn verify>( ); // Add messages to the transcript - transcript.observe_ext_element(&[proofs.wbs[i].to_extension_field()]); - transcript.observe_ext_element(&[proofs.wcs[i].to_extension_field()]); - transcript - .observe_ext_element(&[proofs.sumcheck_proofs[i].claimed_sum.to_extension_field()]); - transcript.observe_ext_element(&proofs.sumcheck_proofs[i].round_polynomials.iter().fold( + transcript.observe(&[proofs.wbs[i]]); + transcript.observe(&[proofs.wcs[i]]); + transcript.observe(&[proofs.sumcheck_proofs[i].claimed_sum]); + transcript.observe(&proofs.sumcheck_proofs[i].round_polynomials.iter().fold( vec![], |mut acc, val| { - acc.extend( - val.iter() - .map(|val| val.to_extension_field()) - .collect::>(), - ); + acc.extend(val); acc }, )); @@ -182,8 +167,8 @@ pub fn verify>( // Sample alpha and beta alpha_n_beta = transcript .sample_n_challenges(2) - .iter() - .map(|val| Fields::Extension(*val)) + .into_iter() + .map(Fields::Extension) .collect::>>(); // Get claimed sum for the next round From 528369ea9b4cf5a8c2c4db46a4740d41c85355b0 Mon Sep 17 00:00:00 2001 From: Ginika-Chinonso Date: Fri, 4 Jul 2025 14:47:43 +0100 Subject: [PATCH 3/6] refac: remove duplicate code in prover --- src/prover.rs | 117 ++++++++++++++------------------------------------ 1 file changed, 32 insertions(+), 85 deletions(-) diff --git a/src/prover.rs b/src/prover.rs index 5a8a5b0..773ba95 100644 --- a/src/prover.rs +++ b/src/prover.rs @@ -38,19 +38,6 @@ pub fn prove>( // Adds the output to the transcript transcript.observe_base_element(&output.layers[circuit.layers.len()]); - // Gets the addi and muli for the output layer - let (add_i, mul_i) = - LibraGKRLayeredCircuitTr::::add_and_mul_mle(circuit, circuit.layers.len() - 1); - - let w_i_plus_one_eval = output.layers[circuit.layers.len() - 1] - .iter() - .map(|val| Fields::Base(*val)) - .collect::>>(); - - // Gets w_i+1 - let mut w_i_plus_one_poly = - MultilinearPoly::new_extend_to_power_of_two(w_i_plus_one_eval, Fields::Base(F::zero())); - // Sample random challenge for the first round let g = transcript .sample_n_challenges(output_mle.num_vars()) @@ -58,85 +45,53 @@ pub fn prove>( .map(Fields::Extension) .collect::>>(); - let mut igz = generate_eq(&g); - - // Prepares parameters for phase one of Libra - let (mut mul_ahg, mut add_b_ahg, mut add_c_ahg) = - prepare_phase_one_params(&igz, &add_i, &mul_i, &w_i_plus_one_poly.evaluations); - - let mut claimed_sum = output_mle.evaluate(&g); - - // Proves the sumcheck relation using Libra algorithms - let (mut sumcheck_proof, mut wb, mut wc) = prove_libra_sumcheck( - ProveLibraInput { - claimed_sum: &claimed_sum, - igz: &igz, - mul_ahg: &mul_ahg, - add_b_ahg: &add_b_ahg, - add_c_ahg: &add_c_ahg, - add_i: &add_i, - mul_i: &mul_i, - w_i_plus_one_poly: &w_i_plus_one_poly, - }, - &mut transcript, - ); - - let (mut rb, mut rc) = ( - sumcheck_proof.challenges[..sumcheck_proof.challenges.len() / 2].to_vec(), - sumcheck_proof.challenges[sumcheck_proof.challenges.len() / 2..].to_vec(), - ); - - // Add messages to the transcript - transcript.observe(&[wb]); - transcript.observe(&[wc]); - transcript.observe(&[sumcheck_proof.claimed_sum]); - transcript.observe( - &sumcheck_proof - .round_polynomials - .iter() - .fold(vec![], |mut acc, val| { - acc.extend(val); - acc - }), - ); - - // Adds messages to the proof - sumcheck_proofs.push(sumcheck_proof); - wbs.push(wb); - wcs.push(wc); - - // Samples alpha and beta for folding - let mut alpha_n_beta = transcript - .sample_n_challenges(2) - .into_iter() - .map(Fields::Extension) - .collect::>>(); + let mut challenges = vec![]; + let mut wb = Fields::Extension(E::zero()); + let mut wc = Fields::Extension(E::zero()); + let mut alpha_n_beta = vec![]; + + for i in (1..=circuit.layers.len()).rev() { + let claimed_sum = if i == circuit.layers.len() { + output_mle.evaluate(&g) + } else { + // Sample alpha and beta + alpha_n_beta = transcript + .sample_n_challenges(2) + .into_iter() + .map(Fields::Extension) + .collect::>>(); + (alpha_n_beta[0] * wb) + (alpha_n_beta[1] * wc) + }; - for i in (1..circuit.layers.len()).rev() { // Get addi and muli let (add_i, mul_i) = LibraGKRLayeredCircuitTr::::add_and_mul_mle(circuit, i - 1); - claimed_sum = alpha_n_beta[0] * w_i_plus_one_poly.evaluate(&rb) - + alpha_n_beta[1] * w_i_plus_one_poly.evaluate(&rc); - let w_i_plus_one_eval = output.layers[i - 1] .iter() .map(|val| Fields::::Base(*val)) .collect(); // Gets w_i+1 - w_i_plus_one_poly = + let w_i_plus_one_poly = MultilinearPoly::new_extend_to_power_of_two(w_i_plus_one_eval, Fields::Base(F::zero())); // Fold Igz for rb and rc using alpha and beta - igz = igz_n_to_1_fold(&[&rb, &rc], &alpha_n_beta); + let igz = if i == circuit.layers.len() { + generate_eq(&g) + } else { + let (rb, rc) = ( + challenges[..challenges.len() / 2].to_vec(), + challenges[challenges.len() / 2..].to_vec(), + ); + igz_n_to_1_fold(&[&rb, &rc], &alpha_n_beta) + }; // Gets new addi and muli based on rb, rc, alpha and beta - (mul_ahg, add_b_ahg, add_c_ahg) = + let (mul_ahg, add_b_ahg, add_c_ahg) = prepare_phase_one_params(&igz, &add_i, &mul_i, &w_i_plus_one_poly.evaluations); // Proves sumcheck relation using Libra algorithms - (sumcheck_proof, wb, wc) = prove_libra_sumcheck( + let (sumcheck_proof, wb_eval, wc_eval) = prove_libra_sumcheck( ProveLibraInput { claimed_sum: &claimed_sum, igz: &igz, @@ -150,10 +105,9 @@ pub fn prove>( &mut transcript, ); - (rb, rc) = ( - sumcheck_proof.challenges[..sumcheck_proof.challenges.len() / 2].to_vec(), - sumcheck_proof.challenges[sumcheck_proof.challenges.len() / 2..].to_vec(), - ); + wb = wb_eval; + wc = wc_eval; + challenges = sumcheck_proof.challenges.to_vec(); // Adds the messages to the transcript transcript.observe(&[wb]); @@ -171,13 +125,6 @@ pub fn prove>( sumcheck_proofs.push(sumcheck_proof); wbs.push(wb); wcs.push(wc); - - // Sample alpha and beta - alpha_n_beta = transcript - .sample_n_challenges(2) - .into_iter() - .map(Fields::Extension) - .collect::>>(); } LibraProof::new( From 037a7f0d116cf4d4a2a803a8b00759c834d033cf Mon Sep 17 00:00:00 2001 From: Ginika-Chinonso Date: Mon, 7 Jul 2025 23:52:46 +0100 Subject: [PATCH 4/6] wip --- src/verifier.rs | 166 ++++++++++++++++++------------------------------ 1 file changed, 61 insertions(+), 105 deletions(-) diff --git a/src/verifier.rs b/src/verifier.rs index 925a7c5..56bd079 100644 --- a/src/verifier.rs +++ b/src/verifier.rs @@ -29,14 +29,10 @@ pub fn verify>( transcript.observe(&proofs.circuit_output); // Gets output vector - let mut output: Vec> = proofs.circuit_output; - - if output.len() == 1 { - output.push(Fields::Base(F::zero())); - } + let output: Vec> = proofs.circuit_output; // Build output polynomial - let output_mle = MultilinearPoly::new_from_vec((output.len() as f64).log2() as usize, output); + let output_mle = MultilinearPoly::new_extend_to_power_of_two(output, Fields::Base(F::zero())); // Samples challenge for round one let g = transcript @@ -48,66 +44,15 @@ pub fn verify>( // Gets claimed sum by evaluating output polynomial at random challenge let mut claimed_sum = output_mle.evaluate(&g); - // Asserts claimed sum is equal to the proof claimed sum - assert_eq!(claimed_sum, proofs.sumcheck_proofs[0].claimed_sum); - - // Verify prover sumcheck - let (sumcheck_claimed_sum, rb_n_rc) = SumCheck::>::verify_partial( - &proofs.sumcheck_proofs[0], - &mut transcript, - ); - - // Get the correct number of vars - let n_vars = compute_num_vars(circuit.layers.len() - 1, circuit.layers.len() - 1); - - // Gets addi and muli - let (add_i, mul_i) = - LibraGKRLayeredCircuitTr::::add_and_mul_mle(circuit, circuit.layers.len() - 1); - - // Gets challenges for use in oracle check - let g_bc = [g.clone(), rb_n_rc.clone()].concat(); - - let mut rb = rb_n_rc[..rb_n_rc.len() / 2].to_vec(); + let mut challenges = vec![]; - let mut rc = rb_n_rc[(rb_n_rc.len() / 2)..].to_vec(); + let mut alpha_n_beta = vec![]; - // Add messages to the transcript - transcript.observe(&[proofs.wbs[0]]); - transcript.observe(&[proofs.wcs[0]]); - transcript.observe(&[proofs.sumcheck_proofs[0].claimed_sum]); - transcript.observe(&proofs.sumcheck_proofs[0].round_polynomials.iter().fold( - vec![], - |mut acc, val| { - acc.extend(val); - acc - }, - )); - - // Calculate the expected claimed sum given wb and wc and challenges - let expected_sum = eval_layer_mle_given_wb_n_wc( - &add_i, - &mul_i, - &g_bc, - &proofs.wbs[0], - &proofs.wcs[0], - circuit.layers.len() - 1, - n_vars, - ); - - // Performs oracle check on the first round - assert_eq!(sumcheck_claimed_sum, expected_sum.to_extension_field()); - - // Get alpha and beta - let mut alpha_n_beta = transcript - .sample_n_challenges(2) - .into_iter() - .map(Fields::Extension) - .collect::>>(); + let mut rb = vec![]; - // Get claimed sum for the next round by calculating: (alpha * wb) + (beta * wc) - claimed_sum = (alpha_n_beta[0] * proofs.wbs[0]) + (alpha_n_beta[1] * proofs.wcs[0]); + let mut rc = vec![]; - for i in 1..(proofs.sumcheck_proofs.len() - 1) { + for i in 0..proofs.sumcheck_proofs.len() - 1 { // Assert claimed sum equals prover claimed sum assert_eq!(claimed_sum, proofs.sumcheck_proofs[i].claimed_sum); @@ -118,6 +63,8 @@ pub fn verify>( &mut transcript, ); + challenges = rb_n_rc; + // Get the correct number of vars let n_vars = compute_num_vars( proofs.sumcheck_proofs.len() - i - 1, @@ -131,20 +78,34 @@ pub fn verify>( ); // Calculates expected claimed sum given wb and wc values - let expected_claimed_sum = eval_new_addi_n_muli_at_rb_bc_n_rc_bc( - EvalNewAddNMulInput { - add_i: &add_i, - mul_i: &mul_i, - alpha_n_beta: &alpha_n_beta, - rb: &rb, - rc: &rc, - bc: &rb_n_rc, - wb: &proofs.wbs[i], - wc: &proofs.wcs[i], - }, - proofs.sumcheck_proofs.len() - i - 1, - n_vars, - ); + let expected_claimed_sum = if i == 0 { + let g_bc = [g.clone(), challenges.clone()].concat(); + + eval_layer_mle_given_wb_n_wc( + &add_i, + &mul_i, + &g_bc, + &proofs.wbs[0], + &proofs.wcs[0], + circuit.layers.len() - 1, + n_vars, + ) + } else { + eval_new_addi_n_muli_at_rb_bc_n_rc_bc( + EvalNewAddNMulInput { + add_i: &add_i, + mul_i: &mul_i, + alpha_n_beta: &alpha_n_beta, + rb: &rb, + rc: &rc, + bc: &challenges, + wb: &proofs.wbs[i], + wc: &proofs.wcs[i], + }, + proofs.sumcheck_proofs.len() - i - 1, + n_vars, + ) + }; // Do oracle check assert_eq!( @@ -171,12 +132,29 @@ pub fn verify>( .map(Fields::Extension) .collect::>>(); + let (wb, wc) = + // if i == proofs.sumcheck_proofs.len() { + // let input_poly: MultilinearPoly = MultilinearPoly::new_from_vec( + // (input.len() as f64).log2() as usize, + // input.iter().map(|val| Fields::Base(*val)).collect(), + // ); + + // // Calculate wb and wc on the input polynomial + // let wb = input_poly.evaluate(&challenges[..challenges.len() / 2]); + + // let wc = input_poly.evaluate(&challenges[(challenges.len() / 2)..]); + + // (wb, wc) + // } else { + // }; + (proofs.wbs[i], proofs.wcs[i]); + // Get claimed sum for the next round - claimed_sum = (alpha_n_beta[0] * proofs.wbs[i]) + (alpha_n_beta[1] * proofs.wcs[i]); + claimed_sum = (alpha_n_beta[0] * wb) + (alpha_n_beta[1] * wc); - rb = rb_n_rc[..rb_n_rc.len() / 2].to_vec(); + rb = challenges[..challenges.len() / 2].to_vec(); - rc = rb_n_rc[(rb_n_rc.len() / 2)..].to_vec(); + rc = challenges[(challenges.len() / 2)..].to_vec(); } // Verify sumcheck proof for the final round @@ -191,35 +169,13 @@ pub fn verify>( // Get the number of vars let n_vars = compute_num_vars(0, circuit.layers.len() - 1); - // Calculate expected claimed sum given wb and wc - let expected_claimed_sum = eval_new_addi_n_muli_at_rb_bc_n_rc_bc( - EvalNewAddNMulInput { - add_i: &add_i, - mul_i: &mul_i, - alpha_n_beta: &alpha_n_beta, - rb: &rb, - rc: &rc, - bc: &rb_n_rc, - wb: &proofs.wbs[proofs.sumcheck_proofs.len() - 1], - wc: &proofs.wcs[proofs.sumcheck_proofs.len() - 1], - }, - proofs.sumcheck_proofs.len() - 1, - n_vars, - ); - - // Do oracle check - assert_eq!( - sumcheck_claimed_sum, - expected_claimed_sum.to_extension_field() - ); - // Get the input polynomial - let input_poly: MultilinearPoly = MultilinearPoly::new_from_vec( - (input.len() as f64).log2() as usize, + let input_poly: MultilinearPoly = MultilinearPoly::new_extend_to_power_of_two( input.iter().map(|val| Fields::Base(*val)).collect(), + Fields::Base(F::zero()), ); - // Calculate wb and wc on the input polynomial + // // Calculate wb and wc on the input polynomial let wb = input_poly.evaluate(&rb_n_rc[..rb_n_rc.len() / 2]); let wc = input_poly.evaluate(&rb_n_rc[(rb_n_rc.len() / 2)..]); @@ -241,7 +197,7 @@ pub fn verify>( ); // Do the oracle check - assert_eq!(expected_claimed_sum, oracle_query); + assert_eq!(sumcheck_claimed_sum, oracle_query.to_extension_field()); Ok(true) } From 209b5609cbb6a6d59dbb595461ce8f9d25de8379 Mon Sep 17 00:00:00 2001 From: Ginika-Chinonso Date: Tue, 15 Jul 2025 16:59:28 +0100 Subject: [PATCH 5/6] refac: remove duplicate code in verifier --- src/verifier.rs | 98 ++++++++++++++++--------------------------------- 1 file changed, 31 insertions(+), 67 deletions(-) diff --git a/src/verifier.rs b/src/verifier.rs index 56bd079..b4b503a 100644 --- a/src/verifier.rs +++ b/src/verifier.rs @@ -44,15 +44,13 @@ pub fn verify>( // Gets claimed sum by evaluating output polynomial at random challenge let mut claimed_sum = output_mle.evaluate(&g); - let mut challenges = vec![]; - let mut alpha_n_beta = vec![]; let mut rb = vec![]; let mut rc = vec![]; - for i in 0..proofs.sumcheck_proofs.len() - 1 { + for i in 0..proofs.sumcheck_proofs.len() { // Assert claimed sum equals prover claimed sum assert_eq!(claimed_sum, proofs.sumcheck_proofs[i].claimed_sum); @@ -63,8 +61,6 @@ pub fn verify>( &mut transcript, ); - challenges = rb_n_rc; - // Get the correct number of vars let n_vars = compute_num_vars( proofs.sumcheck_proofs.len() - i - 1, @@ -79,7 +75,7 @@ pub fn verify>( // Calculates expected claimed sum given wb and wc values let expected_claimed_sum = if i == 0 { - let g_bc = [g.clone(), challenges.clone()].concat(); + let g_bc = [g.clone(), rb_n_rc.clone()].concat(); eval_layer_mle_given_wb_n_wc( &add_i, @@ -90,6 +86,31 @@ pub fn verify>( circuit.layers.len() - 1, n_vars, ) + } else if i == proofs.sumcheck_proofs.len() - 1 { + let input_poly: MultilinearPoly = MultilinearPoly::new_extend_to_power_of_two( + input.iter().map(|val| Fields::Base(*val)).collect(), + Fields::Base(F::zero()), + ); + // // Calculate wb and wc on the input polynomial + let wb = input_poly.evaluate(&rb_n_rc[..rb_n_rc.len() / 2]); + + let wc = input_poly.evaluate(&rb_n_rc[(rb_n_rc.len() / 2)..]); + + // Get the expected claimed sum + eval_new_addi_n_muli_at_rb_bc_n_rc_bc( + EvalNewAddNMulInput { + add_i: &add_i, + mul_i: &mul_i, + alpha_n_beta: &alpha_n_beta, + rb: &rb, + rc: &rc, + bc: &rb_n_rc, + wb: &wb, + wc: &wc, + }, + proofs.sumcheck_proofs.len() - 1, + n_vars, + ) } else { eval_new_addi_n_muli_at_rb_bc_n_rc_bc( EvalNewAddNMulInput { @@ -98,7 +119,7 @@ pub fn verify>( alpha_n_beta: &alpha_n_beta, rb: &rb, rc: &rc, - bc: &challenges, + bc: &rb_n_rc, wb: &proofs.wbs[i], wc: &proofs.wcs[i], }, @@ -132,72 +153,15 @@ pub fn verify>( .map(Fields::Extension) .collect::>>(); - let (wb, wc) = - // if i == proofs.sumcheck_proofs.len() { - // let input_poly: MultilinearPoly = MultilinearPoly::new_from_vec( - // (input.len() as f64).log2() as usize, - // input.iter().map(|val| Fields::Base(*val)).collect(), - // ); - - // // Calculate wb and wc on the input polynomial - // let wb = input_poly.evaluate(&challenges[..challenges.len() / 2]); - - // let wc = input_poly.evaluate(&challenges[(challenges.len() / 2)..]); - - // (wb, wc) - // } else { - // }; - (proofs.wbs[i], proofs.wcs[i]); + let (wb, wc) = (proofs.wbs[i], proofs.wcs[i]); // Get claimed sum for the next round claimed_sum = (alpha_n_beta[0] * wb) + (alpha_n_beta[1] * wc); - rb = challenges[..challenges.len() / 2].to_vec(); + rb = rb_n_rc[..rb_n_rc.len() / 2].to_vec(); - rc = challenges[(challenges.len() / 2)..].to_vec(); + rc = rb_n_rc[(rb_n_rc.len() / 2)..].to_vec(); } - // Verify sumcheck proof for the final round - let (sumcheck_claimed_sum, rb_n_rc) = SumCheck::>::verify_partial( - &proofs.sumcheck_proofs[proofs.sumcheck_proofs.len() - 1], - &mut transcript, - ); - - // Get addi and muli - let (add_i, mul_i) = LibraGKRLayeredCircuitTr::::add_and_mul_mle(circuit, 0); - - // Get the number of vars - let n_vars = compute_num_vars(0, circuit.layers.len() - 1); - - // Get the input polynomial - let input_poly: MultilinearPoly = MultilinearPoly::new_extend_to_power_of_two( - input.iter().map(|val| Fields::Base(*val)).collect(), - Fields::Base(F::zero()), - ); - - // // Calculate wb and wc on the input polynomial - let wb = input_poly.evaluate(&rb_n_rc[..rb_n_rc.len() / 2]); - - let wc = input_poly.evaluate(&rb_n_rc[(rb_n_rc.len() / 2)..]); - - // Get the expected claimed sum - let oracle_query = eval_new_addi_n_muli_at_rb_bc_n_rc_bc( - EvalNewAddNMulInput { - add_i: &add_i, - mul_i: &mul_i, - alpha_n_beta: &alpha_n_beta, - rb: &rb, - rc: &rc, - bc: &rb_n_rc, - wb: &wb, - wc: &wc, - }, - proofs.sumcheck_proofs.len() - 1, - n_vars, - ); - - // Do the oracle check - assert_eq!(sumcheck_claimed_sum, oracle_query.to_extension_field()); - Ok(true) } From 66e7738a60e5bd2e7c8ea2917f49d090cf7c93f6 Mon Sep 17 00:00:00 2001 From: Ginika-Chinonso Date: Wed, 6 Aug 2025 12:23:05 +0100 Subject: [PATCH 6/6] bench --- Cargo.lock | 568 +++++++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 10 + benches/bench.rs | 76 +++++++ 3 files changed, 640 insertions(+), 14 deletions(-) create mode 100644 benches/bench.rs diff --git a/Cargo.lock b/Cargo.lock index f59299b..2284131 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,27 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + [[package]] name = "anyhow" version = "1.0.98" @@ -14,12 +35,57 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cfg-if" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + [[package]] name = "circuits" version = "0.1.0" @@ -28,9 +94,92 @@ dependencies = [ "p3-field", "p3-goldilocks", "poly", - "rand", + "rand 0.8.5", +] + +[[package]] +name = "clap" +version = "4.5.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed87a9d530bb41a67537289bafcac159cb3ee28460e0a4571123d2a778a6a882" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.5.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64f4f3f3c77c94aff3c7e9aac9a2ca1974a5adf392a8bb751e827d6d127ab966" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_lex" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" + +[[package]] +name = "criterion" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "itertools 0.13.0", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338" +dependencies = [ + "cast", + "itertools 0.13.0", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", ] +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + [[package]] name = "crunchy" version = "0.2.4" @@ -66,7 +215,29 @@ checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + +[[package]] +name = "half" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +dependencies = [ + "cfg-if", + "crunchy", ] [[package]] @@ -87,6 +258,22 @@ dependencies = [ "either", ] +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + [[package]] name = "libc" version = "0.2.174" @@ -98,13 +285,27 @@ name = "libra" version = "0.1.0" dependencies = [ "circuits", + "criterion", "p3-field", "p3-mersenne-31", "poly", + "rand 0.9.2", "sum_check", "transcript", ] +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + [[package]] name = "num-bigint" version = "0.4.6" @@ -113,7 +314,7 @@ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", - "rand", + "rand 0.8.5", ] [[package]] @@ -143,7 +344,7 @@ dependencies = [ "num-bigint", "num-integer", "num-traits", - "rand", + "rand 0.8.5", ] [[package]] @@ -152,6 +353,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "oorandom" +version = "11.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" + [[package]] name = "p3-challenger" version = "0.2.0" @@ -191,7 +398,7 @@ dependencies = [ "num-traits", "nums", "p3-util", - "rand", + "rand 0.8.5", "serde", ] @@ -208,7 +415,7 @@ dependencies = [ "p3-poseidon2", "p3-symmetric", "p3-util", - "rand", + "rand 0.8.5", "serde", ] @@ -232,7 +439,7 @@ dependencies = [ "p3-field", "p3-maybe-rayon", "p3-util", - "rand", + "rand 0.8.5", "serde", "tracing", "transpose", @@ -256,7 +463,7 @@ dependencies = [ "p3-matrix", "p3-symmetric", "p3-util", - "rand", + "rand 0.8.5", ] [[package]] @@ -275,7 +482,7 @@ dependencies = [ "p3-poseidon2", "p3-symmetric", "p3-util", - "rand", + "rand 0.8.5", "serde", ] @@ -289,7 +496,7 @@ dependencies = [ "p3-field", "p3-mds", "p3-symmetric", - "rand", + "rand 0.8.5", ] [[package]] @@ -318,6 +525,34 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +[[package]] +name = "plotters" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" + +[[package]] +name = "plotters-svg" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" +dependencies = [ + "plotters-backend", +] + [[package]] name = "poly" version = "0.1.0" @@ -358,6 +593,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "rand" version = "0.8.5" @@ -365,8 +606,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", ] [[package]] @@ -376,7 +627,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", ] [[package]] @@ -385,7 +646,86 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", ] [[package]] @@ -408,6 +748,18 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.142" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + [[package]] name = "strength_reduce" version = "0.2.4" @@ -448,6 +800,16 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "tracing" version = "0.1.41" @@ -507,12 +869,190 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + [[package]] name = "zerocopy" version = "0.8.26" diff --git a/Cargo.toml b/Cargo.toml index c3a4c92..e41bd81 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,13 @@ transcript = {git="https://github.com/sublinearlabs/sl-core.git"} sum_check = {git="https://github.com/sublinearlabs/sl-core.git"} circuits = {git="https://github.com/sublinearlabs/sl-core.git"} p3-mersenne-31 = "0.2.0" + + +[dev-dependencies] +criterion = "0.7.0" +rand = "0.9.2" + + +[[bench]] +name = "bench" +harness = false diff --git a/benches/bench.rs b/benches/bench.rs new file mode 100644 index 0000000..26d362d --- /dev/null +++ b/benches/bench.rs @@ -0,0 +1,76 @@ +use circuits::{ + interface::CircuitTr, + layered_circuit::{ + LayeredCircuit, + primitives::{Evaluation, Gate, GateOp, Layer}, + }, +}; +use criterion::{Criterion, criterion_group, criterion_main}; +use libra::{proof::LibraProof, prover::prove, verifier::verify}; +use p3_field::{AbstractField, extension::BinomialExtensionField}; +use p3_mersenne_31::Mersenne31 as F; +use rand::Rng; + +type E = BinomialExtensionField; + +// Builds a random circuit given input size +fn build_random_circuit(input_size: usize) -> LayeredCircuit { + assert!( + input_size.is_power_of_two(), + "Input size should be a power of 2" + ); + + let n_layers = input_size.ilog2(); + + let mut layers: Vec = Vec::with_capacity(n_layers as usize); + + let mut gates_in_layer = input_size; + + for _ in 0..n_layers { + let mut gates = vec![]; + for i in 0..gates_in_layer / 2 { + let op = if rand::rng().random_bool(0.5) { + GateOp::Add + } else { + GateOp::Mul + }; + let gate = Gate::new(op, [i * 2, (i * 2) + 1]); + gates.push(gate); + } + + layers.push(Layer::new(gates)); + gates_in_layer /= 2; + } + + LayeredCircuit::new(layers) +} + +// Given input size, setup creates a circuit and inputs +// and evaluates the circuit to get the output +// Returns the circuit, input and output +pub fn setup(input_size: usize) -> (LayeredCircuit, Vec, Evaluation) { + let circuit = build_random_circuit(input_size); + + let input = rand::random_iter::() + .take(input_size) + .map(|val| F::from_canonical_usize(val as usize)) + .collect::>(); + + let output = circuit.excecute(&input); + + (circuit, input, output) +} + +fn benchmark(c: &mut Criterion) { + c.bench_function("prove_n_verify_input_64", |b| { + // TODO: fix bug for input greater that 8 + let (circuit, input, output) = setup(8); + b.iter(|| { + let proof: LibraProof = prove(&circuit, output.clone()); + let _ = verify(&circuit, proof, input.clone()); + }); + }); +} + +criterion_group!(benches, benchmark); +criterion_main!(benches);