Skip to content

Commit

Permalink
feat(rln-relay): init group manager integration
Browse files Browse the repository at this point in the history
fix(rln-relay): integrate group manager. todo spam and reg handlers

fix(rln-relay): decouple waku-relay and waku-rln-relay

fix(rln-relay): compiles now

fix(chat2): compilation

fix(rln-relay): wip segfault

fix(rln-relay): segfault

fix(chat2|wakunode2): use optional field

fix(rln-relay): wakunode test

fix(rln-relay): uncomment fields in proto decode

fix(rln-relay): used pragma on tests

fix(rln-relay): include cred processing

fix(rln-relay): add reg callback

fix(rln-relay): args to mount

fix(rln-relay): add timeout to waitForExit

fix(rln-relay): use osproc term instead of posix kill

fix(rln-relay): use poParentStream to prevent deadlock

fix(rln-relay): remove poParentStream, remove ganache log output
  • Loading branch information
rymnc committed Feb 21, 2023
1 parent e12b7cb commit 2f883f8
Show file tree
Hide file tree
Showing 18 changed files with 934 additions and 2,305 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ node_modules/

# Ignore Jetbrains IDE files
.idea/

# RLN / keystore
rlnCredentials.txt
testPath.txt
rlnKeystore.json

# Nimbus Build System
nimbus-build-system.paths
Expand Down
16 changes: 9 additions & 7 deletions apps/chat2/chat2.nim
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ when (NimMajor, NimMinor) < (1, 4):
else:
{.push raises: [].}

import std/[tables, strformat, strutils, times, json, options, random]
import std/[strformat, strutils, times, json, options, random]
import confutils, chronicles, chronos, stew/shims/net as stewNet,
eth/keys, bearssl, stew/[byteutils, results],
nimcrypto/pbkdf2
Expand Down Expand Up @@ -562,7 +562,7 @@ proc processInput(rfd: AsyncFD, rng: ref HmacDrbgContext) {.async.} =
rlnRelayDynamic: conf.rlnRelayDynamic,
rlnRelayPubsubTopic: conf.rlnRelayPubsubTopic,
rlnRelayContentTopic: conf.rlnRelayContentTopic,
rlnRelayMembershipIndex: conf.rlnRelayMembershipIndex,
rlnRelayMembershipIndex: some(conf.rlnRelayMembershipIndex),
rlnRelayEthContractAddress: conf.rlnRelayEthContractAddress,
rlnRelayEthClientAddress: conf.rlnRelayEthClientAddress,
rlnRelayEthAccountPrivateKey: conf.rlnRelayEthAccountPrivateKey,
Expand All @@ -575,11 +575,13 @@ proc processInput(rfd: AsyncFD, rng: ref HmacDrbgContext) {.async.} =
spamHandler=some(spamHandler),
registrationHandler=some(registrationHandler))

