chore(rln-relay): refactor mounting procedure (#1457)

* chore(rln-relay): refactor mounting procedure

* fix(rln-relay): tests

* fix(rln-relay|chat2): update mounting proc in chat2, fix args to mountRlnRelay

* fix(rln-relay): remove stale todo
This commit is contained in:
Aaryamann Challani 2022-12-13 14:56:24 +05:30 committed by GitHub
parent 2915b19dbd
commit 33e9d8b9b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 237 additions and 244 deletions

View File

@ -565,13 +565,13 @@ proc processInput(rfd: AsyncFD) {.async.} =
rlnRelayCredentialsPassword: conf.rlnRelayCredentialsPassword
)
let res = await node.mountRlnRelay(conf=rlnConf, 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
echo "your rln identity key is: ", node.wakuRlnRelay.membershipKeyPair.idKey.inHex()
echo "your rln identity commitment key is: ", node.wakuRlnRelay.membershipKeyPair.idCommitment.inHex()
await node.mountRlnRelay(rlnConf,
spamHandler=some(spamHandler),
registrationHandler=some(registrationHandler))
echo "your membership index is: ", node.wakuRlnRelay.membershipIndex
echo "your rln identity key is: ", node.wakuRlnRelay.membershipKeyPair.idKey.inHex()
echo "your rln identity commitment key is: ", node.wakuRlnRelay.membershipKeyPair.idCommitment.inHex()
if conf.metricsLogging:
startMetricsLog()

View File

@ -371,9 +371,7 @@ proc setupProtocols(node: WakuNode, conf: WakuNodeConf,
)
try:
let res = await node.mountRlnRelay(rlnConf)
if res.isErr():
return err("failed to mount waku RLN relay protocol: " & res.error)
await node.mountRlnRelay(rlnConf)
except:
return err("failed to mount waku RLN relay protocol: " & getCurrentExceptionMsg())

View File

@ -56,7 +56,7 @@ procSuite "Waku rln relay":
# -------- mount rln-relay in the off-chain mode
await node.mountRelay(@[RlnRelayPubsubTopic])
let mountRes = node.mountRlnRelayStatic(group = groupIDCommitments,
let mountRes = node.wakuRelay.mountRlnRelayStatic(group = groupIDCommitments,
memKeyPair = groupKeyPairs[index],
memIndex = index,
pubsubTopic = RlnRelayPubsubTopic,
@ -64,8 +64,13 @@ procSuite "Waku rln relay":
require:
mountRes.isOk()
let wakuRlnRelay = mountRes.get()
# get the root of Merkle tree which is constructed inside the mountRlnRelay proc
let calculatedRoot = node.wakuRlnRelay.rlnInstance.getMerkleRoot().value().inHex
let calculatedRootRes = wakuRlnRelay.rlnInstance.getMerkleRoot()
require:
calculatedRootRes.isOk()
let calculatedRoot = calculatedRootRes.get().inHex()
debug "calculated root by mountRlnRelay", calculatedRoot
# this part checks whether the Merkle tree is constructed correctly inside the mountRlnRelay proc

View File

@ -8,10 +8,7 @@ import
stew/byteutils, stew/shims/net as stewNet,
libp2p/crypto/crypto,
eth/keys,
../../waku/v2/protocol/waku_rln_relay/[utils,
constants,
protocol_types,
rln_relay_contract],
../../waku/v2/protocol/waku_rln_relay,
../../waku/v2/node/waku_node,
../test_helpers,
./test_utils
@ -209,11 +206,11 @@ procSuite "Waku-rln-relay":
let fut = newFuture[void]()
let s = await contractObj.subscribe(MemberRegistered, %*{"fromBlock": "0x0",
"address": contractAddress}) do(
pubkey: Uint256, index: Uint256){.raises: [Defect], gcsafe.}:
idCommitment: Uint256, index: Uint256){.raises: [Defect], gcsafe.}:
try:
debug "onRegister", pubkey = pubkey, index = index
debug "onRegister", idCommitment = idCommitment, index = index
require:
pubkey == pk
idCommitment == pk
fut.complete()
except Exception as err:
# chronos still raises exceptions which inherit directly from Exception
@ -287,9 +284,9 @@ procSuite "Waku-rln-relay":
events[futIndex].complete()
futIndex += 1
let index = members[0].index
let isSuccessful = rlnPeer.rlnInstance.insertMembers(index, members.mapIt(it.idComm))
let insertRes = rlnPeer.insertMembers(index, members.mapIt(it.idComm))
check:
isSuccessful
insertRes.isOk()
return ok()
# mount the handler for listening to the contract events
@ -308,7 +305,7 @@ procSuite "Waku-rln-relay":
debug "a member is registered", tx2 = tx2
# wait for the events to be processed
await all(events)
await allFutures(events)
# release resources -----------------------
await web3.close()
@ -432,7 +429,8 @@ procSuite "Waku-rln-relay":
# test ------------------------------
# start rln-relay
await node.mountRelay(@[RlnRelayPubsubTopic])
let mountRes = node.mountRlnRelayStatic(group = group,
let mountRes = mountRlnRelayStatic(wakuRelay = node.wakuRelay,
group = group,
memKeyPair = keyPair,
memIndex = index,
pubsubTopic = RlnRelayPubsubTopic,
@ -441,7 +439,9 @@ procSuite "Waku-rln-relay":
require:
mountRes.isOk()
let calculatedRoot = node.wakuRlnRelay.rlnInstance.getMerkleRoot().value().inHex
let wakuRlnRelay = mountRes.get()
let calculatedRoot = wakuRlnRelay.rlnInstance.getMerkleRoot().value().inHex()
debug "calculated root ", calculatedRoot
check:
@ -522,7 +522,8 @@ procSuite "Waku-rln-relay":
# test ------------------------------
# start rln-relay
await node.mountRelay(@[RlnRelayPubsubTopic])
discard await node.mountRlnRelayDynamic(ethClientAddr = EthClient,
let mountRes = await mountRlnRelayDynamic(wakuRelay = node.wakuRelay,
ethClientAddr = EthClient,
ethAccountAddress = some(ethacc),
ethAccountPrivKeyOpt = some(ethPrivKey),
memContractAddr = contractAddress,
@ -530,12 +531,17 @@ procSuite "Waku-rln-relay":
memIndex = some(MembershipIndex(0)),
pubsubTopic = RlnRelayPubsubTopic,
contentTopic = RlnRelayContentTopic)
require:
mountRes.isOk()
let wakuRlnRelay = mountRes.get()
await sleepAsync(2000) # wait for the event to reach the group handler
await sleepAsync(2000.milliseconds()) # wait for the event to reach the group handler
# rln pks are inserted into the rln peer's Merkle tree and the resulting root
# is expected to be the same as the calculatedRoot i.e., the one calculated outside of the mountRlnRelayDynamic proc
let calculatedRoot = node.wakuRlnRelay.rlnInstance.getMerkleRoot().value().inHex
let calculatedRoot = wakuRlnRelay.rlnInstance.getMerkleRoot().value().inHex
debug "calculated root ", calculatedRoot=calculatedRoot
debug "expected root ", expectedRoot=expectedRoot
@ -575,7 +581,8 @@ procSuite "Waku-rln-relay":
# start rln-relay on the first node, leave rln-relay credentials empty
await node.mountRelay(@[RlnRelayPubsubTopic])
discard await node.mountRlnRelayDynamic(ethClientAddr = EthClient,
let mountRes = await mountRlnRelayDynamic(wakuRelay=node.wakuRelay,
ethClientAddr = EthClient,
ethAccountAddress = some(ethacc),
ethAccountPrivKeyOpt = some(ethPrivKey),
memContractAddr = contractAddress,
@ -583,12 +590,16 @@ procSuite "Waku-rln-relay":
memIndex = none(MembershipIndex),
pubsubTopic = RlnRelayPubsubTopic,
contentTopic = RlnRelayContentTopic)
require:
mountRes.isOk()
let wakuRlnRelay = mountRes.get()
# start rln-relay on the second node, leave rln-relay credentials empty
await node2.mountRelay(@[RlnRelayPubsubTopic])
discard await node2.mountRlnRelayDynamic(ethClientAddr = EthClient,
let mountRes2 = await mountRlnRelayDynamic(wakuRelay=node2.wakuRelay,
ethClientAddr = EthClient,
ethAccountAddress = some(ethacc),
ethAccountPrivKeyOpt = some(ethPrivKey),
memContractAddr = contractAddress,
@ -597,12 +608,17 @@ procSuite "Waku-rln-relay":
pubsubTopic = RlnRelayPubsubTopic,
contentTopic = RlnRelayContentTopic)
require:
mountRes2.isOk()
let wakuRlnRelay2 = mountRes2.get()
# the two nodes should be registered into the contract
# since nodes are spun up sequentially
# the first node has index 0 whereas the second node gets index 1
check:
node.wakuRlnRelay.membershipIndex == MembershipIndex(0)
node2.wakuRlnRelay.membershipIndex == MembershipIndex(1)
wakuRlnRelay.membershipIndex == MembershipIndex(0)
wakuRlnRelay2.membershipIndex == MembershipIndex(1)
await node.stop()
await node2.stop()

View File

@ -11,7 +11,6 @@ import
libp2p/peerid,
libp2p/multiaddress,
libp2p/switch,
libp2p/protocols/pubsub/rpc/messages,
libp2p/protocols/pubsub/pubsub,
eth/keys
import
@ -48,54 +47,35 @@ procSuite "WakuNode - RLN relay":
# set up three nodes
# node1
await node1.mountRelay(@[rlnRelayPubSubTopic])
let staticSetupRes1 = rlnRelayStaticSetUp(1) # set up rln relay inputs
require:
staticSetupRes1.isOk()
let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = staticSetupRes1.get()
# mount rlnrelay in off-chain mode
let mountRes1 = node1.mountRlnRelayStatic(group = groupOpt1.get(),
memKeyPair = memKeyPairOpt1.get(),
memIndex = memIndexOpt1.get(),
pubsubTopic = rlnRelayPubSubTopic,
contentTopic = contentTopic)
require:
mountRes1.isOk()
await node1.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false,
rlnRelayPubsubTopic: rlnRelayPubSubTopic,
rlnRelayContentTopic: contentTopic,
rlnRelayMembershipIndex: MembershipIndex(1),
))
await node1.start()
# node 2
await node2.mountRelay(@[rlnRelayPubSubTopic])
let staticSetupRes2 = rlnRelayStaticSetUp(2) # set up rln relay inputs
require:
staticSetupRes2.isOk()
let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = staticSetupRes2.get()
# mount rlnrelay in off-chain mode
let mountRes2 = node2.mountRlnRelayStatic(group = groupOpt2.get(),
memKeyPair = memKeyPairOpt2.get(),
memIndex = memIndexOpt2.get(),
pubsubTopic = rlnRelayPubSubTopic,
contentTopic = contentTopic)
require:
mountRes2.isOk()
await node2.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false,
rlnRelayPubsubTopic: rlnRelayPubSubTopic,
rlnRelayContentTopic: contentTopic,
rlnRelayMembershipIndex: MembershipIndex(2),
))
await node2.start()
# node 3
await node3.mountRelay(@[rlnRelayPubSubTopic])
let staticSetupRes3 = rlnRelayStaticSetUp(3) # set up rln relay inputs
require:
staticSetupRes3.isOk()
let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = staticSetupRes3.get()
# mount rlnrelay in off-chain mode
let mountRes3 = node3.mountRlnRelayStatic(group = groupOpt3.get(),
memKeyPair = memKeyPairOpt3.get(),
memIndex = memIndexOpt3.get(),
pubsubTopic = rlnRelayPubSubTopic,
contentTopic = contentTopic)
require:
mountRes3.isOk()
await node3.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false,
rlnRelayPubsubTopic: rlnRelayPubSubTopic,
rlnRelayContentTopic: contentTopic,
rlnRelayMembershipIndex: MembershipIndex(3),
))
await node3.start()
@ -151,56 +131,41 @@ procSuite "WakuNode - RLN relay":
rlnRelayPubSubTopic = RlnRelayPubsubTopic
contentTopic = ContentTopic("/waku/2/default-content/proto")
# set up three nodes
# node1
# set up three nodes
# node1
await node1.mountRelay(@[rlnRelayPubSubTopic])
let staticSetupRes1 = rlnRelayStaticSetUp(1) # set up rln relay inputs
require:
staticSetupRes1.isOk()
let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = staticSetupRes1.get()
# mount rlnrelay in off-chain mode
let mountRes1 = node1.mountRlnRelayStatic(group = groupOpt1.get(),
memKeyPair = memKeyPairOpt1.get(),
memIndex = memIndexOpt1.get(),
pubsubTopic = rlnRelayPubSubTopic,
contentTopic = contentTopic)
require:
mountRes1.isOk()
await node1.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false,
rlnRelayPubsubTopic: rlnRelayPubSubTopic,
rlnRelayContentTopic: contentTopic,
rlnRelayMembershipIndex: MembershipIndex(1),
))
await node1.start()
# node 2
await node2.mountRelay(@[rlnRelayPubSubTopic])
let staticSetupRes2 = rlnRelayStaticSetUp(2) # set up rln relay inputs
require:
staticSetupRes2.isOk()
let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = staticSetupRes2.get()
# mount rlnrelay in off-chain mode
let mountRes2 = node2.mountRlnRelayStatic(group = groupOpt2.get(),
memKeyPair = memKeyPairOpt2.get(),
memIndex = memIndexOpt2.get(),
pubsubTopic = rlnRelayPubSubTopic,
contentTopic = contentTopic)
require:
mountRes2.isOk()
await node2.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false,
rlnRelayPubsubTopic: rlnRelayPubSubTopic,
rlnRelayContentTopic: contentTopic,
rlnRelayMembershipIndex: MembershipIndex(2),
))
await node2.start()
# node 3
await node3.mountRelay(@[rlnRelayPubSubTopic])
let staticSetupRes3 = rlnRelayStaticSetUp(3) # set up rln relay inputs
require:
staticSetupRes3.isOk()
let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = staticSetupRes3.get()
# mount rlnrelay in off-chain mode
let mountRes3 = node3.mountRlnRelayStatic(group = groupOpt3.get(),
memKeyPair = memKeyPairOpt3.get(),
memIndex= memIndexOpt3.get(),
pubsubTopic = rlnRelayPubSubTopic,
contentTopic = contentTopic)
require:
mountRes3.isOk()
await node3.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false,
rlnRelayPubsubTopic: rlnRelayPubSubTopic,
rlnRelayContentTopic: contentTopic,
rlnRelayMembershipIndex: MembershipIndex(3),
))
await node3.start()
# connect them together
@ -278,55 +243,37 @@ procSuite "WakuNode - RLN relay":
# set up three nodes
# node1
await node1.mountRelay(@[rlnRelayPubSubTopic])
let staticSetupRes1 = rlnRelayStaticSetUp(1) # set up rln relay inputs
require:
staticSetupRes1.isOk()
let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = staticSetupRes1.get()
# mount rlnrelay in off-chain mode
let mountRes1 = node1.mountRlnRelayStatic(group = groupOpt1.get(),
memKeyPair = memKeyPairOpt1.get(),
memIndex = memIndexOpt1.get(),
pubsubTopic = rlnRelayPubSubTopic,
contentTopic = contentTopic)
require:
mountRes1.isOk()
await node1.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false,
rlnRelayPubsubTopic: rlnRelayPubSubTopic,
rlnRelayContentTopic: contentTopic,
rlnRelayMembershipIndex: MembershipIndex(1),
))
await node1.start()
# node 2
await node2.mountRelay(@[rlnRelayPubSubTopic])
let staticSetupRes2 = rlnRelayStaticSetUp(2) # set up rln relay inputs
require:
staticSetupRes2.isOk()
let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = staticSetupRes2.get()
# mount rlnrelay in off-chain mode
let mountRes2 = node2.mountRlnRelayStatic(group = groupOpt2.get(),
memKeyPair = memKeyPairOpt2.get(),
memIndex = memIndexOpt2.get(),
pubsubTopic = rlnRelayPubSubTopic,
contentTopic = contentTopic)
require:
mountRes2.isOk()
await node2.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false,
rlnRelayPubsubTopic: rlnRelayPubSubTopic,
rlnRelayContentTopic: contentTopic,
rlnRelayMembershipIndex: MembershipIndex(2),
))
await node2.start()
# node 3
await node3.mountRelay(@[rlnRelayPubSubTopic])
let staticSetupRes3 = rlnRelayStaticSetUp(3) # set up rln relay inputs
require:
staticSetupRes3.isOk()
let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = staticSetupRes3.get()
# mount rlnrelay in off-chain mode
let mountRes3 = node3.mountRlnRelayStatic(group = groupOpt3.get(),
memKeyPair = memKeyPairOpt3.get(),
memIndex = memIndexOpt3.get(),
pubsubTopic = rlnRelayPubSubTopic,
contentTopic = contentTopic)
require:
mountRes3.isOk()
await node3.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false,
rlnRelayPubsubTopic: rlnRelayPubSubTopic,
rlnRelayContentTopic: contentTopic,
rlnRelayMembershipIndex: MembershipIndex(3),
))
await node3.start()

