chore: phase 2 — rename/restructure waku_rln_relay → waku_rln (#3978)

* move rln specific procs and types

* Renaming and restructuring RLN module

* Rename waku_rln_relay to waku_rln

* rename rln-relay types to rln

* Fix linting

* update logScope topics to match new rln module name

* Rename waku_rln module to rln

* Rename WakuRln type to Rln, rename FFI raw type to RlnRaw to avoid collision

* Apply nph formatting

* Rename local rlnRelay to rln in mountRlnRelay
This commit is contained in:
Tanya S 2026-06-27 12:28:59 +02:00 committed by GitHub
parent 26098d76cf
commit 57ff24760f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
61 changed files with 523 additions and 539 deletions

View File

@ -3,11 +3,11 @@ import
import
logos_delivery/waku/[
waku_rln_relay/protocol_types,
waku_rln_relay/rln,
waku_rln_relay,
waku_rln_relay/conversion_utils,
waku_rln_relay/group_manager/on_chain/group_manager,
rln/protocol_types,
rln/bindings,
rln,
rln/conversion_utils,
rln/group_manager/on_chain/group_manager,
],
tests/waku_rln_relay/utils_onchain

View File

@ -48,7 +48,7 @@ import
./config_chat2
import libp2p/protocols/pubsub/rpc/messages, libp2p/protocols/pubsub/pubsub
import ../../logos_delivery/waku/waku_rln_relay
import ../../logos_delivery/waku/rln
const Help = """
Commands: /[?|help|connect|nick|exit]
@ -189,11 +189,11 @@ proc publish(c: Chat, line: string) =
timestamp: getNanosecondTime(time),
)
if not isNil(c.node.wakuRlnRelay):
if not isNil(c.node.rln):
# for future version when we support more than one rln protected content topic,
# we should check the message content topic as well
let proofRes =
waitFor c.node.wakuRlnRelay.generateRLNProof(message.toRLNSignal(), float64(time))
waitFor c.node.rln.generateRLNProof(message.toRLNSignal(), float64(time))
if proofRes.isErr():
info "could not append rate limit proof to the message"
else:
@ -204,13 +204,13 @@ proc publish(c: Chat, line: string) =
return
# TODO move it to log after dogfooding
let msgEpoch = fromEpoch(proof.epoch)
if fromEpoch(c.node.wakuRlnRelay.lastEpoch) == msgEpoch:
if fromEpoch(c.node.rln.lastEpoch) == msgEpoch:
echo "--rln epoch: ",
msgEpoch, " ⚠️ message rate violation! you are spamming the network!"
else:
echo "--rln epoch: ", msgEpoch
# update the last epoch
c.node.wakuRlnRelay.lastEpoch = proof.epoch
c.node.rln.lastEpoch = proof.epoch
try:
if not c.node.wakuLegacyLightPush.isNil():
@ -521,7 +521,7 @@ proc processInput(rfd: AsyncFD, rng: crypto.Rng) {.async.} =
topic = DefaultPubsubTopic, error = error
if conf.rlnRelay:
info "WakuRLNRelay is enabled"
info "Rln is enabled"
proc spamHandler(wakuMessage: WakuMessage) {.gcsafe, closure.} =
info "spam handler is called"
@ -538,9 +538,7 @@ proc processInput(rfd: AsyncFD, rng: crypto.Rng) {.async.} =
chainId: UInt256.fromBytesBE(conf.rlnRelayChainId.toBytesBE()),
ethClientUrls: conf.ethClientUrls.mapIt(string(it)),
creds: some(
RlnRelayCreds(
path: conf.rlnRelayCredPath, password: conf.rlnRelayCredPassword
)
RlnCreds(path: conf.rlnRelayCredPath, password: conf.rlnRelayCredPassword)
),
userMessageLimit: conf.rlnRelayUserMessageLimit,
epochSizeSec: conf.rlnEpochSizeSec,
@ -548,14 +546,14 @@ proc processInput(rfd: AsyncFD, rng: crypto.Rng) {.async.} =
waitFor node.mountRlnRelay(rlnConf, spamHandler = some(spamHandler))
let membershipIndex = node.wakuRlnRelay.groupManager.membershipIndex.get()
let identityCredential = node.wakuRlnRelay.groupManager.idCredentials.get()
let membershipIndex = node.rln.groupManager.membershipIndex.get()
let identityCredential = node.rln.groupManager.idCredentials.get()
echo "your membership index is: ", membershipIndex
echo "your rln identity commitment key is: ",
identityCredential.idCommitment.inHex()
else:
info "WakuRLNRelay is disabled"
echo "WakuRLNRelay is disabled, please enable it by passing in the --rln-relay flag"
info "Rln is disabled"
echo "Rln is disabled, please enable it by passing in the --rln-relay flag"
if conf.metricsLogging:
startMetricsLog()

View File

@ -56,7 +56,7 @@ import
./config_chat2mix
import libp2p/protocols/pubsub/rpc/messages, libp2p/protocols/pubsub/pubsub
import ../../logos_delivery/waku/waku_rln_relay
import ../../logos_delivery/waku/rln
logScope:
topics = "chat2 mix"

View File

@ -25,7 +25,7 @@ import
discovery/waku_discv5,
discovery/waku_dnsdisc,
waku_relay,
waku_rln_relay,
rln,
factory/builder,
factory/networks_config,
],
@ -614,7 +614,7 @@ when isMainModule:
ethContractAddress: conf.rlnRelayEthContractAddress,
ethClientUrls: conf.ethClientUrls.mapIt(string(it)),
epochSizeSec: conf.rlnEpochSizeSec,
creds: none(RlnRelayCreds),
creds: none(RlnCreds),
onFatalErrorAction: onFatalErrorAction,
)

View File

@ -2,7 +2,7 @@
import
results,
logos_delivery/waku/[common/logging, waku_node, waku_rln_relay],
logos_delivery/waku/[common/logging, waku_node, rln],
./erc_5564_interface as StealthCommitmentFFI,
./node_spec,
./wire_spec
@ -47,9 +47,7 @@ proc sendThruWaku*(
)
message.proof = (
await self.waku.node.wakuRlnRelay.generateRLNProof(
message.toRLNSignal(), float64(time)
)
await self.waku.node.rln.generateRLNProof(message.toRLNSignal(), float64(time))
).valueOr:
return err("could not append rate limit proof to the message: " & error)

View File

@ -15,7 +15,7 @@ import
waku_store/client,
waku_store/common,
waku_relay/protocol,
waku_rln_relay/rln_relay,
rln/rln,
waku_lightpush/client,
waku_lightpush/callbacks,
events/message_events,
@ -65,7 +65,7 @@ proc setupSendProcessorChain(
peerManager: PeerManager,
lightpushClient: WakuLightPushClient,
relay: WakuRelay,
rlnRelay: WakuRLNRelay,
rlnRelay: Rln,
brokerCtx: BrokerContext,
): Result[BaseSendProcessor, string] =
let isRelayAvail = not relay.isNil()
@ -77,9 +77,9 @@ proc setupSendProcessorChain(
var processors = newSeq[BaseSendProcessor]()
if isRelayAvail:
let rln: Option[WakuRLNRelay] =
let rln: Option[Rln] =
if rlnRelay.isNil():
none[WakuRLNRelay]()
none[Rln]()
else:
some(rlnRelay)
let publishProc = getRelayPushHandler(relay, rln)
@ -107,7 +107,7 @@ proc new*(
let checkStoreForMessages = preferP2PReliability and not w.wakuStoreClient.isNil()
let sendProcessorChain = setupSendProcessorChain(
w.peerManager, w.wakuLightPushClient, w.wakuRelay, w.wakuRlnRelay, w.brokerCtx
w.peerManager, w.wakuLightPushClient, w.wakuRelay, w.rln, w.brokerCtx
).valueOr:
return err("failed to setup SendProcessorChain: " & $error)

View File

@ -12,7 +12,7 @@ const
##############################
## RLN Relay Config Builder ##
##############################
type RlnRelayConfBuilder* = object
type RlnConfBuilder* = object
enabled*: Option[bool]
chainId*: Option[UInt256]
ethClientUrls*: Option[seq[string]]
@ -24,58 +24,58 @@ type RlnRelayConfBuilder* = object
epochSizeSec*: Option[uint64]
userMessageLimit*: Option[uint64]
proc init*(T: type RlnRelayConfBuilder): RlnRelayConfBuilder =
RlnRelayConfBuilder()
proc init*(T: type RlnConfBuilder): RlnConfBuilder =
RlnConfBuilder()
proc withEnabled*(b: var RlnRelayConfBuilder, enabled: bool) =
proc withEnabled*(b: var RlnConfBuilder, enabled: bool) =
b.enabled = some(enabled)
proc withChainId*(b: var RlnRelayConfBuilder, chainId: uint | UInt256) =
proc withChainId*(b: var RlnConfBuilder, chainId: uint | UInt256) =
when chainId is uint:
b.chainId = some(UInt256.fromBytesBE(chainId.toBytesBE()))
else:
b.chainId = some(chainId)
proc withCredIndex*(b: var RlnRelayConfBuilder, credIndex: uint) =
proc withCredIndex*(b: var RlnConfBuilder, credIndex: uint) =
b.credIndex = some(credIndex)
proc withCredPassword*(b: var RlnRelayConfBuilder, credPassword: string) =
proc withCredPassword*(b: var RlnConfBuilder, credPassword: string) =
b.credPassword = some(credPassword)
proc withCredPath*(b: var RlnRelayConfBuilder, credPath: string) =
proc withCredPath*(b: var RlnConfBuilder, credPath: string) =
b.credPath = some(credPath)
proc withDynamic*(b: var RlnRelayConfBuilder, dynamic: bool) =
proc withDynamic*(b: var RlnConfBuilder, dynamic: bool) =
b.dynamic = some(dynamic)
proc withEthClientUrls*(b: var RlnRelayConfBuilder, ethClientUrls: seq[string]) =
proc withEthClientUrls*(b: var RlnConfBuilder, ethClientUrls: seq[string]) =
b.ethClientUrls = some(ethClientUrls)
proc withEthContractAddress*(b: var RlnRelayConfBuilder, ethContractAddress: string) =
proc withEthContractAddress*(b: var RlnConfBuilder, ethContractAddress: string) =
b.ethContractAddress = some(ethContractAddress)
proc withEpochSizeSec*(b: var RlnRelayConfBuilder, epochSizeSec: uint64) =
proc withEpochSizeSec*(b: var RlnConfBuilder, epochSizeSec: uint64) =
b.epochSizeSec = some(epochSizeSec)
proc withUserMessageLimit*(b: var RlnRelayConfBuilder, userMessageLimit: uint64) =
proc withUserMessageLimit*(b: var RlnConfBuilder, userMessageLimit: uint64) =
b.userMessageLimit = some(userMessageLimit)
proc build*(b: RlnRelayConfBuilder): Result[Option[RlnRelayConf], string] =
proc build*(b: RlnConfBuilder): Result[Option[RlnConf], string] =
if not b.enabled.get(DefaultRlnRelayEnabled):
return ok(none(RlnRelayConf))
return ok(none(RlnConf))
if b.chainId.isNone():
return err("RLN Relay Chain Id is not specified")
let creds =
if b.credPath.isSome() and b.credPassword.isSome():
some(RlnRelayCreds(path: b.credPath.get(), password: b.credPassword.get()))
some(RlnCreds(path: b.credPath.get(), password: b.credPassword.get()))
elif b.credPath.isSome() and b.credPassword.isNone():
return err("RLN Relay Credential Password is not specified but path is")
elif b.credPath.isNone() and b.credPassword.isSome():
return err("RLN Relay Credential Path is not specified but password is")
else:
none(RlnRelayCreds)
none(RlnCreds)
if b.dynamic.isNone():
return err("rlnRelay.dynamic is not specified")
@ -85,7 +85,7 @@ proc build*(b: RlnRelayConfBuilder): Result[Option[RlnRelayConf], string] =
return err("rlnRelay.ethContractAddress is not specified")
return ok(
some(
RlnRelayConf(
RlnConf(
chainId: b.chainId.get(),
credIndex: b.credIndex,
creds: creds,

View File

@ -116,7 +116,7 @@ type WakuConfBuilder* = object
filterServiceConf*: FilterServiceConfBuilder
metricsServerConf*: MetricsServerConfBuilder
restServerConf*: RestServerConfBuilder
rlnRelayConf*: RlnRelayConfBuilder
rlnRelayConf*: RlnConfBuilder
storeServiceConf*: StoreServiceConfBuilder
mixConf*: MixConfBuilder
webSocketConf*: WebSocketConfBuilder
@ -181,7 +181,7 @@ proc init*(T: type WakuConfBuilder): WakuConfBuilder =
filterServiceConf: FilterServiceConfBuilder.init(),
metricsServerConf: MetricsServerConfBuilder.init(),
restServerConf: RestServerConfBuilder.init(),
rlnRelayConf: RlnRelayConfBuilder.init(),
rlnRelayConf: RlnConfBuilder.init(),
storeServiceConf: StoreServiceConfBuilder.init(),
webSocketConf: WebSocketConfBuilder.init(),
quicConf: QuicConfBuilder.init(),

View File

@ -23,7 +23,7 @@ import
../net/net_config,
../waku_core,
../waku_core/codecs,
../waku_rln_relay,
../rln,
../discovery/waku_dnsdisc,
../waku_archive/retention_policy as policy,
../waku_archive/retention_policy/builder as policy_builder,

View File

@ -13,7 +13,7 @@ import
results
import
../waku_rln_relay/rln_relay,
../rln/rln,
../rest_api/endpoint/builder,
../discovery/waku_discv5,
../discovery/waku_kademlia,
@ -25,7 +25,7 @@ import
../waku_mix,
./conf_builder/kademlia_discovery_conf_builder
export RlnRelayConf, RlnRelayCreds, RestServerConf, Discv5Conf, MetricsServerConf
export RlnConf, RlnCreds, RestServerConf, Discv5Conf, MetricsServerConf
logScope:
topics = "waku conf"
@ -113,7 +113,7 @@ type WakuConf* {.requiresInit.} = ref object
dnsDiscoveryConf*: Option[DnsDiscoveryConf]
filterServiceConf*: Option[FilterServiceConf]
storeServiceConf*: Option[StoreServiceConf]
rlnRelayConf*: Option[RlnRelayConf]
rlnRelayConf*: Option[RlnConf]
restServerConf*: Option[RestServerConf]
metricsServerConf*: Option[MetricsServerConf]
webSocketConf*: Option[WebSocketConf]

View File

@ -11,7 +11,7 @@ import
logos_delivery/api/types,
logos_delivery/waku/[
waku_relay,
waku_rln_relay,
rln,
events/health_events,
events/peer_events,
node/waku_node,
@ -89,12 +89,12 @@ proc getRelayHealth(hm: NodeHealthMonitor): ProtocolHealth =
proc getRlnRelayHealth(hm: NodeHealthMonitor): Future[ProtocolHealth] {.async.} =
var p = ProtocolHealth.init(WakuProtocol.RlnRelayProtocol)
if isNil(hm.node.wakuRlnRelay):
if isNil(hm.node.rln):
return p.notMounted()
const FutIsReadyTimout = 5.seconds
let isReadyStateFut = hm.node.wakuRlnRelay.isReady()
let isReadyStateFut = hm.node.rln.isReady()
if not await isReadyStateFut.withTimeout(FutIsReadyTimout):
return p.notReady("Ready state check timed out")

View File

@ -4,7 +4,7 @@ import logos_delivery/waku/compat/option_valueor
import chronicles, chronos, metrics, metrics/chronos_httpserver
import
logos_delivery/waku/
[net/auto_port, waku_rln_relay/protocol_metrics as rln_metrics, utils/collector],
[net/auto_port, rln/protocol_metrics as rln_metrics, utils/collector],
./peer_manager,
./node_telemetry,
./waku_node

View File

@ -52,7 +52,7 @@ import
waku_lightpush as lightpush_protocol,
waku_enr,
waku_peer_exchange,
waku_rln_relay,
rln,
common/rate_limit/setting,
common/callbacks,
common/nimchronos,
@ -110,7 +110,7 @@ type
wakuStoreTransfer*: SyncTransfer
wakuFilter*: waku_filter_v2.WakuFilter
wakuFilterClient*: filter_client.WakuFilterClient
wakuRlnRelay*: WakuRLNRelay
rln*: Rln
wakuLegacyLightPush*: WakuLegacyLightPush
wakuLegacyLightpushClient*: WakuLegacyLightPushClient
wakuLightPush*: WakuLightPush
@ -662,9 +662,9 @@ proc stop*(node: WakuNode) {.async.} =
node.peerManager.stop()
if not node.wakuRlnRelay.isNil():
if not node.rln.isNil():
try:
await node.wakuRlnRelay.stop() ## this can raise an exception
await node.rln.stop() ## this can raise an exception
except Exception:
error "exception stopping the node", error = getCurrentExceptionMsg()
@ -684,7 +684,7 @@ proc stop*(node: WakuNode) {.async.} =
node.started = false
proc isReady*(node: WakuNode): Future[bool] {.async: (raises: [Exception]).} =
if node.wakuRlnRelay == nil:
if node.rln == nil:
return true
return await node.wakuRlnRelay.isReady()
return await node.rln.isReady()
## TODO: add other protocol `isReady` checks

View File

@ -30,7 +30,7 @@ import
../../waku_lightpush as lightpush_protocol,
../peer_manager,
../../common/rate_limit/setting,
../../waku_rln_relay
../../rln
logScope:
topics = "waku node lightpush api"
@ -48,12 +48,12 @@ proc mountLegacyLightPush*(
info "mounting legacy lightpush with relay"
let rlnPeer =
if node.wakuRlnRelay.isNil():
if node.rln.isNil():
info "mounting legacy lightpush without rln-relay"
none(WakuRLNRelay)
none(Rln)
else:
info "mounting legacy lightpush with rln-relay"
some(node.wakuRlnRelay)
some(node.rln)
let pushHandler =
legacy_lightpush_protocol.getRelayPushHandler(node.wakuRelay, rlnPeer)
@ -159,12 +159,12 @@ proc mountLightPush*(
info "mounting lightpush with relay"
let rlnPeer =
if node.wakuRlnRelay.isNil():
if node.rln.isNil():
info "mounting lightpush without rln-relay"
none(WakuRLNRelay)
none(Rln)
else:
info "mounting lightpush with rln-relay"
some(node.wakuRlnRelay)
some(node.rln)
let pushHandler = lightpush_protocol.getRelayPushHandler(node.wakuRelay, rlnPeer)
node.wakuLightPush = WakuLightPush.new(

View File

@ -28,8 +28,8 @@ import
waku_filter_v2,
waku_archive,
waku_store_sync,
waku_rln_relay,
waku_rln_relay/adapters/relay as waku_rln_relay_adapter,
rln,
rln/adapters/relay as waku_rln_adapter,
node/waku_node,
node/subscription_manager,
node/peer_manager,
@ -195,17 +195,17 @@ proc mountRlnRelay*(
if node.wakuRelay.isNil():
raise newException(
CatchableError, "WakuRelay protocol is not mounted, cannot mount WakuRlnRelay"
CatchableError, "WakuRelay protocol is not mounted, cannot mount Rln"
)
let rlnRelay = (await WakuRlnRelay.new(rlnConf, registrationHandler)).valueOr:
raise newException(CatchableError, "failed to mount WakuRlnRelay: " & error)
if (rlnConf.userMessageLimit > rlnRelay.groupManager.rlnRelayMaxMessageLimit):
let rln = (await Rln.new(rlnConf, registrationHandler)).valueOr:
raise newException(CatchableError, "failed to mount Rln: " & error)
if (rlnConf.userMessageLimit > rln.groupManager.rlnRelayMaxMessageLimit):
error "rln-relay-user-message-limit can't exceed the MAX_MESSAGE_LIMIT in the rln contract"
let validator = generateRlnValidator(rlnRelay, spamHandler)
let validator = generateRlnValidator(rln, spamHandler)
# register rln validator as default validator
info "Registering RLN validator"
node.wakuRelay.addValidator(validator, "RLN validation failed")
node.wakuRlnRelay = rlnRelay
node.rln = rln

View File

@ -13,7 +13,7 @@ import
import
../../../waku_node,
../../../waku_relay/protocol,
../../../waku_rln_relay,
../../../rln,
../../../node/waku_node,
../../message_cache,
../../handlers,
@ -167,11 +167,11 @@ proc installRelayApiHandlers*(
return RestApiResponse.badRequest($error)
# if RLN is mounted, append the proof to the message
if not node.wakuRlnRelay.isNil():
if not node.rln.isNil():
# append the proof to the message
message.proof = (
await node.wakuRlnRelay.generateRLNProof(
await node.rln.generateRLNProof(
message.toRLNSignal(), float64(getTime().toUnix())
)
).valueOr:
@ -186,8 +186,7 @@ proc installRelayApiHandlers*(
logMessageInfo(node.wakuRelay, "rest", pubsubTopic, "none", message, onRecv = true)
# if we reach here its either a non-RLN message or a RLN message with a valid proof
info "Publishing message",
pubSubTopic = pubSubTopic, rln = not node.wakuRlnRelay.isNil()
info "Publishing message", pubSubTopic = pubSubTopic, rln = not node.rln.isNil()
if not (waitFor node.publish(some(pubSubTopic), message).withTimeout(futTimeout)):
error "Failed to publish message to topic", pubSubTopic = pubSubTopic
return RestApiResponse.internalServerError("Failed to publish: timedout")
@ -299,9 +298,9 @@ proc installRelayApiHandlers*(
return RestApiResponse.badRequest("Failed to publish. " & msg)
# if RLN is mounted, append the proof to the message
if not node.wakuRlnRelay.isNil():
if not node.rln.isNil():
message.proof = (
await node.wakuRlnRelay.generateRLNProof(
await node.rln.generateRLNProof(
message.toRLNSignal(), float64(getTime().toUnix())
)
).valueOr:
@ -317,7 +316,7 @@ proc installRelayApiHandlers*(
# if we reach here its either a non-RLN message or a RLN message with a valid proof
info "Publishing message",
contentTopic = message.contentTopic, rln = not node.wakuRlnRelay.isNil()
contentTopic = message.contentTopic, rln = not node.rln.isNil()
var publishFut = node.publish(some($pubsubTopic), message)
if not await publishFut.withTimeout(futTimeout):

View File

@ -0,0 +1,3 @@
import ./rln/group_manager, ./rln/conversion_utils, ./rln/rln, ./rln/contract
export group_manager, conversion_utils, rln, contract

View File

@ -8,15 +8,15 @@ import
stew/byteutils,
libp2p/protocols/pubsub/pubsub
import ../rln_relay, ../protocol_types, ../protocol_metrics, ../conversion_utils
import ../rln, ../protocol_types, ../protocol_metrics, ../conversion_utils
import logos_delivery/waku/[waku_relay, waku_core]
logScope:
topics = "waku rln_relay adapter"
topics = "waku rln adapter"
proc generateRlnValidator*(
wakuRlnRelay: WakuRLNRelay, spamHandler = none(SpamHandler)
rln: Rln, spamHandler = none(SpamHandler)
): WakuValidatorHandler =
## Bridges RLN's protocol-agnostic message validation into a relay
## (gossipsub) validator. The core decision is made by
@ -28,14 +28,14 @@ proc generateRlnValidator*(
topic: string, message: WakuMessage
): Future[pubsub.ValidationResult] {.async.} =
trace "rln-relay topic validator is called"
wakuRlnRelay.clearNullifierLog()
rln.clearNullifierLog()
let msgProof = RateLimitProof.init(message.proof).valueOr:
trace "generateRlnValidator reject", error = error
return pubsub.ValidationResult.Reject
# validate the message and update log
let validationRes = await wakuRlnRelay.validateMessageAndUpdateLog(message)
let validationRes = await rln.validateMessageAndUpdateLog(message)
let
proof = byteutils.toHex(msgProof.proof)

View File

@ -0,0 +1,26 @@
{.push raises: [].}
import std/options, stint
import logos_delivery/waku/common/error_handling
type RlnCreds* {.requiresInit.} = object
path*: string
password*: string
type RlnConf* = object of RootObj
# TODO: severals parameters are only needed when it's dynamic
# change the config to either nest or use enum/type variant so it's obvious
# and then it can be set to `requiresInit`
dynamic*: bool
credIndex*: Option[uint]
ethContractAddress*: string
ethClientUrls*: seq[string]
chainId*: UInt256
creds*: Option[RlnCreds]
epochSizeSec*: uint64
userMessageLimit*: uint64
ethPrivateKey*: Option[string]
type WakuRlnConfig* = object of RlnConf
onFatalErrorAction*: OnFatalErrorHandler

View File

@ -23,7 +23,7 @@ const PathCheckMinInterval* = 30.seconds
const RlnCredentialsFilename* = "rlnCredentials.txt"
# inputs of the membership contract constructor
# TODO may be able to make these constants private and put them inside the waku_rln_relay_utils
# TODO may be able to make these constants private and put them inside the waku_rln_utils
const
# in wei
MembershipFee* = 0.u256

View File

@ -12,7 +12,7 @@ import ../waku_keystore
export web3, chronicles, stint, constants, endians2
logScope:
topics = "waku rln_relay conversion_utils"
topics = "waku rln conversion_utils"
proc inHex*(
value:

View File

@ -23,7 +23,7 @@ type GroupManager* = ref object of RootObj
membershipIndex*: Option[MembershipIndex]
registerCb*: Option[OnRegisterCallback]
withdrawCb*: Option[OnWithdrawCallback]
rlnInstance*: ptr RLN
rlnInstance*: ptr RlnRaw
initialized*: bool
latestIndex*: MembershipIndex
validRoots*: Deque[MerkleNode]

View File

@ -17,7 +17,7 @@ import
import
../../../waku_keystore,
../../rln,
../../bindings,
../../rln/rln_interface,
../../conversion_utils,
../group_manager_base,
@ -27,7 +27,7 @@ import
export group_manager_base
logScope:
topics = "waku rln_relay onchain_group_manager"
topics = "waku rln onchain_group_manager"
type
WakuRlnContractWithSender = Sender[WakuRlnContract]

View File

@ -18,7 +18,7 @@ import
../group_manager_base
logScope:
topics = "waku rln_relay onchain rpc_wrapper"
topics = "waku rln onchain rpc_wrapper"
# using the when predicate does not work within the contract macro, hence need to dupe
contract(WakuRlnContract):

View File

@ -0,0 +1,75 @@
{.push raises: [].}
import std/tables
import chronicles, results
import ./types, ./protocol_types, ./conversion_utils, ./proof
logScope:
topics = "waku rln nullifier_log"
proc hasDuplicate*(
rlnPeer: Rln, epoch: Epoch, proofMetadata: ProofMetadata
): RlnResult[bool] =
## 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
## Returns an error if it cannot check for duplicates
# check if the epoch exists
let nullifier = proofMetadata.nullifier
if not rlnPeer.nullifierLog.hasKey(epoch):
return ok(false)
try:
if rlnPeer.nullifierLog[epoch].hasKey(nullifier):
# there is an identical record, mark it as spam
return ok(true)
# there is no duplicate
return ok(false)
except KeyError:
return err("the epoch was not found: " & getCurrentExceptionMsg())
proc updateLog*(
rlnPeer: Rln, epoch: Epoch, proofMetadata: ProofMetadata
): RlnResult[void] =
## saves supplied proofMetadata `proofMetadata`
## in the `nullifierLog` of the `rlnPeer`
## Returns an error if it cannot update the log
# check if the epoch exists
if not rlnPeer.nullifierLog.hasKeyOrPut(
epoch, {proofMetadata.nullifier: proofMetadata}.toTable()
):
return ok()
try:
# check if an identical record exists
if rlnPeer.nullifierLog[epoch].hasKeyOrPut(proofMetadata.nullifier, proofMetadata):
# the above condition could be `discarded` but it is kept for clarity, that slashing will
# be implemented here
# TODO: slashing logic
return ok()
return ok()
except KeyError:
return
err("the epoch was not found: " & getCurrentExceptionMsg()) # should never happen
proc clearNullifierLog*(rlnPeer: Rln) =
# clear the first MaxEpochGap epochs of the nullifer log
# if more than MaxEpochGap epochs are in the log
let currentEpoch = fromEpoch(rlnPeer.getCurrentEpoch())
var epochsToRemove: seq[Epoch] = @[]
for epoch in rlnPeer.nullifierLog.keys():
let epochInt = fromEpoch(epoch)
# clean all epochs that are +- rlnMaxEpochGap from the current epoch
if (currentEpoch + rlnPeer.rlnMaxEpochGap) <= epochInt or
epochInt <= (currentEpoch - rlnPeer.rlnMaxEpochGap):
epochsToRemove.add(epoch)
for epochRemove in epochsToRemove:
trace "clearing epochs from the nullifier log",
currentEpoch = currentEpoch, cleanedEpoch = fromEpoch(epochRemove)
rlnPeer.nullifierLog.del(epochRemove)

View File

@ -0,0 +1,65 @@
{.push raises: [].}
import std/[times, sequtils]
import chronos, results, stew/byteutils
import ./types, ./protocol_types, ./conversion_utils, ./group_manager, ./nonce_manager
import logos_delivery/waku/waku_core
proc calcEpoch*(rlnPeer: Rln, t: float64): Epoch =
## gets time `t` as `flaot64` with subseconds resolution in the fractional part
## and returns its corresponding rln `Epoch` value
let e = uint64(t / rlnPeer.rlnEpochSizeSec.float64)
return toEpoch(e)
proc nextEpoch*(rlnPeer: Rln, time: float64): float64 =
let
currentEpoch = uint64(time / rlnPeer.rlnEpochSizeSec.float64)
nextEpochTime = float64(currentEpoch + 1) * rlnPeer.rlnEpochSizeSec.float64
currentTime = epochTime()
# Ensure we always return a future time
if nextEpochTime > currentTime:
return nextEpochTime
else:
return epochTime()
proc getCurrentEpoch*(rlnPeer: Rln): Epoch =
return rlnPeer.calcEpoch(epochTime())
proc absDiff*(e1, e2: Epoch): uint64 =
## returns the absolute difference between the two rln `Epoch`s `e1` and `e2`
## i.e., e1 - e2
# convert epochs to their corresponding unsigned numerical values
let
epoch1 = fromEpoch(e1)
epoch2 = fromEpoch(e2)
# Manually perform an `abs` calculation
if epoch1 > epoch2:
return epoch1 - epoch2
else:
return epoch2 - epoch1
proc toRLNSignal*(wakumessage: WakuMessage): seq[byte] =
## it is a utility proc that prepares the `data` parameter of the proof generation procedure i.e., `proofGen` that resides in the current module
## it extracts the `contentTopic`, `timestamp` and the `payload` of the supplied `wakumessage` and serializes them into a byte sequence
let
contentTopicBytes = toBytes(wakumessage.contentTopic)
timestampBytes = toBytes(wakumessage.timestamp.uint64)
output = concat(wakumessage.payload, contentTopicBytes, @(timestampBytes))
return output
proc generateRLNProof*(
rlnPeer: Rln, input: seq[byte], senderEpochTime: float64
): Future[RlnResult[seq[byte]]] {.async.} =
let epoch = rlnPeer.calcEpoch(senderEpochTime)
let nonce = rlnPeer.nonceManager.getNonce().valueOr:
return err("could not get new message id to generate an rln proof: " & $error)
let proof = (await rlnPeer.groupManager.generateProof(input, epoch, nonce)).valueOr:
return err("could not generate rln-v2 proof: " & $error)
return ok(proof.encode().buffer)

View File

@ -5,7 +5,7 @@ import chronicles, metrics, metrics/chronos_httpserver, ../utils/collector
export metrics
logScope:
topics = "waku rln_relay"
topics = "waku rln"
func generateBucketsForHistogram*(length: int): seq[float64] =
## Generate a custom set of 5 buckets for a given length

View File

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

View File

@ -18,75 +18,30 @@ import
import
./group_manager,
./rln,
./bindings,
./conversion_utils,
./constants,
./protocol_types,
./protocol_metrics,
./nonce_manager
./nonce_manager,
./types,
./config,
./proof,
./nullifier_log
import
logos_delivery/waku/
[common/error_handling, waku_core, requests/rln_requests, waku_keystore]
# Re-export the submodules so existing `import rln`
# (and `import rln/rln`) callers see the moved symbols
# (Rln, WakuRlnConfig, generateRLNProof, etc.).
export types, config, proof, nullifier_log
logScope:
topics = "waku rln_relay"
topics = "waku rln"
type RlnRelayCreds* {.requiresInit.} = object
path*: string
password*: string
type RlnRelayConf* = object of RootObj
# TODO: severals parameters are only needed when it's dynamic
# change the config to either nest or use enum/type variant so it's obvious
# and then it can be set to `requiresInit`
dynamic*: bool
credIndex*: Option[uint]
ethContractAddress*: string
ethClientUrls*: seq[string]
chainId*: UInt256
creds*: Option[RlnRelayCreds]
epochSizeSec*: uint64
userMessageLimit*: uint64
ethPrivateKey*: Option[string]
type WakuRlnConfig* = object of RlnRelayConf
onFatalErrorAction*: OnFatalErrorHandler
type WakuRLNRelay* = ref object of RootObj
# the log of nullifiers and Shamir shares of the past messages grouped per epoch
nullifierLog*: OrderedTable[Epoch, Table[Nullifier, ProofMetadata]]
lastEpoch*: Epoch # the epoch of the last published rln message
rlnEpochSizeSec*: uint64
rlnMaxTimestampGap*: uint64
rlnMaxEpochGap*: uint64
groupManager*: GroupManager
onFatalErrorAction*: OnFatalErrorHandler
nonceManager*: NonceManager
epochMonitorFuture*: Future[void]
rootChangesFuture*: Future[Result[void, string]]
brokerCtx*: BrokerContext
proc calcEpoch*(rlnPeer: WakuRLNRelay, t: float64): Epoch =
## gets time `t` as `flaot64` with subseconds resolution in the fractional part
## and returns its corresponding rln `Epoch` value
let e = uint64(t / rlnPeer.rlnEpochSizeSec.float64)
return toEpoch(e)
proc nextEpoch*(rlnPeer: WakuRLNRelay, time: float64): float64 =
let
currentEpoch = uint64(time / rlnPeer.rlnEpochSizeSec.float64)
nextEpochTime = float64(currentEpoch + 1) * rlnPeer.rlnEpochSizeSec.float64
currentTime = epochTime()
# Ensure we always return a future time
if nextEpochTime > currentTime:
return nextEpochTime
else:
return epochTime()
proc stop*(rlnPeer: WakuRLNRelay) {.async: (raises: [Exception]).} =
proc stop*(rlnPeer: Rln) {.async: (raises: [Exception]).} =
## stops the rln-relay protocol
## Throws an error if it cannot stop the rln-relay protocol
@ -95,83 +50,8 @@ proc stop*(rlnPeer: WakuRLNRelay) {.async: (raises: [Exception]).} =
RequestGenerateRlnProof.clearProvider(rlnPeer.brokerCtx)
await rlnPeer.groupManager.stop()
proc hasDuplicate*(
rlnPeer: WakuRLNRelay, epoch: Epoch, proofMetadata: ProofMetadata
): RlnRelayResult[bool] =
## 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
## Returns an error if it cannot check for duplicates
# check if the epoch exists
let nullifier = proofMetadata.nullifier
if not rlnPeer.nullifierLog.hasKey(epoch):
return ok(false)
try:
if rlnPeer.nullifierLog[epoch].hasKey(nullifier):
# there is an identical record, mark it as spam
return ok(true)
# there is no duplicate
return ok(false)
except KeyError:
return err("the epoch was not found: " & getCurrentExceptionMsg())
proc updateLog*(
rlnPeer: WakuRLNRelay, epoch: Epoch, proofMetadata: ProofMetadata
): RlnRelayResult[void] =
## saves supplied proofMetadata `proofMetadata`
## in the `nullifierLog` of the `rlnPeer`
## Returns an error if it cannot update the log
# check if the epoch exists
if not rlnPeer.nullifierLog.hasKeyOrPut(
epoch, {proofMetadata.nullifier: proofMetadata}.toTable()
):
return ok()
try:
# check if an identical record exists
if rlnPeer.nullifierLog[epoch].hasKeyOrPut(proofMetadata.nullifier, proofMetadata):
# the above condition could be `discarded` but it is kept for clarity, that slashing will
# be implemented here
# TODO: slashing logic
return ok()
return ok()
except KeyError:
return
err("the epoch was not found: " & getCurrentExceptionMsg()) # should never happen
proc getCurrentEpoch*(rlnPeer: WakuRLNRelay): Epoch =
return rlnPeer.calcEpoch(epochTime())
proc absDiff*(e1, e2: Epoch): uint64 =
## returns the absolute difference between the two rln `Epoch`s `e1` and `e2`
## i.e., e1 - e2
# convert epochs to their corresponding unsigned numerical values
let
epoch1 = fromEpoch(e1)
epoch2 = fromEpoch(e2)
# Manually perform an `abs` calculation
if epoch1 > epoch2:
return epoch1 - epoch2
else:
return epoch2 - epoch1
proc toRLNSignal*(wakumessage: WakuMessage): seq[byte] =
## it is a utility proc that prepares the `data` parameter of the proof generation procedure i.e., `proofGen` that resides in the current module
## it extracts the `contentTopic`, `timestamp` and the `payload` of the supplied `wakumessage` and serializes them into a byte sequence
let
contentTopicBytes = toBytes(wakumessage.contentTopic)
timestampBytes = toBytes(wakumessage.timestamp.uint64)
output = concat(wakumessage.payload, contentTopicBytes, @(timestampBytes))
return output
proc validateMessage*(
rlnPeer: WakuRLNRelay, msg: WakuMessage
rlnPeer: Rln, msg: WakuMessage
): Future[MessageValidationResult] {.async.} =
## validate the supplied `msg` based on the waku-rln-relay routing protocol i.e.,
## the `msg`'s epoch is within MaxEpochGap of the current epoch
@ -266,7 +146,7 @@ proc validateMessage*(
return MessageValidationResult.Valid
proc validateMessageAndUpdateLog*(
rlnPeer: WakuRLNRelay, msg: WakuMessage
rlnPeer: Rln, msg: WakuMessage
): Future[MessageValidationResult] {.async.} =
## validates the message and updates the log to prevent double messaging
## in future messages
@ -286,57 +166,28 @@ proc validateMessageAndUpdateLog*(
return isValidMessage
proc generateRLNProof*(
rlnPeer: WakuRLNRelay, input: seq[byte], senderEpochTime: float64
): Future[RlnRelayResult[seq[byte]]] {.async.} =
let epoch = rlnPeer.calcEpoch(senderEpochTime)
let nonce = rlnPeer.nonceManager.getNonce().valueOr:
return err("could not get new message id to generate an rln proof: " & $error)
let proof = (await rlnPeer.groupManager.generateProof(input, epoch, nonce)).valueOr:
return err("could not generate rln-v2 proof: " & $error)
return ok(proof.encode().buffer)
proc clearNullifierLog*(rlnPeer: WakuRlnRelay) =
# clear the first MaxEpochGap epochs of the nullifer log
# if more than MaxEpochGap epochs are in the log
let currentEpoch = fromEpoch(rlnPeer.getCurrentEpoch())
var epochsToRemove: seq[Epoch] = @[]
for epoch in rlnPeer.nullifierLog.keys():
let epochInt = fromEpoch(epoch)
# clean all epochs that are +- rlnMaxEpochGap from the current epoch
if (currentEpoch + rlnPeer.rlnMaxEpochGap) <= epochInt or
epochInt <= (currentEpoch - rlnPeer.rlnMaxEpochGap):
epochsToRemove.add(epoch)
for epochRemove in epochsToRemove:
trace "clearing epochs from the nullifier log",
currentEpoch = currentEpoch, cleanedEpoch = fromEpoch(epochRemove)
rlnPeer.nullifierLog.del(epochRemove)
proc monitorEpochs(wakuRlnRelay: WakuRLNRelay) {.async.} =
proc monitorEpochs(rln: Rln) {.async.} =
while true:
try:
if wakuRlnRelay.groupManager.userMessageLimit.isSome():
if rln.groupManager.userMessageLimit.isSome():
waku_rln_remaining_proofs_per_epoch.set(
wakuRlnRelay.groupManager.userMessageLimit.get().float64
rln.groupManager.userMessageLimit.get().float64
)
else:
error "userMessageLimit is not set in monitorEpochs"
except CatchableError:
error "Error in epoch monitoring", error = getCurrentExceptionMsg()
let nextEpochTime = wakuRlnRelay.nextEpoch(epochTime())
let nextEpochTime = rln.nextEpoch(epochTime())
let sleepDuration = int((nextEpochTime - epochTime()) * 1000)
await sleepAsync(sleepDuration)
proc mount(
conf: WakuRlnConfig, registrationHandler = none(RegistrationHandler)
): Future[RlnRelayResult[WakuRlnRelay]] {.async.} =
): Future[RlnResult[Rln]] {.async.} =
var
groupManager: GroupManager
wakuRlnRelay: WakuRLNRelay
rln: Rln
# create an RLN instance
let rlnInstance = createRLNInstance().valueOr:
return err("could not create RLN instance: " & $error)
@ -365,7 +216,7 @@ proc mount(
(await groupManager.init()).isOkOr:
return err("could not initialize the group manager: " & $error)
wakuRlnRelay = WakuRLNRelay(
rln = Rln(
groupManager: groupManager,
nonceManager: NonceManager.init(conf.userMessageLimit, conf.epochSizeSec.float),
rlnEpochSizeSec: conf.epochSizeSec,
@ -376,25 +227,23 @@ proc mount(
)
# Start epoch monitoring in the background
wakuRlnRelay.epochMonitorFuture = monitorEpochs(wakuRlnRelay)
rln.epochMonitorFuture = monitorEpochs(rln)
RequestGenerateRlnProof.setProvider(
wakuRlnRelay.brokerCtx,
rln.brokerCtx,
proc(
msg: WakuMessage, senderEpochTime: float64
): Future[Result[RequestGenerateRlnProof, string]] {.async.} =
let proof = (
await wakuRlnRelay.generateRLNProof(msg.toRLNSignal(), senderEpochTime)
).valueOr:
let proof = (await rln.generateRLNProof(msg.toRLNSignal(), senderEpochTime)).valueOr:
return err("Could not create RLN proof: " & error)
return ok(RequestGenerateRlnProof(proof: proof)),
).isOkOr:
return err("Proof generator provider cannot be set: " & $error)
return ok(wakuRlnRelay)
return ok(rln)
proc isReady*(rlnPeer: WakuRLNRelay): Future[bool] {.async.} =
proc isReady*(rlnPeer: Rln): Future[bool] {.async.} =
## returns true if the rln-relay protocol is ready to relay messages
## returns false otherwise
@ -409,10 +258,8 @@ proc isReady*(rlnPeer: WakuRLNRelay): Future[bool] {.async.} =
return false
proc new*(
T: type WakuRlnRelay,
conf: WakuRlnConfig,
registrationHandler = none(RegistrationHandler),
): Future[RlnRelayResult[WakuRlnRelay]] {.async.} =
T: type Rln, conf: WakuRlnConfig, registrationHandler = none(RegistrationHandler)
): Future[RlnResult[Rln]] {.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

@ -51,7 +51,7 @@ type
err*: Vec_uint8
CResultRLNPtrVecU8* = object
ok*: ptr RLN
ok*: ptr RlnRaw
err*: Vec_uint8
CResultCFrPtrVecU8* = object
@ -99,7 +99,7 @@ proc ffi_rln_new_with_params*(
zkey_data: ptr Vec_uint8, graph_data: ptr Vec_uint8
): CResultRLNPtrVecU8 {.importc: "ffi_rln_new_with_params", cdecl.}
proc ffi_rln_free*(rln: ptr RLN) {.importc: "ffi_rln_free", cdecl.}
proc ffi_rln_free*(rln: ptr RlnRaw) {.importc: "ffi_rln_free", cdecl.}
# --- Keygen ---------------------------------------------------------------
@ -143,15 +143,15 @@ proc ffi_rln_partial_witness_input_free*(
# pass `addr handle` where `handle` is `ptr T`.
proc ffi_generate_rln_proof*(
rln: ptr ptr RLN, witness: ptr ptr FFI_RLNWitnessInput
rln: ptr ptr RlnRaw, witness: ptr ptr FFI_RLNWitnessInput
): CResultProofPtrVecU8 {.importc: "ffi_generate_rln_proof", cdecl.}
proc ffi_generate_partial_zk_proof*(
rln: ptr ptr RLN, partial_witness: ptr ptr FFI_RLNPartialWitnessInput
rln: ptr ptr RlnRaw, partial_witness: ptr ptr FFI_RLNPartialWitnessInput
): CResultPartialProofPtrVecU8 {.importc: "ffi_generate_partial_zk_proof", cdecl.}
proc ffi_finish_rln_proof*(
rln: ptr ptr RLN,
rln: ptr ptr RlnRaw,
partial_proof: ptr ptr FFI_RLNPartialProof,
witness: ptr ptr FFI_RLNWitnessInput,
): CResultProofPtrVecU8 {.importc: "ffi_finish_rln_proof", cdecl.}
@ -159,7 +159,7 @@ proc ffi_finish_rln_proof*(
# --- Verification ---------------------------------------------------------
proc ffi_verify_with_roots*(
rln: ptr ptr RLN, proof: ptr ptr FFI_RLNProof, roots: ptr Vec_CFr, x: ptr CFr
rln: ptr ptr RlnRaw, proof: ptr ptr FFI_RLNProof, roots: ptr Vec_CFr, x: ptr CFr
): CBoolResult {.importc: "ffi_verify_with_roots", cdecl.}
# --- Proof serialization --------------------------------------------------
@ -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]): RlnRelayResult[array[32, byte]] =
proc seqToFixed32*(data: openArray[byte]): RlnResult[array[32, byte]] =
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): RlnRelayResult[array[32, byte]] =
proc cfrToBytesLe*(cfr: ptr CFr): RlnResult[array[32, byte]] =
let bytes = ffi_cfr_to_bytes_le(cfr)
defer:
ffi_vec_u8_free(bytes)
@ -333,7 +333,7 @@ proc cfrToBytesLe*(cfr: ptr CFr): RlnRelayResult[array[32, byte]] =
return err("Invalid field byte length: " & $bytes.len)
seqToFixed32(vecToSeq(bytes))
proc bytesToCfrLe*(data: openArray[byte]): RlnRelayResult[ptr CFr] =
proc bytesToCfrLe*(data: openArray[byte]): RlnResult[ptr CFr] =
## 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]): RlnRelayResult[ptr CFr] =
proc cfrResultToBytes*(
res: CResultCFrPtrVecU8, prefix: string
): RlnRelayResult[array[32, byte]] =
): RlnResult[array[32, byte]] =
## 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]): RlnRelayResult[ptr CFr] =
proc hashToFieldLe*(data: openArray[byte]): RlnResult[ptr CFr] =
## 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]): RlnRelayResult[ptr CFr] =
return err("Failed to hash to field")
ok(cfr)
proc poseidonPairLe*(a, b: openArray[byte]): RlnRelayResult[array[32, byte]] =
proc poseidonPairLe*(a, b: openArray[byte]): RlnResult[array[32, byte]] =
## 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

@ -7,14 +7,14 @@ import ../../waku_core, ../../waku_keystore
{.push raises: [], gcsafe.}
logScope:
topics = "waku rln_relay ffi"
topics = "waku rln ffi"
# Forward decl; body defined below.
proc generateExternalNullifier*(
epoch: Epoch, rlnIdentifier: RlnIdentifier
): RlnRelayResult[ExternalNullifier]
): RlnResult[ExternalNullifier]
proc toRootVec(validRoots: seq[MerkleNode]): RlnRelayResult[Vec_CFr] =
proc toRootVec(validRoots: seq[MerkleNode]): RlnResult[Vec_CFr] =
## 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]): RlnRelayResult[Vec_CFr] =
proc proofPtrToRateLimitProof(
proofPtr: ptr FFI_RLNProof, epoch: Epoch, rlnIdentifier: RlnIdentifier
): RlnRelayResult[RateLimitProof] =
): RlnResult[RateLimitProof] =
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): RlnRelayResult[IdentityCredential] =
proc parseCredentialVec(vec: var Vec_CFr): RlnResult[IdentityCredential] =
## 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): RlnRelayResult[IdentityCredential] =
)
)
proc membershipKeyGen*(): RlnRelayResult[IdentityCredential] =
proc membershipKeyGen*(): RlnResult[IdentityCredential] =
var vec = ffi_extended_key_gen()
defer:
ffi_vec_cfr_free(vec)
parseCredentialVec(vec)
proc createRLNInstanceLocal(): RLNResult =
proc createRLNInstanceLocal(): RlnInstanceResult =
## Creates a stateless RLN instance (no local Merkle tree).
let res = ffi_rln_new()
if res.ok.isNil():
@ -135,18 +135,18 @@ proc createRLNInstanceLocal(): RLNResult =
return err(msg)
ok(res.ok)
proc createRLNInstance*(): RLNResult =
proc createRLNInstance*(): RlnInstanceResult =
## Wraps createRLNInstanceLocal with metrics timing.
var res: RLNResult
var res: RlnInstanceResult
waku_rln_instance_creation_duration_seconds.nanosecondTime:
res = createRLNInstanceLocal()
return res
proc poseidon*(left, right: seq[byte]): RlnRelayResult[array[32, byte]] =
proc poseidon*(left, right: seq[byte]): RlnResult[array[32, byte]] =
## Poseidon hash of exactly 2 inputs; zerokit v2 FFI only exposes the pair variant.
poseidonPairLe(left, right)
proc toLeaf*(rateCommitment: RateCommitment): RlnRelayResult[seq[byte]] =
proc toLeaf*(rateCommitment: RateCommitment): RlnResult[seq[byte]] =
let idCommitment = rateCommitment.idCommitment
var userMessageLimit: array[32, byte]
try:
@ -164,7 +164,7 @@ proc toLeaf*(rateCommitment: RateCommitment): RlnRelayResult[seq[byte]] =
retLeaf[i] = leaf[i]
return ok(retLeaf)
proc toLeaves*(rateCommitments: seq[RateCommitment]): RlnRelayResult[seq[seq[byte]]] =
proc toLeaves*(rateCommitments: seq[RateCommitment]): RlnResult[seq[seq[byte]]] =
var leaves = newSeq[seq[byte]]()
for rateCommitment in rateCommitments:
let leaf = toLeaf(rateCommitment).valueOr:
@ -174,7 +174,7 @@ proc toLeaves*(rateCommitments: seq[RateCommitment]): RlnRelayResult[seq[seq[byt
proc generateExternalNullifier*(
epoch: Epoch, rlnIdentifier: RlnIdentifier
): RlnRelayResult[ExternalNullifier] =
): RlnResult[ExternalNullifier] =
## 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): RlnRelayResult[ProofMetadata] =
proc extractMetadata*(proof: RateLimitProof): RlnResult[ProofMetadata] =
let externalNullifier = generateExternalNullifier(proof.epoch, proof.rlnIdentifier).valueOr:
return err("Failed to compute external nullifier: " & error)
return ok(
@ -206,9 +206,7 @@ proc extractMetadata*(proof: RateLimitProof): RlnRelayResult[ProofMetadata] =
)
)
proc buildPathElementsVec(
pathElements: seq[byte], depth: int
): RlnRelayResult[Vec_CFr] =
proc buildPathElementsVec(pathElements: seq[byte], depth: int): RlnResult[Vec_CFr] =
## Caller MUST ffi_vec_cfr_free the returned Vec_CFr.
var vec = ffi_vec_cfr_new(csize_t(depth))
for i in 0 ..< depth:
@ -224,9 +222,7 @@ proc buildPathElementsVec(
ffi_cfr_free(element)
ok(vec)
proc buildWitnessInput(
witness: RLNWitnessInput
): RlnRelayResult[ptr FFI_RLNWitnessInput] =
proc buildWitnessInput(witness: RLNWitnessInput): RlnResult[ptr FFI_RLNWitnessInput] =
## 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,11 +283,11 @@ proc buildWitnessInput(
return ok(witnessRes.ok)
proc generateRlnProofWithWitness*(
rlnInstance: ptr RLN,
rlnInstance: ptr RlnRaw,
witness: RLNWitnessInput,
epoch: Epoch,
rlnIdentifier: RlnIdentifier,
): RlnRelayResult[RateLimitProof] =
): RlnResult[RateLimitProof] =
let witnessHandle = buildWitnessInput(witness).valueOr:
return
err("failed call to buildWitnessInput in generateRlnProofWithWitness: " & error)
@ -310,7 +306,7 @@ proc generateRlnProofWithWitness*(
proc buildRlnProof(
proof: RateLimitProof, externalNullifier: ExternalNullifier
): RlnRelayResult[ptr FFI_RLNProof] =
): RlnResult[ptr FFI_RLNProof] =
## 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,11 +341,11 @@ proc buildRlnProof(
return ok(proofRes.ok)
proc verifyRlnProof*(
rlnInstance: ptr RLN,
rlnInstance: ptr RlnRaw,
proof: RateLimitProof,
signal: openArray[byte],
validRoots: seq[MerkleNode],
): RlnRelayResult[bool] =
): RlnResult[bool] =
if validRoots.len == 0:
return err("verifyRlnProof requires at least one valid root (stateless mode)")

View File

@ -0,0 +1,22 @@
{.push raises: [].}
import std/tables, chronos, results
import brokers/broker_context
import ./group_manager, ./nonce_manager, ./protocol_types
import logos_delivery/waku/common/error_handling
type Rln* = ref object of RootObj
# the log of nullifiers and Shamir shares of the past messages grouped per epoch
nullifierLog*: OrderedTable[Epoch, Table[Nullifier, ProofMetadata]]
lastEpoch*: Epoch # the epoch of the last published rln message
rlnEpochSizeSec*: uint64
rlnMaxTimestampGap*: uint64
rlnMaxEpochGap*: uint64
groupManager*: GroupManager
onFatalErrorAction*: OnFatalErrorHandler
nonceManager*: NonceManager
epochMonitorFuture*: Future[void]
rootChangesFuture*: Future[Result[void, string]]
brokerCtx*: BrokerContext

View File

@ -26,7 +26,7 @@ import
waku_core,
waku_node,
waku_archive,
waku_rln_relay,
rln,
waku_store,
waku_filter_v2,
waku_relay/protocol,

View File

@ -77,7 +77,7 @@ proc toIdentityCredentials*(
proc serialize*(idComms: seq[IDCommitment]): seq[byte] =
## serializes a seq of IDCommitments to a byte seq
## the serialization is based on https://github.com/status-im/nwaku/blob/37bd29fbc37ce5cf636734e7dd410b1ed27b88c8/waku/v2/protocol/waku_rln_relay/rln.nim#L142
## the serialization is based on https://github.com/status-im/nwaku/blob/37bd29fbc37ce5cf636734e7dd410b1ed27b88c8/waku/v2/protocol/waku_rln/rln.nim#L142
## the order of serialization is |id_commitment_len<8>|id_commitment<var>|
var idCommsBytes = newSeq[byte]()

View File

@ -3,17 +3,12 @@ import logos_delivery/waku/compat/option_valueor
import results
import
../waku_core,
../waku_relay,
./common,
../waku_rln_relay,
../waku_rln_relay/protocol_types
import ../waku_core, ../waku_relay, ./common, ../rln, ../rln/protocol_types
import std/times, libp2p/peerid, stew/byteutils
proc checkAndGenerateRLNProof*(
rlnPeer: Option[WakuRLNRelay], message: WakuMessage
rlnPeer: Option[Rln], message: WakuMessage
): Future[Result[WakuMessage, string]] {.async.} =
# check if the message already has RLN proof
if message.proof.len > 0:
@ -40,7 +35,7 @@ proc getNilPushHandler*(): PushMessageHandler =
return lightpushResultInternalError("no waku relay found")
proc getRelayPushHandler*(
wakuRelay: WakuRelay, rlnPeer: Option[WakuRLNRelay] = none[WakuRLNRelay]()
wakuRelay: WakuRelay, rlnPeer: Option[Rln] = none[Rln]()
): PushMessageHandler =
return proc(
pubsubTopic: string, message: WakuMessage

View File

@ -5,13 +5,13 @@ import
../waku_relay,
./common,
./protocol_metrics,
../waku_rln_relay,
../waku_rln_relay/protocol_types
../rln,
../rln/protocol_types
import std/times, libp2p/peerid, stew/byteutils
proc checkAndGenerateRLNProof*(
rlnPeer: Option[WakuRLNRelay], message: WakuMessage
rlnPeer: Option[Rln], message: WakuMessage
): Future[Result[WakuMessage, string]] {.async.} =
# check if the message already has RLN proof
if message.proof.len > 0:
@ -38,7 +38,7 @@ proc getNilPushHandler*(): PushMessageHandler =
return err("no waku relay found")
proc getRelayPushHandler*(
wakuRelay: WakuRelay, rlnPeer: Option[WakuRLNRelay] = none[WakuRLNRelay]()
wakuRelay: WakuRelay, rlnPeer: Option[Rln] = none[Rln]()
): PushMessageHandler =
return proc(
pubsubTopic: string, message: WakuMessage

View File

@ -1,7 +0,0 @@
import
./waku_rln_relay/group_manager,
./waku_rln_relay/conversion_utils,
./waku_rln_relay/rln_relay,
./waku_rln_relay/contract
export group_manager, conversion_utils, rln_relay, contract

View File

@ -15,7 +15,7 @@ import
waku_lightpush_legacy,
waku_lightpush_legacy/common,
waku_lightpush_legacy/protocol_metrics,
waku_rln_relay,
rln,
],
../testlib/[wakucore, wakunode, testasync, futures, testutils],
../resources/payloads,
@ -132,7 +132,7 @@ suite "RLN Proofs as a Lightpush Service":
check (await server.mountLegacyLightPush()).isOk()
client.mountLegacyLightPushClient()
let manager1 = cast[OnchainGroupManager](server.wakuRlnRelay.groupManager)
let manager1 = cast[OnchainGroupManager](server.rln.groupManager)
let idCredentials1 = generateCredentials()
(waitFor manager1.register(idCredentials1, UserMessageLimit(20))).isOkOr:

View File

@ -8,8 +8,7 @@ import
libp2p/crypto/crypto
import
logos_delivery/waku/
[waku_core, node/peer_manager, waku_node, waku_lightpush, waku_rln_relay],
logos_delivery/waku/[waku_core, node/peer_manager, waku_node, waku_lightpush, rln],
../testlib/[wakucore, wakunode, testasync, futures],
../resources/payloads,
../waku_rln_relay/[rln/waku_rln_relay_utils, utils_onchain]
@ -130,7 +129,7 @@ suite "RLN Proofs as a Lightpush Service":
check (await server.mountLightPush()).isOk()
client.mountLightPushClient()
let manager1 = cast[OnchainGroupManager](server.wakuRlnRelay.groupManager)
let manager1 = cast[OnchainGroupManager](server.rln.groupManager)
let idCredentials1 = generateCredentials()
(waitFor manager1.register(idCredentials1, UserMessageLimit(20))).isOkOr:

View File

@ -17,9 +17,9 @@ import
waku_core,
waku_node,
common/error_handling,
waku_rln_relay,
waku_rln_relay/rln,
waku_rln_relay/protocol_types,
rln,
rln/bindings,
rln/protocol_types,
waku_keystore/keystore,
],
../waku_store/store_utils,
@ -85,8 +85,8 @@ proc getWakuRlnConfigOnChain*(
ethClientAddress: ethClientAddress.get(EthClient),
epochSizeSec: 1,
onFatalErrorAction: fatalErrorHandler.get(fatalErrorVoidHandler),
# If these are used, initialisation fails with "failed to mount WakuRlnRelay: could not initialize the group manager: the commitment does not have a membership"
creds: some(RlnRelayCreds(path: keystorePath, password: password)),
# If these are used, initialisation fails with "failed to mount Rln: could not initialize the group manager: the commitment does not have a membership"
creds: some(RlnCreds(path: keystorePath, password: password)),
)
proc setupRelayWithOnChainRln*(
@ -132,7 +132,7 @@ suite "Waku RlnRelay - End to End - Static":
# Given Relay and RLN are not mounted
check:
server.wakuRelay == nil
server.wakuRlnRelay == nil
server.rln == nil
# When RlnRelay is mounted
let catchRes = catch:
@ -141,9 +141,8 @@ suite "Waku RlnRelay - End to End - Static":
# Then Relay and RLN are not mounted,and the process fails
check:
server.wakuRelay == nil
server.wakuRlnRelay == nil
catchRes.error()[].msg ==
"WakuRelay protocol is not mounted, cannot mount WakuRlnRelay"
server.rln == nil
catchRes.error()[].msg == "WakuRelay protocol is not mounted, cannot mount Rln"
asyncTest "Pubsub topics subscribed before mounting RlnRelay are added to it":
# Given the node enables Relay and Rln while subscribing to a pubsub topic
@ -151,9 +150,9 @@ suite "Waku RlnRelay - End to End - Static":
await client.setupRelayWithStaticRln(2.uint, @[pubsubTopic])
check:
server.wakuRelay != nil
server.wakuRlnRelay != nil
server.rln != nil
client.wakuRelay != nil
client.wakuRlnRelay != nil
client.rln != nil
# And the nodes are connected
await client.connectToNodes(@[serverRemotePeerInfo])
@ -236,7 +235,7 @@ suite "Waku RlnRelay - End to End - Static":
await node.mountRlnRelay(wakuRlnConfig)
except CatchableError as e:
check e.msg ==
"failed to mount WakuRlnRelay: rln-relay-user-message-limit can't exceed the MAX_MESSAGE_LIMIT in the rln contract"
"failed to mount Rln: rln-relay-user-message-limit can't exceed the MAX_MESSAGE_LIMIT in the rln contract"
suite "Analysis of Bandwith Limitations":
asyncTest "Valid Payload Sizes":
@ -278,30 +277,27 @@ suite "Waku RlnRelay - End to End - Static":
WakuMessage(payload: @payload150kibPlus, contentTopic: contentTopic)
message1b.proof = (
await client.wakuRlnRelay.generateRLNProof(
message1b.toRLNSignal(),
epoch + float64(client.wakuRlnRelay.rlnEpochSizeSec * 0),
await client.rln.generateRLNProof(
message1b.toRLNSignal(), epoch + float64(client.rln.rlnEpochSizeSec * 0)
)
).valueOr:
raiseAssert "generateRLNProof failed: " & error
message1kib.proof = (
await client.wakuRlnRelay.generateRLNProof(
message1kib.toRLNSignal(),
epoch + float64(client.wakuRlnRelay.rlnEpochSizeSec * 1),
await client.rln.generateRLNProof(
message1kib.toRLNSignal(), epoch + float64(client.rln.rlnEpochSizeSec * 1)
)
).valueOr:
raiseAssert "generateRLNProof failed: " & error
message150kib.proof = (
await client.wakuRlnRelay.generateRLNProof(
message150kib.toRLNSignal(),
epoch + float64(client.wakuRlnRelay.rlnEpochSizeSec * 2),
await client.rln.generateRLNProof(
message150kib.toRLNSignal(), epoch + float64(client.rln.rlnEpochSizeSec * 2)
)
).valueOr:
raiseAssert "generateRLNProof failed: " & error
message151kibPlus.proof = (
await client.wakuRlnRelay.generateRLNProof(
await client.rln.generateRLNProof(
message151kibPlus.toRLNSignal(),
epoch + float64(client.wakuRlnRelay.rlnEpochSizeSec * 3),
epoch + float64(client.rln.rlnEpochSizeSec * 3),
)
).valueOr:
raiseAssert "generateRLNProof failed: " & error
@ -367,9 +363,9 @@ suite "Waku RlnRelay - End to End - Static":
WakuMessage(payload: @payload150kibPlus, contentTopic: contentTopic)
message151kibPlus.proof = (
await client.wakuRlnRelay.generateRLNProof(
await client.rln.generateRLNProof(
message151kibPlus.toRLNSignal(),
epoch + float64(client.wakuRlnRelay.rlnEpochSizeSec * 3),
epoch + float64(client.rln.rlnEpochSizeSec * 3),
)
).valueOr:
raiseAssert "generateRLNProof failed: " & error
@ -576,14 +572,14 @@ suite "Waku RlnRelay - End to End - OnChain":
await client.setupRelayWithOnChainRln(@[pubsubTopic], wakuRlnConfig2)
try:
(await server.wakuRlnRelay.groupManager.startGroupSync()).isOkOr:
(await server.rln.groupManager.startGroupSync()).isOkOr:
raiseAssert $error
(await client.wakuRlnRelay.groupManager.startGroupSync()).isOkOr:
(await client.rln.groupManager.startGroupSync()).isOkOr:
raiseAssert $error
# Test Hack: Monkeypatch the idCredentials into the groupManager
server.wakuRlnRelay.groupManager.idCredentials = some(idCredential1)
client.wakuRlnRelay.groupManager.idCredentials = some(idCredential2)
server.rln.groupManager.idCredentials = some(idCredential1)
client.rln.groupManager.idCredentials = some(idCredential2)
except Exception, CatchableError:
assert false, "exception raised: " & getCurrentExceptionMsg()
@ -657,14 +653,14 @@ suite "Waku RlnRelay - End to End - OnChain":
await client.setupRelayWithOnChainRln(@[pubsubTopic], wakuRlnConfig2)
try:
(await server.wakuRlnRelay.groupManager.startGroupSync()).isOkOr:
(await server.rln.groupManager.startGroupSync()).isOkOr:
raiseAssert $error
(await client.wakuRlnRelay.groupManager.startGroupSync()).isOkOr:
(await client.rln.groupManager.startGroupSync()).isOkOr:
raiseAssert $error
# Test Hack: Monkeypatch the idCredentials into the groupManager
echo server.wakuRlnRelay.groupManager.idCredentials
echo client.wakuRlnRelay.groupManager.idCredentials
echo server.rln.groupManager.idCredentials
echo client.rln.groupManager.idCredentials
except Exception, CatchableError:
assert false, "exception raised: " & getCurrentExceptionMsg()

View File

@ -3,9 +3,7 @@
import stint
import
logos_delivery/waku/
[waku_keystore/protocol_types, waku_rln_relay, waku_rln_relay/protocol_types]
import logos_delivery/waku/[waku_keystore/protocol_types, rln, rln/protocol_types]
func fromStrToBytesLe*(v: string): seq[byte] =
try:

View File

@ -13,9 +13,8 @@ import brokers/broker_context
from std/times import epochTime
import
logos_delivery/waku/[
waku_relay, node/waku_node, node/peer_manager, waku_core, waku_node, waku_rln_relay
],
logos_delivery/waku/
[waku_relay, node/waku_node, node/peer_manager, waku_core, waku_node, rln],
../waku_store/store_utils,
../waku_archive/archive_utils,
../testlib/[wakucore, futures]
@ -78,7 +77,7 @@ proc sendRlnMessage*(
): Future[bool] {.async.} =
var message = WakuMessage(payload: payload, contentTopic: contentTopic)
message.proof = (
await client.wakuRlnRelay.generateRLNProof(message.toRLNSignal(), epochTime())
await client.rln.generateRLNProof(message.toRLNSignal(), epochTime())
).valueOr:
raiseAssert "generateRLNProof failed: " & error
discard await client.publish(some(pubsubTopic), message)
@ -93,10 +92,10 @@ proc sendRlnMessageWithInvalidProof*(
payload: seq[byte] = "Hello".toBytes(),
): Future[bool] {.async.} =
let extraBytes: seq[byte] = @[byte(1), 2, 3]
let rateLimitProofRes = await client.wakuRlnRelay.groupManager.generateProof(
let rateLimitProofRes = await client.rln.groupManager.generateProof(
concat(payload, extraBytes),
# we add extra bytes to invalidate proof verification against original payload
client.wakuRlnRelay.getCurrentEpoch(),
client.rln.getCurrentEpoch(),
messageId = MessageId(0),
)
let

View File

@ -1,7 +1,7 @@
import testutils/unittests, results
import logos_delivery/waku/waku_rln_relay/rln/rln_interface
import logos_delivery/waku/waku_rln_relay/rln/wrappers
import logos_delivery/waku/rln/rln/rln_interface
import logos_delivery/waku/rln/rln/wrappers
suite "Vec_uint8":
suite "toVecUint8":

View File

@ -1,8 +1,8 @@
import testutils/unittests, results
import
logos_delivery/waku/waku_rln_relay/rln,
logos_delivery/waku/waku_rln_relay/rln/wrappers,
logos_delivery/waku/rln/bindings,
logos_delivery/waku/rln/rln/wrappers,
./waku_rln_relay_utils
suite "membershipKeyGen":

View File

@ -2,18 +2,18 @@ import std/options
import std/tempfiles
import
logos_delivery/waku/waku_rln_relay,
logos_delivery/waku/waku_rln_relay/[
group_manager, rln, conversion_utils, constants, protocol_types, protocol_metrics,
nonce_manager,
logos_delivery/waku/rln,
logos_delivery/waku/rln/[
group_manager, bindings, conversion_utils, constants, protocol_types,
protocol_metrics, nonce_manager,
]
proc createRLNInstanceWrapper*(): RLNResult =
proc createRLNInstanceWrapper*(): RlnInstanceResult =
return createRlnInstance()
proc unsafeAppendRLNProof*(
rlnPeer: WakuRLNRelay, msg: var WakuMessage, epoch: Epoch, messageId: MessageId
): RlnRelayResult[void] =
rlnPeer: Rln, msg: var WakuMessage, epoch: Epoch, messageId: MessageId
): RlnResult[void] =
## 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

@ -5,11 +5,8 @@
import std/[options, os], results, testutils/unittests, chronos, web3
import
logos_delivery/waku/[
waku_rln_relay,
waku_rln_relay/conversion_utils,
waku_rln_relay/group_manager/on_chain/group_manager,
],
logos_delivery/waku/
[rln, rln/conversion_utils, rln/group_manager/on_chain/group_manager],
./utils_onchain
suite "Token and RLN Contract Deployment":

View File

@ -18,13 +18,13 @@ import
import
logos_delivery/waku/[
waku_rln_relay,
waku_rln_relay/protocol_types,
waku_rln_relay/protocol_metrics,
waku_rln_relay/constants,
waku_rln_relay/rln,
waku_rln_relay/conversion_utils,
waku_rln_relay/group_manager/on_chain/group_manager,
rln,
rln/protocol_types,
rln/protocol_metrics,
rln/constants,
rln/bindings,
rln/conversion_utils,
rln/group_manager/on_chain/group_manager,
],
../testlib/wakucore,
./utils_onchain

View File

@ -1,7 +1,7 @@
{.used.}
import testutils/unittests, chronos, os
import logos_delivery/waku/waku_rln_relay/nonce_manager
import logos_delivery/waku/rln/nonce_manager
suite "Nonce manager":
test "should initialize successfully":

View File

@ -12,13 +12,8 @@ import
import brokers/broker_context
import
logos_delivery/waku/[
waku_core,
waku_rln_relay,
waku_rln_relay/rln,
waku_rln_relay/protocol_metrics,
waku_keystore,
],
logos_delivery/waku/
[waku_core, rln, rln/bindings, rln/protocol_metrics, waku_keystore],
./rln/waku_rln_relay_utils,
./utils_onchain,
../testlib/[wakucore, futures, wakunode, testutils]
@ -159,8 +154,8 @@ suite "Waku rln relay":
test "updateLog and hasDuplicate tests":
let
wakuRlnRelay = WakuRLNRelay()
epoch = wakuRlnRelay.getCurrentEpoch()
rln = Rln()
epoch = rln.getCurrentEpoch()
# create some dummy nullifiers and secret shares
var nullifier1: Nullifier
@ -205,25 +200,23 @@ suite "Waku rln relay":
# check whether hasDuplicate correctly finds records with the same nullifiers but different secret shares
# no duplicate for proof1 should be found, since the log is empty
let proofMetadata1 = proof1.extractMetadata().tryGet()
let isDuplicate1 = wakuRlnRelay.hasDuplicate(epoch, proofMetadata1).valueOr:
let isDuplicate1 = rln.hasDuplicate(epoch, proofMetadata1).valueOr:
raiseAssert $error
assert isDuplicate1 == false, "no duplicate should be found"
# add it to the log
discard wakuRlnRelay.updateLog(epoch, proofMetadata1)
discard rln.updateLog(epoch, proofMetadata1)
# no duplicate for proof2 should be found, its nullifier differs from proof1
let proofMetadata2 = proof2.extractMetadata().tryGet()
let isDuplicate2 = wakuRlnRelay.hasDuplicate(epoch, proofMetadata2).valueOr:
let isDuplicate2 = rln.hasDuplicate(epoch, proofMetadata2).valueOr:
raiseAssert $error
# no duplicate is found
assert isDuplicate2 == false, "no duplicate should be found"
# add it to the log
discard wakuRlnRelay.updateLog(epoch, proofMetadata2)
discard rln.updateLog(epoch, proofMetadata2)
# proof3 has the same nullifier as proof1 but different secret shares, it should be detected as duplicate
let isDuplicate3 = wakuRlnRelay.hasDuplicate(
epoch, proof3.extractMetadata().tryGet()
).valueOr:
let isDuplicate3 = rln.hasDuplicate(epoch, proof3.extractMetadata().tryGet()).valueOr:
raiseAssert $error
# it is a duplicate
assert isDuplicate3, "duplicate should be found"
@ -232,18 +225,18 @@ suite "Waku rln relay":
let index = MembershipIndex(5)
let wakuRlnConfig = getWakuRlnConfig(manager = manager, index = index)
var wakuRlnRelay: WakuRlnRelay
var rln: Rln
lockNewGlobalBrokerContext:
wakuRlnRelay = (await WakuRlnRelay.new(wakuRlnConfig)).valueOr:
rln = (await Rln.new(wakuRlnConfig)).valueOr:
raiseAssert $error
let manager = cast[OnchainGroupManager](wakuRlnRelay.groupManager)
let manager = cast[OnchainGroupManager](rln.groupManager)
let idCredentials = generateCredentials()
(waitFor manager.register(idCredentials, UserMessageLimit(20))).isOkOr:
assert false, "error returned when calling register: " & error
let epoch1 = wakuRlnRelay.getCurrentEpoch()
let epoch1 = rln.getCurrentEpoch()
# Create messages from the same peer and append RLN proof to them (except wm4)
var
@ -252,7 +245,7 @@ suite "Waku rln relay":
wm2 = WakuMessage(payload: "Spam message".toBytes(), timestamp: now())
await sleepAsync(1.seconds)
let epoch2 = wakuRlnRelay.getCurrentEpoch()
let epoch2 = rln.getCurrentEpoch()
var
# wm3 points to the next epoch due to the sleep
@ -260,22 +253,22 @@ suite "Waku rln relay":
wm4 = WakuMessage(payload: "Invalid message".toBytes(), timestamp: now())
# Append RLN proofs
wakuRlnRelay.unsafeAppendRLNProof(wm1, epoch1, MessageId(1)).isOkOr:
rln.unsafeAppendRLNProof(wm1, epoch1, MessageId(1)).isOkOr:
raiseAssert $error
wakuRlnRelay.unsafeAppendRLNProof(wm2, epoch1, MessageId(1)).isOkOr:
rln.unsafeAppendRLNProof(wm2, epoch1, MessageId(1)).isOkOr:
raiseAssert $error
wakuRlnRelay.unsafeAppendRLNProof(wm3, epoch2, MessageId(3)).isOkOr:
rln.unsafeAppendRLNProof(wm3, epoch2, MessageId(3)).isOkOr:
raiseAssert $error
# Validate messages
let
msgValidate1 = await wakuRlnRelay.validateMessageAndUpdateLog(wm1)
msgValidate1 = await rln.validateMessageAndUpdateLog(wm1)
# wm2 is within the same epoch as wm1 → should be spam
msgValidate2 = await wakuRlnRelay.validateMessageAndUpdateLog(wm2)
msgValidate2 = await rln.validateMessageAndUpdateLog(wm2)
# wm3 is in the next epoch → should be valid
msgValidate3 = await wakuRlnRelay.validateMessageAndUpdateLog(wm3)
msgValidate3 = await rln.validateMessageAndUpdateLog(wm3)
# wm4 has no RLN proof → should be invalid
msgValidate4 = await wakuRlnRelay.validateMessageAndUpdateLog(wm4)
msgValidate4 = await rln.validateMessageAndUpdateLog(wm4)
check:
msgValidate1 == MessageValidationResult.Valid
@ -288,21 +281,21 @@ suite "Waku rln relay":
let wakuRlnConfig = getWakuRlnConfig(manager = manager, index = index)
var wakuRlnRelay: WakuRlnRelay
var rln: Rln
lockNewGlobalBrokerContext:
wakuRlnRelay = (await WakuRlnRelay.new(wakuRlnConfig)).valueOr:
rln = (await Rln.new(wakuRlnConfig)).valueOr:
raiseAssert $error
let manager = cast[OnchainGroupManager](wakuRlnRelay.groupManager)
let manager = cast[OnchainGroupManager](rln.groupManager)
let idCredentials = generateCredentials()
(waitFor manager.register(idCredentials, UserMessageLimit(20))).isOkOr:
assert false, "error returned when calling register: " & error
# usually it's 20 seconds but we set it to 1 for testing purposes which make the test faster
wakuRlnRelay.rlnMaxTimestampGap = 1
rln.rlnMaxTimestampGap = 1
var epoch = wakuRlnRelay.getCurrentEpoch()
var epoch = rln.getCurrentEpoch()
var
wm1 = WakuMessage(
@ -316,19 +309,19 @@ suite "Waku rln relay":
timestamp: now(),
)
wakuRlnRelay.unsafeAppendRLNProof(wm1, epoch, MessageId(1)).isOkOr:
rln.unsafeAppendRLNProof(wm1, epoch, MessageId(1)).isOkOr:
raiseAssert $error
wakuRlnRelay.unsafeAppendRLNProof(wm2, epoch, MessageId(2)).isOkOr:
rln.unsafeAppendRLNProof(wm2, epoch, MessageId(2)).isOkOr:
raiseAssert $error
# validate the first message because it's timestamp is the same as the generated timestamp
let msgValidate1 = await wakuRlnRelay.validateMessageAndUpdateLog(wm1)
let msgValidate1 = await rln.validateMessageAndUpdateLog(wm1)
# wait for 2 seconds to make the timestamp different from generated timestamp
await sleepAsync(2.seconds)
let msgValidate2 = await wakuRlnRelay.validateMessageAndUpdateLog(wm2)
let msgValidate2 = await rln.validateMessageAndUpdateLog(wm2)
check:
msgValidate1 == MessageValidationResult.Valid
@ -337,9 +330,9 @@ suite "Waku rln relay":
asyncTest "multiple senders with same external nullifier":
let index1 = MembershipIndex(5)
let rlnConf1 = getWakuRlnConfig(manager = manager, index = index1)
var wakuRlnRelay1: WakuRlnRelay
var wakuRlnRelay1: Rln
lockNewGlobalBrokerContext:
wakuRlnRelay1 = (await WakuRlnRelay.new(rlnConf1)).valueOr:
wakuRlnRelay1 = (await Rln.new(rlnConf1)).valueOr:
raiseAssert "failed to create waku rln relay: " & $error
let manager1 = cast[OnchainGroupManager](wakuRlnRelay1.groupManager)
@ -350,9 +343,9 @@ suite "Waku rln relay":
let index2 = MembershipIndex(6)
let rlnConf2 = getWakuRlnConfig(manager = manager, index = index2)
var wakuRlnRelay2: WakuRlnRelay
var wakuRlnRelay2: Rln
lockNewGlobalBrokerContext:
wakuRlnRelay2 = (await WakuRlnRelay.new(rlnConf2)).valueOr:
wakuRlnRelay2 = (await Rln.new(rlnConf2)).valueOr:
raiseAssert "failed to create waku rln relay: " & $error
let manager2 = cast[OnchainGroupManager](wakuRlnRelay2.groupManager)
@ -481,31 +474,31 @@ suite "Waku rln relay":
let wakuRlnConfig = getWakuRlnConfig(
manager = manager, index = index, epochSizeSec = rlnEpochSizeSec.uint64
)
var wakuRlnRelay: WakuRlnRelay
var rln: Rln
lockNewGlobalBrokerContext:
wakuRlnRelay = (await WakuRlnRelay.new(wakuRlnConfig)).valueOr:
rln = (await Rln.new(wakuRlnConfig)).valueOr:
raiseAssert $error
let rlnMaxEpochGap = wakuRlnRelay.rlnMaxEpochGap
let rlnMaxEpochGap = rln.rlnMaxEpochGap
let testProofMetadata = default(ProofMetadata)
let testProofMetadataTable =
{testProofMetadata.nullifier: testProofMetadata}.toTable()
for i in 0 .. rlnMaxEpochGap:
# we add epochs to the nullifierLog
let testEpoch = wakuRlnRelay.calcEpoch(epochTime() + float(rlnEpochSizeSec * i))
wakuRlnRelay.nullifierLog[testEpoch] = testProofMetadataTable
let testEpoch = rln.calcEpoch(epochTime() + float(rlnEpochSizeSec * i))
rln.nullifierLog[testEpoch] = testProofMetadataTable
check:
wakuRlnRelay.nullifierLog.len().uint == i + 1
rln.nullifierLog.len().uint == i + 1
check:
wakuRlnRelay.nullifierLog.len().uint == rlnMaxEpochGap + 1
rln.nullifierLog.len().uint == rlnMaxEpochGap + 1
# clearing it now will remove 1 epoch
wakuRlnRelay.clearNullifierLog()
rln.clearNullifierLog()
check:
wakuRlnRelay.nullifierLog.len().uint == rlnMaxEpochGap
rln.nullifierLog.len().uint == rlnMaxEpochGap
var testEpochSizes: seq[uint] = @[1, 5, 10, 30, 60, 600]
for i in testEpochSizes:

View File

@ -11,7 +11,7 @@ import
brokers/broker_context
import
logos_delivery/waku/[waku_core, waku_node, waku_rln_relay],
logos_delivery/waku/[waku_core, waku_node, rln],
../testlib/[wakucore, futures, wakunode, testutils],
./utils_onchain,
./rln/waku_rln_relay_utils
@ -21,7 +21,7 @@ from std/times import epochTime
proc waitForNullifierLog(node: WakuNode, expectedLen: int): Future[bool] {.async.} =
## Helper function
for i in 0 .. 100: # Try for up to 50 seconds (100 * 500ms)
if node.wakuRlnRelay.nullifierLog.len() == expectedLen:
if node.rln.nullifierLog.len() == expectedLen:
return true
await sleepAsync(500.millis)
return false
@ -56,7 +56,7 @@ procSuite "WakuNode - RLN relay":
await node1.start()
# Registration is mandatory before sending messages with rln-relay
let manager1 = cast[OnchainGroupManager](node1.wakuRlnRelay.groupManager)
let manager1 = cast[OnchainGroupManager](node1.rln.groupManager)
let idCredentials1 = generateCredentials()
(waitFor manager1.register(idCredentials1, UserMessageLimit(20))).isOkOr:
@ -79,7 +79,7 @@ procSuite "WakuNode - RLN relay":
await node2.mountRlnRelay(wakuRlnConfig2)
await node2.start()
let manager2 = cast[OnchainGroupManager](node2.wakuRlnRelay.groupManager)
let manager2 = cast[OnchainGroupManager](node2.rln.groupManager)
let rootUpdated2 = waitFor manager2.updateRoots()
info "Updated root for node2", rootUpdated2
@ -97,7 +97,7 @@ procSuite "WakuNode - RLN relay":
await node3.mountRlnRelay(wakuRlnConfig3)
await node3.start()
let manager3 = cast[OnchainGroupManager](node3.wakuRlnRelay.groupManager)
let manager3 = cast[OnchainGroupManager](node3.rln.groupManager)
let rootUpdated3 = waitFor manager3.updateRoots()
info "Updated root for node3", rootUpdated3
@ -135,10 +135,8 @@ procSuite "WakuNode - RLN relay":
var message =
WakuMessage(payload: @payload, contentTopic: contentTopic, timestamp: now())
doAssert(
node1.wakuRlnRelay
.unsafeAppendRLNProof(
message, node1.wakuRlnRelay.getCurrentEpoch(), MessageId(0)
)
node1.rln
.unsafeAppendRLNProof(message, node1.rln.getCurrentEpoch(), MessageId(0))
.isOk()
)
@ -169,7 +167,7 @@ procSuite "WakuNode - RLN relay":
getWakuRlnConfig(manager = manager, index = MembershipIndex(1))
await node1.mountRlnRelay(wakuRlnConfig1)
await node1.start()
let manager1 = cast[OnchainGroupManager](node1.wakuRlnRelay.groupManager)
let manager1 = cast[OnchainGroupManager](node1.rln.groupManager)
let idCredentials1 = generateCredentials()
(waitFor manager1.register(idCredentials1, UserMessageLimit(20))).isOkOr:
@ -186,7 +184,7 @@ procSuite "WakuNode - RLN relay":
getWakuRlnConfig(manager = manager, index = MembershipIndex(2))
await node2.mountRlnRelay(wakuRlnConfig2)
await node2.start()
let manager2 = cast[OnchainGroupManager](node2.wakuRlnRelay.groupManager)
let manager2 = cast[OnchainGroupManager](node2.rln.groupManager)
let idCredentials2 = generateCredentials()
(waitFor manager2.register(idCredentials2, UserMessageLimit(20))).isOkOr:
@ -203,7 +201,7 @@ procSuite "WakuNode - RLN relay":
getWakuRlnConfig(manager = manager, index = MembershipIndex(3))
await node3.mountRlnRelay(wakuRlnConfig3)
await node3.start()
let manager3 = cast[OnchainGroupManager](node3.wakuRlnRelay.groupManager)
let manager3 = cast[OnchainGroupManager](node3.rln.groupManager)
let idCredentials3 = generateCredentials()
(waitFor manager3.register(idCredentials3, UserMessageLimit(20))).isOkOr:
@ -264,8 +262,8 @@ procSuite "WakuNode - RLN relay":
contentTopic: contentTopics[0],
)
node1.wakuRlnRelay.unsafeAppendRLNProof(
message, node1.wakuRlnRelay.getCurrentEpoch(), MessageId(i.uint8)
node1.rln.unsafeAppendRLNProof(
message, node1.rln.getCurrentEpoch(), MessageId(i.uint8)
).isOkOr:
raiseAssert $error
messages1.add(message)
@ -277,8 +275,8 @@ procSuite "WakuNode - RLN relay":
contentTopic: contentTopics[1],
)
node2.wakuRlnRelay.unsafeAppendRLNProof(
message, node2.wakuRlnRelay.getCurrentEpoch(), MessageId(i.uint8)
node2.rln.unsafeAppendRLNProof(
message, node2.rln.getCurrentEpoch(), MessageId(i.uint8)
).isOkOr:
raiseAssert $error
messages2.add(message)
@ -320,7 +318,7 @@ procSuite "WakuNode - RLN relay":
await node1.mountRlnRelay(wakuRlnConfig1)
await node1.start()
let manager1 = cast[OnchainGroupManager](node1.wakuRlnRelay.groupManager)
let manager1 = cast[OnchainGroupManager](node1.rln.groupManager)
let idCredentials1 = generateCredentials()
(waitFor manager1.register(idCredentials1, UserMessageLimit(20))).isOkOr:
@ -341,7 +339,7 @@ procSuite "WakuNode - RLN relay":
await node2.mountRlnRelay(wakuRlnConfig2)
await node2.start()
let manager2 = cast[OnchainGroupManager](node2.wakuRlnRelay.groupManager)
let manager2 = cast[OnchainGroupManager](node2.rln.groupManager)
let rootUpdated2 = waitFor manager2.updateRoots()
info "Updated root for node2", rootUpdated2
lockNewGlobalBrokerContext:
@ -357,7 +355,7 @@ procSuite "WakuNode - RLN relay":
await node3.mountRlnRelay(wakuRlnConfig3)
await node3.start()
let manager3 = cast[OnchainGroupManager](node3.wakuRlnRelay.groupManager)
let manager3 = cast[OnchainGroupManager](node3.rln.groupManager)
let rootUpdated3 = waitFor manager3.updateRoots()
info "Updated root for node3", rootUpdated3
@ -392,12 +390,12 @@ procSuite "WakuNode - RLN relay":
# prepare the message payload
let payload = "valid".toBytes()
# prepare the epoch
let epoch = node1.wakuRlnRelay.getCurrentEpoch()
let epoch = node1.rln.getCurrentEpoch()
var message =
WakuMessage(payload: @payload, contentTopic: DefaultPubsubTopic, timestamp: now())
node1.wakuRlnRelay.unsafeAppendRLNProof(message, epoch, MessageId(0)).isOkOr:
node1.rln.unsafeAppendRLNProof(message, epoch, MessageId(0)).isOkOr:
assert false, "Failed to append rln proof: " & $error
# message.payload = "Invalid".toBytes()
@ -432,7 +430,7 @@ procSuite "WakuNode - RLN relay":
await node1.start()
# Registration is mandatory before sending messages with rln-relay
let manager1 = cast[OnchainGroupManager](node1.wakuRlnRelay.groupManager)
let manager1 = cast[OnchainGroupManager](node1.rln.groupManager)
let idCredentials1 = generateCredentials()
(waitFor manager1.register(idCredentials1, UserMessageLimit(20))).isOkOr:
@ -455,7 +453,7 @@ procSuite "WakuNode - RLN relay":
await node2.start()
# Registration is mandatory before sending messages with rln-relay
let manager2 = cast[OnchainGroupManager](node2.wakuRlnRelay.groupManager)
let manager2 = cast[OnchainGroupManager](node2.rln.groupManager)
let rootUpdated2 = waitFor manager2.updateRoots()
info "Updated root for node2", rootUpdated2
lockNewGlobalBrokerContext:
@ -473,7 +471,7 @@ procSuite "WakuNode - RLN relay":
await node3.start()
# Registration is mandatory before sending messages with rln-relay
let manager3 = cast[OnchainGroupManager](node3.wakuRlnRelay.groupManager)
let manager3 = cast[OnchainGroupManager](node3.rln.groupManager)
let rootUpdated3 = waitFor manager3.updateRoots()
info "Updated root for node3", rootUpdated3
@ -482,7 +480,7 @@ procSuite "WakuNode - RLN relay":
await node3.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()])
# get the current epoch time
let epoch_1 = node1.wakuRlnRelay.getCurrentEpoch()
let epoch_1 = node1.rln.getCurrentEpoch()
# create some messages with rate limit proofs
var
@ -500,7 +498,7 @@ procSuite "WakuNode - RLN relay":
# wm3 points to the next epoch
await sleepAsync(1000.millis)
let epoch_2 = node1.wakuRlnRelay.getCurrentEpoch()
let epoch_2 = node1.rln.getCurrentEpoch()
var
wm3 = WakuMessage(
@ -514,12 +512,12 @@ procSuite "WakuNode - RLN relay":
contentTopic: DefaultPubsubTopic,
)
node1.wakuRlnRelay.unsafeAppendRLNProof(wm1, epoch_1, MessageId(0)).isOkOr:
node1.rln.unsafeAppendRLNProof(wm1, epoch_1, MessageId(0)).isOkOr:
raiseAssert $error
node1.wakuRlnRelay.unsafeAppendRLNProof(wm2, epoch_1, MessageId(0)).isOkOr:
node1.rln.unsafeAppendRLNProof(wm2, epoch_1, MessageId(0)).isOkOr:
raiseAssert $error
node1.wakuRlnRelay.unsafeAppendRLNProof(wm3, epoch_2, MessageId(2)).isOkOr:
node1.rln.unsafeAppendRLNProof(wm3, epoch_2, MessageId(2)).isOkOr:
raiseAssert $error
# relay handler for node3
@ -601,7 +599,7 @@ procSuite "WakuNode - RLN relay":
await node1.start()
# Registration is mandatory before sending messages with rln-relay
let manager1 = cast[OnchainGroupManager](node1.wakuRlnRelay.groupManager)
let manager1 = cast[OnchainGroupManager](node1.rln.groupManager)
let idCredentials1 = generateCredentials()
(waitFor manager1.register(idCredentials1, UserMessageLimit(20))).isOkOr:
@ -620,7 +618,7 @@ procSuite "WakuNode - RLN relay":
await node2.start()
# Registration is mandatory before sending messages with rln-relay
let manager2 = cast[OnchainGroupManager](node2.wakuRlnRelay.groupManager)
let manager2 = cast[OnchainGroupManager](node2.rln.groupManager)
let rootUpdated2 = waitFor manager2.updateRoots()
info "Updated root for node2", rootUpdated2
@ -673,26 +671,22 @@ procSuite "WakuNode - RLN relay":
# Given all messages have an rln proof and are published by the node 1
let publishSleepDuration: Duration = 5000.millis
let epoch_1 = node1.wakuRlnRelay.calcEpoch(epochTime().float64)
let epoch_2 = node1.wakuRlnRelay.calcEpoch(
epochTime().float64 + node1.wakuRlnRelay.rlnEpochSizeSec.float64 * 1
)
let epoch_3 = node1.wakuRlnRelay.calcEpoch(
epochTime().float64 + node1.wakuRlnRelay.rlnEpochSizeSec.float64 * 2
)
let epoch_4 = node1.wakuRlnRelay.calcEpoch(
epochTime().float64 + node1.wakuRlnRelay.rlnEpochSizeSec.float64 * 3
)
let epoch_5 = node1.wakuRlnRelay.calcEpoch(
epochTime().float64 + node1.wakuRlnRelay.rlnEpochSizeSec.float64 * 4
)
let epoch_1 = node1.rln.calcEpoch(epochTime().float64)
let epoch_2 =
node1.rln.calcEpoch(epochTime().float64 + node1.rln.rlnEpochSizeSec.float64 * 1)
let epoch_3 =
node1.rln.calcEpoch(epochTime().float64 + node1.rln.rlnEpochSizeSec.float64 * 2)
let epoch_4 =
node1.rln.calcEpoch(epochTime().float64 + node1.rln.rlnEpochSizeSec.float64 * 3)
let epoch_5 =
node1.rln.calcEpoch(epochTime().float64 + node1.rln.rlnEpochSizeSec.float64 * 4)
# Epoch 1
node1.wakuRlnRelay.unsafeAppendRLNProof(wm1, epoch_1, MessageId(0)).isOkOr:
node1.rln.unsafeAppendRLNProof(wm1, epoch_1, MessageId(0)).isOkOr:
raiseAssert $error
# Message wm2 is published in the same epoch as wm1, so it'll be considered spam
node1.wakuRlnRelay.unsafeAppendRLNProof(wm2, epoch_1, MessageId(0)).isOkOr:
node1.rln.unsafeAppendRLNProof(wm2, epoch_1, MessageId(0)).isOkOr:
raiseAssert $error
discard await node1.publish(some(DefaultPubsubTopic), wm1)
@ -704,7 +698,7 @@ procSuite "WakuNode - RLN relay":
# Epoch 2
node1.wakuRlnRelay.unsafeAppendRLNProof(wm3, epoch_2, MessageId(0)).isOkOr:
node1.rln.unsafeAppendRLNProof(wm3, epoch_2, MessageId(0)).isOkOr:
raiseAssert $error
discard await node1.publish(some(DefaultPubsubTopic), wm3)
@ -716,7 +710,7 @@ procSuite "WakuNode - RLN relay":
await node2.waitForNullifierLog(2)
# Epoch 3
node1.wakuRlnRelay.unsafeAppendRLNProof(wm4, epoch_3, MessageId(0)).isOkOr:
node1.rln.unsafeAppendRLNProof(wm4, epoch_3, MessageId(0)).isOkOr:
raiseAssert $error
discard await node1.publish(some(DefaultPubsubTopic), wm4)
@ -726,7 +720,7 @@ procSuite "WakuNode - RLN relay":
await node2.waitForNullifierLog(3)
# Epoch 4
node1.wakuRlnRelay.unsafeAppendRLNProof(wm5, epoch_4, MessageId(0)).isOkOr:
node1.rln.unsafeAppendRLNProof(wm5, epoch_4, MessageId(0)).isOkOr:
raiseAssert $error
discard await node1.publish(some(DefaultPubsubTopic), wm5)
@ -736,7 +730,7 @@ procSuite "WakuNode - RLN relay":
await node2.waitForNullifierLog(4)
# Epoch 5
node1.wakuRlnRelay.unsafeAppendRLNProof(wm6, epoch_5, MessageId(0)).isOkOr:
node1.rln.unsafeAppendRLNProof(wm6, epoch_5, MessageId(0)).isOkOr:
raiseAssert $error
discard await node1.publish(some(DefaultPubsubTopic), wm6)

View File

@ -12,7 +12,7 @@ from std/times import epochTime
import
../../../logos_delivery/waku/
[node/waku_node, node/peer_manager, waku_core, waku_node, waku_rln_relay],
[node/waku_node, node/peer_manager, waku_core, waku_node, rln],
../waku_store/store_utils,
../waku_archive/archive_utils,
../testlib/[wakucore, futures, assertions]
@ -55,7 +55,7 @@ proc sendRlnMessage*(
): Future[bool] {.async.} =
var message = WakuMessage(payload: payload, contentTopic: contentTopic)
message.proof = (
await client.wakuRlnRelay.generateRLNProof(message.toRLNSignal(), epochTime())
await client.rln.generateRLNProof(message.toRLNSignal(), epochTime())
).valueOr:
raiseAssert "generateRLNProof failed: " & error
discard await client.publish(some(pubsubTopic), message)
@ -70,10 +70,10 @@ proc sendRlnMessageWithInvalidProof*(
payload: seq[byte] = "Hello".toBytes(),
): Future[bool] {.async.} =
let extraBytes: seq[byte] = @[byte(1), 2, 3]
let rateLimitProofRes = await client.wakuRlnRelay.groupManager.generateProof(
let rateLimitProofRes = await client.rln.groupManager.generateProof(
concat(payload, extraBytes),
# we add extra bytes to invalidate proof verification against original payload
client.wakuRlnRelay.getCurrentEpoch(),
client.rln.getCurrentEpoch(),
)
let
rateLimitProof = rateLimitProofRes.get().encode().buffer

View File

@ -20,12 +20,7 @@ import
results
import
logos_delivery/waku/[
waku_rln_relay,
waku_rln_relay/protocol_types,
waku_rln_relay/constants,
waku_rln_relay/rln,
],
logos_delivery/waku/[rln, rln/protocol_types, rln/constants, rln/bindings],
../testlib/common
const CHAIN_ID* = 1234'u256
@ -42,7 +37,7 @@ proc generateCredentials*(): IdentityCredential =
proc getRateCommitment*(
idCredential: IdentityCredential, userMessageLimit: UserMessageLimit
): RlnRelayResult[RawRateCommitment] =
): RlnResult[RawRateCommitment] =
return RateCommitment(
idCommitment: idCredential.idCommitment, userMessageLimit: userMessageLimit
).toLeaf()

View File

@ -19,7 +19,7 @@ import
rest_api/endpoint/responses,
rest_api/endpoint/health/handlers as health_rest_interface,
rest_api/endpoint/health/client as health_rest_client,
waku_rln_relay,
rln,
node/health_monitor,
],
../testlib/common,

View File

@ -21,7 +21,7 @@ import
rest_api/endpoint/relay/handlers as relay_rest_interface,
rest_api/endpoint/relay/client as relay_rest_client,
waku_relay,
waku_rln_relay,
rln,
],
../testlib/wakucore,
../testlib/wakunode,
@ -264,7 +264,7 @@ suite "Waku v2 Rest API - Relay":
await node.mountRlnRelay(wakuRlnConfig)
await node.start()
# Registration is mandatory before sending messages with rln-relay
let manager = cast[OnchainGroupManager](node.wakuRlnRelay.groupManager)
let manager = cast[OnchainGroupManager](node.rln.groupManager)
let idCredentials = generateCredentials()
(waitFor manager.register(idCredentials, UserMessageLimit(20))).isOkOr:
@ -535,7 +535,7 @@ suite "Waku v2 Rest API - Relay":
await node.connectToNodes(@[meshNode.peerInfo.toRemotePeerInfo()])
# Registration is mandatory before sending messages with rln-relay
let manager = cast[OnchainGroupManager](node.wakuRlnRelay.groupManager)
let manager = cast[OnchainGroupManager](node.rln.groupManager)
let idCredentials = generateCredentials()
(waitFor manager.register(idCredentials, UserMessageLimit(20))).isOkOr:
@ -604,7 +604,7 @@ suite "Waku v2 Rest API - Relay":
await node.start()
# Registration is mandatory before sending messages with rln-relay
let manager = cast[OnchainGroupManager](node.wakuRlnRelay.groupManager)
let manager = cast[OnchainGroupManager](node.rln.groupManager)
let idCredentials = generateCredentials()
(waitFor manager.register(idCredentials, UserMessageLimit(20))).isOkOr:
@ -663,7 +663,7 @@ suite "Waku v2 Rest API - Relay":
await node.start()
# Registration is mandatory before sending messages with rln-relay
let manager = cast[OnchainGroupManager](node.wakuRlnRelay.groupManager)
let manager = cast[OnchainGroupManager](node.rln.groupManager)
let idCredentials = generateCredentials()
(waitFor manager.register(idCredentials, UserMessageLimit(20))).isOkOr:
@ -735,7 +735,7 @@ suite "Waku v2 Rest API - Relay":
await node.start()
# Registration is mandatory before sending messages with rln-relay
let manager = cast[OnchainGroupManager](node.wakuRlnRelay.groupManager)
let manager = cast[OnchainGroupManager](node.rln.groupManager)
let idCredentials = generateCredentials()
(waitFor manager.register(idCredentials, UserMessageLimit(20))).isOkOr:

View File

@ -6,12 +6,8 @@ else:
import chronicles, results, std/[tempfiles, sequtils]
import
logos_delivery/waku/[
waku_keystore,
waku_rln_relay/rln,
waku_rln_relay/conversion_utils,
waku_rln_relay/group_manager/on_chain,
]
logos_delivery/waku/
[waku_keystore, rln/bindings, rln/conversion_utils, rln/group_manager/on_chain]
logScope:
topics = "rln_keystore_generator"