diff --git a/rust/Cargo.lock b/rust/Cargo.lock
index 22a65e3..823efcf 100644
--- a/rust/Cargo.lock
+++ b/rust/Cargo.lock
@@ -166,7 +166,6 @@ name = "logos-blockchain-circuits-types"
version = "0.4.2"
dependencies = [
"libc",
- "thiserror",
]
[[package]]
@@ -197,24 +196,6 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
-[[package]]
-name = "proc-macro2"
-version = "1.0.106"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.45"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
-dependencies = [
- "proc-macro2",
-]
-
[[package]]
name = "redox_syscall"
version = "0.7.4"
@@ -304,17 +285,6 @@ version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
-[[package]]
-name = "syn"
-version = "2.0.117"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
[[package]]
name = "tar"
version = "0.4.45"
@@ -326,32 +296,6 @@ dependencies = [
"xattr",
]
-[[package]]
-name = "thiserror"
-version = "2.0.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
-dependencies = [
- "thiserror-impl",
-]
-
-[[package]]
-name = "thiserror-impl"
-version = "2.0.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
-
[[package]]
name = "untrusted"
version = "0.9.0"
diff --git a/rust/Cargo.toml b/rust/Cargo.toml
index 11df230..a83eff5 100644
--- a/rust/Cargo.toml
+++ b/rust/Cargo.toml
@@ -24,5 +24,4 @@ lbc-types = { default-features = false, package = "logos-blockchain-circuits-typ
flate2 = "1"
libc = "0.2.185"
tar = "0.4"
-thiserror = "2.0.18"
ureq = "3.3.0"
diff --git a/rust/logos-blockchain-circuits-poq-sys/Cargo.toml b/rust/logos-blockchain-circuits-poq-sys/Cargo.toml
index 7a54adc..cbac3bd 100644
--- a/rust/logos-blockchain-circuits-poq-sys/Cargo.toml
+++ b/rust/logos-blockchain-circuits-poq-sys/Cargo.toml
@@ -10,7 +10,7 @@ repository.workspace = true
version.workspace = true
[dependencies]
-lbc-types = { workspace = true}
+lbc-types = { workspace = true }
[build-dependencies]
flate2 = { workspace = true }
diff --git a/rust/logos-blockchain-circuits-poq-sys/build.rs b/rust/logos-blockchain-circuits-poq-sys/build.rs
index 93c742f..06f3eef 100644
--- a/rust/logos-blockchain-circuits-poq-sys/build.rs
+++ b/rust/logos-blockchain-circuits-poq-sys/build.rs
@@ -20,6 +20,7 @@ fn get_artifact_url(version: &str, os: &str, arch: &str) -> String {
fn fetch_library(version: &str, os: &str, arch: &str) -> Response
{
let url = get_artifact_url(version, os, arch);
+ // TODO: Verify checksum.
ureq::get(&url).call().unwrap_or_else(|error| {
panic!(
"Failed to download a prebuilt library for {os}-{arch} v{version}: {error}. \
@@ -35,7 +36,11 @@ fn unpack_library(response: Response, version: &str, os: &str, arch: &str,
let unpacked_artifact_path = output_dir.join(get_artifact_name(version, os, arch));
let unpacked_library_directory = unpacked_artifact_path.join(CIRCUIT_NAME);
- assert!(unpacked_library_directory.exists(), "Expected the unpacked library at {}.", unpacked_library_directory.display());
+
+ if !unpacked_library_directory.exists() {
+ panic!("Failed to find the unpacked library at {}.", unpacked_library_directory.display());
+ }
+
unpacked_library_directory
}
@@ -57,12 +62,18 @@ fn provision_library() -> PathBuf {
fn main() {
println!("cargo:rerun-if-env-changed={LIB_VAR_NAME}");
+ println!("cargo:rerun-if-env-changed=CARGO_PKG_VERSION");
+ println!("cargo:rerun-if-changed=Cargo.toml");
+ println!("cargo:rerun-if-changed=build.rs");
let lib_dir = std::env::var(LIB_VAR_NAME).map(
|lib_dir| {
println!("Using a library directory from {LIB_VAR_NAME}: {lib_dir}");
let lib_dir_path = PathBuf::from(lib_dir);
- assert!(lib_dir_path.exists(), "The library directory at {} does not exist.", lib_dir_path.display());
+ if !lib_dir_path.exists() {
+ panic!("The library directory specified in {LIB_VAR_NAME} at {} does not exist.", lib_dir_path.display());
+
+ }
lib_dir_path
}
).unwrap_or_else(|_| {
diff --git a/rust/logos-blockchain-circuits-poq-sys/src/native.rs b/rust/logos-blockchain-circuits-poq-sys/src/native.rs
index ce49465..df85c72 100644
--- a/rust/logos-blockchain-circuits-poq-sys/src/native.rs
+++ b/rust/logos-blockchain-circuits-poq-sys/src/native.rs
@@ -1,18 +1,28 @@
-use std::ffi::c_char;
use std::path::Path;
use lbc_types::{ffi, native::{Bytes, Error, WitnessInput}};
use crate::ffi::{poq_generate_witness, poq_generate_witness_from_files};
+fn into_null_terminated_string(
+ string: &str,
+) -> Result {
+ std::ffi::CString::new(string)
+ .map_err(|error| Error::InvalidInput(Some(format!("Could not convert string to CString: {error}"))))
+}
+
+fn path_as_null_terminated_string(
+ path: &Path,
+) -> Result {
+ let path = path.to_str().ok_or(Error::InvalidInput(Some(format!("Could not convert the path to a string: {}", path.display()))))?;
+ into_null_terminated_string(path)
+}
+
pub fn generate_witness(
input: WitnessInput,
) -> Result {
let ffi_input_guard = input.as_ffi();
let ffi_input = ffi_input_guard.as_ref();
- let mut ffi_output_bytes = ffi::Bytes {
- data: std::ptr::null_mut(),
- size: 0
- };
+ let mut ffi_output_bytes = ffi::Bytes::null();
let status = unsafe {
poq_generate_witness(
@@ -29,15 +39,15 @@ pub fn generate_witness_from_files(
inputs: &Path,
output: &Path,
) -> Result<(), Error> {
- let dat = dat.to_str().ok_or_else(|| Error::InvalidInput)?; // TODO: Message
- let inputs = inputs.to_str().ok_or_else(|| Error::InvalidInput)?;
- let output = output.to_str().ok_or_else(|| Error::InvalidInput)?;
+ let c_dat = path_as_null_terminated_string(dat)?;
+ let c_inputs = path_as_null_terminated_string(inputs)?;
+ let c_output = path_as_null_terminated_string(output)?;
unsafe {
poq_generate_witness_from_files (
- dat.as_ptr() as *const c_char,
- inputs.as_ptr() as *const c_char,
- output.as_ptr() as *const c_char
+ c_dat.as_ptr(),
+ c_inputs.as_ptr(),
+ c_output.as_ptr(),
)
}.try_into()
}
diff --git a/rust/logos-blockchain-circuits-types/Cargo.toml b/rust/logos-blockchain-circuits-types/Cargo.toml
index defada9..898cb4f 100644
--- a/rust/logos-blockchain-circuits-types/Cargo.toml
+++ b/rust/logos-blockchain-circuits-types/Cargo.toml
@@ -11,4 +11,3 @@ version.workspace = true
[dependencies]
libc = { workspace = true }
-thiserror = { workspace = true }
diff --git a/rust/logos-blockchain-circuits-types/src/ffi/bytes.rs b/rust/logos-blockchain-circuits-types/src/ffi/bytes.rs
index 046257d..d0e37d0 100644
--- a/rust/logos-blockchain-circuits-types/src/ffi/bytes.rs
+++ b/rust/logos-blockchain-circuits-types/src/ffi/bytes.rs
@@ -8,6 +8,24 @@ mod inner {
}
}
+impl inner::Buffer<*const T> {
+ pub fn null() -> Self {
+ Self {
+ data: std::ptr::null(),
+ size: 0,
+ }
+ }
+}
+
+impl inner::Buffer<*mut T> {
+ pub fn null() -> Self {
+ Self {
+ data: std::ptr::null_mut(),
+ size: 0,
+ }
+ }
+}
+
/// Owned byte buffer returned by the C witness generator functions.
///
/// The inner `data` pointer must be null-initialized. It's heap-allocated by the C side and must be
@@ -29,7 +47,7 @@ pub type ConstBytes = inner::Buffer<*const u8>;
///
/// # Safety
///
-/// Dereferences raw pointers. The caller must ensure that the pointer is valid.
+/// Dereferences raw pointers.
pub unsafe fn free_bytes(bytes: *mut Bytes) {
if bytes.is_null() {
return;
diff --git a/rust/logos-blockchain-circuits-types/src/ffi/status.rs b/rust/logos-blockchain-circuits-types/src/ffi/status.rs
index 746dfaf..44ad026 100644
--- a/rust/logos-blockchain-circuits-types/src/ffi/status.rs
+++ b/rust/logos-blockchain-circuits-types/src/ffi/status.rs
@@ -1,17 +1,20 @@
use std::ffi::c_char;
/// Status codes for C API functions.
-#[repr(C)]
-pub enum Code {
- Ok = 0,
- DynError = 1,
- InvalidInput = 2,
- OutOfMemory = 3,
+#[derive(PartialEq, Eq)] // Enables comparisons with named constants.
+#[repr(transparent)]
+pub struct Code(pub i32);
+
+impl Code {
+ pub const OK: Self = Self(0);
+ pub const DYN_ERROR: Self = Self(1);
+ pub const INVALID_INPUT: Self = Self(2);
+ pub const OUT_OF_MEMORY: Self = Self(3);
}
impl Code {
pub fn is_ok(&self) -> bool {
- matches!(self, Code::Ok)
+ self == &Self::OK
}
pub fn is_error(&self) -> bool {
@@ -29,7 +32,7 @@ pub struct Status {
impl Status {
pub fn ok() -> Self {
Status {
- code: Code::Ok,
+ code: Code::OK,
message: [0; 256],
}
}
diff --git a/rust/logos-blockchain-circuits-types/src/native/bytes.rs b/rust/logos-blockchain-circuits-types/src/native/bytes.rs
index 53251d4..2f35fbb 100644
--- a/rust/logos-blockchain-circuits-types/src/native/bytes.rs
+++ b/rust/logos-blockchain-circuits-types/src/native/bytes.rs
@@ -26,10 +26,14 @@ impl From> for Bytes {
impl From for Bytes {
fn from(mut ffi_value: ffi::Bytes) -> Self {
- let raw = unsafe {
- std::slice::from_raw_parts(ffi_value.data, ffi_value.size).to_vec()
+ let vec = if ffi_value.size == 0 || ffi_value.data.is_null() {
+ Vec::new()
+ } else {
+ unsafe {
+ std::slice::from_raw_parts(ffi_value.data, ffi_value.size).to_vec()
+ }
};
- unsafe { ffi::free_bytes(&mut ffi_value); }
- Self(raw)
+ unsafe { ffi::free_bytes(&mut ffi_value) };
+ Self(vec)
}
}
diff --git a/rust/logos-blockchain-circuits-types/src/native/status.rs b/rust/logos-blockchain-circuits-types/src/native/status.rs
index d2dddc7..75c3c74 100644
--- a/rust/logos-blockchain-circuits-types/src/native/status.rs
+++ b/rust/logos-blockchain-circuits-types/src/native/status.rs
@@ -1,44 +1,52 @@
use std::ffi::CStr;
-use thiserror::Error;
+use std::fmt::Display;
use crate::ffi::status::Code as FfiStatusCode;
-pub type DynError = Box;
pub type Result = std::result::Result;
/// Error returned when a witness generator call does not succeed.
-#[derive(Debug, Error)]
+#[derive(Debug)]
pub enum Error {
- #[error("Invalid input")]
- InvalidInput,
- #[error("Out of memory")]
- OutOfMemory,
- #[error(transparent)]
- Other(#[from] DynError),
+ InvalidInput(Option),
+ OutOfMemory(Option),
+ Other(Option),
+}
+
+impl std::error::Error for Error {}
+
+impl Display for Error {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let (kind, message) = match self {
+ Error::InvalidInput(msg) => ("Invalid input", msg),
+ Error::OutOfMemory(msg) => ("Out of memory", msg),
+ Error::Other(msg) => ("Other error", msg),
+ };
+ match message {
+ Some(message) => write!(f, "{kind}: {message}"),
+ None => write!(f, "{kind}"),
+ }
+ }
}
impl TryFrom for () {
type Error = Error;
fn try_from(status: crate::ffi::Status) -> Result<()> {
+ let message: Option = if status.has_message() {
+ let status_message = unsafe {
+ CStr::from_ptr(status.message.as_ptr())
+ };
+ Some(status_message.to_string_lossy().into_owned())
+ } else {
+ None
+ };
+
match status.code {
- FfiStatusCode::Ok => Ok(()),
- FfiStatusCode::DynError => {
- let message: Option<&CStr> =
- if status.has_message() {
- let status_message = unsafe {
- CStr::from_ptr(status.message.as_ptr())
- };
- Some(status_message)
- } else {
- None
- };
- let error_message = message
- .map(|inner| DynError::from(inner.to_string_lossy().into_owned()))
- .unwrap_or_else(|| DynError::from("Unknown error"));
- Err(error_message.into())
- },
- FfiStatusCode::InvalidInput => Err(Error::InvalidInput),
- FfiStatusCode::OutOfMemory => Err(Error::OutOfMemory),
+ FfiStatusCode::OK => Ok(()),
+ FfiStatusCode::DYN_ERROR => Err(Error::Other(message)),
+ FfiStatusCode::INVALID_INPUT => Err(Error::InvalidInput(message)),
+ FfiStatusCode::OUT_OF_MEMORY => Err(Error::OutOfMemory(message)),
+ other => Err(Error::Other(Some(format!("Unknown status code: {}", other.0))))
}
}
}
diff --git a/rust/logos-blockchain-circuits-types/src/native/witness_input.rs b/rust/logos-blockchain-circuits-types/src/native/witness_input.rs
index 00843db..ced2660 100644
--- a/rust/logos-blockchain-circuits-types/src/native/witness_input.rs
+++ b/rust/logos-blockchain-circuits-types/src/native/witness_input.rs
@@ -1,5 +1,6 @@
-use std::ffi::{CString, NulError};
+use std::ffi::CString;
use crate::ffi;
+use crate::native::Error;
/// Input for witness generators
pub struct WitnessInput {
@@ -10,8 +11,12 @@ pub struct WitnessInput {
}
impl WitnessInput {
- pub fn new(dat: Vec, inputs_json: String) -> Result {
- let inputs_json = CString::new(inputs_json)?;
+ pub fn new(dat: Vec, inputs_json: String) -> Result {
+ let inputs_json = CString::new(inputs_json).map_err(
+ |error| Error::InvalidInput(Some(
+ format!("The parameter inputs_json could not be converted to CString: {}", error)
+ ))
+ )?;
Ok(Self { dat, inputs_json })
}