diff --git a/bindings/rust/.gitignore b/bindings/rust/.gitignore index af69316..2f7896d 100644 --- a/bindings/rust/.gitignore +++ b/bindings/rust/.gitignore @@ -1,2 +1 @@ -src/bindings/generated.rs target/ diff --git a/bindings/rust/Cargo.toml b/bindings/rust/Cargo.toml index 62cbb79..e9b9f34 100644 --- a/bindings/rust/Cargo.toml +++ b/bindings/rust/Cargo.toml @@ -2,7 +2,9 @@ name = "c-kzg" version = "0.1.0" edition = "2021" -links = "ckzg" +# XXX: Note that we don't set a `links` attribute for Cargo, because this library may link +# either `ckzg` or `ckzg_min`. This allows the crate to be linked twice as minimal/mainnet variants +# without Cargo complaining. # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/bindings/rust/build.rs b/bindings/rust/build.rs index d2dba36..37d0e4f 100644 --- a/bindings/rust/build.rs +++ b/bindings/rust/build.rs @@ -125,13 +125,14 @@ fn main() { .parent() .expect("bindings dir is nested"); - let field_elements_per_blob = if cfg!(feature = "minimal-spec") { - MINIMAL_FIELD_ELEMENTS_PER_BLOB + let (lib_name, field_elements_per_blob) = if cfg!(feature = "minimal-spec") { + ("ckzg_min", MINIMAL_FIELD_ELEMENTS_PER_BLOB) } else { - MAINNET_FIELD_ELEMENTS_PER_BLOB + ("ckzg", MAINNET_FIELD_ELEMENTS_PER_BLOB) }; - eprintln!("Using FIELD_ELEMENTS_PER_BLOB={}", field_elements_per_blob); + eprintln!("Using LIB_PREFIX={lib_name}"); + eprintln!("Using FIELD_ELEMENTS_PER_BLOB={field_elements_per_blob}"); let blst_base_dir = root_dir.join("blst"); compile_blst(blst_base_dir.clone()); @@ -148,30 +149,34 @@ fn main() { cc.include(blst_headers_dir.clone()); cc.warnings(false); + cc.flag(format!("-DLIB_PREFIX={lib_name}").as_str()); cc.flag(format!("-DFIELD_ELEMENTS_PER_BLOB={}", field_elements_per_blob).as_str()); cc.file(c_src_dir.join("c_kzg_4844.c")); - cc.try_compile("ckzg").expect("Failed to compile ckzg"); + cc.try_compile(lib_name).expect("Failed to compile ckzg"); // Tell cargo to search for the static blst exposed by the blst-bindings' crate. println!("cargo:rustc-link-lib=static=blst"); - let bindings_out_path = cargo_dir.join("src").join("bindings").join("generated.rs"); + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + let bindings_out_path = out_dir.join("generated.rs"); let header_file_path = c_src_dir.join("c_kzg_4844.h"); let header_file = header_file_path.to_str().expect("valid header file"); make_bindings( + lib_name, field_elements_per_blob, header_file, &blst_headers_dir.to_string_lossy(), bindings_out_path, ); - // Finally, tell cargo this provides ckzg - println!("cargo:rustc-link-lib=ckzg"); + // Finally, tell cargo this provides ckzg/ckzg_min + println!("cargo:rustc-link-lib={lib_name}"); } fn make_bindings

