Enables RLN compilation under CI env var (#786)

* compiles RLN if CI is defined

* minor ineffective change

* minor

* removes excess space

* resolves namespace conflicts

* moves pubsub import under compiler flag

* disables rln on-chain tests

* brings back the on-chain tests and fixes a name mismatch

* adds a debug log message

* minor formating

* kills ganache-cli procces on windows

* wip: adds a line to kill ganache-cli on windows

* disables rln-relay tests that depend on ganache-cli

* disables ganache-cli installation

* introduces onchain rln flag

* fixes a flaky test

* enables onchain test in non-windows CIs

* moves variables around

it seems detected_os is undefined, hence the compiler flag onchain_rln, which is conditioned to the os, does not get added

* limits onchain rln to macOS
This commit is contained in:
Sanaz Taheri Boshrooyeh 2022-01-28 13:57:17 -08:00 committed by GitHub
parent 4421b8de00
commit a5f8b90c23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 149 additions and 117 deletions

View File

@ -68,10 +68,34 @@ else
NIM_PARAMS := $(NIM_PARAMS) -d:release NIM_PARAMS := $(NIM_PARAMS) -d:release
endif endif
# control rln code compilation
ifeq ($(RLN), true) ifeq ($(RLN), true)
NIM_PARAMS := $(NIM_PARAMS) -d:rln
else ifeq ($(CI), true)
NIM_PARAMS := $(NIM_PARAMS) -d:rln NIM_PARAMS := $(NIM_PARAMS) -d:rln
endif endif
# detecting the os
ifeq ($(OS),Windows_NT) # is Windows_NT on XP, 2000, 7, Vista, 10...
detected_OS := Windows
else ifeq ($(strip $(shell uname)),Darwin)
detected_OS := macOS
else
# e.g. Linux
detected_OS := $(strip $(shell uname))
endif
# control compilation of rln tests that require on chain interaction
ifeq ($(ONCHAIN_RLN), true)
NIM_PARAMS := $(NIM_PARAMS) -d:onchain_rln
else
ifeq ($(CI), true)
ifeq ($(detected_OS), macOS)
NIM_PARAMS := $(NIM_PARAMS) -d:onchain_rln
endif
endif
endif
deps: | deps-common nat-libs waku.nims rlnlib deps: | deps-common nat-libs waku.nims rlnlib
ifneq ($(USE_LIBBACKTRACE), 0) ifneq ($(USE_LIBBACKTRACE), 0)
deps: | libbacktrace deps: | libbacktrace
@ -123,24 +147,23 @@ example2: | build deps
echo -e $(BUILD_MSG) "build/$@" && \ echo -e $(BUILD_MSG) "build/$@" && \
$(ENV_SCRIPT) nim example2 $(NIM_PARAMS) waku.nims $(ENV_SCRIPT) nim example2 $(NIM_PARAMS) waku.nims
# detecting the os
ifeq ($(OS),Windows_NT) # is Windows_NT on XP, 2000, 7, Vista, 10...
detected_OS := Windows
else ifeq ($(strip $(shell uname)),Darwin)
detected_OS := macOS
else
# e.g. Linux
detected_OS := $(strip $(shell uname))
endif
installganache: installganache:
ifeq ($(RLN), true) ifeq ($(ONCHAIN_RLN), true)
npm install ganache-cli; npx ganache-cli -p 8540 -g 0 -l 3000000000000& npm install ganache-cli; npx ganache-cli -p 8540 -g 0 -l 3000000000000&
else
ifeq ($(CI), true)
ifeq ($(detected_OS), macOS)
npm install ganache-cli; npx ganache-cli -p 8540 -g 0 -l 3000000000000&
endif
endif
endif endif
rlnlib: rlnlib:
ifeq ($(RLN), true) ifeq ($(RLN), true)
cargo build --manifest-path vendor/rln/Cargo.toml cargo build --manifest-path vendor/rln/Cargo.toml
else ifeq ($(CI), true)
cargo build --manifest-path vendor/rln/Cargo.toml
endif endif
test2: | build deps installganache test2: | build deps installganache

View File

@ -136,125 +136,127 @@ proc uploadContract(ethClientAddress: string): Future[Address] {.async.} =
return contractAddress return contractAddress
procSuite "Waku rln relay": procSuite "Waku rln relay":
asyncTest "contract membership": when defined(onchain_rln):
let contractAddress = await uploadContract(EthClient) asyncTest "contract membership":
# connect to the eth client debug "ethereum client address", ETH_CLIENT
let web3 = await newWeb3(EthClient) let contractAddress = await uploadContract(ETH_CLIENT)
debug "web3 connected to", EthClient # connect to the eth client
let web3 = await newWeb3(ETH_CLIENT)
debug "web3 connected to", ETH_CLIENT
# fetch the list of registered accounts # fetch the list of registered accounts
let accounts = await web3.provider.eth_accounts() let accounts = await web3.provider.eth_accounts()
web3.defaultAccount = accounts[1] web3.defaultAccount = accounts[1]
let add = web3.defaultAccount let add = web3.defaultAccount
debug "contract deployer account address ", add debug "contract deployer account address ", add
# prepare a contract sender to interact with it # prepare a contract sender to interact with it
var sender = web3.contractSender(MembershipContract, contractAddress) # creates a Sender object with a web3 field and contract address of type Address var sender = web3.contractSender(MembershipContract, contractAddress) # creates a Sender object with a web3 field and contract address of type Address
# send takes three parameters, c: ContractCallBase, value = 0.u256, gas = 3000000'u64 gasPrice = 0 # send takes three parameters, c: ContractCallBase, value = 0.u256, gas = 3000000'u64 gasPrice = 0
# should use send proc for the contract functions that update the state of the contract # should use send proc for the contract functions that update the state of the contract
let tx = await sender.register(20.u256).send(value = MembershipFee) let tx = await sender.register(20.u256).send(value = MembershipFee)
debug "The hash of registration tx: ", tx # value is the membership fee debug "The hash of registration tx: ", tx # value is the membership fee
# var members: array[2, uint256] = [20.u256, 21.u256] # var members: array[2, uint256] = [20.u256, 21.u256]
# debug "This is the batch registration result ", await sender.registerBatch(members).send(value = (members.len * membershipFee)) # value is the membership fee # debug "This is the batch registration result ", await sender.registerBatch(members).send(value = (members.len * membershipFee)) # value is the membership fee
# balance = await web3.provider.eth_getBalance(web3.defaultAccount , "latest") # balance = await web3.provider.eth_getBalance(web3.defaultAccount , "latest")
# debug "Balance after registration: ", balance # debug "Balance after registration: ", balance
await web3.close() await web3.close()
debug "disconnected from", EthClient debug "disconnected from", ETH_CLIENT
asyncTest "registration procedure": asyncTest "registration procedure":
# deploy the contract # deploy the contract
let contractAddress = await uploadContract(EthClient) let contractAddress = await uploadContract(ETH_CLIENT)
# prepare rln-relay peer inputs # prepare rln-relay peer inputs
let let
web3 = await newWeb3(EthClient) web3 = await newWeb3(ETH_CLIENT)
accounts = await web3.provider.eth_accounts() accounts = await web3.provider.eth_accounts()
# choose one of the existing accounts for the rln-relay peer # choose one of the existing accounts for the rln-relay peer
ethAccountAddress = accounts[9] ethAccountAddress = accounts[9]
await web3.close() await web3.close()
# create an RLN instance # create an RLN instance
var rlnInstance = createRLNInstance() var rlnInstance = createRLNInstance()
check: rlnInstance.isOk == true check: rlnInstance.isOk == true
# generate the membership keys # generate the membership keys
let membershipKeyPair = membershipKeyGen(rlnInstance.value) let membershipKeyPair = membershipKeyGen(rlnInstance.value)
check: membershipKeyPair.isSome check: membershipKeyPair.isSome
# initialize the WakuRLNRelay # initialize the WakuRLNRelay
var rlnPeer = WakuRLNRelay(membershipKeyPair: membershipKeyPair.get(), var rlnPeer = WakuRLNRelay(membershipKeyPair: membershipKeyPair.get(),
membershipIndex: MembershipIndex(0), membershipIndex: MembershipIndex(0),
ethClientAddress: EthClient, ethClientAddress: ETH_CLIENT,
ethAccountAddress: ethAccountAddress, ethAccountAddress: ethAccountAddress,
membershipContractAddress: contractAddress) membershipContractAddress: contractAddress)
# register the rln-relay peer to the membership contract # register the rln-relay peer to the membership contract
let is_successful = await rlnPeer.register() let is_successful = await rlnPeer.register()
check: check:
is_successful is_successful
asyncTest "mounting waku rln-relay": asyncTest "mounting waku rln-relay":
let let
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[] nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[]
node = WakuNode.new(nodeKey, ValidIpAddress.init("0.0.0.0"), node = WakuNode.new(nodeKey, ValidIpAddress.init("0.0.0.0"),
Port(60000)) Port(60000))
await node.start() await node.start()
# deploy the contract # deploy the contract
let membershipContractAddress = await uploadContract(EthClient) let membershipContractAddress = await uploadContract(ETH_CLIENT)
# prepare rln-relay inputs # prepare rln-relay inputs
let let
web3 = await newWeb3(EthClient) web3 = await newWeb3(ETH_CLIENT)
accounts = await web3.provider.eth_accounts() accounts = await web3.provider.eth_accounts()
# choose one of the existing account for the rln-relay peer # choose one of the existing account for the rln-relay peer
ethAccountAddress = accounts[9] ethAccountAddress = accounts[9]
await web3.close() await web3.close()
# create current peer's pk # create current peer's pk
var rlnInstance = createRLNInstance() var rlnInstance = createRLNInstance()
check rlnInstance.isOk == true check rlnInstance.isOk == true
var rln = rlnInstance.value var rln = rlnInstance.value
# generate a key pair # generate a key pair
var keypair = rln.membershipKeyGen() var keypair = rln.membershipKeyGen()
doAssert(keypair.isSome()) doAssert(keypair.isSome())
# current peer index in the Merkle tree # current peer index in the Merkle tree
let index = uint(5) let index = uint(5)
# Create a group of 10 members # Create a group of 10 members
var group = newSeq[IDCommitment]() var group = newSeq[IDCommitment]()
for i in 0..10: for i in 0..10:
var member_is_added: bool = false var member_is_added: bool = false
if (uint(i) == index): if (uint(i) == index):
# insert the current peer's pk # insert the current peer's pk
group.add(keypair.get().idCommitment) group.add(keypair.get().idCommitment)
member_is_added = rln.insertMember(keypair.get().idCommitment) member_is_added = rln.insertMember(keypair.get().idCommitment)
doAssert(member_is_added) doAssert(member_is_added)
debug "member key", key=keypair.get().idCommitment.toHex debug "member key", key=keypair.get().idCommitment.toHex
else: else:
var memberKeypair = rln.membershipKeyGen() var memberKeypair = rln.membershipKeyGen()
doAssert(memberKeypair.isSome()) doAssert(memberKeypair.isSome())
group.add(memberKeypair.get().idCommitment) group.add(memberKeypair.get().idCommitment)
member_is_added = rln.insertMember(memberKeypair.get().idCommitment) member_is_added = rln.insertMember(memberKeypair.get().idCommitment)
doAssert(member_is_added) doAssert(member_is_added)
debug "member key", key=memberKeypair.get().idCommitment.toHex debug "member key", key=memberKeypair.get().idCommitment.toHex
let expectedRoot = rln.getMerkleRoot().value().toHex let expectedRoot = rln.getMerkleRoot().value().toHex
debug "expected root ", expectedRoot debug "expected root ", expectedRoot
# start rln-relay # start rln-relay
node.mountRelay(@[RLNRELAY_PUBSUB_TOPIC]) 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), pubsubTopic = RLNRELAY_PUBSUB_TOPIC) await node.mountRlnRelay(ethClientAddrOpt = some(ETH_CLIENT), 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
check expectedRoot == calculatedRoot check expectedRoot == calculatedRoot
await node.stop() await node.stop()
asyncTest "mount waku-rln-relay in the off-chain mode": asyncTest "mount waku-rln-relay in the off-chain mode":
let let
@ -885,13 +887,13 @@ suite "Waku rln relay":
# validate messages # validate messages
# validateMessage proc checks the validity of the message fields and adds it to the log (if valid) # validateMessage proc checks the validity of the message fields and adds it to the log (if valid)
let let
msgValidate1 = wakuRlnRelay.validateMessage(wm1) msgValidate1 = wakuRlnRelay.validateMessage(wm1, some(time))
# wm2 is published within the same Epoch as wm1 and should be found as spam # wm2 is published within the same Epoch as wm1 and should be found as spam
msgValidate2 = wakuRlnRelay.validateMessage(wm2) msgValidate2 = wakuRlnRelay.validateMessage(wm2, some(time))
# a valid message should be validated successfully # a valid message should be validated successfully
msgValidate3 = wakuRlnRelay.validateMessage(wm3) msgValidate3 = wakuRlnRelay.validateMessage(wm3, some(time))
# wm4 has no rln proof and should not be validated # wm4 has no rln proof and should not be validated
msgValidate4 = wakuRlnRelay.validateMessage(wm4) msgValidate4 = wakuRlnRelay.validateMessage(wm4, some(time))
check: check:

View File

@ -427,18 +427,25 @@ proc compare*(e1, e2: Epoch): int64 =
return int64(epoch1) - int64(epoch2) return int64(epoch1) - int64(epoch2)
proc validateMessage*(rlnPeer: WakuRLNRelay, msg: WakuMessage): MessageValidationResult = proc validateMessage*(rlnPeer: WakuRLNRelay, msg: WakuMessage, timeOption: Option[float64] = none(float64)): MessageValidationResult =
## validate the supplied `msg` based on the waku-rln-relay routing protocol i.e., ## validate the supplied `msg` based on the waku-rln-relay routing protocol i.e.,
## the `msg`'s epoch is within MAX_EPOCH_GAP of the current epoch ## the `msg`'s epoch is within MAX_EPOCH_GAP of the current epoch
## the `msg` has valid rate limit proof ## the `msg` has valid rate limit proof
## the `msg` does not violate the rate limit ## the `msg` does not violate the rate limit
## `timeOption` indicates Unix epoch time (fractional part holds sub-seconds)
## if `timeOption` is supplied, then the current epoch is calculated based on that
# checks if the `msg`'s epoch is far from the current epoch # checks if the `msg`'s epoch is far from the current epoch
# it corresponds to the validation of rln external nullifier # it corresponds to the validation of rln external nullifier
let var epoch: Epoch
if timeOption.isSome():
epoch = calcEpoch(timeOption.get())
else:
# get current rln epoch # get current rln epoch
epoch = getCurrentEpoch() epoch = getCurrentEpoch()
let
msgEpoch = msg.proof.epoch msgEpoch = msg.proof.epoch
# calculate the gaps # calculate the gaps
gap = compare(epoch, msgEpoch) gap = compare(epoch, msgEpoch)