From e093af4c1245ded22d23cad4d83882a9b15c6c68 Mon Sep 17 00:00:00 2001 From: Aaryamann Challani <43716372+rymnc@users.noreply.github.com> Date: Fri, 28 Jun 2024 14:49:16 +0530 Subject: [PATCH] chore(rln-relay): add chain-id flag to wakunode and restrict usage if mismatches rpc provider (#2858) --- .../test_rln_group_manager_onchain.nim | 19 ++++++++++++++- .../rln_keystore_generator.nim | 4 ++-- waku/factory/external_config.nim | 6 +++++ waku/factory/networks_config.nim | 2 ++ waku/factory/node_factory.nim | 1 + waku/factory/waku.nim | 1 + .../group_manager/on_chain/group_manager.nim | 23 ++++++++++++------- waku/waku_rln_relay/rln_relay.nim | 2 ++ 8 files changed, 47 insertions(+), 11 deletions(-) diff --git a/tests/waku_rln_relay/test_rln_group_manager_onchain.nim b/tests/waku_rln_relay/test_rln_group_manager_onchain.nim index 94b1ed213..f87e6c702 100644 --- a/tests/waku_rln_relay/test_rln_group_manager_onchain.nim +++ b/tests/waku_rln_relay/test_rln_group_manager_onchain.nim @@ -26,6 +26,8 @@ import ../testlib/common, ./utils +const CHAIN_ID = 1337 + proc generateCredentials(rlnInstance: ptr RLN): IdentityCredential = let credRes = membershipKeyGen(rlnInstance) return credRes.get() @@ -140,7 +142,7 @@ proc runAnvil(): Process = anvilPath, args = [ "--port", "8540", "--gas-limit", "300000000000000", "--balance", "1000000000", - "--chain-id", "1337", + "--chain-id", $CHAIN_ID, ], options = {poUsePath}, ) @@ -195,6 +197,7 @@ proc setup(): Future[OnchainGroupManager] {.async.} = let manager = OnchainGroupManager( ethClientUrl: EthClient, ethContractAddress: $contractAddress, + chainId: CHAIN_ID, ethPrivateKey: pk, rlnInstance: rlnInstance, ) @@ -218,6 +221,20 @@ suite "Onchain group manager": await manager.stop() + asyncTest "should error on initialization when chainId does not match": + let manager = await setup() + manager.chainId = CHAIN_ID + 1 + + (await manager.init()).isErrOr: + raiseAssert "Expected error when chainId does not match" + + asyncTest "should initialize when chainId is set to 0": + let manager = await setup() + manager.chainId = 0 + + (await manager.init()).isOkOr: + raiseAssert $error + asyncTest "should error on initialization when loaded metadata does not match": let manager = await setup() (await manager.init()).isOkOr: diff --git a/tools/rln_keystore_generator/rln_keystore_generator.nim b/tools/rln_keystore_generator/rln_keystore_generator.nim index 6c64ed6d2..2157b1c1b 100644 --- a/tools/rln_keystore_generator/rln_keystore_generator.nim +++ b/tools/rln_keystore_generator/rln_keystore_generator.nim @@ -76,7 +76,7 @@ proc doRlnKeystoreGenerator*(conf: WakuNodeConf) = debug "Transaction hash", txHash = groupManager.registrationTxHash.get() info "Your membership has been registered on-chain.", - chainId = $groupManager.chainId.get(), + chainId = $groupManager.chainId, contractAddress = conf.rlnRelayEthContractAddress, membershipIndex = groupManager.membershipIndex.get() info "Your user message limit is", userMessageLimit = conf.rlnRelayUserMessageLimit @@ -84,7 +84,7 @@ proc doRlnKeystoreGenerator*(conf: WakuNodeConf) = # 6. write to keystore let keystoreCred = KeystoreMembership( membershipContract: MembershipContract( - chainId: $groupManager.chainId.get(), address: conf.rlnRelayEthContractAddress + chainId: $groupManager.chainId, address: conf.rlnRelayEthContractAddress ), treeIndex: groupManager.membershipIndex.get(), identityCredential: credential, diff --git a/waku/factory/external_config.nim b/waku/factory/external_config.nim index bc3c08bb1..a4d487e6a 100644 --- a/waku/factory/external_config.nim +++ b/waku/factory/external_config.nim @@ -76,6 +76,12 @@ type WakuNodeConf* = object name: "rln-relay-eth-contract-address" .}: string + rlnRelayChainId* {. + desc: "Chain ID of the provided contract (optional, will fetch from RPC provider if not used)", + defaultValue: 0, + name: "rln-relay-chain-id" + .}: uint + rlnRelayCredPassword* {. desc: "Password for encrypting RLN credentials", defaultValue: "", diff --git a/waku/factory/networks_config.nim b/waku/factory/networks_config.nim index 92a4956f5..1c5ab0097 100644 --- a/waku/factory/networks_config.nim +++ b/waku/factory/networks_config.nim @@ -8,6 +8,7 @@ type ClusterConf* = object clusterId*: uint16 rlnRelay*: bool rlnRelayEthContractAddress*: string + rlnRelayChainId*: uint rlnRelayDynamic*: bool rlnRelayBandwidthThreshold*: int rlnEpochSizeSec*: uint64 @@ -37,6 +38,7 @@ proc TheWakuNetworkConf*(T: type ClusterConf): ClusterConf = rlnRelay: true, rlnRelayEthContractAddress: "0x4976Df0f61135EF3E5720D92eadE2e5F47A68Ef9", rlnRelayDynamic: true, + rlnRelayChainId: 2442, # https://chainlist.org/chain/2442 rlnRelayBandwidthThreshold: 0, rlnEpochSizeSec: 600, rlnRelayUserMessageLimit: 20, diff --git a/waku/factory/node_factory.nim b/waku/factory/node_factory.nim index 2bc468fb8..b74d1a3e7 100644 --- a/waku/factory/node_factory.nim +++ b/waku/factory/node_factory.nim @@ -199,6 +199,7 @@ proc setupProtocols( rlnRelayDynamic: conf.rlnRelayDynamic, rlnRelayCredIndex: conf.rlnRelayCredIndex, rlnRelayEthContractAddress: conf.rlnRelayEthContractAddress, + rlnRelayChainId: conf.rlnRelayChainId, rlnRelayEthClientAddress: string(conf.rlnRelayethClientAddress), rlnRelayCredPath: conf.rlnRelayCredPath, rlnRelayCredPassword: conf.rlnRelayCredPassword, diff --git a/waku/factory/waku.nim b/waku/factory/waku.nim index a461f65c5..dc3b01314 100644 --- a/waku/factory/waku.nim +++ b/waku/factory/waku.nim @@ -116,6 +116,7 @@ proc init*(T: type Waku, conf: WakuNodeConf): Result[Waku, string] = confCopy.clusterId = twnClusterConf.clusterId confCopy.rlnRelay = twnClusterConf.rlnRelay confCopy.rlnRelayEthContractAddress = twnClusterConf.rlnRelayEthContractAddress + confCopy.rlnRelayChainId = twnClusterConf.rlnRelayChainId confCopy.rlnRelayDynamic = twnClusterConf.rlnRelayDynamic confCopy.rlnRelayBandwidthThreshold = twnClusterConf.rlnRelayBandwidthThreshold confCopy.discv5Discovery = twnClusterConf.discv5Discovery diff --git a/waku/waku_rln_relay/group_manager/on_chain/group_manager.nim b/waku/waku_rln_relay/group_manager/on_chain/group_manager.nim index a83ae9bb3..637bd1354 100644 --- a/waku/waku_rln_relay/group_manager/on_chain/group_manager.nim +++ b/waku/waku_rln_relay/group_manager/on_chain/group_manager.nim @@ -61,7 +61,7 @@ type wakuRlnContract*: Option[WakuRlnContractWithSender] latestProcessedBlock*: BlockNumber registrationTxHash*: Option[TxHash] - chainId*: Option[Quantity] + chainId*: uint keystorePath*: Option[string] keystorePassword*: Option[string] registrationHandler*: Option[RegistrationHandler] @@ -106,7 +106,7 @@ proc setMetadata*( let metadataSetRes = g.rlnInstance.setMetadata( RlnMetadata( lastProcessedBlock: normalizedBlock, - chainId: uint64(g.chainId.get()), + chainId: g.chainId, contractAddress: g.ethContractAddress, validRoots: g.validRoots.toSeq(), ) @@ -540,11 +540,18 @@ method init*(g: OnchainGroupManager): Future[GroupManagerResult[void]] {.async.} g.retryWrapper(ethRpc, "Failed to connect to the Ethereum client"): await newWeb3(g.ethClientUrl) + var fetchedChainId: uint + g.retryWrapper(fetchedChainId, "Failed to get the chain id"): + uint(await ethRpc.provider.eth_chainId()) + # Set the chain id - var chainId: Quantity - g.retryWrapper(chainId, "Failed to get the chain id"): - await ethRpc.provider.eth_chainId() - g.chainId = some(chainId) + if g.chainId == 0: + warn "Chain ID not set in config, using RPC Provider's Chain ID", providerChainId = fetchedChainId + + if g.chainId != 0 and g.chainId != fetchedChainId: + return err("The RPC Provided a Chain ID which is different than the provided Chain ID: provided = " & $g.chainId & ", actual = " & $fetchedChainId) + + g.chainId = fetchedChainId if g.ethPrivateKey.isSome(): let pk = g.ethPrivateKey.get() @@ -567,7 +574,7 @@ method init*(g: OnchainGroupManager): Future[GroupManagerResult[void]] {.async.} var keystoreQuery = KeystoreMembership( membershipContract: - MembershipContract(chainId: $g.chainId.get(), address: g.ethContractAddress) + MembershipContract(chainId: $g.chainId, address: g.ethContractAddress) ) if g.membershipIndex.isSome(): keystoreQuery.treeIndex = MembershipIndex(g.membershipIndex.get()) @@ -599,7 +606,7 @@ method init*(g: OnchainGroupManager): Future[GroupManagerResult[void]] {.async.} warn "could not initialize with persisted rln metadata" elif metadataGetOptRes.get().isSome(): let metadata = metadataGetOptRes.get().get() - if metadata.chainId != uint64(g.chainId.get()): + if metadata.chainId != uint(g.chainId): return err("persisted data: chain id mismatch") if metadata.contractAddress != g.ethContractAddress.toLower(): diff --git a/waku/waku_rln_relay/rln_relay.nim b/waku/waku_rln_relay/rln_relay.nim index 85890a2cd..c7c320c27 100644 --- a/waku/waku_rln_relay/rln_relay.nim +++ b/waku/waku_rln_relay/rln_relay.nim @@ -40,6 +40,7 @@ type WakuRlnConfig* = object rlnRelayCredIndex*: Option[uint] rlnRelayEthContractAddress*: string rlnRelayEthClientAddress*: string + rlnRelayChainId*: uint rlnRelayCredPath*: string rlnRelayCredPassword*: string rlnRelayTreePath*: string @@ -429,6 +430,7 @@ proc mount( groupManager = OnchainGroupManager( ethClientUrl: string(conf.rlnRelayethClientAddress), ethContractAddress: $conf.rlnRelayEthContractAddress, + chainId: conf.rlnRelayChainId, rlnInstance: rlnInstance, registrationHandler: registrationHandler, keystorePath: rlnRelayCredPath,