echo "your membership index is: ", node.wakuRlnRelay.membershipIndex
echo "your rln identity trapdoor is: ", node.wakuRlnRelay.identityCredential.idTrapdoor.inHex()
echo "your rln identity nullifier is: ", node.wakuRlnRelay.identityCredential.idNullifier.inHex()
echo "your rln identity secret hash is: ", node.wakuRlnRelay.identityCredential.idSecretHash.inHex()
echo "your rln identity commitment key is: ", node.wakuRlnRelay.identityCredential.idCommitment.inHex()
let membershipIndex = node.wakuRlnRelay.groupManager.membershipIndex.get()
let identityCredential = node.wakuRlnRelay.groupManager.idCredentials.get()
echo "your membership index is: ", membershipIndex
echo "your rln identity trapdoor is: ", identityCredential.idTrapdoor.inHex()
echo "your rln identity nullifier is: ", identityCredential.idNullifier.inHex()
echo "your rln identity secret hash is: ", identityCredential.idSecretHash.inHex()
echo "your rln identity commitment key is: ", identityCredential.idCommitment.inHex()
else:
info "WakuRLNRelay is disabled"
if conf.rlnRelay:
Expand Down
2 changes: 1 addition & 1 deletion apps/wakunode2/wakunode2.nim
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ proc setupProtocols(node: WakuNode, conf: WakuNodeConf,
rlnRelayDynamic: conf.rlnRelayDynamic,
rlnRelayPubsubTopic: conf.rlnRelayPubsubTopic,
rlnRelayContentTopic: conf.rlnRelayContentTopic,
rlnRelayMembershipIndex: conf.rlnRelayMembershipIndex,
rlnRelayMembershipIndex: some(conf.rlnRelayMembershipIndex),
rlnRelayEthContractAddress: conf.rlnRelayEthContractAddress,
rlnRelayEthClientAddress: conf.rlnRelayEthClientAddress,
rlnRelayEthAccountPrivateKey: conf.rlnRelayEthAccountPrivateKey,
Expand Down
3 changes: 2 additions & 1 deletion tests/all_tests_v2.nim
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ when defined(rln):
import
./v2/test_waku_rln_relay,
./v2/test_wakunode_rln_relay,
./v2/test_waku_rln_relay_onchain
./v2/test_rln_group_manager_onchain,
./v2/test_rln_group_manager_static

# Waku swap test suite
import
Expand Down
218 changes: 176 additions & 42 deletions tests/v2/test_rln_group_manager_onchain.nim
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
{.used.}

when (NimMajor, NimMinor) < (1, 4):
{.push raises: [Defect].}
else:
{.push raises: [].}

import
std/[options, osproc, streams, strutils, sequtils],
stew/results,
stew/[results, byteutils],
stew/shims/net as stewNet,
testutils/unittests,
chronos,
Expand All @@ -25,8 +27,6 @@ import
./testlib/common,
./test_utils

from posix import kill, SIGINT

proc generateCredentials(rlnInstance: ptr RLN): IdentityCredential =
let credRes = membershipKeyGen(rlnInstance)
return credRes.get()
Expand Down Expand Up @@ -145,20 +145,18 @@ proc runGanache(): Process =
proc stopGanache(runGanache: Process) {.used.} =

let ganachePID = runGanache.processID

# We gracefully terminate Ganache daemon by sending a SIGINT signal to the runGanache PID to trigger RPC server termination and clean-up
let returnCodeSIGINT = kill(ganachePID.int32, SIGINT)
debug "Sent SIGINT to Ganache", ganachePID=ganachePID, returnCode=returnCodeSIGINT

# We wait the daemon to exit
try:
let returnCodeExit = runGanache.waitForExit()
debug "Ganache daemon terminated", returnCode=returnCodeExit
debug "Ganache daemon run log", log=runGanache.outputstream.readAll()
# We terminate Ganache daemon by sending a SIGTERM signal to the runGanache PID to trigger RPC server termination and clean-up
terminate(runGanache)
# NOTE: the below line must remain commented out, otherwise it will cause a deadlocked state
# ref: https://nim-lang.org/docs/osproc.html#waitForExit%2CProcess%2Cint
# debug "ganache logs", logs=runGanache.outputstream.readAll()
debug "Sent SIGTERM to Ganache", ganachePID=ganachePID
except:
error "Ganache daemon termination failed"
error "Ganache daemon termination failed: ", err = getCurrentExceptionMsg()

proc setup(): Future[OnchainGroupManager] {.async.} =
proc setup(signer = true): Future[OnchainGroupManager] {.async.} =
let rlnInstanceRes = createRlnInstance()
require:
rlnInstanceRes.isOk()
Expand All @@ -172,14 +170,16 @@ proc setup(): Future[OnchainGroupManager] {.async.} =
let accounts = await web3.provider.eth_accounts()
web3.defaultAccount = accounts[1]

let (pk, _) = await createEthAccount()

let onchainConfig = OnchainGroupManagerConfig(ethClientUrl: EthClient,
ethContractAddress: $contractAddress,
ethPrivateKey: some($pk))
var pk = none(string)
if signer:
let (privateKey, _) = await createEthAccount()
pk = some($privateKey)

let manager {.used.} = OnchainGroupManager(config: onchainConfig,
rlnInstance: rlnInstance)
let manager = OnchainGroupManager(ethClientUrl: EthClient,
ethContractAddress: $contractAddress,
ethPrivateKey: pk,
rlnInstance: rlnInstance,
saveKeystore: false)

return manager

Expand All @@ -192,9 +192,9 @@ suite "Onchain group manager":
await manager.init()

check:
manager.config.ethRpc.isSome()
manager.config.rlnContract.isSome()
manager.config.membershipFee.isSome()
manager.ethRpc.isSome()
manager.rlnContract.isSome()
manager.membershipFee.isSome()
manager.initialized

asyncTest "startGroupSync: should start group sync":
Expand All @@ -211,31 +211,30 @@ suite "Onchain group manager":

asyncTest "startGroupSync: should sync to the state of the group":
let manager = await setup()
let credentials = generateCredentials(manager.rlnInstance)

manager.idCredentials = some(credentials)
await manager.init()

let merkleRootBeforeRes = manager.rlnInstance.getMerkleRoot()
require:
merkleRootBeforeRes.isOk()
let merkleRootBefore = merkleRootBeforeRes.get()

let future = newFuture[void]("startGroupSync")
let fut = newFuture[void]("startGroupSync")

proc generateCallback(fut: Future[void], idCommitment: IDCommitment): OnRegisterCallback =
proc generateCallback(fut: Future[void]): OnRegisterCallback =
proc callback(registrations: seq[Membership]): Future[void] {.async.} =
require:
registrations.len == 1
registrations[0].idCommitment == idCommitment
registrations[0].idCommitment == manager.idCredentials.get().idCommitment
registrations[0].index == 0
fut.complete()
return callback

manager.onRegister(generateCallback(future, credentials.idCommitment))
manager.onRegister(generateCallback(fut))

await manager.startGroupSync()

await future
await fut

let merkleRootAfterRes = manager.rlnInstance.getMerkleRoot()
require:
Expand All @@ -260,12 +259,11 @@ suite "Onchain group manager":
proc generateCallback(futs: array[0..4, Future[system.void]], credentials: seq[IdentityCredential]): OnRegisterCallback =
var futureIndex = 0
proc callback(registrations: seq[Membership]): Future[void] {.async.} =
require:
registrations.len == 1
registrations[0].idCommitment == credentials[futureIndex].idCommitment
registrations[0].index == MembershipIndex(futureIndex)
futs[futureIndex].complete()
futureIndex += 1
if registrations.len == 1 and
registrations[0].idCommitment == credentials[futureIndex].idCommitment and
registrations[0].index == MembershipIndex(futureIndex + 1):
futs[futureIndex].complete()
futureIndex += 1
return callback

manager.onRegister(generateCallback(futures, credentials))
Expand All @@ -292,7 +290,7 @@ suite "Onchain group manager":
await manager.register(dummyCommitment)

asyncTest "register: should register successfully":
let manager = await setup()
let manager = await setup(false)
await manager.init()
await manager.startGroupSync()

Expand All @@ -311,9 +309,8 @@ suite "Onchain group manager":
manager.latestIndex == 1

asyncTest "register: callback is called":
let manager = await setup()
let manager = await setup(false)

var callbackCalled = false
let idCommitment = generateCredentials(manager.rlnInstance).idCommitment

let fut = newFuture[void]()
Expand All @@ -323,7 +320,6 @@ suite "Onchain group manager":
registrations.len == 1
registrations[0].idCommitment == idCommitment
registrations[0].index == 0
callbackCalled = true
fut.complete()

manager.onRegister(callback)
Expand All @@ -333,8 +329,6 @@ suite "Onchain group manager":
await manager.register(idCommitment)

await fut
check:
callbackCalled

asyncTest "withdraw: should guard against uninitialized state":
let manager = await setup()
Expand All @@ -343,6 +337,146 @@ suite "Onchain group manager":
expect(ValueError):
await manager.withdraw(idSecretHash)

asyncTest "validateRoot: should validate good root":
let manager = await setup()
await manager.init()

let fut = newFuture[void]()

proc callback(registrations: seq[Membership]): Future[void] {.async.} =
if registrations.len == 1 and
registrations[0].idCommitment == manager.idCredentials.get().idCommitment and
registrations[0].index == 0:
fut.complete()

manager.onRegister(callback)

await manager.startGroupSync()
await fut

let messageBytes = "Hello".toBytes()

# prepare the epoch
let epoch = default(Epoch)
debug "epoch in bytes", epochHex = epoch.inHex()

# generate proof
let validProofRes = manager.generateProof(data = messageBytes,
epoch = epoch)
require:
validProofRes.isOk()
let validProof = validProofRes.get()

# validate the root (should be true)
let validated = manager.validateRoot(validProof.merkleRoot)

check:
validated

asyncTest "validateRoot: should reject bad root":
let manager = await setup()
await manager.init()
await manager.startGroupSync()

let idCredential = generateCredentials(manager.rlnInstance)

## Assume the registration occured out of band
manager.idCredentials = some(idCredential)
manager.membershipIndex = some(MembershipIndex(0))

let messageBytes = "Hello".toBytes()

# prepare the epoch
let epoch = default(Epoch)
debug "epoch in bytes", epochHex = epoch.inHex()

# generate proof
let validProofRes = manager.generateProof(data = messageBytes,
epoch = epoch)
require:
validProofRes.isOk()
let validProof = validProofRes.get()

# validate the root (should be false)
let validated = manager.validateRoot(validProof.merkleRoot)

check:
validated == false

asyncTest "verifyProof: should verify valid proof":
let manager = await setup()
await manager.init()

let fut = newFuture[void]()

proc callback(registrations: seq[Membership]): Future[void] {.async.} =
if registrations.len == 1 and
registrations[0].idCommitment == manager.idCredentials.get().idCommitment and
registrations[0].index == 0:
fut.complete()

manager.onRegister(callback)

await manager.startGroupSync()
await fut

let messageBytes = "Hello".toBytes()

# prepare the epoch
let epoch = default(Epoch)
debug "epoch in bytes", epochHex = epoch.inHex()

# generate proof
let validProofRes = manager.generateProof(data = messageBytes,
epoch = epoch)
require:
validProofRes.isOk()
let validProof = validProofRes.get()

# verify the proof (should be true)
let verifiedRes = manager.verifyProof(messageBytes, validProof)
require:
verifiedRes.isOk()

check:
verifiedRes.get()

asyncTest "verifyProof: should reject invalid proof":
let manager = await setup()
await manager.init()
await manager.startGroupSync()

let idCredential = generateCredentials(manager.rlnInstance)
await manager.register(idCredential.idCommitment)

let idCredential2 = generateCredentials(manager.rlnInstance)

## Assume the registration occured out of band
manager.idCredentials = some(idCredential2)
manager.membershipIndex = some(MembershipIndex(0))

let messageBytes = "Hello".toBytes()

# prepare the epoch
let epoch = default(Epoch)
debug "epoch in bytes", epochHex = epoch.inHex()

# generate proof
let invalidProofRes = manager.generateProof(data = messageBytes,
epoch = epoch)
require:
invalidProofRes.isOk()
let invalidProof = invalidProofRes.get()


# verify the proof (should be false)
let verifiedRes = manager.verifyProof(messageBytes, invalidProof)
require:
verifiedRes.isOk()

check:
verifiedRes.get() == false

################################
## Terminating/removing Ganache
################################
Expand Down
Loading

0 comments on commit 2f883f8

Please sign in to comment.