diff --git a/Cargo.lock b/Cargo.lock index 23307ecaa..c313dec64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -200,6 +200,29 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "bindgen" +version = "0.69.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +dependencies = [ + "bitflags 2.4.1", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.58", + "which", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -325,6 +348,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -358,6 +390,17 @@ dependencies = [ "half", ] +[[package]] +name = "clang-sys" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "2.34.0" @@ -394,6 +437,15 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +[[package]] +name = "cmake" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +dependencies = [ + "cc", +] + [[package]] name = "constantine-core" version = "0.1.0" @@ -623,7 +675,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -753,6 +805,43 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "icicle-bls12-381" +version = "1.9.1" +source = "git+https://github.com/ArtiomTr/icicle.git?rev=2942ad9f9894119f0204325e08ddb55b8a8de227#2942ad9f9894119f0204325e08ddb55b8a8de227" +dependencies = [ + "cmake", + "icicle-core", + "icicle-cuda-runtime", +] + +[[package]] +name = "icicle-core" +version = "1.9.1" +source = "git+https://github.com/ArtiomTr/icicle.git?rev=2942ad9f9894119f0204325e08ddb55b8a8de227#2942ad9f9894119f0204325e08ddb55b8a8de227" +dependencies = [ + "icicle-cuda-runtime", + "rayon", +] + +[[package]] +name = "icicle-cuda-runtime" +version = "1.9.1" +source = "git+https://github.com/ArtiomTr/icicle.git?rev=2942ad9f9894119f0204325e08ddb55b8a8de227#2942ad9f9894119f0204325e08ddb55b8a8de227" +dependencies = [ + "bindgen", + "bitflags 1.3.2", +] + [[package]] name = "impl-codec" version = "0.6.0" @@ -791,7 +880,7 @@ checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi 0.3.3", "rustix", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -837,7 +926,17 @@ dependencies = [ name = "kzg" version = "0.1.0" dependencies = [ + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", "blst", + "hex", + "icicle-bls12-381", + "icicle-core", + "icicle-cuda-runtime", "num_cpus", "rayon", "sha2 0.10.8", @@ -866,12 +965,28 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +[[package]] +name = "libloading" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +dependencies = [ + "cfg-if", + "windows-targets 0.48.5", +] + [[package]] name = "linux-raw-sys" version = "0.4.10" @@ -899,6 +1014,22 @@ dependencies = [ "autocfg", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "num-bigint" version = "0.3.3" @@ -1053,6 +1184,16 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "prettyplease" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7" +dependencies = [ + "proc-macro2", + "syn 2.0.58", +] + [[package]] name = "primitive-types" version = "0.12.2" @@ -1076,18 +1217,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -1139,9 +1280,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -1149,9 +1290,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -1292,6 +1433,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc-hex" version = "2.1.0" @@ -1317,7 +1464,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1374,7 +1521,7 @@ checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.58", ] [[package]] @@ -1437,6 +1584,12 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "siphasher" version = "1.0.0" @@ -1474,9 +1627,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" dependencies = [ "proc-macro2", "quote", @@ -1613,7 +1766,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.58", "wasm-bindgen-shared", ] @@ -1635,7 +1788,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.58", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1656,6 +1809,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1693,7 +1858,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.4", ] [[package]] @@ -1702,13 +1876,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] @@ -1717,42 +1906,84 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + [[package]] name = "winnow" version = "0.5.18" @@ -1788,7 +2019,7 @@ checksum = "020f3dfe25dfc38dfea49ce62d5d45ecdd7f0d8a724fa63eb36b6eba4ec76806" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.58", ] [[package]] @@ -1808,5 +2039,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.58", ] diff --git a/arkworks/Cargo.toml b/arkworks/Cargo.toml index c73c9671f..ee6e6453e 100644 --- a/arkworks/Cargo.toml +++ b/arkworks/Cargo.toml @@ -15,7 +15,7 @@ ark-serialize = { version = "^0.4.2", default-features = false } hex = "0.4.3" rand = { version = "0.8.5", optional = true } libc = { version = "0.2.148", default-features = false } -rayon = { version = "1.8.0", optional = true } +rayon = { version = "1.9.0", optional = true } [dev-dependencies] criterion = "0.5.1" @@ -47,6 +47,9 @@ bgmw = [ arkmsm = [ "kzg/arkmsm" ] +cuda = [ + "kzg/cuda" +] [[bench]] name = "fft" diff --git a/arkworks/benches/eip_4844.rs b/arkworks/benches/eip_4844.rs index 0c3d8e161..b29fdd45c 100644 --- a/arkworks/benches/eip_4844.rs +++ b/arkworks/benches/eip_4844.rs @@ -2,7 +2,7 @@ use criterion::{criterion_group, criterion_main, Criterion}; use kzg::eip_4844::{ blob_to_kzg_commitment_rust, bytes_to_blob, compute_blob_kzg_proof_rust, compute_kzg_proof_rust, verify_blob_kzg_proof_batch_rust, verify_blob_kzg_proof_rust, - verify_kzg_proof_rust, + verify_kzg_proof_rust, compute_cells_and_kzg_proofs_rust, }; use kzg_bench::benches::eip_4844::bench_eip_4844; use rust_kzg_arkworks::eip_4844::load_trusted_setup_filename_rust; @@ -21,6 +21,7 @@ fn bench_eip_4844_(c: &mut Criterion) { &compute_blob_kzg_proof_rust, &verify_blob_kzg_proof_rust, &verify_blob_kzg_proof_batch_rust, + &compute_cells_and_kzg_proofs_rust ); } diff --git a/arkworks/src/eip_4844.rs b/arkworks/src/eip_4844.rs index fb8c62284..2ded5b009 100644 --- a/arkworks/src/eip_4844.rs +++ b/arkworks/src/eip_4844.rs @@ -10,7 +10,7 @@ use kzg::eip_4844::{ verify_kzg_proof_rust, Blob, Bytes32, Bytes48, CKZGSettings, KZGCommitment, KZGProof, PrecomputationTableManager, BYTES_PER_FIELD_ELEMENT, BYTES_PER_G1, BYTES_PER_G2, C_KZG_RET, C_KZG_RET_BADARGS, C_KZG_RET_OK, FIELD_ELEMENTS_PER_BLOB, TRUSTED_SETUP_NUM_G1_POINTS, - TRUSTED_SETUP_NUM_G2_POINTS, + TRUSTED_SETUP_NUM_G2_POINTS, BYTES_PER_BLOB, }; use kzg::{cfg_into_iter, Fr, G1}; use std::ptr::null_mut; @@ -423,3 +423,18 @@ pub unsafe extern "C" fn compute_kzg_proof( (*y_out).bytes = fry_tmp.to_bytes(); C_KZG_RET_OK } + + +/// # Safety +#[no_mangle] +pub unsafe extern "C" fn compute_cells_and_kzg_proofs( + cells: *mut Cell, + proofs: *mut KZGProof, + blob: *const Blob, + s: &CKZGSettings, +) -> CKZGSettings { + // Check for null pointers + if cells.is_null() || proofs.is_null() || blob.is_null() || s.is_null() { + return C_KZG_RET_BADARGS; + } +} \ No newline at end of file diff --git a/arkworks/src/kzg_types.rs b/arkworks/src/kzg_types.rs index 1d77111b3..67ce99f66 100644 --- a/arkworks/src/kzg_types.rs +++ b/arkworks/src/kzg_types.rs @@ -17,6 +17,7 @@ use crate::utils::{ use ark_bls12_381::{g1, g2, Fr, G1Affine, G2Affine}; use ark_ec::{models::short_weierstrass::Projective, AffineRepr, Group}; use ark_ec::{CurveConfig, CurveGroup}; +use ark_ff::BigInt; use ark_ff::{biginteger::BigInteger256, BigInteger, Field}; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::{One, Zero}; @@ -840,6 +841,16 @@ impl G1Fp for ArkFp { Self(default) } + fn to_limbs(&self) -> [u64; 6] { + self.0.0.0 + } + + fn from_bytes_le(bytes: &[u8; 48]) -> Self { + let storage: [u64; 6] = bytes.chunks(8).map(|it| u64::from_le_bytes(it.try_into().unwrap())).collect::>().try_into().unwrap(); + let big_int = BigInt::new(storage); + Self(ArkFpInt::from(big_int)) + } + fn neg_assign(&mut self) { self.0 = -self.0; } diff --git a/blst/src/types/fp.rs b/blst/src/types/fp.rs index 460098a9f..877e2e2f3 100644 --- a/blst/src/types/fp.rs +++ b/blst/src/types/fp.rs @@ -29,6 +29,18 @@ impl G1Fp for FsFp { ], }); + fn to_limbs(&self) -> [u64; 6] { + self.0.l + } + + fn from_bytes_le(bytes: &[u8; 48]) -> Self { + let mut limbs = [0u64; 6]; + for i in 0..6 { + limbs[i] = u64::from_le_bytes(bytes[i*8..(i+1)*8].try_into().unwrap()); + } + Self(blst_fp { l: limbs}) + } + fn inverse(&self) -> Option { let mut out: Self = *self; unsafe { diff --git a/constantine/benches/eip_4844.rs b/constantine/benches/eip_4844.rs index cad3bd228..6e26a2e1e 100644 --- a/constantine/benches/eip_4844.rs +++ b/constantine/benches/eip_4844.rs @@ -1,8 +1,6 @@ use criterion::{criterion_group, criterion_main, Criterion}; use kzg::eip_4844::{ - blob_to_kzg_commitment_rust, bytes_to_blob, compute_blob_kzg_proof_rust, - compute_kzg_proof_rust, verify_blob_kzg_proof_batch_rust, verify_blob_kzg_proof_rust, - verify_kzg_proof_rust, + blob_to_kzg_commitment_rust, bytes_to_blob, compute_blob_kzg_proof_rust, compute_cells_and_kzg_proofs_rust, compute_kzg_proof_rust, verify_blob_kzg_proof_batch_rust, verify_blob_kzg_proof_rust, verify_kzg_proof_rust }; use kzg_bench::benches::eip_4844::bench_eip_4844; use rust_kzg_constantine::{ @@ -27,6 +25,7 @@ fn bench_eip_4844_(c: &mut Criterion) { &compute_kzg_proof_rust, &verify_kzg_proof_rust, &compute_blob_kzg_proof_rust, + &compute_cells_and_kzg_proofs_rust, &verify_blob_kzg_proof_rust, &verify_blob_kzg_proof_batch_rust, ); diff --git a/kzg-bench/src/benches/eip_4844.rs b/kzg-bench/src/benches/eip_4844.rs index 53dab60d8..e6f9e6746 100644 --- a/kzg-bench/src/benches/eip_4844.rs +++ b/kzg-bench/src/benches/eip_4844.rs @@ -24,6 +24,7 @@ pub fn bench_eip_4844< compute_kzg_proof: &dyn Fn(&[TFr], &TFr, &TKZGSettings) -> Result<(TG1, TFr), String>, verify_kzg_proof: &dyn Fn(&TG1, &TFr, &TFr, &TG1, &TKZGSettings) -> Result, compute_blob_kzg_proof: &dyn Fn(&[TFr], &TG1, &TKZGSettings) -> Result, + compute_cells_and_kzg_proofs: &dyn Fn(&[u8], &TKZGSettings) -> Result<(Vec>, Vec), String>, verify_blob_kzg_proof: &dyn Fn(&[TFr], &TG1, &TG1, &TKZGSettings) -> Result, verify_blob_kzg_proof_batch: &dyn Fn( &[Vec], @@ -100,6 +101,11 @@ pub fn bench_eip_4844< }) }); + c.bench_function("compute_cells_and_kzg_proofs", |b| { + let blob_bytes = generate_random_blob_bytes(&mut rng); + b.iter(|| compute_cells_and_kzg_proofs(&blob_bytes, &ts)) + }); + let mut group = c.benchmark_group("verify_blob_kzg_proof_batch"); for count in [1, 2, 4, 8, 16, 32, 64] { group.throughput(Throughput::Elements(count as u64)); diff --git a/kzg/Cargo.toml b/kzg/Cargo.toml index ad5fb2524..eb6c6f757 100644 --- a/kzg/Cargo.toml +++ b/kzg/Cargo.toml @@ -5,11 +5,21 @@ edition = "2021" [dependencies] blst = "0.3.11" +hex = "0.4.3" sha2 = { version = "0.10.6", default-features = false } num_cpus = { version = "1.16.0", optional = true } rayon = { version = "1.8.0", optional = true } threadpool = { version = "^1.8.1", optional = true } siphasher = { version = "1.0.0", default-features = false } +ark-std = { version = "^0.4.0", default-features = false } +ark-ec = { version = "^0.4.2", default-features = false } +ark-poly = { version = "^0.4.2", default-features = false } +ark-ff = { version = "^0.4.2", default-features = false, features = [ "asm" ] } +ark-bls12-381 = { version = "^0.4.0", default-features = false, features = [ "curve" ] } +ark-serialize = { version = "^0.4.2", default-features = false } +icicle-bls12-381 = { git = "https://github.com/ArtiomTr/icicle.git", rev = "2942ad9f9894119f0204325e08ddb55b8a8de227", version = "1.9.1", optional = true } +icicle-core = { git = "https://github.com/ArtiomTr/icicle.git", rev = "2942ad9f9894119f0204325e08ddb55b8a8de227", version = "1.9.1", optional = true } +icicle-cuda-runtime = { git = "https://github.com/ArtiomTr/icicle.git", rev = "2942ad9f9894119f0204325e08ddb55b8a8de227", version = "1.9.1", optional = true } [features] default = [ @@ -29,3 +39,9 @@ std = [ rand = [] arkmsm = [] bgmw = [] +cuda = [ + "parallel", + "dep:icicle-bls12-381", + "dep:icicle-core", + "dep:icicle-cuda-runtime" +] diff --git a/kzg/src/eip_4844.rs b/kzg/src/eip_4844.rs index 388f6dbf1..4cdfc384b 100644 --- a/kzg/src/eip_4844.rs +++ b/kzg/src/eip_4844.rs @@ -8,21 +8,25 @@ use alloc::string::ToString; use alloc::sync::Arc; use alloc::vec; use alloc::vec::Vec; - +// use sha2::digest::generic_array::sequence; +// use core::cell; +// use core::result; pub use blst::{blst_fr, blst_p1, blst_p2}; use core::ffi::c_uint; use core::hash::Hash; use core::hash::Hasher; use sha2::{Digest, Sha256}; use siphasher::sip::SipHasher; - +// use crate::kzg::{FFTFr, Fr}; use crate::common_utils::reverse_bit_order; use crate::msm::precompute::PrecomputationTable; +use crate::FFTFr; use crate::G1Affine; use crate::G1Fp; use crate::G1GetFp; use crate::G1LinComb; use crate::{FFTSettings, Fr, G1Mul, KZGSettings, PairingVerify, Poly, G1, G2}; +use crate::fk20_proofs::compute_fk20_proofs; #[cfg(feature = "parallel")] use rayon::prelude::*; @@ -57,6 +61,14 @@ pub const RANDOM_CHALLENGE_KZG_BATCH_DOMAIN: [u8; 16] = [ 82, 67, 75, 90, 71, 66, 65, 84, 67, 72, 95, 95, 95, 86, 49, 95, ]; // "RCKZGBATCH___V1_" +////////////////////////////// Constant values for EIP-7594 ////////////////////////////// +pub const FIELD_ELEMENTS_PER_EXT_BLOB: usize = 2 * FIELD_ELEMENTS_PER_BLOB; +pub const FIELD_ELEMENTS_PER_CELL: usize = 64; +pub const BYTES_PER_CELL: usize = FIELD_ELEMENTS_PER_CELL * BYTES_PER_FIELD_ELEMENT; +pub const CELLS_PER_EXT_BLOB: usize = FIELD_ELEMENTS_PER_EXT_BLOB / FIELD_ELEMENTS_PER_CELL; +pub const RANDOM_CHALLENGE_KZG_CELL_BATCH_DOMAIN: [u8; 32] = [82, 67, 95, 86, 69, 82, 73, 70, 89, 95, 67, 69, 76, 76, 95, 75, +90, 71, 95, 80, 82, 79, 79, 70, 95, 66, 65, 84, 67, 72, 95, 86,]; // "b'RCKZGCBATCH__V1_'" + ////////////////////////////// C API for EIP-4844 ////////////////////////////// pub type C_KZG_RET = c_uint; @@ -92,10 +104,19 @@ pub struct KZGCommitment { } #[repr(C)] +#[derive(Clone)] pub struct KZGProof { pub bytes: [u8; BYTES_PER_PROOF], } +impl Default for KZGProof { + fn default() -> Self { + KZGProof { + bytes: [0; BYTES_PER_PROOF], + } + } +} + #[repr(C)] pub struct CKZGSettings { pub max_width: u64, @@ -104,6 +125,29 @@ pub struct CKZGSettings { pub g2_values: *mut blst_p2, } +#[repr(C)] +#[derive(Clone)] +pub struct Cell { + bytes: [u8; BYTES_PER_CELL], +} + +impl Default for Cell { + fn default() -> Self { + Cell { + bytes: [0; BYTES_PER_CELL], + } + } +} + +impl Cell { + pub fn to_bytes(&self) -> &[u8; BYTES_PER_CELL] { + &self.bytes + } +} + +#[repr(C)] +pub struct CellIndex(u64); + pub struct PrecomputationTableManager where TFr: Fr, @@ -712,6 +756,7 @@ pub fn verify_blob_kzg_proof_batch_rust< } } + #[allow(clippy::useless_conversion)] pub fn bytes_to_blob(bytes: &[u8]) -> Result, String> { if bytes.len() != BYTES_PER_BLOB { @@ -914,3 +959,63 @@ pub fn load_trusted_setup_rust< reverse_bit_order(&mut g1_values)?; TKZGSettings::new(g1_values.as_slice(), g2_values.as_slice(), max_scale, &fs) } + +////////////////////////////// Trait based implementations of functions for EIP-7594 ////////////////////////////// +#[no_mangle] +pub extern "C" fn compute_cells_and_kzg_proofs_rust< + TFr: Fr, + TPoly: Poly, + TG1: G1 + G1Mul + G1GetFp + PairingVerify + Default, + TG2: G2, + TG1Fp: G1Fp, + TG1Affine: G1Affine, + TFFTSettings: FFTSettings + FFTFr, + TKZGSettings: KZGSettings, +>( + blob: &[TFr], + s: &TKZGSettings, +) -> Result< +( + Vec, + Vec +), String>{ + // Ensure blob length is equal to Bytes per blob + if blob.len() != BYTES_PER_BLOB { + return Err(String::from("Blob length must be BYTES_PER_BLOB")); + } + // Convert the blob to a polynomial. + let polynomial: TPoly = blob_to_polynomial(blob)?; + + // Allocate arrays to hold cells and proofs + let mut cells = vec![Cell::default(); CELLS_PER_EXT_BLOB]; + let mut proofs = vec![KZGProof::default(); CELLS_PER_EXT_BLOB]; + + // Compute cells + let mut data_fr = vec![TFr::zero(); FIELD_ELEMENTS_PER_EXT_BLOB]; + + // Perform FFT on the polynomial + data_fr = s.get_fft_settings().fft_fr(&polynomial.get_coeffs(), false)?; + + // Perform bit reversal permutation + reverse_bit_order(&mut data_fr)?; + + // Covert field elements to cell bytes + for (i, cell) in cells.iter_mut().enumerate() { + let mut cell_data = Vec::new(); + for j in 0..FIELD_ELEMENTS_PER_CELL { + let index = i * FIELD_ELEMENTS_PER_CELL + j; + let fr_bytes = data_fr[index].to_bytes(); + cell_data.extend_from_slice(&fr_bytes); + } + let cell_bytes = cell.to_bytes(); + } + + // Compute proofs + // let mut proofs_g1 = vec![TG1::identity(); CELLS_PER_EXT_BLOB]; + let mut proofs_g1 = compute_fk20_proofs::(&polynomial.get_coeffs(), FIELD_ELEMENTS_PER_BLOB, s)?; + reverse_bit_order(&mut proofs_g1)?; + + Ok((cells, proofs)) +} + + diff --git a/kzg/src/fk20_proofs.rs b/kzg/src/fk20_proofs.rs new file mode 100644 index 000000000..af108b1a3 --- /dev/null +++ b/kzg/src/fk20_proofs.rs @@ -0,0 +1,113 @@ +use crate::{eip_4844::FIELD_ELEMENTS_PER_CELL, msm::precompute, FFTSettings, Fr, G1Affine, G1Fp, G1GetFp, G1Mul, KZGSettings, Poly, G1, G2}; +use blst::blst_scalar; +use blst::{blst_fr, blst_p1, blst_p2}; + +pub fn toeplitz_coeffs_stride, Coeff: Fr>( + poly: &PolyData, + offset: usize, + stride: usize, + outlen: usize, +) -> Result { + let n = poly.len(); + + if stride == 0 { + return Err(String::from("stride must be greater than 0")); + } + + let k = n / stride; + let k2 = k * 2; + + if outlen < k2 { + return Err(String::from("outlen must be equal or greater than k2")); + } + + let mut out = PolyData::new(outlen); + out.set_coeff_at(0, &poly.get_coeffs()[n - 1 - offset]); + let mut i = 1; + while i <= (k + 1) && i < k2 { + out.set_coeff_at(i, &Fr::zero()); + i += 1; + } + let mut j = 2 * stride - offset - 1; + for i in (k + 2)..k2 { + out.set_coeff_at(i, &poly.get_coeffs()[j]); + j += stride; + } + Ok(out) +} + + +pub fn compute_fk20_proofs< + Coeff1: Fr, + Coeff2: G1 + G1Mul + G1GetFp, + Coeff3: G2, + Fs: FFTSettings, + Polynomial: Poly, + TG1Fp: G1Fp, + TG1Affine: G1Affine, + KZG: KZGSettings, + TG1: G1 + Default, +>( + p: &[Coeff1], + n: usize, + s: &KZG +) -> Result, String> { + let k = n / FIELD_ELEMENTS_PER_CELL; + let k2 = k * 2; + let mut toeplitz_coeffs: Vec<_> = vec![TG1::default(); k2]; + let mut toeplitz_coeffs_fft: Vec<_> = vec![TG1::default(); k2]; + let mut h_ext_fft: Vec<_> = vec![G1::default(); k2]; + let mut h: Vec<_> = vec![G1::default(); k2]; + + let precompute = s.wbit != 0; + let mut scratch: Option> = None; + let mut scalars: Option> = None; + + if precompute { + scratch = Some(vec![0u8; s.scratch_size]); + scalars = Some(vec![blst_scalar::default(); FIELD_ELEMENTS_PER_CELL]); + } + + let mut coeffs: Vec> = vec![vec![blst_fr::default(); k]; k2]; + + // Compute toeplitz coeffiecients and organize by column + for i in 0..FIELD_ELEMENTS_PER_CELL { + toeplitz_coeffs_stride(&PolyData::new(p.to_vec()), i, FIELD_ELEMENTS_PER_CELL, k2)?; + fr_fft(&mut toeplitz_coeffs_fft, &toeplitz_coeffs, k2, s)?; + for j in 0..k2 { + coeffs[j][i] = toeplitz_coeffs_fft[j]; + } + } + + // Compute h_ext_fft_via MSM + for i in 0..k2 { + if precompute { + let scalars = scalars.as_mut().unwrap(); + for j in 0..FIELD_ELEMENTS_PER_CELL { + blst_scalar::from_fr(&mut scalars[j], &coeffs[i][j]); + } + let scalars_arg: [&[u8]; 2] = [ + unsafe { std::slice::from_raw_parts(scalars.as_ptr() as *const u8, scalars.len() * std::mem::size_of::())}, + &[] + ]; + + unsafe { + blst::blst_p1s_mult_wbits(&mut h_ext_fft[i], s.tables[i].as_ptr(), s.wbits, FIELD_ELEMENTS_PER_CELL, scalars_arg.as_ptr(), Fr::BITS, scratch.as_mut().unwrap().as_mut_ptr()); + } + } else { + g1_lincomb_fast(&mut h_ext_fft[i], &s.x_ext_fft_columns[i], &coeffs[i], FIELD_ELEMENTS_PER_CELL)?; + } + } + g1_ifft(&mut h, &h_ext_fft, k2, s)?; + + // Zero the second half of h + for i in k..k2 { + h[i] = G1::identity(); + } + + let mut out = vec![G1::default(); k2]; + g1_fft(&mut out, &h, k2, s)?; + + Ok(out) +} + diff --git a/kzg/src/lib.rs b/kzg/src/lib.rs index 3f546fd84..209a0a6f1 100644 --- a/kzg/src/lib.rs +++ b/kzg/src/lib.rs @@ -7,9 +7,24 @@ use alloc::vec::Vec; use core::fmt::Debug; use msm::precompute::PrecomputationTable; +// pub type P1 = blst::blst_p1; +// pub type P2 = blst::blst_p2; +// pub type Fp = blst::blst_fp; + pub mod common_utils; pub mod eip_4844; pub mod msm; +pub mod fk20_proofs; +//pub mod fk20_proof; +//pub mod consts; +//pub mod kzg_types; +//pub mod utils; +//pub mod fft_g1; +// pub mod kzg_proofs; +// pub mod poly; +// pub mod recover; +// pub mod zero_poly; + pub trait Fr: Default + Clone + PartialEq + Sync { fn null() -> Self; @@ -68,6 +83,7 @@ pub trait Fr: Default + Clone + PartialEq + Sync { } fn to_scalar(&self) -> Scalar256; + } pub trait G1: Clone + Default + PartialEq + Sync + Debug + Send { @@ -132,7 +148,7 @@ pub trait G1GetFp: G1 + Clone { } pub trait G1Mul: G1 + Clone { - fn mul(&self, b: &TFr) -> Self; + fn mul(&self, b: &TFr) -> Self; } pub trait G1LinComb>: @@ -201,6 +217,10 @@ pub trait G1Fp: Clone + Default + Sync + Copy + PartialEq + Debug + Send { fn set_one(&mut self) { *self = Self::ONE; } + + fn to_limbs(&self) -> [u64; 6]; + + fn from_bytes_le(bytes: &[u8; 48]) -> Self; } pub trait G1Affine: diff --git a/kzg/src/msm/cuda.rs b/kzg/src/msm/cuda.rs new file mode 100644 index 000000000..403d4adf9 --- /dev/null +++ b/kzg/src/msm/cuda.rs @@ -0,0 +1,122 @@ +use core::marker::PhantomData; + +use icicle_bls12_381::curve::CurveCfg; +use icicle_core::{curve::Affine, msm::{precompute_bases, MSMConfig}, traits::FieldImpl}; +use icicle_cuda_runtime::{memory::HostOrDeviceSlice, device_context::{DeviceContext, DEFAULT_DEVICE_ID}}; +use core::fmt::Debug; +use crate::{Fr, G1Affine, G1Fp, G1GetFp, G1Mul, Scalar256, G1}; + +use super::msm_impls::batch_convert; + +pub struct IcicleConfig +where + TFr: Fr, + TG1: G1 + G1Mul + G1GetFp, + TG1Fp: G1Fp, + TG1Affine: G1Affine, +{ + affines: HostOrDeviceSlice<'static, Affine>, + + g1_marker: PhantomData, + g1_fp_marker: PhantomData, + fr_marker: PhantomData, + g1_affine_marker: PhantomData +} + +impl< +TFr: Fr, +TG1Fp: G1Fp, +TG1: G1 + G1Mul + G1GetFp, +TG1Affine: G1Affine, +> Debug for IcicleConfig { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + // TODO: add formatting for affines + f.debug_struct("IcicleConfig").finish() + } +} + +impl< +TFr: Fr, +TG1Fp: G1Fp, +TG1: G1 + G1Mul + G1GetFp, +TG1Affine: G1Affine, +> Clone for IcicleConfig { + fn clone(&self) -> Self { + // FIXME: affines should be cloned actually + Self { affines: HostOrDeviceSlice::Host(vec![]), g1_marker: PhantomData, g1_fp_marker: PhantomData, fr_marker: PhantomData, g1_affine_marker: PhantomData } + } +} + +const PRECOMPUTE_FACTOR: usize = 8; + +impl< + TFr: Fr, + TG1Fp: G1Fp, + TG1: G1 + G1Mul + G1GetFp, + TG1Affine: G1Affine, + > IcicleConfig +{ + pub fn new(points: &[TG1]) -> Result, String> { + let affines_raw = batch_convert::(points).iter().map(|it| icicle_bls12_381::curve::G1Affine::from_limbs(it.x().to_limbs(), it.y().to_limbs())).collect::>(); + // let Ok(mut affines) = HostOrDeviceSlice::<'static, Affine>::cuda_malloc(affines_raw.len()) else { + // return Ok(None); + // }; + // if affines.copy_from_host(&affines_raw).is_err() { + // return Ok(None); + // } + let device_affines = HostOrDeviceSlice::on_host(affines_raw); + + let Ok(mut affines) = HostOrDeviceSlice::<'static, Affine>::cuda_malloc(points.len() * PRECOMPUTE_FACTOR) else { + return Ok(None); + }; + + if precompute_bases(&device_affines, PRECOMPUTE_FACTOR as i32, 0, &DeviceContext::default_for_device(DEFAULT_DEVICE_ID), &mut affines).is_err() { + return Ok(None); + } + + Ok(Some(Self { + affines, + + fr_marker: PhantomData, + g1_fp_marker: PhantomData, + g1_marker: PhantomData, + g1_affine_marker: PhantomData + })) + } + + pub fn multiply_sequential(&self, _scalars: &[Scalar256]) -> TG1 { + panic!("No sequential implementation for CUDA MSM"); + } + + #[cfg(feature = "parallel")] + pub fn multiply_parallel(&self, scalars: &[Scalar256]) -> TG1 { + use icicle_bls12_381::curve::ScalarField; + use icicle_core::curve::Projective; + use icicle_cuda_runtime::stream::CudaStream; + + let mut results = HostOrDeviceSlice::cuda_malloc(1).unwrap(); + let mut scalars_d = HostOrDeviceSlice::cuda_malloc(scalars.len()).unwrap(); + let stream = CudaStream::create().unwrap(); + scalars_d.copy_from_host_async(&scalars.iter().map(|it| ScalarField::from_bytes_le(it.as_u8())).collect::>(), &stream).unwrap(); + let mut config = MSMConfig::default_for_device(DEFAULT_DEVICE_ID); + config.precompute_factor = PRECOMPUTE_FACTOR as i32; + config.ctx.stream = &stream; + config.is_async = true; + + icicle_core::msm::msm(&scalars_d, &self.affines, &config, &mut results).unwrap(); + + let mut results_h = vec![Projective::::zero(); 1]; + results.copy_to_host_async(&mut results_h, &stream); + + stream.synchronize().unwrap(); + stream.destroy().unwrap(); + + let mut output = TG1::default(); + + *output.x_mut() = TG1Fp::from_bytes_le(&results_h.as_slice()[0].x.to_bytes_le().try_into().unwrap()); + *output.y_mut() = TG1Fp::from_bytes_le(&results_h.as_slice()[0].y.to_bytes_le().try_into().unwrap()); + *output.z_mut() = TG1Fp::from_bytes_le(&results_h.as_slice()[0].z.to_bytes_le().try_into().unwrap()); + + output + } +} diff --git a/kzg/src/msm/mod.rs b/kzg/src/msm/mod.rs index 9167c71e3..c2fb30264 100644 --- a/kzg/src/msm/mod.rs +++ b/kzg/src/msm/mod.rs @@ -15,3 +15,11 @@ mod pippenger_utils; #[cfg(all(feature = "bgmw", any(not(feature = "arkmsm"), feature = "parallel")))] mod bgmw; + +#[cfg(feature = "cuda")] +mod cuda; + +#[cfg(all(feature = "cuda", feature = "bgmw"))] +compile_error!{"features `cuda` and `bgmw` are mutally exclusive"} +#[cfg(all(feature = "cuda", not(feature = "parallel")))] +compile_error!{"feature `cuda` requires feature `parallel`"} diff --git a/kzg/src/msm/msm_impls.rs b/kzg/src/msm/msm_impls.rs index d44a0348a..d4ca4349d 100644 --- a/kzg/src/msm/msm_impls.rs +++ b/kzg/src/msm/msm_impls.rs @@ -59,7 +59,7 @@ fn msm_sequential< } } -fn batch_convert + Sized>( +pub fn batch_convert + Sized>( points: &[TG1], ) -> Vec { #[cfg(feature = "parallel")] diff --git a/kzg/src/msm/precompute.rs b/kzg/src/msm/precompute.rs index 7eacbf98d..9a435acc1 100644 --- a/kzg/src/msm/precompute.rs +++ b/kzg/src/msm/precompute.rs @@ -9,7 +9,7 @@ pub type PrecomputationTable = super::bgmw::BgmwTable; #[cfg(any( - not(feature = "bgmw"), + all(not(feature = "bgmw"), not(feature = "cuda")), all(feature = "arkmsm", not(feature = "parallel")) ))] #[derive(Debug, Clone)] @@ -27,7 +27,7 @@ where } #[cfg(any( - not(feature = "bgmw"), + all(not(feature = "bgmw"), not(feature = "cuda")), all(feature = "arkmsm", not(feature = "parallel")) ))] impl EmptyTable @@ -52,11 +52,14 @@ where } #[cfg(any( - not(feature = "bgmw"), + all(not(feature = "bgmw"), not(feature = "cuda")), all(feature = "arkmsm", not(feature = "parallel")) ))] pub type PrecomputationTable = EmptyTable; +#[cfg(feature = "cuda")] +pub type PrecomputationTable = super::cuda::IcicleConfig; + pub fn precompute( points: &[TG1], ) -> Result>, String> diff --git a/kzg/tests/eip-7594_test.rs b/kzg/tests/eip-7594_test.rs new file mode 100644 index 000000000..9e1a5f842 --- /dev/null +++ b/kzg/tests/eip-7594_test.rs @@ -0,0 +1,23 @@ +use kzg::eip_4844::{compute_cells_and_kzg_proofs_rust, CELLS_PER_EXT_BLOB}; +use rand::Rng; +use crate::compute_cells_and_kzg_proofs; +use crate::types::{Blob, Cell, KZGProof, S}; // Adjust imports as necessary + +#[test] + +fn test_compute_cells_and_kzg_proofs() { + let mut blob = Blob::default(); + let mut cells = [Cell::default(); CELLS_PER_EXT_BLOB]; + let mut proofs: [KZGProof::default(); CELLS_PER_EXT_BLOB]; + let s = S::default(); // Assuming 's' is an instance of some struct + + // Randomly generate the blob + let mut rng = rand::thread_rng(); + for i in 0..blob.data.len() { + blob.data[i] = rng.gen(); // Assuming Blob has a data field that's a byte array + } + for _ in 0..5 { + let ret = compute_cells_and_kzg_proofs_rust(blob, s); + assert_eq!(ret, C_KZG_RET_OK); // Replace `C_KZG_OK` with the appropriate success constant or value in Rust + } +} \ No newline at end of file