Skip to content

Commit 9bba8b0

Browse files
fix: refact rln-relay and post sync test (#3434)
1 parent 5fc8c59 commit 9bba8b0

25 files changed

+672
-1732
lines changed

apps/benchmarks/benchmarks.nim

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,66 @@
11
import
2-
math,
3-
std/sequtils,
4-
results,
5-
options,
2+
std/[strutils, times, sequtils, osproc], math, results, options, testutils/unittests
3+
4+
import
65
waku/[
76
waku_rln_relay/protocol_types,
87
waku_rln_relay/rln,
98
waku_rln_relay,
109
waku_rln_relay/conversion_utils,
11-
waku_rln_relay/group_manager/static/group_manager,
12-
]
13-
14-
import std/[times, os]
10+
waku_rln_relay/group_manager/on_chain/group_manager,
11+
],
12+
tests/waku_rln_relay/utils_onchain
1513

1614
proc main(): Future[string] {.async, gcsafe.} =
17-
let rlnIns = createRLNInstance(20).get()
18-
let credentials = toSeq(0 .. 1000).mapIt(membershipKeyGen(rlnIns).get())
15+
# Spin up a local Ethereum JSON-RPC (Anvil) and deploy the RLN contract
16+
let anvilProc = runAnvil()
17+
defer:
18+
stopAnvil(anvilProc)
19+
20+
# Set up an On-chain group manager (includes contract deployment)
21+
let manager = await setupOnchainGroupManager()
22+
(await manager.init()).isOkOr:
23+
raiseAssert $error
1924

20-
let manager = StaticGroupManager(
21-
rlnInstance: rlnIns,
22-
groupSize: 1000,
23-
membershipIndex: some(MembershipIndex(900)),
24-
groupKeys: credentials,
25-
)
25+
# Register a new member so that we can later generate proofs
26+
let idCredentials = generateCredentials(manager.rlnInstance)
2627

27-
await manager.init()
28+
try:
29+
await manager.register(idCredentials, UserMessageLimit(100))
30+
except Exception, CatchableError:
31+
assert false, "exception raised: " & getCurrentExceptionMsg()
32+
33+
let rootUpdated = await manager.updateRoots()
2834

35+
if rootUpdated:
36+
let proofResult = await manager.fetchMerkleProofElements()
37+
if proofResult.isErr():
38+
error "Failed to fetch Merkle proof", error = proofResult.error
39+
manager.merkleProofCache = proofResult.get()
40+
41+
let epoch = default(Epoch)
42+
debug "epoch in bytes", epochHex = epoch.inHex()
2943
let data: seq[byte] = newSeq[byte](1024)
3044

3145
var proofGenTimes: seq[times.Duration] = @[]
3246
var proofVerTimes: seq[times.Duration] = @[]
33-
for i in 0 .. 50:
47+
48+
for i in 1 .. 100:
3449
var time = getTime()
35-
let proof = manager.generateProof(data, default(Epoch)).get()
50+
let proof = manager.generateProof(data, epoch, MessageId(i.uint8)).valueOr:
51+
raiseAssert $error
3652
proofGenTimes.add(getTime() - time)
3753

3854
time = getTime()
39-
let res = manager.verifyProof(data, proof).get()
55+
let ok = manager.verifyProof(data, proof).valueOr:
56+
raiseAssert $error
4057
proofVerTimes.add(getTime() - time)
4158

4259
echo "Proof generation times: ", sum(proofGenTimes) div len(proofGenTimes)
4360
echo "Proof verification times: ", sum(proofVerTimes) div len(proofVerTimes)
4461

4562
when isMainModule:
4663
try:
47-
waitFor(main())
64+
discard waitFor main()
4865
except CatchableError as e:
4966
raise e

tests/node/test_wakunode_legacy_lightpush.nim

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{.used.}
22

33
import
4-
std/[options, tempfiles, net],
4+
std/[options, tempfiles, net, osproc],
55
testutils/unittests,
66
chronos,
77
std/strformat,
@@ -17,8 +17,9 @@ import
1717
waku_lightpush_legacy/protocol_metrics,
1818
waku_rln_relay,
1919
],
20-
../testlib/[wakucore, wakunode, testasync, futures],
21-
../resources/payloads
20+
../testlib/[wakucore, wakunode, testasync, futures, testutils],
21+
../resources/payloads,
22+
../waku_rln_relay/[rln/waku_rln_relay_utils, utils_onchain]
2223