View File

@ -43,7 +43,7 @@ import
when defined(rln):
import
../protocol/waku_rln_relay/protocol_types
../protocol/waku_rln_relay
declarePublicGauge waku_version, "Waku version info (in git describe format)", ["version"]
declarePublicCounter waku_node_messages, "number of messages received", ["type"]
@ -777,6 +777,22 @@ proc lightpushPublish*(node: WakuNode, pubsubTopic: PubsubTopic, message: WakuMe
error "failed to publish message", error=publishRes.error
## Waku RLN Relay
when defined(rln):
proc mountRlnRelay*(node: WakuNode,
rlnConf: WakuRlnConfig,
spamHandler: Option[SpamHandler] = none(SpamHandler),
registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)) {.async.} =
info "mounting rln relay"
let rlnRelayRes = await WakuRlnRelay.new(node.wakuRelay,
rlnConf,
spamHandler,
registrationHandler)
if rlnRelayRes.isErr():
error "failed to mount rln relay", error=rlnRelayRes.error
return
node.wakuRlnRelay = rlnRelayRes.get()
## Waku peer-exchange

View File

@ -3,11 +3,13 @@ import
./waku_rln_relay/constants,
./waku_rln_relay/protocol_types,
./waku_rln_relay/protocol_metrics,
./waku_rln_relay/utils
./waku_rln_relay/utils,
./waku_rln_relay/contract
export
rln,
constants,
protocol_types,
protocol_metrics,
utils
utils,
contract

