diff --git a/src/lib/crypto/kimchi_backend/pasta/pallas_based_plonk.ml b/src/lib/crypto/kimchi_backend/pasta/pallas_based_plonk.ml index cf747c75755..3c0fc37c3fb 100644 --- a/src/lib/crypto/kimchi_backend/pasta/pallas_based_plonk.ml +++ b/src/lib/crypto/kimchi_backend/pasta/pallas_based_plonk.ml @@ -34,10 +34,11 @@ end module R1CS_constraint_system = Kimchi_pasta_constraint_system.Pallas_constraint_system -let lagrange srs domain_log2 : _ Kimchi_types.poly_comm array = +let lagrange (srs : Kimchi_bindings.Protocol.SRS.Fq.t) domain_log2 : + _ Kimchi_types.poly_comm array = let domain_size = Int.pow 2 domain_log2 in - Array.init domain_size ~f:(fun i -> - Kimchi_bindings.Protocol.SRS.Fq.lagrange_commitment srs domain_size i ) + Kimchi_bindings.Protocol.SRS.Fq.lagrange_commitments_whole_domain srs + domain_size let with_lagrange f (vk : Verification_key.t) = f (lagrange vk.srs vk.domain.log_size_of_group) vk diff --git a/src/lib/crypto/kimchi_backend/pasta/vesta_based_plonk.ml b/src/lib/crypto/kimchi_backend/pasta/vesta_based_plonk.ml index 4321b8963eb..1cc6717a270 100644 --- a/src/lib/crypto/kimchi_backend/pasta/vesta_based_plonk.ml +++ b/src/lib/crypto/kimchi_backend/pasta/vesta_based_plonk.ml @@ -35,8 +35,8 @@ module R1CS_constraint_system = let lagrange srs domain_log2 : _ Kimchi_types.poly_comm array = let domain_size = Int.pow 2 domain_log2 in - Array.init domain_size ~f:(fun i -> - Kimchi_bindings.Protocol.SRS.Fp.lagrange_commitment srs domain_size i ) + Kimchi_bindings.Protocol.SRS.Fp.lagrange_commitments_whole_domain srs + domain_size let with_lagrange f (vk : Verification_key.t) = f (lagrange vk.srs vk.domain.log_size_of_group) vk diff --git a/src/lib/crypto/kimchi_bindings/stubs/kimchi_bindings.ml b/src/lib/crypto/kimchi_bindings/stubs/kimchi_bindings.ml index 07a4d89b681..7d2ebb242f8 100644 --- a/src/lib/crypto/kimchi_bindings/stubs/kimchi_bindings.ml +++ b/src/lib/crypto/kimchi_bindings/stubs/kimchi_bindings.ml @@ -107,6 +107,12 @@ module Protocol = struct -> Pasta_bindings.Fq.t Kimchi_types.or_infinity Kimchi_types.poly_comm = "caml_fp_srs_lagrange_commitment" + external lagrange_commitments_whole_domain : + t + -> int + -> Pasta_bindings.Fq.t Kimchi_types.or_infinity Kimchi_types.poly_comm + array = "caml_fp_srs_lagrange_commitments_whole_domain" + external add_lagrange_basis : t -> int -> unit = "caml_fp_srs_add_lagrange_basis" @@ -156,6 +162,12 @@ module Protocol = struct -> Pasta_bindings.Fp.t Kimchi_types.or_infinity Kimchi_types.poly_comm = "caml_fq_srs_lagrange_commitment" + external lagrange_commitments_whole_domain : + t + -> int + -> Pasta_bindings.Fp.t Kimchi_types.or_infinity Kimchi_types.poly_comm + array = "caml_fq_srs_lagrange_commitments_whole_domain" + external add_lagrange_basis : t -> int -> unit = "caml_fq_srs_add_lagrange_basis" diff --git a/src/lib/crypto/kimchi_bindings/stubs/src/lagrange_basis.rs b/src/lib/crypto/kimchi_bindings/stubs/src/lagrange_basis.rs index 818edc09776..a132e142621 100644 --- a/src/lib/crypto/kimchi_bindings/stubs/src/lagrange_basis.rs +++ b/src/lib/crypto/kimchi_bindings/stubs/src/lagrange_basis.rs @@ -6,11 +6,11 @@ use poly_commitment::{commitment::CommitmentCurve, srs::SRS}; use std::env; pub trait WithLagrangeBasis { - fn with_lagrange_basis(&mut self, domain: D); + fn with_lagrange_basis(&self, domain: D); } impl WithLagrangeBasis for SRS { - fn with_lagrange_basis(&mut self, domain: D<::ScalarField>) { + fn with_lagrange_basis(&self, domain: D<::ScalarField>) { match env::var("LAGRANGE_CACHE_DIR") { Ok(_) => add_lagrange_basis_with_cache(self, domain, cache::get_vesta_file_cache()), Err(_) => { @@ -21,7 +21,7 @@ impl WithLagrangeBasis for SRS { } impl WithLagrangeBasis for SRS { - fn with_lagrange_basis(&mut self, domain: D<::ScalarField>) { + fn with_lagrange_basis(&self, domain: D<::ScalarField>) { match env::var("LAGRANGE_CACHE_DIR") { Ok(_) => add_lagrange_basis_with_cache(self, domain, cache::get_pallas_file_cache()), Err(_) => { @@ -32,7 +32,7 @@ impl WithLagrangeBasis for SRS { } fn add_lagrange_basis_with_cache>( - srs: &mut SRS, + srs: &SRS, domain: D, cache: &C, ) { @@ -41,7 +41,7 @@ fn add_lagrange_basis_with_cache>( return; } if let Some(basis) = cache.load_lagrange_basis_from_cache(srs.g.len(), &domain) { - srs.lagrange_bases.get_or_generate(n, || { basis }); + srs.lagrange_bases.get_or_generate(n, || basis); return; } else { let basis = srs.get_lagrange_basis(domain); diff --git a/src/lib/crypto/kimchi_bindings/stubs/src/main.rs b/src/lib/crypto/kimchi_bindings/stubs/src/main.rs index 5b74b542a3f..a3421e345b6 100644 --- a/src/lib/crypto/kimchi_bindings/stubs/src/main.rs +++ b/src/lib/crypto/kimchi_bindings/stubs/src/main.rs @@ -363,6 +363,7 @@ fn generate_kimchi_bindings(mut w: impl std::io::Write, env: &mut Env) { decl_func!(w, env, caml_fp_srs_write => "write"); decl_func!(w, env, caml_fp_srs_read => "read"); decl_func!(w, env, caml_fp_srs_lagrange_commitment => "lagrange_commitment"); + decl_func!(w, env, caml_fp_srs_lagrange_commitments_whole_domain => "lagrange_commitments_whole_domain"); decl_func!(w, env, caml_fp_srs_add_lagrange_basis=> "add_lagrange_basis"); decl_func!(w, env, caml_fp_srs_commit_evaluations => "commit_evaluations"); decl_func!(w, env, caml_fp_srs_b_poly_commitment => "b_poly_commitment"); @@ -378,6 +379,7 @@ fn generate_kimchi_bindings(mut w: impl std::io::Write, env: &mut Env) { decl_func!(w, env, caml_fq_srs_write => "write"); decl_func!(w, env, caml_fq_srs_read => "read"); decl_func!(w, env, caml_fq_srs_lagrange_commitment => "lagrange_commitment"); + decl_func!(w, env, caml_fq_srs_lagrange_commitments_whole_domain => "lagrange_commitments_whole_domain"); decl_func!(w, env, caml_fq_srs_add_lagrange_basis=> "add_lagrange_basis"); decl_func!(w, env, caml_fq_srs_commit_evaluations => "commit_evaluations"); decl_func!(w, env, caml_fq_srs_b_poly_commitment => "b_poly_commitment"); diff --git a/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fp_plonk_index.rs b/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fp_plonk_index.rs index f750f8769c0..acd6f90a390 100644 --- a/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fp_plonk_index.rs +++ b/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fp_plonk_index.rs @@ -87,12 +87,7 @@ pub fn caml_pasta_fp_plonk_index_create( // endo let (endo_q, _endo_r) = poly_commitment::srs::endos::(); - // Unsafe if we are in a multi-core ocaml - { - let ptr: &mut poly_commitment::srs::SRS = - unsafe { &mut *(std::sync::Arc::as_ptr(&srs.0) as *mut _) }; - ptr.with_lagrange_basis(cs.domain.d1); - } + srs.0.with_lagrange_basis(cs.domain.d1); // create index let mut index = ProverIndex::>::create(cs, endo_q, srs.clone()); diff --git a/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fp_plonk_proof.rs b/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fp_plonk_proof.rs index dd15d0e1303..23816ccf39c 100644 --- a/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fp_plonk_proof.rs +++ b/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fp_plonk_proof.rs @@ -46,10 +46,13 @@ pub fn caml_pasta_fp_plonk_proof_create( prev_sgs: Vec, ) -> Result, ocaml::Error> { { - let ptr: &mut poly_commitment::srs::SRS = - unsafe { &mut *(std::sync::Arc::as_ptr(&index.as_ref().0.srs) as *mut _) }; - ptr.with_lagrange_basis(index.as_ref().0.cs.domain.d1); + index + .as_ref() + .0 + .srs + .with_lagrange_basis(index.as_ref().0.cs.domain.d1); } + let prev = if prev_challenges.is_empty() { Vec::new() } else { @@ -112,9 +115,11 @@ pub fn caml_pasta_fp_plonk_proof_create_and_verify( prev_sgs: Vec, ) -> Result, ocaml::Error> { { - let ptr: &mut poly_commitment::srs::SRS = - unsafe { &mut *(std::sync::Arc::as_ptr(&index.as_ref().0.srs) as *mut _) }; - ptr.with_lagrange_basis(index.as_ref().0.cs.domain.d1); + index + .as_ref() + .0 + .srs + .with_lagrange_basis(index.as_ref().0.cs.domain.d1); } let prev = if prev_challenges.is_empty() { Vec::new() @@ -199,7 +204,7 @@ pub fn caml_pasta_fp_plonk_proof_example_with_lookup( polynomial::COLUMNS, wires::Wire, }; - use poly_commitment::srs::{endos, SRS}; + use poly_commitment::srs::endos; let num_gates = 1000; let num_tables: usize = 5; @@ -276,8 +281,7 @@ pub fn caml_pasta_fp_plonk_proof_example_with_lookup( .build() .unwrap(); - let ptr: &mut SRS = unsafe { &mut *(std::sync::Arc::as_ptr(&srs.0) as *mut _) }; - ptr.with_lagrange_basis(cs.domain.d1); + srs.0.with_lagrange_basis(cs.domain.d1); let (endo_q, _endo_r) = endos::(); let index = ProverIndex::>::create(cs, endo_q, srs.0); @@ -321,7 +325,7 @@ pub fn caml_pasta_fp_plonk_proof_example_with_foreign_field_mul( use num_bigint::BigUint; use num_bigint::RandBigInt; use o1_utils::{foreign_field::BigUintForeignFieldHelpers, FieldHelpers}; - use poly_commitment::srs::{endos, SRS}; + use poly_commitment::srs::endos; use rand::{rngs::StdRng, SeedableRng}; let foreign_field_modulus = Fq::modulus_biguint(); @@ -441,8 +445,7 @@ pub fn caml_pasta_fp_plonk_proof_example_with_foreign_field_mul( // Create constraint system let cs = ConstraintSystem::::create(gates).build().unwrap(); - let ptr: &mut SRS = unsafe { &mut *(std::sync::Arc::as_ptr(&srs.0) as *mut _) }; - ptr.with_lagrange_basis(cs.domain.d1); + srs.0.with_lagrange_basis(cs.domain.d1); let (endo_q, _endo_r) = endos::(); let index = ProverIndex::>::create(cs, endo_q, srs.0); @@ -478,7 +481,7 @@ pub fn caml_pasta_fp_plonk_proof_example_with_range_check( use num_bigint::BigUint; use num_bigint::RandBigInt; use o1_utils::{foreign_field::BigUintForeignFieldHelpers, BigUintFieldHelpers}; - use poly_commitment::srs::{endos, SRS}; + use poly_commitment::srs::endos; use rand::{rngs::StdRng, SeedableRng}; let rng = &mut StdRng::from_seed([255u8; 32]); @@ -508,8 +511,7 @@ pub fn caml_pasta_fp_plonk_proof_example_with_range_check( // Create constraint system let cs = ConstraintSystem::::create(gates).build().unwrap(); - let ptr: &mut SRS = unsafe { &mut *(std::sync::Arc::as_ptr(&srs.0) as *mut _) }; - ptr.with_lagrange_basis(cs.domain.d1); + srs.0.with_lagrange_basis(cs.domain.d1); let (endo_q, _endo_r) = endos::(); let index = ProverIndex::>::create(cs, endo_q, srs.0); @@ -546,7 +548,7 @@ pub fn caml_pasta_fp_plonk_proof_example_with_range_check0( polynomials::{generic::GenericGateSpec, range_check}, wires::Wire, }; - use poly_commitment::srs::{endos, SRS}; + use poly_commitment::srs::endos; let gates = { // Public input row with value 0 @@ -581,8 +583,7 @@ pub fn caml_pasta_fp_plonk_proof_example_with_range_check0( // not sure if theres a smarter way instead of the double unwrap, but should be fine in the test let cs = ConstraintSystem::::create(gates).build().unwrap(); - let ptr: &mut SRS = unsafe { &mut *(std::sync::Arc::as_ptr(&srs.0) as *mut _) }; - ptr.with_lagrange_basis(cs.domain.d1); + srs.0.with_lagrange_basis(cs.domain.d1); let (endo_q, _endo_r) = endos::(); let index = ProverIndex::>::create(cs, endo_q, srs.0); @@ -625,7 +626,7 @@ pub fn caml_pasta_fp_plonk_proof_example_with_ffadd( wires::Wire, }; use num_bigint::BigUint; - use poly_commitment::srs::{endos, SRS}; + use poly_commitment::srs::endos; // Includes a row to store value 1 let num_public_inputs = 1; @@ -706,8 +707,7 @@ pub fn caml_pasta_fp_plonk_proof_example_with_ffadd( .build() .unwrap(); - let ptr: &mut SRS = unsafe { &mut *(std::sync::Arc::as_ptr(&srs.0) as *mut _) }; - ptr.with_lagrange_basis(cs.domain.d1); + srs.0.with_lagrange_basis(cs.domain.d1); let (endo_q, _endo_r) = endos::(); let index = ProverIndex::>::create(cs, endo_q, srs.0); @@ -747,7 +747,7 @@ pub fn caml_pasta_fp_plonk_proof_example_with_xor( polynomials::{generic::GenericGateSpec, xor}, wires::Wire, }; - use poly_commitment::srs::{endos, SRS}; + use poly_commitment::srs::endos; let num_public_inputs = 2; @@ -795,8 +795,7 @@ pub fn caml_pasta_fp_plonk_proof_example_with_xor( .build() .unwrap(); - let ptr: &mut SRS = unsafe { &mut *(std::sync::Arc::as_ptr(&srs.0) as *mut _) }; - ptr.with_lagrange_basis(cs.domain.d1); + srs.0.with_lagrange_basis(cs.domain.d1); let (endo_q, _endo_r) = endos::(); let index = ProverIndex::>::create(cs, endo_q, srs.0); @@ -839,7 +838,7 @@ pub fn caml_pasta_fp_plonk_proof_example_with_rot( }, wires::Wire, }; - use poly_commitment::srs::{endos, SRS}; + use poly_commitment::srs::endos; // Includes the actual input of the rotation and a row with the zero value let num_public_inputs = 2; @@ -889,8 +888,7 @@ pub fn caml_pasta_fp_plonk_proof_example_with_rot( .build() .unwrap(); - let ptr: &mut SRS = unsafe { &mut *(std::sync::Arc::as_ptr(&srs.0) as *mut _) }; - ptr.with_lagrange_basis(cs.domain.d1); + srs.0.with_lagrange_basis(cs.domain.d1); let (endo_q, _endo_r) = endos::(); let index = ProverIndex::>::create(cs, endo_q, srs.0); diff --git a/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fp_plonk_verifier_index.rs b/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fp_plonk_verifier_index.rs index 6f05f08773b..ed950841f3f 100644 --- a/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fp_plonk_verifier_index.rs +++ b/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fp_plonk_verifier_index.rs @@ -221,11 +221,11 @@ pub fn caml_pasta_fp_plonk_verifier_index_write( pub fn caml_pasta_fp_plonk_verifier_index_create( index: CamlPastaFpPlonkIndexPtr, ) -> CamlPastaFpPlonkVerifierIndex { - { - let ptr: &mut poly_commitment::srs::SRS = - unsafe { &mut *(std::sync::Arc::as_ptr(&index.as_ref().0.srs) as *mut _) }; - ptr.with_lagrange_basis(index.as_ref().0.cs.domain.d1); - } + index + .as_ref() + .0 + .srs + .with_lagrange_basis(index.as_ref().0.cs.domain.d1); let verifier_index = index.as_ref().0.verifier_index(); verifier_index.into() } diff --git a/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fq_plonk_index.rs b/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fq_plonk_index.rs index c1f6f50f9e9..fc360eb168b 100644 --- a/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fq_plonk_index.rs +++ b/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fq_plonk_index.rs @@ -86,12 +86,7 @@ pub fn caml_pasta_fq_plonk_index_create( // endo let (endo_q, _endo_r) = poly_commitment::srs::endos::(); - // Unsafe if we are in a multi-core ocaml - { - let ptr: &mut poly_commitment::srs::SRS = - unsafe { &mut *(std::sync::Arc::as_ptr(&srs.0) as *mut _) }; - ptr.with_lagrange_basis(cs.domain.d1); - } + srs.0.with_lagrange_basis(cs.domain.d1); // create index let mut index = ProverIndex::>::create(cs, endo_q, srs.clone()); diff --git a/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fq_plonk_proof.rs b/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fq_plonk_proof.rs index 607d28691ae..14be39c2269 100644 --- a/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fq_plonk_proof.rs +++ b/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fq_plonk_proof.rs @@ -41,9 +41,11 @@ pub fn caml_pasta_fq_plonk_proof_create( prev_sgs: Vec, ) -> Result, ocaml::Error> { { - let ptr: &mut poly_commitment::srs::SRS = - unsafe { &mut *(std::sync::Arc::as_ptr(&index.as_ref().0.srs) as *mut _) }; - ptr.with_lagrange_basis(index.as_ref().0.cs.domain.d1); + index + .as_ref() + .0 + .srs + .with_lagrange_basis(index.as_ref().0.cs.domain.d1); } let prev = if prev_challenges.is_empty() { Vec::new() diff --git a/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fq_plonk_verifier_index.rs b/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fq_plonk_verifier_index.rs index 7b81e74a7a8..5251923a42d 100644 --- a/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fq_plonk_verifier_index.rs +++ b/src/lib/crypto/kimchi_bindings/stubs/src/pasta_fq_plonk_verifier_index.rs @@ -220,11 +220,11 @@ pub fn caml_pasta_fq_plonk_verifier_index_write( pub fn caml_pasta_fq_plonk_verifier_index_create( index: CamlPastaFqPlonkIndexPtr, ) -> CamlPastaFqPlonkVerifierIndex { - { - let ptr: &mut poly_commitment::srs::SRS = - unsafe { &mut *(std::sync::Arc::as_ptr(&index.as_ref().0.srs) as *mut _) }; - ptr.with_lagrange_basis(index.as_ref().0.cs.domain.d1); - } + index + .as_ref() + .0 + .srs + .with_lagrange_basis(index.as_ref().0.cs.domain.d1); let verifier_index = index.as_ref().0.verifier_index(); verifier_index.into() } diff --git a/src/lib/crypto/kimchi_bindings/stubs/src/srs.rs b/src/lib/crypto/kimchi_bindings/stubs/src/srs.rs index e32617aeb6e..6269de0aa9d 100644 --- a/src/lib/crypto/kimchi_bindings/stubs/src/srs.rs +++ b/src/lib/crypto/kimchi_bindings/stubs/src/srs.rs @@ -1,4 +1,4 @@ -use crate::WithLagrangeBasis; +use crate::lagrange_basis::WithLagrangeBasis; use ark_poly::DenseUVPolynomial; use ark_poly::{univariate::DensePolynomial, EvaluationDomain, Evaluations}; use paste::paste; @@ -72,6 +72,18 @@ macro_rules! impl_srs { Ok(Some($name::new(srs))) } + #[ocaml_gen::func] + #[ocaml::func] + /// This is same as _lagrange_commitments, but returns the result for every + /// i <= domain_size. + pub fn [<$name:snake _lagrange_commitments_whole_domain>]( + srs: $name, + domain_size: ocaml::Int, + ) -> Result>, ocaml::Error> { + Ok(srs.get_lagrange_basis_from_domain_size(domain_size as usize).clone().into_iter().map(|x| x.into()).collect()) + } + + #[ocaml_gen::func] #[ocaml::func] pub fn [<$name:snake _lagrange_commitment>]( @@ -84,15 +96,9 @@ macro_rules! impl_srs { .err() .unwrap() })?; - - { - // We're single-threaded, so it's safe to grab this pointer as mutable. - // Do not try this at home. - let srs = unsafe { &mut *((&**srs as *const SRS<$G>) as *mut SRS<$G>) as &mut SRS<$G> }; - srs.with_lagrange_basis(x_domain); - } - - Ok(srs.get_lagrange_basis(x_domain)[i as usize].clone().into()) + srs.with_lagrange_basis(x_domain); + let vec_polycomm = srs.get_lagrange_basis_from_domain_size(domain_size as usize); + Ok(vec_polycomm[i as usize].clone().into()) } #[ocaml_gen::func] @@ -101,10 +107,8 @@ macro_rules! impl_srs { srs: $name, log2_size: ocaml::Int, ) { - let ptr: &mut poly_commitment::srs::SRS<$G> = - unsafe { &mut *(std::sync::Arc::as_ptr(&srs) as *mut _) }; let domain = EvaluationDomain::<$F>::new(1 << (log2_size as usize)).expect("invalid domain size"); - ptr.with_lagrange_basis(domain); + srs.with_lagrange_basis(domain); } #[ocaml_gen::func]