( + lib_name: &str, field_elements_per_blob: usize, header_path: &str, blst_headers_dir: &str, @@ -207,11 +212,15 @@ fn make_bindings

( // -D is not supported by bindgen https://github.com/rust-lang/rust-bindgen/issues/2394 .header_contents( "consts", - &format!("#define FIELD_ELEMENTS_PER_BLOB {field_elements_per_blob}"), + &format!( + "#define LIB_PREFIX {lib_name} + #define FIELD_ELEMENTS_PER_BLOB {field_elements_per_blob}" + ), ) .header(header_path) .clang_args([format!("-I{blst_headers_dir}")]) // Since this is not part of the header file, needs to be allowed explicitly. + .allowlist_var("LIB_PREFIX") .allowlist_var("FIELD_ELEMENTS_PER_BLOB") // Get bindings only for the header file. .allowlist_file(".*c_kzg_4844.h") diff --git a/bindings/rust/src/bindings/mod.rs b/bindings/rust/src/bindings/mod.rs index d19a961..c3d7728 100644 --- a/bindings/rust/src/bindings/mod.rs +++ b/bindings/rust/src/bindings/mod.rs @@ -4,7 +4,31 @@ mod test_formats; -include!("generated.rs"); +include!(concat!(env!("OUT_DIR"), "/generated.rs")); + +#[cfg(not(feature = "minimal-spec"))] +use { + ckzg_blob_to_kzg_commitment as blob_to_kzg_commitment, + ckzg_compute_blob_kzg_proof as compute_blob_kzg_proof, + ckzg_compute_kzg_proof as compute_kzg_proof, ckzg_free_trusted_setup as free_trusted_setup, + ckzg_load_trusted_setup as load_trusted_setup, + ckzg_load_trusted_setup_file as load_trusted_setup_file, + ckzg_verify_blob_kzg_proof as verify_blob_kzg_proof, + ckzg_verify_blob_kzg_proof_batch as verify_blob_kzg_proof_batch, + ckzg_verify_kzg_proof as verify_kzg_proof, +}; +#[cfg(feature = "minimal-spec")] +use { + ckzg_min_blob_to_kzg_commitment as blob_to_kzg_commitment, + ckzg_min_compute_blob_kzg_proof as compute_blob_kzg_proof, + ckzg_min_compute_kzg_proof as compute_kzg_proof, + ckzg_min_free_trusted_setup as free_trusted_setup, + ckzg_min_load_trusted_setup as load_trusted_setup, + ckzg_min_load_trusted_setup_file as load_trusted_setup_file, + ckzg_min_verify_blob_kzg_proof as verify_blob_kzg_proof, + ckzg_min_verify_blob_kzg_proof_batch as verify_blob_kzg_proof_batch, + ckzg_min_verify_kzg_proof as verify_kzg_proof, +}; use std::ffi::CString; use std::mem::MaybeUninit; diff --git a/src/c_kzg_4844.c b/src/c_kzg_4844.c index a43d76c..7b493fd 100644 --- a/src/c_kzg_4844.c +++ b/src/c_kzg_4844.c @@ -887,7 +887,7 @@ static C_KZG_RET poly_to_kzg_commitment( * @param[in] blob The blob representing the polynomial to be committed to * @param[in] s The trusted setup */ -C_KZG_RET blob_to_kzg_commitment( +C_KZG_RET BLOB_TO_KZG_COMMITMENT( KZGCommitment *out, const Blob *blob, const KZGSettings *s ) { C_KZG_RET ret; @@ -922,7 +922,7 @@ static C_KZG_RET verify_kzg_proof_impl( * @param[in] kzg_proof The KZG proof * @param[in] s The trusted setup */ -C_KZG_RET verify_kzg_proof( +C_KZG_RET VERIFY_KZG_PROOF( bool *ok, const Bytes48 *commitment_bytes, const Bytes32 *z_bytes, @@ -1011,7 +1011,7 @@ static C_KZG_RET compute_kzg_proof_impl( * @param[in] z The generator z-value for the evaluation points * @param[in] s The trusted setup */ -C_KZG_RET compute_kzg_proof( +C_KZG_RET COMPUTE_KZG_PROOF( KZGProof *proof_out, Bytes32 *y_out, const Blob *blob, @@ -1137,7 +1137,7 @@ out: * @param[in] commitment_bytes Commitment to verify * @param[in] s The trusted setup */ -C_KZG_RET compute_blob_kzg_proof( +C_KZG_RET COMPUTE_BLOB_KZG_PROOF( KZGProof *out, const Blob *blob, const Bytes48 *commitment_bytes, @@ -1178,7 +1178,7 @@ out: * @param[in] proof_bytes Proof used for verification * @param[in] s The trusted setup */ -C_KZG_RET verify_blob_kzg_proof( +C_KZG_RET VERIFY_BLOB_KZG_PROOF( bool *ok, const Blob *blob, const Bytes48 *commitment_bytes, @@ -1391,7 +1391,7 @@ out: * @param[in] n The number of blobs/commitments/proofs * @param[in] s The trusted setup */ -C_KZG_RET verify_blob_kzg_proof_batch( +C_KZG_RET VERIFY_BLOB_KZG_PROOF_BATCH( bool *ok, const Blob *blobs, const Bytes48 *commitments_bytes, @@ -1413,7 +1413,7 @@ C_KZG_RET verify_blob_kzg_proof_batch( /* For a single blob, just do a regular single verification */ if (n == 1) { - return verify_blob_kzg_proof( + return VERIFY_BLOB_KZG_PROOF( ok, &blobs[0], &commitments_bytes[0], &proofs_bytes[0], s ); } @@ -1648,7 +1648,7 @@ out: * * @param[in] s The trusted setup to free */ -void free_trusted_setup(KZGSettings *s) { +void FREE_TRUSTED_SETUP(KZGSettings *s) { if (s == NULL) return; s->max_width = 0; c_kzg_free(s->roots_of_unity); @@ -1694,7 +1694,7 @@ static C_KZG_RET is_trusted_setup_in_lagrange_form( * @param[in] g2_bytes Array of G2 points in monomial form * @param[in] n2 Number of `g2` points in g2_bytes */ -C_KZG_RET load_trusted_setup( +C_KZG_RET LOAD_TRUSTED_SETUP( KZGSettings *out, const uint8_t *g1_bytes, size_t n1, @@ -1772,7 +1772,7 @@ out_error: * (roots_of_unity, g1_values, g2_values). It does not free the KZGSettings * structure memory. If necessary, that must be done by the caller. */ - free_trusted_setup(out); + FREE_TRUSTED_SETUP(out); out_success: return ret; } @@ -1790,7 +1790,7 @@ out_success: * @param[out] out Pointer to the loaded trusted setup data * @param[in] in File handle for input */ -C_KZG_RET load_trusted_setup_file(KZGSettings *out, FILE *in) { +C_KZG_RET LOAD_TRUSTED_SETUP_FILE(KZGSettings *out, FILE *in) { int num_matches; uint64_t i; uint8_t g1_bytes[TRUSTED_SETUP_NUM_G1_POINTS * BYTES_PER_G1]; @@ -1818,7 +1818,7 @@ C_KZG_RET load_trusted_setup_file(KZGSettings *out, FILE *in) { CHECK(num_matches == 1); } - return load_trusted_setup( + return LOAD_TRUSTED_SETUP( out, g1_bytes, TRUSTED_SETUP_NUM_G1_POINTS, diff --git a/src/c_kzg_4844.h b/src/c_kzg_4844.h index 51c4e26..9f583fe 100644 --- a/src/c_kzg_4844.h +++ b/src/c_kzg_4844.h @@ -36,6 +36,32 @@ extern "C" { // Macros /////////////////////////////////////////////////////////////////////////////// +/* + * Helper function for when LIB_PREFIX is defined. + */ +#ifdef LIB_PREFIX +#define CONCAT_IMPL(a, b) a##_##b +#define CONCAT(a, b) CONCAT_IMPL(a, b) +#define PREFIX_FUNCNAME(name) CONCAT(LIB_PREFIX, name) +#else +#define PREFIX_FUNCNAME(name) (name) +#endif /* LIB_PREFIX */ + +/* + * If LIB_PREFIX is defined, the following functions will prepend `LIB_PREFIX` + * to all public methods of this library. If LIB_PREFIX is undefined, + * everything stays as is. + */ +#define BLOB_TO_KZG_COMMITMENT PREFIX_FUNCNAME(blob_to_kzg_commitment) +#define COMPUTE_KZG_PROOF PREFIX_FUNCNAME(compute_kzg_proof) +#define COMPUTE_BLOB_KZG_PROOF PREFIX_FUNCNAME(compute_blob_kzg_proof) +#define VERIFY_KZG_PROOF PREFIX_FUNCNAME(verify_kzg_proof) +#define VERIFY_BLOB_KZG_PROOF PREFIX_FUNCNAME(verify_blob_kzg_proof) +#define VERIFY_BLOB_KZG_PROOF_BATCH PREFIX_FUNCNAME(verify_blob_kzg_proof_batch) +#define LOAD_TRUSTED_SETUP PREFIX_FUNCNAME(load_trusted_setup) +#define LOAD_TRUSTED_SETUP_FILE PREFIX_FUNCNAME(load_trusted_setup_file) +#define FREE_TRUSTED_SETUP PREFIX_FUNCNAME(free_trusted_setup) + /* * This value represents the number of field elements in a blob. It must be * supplied externally. It is expected to be 4096 for mainnet and 4 for minimal. @@ -150,7 +176,7 @@ typedef struct { // Interface functions /////////////////////////////////////////////////////////////////////////////// -C_KZG_RET load_trusted_setup( +C_KZG_RET LOAD_TRUSTED_SETUP( KZGSettings *out, const uint8_t *g1_bytes, /* n1 * 48 bytes */ size_t n1, @@ -158,15 +184,15 @@ C_KZG_RET load_trusted_setup( size_t n2 ); -C_KZG_RET load_trusted_setup_file(KZGSettings *out, FILE *in); +C_KZG_RET LOAD_TRUSTED_SETUP_FILE(KZGSettings *out, FILE *in); -void free_trusted_setup(KZGSettings *s); +void FREE_TRUSTED_SETUP(KZGSettings *s); -C_KZG_RET blob_to_kzg_commitment( +C_KZG_RET BLOB_TO_KZG_COMMITMENT( KZGCommitment *out, const Blob *blob, const KZGSettings *s ); -C_KZG_RET compute_kzg_proof( +C_KZG_RET COMPUTE_KZG_PROOF( KZGProof *proof_out, Bytes32 *y_out, const Blob *blob, @@ -174,14 +200,14 @@ C_KZG_RET compute_kzg_proof( const KZGSettings *s ); -C_KZG_RET compute_blob_kzg_proof( +C_KZG_RET COMPUTE_BLOB_KZG_PROOF( KZGProof *out, const Blob *blob, const Bytes48 *commitment_bytes, const KZGSettings *s ); -C_KZG_RET verify_kzg_proof( +C_KZG_RET VERIFY_KZG_PROOF( bool *ok, const Bytes48 *commitment_bytes, const Bytes32 *z_bytes, @@ -190,7 +216,7 @@ C_KZG_RET verify_kzg_proof( const KZGSettings *s ); -C_KZG_RET verify_blob_kzg_proof( +C_KZG_RET VERIFY_BLOB_KZG_PROOF( bool *ok, const Blob *blob, const Bytes48 *commitment_bytes, @@ -198,7 +224,7 @@ C_KZG_RET verify_blob_kzg_proof( const KZGSettings *s ); -C_KZG_RET verify_blob_kzg_proof_batch( +C_KZG_RET VERIFY_BLOB_KZG_PROOF_BATCH( bool *ok, const Blob *blobs, const Bytes48 *commitments_bytes,