From 4a710252d8a668124c7f2f5ec76090abdd226168 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Fri, 6 Nov 2020 23:45:56 +0200 Subject: [PATCH] Check the web3 provider for network compatibility --- beacon_chain/beacon_node.nim | 19 +++++++++++++------ beacon_chain/eth1_monitor.nim | 14 +++++++++++++- beacon_chain/network_metadata.nim | 5 +++++ run-mainnet-beacon-node.sh | 12 ++++++++++++ 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/beacon_chain/beacon_node.nim b/beacon_chain/beacon_node.nim index 5ecc836df..5d090d776 100644 --- a/beacon_chain/beacon_node.nim +++ b/beacon_chain/beacon_node.nim @@ -67,13 +67,15 @@ func enrForkIdFromState(state: BeaconState): ENRForkID = next_fork_epoch: FAR_FUTURE_EPOCH) proc startEth1Monitor(db: BeaconChainDB, + eth1Network: Option[Eth1Network], conf: BeaconNodeConf): Future[Eth1Monitor] {.async.} = let eth1MonitorRes = await Eth1Monitor.init( db, conf.runtimePreset, conf.web3Url, conf.depositContractAddress.get, - conf.depositContractDeployedAt.get) + conf.depositContractDeployedAt.get, + eth1Network) result = if eth1MonitorRes.isOk: eth1MonitorRes.get @@ -90,7 +92,8 @@ proc startEth1Monitor(db: BeaconChainDB, proc init*(T: type BeaconNode, rng: ref BrHmacDrbgContext, conf: BeaconNodeConf, - genesisStateContents: ref string): Future[BeaconNode] {.async.} = + genesisStateContents: ref string, + eth1Network: Option[Eth1Network]): Future[BeaconNode] {.async.} = let netKeys = getPersistentNetKeys(rng[], conf) nickname = if conf.nodeName == "auto": shortForm(netKeys) @@ -159,7 +162,7 @@ proc init*(T: type BeaconNode, # TODO Could move this to a separate "GenesisMonitor" process or task # that would do only this - see Paul's proposal for this. - eth1Monitor = await startEth1Monitor(db, conf) + eth1Monitor = await startEth1Monitor(db, eth1Network, conf) genesisState = await eth1Monitor.waitGenesis() if bnStatus == BeaconNodeStatus.Stopping: @@ -233,7 +236,7 @@ proc init*(T: type BeaconNode, conf.depositContractDeployedAt.isSome: # TODO if we don't have any validators attached, # we don't need a mainchain monitor - eth1Monitor = await startEth1Monitor(db, conf) + eth1Monitor = await startEth1Monitor(db, eth1Network, conf) let rpcServer = if conf.rpcEnabled: RpcServer.init(conf.rpcAddress, conf.rpcPort) @@ -981,6 +984,7 @@ programMain: config = makeBannerAndConfig(clientId, BeaconNodeConf) # This is ref so we can mutate it (to erase it) after the initial loading. genesisStateContents: ref string + eth1Network: Option[Eth1Network] setupStdoutLogging(config.logLevel) @@ -1029,9 +1033,10 @@ programMain: checkForIncompatibleOption "deposit-contract", depositContractAddress checkForIncompatibleOption "deposit-contract-block", depositContractDeployedAt - config.depositContractAddress = some metadata.depositContractAddress config.depositContractDeployedAt = some metadata.depositContractDeployedAt + + eth1Network = metadata.eth1Network else: config.runtimePreset = defaultRuntimePreset when const_preset == "mainnet": @@ -1041,6 +1046,7 @@ programMain: if config.depositContractDeployedAt.isNone: config.depositContractDeployedAt = some mainnetMetadata.depositContractDeployedAt + eth1Network = some mainnet # Single RNG instance for the application - will be seeded on construction # and avoid using system resources (such as urandom) after that @@ -1129,7 +1135,8 @@ programMain: # There are no managed event loops in here, to do a graceful shutdown, but # letting the default Ctrl+C handler exit is safe, since we only read from # the db. - var node = waitFor BeaconNode.init(rng, config, genesisStateContents) + var node = waitFor BeaconNode.init( + rng, config, genesisStateContents, eth1Network) if bnStatus == BeaconNodeStatus.Stopping: return diff --git a/beacon_chain/eth1_monitor.nim b/beacon_chain/eth1_monitor.nim index 6f6683520..6f40384a6 100644 --- a/beacon_chain/eth1_monitor.nim +++ b/beacon_chain/eth1_monitor.nim @@ -388,7 +388,8 @@ proc init*(T: type Eth1Monitor, preset: RuntimePreset, web3Url: string, depositContractAddress: Eth1Address, - depositContractDeployedAt: string): Future[Result[T, string]] {.async.} = + depositContractDeployedAt: string, + eth1Network: Option[Eth1Network]): Future[Result[T, string]] {.async.} = var web3Url = web3Url fixupInfuraUrls web3Url @@ -399,6 +400,17 @@ proc init*(T: type Eth1Monitor, ns = web3.contractSender(DepositContract, depositContractAddress) dataProvider = Web3DataProviderRef(url: web3Url, web3: web3, ns: ns) + if eth1Network.isSome: + let + providerNetwork = await web3.provider.net_version() + expectedNetwork = case eth1Network.get + of mainnet: "1" + of rinkeby: "4" + of goerli: "5" + if expectedNetwork != providerNetwork: + return err("The specified we3 provider is not attached to the " & + $eth1Network.get & " network") + let previouslyPersistedTo = db.getEth1PersistedTo() knownStart = previouslyPersistedTo.get: diff --git a/beacon_chain/network_metadata.nim b/beacon_chain/network_metadata.nim index e09a97660..7d90b10c0 100644 --- a/beacon_chain/network_metadata.nim +++ b/beacon_chain/network_metadata.nim @@ -35,6 +35,11 @@ type Eth2NetworkMetadata* = object case incompatible*: bool of false: + # TODO work-around a Nim codegen issue where upon constant assignment + # the compiler will copy `incompatibilityDesc` even when the case + # branch is not active and thus it will override the first variable + # in this branch. + dummy: string eth1Network*: Option[Eth1Network] runtimePreset*: RuntimePreset diff --git a/run-mainnet-beacon-node.sh b/run-mainnet-beacon-node.sh index 0b206dfe5..dc2e8cf63 100755 --- a/run-mainnet-beacon-node.sh +++ b/run-mainnet-beacon-node.sh @@ -5,6 +5,18 @@ set -e cd "$(dirname $0)" if [[ "$WEB3_URL" == "" ]]; then + cat <