2022-09-06 20:43:46 +02:00
|
|
|
|
{.used.}
|
|
|
|
|
|
|
|
|
|
|
|
import
|
2025-09-10 16:18:51 +05:30
|
|
|
|
std/[options, os, sequtils, tempfiles, strutils, osproc],
|
2022-09-06 20:43:46 +02:00
|
|
|
|
stew/byteutils,
|
|
|
|
|
|
testutils/unittests,
|
2022-11-04 10:52:08 +01:00
|
|
|
|
chronicles,
|
|
|
|
|
|
chronos,
|
2022-09-06 20:43:46 +02:00
|
|
|
|
libp2p/switch,
|
2023-09-06 13:48:02 +05:30
|
|
|
|
libp2p/protocols/pubsub/pubsub
|
2022-09-06 20:43:46 +02:00
|
|
|
|
import
|
2024-07-06 03:33:38 +05:30
|
|
|
|
waku/[waku_core, waku_node, waku_rln_relay],
|
2024-10-07 18:02:06 +03:00
|
|
|
|
../testlib/[wakucore, futures, wakunode, testutils],
|
2025-09-10 16:18:51 +05:30
|
|
|
|
./utils_onchain,
|
2024-03-12 16:20:30 +05:30
|
|
|
|
./rln/waku_rln_relay_utils
|
2022-09-06 20:43:46 +02:00
|
|
|
|
|
|
|
|
|
|
from std/times import epochTime
|
|
|
|
|
|
|
2025-01-06 13:47:17 +01:00
|
|
|
|
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:
|
|
|
|
|
|
return true
|
|
|
|
|
|
await sleepAsync(500.millis)
|
|
|
|
|
|
return false
|
|
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
procSuite "WakuNode - RLN relay":
|
2024-03-12 16:20:30 +05:30
|
|
|
|
# NOTE: we set the rlnRelayUserMessageLimit to 1 to make the tests easier to reason about
|
2025-09-10 16:18:51 +05:30
|
|
|
|
var anvilProc {.threadVar.}: Process
|
|
|
|
|
|
var manager {.threadVar.}: OnchainGroupManager
|
|
|
|
|
|
|
|
|
|
|
|
setup:
|
|
|
|
|
|
anvilProc = runAnvil()
|
|
|
|
|
|
manager = waitFor setupOnchainGroupManager()
|
|
|
|
|
|
|
|
|
|
|
|
teardown:
|
|
|
|
|
|
stopAnvil(anvilProc)
|
|
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
asyncTest "testing rln-relay with valid proof":
|
|
|
|
|
|
let
|
|
|
|
|
|
# publisher node
|
2023-02-13 11:43:49 +01:00
|
|
|
|
nodeKey1 = generateSecp256k1Key()
|
2023-12-14 07:16:39 +01:00
|
|
|
|
node1 = newTestWakuNode(nodeKey1, parseIpAddress("0.0.0.0"), Port(0))
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# Relay node
|
2023-02-13 11:43:49 +01:00
|
|
|
|
nodeKey2 = generateSecp256k1Key()
|
2023-12-14 07:16:39 +01:00
|
|
|
|
node2 = newTestWakuNode(nodeKey2, parseIpAddress("0.0.0.0"), Port(0))
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# Subscriber
|
2023-02-13 11:43:49 +01:00
|
|
|
|
nodeKey3 = generateSecp256k1Key()
|
2023-12-14 07:16:39 +01:00
|
|
|
|
node3 = newTestWakuNode(nodeKey3, parseIpAddress("0.0.0.0"), Port(0))
|
2022-09-06 20:43:46 +02:00
|
|
|
|
|
|
|
|
|
|
contentTopic = ContentTopic("/waku/2/default-content/proto")
|
|
|
|
|
|
|
|
|
|
|
|
# set up three nodes
|
|
|
|
|
|
# node1
|
2025-06-02 22:02:49 +02:00
|
|
|
|
(await node1.mountRelay()).isOkOr:
|
2025-05-05 22:57:20 +02:00
|
|
|
|
assert false, "Failed to mount relay"
|
2022-11-04 08:30:42 +05:30
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# mount rlnrelay in off-chain mode
|
2025-09-26 14:47:15 +05:30
|
|
|
|
let wakuRlnConfig1 = getWakuRlnConfig(manager = manager, index = MembershipIndex(1))
|
2024-06-20 15:05:21 +05:30
|
|
|
|
|
2024-03-12 16:20:30 +05:30
|
|
|
|
await node1.mountRlnRelay(wakuRlnConfig1)
|
2022-09-06 20:43:46 +02:00
|
|
|
|
await node1.start()
|
|
|
|
|
|
|
2025-09-10 16:18:51 +05:30
|
|
|
|
# Registration is mandatory before sending messages with rln-relay
|
|
|
|
|
|
let manager1 = cast[OnchainGroupManager](node1.wakuRlnRelay.groupManager)
|
|
|
|
|
|
let idCredentials1 = generateCredentials(manager1.rlnInstance)
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
waitFor manager1.register(idCredentials1, UserMessageLimit(20))
|
|
|
|
|
|
except Exception, CatchableError:
|
|
|
|
|
|
assert false,
|
|
|
|
|
|
"exception raised when calling register: " & getCurrentExceptionMsg()
|
|
|
|
|
|
|
|
|
|
|
|
let rootUpdated1 = waitFor manager1.updateRoots()
|
2025-10-15 10:49:36 +02:00
|
|
|
|
info "Updated root for node1", rootUpdated1
|
2025-09-10 16:18:51 +05:30
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# node 2
|
2025-06-02 22:02:49 +02:00
|
|
|
|
(await node2.mountRelay()).isOkOr:
|
2025-05-05 22:57:20 +02:00
|
|
|
|
assert false, "Failed to mount relay"
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# mount rlnrelay in off-chain mode
|
2025-09-26 14:47:15 +05:30
|
|
|
|
let wakuRlnConfig2 = getWakuRlnConfig(manager = manager, index = MembershipIndex(2))
|
2024-06-20 15:05:21 +05:30
|
|
|
|
|
2024-03-12 16:20:30 +05:30
|
|
|
|
await node2.mountRlnRelay(wakuRlnConfig2)
|
2022-09-06 20:43:46 +02:00
|
|
|
|
await node2.start()
|
|
|
|
|
|
|
2025-09-10 16:18:51 +05:30
|
|
|
|
let manager2 = cast[OnchainGroupManager](node2.wakuRlnRelay.groupManager)
|
|
|
|
|
|
let rootUpdated2 = waitFor manager2.updateRoots()
|
2025-10-15 10:49:36 +02:00
|
|
|
|
info "Updated root for node2", rootUpdated2
|
2025-09-10 16:18:51 +05:30
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# node 3
|
2025-06-02 22:02:49 +02:00
|
|
|
|
(await node3.mountRelay()).isOkOr:
|
2025-05-05 22:57:20 +02:00
|
|
|
|
assert false, "Failed to mount relay"
|
2022-11-04 08:30:42 +05:30
|
|
|
|
|
2025-09-26 14:47:15 +05:30
|
|
|
|
let wakuRlnConfig3 = getWakuRlnConfig(manager = manager, index = MembershipIndex(3))
|
2024-06-20 15:05:21 +05:30
|
|
|
|
|
2024-03-12 16:20:30 +05:30
|
|
|
|
await node3.mountRlnRelay(wakuRlnConfig3)
|
2022-09-06 20:43:46 +02:00
|
|
|
|
await node3.start()
|
|
|
|
|
|
|
2025-09-10 16:18:51 +05:30
|
|
|
|
let manager3 = cast[OnchainGroupManager](node3.wakuRlnRelay.groupManager)
|
|
|
|
|
|
let rootUpdated3 = waitFor manager3.updateRoots()
|
2025-10-15 10:49:36 +02:00
|
|
|
|
info "Updated root for node3", rootUpdated3
|
2025-09-10 16:18:51 +05:30
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# connect them together
|
|
|
|
|
|
await node1.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()])
|
|
|
|
|
|
await node3.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()])
|
|
|
|
|
|
|
|
|
|
|
|
var completionFut = newFuture[bool]()
|
2024-03-16 00:08:47 +01:00
|
|
|
|
proc relayHandler(
|
|
|
|
|
|
topic: PubsubTopic, msg: WakuMessage
|
|
|
|
|
|
): Future[void] {.async, gcsafe.} =
|
2025-10-15 10:49:36 +02:00
|
|
|
|
info "The received topic:", topic
|
2023-08-21 08:55:34 +02:00
|
|
|
|
if topic == DefaultPubsubTopic:
|
2023-06-06 19:28:47 +02:00
|
|
|
|
completionFut.complete(true)
|
2022-09-06 20:43:46 +02:00
|
|
|
|
|
2025-06-02 22:02:49 +02:00
|
|
|
|
proc simpleHandler(
|
|
|
|
|
|
topic: PubsubTopic, msg: WakuMessage
|
|
|
|
|
|
): Future[void] {.async, gcsafe.} =
|
|
|
|
|
|
await sleepAsync(0.milliseconds)
|
|
|
|
|
|
|
|
|
|
|
|
node1.subscribe((kind: PubsubSub, topic: DefaultPubsubTopic), simpleHandler).isOkOr:
|
|
|
|
|
|
assert false, "Failed to subscribe to pubsub topic in node1: " & $error
|
|
|
|
|
|
node2.subscribe((kind: PubsubSub, topic: DefaultPubsubTopic), simpleHandler).isOkOr:
|
|
|
|
|
|
assert false, "Failed to subscribe to pubsub topic in node2: " & $error
|
2025-05-05 22:57:20 +02:00
|
|
|
|
|
|
|
|
|
|
## Subscribe to the relay topic to add the custom relay handler defined above
|
2025-06-02 22:02:49 +02:00
|
|
|
|
node3.subscribe((kind: PubsubSub, topic: DefaultPubsubTopic), relayHandler).isOkOr:
|
2025-05-05 22:57:20 +02:00
|
|
|
|
assert false, "Failed to subscribe to pubsub topic: " & $error
|
2022-09-06 20:43:46 +02:00
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
|
|
|
|
|
|
|
# prepare the message payload
|
|
|
|
|
|
let payload = "Hello".toBytes()
|
|
|
|
|
|
|
|
|
|
|
|
# prepare the epoch
|
2025-05-26 17:56:29 +05:30
|
|
|
|
var message =
|
|
|
|
|
|
WakuMessage(payload: @payload, contentTopic: contentTopic, timestamp: now())
|
2025-09-10 16:18:51 +05:30
|
|
|
|
doAssert(
|
|
|
|
|
|
node1.wakuRlnRelay
|
|
|
|
|
|
.unsafeAppendRLNProof(message, node1.wakuRlnRelay.getCurrentEpoch(), MessageId(0))
|
|
|
|
|
|
.isOk()
|
|
|
|
|
|
)
|
2022-09-06 20:43:46 +02:00
|
|
|
|
|
2025-10-15 10:49:36 +02:00
|
|
|
|
info " Nodes participating in the test",
|
2025-05-05 22:57:20 +02:00
|
|
|
|
node1 = shortLog(node1.switch.peerInfo.peerId),
|
|
|
|
|
|
node2 = shortLog(node2.switch.peerInfo.peerId),
|
|
|
|
|
|
node3 = shortLog(node3.switch.peerInfo.peerId)
|
|
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
## node1 publishes a message with a rate limit proof, the message is then relayed to node2 which in turn
|
|
|
|
|
|
## verifies the rate limit proof of the message and relays the message to node3
|
|
|
|
|
|
## verification at node2 occurs inside a topic validator which is installed as part of the waku-rln-relay mount proc
|
2024-01-18 13:49:13 +01:00
|
|
|
|
discard await node1.publish(some(DefaultPubsubTopic), message)
|
2025-09-10 16:18:51 +05:30
|
|
|
|
assert (await completionFut.withTimeout(15.seconds)), "completionFut timed out"
|
2022-09-06 20:43:46 +02:00
|
|
|
|
|
|
|
|
|
|
await node1.stop()
|
|
|
|
|
|
await node2.stop()
|
|
|
|
|
|
await node3.stop()
|
2023-02-13 11:43:49 +01:00
|
|
|
|
|
2024-09-10 15:07:12 -06:00
|
|
|
|
asyncTest "testing rln-relay is applied in all rln shards/content topics":
|
2023-08-21 08:55:34 +02:00
|
|
|
|
# create 3 nodes
|
2024-03-16 00:08:47 +01:00
|
|
|
|
let nodes = toSeq(0 ..< 3).mapIt(
|
|
|
|
|
|
newTestWakuNode(generateSecp256k1Key(), parseIpAddress("0.0.0.0"), Port(0))
|
|
|
|
|
|
)
|
2023-08-21 08:55:34 +02:00
|
|
|
|
await allFutures(nodes.mapIt(it.start()))
|
|
|
|
|
|
|
2024-09-10 15:07:12 -06:00
|
|
|
|
let shards =
|
|
|
|
|
|
@[RelayShard(clusterId: 0, shardId: 0), RelayShard(clusterId: 0, shardId: 1)]
|
2024-03-16 00:08:47 +01:00
|
|
|
|
let contentTopics =
|
|
|
|
|
|
@[
|
2023-08-21 08:55:34 +02:00
|
|
|
|
ContentTopic("/waku/2/content-topic-a/proto"),
|
2024-03-16 00:08:47 +01:00
|
|
|
|
ContentTopic("/waku/2/content-topic-b/proto"),
|
|
|
|
|
|
]
|
2023-08-21 08:55:34 +02:00
|
|
|
|
|
|
|
|
|
|
# set up three nodes
|
2025-06-02 22:02:49 +02:00
|
|
|
|
await allFutures(nodes.mapIt(it.mountRelay()))
|
2023-08-21 08:55:34 +02:00
|
|
|
|
|
|
|
|
|
|
# mount rlnrelay in off-chain mode
|
|
|
|
|
|
for index, node in nodes:
|
2025-09-26 14:47:15 +05:30
|
|
|
|
let wakuRlnConfig =
|
|
|
|
|
|
getWakuRlnConfig(manager = manager, index = MembershipIndex(index + 1))
|
2024-06-20 15:05:21 +05:30
|
|
|
|
|
2024-03-12 16:20:30 +05:30
|
|
|
|
await node.mountRlnRelay(wakuRlnConfig)
|
2025-09-10 16:18:51 +05:30
|
|
|
|
await node.start()
|
|
|
|
|
|
let manager = cast[OnchainGroupManager](node.wakuRlnRelay.groupManager)
|
|
|
|
|
|
let idCredentials = generateCredentials(manager.rlnInstance)
|
2023-08-21 08:55:34 +02:00
|
|
|
|
|
2025-09-10 16:18:51 +05:30
|
|
|
|
try:
|
|
|
|
|
|
waitFor manager.register(idCredentials, UserMessageLimit(20))
|
|
|
|
|
|
except Exception, CatchableError:
|
|
|
|
|
|
assert false,
|
|
|
|
|
|
"exception raised when calling register: " & getCurrentExceptionMsg()
|
|
|
|
|
|
|
|
|
|
|
|
let rootUpdated = waitFor manager.updateRoots()
|
2025-10-15 10:49:36 +02:00
|
|
|
|
info "Updated root for node", node = index + 1, rootUpdated = rootUpdated
|
2023-08-21 08:55:34 +02:00
|
|
|
|
|
|
|
|
|
|
# connect them together
|
|
|
|
|
|
await nodes[0].connectToNodes(@[nodes[1].switch.peerInfo.toRemotePeerInfo()])
|
|
|
|
|
|
await nodes[2].connectToNodes(@[nodes[1].switch.peerInfo.toRemotePeerInfo()])
|
|
|
|
|
|
|
|
|
|
|
|
var rxMessagesTopic1 = 0
|
|
|
|
|
|
var rxMessagesTopic2 = 0
|
2024-03-16 00:08:47 +01:00
|
|
|
|
proc relayHandler(
|
|
|
|
|
|
topic: PubsubTopic, msg: WakuMessage
|
|
|
|
|
|
): Future[void] {.async, gcsafe.} =
|
2023-08-21 08:55:34 +02:00
|
|
|
|
info "relayHandler. The received topic:", topic
|
2024-09-10 15:07:12 -06:00
|
|
|
|
if topic == $shards[0]:
|
2023-08-21 08:55:34 +02:00
|
|
|
|
rxMessagesTopic1 = rxMessagesTopic1 + 1
|
2024-09-10 15:07:12 -06:00
|
|
|
|
elif topic == $shards[1]:
|
2023-08-21 08:55:34 +02:00
|
|
|
|
rxMessagesTopic2 = rxMessagesTopic2 + 1
|
|
|
|
|
|
|
2025-06-02 22:02:49 +02:00
|
|
|
|
proc simpleHandler(
|
|
|
|
|
|
topic: PubsubTopic, msg: WakuMessage
|
|
|
|
|
|
): Future[void] {.async, gcsafe.} =
|
|
|
|
|
|
await sleepAsync(0.milliseconds)
|
|
|
|
|
|
|
|
|
|
|
|
nodes[0].subscribe((kind: PubsubSub, topic: DefaultPubsubTopic), simpleHandler).isOkOr:
|
|
|
|
|
|
assert false, "Failed to subscribe to pubsub topic in nodes[0]: " & $error
|
|
|
|
|
|
nodes[1].subscribe((kind: PubsubSub, topic: DefaultPubsubTopic), simpleHandler).isOkOr:
|
|
|
|
|
|
assert false, "Failed to subscribe to pubsub topic in nodes[1]: " & $error
|
2025-05-05 22:57:20 +02:00
|
|
|
|
|
2023-08-21 08:55:34 +02:00
|
|
|
|
# mount the relay handlers
|
2025-06-02 22:02:49 +02:00
|
|
|
|
nodes[2].subscribe((kind: PubsubSub, topic: $shards[0]), relayHandler).isOkOr:
|
2025-05-05 22:57:20 +02:00
|
|
|
|
assert false, "Failed to subscribe to pubsub topic: " & $error
|
2025-06-02 22:02:49 +02:00
|
|
|
|
nodes[2].subscribe((kind: PubsubSub, topic: $shards[1]), relayHandler).isOkOr:
|
2025-05-05 22:57:20 +02:00
|
|
|
|
assert false, "Failed to subscribe to pubsub topic: " & $error
|
2023-08-21 08:55:34 +02:00
|
|
|
|
await sleepAsync(1000.millis)
|
|
|
|
|
|
|
2023-08-31 12:24:41 +02:00
|
|
|
|
# generate some messages with rln proofs first. generating
|
|
|
|
|
|
# the proof takes some time, so this is done before publishing
|
|
|
|
|
|
# to avoid blocking the test
|
|
|
|
|
|
var messages1: seq[WakuMessage] = @[]
|
|
|
|
|
|
var messages2: seq[WakuMessage] = @[]
|
|
|
|
|
|
|
2024-03-16 00:08:47 +01:00
|
|
|
|
for i in 0 ..< 3:
|
|
|
|
|
|
var message = WakuMessage(
|
2025-05-26 17:56:29 +05:30
|
|
|
|
payload: ("Payload_" & $i).toBytes(),
|
|
|
|
|
|
timestamp: now(),
|
|
|
|
|
|
contentTopic: contentTopics[0],
|
2024-03-16 00:08:47 +01:00
|
|
|
|
)
|
2025-09-10 16:18:51 +05:30
|
|
|
|
|
|
|
|
|
|
nodes[0].wakuRlnRelay.unsafeAppendRLNProof(
|
|
|
|
|
|
message, nodes[0].wakuRlnRelay.getCurrentEpoch(), MessageId(i.uint8)
|
|
|
|
|
|
).isOkOr:
|
2024-03-12 16:20:30 +05:30
|
|
|
|
raiseAssert $error
|
2023-08-31 12:24:41 +02:00
|
|
|
|
messages1.add(message)
|
2023-08-21 08:55:34 +02:00
|
|
|
|
|
2024-03-16 00:08:47 +01:00
|
|
|
|
for i in 0 ..< 3:
|
|
|
|
|
|
var message = WakuMessage(
|
2025-05-26 17:56:29 +05:30
|
|
|
|
payload: ("Payload_" & $i).toBytes(),
|
|
|
|
|
|
timestamp: now(),
|
|
|
|
|
|
contentTopic: contentTopics[1],
|
2024-03-16 00:08:47 +01:00
|
|
|
|
)
|
2025-09-10 16:18:51 +05:30
|
|
|
|
|
|
|
|
|
|
nodes[1].wakuRlnRelay.unsafeAppendRLNProof(
|
|
|
|
|
|
message, nodes[1].wakuRlnRelay.getCurrentEpoch(), MessageId(i.uint8)
|
|
|
|
|
|
).isOkOr:
|
2024-03-12 16:20:30 +05:30
|
|
|
|
raiseAssert $error
|
2023-08-31 12:24:41 +02:00
|
|
|
|
messages2.add(message)
|
|
|
|
|
|
|
2025-09-10 16:18:51 +05:30
|
|
|
|
# publish 3 messages from node[0] (last 2 are spam, window is 10 secs)
|
|
|
|
|
|
# publish 3 messages from node[1] (last 2 are spam, window is 10 secs)
|
2024-03-16 00:08:47 +01:00
|
|
|
|
for msg in messages1:
|
2024-09-10 15:07:12 -06:00
|
|
|
|
discard await nodes[0].publish(some($shards[0]), msg)
|
2024-03-16 00:08:47 +01:00
|
|
|
|
for msg in messages2:
|
2024-09-10 15:07:12 -06:00
|
|
|
|
discard await nodes[1].publish(some($shards[1]), msg)
|
2023-08-21 08:55:34 +02:00
|
|
|
|
|
|
|
|
|
|
# wait for gossip to propagate
|
2023-08-22 10:10:54 +02:00
|
|
|
|
await sleepAsync(5000.millis)
|
2023-08-21 08:55:34 +02:00
|
|
|
|
|
|
|
|
|
|
# check that node[2] got messages from both topics
|
2023-08-22 10:10:54 +02:00
|
|
|
|
# and that rln was applied (just 1 msg is rx, rest are spam)
|
2023-08-21 08:55:34 +02:00
|
|
|
|
check:
|
2025-09-10 16:18:51 +05:30
|
|
|
|
rxMessagesTopic1 == 3
|
|
|
|
|
|
rxMessagesTopic2 == 3
|
2023-08-21 08:55:34 +02:00
|
|
|
|
|
|
|
|
|
|
await allFutures(nodes.mapIt(it.stop()))
|
|
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
asyncTest "testing rln-relay with invalid proof":
|
|
|
|
|
|
let
|
|
|
|
|
|
# publisher node
|
2023-02-13 11:43:49 +01:00
|
|
|
|
nodeKey1 = generateSecp256k1Key()
|
2023-12-14 07:16:39 +01:00
|
|
|
|
node1 = newTestWakuNode(nodeKey1, parseIpAddress("0.0.0.0"), Port(0))
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# Relay node
|
2023-02-13 11:43:49 +01:00
|
|
|
|
nodeKey2 = generateSecp256k1Key()
|
2023-12-14 07:16:39 +01:00
|
|
|
|
node2 = newTestWakuNode(nodeKey2, parseIpAddress("0.0.0.0"), Port(0))
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# Subscriber
|
2023-02-13 11:43:49 +01:00
|
|
|
|
nodeKey3 = generateSecp256k1Key()
|
2023-12-14 07:16:39 +01:00
|
|
|
|
node3 = newTestWakuNode(nodeKey3, parseIpAddress("0.0.0.0"), Port(0))
|
2022-09-06 20:43:46 +02:00
|
|
|
|
|
|
|
|
|
|
contentTopic = ContentTopic("/waku/2/default-content/proto")
|
|
|
|
|
|
|
|
|
|
|
|
# set up three nodes
|
|
|
|
|
|
# node1
|
2025-06-02 22:02:49 +02:00
|
|
|
|
(await node1.mountRelay()).isOkOr:
|
2025-05-05 22:57:20 +02:00
|
|
|
|
assert false, "Failed to mount relay"
|
2022-11-04 08:30:42 +05:30
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# mount rlnrelay in off-chain mode
|
2025-09-26 14:47:15 +05:30
|
|
|
|
let wakuRlnConfig1 = getWakuRlnConfig(manager = manager, index = MembershipIndex(1))
|
2024-06-20 15:05:21 +05:30
|
|
|
|
|
2024-03-12 16:20:30 +05:30
|
|
|
|
await node1.mountRlnRelay(wakuRlnConfig1)
|
2022-09-06 20:43:46 +02:00
|
|
|
|
await node1.start()
|
|
|
|
|
|
|
2025-09-10 16:18:51 +05:30
|
|
|
|
let manager1 = cast[OnchainGroupManager](node1.wakuRlnRelay.groupManager)
|
|
|
|
|
|
let idCredentials1 = generateCredentials(manager1.rlnInstance)
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
waitFor manager1.register(idCredentials1, UserMessageLimit(20))
|
|
|
|
|
|
except Exception, CatchableError:
|
|
|
|
|
|
assert false,
|
|
|
|
|
|
"exception raised when calling register: " & getCurrentExceptionMsg()
|
|
|
|
|
|
|
|
|
|
|
|
let rootUpdated1 = waitFor manager1.updateRoots()
|
2025-10-15 10:49:36 +02:00
|
|
|
|
info "Updated root for node1", rootUpdated1
|
2025-09-10 16:18:51 +05:30
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# node 2
|
2025-06-02 22:02:49 +02:00
|
|
|
|
(await node2.mountRelay()).isOkOr:
|
2025-05-05 22:57:20 +02:00
|
|
|
|
assert false, "Failed to mount relay"
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# mount rlnrelay in off-chain mode
|
2025-09-26 14:47:15 +05:30
|
|
|
|
let wakuRlnConfig2 = getWakuRlnConfig(manager = manager, index = MembershipIndex(2))
|
2024-06-20 15:05:21 +05:30
|
|
|
|
|
2024-03-12 16:20:30 +05:30
|
|
|
|
await node2.mountRlnRelay(wakuRlnConfig2)
|
2022-09-06 20:43:46 +02:00
|
|
|
|
await node2.start()
|
|
|
|
|
|
|
2025-09-10 16:18:51 +05:30
|
|
|
|
let manager2 = cast[OnchainGroupManager](node2.wakuRlnRelay.groupManager)
|
|
|
|
|
|
let rootUpdated2 = waitFor manager2.updateRoots()
|
2025-10-15 10:49:36 +02:00
|
|
|
|
info "Updated root for node2", rootUpdated2
|
2025-09-10 16:18:51 +05:30
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# node 3
|
2025-06-02 22:02:49 +02:00
|
|
|
|
(await node3.mountRelay()).isOkOr:
|
2025-05-05 22:57:20 +02:00
|
|
|
|
assert false, "Failed to mount relay"
|
2022-11-04 08:30:42 +05:30
|
|
|
|
|
2025-09-26 14:47:15 +05:30
|
|
|
|
let wakuRlnConfig3 = getWakuRlnConfig(manager = manager, index = MembershipIndex(3))
|
2024-06-20 15:05:21 +05:30
|
|
|
|
|
2024-03-12 16:20:30 +05:30
|
|
|
|
await node3.mountRlnRelay(wakuRlnConfig3)
|
2022-09-06 20:43:46 +02:00
|
|
|
|
await node3.start()
|
|
|
|
|
|
|
2025-09-10 16:18:51 +05:30
|
|
|
|
let manager3 = cast[OnchainGroupManager](node3.wakuRlnRelay.groupManager)
|
|
|
|
|
|
let rootUpdated3 = waitFor manager3.updateRoots()
|
2025-10-15 10:49:36 +02:00
|
|
|
|
info "Updated root for node3", rootUpdated3
|
2025-09-10 16:18:51 +05:30
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# connect them together
|
|
|
|
|
|
await node1.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()])
|
|
|
|
|
|
await node3.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()])
|
|
|
|
|
|
|
|
|
|
|
|
# define a custom relay handler
|
|
|
|
|
|
var completionFut = newFuture[bool]()
|
2024-03-16 00:08:47 +01:00
|
|
|
|
proc relayHandler(
|
|
|
|
|
|
topic: PubsubTopic, msg: WakuMessage
|
|
|
|
|
|
): Future[void] {.async, gcsafe.} =
|
2025-10-15 10:49:36 +02:00
|
|
|
|
info "The received topic:", topic
|
2023-08-21 08:55:34 +02:00
|
|
|
|
if topic == DefaultPubsubTopic:
|
2023-06-06 19:28:47 +02:00
|
|
|
|
completionFut.complete(true)
|
2022-09-06 20:43:46 +02:00
|
|
|
|
|
2025-06-02 22:02:49 +02:00
|
|
|
|
proc simpleHandler(
|
|
|
|
|
|
topic: PubsubTopic, msg: WakuMessage
|
|
|
|
|
|
): Future[void] {.async, gcsafe.} =
|
|
|
|
|
|
await sleepAsync(0.milliseconds)
|
|
|
|
|
|
|
|
|
|
|
|
node1.subscribe((kind: PubsubSub, topic: DefaultPubsubTopic), simpleHandler).isOkOr:
|
|
|
|
|
|
assert false, "Failed to subscribe to pubsub topic in node1: " & $error
|
|
|
|
|
|
node2.subscribe((kind: PubsubSub, topic: DefaultPubsubTopic), simpleHandler).isOkOr:
|
|
|
|
|
|
assert false, "Failed to subscribe to pubsub topic in node2: " & $error
|
2025-05-05 22:57:20 +02:00
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# mount the relay handler
|
2025-06-02 22:02:49 +02:00
|
|
|
|
node3.subscribe((kind: PubsubSub, topic: DefaultPubsubTopic), relayHandler).isOkOr:
|
2025-05-05 22:57:20 +02:00
|
|
|
|
assert false, "Failed to subscribe to pubsub topic: " & $error
|
2022-09-06 20:43:46 +02:00
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
|
|
|
|
|
|
|
# prepare the message payload
|
2025-09-10 16:18:51 +05:30
|
|
|
|
let payload = "valid".toBytes()
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# prepare the epoch
|
2024-02-28 17:19:20 +01:00
|
|
|
|
let epoch = node1.wakuRlnRelay.getCurrentEpoch()
|
2022-09-06 20:43:46 +02:00
|
|
|
|
|
2025-09-10 16:18:51 +05:30
|
|
|
|
var message =
|
|
|
|
|
|
WakuMessage(payload: @payload, contentTopic: DefaultPubsubTopic, timestamp: now())
|
2024-06-20 15:05:21 +05:30
|
|
|
|
|
2025-09-10 16:18:51 +05:30
|
|
|
|
node1.wakuRlnRelay.unsafeAppendRLNProof(message, epoch, MessageId(0)).isOkOr:
|
|
|
|
|
|
assert false, "Failed to append rln proof: " & $error
|
2022-09-06 20:43:46 +02:00
|
|
|
|
|
2025-09-10 16:18:51 +05:30
|
|
|
|
# message.payload = "Invalid".toBytes()
|
|
|
|
|
|
message.proof[0] = message.proof[0] xor 0x01
|
2022-09-06 20:43:46 +02:00
|
|
|
|
|
2024-01-18 13:49:13 +01:00
|
|
|
|
discard await node1.publish(some(DefaultPubsubTopic), message)
|
2022-09-06 20:43:46 +02:00
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
|
|
|
|
|
|
|
check:
|
|
|
|
|
|
# the relayHandler of node3 never gets called
|
|
|
|
|
|
(await completionFut.withTimeout(10.seconds)) == false
|
|
|
|
|
|
|
|
|
|
|
|
await node1.stop()
|
|
|
|
|
|
await node2.stop()
|
|
|
|
|
|
await node3.stop()
|
|
|
|
|
|
|
|
|
|
|
|
asyncTest "testing rln-relay double-signaling detection":
|
|
|
|
|
|
let
|
|
|
|
|
|
# publisher node
|
2023-02-13 11:43:49 +01:00
|
|
|
|
nodeKey1 = generateSecp256k1Key()
|
2023-12-14 07:16:39 +01:00
|
|
|
|
node1 = newTestWakuNode(nodeKey1, parseIpAddress("0.0.0.0"), Port(0))
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# Relay node
|
2023-02-13 11:43:49 +01:00
|
|
|
|
nodeKey2 = generateSecp256k1Key()
|
2023-12-14 07:16:39 +01:00
|
|
|
|
node2 = newTestWakuNode(nodeKey2, parseIpAddress("0.0.0.0"), Port(0))
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# Subscriber
|
2023-02-13 11:43:49 +01:00
|
|
|
|
nodeKey3 = generateSecp256k1Key()
|
2023-12-14 07:16:39 +01:00
|
|
|
|
node3 = newTestWakuNode(nodeKey3, parseIpAddress("0.0.0.0"), Port(0))
|
2022-09-06 20:43:46 +02:00
|
|
|
|
|
|
|
|
|
|
contentTopic = ContentTopic("/waku/2/default-content/proto")
|
|
|
|
|
|
|
|
|
|
|
|
# set up three nodes
|
|
|
|
|
|
# node1
|
2025-06-02 22:02:49 +02:00
|
|
|
|
(await node1.mountRelay()).isOkOr:
|
2025-05-05 22:57:20 +02:00
|
|
|
|
assert false, "Failed to mount relay"
|
2022-12-13 14:56:24 +05:30
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# mount rlnrelay in off-chain mode
|
2025-09-26 14:47:15 +05:30
|
|
|
|
let wakuRlnConfig1 = getWakuRlnConfig(manager = manager, index = MembershipIndex(1))
|
2024-06-20 15:05:21 +05:30
|
|
|
|
|
2024-03-12 16:20:30 +05:30
|
|
|
|
await node1.mountRlnRelay(wakuRlnConfig1)
|
2022-09-06 20:43:46 +02:00
|
|
|
|
await node1.start()
|
|
|
|
|
|
|
2025-09-10 16:18:51 +05:30
|
|
|
|
# Registration is mandatory before sending messages with rln-relay
|
|
|
|
|
|
let manager1 = cast[OnchainGroupManager](node1.wakuRlnRelay.groupManager)
|
|
|
|
|
|
let idCredentials1 = generateCredentials(manager1.rlnInstance)
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
waitFor manager1.register(idCredentials1, UserMessageLimit(20))
|
|
|
|
|
|
except Exception, CatchableError:
|
|
|
|
|
|
assert false,
|
|
|
|
|
|
"exception raised when calling register: " & getCurrentExceptionMsg()
|
|
|
|
|
|
|
|
|
|
|
|
let rootUpdated1 = waitFor manager1.updateRoots()
|
2025-10-15 10:49:36 +02:00
|
|
|
|
info "Updated root for node1", rootUpdated1
|
2025-09-10 16:18:51 +05:30
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# node 2
|
2025-06-02 22:02:49 +02:00
|
|
|
|
(await node2.mountRelay()).isOkOr:
|
2025-05-05 22:57:20 +02:00
|
|
|
|
assert false, "Failed to mount relay"
|
2022-12-13 14:56:24 +05:30
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# mount rlnrelay in off-chain mode
|
2025-09-26 14:47:15 +05:30
|
|
|
|
let wakuRlnConfig2 = getWakuRlnConfig(manager = manager, index = MembershipIndex(2))
|
2024-06-20 15:05:21 +05:30
|
|
|
|
|
2024-03-12 16:20:30 +05:30
|
|
|
|
await node2.mountRlnRelay(wakuRlnConfig2)
|
2022-09-06 20:43:46 +02:00
|
|
|
|
await node2.start()
|
|
|
|
|
|
|
2025-09-10 16:18:51 +05:30
|
|
|
|
# Registration is mandatory before sending messages with rln-relay
|
|
|
|
|
|
let manager2 = cast[OnchainGroupManager](node2.wakuRlnRelay.groupManager)
|
|
|
|
|
|
let rootUpdated2 = waitFor manager2.updateRoots()
|
2025-10-15 10:49:36 +02:00
|
|
|
|
info "Updated root for node2", rootUpdated2
|
2025-09-10 16:18:51 +05:30
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# node 3
|
2025-06-02 22:02:49 +02:00
|
|
|
|
(await node3.mountRelay()).isOkOr:
|
2025-05-05 22:57:20 +02:00
|
|
|
|
assert false, "Failed to mount relay"
|
2022-12-13 14:56:24 +05:30
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# mount rlnrelay in off-chain mode
|
2025-09-26 14:47:15 +05:30
|
|
|
|
let wakuRlnConfig3 = getWakuRlnConfig(manager = manager, index = MembershipIndex(3))
|
2024-06-20 15:05:21 +05:30
|
|
|
|
|
2024-03-12 16:20:30 +05:30
|
|
|
|
await node3.mountRlnRelay(wakuRlnConfig3)
|
2022-09-06 20:43:46 +02:00
|
|
|
|
await node3.start()
|
|
|
|
|
|
|
2025-09-10 16:18:51 +05:30
|
|
|
|
# Registration is mandatory before sending messages with rln-relay
|
|
|
|
|
|
let manager3 = cast[OnchainGroupManager](node3.wakuRlnRelay.groupManager)
|
|
|
|
|
|
let rootUpdated3 = waitFor manager3.updateRoots()
|
2025-10-15 10:49:36 +02:00
|
|
|
|
info "Updated root for node3", rootUpdated3
|
2025-09-10 16:18:51 +05:30
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# connect the nodes together node1 <-> node2 <-> node3
|
|
|
|
|
|
await node1.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()])
|
|
|
|
|
|
await node3.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()])
|
|
|
|
|
|
|
|
|
|
|
|
# get the current epoch time
|
2025-09-10 16:18:51 +05:30
|
|
|
|
let epoch_1 = node1.wakuRlnRelay.getCurrentEpoch()
|
2025-05-26 17:56:29 +05:30
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# create some messages with rate limit proofs
|
|
|
|
|
|
var
|
2025-05-26 17:56:29 +05:30
|
|
|
|
wm1 = WakuMessage(
|
2025-09-10 16:18:51 +05:30
|
|
|
|
payload: "message 1".toBytes(),
|
|
|
|
|
|
timestamp: now(),
|
|
|
|
|
|
contentTopic: DefaultPubsubTopic,
|
2025-05-26 17:56:29 +05:30
|
|
|
|
)
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# another message in the same epoch as wm1, it will break the messaging rate limit
|
2025-05-26 17:56:29 +05:30
|
|
|
|
wm2 = WakuMessage(
|
2025-09-10 16:18:51 +05:30
|
|
|
|
payload: "message 2".toBytes(),
|
|
|
|
|
|
timestamp: now(),
|
|
|
|
|
|
contentTopic: DefaultPubsubTopic,
|
2025-05-26 17:56:29 +05:30
|
|
|
|
)
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# wm3 points to the next epoch
|
2024-03-16 00:08:47 +01:00
|
|
|
|
|
2025-05-26 17:56:29 +05:30
|
|
|
|
await sleepAsync(1000.millis)
|
2025-09-10 16:18:51 +05:30
|
|
|
|
let epoch_2 = node1.wakuRlnRelay.getCurrentEpoch()
|
2025-05-26 17:56:29 +05:30
|
|
|
|
|
|
|
|
|
|
var
|
|
|
|
|
|
wm3 = WakuMessage(
|
2025-09-10 16:18:51 +05:30
|
|
|
|
payload: "message 3".toBytes(),
|
|
|
|
|
|
timestamp: now(),
|
|
|
|
|
|
contentTopic: DefaultPubsubTopic,
|
2025-05-26 17:56:29 +05:30
|
|
|
|
)
|
|
|
|
|
|
wm4 = WakuMessage(
|
2025-09-10 16:18:51 +05:30
|
|
|
|
payload: "message 4".toBytes(),
|
|
|
|
|
|
timestamp: now(),
|
|
|
|
|
|
contentTopic: DefaultPubsubTopic,
|
2025-05-26 17:56:29 +05:30
|
|
|
|
)
|
|
|
|
|
|
|
2025-09-10 16:18:51 +05:30
|
|
|
|
node1.wakuRlnRelay.unsafeAppendRLNProof(wm1, epoch_1, MessageId(0)).isOkOr:
|
2024-03-12 16:20:30 +05:30
|
|
|
|
raiseAssert $error
|
2025-09-10 16:18:51 +05:30
|
|
|
|
node1.wakuRlnRelay.unsafeAppendRLNProof(wm2, epoch_1, MessageId(0)).isOkOr:
|
2024-03-12 16:20:30 +05:30
|
|
|
|
raiseAssert $error
|
2024-07-06 03:33:38 +05:30
|
|
|
|
|
2025-09-10 16:18:51 +05:30
|
|
|
|
node1.wakuRlnRelay.unsafeAppendRLNProof(wm3, epoch_2, MessageId(2)).isOkOr:
|
2024-03-12 16:20:30 +05:30
|
|
|
|
raiseAssert $error
|
2022-09-06 20:43:46 +02:00
|
|
|
|
|
|
|
|
|
|
# relay handler for node3
|
|
|
|
|
|
var completionFut1 = newFuture[bool]()
|
|
|
|
|
|
var completionFut2 = newFuture[bool]()
|
|
|
|
|
|
var completionFut3 = newFuture[bool]()
|
|
|
|
|
|
var completionFut4 = newFuture[bool]()
|
2024-03-16 00:08:47 +01:00
|
|
|
|
proc relayHandler(
|
|
|
|
|
|
topic: PubsubTopic, msg: WakuMessage
|
|
|
|
|
|
): Future[void] {.async, gcsafe.} =
|
2025-10-15 10:49:36 +02:00
|
|
|
|
info "The received topic:", topic
|
2023-08-21 08:55:34 +02:00
|
|
|
|
if topic == DefaultPubsubTopic:
|
2023-06-06 19:28:47 +02:00
|
|
|
|
if msg == wm1:
|
|
|
|
|
|
completionFut1.complete(true)
|
|
|
|
|
|
if msg == wm2:
|
|
|
|
|
|
completionFut2.complete(true)
|
2025-04-17 13:03:56 +02:00
|
|
|
|
if msg.payload == wm3.payload:
|
2023-06-06 19:28:47 +02:00
|
|
|
|
completionFut3.complete(true)
|
2025-04-17 13:03:56 +02:00
|
|
|
|
if msg.payload == wm4.payload:
|
2023-06-06 19:28:47 +02:00
|
|
|
|
completionFut4.complete(true)
|
2022-09-06 20:43:46 +02:00
|
|
|
|
|
2025-06-02 22:02:49 +02:00
|
|
|
|
proc simpleHandler(
|
|
|
|
|
|
topic: PubsubTopic, msg: WakuMessage
|
|
|
|
|
|
): Future[void] {.async, gcsafe.} =
|
|
|
|
|
|
await sleepAsync(0.milliseconds)
|
|
|
|
|
|
|
|
|
|
|
|
node1.subscribe((kind: PubsubSub, topic: DefaultPubsubTopic), simpleHandler).isOkOr:
|
|
|
|
|
|
assert false, "Failed to subscribe to pubsub topic in node1: " & $error
|
|
|
|
|
|
node2.subscribe((kind: PubsubSub, topic: DefaultPubsubTopic), simpleHandler).isOkOr:
|
|
|
|
|
|
assert false, "Failed to subscribe to pubsub topic in node2: " & $error
|
2025-05-05 22:57:20 +02:00
|
|
|
|
|
2022-09-06 20:43:46 +02:00
|
|
|
|
# mount the relay handler for node3
|
2025-06-02 22:02:49 +02:00
|
|
|
|
node3.subscribe((kind: PubsubSub, topic: DefaultPubsubTopic), relayHandler).isOkOr:
|
2025-05-05 22:57:20 +02:00
|
|
|
|
assert false, "Failed to subscribe to pubsub topic: " & $error
|
2022-09-06 20:43:46 +02:00
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
|
|
|
|
|
|
|
## node1 publishes and relays 4 messages to node2
|
|
|
|
|
|
## verification at node2 occurs inside a topic validator which is installed as part of the waku-rln-relay mount proc
|
|
|
|
|
|
## node2 relays either of wm1 or wm2 to node3, depending on which message arrives at node2 first
|
|
|
|
|
|
## node2 should detect either of wm1 or wm2 as spam and not relay it
|
|
|
|
|
|
## node2 should relay wm3 to node3
|
|
|
|
|
|
## node2 should not relay wm4 because it has no valid rln proof
|
2024-01-18 13:49:13 +01:00
|
|
|
|
discard await node1.publish(some(DefaultPubsubTopic), wm1)
|
|
|
|
|
|
discard await node1.publish(some(DefaultPubsubTopic), wm2)
|
|
|
|
|
|
discard await node1.publish(some(DefaultPubsubTopic), wm3)
|
|
|
|
|
|
discard await node1.publish(some(DefaultPubsubTopic), wm4)
|
2022-09-06 20:43:46 +02:00
|
|
|
|
await sleepAsync(2000.millis)
|
|
|
|
|
|
|
|
|
|
|
|
let
|
|
|
|
|
|
res1 = await completionFut1.withTimeout(10.seconds)
|
|
|
|
|
|
res2 = await completionFut2.withTimeout(10.seconds)
|
|
|
|
|
|
|
|
|
|
|
|
check:
|
2024-03-16 00:08:47 +01:00
|
|
|
|
(res1 and res2) == false
|
|
|
|
|
|
# either of the wm1 and wm2 is found as spam hence not relayed
|
2022-09-06 20:43:46 +02:00
|
|
|
|
(await completionFut3.withTimeout(10.seconds)) == true
|
|
|
|
|
|
(await completionFut4.withTimeout(10.seconds)) == false
|
|
|
|
|
|
|
|
|
|
|
|
await node1.stop()
|
|
|
|
|
|
await node2.stop()
|
2023-02-10 17:55:47 +01:00
|
|
|
|
await node3.stop()
|
2023-09-06 13:48:02 +05:30
|
|
|
|
|
2025-04-10 00:28:25 +02:00
|
|
|
|
xasyncTest "clearNullifierLog: should clear epochs > MaxEpochGap":
|
|
|
|
|
|
## This is skipped because is flaky and made CI randomly fail but is useful to run manually
|
2024-08-02 16:43:22 +02:00
|
|
|
|
# Given two nodes
|
2023-09-06 13:48:02 +05:30
|
|
|
|
let
|
2024-08-02 16:43:22 +02:00
|
|
|
|
contentTopic = ContentTopic("/waku/2/default-content/proto")
|
2024-09-10 15:07:12 -06:00
|
|
|
|
shardSeq = @[DefaultRelayShard]
|
2023-09-06 13:48:02 +05:30
|
|
|
|
nodeKey1 = generateSecp256k1Key()
|
2023-12-14 07:16:39 +01:00
|
|
|
|
node1 = newTestWakuNode(nodeKey1, parseIpAddress("0.0.0.0"), Port(0))
|
2023-09-06 13:48:02 +05:30
|
|
|
|
nodeKey2 = generateSecp256k1Key()
|
2023-12-14 07:16:39 +01:00
|
|
|
|
node2 = newTestWakuNode(nodeKey2, parseIpAddress("0.0.0.0"), Port(0))
|
2024-08-02 16:43:22 +02:00
|
|
|
|
epochSizeSec: uint64 = 5 # This means rlnMaxEpochGap = 4
|
2024-06-20 15:05:21 +05:30
|
|
|
|
|
2024-08-02 16:43:22 +02:00
|
|
|
|
# Given both nodes mount relay and rlnrelay
|
2025-06-02 22:02:49 +02:00
|
|
|
|
(await node1.mountRelay()).isOkOr:
|
2025-05-05 22:57:20 +02:00
|
|
|
|
assert false, "Failed to mount relay"
|
2025-09-26 14:47:15 +05:30
|
|
|
|
let wakuRlnConfig1 = getWakuRlnConfig(manager = manager, index = MembershipIndex(1))
|
2025-09-10 16:18:51 +05:30
|
|
|
|
await node1.mountRlnRelay(wakuRlnConfig1)
|
|
|
|
|
|
await node1.start()
|
|
|
|
|
|
|
|
|
|
|
|
# Registration is mandatory before sending messages with rln-relay
|
|
|
|
|
|
let manager1 = cast[OnchainGroupManager](node1.wakuRlnRelay.groupManager)
|
|
|
|
|
|
let idCredentials1 = generateCredentials(manager1.rlnInstance)
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
waitFor manager1.register(idCredentials1, UserMessageLimit(20))
|
|
|
|
|
|
except Exception, CatchableError:
|
|
|
|
|
|
assert false,
|
|
|
|
|
|
"exception raised when calling register: " & getCurrentExceptionMsg()
|
|
|
|
|
|
|
|
|
|
|
|
let rootUpdated1 = waitFor manager1.updateRoots()
|
2025-10-15 10:49:36 +02:00
|
|
|
|
info "Updated root for node1", rootUpdated1
|
2023-09-06 13:48:02 +05:30
|
|
|
|
|
2024-08-02 16:43:22 +02:00
|
|
|
|
# Mount rlnrelay in node2 in off-chain mode
|
2025-06-02 22:02:49 +02:00
|
|
|
|
(await node2.mountRelay()).isOkOr:
|
2025-05-05 22:57:20 +02:00
|
|
|
|
assert false, "Failed to mount relay"
|
2025-09-26 14:47:15 +05:30
|
|
|
|
let wakuRlnConfig2 = getWakuRlnConfig(manager = manager, index = MembershipIndex(2))
|
2024-03-12 16:20:30 +05:30
|
|
|
|
await node2.mountRlnRelay(wakuRlnConfig2)
|
2025-09-10 16:18:51 +05:30
|
|
|
|
await node2.start()
|
|
|
|
|
|
|
|
|
|
|
|
# Registration is mandatory before sending messages with rln-relay
|
|
|
|
|
|
let manager2 = cast[OnchainGroupManager](node2.wakuRlnRelay.groupManager)
|
|
|
|
|
|
let rootUpdated2 = waitFor manager2.updateRoots()
|
2025-10-15 10:49:36 +02:00
|
|
|
|
info "Updated root for node2", rootUpdated2
|
2023-09-06 13:48:02 +05:30
|
|
|
|
|
2024-08-02 16:43:22 +02:00
|
|
|
|
# Given the two nodes are started and connected
|
|
|
|
|
|
waitFor allFutures(node1.start(), node2.start())
|
2023-09-06 13:48:02 +05:30
|
|
|
|
await node1.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()])
|
|
|
|
|
|
|
2024-08-02 16:43:22 +02:00
|
|
|
|
# Given some messages
|
2023-09-06 13:48:02 +05:30
|
|
|
|
var
|
2025-09-10 16:18:51 +05:30
|
|
|
|
wm1 =
|
|
|
|
|
|
WakuMessage(payload: "message 1".toBytes(), contentTopic: DefaultPubsubTopic)
|
|
|
|
|
|
wm2 =
|
|
|
|
|
|
WakuMessage(payload: "message 2".toBytes(), contentTopic: DefaultPubsubTopic)
|
|
|
|
|
|
wm3 =
|
|
|
|
|
|
WakuMessage(payload: "message 3".toBytes(), contentTopic: DefaultPubsubTopic)
|
|
|
|
|
|
wm4 =
|
|
|
|
|
|
WakuMessage(payload: "message 4".toBytes(), contentTopic: DefaultPubsubTopic)
|
|
|
|
|
|
wm5 =
|
|
|
|
|
|
WakuMessage(payload: "message 5".toBytes(), contentTopic: DefaultPubsubTopic)
|
|
|
|
|
|
wm6 =
|
|
|
|
|
|
WakuMessage(payload: "message 6".toBytes(), contentTopic: DefaultPubsubTopic)
|
2023-09-06 13:48:02 +05:30
|
|
|
|
|
2024-08-02 16:43:22 +02:00
|
|
|
|
# And node2 mounts a relay handler that completes the respective future when a message is received
|
|
|
|
|
|
var
|
|
|
|
|
|
completionFut1 = newFuture[bool]()
|
|
|
|
|
|
completionFut2 = newFuture[bool]()
|
|
|
|
|
|
completionFut3 = newFuture[bool]()
|
|
|
|
|
|
completionFut4 = newFuture[bool]()
|
|
|
|
|
|
completionFut5 = newFuture[bool]()
|
|
|
|
|
|
completionFut6 = newFuture[bool]()
|
2024-03-16 00:08:47 +01:00
|
|
|
|
proc relayHandler(
|
|
|
|
|
|
topic: PubsubTopic, msg: WakuMessage
|
|
|
|
|
|
): Future[void] {.async, gcsafe.} =
|
2025-10-15 10:49:36 +02:00
|
|
|
|
info "The received topic:", topic
|
2023-09-06 13:48:02 +05:30
|
|
|
|
if topic == DefaultPubsubTopic:
|
|
|
|
|
|
if msg == wm1:
|
|
|
|
|
|
completionFut1.complete(true)
|
|
|
|
|
|
if msg == wm2:
|
|
|
|
|
|
completionFut2.complete(true)
|
|
|
|
|
|
if msg == wm3:
|
|
|
|
|
|
completionFut3.complete(true)
|
2024-08-02 16:43:22 +02:00
|
|
|
|
if msg == wm4:
|
|
|
|
|
|
completionFut4.complete(true)
|
|
|
|
|
|
if msg == wm5:
|
|
|
|
|
|
completionFut5.complete(true)
|
|
|
|
|
|
if msg == wm6:
|
|
|
|
|
|
completionFut6.complete(true)
|
2023-12-15 10:26:17 +01:00
|
|
|
|
|
2025-06-02 22:02:49 +02:00
|
|
|
|
node2.subscribe((kind: PubsubSub, topic: DefaultPubsubTopic), relayHandler).isOkOr:
|
2025-05-05 22:57:20 +02:00
|
|
|
|
assert false, "Failed to subscribe to pubsub topic: " & $error
|
2023-09-06 13:48:02 +05:30
|
|
|
|
|
2024-08-02 16:43:22 +02:00
|
|
|
|
# Given all messages have an rln proof and are published by the node 1
|
|
|
|
|
|
let publishSleepDuration: Duration = 5000.millis
|
2025-09-10 16:18:51 +05:30
|
|
|
|
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
|
|
|
|
|
|
)
|
2024-08-02 16:43:22 +02:00
|
|
|
|
|
|
|
|
|
|
# Epoch 1
|
2025-09-10 16:18:51 +05:30
|
|
|
|
node1.wakuRlnRelay.unsafeAppendRLNProof(wm1, epoch_1, MessageId(0)).isOkOr:
|
2024-08-02 16:43:22 +02:00
|
|
|
|
raiseAssert $error
|
2025-02-28 15:36:50 +01:00
|
|
|
|
|
2024-08-02 16:43:22 +02:00
|
|
|
|
# Message wm2 is published in the same epoch as wm1, so it'll be considered spam
|
2025-09-10 16:18:51 +05:30
|
|
|
|
node1.wakuRlnRelay.unsafeAppendRLNProof(wm2, epoch_1, MessageId(0)).isOkOr:
|
2024-08-02 16:43:22 +02:00
|
|
|
|
raiseAssert $error
|
2025-02-28 15:36:50 +01:00
|
|
|
|
|
2024-01-18 13:49:13 +01:00
|
|
|
|
discard await node1.publish(some(DefaultPubsubTopic), wm1)
|
|
|
|
|
|
discard await node1.publish(some(DefaultPubsubTopic), wm2)
|
2024-08-02 16:43:22 +02:00
|
|
|
|
await sleepAsync(publishSleepDuration)
|
|
|
|
|
|
check:
|
2025-01-06 13:47:17 +01:00
|
|
|
|
await node1.waitForNullifierLog(0)
|
|
|
|
|
|
await node2.waitForNullifierLog(1)
|
2024-08-02 16:43:22 +02:00
|
|
|
|
|
|
|
|
|
|
# Epoch 2
|
2025-02-28 15:36:50 +01:00
|
|
|
|
|
2025-09-10 16:18:51 +05:30
|
|
|
|
node1.wakuRlnRelay.unsafeAppendRLNProof(wm3, epoch_2, MessageId(0)).isOkOr:
|
2024-08-02 16:43:22 +02:00
|
|
|
|
raiseAssert $error
|
2025-02-28 15:36:50 +01:00
|
|
|
|
|
2024-01-18 13:49:13 +01:00
|
|
|
|
discard await node1.publish(some(DefaultPubsubTopic), wm3)
|
2025-02-28 15:36:50 +01:00
|
|
|
|
|
2024-08-02 16:43:22 +02:00
|
|
|
|
await sleepAsync(publishSleepDuration)
|
2025-02-28 15:36:50 +01:00
|
|
|
|
|
2025-01-06 13:47:17 +01:00
|
|
|
|
check:
|
|
|
|
|
|
await node1.waitForNullifierLog(0)
|
|
|
|
|
|
await node2.waitForNullifierLog(2)
|
2023-12-15 10:26:17 +01:00
|
|
|
|
|
2024-08-02 16:43:22 +02:00
|
|
|
|
# Epoch 3
|
2025-09-10 16:18:51 +05:30
|
|
|
|
node1.wakuRlnRelay.unsafeAppendRLNProof(wm4, epoch_3, MessageId(0)).isOkOr:
|
2024-08-02 16:43:22 +02:00
|
|
|
|
raiseAssert $error
|
2025-02-28 15:36:50 +01:00
|
|
|
|
|
2024-08-02 16:43:22 +02:00
|
|
|
|
discard await node1.publish(some(DefaultPubsubTopic), wm4)
|
|
|
|
|
|
await sleepAsync(publishSleepDuration)
|
|
|
|
|
|
check:
|
2025-01-06 13:47:17 +01:00
|
|
|
|
await node1.waitForNullifierLog(0)
|
|
|
|
|
|
await node2.waitForNullifierLog(3)
|
2024-08-02 16:43:22 +02:00
|
|
|
|
|
|
|
|
|
|
# Epoch 4
|
2025-09-10 16:18:51 +05:30
|
|
|
|
node1.wakuRlnRelay.unsafeAppendRLNProof(wm5, epoch_4, MessageId(0)).isOkOr:
|
2024-08-02 16:43:22 +02:00
|
|
|
|
raiseAssert $error
|
2025-02-28 15:36:50 +01:00
|
|
|
|
|
2024-08-02 16:43:22 +02:00
|
|
|
|
discard await node1.publish(some(DefaultPubsubTopic), wm5)
|
|
|
|
|
|
await sleepAsync(publishSleepDuration)
|
2025-01-06 13:47:17 +01:00
|
|
|
|
check:
|
|
|
|
|
|
await node1.waitForNullifierLog(0)
|
|
|
|
|
|
await node2.waitForNullifierLog(4)
|
2024-08-02 16:43:22 +02:00
|
|
|
|
|
|
|
|
|
|
# Epoch 5
|
2025-09-10 16:18:51 +05:30
|
|
|
|
node1.wakuRlnRelay.unsafeAppendRLNProof(wm6, epoch_5, MessageId(0)).isOkOr:
|
2024-08-02 16:43:22 +02:00
|
|
|
|
raiseAssert $error
|
2025-02-28 15:36:50 +01:00
|
|
|
|
|
2024-08-02 16:43:22 +02:00
|
|
|
|
discard await node1.publish(some(DefaultPubsubTopic), wm6)
|
|
|
|
|
|
await sleepAsync(publishSleepDuration)
|
|
|
|
|
|
check:
|
2025-01-06 13:47:17 +01:00
|
|
|
|
await node1.waitForNullifierLog(0)
|
|
|
|
|
|
await node2.waitForNullifierLog(4)
|
2024-08-02 16:43:22 +02:00
|
|
|
|
|
|
|
|
|
|
# Then the node 2 should have cleared the nullifier log for epochs > MaxEpochGap
|
|
|
|
|
|
# Therefore, with 4 max epochs, the first 4 messages will be published (except wm2, which shares epoch with wm1)
|
|
|
|
|
|
check:
|
|
|
|
|
|
(await completionFut1.waitForResult()).value() == true
|
|
|
|
|
|
(await completionFut2.waitForResult()).isErr()
|
|
|
|
|
|
(await completionFut3.waitForResult()).value() == true
|
|
|
|
|
|
(await completionFut4.waitForResult()).value() == true
|
|
|
|
|
|
(await completionFut5.waitForResult()).value() == true
|
|
|
|
|
|
(await completionFut6.waitForResult()).value() == true
|
|
|
|
|
|
|
|
|
|
|
|
# Cleanup
|
|
|
|
|
|
waitFor allFutures(node1.stop(), node2.stop())
|