deploy: 645832e9fd42f41eeb6932983aa9575592e024f8

This commit is contained in:
staheri14 2021-09-24 17:57:33 +00:00
parent 329d305416
commit 667b2422f9
9 changed files with 117 additions and 90 deletions

View File

@ -23,7 +23,7 @@ proc runBackground() {.async.} =
Port(uint16(conf.tcpPort) + conf.portsShift), extIp, extTcpPort) Port(uint16(conf.tcpPort) + conf.portsShift), extIp, extTcpPort)
await node.start() await node.start()
node.mountRelay(rlnRelayEnabled = conf.rlnrelay) node.mountRelay()
# Subscribe to a topic # Subscribe to a topic
let topic = cast[Topic]("foobar") let topic = cast[Topic]("foobar")

View File

@ -326,7 +326,6 @@ proc processInput(rfd: AsyncFD, rng: ref BrHmacDrbgContext) {.async.} =
await node.start() await node.start()
node.mountRelay(conf.topics.split(" "), node.mountRelay(conf.topics.split(" "),
rlnRelayEnabled = conf.rlnRelay,
relayMessages = conf.relay) # Indicates if node is capable to relay messages relayMessages = conf.relay) # Indicates if node is capable to relay messages
node.mountLibp2pPing() node.mountLibp2pPing()

View File

@ -11,6 +11,8 @@ import
../test_helpers, ../test_helpers,
./test_utils ./test_utils
const RLNRELAY_PUBSUB_TOPIC = "waku/2/rlnrelay/proto"
# POSEIDON_HASHER_CODE holds the bytecode of Poseidon hasher solidity smart contract: # POSEIDON_HASHER_CODE holds the bytecode of Poseidon hasher solidity smart contract:
# https://github.com/kilic/rlnapp/blob/master/packages/contracts/contracts/crypto/PoseidonHasher.sol # https://github.com/kilic/rlnapp/blob/master/packages/contracts/contracts/crypto/PoseidonHasher.sol
# the solidity contract is compiled separately and the resultant bytecode is copied here # the solidity contract is compiled separately and the resultant bytecode is copied here
@ -244,7 +246,8 @@ procSuite "Waku rln relay":
debug "expected root ", expectedRoot debug "expected root ", expectedRoot
# start rln-relay # start rln-relay
await node.mountRlnRelay(ethClientAddrOpt = some(EthClient), ethAccAddrOpt = some(ethAccountAddress), memContractAddOpt = some(membershipContractAddress), groupOpt = some(group), memKeyPairOpt = some(keypair.get()), memIndexOpt = some(index)) node.mountRelay()
await node.mountRlnRelay(ethClientAddrOpt = some(EthClient), ethAccAddrOpt = some(ethAccountAddress), memContractAddOpt = some(membershipContractAddress), groupOpt = some(group), memKeyPairOpt = some(keypair.get()), memIndexOpt = some(index), pubsubTopic = RLNRELAY_PUBSUB_TOPIC)
let calculatedRoot = node.wakuRlnRelay.rlnInstance.getMerkleRoot().value().toHex let calculatedRoot = node.wakuRlnRelay.rlnInstance.getMerkleRoot().value().toHex
debug "calculated root ", calculatedRoot debug "calculated root ", calculatedRoot
@ -274,10 +277,11 @@ procSuite "Waku rln relay":
# index indicates the position of a membership key pair in the static list of group keys i.e., groupKeyPairs # index indicates the position of a membership key pair in the static list of group keys i.e., groupKeyPairs
# the corresponding key pair will be used to mount rlnRelay on the current node # the corresponding key pair will be used to mount rlnRelay on the current node
# index also represents the index of the leaf in the Merkle tree that contains node's commitment key # index also represents the index of the leaf in the Merkle tree that contains node's commitment key
let index = MembeshipIndex(5) let index = MembershipIndex(5)
# -------- mount rln-relay in the off-chain mode # -------- mount rln-relay in the off-chain mode
await node.mountRlnRelay(groupOpt = some(groupIDCommitments), memKeyPairOpt = some(groupKeyPairs[index]), memIndexOpt = some(index), onchainMode = false) node.mountRelay()
await node.mountRlnRelay(groupOpt = some(groupIDCommitments), memKeyPairOpt = some(groupKeyPairs[index]), memIndexOpt = some(index), onchainMode = false, pubsubTopic = RLNRELAY_PUBSUB_TOPIC)
# get the root of Merkle tree which is constructed inside the mountRlnRelay proc # get the root of Merkle tree which is constructed inside the mountRlnRelay proc
let calculatedRoot = node.wakuRlnRelay.rlnInstance.getMerkleRoot().value().toHex let calculatedRoot = node.wakuRlnRelay.rlnInstance.getMerkleRoot().value().toHex
@ -420,7 +424,7 @@ suite "Waku rln relay":
rlnInstance.isOk == true rlnInstance.isOk == true
# delete the first member # delete the first member
var deleted_member_index = MembeshipIndex(0) var deleted_member_index = MembershipIndex(0)
let deletion_success = delete_member(rlnInstance.value, deleted_member_index) let deletion_success = delete_member(rlnInstance.value, deleted_member_index)
doAssert(deletion_success) doAssert(deletion_success)
@ -443,7 +447,7 @@ suite "Waku rln relay":
rlnInstance.isOk == true rlnInstance.isOk == true
var rln = rlnInstance.value var rln = rlnInstance.value
check: check:
rln.removeMember(MembeshipIndex(0)) rln.removeMember(MembershipIndex(0))
test "Merkle tree consistency check between deletion and insertion": test "Merkle tree consistency check between deletion and insertion":
# create an RLN instance # create an RLN instance
@ -478,7 +482,7 @@ suite "Waku rln relay":
doAssert(root2.len == 32) doAssert(root2.len == 32)
# delete the first member # delete the first member
var deleted_member_index = MembeshipIndex(0) var deleted_member_index = MembershipIndex(0)
let deletion_success = delete_member(rlnInstance.value, deleted_member_index) let deletion_success = delete_member(rlnInstance.value, deleted_member_index)
doAssert(deletion_success) doAssert(deletion_success)
@ -533,7 +537,7 @@ suite "Waku rln relay":
# delete the first member # delete the first member
var deleted_member_index = MembeshipIndex(0) var deleted_member_index = MembershipIndex(0)
let deletion_success = rln.removeMember(deleted_member_index) let deletion_success = rln.removeMember(deleted_member_index)
doAssert(deletion_success) doAssert(deletion_success)
@ -603,7 +607,7 @@ suite "Waku rln relay":
var index = 5 var index = 5
# prepare the authentication object with peer's index and sk # prepare the authentication object with peer's index and sk
var authObj: Auth = Auth(secret_buffer: addr skBuffer, index: MembeshipIndex(index)) var authObj: Auth = Auth(secret_buffer: addr skBuffer, index: MembershipIndex(index))
# Create a Merkle tree with random members # Create a Merkle tree with random members
for i in 0..10: for i in 0..10:
@ -685,7 +689,7 @@ suite "Waku rln relay":
# create and test a bad proof # create and test a bad proof
# prepare a bad authentication object with a wrong peer's index # prepare a bad authentication object with a wrong peer's index
var badIndex = 8 var badIndex = 8
var badAuthObj: Auth = Auth(secret_buffer: addr skBuffer, index: MembeshipIndex(badIndex)) var badAuthObj: Auth = Auth(secret_buffer: addr skBuffer, index: MembershipIndex(badIndex))
var badProof: Buffer var badProof: Buffer
let badProofIsSuccessful = generate_proof(rlnInstance.value, addr inputBuffer, addr badAuthObj, addr badProof) let badProofIsSuccessful = generate_proof(rlnInstance.value, addr inputBuffer, addr badAuthObj, addr badProof)
# check whether the generate_proof call is done successfully # check whether the generate_proof call is done successfully

View File

@ -2,7 +2,7 @@
# libtool - Provide generalized library-building support services. # libtool - Provide generalized library-building support services.
# Generated automatically by config.status (libbacktrace) version-unused # Generated automatically by config.status (libbacktrace) version-unused
# Libtool was configured on host fv-az129-673: # Libtool was configured on host fv-az193-28:
# NOTE: Changes made to this file will be lost: look at ltmain.sh. # NOTE: Changes made to this file will be lost: look at ltmain.sh.
# #
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,

View File

@ -5,7 +5,8 @@ import
libp2p/crypto/crypto, libp2p/crypto/crypto,
libp2p/crypto/secp, libp2p/crypto/secp,
nimcrypto/utils, nimcrypto/utils,
eth/keys eth/keys,
../protocol/waku_rln_relay/[waku_rln_relay_types]
type type
WakuNodeConf* = object WakuNodeConf* = object
@ -76,10 +77,14 @@ type
name: "rln-relay" }: bool name: "rln-relay" }: bool
rlnRelayMemIndex* {. rlnRelayMemIndex* {.
desc: "(experimental) the index of node in the rln-relay group: a value between 0-49 inclusive", desc: "(experimental) the index of node in the rln-relay group: a value between 0-99 inclusive",
defaultValue: 0 defaultValue: MembershipIndex(0)
name: "rln-relay-membership-index" }: uint32 name: "rln-relay-membership-index" }: MembershipIndex
rlnRelayPubsubTopic* {.
desc: "the pubsub topic for which rln-relay gets enabled",
defaultValue: "waku/2/rlnrelay/proto"
name: "rln-relay-pubsub-topic" }: string
staticnodes* {. staticnodes* {.
desc: "Peer multiaddr to directly connect with. Argument may be repeated." desc: "Peer multiaddr to directly connect with. Argument may be repeated."
name: "staticnode" }: seq[string] name: "staticnode" }: seq[string]

