mirror of https://github.com/waku-org/nwaku.git
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:
parent
4421b8de00
commit
a5f8b90c23
45
Makefile
45
Makefile
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue