Simplify FFIs.

This commit is contained in:
Alejandro Cabeza Romero 2026-04-20 16:08:13 +02:00
parent 2e1dd99ac5
commit 02cc519f29
No known key found for this signature in database
GPG Key ID: DA3D14AE478030FD
5 changed files with 36 additions and 56 deletions

View File

@ -7,19 +7,7 @@ endif
# ---- Common ----
CXX := g++
CXXFLAGS_COMMON := -std=c++11 -O3 -I. -Wno-address-of-packed-member -Dmain=circom_main
UNAME_S := $(shell uname -s)
MACOS_OBJCOPY := /opt/homebrew/opt/binutils/bin/gobjcopy
ifeq ($(UNAME_S),Darwin)
# On macOS CI we expect GNU objcopy from Homebrew binutils at this exact path.
ifeq ($(wildcard $(MACOS_OBJCOPY)),)
$(error Missing $(MACOS_OBJCOPY). Install binutils with Homebrew or update OBJCOPY for this environment.)
endif
OBJCOPY := $(MACOS_OBJCOPY)
else
# On non-macOS targets we assume objcopy is available on PATH.
OBJCOPY := objcopy
endif
CXXFLAGS_COMMON := -std=c++11 -O3 -I. -Wno-address-of-packed-member -Dmain=circom_main -DCIRCUIT_NAME=$(PROJECT)
COMMON_SRCS := main.cpp calcwit.cpp fr.cpp $(PROJECT).cpp
COMMON_OBJS := $(COMMON_SRCS:.cpp=.o)
LIB_ONLY_SRCS := ffi.cpp
@ -68,7 +56,6 @@ $(BIN): $(COMMON_OBJS)
$(LIB): $(LIB_OBJS)
ar rcs $@ $^
$(OBJCOPY) --prefix-symbols=$(PROJECT)_ $@
%.o: %.cpp $(DEPS_HPP)
$(CXX) $(CXXFLAGS) -c $< -o $@

View File

@ -1,13 +0,0 @@
#include "types.hpp"
#include <cstdlib>
extern "C" void free_bytes(Bytes* bytes) {
if (bytes == nullptr) {
return;
}
free(bytes->data);
bytes->data = nullptr;
bytes->size = 0;
}

View File