2324
suite "Waku Legacy Lightpush - End To End":
2425
var
@@ -110,6 +111,8 @@ suite "RLN Proofs as a Lightpush Service":
110111

111112
server {.threadvar.}: WakuNode
112113
client {.threadvar.}: WakuNode
114+
anvilProc {.threadvar.}: Process
115+
manager {.threadvar.}: OnchainGroupManager
113116

114117
serverRemotePeerInfo {.threadvar.}: RemotePeerInfo
115118
pubsubTopic {.threadvar.}: PubsubTopic
@@ -131,13 +134,14 @@ suite "RLN Proofs as a Lightpush Service":
131134
server = newTestWakuNode(serverKey, parseIpAddress("0.0.0.0"), Port(0))
132135
client = newTestWakuNode(clientKey, parseIpAddress("0.0.0.0"), Port(0))
133136

137+
anvilProc = runAnvil()
138+
manager = waitFor setupOnchainGroupManager()
139+
134140
# mount rln-relay
135-
let wakuRlnConfig = WakuRlnConfig(
136-
dynamic: false,
137-
credIndex: some(1.uint),
138-
userMessageLimit: 1,
139-
epochSizeSec: 1,
140-
treePath: genTempPath("rln_tree", "wakunode"),
141+
let wakuRlnConfig = getWakuRlnConfig(
142+
manager = manager,
143+
treePath = genTempPath("rln_tree", "wakunode_1"),
144+
index = MembershipIndex(1),
141145
)
142146

143147
await allFutures(server.start(), client.start())
@@ -149,13 +153,32 @@ suite "RLN Proofs as a Lightpush Service":
149153
await server.mountLegacyLightPush()
150154
client.mountLegacyLightPushClient()
151155

156+
let manager1 = cast[OnchainGroupManager](server.wakuRlnRelay.groupManager)
157+
let idCredentials1 = generateCredentials(manager1.rlnInstance)
158+
159+
try:
160+
waitFor manager1.register(idCredentials1, UserMessageLimit(20))
161+
except Exception, CatchableError:
162+
assert false,
163+
"exception raised when calling register: " & getCurrentExceptionMsg()
164+
165+
let rootUpdated1 = waitFor manager1.updateRoots()
166+
debug "Updated root for node1", rootUpdated1
167+
168+
if rootUpdated1:
169+
let proofResult = waitFor manager1.fetchMerkleProofElements()
170+
if proofResult.isErr():
171+
error "Failed to fetch Merkle proof", error = proofResult.error
172+
manager1.merkleProofCache = proofResult.get()
173+
152174
serverRemotePeerInfo = server.peerInfo.toRemotePeerInfo()
153175
pubsubTopic = DefaultPubsubTopic
154176
contentTopic = DefaultContentTopic
155177
message = fakeWakuMessage()
156178

157179
asyncTeardown:
158180
await server.stop()
181+
stopAnvil(anvilProc)
159182

160183
suite "Lightpush attaching RLN proofs":
161184
asyncTest "Message is published when RLN enabled":

tests/node/test_wakunode_lightpush.nim

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{.used.}
22

33
import
4-
std/[options, tempfiles],
4+
std/[options, tempfiles, osproc],
55
testutils/unittests,
66
chronos,
77
std/strformat,
@@ -10,7 +10,8 @@ import
1010
import
1111
waku/[waku_core, node/peer_manager, node/waku_node, waku_lightpush, waku_rln_relay],
1212
../testlib/[wakucore, wakunode, testasync, futures],
13-
../resources/payloads
13+
../resources/payloads,
14+
../waku_rln_relay/[rln/waku_rln_relay_utils, utils_onchain]
1415

1516
const PublishedToOnePeer = 1
1617

@@ -104,6 +105,8 @@ suite "RLN Proofs as a Lightpush Service":
104105

105106
server {.threadvar.}: WakuNode
106107
client {.threadvar.}: WakuNode
108+
anvilProc {.threadvar.}: Process
109+
manager {.threadvar.}: OnchainGroupManager
107110

108111
serverRemotePeerInfo {.threadvar.}: RemotePeerInfo
109112
pubsubTopic {.threadvar.}: PubsubTopic
@@ -125,13 +128,14 @@ suite "RLN Proofs as a Lightpush Service":
125128
server = newTestWakuNode(serverKey, parseIpAddress("0.0.0.0"), Port(0))
126129
client = newTestWakuNode(clientKey, parseIpAddress("0.0.0.0"), Port(0))
127130

131+
anvilProc = runAnvil()
132+
manager = waitFor setupOnchainGroupManager()
133+
128134
# mount rln-relay
129-
let wakuRlnConfig = WakuRlnConfig(
130-
dynamic: false,
131-
credIndex: some(1.uint),
132-
userMessageLimit: 1,
133-
epochSizeSec: 1,
134-
treePath: genTempPath("rln_tree", "wakunode"),
135+
let wakuRlnConfig = getWakuRlnConfig(
136+
manager = manager,
137+
treePath = genTempPath("rln_tree", "wakunode_1"),
138+
index = MembershipIndex(1),
135139
)
136140

137141
await allFutures(server.start(), client.start())
@@ -143,13 +147,32 @@ suite "RLN Proofs as a Lightpush Service":
143147
await server.mountLightPush()
144148
client.mountLightPushClient()
145149

150+
let manager1 = cast[OnchainGroupManager](server.wakuRlnRelay.groupManager)
151+
let idCredentials1 = generateCredentials(manager1.rlnInstance)
152+
153+
try:
154+
waitFor manager1.register(idCredentials1, UserMessageLimit(20))
155+
except Exception, CatchableError:
156+
assert false,
157+
"exception raised when calling register: " & getCurrentExceptionMsg()
158+
159+
let rootUpdated1 = waitFor manager1.updateRoots()
160+
debug "Updated root for node1", rootUpdated1
161+
162+
if rootUpdated1:
163+
let proofResult = waitFor manager1.fetchMerkleProofElements()
164+
if proofResult.isErr():
165+
error "Failed to fetch Merkle proof", error = proofResult.error
166+
manager1.merkleProofCache = proofResult.get()
167+
146168
serverRemotePeerInfo = server.peerInfo.toRemotePeerInfo()
147169
pubsubTopic = DefaultPubsubTopic
148170
contentTopic = DefaultContentTopic
149171
message = fakeWakuMessage()
150172

151173
asyncTeardown:
152174
await server.stop()
175+
stopAnvil(anvilProc)
153176

154177
suite "Lightpush attaching RLN proofs":
155178
asyncTest "Message is published when RLN enabled":

tests/waku_rln_relay/rln/test_wrappers.nim

Lines changed: 4 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import
1515
waku/waku_rln_relay/rln/wrappers,
1616
./waku_rln_relay_utils,
1717
../../testlib/[simple_mock, assertions],
18-
../../waku_keystore/utils
18+
../../waku_keystore/utils,
19+
../../testlib/testutils
1920

2021
from std/times import epochTime
2122

@@ -98,7 +99,7 @@ suite "RlnConfig":
9899
suite "createRLNInstance":
99100
test "ok":
100101
# When we create the RLN instance
101-
let rlnRes: RLNResult = createRLNInstance(15, "my.db")
102+
let rlnRes: RLNResult = createRLNInstance(15)
102103

103104
# Then it succeeds
104105
check:
@@ -124,7 +125,7 @@ suite "RlnConfig":
124125
newCircuitMock
125126

126127
# When we create the RLN instance
127-
let rlnRes: RLNResult = createRLNInstance(15, "my.db")
128+
let rlnRes: RLNResult = createRLNInstance(15)
128129

129130
# Then it fails
130131
check:
@@ -133,42 +134,3 @@ suite "RlnConfig":
133134
# Cleanup
134135
mock(new_circuit):
135136
backup
136-
137-
suite "proofGen":
138-
test "Valid zk proof":
139-
# this test vector is from zerokit
140-
let rlnInstanceRes = createRLNInstanceWrapper()
141-
assertResultOk(rlnInstanceRes)
142-
let rlnInstance = rlnInstanceRes.value
143-
144-
let identityCredential = defaultIdentityCredential()
145-
assert rlnInstance.insertMember(identityCredential.idCommitment)
146-
147-
let merkleRootRes = rlnInstance.getMerkleRoot()
148-
assertResultOk(merkleRootRes)
149-
let merkleRoot = merkleRootRes.value
150-
151-
let proofGenRes = rlnInstance.proofGen(
152-
data = @[],
153-
memKeys = identityCredential,
154-
memIndex = MembershipIndex(0),
155-
epoch = uint64(epochTime() / 1.float64).toEpoch(),
156-
)
157-
assertResultOk(proofGenRes)
158-
159-
let
160-
rateLimitProof = proofGenRes.value
161-
proofVerifyRes = rlnInstance.proofVerify(
162-
data = @[], proof = rateLimitProof, validRoots = @[merkleRoot]
163-
)
164-
165-
assertResultOk(proofVerifyRes)
166-
assert proofVerifyRes.value, "proof verification failed"
167-
168-
# Assert the proof fields adhere to the specified types and lengths
169-
check:
170-
typeEq(rateLimitProof.proof, array[256, byte])
171-
typeEq(rateLimitProof.merkleRoot, array[32, byte])
172-
typeEq(rateLimitProof.shareX, array[32, byte])
173-
typeEq(rateLimitProof.shareY, array[32, byte])
174-
typeEq(rateLimitProof.nullifier, array[32, byte])
Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,59 @@
11
import std/tempfiles
22

3-
import waku/waku_rln_relay, waku/waku_rln_relay/[rln, protocol_types]
3+
import
4+
waku/waku_rln_relay,
5+
waku/waku_rln_relay/[
6+
group_manager, rln, conversion_utils, constants, protocol_types, protocol_metrics,
7+
nonce_manager,
8+
]
49

510
proc createRLNInstanceWrapper*(): RLNResult =
611
return createRlnInstance(tree_path = genTempPath("rln_tree", "waku_rln_relay"))
712

813
proc unsafeAppendRLNProof*(
9-
rlnPeer: WakuRLNRelay, msg: var WakuMessage, senderEpochTime: float64
14+
rlnPeer: WakuRLNRelay, msg: var WakuMessage, epoch: Epoch, messageId: MessageId
1015
): RlnRelayResult[void] =
11-
## this proc derived from appendRLNProof, does not perform nonce check to
12-
## facilitate bad message id generation for testing
16+
## Test helper derived from `appendRLNProof`.
17+
## - Skips nonce validation to intentionally allow generating "bad" message IDs for tests.
18+
## - Forces a real-time on-chain Merkle root refresh via `updateRoots()` and fetches Merkle
19+
## proof elements, updating `merkleProofCache` (bypasses `trackRootsChanges`).
20+
## WARNING: For testing only
1321

14-
let input = msg.toRLNSignal()
15-
let epoch = rlnPeer.calcEpoch(senderEpochTime)
22+
let manager = cast[OnchainGroupManager](rlnPeer.groupManager)
23+
let rootUpdated = waitFor manager.updateRoots()
1624

17-
# we do not fetch a nonce from the nonce manager,
18-
# instead we use 0 as the nonce
19-
let proof = rlnPeer.groupManager.generateProof(input, epoch, 0).valueOr:
25+
# Fetch Merkle proof either when a new root was detected *or* when the cache is empty.
26+
if rootUpdated or manager.merkleProofCache.len == 0:
27+
let proofResult = waitFor manager.fetchMerkleProofElements()
28+
if proofResult.isErr():
29+
error "Failed to fetch Merkle proof", error = proofResult.error
30+
manager.merkleProofCache = proofResult.get()
31+
32+
let proof = manager.generateProof(msg.toRLNSignal(), epoch, messageId).valueOr:
2033
return err("could not generate rln-v2 proof: " & $error)
2134

2235
msg.proof = proof.encode().buffer
2336
return ok()
37+
38+
proc getWakuRlnConfig*(
39+
manager: OnchainGroupManager,
40+
userMessageLimit: uint64 = 1,
41+
epochSizeSec: uint64 = 1,
42+
treePath: string = genTempPath("rln_tree", "waku_rln_relay"),
43+
index: MembershipIndex = MembershipIndex(0),
44+
): WakuRlnConfig =
45+
let wakuRlnConfig = WakuRlnConfig(
46+
dynamic: true,
47+
ethClientUrls: @[EthClient],
48+
ethContractAddress: manager.ethContractAddress,
49+
chainId: manager.chainId,
50+
credIndex: some(index),
51+
userMessageLimit: userMessageLimit,
52+
epochSizeSec: epochSizeSec,
53+
treePath: treePath,
54+
ethPrivateKey: some(manager.ethPrivateKey.get()),
55+
onFatalErrorAction: proc(errStr: string) =
56+
warn "non-fatal onchain test error", errStr
57+
,
58+
)
59+
return wakuRlnConfig

0 commit comments

Comments
 (0)