Allow the node to start when it fails to initialize the Eth1 monitor

* Avoid hangs when wss:// is specified for a non-secure HTTP server
* Produce an ERROR when the web3 provider is unsupported, but still launch the node
This commit is contained in:
Zahary Karadjov 2020-11-12 18:21:04 +02:00 committed by zah
parent 5e45e7429e
commit 17d35e1fd9
2 changed files with 62 additions and 44 deletions

View File

@ -400,10 +400,14 @@ proc init*(T: type Eth1Monitor,
var web3Url = web3Url
fixupWeb3Urls web3Url
let web3 = try: await newWeb3(web3Url)
except CatchableError as err:
return err "Failed to setup web3 connection"
let web3Fut = newWeb3(web3Url)
yield web3Fut or sleepAsync(chronos.seconds(5))
if (not web3Fut.finished) or web3Fut.failed:
web3Fut.cancel()
return err "Failed to setup web3 connection"
let
web3 = web3Fut.read
ns = web3.contractSender(DepositContract, depositContractAddress)
dataProvider = Web3DataProviderRef(url: web3Url, web3: web3, ns: ns)
@ -415,7 +419,7 @@ proc init*(T: type Eth1Monitor,
of rinkeby: "4"
of goerli: "5"
if expectedNetwork != providerNetwork:
return err("The specified we3 provider is not attached to the " &
return err("The specified web3 provider is not attached to the " &
$eth1Network.get & " network")
let
@ -538,21 +542,6 @@ proc safeCancel(fut: var Future[void]) =
proc stop*(m: Eth1Monitor) =
safeCancel m.runFut
proc waitGenesis*(m: Eth1Monitor): Future[BeaconStateRef] {.async.} =
if m.genesisState.isNil:
if m.genesisStateFut.isNil:
m.genesisStateFut = newFuture[void]("waitGenesis")
info "Awaiting genesis event"
await m.genesisStateFut
m.genesisStateFut = nil
if m.genesisState != nil:
return m.genesisState
else:
doAssert bnStatus == BeaconNodeStatus.Stopping
return new BeaconStateRef # cannot return nil...
proc syncBlockRange(m: Eth1Monitor, fromBlock, toBlock: Eth1BlockNumber) {.async.} =
var currentBlock = fromBlock
while currentBlock <= toBlock:
@ -729,6 +718,23 @@ proc start(m: Eth1Monitor, delayBeforeStart: Duration) =
proc start*(m: Eth1Monitor) {.inline.} =
m.start(0.seconds)
proc waitGenesis*(m: Eth1Monitor): Future[BeaconStateRef] {.async.} =
if m.genesisState.isNil:
m.start()
if m.genesisStateFut.isNil:
m.genesisStateFut = newFuture[void]("waitGenesis")
info "Awaiting genesis event"
await m.genesisStateFut
m.genesisStateFut = nil
if m.genesisState != nil:
return m.genesisState
else:
doAssert bnStatus == BeaconNodeStatus.Stopping
return new BeaconStateRef # cannot return nil...
proc getEth1BlockHash*(url: string, blockId: RtBlockIdentifier): Future[BlockHash] {.async.} =
let web3 = await newWeb3(url)
try:

View File

@ -66,29 +66,6 @@ func enrForkIdFromState(state: BeaconState): ENRForkID =
next_fork_version: forkVer,
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,
eth1Network)
result = if eth1MonitorRes.isOk:
eth1MonitorRes.get
else:
fatal "Failed to start Eth1 monitor",
reason = eth1MonitorRes.error,
web3Url = conf.web3Url,
depositContractAddress = conf.depositContractAddress.get,
depositContractDeployedAt = conf.depositContractDeployedAt.get
quit 1
result.start()
proc init*(T: type BeaconNode,
rng: ref BrHmacDrbgContext,
conf: BeaconNodeConf,
@ -162,7 +139,23 @@ 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, eth1Network, conf)
let eth1MonitorRes = await Eth1Monitor.init(
db,
conf.runtimePreset,
conf.web3Url,
conf.depositContractAddress.get,
conf.depositContractDeployedAt.get,
eth1Network)
if eth1MonitorRes.isErr:
fatal "Failed to start Eth1 monitor",
reason = eth1MonitorRes.error,
web3Url = conf.web3Url,
depositContractAddress = conf.depositContractAddress.get,
depositContractDeployedAt = conf.depositContractDeployedAt.get
quit 1
else:
eth1Monitor = eth1MonitorRes.get
genesisState = await eth1Monitor.waitGenesis()
if bnStatus == BeaconNodeStatus.Stopping:
@ -236,7 +229,22 @@ proc init*(T: type BeaconNode,
conf.depositContractDeployedAt.isSome:
# TODO(zah) if we don't have any validators attached,
# we don't need a mainchain monitor
eth1Monitor = await startEth1Monitor(db, eth1Network, conf)
let eth1MonitorRes = await Eth1Monitor.init(
db,
conf.runtimePreset,
conf.web3Url,
conf.depositContractAddress.get,
conf.depositContractDeployedAt.get,
eth1Network)
if eth1MonitorRes.isErr:
error "Failed to start Eth1 monitor",
reason = eth1MonitorRes.error,
web3Url = conf.web3Url,
depositContractAddress = conf.depositContractAddress.get,
depositContractDeployedAt = conf.depositContractDeployedAt.get
else:
eth1Monitor = eth1MonitorRes.get
let rpcServer = if conf.rpcEnabled:
RpcServer.init(conf.rpcAddress, conf.rpcPort)
@ -823,6 +831,10 @@ proc start(node: BeaconNode) =
notice "Waiting for genesis", genesisIn = genesisTime.offset
waitFor node.initializeNetworking()
if node.eth1Monitor != nil:
node.eth1Monitor.start()
node.run()
func formatGwei(amount: uint64): string =