@ -1,4 +1,4 @@
#include "ffi.hpp"
#include "poq/ffi.hpp"
#include <string>
#include <vector>
@ -15,7 +15,7 @@ using json = nlohmann::json;
// ---- Forward declarations from circom-generated main.cpp ----
/// This is a forward declaration of circom main(). It's renamed due to UB when calling a main() function.
/// TODO: Successful path of the function returns nothing despite the int return type.
/// TODO: Successful path of the function has no explicit return.
int circom_main(int argc, char* argv[]);
bool check_valid_number(std::string& s, uint base);
void json2FrElements(json val, std::vector<FrElement>& vval);
@ -25,7 +25,6 @@ void qualify_input_list(std::string prefix, json& in, json& in1);
// -------------------------------------------------------------
// ---- File-based entry point (wraps circom-generated main) ----
template<typename T>
static Status exceptions_into_status(T&& func) {
try {
@ -68,8 +67,8 @@ static Status generate_witness_from_files_impl(const char* dat, const char* inpu
return status_new(StatusCode_DynError, message.c_str());
}
extern "C" Status generate_witness_from_files(const char* dat, const char* inputs, const char* output) {
const Status status = validate_generate_witness_from_files_input(dat, inputs, output);
extern "C" Status poq_generate_witness_from_files(const char* dat, const char* inputs, const char* output) {
const Status status = validate_generate_witness_from_files_input(dat, inputs, output); // NOLINT: if-init
if (status_is_error(status)) {
return status;
}
@ -82,13 +81,6 @@ extern "C" Status generate_witness_from_files(const char* dat, const char* input
// ---- Memory-based entry point ----
static Status validate_witness_input(const WitnessInput* input, const Bytes* output) {
if (output == nullptr) {
return status_new(StatusCode_InvalidInput, "output is null.");
}
if (output->data != nullptr) {
return status_new(StatusCode_InvalidInput, "output.data is not null.");
}
if (input == nullptr) {
return status_new(StatusCode_InvalidInput, "input is null.");
}
@ -101,12 +93,20 @@ static Status validate_witness_input(const WitnessInput* input, const Bytes* out
if (input->inputs_json == nullptr) {
return status_new(StatusCode_InvalidInput, "input.inputs_json is null.");
}
if (output == nullptr) {
return status_new(StatusCode_InvalidInput, "output is null.");
}
if (output->data != nullptr) {
return status_new(StatusCode_InvalidInput, "output.data is not null.");
}
return status_ok();
}
static Status generate_witness_impl(const WitnessInput* input, Bytes* output) {
// TODO: Implement the actual witness generation logic using the provided input data.
const uint8_t dummy_witness[] = {0, 1, 2, 3}; // Placeholder for actual witness data
const uint8_t dummy_witness[] = {0, 1, 2, 3};
const size_t witness_size = sizeof(dummy_witness);
uint8_t* witness_data = static_cast<uint8_t*>(malloc(witness_size));
@ -121,8 +121,8 @@ static Status generate_witness_impl(const WitnessInput* input, Bytes* output) {
return status_ok();
}
extern "C" Status generate_witness(const WitnessInput* input, Bytes* output) {
const Status status = validate_witness_input(input, output);
extern "C" Status poq_generate_witness(const WitnessInput* input, Bytes* output) {
const Status status = validate_witness_input(input, output); // NOLINT: if-init
if (status_is_error(status)) {
return status;
}

View File

@ -1,16 +1,8 @@
#ifndef FFI_HPP
#define FFI_HPP
#ifndef FFI_POQ_HPP
#define FFI_POQ_HPP
#include "types.hpp"
/// Inputs for witness generation.
typedef struct WitnessInput {
/// Contents of the circuit's .dat file.
const ConstBytes dat;
/// Null-terminated JSON string of circuit inputs.
const char* inputs_json;
} WitnessInput;
#ifdef __cplusplus
extern "C" {
#endif
@ -27,7 +19,7 @@ extern "C" {
///
/// On success, returns a `Status` with `StatusCode_Ok` and writes the witness to the specified output file.
/// On failure, returns a `Status` with an appropriate error code.
Status generate_witness_from_files(const char* dat, const char* inputs, const char* output);
Status poq_generate_witness_from_files(const char* dat, const char* inputs, const char* output);
/// Generates a witness from in-memory buffers.
///
@ -41,9 +33,7 @@ Status generate_witness_from_files(const char* dat, const char* inputs, const ch
/// On success, returns a `Status` with `StatusCode_Ok` and populates `output` with the generated witness bytes. The
/// caller is responsible for freeing the resources allocated into `output` by this function using `free_bytes`.
/// On failure, returns a `Status` with an appropriate error code, and `output` will not be modified.
Status generate_witness(const WitnessInput* input, Bytes* output);
void free_bytes(Bytes* bytes);
Status poq_generate_witness(const WitnessInput* input, Bytes* output);
#ifdef __cplusplus
}

View File

@ -3,6 +3,7 @@
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#define STATUS_MESSAGE_LENGTH 256
@ -57,6 +58,21 @@ static inline Status status_ok() { return status_from_code(StatusCode_Ok); }
static inline bool status_is_ok(const Status status) { return status_code_is_ok(status.code); }
static inline bool status_is_error(const Status status) { return status_code_is_error(status.code); }
/// Inputs for witness generation.
typedef struct WitnessInput {
/// Contents of the circuit's .dat file.
const ConstBytes dat;
/// Null-terminated JSON string of circuit inputs.
const char* inputs_json;
} WitnessInput;
static inline void free_bytes(Bytes* bytes) {
if (bytes == NULL) return;
free(bytes->data);
bytes->data = NULL;
bytes->size = 0;
}
#ifdef __cplusplus
}
#endif