mirror of
https://github.com/waku-org/nwaku.git
synced 2025-01-13 16:25:00 +00:00
deploy: 6c8ab0ab0f76fe765d95ef2f7bfb88d691a18bf7
This commit is contained in:
parent
d1f7da16c7
commit
3300ada856
@ -511,12 +511,12 @@ proc processInput(rfd: AsyncFD, rng: ref BrHmacDrbgContext) {.async.} =
|
||||
showChatPrompt(chat)
|
||||
|
||||
# set up rln relay inputs
|
||||
let (groupOpt, memKeyPairOpt, memIndexOpt) = rlnRelaySetUp(conf.rlnRelayMemIndex)
|
||||
let (groupOpt, memKeyPairOpt, memIndexOpt) = rlnRelayStaticSetUp(conf.rlnRelayMemIndex)
|
||||
if memIndexOpt.isNone:
|
||||
error "failed to mount WakuRLNRelay"
|
||||
else:
|
||||
# mount rlnrelay in offline mode (for now)
|
||||
waitFor node.mountRlnRelay(groupOpt = groupOpt, memKeyPairOpt = memKeyPairOpt, memIndexOpt= memIndexOpt, onchainMode = false, pubsubTopic = conf.rlnRelayPubsubTopic, contentTopic = conf.rlnRelayContentTopic, spamHandler = some(spamHandler))
|
||||
node.mountRlnRelayStatic(group = groupOpt.get(), memKeyPair = memKeyPairOpt.get(), memIndex = memIndexOpt.get(), pubsubTopic = conf.rlnRelayPubsubTopic, contentTopic = conf.rlnRelayContentTopic, spamHandler = some(spamHandler))
|
||||
|
||||
debug "membership id key", idkey=memKeyPairOpt.get().idKey.toHex
|
||||
debug "membership id commitment key", idCommitmentkey=memKeyPairOpt.get().idCommitment.toHex
|
||||
|
@ -45,10 +45,9 @@ procSuite "Waku rln relay":
|
||||
|
||||
# -------- mount rln-relay in the off-chain mode
|
||||
node.mountRelay(@[RLNRELAY_PUBSUB_TOPIC])
|
||||
await node.mountRlnRelay(groupOpt = some(groupIDCommitments),
|
||||
memKeyPairOpt = some(groupKeyPairs[index]),
|
||||
memIndexOpt = some(index),
|
||||
onchainMode = false,
|
||||
node.mountRlnRelayStatic(group = groupIDCommitments,
|
||||
memKeyPair = groupKeyPairs[index],
|
||||
memIndex = index,
|
||||
pubsubTopic = RLNRELAY_PUBSUB_TOPIC,
|
||||
contentTopic = RLNRELAY_CONTENT_TOPIC)
|
||||
|
||||
|
@ -155,7 +155,6 @@ procSuite "Waku-rln-relay":
|
||||
rlnInstance.isOk == true
|
||||
var rln = rlnInstance.value
|
||||
|
||||
# create rln membership key pair
|
||||
let keyPair = rln.membershipKeyGen()
|
||||
check:
|
||||
keyPair.isSome
|
||||
@ -273,7 +272,8 @@ procSuite "Waku-rln-relay":
|
||||
check:
|
||||
is_successful
|
||||
|
||||
asyncTest "mounting waku rln-relay":
|
||||
|
||||
asyncTest "mounting waku rln-relay: check correct Merkle tree construction in the static/off-chain group management":
|
||||
# preparation ------------------------------
|
||||
let
|
||||
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
||||
@ -281,17 +281,6 @@ procSuite "Waku-rln-relay":
|
||||
Port(60000))
|
||||
await node.start()
|
||||
|
||||
# deploy the contract
|
||||
let membershipContractAddress = await uploadRLNContract(ETH_CLIENT)
|
||||
|
||||
# prepare rln-relay inputs
|
||||
let
|
||||
web3 = await newWeb3(ETH_CLIENT)
|
||||
accounts = await web3.provider.eth_accounts()
|
||||
# choose one of the existing account for the rln-relay peer
|
||||
ethAccountAddress = accounts[0]
|
||||
await web3.close()
|
||||
|
||||
# create current peer's pk
|
||||
var rlnInstance = createRLNInstance()
|
||||
check:
|
||||
@ -321,18 +310,16 @@ procSuite "Waku-rln-relay":
|
||||
member_is_added = rln.insertMember(memberKeypair.get().idCommitment)
|
||||
doAssert(member_is_added)
|
||||
debug "member key", key = memberKeypair.get().idCommitment.toHex
|
||||
|
||||
let expectedRoot = rln.getMerkleRoot().value().toHex
|
||||
debug "expected root ", expectedRoot
|
||||
|
||||
# test ------------------------------
|
||||
# start rln-relay
|
||||
node.mountRelay(@[RLNRELAY_PUBSUB_TOPIC])
|
||||
await node.mountRlnRelay(ethClientAddrOpt = some(EthClient),
|
||||
ethAccAddrOpt = some(ethAccountAddress),
|
||||
memContractAddOpt = some(membershipContractAddress),
|
||||
groupOpt = some(group),
|
||||
memKeyPairOpt = some(keypair.get()),
|
||||
memIndexOpt = some(index),
|
||||
node.mountRlnRelayStatic(group = group,
|
||||
memKeyPair = keypair.get(),
|
||||
memIndex = index,
|
||||
pubsubTopic = RLNRELAY_PUBSUB_TOPIC,
|
||||
contentTopic = RLNRELAY_CONTENT_TOPIC)
|
||||
let calculatedRoot = node.wakuRlnRelay.rlnInstance.getMerkleRoot().value().toHex
|
||||
@ -341,4 +328,145 @@ procSuite "Waku-rln-relay":
|
||||
check:
|
||||
expectedRoot == calculatedRoot
|
||||
|
||||
await node.stop()
|
||||
await node.stop()
|
||||
|
||||
asyncTest "mounting waku rln-relay: check correct Merkle tree construction in the dynamic/onchain group management":
|
||||
# preparation ------------------------------
|
||||
let
|
||||
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
||||
node = WakuNode.new(nodeKey, ValidIpAddress.init("0.0.0.0"), Port(60000))
|
||||
await node.start()
|
||||
|
||||
# deploy the contract
|
||||
let contractAddress = await uploadRLNContract(ETH_CLIENT)
|
||||
|
||||
# prepare rln-relay inputs
|
||||
let
|
||||
web3 = await newWeb3(ETH_CLIENT)
|
||||
accounts = await web3.provider.eth_accounts()
|
||||
# choose one of the existing accounts for the rln-relay peer
|
||||
ethAccountAddress = accounts[0]
|
||||
web3.defaultAccount = accounts[0]
|
||||
|
||||
# create an rln instance
|
||||
var rlnInstance = createRLNInstance()
|
||||
check:
|
||||
rlnInstance.isOk == true
|
||||
var rln = rlnInstance.value
|
||||
|
||||
# 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.toHex
|
||||
debug "member key2", key = keyPair2.get().idCommitment.toHex
|
||||
|
||||
# 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)
|
||||
|
||||
# get the Merkle root
|
||||
let expectedRoot = rln.getMerkleRoot().value().toHex
|
||||
|
||||
# prepare a contract sender to interact with it
|
||||
var 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
|
||||
let tx1Hash = await contractObj.register(pk1).send(value = MEMBERSHIP_FEE)
|
||||
debug "a member is registered", tx1 = tx1Hash
|
||||
|
||||
# register another member to the contract
|
||||
let tx2Hash = await contractObj.register(pk2).send(value = MEMBERSHIP_FEE)
|
||||
debug "a member is registered", tx2 = tx2Hash
|
||||
|
||||
# test ------------------------------
|
||||
# start rln-relay
|
||||
node.mountRelay(@[RLNRELAY_PUBSUB_TOPIC])
|
||||
await node.mountRlnRelayDynamic(ethClientAddr = EthClient,
|
||||
ethAccAddr = ethAccountAddress,
|
||||
memContractAddr = contractAddress,
|
||||
memKeyPair = keyPair1,
|
||||
memIndex = some(MembershipIndex(0)),
|
||||
pubsubTopic = RLNRELAY_PUBSUB_TOPIC,
|
||||
contentTopic = RLNRELAY_CONTENT_TOPIC)
|
||||
|
||||
await sleepAsync(2000) # 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().toHex
|
||||
debug "calculated root ", calculatedRoot=calculatedRoot
|
||||
debug "expected root ", expectedRoot=expectedRoot
|
||||
|
||||
check:
|
||||
expectedRoot == calculatedRoot
|
||||
|
||||
|
||||
await web3.close()
|
||||
await node.stop()
|
||||
|
||||
asyncTest "mounting waku rln-relay: check correct registration of peers without rln-relay credentials in dynamic/on-chain mode":
|
||||
# deploy the contract
|
||||
let contractAddress = await uploadRLNContract(ETH_CLIENT)
|
||||
|
||||
# prepare rln-relay inputs
|
||||
let
|
||||
web3 = await newWeb3(ETH_CLIENT)
|
||||
accounts = await web3.provider.eth_accounts()
|
||||
# choose two of the existing accounts for the rln-relay peers
|
||||
ethAccountAddress1 = accounts[0]
|
||||
ethAccountAddress2 = accounts[1]
|
||||
await web3.close()
|
||||
|
||||
# prepare two nodes
|
||||
let
|
||||
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
||||
node = WakuNode.new(nodeKey, ValidIpAddress.init("0.0.0.0"), Port(60000))
|
||||
await node.start()
|
||||
|
||||
let
|
||||
nodeKey2 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
||||
node2 = WakuNode.new(nodeKey2, ValidIpAddress.init("0.0.0.0"), Port(60001))
|
||||
await node2.start()
|
||||
|
||||
# start rln-relay on the first node, leave rln-relay credentials empty
|
||||
node.mountRelay(@[RLNRELAY_PUBSUB_TOPIC])
|
||||
await node.mountRlnRelayDynamic(ethClientAddr = EthClient,
|
||||
ethAccAddr = ethAccountAddress1,
|
||||
memContractAddr = contractAddress,
|
||||
memKeyPair = none(MembershipKeyPair),
|
||||
memIndex = none(MembershipIndex),
|
||||
pubsubTopic = RLNRELAY_PUBSUB_TOPIC,
|
||||
contentTopic = RLNRELAY_CONTENT_TOPIC)
|
||||
|
||||
|
||||
|
||||
# start rln-relay on the second node, leave rln-relay credentials empty
|
||||
node2.mountRelay(@[RLNRELAY_PUBSUB_TOPIC])
|
||||
await node2.mountRlnRelayDynamic(ethClientAddr = EthClient,
|
||||
ethAccAddr = ethAccountAddress2,
|
||||
memContractAddr = contractAddress,
|
||||
memKeyPair = none(MembershipKeyPair),
|
||||
memIndex = none(MembershipIndex),
|
||||
pubsubTopic = RLNRELAY_PUBSUB_TOPIC,
|
||||
contentTopic = RLNRELAY_CONTENT_TOPIC)
|
||||
|
||||
# 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)
|
||||
|
||||
await node.stop()
|
||||
await node2.stop()
|
@ -725,36 +725,33 @@ procSuite "WakuNode":
|
||||
# set up three nodes
|
||||
# node1
|
||||
node1.mountRelay(@[rlnRelayPubSubTopic])
|
||||
let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = rlnRelaySetUp(1) # set up rln relay inputs
|
||||
let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = rlnRelayStaticSetUp(1) # set up rln relay inputs
|
||||
# mount rlnrelay in off-chain mode
|
||||
waitFor node1.mountRlnRelay(groupOpt = groupOpt1,
|
||||
memKeyPairOpt = memKeyPairOpt1,
|
||||
memIndexOpt= memIndexOpt1,
|
||||
onchainMode = false,
|
||||
node1.mountRlnRelayStatic(group = groupOpt1.get(),
|
||||
memKeyPair = memKeyPairOpt1.get(),
|
||||
memIndex = memIndexOpt1.get(),
|
||||
pubsubTopic = rlnRelayPubSubTopic,
|
||||
contentTopic = contentTopic)
|
||||
await node1.start()
|
||||
|
||||
# node 2
|
||||
node2.mountRelay(@[rlnRelayPubSubTopic])
|
||||
let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = rlnRelaySetUp(2) # set up rln relay inputs
|
||||
let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = rlnRelayStaticSetUp(2) # set up rln relay inputs
|
||||
# mount rlnrelay in off-chain mode
|
||||
waitFor node2.mountRlnRelay(groupOpt = groupOpt2,
|
||||
memKeyPairOpt = memKeyPairOpt2,
|
||||
memIndexOpt= memIndexOpt2,
|
||||
onchainMode = false,
|
||||
node2.mountRlnRelayStatic(group = groupOpt2.get(),
|
||||
memKeyPair = memKeyPairOpt2.get(),
|
||||
memIndex = memIndexOpt2.get(),
|
||||
pubsubTopic = rlnRelayPubSubTopic,
|
||||
contentTopic = contentTopic)
|
||||
await node2.start()
|
||||
|
||||
# node 3
|
||||
node3.mountRelay(@[rlnRelayPubSubTopic])
|
||||
let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = rlnRelaySetUp(3) # set up rln relay inputs
|
||||
let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = rlnRelayStaticSetUp(3) # set up rln relay inputs
|
||||
# mount rlnrelay in off-chain mode
|
||||
waitFor node3.mountRlnRelay(groupOpt = groupOpt3,
|
||||
memKeyPairOpt = memKeyPairOpt3,
|
||||
memIndexOpt= memIndexOpt3,
|
||||
onchainMode = false,
|
||||
node3.mountRlnRelayStatic(group = groupOpt3.get(),
|
||||
memKeyPair = memKeyPairOpt3.get(),
|
||||
memIndex = memIndexOpt3.get(),
|
||||
pubsubTopic = rlnRelayPubSubTopic,
|
||||
contentTopic = contentTopic)
|
||||
await node3.start()
|
||||
@ -818,36 +815,33 @@ procSuite "WakuNode":
|
||||
# set up three nodes
|
||||
# node1
|
||||
node1.mountRelay(@[rlnRelayPubSubTopic])
|
||||
let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = rlnRelaySetUp(1) # set up rln relay inputs
|
||||
let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = rlnRelayStaticSetUp(1) # set up rln relay inputs
|
||||
# mount rlnrelay in off-chain mode
|
||||
waitFor node1.mountRlnRelay(groupOpt = groupOpt1,
|
||||
memKeyPairOpt = memKeyPairOpt1,
|
||||
memIndexOpt= memIndexOpt1,
|
||||
onchainMode = false,
|
||||
node1.mountRlnRelayStatic(group = groupOpt1.get(),
|
||||
memKeyPair = memKeyPairOpt1.get(),
|
||||
memIndex = memIndexOpt1.get(),
|
||||
pubsubTopic = rlnRelayPubSubTopic,
|
||||
contentTopic = contentTopic)
|
||||
await node1.start()
|
||||
|
||||
# node 2
|
||||
node2.mountRelay(@[rlnRelayPubSubTopic])
|
||||
let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = rlnRelaySetUp(2) # set up rln relay inputs
|
||||
let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = rlnRelayStaticSetUp(2) # set up rln relay inputs
|
||||
# mount rlnrelay in off-chain mode
|
||||
waitFor node2.mountRlnRelay(groupOpt = groupOpt2,
|
||||
memKeyPairOpt = memKeyPairOpt2,
|
||||
memIndexOpt= memIndexOpt2,
|
||||
onchainMode = false,
|
||||
node2.mountRlnRelayStatic(group = groupOpt2.get(),
|
||||
memKeyPair = memKeyPairOpt2.get(),
|
||||
memIndex = memIndexOpt2.get(),
|
||||
pubsubTopic = rlnRelayPubSubTopic,
|
||||
contentTopic = contentTopic)
|
||||
await node2.start()
|
||||
|
||||
# node 3
|
||||
node3.mountRelay(@[rlnRelayPubSubTopic])
|
||||
let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = rlnRelaySetUp(3) # set up rln relay inputs
|
||||
let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = rlnRelayStaticSetUp(3) # set up rln relay inputs
|
||||
# mount rlnrelay in off-chain mode
|
||||
waitFor node3.mountRlnRelay(groupOpt = groupOpt3,
|
||||
memKeyPairOpt = memKeyPairOpt3,
|
||||
memIndexOpt= memIndexOpt3,
|
||||
onchainMode = false,
|
||||
node3.mountRlnRelayStatic(group = groupOpt3.get(),
|
||||
memKeyPair = memKeyPairOpt3.get(),
|
||||
memIndex= memIndexOpt3.get(),
|
||||
pubsubTopic = rlnRelayPubSubTopic,
|
||||
contentTopic = contentTopic)
|
||||
await node3.start()
|
||||
@ -926,36 +920,33 @@ procSuite "WakuNode":
|
||||
# set up three nodes
|
||||
# node1
|
||||
node1.mountRelay(@[rlnRelayPubSubTopic])
|
||||
let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = rlnRelaySetUp(1) # set up rln relay inputs
|
||||
let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = rlnRelayStaticSetUp(1) # set up rln relay inputs
|
||||
# mount rlnrelay in off-chain mode
|
||||
waitFor node1.mountRlnRelay(groupOpt = groupOpt1,
|
||||
memKeyPairOpt = memKeyPairOpt1,
|
||||
memIndexOpt= memIndexOpt1,
|
||||
onchainMode = false,
|
||||
node1.mountRlnRelayStatic(group = groupOpt1.get(),
|
||||
memKeyPair = memKeyPairOpt1.get(),
|
||||
memIndex = memIndexOpt1.get(),
|
||||
pubsubTopic = rlnRelayPubSubTopic,
|
||||
contentTopic = contentTopic)
|
||||
await node1.start()
|
||||
|
||||
# node 2
|
||||
node2.mountRelay(@[rlnRelayPubSubTopic])
|
||||
let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = rlnRelaySetUp(2) # set up rln relay inputs
|
||||
let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = rlnRelayStaticSetUp(2) # set up rln relay inputs
|
||||
# mount rlnrelay in off-chain mode
|
||||
waitFor node2.mountRlnRelay(groupOpt = groupOpt2,
|
||||
memKeyPairOpt = memKeyPairOpt2,
|
||||
memIndexOpt= memIndexOpt2,
|
||||
onchainMode = false,
|
||||
node2.mountRlnRelayStatic(group = groupOpt2.get(),
|
||||
memKeyPair = memKeyPairOpt2.get(),
|
||||
memIndex = memIndexOpt2.get(),
|
||||
pubsubTopic = rlnRelayPubSubTopic,
|
||||
contentTopic = contentTopic)
|
||||
await node2.start()
|
||||
|
||||
# node 3
|
||||
node3.mountRelay(@[rlnRelayPubSubTopic])
|
||||
let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = rlnRelaySetUp(3) # set up rln relay inputs
|
||||
let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = rlnRelayStaticSetUp(3) # set up rln relay inputs
|
||||
# mount rlnrelay in off-chain mode
|
||||
waitFor node3.mountRlnRelay(groupOpt = groupOpt3,
|
||||
memKeyPairOpt = memKeyPairOpt3,
|
||||
memIndexOpt= memIndexOpt3,
|
||||
onchainMode = false,
|
||||
node3.mountRlnRelayStatic(group = groupOpt3.get(),
|
||||
memKeyPair = memKeyPairOpt3.get(),
|
||||
memIndex = memIndexOpt3.get(),
|
||||
pubsubTopic = rlnRelayPubSubTopic,
|
||||
contentTopic = contentTopic)
|
||||
await node3.start()
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# libtool - Provide generalized library-building support services.
|
||||
# Generated automatically by config.status (libbacktrace) version-unused
|
||||
# Libtool was configured on host fv-az447-649:
|
||||
# Libtool was configured on host fv-az241-328:
|
||||
# NOTE: Changes made to this file will be lost: look at ltmain.sh.
|
||||
#
|
||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
|
||||
|
@ -8,6 +8,7 @@ import
|
||||
libp2p/crypto/secp,
|
||||
nimcrypto/utils,
|
||||
eth/keys,
|
||||
web3,
|
||||
../protocol/waku_rln_relay/waku_rln_relay_types,
|
||||
../protocol/waku_message
|
||||
|
||||
@ -129,6 +130,36 @@ type
|
||||
defaultValue: "/toy-chat/2/luzhou/proto"
|
||||
name: "rln-relay-content-topic" }: ContentTopic
|
||||
|
||||
rlnRelayDynamic* {.
|
||||
desc: "Enable waku-rln-relay with on-chain dynamic group management: true|false",
|
||||
defaultValue: false
|
||||
name: "rln-relay-dynamic" }: bool
|
||||
|
||||
rlnRelayIdKey* {.
|
||||
desc: "Rln relay identity secret key as a Hex string",
|
||||
defaultValue: ""
|
||||
name: "rln-relay-id" }: string
|
||||
|
||||
rlnRelayIdCommitmentKey* {.
|
||||
desc: "Rln relay identity commitment key as a Hex string",
|
||||
defaultValue: ""
|
||||
name: "rln-relay-id-commitment" }: string
|
||||
|
||||
rlnRelayEthAccount* {.
|
||||
desc: "Ethereum testnet account address",
|
||||
defaultValue: ""
|
||||
name: "eth-account-address" }: string
|
||||
|
||||
rlnRelayEthClientAddress* {.
|
||||
desc: "Ethereum testnet client address e.g., ws://localhost:8540/",
|
||||
defaultValue: "ws://localhost:8540/"
|
||||
name: "eth-client-address" }: string
|
||||
|
||||
rlnRelayEthMemContractAddress* {.
|
||||
desc: "Address of membership contract on an Ethereum testnet",
|
||||
defaultValue: ""
|
||||
name: "eth-mem-contract-address" }: string
|
||||
|
||||
staticnodes* {.
|
||||
desc: "Peer multiaddr to directly connect with. Argument may be repeated."
|
||||
name: "staticnode" }: seq[string]
|
||||
|
@ -6,6 +6,7 @@ import
|
||||
stew/shims/net as stewNet,
|
||||
stew/byteutils,
|
||||
eth/keys,
|
||||
nimcrypto,
|
||||
eth/p2p/discoveryv5/enr,
|
||||
libp2p/crypto/crypto,
|
||||
libp2p/protocols/ping,
|
||||
@ -38,7 +39,7 @@ when defined(rln):
|
||||
import
|
||||
libp2p/protocols/pubsub/rpc/messages,
|
||||
libp2p/protocols/pubsub/pubsub,
|
||||
web3,
|
||||
web3, web3/ethtypes,
|
||||
../protocol/waku_rln_relay/[rln, waku_rln_relay_utils]
|
||||
|
||||
declarePublicCounter waku_node_messages, "number of messages received", ["type"]
|
||||
@ -543,20 +544,17 @@ when defined(rln):
|
||||
let pb = PubSub(node.wakuRelay)
|
||||
pb.addValidator(pubsubTopic, validator)
|
||||
|
||||
proc mountRlnRelay*(node: WakuNode,
|
||||
ethClientAddrOpt: Option[string] = none(string),
|
||||
ethAccAddrOpt: Option[web3.Address] = none(web3.Address),
|
||||
memContractAddOpt: Option[web3.Address] = none(web3.Address),
|
||||
groupOpt: Option[seq[IDCommitment]] = none(seq[IDCommitment]),
|
||||
memKeyPairOpt: Option[MembershipKeyPair] = none(MembershipKeyPair),
|
||||
memIndexOpt: Option[MembershipIndex] = none(MembershipIndex),
|
||||
onchainMode: bool = true,
|
||||
proc mountRlnRelayStatic*(node: WakuNode,
|
||||
group: seq[IDCommitment],
|
||||
memKeyPair: MembershipKeyPair,
|
||||
memIndex: MembershipIndex,
|
||||
pubsubTopic: string,
|
||||
contentTopic: ContentTopic,
|
||||
spamHandler: Option[SpamHandler] = none(SpamHandler)) {.async.} =
|
||||
spamHandler: Option[SpamHandler] = none(SpamHandler)) {.raises: [Defect, IOError].}=
|
||||
# TODO return a bool value to indicate the success of the call
|
||||
# check whether inputs are provided
|
||||
|
||||
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 "Failed to mount WakuRLNRelay. Relay protocol is not mounted."
|
||||
@ -565,41 +563,8 @@ when defined(rln):
|
||||
if pubsubTopic notin node.wakuRelay.defaultTopics:
|
||||
error "Failed to mount WakuRLNRelay. The relay protocol does not support the configured pubsub topic.", pubsubTopic=pubsubTopic
|
||||
return
|
||||
if onchainMode:
|
||||
if memContractAddOpt.isNone():
|
||||
error "failed to mount rln relay: membership contract address is not provided"
|
||||
return
|
||||
if ethClientAddrOpt.isNone():
|
||||
error "failed to mount rln relay: Ethereum client address is not provided"
|
||||
return
|
||||
if ethAccAddrOpt.isNone():
|
||||
error "failed to mount rln relay: Ethereum account address is not provided"
|
||||
return
|
||||
else:
|
||||
if groupOpt.isNone():
|
||||
error "failed to mount rln relay: group information is not provided"
|
||||
return
|
||||
|
||||
if memKeyPairOpt.isNone():
|
||||
error "failed to mount rln relay: membership key of the node is not provided"
|
||||
return
|
||||
if memIndexOpt.isNone():
|
||||
error "failed to mount rln relay: membership index is not provided"
|
||||
return
|
||||
|
||||
var
|
||||
ethClientAddr: string
|
||||
ethAccAddr: web3.Address
|
||||
memContractAdd: web3.Address
|
||||
if onchainMode:
|
||||
ethClientAddr = ethClientAddrOpt.get()
|
||||
ethAccAddr = ethAccAddrOpt.get()
|
||||
memContractAdd = memContractAddOpt.get()
|
||||
|
||||
let
|
||||
group = groupOpt.get()
|
||||
memKeyPair = memKeyPairOpt.get()
|
||||
memIndex = memIndexOpt.get()
|
||||
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)])
|
||||
@ -609,40 +574,94 @@ when defined(rln):
|
||||
doAssert(rlnInstance.isOk)
|
||||
var rln = rlnInstance.value
|
||||
|
||||
# generate the membership keys if none is provided
|
||||
# in a happy path, this condition never gets through for a static group of users
|
||||
# the node should pass its keys i.e., memKeyPairOpt to the function
|
||||
if not memKeyPairOpt.isSome:
|
||||
let membershipKeyPair = rln.membershipKeyGen()
|
||||
# check whether keys are generated
|
||||
doAssert(membershipKeyPair.isSome())
|
||||
debug "the membership key for the rln relay is generated", idKey=membershipKeyPair.get().idKey.toHex, idCommitment=membershipKeyPair.get().idCommitment.toHex
|
||||
|
||||
|
||||
# add members to the Merkle tree
|
||||
for index in 0..group.len-1:
|
||||
let member = group[index]
|
||||
let member_is_added = rln.insertMember(member)
|
||||
doAssert(member_is_added)
|
||||
|
||||
|
||||
# create the WakuRLNRelay
|
||||
var rlnPeer = WakuRLNRelay(membershipKeyPair: memKeyPair,
|
||||
membershipIndex: memIndex,
|
||||
membershipContractAddress: memContractAdd,
|
||||
rlnInstance: rln,
|
||||
pubsubTopic: pubsubTopic,
|
||||
contentTopic: contentTopic)
|
||||
|
||||
# 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)
|
||||
debug "rln relay topic validator is mounted successfully", pubsubTopic=pubsubTopic, contentTopic=contentTopic
|
||||
|
||||
node.wakuRlnRelay = rlnPeer
|
||||
|
||||
|
||||
proc mountRlnRelayDynamic*(node: WakuNode,
|
||||
ethClientAddr: string = "",
|
||||
ethAccAddr: web3.Address,
|
||||
memContractAddr: web3.Address,
|
||||
memKeyPair: Option[MembershipKeyPair] = none(MembershipKeyPair),
|
||||
memIndex: Option[MembershipIndex] = none(MembershipIndex),
|
||||
pubsubTopic: string,
|
||||
contentTopic: ContentTopic,
|
||||
spamHandler: Option[SpamHandler] = none(SpamHandler)) {.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 "Failed to mount WakuRLNRelay. Relay protocol is not mounted."
|
||||
return
|
||||
# check whether the pubsub topic is supported at the relay level
|
||||
if pubsubTopic notin node.wakuRelay.defaultTopics:
|
||||
error "Failed to mount WakuRLNRelay. The relay protocol does not support the configured pubsub topic.", pubsubTopic=pubsubTopic
|
||||
return
|
||||
debug "rln-relay input validation passed"
|
||||
|
||||
# create an RLN instance
|
||||
var rlnInstance = createRLNInstance()
|
||||
doAssert(rlnInstance.isOk)
|
||||
var rln = rlnInstance.value
|
||||
|
||||
# prepare rln membership key pair
|
||||
var
|
||||
keyPair: MembershipKeyPair
|
||||
rlnIndex: MembershipIndex
|
||||
if memKeyPair.isNone: # if non provided, create one and register to the contract
|
||||
trace "no rln-relay key is provided, generating one"
|
||||
let keyPairOpt = rln.membershipKeyGen()
|
||||
doAssert(keyPairOpt.isSome)
|
||||
keyPair = keyPairOpt.get()
|
||||
# register the rln-relay peer to the membership contract
|
||||
let regIndexRes = await register(idComm = keyPair.idCommitment, ethAccountAddress = ethAccAddr, ethClientAddress = ethClientAddr, membershipContractAddress = memContractAddr)
|
||||
# check whether registration is done
|
||||
doAssert(regIndexRes.isOk())
|
||||
rlnIndex = regIndexRes.value
|
||||
debug "peer is successfully registered into the membership contract", rlnIndex=rlnIndex, idComm=keyPair.idCommitment.toHex(), idKey=keyPair.idKey.toHex()
|
||||
else:
|
||||
keyPair = memKeyPair.get()
|
||||
rlnIndex = memIndex.get()
|
||||
|
||||
# create the WakuRLNRelay
|
||||
var rlnPeer = WakuRLNRelay(membershipKeyPair: keyPair,
|
||||
membershipIndex: rlnIndex,
|
||||
membershipContractAddress: memContractAddr,
|
||||
ethClientAddress: ethClientAddr,
|
||||
ethAccountAddress: ethAccAddr,
|
||||
rlnInstance: rln,
|
||||
pubsubTopic: pubsubTopic,
|
||||
contentTopic: contentTopic)
|
||||
|
||||
if onchainMode:
|
||||
# register the rln-relay peer to the membership contract
|
||||
let isSuccessful = await rlnPeer.register()
|
||||
# check whether registration is done
|
||||
doAssert(isSuccessful)
|
||||
debug "peer is successfully registered into the membership contract"
|
||||
|
||||
proc handler(pubkey: Uint256, index: Uint256) =
|
||||
debug "a new key is added", pubkey=pubkey
|
||||
# assuming all the members arrive in order
|
||||
let pk = pubkey.toIDCommitment()
|
||||
let isSuccessful = rlnPeer.rlnInstance.insertMember(pk)
|
||||
debug "received pk", pk=pk.toHex, index =index
|
||||
doAssert(isSuccessful)
|
||||
|
||||
asyncSpawn rlnPeer.handleGroupUpdates(handler)
|
||||
debug "dynamic group management is started"
|
||||
# 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
|
||||
@ -1207,29 +1226,51 @@ when isMainModule:
|
||||
|
||||
when defined(rln):
|
||||
if conf.rlnRelay:
|
||||
info "WakuRLNRelay is enabled"
|
||||
if not conf.rlnRelayDynamic:
|
||||
info " setting up waku-rln-relay in on-chain mode... "
|
||||
# set up rln relay inputs
|
||||
let (groupOpt, memKeyPairOpt, memIndexOpt) = rlnRelayStaticSetUp(conf.rlnRelayMemIndex)
|
||||
if memIndexOpt.isNone:
|
||||
error "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)
|
||||
|
||||
# set up rln relay inputs
|
||||
let (groupOpt, memKeyPairOpt, memIndexOpt) = rlnRelaySetUp(conf.rlnRelayMemIndex)
|
||||
if memIndexOpt.isNone:
|
||||
error "failed to mount WakuRLNRelay"
|
||||
info "membership id key", idkey=memKeyPairOpt.get().idKey.toHex
|
||||
info "membership id commitment key", idCommitmentkey=memKeyPairOpt.get().idCommitment.toHex
|
||||
|
||||
# check the correct construction of the tree by comparing the calculated root against the expected root
|
||||
# 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
|
||||
root = node.wakuRlnRelay.rlnInstance.getMerkleRoot.value.toHex()
|
||||
expectedRoot = STATIC_GROUP_MERKLE_ROOT
|
||||
if root != expectedRoot:
|
||||
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
|
||||
else:
|
||||
# mount rlnrelay in offline mode (for now)
|
||||
waitFor node.mountRlnRelay(groupOpt = groupOpt, memKeyPairOpt = memKeyPairOpt, memIndexOpt= memIndexOpt, onchainMode = false, pubsubTopic = conf.rlnRelayPubsubTopic, contentTopic = conf.rlnRelayContentTopic)
|
||||
|
||||
info "membership id key", idkey=memKeyPairOpt.get().idKey.toHex
|
||||
info "membership id commitment key", idCommitmentkey=memKeyPairOpt.get().idCommitment.toHex
|
||||
|
||||
# check the correct construction of the tree by comparing the calculated root against the expected root
|
||||
# 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
|
||||
info " setting up waku-rln-relay in on-chain mode... "
|
||||
|
||||
# read related inputs to run rln-relay in on-chain mode and do type conversion when needed
|
||||
let
|
||||
root = node.wakuRlnRelay.rlnInstance.getMerkleRoot.value.toHex()
|
||||
expectedRoot = STATIC_GROUP_MERKLE_ROOT
|
||||
if root != expectedRoot:
|
||||
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
|
||||
ethAccountAddr = web3.fromHex(web3.Address, conf.rlnRelayEthAccount)
|
||||
ethClientAddr = conf.rlnRelayEthClientAddress
|
||||
ethMemContractAddress = web3.fromHex(web3.Address, conf.rlnRelayEthMemContractAddress)
|
||||
rlnRelayId = conf.rlnRelayIdKey
|
||||
rlnRelayIdCommitmentKey = conf.rlnRelayIdCommitmentKey
|
||||
rlnRelayIndex = conf.rlnRelayMemIndex
|
||||
# check if the peer has provided its rln credentials
|
||||
if rlnRelayIdCommitmentKey != "" and rlnRelayId != "":
|
||||
# type conversation from hex strings to MembershipKeyPair
|
||||
let keyPair = @[(rlnRelayId, rlnRelayIdCommitmentKey)]
|
||||
let memKeyPair = keyPair.toMembershipKeyPairs()[0]
|
||||
# mount the rln relay protocol in the on-chain/dynamic mode
|
||||
waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr, memKeyPair = some(memKeyPair), memIndex = some(rlnRelayIndex), ethAccAddr = ethAccountAddr, pubsubTopic = conf.rlnRelayPubsubTopic, contentTopic = conf.rlnRelayContentTopic)
|
||||
else:
|
||||
# no rln credential is provided
|
||||
# mount the rln relay protocol in the on-chain/dynamic mode
|
||||
waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr, ethAccAddr = ethAccountAddr, pubsubTopic = conf.rlnRelayPubsubTopic, contentTopic = conf.rlnRelayContentTopic)
|
||||
|
||||
if conf.swap:
|
||||
mountSwap(node)
|
||||
|
@ -74,7 +74,7 @@ type WakuRLNRelay* = ref object
|
||||
# this field is required for signing transactions
|
||||
# TODO may need to erase this ethAccountPrivateKey when is not used
|
||||
# TODO may need to make ethAccountPrivateKey mandatory
|
||||
ethAccountPrivateKey*: Option[PrivateKey]
|
||||
ethAccountPrivateKey*: PrivateKey
|
||||
rlnInstance*: RLN[Bn256]
|
||||
pubsubTopic*: string # the pubsub topic for which rln relay is mounted
|
||||
# contentTopic should be of type waku_message.ContentTopic, however, due to recursive module dependency, the underlying type of ContentTopic is used instead
|
||||
|
@ -4,9 +4,10 @@ import
|
||||
std/sequtils, tables, times,
|
||||
chronicles, options, chronos, stint,
|
||||
web3, json,
|
||||
eth/keys,
|
||||
stew/results,
|
||||
stew/[byteutils, arrayops, endians2],
|
||||
rln,
|
||||
rln,
|
||||
waku_rln_relay_types,
|
||||
../waku_message
|
||||
|
||||
@ -65,6 +66,7 @@ proc createRLNInstance*(d: int = MERKLE_TREE_DEPTH): RLNResult
|
||||
return err("error in parameters generation")
|
||||
return ok(rlnInstance)
|
||||
|
||||
|
||||
proc membershipKeyGen*(ctxPtr: RLN[Bn256]): Option[MembershipKeyPair] =
|
||||
## generates a MembershipKeyPair that can be used for the registration into the rln membership contract
|
||||
|
||||
@ -99,28 +101,65 @@ proc membershipKeyGen*(ctxPtr: RLN[Bn256]): Option[MembershipKeyPair] =
|
||||
return some(keypair)
|
||||
|
||||
proc toUInt256*(idCommitment: IDCommitment): UInt256 =
|
||||
let pk = cast[UInt256](idCommitment)
|
||||
let pk = UInt256.fromBytesBE(idCommitment)
|
||||
return pk
|
||||
|
||||
proc toIDCommitment*(idCommitment: UInt256): IDCommitment =
|
||||
let pk = cast[IDCommitment](idCommitment)
|
||||
proc toIDCommitment*(idCommitmentUint: UInt256): IDCommitment =
|
||||
let pk = IDCommitment(idCommitmentUint.toBytesBE())
|
||||
return pk
|
||||
|
||||
proc toMembershipIndex(v: UInt256): MembershipIndex =
|
||||
let result: MembershipIndex = cast[MembershipIndex](v)
|
||||
return result
|
||||
|
||||
proc register*(idComm: IDCommitment, ethAccountAddress: Address, ethClientAddress: string, membershipContractAddress: Address): Future[Result[MembershipIndex, string]] {.async.} =
|
||||
# TODO may need to also get eth Account Private Key as PrivateKey
|
||||
## registers the idComm into the membership contract whose address is in rlnPeer.membershipContractAddress
|
||||
let web3 = await newWeb3(ethClientAddress)
|
||||
web3.defaultAccount = ethAccountAddress
|
||||
|
||||
# when the private key is set in a web3 instance, the send proc (sender.register(pk).send(MEMBERSHIP_FEE))
|
||||
# does the signing using the provided key
|
||||
# web3.privateKey = some(ethAccountPrivateKey)
|
||||
var sender = web3.contractSender(MembershipContract, membershipContractAddress) # creates a Sender object with a web3 field and contract address of type Address
|
||||
|
||||
debug "registering an id commitment", idComm=idComm
|
||||
let
|
||||
pk = idComm.toUInt256()
|
||||
txHash = await sender.register(pk).send(MEMBERSHIP_FEE)
|
||||
tsReceipt = await web3.getMinedTransactionReceipt(txHash)
|
||||
|
||||
# the receipt topic holds the hash of signature of the raised events
|
||||
let firstTopic = tsReceipt.logs[0].topics[0]
|
||||
# the hash of the signature of MemberRegistered(uint256,uint256) event is equal to the following hex value
|
||||
if firstTopic[0..65] != "0x5a92c2530f207992057b9c3e544108ffce3beda4a63719f316967c49bf6159d2":
|
||||
return err("invalid event signature hash")
|
||||
|
||||
# the arguments of the raised event i.e., MemberRegistered are encoded inside the data field
|
||||
# data = pk encoded as 256 bits || index encoded as 256 bits
|
||||
let arguments = tsReceipt.logs[0].data
|
||||
debug "tx log data", arguments=arguments
|
||||
let
|
||||
argumentsBytes = arguments.hexToSeqByte()
|
||||
eventIdCommUint = UInt256.fromBytesBE(argumentsBytes[0..31])
|
||||
eventIndex = UInt256.fromBytesBE(argumentsBytes[32..^1])
|
||||
eventIdComm = eventIdCommUint.toIDCommitment()
|
||||
debug "the identity commitment key extracted from tx log", eventIdComm=eventIdComm
|
||||
debug "the index of registered identity commitment key", eventIndex=eventIndex
|
||||
|
||||
if eventIdComm != idComm:
|
||||
return err("invalid id commitment key")
|
||||
|
||||
|
||||
await web3.close()
|
||||
return ok(toMembershipIndex(eventIndex))
|
||||
|
||||
proc register*(rlnPeer: WakuRLNRelay): Future[bool] {.async.} =
|
||||
## registers the public key of the rlnPeer which is rlnPeer.membershipKeyPair.publicKey
|
||||
## into the membership contract whose address is in rlnPeer.membershipContractAddress
|
||||
let web3 = await newWeb3(rlnPeer.ethClientAddress)
|
||||
web3.defaultAccount = rlnPeer.ethAccountAddress
|
||||
# when the private key is set in a web3 instance, the send proc (sender.register(pk).send(MEMBERSHIP_FEE))
|
||||
# does the signing using the provided key
|
||||
web3.privateKey = rlnPeer.ethAccountPrivateKey
|
||||
var sender = web3.contractSender(MembershipContract,
|
||||
rlnPeer.membershipContractAddress) # creates a Sender object with a web3 field and contract address of type Address
|
||||
let pk = rlnPeer.membershipKeyPair.idCommitment.toUInt256()
|
||||
discard await sender.register(pk).send(MEMBERSHIP_FEE)
|
||||
debug "pk", pk = pk
|
||||
# TODO check the receipt and then return true/false
|
||||
await web3.close()
|
||||
let pk = rlnPeer.membershipKeyPair.idCommitment
|
||||
discard await register(idComm = pk, ethAccountAddress = rlnPeer.ethAccountAddress, ethClientAddress = rlnPeer.ethClientAddress, membershipContractAddress = rlnPeer.membershipContractAddress )
|
||||
|
||||
return true
|
||||
|
||||
proc appendLength*(input: openArray[byte]): seq[byte] =
|
||||
@ -343,7 +382,7 @@ proc createMembershipList*(n: int): (seq[(string, string)], string) {.raises: [
|
||||
let root = rln.getMerkleRoot().value.toHex
|
||||
return (output, root)
|
||||
|
||||
proc rlnRelaySetUp*(rlnRelayMemIndex: MembershipIndex): (Option[seq[
|
||||
proc rlnRelayStaticSetUp*(rlnRelayMemIndex: MembershipIndex): (Option[seq[
|
||||
IDCommitment]], Option[MembershipKeyPair], Option[
|
||||
MembershipIndex]) {.raises: [Defect, ValueError].} =
|
||||
let
|
||||
@ -579,6 +618,7 @@ proc subscribeToGroupEvents(ethClientUri: string, contractAddress: Address, bloc
|
||||
debug "onRegister", pubkey = pubkey, index = index
|
||||
handler(pubkey, index)
|
||||
except Exception as err:
|
||||
# chronos still raises exceptions which inherit directly from Exception
|
||||
doAssert false, err.msg
|
||||
do (err: CatchableError):
|
||||
echo "Error from subscription: ", err.msg
|
||||
|
Loading…
x
Reference in New Issue
Block a user