diff --git a/barretenberg/acir_tests/yarn.lock b/barretenberg/acir_tests/yarn.lock index 8608993b859f..4070613de6d4 100644 --- a/barretenberg/acir_tests/yarn.lock +++ b/barretenberg/acir_tests/yarn.lock @@ -24,6 +24,7 @@ __metadata: version: 0.0.0-use.local resolution: "@aztec/bb.js@portal:../../ts::locator=bbjs-test%40workspace%3Abbjs-test" dependencies: + "@aztec/ipc-runtime": "portal:../../ipc-runtime/ts" comlink: "npm:^4.4.1" commander: "npm:^12.1.0" idb-keyval: "npm:^6.2.1" @@ -39,6 +40,7 @@ __metadata: version: 0.0.0-use.local resolution: "@aztec/bb.js@portal:../../ts::locator=browser-test-app%40workspace%3Abrowser-test-app" dependencies: + "@aztec/ipc-runtime": "portal:../../ipc-runtime/ts" comlink: "npm:^4.4.1" commander: "npm:^12.1.0" idb-keyval: "npm:^6.2.1" @@ -50,6 +52,18 @@ __metadata: languageName: node linkType: soft +"@aztec/ipc-runtime@portal:../../ipc-runtime/ts::locator=%40aztec%2Fbb.js%40portal%3A..%2F..%2Fts%3A%3Alocator%3Dbbjs-test%2540workspace%253Abbjs-test": + version: 0.0.0-use.local + resolution: "@aztec/ipc-runtime@portal:../../ipc-runtime/ts::locator=%40aztec%2Fbb.js%40portal%3A..%2F..%2Fts%3A%3Alocator%3Dbbjs-test%2540workspace%253Abbjs-test" + languageName: node + linkType: soft + +"@aztec/ipc-runtime@portal:../../ipc-runtime/ts::locator=%40aztec%2Fbb.js%40portal%3A..%2F..%2Fts%3A%3Alocator%3Dbrowser-test-app%2540workspace%253Abrowser-test-app": + version: 0.0.0-use.local + resolution: "@aztec/ipc-runtime@portal:../../ipc-runtime/ts::locator=%40aztec%2Fbb.js%40portal%3A..%2F..%2Fts%3A%3Alocator%3Dbrowser-test-app%2540workspace%253Abrowser-test-app" + languageName: node + linkType: soft + "@babel/code-frame@npm:^7.0.0": version: 7.26.2 resolution: "@babel/code-frame@npm:7.26.2" diff --git a/barretenberg/cpp/src/barretenberg/bbapi/c_bind.cpp b/barretenberg/cpp/src/barretenberg/bbapi/c_bind.cpp index b696c7c60db3..756e3e3e352f 100644 --- a/barretenberg/cpp/src/barretenberg/bbapi/c_bind.cpp +++ b/barretenberg/cpp/src/barretenberg/bbapi/c_bind.cpp @@ -17,12 +17,15 @@ BBApiRequest global_request; } // namespace bb::bbapi -// WASM-exported bbapi entry point. Takes msgpack-encoded `[ [name, payload] ]` +// WASM-exported FFI entry point. Takes msgpack-encoded `[ [name, payload] ]` // (tuple-wrapped command in NamedUnion shape), returns msgpack-encoded // `[name, payload]` (response in NamedUnion shape). The codegen-emitted // dispatcher owns the command-name → handle_ table and runs the // per-call deserialize / serialize / exception → ErrorResponse plumbing. -WASM_EXPORT void bbapi(const uint8_t* input_in, size_t input_len_in, uint8_t** output_out, size_t* output_len_out) +WASM_EXPORT void ipc_ffi_entry(const uint8_t* input_in, + size_t input_len_in, + uint8_t** output_out, + size_t* output_len_out) { auto handler = bb::bbapi::make_bb_handler(bb::bbapi::global_request); std::vector input(input_in, input_in + input_len_in); diff --git a/barretenberg/cpp/src/barretenberg/bbapi/c_bind.hpp b/barretenberg/cpp/src/barretenberg/bbapi/c_bind.hpp index e21767f5cd89..79b0014bd5b4 100644 --- a/barretenberg/cpp/src/barretenberg/bbapi/c_bind.hpp +++ b/barretenberg/cpp/src/barretenberg/bbapi/c_bind.hpp @@ -2,7 +2,7 @@ #include "barretenberg/serialize/cbind_fwd.hpp" #include -// WASM-exported bbapi entry point. Takes msgpack `[ [name, payload] ]`, +// WASM-exported FFI entry point. Takes msgpack `[ [name, payload] ]`, // returns msgpack `[name, payload]`. See c_bind.cpp for the implementation // (calls the codegen-emitted `make_bb_handler` dispatcher). -CBIND_DECL(bbapi) +CBIND_DECL(ipc_ffi_entry) diff --git a/barretenberg/rust/Cargo.toml b/barretenberg/rust/Cargo.toml index 4ba3a07b7118..40a56d508b7a 100644 --- a/barretenberg/rust/Cargo.toml +++ b/barretenberg/rust/Cargo.toml @@ -17,17 +17,12 @@ rmp-serde = "1.1" rmpv = "1.0" serde = { version = "1.0", features = ["derive"] } -# Async runtime -tokio = { version = "1.35", features = ["full"] } - # IPC and system libc = "0.2" -nix = { version = "0.27", features = ["socket", "uio"] } # Testing criterion = "0.5" # Utilities thiserror = "1.0" -tracing = "0.1" hex = "0.4" diff --git a/barretenberg/rust/barretenberg-rs/Cargo.toml b/barretenberg/rust/barretenberg-rs/Cargo.toml index f637a2a82a56..9334f2b73b15 100644 --- a/barretenberg/rust/barretenberg-rs/Cargo.toml +++ b/barretenberg/rust/barretenberg-rs/Cargo.toml @@ -21,21 +21,17 @@ rmp-serde.workspace = true rmpv.workspace = true serde.workspace = true -# Async runtime -tokio = { workspace = true, optional = true } - # IPC and system libc.workspace = true -nix = { workspace = true, optional = true } + +# UDS / MPSC-SHM transport for the codegen-generated Backend bridge. +ipc-runtime = { path = "../../../ipc-runtime/rust" } # Utilities thiserror.workspace = true -tracing = { workspace = true, optional = true } hex.workspace = true [features] -default = ["native", "ffi"] -native = ["tokio", "nix", "tracing"] -async = ["tokio"] +default = ["ffi"] # FFI backend - links against libbarretenberg from cpp build ffi = [] diff --git a/barretenberg/rust/barretenberg-rs/src/backend.rs b/barretenberg/rust/barretenberg-rs/src/backend.rs deleted file mode 100644 index 75eef08387c3..000000000000 --- a/barretenberg/rust/barretenberg-rs/src/backend.rs +++ /dev/null @@ -1,44 +0,0 @@ -//! Backend trait for msgpack communication -//! -//! This module defines a simple, pluggable interface for Barretenberg backends. -//! Users can easily implement custom backends (FFI, WASM, IPC, etc.). - -use crate::error::Result; - -/// Simple interface for msgpack backend implementations. -/// -/// Implement this trait to create a custom backend for Barretenberg. -/// The backend handles msgpack-encoded command/response communication. -/// -/// # Example -/// -/// ```ignore -/// struct MyCustomBackend { -/// // your FFI handle, connection, etc. -/// } -/// -/// impl Backend for MyCustomBackend { -/// fn call(&mut self, input: &[u8]) -> Result> { -/// // Send input to your backend -/// // Return the response -/// } -/// -/// fn destroy(&mut self) -> Result<()> { -/// // Clean up resources -/// Ok(()) -/// } -/// } -/// ``` -pub trait Backend { - /// Execute a msgpack command and return the msgpack response. - /// - /// # Arguments - /// * `input` - Msgpack-encoded command - /// - /// # Returns - /// Msgpack-encoded response - fn call(&mut self, input: &[u8]) -> Result>; - - /// Clean up resources and shutdown the backend. - fn destroy(&mut self) -> Result<()>; -} diff --git a/barretenberg/rust/barretenberg-rs/src/backends/ffi.rs b/barretenberg/rust/barretenberg-rs/src/backends/ffi.rs deleted file mode 100644 index 22a4243d92ef..000000000000 --- a/barretenberg/rust/barretenberg-rs/src/backends/ffi.rs +++ /dev/null @@ -1,163 +0,0 @@ -//! FFI backend for Barretenberg -//! -//! This backend calls the Barretenberg C API directly via FFI, -//! eliminating process spawn overhead. Ideal for mobile and embedded use cases. -//! -//! # Requirements -//! -//! This backend requires linking against `libbarretenberg`. You must: -//! 1. Build Barretenberg as a static library (`libbarretenberg.a`) -//! 2. Configure the library search path, either via: -//! - `.cargo/config.toml`: `[build] rustflags = ["-L", "/path/to/lib"]` -//! - Environment: `RUSTFLAGS="-L /path/to/lib"` -//! -//! # Example -//! -//! ```ignore -//! use barretenberg_rs::{BarretenbergApi, backends::FfiBackend}; -//! -//! let backend = FfiBackend::new()?; -//! let mut api = BarretenbergApi::new(backend); -//! -//! let response = api.blake2s(b"hello world")?; -//! println!("Hash: {:?}", response.hash); -//! ``` - -use crate::backend::Backend; -use crate::error::{BarretenbergError, Result}; -use std::ptr; - -// C API exported by Barretenberg -// See: barretenberg/cpp/src/barretenberg/bbapi/c_bind.hpp -// Link directives are in build.rs to control link order (barretenberg depends on env) -extern "C" { - /// Execute a msgpack-encoded command and return msgpack-encoded response. - /// - /// # Safety - /// - `input_in` must point to valid memory of `input_len_in` bytes - /// - `output_out` and `output_len_out` must be valid pointers - /// - Caller must free `*output_out` using `libc::free` - fn bbapi( - input_in: *const u8, - input_len_in: usize, - output_out: *mut *mut u8, - output_len_out: *mut usize, - ); -} - -/// FFI backend that calls Barretenberg directly via C API. -/// -/// This is the most performant backend option as it avoids process spawning -/// and IPC overhead. However, it requires linking against `libbarretenberg`. -/// -/// # Thread Safety -/// -/// This backend is **not** thread-safe. Each thread should have its own -/// `FfiBackend` instance, or access should be synchronized externally. -pub struct FfiBackend { - _initialized: bool, -} - -impl FfiBackend { - /// Create a new FFI backend. - /// - /// # Errors - /// - /// Returns an error if Barretenberg initialization fails. - pub fn new() -> Result { - // Future: Could add SRS initialization here if needed - // For now, Barretenberg initializes lazily on first use - Ok(Self { _initialized: true }) - } -} - -impl Backend for FfiBackend { - fn call(&mut self, input: &[u8]) -> Result> { - let mut output_ptr: *mut u8 = ptr::null_mut(); - let mut output_len: usize = 0; - - // SAFETY: - // - input.as_ptr() is valid for input.len() bytes - // - output_ptr and output_len are valid stack pointers - // - bbapi allocates output using malloc, which we free below - unsafe { - bbapi( - input.as_ptr(), - input.len(), - &mut output_ptr, - &mut output_len, - ); - } - - if output_ptr.is_null() { - return Err(BarretenbergError::Backend( - "bbapi returned null pointer".to_string(), - )); - } - - if output_len == 0 { - // Free the pointer even if length is 0 - unsafe { - libc::free(output_ptr as *mut libc::c_void); - } - return Err(BarretenbergError::Backend( - "bbapi returned empty response".to_string(), - )); - } - - // SAFETY: output_ptr is valid for output_len bytes, allocated by malloc - let output = unsafe { std::slice::from_raw_parts(output_ptr, output_len).to_vec() }; - - // Free the C-allocated memory - // SAFETY: output_ptr was allocated by bbapi using malloc - unsafe { - libc::free(output_ptr as *mut libc::c_void); - } - - Ok(output) - } - - fn destroy(&mut self) -> Result<()> { - // No cleanup needed - Barretenberg manages its own state - // Future: Could send Shutdown command here if needed - self._initialized = false; - Ok(()) - } -} - -impl Drop for FfiBackend { - fn drop(&mut self) { - let _ = self.destroy(); - } -} - -impl Default for FfiBackend { - fn default() -> Self { - Self::new().expect("Failed to initialize FfiBackend") - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::api::BarretenbergApi; - - #[test] - fn test_ffi_backend_creation() { - let backend = FfiBackend::new(); - assert!(backend.is_ok()); - } - - #[test] - fn test_ffi_blake2s() { - let backend = FfiBackend::new().unwrap(); - let mut api = BarretenbergApi::new(backend); - - let response = api.blake2s(b"hello world").unwrap(); - assert_eq!(response.hash.len(), 32); - - // Verify deterministic output - let response2 = api.blake2s(b"hello world").unwrap(); - assert_eq!(response.hash, response2.hash); - } -} diff --git a/barretenberg/rust/barretenberg-rs/src/backends/pipe.rs b/barretenberg/rust/barretenberg-rs/src/backends/pipe.rs deleted file mode 100644 index 2e3cd248061d..000000000000 --- a/barretenberg/rust/barretenberg-rs/src/backends/pipe.rs +++ /dev/null @@ -1,112 +0,0 @@ -//! Pipe backend for Barretenberg -//! -//! This backend communicates with the BB binary via stdin/stdout pipes, -//! using a 4-byte little-endian length prefix protocol. - -use crate::backend::Backend; -use crate::error::{BarretenbergError, Result}; -use std::io::{Read, Write}; -use std::path::Path; -use std::process::{Child, ChildStdin, ChildStdout, Command, Stdio}; - -/// Pipe backend implementation using stdin/stdout -pub struct PipeBackend { - stdin: ChildStdin, - stdout: ChildStdout, - process: Option, -} - -impl PipeBackend { - /// Create a new pipe backend by spawning the BB process - /// - /// # Arguments - /// * `bb_binary_path` - Path to the BB binary - /// * `threads` - Number of threads for BB to use - pub fn new(bb_binary_path: impl AsRef, threads: Option) -> Result { - // Build command - let mut cmd = Command::new(bb_binary_path.as_ref()); - cmd.arg("msgpack") - .arg("run") - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .stderr(Stdio::inherit()); - - // Note: BB uses HARDWARE_CONCURRENCY env var for thread control - if let Some(t) = threads { - cmd.env("HARDWARE_CONCURRENCY", t.to_string()); - } - - // Spawn the process - let mut process = cmd.spawn() - .map_err(|e| BarretenbergError::Backend(format!("Failed to spawn BB process: {}", e)))?; - - // Take stdin and stdout handles - let stdin = process.stdin.take() - .ok_or_else(|| BarretenbergError::Backend("Failed to get stdin handle".to_string()))?; - let stdout = process.stdout.take() - .ok_or_else(|| BarretenbergError::Backend("Failed to get stdout handle".to_string()))?; - - // Check if process exited immediately (indicates startup failure) - if let Ok(Some(status)) = process.try_wait() { - return Err(BarretenbergError::Backend( - format!("BB process exited immediately with status: {}", status) - )); - } - - Ok(Self { - stdin, - stdout, - process: Some(process), - }) - } - - /// Send data with length prefix - fn send_with_prefix(&mut self, data: &[u8]) -> Result<()> { - let len = data.len() as u32; - self.stdin.write_all(&len.to_le_bytes()) - .map_err(|e| BarretenbergError::Ipc(format!("Failed to write length: {}", e)))?; - self.stdin.write_all(data) - .map_err(|e| BarretenbergError::Ipc(format!("Failed to write data: {}", e)))?; - self.stdin.flush() - .map_err(|e| BarretenbergError::Ipc(format!("Failed to flush stdin: {}", e)))?; - Ok(()) - } - - /// Receive data with length prefix - fn receive_with_prefix(&mut self) -> Result> { - let mut len_buf = [0u8; 4]; - self.stdout.read_exact(&mut len_buf) - .map_err(|e| BarretenbergError::Ipc(format!("Failed to read length: {}", e)))?; - - let len = u32::from_le_bytes(len_buf) as usize; - - let mut data = vec![0u8; len]; - self.stdout.read_exact(&mut data) - .map_err(|e| BarretenbergError::Ipc(format!("Failed to read data: {}", e)))?; - - Ok(data) - } -} - -impl Backend for PipeBackend { - fn call(&mut self, input: &[u8]) -> Result> { - self.send_with_prefix(input)?; - self.receive_with_prefix() - } - - fn destroy(&mut self) -> Result<()> { - // Kill the process if it's still running - if let Some(mut process) = self.process.take() { - let _ = process.kill(); - let _ = process.wait(); - } - - Ok(()) - } -} - -impl Drop for PipeBackend { - fn drop(&mut self) { - let _ = self.destroy(); - } -} diff --git a/barretenberg/rust/barretenberg-rs/src/error.rs b/barretenberg/rust/barretenberg-rs/src/error.rs deleted file mode 100644 index 726ac4a9ad2f..000000000000 --- a/barretenberg/rust/barretenberg-rs/src/error.rs +++ /dev/null @@ -1,32 +0,0 @@ -//! Error types for Barretenberg operations - -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum BarretenbergError { - #[error("Serialization error: {0}")] - Serialization(String), - - #[error("Deserialization error: {0}")] - Deserialization(String), - - #[error("Backend error: {0}")] - Backend(String), - - #[error("IPC error: {0}")] - Ipc(String), - - #[error("IO error: {0}")] - Io(#[from] std::io::Error), - - #[error("Invalid response: {0}")] - InvalidResponse(String), - - #[error("Connection error: {0}")] - Connection(String), - - #[error("WASM error: {0}")] - Wasm(String), -} - -pub type Result = std::result::Result; diff --git a/barretenberg/rust/barretenberg-rs/src/fr_ext.rs b/barretenberg/rust/barretenberg-rs/src/fr_ext.rs new file mode 100644 index 000000000000..8d3917dd22c2 --- /dev/null +++ b/barretenberg/rust/barretenberg-rs/src/fr_ext.rs @@ -0,0 +1,59 @@ +//! Extra constructors / accessors on the generated `Fr` type that downstream +//! callers (tests, ports of TS helpers) already depend on. Kept as a separate +//! impl block here rather than inside `generated/bb_types.rs` so the generated +//! file stays a pure regen target. + +use crate::generated::bb_types::{Bin32, Fr}; + +impl From<[u8; 32]> for Bin32 { + fn from(bytes: [u8; 32]) -> Self { + Self(bytes) + } +} + +impl From for [u8; 32] { + fn from(value: Bin32) -> Self { + value.0 + } +} + +impl Fr { + /// Create a field element from a u64 value (big-endian, matching the + /// C++ msgpack representation). + pub fn from_u64(value: u64) -> Self { + let mut bytes = [0u8; 32]; + bytes[24..32].copy_from_slice(&value.to_be_bytes()); + Self(bytes) + } + + /// Create a field element from 32 big-endian bytes. + pub fn from_be_bytes(bytes: [u8; 32]) -> Self { + Self(bytes) + } + + /// Create a field element from 32 little-endian bytes. + pub fn from_le_bytes(bytes: [u8; 32]) -> Self { + Self(bytes) + } + + /// Create a field element from a 32-byte buffer (no reduction). + /// Panics if the buffer is not exactly 32 bytes long. + pub fn from_buffer(buffer: &[u8]) -> Self { + let bytes: [u8; 32] = buffer.try_into().expect("Buffer must be exactly 32 bytes"); + Self(bytes) + } + + /// Create a field element from a byte slice, truncating or zero-padding + /// to 32 bytes as needed. + pub fn from_buffer_reduce(buffer: &[u8]) -> Self { + let mut bytes = [0u8; 32]; + let len = buffer.len().min(32); + bytes[..len].copy_from_slice(&buffer[..len]); + Self(bytes) + } + + /// Convert to a byte buffer (as used in msgpack). + pub fn to_buffer(&self) -> Vec { + self.0.to_vec() + } +} diff --git a/barretenberg/rust/barretenberg-rs/src/legacy.rs b/barretenberg/rust/barretenberg-rs/src/legacy.rs new file mode 100644 index 000000000000..0397e3a7d001 --- /dev/null +++ b/barretenberg/rust/barretenberg-rs/src/legacy.rs @@ -0,0 +1,223 @@ +//! Back-compat shim mirroring the pre-codegen `BarretenbergApi` surface. +//! +//! The codegen migration replaced loose `&[u8]` / `Vec>` scalar +//! parameters with typed newtypes (`Fr`, `Fq`, `Secp256k1Fr`, ...). External +//! consumers were already depending on the old surface, so this shim +//! preserves it: callers that did +//! +//! ```ignore +//! use barretenberg_rs::{BarretenbergApi, FfiBackend}; +//! let mut api = BarretenbergApi::new(FfiBackend::new()?); +//! api.schnorr_compute_public_key(&private_key_bytes)?; +//! ``` +//! +//! continue to compile against this crate while they migrate to the new +//! [`crate::BbApi`] surface (typed scalars, `Vec` for hash inputs, +//! etc.). +//! +//! Wire format is identical — only the Rust call surface changed. Methods +//! whose signature did not change reach `BbApi` through `Deref` (no +//! explicit wrapper here). + +#![allow(deprecated)] + +use std::ops::{Deref, DerefMut}; + +use crate::generated::backend::Backend; +use crate::generated::bb_client::BbApi; +use crate::generated::bb_types::{ + Bn254FqSqrtResponse, Bn254FrSqrtResponse, Bn254G1MulResponse, Bn254G1Point, Bn254G2MulResponse, + Bn254G2Point, EcdsaSecp256k1ComputePublicKeyResponse, EcdsaSecp256k1ConstructSignatureResponse, + EcdsaSecp256r1ComputePublicKeyResponse, EcdsaSecp256r1ConstructSignatureResponse, Fq, Fr, + GrumpkinBatchMulResponse, GrumpkinMulResponse, GrumpkinPoint, PedersenCommitResponse, + PedersenHashResponse, Poseidon2HashResponse, Poseidon2PermutationResponse, + SchnorrComputePublicKeyResponse, SchnorrConstructSignatureResponse, Secp256k1Fr, + Secp256k1MulResponse, Secp256k1Point, Secp256r1Fr, +}; +use crate::generated::error::Result; + +/// Deprecated alias for [`crate::BbApi`] preserving the pre-migration call +/// surface (`&[u8]` scalars, `Vec>` hash inputs). Forwards unchanged +/// methods to `BbApi` via `Deref`; overrides methods whose signature changed. +#[deprecated( + note = "use `BbApi` directly; typed scalars (Fr/Fq/Secp256k1Fr) replace raw `&[u8]` parameters" +)] +pub struct BarretenbergApi(BbApi); + +impl BarretenbergApi { + pub fn new(backend: B) -> Self { + Self(BbApi::new(backend)) + } + + pub fn into_inner(self) -> BbApi { + self.0 + } +} + +impl Deref for BarretenbergApi { + type Target = BbApi; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for BarretenbergApi { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +fn to_fr_array(s: &[u8]) -> Fr { + let arr: [u8; 32] = s.try_into().expect("expected 32-byte scalar"); + Fr::from_be_bytes(arr) +} + +fn to_fq_array(s: &[u8]) -> Fq { + let arr: [u8; 32] = s.try_into().expect("expected 32-byte scalar"); + Fq::from_bytes(arr) +} + +fn to_secp256k1_fr(s: &[u8]) -> Secp256k1Fr { + let arr: [u8; 32] = s.try_into().expect("expected 32-byte secp256k1 scalar"); + Secp256k1Fr::from_bytes(arr) +} + +fn to_secp256r1_fr(s: &[u8]) -> Secp256r1Fr { + let arr: [u8; 32] = s.try_into().expect("expected 32-byte secp256r1 scalar"); + Secp256r1Fr::from_bytes(arr) +} + +fn fr_vec(inputs: Vec>) -> Vec { + inputs.into_iter().map(|b| to_fr_array(&b)).collect() +} + +// Old-surface methods. These shadow the same-named methods reached through +// `Deref`, so callers picking up `BarretenbergApi` get the legacy signature. +#[allow(deprecated)] +impl BarretenbergApi { + pub fn poseidon2_hash(&mut self, inputs: Vec>) -> Result { + self.0.poseidon2_hash(fr_vec(inputs)) + } + + pub fn poseidon2_permutation( + &mut self, + inputs: [Vec; 4], + ) -> Result { + let typed: [Fr; 4] = inputs.map(|b| to_fr_array(&b)); + self.0.poseidon2_permutation(typed) + } + + pub fn pedersen_commit( + &mut self, + inputs: Vec>, + hash_index: u32, + ) -> Result { + self.0.pedersen_commit(fr_vec(inputs), hash_index) + } + + pub fn pedersen_hash( + &mut self, + inputs: Vec>, + hash_index: u32, + ) -> Result { + self.0.pedersen_hash(fr_vec(inputs), hash_index) + } + + pub fn grumpkin_mul( + &mut self, + point: GrumpkinPoint, + scalar: &[u8], + ) -> Result { + self.0.grumpkin_mul(point, to_fq_array(scalar)) + } + + pub fn grumpkin_batch_mul( + &mut self, + points: Vec, + scalar: &[u8], + ) -> Result { + self.0.grumpkin_batch_mul(points, to_fq_array(scalar)) + } + + pub fn secp256k1_mul( + &mut self, + point: Secp256k1Point, + scalar: &[u8], + ) -> Result { + self.0.secp256k1_mul(point, to_secp256k1_fr(scalar)) + } + + pub fn bn254_fr_sqrt(&mut self, input: &[u8]) -> Result { + self.0.bn254_fr_sqrt(to_fr_array(input)) + } + + pub fn bn254_fq_sqrt(&mut self, input: &[u8]) -> Result { + self.0.bn254_fq_sqrt(to_fq_array(input)) + } + + pub fn bn254_g1_mul( + &mut self, + point: Bn254G1Point, + scalar: &[u8], + ) -> Result { + self.0.bn254_g1_mul(point, to_fr_array(scalar)) + } + + pub fn bn254_g2_mul( + &mut self, + point: Bn254G2Point, + scalar: &[u8], + ) -> Result { + self.0.bn254_g2_mul(point, to_fr_array(scalar)) + } + + pub fn schnorr_compute_public_key( + &mut self, + private_key: &[u8], + ) -> Result { + self.0.schnorr_compute_public_key(to_fq_array(private_key)) + } + + pub fn schnorr_construct_signature( + &mut self, + message: &[u8], + private_key: &[u8], + ) -> Result { + self.0 + .schnorr_construct_signature(message, to_fq_array(private_key)) + } + + pub fn ecdsa_secp256k1_compute_public_key( + &mut self, + private_key: &[u8], + ) -> Result { + self.0 + .ecdsa_secp256k1_compute_public_key(to_secp256k1_fr(private_key)) + } + + pub fn ecdsa_secp256r1_compute_public_key( + &mut self, + private_key: &[u8], + ) -> Result { + self.0 + .ecdsa_secp256r1_compute_public_key(to_secp256r1_fr(private_key)) + } + + pub fn ecdsa_secp256k1_construct_signature( + &mut self, + message: &[u8], + private_key: &[u8], + ) -> Result { + self.0 + .ecdsa_secp256k1_construct_signature(message, to_secp256k1_fr(private_key)) + } + + pub fn ecdsa_secp256r1_construct_signature( + &mut self, + message: &[u8], + private_key: &[u8], + ) -> Result { + self.0 + .ecdsa_secp256r1_construct_signature(message, to_secp256r1_fr(private_key)) + } +} diff --git a/barretenberg/rust/barretenberg-rs/src/lib.rs b/barretenberg/rust/barretenberg-rs/src/lib.rs index ffccd08c514d..e737ded490cb 100644 --- a/barretenberg/rust/barretenberg-rs/src/lib.rs +++ b/barretenberg/rust/barretenberg-rs/src/lib.rs @@ -1,75 +1,78 @@ //! # Barretenberg Rust Bindings //! -//! High-performance Rust bindings to the Barretenberg cryptographic library -//! using msgpack protocol over pluggable backends. +//! Rust bindings to the Barretenberg cryptographic library using msgpack +//! over a pluggable [`Backend`]. //! -//! ## Usage with PipeBackend +//! Two ready-made backends ship with the crate: //! -//! ```ignore -//! use barretenberg_rs::{BarretenbergApi, backends::PipeBackend}; +//! * [`FfiBackend`] (default) — links `libbarretenberg` and calls `bbapi` +//! directly in-process. Required for environments that can't spawn the +//! `bb` binary (iOS, Android, embedded). +//! * `ipc_runtime::IpcClient` (re-exported, via the [`Backend`] impl in +//! [`generated::backend`]) — talks to a separately-spawned `bb` over a +//! Unix domain socket or shared-memory ring. Useful for development and +//! for hosts that want to isolate the prover in its own process. //! -//! // Create a pipe backend (requires BB binary) -//! let backend = PipeBackend::new("/path/to/bb", Some(4))?; -//! let mut api = BarretenbergApi::new(backend); +//! ## Custom backends //! -//! // Use the API -//! let response = api.blake2s(b"hello world")?; -//! println!("Hash: {:?}", response.hash); -//! -//! // Cleanup -//! api.destroy()?; -//! ``` -//! -//! ## Custom Backend -//! -//! Implement the `Backend` trait for custom IPC strategies: +//! Implement the [`Backend`] trait to plug in your own transport (WASM +//! module, RPC, etc.): //! //! ``` //! use barretenberg_rs::{Backend, BarretenbergError, Result}; //! -//! struct MyBackend { -//! // Your implementation (WASM module, FFI handle, network connection, etc.) -//! } +//! struct MyBackend; //! //! impl Backend for MyBackend { //! fn call(&mut self, request: &[u8]) -> Result> { -//! // Send msgpack request, receive msgpack response -//! // The request is a msgpack-encoded Vec -//! // The response should be a msgpack-encoded Response +//! // request is a msgpack-encoded Vec; return a +//! // msgpack-encoded Response. //! todo!() //! } //! //! fn destroy(&mut self) -> Result<()> { -//! // Cleanup resources //! Ok(()) //! } //! } //! ``` -pub mod backend; -pub mod types; -pub mod api; -pub mod error; +// Bb API bindings produced by `ipc-codegen` from `ipc-codegen/schemas/bb_schema.json`. +// Output lives under src/generated/ and is regenerated by +// `barretenberg/ts/scripts/generate.sh`. +pub mod generated { + pub mod backend; + pub mod bb_client; + pub mod bb_types; + pub mod error; -// Generated types from msgpack schema -// Run: cd ../ts && yarn generate -pub mod generated_types; + #[cfg(feature = "ffi")] + pub mod ffi_backend; +} -pub use backend::Backend; -pub use types::{Fr, Point}; -pub use generated_types::{Command, Response, GrumpkinPoint}; -pub use api::BarretenbergApi; -pub use error::{BarretenbergError, Result}; +mod fr_ext; +pub mod legacy; -/// Backend implementations -pub mod backends { - #[cfg(feature = "native")] - pub mod pipe; - #[cfg(feature = "native")] - pub use pipe::PipeBackend; +pub use generated::backend::Backend; +pub use generated::bb_client::BbApi; +pub use generated::bb_types::{ + Bn254G1Point, Bn254G2Point, Command, Fr, GrumpkinPoint, Response, Secp256k1Point, + Secp256r1Point, +}; +pub use generated::error::{IpcError as BarretenbergError, Result}; - #[cfg(feature = "ffi")] - pub mod ffi; - #[cfg(feature = "ffi")] - pub use ffi::FfiBackend; -} +// Pre-codegen surface kept around so external consumers can migrate at their +// own pace; see [`legacy`] for the deprecation notes and the typed-scalar +// replacements on [`BbApi`]. +#[allow(deprecated)] +pub use legacy::BarretenbergApi; + +// Preserved alias for callers that imported types directly via +// `barretenberg_rs::generated_types::*`. +pub use generated::bb_types as generated_types; + +#[cfg(feature = "ffi")] +pub use generated::ffi_backend::FfiBackend; + +// Re-export `ipc_runtime` so callers can write +// `barretenberg_rs::ipc_runtime::IpcClient` without taking a separate dep. +pub use ipc_runtime; diff --git a/barretenberg/rust/barretenberg-rs/src/types.rs b/barretenberg/rust/barretenberg-rs/src/types.rs deleted file mode 100644 index 6ad04b26ecd7..000000000000 --- a/barretenberg/rust/barretenberg-rs/src/types.rs +++ /dev/null @@ -1,53 +0,0 @@ -//! Core utility types for Barretenberg operations - -use serde::{Deserialize, Serialize}; - -/// Field element (Fr) - 254-bit field element for BN254 -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct Fr(pub [u8; 32]); - -impl Fr { - /// Create a new field element from a u64 value (big-endian encoding, matching C++ msgpack format) - pub fn from_u64(value: u64) -> Self { - let mut bytes = [0u8; 32]; - bytes[24..32].copy_from_slice(&value.to_be_bytes()); - Fr(bytes) - } - - /// Create a field element from bytes (big-endian) - pub fn from_be_bytes(bytes: [u8; 32]) -> Self { - Fr(bytes) - } - - /// Create a field element from bytes (little-endian) - pub fn from_le_bytes(bytes: [u8; 32]) -> Self { - Fr(bytes) - } - - /// Create a field element from a 32-byte buffer (no reduction) - /// Panics if buffer is not exactly 32 bytes - pub fn from_buffer(buffer: &[u8]) -> Self { - let bytes: [u8; 32] = buffer.try_into().expect("Buffer must be exactly 32 bytes"); - Fr(bytes) - } - - /// Create a field element from a byte slice, reducing if necessary - pub fn from_buffer_reduce(buffer: &[u8]) -> Self { - let mut bytes = [0u8; 32]; - let len = buffer.len().min(32); - bytes[..len].copy_from_slice(&buffer[..len]); - Fr(bytes) - } - - /// Convert to a byte buffer (as used in msgpack) - pub fn to_buffer(&self) -> Vec { - self.0.to_vec() - } -} - -/// Point on the elliptic curve (affine_element) -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct Point { - pub x: [u8; 32], - pub y: [u8; 32], -} diff --git a/barretenberg/rust/bootstrap.sh b/barretenberg/rust/bootstrap.sh index 6c3938fc2d58..b64fe109f3ce 100755 --- a/barretenberg/rust/bootstrap.sh +++ b/barretenberg/rust/bootstrap.sh @@ -9,8 +9,13 @@ function build { echo_header "barretenberg-rs build" if ! cache_download barretenberg-rs-$hash.tar.gz; then - # Generate Rust bindings from msgpack schema (uses ts-node, no build needed) - (cd ../ts && yarn generate) + # Generate Rust bindings from msgpack schema via ipc-codegen. + (cd barretenberg-rs && node --experimental-strip-types --experimental-transform-types --no-warnings \ + ../../../ipc-codegen/src/generate.ts \ + --schema ../../cpp/src/barretenberg/bbapi/bb_schema.json \ + --lang rust --client --ffi --strip-method-prefix \ + --out src/generated \ + --prefix Bb) # Build all targets # BB_LIB_DIR tells build.rs to use local lib instead of downloading (ffi feature is on by default) @@ -18,7 +23,7 @@ function build { BB_LIB_DIR="$(cd ../cpp/build/lib && pwd)" denoise "cargo build --release" # Upload build artifacts and generated source files to cache - cache_upload barretenberg-rs-$hash.tar.gz target/release barretenberg-rs/src/generated_types.rs barretenberg-rs/src/api.rs + cache_upload barretenberg-rs-$hash.tar.gz target/release barretenberg-rs/src/generated fi } @@ -36,9 +41,8 @@ function test { source "$HOME/.cargo/env" fi - # Run PipeBackend tests (spawns bb binary) - # Use --no-default-features to skip FFI (which requires libbb-external.a) - denoise "cargo test --release --no-default-features --features native" + # PipeBackend tests were dropped along with `--features native` when bb-rs + # migrated to ipc-codegen + ipc-runtime; only the FFI backend remains. # Run FFI backend tests (requires libbb-external.a from cpp build) # BB_LIB_DIR tells build.rs to use local lib instead of downloading @@ -55,9 +59,14 @@ function release { sed -i "s/^version = \".*\"/version = \"$version\"/" Cargo.toml # Generated files must exist (created during build step, or generate now) - if [ ! -f barretenberg-rs/src/api.rs ] || [ ! -f barretenberg-rs/src/generated_types.rs ]; then - echo "Generated files not found, running yarn generate..." - (cd ../ts && yarn generate) + if [ ! -f barretenberg-rs/src/generated/bb_client.rs ] || [ ! -f barretenberg-rs/src/generated/bb_types.rs ]; then + echo "Generated files not found, running ipc-codegen..." + (cd barretenberg-rs && node --experimental-strip-types --experimental-transform-types --no-warnings \ + ../../../ipc-codegen/src/generate.ts \ + --schema ../../cpp/src/barretenberg/bbapi/bb_schema.json \ + --lang rust --client --ffi --strip-method-prefix \ + --out src/generated \ + --prefix Bb) fi # Check if this version is already published on crates.io (idempotent re-runs). diff --git a/barretenberg/rust/scripts/run_test.sh b/barretenberg/rust/scripts/run_test.sh index 02cf98907bd4..bab38de861ae 100755 --- a/barretenberg/rust/scripts/run_test.sh +++ b/barretenberg/rust/scripts/run_test.sh @@ -8,9 +8,8 @@ if [ -f "$HOME/.cargo/env" ]; then source "$HOME/.cargo/env" fi -# Run PipeBackend tests (spawns bb binary) -# Use --no-default-features to skip FFI (which requires libbb-external.a) -denoise "cargo test --release --no-default-features --features native" +# PipeBackend tests were dropped along with `--features native` when bb-rs +# migrated to ipc-codegen + ipc-runtime; only the FFI backend remains. # Run FFI backend tests (requires libbb-external.a from cpp build) # BB_LIB_DIR tells build.rs to use local lib instead of downloading diff --git a/barretenberg/rust/tests/Cargo.toml b/barretenberg/rust/tests/Cargo.toml index c52ddf88621e..7bd7cc99acbe 100644 --- a/barretenberg/rust/tests/Cargo.toml +++ b/barretenberg/rust/tests/Cargo.toml @@ -9,7 +9,7 @@ publish = false ffi = ["barretenberg-rs/ffi"] [dependencies] -barretenberg-rs = { path = "../barretenberg-rs", default-features = false, features = ["native", "async"] } +barretenberg-rs = { path = "../barretenberg-rs", default-features = false } # Serialization serde.workspace = true @@ -18,11 +18,5 @@ rmp-serde.workspace = true # Testing and benchmarking criterion.workspace = true -# Async runtime -tokio = { workspace = true, features = ["test-util"] } - # Utilities hex.workspace = true - -[dev-dependencies] -tokio = { workspace = true, features = ["test-util", "macros"] } diff --git a/barretenberg/rust/tests/src/blake2s.rs b/barretenberg/rust/tests/src/blake2s.rs deleted file mode 100644 index c6181452e0d3..000000000000 --- a/barretenberg/rust/tests/src/blake2s.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! Blake2s hash tests -//! -//! Parallels barretenberg/ts/src/barretenberg/blake2s.test.ts -//! -//! These tests require the BB binary to be built. They are skipped if the binary is not found. - -#[cfg(test)] -use barretenberg_rs::{backends::PipeBackend, BarretenbergApi, Fr}; -#[cfg(test)] -use crate::utils::get_bb_binary_path; -#[cfg(test)] -use crate::require_bb_binary; - -#[test] -fn test_blake2s() { - require_bb_binary!(); - let bb_path = get_bb_binary_path(); - - let backend = PipeBackend::new(&bb_path, Some(1)) - .expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); - - let input = b"abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789"; - let expected: [u8; 32] = [ - 0x44, 0xdd, 0xdb, 0x39, 0xbd, 0xb2, 0xaf, 0x80, 0xc1, 0x47, 0x89, 0x4c, 0x1d, 0x75, 0x6a, - 0xda, 0x3d, 0x1c, 0x2a, 0xc2, 0xb1, 0x00, 0x54, 0x1e, 0x04, 0xfe, 0x87, 0xb4, 0xa5, 0x9e, - 0x12, 0x43, - ]; - - let response = api.blake2s(input).expect("Blake2s failed"); - - assert_eq!( - response.hash.as_slice(), - &expected, - "Blake2s hash mismatch" - ); - - api.destroy().expect("Failed to destroy backend"); -} - -#[test] -fn test_blake2s_to_field() { - require_bb_binary!(); - let bb_path = get_bb_binary_path(); - - let backend = PipeBackend::new(&bb_path, Some(1)) - .expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); - - let input = b"abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789"; - // Blake2sToField returns the hash reduced to a field element - let expected_field: [u8; 32] = [ - 20, 121, 140, 198, 220, 129, 15, 87, 8, 247, 67, 149, 155, 244, 18, 125, - 20, 232, 66, 122, 55, 70, 227, 140, 193, 28, 146, 32, 181, 158, 18, 66, - ]; - - let expected = Fr(expected_field); - - let response = api.blake2s_to_field(input).expect("Blake2sToField failed"); - let result = Fr::from_buffer_reduce(&response.field); - - assert_eq!(result, expected, "Blake2sToField result mismatch"); - - api.destroy().expect("Failed to destroy backend"); -} diff --git a/barretenberg/rust/tests/src/debug_msgpack.rs b/barretenberg/rust/tests/src/debug_msgpack.rs index 5ab317a5d8bd..9ac13dd40853 100644 --- a/barretenberg/rust/tests/src/debug_msgpack.rs +++ b/barretenberg/rust/tests/src/debug_msgpack.rs @@ -16,22 +16,32 @@ fn test_msgpack_format() { // Show first 30 bytes in detail println!("\nFirst 30 bytes:"); for (i, b) in bytes.iter().take(30).enumerate() { - println!(" [{}] = 0x{:02x} ({})", i, b, if *b >= 32 && *b < 127 { *b as char } else { '.' }); + println!( + " [{}] = 0x{:02x} ({})", + i, + b, + if *b >= 32 && *b < 127 { + *b as char + } else { + '.' + } + ); } } #[test] fn test_pedersen_msgpack_format() { - let inputs: Vec> = vec![ - Fr::from_u64(4).to_buffer().to_vec(), - Fr::from_u64(8).to_buffer().to_vec(), - ]; + let inputs: Vec = vec![Fr::from_u64(4), Fr::from_u64(8)]; let cmd = Command::PedersenHash(PedersenHash::new(inputs, 7)); let bytes = rmp_serde::to_vec_named(&vec![cmd]).unwrap(); println!("\n=== Msgpack Format Debug (PedersenHash) ==="); - println!("Msgpack bytes (length {}): {:?}", bytes.len(), &bytes[..bytes.len().min(50)]); + println!( + "Msgpack bytes (length {}): {:?}", + bytes.len(), + &bytes[..bytes.len().min(50)] + ); println!("Msgpack hex: {}", hex::encode(&bytes)); // Show structure diff --git a/barretenberg/rust/tests/src/ffi/aes.rs b/barretenberg/rust/tests/src/ffi/aes.rs index c9fc81731401..e7e188b14950 100644 --- a/barretenberg/rust/tests/src/ffi/aes.rs +++ b/barretenberg/rust/tests/src/ffi/aes.rs @@ -3,7 +3,7 @@ //! Ported from zkpassport/aztec-packages bb_rs aes_tests.rs #[cfg(test)] -use barretenberg_rs::{backends::FfiBackend, BarretenbergApi}; +use barretenberg_rs::{BbApi, FfiBackend}; /// Apply PKCS#7 padding to input data (for testing purposes) #[cfg(test)] @@ -44,7 +44,7 @@ fn remove_pkcs7_padding(data: &[u8]) -> Result, &'static str> { #[test] fn test_aes_encrypt_decrypt_roundtrip() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let plaintext = b"Hello, AES world! This is a test message for encryption."; let key = [ @@ -74,11 +74,13 @@ fn test_aes_encrypt_decrypt_roundtrip() { let decrypted_with_padding = &decrypt_response.plaintext; // Remove padding after decryption - let decrypted = - remove_pkcs7_padding(decrypted_with_padding).expect("Failed to remove padding"); + let decrypted = remove_pkcs7_padding(decrypted_with_padding).expect("Failed to remove padding"); // The decrypted data should match the original plaintext exactly - assert_eq!(decrypted, plaintext, "Decrypted data doesn't match plaintext"); + assert_eq!( + decrypted, plaintext, + "Decrypted data doesn't match plaintext" + ); api.destroy().expect("Failed to destroy backend"); } @@ -86,7 +88,7 @@ fn test_aes_encrypt_decrypt_roundtrip() { #[test] fn test_aes_buffer_encrypt_decrypt() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let plaintext = b"AES buffer test message"; let key = [ @@ -113,10 +115,12 @@ fn test_aes_buffer_encrypt_decrypt() { let decrypted_with_padding = &decrypt_response.plaintext; // Remove padding after decryption - let decrypted = - remove_pkcs7_padding(decrypted_with_padding).expect("Failed to remove padding"); + let decrypted = remove_pkcs7_padding(decrypted_with_padding).expect("Failed to remove padding"); - assert_eq!(decrypted, plaintext, "Decrypted data doesn't match plaintext"); + assert_eq!( + decrypted, plaintext, + "Decrypted data doesn't match plaintext" + ); api.destroy().expect("Failed to destroy backend"); } @@ -124,7 +128,7 @@ fn test_aes_buffer_encrypt_decrypt() { #[test] fn test_aes_different_keys_produce_different_outputs() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let plaintext = b"Test message for key difference"; let key1 = [ @@ -160,7 +164,7 @@ fn test_aes_different_keys_produce_different_outputs() { #[test] fn test_aes_deterministic() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let plaintext = b"Deterministic test message"; let key = [ diff --git a/barretenberg/rust/tests/src/ffi/blake2s.rs b/barretenberg/rust/tests/src/ffi/blake2s.rs index ddb7ab85f794..0cf2487cf6ab 100644 --- a/barretenberg/rust/tests/src/ffi/blake2s.rs +++ b/barretenberg/rust/tests/src/ffi/blake2s.rs @@ -3,12 +3,12 @@ //! Parallels barretenberg/ts/src/barretenberg/blake2s.test.ts #[cfg(test)] -use barretenberg_rs::{backends::FfiBackend, BarretenbergApi, Fr}; +use barretenberg_rs::{BbApi, FfiBackend, Fr}; #[test] fn test_blake2s() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let input = b"abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789"; let expected: [u8; 32] = [ @@ -19,11 +19,7 @@ fn test_blake2s() { let response = api.blake2s(input).expect("Blake2s failed"); - assert_eq!( - response.hash.as_slice(), - &expected, - "Blake2s hash mismatch" - ); + assert_eq!(response.hash.as_slice(), &expected, "Blake2s hash mismatch"); api.destroy().expect("Failed to destroy backend"); } @@ -31,21 +27,19 @@ fn test_blake2s() { #[test] fn test_blake2s_to_field() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let input = b"abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789"; // Blake2sToField returns the hash reduced to a field element let expected_field: [u8; 32] = [ - 20, 121, 140, 198, 220, 129, 15, 87, 8, 247, 67, 149, 155, 244, 18, 125, - 20, 232, 66, 122, 55, 70, 227, 140, 193, 28, 146, 32, 181, 158, 18, 66, + 20, 121, 140, 198, 220, 129, 15, 87, 8, 247, 67, 149, 155, 244, 18, 125, 20, 232, 66, 122, + 55, 70, 227, 140, 193, 28, 146, 32, 181, 158, 18, 66, ]; - let expected = Fr(expected_field); + let expected = Fr::from_be_bytes(expected_field); let response = api.blake2s_to_field(input).expect("Blake2sToField failed"); - let result = Fr::from_buffer_reduce(&response.field); - - assert_eq!(result, expected, "Blake2sToField result mismatch"); + assert_eq!(response.field, expected, "Blake2sToField result mismatch"); api.destroy().expect("Failed to destroy backend"); } diff --git a/barretenberg/rust/tests/src/ffi/bn254.rs b/barretenberg/rust/tests/src/ffi/bn254.rs index f15484a14cea..fc15f07da881 100644 --- a/barretenberg/rust/tests/src/ffi/bn254.rs +++ b/barretenberg/rust/tests/src/ffi/bn254.rs @@ -4,25 +4,24 @@ #[cfg(test)] use barretenberg_rs::{ - backends::FfiBackend, generated_types::{Bn254G1Point, Bn254G2Point}, - BarretenbergApi, + BbApi, FfiBackend, Fr, }; #[test] fn test_bn254_fr_sqrt_of_zero() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); // Square root of zero should be zero - let zero = vec![0u8; 32]; + let zero = Fr::from_be_bytes([0u8; 32]); - let response = api.bn254_fr_sqrt(&zero).expect("bn254_fr_sqrt failed"); + let response = api.bn254_fr_sqrt(zero).expect("bn254_fr_sqrt failed"); assert!(response.is_square_root, "Square root of zero should exist"); assert_eq!( response.value, - vec![0u8; 32], + Fr::from_be_bytes([0u8; 32]), "Square root of zero should be zero" ); @@ -32,13 +31,14 @@ fn test_bn254_fr_sqrt_of_zero() { #[test] fn test_bn254_fr_sqrt_of_one() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); // Square root of one should be one - let mut one = vec![0u8; 32]; - one[31] = 1; + let one = Fr::from_u64(1); - let response = api.bn254_fr_sqrt(&one).expect("bn254_fr_sqrt failed"); + let response = api + .bn254_fr_sqrt(one.clone()) + .expect("bn254_fr_sqrt failed"); assert!(response.is_square_root, "Square root of one should exist"); assert_eq!(response.value, one, "Square root of one should be one"); @@ -49,21 +49,19 @@ fn test_bn254_fr_sqrt_of_one() { #[test] fn test_bn254_fr_sqrt_of_four() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); // Square root of four should be two - let mut four = vec![0u8; 32]; - four[31] = 4; + let four = Fr::from_u64(4); - let response = api.bn254_fr_sqrt(&four).expect("bn254_fr_sqrt failed"); + let response = api.bn254_fr_sqrt(four).expect("bn254_fr_sqrt failed"); assert!(response.is_square_root, "Square root of four should exist"); // The square root should be 2 - let mut expected = vec![0u8; 32]; - expected[31] = 2; assert_eq!( - response.value, expected, + response.value, + Fr::from_u64(2), "Square root of four should be two" ); @@ -73,13 +71,14 @@ fn test_bn254_fr_sqrt_of_four() { #[test] fn test_bn254_fr_sqrt_deterministic() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); - let mut input = vec![0u8; 32]; - input[31] = 16; // Perfect square + let input = Fr::from_u64(16); // Perfect square - let response1 = api.bn254_fr_sqrt(&input).expect("bn254_fr_sqrt failed"); - let response2 = api.bn254_fr_sqrt(&input).expect("bn254_fr_sqrt failed"); + let response1 = api + .bn254_fr_sqrt(input.clone()) + .expect("bn254_fr_sqrt failed"); + let response2 = api.bn254_fr_sqrt(input).expect("bn254_fr_sqrt failed"); // Should be deterministic assert_eq!(response1.is_square_root, response2.is_square_root); @@ -91,33 +90,34 @@ fn test_bn254_fr_sqrt_deterministic() { #[test] fn test_bn254_g1_mul_consistency() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); // BN254 G1 generator: (1, 2) - let mut x = vec![0u8; 32]; - x[31] = 1; - let mut y = vec![0u8; 32]; - y[31] = 2; - let g1 = Bn254G1Point { x, y }; + let mut one = [0u8; 32]; + one[31] = 1; + let mut two_bytes = [0u8; 32]; + two_bytes[31] = 2; + let g1 = Bn254G1Point { + x: one.into(), + y: two_bytes.into(), + }; - let mut two = vec![0u8; 32]; - two[31] = 2; - let mut three = vec![0u8; 32]; - three[31] = 3; + let two = Fr::from_u64(2); + let three = Fr::from_u64(3); // Verify 2*(3*G1) == 3*(2*G1) == 6*G1 let result_3g = api - .bn254_g1_mul(g1.clone(), &three) + .bn254_g1_mul(g1.clone(), three.clone()) .expect("bn254_g1_mul(3) failed"); let result_2_of_3g = api - .bn254_g1_mul(result_3g.point.clone(), &two) + .bn254_g1_mul(result_3g.point.clone(), two.clone()) .expect("bn254_g1_mul(2*3G) failed"); let result_2g = api - .bn254_g1_mul(g1.clone(), &two) + .bn254_g1_mul(g1.clone(), two) .expect("bn254_g1_mul(2) failed"); let result_3_of_2g = api - .bn254_g1_mul(result_2g.point.clone(), &three) + .bn254_g1_mul(result_2g.point.clone(), three) .expect("bn254_g1_mul(3*2G) failed"); assert_eq!(result_2_of_3g.point.x, result_3_of_2g.point.x); @@ -135,65 +135,60 @@ fn test_bn254_g1_mul_consistency() { fn bn254_g2_generator() -> Bn254G2Point { Bn254G2Point { x: [ - vec![ + [ 0x18, 0x00, 0xde, 0xef, 0x12, 0x1f, 0x1e, 0x76, 0x42, 0x6a, 0x00, 0x66, 0x5e, 0x5c, 0x44, 0x79, 0x67, 0x43, 0x22, 0xd4, 0xf7, 0x5e, 0xda, 0xdd, 0x46, 0xde, 0xbd, 0x5c, 0xd9, 0x92, 0xf6, 0xed, - ], - vec![ + ] + .into(), + [ 0x19, 0x8e, 0x93, 0x93, 0x92, 0x0d, 0x48, 0x3a, 0x72, 0x60, 0xbf, 0xb7, 0x31, 0xfb, 0x5d, 0x25, 0xf1, 0xaa, 0x49, 0x33, 0x35, 0xa9, 0xe7, 0x12, 0x97, 0xe4, 0x85, 0xb7, 0xae, 0xf3, 0x12, 0xc2, - ], + ] + .into(), ], y: [ - vec![ + [ 0x12, 0xc8, 0x5e, 0xa5, 0xdb, 0x8c, 0x6d, 0xeb, 0x4a, 0xab, 0x71, 0x80, 0x8d, 0xcb, 0x40, 0x8f, 0xe3, 0xd1, 0xe7, 0x69, 0x0c, 0x43, 0xd3, 0x7b, 0x4c, 0xe6, 0xcc, 0x01, 0x66, 0xfa, 0x7d, 0xaa, - ], - vec![ + ] + .into(), + [ 0x09, 0x06, 0x89, 0xd0, 0x58, 0x5f, 0xf0, 0x75, 0xec, 0x9e, 0x99, 0xad, 0x69, 0x0c, 0x33, 0x95, 0xbc, 0x4b, 0x31, 0x33, 0x70, 0xb3, 0x8e, 0xf3, 0x55, 0xac, 0xda, 0xdc, 0xd1, 0x22, 0x97, 0x5b, - ], + ] + .into(), ], } } -// TODO(cl/ipc-bb-rs-migrate): the OLD api.rs codegen still in this PR sends -// Bn254G2Point with a wire shape that pre-dates the bbapi schema change in -// this commit; the new C++ backend throws std::bad_cast deserializing it. -// The follow-up rust-binding migration PR regenerates against the new -// schema; un-ignore there. #[test] -#[ignore] fn test_bn254_g2_mul_consistency() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let g2 = bn254_g2_generator(); // Compute 3*G2 directly - let mut three = vec![0u8; 32]; - three[31] = 3; + let three = Fr::from_u64(3); let result_3g = api - .bn254_g2_mul(g2.clone(), &three) + .bn254_g2_mul(g2.clone(), three.clone()) .expect("bn254_g2_mul(3) failed"); - // Compute 3*G2 as 2*G2 then add G2 via scalar mul of the same point: - // We can verify by computing 6*G2 two ways: 2*(3*G2) vs 3*(2*G2) - let mut two = vec![0u8; 32]; - two[31] = 2; + // Compute 6*G2 two ways: 2*(3*G2) vs 3*(2*G2) + let two = Fr::from_u64(2); let result_2_of_3g = api - .bn254_g2_mul(result_3g.point.clone(), &two) + .bn254_g2_mul(result_3g.point.clone(), two.clone()) .expect("bn254_g2_mul(2*3G) failed"); let result_2g = api - .bn254_g2_mul(g2.clone(), &two) + .bn254_g2_mul(g2.clone(), two) .expect("bn254_g2_mul(2) failed"); let result_3_of_2g = api - .bn254_g2_mul(result_2g.point.clone(), &three) + .bn254_g2_mul(result_2g.point.clone(), three) .expect("bn254_g2_mul(3*2G) failed"); // 2*(3*G2) == 3*(2*G2) == 6*G2 @@ -209,22 +204,24 @@ fn test_bn254_g2_mul_consistency() { #[test] fn test_bn254_fq_sqrt() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); // Test Fq sqrt (base field) with a perfect square - let mut four = vec![0u8; 32]; + let mut four = [0u8; 32]; four[31] = 4; - let response = api.bn254_fq_sqrt(&four).expect("bn254_fq_sqrt failed"); + let response = api + .bn254_fq_sqrt(four.into()) + .expect("bn254_fq_sqrt failed"); assert!( response.is_square_root, "Square root of four in Fq should exist" ); - let mut expected = vec![0u8; 32]; + let mut expected = [0u8; 32]; expected[31] = 2; - assert_eq!(response.value, expected); + assert_eq!(response.value, expected.into()); api.destroy().expect("Failed to destroy backend"); } diff --git a/barretenberg/rust/tests/src/ffi/ecdsa.rs b/barretenberg/rust/tests/src/ffi/ecdsa.rs index 1a4ce8455120..b0a2423237c7 100644 --- a/barretenberg/rust/tests/src/ffi/ecdsa.rs +++ b/barretenberg/rust/tests/src/ffi/ecdsa.rs @@ -3,12 +3,15 @@ //! Tests for ECDSA secp256k1 signatures. #[cfg(test)] -use barretenberg_rs::{backends::FfiBackend, generated_types::Secp256k1Point, BarretenbergApi}; +use barretenberg_rs::{ + generated_types::{Secp256k1Fq, Secp256k1Point}, + BbApi, FfiBackend, +}; #[test] fn test_ecdsa_compute_public_key() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); // A valid secp256k1 private key (32 bytes) let private_key: [u8; 32] = [ @@ -18,14 +21,11 @@ fn test_ecdsa_compute_public_key() { ]; let response = api - .ecdsa_secp256k1_compute_public_key(&private_key) + .ecdsa_secp256k1_compute_public_key(private_key.into()) .expect("ecdsa_secp256k1_compute_public_key failed"); - // Should return a valid public key point - assert_eq!(response.public_key.x.len(), 32); - assert_eq!(response.public_key.y.len(), 32); // Should not be all zeros - assert_ne!(response.public_key.x, vec![0u8; 32]); + assert_ne!(response.public_key.x, Secp256k1Fq::from_bytes([0u8; 32])); api.destroy().expect("Failed to destroy backend"); } @@ -33,7 +33,7 @@ fn test_ecdsa_compute_public_key() { #[test] fn test_ecdsa_compute_public_key_deterministic() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let private_key: [u8; 32] = [ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, @@ -42,10 +42,10 @@ fn test_ecdsa_compute_public_key_deterministic() { ]; let response1 = api - .ecdsa_secp256k1_compute_public_key(&private_key) + .ecdsa_secp256k1_compute_public_key(private_key.into()) .expect("ecdsa_secp256k1_compute_public_key failed"); let response2 = api - .ecdsa_secp256k1_compute_public_key(&private_key) + .ecdsa_secp256k1_compute_public_key(private_key.into()) .expect("ecdsa_secp256k1_compute_public_key failed"); // Same private key should produce same public key @@ -58,7 +58,7 @@ fn test_ecdsa_compute_public_key_deterministic() { #[test] fn test_ecdsa_different_private_keys() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let private_key1: [u8; 32] = [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -72,10 +72,10 @@ fn test_ecdsa_different_private_keys() { ]; let response1 = api - .ecdsa_secp256k1_compute_public_key(&private_key1) + .ecdsa_secp256k1_compute_public_key(private_key1.into()) .expect("ecdsa_secp256k1_compute_public_key failed"); let response2 = api - .ecdsa_secp256k1_compute_public_key(&private_key2) + .ecdsa_secp256k1_compute_public_key(private_key2.into()) .expect("ecdsa_secp256k1_compute_public_key failed"); // Different private keys should produce different public keys @@ -90,7 +90,7 @@ fn test_ecdsa_different_private_keys() { #[test] fn test_ecdsa_sign_and_verify() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); // Private key let private_key: [u8; 32] = [ @@ -101,7 +101,7 @@ fn test_ecdsa_sign_and_verify() { // Compute public key let pub_key_response = api - .ecdsa_secp256k1_compute_public_key(&private_key) + .ecdsa_secp256k1_compute_public_key(private_key.into()) .expect("ecdsa_secp256k1_compute_public_key failed"); let public_key = Secp256k1Point { x: pub_key_response.public_key.x.clone(), @@ -117,16 +117,18 @@ fn test_ecdsa_sign_and_verify() { // Sign let sign_response = api - .ecdsa_secp256k1_construct_signature(&message_hash, &private_key) + .ecdsa_secp256k1_construct_signature(&message_hash, private_key.into()) .expect("ecdsa_secp256k1_construct_signature failed"); - // Signature should have r, s, and v components - assert_eq!(sign_response.r.len(), 32); - assert_eq!(sign_response.s.len(), 32); - // Verify let verify_response = api - .ecdsa_secp256k1_verify_signature(&message_hash, public_key, &sign_response.r, &sign_response.s, sign_response.v) + .ecdsa_secp256k1_verify_signature( + &message_hash, + public_key, + sign_response.r, + sign_response.s, + sign_response.v, + ) .expect("ecdsa_secp256k1_verify_signature failed"); assert!(verify_response.verified, "Signature should be valid"); @@ -137,7 +139,7 @@ fn test_ecdsa_sign_and_verify() { #[test] fn test_ecdsa_verify_wrong_message() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let private_key: [u8; 32] = [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -146,7 +148,7 @@ fn test_ecdsa_verify_wrong_message() { ]; let pub_key_response = api - .ecdsa_secp256k1_compute_public_key(&private_key) + .ecdsa_secp256k1_compute_public_key(private_key.into()) .expect("ecdsa_secp256k1_compute_public_key failed"); let public_key = Secp256k1Point { x: pub_key_response.public_key.x.clone(), @@ -158,15 +160,24 @@ fn test_ecdsa_verify_wrong_message() { // Sign with message_hash1 let sign_response = api - .ecdsa_secp256k1_construct_signature(&message_hash1, &private_key) + .ecdsa_secp256k1_construct_signature(&message_hash1, private_key.into()) .expect("ecdsa_secp256k1_construct_signature failed"); // Verify with message_hash2 - should fail let verify_response = api - .ecdsa_secp256k1_verify_signature(&message_hash2, public_key, &sign_response.r, &sign_response.s, sign_response.v) + .ecdsa_secp256k1_verify_signature( + &message_hash2, + public_key, + sign_response.r, + sign_response.s, + sign_response.v, + ) .expect("ecdsa_secp256k1_verify_signature failed"); - assert!(!verify_response.verified, "Signature should be invalid for wrong message"); + assert!( + !verify_response.verified, + "Signature should be invalid for wrong message" + ); api.destroy().expect("Failed to destroy backend"); } diff --git a/barretenberg/rust/tests/src/ffi/grumpkin.rs b/barretenberg/rust/tests/src/ffi/grumpkin.rs index 1482485000a1..c8674bd6e7de 100644 --- a/barretenberg/rust/tests/src/ffi/grumpkin.rs +++ b/barretenberg/rust/tests/src/ffi/grumpkin.rs @@ -3,7 +3,7 @@ //! Ported from zkpassport/aztec-packages bb_rs grumpkin_tests.rs #[cfg(test)] -use barretenberg_rs::{backends::FfiBackend, generated_types::GrumpkinPoint, BarretenbergApi}; +use barretenberg_rs::{generated_types::GrumpkinPoint, BbApi, FfiBackend, Fr}; // Grumpkin generator point // x = 1 @@ -24,28 +24,27 @@ fn grumpkin_generator() -> GrumpkinPoint { 0x27, 0x2c, ]; GrumpkinPoint { - x: x.to_vec(), - y: y.to_vec(), + x: x.into(), + y: y.into(), } } #[test] fn test_grumpkin_scalar_multiplication() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let point = grumpkin_generator(); - let mut scalar = vec![0u8; 32]; - scalar[31] = 3; // scalar = 3 + let scalar = Fr::from_u64(3); let response = api - .grumpkin_mul(point.clone(), &scalar) + .grumpkin_mul(point.clone(), scalar) .expect("grumpkin_mul failed"); // Result should be different from input (3*G != G) assert_ne!(response.point.x, point.x); // Result should be a valid point (non-zero) - assert_ne!(response.point.x, vec![0u8; 32]); + assert_ne!(response.point.x, Fr::from_be_bytes([0u8; 32])); api.destroy().expect("Failed to destroy backend"); } @@ -53,15 +52,13 @@ fn test_grumpkin_scalar_multiplication() { #[test] fn test_grumpkin_scalar_multiplication_by_one() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let point = grumpkin_generator(); - - let mut scalar = vec![0u8; 32]; - scalar[31] = 1; // scalar = 1 + let scalar = Fr::from_u64(1); let response = api - .grumpkin_mul(point.clone(), &scalar) + .grumpkin_mul(point.clone(), scalar) .expect("grumpkin_mul failed"); // Multiplying by 1 should give the same point @@ -74,7 +71,7 @@ fn test_grumpkin_scalar_multiplication_by_one() { #[test] fn test_grumpkin_random_scalar_generation() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let response1 = api .grumpkin_get_random_fr(0) @@ -86,8 +83,8 @@ fn test_grumpkin_random_scalar_generation() { // Random scalars should be different (very high probability) assert_ne!(response1.value, response2.value); // Should not be zero - assert_ne!(response1.value, vec![0u8; 32]); - assert_ne!(response2.value, vec![0u8; 32]); + assert_ne!(response1.value, Fr::from_be_bytes([0u8; 32])); + assert_ne!(response2.value, Fr::from_be_bytes([0u8; 32])); api.destroy().expect("Failed to destroy backend"); } @@ -95,7 +92,7 @@ fn test_grumpkin_random_scalar_generation() { #[test] fn test_grumpkin_random_scalar_multiple_calls() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let mut scalars = Vec::new(); for _ in 0..10 { @@ -122,7 +119,7 @@ fn test_grumpkin_random_scalar_multiple_calls() { #[test] fn test_grumpkin_reduce512() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let large_input = [0xffu8; 64]; // Maximum 512-bit value @@ -131,7 +128,7 @@ fn test_grumpkin_reduce512() { .expect("grumpkin_reduce512 failed"); // Should produce a valid field element - assert_ne!(response.value, vec![0u8; 32]); + assert_ne!(response.value, Fr::from_be_bytes([0u8; 32])); // Should be different from the first 32 bytes of input (since we're reducing) assert_ne!(response.value.as_slice(), &large_input[..32]); @@ -141,7 +138,7 @@ fn test_grumpkin_reduce512() { #[test] fn test_grumpkin_reduce512_small_value() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let mut small_input = [0u8; 64]; small_input[63] = 42; // A small value @@ -151,9 +148,9 @@ fn test_grumpkin_reduce512_small_value() { .expect("grumpkin_reduce512 failed"); // For a small value, the reduction should preserve it - let mut expected = vec![0u8; 32]; + let mut expected = [0u8; 32]; expected[31] = 42; - assert_eq!(response.value, expected); + assert_eq!(response.value, Fr::from_be_bytes(expected)); api.destroy().expect("Failed to destroy backend"); } @@ -161,7 +158,7 @@ fn test_grumpkin_reduce512_small_value() { #[test] fn test_grumpkin_reduce512_zero() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let zero_input = [0u8; 64]; @@ -170,7 +167,7 @@ fn test_grumpkin_reduce512_zero() { .expect("grumpkin_reduce512 failed"); // Zero should remain zero after reduction - assert_eq!(response.value, vec![0u8; 32]); + assert_eq!(response.value, Fr::from_be_bytes([0u8; 32])); api.destroy().expect("Failed to destroy backend"); } @@ -178,18 +175,16 @@ fn test_grumpkin_reduce512_zero() { #[test] fn test_grumpkin_mul_deterministic() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let point = grumpkin_generator(); - - let mut scalar = vec![0u8; 32]; - scalar[31] = 5; + let scalar = Fr::from_u64(5); let result1 = api - .grumpkin_mul(point.clone(), &scalar) + .grumpkin_mul(point.clone(), scalar.clone()) .expect("grumpkin_mul failed"); let result2 = api - .grumpkin_mul(point, &scalar) + .grumpkin_mul(point, scalar) .expect("grumpkin_mul failed"); // Should be deterministic @@ -202,7 +197,7 @@ fn test_grumpkin_mul_deterministic() { #[test] fn test_grumpkin_reduce512_deterministic() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let large_scalar_512 = [0xffu8; 64]; diff --git a/barretenberg/rust/tests/src/ffi/pedersen.rs b/barretenberg/rust/tests/src/ffi/pedersen.rs index e317b5bccd32..16078e4f9aed 100644 --- a/barretenberg/rust/tests/src/ffi/pedersen.rs +++ b/barretenberg/rust/tests/src/ffi/pedersen.rs @@ -3,25 +3,19 @@ //! Ported from zkpassport/aztec-packages bb_rs pedersen_tests.rs #[cfg(test)] -use barretenberg_rs::{backends::FfiBackend, BarretenbergApi, Fr}; +use barretenberg_rs::{BbApi, FfiBackend, Fr}; #[test] fn test_pedersen_hash_basic() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); - // Test with simple inputs - let inputs = vec![ - Fr::from_u64(1).to_buffer(), - Fr::from_u64(2).to_buffer(), - ]; + let inputs = vec![Fr::from_u64(1), Fr::from_u64(2)]; let response = api.pedersen_hash(inputs, 0).expect("PedersenHash failed"); - // Result should be a valid field element (32 bytes) - assert_eq!(response.hash.len(), 32); // Should not be zero - assert_ne!(response.hash, vec![0u8; 32]); + assert_ne!(response.hash, Fr::from_be_bytes([0u8; 32])); api.destroy().expect("Failed to destroy backend"); } @@ -29,14 +23,13 @@ fn test_pedersen_hash_basic() { #[test] fn test_pedersen_hash_deterministic() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); - let inputs = vec![ - Fr::from_u64(42).to_buffer(), - Fr::from_u64(123).to_buffer(), - ]; + let inputs = vec![Fr::from_u64(42), Fr::from_u64(123)]; - let response1 = api.pedersen_hash(inputs.clone(), 0).expect("PedersenHash failed"); + let response1 = api + .pedersen_hash(inputs.clone(), 0) + .expect("PedersenHash failed"); let response2 = api.pedersen_hash(inputs, 0).expect("PedersenHash failed"); // Same inputs should produce same output @@ -48,16 +41,10 @@ fn test_pedersen_hash_deterministic() { #[test] fn test_pedersen_hash_different_inputs() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); - let inputs1 = vec![ - Fr::from_u64(1).to_buffer(), - Fr::from_u64(2).to_buffer(), - ]; - let inputs2 = vec![ - Fr::from_u64(3).to_buffer(), - Fr::from_u64(4).to_buffer(), - ]; + let inputs1 = vec![Fr::from_u64(1), Fr::from_u64(2)]; + let inputs2 = vec![Fr::from_u64(3), Fr::from_u64(4)]; let response1 = api.pedersen_hash(inputs1, 0).expect("PedersenHash failed"); let response2 = api.pedersen_hash(inputs2, 0).expect("PedersenHash failed"); @@ -71,14 +58,13 @@ fn test_pedersen_hash_different_inputs() { #[test] fn test_pedersen_hash_single_input() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); - let inputs = vec![Fr::from_u64(42).to_buffer()]; + let inputs = vec![Fr::from_u64(42)]; let response = api.pedersen_hash(inputs, 0).expect("PedersenHash failed"); - assert_eq!(response.hash.len(), 32); - assert_ne!(response.hash, vec![0u8; 32]); + assert_ne!(response.hash, Fr::from_be_bytes([0u8; 32])); api.destroy().expect("Failed to destroy backend"); } @@ -86,14 +72,16 @@ fn test_pedersen_hash_single_input() { #[test] fn test_pedersen_hash_zero_input() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); - let inputs = vec![Fr::from_u64(0).to_buffer()]; + let inputs = vec![Fr::from_u64(0)]; - let response = api.pedersen_hash(inputs.clone(), 0).expect("PedersenHash failed"); + let response = api + .pedersen_hash(inputs.clone(), 0) + .expect("PedersenHash failed"); // Even zero input should produce non-zero output - assert_ne!(response.hash, vec![0u8; 32]); + assert_ne!(response.hash, Fr::from_be_bytes([0u8; 32])); assert_ne!(response.hash, inputs[0]); api.destroy().expect("Failed to destroy backend"); @@ -102,15 +90,13 @@ fn test_pedersen_hash_zero_input() { #[test] fn test_pedersen_hash_many_inputs() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); - // Test with many inputs - let inputs: Vec> = (0..10).map(|i| Fr::from_u64(i).to_buffer()).collect(); + let inputs: Vec = (0..10).map(Fr::from_u64).collect(); let response = api.pedersen_hash(inputs, 0).expect("PedersenHash failed"); - assert_eq!(response.hash.len(), 32); - assert_ne!(response.hash, vec![0u8; 32]); + assert_ne!(response.hash, Fr::from_be_bytes([0u8; 32])); api.destroy().expect("Failed to destroy backend"); } @@ -118,14 +104,13 @@ fn test_pedersen_hash_many_inputs() { #[test] fn test_pedersen_hash_different_hash_indices() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); - let inputs = vec![ - Fr::from_u64(1).to_buffer(), - Fr::from_u64(2).to_buffer(), - ]; + let inputs = vec![Fr::from_u64(1), Fr::from_u64(2)]; - let response1 = api.pedersen_hash(inputs.clone(), 0).expect("PedersenHash failed"); + let response1 = api + .pedersen_hash(inputs.clone(), 0) + .expect("PedersenHash failed"); let response2 = api.pedersen_hash(inputs, 1).expect("PedersenHash failed"); // Different hash indices should produce different outputs @@ -137,20 +122,16 @@ fn test_pedersen_hash_different_hash_indices() { #[test] fn test_pedersen_commit_basic() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); - let inputs = vec![ - Fr::from_u64(1).to_buffer(), - Fr::from_u64(2).to_buffer(), - ]; + let inputs = vec![Fr::from_u64(1), Fr::from_u64(2)]; - let response = api.pedersen_commit(inputs, 0).expect("PedersenCommit failed"); + let response = api + .pedersen_commit(inputs, 0) + .expect("PedersenCommit failed"); - // Result should be a point (x, y coordinates) - assert_eq!(response.point.x.len(), 32); - assert_eq!(response.point.y.len(), 32); // Should not be the point at infinity - assert_ne!(response.point.x, vec![0u8; 32]); + assert_ne!(response.point.x, Fr::from_be_bytes([0u8; 32])); api.destroy().expect("Failed to destroy backend"); } @@ -158,15 +139,16 @@ fn test_pedersen_commit_basic() { #[test] fn test_pedersen_commit_deterministic() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); - let inputs = vec![ - Fr::from_u64(42).to_buffer(), - Fr::from_u64(123).to_buffer(), - ]; + let inputs = vec![Fr::from_u64(42), Fr::from_u64(123)]; - let response1 = api.pedersen_commit(inputs.clone(), 0).expect("PedersenCommit failed"); - let response2 = api.pedersen_commit(inputs, 0).expect("PedersenCommit failed"); + let response1 = api + .pedersen_commit(inputs.clone(), 0) + .expect("PedersenCommit failed"); + let response2 = api + .pedersen_commit(inputs, 0) + .expect("PedersenCommit failed"); // Same inputs should produce same commitment assert_eq!(response1.point.x, response2.point.x); @@ -178,25 +160,20 @@ fn test_pedersen_commit_deterministic() { #[test] fn test_pedersen_commit_different_inputs() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); - let inputs1 = vec![ - Fr::from_u64(1).to_buffer(), - Fr::from_u64(2).to_buffer(), - ]; - let inputs2 = vec![ - Fr::from_u64(3).to_buffer(), - Fr::from_u64(4).to_buffer(), - ]; + let inputs1 = vec![Fr::from_u64(1), Fr::from_u64(2)]; + let inputs2 = vec![Fr::from_u64(3), Fr::from_u64(4)]; - let response1 = api.pedersen_commit(inputs1, 0).expect("PedersenCommit failed"); - let response2 = api.pedersen_commit(inputs2, 0).expect("PedersenCommit failed"); + let response1 = api + .pedersen_commit(inputs1, 0) + .expect("PedersenCommit failed"); + let response2 = api + .pedersen_commit(inputs2, 0) + .expect("PedersenCommit failed"); // Different inputs should produce different commitments - assert!( - response1.point.x != response2.point.x - || response1.point.y != response2.point.y - ); + assert!(response1.point.x != response2.point.x || response1.point.y != response2.point.y); api.destroy().expect("Failed to destroy backend"); } diff --git a/barretenberg/rust/tests/src/ffi/poseidon.rs b/barretenberg/rust/tests/src/ffi/poseidon.rs index c1aae2dd7080..301128cd3c42 100644 --- a/barretenberg/rust/tests/src/ffi/poseidon.rs +++ b/barretenberg/rust/tests/src/ffi/poseidon.rs @@ -3,23 +3,19 @@ //! Ported from zkpassport/aztec-packages bb_rs poseidon2_tests.rs #[cfg(test)] -use barretenberg_rs::{backends::FfiBackend, BarretenbergApi, Fr}; +use barretenberg_rs::{BbApi, FfiBackend, Fr}; #[test] fn test_poseidon2_hash() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); - let inputs = vec![ - Fr::from_u64(4).to_buffer(), - Fr::from_u64(8).to_buffer(), - ]; + let inputs = vec![Fr::from_u64(4), Fr::from_u64(8)]; let response = api.poseidon2_hash(inputs).expect("Poseidon2Hash failed"); - let result = Fr::from_buffer_reduce(&response.hash); // Print result for snapshot comparison - println!("Poseidon2 hash result: {:?}", hex::encode(&result.0)); + println!("Poseidon2 hash result: {:?}", hex::encode(&response.hash.0)); api.destroy().expect("Failed to destroy backend"); } @@ -27,12 +23,16 @@ fn test_poseidon2_hash() { #[test] fn test_poseidon2_hash_deterministic() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); - let input = vec![42u8; 32]; + let input = Fr::from_be_bytes([42u8; 32]); - let response1 = api.poseidon2_hash(vec![input.clone()]).expect("Poseidon2Hash failed"); - let response2 = api.poseidon2_hash(vec![input]).expect("Poseidon2Hash failed"); + let response1 = api + .poseidon2_hash(vec![input.clone()]) + .expect("Poseidon2Hash failed"); + let response2 = api + .poseidon2_hash(vec![input]) + .expect("Poseidon2Hash failed"); // Same input should produce same output assert_eq!(response1.hash, response2.hash); @@ -43,13 +43,17 @@ fn test_poseidon2_hash_deterministic() { #[test] fn test_poseidon2_hash_different_inputs() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); - let input1 = vec![1u8; 32]; - let input2 = vec![2u8; 32]; + let input1 = Fr::from_be_bytes([1u8; 32]); + let input2 = Fr::from_be_bytes([2u8; 32]); - let response1 = api.poseidon2_hash(vec![input1]).expect("Poseidon2Hash failed"); - let response2 = api.poseidon2_hash(vec![input2]).expect("Poseidon2Hash failed"); + let response1 = api + .poseidon2_hash(vec![input1]) + .expect("Poseidon2Hash failed"); + let response2 = api + .poseidon2_hash(vec![input2]) + .expect("Poseidon2Hash failed"); // Different inputs should produce different outputs assert_ne!(response1.hash, response2.hash); @@ -60,14 +64,16 @@ fn test_poseidon2_hash_different_inputs() { #[test] fn test_poseidon2_hash_zero_input() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); - let input = vec![0u8; 32]; + let input = Fr::from_be_bytes([0u8; 32]); - let response = api.poseidon2_hash(vec![input.clone()]).expect("Poseidon2Hash failed"); + let response = api + .poseidon2_hash(vec![input.clone()]) + .expect("Poseidon2Hash failed"); // Even zero input should produce non-zero output - assert_ne!(response.hash, vec![0u8; 32]); + assert_ne!(response.hash, Fr::from_be_bytes([0u8; 32])); assert_ne!(response.hash, input); api.destroy().expect("Failed to destroy backend"); @@ -76,17 +82,19 @@ fn test_poseidon2_hash_zero_input() { #[test] fn test_poseidon2_permutation_js_compatibility_cpp() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); // JS test: poseidon2Permutation([0, 1, 2, 3]) - // Expected results from the JS test - let mut inputs = [vec![0u8; 32], vec![0u8; 32], vec![0u8; 32], vec![0u8; 32]]; - // inputs[0] stays 0 - inputs[1][31] = 1; - inputs[2][31] = 2; - inputs[3][31] = 3; + let inputs = [ + Fr::from_u64(0), + Fr::from_u64(1), + Fr::from_u64(2), + Fr::from_u64(3), + ]; - let response = api.poseidon2_permutation(inputs).expect("Poseidon2Permutation failed"); + let response = api + .poseidon2_permutation(inputs) + .expect("Poseidon2Permutation failed"); assert_eq!(response.outputs.len(), 4); @@ -112,10 +120,10 @@ fn test_poseidon2_permutation_js_compatibility_cpp() { 0x84, 0x7a, ]; - assert_eq!(response.outputs[0].as_slice(), &expected_0); - assert_eq!(response.outputs[1].as_slice(), &expected_1); - assert_eq!(response.outputs[2].as_slice(), &expected_2); - assert_eq!(response.outputs[3].as_slice(), &expected_3); + assert_eq!(response.outputs[0].0, expected_0); + assert_eq!(response.outputs[1].0, expected_1); + assert_eq!(response.outputs[2].0, expected_2); + assert_eq!(response.outputs[3].0, expected_3); api.destroy().expect("Failed to destroy backend"); } @@ -123,19 +131,21 @@ fn test_poseidon2_permutation_js_compatibility_cpp() { #[test] fn test_poseidon2_permutation_js_compatibility_noir() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); // JS test: poseidon2Permutation([1n, 2n, 3n, 0x0a0000000000000000n]) - let mut inputs = [vec![0u8; 32], vec![0u8; 32], vec![0u8; 32], vec![0u8; 32]]; - - // Set the values in big-endian - inputs[0][31] = 1; // 1n - inputs[1][31] = 2; // 2n - inputs[2][31] = 3; // 3n - // 0x0a0000000000000000n = 720575940379279360 - inputs[3][23] = 0x0a; // Set the appropriate byte for this large number + let mut input3 = [0u8; 32]; + input3[23] = 0x0a; // 0x0a0000000000000000n + let inputs = [ + Fr::from_u64(1), + Fr::from_u64(2), + Fr::from_u64(3), + Fr::from_be_bytes(input3), + ]; - let response = api.poseidon2_permutation(inputs).expect("Poseidon2Permutation failed"); + let response = api + .poseidon2_permutation(inputs) + .expect("Poseidon2Permutation failed"); assert_eq!(response.outputs.len(), 4); @@ -161,10 +171,10 @@ fn test_poseidon2_permutation_js_compatibility_noir() { 0x3d, 0x4a, ]; - assert_eq!(response.outputs[0].as_slice(), &expected_0); - assert_eq!(response.outputs[1].as_slice(), &expected_1); - assert_eq!(response.outputs[2].as_slice(), &expected_2); - assert_eq!(response.outputs[3].as_slice(), &expected_3); + assert_eq!(response.outputs[0].0, expected_0); + assert_eq!(response.outputs[1].0, expected_1); + assert_eq!(response.outputs[2].0, expected_2); + assert_eq!(response.outputs[3].0, expected_3); api.destroy().expect("Failed to destroy backend"); } diff --git a/barretenberg/rust/tests/src/ffi/schnorr.rs b/barretenberg/rust/tests/src/ffi/schnorr.rs index b31f662339fd..b3bd44980be8 100644 --- a/barretenberg/rust/tests/src/ffi/schnorr.rs +++ b/barretenberg/rust/tests/src/ffi/schnorr.rs @@ -3,12 +3,12 @@ //! Tests for Schnorr signatures over the Grumpkin curve. #[cfg(test)] -use barretenberg_rs::{backends::FfiBackend, BarretenbergApi}; +use barretenberg_rs::{BbApi, FfiBackend, Fr}; #[test] fn test_schnorr_compute_public_key() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); // A valid private key (32 bytes) let private_key: [u8; 32] = [ @@ -18,14 +18,11 @@ fn test_schnorr_compute_public_key() { ]; let response = api - .schnorr_compute_public_key(&private_key) + .schnorr_compute_public_key(private_key.into()) .expect("schnorr_compute_public_key failed"); - // Should return a valid public key point - assert_eq!(response.public_key.x.len(), 32); - assert_eq!(response.public_key.y.len(), 32); // Should not be zero - assert_ne!(response.public_key.x, vec![0u8; 32]); + assert_ne!(response.public_key.x, Fr::from_be_bytes([0u8; 32])); api.destroy().expect("Failed to destroy backend"); } @@ -33,7 +30,7 @@ fn test_schnorr_compute_public_key() { #[test] fn test_schnorr_compute_public_key_deterministic() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let private_key: [u8; 32] = [ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, @@ -42,10 +39,10 @@ fn test_schnorr_compute_public_key_deterministic() { ]; let response1 = api - .schnorr_compute_public_key(&private_key) + .schnorr_compute_public_key(private_key.into()) .expect("schnorr_compute_public_key failed"); let response2 = api - .schnorr_compute_public_key(&private_key) + .schnorr_compute_public_key(private_key.into()) .expect("schnorr_compute_public_key failed"); // Same private key should produce same public key @@ -58,7 +55,7 @@ fn test_schnorr_compute_public_key_deterministic() { #[test] fn test_schnorr_different_private_keys() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let private_key1: [u8; 32] = [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -72,10 +69,10 @@ fn test_schnorr_different_private_keys() { ]; let response1 = api - .schnorr_compute_public_key(&private_key1) + .schnorr_compute_public_key(private_key1.into()) .expect("schnorr_compute_public_key failed"); let response2 = api - .schnorr_compute_public_key(&private_key2) + .schnorr_compute_public_key(private_key2.into()) .expect("schnorr_compute_public_key failed"); // Different private keys should produce different public keys @@ -90,7 +87,7 @@ fn test_schnorr_different_private_keys() { #[test] fn test_schnorr_sign_and_verify() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); // Private key let private_key: [u8; 32] = [ @@ -101,32 +98,28 @@ fn test_schnorr_sign_and_verify() { // Compute public key let pub_key_response = api - .schnorr_compute_public_key(&private_key) + .schnorr_compute_public_key(private_key.into()) .expect("schnorr_compute_public_key failed"); - // Message: a 32-byte big-endian serialized grumpkin base-field element (bbapi asserts size == 32). + // Message is a pre-derived 32-byte field element (post-#21808 schnorr API). let message: [u8; 32] = [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0xbc, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, + 0x1f, 0x20, ]; // Sign let sign_response = api - .schnorr_construct_signature(&message, &private_key) + .schnorr_construct_signature(&message, private_key.into()) .expect("schnorr_construct_signature failed"); - // Signature should have s and e components (32 bytes each) - assert_eq!(sign_response.s.len(), 32); - assert_eq!(sign_response.e.len(), 32); - // Verify let verify_response = api .schnorr_verify_signature( &message, pub_key_response.public_key.clone(), - &sign_response.s, - &sign_response.e, + sign_response.s, + sign_response.e, ) .expect("schnorr_verify_signature failed"); @@ -138,7 +131,7 @@ fn test_schnorr_sign_and_verify() { #[test] fn test_schnorr_verify_wrong_message() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let private_key: [u8; 32] = [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -147,24 +140,16 @@ fn test_schnorr_verify_wrong_message() { ]; let pub_key_response = api - .schnorr_compute_public_key(&private_key) + .schnorr_compute_public_key(private_key.into()) .expect("schnorr_compute_public_key failed"); - // Two distinct 32-byte serialized field elements (bbapi asserts size == 32). - let message1: [u8; 32] = [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x11, - ]; - let message2: [u8; 32] = [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x22, - ]; + // Messages are pre-derived 32-byte field elements. + let message1: [u8; 32] = [0x01; 32]; + let message2: [u8; 32] = [0x02; 32]; // Sign with message1 let sign_response = api - .schnorr_construct_signature(&message1, &private_key) + .schnorr_construct_signature(&message1, private_key.into()) .expect("schnorr_construct_signature failed"); // Verify with message2 - should fail @@ -172,8 +157,8 @@ fn test_schnorr_verify_wrong_message() { .schnorr_verify_signature( &message2, pub_key_response.public_key.clone(), - &sign_response.s, - &sign_response.e, + sign_response.s, + sign_response.e, ) .expect("schnorr_verify_signature failed"); diff --git a/barretenberg/rust/tests/src/ffi/secp256k1.rs b/barretenberg/rust/tests/src/ffi/secp256k1.rs index d65358663ef9..4958769c5c5a 100644 --- a/barretenberg/rust/tests/src/ffi/secp256k1.rs +++ b/barretenberg/rust/tests/src/ffi/secp256k1.rs @@ -3,7 +3,27 @@ //! Ported from zkpassport/aztec-packages bb_rs secp256k1_tests.rs #[cfg(test)] -use barretenberg_rs::{backends::FfiBackend, generated_types::Secp256k1Point, BarretenbergApi}; +use barretenberg_rs::{ + generated_types::{Secp256k1Fq, Secp256k1Fr, Secp256k1Point}, + BbApi, FfiBackend, +}; + +#[cfg(test)] +fn zero_fq() -> Secp256k1Fq { + Secp256k1Fq::from_bytes([0u8; 32]) +} + +#[cfg(test)] +fn zero_fr() -> Secp256k1Fr { + Secp256k1Fr::from_bytes([0u8; 32]) +} + +#[cfg(test)] +fn fr_from_u32(value: u32) -> Secp256k1Fr { + let mut bytes = [0u8; 32]; + bytes[28..32].copy_from_slice(&value.to_be_bytes()); + Secp256k1Fr::from_bytes(bytes) +} // secp256k1 generator point G // x = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798 @@ -11,40 +31,37 @@ use barretenberg_rs::{backends::FfiBackend, generated_types::Secp256k1Point, Bar #[cfg(test)] fn secp256k1_generator() -> Secp256k1Point { let generator_x: [u8; 32] = [ - 0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac, - 0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07, - 0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9, - 0x59, 0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98, + 0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac, 0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, + 0x07, 0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9, 0x59, 0xf2, 0x81, 0x5b, 0x16, 0xf8, + 0x17, 0x98, ]; let generator_y: [u8; 32] = [ - 0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, - 0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8, - 0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19, - 0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8, + 0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, + 0xa8, 0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19, 0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, + 0xd4, 0xb8, ]; Secp256k1Point { - x: generator_x.to_vec(), - y: generator_y.to_vec(), + x: generator_x.into(), + y: generator_y.into(), } } #[test] fn test_secp256k1_scalar_multiplication() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let point = secp256k1_generator(); - let mut scalar = vec![0u8; 32]; - scalar[31] = 3; // scalar = 3 + let scalar = fr_from_u32(3); let response = api - .secp256k1_mul(point.clone(), &scalar) + .secp256k1_mul(point.clone(), scalar) .expect("secp256k1_mul failed"); // Result should be different from input (3*G != G) assert_ne!(response.point.x, point.x); // Result should be a valid point (non-zero) - assert_ne!(response.point.x, vec![0u8; 32]); + assert_ne!(response.point.x, zero_fq()); api.destroy().expect("Failed to destroy backend"); } @@ -52,15 +69,13 @@ fn test_secp256k1_scalar_multiplication() { #[test] fn test_secp256k1_scalar_multiplication_by_one() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let point = secp256k1_generator(); - - let mut scalar = vec![0u8; 32]; - scalar[31] = 1; // scalar = 1 + let scalar = fr_from_u32(1); let response = api - .secp256k1_mul(point.clone(), &scalar) + .secp256k1_mul(point.clone(), scalar) .expect("secp256k1_mul failed"); // Multiplying by 1 should give the same point @@ -73,7 +88,7 @@ fn test_secp256k1_scalar_multiplication_by_one() { #[test] fn test_secp256k1_random_scalar_generation() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let response1 = api .secp256k1_get_random_fr(0) @@ -85,8 +100,8 @@ fn test_secp256k1_random_scalar_generation() { // Random scalars should be different (very high probability) assert_ne!(response1.value, response2.value); // Should not be zero - assert_ne!(response1.value, vec![0u8; 32]); - assert_ne!(response2.value, vec![0u8; 32]); + assert_ne!(response1.value, zero_fr()); + assert_ne!(response2.value, zero_fr()); api.destroy().expect("Failed to destroy backend"); } @@ -94,7 +109,7 @@ fn test_secp256k1_random_scalar_generation() { #[test] fn test_secp256k1_random_scalar_multiple_calls() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let mut scalars = Vec::new(); for _ in 0..10 { @@ -121,7 +136,7 @@ fn test_secp256k1_random_scalar_multiple_calls() { #[test] fn test_secp256k1_reduce512() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let large_input = [0xffu8; 64]; // Maximum 512-bit value @@ -130,7 +145,7 @@ fn test_secp256k1_reduce512() { .expect("secp256k1_reduce512 failed"); // Should produce a valid field element - assert_ne!(response.value, vec![0u8; 32]); + assert_ne!(response.value, zero_fr()); // Should be different from the first 32 bytes of input (since we're reducing) assert_ne!(response.value.as_slice(), &large_input[..32]); @@ -140,7 +155,7 @@ fn test_secp256k1_reduce512() { #[test] fn test_secp256k1_reduce512_small_value() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let mut small_input = [0u8; 64]; small_input[63] = 42; // A small value @@ -150,9 +165,9 @@ fn test_secp256k1_reduce512_small_value() { .expect("secp256k1_reduce512 failed"); // For a small value, the reduction should preserve it - let mut expected = vec![0u8; 32]; + let mut expected = [0u8; 32]; expected[31] = 42; - assert_eq!(response.value, expected); + assert_eq!(response.value, Secp256k1Fr::from_bytes(expected)); api.destroy().expect("Failed to destroy backend"); } @@ -160,7 +175,7 @@ fn test_secp256k1_reduce512_small_value() { #[test] fn test_secp256k1_reduce512_zero() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let zero_input = [0u8; 64]; @@ -169,7 +184,7 @@ fn test_secp256k1_reduce512_zero() { .expect("secp256k1_reduce512 failed"); // Zero should remain zero after reduction - assert_eq!(response.value, vec![0u8; 32]); + assert_eq!(response.value, zero_fr()); api.destroy().expect("Failed to destroy backend"); } @@ -177,7 +192,7 @@ fn test_secp256k1_reduce512_zero() { #[test] fn test_secp256k1_reduce512_various_inputs() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); // Test with different patterns let mut input1 = [0u8; 64]; @@ -201,18 +216,16 @@ fn test_secp256k1_reduce512_various_inputs() { #[test] fn test_secp256k1_mul_deterministic() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let point = secp256k1_generator(); - - let mut scalar = vec![0u8; 32]; - scalar[31] = 5; + let scalar = fr_from_u32(5); let result1 = api - .secp256k1_mul(point.clone(), &scalar) + .secp256k1_mul(point.clone(), scalar.clone()) .expect("secp256k1_mul failed"); let result2 = api - .secp256k1_mul(point, &scalar) + .secp256k1_mul(point, scalar) .expect("secp256k1_mul failed"); // Should be deterministic @@ -225,7 +238,7 @@ fn test_secp256k1_mul_deterministic() { #[test] fn test_secp256k1_reduce512_deterministic() { let backend = FfiBackend::new().expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); + let mut api = BbApi::new(backend); let large_scalar_512 = [0xffu8; 64]; diff --git a/barretenberg/rust/tests/src/legacy_shim.rs b/barretenberg/rust/tests/src/legacy_shim.rs new file mode 100644 index 000000000000..b68697cf05ce --- /dev/null +++ b/barretenberg/rust/tests/src/legacy_shim.rs @@ -0,0 +1,71 @@ +//! Smoke tests for the deprecated `BarretenbergApi` back-compat shim. +//! +//! Exercises a handful of methods whose signatures changed between the +//! pre-codegen and codegen surface (typed scalars vs `&[u8]`, +//! `Vec` vs `Vec>`). Confirms the shim still accepts the old +//! shape and forwards correctly. + +#![cfg(feature = "ffi")] +#![allow(deprecated)] + +use barretenberg_rs::{BarretenbergApi, FfiBackend}; + +#[test] +fn shim_pedersen_hash_old_surface() { + let backend = FfiBackend::new().expect("Failed to create backend"); + let mut api = BarretenbergApi::new(backend); + + // Old surface: Vec> (32-byte buffers per scalar). + let inputs: Vec> = vec![{ + let mut b = vec![0u8; 32]; + b[31] = 1; + b + }]; + + let response = api + .pedersen_hash(inputs, 0) + .expect("pedersen_hash via shim failed"); + assert_ne!(response.hash.0, [0u8; 32]); + + api.destroy().expect("Failed to destroy backend"); +} + +#[test] +fn shim_schnorr_compute_public_key_old_surface() { + let backend = FfiBackend::new().expect("Failed to create backend"); + let mut api = BarretenbergApi::new(backend); + + // Old surface: &[u8] for private_key. + let private_key = vec![{ + let mut b = [0u8; 32]; + b[31] = 1; + b + }] + .pop() + .unwrap(); + + let response = api + .schnorr_compute_public_key(&private_key) + .expect("schnorr_compute_public_key via shim failed"); + assert_ne!(response.public_key.x.0, [0u8; 32]); + + api.destroy().expect("Failed to destroy backend"); +} + +#[test] +fn shim_bn254_fr_sqrt_old_surface() { + let backend = FfiBackend::new().expect("Failed to create backend"); + let mut api = BarretenbergApi::new(backend); + + // Old surface: &[u8] for input. + let mut four = vec![0u8; 32]; + four[31] = 4; + + let response = api + .bn254_fr_sqrt(&four) + .expect("bn254_fr_sqrt via shim failed"); + assert!(response.is_square_root); + assert_eq!(response.value.0[31], 2); + + api.destroy().expect("Failed to destroy backend"); +} diff --git a/barretenberg/rust/tests/src/lib.rs b/barretenberg/rust/tests/src/lib.rs index 957f9277fa05..c6616108a85a 100644 --- a/barretenberg/rust/tests/src/lib.rs +++ b/barretenberg/rust/tests/src/lib.rs @@ -1,28 +1,14 @@ -//! Barretenberg Rust test suite +//! Barretenberg Rust test suite. //! -//! This test suite parallels the TypeScript test suite in barretenberg/ts/src/barretenberg. -//! -//! ## Running Tests -//! -//! ```bash -//! # Build BB binary first (from barretenberg root) -//! ./bootstrap.sh -//! -//! # Run all tests -//! cargo test --release -//! -//! # Or set custom BB binary path -//! BB_BINARY_PATH=/path/to/bb cargo test --release -//! ``` +//! Parallels the TypeScript test suite in barretenberg/ts/src/barretenberg. +//! All integration tests run through the FFI backend — build BB locally +//! first (`barretenberg/cpp/bootstrap.sh`) so `libbarretenberg` is on the +//! link path, then `cargo test --features ffi --release`. -pub mod blake2s; -pub mod pedersen; -pub mod poseidon; -pub mod pipe_test; -pub mod utils; pub mod debug_msgpack; #[cfg(feature = "ffi")] pub mod ffi; -pub use utils::Timer; +#[cfg(feature = "ffi")] +pub mod legacy_shim; diff --git a/barretenberg/rust/tests/src/pedersen.rs b/barretenberg/rust/tests/src/pedersen.rs deleted file mode 100644 index d7ff5f9c62d3..000000000000 --- a/barretenberg/rust/tests/src/pedersen.rs +++ /dev/null @@ -1,148 +0,0 @@ -//! Pedersen hash and commit tests -//! -//! Parallels barretenberg/ts/src/barretenberg/pedersen.test.ts -//! -//! These tests require the BB binary to be built. They are skipped if the binary is not found. - -#[cfg(test)] -use barretenberg_rs::{backends::PipeBackend, BarretenbergApi, Fr}; -#[cfg(test)] -use crate::utils::{get_bb_binary_path, random_fr, Timer}; -#[cfg(test)] -use crate::require_bb_binary; - -#[test] -fn test_pedersen_hash() { - require_bb_binary!(); - let bb_path = get_bb_binary_path(); - - let backend = PipeBackend::new(&bb_path, Some(1)) - .expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); - - let inputs = vec![ - Fr::from_u64(4).to_buffer().try_into().unwrap(), - Fr::from_u64(8).to_buffer().try_into().unwrap(), - ]; - - let response = api.pedersen_hash(inputs, 7).expect("PedersenHash failed"); - let result = Fr::from_buffer_reduce(&response.hash); - - // Print result for snapshot comparison - println!("Pedersen hash result: {:?}", hex::encode(&result.0)); - - api.destroy().expect("Failed to destroy backend"); -} - -#[test] -fn test_pedersen_hash_buffer() { - require_bb_binary!(); - let bb_path = get_bb_binary_path(); - - let backend = PipeBackend::new(&bb_path, Some(1)) - .expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); - - let mut input = vec![0u8; 123]; - input[0..4].copy_from_slice(&321u32.to_be_bytes()); - input[119..123].copy_from_slice(&456u32.to_be_bytes()); - - let response = api - .pedersen_hash_buffer(input.as_slice(), 0) - .expect("PedersenHashBuffer failed"); - let result = Fr::from_buffer_reduce(&response.hash); - - // Print result for snapshot comparison - println!("Pedersen hash buffer result: {:?}", hex::encode(&result.0)); - - api.destroy().expect("Failed to destroy backend"); -} - -#[test] -fn test_pedersen_commit() { - require_bb_binary!(); - let bb_path = get_bb_binary_path(); - - let backend = PipeBackend::new(&bb_path, Some(1)) - .expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); - - let inputs = vec![ - Fr::from_u64(4).to_buffer().try_into().unwrap(), - Fr::from_u64(8).to_buffer().try_into().unwrap(), - Fr::from_u64(12).to_buffer().try_into().unwrap(), - ]; - - let response = api.pedersen_commit(inputs, 0).expect("PedersenCommit failed"); - - let x = Fr::from_buffer_reduce(&response.point.x); - let y = Fr::from_buffer_reduce(&response.point.y); - - // Print result for snapshot comparison - println!("Pedersen commit point.x: {:?}", hex::encode(&x.0)); - println!("Pedersen commit point.y: {:?}", hex::encode(&y.0)); - - api.destroy().expect("Failed to destroy backend"); -} - -#[test] -#[ignore] // Performance test - run with --ignored -fn test_pedersen_hash_perf() { - require_bb_binary!(); - let bb_path = get_bb_binary_path(); - - let backend = PipeBackend::new(&bb_path, Some(1)) - .expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); - - let loops = 1000; - let mut fields = Vec::with_capacity(loops * 2); - for _ in 0..loops * 2 { - fields.push(random_fr()); - } - - let timer = Timer::new(); - for i in 0..loops { - let inputs = vec![ - fields[i * 2].to_buffer().try_into().unwrap(), - fields[i * 2 + 1].to_buffer().try_into().unwrap(), - ]; - let _ = api.pedersen_hash(inputs, 0).expect("PedersenHash failed"); - } - let us = timer.us() / loops as u128; - - println!("Executed {} hashes at an average {}us / hash", loops, us); - - api.destroy().expect("Failed to destroy backend"); -} - -#[test] -#[ignore] // Performance test - run with --ignored -fn test_pedersen_commit_perf() { - require_bb_binary!(); - let bb_path = get_bb_binary_path(); - - let backend = PipeBackend::new(&bb_path, Some(1)) - .expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); - - let loops = 1000; - let mut fields = Vec::with_capacity(loops * 2); - for _ in 0..loops * 2 { - fields.push(random_fr()); - } - - let timer = Timer::new(); - for i in 0..loops { - let inputs = vec![ - fields[i * 2].to_buffer().try_into().unwrap(), - fields[i * 2 + 1].to_buffer().try_into().unwrap(), - ]; - let _ = api.pedersen_commit(inputs, 0).expect("PedersenCommit failed"); - } - let us = timer.us() / loops as u128; - - println!("Executed {} commits at an average {}us / commit", loops, us); - - api.destroy().expect("Failed to destroy backend"); -} diff --git a/barretenberg/rust/tests/src/pipe_test.rs b/barretenberg/rust/tests/src/pipe_test.rs deleted file mode 100644 index 3cb17bcc2809..000000000000 --- a/barretenberg/rust/tests/src/pipe_test.rs +++ /dev/null @@ -1,176 +0,0 @@ -//! Pipe backend tests -//! -//! Tests for the pipe (stdin/stdout) backend implementation -//! -//! These tests require the BB binary to be built. They are skipped if the binary is not found. - -#[cfg(test)] -use barretenberg_rs::{backends::PipeBackend, BarretenbergApi, Fr}; -#[cfg(test)] -use crate::utils::get_bb_binary_path; -#[cfg(test)] -use crate::require_bb_binary; - -#[test] -fn test_pipe_blake2s() { - require_bb_binary!(); - let bb_path = get_bb_binary_path(); - - let backend = PipeBackend::new(&bb_path, Some(1)) - .expect("Failed to create pipe backend"); - let mut api = BarretenbergApi::new(backend); - - let input = b"abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789"; - let expected: [u8; 32] = [ - 0x44, 0xdd, 0xdb, 0x39, 0xbd, 0xb2, 0xaf, 0x80, 0xc1, 0x47, 0x89, 0x4c, 0x1d, 0x75, 0x6a, - 0xda, 0x3d, 0x1c, 0x2a, 0xc2, 0xb1, 0x00, 0x54, 0x1e, 0x04, 0xfe, 0x87, 0xb4, 0xa5, 0x9e, - 0x12, 0x43, - ]; - - let response = api.blake2s(input).expect("Blake2s failed"); - - assert_eq!( - response.hash.as_slice(), - &expected, - "Blake2s hash mismatch" - ); - - api.destroy().expect("Failed to destroy backend"); -} - -#[test] -fn test_pipe_pedersen_hash() { - require_bb_binary!(); - let bb_path = get_bb_binary_path(); - - let backend = PipeBackend::new(&bb_path, Some(1)) - .expect("Failed to create pipe backend"); - let mut api = BarretenbergApi::new(backend); - - let inputs = vec![ - Fr::from_u64(4).to_buffer(), - Fr::from_u64(8).to_buffer(), - ]; - - let response = api.pedersen_hash(inputs, 7).expect("PedersenHash failed"); - let result = Fr::from_buffer_reduce(&response.hash); - - // Print result for snapshot comparison - println!("Pedersen hash result (pipe): {:?}", hex::encode(&result.0)); - - api.destroy().expect("Failed to destroy backend"); -} - -#[test] -fn test_pipe_poseidon2_hash() { - require_bb_binary!(); - let bb_path = get_bb_binary_path(); - - let backend = PipeBackend::new(&bb_path, Some(1)) - .expect("Failed to create pipe backend"); - let mut api = BarretenbergApi::new(backend); - - let inputs = vec![ - Fr::from_u64(4).to_buffer(), - Fr::from_u64(8).to_buffer(), - ]; - - let response = api.poseidon2_hash(inputs).expect("Poseidon2Hash failed"); - let result = Fr::from_buffer_reduce(&response.hash); - - // Print result for snapshot comparison - println!("Poseidon2 hash result (pipe): {:?}", hex::encode(&result.0)); - - api.destroy().expect("Failed to destroy backend"); -} - -#[test] -fn test_pipe_grumpkin_add() { - require_bb_binary!(); - let bb_path = get_bb_binary_path(); - - let backend = PipeBackend::new(&bb_path, Some(1)) - .expect("Failed to create pipe backend"); - let mut api = BarretenbergApi::new(backend); - - // Grumpkin generator point (from precomputed_generators_grumpkin_impl.hpp) - // x = 0x2df8b940e5890e4e1377e05373fae69a1d754f6935e6a780b666947431f2cdcd - // y = 0x2ecd88d15967bc53b885912e0d16866154acb6aac2d3f85e27ca7eefb2c19083 - let generator_x: [u8; 32] = [ - 0x2d, 0xf8, 0xb9, 0x40, 0xe5, 0x89, 0x0e, 0x4e, - 0x13, 0x77, 0xe0, 0x53, 0x73, 0xfa, 0xe6, 0x9a, - 0x1d, 0x75, 0x4f, 0x69, 0x35, 0xe6, 0xa7, 0x80, - 0xb6, 0x66, 0x94, 0x74, 0x31, 0xf2, 0xcd, 0xcd, - ]; - let generator_y: [u8; 32] = [ - 0x2e, 0xcd, 0x88, 0xd1, 0x59, 0x67, 0xbc, 0x53, - 0xb8, 0x85, 0x91, 0x2e, 0x0d, 0x16, 0x86, 0x61, - 0x54, 0xac, 0xb6, 0xaa, 0xc2, 0xd3, 0xf8, 0x5e, - 0x27, 0xca, 0x7e, 0xef, 0xb2, 0xc1, 0x90, 0x83, - ]; - - use barretenberg_rs::GrumpkinPoint; - let point_a = GrumpkinPoint { - x: generator_x.to_vec(), - y: generator_y.to_vec(), - }; - let point_b = point_a.clone(); - - let response = api.grumpkin_add(point_a, point_b).expect("GrumpkinAdd failed"); - println!("GrumpkinAdd result: x={}, y={}", - hex::encode(&response.point.x), - hex::encode(&response.point.y)); - - api.destroy().expect("Failed to destroy backend"); -} - -#[test] -fn test_pipe_error_response() { - require_bb_binary!(); - let bb_path = get_bb_binary_path(); - - let backend = PipeBackend::new(&bb_path, Some(1)) - .expect("Failed to create pipe backend"); - let mut api = BarretenbergApi::new(backend); - - // Create an invalid point (off-curve) to trigger an error - // This point has x=1, y=1 which is NOT on the Grumpkin curve - let invalid_x: [u8; 32] = [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - ]; - let invalid_y: [u8; 32] = [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - ]; - - use barretenberg_rs::GrumpkinPoint; - let invalid_point = GrumpkinPoint { - x: invalid_x.to_vec(), - y: invalid_y.to_vec(), - }; - - // This should fail because the point is not on the curve - let result = api.grumpkin_add(invalid_point.clone(), invalid_point); - - match result { - Ok(_) => { - // Some backends might not validate points, which is also acceptable - println!("Note: Backend did not validate point on curve"); - }, - Err(e) => { - println!("Got expected error for off-curve point: {:?}", e); - // Verify it's a backend error (ErrorResponse) - assert!( - format!("{:?}", e).contains("Backend") || format!("{:?}", e).contains("error"), - "Expected a backend error, got: {:?}", e - ); - } - } - - api.destroy().expect("Failed to destroy backend"); -} diff --git a/barretenberg/rust/tests/src/poseidon.rs b/barretenberg/rust/tests/src/poseidon.rs deleted file mode 100644 index 10391a00c42c..000000000000 --- a/barretenberg/rust/tests/src/poseidon.rs +++ /dev/null @@ -1,66 +0,0 @@ -//! Poseidon2 hash tests -//! -//! Parallels barretenberg/ts/src/barretenberg/poseidon.test.ts -//! -//! These tests require the BB binary to be built. They are skipped if the binary is not found. - -#[cfg(test)] -use barretenberg_rs::{backends::PipeBackend, BarretenbergApi, Fr}; -#[cfg(test)] -use crate::utils::{get_bb_binary_path, random_fr, Timer}; -#[cfg(test)] -use crate::require_bb_binary; - -#[test] -fn test_poseidon2_hash() { - require_bb_binary!(); - let bb_path = get_bb_binary_path(); - - let backend = PipeBackend::new(&bb_path, Some(1)) - .expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); - - let inputs = vec![ - Fr::from_u64(4).to_buffer(), - Fr::from_u64(8).to_buffer(), - ]; - - let response = api.poseidon2_hash(inputs).expect("Poseidon2Hash failed"); - let result = Fr::from_buffer_reduce(&response.hash); - - // Print result for snapshot comparison - println!("Poseidon2 hash result: {:?}", hex::encode(&result.0)); - - api.destroy().expect("Failed to destroy backend"); -} - -#[test] -#[ignore] // Performance test - run with --ignored -fn test_poseidon2_hash_perf() { - require_bb_binary!(); - let bb_path = get_bb_binary_path(); - - let backend = PipeBackend::new(&bb_path, Some(1)) - .expect("Failed to create backend"); - let mut api = BarretenbergApi::new(backend); - - let loops = 1000; - let mut fields = Vec::with_capacity(loops * 2); - for _ in 0..loops * 2 { - fields.push(random_fr().to_buffer()); - } - - let timer = Timer::new(); - for i in 0..loops { - let inputs = vec![ - fields[i * 2].clone(), - fields[i * 2 + 1].clone(), - ]; - let _ = api.poseidon2_hash(inputs).expect("Poseidon2Hash failed"); - } - let us = timer.us() / loops as u128; - - println!("Executed {} hashes at an average {}us / hash", loops, us); - - api.destroy().expect("Failed to destroy backend"); -} diff --git a/barretenberg/rust/tests/src/utils.rs b/barretenberg/rust/tests/src/utils.rs deleted file mode 100644 index 5d19a2e8ce96..000000000000 --- a/barretenberg/rust/tests/src/utils.rs +++ /dev/null @@ -1,121 +0,0 @@ -//! Utility functions and helpers for tests - -use std::time::Instant; -use barretenberg_rs::Fr; - -/// Generate a pseudo-random Fr for testing (NOT cryptographically secure) -pub fn random_fr() -> Fr { - use std::time::SystemTime; - let nanos = SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .unwrap() - .as_nanos(); - - let mut bytes = [0u8; 32]; - bytes[0..16].copy_from_slice(&nanos.to_le_bytes()); - bytes[16..24].copy_from_slice(&(nanos >> 64).to_le_bytes()[0..8]); - Fr(bytes) -} - -/// Timer for performance measurements -/// -/// Parallels the Timer class in barretenberg/ts/src/benchmark/timer.ts -pub struct Timer { - start: Instant, -} - -impl Timer { - /// Create a new timer starting now - pub fn new() -> Self { - Self { - start: Instant::now(), - } - } - - /// Get elapsed time in microseconds - pub fn us(&self) -> u128 { - self.start.elapsed().as_micros() - } - - /// Get elapsed time in milliseconds - pub fn ms(&self) -> u128 { - self.start.elapsed().as_millis() - } - - /// Get elapsed time in seconds - pub fn s(&self) -> f64 { - self.start.elapsed().as_secs_f64() - } -} - -impl Default for Timer { - fn default() -> Self { - Self::new() - } -} - -/// Get path to BB binary for testing -pub fn get_bb_binary_path() -> String { - std::env::var("BB_BINARY_PATH") - .unwrap_or_else(|_| { - // Default path relative to the repository root - // From rust/tests, need to go up two levels to barretenberg/ - "../../cpp/build/bin/bb".to_string() - }) -} - -/// Check if BB binary exists at the expected path -pub fn bb_binary_exists() -> bool { - let path = get_bb_binary_path(); - std::path::Path::new(&path).exists() -} - -/// Check if BB binary supports the msgpack API -pub fn bb_supports_msgpack() -> bool { - let path = get_bb_binary_path(); - if !std::path::Path::new(&path).exists() { - return false; - } - - // Try to run `bb --help` and check if "msgpack" appears in the output - // This is more reliable than checking exit codes - match std::process::Command::new(&path) - .args(["--help"]) - .output() - { - Ok(output) => { - let stdout = String::from_utf8_lossy(&output.stdout); - stdout.contains("msgpack") - } - Err(_) => false, - } -} - -/// Require BB binary with msgpack support. -/// Panics if BB binary is not found or doesn't support msgpack API. -#[macro_export] -macro_rules! require_bb_binary { - () => { - if !$crate::utils::bb_binary_exists() { - panic!("BB binary not found at {}. Build it with `./bootstrap.sh` or set BB_BINARY_PATH.", - $crate::utils::get_bb_binary_path()); - } - if !$crate::utils::bb_supports_msgpack() { - panic!("BB binary at {} does not support msgpack API. Rebuild with latest code.", - $crate::utils::get_bb_binary_path()); - } - }; -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_bb_binary_detection() { - let path = get_bb_binary_path(); - eprintln!("BB_BINARY_PATH: {}", path); - eprintln!("bb_binary_exists: {}", bb_binary_exists()); - eprintln!("bb_supports_msgpack: {}", bb_supports_msgpack()); - } -} diff --git a/barretenberg/ts/src/bb_backends/wasm.ts b/barretenberg/ts/src/bb_backends/wasm.ts index 37e895de33ab..17acd40d9665 100644 --- a/barretenberg/ts/src/bb_backends/wasm.ts +++ b/barretenberg/ts/src/bb_backends/wasm.ts @@ -25,7 +25,7 @@ export class BarretenbergWasmSyncBackend implements IMsgpackBackendSync { } call(inputBuffer: Uint8Array): Uint8Array { - return this.wasm.cbindCall('bbapi', inputBuffer); + return this.wasm.cbindCall('ipc_ffi_entry', inputBuffer); } destroy(): void { @@ -95,7 +95,7 @@ export class BarretenbergWasmAsyncBackend implements IMsgpackBackendAsync { } async call(inputBuffer: Uint8Array): Promise { - return this.wasm.cbindCall('bbapi', inputBuffer); + return this.wasm.cbindCall('ipc_ffi_entry', inputBuffer); } async destroy(): Promise { diff --git a/ipc-codegen/src/rust_codegen.ts b/ipc-codegen/src/rust_codegen.ts index 660dd7a21b20..2f87950c7477 100644 --- a/ipc-codegen/src/rust_codegen.ts +++ b/ipc-codegen/src/rust_codegen.ts @@ -89,6 +89,13 @@ export class RustCodegen { case "array": const elemType = this.mapType(type.element!); + // Byte arrays wire-encode as msgpack `bin` (matches std::array + // in C++ via msgpack-c's adapter), so emit Vec to pair with the + // `serde_bytes` adapter — `[u8; N]` would serialize as an array of N + // u8 elements, which is a different wire type and would fail to decode. + if (elemType === "u8") { + return "Vec"; + } // Large arrays become Vec for ergonomics return type.size! > 32 ? `Vec<${elemType}>` @@ -107,7 +114,17 @@ export class RustCodegen { // Check if field needs serde(with = "serde_bytes") private needsSerdeBytes(type: Type): boolean { - return type.kind === "primitive" && type.primitive === "bytes"; + if (type.kind === "primitive" && type.primitive === "bytes") return true; + // `array of u8` and `vector of u8` both map to Vec and must wire-encode + // as msgpack `bin` to match the C++ representation. + if (type.kind === "array" && this.isU8Primitive(type.element!)) return true; + if (type.kind === "vector" && this.isU8Primitive(type.element!)) + return true; + return false; + } + + private isU8Primitive(type: Type): boolean { + return type.kind === "primitive" && type.primitive === "u8"; } // Check if field needs serde(with = "serde_vec_bytes")