From 1a37cae3297384e052221677421ed3fc8952feea Mon Sep 17 00:00:00 2001 From: tersec Date: Fri, 21 Jan 2022 10:59:09 +0000 Subject: [PATCH] allow Eth1 monitor to run without genesis_deposit_contract_snapshot.ssz (#3279) --- beacon_chain/eth1/eth1_monitor.nim | 57 +++++++++++++++++++++++------ beacon_chain/nimbus_beacon_node.nim | 41 ++++++++++++++++----- 2 files changed, 77 insertions(+), 21 deletions(-) diff --git a/beacon_chain/eth1/eth1_monitor.nim b/beacon_chain/eth1/eth1_monitor.nim index 6c5aeaee5..d2cf7903a 100644 --- a/beacon_chain/eth1/eth1_monitor.nim +++ b/beacon_chain/eth1/eth1_monitor.nim @@ -868,11 +868,35 @@ proc init*(T: type Eth1Chain, cfg: RuntimeConfig, db: BeaconChainDB): T = finalizedBlockHash: finalizedDeposits.eth1Block, finalizedDepositsMerkleizer: finalizedDeposits.createMerkleizer) +proc createInitialDepositSnapshot*( + depositContractAddress: Eth1Address, + depositContractDeployedAt: BlockHashOrNumber, + web3Url: string): Future[Result[DepositContractSnapshot, string]] {.async.} = + + let dataProviderRes = + await Web3DataProvider.new(depositContractAddress, web3Url) + if dataProviderRes.isErr: + return err(dataProviderRes.error) + var dataProvider = dataProviderRes.get + + let knownStartBlockHash = + if depositContractDeployedAt.isHash: + depositContractDeployedAt.hash + else: + try: + var blk = awaitWithRetries( + dataProvider.getBlockByNumber(depositContractDeployedAt.number)) + blk.hash.asEth2Digest + except CatchableError as err: + return err(err.msg) + + return ok DepositContractSnapshot(eth1Block: knownStartBlockHash) + proc init*(T: type Eth1Monitor, cfg: RuntimeConfig, db: BeaconChainDB, web3Urls: seq[string], - depositContractSnapshot: DepositContractSnapshot, + depositContractSnapshot: Option[DepositContractSnapshot], eth1Network: Option[Eth1Network], forcePolling: bool): T = doAssert web3Urls.len > 0 @@ -881,7 +905,8 @@ proc init*(T: type Eth1Monitor, for url in mitems(web3Urls): fixupWeb3Urls url - putInitialDepositContractSnapshot(db, depositContractSnapshot) + if depositContractSnapshot.isSome: + putInitialDepositContractSnapshot(db, depositContractSnapshot.get) T(state: Initialized, depositsChain: Eth1Chain.init(cfg, db), @@ -911,6 +936,19 @@ proc resetState(m: Eth1Monitor) {.async.} = await m.dataProvider.close() m.dataProvider = nil +proc ensureDataProvider*(m: Eth1Monitor) {.async.} = + if not m.dataProvider.isNil: + return + + let web3Url = m.web3Urls[m.startIdx mod m.web3Urls.len] + inc m.startIdx + + m.dataProvider = block: + let v = await Web3DataProvider.new(m.depositContractAddress, web3Url) + if v.isErr(): + raise (ref CatchableError)(msg: v.error()) + v.get() + proc stop(m: Eth1Monitor) {.async.} = if m.state == Started: m.state = Stopping @@ -1112,20 +1150,14 @@ proc startEth1Syncing(m: Eth1Monitor, delayBeforeStart: Duration) {.async.} = if delayBeforeStart != ZeroDuration: await sleepAsync(delayBeforeStart) - let web3Url = m.web3Urls[m.startIdx mod m.web3Urls.len] - inc m.startIdx + await m.ensureDataProvider() + let + web3Url = m.web3Urls[(m.startIdx + m.web3Urls.len - 1) mod m.web3Urls.len] + web3 = m.dataProvider.web3 info "Starting Eth1 deposit contract monitoring", contract = $m.depositContractAddress, url = web3Url - m.dataProvider = block: - let v = await Web3DataProvider.new(m.depositContractAddress, web3Url) - if v.isErr(): - raise (ref CatchableError)(msg: v.error()) - v.get() - - let web3 = m.dataProvider.web3 - if m.state == Initialized and m.eth1Network.isSome: let providerNetwork = awaitWithRetries web3.provider.net_version() @@ -1239,6 +1271,7 @@ proc start(m: Eth1Monitor, delayBeforeStart: Duration) = if runFut.error[] of CatchableError: if runFut == m.runFut: warn "Eth1 chain monitoring failure, restarting", err = runFut.error.msg + m.dataProvider = nil m.state = Failed else: fatal "Fatal exception reached", err = runFut.error.msg diff --git a/beacon_chain/nimbus_beacon_node.nim b/beacon_chain/nimbus_beacon_node.nim index 9ad2babdb..fd5dac0f3 100644 --- a/beacon_chain/nimbus_beacon_node.nim +++ b/beacon_chain/nimbus_beacon_node.nim @@ -119,11 +119,20 @@ proc init*(T: type BeaconNode, depositContractDeployedAt: BlockHashOrNumber, eth1Network: Option[Eth1Network], genesisStateContents: string, - genesisDepositsSnapshotContents: string): BeaconNode {. + depositContractSnapshotContents: string): BeaconNode {. raises: [Defect, CatchableError].} = var taskpool: TaskpoolPtr + let depositContractSnapshot = if depositContractSnapshotContents.len > 0: + try: + some SSZ.decode(depositContractSnapshotContents, DepositContractSnapshot) + except CatchableError as err: + fatal "Invalid deposit contract snapshot", err = err.msg + quit 1 + else: + none DepositContractSnapshot + try: if config.numThreads < 0: fatal "The number of threads --numThreads cannot be negative." @@ -199,6 +208,24 @@ proc init*(T: type BeaconNode, fatal "--finalized-checkpoint-block cannot be specified without --finalized-checkpoint-state" quit 1 + template getDepositContractSnapshot: auto = + if depositContractSnapshot.isSome: + depositContractSnapshot + elif not cfg.DEPOSIT_CONTRACT_ADDRESS.isZeroMemory: + let snapshotRes = waitFor createInitialDepositSnapshot( + cfg.DEPOSIT_CONTRACT_ADDRESS, + depositContractDeployedAt, + config.web3Urls[0]) + if snapshotRes.isErr: + fatal "Failed to locate the deposit contract deployment block", + depositContract = cfg.DEPOSIT_CONTRACT_ADDRESS, + deploymentBlock = $depositContractDeployedAt + quit 1 + else: + some snapshotRes.get + else: + none(DepositContractSnapshot) + var eth1Monitor: Eth1Monitor if not ChainDAGRef.isInitialized(db).isOk(): var @@ -207,7 +234,7 @@ proc init*(T: type BeaconNode, if genesisStateContents.len == 0 and checkpointState == nil: when hasGenesisDetection: - if genesisDepositsSnapshotContents.len > 0: + if depositContractSnapshotContents.len > 0: fatal "A deposits snapshot cannot be provided without also providing a matching beacon state snapshot" quit 1 @@ -224,7 +251,7 @@ proc init*(T: type BeaconNode, cfg, db, config.web3Urls, - depositContractDeployedAt, + getDepositContractSnapshot(), eth1Network, config.web3ForcePolling) @@ -346,16 +373,12 @@ proc init*(T: type BeaconNode, headStateSlot = getStateField(dag.headState.data, slot) quit 1 - if eth1Monitor.isNil and - config.web3Urls.len > 0 and - genesisDepositsSnapshotContents.len > 0: - let genesisDepositsSnapshot = SSZ.decode(genesisDepositsSnapshotContents, - DepositContractSnapshot) + if eth1Monitor.isNil and config.web3Urls.len > 0: eth1Monitor = Eth1Monitor.init( cfg, db, config.web3Urls, - genesisDepositsSnapshot, + getDepositContractSnapshot(), eth1Network, config.web3ForcePolling)