resolve conflict

This commit is contained in:
stubbsta 2026-07-07 09:15:17 +02:00
commit 1767234e9f
No known key found for this signature in database
21 changed files with 124 additions and 269 deletions

View File

@ -327,7 +327,7 @@ int main(int argc, char **argv)
cfgNode.storeRetentionPolicy,
cfgNode.storeMaxNumDbConnections);
ctx = waku_new(jsonConfig, event_handler, userData);
ctx = logosdelivery_create_node(jsonConfig, event_handler, userData);
waitForCallback();
WAKU_CALL(waku_default_pubsub_topic(ctx, print_default_pubsub_topic, userData));
@ -338,7 +338,7 @@ int main(int argc, char **argv)
logosdelivery_set_event_callback(ctx, on_event_received, userData);
waku_start(ctx, event_handler, userData);
logosdelivery_start_node(ctx, event_handler, userData);
waitForCallback();
WAKU_CALL(waku_listen_addresses(ctx, event_handler, userData));

View File

@ -257,9 +257,9 @@ int main(int argc, char **argv)
cfgNode.port);
void *ctx =
waku_new(jsonConfig,
logosdelivery_create_node(jsonConfig,
cify([](const char *msg, size_t len)
{ std::cout << "waku_new feedback: " << msg << std::endl; }),
{ std::cout << "logosdelivery_create_node feedback: " << msg << std::endl; }),
nullptr);
waitForCallback();
@ -296,7 +296,7 @@ int main(int argc, char **argv)
{ event_handler(msg, len); }),
nullptr);
WAKU_CALL(waku_start(ctx,
WAKU_CALL(logosdelivery_start_node(ctx,
cify([&](const char *msg, size_t len)
{ event_handler(msg, len); }),
nullptr));

View File

@ -71,20 +71,20 @@ package main
static void* cGoWakuNew(const char* configJson, void* resp) {
// We pass NULL because we are not interested in retrieving data from this callback
void* ret = waku_new(configJson, (FFICallBack) callback, resp);
void* ret = logosdelivery_create_node(configJson, (FFICallBack) callback, resp);
return ret;
}
static void cGoWakuStart(void* wakuCtx, void* resp) {
WAKU_CALL(waku_start(wakuCtx, (FFICallBack) callback, resp));
WAKU_CALL(logosdelivery_start_node(wakuCtx, (FFICallBack) callback, resp));
}
static void cGoWakuStop(void* wakuCtx, void* resp) {
WAKU_CALL(waku_stop(wakuCtx, (FFICallBack) callback, resp));
WAKU_CALL(logosdelivery_stop_node(wakuCtx, (FFICallBack) callback, resp));
}
static void cGoWakuDestroy(void* wakuCtx, void* resp) {
WAKU_CALL(waku_destroy(wakuCtx, (FFICallBack) callback, resp));
WAKU_CALL(logosdelivery_destroy(wakuCtx, (FFICallBack) callback, resp));
}
static void cGoWakuStartDiscV5(void* wakuCtx, void* resp) {

View File

@ -240,11 +240,11 @@ actor WakuActor {
print("[WakuActor] Unsubscribed from filter")
// Stop
_ = await self.callWakuSync { waku_stop(ctxToStop, WakuActor.syncCallback, $0) }
_ = await self.callWakuSync { logosdelivery_stop_node(ctxToStop, WakuActor.syncCallback, $0) }
print("[WakuActor] Node stopped")
// Destroy
_ = await self.callWakuSync { waku_destroy(ctxToStop, WakuActor.syncCallback, $0) }
_ = await self.callWakuSync { logosdelivery_destroy(ctxToStop, WakuActor.syncCallback, $0) }
print("[WakuActor] Node destroyed")
}
}
@ -319,13 +319,13 @@ actor WakuActor {
}
"""
// Create node - waku_new is special, it returns the context directly
// Create node - logosdelivery_create_node is special, it returns the context directly
let createResult = await withCheckedContinuation { (continuation: CheckedContinuation<(ctx: UnsafeMutableRawPointer?, success: Bool, result: String?), Never>) in
let callbackCtx = CallbackContext()
let userDataPtr = Unmanaged.passRetained(callbackCtx).toOpaque()
// Set up a simple callback for waku_new
let newCtx = waku_new(config, { ret, msg, len, userData in
// Set up a simple callback for logosdelivery_create_node
let newCtx = logosdelivery_create_node(config, { ret, msg, len, userData in
guard let userData = userData else { return }
let context = Unmanaged<CallbackContext>.fromOpaque(userData).takeUnretainedValue()
context.success = (ret == RET_OK)
@ -354,7 +354,7 @@ actor WakuActor {
// Start node
let startResult = await callWakuSync { userData in
waku_start(self.ctx, WakuActor.syncCallback, userData)
logosdelivery_start_node(self.ctx, WakuActor.syncCallback, userData)
}
guard startResult.success else {

View File

@ -123,7 +123,7 @@ class WakuModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
val configStr = stringifyReadableMap(config)
val response = wakuNew(configStr)
if (response.error) {
promise.reject("waku_new", response.errorMessage)
promise.reject("logosdelivery_create_node", response.errorMessage)
} else {
// With this we just indicate to waku_ffi that we have registered a
// closure, for this wakuPtr. Later once a message is received the
@ -140,7 +140,7 @@ class WakuModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
val wakuPtr = BigInteger(ctx).toLong()
val response = wakuStart(wakuPtr)
if (response.error) {
promise.reject("waku_start", response.message)
promise.reject("logosdelivery_start_node", response.message)
} else {
promise.resolve(null)
}
@ -162,7 +162,7 @@ class WakuModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
val wakuPtr = BigInteger(ctx).toLong()
val response = wakuStop(wakuPtr)
if (response.error) {
promise.reject("waku_stop", response.message)
promise.reject("logosdelivery_stop_node", response.message)
} else {
promise.resolve(null)
}
@ -173,7 +173,7 @@ class WakuModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
val wakuPtr = BigInteger(ctx).toLong()
val response = wakuDestroy(wakuPtr)
if (response.error) {
promise.reject("waku_destroy", response.message)
promise.reject("logosdelivery_destroy", response.message)
} else {
promise.resolve(null)
}

View File

@ -184,7 +184,7 @@ jobject Java_com_mobile_WakuModule_wakuNew(JNIEnv *env, jobject thiz,
jstring configJson) {
const char *config = (*env)->GetStringUTFChars(env, configJson, 0);
cb_result *result = NULL;
void *wakuPtr = waku_new(config, on_response, (void *)&result);
void *wakuPtr = logosdelivery_create_node(config, on_response, (void *)&result);
jobject response = to_jni_ptr(env, result, wakuPtr);
(*env)->ReleaseStringUTFChars(env, configJson, config);
free_cb_result(result);
@ -194,7 +194,7 @@ jobject Java_com_mobile_WakuModule_wakuNew(JNIEnv *env, jobject thiz,
jobject Java_com_mobile_WakuModule_wakuStart(JNIEnv *env, jobject thiz,
jlong wakuPtr) {
cb_result *result = NULL;
waku_start((void *)wakuPtr, on_response, &result);
logosdelivery_start_node((void *)wakuPtr, on_response, &result);
jobject response = to_jni_result(env, result);
free_cb_result(result);
return response;
@ -212,7 +212,7 @@ jobject Java_com_mobile_WakuModule_wakuVersion(JNIEnv *env, jobject thiz,
jobject Java_com_mobile_WakuModule_wakuStop(JNIEnv *env, jobject thiz,
jlong wakuPtr) {
cb_result *result = NULL;
waku_stop((void *)wakuPtr, on_response, &result);
logosdelivery_stop_node((void *)wakuPtr, on_response, &result);
jobject response = to_jni_result(env, result);
free_cb_result(result);
return response;
@ -221,7 +221,7 @@ jobject Java_com_mobile_WakuModule_wakuStop(JNIEnv *env, jobject thiz,
jobject Java_com_mobile_WakuModule_wakuDestroy(JNIEnv *env, jobject thiz,
jlong wakuPtr) {
cb_result *result = NULL;
waku_destroy((void *)wakuPtr, on_response, &result);
logosdelivery_destroy((void *)wakuPtr, on_response, &result);
jobject response = to_jni_result(env, result);
free_cb_result(result);
return response;

View File

@ -200,7 +200,7 @@ static napi_value WakuNew(napi_env env, napi_callback_info info) {
str_size = str_size + 1;
napi_get_value_string_utf8(env, args[0], jsonConfig, str_size, &str_size_read);
ctx = waku_new(jsonConfig, event_handler, userData);
ctx = logosdelivery_create_node(jsonConfig, event_handler, userData);
free(jsonConfig);
@ -290,7 +290,7 @@ static napi_value WakuSetEventCallback(napi_env env, napi_callback_info info) {
}
static napi_value WakuStart(napi_env env, napi_callback_info info) {
waku_start(ctx, event_handler, userData);
logosdelivery_start_node(ctx, event_handler, userData);
return NULL;
}

View File

@ -53,7 +53,7 @@ parser.add_argument('--peer', dest='peer', default="",
args = parser.parse_args()
# The next 'json_config' is the item passed to the 'waku_new'.
# The next 'json_config' is the item passed to the 'logosdelivery_create_node'.
json_config = "{ \
\"host\": \"%s\", \
\"port\": %d, \
@ -68,16 +68,16 @@ json_config = "{ \
callback_type = ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_char_p, ctypes.c_size_t)
# Node creation
libwaku.waku_new.restype = ctypes.c_void_p
libwaku.waku_new.argtypes = [ctypes.c_char_p,
libwaku.logosdelivery_create_node.restype = ctypes.c_void_p
libwaku.logosdelivery_create_node.argtypes = [ctypes.c_char_p,
callback_type,
ctypes.c_void_p]
ctx = libwaku.waku_new(bytes(json_config, 'utf-8'),
ctx = libwaku.logosdelivery_create_node(bytes(json_config, 'utf-8'),
callback_type(
#onErrCb
lambda ret, msg, len:
print("Error calling waku_new: %s",
print("Error calling logosdelivery_create_node: %s",
msg.decode('utf-8'))
),
ctypes.c_void_p(0))
@ -115,12 +115,12 @@ libwaku.logosdelivery_set_event_callback.argtypes = [callback_type, ctypes.c_voi
libwaku.logosdelivery_set_event_callback(callback, ctypes.c_void_p(0))
# Start the node
libwaku.waku_start.argtypes = [ctypes.c_void_p,
libwaku.logosdelivery_start_node.argtypes = [ctypes.c_void_p,
callback_type,
ctypes.c_void_p]
libwaku.waku_start(ctx,
libwaku.logosdelivery_start_node(ctx,
callback_type(lambda ret, msg, len:
print("Error in waku_start: %s" %
print("Error in logosdelivery_start_node: %s" %
msg.decode('utf-8'))),
ctypes.c_void_p(0))

View File

@ -25,7 +25,7 @@ public:
WakuHandler() : QObject(), ctx(nullptr) {}
void initialize(const QString& jsonConfig, WakuCallBack event_handler, void* userData) {
ctx = waku_new(jsonConfig.toUtf8().constData(), WakuCallBack(event_handler), userData);
ctx = logosdelivery_create_node(jsonConfig.toUtf8().constData(), WakuCallBack(event_handler), userData);
logosdelivery_set_event_callback(ctx, on_event_received, userData);
qDebug() << "Waku context initialized, ready to start.";
@ -33,7 +33,7 @@ public:
Q_INVOKABLE void start() {
if (ctx) {
waku_start(ctx, event_handler, nullptr);
logosdelivery_start_node(ctx, event_handler, nullptr);
qDebug() << "Waku start called with event_handler and userData.";
} else {
qDebug() << "Context is not initialized in start.";
@ -42,7 +42,7 @@ public:
Q_INVOKABLE void stop() {
if (ctx) {
waku_stop(ctx, event_handler, nullptr);
logosdelivery_stop_node(ctx, event_handler, nullptr);
qDebug() << "Waku stop called with event_handler and userData.";
} else {
qDebug() << "Context is not initialized in stop.";

View File

@ -6,7 +6,7 @@ use std::{slice, thread, time};
pub type FFICallBack = unsafe extern "C" fn(c_int, *const c_char, usize, *const c_void);
extern "C" {
pub fn waku_new(
pub fn logosdelivery_create_node(
config_json: *const u8,
cb: FFICallBack,
user_data: *const c_void,
@ -14,7 +14,7 @@ extern "C" {
pub fn waku_version(ctx: *const c_void, cb: FFICallBack, user_data: *const c_void) -> c_int;
pub fn waku_start(ctx: *const c_void, cb: FFICallBack, user_data: *const c_void) -> c_int;
pub fn logosdelivery_start_node(ctx: *const c_void, cb: FFICallBack, user_data: *const c_void) -> c_int;
pub fn waku_default_pubsub_topic(
ctx: *mut c_void,
@ -60,11 +60,11 @@ fn main() {
unsafe {
// Create the waku node
let closure = |ret: i32, data: &str| {
println!("Ret {ret}. waku_new closure called {data}");
println!("Ret {ret}. logosdelivery_create_node closure called {data}");
};
let cb = get_trampoline(&closure);
let config_json_str = CString::new(config_json).unwrap();
let ctx = waku_new(
let ctx = logosdelivery_create_node(
config_json_str.as_ptr() as *const u8,
cb,
&closure as *const _ as *const c_void,
@ -99,10 +99,10 @@ fn main() {
// Start the Waku node
let closure = |ret: i32, data: &str| {
println!("Ret {ret}. waku_start closure called {data}");
println!("Ret {ret}. logosdelivery_start_node closure called {data}");
};
let cb = get_trampoline(&closure);
let _ret = waku_start(ctx, cb, &closure as *const _ as *const c_void);
let _ret = logosdelivery_start_node(ctx, cb, &closure as *const _ as *const c_void);
}
loop {

View File

@ -1,82 +0,0 @@
import logos_delivery/waku/compat/option_valueor
import std/[options, json, strutils, net]
import chronos, chronicles, results, confutils, confutils/std/net, ffi
import
logos_delivery/waku/node/peer_manager/peer_manager,
tools/confutils/cli_args,
logos_delivery/waku/waku,
logos_delivery/waku/factory/node_factory,
logos_delivery/waku/factory/app_callbacks,
logos_delivery/waku/rest_api/endpoint/builder,
library/declare_lib
proc createWaku(
configJson: cstring, appCallbacks: AppCallbacks = nil
): Future[Result[LogosDelivery, string]] {.async.} =
var conf = defaultWakuNodeConf().valueOr:
return err("Failed creating node: " & error)
var errorResp: string
var jsonNode: JsonNode
try:
jsonNode = parseJson($configJson)
except Exception:
return err(
"exception in createWaku when calling parseJson: " & getCurrentExceptionMsg() &
" configJson string: " & $configJson
)
for confField, confValue in fieldPairs(conf):
if jsonNode.contains(confField):
# Make sure string doesn't contain the leading or trailing " character
let formattedString = ($jsonNode[confField]).strip(chars = {'\"'})
# Override conf field with the value set in the json-string
try:
confValue = parseCmdArg(typeof(confValue), formattedString)
except Exception:
return err(
"exception in createWaku when parsing configuration. exc: " &
getCurrentExceptionMsg() & ". string that could not be parsed: " &
formattedString & ". expected type: " & $typeof(confValue)
)
# Don't send relay app callbacks if relay is disabled
if not conf.relay and not appCallbacks.isNil():
appCallbacks.relayHandler = nil
appCallbacks.topicHealthChangeHandler = nil
conf.rest = false ## libwaku never runs the REST server
let logosRes = (await LogosDelivery.new(conf, appCallbacks)).valueOr:
error "LogosDelivery initialization failed", error = error
return err("Failed setting up LogosDelivery: " & $error)
return ok(logosRes)
registerReqFFI(CreateNodeWithCallbacksRequest, ctx: ptr FFIContext[LogosDelivery]):
proc(
configJson: cstring, appCallbacks: AppCallbacks
): Future[Result[string, string]] {.async.} =
ctx.myLib[] = (await createWaku(configJson, cast[AppCallbacks](appCallbacks))).valueOr:
error "CreateNodeWithCallbacksRequest failed", error = error
return err($error)
return ok("")
proc waku_start(
ctx: ptr FFIContext[LogosDelivery], callback: FFICallBack, userData: pointer
) {.ffi.} =
(await ctx.myLib[].start()).isOkOr:
error "START_NODE failed", error = error
return err("failed to start: " & $error)
return ok("")
proc waku_stop(
ctx: ptr FFIContext[LogosDelivery], callback: FFICallBack, userData: pointer
) {.ffi.} =
(await ctx.myLib[].stop()).isOkOr:
error "STOP_NODE failed", error = error
return err("failed to stop: " & $error)
return ok("")

View File

@ -9,11 +9,7 @@ import
logos_delivery/waku/waku,
logos_delivery/waku/node/waku_node,
logos_delivery/waku/node/health_monitor/health_status,
../logos_delivery/waku/factory/app_callbacks,
./events/json_message_event,
./events/json_topic_health_change_event,
./events/json_connection_change_event,
./events/json_connection_status_change_event,
./declare_lib
################################################################################
@ -25,7 +21,6 @@ include
./logos_delivery_api/debug_api,
./kernel_api/peer_manager_api,
./kernel_api/discovery_api,
./kernel_api/node_lifecycle_api,
./kernel_api/debug_node_api,
./kernel_api/ping_api,
./kernel_api/protocols/relay_api,
@ -34,81 +29,7 @@ include
./kernel_api/protocols/filter_api,
./channels_api/channel_api
################################################################################
### Exported procs (former libwaku API)
proc waku_new(
configJson: cstring, callback: FFICallback, userData: pointer
): pointer {.dynlib, exportc, cdecl.} =
initializeLibrary()
## Creates a new instance of the WakuNode.
if isNil(callback):
echo "error: missing callback in waku_new"
return nil
## Create the Waku thread that will keep waiting for req from the main thread.
var ctx = ffi.createFFIContext[LogosDelivery]().valueOr:
let msg = "Error in createFFIContext: " & $error
callback(RET_ERR, unsafeAddr msg[0], cast[csize_t](len(msg)), userData)
return nil
ctx.userData = userData
proc onReceivedMessage(ctx: ptr FFIContext): WakuRelayHandler =
return proc(pubsubTopic: PubsubTopic, msg: WakuMessage) {.async.} =
callEventCallback(ctx, "onReceivedMessage"):
$JsonMessageEvent.new(pubsubTopic, msg)
proc onTopicHealthChange(ctx: ptr FFIContext): TopicHealthChangeHandler =
return proc(pubsubTopic: PubsubTopic, topicHealth: TopicHealth) {.async.} =
callEventCallback(ctx, "onTopicHealthChange"):
$JsonTopicHealthChangeEvent.new(pubsubTopic, topicHealth)
proc onConnectionChange(ctx: ptr FFIContext): ConnectionChangeHandler =
return proc(peerId: PeerId, peerEvent: PeerEventKind) {.async.} =
callEventCallback(ctx, "onConnectionChange"):
$JsonConnectionChangeEvent.new($peerId, peerEvent)
proc onConnectionStatusChange(ctx: ptr FFIContext): ConnectionStatusChangeHandler =
return proc(status: ConnectionStatus) {.async.} =
callEventCallback(ctx, "onConnectionStatusChange"):
$JsonConnectionStatusChangeEvent.new(status)
let appCallbacks = AppCallbacks(
relayHandler: onReceivedMessage(ctx),
topicHealthChangeHandler: onTopicHealthChange(ctx),
connectionChangeHandler: onConnectionChange(ctx),
connectionStatusChangeHandler: onConnectionStatusChange(ctx),
)
ffi.sendRequestToFFIThread(
ctx,
CreateNodeWithCallbacksRequest.ffiNewReq(
callback, userData, configJson, appCallbacks
),
).isOkOr:
let msg = "error in sendRequestToFFIThread: " & $error
callback(RET_ERR, unsafeAddr msg[0], cast[csize_t](len(msg)), userData)
return nil
return ctx
proc waku_destroy(
ctx: ptr FFIContext[LogosDelivery], callback: FFICallBack, userData: pointer
): cint {.dynlib, exportc, cdecl.} =
initializeLibrary()
checkParams(ctx, callback, userData)
ffi.destroyFFIContext(ctx).isOkOr:
let msg = "libwaku error: " & $error
callback(RET_ERR, unsafeAddr msg[0], cast[csize_t](len(msg)), userData)
return RET_ERR
## always need to invoke the callback although we don't retrieve value to the caller
callback(RET_OK, nil, 0, userData)
return RET_OK
# ### End of exported procs
# ################################################################################
# Node lifecycle (create / start / stop / destroy) is unified under the stable
# logosdelivery_* surface in ./logos_delivery_api/node_api. The former
# waku_new / waku_start / waku_stop / waku_destroy entry points were removed to
# avoid maintaining two parallel node-lifecycle APIs.

View File

@ -26,26 +26,11 @@ extern "C"
{
#endif
// Creates a new instance of the waku node.
// Sets up the waku node from the given configuration.
// Returns a pointer to the Context needed by the rest of the API functions.
void *waku_new(
const char *configJson,
FFICallBack callback,
void *userData);
int waku_start(void *ctx,
FFICallBack callback,
void *userData);
int waku_stop(void *ctx,
FFICallBack callback,
void *userData);
// Destroys an instance of a waku node created with waku_new
int waku_destroy(void *ctx,
FFICallBack callback,
void *userData);
// NOTE: node lifecycle (create / start / stop / destroy) is unified and lives
// only in the stable header. Use logosdelivery_create_node,
// logosdelivery_start_node, logosdelivery_stop_node and logosdelivery_destroy
// (declared in liblogosdelivery.h, included above) regardless of whether you
// drive the node through the messaging surface or this kernel API.
int waku_version(void *ctx,
FFICallBack callback,

View File

@ -6,6 +6,7 @@ import
logos_delivery/waku/node/waku_node,
logos_delivery/api/types,
logos_delivery/waku/api/events/health_events,
logos_delivery/waku/api/events/peer_events,
tools/confutils/conf_from_json,
../declare_lib,
../json_event
@ -125,6 +126,36 @@ proc logosdelivery_start_node(
chronicles.error "ConnectionStatusChange.listen failed", err = $error
return err("ConnectionStatusChange.listen failed: " & $error)
let shardTopicHealthListener = EventShardTopicHealthChange.listen(
ctx.myLib[].waku.brokerCtx,
proc(event: EventShardTopicHealthChange) {.async: (raises: []).} =
callEventCallback(ctx, "onTopicHealthChange"):
$(
%*{
"eventType": "relay_topic_health_change",
"pubsubTopic": $event.topic,
"topicHealth": $event.health,
}
),
).valueOr:
chronicles.error "EventShardTopicHealthChange.listen failed", err = $error
return err("EventShardTopicHealthChange.listen failed: " & $error)
let peerEventListener = WakuPeerEvent.listen(
ctx.myLib[].waku.brokerCtx,
proc(event: WakuPeerEvent) {.async: (raises: []).} =
callEventCallback(ctx, "onConnectionChange"):
$(
%*{
"eventType": "connection_change",
"peerId": $event.peerId,
"peerEvent": $event.kind,
}
),
).valueOr:
chronicles.error "WakuPeerEvent.listen failed", err = $error
return err("WakuPeerEvent.listen failed: " & $error)
let channelReceivedListener = ChannelMessageReceivedEvent.listen(
ctx.myLib[].waku.brokerCtx,
proc(event: ChannelMessageReceivedEvent) {.async: (raises: []).} =
@ -176,6 +207,8 @@ proc logosdelivery_stop_node(
await MessagePropagatedEvent.dropAllListeners(ctx.myLib[].waku.brokerCtx)
await MessageReceivedEvent.dropAllListeners(ctx.myLib[].waku.brokerCtx)
await EventConnectionStatusChange.dropAllListeners(ctx.myLib[].waku.brokerCtx)
await EventShardTopicHealthChange.dropAllListeners(ctx.myLib[].waku.brokerCtx)
await WakuPeerEvent.dropAllListeners(ctx.myLib[].waku.brokerCtx)
await ChannelMessageReceivedEvent.dropAllListeners(ctx.myLib[].waku.brokerCtx)
await ChannelMessageSentEvent.dropAllListeners(ctx.myLib[].waku.brokerCtx)
await ChannelMessageErrorEvent.dropAllListeners(ctx.myLib[].waku.brokerCtx)

View File

@ -10,7 +10,7 @@ logScope:
proc hasDuplicate*(
rlnPeer: Rln, epoch: Epoch, proofMetadata: ProofMetadata
): RlnResult[bool] =
): Result[bool, string] =
## returns true if there is another message in the `nullifierLog` of the `rlnPeer` with the same
## epoch and nullifier as `proofMetadata`'s epoch and nullifier
## otherwise, returns false
@ -32,7 +32,7 @@ proc hasDuplicate*(
proc updateLog*(
rlnPeer: Rln, epoch: Epoch, proofMetadata: ProofMetadata
): RlnResult[void] =
): Result[void, string] =
## saves supplied proofMetadata `proofMetadata`
## in the `nullifierLog` of the `rlnPeer`
## Returns an error if it cannot update the log

View File

@ -5,11 +5,8 @@ import ../waku_core, ../waku_keystore, ../common/protobuf
export waku_keystore, waku_core
type RlnResult*[T] = Result[T, string]
## RLN is a Nim wrapper for the data types used in zerokit RLN
type RlnRaw* {.incompleteStruct.} = object
type RlnInstanceResult* = RlnResult[ptr RlnRaw]
type
MerkleNode* = array[32, byte]
@ -72,14 +69,10 @@ type ProofMetadata* = object
shareY*: MerkleNode
externalNullifier*: Nullifier
type
MessageValidationResult* {.pure.} = enum
Valid
Invalid
Spam
MerkleNodeResult* = RlnResult[MerkleNode]
RateLimitProofResult* = RlnResult[RateLimitProof]
type MessageValidationResult* {.pure.} = enum
Valid
Invalid
Spam
# Protobufs enc and init
proc init*(T: type RateLimitProof, buffer: seq[byte]): ProtoResult[T] =

View File

@ -183,7 +183,7 @@ proc monitorEpochs(rln: Rln) {.async.} =
proc mount(
conf: WakuRlnConfig, registrationHandler = none(RegistrationHandler)
): Future[RlnResult[Rln]] {.async.} =
): Future[Result[Rln, string]] {.async.} =
var
groupManager: GroupManager
rln: Rln
@ -271,7 +271,7 @@ proc isReady*(rlnPeer: Rln): Future[bool] {.async.} =
proc new*(
T: type Rln, conf: WakuRlnConfig, registrationHandler = none(RegistrationHandler)
): Future[RlnResult[Rln]] {.async.} =
): Future[Result[Rln, string]] {.async.} =
## Mounts the rln-relay protocol on the node.
## The rln-relay protocol can be mounted in two modes: on-chain and off-chain.
## Returns an error if the rln-relay protocol could not be mounted.

View File

@ -318,14 +318,14 @@ proc vecToSeq*(data: Vec_uint8): seq[byte] =
if result.len > 0:
copyMem(addr result[0], data.dataPtr, result.len)
proc seqToFixed32*(data: openArray[byte]): RlnResult[array[32, byte]] =
proc seqToFixed32*(data: openArray[byte]): Result[array[32, byte], string] =
if data.len != FieldElementSize:
return err("Expected 32 bytes, got " & $data.len)
var output: array[32, byte]
copyMem(addr output[0], unsafeAddr data[0], FieldElementSize)
ok(output)
proc cfrToBytesLe*(cfr: ptr CFr): RlnResult[array[32, byte]] =
proc cfrToBytesLe*(cfr: ptr CFr): Result[array[32, byte], string] =
let bytes = ffi_cfr_to_bytes_le(cfr)
defer:
ffi_vec_u8_free(bytes)
@ -333,7 +333,7 @@ proc cfrToBytesLe*(cfr: ptr CFr): RlnResult[array[32, byte]] =
return err("Invalid field byte length: " & $bytes.len)
seqToFixed32(vecToSeq(bytes))
proc bytesToCfrLe*(data: openArray[byte]): RlnResult[ptr CFr] =
proc bytesToCfrLe*(data: openArray[byte]): Result[ptr CFr, string] =
## Allocate a ptr CFr from raw bytes. Caller MUST ffi_cfr_free(x).
var vec = toVecUint8(data)
let res = ffi_bytes_le_to_cfr(addr vec)
@ -343,7 +343,7 @@ proc bytesToCfrLe*(data: openArray[byte]): RlnResult[ptr CFr] =
proc cfrResultToBytes*(
res: CResultCFrPtrVecU8, prefix: string
): RlnResult[array[32, byte]] =
): Result[array[32, byte], string] =
## Consume a CResultCFrPtrVecU8: read bytes if ok, free the CFr, or
## propagate the error (also freeing the error string).
if res.ok.isNil:
@ -352,7 +352,7 @@ proc cfrResultToBytes*(
ffi_cfr_free(res.ok)
cfrToBytesLe(res.ok)
proc hashToFieldLe*(data: openArray[byte]): RlnResult[ptr CFr] =
proc hashToFieldLe*(data: openArray[byte]): Result[ptr CFr, string] =
## Caller MUST ffi_cfr_free the returned ptr.
var vec = toVecUint8(data)
let cfr = ffi_hash_to_field_le(addr vec)
@ -360,7 +360,7 @@ proc hashToFieldLe*(data: openArray[byte]): RlnResult[ptr CFr] =
return err("Failed to hash to field")
ok(cfr)
proc poseidonPairLe*(a, b: openArray[byte]): RlnResult[array[32, byte]] =
proc poseidonPairLe*(a, b: openArray[byte]): Result[array[32, byte], string] =
## Poseidon hash of exactly two 32-byte field elements (little-endian).
## zerokit v2 FFI only exposes pair-input Poseidon; unary is not supported.
let aPtr = bytesToCfrLe(a).valueOr:

View File

@ -12,9 +12,9 @@ logScope:
# Forward decl; body defined below.
proc generateExternalNullifier*(
epoch: Epoch, rlnIdentifier: RlnIdentifier
): RlnResult[ExternalNullifier]
): Result[ExternalNullifier, string]
proc toRootVec(validRoots: seq[MerkleNode]): RlnResult[Vec_CFr] =
proc toRootVec(validRoots: seq[MerkleNode]): Result[Vec_CFr, string] =
## Caller MUST ffi_vec_cfr_free the returned Vec_CFr.
var roots = ffi_vec_cfr_new(csize_t(validRoots.len))
for root in validRoots:
@ -27,7 +27,7 @@ proc toRootVec(validRoots: seq[MerkleNode]): RlnResult[Vec_CFr] =
proc proofPtrToRateLimitProof(
proofPtr: ptr FFI_RLNProof, epoch: Epoch, rlnIdentifier: RlnIdentifier
): RlnResult[RateLimitProof] =
): Result[RateLimitProof, string] =
var proofHandle = proofPtr
let proofBytesRes = ffi_rln_proof_to_bytes_le(addr proofHandle)
if hasError(proofBytesRes.err):
@ -93,7 +93,7 @@ proc proofPtrToRateLimitProof(
ok(output)
proc parseCredentialVec(vec: var Vec_CFr): RlnResult[IdentityCredential] =
proc parseCredentialVec(vec: var Vec_CFr): Result[IdentityCredential, string] =
## Vec_CFr order: idTrapdoor, idNullifier, idSecretHash, idCommitment.
if int(ffi_vec_cfr_len(addr vec)) != 4:
return err("Unexpected credential element count")
@ -120,13 +120,13 @@ proc parseCredentialVec(vec: var Vec_CFr): RlnResult[IdentityCredential] =
)
)
proc membershipKeyGen*(): RlnResult[IdentityCredential] =
proc membershipKeyGen*(): Result[IdentityCredential, string] =
var vec = ffi_extended_key_gen()
defer:
ffi_vec_cfr_free(vec)
parseCredentialVec(vec)
proc createRLNInstanceLocal(): RlnInstanceResult =
proc createRLNInstanceLocal(): Result[ptr RlnRaw, string] =
## Creates a stateless RLN instance (no local Merkle tree).
let res = ffi_rln_new()
if res.ok.isNil():
@ -135,18 +135,18 @@ proc createRLNInstanceLocal(): RlnInstanceResult =
return err(msg)
ok(res.ok)
proc createRLNInstance*(): RlnInstanceResult =
proc createRLNInstance*(): Result[ptr RlnRaw, string] =
## Wraps createRLNInstanceLocal with metrics timing.
var res: RlnInstanceResult
var res: Result[ptr RlnRaw, string]
waku_rln_instance_creation_duration_seconds.nanosecondTime:
res = createRLNInstanceLocal()
return res
proc poseidon*(left, right: seq[byte]): RlnResult[array[32, byte]] =
proc poseidon*(left, right: seq[byte]): Result[array[32, byte], string] =
## Poseidon hash of exactly 2 inputs; zerokit v2 FFI only exposes the pair variant.
poseidonPairLe(left, right)
proc toLeaf*(rateCommitment: RateCommitment): RlnResult[seq[byte]] =
proc toLeaf*(rateCommitment: RateCommitment): Result[seq[byte], string] =
let idCommitment = rateCommitment.idCommitment
var userMessageLimit: array[32, byte]
try:
@ -164,7 +164,7 @@ proc toLeaf*(rateCommitment: RateCommitment): RlnResult[seq[byte]] =
retLeaf[i] = leaf[i]
return ok(retLeaf)
proc toLeaves*(rateCommitments: seq[RateCommitment]): RlnResult[seq[seq[byte]]] =
proc toLeaves*(rateCommitments: seq[RateCommitment]): Result[seq[seq[byte]], string] =
var leaves = newSeq[seq[byte]]()
for rateCommitment in rateCommitments:
let leaf = toLeaf(rateCommitment).valueOr:
@ -174,7 +174,7 @@ proc toLeaves*(rateCommitments: seq[RateCommitment]): RlnResult[seq[seq[byte]]]
proc generateExternalNullifier*(
epoch: Epoch, rlnIdentifier: RlnIdentifier
): RlnResult[ExternalNullifier] =
): Result[ExternalNullifier, string] =
## externalNullifier = Poseidon(H(epoch), H(rlnIdentifier)); H = ffi_hash_to_field_le.
let epochFr = hashToFieldLe(@epoch).valueOr:
return err("Failed to hash epoch to field: " & error)
@ -194,7 +194,7 @@ proc generateExternalNullifier*(
"Failed to serialize external nullifier: " & e
)
proc extractMetadata*(proof: RateLimitProof): RlnResult[ProofMetadata] =
proc extractMetadata*(proof: RateLimitProof): Result[ProofMetadata, string] =
let externalNullifier = generateExternalNullifier(proof.epoch, proof.rlnIdentifier).valueOr:
return err("Failed to compute external nullifier: " & error)
return ok(
@ -206,7 +206,9 @@ proc extractMetadata*(proof: RateLimitProof): RlnResult[ProofMetadata] =
)
)
proc buildPathElementsVec(pathElements: seq[byte], depth: int): RlnResult[Vec_CFr] =
proc buildPathElementsVec(
pathElements: seq[byte], depth: int
): Result[Vec_CFr, string] =
## Caller MUST ffi_vec_cfr_free the returned Vec_CFr.
var vec = ffi_vec_cfr_new(csize_t(depth))
for i in 0 ..< depth:
@ -222,7 +224,9 @@ proc buildPathElementsVec(pathElements: seq[byte], depth: int): RlnResult[Vec_CF
ffi_cfr_free(element)
ok(vec)
proc buildWitnessInput(witness: RLNWitnessInput): RlnResult[ptr FFI_RLNWitnessInput] =
proc buildWitnessInput(
witness: RLNWitnessInput
): Result[ptr FFI_RLNWitnessInput, string] =
## ffi_rln_witness_input_new copies all inputs, so the intermediate CFrs/vecs
## are freed here. Caller MUST ffi_rln_witness_input_free the returned handle.
let depth = witness.identity_path_index.len
@ -287,7 +291,7 @@ proc generateRlnProofWithWitness*(
witness: RLNWitnessInput,
epoch: Epoch,
rlnIdentifier: RlnIdentifier,
): RlnResult[RateLimitProof] =
): Result[RateLimitProof, string] =
let witnessHandle = buildWitnessInput(witness).valueOr:
return
err("failed call to buildWitnessInput in generateRlnProofWithWitness: " & error)
@ -306,7 +310,7 @@ proc generateRlnProofWithWitness*(
proc buildRlnProof(
proof: RateLimitProof, externalNullifier: ExternalNullifier
): RlnResult[ptr FFI_RLNProof] =
): Result[ptr FFI_RLNProof, string] =
## ffi_rln_proof_new copies all inputs, so the intermediate CFrs are freed
## here. Caller MUST ffi_rln_proof_free the returned handle.
var groth16Vec = toVecUint8(proof.proof)
@ -345,7 +349,7 @@ proc verifyRlnProof*(
proof: RateLimitProof,
signal: openArray[byte],
validRoots: seq[MerkleNode],
): RlnResult[bool] =
): Result[bool, string] =
if validRoots.len == 0:
return err("verifyRlnProof requires at least one valid root (stateless mode)")

View File

@ -1,5 +1,6 @@
import std/options
import std/tempfiles
import results
import
logos_delivery/waku/rln,
@ -8,12 +9,12 @@ import
protocol_metrics, nonce_manager,
]
proc createRLNInstanceWrapper*(): RlnInstanceResult =
proc createRLNInstanceWrapper*(): Result[ptr RlnRaw, string] =
return createRlnInstance()
proc unsafeAppendRLNProof*(
rlnPeer: Rln, msg: var WakuMessage, epoch: Epoch, messageId: MessageId
): RlnResult[void] =
): Result[void, string] =
## Test helper derived from the publish-path proof flow.
## - Skips nonce validation to intentionally allow generating "bad" message IDs for tests.
## - Forces a real-time on-chain Merkle root refresh via `updateRoots()` and fetches Merkle

View File

@ -37,7 +37,7 @@ proc generateCredentials*(): IdentityCredential =
proc getRateCommitment*(
idCredential: IdentityCredential, userMessageLimit: UserMessageLimit
): RlnResult[RawRateCommitment] =
): Result[RawRateCommitment, string] =
return RateCommitment(
idCommitment: idCredential.idCommitment, userMessageLimit: userMessageLimit
).toLeaf()