From ee42bf8da72e6378f53176bd54d33ec9c9963d5a Mon Sep 17 00:00:00 2001 From: kevaundray Date: Fri, 16 Aug 2024 02:26:59 +0100 Subject: [PATCH] feat: Allow bindings to specify the number of threads and whether precomputation is wanted (#228) * add parameters to C code * update nim code * update csharp code * update java code * update node code * fix: golang dummy code * c code specifies num_threads as u32 * modify downstream code * golang uses uint32_t --- bindings/c/src/lib.rs | 18 ++++++--- .../csharp_code/EthKZG.bindings/ethkzg.cs | 4 +- .../EthKZG.bindings/native_methods.g.cs | 4 +- bindings/golang/prover.go | 2 +- .../java/ethereum/cryptography/LibEthKZG.java | 11 +++++- .../ethereum_cryptography_LibEthKZG.h | 4 +- bindings/java/rust_code/src/lib.rs | 6 ++- bindings/nim/nim_code/nim_eth_kzg/header.nim | 5 ++- .../nim/nim_code/nim_eth_kzg/nim_eth_kzg.nim | 4 +- bindings/node/index.d.ts | 5 +++ bindings/node/src/lib.rs | 37 +++++++++++++++++-- 11 files changed, 79 insertions(+), 21 deletions(-) diff --git a/bindings/c/src/lib.rs b/bindings/c/src/lib.rs index 9b458213..b01288b0 100644 --- a/bindings/c/src/lib.rs +++ b/bindings/c/src/lib.rs @@ -53,19 +53,27 @@ impl Deref for DASContext { /// Create a new DASContext and return a pointer to it. /// +/// `num_threads`: set to `0`` to indicate that the library should pick a sensible default. +/// /// # Memory faults /// /// To avoid memory leaks, one should ensure that the pointer is freed after use /// by calling `eth_kzg_das_context_free`. #[no_mangle] -pub extern "C" fn eth_kzg_das_context_new() -> *mut DASContext { +pub extern "C" fn eth_kzg_das_context_new(use_precomp: bool, num_threads: u32) -> *mut DASContext { + let use_precomp = if use_precomp { + rust_eth_kzg::UsePrecomp::Yes { + width: RECOMMENDED_PRECOMP_WIDTH, + } + } else { + rust_eth_kzg::UsePrecomp::No + }; + let ctx = Box::new(DASContext { inner: rust_eth_kzg::DASContext::with_threads( &rust_eth_kzg::TrustedSetup::default(), - 1, - rust_eth_kzg::UsePrecomp::Yes { - width: RECOMMENDED_PRECOMP_WIDTH, - }, + num_threads as usize, + use_precomp, ), }); Box::into_raw(ctx) diff --git a/bindings/csharp/csharp_code/EthKZG.bindings/ethkzg.cs b/bindings/csharp/csharp_code/EthKZG.bindings/ethkzg.cs index aa171242..775543d9 100644 --- a/bindings/csharp/csharp_code/EthKZG.bindings/ethkzg.cs +++ b/bindings/csharp/csharp_code/EthKZG.bindings/ethkzg.cs @@ -26,9 +26,9 @@ public sealed unsafe class EthKZG : IDisposable private DASContext* _context; - public EthKZG() + public EthKZG(bool usePrecomp = true, uint numThreads = 1) { - _context = eth_kzg_das_context_new(); + _context = eth_kzg_das_context_new(usePrecomp, numThreads); } public void Dispose() diff --git a/bindings/csharp/csharp_code/EthKZG.bindings/native_methods.g.cs b/bindings/csharp/csharp_code/EthKZG.bindings/native_methods.g.cs index bde1d73d..4751a50b 100644 --- a/bindings/csharp/csharp_code/EthKZG.bindings/native_methods.g.cs +++ b/bindings/csharp/csharp_code/EthKZG.bindings/native_methods.g.cs @@ -19,13 +19,15 @@ internal static unsafe partial class NativeMethods /// /// Create a new DASContext and return a pointer to it. /// + /// `num_threads`: set to `0`` to indicate that the library should pick a sensible default. + /// /// # Memory faults /// /// To avoid memory leaks, one should ensure that the pointer is freed after use /// by calling `eth_kzg_das_context_free`. /// [DllImport(__DllName, EntryPoint = "eth_kzg_das_context_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - internal static extern DASContext* eth_kzg_das_context_new(); + internal static extern DASContext* eth_kzg_das_context_new([MarshalAs(UnmanagedType.U1)] bool use_precomp, uint num_threads); /// /// # Safety diff --git a/bindings/golang/prover.go b/bindings/golang/prover.go index 4da542cb..71d763d9 100644 --- a/bindings/golang/prover.go +++ b/bindings/golang/prover.go @@ -46,7 +46,7 @@ type DASContext struct { } func NewProverContext() *DASContext { - self := &DASContext{_inner: C.eth_kzg_das_context_new()} + self := &DASContext{_inner: C.eth_kzg_das_context_new(C._Bool(true), C.uint32_t(1))} runtime.SetFinalizer(self, func(self *DASContext) { C.eth_kzg_das_context_free(self.inner()) diff --git a/bindings/java/java_code/src/main/java/ethereum/cryptography/LibEthKZG.java b/bindings/java/java_code/src/main/java/ethereum/cryptography/LibEthKZG.java index d2993fc5..8829a95b 100644 --- a/bindings/java/java_code/src/main/java/ethereum/cryptography/LibEthKZG.java +++ b/bindings/java/java_code/src/main/java/ethereum/cryptography/LibEthKZG.java @@ -28,7 +28,14 @@ public class LibEthKZG implements AutoCloseable{ public LibEthKZG() { ensureLibraryLoaded(); - this.contextPtr = DASContextNew(); + boolean usePrecomp = true; + long numThreads = 1; + this.contextPtr = DASContextNew(usePrecomp, numThreads); + } + + public LibEthKZG(boolean usePrecomp, long numThreads) { + ensureLibraryLoaded(); + this.contextPtr = DASContextNew(usePrecomp, numThreads); } private static void ensureLibraryLoaded() { @@ -87,7 +94,7 @@ public CellsAndProofs recoverCellsAndProofs(long[] cellIDs, byte[][] cellsArr) { * library */ - private static native long DASContextNew(); + private static native long DASContextNew(boolean usePrecomp, long numThreads); private static native void DASContextDestroy(long ctx_ptr); diff --git a/bindings/java/rust_code/ethereum_cryptography_LibEthKZG.h b/bindings/java/rust_code/ethereum_cryptography_LibEthKZG.h index 42ac2c51..3e08515b 100644 --- a/bindings/java/rust_code/ethereum_cryptography_LibEthKZG.h +++ b/bindings/java/rust_code/ethereum_cryptography_LibEthKZG.h @@ -22,10 +22,10 @@ extern "C" { /* * Class: ethereum_cryptography_LibEthKZG * Method: DASContextNew - * Signature: ()J + * Signature: (ZJ)J */ JNIEXPORT jlong JNICALL Java_ethereum_cryptography_LibEthKZG_DASContextNew - (JNIEnv *, jclass); + (JNIEnv *, jclass, jboolean, jlong); /* * Class: ethereum_cryptography_LibEthKZG diff --git a/bindings/java/rust_code/src/lib.rs b/bindings/java/rust_code/src/lib.rs index 5ca69196..54387514 100644 --- a/bindings/java/rust_code/src/lib.rs +++ b/bindings/java/rust_code/src/lib.rs @@ -10,8 +10,12 @@ use errors::Error; pub extern "system" fn Java_ethereum_cryptography_LibEthKZG_DASContextNew( _env: JNIEnv, _class: JClass, + use_precomp: jboolean, + num_threads: jlong, ) -> jlong { - c_eth_kzg::eth_kzg_das_context_new() as jlong + let use_precomp = use_precomp != 0; + let num_threads = (num_threads as u64) as u32; + c_eth_kzg::eth_kzg_das_context_new(use_precomp, num_threads) as jlong } #[no_mangle] diff --git a/bindings/nim/nim_code/nim_eth_kzg/header.nim b/bindings/nim/nim_code/nim_eth_kzg/header.nim index 6896a6b7..1ddcd23f 100644 --- a/bindings/nim/nim_code/nim_eth_kzg/header.nim +++ b/bindings/nim/nim_code/nim_eth_kzg/header.nim @@ -18,11 +18,14 @@ type CResult* = object ## Create a new DASContext and return a pointer to it. # +# `num_threads`: set to `0`` to indicate that the library should pick a sensible default. +# # # Memory faults # # To avoid memory leaks, one should ensure that the pointer is freed after use # by calling `eth_kzg_das_context_free`. -proc eth_kzg_das_context_new*(): ptr DASContext {.importc: "eth_kzg_das_context_new".} +proc eth_kzg_das_context_new*(use_precomp: bool, + num_threads: uint32): ptr DASContext {.importc: "eth_kzg_das_context_new".} ## # Safety # diff --git a/bindings/nim/nim_code/nim_eth_kzg/nim_eth_kzg.nim b/bindings/nim/nim_code/nim_eth_kzg/nim_eth_kzg.nim index 34b48c1e..0a6a92d0 100644 --- a/bindings/nim/nim_code/nim_eth_kzg/nim_eth_kzg.nim +++ b/bindings/nim/nim_code/nim_eth_kzg/nim_eth_kzg.nim @@ -84,9 +84,9 @@ proc `=destroy`(x: typeof KZGCtx()[]) = if x.ctx_ptr != nil: eth_kzg_das_context_free(x.ctx_ptr) -proc newKZGCtx*(): KZGCtx = +proc newKZGCtx*(use_precomp: bool = true, num_threads: uint32 = 1): KZGCtx = var kzgCtx = KZGCtx() - kzgCtx.ctx_ptr = eth_kzg_das_context_new() + kzgCtx.ctx_ptr = eth_kzg_das_context_new(use_precomp, num_threads) return kzgCtx diff --git a/bindings/node/index.d.ts b/bindings/node/index.d.ts index 3d90a051..a44fe3b0 100644 --- a/bindings/node/index.d.ts +++ b/bindings/node/index.d.ts @@ -9,6 +9,10 @@ export const BYTES_PER_FIELD_ELEMENT: number export const BYTES_PER_BLOB: number export const MAX_NUM_COLUMNS: number export const BYTES_PER_CELL: number +export interface DasContextOptions { + usePrecomp: boolean + numThreads: number +} export class CellsAndProofs { cells: Array proofs: Array @@ -16,6 +20,7 @@ export class CellsAndProofs { export type DASContextJs = DasContextJs export class DasContextJs { constructor() + static create(options: DasContextOptions): DasContextJs blobToKzgCommitment(blob: Uint8Array): Uint8Array asyncBlobToKzgCommitment(blob: Uint8Array): Promise computeCellsAndKzgProofs(blob: Uint8Array): CellsAndProofs diff --git a/bindings/node/src/lib.rs b/bindings/node/src/lib.rs index 45d3c958..ae37a845 100644 --- a/bindings/node/src/lib.rs +++ b/bindings/node/src/lib.rs @@ -41,17 +41,46 @@ impl Default for DASContextJs { } } +#[napi(object)] +pub struct DASContextOptions { + pub use_precomp: bool, + pub num_threads: u32, +} + +impl Default for DASContextOptions { + fn default() -> Self { + Self { + use_precomp: true, + num_threads: 1, + } + } +} + #[napi] impl DASContextJs { #[napi(constructor)] pub fn new() -> Self { + Self::create(DASContextOptions::default()) + } + + #[napi(factory)] + pub fn create(options: DASContextOptions) -> Self { + let use_precomp = options.use_precomp; + let num_threads = options.num_threads; + + let precomp = if use_precomp { + UsePrecomp::Yes { + width: RECOMMENDED_PRECOMP_WIDTH, + } + } else { + UsePrecomp::No + }; + DASContextJs { inner: Arc::new(DASContext::with_threads( &TrustedSetup::default(), - 1, - UsePrecomp::Yes { - width: RECOMMENDED_PRECOMP_WIDTH, - }, + num_threads as usize, + precomp, )), } }