View File

@ -23,8 +23,8 @@ import
import
../../utils/time,
../../utils/keyfile,
../../node/waku_node,
../waku_message
../waku_message,
../waku_relay
logScope:
topics = "waku rln_relay"
@ -971,7 +971,11 @@ proc handleGroupUpdates*(rlnPeer: WakuRLNRelay) {.async, gcsafe.} =
contractAddress = rlnPeer.membershipContractAddress,
handler = handler)
proc addRLNRelayValidator*(node: WakuNode, pubsubTopic: PubsubTopic, contentTopic: ContentTopic, spamHandler: Option[SpamHandler] = none(SpamHandler)) =
proc addRLNRelayValidator*(wakuRlnRelay: WakuRLNRelay,
wakuRelay: WakuRelay,
pubsubTopic: PubsubTopic,
contentTopic: ContentTopic,
spamHandler: Option[SpamHandler] = none(SpamHandler)) =
## this procedure is a thin wrapper for the pubsub addValidator method
## it sets a validator for the waku messages published on the supplied pubsubTopic and contentTopic
## if contentTopic is empty, then validation takes place for All the messages published on the given pubsubTopic
@ -998,7 +1002,7 @@ proc addRLNRelayValidator*(node: WakuNode, pubsubTopic: PubsubTopic, contentTopi
# validate the message
let
validationRes = node.wakuRlnRelay.validateMessage(wakumessage)
validationRes = wakuRlnRelay.validateMessage(wakumessage)
proof = toHex(msgProof.proof)
epoch = fromEpoch(msgProof.epoch)
root = inHex(msgProof.merkleRoot)
@ -1022,29 +1026,19 @@ proc addRLNRelayValidator*(node: WakuNode, pubsubTopic: PubsubTopic, contentTopi
handler(wakumessage)
return pubsub.ValidationResult.Reject
# set a validator for the supplied pubsubTopic
let pb = PubSub(node.wakuRelay)
let pb = PubSub(wakuRelay)
pb.addValidator(pubsubTopic, validator)
proc mountRlnRelayStatic*(node: WakuNode,
group: seq[IDCommitment],
memKeyPair: MembershipKeyPair,
memIndex: MembershipIndex,
pubsubTopic: PubsubTopic,
contentTopic: ContentTopic,
spamHandler: Option[SpamHandler] = none(SpamHandler)): RlnRelayResult[void] =
proc mountRlnRelayStatic*(wakuRelay: WakuRelay,
group: seq[IDCommitment],
memKeyPair: MembershipKeyPair,
memIndex: MembershipIndex,
pubsubTopic: PubsubTopic,
contentTopic: ContentTopic,
spamHandler: Option[SpamHandler] = none(SpamHandler)): RlnRelayResult[WakuRlnRelay] =
# 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():
return err("WakuRelay protocol is not mounted")
# check whether the pubsub topic is supported at the relay level
if pubsubTopic notin node.wakuRelay.defaultPubsubTopics:
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
if not memKeyPair.idCommitment == group[int(memIndex)]:
return err("The peer's index is not consistent with the group")
@ -1070,33 +1064,23 @@ proc mountRlnRelayStatic*(node: WakuNode,
# 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
# the topic validator checks for the correct non-spamming proof of the message
node.addRLNRelayValidator(pubsubTopic, contentTopic, spamHandler)
rlnPeer.addRLNRelayValidator(wakuRelay, pubsubTopic, contentTopic, spamHandler)
debug "rln relay topic validator is mounted successfully", pubsubTopic=pubsubTopic, contentTopic=contentTopic
node.wakuRlnRelay = rlnPeer
return ok()
return ok(rlnPeer)
proc mountRlnRelayDynamic*(node: WakuNode,
ethClientAddr: string = "",
ethAccountAddress: Option[web3.Address] = none(web3.Address),
ethAccountPrivKeyOpt: Option[keys.PrivateKey],
memContractAddr: web3.Address,
memKeyPair: Option[MembershipKeyPair] = none(MembershipKeyPair),
memIndex: Option[MembershipIndex] = none(MembershipIndex),
pubsubTopic: PubsubTopic,
contentTopic: ContentTopic,
spamHandler: Option[SpamHandler] = none(SpamHandler),
registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)) : Future[RlnRelayResult[void]] {.async.} =
proc mountRlnRelayDynamic*(wakuRelay: WakuRelay,
ethClientAddr: string = "",
ethAccountAddress: Option[web3.Address] = none(web3.Address),
ethAccountPrivKeyOpt: Option[keys.PrivateKey],
memContractAddr: web3.Address,
memKeyPair: Option[MembershipKeyPair] = none(MembershipKeyPair),
memIndex: Option[MembershipIndex] = none(MembershipIndex),
pubsubTopic: PubsubTopic,
contentTopic: ContentTopic,
spamHandler: Option[SpamHandler] = none(SpamHandler),
registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)) : Future[RlnRelayResult[WakuRlnRelay]] {.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:
return err("WakuRelay protocol is not mounted.")
# check whether the pubsub topic is supported at the relay level
if pubsubTopic notin node.wakuRelay.defaultPubsubTopics:
return err("WakuRelay protocol does not support the configured pubsub topic.")
debug "rln-relay input validation passed"
# create an RLN instance
let rlnInstance = createRLNInstance()
@ -1153,11 +1137,10 @@ proc mountRlnRelayDynamic*(node: WakuNode,
# 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
# the topic validator checks for the correct non-spamming proof of the message
addRLNRelayValidator(node, pubsubTopic, contentTopic, spamHandler)
rlnPeer.addRLNRelayValidator(wakuRelay, pubsubTopic, contentTopic, spamHandler)
debug "rln relay topic validator is mounted successfully", pubsubTopic=pubsubTopic, contentTopic=contentTopic
node.wakuRlnRelay = rlnPeer
return ok()
return ok(rlnPeer)
proc writeRlnCredentials*(path: string,
credentials: RlnMembershipCredentials,
@ -1204,34 +1187,37 @@ proc readRlnCredentials*(path: string,
except:
return err("Error while loading keyfile for RLN credentials at " & path)
proc mount(node: WakuNode,
proc mount(wakuRelay: WakuRelay,
conf: WakuRlnConfig,
spamHandler: Option[SpamHandler] = none(SpamHandler),
registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)
): Future[RlnRelayResult[void]] {.async.} =
# Returns RlnRelayResult[void], which indicates the success of the call
if not conf.rlnRelayDynamic:
): Future[RlnRelayResult[WakuRlnRelay]] {.async.} =
if not conf.rlnRelayDynamic:
info " setting up waku-rln-relay in off-chain mode... "
# set up rln relay inputs
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:
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
let mountRes = node.mountRlnRelayStatic(group = groupOpt.get(),
memKeyPair = memKeyPairOpt.get(),
memIndex= memIndexOpt.get(),
pubsubTopic = conf.rlnRelayPubsubTopic,
contentTopic = conf.rlnRelayContentTopic,
spamHandler = spamHandler)
let mountRes = mountRlnRelayStatic(wakuRelay,
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())
let rlnRelay = mountRes.get()
info "membership id key", idkey=memKeyPairOpt.get().idKey.inHex()
info "membership id commitment key", idCommitmentkey=memKeyPairOpt.get().idCommitment.inHex()
@ -1239,7 +1225,7 @@ proc mount(node: WakuNode,
# no error should happen as it is already captured in the unit tests
# TODO have added this check to account for unseen corner cases, will remove it later
let
rootRes = node.wakuRlnRelay.rlnInstance.getMerkleRoot()
rootRes = rlnRelay.rlnInstance.getMerkleRoot()
expectedRoot = StaticGroupMerkleRoot
if rootRes.isErr():
@ -1251,7 +1237,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()
return ok(rlnRelay)
else: # mount the rln relay protocol in the on-chain/dynamic mode
debug "setting up waku-rln-relay in on-chain mode... "
@ -1268,7 +1254,9 @@ proc mount(node: WakuNode,
var ethAccountPrivKeyOpt = none(keys.PrivateKey)
var ethAccountAddressOpt = none(Address)
var credentials = none(RlnMembershipCredentials)
var res: RlnRelayResult[void]
var rlnRelayRes: RlnRelayResult[WakuRlnRelay]
var rlnRelayCredPath: string
var persistCredentials: bool = false
if conf.rlnRelayEthAccountPrivateKey != "":
ethAccountPrivKeyOpt = some(keys.PrivateKey(SkSecretKey.fromHex(conf.rlnRelayEthAccountPrivateKey).value))
@ -1286,7 +1274,7 @@ proc mount(node: WakuNode,
# if there is a credential file, then no new credentials are generated, instead the content of the file is read and used to mount rln-relay
if conf.rlnRelayCredPath != "":
let rlnRelayCredPath = joinPath(conf.rlnRelayCredPath, RlnCredentialsFilename)
rlnRelayCredPath = joinPath(conf.rlnRelayCredPath, RlnCredentialsFilename)
debug "rln-relay credential path", rlnRelayCredPath
# check if there is an rln-relay credential file in the supplied path
@ -1298,7 +1286,7 @@ proc mount(node: WakuNode,
let readCredentialsRes = readRlnCredentials(rlnRelayCredPath, conf.rlnRelayCredentialsPassword)
if readCredentialsRes.isErr():
return err("RLN credentials cannot be read: " & readCredentialsRes.error())
return err("RLN credentials cannot be read: " & readCredentialsRes.error())
credentials = readCredentialsRes.get()
@ -1309,59 +1297,80 @@ proc mount(node: WakuNode,
if credentials.isSome():
# mount rln-relay in on-chain mode, with credentials that were read or generated
res = await node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress,
ethClientAddr = ethClientAddr,
ethAccountAddress = ethAccountAddressOpt,
ethAccountPrivKeyOpt = ethAccountPrivKeyOpt,
pubsubTopic = conf.rlnRelayPubsubTopic,
contentTopic = conf.rlnRelayContentTopic,
spamHandler = spamHandler,
registrationHandler = registrationHandler,
memKeyPair = some(credentials.get().membershipKeyPair),
memIndex = some(credentials.get().rlnIndex))
rlnRelayRes = await mountRlnRelayDynamic(wakuRelay,
memContractAddr = ethMemContractAddress,
ethClientAddr = ethClientAddr,
ethAccountAddress = ethAccountAddressOpt,
ethAccountPrivKeyOpt = ethAccountPrivKeyOpt,
pubsubTopic = conf.rlnRelayPubsubTopic,
contentTopic = conf.rlnRelayContentTopic,
spamHandler = spamHandler,
registrationHandler = registrationHandler,
memKeyPair = some(credentials.get().membershipKeyPair),
memIndex = some(credentials.get().rlnIndex))
else:
# mount rln-relay in on-chain mode, with the provided private key
res = await node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress,
ethClientAddr = ethClientAddr,
ethAccountAddress = ethAccountAddressOpt,
ethAccountPrivKeyOpt = ethAccountPrivKeyOpt,
pubsubTopic = conf.rlnRelayPubsubTopic,
contentTopic = conf.rlnRelayContentTopic,
spamHandler = spamHandler,
registrationHandler = registrationHandler)
rlnRelayRes = await mountRlnRelayDynamic(wakuRelay,
memContractAddr = ethMemContractAddress,
ethClientAddr = ethClientAddr,
ethAccountAddress = ethAccountAddressOpt,
ethAccountPrivKeyOpt = ethAccountPrivKeyOpt,
pubsubTopic = conf.rlnRelayPubsubTopic,
contentTopic = conf.rlnRelayContentTopic,
spamHandler = spamHandler,
registrationHandler = registrationHandler)
# TODO should be replaced with key-store with proper encryption
# persist rln credential
credentials = some(RlnMembershipCredentials(rlnIndex: node.wakuRlnRelay.membershipIndex,
membershipKeyPair: node.wakuRlnRelay.membershipKeyPair))
if writeRlnCredentials(rlnRelayCredPath, credentials.get(), conf.rlnRelayCredentialsPassword).isErr():
return err("error in storing rln credentials")
persistCredentials = true
else:
# 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 = await node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr,
ethAccountAddress = ethAccountAddressOpt, ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, pubsubTopic = conf.rlnRelayPubsubTopic,
contentTopic = conf.rlnRelayContentTopic, spamHandler = spamHandler, registrationHandler = registrationHandler)
rlnRelayRes = await mountRlnRelayDynamic(wakuRelay,
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()
if rlnRelayRes.isErr():
return err("dynamic rln-relay could not be mounted: " & rlnRelayRes.error())
let wakuRlnRelay = rlnRelayRes.get()
if persistCredentials:
# persist rln credential
credentials = some(RlnMembershipCredentials(rlnIndex: wakuRlnRelay.membershipIndex,
membershipKeyPair: wakuRlnRelay.membershipKeyPair))
if writeRlnCredentials(rlnRelayCredPath, credentials.get(), conf.rlnRelayCredentialsPassword).isErr():
return err("error in storing rln credentials")
return ok(wakuRlnRelay)
proc mountRlnRelay*(node: WakuNode,
conf: WakuRlnConfig,
spamHandler: Option[SpamHandler] = none(SpamHandler),
registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)
): Future[RlnRelayResult[void]] {.async.} =
proc new*(T: type WakuRlnRelay,
wakuRelay: WakuRelay,
conf: WakuRlnConfig,
spamHandler: Option[SpamHandler] = none(SpamHandler),
registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)
): Future[RlnRelayResult[WakuRlnRelay]] {.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,
# check whether inputs are provided
# relay protocol is the prerequisite of rln-relay
if wakuRelay.isNil():
return err("WakuRelay protocol is not mounted")
# check whether the pubsub topic is supported at the relay level
if conf.rlnRelayPubsubTopic notin wakuRelay.defaultPubsubTopics:
return err("The relay protocol does not support the configured pubsub topic")
debug "rln-relay input validation passed"
waku_rln_relay_mounting_duration_seconds.nanosecondTime:
let rlnRelayRes = await mount(
wakuRelay,
conf,
spamHandler,
registrationHandler
)
return res
return rlnRelayRes