chore(rln-relay): remove all raises and replace with Result types (#1321)

* chore(rln-relay): remove all raises and replace with Result types

* chore(rln-relay): s/var/let

* chore(rln-relay): s/isOk/isOk()

* fix(rln-relay): proc def comments about the result type

Co-authored-by: Lorenzo Delgado <lorenzo@status.im>
This commit is contained in:
Aaryamann Challani 2022-11-04 08:30:42 +05:30 committed by GitHub
parent d1df046c87
commit 53e8979aa9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 631 additions and 395 deletions

View File

@ -541,8 +541,8 @@ proc processInput(rfd: AsyncFD) {.async.} =
echo "You are registered to the rln membership contract, find details of your registration transaction in https://goerli.etherscan.io/tx/0x", txHash
echo "rln-relay preparation is in progress..."
let res = node.mountRlnRelay(conf = conf, spamHandler = some(spamHandler), registrationHandler = some(registrationHandler))
if res.isErr:
let res = await node.mountRlnRelay(conf = conf, spamHandler = some(spamHandler), registrationHandler = some(registrationHandler))
if res.isErr():
echo "failed to mount rln-relay: " & res.error()
else:
echo "your membership index is: ", node.wakuRlnRelay.membershipIndex

View File

@ -363,7 +363,7 @@ proc setupProtocols(node: WakuNode, conf: WakuNodeConf,
when defined(rln) or defined(rlnzerokit):
if conf.rlnRelay:
try:
let res = node.mountRlnRelay(conf)
let res = await node.mountRlnRelay(conf)
if res.isErr():
return err("failed to mount waku RLN relay protocol: " & res.error)
except:

View File

@ -30,13 +30,21 @@ procSuite "Waku rln relay":
# preparing inputs to mount rln-relay
# create a group of 100 membership keys
let
(groupKeys, root) = createMembershipList(100)
let memListRes = createMembershipList(100)
require:
memListRes.isOk()
let (groupKeys, root) = memListRes.get()
check:
groupKeys.len == 100
groupKeys.len == 100
let
# convert the keys to MembershipKeyPair structs
groupKeyPairs = groupKeys.toMembershipKeyPairs()
groupKeyPairsRes = groupKeys.toMembershipKeyPairs()
require:
groupKeyPairsRes.isOk()
let
groupKeyPairs = groupKeyPairsRes.get()
# extract the id commitments
groupIDCommitments = groupKeyPairs.mapIt(it.idCommitment)
debug "groupKeyPairs", groupKeyPairs
@ -49,11 +57,13 @@ procSuite "Waku rln relay":
# -------- mount rln-relay in the off-chain mode
await node.mountRelay(@[RlnRelayPubsubTopic])
node.mountRlnRelayStatic(group = groupIDCommitments,
let mountRes = node.mountRlnRelayStatic(group = groupIDCommitments,
memKeyPair = groupKeyPairs[index],
memIndex = index,
pubsubTopic = RlnRelayPubsubTopic,
contentTopic = RlnRelayContentTopic)
require:
mountRes.isOk()
# get the root of Merkle tree which is constructed inside the mountRlnRelay proc
let calculatedRoot = node.wakuRlnRelay.rlnInstance.getMerkleRoot().value().inHex
@ -115,15 +125,15 @@ suite "Waku rln relay":
var
merkleDepth: csize_t = 20
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
# keysBufferPtr will hold the generated key pairs i.e., secret and public keys
var
keysBuffer: Buffer
keysBufferPtr = addr(keysBuffer)
done = key_gen(rlnInstance.value(), keysBufferPtr)
done = key_gen(rlnInstance.get(), keysBufferPtr)
check:
# check whether the keys are generated successfully
done == true
@ -135,45 +145,48 @@ suite "Waku rln relay":
generatedKeys.len == 64
debug "generated keys: ", generatedKeys
test "membership Key Gen":
test "membership Key Generation":
# create an RLN instance
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
var key = membershipKeyGen(rlnInstance.value)
let keyPairRes = membershipKeyGen(rlnInstance.get())
require:
keyPairRes.isOk()
let keyPair = keyPairRes.get()
var empty: array[32, byte]
check:
key.isSome
key.get().idKey.len == 32
key.get().idCommitment.len == 32
key.get().idKey != empty
key.get().idCommitment != empty
keyPair.idKey.len == 32
keyPair.idCommitment.len == 32
keyPair.idKey != empty
keyPair.idCommitment != empty
debug "the generated membership key pair: ", key
debug "the generated membership key pair: ", keyPair
test "get_root Nim binding":
test "getRoot Nim binding":
# create an RLN instance which also includes an empty Merkle tree
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
# read the Merkle Tree root
var
root1 {.noinit.}: Buffer = Buffer()
rootPtr1 = addr(root1)
get_root_successful1 = get_root(rlnInstance.value, rootPtr1)
getRootSuccessful1 = getRoot(rlnInstance.get(), rootPtr1)
check:
get_root_successful1
getRootSuccessful1
root1.len == 32
# read the Merkle Tree root
var
root2 {.noinit.}: Buffer = Buffer()
rootPtr2 = addr(root2)
get_root_successful2 = get_root(rlnInstance.value, rootPtr2)
getRootSuccessful2 = getRoot(rlnInstance.get(), rootPtr2)
check:
get_root_successful2
getRootSuccessful2
root2.len == 32
var rootValue1 = cast[ptr array[32, byte]] (root1.`ptr`)
@ -187,20 +200,21 @@ suite "Waku rln relay":
rootHex1 == rootHex2
test "getMerkleRoot utils":
# create an RLN instance which also includes an empty Merkle tree
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
let rln = rlnInstance.get()
# read the Merkle Tree root
var root1 = getMerkleRoot(rlnInstance.value())
check:
root1.isOk
var root1 = getMerkleRoot(rln)
require:
root1.isOk()
let rootHex1 = root1.value().inHex
# read the Merkle Tree root
var root2 = getMerkleRoot(rlnInstance.value())
check:
root2.isOk
var root2 = getMerkleRoot(rln)
require:
root2.isOk()
let rootHex2 = root2.value().inHex
# the two roots must be identical
@ -209,163 +223,173 @@ suite "Waku rln relay":
test "update_next_member Nim Wrapper":
# create an RLN instance which also includes an empty Merkle tree
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
let rln = rlnInstance.get()
# generate a key pair
var keypair = membershipKeyGen(rlnInstance.value)
check:
keypair.isSome()
var pkBuffer = toBuffer(keypair.get().idCommitment)
let keyPairRes = membershipKeyGen(rln)
require:
keypairRes.isOk()
let keyPair = keyPairRes.get()
var pkBuffer = toBuffer(keyPair.idCommitment)
let pkBufferPtr = addr pkBuffer
# add the member to the tree
var member_is_added = update_next_member(rlnInstance.value, pkBufferPtr)
let memberAdded = updateNextMember(rln, pkBufferPtr)
check:
member_is_added == true
memberAdded
test "delete_member Nim wrapper":
# create an RLN instance which also includes an empty Merkle tree
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
# delete the first member
var deleted_member_index = MembershipIndex(0)
let deletion_success = delete_member(rlnInstance.value, deleted_member_index)
let deletedMemberIndex = MembershipIndex(0)
let deletionSuccess = deleteMember(rlnInstance.get(), deletedMemberIndex)
check:
deletion_success
deletionSuccess
test "insertMember rln utils":
# create an RLN instance which also includes an empty Merkle tree
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
var rln = rlnInstance.value
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
let rln = rlnInstance.get()
# generate a key pair
var keypair = rln.membershipKeyGen()
let keyPairRes = rln.membershipKeyGen()
require:
keypairRes.isOk()
check:
keypair.isSome()
check:
rln.insertMember(keypair.get().idCommitment)
rln.insertMember(keyPairRes.get().idCommitment)
test "removeMember rln utils":
# create an RLN instance which also includes an empty Merkle tree
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
var rln = rlnInstance.value
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
let rln = rlnInstance.get()
check:
rln.removeMember(MembershipIndex(0))
test "Merkle tree consistency check between deletion and insertion":
# create an RLN instance
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
let rln = rlnInstance.get()
# read the Merkle Tree root
var
root1 {.noinit.}: Buffer = Buffer()
rootPtr1 = addr(root1)
get_root_successful1 = get_root(rlnInstance.value, rootPtr1)
check:
get_root_successful1
getRootSuccessful1 = getRoot(rln, rootPtr1)
require:
getRootSuccessful1
root1.len == 32
# generate a key pair
var keypair = membershipKeyGen(rlnInstance.value)
check: keypair.isSome()
var pkBuffer = toBuffer(keypair.get().idCommitment)
let keyPairRes = membershipKeyGen(rln)
require:
keypairRes.isOk()
let keyPair = keyPairRes.get()
var pkBuffer = toBuffer(keyPair.idCommitment)
let pkBufferPtr = addr pkBuffer
# add the member to the tree
var member_is_added = update_next_member(rlnInstance.value, pkBufferPtr)
check:
member_is_added
let memberAdded = updateNextMember(rln, pkBufferPtr)
require:
memberAdded
# read the Merkle Tree root after insertion
var
root2 {.noinit.}: Buffer = Buffer()
rootPtr2 = addr(root2)
get_root_successful2 = get_root(rlnInstance.value, rootPtr2)
check:
get_root_successful2
getRootSuccessful = getRoot(rln, rootPtr2)
require:
getRootSuccessful
root2.len == 32
# delete the first member
var deleted_member_index = MembershipIndex(0)
let deletion_success = delete_member(rlnInstance.value, deleted_member_index)
check:
deletion_success
let deletedMemberIndex = MembershipIndex(0)
let deletionSuccess = deleteMember(rln, deletedMemberIndex)
require:
deletionSuccess
# read the Merkle Tree root after the deletion
var
root3 {.noinit.}: Buffer = Buffer()
rootPtr3 = addr(root3)
get_root_successful3 = get_root(rlnInstance.value, rootPtr3)
check:
get_root_successful3
getRootSuccessful3 = getRoot(rln, rootPtr3)
require:
getRootSuccessful3
root3.len == 32
var rootValue1 = cast[ptr array[32, byte]] (root1.`ptr`)
let rootValue1 = cast[ptr array[32, byte]] (root1.`ptr`)
let rootHex1 = rootValue1[].inHex
debug "The initial root", rootHex1
var rootValue2 = cast[ptr array[32, byte]] (root2.`ptr`)
let rootValue2 = cast[ptr array[32, byte]] (root2.`ptr`)
let rootHex2 = rootValue2[].inHex
debug "The root after insertion", rootHex2
var rootValue3 = cast[ptr array[32, byte]] (root3.`ptr`)
let rootValue3 = cast[ptr array[32, byte]] (root3.`ptr`)
let rootHex3 = rootValue3[].inHex
debug "The root after deletion", rootHex3
# the root must change after the insertion
check: not(rootHex1 == rootHex2)
check:
not(rootHex1 == rootHex2)
## The initial root of the tree (empty tree) must be identical to
## the root of the tree after one insertion followed by a deletion
check:
rootHex1 == rootHex3
test "Merkle tree consistency check between deletion and insertion using rln utils":
# create an RLN instance
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
var rln = rlnInstance.value()
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
let rln = rlnInstance.get()
# read the Merkle Tree root
var root1 = rln.getMerkleRoot()
check:
root1.isOk
let root1 = rln.getMerkleRoot()
require:
root1.isOk()
let rootHex1 = root1.value().inHex()
# generate a key pair
var keypair = rln.membershipKeyGen()
check:
keypair.isSome()
let member_inserted = rln.insertMember(keypair.get().idCommitment)
check:
member_inserted
let keyPairRes = rln.membershipKeyGen()
require:
keyPairRes.isOk()
let memberInserted = rln.insertMember(keypairRes.get().idCommitment)
require:
memberInserted
# read the Merkle Tree root after insertion
var root2 = rln.getMerkleRoot()
check:
root2.isOk
let root2 = rln.getMerkleRoot()
require:
root2.isOk()
let rootHex2 = root2.value().inHex()
# delete the first member
var deleted_member_index = MembershipIndex(0)
let deletion_success = rln.removeMember(deleted_member_index)
check:
deletion_success
let deletedMemberIndex = MembershipIndex(0)
let deletionSuccess = rln.removeMember(deletedMemberIndex)
require:
deletionSuccess
# read the Merkle Tree root after the deletion
var root3 = rln.getMerkleRoot()
check:
root3.isOk
let root3 = rln.getMerkleRoot()
require:
root3.isOk()
let rootHex3 = root3.value().inHex()
@ -384,9 +408,9 @@ suite "Waku rln relay":
test "hash Nim Wrappers":
# create an RLN instance
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
# prepare the input
var
@ -397,7 +421,7 @@ suite "Waku rln relay":
# prepare other inputs to the hash function
var outputBuffer: Buffer
let hashSuccess = hash(rlnInstance.value, addr hashInputBuffer,
let hashSuccess = hash(rlnInstance.get(), addr hashInputBuffer,
addr outputBuffer)
check:
hashSuccess
@ -420,10 +444,10 @@ suite "Waku rln relay":
test "hash utils":
# create an RLN instance
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
let rln = rlnInstance.value
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
let rln = rlnInstance.get()
# prepare the input
let msg = "Hello".toBytes()
@ -442,7 +466,12 @@ suite "Waku rln relay":
test "create a list of membership keys and construct a Merkle tree based on the list":
let
groupSize = 100
(list, root) = createMembershipList(groupSize)
memListRes = createMembershipList(groupSize)
require:
memListRes.isOk()
let (list, root) = memListRes.get()
debug "created membership key list", list
debug "the Merkle tree root", root
@ -455,11 +484,20 @@ suite "Waku rln relay":
let groupKeys = StaticGroupKeys
# create a set of MembershipKeyPair objects from groupKeys
let groupKeyPairs = groupKeys.toMembershipKeyPairs()
let groupKeyPairsRes = groupKeys.toMembershipKeyPairs()
require:
groupKeyPairsRes.isOk()
let groupKeyPairs = groupKeyPairsRes.get()
# extract the id commitments
let groupIDCommitments = groupKeyPairs.mapIt(it.idCommitment)
# calculate the Merkle tree root out of the extracted id commitments
let root = calcMerkleRoot(groupIDCommitments)
let rootRes = calcMerkleRoot(groupIDCommitments)
require:
rootRes.isOk()
let root = rootRes.get()
debug "groupKeyPairs", groupKeyPairs
debug "groupIDCommitments", groupIDCommitments
@ -538,30 +576,37 @@ suite "Waku rln relay":
decodednsp.value == rateLimitProof
test "test proofVerify and proofGen for a valid proof":
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk
var rln = rlnInstance.value
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
let rln = rlnInstance.get()
let
# create a membership key pair
memKeys = membershipKeyGen(rln).get()
# peer's index in the Merkle Tree
index = 5
# create a membership key pair
memKeysRes = membershipKeyGen(rln)
require:
memKeysRes.isOk()
let memKeys = memKeysRes.get()
# Create a Merkle tree with random members
for i in 0..10:
var member_is_added: bool = false
var memberAdded: bool = false
if (i == index):
# insert the current peer's pk
member_is_added = rln.insertMember(memKeys.idCommitment)
memberAdded = rln.insertMember(memKeys.idCommitment)
else:
# create a new key pair
let memberKeys = rln.membershipKeyGen()
member_is_added = rln.insertMember(memberKeys.get().idCommitment)
let memberKeysRes = rln.membershipKeyGen()
require:
memberKeysRes.isOk()
memberAdded = rln.insertMember(memberKeysRes.get().idCommitment)
# check the member is added
check:
member_is_added
require:
memberAdded
# prepare the message
let messageBytes = "Hello".toBytes()
@ -590,30 +635,37 @@ suite "Waku rln relay":
verified.value() == true
test "test proofVerify and proofGen for an invalid proof":
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
var rln = rlnInstance.value
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
let rln = rlnInstance.get()
let
# create a membership key pair
memKeys = membershipKeyGen(rln).get()
# peer's index in the Merkle Tree
index = 5
# create a membership key pair
memKeysRes = membershipKeyGen(rln)
require:
memKeysRes.isOk()
let memKeys = memKeysRes.get()
# Create a Merkle tree with random members
for i in 0..10:
var member_is_added: bool = false
var memberAdded: bool = false
if (i == index):
# insert the current peer's pk
member_is_added = rln.insertMember(memKeys.idCommitment)
memberAdded = rln.insertMember(memKeys.idCommitment)
else:
# create a new key pair
let memberKeys = rln.membershipKeyGen()
member_is_added = rln.insertMember(memberKeys.get().idCommitment)
let memberKeysRes = rln.membershipKeyGen()
require:
memberKeysRes.isOk()
memberAdded = rln.insertMember(memberKeysRes.get().idCommitment)
# check the member is added
check:
member_is_added
require:
memberAdded
# prepare the message
let messageBytes = "Hello".toBytes()
@ -648,18 +700,23 @@ suite "Waku rln relay":
# This step consists of creating the rln instance and waku-rln-relay,
# Inserting members, and creating a valid proof with the merkle root
# create an RLN instance
var rlnInstance = createRLNInstance()
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
var rln = rlnInstance.value
let rln = rlnInstance.get()
let rlnRelay = WakuRLNRelay(rlnInstance:rln)
let
# create a membership key pair
memKeys = membershipKeyGen(rlnRelay.rlnInstance).get()
# peer's index in the Merkle Tree.
index = 5
# create a membership key pair
memKeysRes = membershipKeyGen(rlnRelay.rlnInstance)
require:
memKeysRes.isOk()
let memKeys = memKeysRes.get()
let membershipCount = AcceptableRootWindowSize + 5
@ -671,8 +728,10 @@ suite "Waku rln relay":
memberIsAdded = rlnRelay.insertMember(memKeys.idCommitment)
else:
# create a new key pair
let memberKeys = rlnRelay.rlnInstance.membershipKeyGen()
memberIsAdded = rlnRelay.insertMember(memberKeys.get().idCommitment)
let memberKeysRes = rlnRelay.rlnInstance.membershipKeyGen()
require:
memberKeysRes.isOk()
memberIsAdded = rlnRelay.insertMember(memberKeysRes.get().idCommitment)
# require that the member is added
require:
memberIsAdded.isOk()
@ -733,18 +792,23 @@ suite "Waku rln relay":
AcceptableRootWindowSize < 10
# create an RLN instance
var rlnInstance = createRLNInstance()
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
var rln = rlnInstance.value
let rln = rlnInstance.get()
let rlnRelay = WakuRLNRelay(rlnInstance:rln)
let
# create a membership key pair
memKeys = membershipKeyGen(rlnRelay.rlnInstance).get()
# peer's index in the Merkle Tree.
index = 6
# create a membership key pair
memKeysRes = membershipKeyGen(rlnRelay.rlnInstance)
require:
memKeysRes.isOk()
let memKeys = memKeysRes.get()
let membershipCount = AcceptableRootWindowSize + 5
@ -756,8 +820,10 @@ suite "Waku rln relay":
memberIsAdded = rlnRelay.insertMember(memKeys.idCommitment)
else:
# create a new key pair
let memberKeys = rlnRelay.rlnInstance.membershipKeyGen()
memberIsAdded = rlnRelay.insertMember(memberKeys.get().idCommitment)
let memberKeysRes = rlnRelay.rlnInstance.membershipKeyGen()
require:
memberKeysRes.isOk()
memberIsAdded = rlnRelay.insertMember(memberKeysRes.get().idCommitment)
# require that the member is added
require:
memberIsAdded.isOk()
@ -865,8 +931,8 @@ suite "Waku rln relay":
# check whether hasDuplicate correctly finds records with the same nullifiers but different secret shares
# no duplicate for wm1 should be found, since the log is empty
let result1 = wakurlnrelay.hasDuplicate(wm1)
check:
result1.isOk
require:
result1.isOk()
# no duplicate is found
result1.value == false
# add it to the log
@ -874,8 +940,8 @@ suite "Waku rln relay":
# # no duplicate for wm2 should be found, its nullifier differs from wm1
let result2 = wakurlnrelay.hasDuplicate(wm2)
check:
result2.isOk
require:
result2.isOk()
# no duplicate is found
result2.value == false
# add it to the log
@ -884,7 +950,7 @@ suite "Waku rln relay":
# wm3 has the same nullifier as wm1 but different secret shares, it should be detected as duplicate
let result3 = wakurlnrelay.hasDuplicate(wm3)
check:
result3.isOk
result3.isOk()
# it is a duplicate
result3.value == true
@ -892,12 +958,21 @@ suite "Waku rln relay":
# setup a wakurlnrelay peer with a static group----------
# create a group of 100 membership keys
let
(groupKeys, root) = createMembershipList(100)
let memListRes = createMembershipList(100)
require:
memListRes.isOk()
let
(groupKeys, _) = memListRes.get()
# convert the keys to MembershipKeyPair structs
groupKeyPairs = groupKeys.toMembershipKeyPairs()
# extract the id commitments
groupIDCommitments = groupKeyPairs.mapIt(it.idCommitment)
groupKeyPairsRes = groupKeys.toMembershipKeyPairs()
require:
groupKeyPairsRes.isOk()
let groupKeyPairs = groupKeyPairsRes.get()
# extract the id commitments
let groupIDCommitments = groupKeyPairs.mapIt(it.idCommitment)
debug "groupKeyPairs", groupKeyPairs
debug "groupIDCommitments", groupIDCommitments
@ -907,9 +982,10 @@ suite "Waku rln relay":
let index = MembershipIndex(5)
# create an RLN instance
var rlnInstance = createRLNInstance()
doAssert(rlnInstance.isOk)
var rln = rlnInstance.value
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
let rln = rlnInstance.get()
let
wakuRlnRelay = WakuRLNRelay(membershipIndex: index,
@ -961,46 +1037,52 @@ suite "Waku rln relay":
test "toIDCommitment and toUInt256":
# create an instance of rln
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
let rln = rlnInstance.get()
# create a key pair
var keypair = rlnInstance.value.membershipKeyGen()
check:
keypair.isSome()
let keyPairRes = rln.membershipKeyGen()
require:
keyPairRes.isOk()
let keyPair = keyPairRes.get()
# convert the idCommitment to UInt256
let idCUInt = keypair.get().idCommitment.toUInt256()
let idCUInt = keypair.idCommitment.toUInt256()
# convert the UInt256 back to ICommitment
let idCommitment = toIDCommitment(idCUInt)
# check that the conversion has not distorted the original value
check:
keypair.get().idCommitment == idCommitment
keypair.idCommitment == idCommitment
test "Read/Write RLN credentials":
# create an RLN instance
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
var key = membershipKeyGen(rlnInstance.value)
let keyPairRes = membershipKeyGen(rlnInstance.get())
require:
keyPairRes.isOk()
let keyPair = keyPairRes.get()
var empty: array[32, byte]
check:
key.isSome
key.get().idKey.len == 32
key.get().idCommitment.len == 32
key.get().idKey != empty
key.get().idCommitment != empty
keyPair.idKey.len == 32
keyPair.idCommitment.len == 32
keyPair.idKey != empty
keyPair.idCommitment != empty
debug "the generated membership key pair: ", key
debug "the generated membership key pair: ", keyPair
let
k = key.get()
index = MembershipIndex(1)
let index = MembershipIndex(1)
var rlnMembershipCredentials = RlnMembershipCredentials(membershipKeyPair: k, rlnIndex: index)
let rlnMembershipCredentials = RlnMembershipCredentials(membershipKeyPair: keyPair,
rlnIndex: index)
let password = "%m0um0ucoW%"
@ -1008,7 +1090,7 @@ suite "Waku rln relay":
defer: removeFile(filepath)
# Write RLN credentials
check:
require:
writeRlnCredentials(filepath, rlnMembershipCredentials, password).isOk()
let readCredentialsResult = readRlnCredentials(filepath, password)
@ -1019,7 +1101,7 @@ suite "Waku rln relay":
check:
credentials.isSome()
credentials.get().membershipKeyPair == k
credentials.get().membershipKeyPair == keyPair
credentials.get().rlnIndex == index
test "histogram static bucket generation":

View File

@ -119,18 +119,19 @@ procSuite "Waku-rln-relay":
defaultAccount = web3.defaultAccount
# prepare a contract sender to interact with it
var contractObj = web3.contractSender(MembershipContract,
let contractObj = web3.contractSender(MembershipContract,
contractAddress) # creates a Sender object with a web3 field and contract address of type Address
# create an RLN instance
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
# generate the membership keys
let membershipKeyPair = membershipKeyGen(rlnInstance.value)
check:
membershipKeyPair.isSome
let pk = membershipKeyPair.get().idCommitment.toUInt256()
let membershipKeyPairRes = membershipKeyGen(rlnInstance.get())
require:
membershipKeyPairRes.isOk()
let membershipKeyPair = membershipKeyPairRes.get()
let pk = membershipKeyPair.idCommitment.toUInt256()
debug "membership commitment key", pk = pk
# test ------------------------------
@ -173,24 +174,25 @@ procSuite "Waku-rln-relay":
defaultAccount = web3.defaultAccount
# prepare a contract sender to interact with it
var contractObj = web3.contractSender(MembershipContract,
let contractObj = web3.contractSender(MembershipContract,
contractAddress) # creates a Sender object with a web3 field and contract address of type Address
# test ------------------------------
# create an RLN instance
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
var rln = rlnInstance.value
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
let rln = rlnInstance.get()
let keyPair = rln.membershipKeyGen()
check:
keyPair.isSome
let pk = keyPair.get().idCommitment.toUInt256()
let keyPairRes = rln.membershipKeyGen()
require:
keyPairRes.isOk()
let keypair = keyPairRes.get()
let pk = keyPair.idCommitment.toUInt256()
debug "membership commitment key", pk = pk
# initialize the WakuRLNRelay
var rlnPeer = WakuRLNRelay(membershipKeyPair: keyPair.get(),
let rlnPeer = WakuRLNRelay(membershipKeyPair: keyPair,
membershipIndex: MembershipIndex(0),
ethClientAddress: EthClient,
ethAccountAddress: some(accounts[0]),
@ -198,10 +200,11 @@ procSuite "Waku-rln-relay":
rlnInstance: rln)
# generate another membership key pair
let keyPair2 = rln.membershipKeyGen()
check:
keyPair2.isSome
let pk2 = keyPair2.get().idCommitment.toUInt256()
let keyPair2Res = rln.membershipKeyGen()
require:
keyPair2Res.isOk()
let keyPair2 = keyPair2Res.get()
let pk2 = keyPair2.idCommitment.toUInt256()
debug "membership commitment key", pk2 = pk2
var events = [newFuture[void](), newFuture[void]()]
@ -252,7 +255,7 @@ procSuite "Waku-rln-relay":
debug "contract deployer account address ", add
# prepare a contract sender to interact with it
var sender = web3.contractSender(MembershipContract,
let sender = web3.contractSender(MembershipContract,
contractAddress) # creates a Sender object with a web3 field and contract address of type Address
# send takes the following parameters, c: ContractCallBase, value = 0.u256, gas = 3000000'u64 gasPrice = 0
@ -277,27 +280,25 @@ procSuite "Waku-rln-relay":
# prepare rln-relay peer inputs
let
web3 = await newWeb3(EthClient)
accounts = await web3.provider.eth_accounts()
# choose one of the existing accounts for the rln-relay peer
ethAccountAddress = accounts[0]
await web3.close()
# create an RLN instance
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
# generate the membership keys
let membershipKeyPair = membershipKeyGen(rlnInstance.value)
check:
membershipKeyPair.isSome
let membershipKeyPairRes = membershipKeyGen(rlnInstance.get())
require:
membershipKeyPairRes.isOk()
let membershipKeyPair = membershipKeyPairRes.get()
# create an Ethereum private key and the corresponding account
let (ethPrivKey, ethacc) = await createEthAccount()
# test ------------------------------
# initialize the WakuRLNRelay
var rlnPeer = WakuRLNRelay(membershipKeyPair: membershipKeyPair.get(),
let rlnPeer = WakuRLNRelay(membershipKeyPair: membershipKeyPair,
membershipIndex: MembershipIndex(0),
ethClientAddress: EthClient,
ethAccountPrivateKey: some(ethPrivKey),
@ -305,9 +306,9 @@ procSuite "Waku-rln-relay":
membershipContractAddress: contractAddress)
# register the rln-relay peer to the membership contract
let is_successful = await rlnPeer.register()
let isSuccessful = await rlnPeer.register()
check:
is_successful.isOk
isSuccessful.isOk()
asyncTest "mounting waku rln-relay: check correct Merkle tree construction in the static/off-chain group management":
@ -318,34 +319,39 @@ procSuite "Waku-rln-relay":
await node.start()
# create current peer's pk
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
var rln = rlnInstance.value
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
let rln = rlnInstance.get()
# generate a key pair
var keypair = rln.membershipKeyGen()
doAssert(keypair.isSome())
let keyPairRes = rln.membershipKeyGen()
require:
keyPairRes.isOk()
let keyPair = keyPairRes.get()
# current peer index in the Merkle tree
let index = uint(5)
# Create a group of 10 members
var group = newSeq[IDCommitment]()
for i in 0..10:
var member_is_added: bool = false
var memberAdded: bool = false
if (uint(i) == index):
# insert the current peer's pk
group.add(keypair.get().idCommitment)
member_is_added = rln.insertMember(keypair.get().idCommitment)
doAssert(member_is_added)
debug "member key", key = keypair.get().idCommitment.inHex
group.add(keyPair.idCommitment)
memberAdded = rln.insertMember(keyPair.idCommitment)
doAssert(memberAdded)
debug "member key", key = keyPair.idCommitment.inHex
else:
var memberKeypair = rln.membershipKeyGen()
doAssert(memberKeypair.isSome())
group.add(memberKeypair.get().idCommitment)
member_is_added = rln.insertMember(memberKeypair.get().idCommitment)
doAssert(member_is_added)
debug "member key", key = memberKeypair.get().idCommitment.inHex
let memberKeyPairRes = rln.membershipKeyGen()
require:
memberKeyPairRes.isOk()
let memberKeyPair = memberKeyPairRes.get()
group.add(memberKeyPair.idCommitment)
let memberAdded = rln.insertMember(memberKeyPair.idCommitment)
require:
memberAdded
debug "member key", key = memberKeyPair.idCommitment.inHex
let expectedRoot = rln.getMerkleRoot().value().inHex
debug "expected root ", expectedRoot
@ -353,11 +359,15 @@ procSuite "Waku-rln-relay":
# test ------------------------------
# start rln-relay
await node.mountRelay(@[RlnRelayPubsubTopic])
node.mountRlnRelayStatic(group = group,
memKeyPair = keypair.get(),
let mountRes = node.mountRlnRelayStatic(group = group,
memKeyPair = keyPair,
memIndex = index,
pubsubTopic = RlnRelayPubsubTopic,
contentTopic = RlnRelayContentTopic)
require:
mountRes.isOk()
let calculatedRoot = node.wakuRlnRelay.rlnInstance.getMerkleRoot().value().inHex
debug "calculated root ", calculatedRoot
@ -387,36 +397,41 @@ procSuite "Waku-rln-relay":
# create an rln instance
var rlnInstance = createRLNInstance()
check:
rlnInstance.isOk == true
var rln = rlnInstance.value
let rlnInstance = createRLNInstance()
require:
rlnInstance.isOk()
let rln = rlnInstance.get()
# create two rln key pairs
let
keyPair1 = rln.membershipKeyGen()
keyPair2 = rln.membershipKeyGen()
check:
keyPair1.isSome
keyPair2.isSome
let
pk1 = keyPair1.get().idCommitment.toUInt256()
pk2 = keyPair2.get().idCommitment.toUInt256()
debug "member key1", key = keyPair1.get().idCommitment.inHex
debug "member key2", key = keyPair2.get().idCommitment.inHex
keyPair1Res = rln.membershipKeyGen()
keyPair2Res = rln.membershipKeyGen()
require:
keyPair1Res.isOk()
keyPair2Res.isOk()
let
keyPair1 = keyPair1Res.get()
keyPair2 = keyPair2Res.get()
pk1 = keyPair1.idCommitment.toUInt256()
pk2 = keyPair2.idCommitment.toUInt256()
debug "member key1", key = keyPair1.idCommitment.inHex
debug "member key2", key = keyPair2.idCommitment.inHex
# add the rln keys to the Merkle tree
let
member_is_added1 = rln.insertMember(keyPair1.get().idCommitment)
member_is_added2 = rln.insertMember(keyPair2.get().idCommitment)
doAssert(member_is_added1)
doAssert(member_is_added2)
memberIsAdded1 = rln.insertMember(keyPair1.idCommitment)
memberIsAdded2 = rln.insertMember(keyPair2.idCommitment)
require:
memberIsAdded1
memberIsAdded2
# get the Merkle root
let expectedRoot = rln.getMerkleRoot().value().inHex
# prepare a contract sender to interact with it
var contractObj = web3.contractSender(MembershipContract,
let contractObj = web3.contractSender(MembershipContract,
contractAddress) # creates a Sender object with a web3 field and contract address of type Address
# register the members to the contract
@ -438,7 +453,7 @@ procSuite "Waku-rln-relay":
ethAccountAddress = some(ethacc),
ethAccountPrivKeyOpt = some(ethPrivKey),
memContractAddr = contractAddress,
memKeyPair = keyPair1,
memKeyPair = some(keyPair1),
memIndex = some(MembershipIndex(0)),
pubsubTopic = RlnRelayPubsubTopic,
contentTopic = RlnRelayContentTopic)

View File

@ -50,35 +50,55 @@ procSuite "WakuNode - RLN relay":
# set up three nodes
# node1
await node1.mountRelay(@[rlnRelayPubSubTopic])
let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = rlnRelayStaticSetUp(1) # set up rln relay inputs
let staticSetupRes1 = rlnRelayStaticSetUp(1) # set up rln relay inputs
require:
staticSetupRes1.isOk()
let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = staticSetupRes1.get()
# mount rlnrelay in off-chain mode
node1.mountRlnRelayStatic(group = groupOpt1.get(),
let mountRes1 = node1.mountRlnRelayStatic(group = groupOpt1.get(),
memKeyPair = memKeyPairOpt1.get(),
memIndex = memIndexOpt1.get(),
pubsubTopic = rlnRelayPubSubTopic,
contentTopic = contentTopic)
require:
mountRes1.isOk()
await node1.start()
# node 2
await node2.mountRelay(@[rlnRelayPubSubTopic])
let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = rlnRelayStaticSetUp(2) # set up rln relay inputs
let staticSetupRes2 = rlnRelayStaticSetUp(2) # set up rln relay inputs
require:
staticSetupRes2.isOk()
let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = staticSetupRes2.get()
# mount rlnrelay in off-chain mode
node2.mountRlnRelayStatic(group = groupOpt2.get(),
let mountRes2 = node2.mountRlnRelayStatic(group = groupOpt2.get(),
memKeyPair = memKeyPairOpt2.get(),
memIndex = memIndexOpt2.get(),
pubsubTopic = rlnRelayPubSubTopic,
contentTopic = contentTopic)
require:
mountRes2.isOk()
await node2.start()
# node 3
await node3.mountRelay(@[rlnRelayPubSubTopic])
let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = rlnRelayStaticSetUp(3) # set up rln relay inputs
let staticSetupRes3 = rlnRelayStaticSetUp(3) # set up rln relay inputs
require:
staticSetupRes3.isOk()
let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = staticSetupRes3.get()
# mount rlnrelay in off-chain mode
node3.mountRlnRelayStatic(group = groupOpt3.get(),
let mountRes3 = node3.mountRlnRelayStatic(group = groupOpt3.get(),
memKeyPair = memKeyPairOpt3.get(),
memIndex = memIndexOpt3.get(),
pubsubTopic = rlnRelayPubSubTopic,
contentTopic = contentTopic)
require:
mountRes3.isOk()
await node3.start()
# connect them together
@ -136,35 +156,53 @@ procSuite "WakuNode - RLN relay":
# set up three nodes
# node1
await node1.mountRelay(@[rlnRelayPubSubTopic])
let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = rlnRelayStaticSetUp(1) # set up rln relay inputs
let staticSetupRes1 = rlnRelayStaticSetUp(1) # set up rln relay inputs
require:
staticSetupRes1.isOk()
let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = staticSetupRes1.get()
# mount rlnrelay in off-chain mode
node1.mountRlnRelayStatic(group = groupOpt1.get(),
let mountRes1 = node1.mountRlnRelayStatic(group = groupOpt1.get(),
memKeyPair = memKeyPairOpt1.get(),
memIndex = memIndexOpt1.get(),
pubsubTopic = rlnRelayPubSubTopic,
contentTopic = contentTopic)
require:
mountRes1.isOk()
await node1.start()
# node 2
await node2.mountRelay(@[rlnRelayPubSubTopic])
let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = rlnRelayStaticSetUp(2) # set up rln relay inputs
let staticSetupRes2 = rlnRelayStaticSetUp(2) # set up rln relay inputs
require:
staticSetupRes2.isOk()
let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = staticSetupRes2.get()
# mount rlnrelay in off-chain mode
node2.mountRlnRelayStatic(group = groupOpt2.get(),
let mountRes2 = node2.mountRlnRelayStatic(group = groupOpt2.get(),
memKeyPair = memKeyPairOpt2.get(),
memIndex = memIndexOpt2.get(),
pubsubTopic = rlnRelayPubSubTopic,
contentTopic = contentTopic)
require:
mountRes2.isOk()
await node2.start()
# node 3
await node3.mountRelay(@[rlnRelayPubSubTopic])
let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = rlnRelayStaticSetUp(3) # set up rln relay inputs
let staticSetupRes3 = rlnRelayStaticSetUp(3) # set up rln relay inputs
require:
staticSetupRes3.isOk()
let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = staticSetupRes3.get()
# mount rlnrelay in off-chain mode
node3.mountRlnRelayStatic(group = groupOpt3.get(),
let mountRes3 = node3.mountRlnRelayStatic(group = groupOpt3.get(),
memKeyPair = memKeyPairOpt3.get(),
memIndex= memIndexOpt3.get(),
pubsubTopic = rlnRelayPubSubTopic,
contentTopic = contentTopic)
require:
mountRes3.isOk()
await node3.start()
# connect them together
@ -241,35 +279,56 @@ procSuite "WakuNode - RLN relay":
# set up three nodes
# node1
await node1.mountRelay(@[rlnRelayPubSubTopic])
let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = rlnRelayStaticSetUp(1) # set up rln relay inputs
let staticSetupRes1 = rlnRelayStaticSetUp(1) # set up rln relay inputs
require:
staticSetupRes1.isOk()
let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = staticSetupRes1.get()
# mount rlnrelay in off-chain mode
node1.mountRlnRelayStatic(group = groupOpt1.get(),
let mountRes1 = node1.mountRlnRelayStatic(group = groupOpt1.get(),
memKeyPair = memKeyPairOpt1.get(),
memIndex = memIndexOpt1.get(),
pubsubTopic = rlnRelayPubSubTopic,
contentTopic = contentTopic)
require:
mountRes1.isOk()
await node1.start()
# node 2
await node2.mountRelay(@[rlnRelayPubSubTopic])
let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = rlnRelayStaticSetUp(2) # set up rln relay inputs
let staticSetupRes2 = rlnRelayStaticSetUp(2) # set up rln relay inputs
require:
staticSetupRes2.isOk()
let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = staticSetupRes2.get()
# mount rlnrelay in off-chain mode
node2.mountRlnRelayStatic(group = groupOpt2.get(),
let mountRes2 = node2.mountRlnRelayStatic(group = groupOpt2.get(),
memKeyPair = memKeyPairOpt2.get(),
memIndex = memIndexOpt2.get(),
pubsubTopic = rlnRelayPubSubTopic,
contentTopic = contentTopic)
require:
mountRes2.isOk()
await node2.start()
# node 3
await node3.mountRelay(@[rlnRelayPubSubTopic])
let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = rlnRelayStaticSetUp(3) # set up rln relay inputs
let staticSetupRes3 = rlnRelayStaticSetUp(3) # set up rln relay inputs
require:
staticSetupRes3.isOk()
let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = staticSetupRes3.get()
# mount rlnrelay in off-chain mode
node3.mountRlnRelayStatic(group = groupOpt3.get(),
let mountRes3 = node3.mountRlnRelayStatic(group = groupOpt3.get(),
memKeyPair = memKeyPairOpt3.get(),
memIndex = memIndexOpt3.get(),
pubsubTopic = rlnRelayPubSubTopic,
contentTopic = contentTopic)
require:
mountRes3.isOk()
await node3.start()
# connect the nodes together node1 <-> node2 <-> node3

View File

@ -10,19 +10,19 @@ import
waku_rln_relay_constants,
../../utils/protobuf
type RlnRelayResult*[T] = Result[T, string]
when defined(rln) or (not defined(rln) and not defined(rlnzerokit)):
## Bn256 and RLN are Nim wrappers for the data types used in
## the rln library https://github.com/kilic/rln/blob/3bbec368a4adc68cd5f9bfae80b17e1bbb4ef373/src/ffi.rs
type Bn256* = pointer
type RLN*[E] = pointer
type RLNResult* = Result[RLN[Bn256], string]
type RLNResult* = RlnRelayResult[RLN[Bn256]]
when defined(rlnzerokit):
## RLN is a Nim wrapper for the data types used in zerokit RLN
type RLN* {.incompleteStruct.} = object
type RLNResult* = Result[ptr RLN, string]
type RlnRelayResult*[T] = Result[T, string]
type RLNResult* = RlnRelayResult[ptr RLN]
type
# identity key as defined in https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Membership

View File

@ -49,12 +49,11 @@ proc toBuffer*(x: openArray[byte]): Buffer =
when defined(rln) or (not defined(rln) and not defined(rlnzerokit)):
proc createRLNInstanceLocal(d: int = MerkleTreeDepth): RLNResult
{.raises: [Defect, IOError].} =
proc createRLNInstanceLocal(d: int = MerkleTreeDepth): RLNResult =
## generates an instance of RLN
## An RLN instance supports both zkSNARKs logics and Merkle tree data structure and operations
## d indicates the depth of Merkle tree
## Returns an error if the instance creation fails
var
rlnInstance: RLN[Bn256]
merkleDepth: csize_t = uint(d)
@ -67,7 +66,12 @@ when defined(rln) or (not defined(rln) and not defined(rlnzerokit)):
## to generate parameters for a different tree depth, change the tree size in the following line of rln library
## https://github.com/kilic/rln/blob/3bbec368a4adc68cd5f9bfae80b17e1bbb4ef373/examples/export_test_keys/main.rs#L4
## and then proceed as explained above
parameters: string
try:
parameters = readFile("waku/v2/protocol/waku_rln_relay/parameters.key")
except Exception as err:
return err("failed to read the parameters file: " & err.msg)
var
pbytes = parameters.toBytes()
len: csize_t = uint(pbytes.len)
parametersBuffer = Buffer(`ptr`: addr(pbytes[0]), len: len)
@ -87,8 +91,9 @@ when defined(rln) or (not defined(rln) and not defined(rlnzerokit)):
return ok(rlnInstance)
proc membershipKeyGen*(ctxPtr: RLN[Bn256]): Option[MembershipKeyPair] =
proc membershipKeyGen*(ctxPtr: RLN[Bn256]): RlnRelayResult[MembershipKeyPair] =
## generates a MembershipKeyPair that can be used for the registration into the rln membership contract
## Returns an error if the key generation fails
# keysBufferPtr will hold the generated key pairs i.e., secret and public keys
var
@ -98,14 +103,12 @@ when defined(rln) or (not defined(rln) and not defined(rlnzerokit)):
# check whether the keys are generated successfully
if(done == false):
debug "error in key generation"
return none(MembershipKeyPair)
return err("error in key generation")
var generatedKeys = cast[ptr array[64, byte]](keysBufferPtr.`ptr`)[]
# the public and secret keys together are 64 bytes
if (generatedKeys.len != 64):
debug "the generated keys are invalid"
return none(MembershipKeyPair)
return err("generated keys are of invalid length")
# TODO define a separate proc to decode the generated keys to the secret and public components
var
@ -118,15 +121,14 @@ when defined(rln) or (not defined(rln) and not defined(rlnzerokit)):
keypair = MembershipKeyPair(idKey: secret, idCommitment: public)
return some(keypair)
return ok(keypair)
when defined(rlnzerokit):
proc createRLNInstanceLocal(d: int = MerkleTreeDepth): RLNResult
{.raises: [Defect, IOError].} =
proc createRLNInstanceLocal(d: int = MerkleTreeDepth): RLNResult =
## generates an instance of RLN
## An RLN instance supports both zkSNARKs logics and Merkle tree data structure and operations
## d indicates the depth of Merkle tree
## Returns an error if the instance creation fails
var
rlnInstance: ptr RLN
merkleDepth: csize_t = uint(d)
@ -141,8 +143,9 @@ when defined(rlnzerokit):
return ok(rlnInstance)
proc membershipKeyGen*(ctxPtr: ptr RLN): Option[MembershipKeyPair] =
proc membershipKeyGen*(ctxPtr: ptr RLN): RlnRelayResult[MembershipKeyPair] =
## generates a MembershipKeyPair that can be used for the registration into the rln membership contract
## Returns an error if the key generation fails
# keysBufferPtr will hold the generated key pairs i.e., secret and public keys
var
@ -152,14 +155,12 @@ when defined(rlnzerokit):
# check whether the keys are generated successfully
if(done == false):
debug "error in key generation"
return none(MembershipKeyPair)
return err("error in key generation")
var generatedKeys = cast[ptr array[64, byte]](keysBufferPtr.`ptr`)[]
# the public and secret keys together are 64 bytes
if (generatedKeys.len != 64):
debug "the generated keys are invalid"
return none(MembershipKeyPair)
return err("generated keys are of invalid length")
# TODO define a separate proc to decode the generated keys to the secret and public components
var
@ -171,12 +172,14 @@ when defined(rlnzerokit):
var
keypair = MembershipKeyPair(idKey: secret, idCommitment: public)
return some(keypair)
return ok(keypair)
proc createRLNInstance*(d: int = MerkleTreeDepth): RLNResult {.raises: [Defect, IOError].} =
proc createRLNInstance*(d: int = MerkleTreeDepth): RLNResult =
## Wraps the rln instance creation for metrics
## Returns an error if the instance creation fails
var res: RLNResult
waku_rln_instance_creation_duration_seconds.nanosecondTime:
let res = createRLNInstanceLocal(d)
res = createRLNInstanceLocal(d)
return res
proc toUInt256*(idCommitment: IDCommitment): UInt256 =
@ -412,6 +415,8 @@ when defined(rln) or (not defined(rln) and not defined(rlnzerokit)):
return ok(rootValue)
proc proofVerify*(rlnInstance: RLN[Bn256], data: openArray[byte], proof: RateLimitProof, validRoots: seq[MerkleNode] = @[]): RlnRelayResult[bool] =
## verifies the proof, returns an error if the proof verification fails
## returns true if the proof is valid
var
proofBytes = serialize(proof, data)
proofBuffer = proofBytes.toBuffer()
@ -528,7 +533,12 @@ when defined(rlnzerokit):
# validRoots should contain a sequence of roots in the acceptable windows.
# As default, it is set to an empty sequence of roots. This implies that the validity check for the proof's root is skipped
proc proofVerify*(rlnInstance: ptr RLN, data: openArray[byte], proof: RateLimitProof, validRoots: seq[MerkleNode] = @[]): RlnRelayResult[bool] =
proc proofVerify*(rlnInstance: ptr RLN,
data: openArray[byte],
proof: RateLimitProof,
validRoots: seq[MerkleNode] = @[]): RlnRelayResult[bool] =
## verifies the proof, returns an error if the proof verification fails
## returns true if the proof is valid
var
proofBytes = serialize(proof, data)
proofBuffer = proofBytes.toBuffer()
@ -589,6 +599,7 @@ proc updateValidRootQueue*(wakuRlnRelay: WakuRLNRelay, root: MerkleNode): void =
proc insertMember*(wakuRlnRelay: WakuRLNRelay, idComm: IDCommitment): RlnRelayResult[void] =
## inserts a new id commitment into the local merkle tree, and adds the changed root to the
## queue of valid roots
## Returns an error if the insertion fails
waku_rln_membership_insertion_duration_seconds.nanosecondTime:
let actionSucceeded = wakuRlnRelay.rlnInstance.insertMember(idComm)
if not actionSucceeded:
@ -602,6 +613,8 @@ proc insertMember*(wakuRlnRelay: WakuRLNRelay, idComm: IDCommitment): RlnRelayRe
proc removeMember*(wakuRlnRelay: WakuRLNRelay, index: MembershipIndex): RlnRelayResult[void] =
## removes a commitment from the local merkle tree at `index`, and adds the changed root to the
## queue of valid roots
## Returns an error if the removal fails
let actionSucceeded = wakuRlnRelay.rlnInstance.removeMember(index)
if not actionSucceeded:
return err("could not remove id commitment from the merkle tree")
@ -614,28 +627,35 @@ proc validateRoot*(wakuRlnRelay: WakuRLNRelay, root: MerkleNode): bool =
## Validate against the window of roots stored in wakuRlnRelay.validMerkleRoots
return root in wakuRlnRelay.validMerkleRoots
proc toMembershipKeyPairs*(groupKeys: seq[(string, string)]): seq[
MembershipKeyPair] {.raises: [Defect, ValueError].} =
proc toMembershipKeyPairs*(groupKeys: seq[(string, string)]): RlnRelayResult[seq[
MembershipKeyPair]] =
## groupKeys is sequence of membership key tuples in the form of (identity key, identity commitment) all in the hexadecimal format
## the toMembershipKeyPairs proc populates a sequence of MembershipKeyPairs using the supplied groupKeys
## Returns an error if the conversion fails
var groupKeyPairs = newSeq[MembershipKeyPair]()
for i in 0..groupKeys.len-1:
let
idKey = hexToUint[IDKey.len*8](groupKeys[i][0]).toBytesLE()
idCommitment = hexToUint[IDCommitment.len*8](groupKeys[i][1]).toBytesLE()
groupKeyPairs.add(MembershipKeyPair(idKey: idKey,
idCommitment: idCommitment))
return groupKeyPairs
try:
let
idKey = hexToUint[IDKey.len*8](groupKeys[i][0]).toBytesLE()
idCommitment = hexToUint[IDCommitment.len*8](groupKeys[i][1]).toBytesLE()
groupKeyPairs.add(MembershipKeyPair(idKey: idKey,
idCommitment: idCommitment))
except ValueError as err:
warn "could not convert the group key to bytes", err = err.msg
return err("could not convert the group key to bytes: " & err.msg)
return ok(groupKeyPairs)
proc calcMerkleRoot*(list: seq[IDCommitment]): string {.raises: [Defect, IOError].} =
proc calcMerkleRoot*(list: seq[IDCommitment]): RlnRelayResult[string] =
## returns the root of the Merkle tree that is computed from the supplied list
## the root is in hexadecimal format
## Returns an error if the computation fails
var rlnInstance = createRLNInstance()
doAssert(rlnInstance.isOk)
var rln = rlnInstance.value
let rlnInstance = createRLNInstance()
if rlnInstance.isErr():
return err("could not create rln instance: " & rlnInstance.error())
let rln = rlnInstance.get()
# create a Merkle tree
for i in 0..list.len-1:
@ -644,42 +664,49 @@ proc calcMerkleRoot*(list: seq[IDCommitment]): string {.raises: [Defect, IOError
doAssert(member_is_added)
let root = rln.getMerkleRoot().value().inHex
return root
return ok(root)
proc createMembershipList*(n: int): (seq[(string, string)], string) {.raises: [
Defect, IOError].} =
proc createMembershipList*(n: int): RlnRelayResult[(
seq[(string, string)], string
)] =
## createMembershipList produces a sequence of membership key pairs in the form of (identity key, id commitment keys) in the hexadecimal format
## this proc also returns the root of a Merkle tree constructed out of the identity commitment keys of the generated list
## the output of this proc is used to initialize a static group keys (to test waku-rln-relay in the off-chain mode)
## Returns an error if it cannot create the membership list
# initialize a Merkle tree
var rlnInstance = createRLNInstance()
if not rlnInstance.isOk:
return (@[], "")
var rln = rlnInstance.value
let rlnInstance = createRLNInstance()
if rlnInstance.isErr():
return err("could not create rln instance: " & rlnInstance.error())
let rln = rlnInstance.get()
var output = newSeq[(string, string)]()
for i in 0..n-1:
# generate a key pair
let keypair = rln.membershipKeyGen()
doAssert(keypair.isSome())
let keyTuple = (keypair.get().idKey.inHex, keypair.get().idCommitment.inHex)
let keypairRes = rln.membershipKeyGen()
if keypairRes.isErr():
return err("could not generate a key pair: " & keypairRes.error())
let keypair = keypairRes.get()
let keyTuple = (keypair.idKey.inHex, keypair.idCommitment.inHex)
output.add(keyTuple)
# insert the key to the Merkle tree
let inserted = rln.insertMember(keypair.get().idCommitment)
let inserted = rln.insertMember(keypair.idCommitment)
if not inserted:
return (@[], "")
return err("could not insert the key into the Merkle tree")
let root = rln.getMerkleRoot().value().inHex
return (output, root)
return ok((output, root))
proc rlnRelayStaticSetUp*(rlnRelayMembershipIndex: MembershipIndex): (Option[seq[
proc rlnRelayStaticSetUp*(rlnRelayMembershipIndex: MembershipIndex): RlnRelayResult[(Option[seq[
IDCommitment]], Option[MembershipKeyPair], Option[
MembershipIndex]) {.raises: [Defect, ValueError].} =
MembershipIndex])] =
## rlnRelayStaticSetUp is a proc that is used to initialize the static group keys and the static membership index
## this proc is used to test waku-rln-relay in the off-chain mode
## it returns the static group keys, the static membership key pair, and the static membership index
## Returns an error if it cannot initialize the static group keys and the static membership index
let
# static group
groupKeys = StaticGroupKeys
@ -691,12 +718,19 @@ proc rlnRelayStaticSetUp*(rlnRelayMembershipIndex: MembershipIndex): (Option[seq
if rlnRelayMembershipIndex < MembershipIndex(0) or rlnRelayMembershipIndex >=
MembershipIndex(groupSize):
error "wrong membership index"
return(none(seq[IDCommitment]), none(MembershipKeyPair), none(MembershipIndex))
return ok((none(seq[IDCommitment]), none(MembershipKeyPair), none(MembershipIndex)))
# prepare the outputs from the static group keys
let
# create a sequence of MembershipKeyPairs from the group keys (group keys are in string format)
groupKeyPairs = groupKeys.toMembershipKeyPairs()
groupKeyPairsRes = groupKeys.toMembershipKeyPairs()
if groupKeyPairsRes.isErr():
return err("could not convert the group keys to MembershipKeyPairs: " &
groupKeyPairsRes.error())
let
groupKeyPairs = groupKeyPairsRes.get()
# extract id commitment keys
groupIDCommitments = groupKeyPairs.mapIt(it.idCommitment)
groupOpt = some(groupIDCommitments)
@ -704,13 +738,13 @@ proc rlnRelayStaticSetUp*(rlnRelayMembershipIndex: MembershipIndex): (Option[seq
memKeyPairOpt = some(groupKeyPairs[rlnRelayMembershipIndex])
memIndexOpt = some(rlnRelayMembershipIndex)
return (groupOpt, memKeyPairOpt, memIndexOpt)
return ok((groupOpt, memKeyPairOpt, memIndexOpt))
proc hasDuplicate*(rlnPeer: WakuRLNRelay, msg: WakuMessage): RlnRelayResult[bool] =
## returns true if there is another message in the `nullifierLog` of the `rlnPeer` with the same
## epoch and nullifier as `msg`'s epoch and nullifier but different Shamir secret shares
## otherwise, returns false
## emits an error string if `KeyError` occurs (never happens, it is just to avoid raising unnecessary `KeyError` exception )
## Returns an error if it cannot check for duplicates
# extract the proof metadata of the supplied `msg`
let proofMD = ProofMetadata(nullifier: msg.proof.nullifier,
@ -742,6 +776,7 @@ proc hasDuplicate*(rlnPeer: WakuRLNRelay, msg: WakuMessage): RlnRelayResult[bool
proc updateLog*(rlnPeer: WakuRLNRelay, msg: WakuMessage): RlnRelayResult[bool] =
## extracts the `ProofMetadata` of the supplied messages `msg` and
## saves it in the `nullifierLog` of the `rlnPeer`
## Returns an error if it cannot update the log
let proofMD = ProofMetadata(nullifier: msg.proof.nullifier,
shareX: msg.proof.shareX, shareY: msg.proof.shareY)
@ -913,6 +948,7 @@ proc appendRLNProof*(rlnPeer: WakuRLNRelay, msg: var WakuMessage,
proc addAll*(wakuRlnRelay: WakuRLNRelay, list: seq[IDCommitment]): RlnRelayResult[void] =
# add members to the Merkle tree of the `rlnInstance`
## Returns an error if it cannot add any member to the Merkle tree
for i in 0..list.len-1:
let member = list[i]
let memberAdded = wakuRlnRelay.insertMember(member)
@ -920,14 +956,14 @@ proc addAll*(wakuRlnRelay: WakuRLNRelay, list: seq[IDCommitment]): RlnRelayResul
return err(memberAdded.error())
return ok()
type GroupUpdateHandler* = proc(pubkey: Uint256, index: Uint256): RlnRelayResult[void] {.gcsafe, raises: [Defect].}
type GroupUpdateHandler* = proc(pubkey: Uint256, index: Uint256): RlnRelayResult[void] {.gcsafe.}
proc generateGroupUpdateHandler(rlnPeer: WakuRLNRelay): GroupUpdateHandler =
## assuming all the members arrive in order
## TODO: check the index and the pubkey depending on
## the group update operation
var handler: GroupUpdateHandler
handler = proc(pubkey: Uint256, index: Uint256): RlnRelayResult[void] {.raises: [Defect].} =
handler = proc(pubkey: Uint256, index: Uint256): RlnRelayResult[void] =
var pk: IDCommitment
try:
pk = pubkey.toIDCommitment()
@ -959,7 +995,11 @@ proc subscribeToMemberRegistrations(web3: Web3,
let onMemberRegistered = proc (pubkey: Uint256, index: Uint256) {.gcsafe.} =
debug "onRegister", pubkey = pubkey, index = index
let groupUpdateRes = handler(pubkey, index)
var groupUpdateRes: RlnRelayResult[void]
try:
groupUpdateRes = handler(pubkey, index)
except Exception as err:
error "failed to handle group update", err = err.msg
if groupUpdateRes.isErr():
error "Error handling new member registration", err=groupUpdateRes.error()
@ -1065,32 +1105,32 @@ proc mountRlnRelayStatic*(node: WakuNode,
memIndex: MembershipIndex,
pubsubTopic: string,
contentTopic: ContentTopic,
spamHandler: Option[SpamHandler] = none(SpamHandler)) {.raises: [Defect, IOError].}=
# TODO return a bool value to indicate the success of the call
spamHandler: Option[SpamHandler] = none(SpamHandler)): RlnRelayResult[void] =
# Returns RlnRelayResult[void] to indicate the success of the call
debug "mounting rln-relay in off-chain/static mode"
# check whether inputs are provided
# relay protocol is the prerequisite of rln-relay
if node.wakuRelay.isNil:
error "WakuRelay protocol is not mounted."
return
if node.wakuRelay.isNil():
return err("WakuRelay protocol is not mounted")
# check whether the pubsub topic is supported at the relay level
if pubsubTopic notin node.wakuRelay.defaultTopics:
error "The relay protocol does not support the configured pubsub topic.", pubsubTopic=pubsubTopic
return
return err("The relay protocol does not support the configured pubsub topic")
debug "rln-relay input validation passed"
# check the peer's index and the inclusion of user's identity commitment in the group
doAssert((memKeyPair.idCommitment) == group[int(memIndex)])
if not memKeyPair.idCommitment == group[int(memIndex)]:
return err("The peer's index is not consistent with the group")
# create an RLN instance
var rlnInstance = createRLNInstance()
doAssert(rlnInstance.isOk)
var rln = rlnInstance.value
let rlnInstance = createRLNInstance()
if rlnInstance.isErr():
return err("RLN instance creation failed")
let rln = rlnInstance.get()
# create the WakuRLNRelay
var rlnPeer = WakuRLNRelay(membershipKeyPair: memKeyPair,
let rlnPeer = WakuRLNRelay(membershipKeyPair: memKeyPair,
membershipIndex: memIndex,
rlnInstance: rln,
pubsubTopic: pubsubTopic,
@ -1100,7 +1140,8 @@ proc mountRlnRelayStatic*(node: WakuNode,
for index in 0..group.len-1:
let member = group[index]
let memberAdded = rlnPeer.insertMember(member)
doAssert(memberAdded.isOk())
if memberAdded.isErr():
return err("member addition to the Merkle tree failed: " & memberAdded.error())
# adds a topic validator for the supplied pubsub topic at the relay protocol
# messages published on this pubsub topic will be relayed upon a successful validation, otherwise they will be dropped
@ -1108,7 +1149,8 @@ proc mountRlnRelayStatic*(node: WakuNode,
node.addRLNRelayValidator(pubsubTopic, contentTopic, spamHandler)
debug "rln relay topic validator is mounted successfully", pubsubTopic=pubsubTopic, contentTopic=contentTopic
node.wakuRlnRelay = rlnPeer
node.wakuRlnRelay = rlnPeer
return ok()
proc mountRlnRelayDynamic*(node: WakuNode,
ethClientAddr: string = "",
@ -1120,23 +1162,23 @@ proc mountRlnRelayDynamic*(node: WakuNode,
pubsubTopic: string,
contentTopic: ContentTopic,
spamHandler: Option[SpamHandler] = none(SpamHandler),
registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)) : Future[RlnRelayResult[bool]] {.async.} =
registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)) : Future[RlnRelayResult[void]] {.async.} =
debug "mounting rln-relay in on-chain/dynamic mode"
# TODO return a bool value to indicate the success of the call
# relay protocol is the prerequisite of rln-relay
if node.wakuRelay.isNil:
error "WakuRelay protocol is not mounted."
return err("WakuRelay protocol is not mounted.")
# check whether the pubsub topic is supported at the relay level
if pubsubTopic notin node.wakuRelay.defaultTopics:
error "Wakurelay protocol does not support the configured pubsub topic.", pubsubTopic=pubsubTopic
return err("WakuRelay protocol does not support the configured pubsub topic.")
debug "rln-relay input validation passed"
# create an RLN instance
var rlnInstance = createRLNInstance()
doAssert(rlnInstance.isOk)
var rln = rlnInstance.value
let rlnInstance = createRLNInstance()
if rlnInstance.isErr():
return err("RLN instance creation failed.")
let rln = rlnInstance.get()
# prepare rln membership key pair
var
@ -1145,12 +1187,19 @@ proc mountRlnRelayDynamic*(node: WakuNode,
if memKeyPair.isNone: # no rln credentials provided
if ethAccountPrivKeyOpt.isSome: # if an ethereum private key is supplied, then create rln credentials and register to the membership contract
trace "no rln-relay key is provided, generating one"
let keyPairOpt = rln.membershipKeyGen()
doAssert(keyPairOpt.isSome)
keyPair = keyPairOpt.get()
let keyPairRes = rln.membershipKeyGen()
if keyPairRes.isErr():
error "failed to generate rln-relay key pair"
return err("failed to generate rln-relay key pair: " & keyPairRes.error())
keyPair = keyPairRes.value()
# register the rln-relay peer to the membership contract
waku_rln_registration_duration_seconds.nanosecondTime:
let regIndexRes = await register(idComm = keyPair.idCommitment, ethAccountAddress = ethAccountAddress, ethAccountPrivKey = ethAccountPrivKeyOpt.get(), ethClientAddress = ethClientAddr, membershipContractAddress = memContractAddr, registrationHandler = registrationHandler)
let regIndexRes = await register(idComm = keyPair.idCommitment,
ethAccountAddress = ethAccountAddress,
ethAccountPrivKey = ethAccountPrivKeyOpt.get(),
ethClientAddress = ethClientAddr,
membershipContractAddress = memContractAddr,
registrationHandler = registrationHandler)
# check whether registration is done
if regIndexRes.isErr():
debug "membership registration failed", err=regIndexRes.error()
@ -1184,9 +1233,12 @@ proc mountRlnRelayDynamic*(node: WakuNode,
debug "rln relay topic validator is mounted successfully", pubsubTopic=pubsubTopic, contentTopic=contentTopic
node.wakuRlnRelay = rlnPeer
return ok(true)
return ok()
proc writeRlnCredentials*(path: string, credentials: RlnMembershipCredentials, password: string): RlnRelayResult[void] =
proc writeRlnCredentials*(path: string,
credentials: RlnMembershipCredentials,
password: string): RlnRelayResult[void] =
# Returns RlnRelayResult[void], which indicates the success of the call
info "Storing RLN credentials"
var jsonString: string
jsonString.toUgly(%credentials)
@ -1199,7 +1251,10 @@ proc writeRlnCredentials*(path: string, credentials: RlnMembershipCredentials, p
# Attempts decryptions of all keyfiles with the provided password.
# If one or more credentials are successfully decrypted, the max(min(index,number_decrypted),0)-th is returned.
proc readRlnCredentials*(path: string, password: string, index: int = 0): RlnRelayResult[Option[RlnMembershipCredentials]] =
proc readRlnCredentials*(path: string,
password: string,
index: int = 0): RlnRelayResult[Option[RlnMembershipCredentials]] =
# Returns RlnRelayResult[Option[RlnMembershipCredentials]], which indicates the success of the call
info "Reading RLN credentials"
# With regards to printing the keys, it is purely for debugging purposes so that the user becomes explicitly aware of the current keys in use when nwaku is started.
# Note that this is only until the RLN contract being used is the one deployed on Goerli testnet.
@ -1230,16 +1285,29 @@ proc mount(node: WakuNode,
conf: WakuNodeConf|Chat2Conf,
spamHandler: Option[SpamHandler] = none(SpamHandler),
registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)
): RlnRelayResult[bool] {.raises: [Defect, ValueError, IOError, CatchableError, Exception].} =
): Future[RlnRelayResult[void]] {.async.} =
# Returns RlnRelayResult[void], which indicates the success of the call
if not conf.rlnRelayDynamic:
info " setting up waku-rln-relay in off-chain mode... "
# set up rln relay inputs
let (groupOpt, memKeyPairOpt, memIndexOpt) = rlnRelayStaticSetUp(MembershipIndex(conf.rlnRelayMembershipIndex))
let staticSetupRes = rlnRelayStaticSetUp(MembershipIndex(conf.rlnRelayMembershipIndex))
if staticSetupRes.isErr():
return err("rln relay static setup failed: " & staticSetupRes.error())
let (groupOpt, memKeyPairOpt, memIndexOpt) = staticSetupRes.get()
if memIndexOpt.isNone:
error "failed to mount WakuRLNRelay"
return err("failed to mount WakuRLNRelay")
else:
# mount rlnrelay in off-chain mode with a static group of users
node.mountRlnRelayStatic(group = groupOpt.get(), memKeyPair = memKeyPairOpt.get(), memIndex= memIndexOpt.get(), pubsubTopic = conf.rlnRelayPubsubTopic, contentTopic = conf.rlnRelayContentTopic, spamHandler = spamHandler)
let mountRes = node.mountRlnRelayStatic(group = groupOpt.get(),
memKeyPair = memKeyPairOpt.get(),
memIndex= memIndexOpt.get(),
pubsubTopic = conf.rlnRelayPubsubTopic,
contentTopic = conf.rlnRelayContentTopic,
spamHandler = spamHandler)
if mountRes.isErr():
return err("Failed to mount WakuRLNRelay: " & mountRes.error())
info "membership id key", idkey=memKeyPairOpt.get().idKey.inHex
info "membership id commitment key", idCommitmentkey=memKeyPairOpt.get().idCommitment.inHex
@ -1260,7 +1328,7 @@ proc mount(node: WakuNode,
error "root mismatch: something went wrong not in Merkle tree construction"
debug "the calculated root", root
info "WakuRLNRelay is mounted successfully", pubsubtopic=conf.rlnRelayPubsubTopic, contentTopic=conf.rlnRelayContentTopic
return ok(true)
return ok()
else: # mount the rln relay protocol in the on-chain/dynamic mode
debug "setting up waku-rln-relay in on-chain mode... "
@ -1268,17 +1336,27 @@ proc mount(node: WakuNode,
# read related inputs to run rln-relay in on-chain mode and do type conversion when needed
let
ethClientAddr = conf.rlnRelayEthClientAddress
var ethMemContractAddress: web3.Address
try:
ethMemContractAddress = web3.fromHex(web3.Address, conf.rlnRelayEthContractAddress)
except ValueError as err:
return err("invalid eth contract address: " & err.msg)
var ethAccountPrivKeyOpt = none(keys.PrivateKey)
var ethAccountAddressOpt = none(Address)
var credentials = none(RlnMembershipCredentials)
var res: RlnRelayResult[bool]
var res: RlnRelayResult[void]
if conf.rlnRelayEthAccountPrivateKey != "":
ethAccountPrivKeyOpt = some(keys.PrivateKey(SkSecretKey.fromHex(conf.rlnRelayEthAccountPrivateKey).value))
if conf.rlnRelayEthAccountAddress != "":
ethAccountAddressOpt = some(web3.fromHex(web3.Address, conf.rlnRelayEthAccountAddress))
var ethAccountAddress: web3.Address
try:
ethAccountAddress = web3.fromHex(web3.Address, conf.rlnRelayEthAccountAddress)
except ValueError as err:
return err("invalid eth account address: " & err.msg)
ethAccountAddressOpt = some(ethAccountAddress)
# if the rlnRelayCredPath config option is non-empty, then rln-relay credentials should be persisted
# if the path does not contain any credential file, then a new set is generated and pesisted in the same path
@ -1308,7 +1386,7 @@ proc mount(node: WakuNode,
if credentials.isSome():
# mount rln-relay in on-chain mode, with credentials that were read or generated
res = waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress,
res = await node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress,
ethClientAddr = ethClientAddr,
ethAccountAddress = ethAccountAddressOpt,
ethAccountPrivKeyOpt = ethAccountPrivKeyOpt,
@ -1320,7 +1398,7 @@ proc mount(node: WakuNode,
memIndex = some(credentials.get().rlnIndex))
else:
# mount rln-relay in on-chain mode, with the provided private key
res = waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress,
res = await node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress,
ethClientAddr = ethClientAddr,
ethAccountAddress = ethAccountAddressOpt,
ethAccountPrivKeyOpt = ethAccountPrivKeyOpt,
@ -1340,26 +1418,28 @@ proc mount(node: WakuNode,
# do not persist or use a persisted rln-relay credential
# a new credential will be generated during the mount process but will not be persisted
info "no need to persist or use a persisted rln-relay credential"
res = waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr,
res = await node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr,
ethAccountAddress = ethAccountAddressOpt, ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, pubsubTopic = conf.rlnRelayPubsubTopic,
contentTopic = conf.rlnRelayContentTopic, spamHandler = spamHandler, registrationHandler = registrationHandler)
if res.isErr():
return err("dynamic rln-relay could not be mounted: " & res.error())
return ok(res.value())
return err("dynamic rln-relay could not be mounted: " & res.error())
return ok()
proc mountRlnRelay*(node: WakuNode,
conf: WakuNodeConf|Chat2Conf,
spamHandler: Option[SpamHandler] = none(SpamHandler),
registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)
): RlnRelayResult[bool] {.raises: [Defect, ValueError, IOError, CatchableError, Exception].} =
waku_rln_relay_mounting_duration_seconds.nanosecondTime:
let res = mount(
): Future[RlnRelayResult[void]] {.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.
waku_rln_relay_mounting_duration_seconds.nanosecondTime:
let res = await mount(
node,
conf,
spamHandler,
registrationHandler
)
return res