diff --git a/include/wally_core.h b/include/wally_core.h index 4338f679f..e5d6a958e 100644 --- a/include/wally_core.h +++ b/include/wally_core.h @@ -350,6 +350,13 @@ typedef int (*wally_ec_nonce_t)( typedef struct secp256k1_context_struct *(*secp_context_t)( void); +/** The type of an overridable function to get the last extended error code */ +typedef int (*wally_get_error_t)(void); + +/** The type of an overridable function to set the last extended error code */ +typedef int (*wally_set_error_t)( + int error_code); + /** Structure holding function pointers for overridable wally operations */ struct wally_operations { uintptr_t struct_size; /* Must be initialised to sizeof(wally_operations) */ @@ -358,9 +365,9 @@ struct wally_operations { wally_bzero_t bzero_fn; wally_ec_nonce_t ec_nonce_fn; secp_context_t secp_context_fn; - void *reserved_1; /* reserved_ pointers are reserved for future use */ - void *reserved_2; - void *reserved_3; + wally_get_error_t get_error_fn; + wally_set_error_t set_error_fn; + void *reserved_3; /* reserved_ pointers are reserved for future use */ void *reserved_4; }; diff --git a/src/internal.c b/src/internal.c index 0e9cb78d3..1a4e53d0d 100644 --- a/src/internal.c +++ b/src/internal.c @@ -17,6 +17,8 @@ /* Caller is responsible for thread safety */ static secp256k1_context *global_ctx = NULL; +/* Global extended error code. Not thread-safe unless caller-overridden */ +static int global_error = WALLY_OK; int wally_get_build_version(uint32_t *value) { @@ -378,6 +380,16 @@ struct secp256k1_context_struct *wally_internal_secp_context(void) return global_ctx; } +int wally_internal_get_error(void) { + return global_error; +} + +int wally_internal_set_error(int error_code) +{ + global_error = error_code; + return error_code; +} + static struct wally_operations _ops = { sizeof(struct wally_operations), wally_internal_malloc, @@ -385,8 +397,8 @@ static struct wally_operations _ops = { wally_internal_bzero, wally_internal_ec_nonce_fn, wally_internal_secp_context, - NULL, - NULL, + wally_internal_get_error, + wally_internal_set_error, NULL, NULL }; @@ -428,6 +440,15 @@ char *wally_strdup(const char *str) return wally_strdup_n(str, strlen(str)); } +int wally_get_error(void) { + return _ops.get_error_fn(); +} + +int wally_set_error(int error_code) +{ + return _ops.set_error_fn(error_code); +} + const struct wally_operations *wally_ops(void) { return &_ops; @@ -447,7 +468,7 @@ int wally_set_operations(const struct wally_operations *ops) return WALLY_EINVAL; /* Null or invalid version of ops */ /* Reserved pointers must be null so they can be enabled in the * future without breaking back compatibility */ - if (ops->reserved_1 || ops->reserved_2 || ops->reserved_3 || ops->reserved_4) + if (ops->reserved_3 || ops->reserved_4) return WALLY_EINVAL; #define COPY_FN_PTR(name) if (ops->name) _ops.name = ops->name @@ -456,6 +477,8 @@ int wally_set_operations(const struct wally_operations *ops) COPY_FN_PTR (bzero_fn); COPY_FN_PTR (ec_nonce_fn); COPY_FN_PTR (secp_context_fn); + COPY_FN_PTR (get_error_fn); + COPY_FN_PTR (set_error_fn); #undef COPY_FN_PTR return WALLY_OK; }