View File

@ -410,16 +410,40 @@ proc mountStore*(node: WakuNode, store: MessageStore = nil, persistMessages: boo
node.switch.mount(node.wakuStore, protocolMatcher(WakuStoreCodec)) node.switch.mount(node.wakuStore, protocolMatcher(WakuStoreCodec))
when defined(rln): when defined(rln):
proc addRLNRelayValidator*(node: WakuNode, pubsubTopic: string) =
## this procedure is a thin wrapper for the pubsub addValidator method
## it sets message validator on the given pubsubTopic, the validator will check that
## all the messages published in the pubsubTopic have a valid zero-knowledge proof
proc validator(topic: string, message: messages.Message): Future[ValidationResult] {.async.} =
let msg = WakuMessage.init(message.data)
if msg.isOk():
# check the proof
if proofVrfy(msg.value().payload, msg.value().proof):
return ValidationResult.Accept
# set a validator for the pubsubTopic
let pb = PubSub(node.wakuRelay)
pb.addValidator(pubsubTopic, validator)
proc mountRlnRelay*(node: WakuNode, proc mountRlnRelay*(node: WakuNode,
ethClientAddrOpt: Option[string] = none(string), ethClientAddrOpt: Option[string] = none(string),
ethAccAddrOpt: Option[Address] = none(Address), ethAccAddrOpt: Option[Address] = none(Address),
memContractAddOpt: Option[Address] = none(Address), memContractAddOpt: Option[Address] = none(Address),
groupOpt: Option[seq[IDCommitment]] = none(seq[IDCommitment]), groupOpt: Option[seq[IDCommitment]] = none(seq[IDCommitment]),
memKeyPairOpt: Option[MembershipKeyPair] = none(MembershipKeyPair), memKeyPairOpt: Option[MembershipKeyPair] = none(MembershipKeyPair),
memIndexOpt: Option[uint] = none(uint), memIndexOpt: Option[MembershipIndex] = none(MembershipIndex),
onchainMode: bool = true) {.async.} = onchainMode: bool = true,
pubsubTopic: string) {.async.} =
# TODO return a bool value to indicate the success of the call # TODO return a bool value to indicate the success of the call
# check whether inputs are provided # 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."
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
if onchainMode: if onchainMode:
if memContractAddOpt.isNone(): if memContractAddOpt.isNone():
error "failed to mount rln relay: membership contract address is not provided" error "failed to mount rln relay: membership contract address is not provided"
@ -495,23 +519,15 @@ when defined(rln):
doAssert(is_successful) doAssert(is_successful)
debug "peer is successfully registered into the membership contract" debug "peer is successfully registered into the membership contract"
# 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)
debug "rln relay topic validator is mounted successfully", pubsubTopic=pubsubTopic
node.wakuRlnRelay = rlnPeer node.wakuRlnRelay = rlnPeer
proc addRLNRelayValidator*(node: WakuNode, pubsubTopic: string) =
## this procedure is a thin wrapper for the pubsub addValidator method
## it sets message validator on the given pubsubTopic, the validator will check that
## all the messages published in the pubsubTopic have a valid zero-knowledge proof
proc validator(topic: string, message: messages.Message): Future[ValidationResult] {.async.} =
let msg = WakuMessage.init(message.data)
if msg.isOk():
# check the proof
if proofVrfy(msg.value().payload, msg.value().proof):
return ValidationResult.Accept
# set a validator for the pubsubTopic
let pb = PubSub(node.wakuRelay)
pb.addValidator(pubsubTopic, validator)
proc startRelay*(node: WakuNode) {.async.} = proc startRelay*(node: WakuNode) {.async.} =
if node.wakuRelay.isNil: if node.wakuRelay.isNil:
trace "Failed to start relay. Not mounted." trace "Failed to start relay. Not mounted."
@ -535,12 +551,6 @@ proc startRelay*(node: WakuNode) {.async.} =
protocolMatcher(WakuRelayCodec), protocolMatcher(WakuRelayCodec),
backoffPeriod) backoffPeriod)
when defined(rln):
if node.wakuRelay.rlnRelayEnabled:
# TODO currently the message validator is set for the defaultTopic, this can be configurable to accept other pubsub topics as well
addRLNRelayValidator(node, defaultTopic)
info "WakuRLNRelay is mounted successfully"
# Start the WakuRelay protocol # Start the WakuRelay protocol
await node.wakuRelay.start() await node.wakuRelay.start()
@ -548,8 +558,6 @@ proc startRelay*(node: WakuNode) {.async.} =
proc mountRelay*(node: WakuNode, proc mountRelay*(node: WakuNode,
topics: seq[string] = newSeq[string](), topics: seq[string] = newSeq[string](),
rlnRelayEnabled = false,
rlnRelayMemIndex = uint(0),
relayMessages = true, relayMessages = true,
triggerSelf = true) triggerSelf = true)
# @TODO: Better error handling: CatchableError is raised by `waitFor` # @TODO: Better error handling: CatchableError is raised by `waitFor`
@ -564,12 +572,11 @@ proc mountRelay*(node: WakuNode,
verifySignature = false verifySignature = false
) )
info "mounting relay", rlnRelayEnabled=rlnRelayEnabled, relayMessages=relayMessages info "mounting relay", relayMessages=relayMessages
## The default relay topics is the union of ## The default relay topics is the union of
## all configured topics plus the hard-coded defaultTopic(s) ## all configured topics plus the hard-coded defaultTopic(s)
wakuRelay.defaultTopics = concat(@[defaultTopic], topics) wakuRelay.defaultTopics = concat(@[defaultTopic], topics)
wakuRelay.rlnRelayEnabled = rlnRelayEnabled
node.switch.mount(wakuRelay, protocolMatcher(WakuRelayCodec)) node.switch.mount(wakuRelay, protocolMatcher(WakuRelayCodec))
@ -582,44 +589,6 @@ proc mountRelay*(node: WakuNode,
## @TODO: in future, this WakuRelay dependency will be removed completely ## @TODO: in future, this WakuRelay dependency will be removed completely
node.wakuRelay = wakuRelay node.wakuRelay = wakuRelay
when defined(rln):
if rlnRelayEnabled:
# TODO get user inputs via cli options
info "WakuRLNRelay is enabled"
# a static list of 50 membership keys in hexadecimal format
let
groupKeys = STATIC_GROUP_KEYS
groupSize = int(groupKeys.len/2)
debug "rln-relay membership index", rlnRelayMemIndex
# validate the user-supplied membership index
if rlnRelayMemIndex < uint(0) or rlnRelayMemIndex >= uint(groupSize):
error "wrong membership index, failed to mount WakuRLNRelay"
else:
# prepare group related inputs from the hardcoded keys
let
groupKeyPairs = groupKeys.toMembershipKeyPairs()
groupIDCommitments = groupKeyPairs.mapIt(it.idCommitment)
# mount rlnrelay in offline mode
waitFor node.mountRlnRelay(groupOpt= some(groupIDCommitments), memKeyPairOpt = some(groupKeyPairs[rlnRelayMemIndex]), memIndexOpt= some(rlnRelayMemIndex), onchainMode = false)
info "membership id key", idkey=groupKeyPairs[rlnRelayMemIndex].idKey.toHex
info "membership id commitment key", idCommitmentkey=groupIDCommitments[rlnRelayMemIndex].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"
info "relay mounted successfully" info "relay mounted successfully"
if node.started: if node.started:
@ -885,13 +854,38 @@ when isMainModule:
# Mount relay on all nodes # Mount relay on all nodes
mountRelay(node, mountRelay(node,
conf.topics.split(" "), conf.topics.split(" "),
rlnRelayEnabled = conf.rlnRelay,
relayMessages = conf.relay, # Indicates if node is capable to relay messages relayMessages = conf.relay, # Indicates if node is capable to relay messages
rlnRelayMemIndex = conf.rlnRelayMemIndex) )
# Keepalive mounted on all nodes # Keepalive mounted on all nodes
mountLibp2pPing(node) mountLibp2pPing(node)
when defined(rln):
if conf.rlnRelay:
info "WakuRLNRelay is enabled"
# set up rln relay inputs
let (groupOpt, memKeyPairOpt, memIndexOpt) = rlnRelaySetUp(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)
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
if conf.swap: if conf.swap:
mountSwap(node) mountSwap(node)
# TODO Set swap peer, for now should be same as store peer # TODO Set swap peer, for now should be same as store peer

View File

@ -20,7 +20,6 @@ const
type type
WakuRelay* = ref object of GossipSub WakuRelay* = ref object of GossipSub
defaultTopics*: seq[string] # Default configured PubSub topics defaultTopics*: seq[string] # Default configured PubSub topics
rlnRelayEnabled*: bool # Flag indicating if RLN relay is enabled
method init*(w: WakuRelay) = method init*(w: WakuRelay) =
debug "init WakuRelay" debug "init WakuRelay"

View File

@ -37,7 +37,7 @@ type WakuRLNRelay* = object
ethAccountPrivateKey*: Option[PrivateKey] ethAccountPrivateKey*: Option[PrivateKey]
rlnInstance*: RLN[Bn256] rlnInstance*: RLN[Bn256]
type MembeshipIndex* = uint type MembershipIndex* = uint
# inputs of the membership contract constructor # inputs of the membership contract constructor
# TODO may be able to make these constants private and put them inside the waku_rln_relay_utils # TODO may be able to make these constants private and put them inside the waku_rln_relay_utils
@ -69,4 +69,3 @@ const
# the root is created locally, using createMembershipList proc from waku_rln_relay_utils module, and the result is hardcoded in here # the root is created locally, using createMembershipList proc from waku_rln_relay_utils module, and the result is hardcoded in here
STATIC_GROUP_MERKLE_ROOT* = "25e03b7d551c3016cb21c057a113be5bf27eaa9b2529e806715bc0a1ef221e07" STATIC_GROUP_MERKLE_ROOT* = "25e03b7d551c3016cb21c057a113be5bf27eaa9b2529e806715bc0a1ef221e07"

View File

@ -1,6 +1,7 @@
{.push raises: [Defect].} {.push raises: [Defect].}
import import
std/sequtils,
chronicles, options, chronos, stint, chronicles, options, chronos, stint,
web3, web3,
stew/results, stew/results,
@ -114,7 +115,7 @@ proc insertMember*(rlnInstance: RLN[Bn256], idComm: IDCommitment): bool =
var member_is_added = update_next_member(rlnInstance, pkBufferPtr) var member_is_added = update_next_member(rlnInstance, pkBufferPtr)
return member_is_added return member_is_added
proc removeMember*(rlnInstance: RLN[Bn256], index: MembeshipIndex): bool = proc removeMember*(rlnInstance: RLN[Bn256], index: MembershipIndex): bool =
let deletion_success = delete_member(rlnInstance, index) let deletion_success = delete_member(rlnInstance, index)
return deletion_success return deletion_success
@ -190,3 +191,29 @@ proc createMembershipList*(n: int): (seq[(string,string)], string) {.raises: [De
let root = rln.getMerkleRoot().value.toHex let root = rln.getMerkleRoot().value.toHex
return (output, root) return (output, root)
proc rlnRelaySetUp*(rlnRelayMemIndex: MembershipIndex): (Option[seq[IDCommitment]],Option[MembershipKeyPair], Option[MembershipIndex]) {.raises:[Defect, ValueError].} =
let
# static group
groupKeys = STATIC_GROUP_KEYS
groupSize = STATIC_GROUP_SIZE
debug "rln-relay membership index", rlnRelayMemIndex
# validate the user-supplied membership index
if rlnRelayMemIndex < MembershipIndex(0) or rlnRelayMemIndex >= MembershipIndex(groupSize):
error "wrong membership index"
return(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()
# extract id commitment keys
groupIDCommitments = groupKeyPairs.mapIt(it.idCommitment)
groupOpt= some(groupIDCommitments)
# user selected membership key pair
memKeyPairOpt = some(groupKeyPairs[rlnRelayMemIndex])
memIndexOpt= some(rlnRelayMemIndex)
return (groupOpt, memKeyPairOpt, memIndexOpt)