diff --git a/.github/resources/witness-generator/Makefile b/.github/resources/witness-generator/Makefile index 35989e0..96b290b 100644 --- a/.github/resources/witness-generator/Makefile +++ b/.github/resources/witness-generator/Makefile @@ -7,7 +7,7 @@ endif # ---- Common ---- CXX := g++ -CXXFLAGS_COMMON := -std=c++11 -O3 -I. -Wno-address-of-packed-member +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) diff --git a/src/ffi.cpp b/src/ffi.cpp index 6361c53..e490d2d 100644 --- a/src/ffi.cpp +++ b/src/ffi.cpp @@ -1,4 +1,4 @@ -#include "ffi.hpp" +#include "ffi.hpp." #include #include @@ -7,14 +7,17 @@ #include -#include "calcwit.hpp" -#include "circom.hpp" -#include "fr.hpp" +#include "calcwit.hpp." +#include "circom.hpp." +#include "fr.hpp." 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. +int circom_main(int argc, char* argv[]); bool check_valid_number(std::string& s, uint base); void json2FrElements(json val, std::vector& vval); json::value_t check_type(std::string prefix, json in); @@ -31,39 +34,39 @@ static Status exceptions_into_status(T&& func) { } catch (const std::bad_alloc&) { return status_from_code(StatusCode_OutOfMemory); } catch (const std::exception& e) { - return Status{StatusCode_DynError, e.what()}; + return status_new(StatusCode_DynError, e.what()); } catch (...) { - return Status{StatusCode_DynError, "An unknown error occurred."}; + return status_new(StatusCode_DynError, "An unknown error occurred."); } } static Status validate_generate_witness_from_files_input(const char* dat, const char* inputs, const char* output) { if (dat == nullptr) { - return Status{StatusCode_InvalidInput, "dat is null"}; + return status_new(StatusCode_InvalidInput, "dat is null."); } if (inputs == nullptr) { - return Status{StatusCode_InvalidInput, "inputs is null"}; + return status_new(StatusCode_InvalidInput, "inputs is null."); } if (output == nullptr) { - return Status{StatusCode_InvalidInput, "output is null"}; + return status_new(StatusCode_InvalidInput, "output is null."); } return status_ok(); } static Status generate_witness_from_files_impl(const char* dat, const char* inputs, const char* output) { char* argv[] = { - const_cast("generate_witness_from_files"), const_cast(dat), const_cast(inputs), const_cast(output), nullptr }; - const int code = main(4, argv); + const int code = circom_main(3, argv); if (code == 0) { return status_ok(); } - return status_from_code(StatusCode_DynError); + const std::string message = "Witness generation [circom main()] failed with code: " + std::to_string(code) + "."; + return status_new(StatusCode_DynError, message.c_str()); } extern "C" Status generate_witness_from_files(const char* dat, const char* inputs, const char* output) { @@ -81,23 +84,23 @@ extern "C" Status generate_witness_from_files(const char* dat, const char* input static Status validate_witness_input(const WitnessInput* input, const Bytes* output) { if (output == nullptr) { - return Status{StatusCode_InvalidInput, "output is null"}; + return status_new(StatusCode_InvalidInput, "output is null."); } if (output->data != nullptr) { - return Status{StatusCode_InvalidInput, "output.data is not null"}; + return status_new(StatusCode_InvalidInput, "output.data is not null."); } if (input == nullptr) { - return Status{StatusCode_InvalidInput, "input is null"}; + return status_new(StatusCode_InvalidInput, "input is null."); } if (input->dat.data == nullptr) { - return Status{StatusCode_InvalidInput, "input.dat.data is null"}; + return status_new(StatusCode_InvalidInput, "input.dat.data is null."); } if (input->dat.size == 0) { - return Status{StatusCode_InvalidInput, "input.dat.size is zero"}; + return status_new(StatusCode_InvalidInput, "input.dat.size is zero."); } if (input->inputs_json == nullptr) { - return Status{StatusCode_InvalidInput, "input.inputs_json is null"}; + return status_new(StatusCode_InvalidInput, "input.inputs_json is null."); } return status_ok(); } @@ -109,7 +112,7 @@ static Status generate_witness_impl(const WitnessInput* input, Bytes* output) { const size_t witness_size = sizeof(dummy_witness); uint8_t* witness_data = static_cast(malloc(witness_size)); if (witness_data == nullptr) { - return Status{StatusCode_OutOfMemory, "Failed to allocate witness memory"}; + return status_new(StatusCode_OutOfMemory, "Failed to allocate witness memory."); } std::copy(dummy_witness, dummy_witness + witness_size, witness_data); diff --git a/src/types.hpp b/src/types.hpp index f0a211c..0529c24 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -3,6 +3,9 @@ #include #include +#include + +#define STATUS_MESSAGE_LENGTH 256 #ifdef __cplusplus extern "C" { @@ -27,25 +30,32 @@ typedef enum StatusCode { StatusCode_OutOfMemory = 3, } StatusCode; -static bool status_code_is_ok(const StatusCode code) { +static inline bool status_code_is_ok(const StatusCode code) { return code == StatusCode_Ok; } -static bool status_code_is_error(const StatusCode code) { +static inline bool status_code_is_error(const StatusCode code) { return !status_code_is_ok(code); } /// A status code with an optional human-readable description. typedef struct Status { StatusCode code; - const char* message; + char message[STATUS_MESSAGE_LENGTH]; } Status; -static Status status_from_code(const StatusCode code) { return Status { code, NULL }; } -static Status status_ok() { return status_from_code(StatusCode_Ok); } +static inline Status status_new(const StatusCode code, const char* message) { + Status status = {code, {}}; + if (message != NULL) { + strncpy(status.message, message, STATUS_MESSAGE_LENGTH - 1); + } + return status; +} +static inline Status status_from_code(const StatusCode code) { return status_new(code, NULL); } +static inline Status status_ok() { return status_from_code(StatusCode_Ok); } -static bool status_is_ok(const Status status) { return status_code_is_ok(status.code); } -static bool status_is_error(const Status status) { return status_code_is_error(status.code); } +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); } #ifdef __cplusplus }