Skip to content

Commit 11e1a9e

Browse files
committed
A hacky work-around for a web3 issue that may cause the client to go into a loop of failing requests
1 parent ebfacf5 commit 11e1a9e

File tree

1 file changed

+33
-12
lines changed

1 file changed

+33
-12
lines changed

beacon_chain/eth1_monitor.nim

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,21 @@ proc getBlockProposalData*(m: Eth1Monitor,
391391

392392
swap(result[1], deposits)
393393

394+
proc new(T: type Web3DataProvider,
395+
depositContractAddress: Eth1Address,
396+
web3Url: string): Future[Result[Web3DataProviderRef, string]] {.async.} =
397+
let web3Fut = newWeb3(web3Url)
398+
yield web3Fut or sleepAsync(chronos.seconds(5))
399+
if (not web3Fut.finished) or web3Fut.failed:
400+
await cancelAndWait(web3Fut)
401+
return err "Failed to setup web3 connection"
402+
403+
let
404+
web3 = web3Fut.read
405+
ns = web3.contractSender(DepositContract, depositContractAddress)
406+
407+
return ok Web3DataProviderRef(url: web3Url, web3: web3, ns: ns)
408+
394409
proc init*(T: type Eth1Monitor,
395410
db: BeaconChainDB,
396411
preset: RuntimePreset,
@@ -401,16 +416,13 @@ proc init*(T: type Eth1Monitor,
401416
var web3Url = web3Url
402417
fixupWeb3Urls web3Url
403418

404-
let web3Fut = newWeb3(web3Url)
405-
yield web3Fut or sleepAsync(chronos.seconds(5))
406-
if (not web3Fut.finished) or web3Fut.failed:
407-
await cancelAndWait(web3Fut)
408-
return err "Failed to setup web3 connection"
419+
let dataProviderRes = await Web3DataProvider.new(depositContractAddress, web3Url)
420+
if dataProviderRes.isErr:
421+
return err(dataProviderRes.error)
409422

410423
let
411-
web3 = web3Fut.read
412-
ns = web3.contractSender(DepositContract, depositContractAddress)
413-
dataProvider = Web3DataProviderRef(url: web3Url, web3: web3, ns: ns)
424+
dataProvider = dataProviderRes.get
425+
web3 = dataProvider.web3
414426

415427
if eth1Network.isSome:
416428
let
@@ -590,11 +602,11 @@ proc syncBlockRange(m: Eth1Monitor, fromBlock, toBlock: Eth1BlockNumber) {.async
590602
notice "Eth1 sync progress",
591603
blockNumber = lastBlock.number,
592604
depositsProcessed = lastBlock.voteData.deposit_count
593-
605+
594606
if m.genesisStateFut != nil and m.chainHasEnoughValidators:
595607
let lastIdx = m.eth1Chain.blocks.len - 1
596608
template lastBlock: auto = m.eth1Chain.blocks[lastIdx]
597-
609+
598610
if maxBlockNumberRequested == toBlock and
599611
(m.eth1Chain.blocks.len == 0 or lastBlock.number != toBlock):
600612
let web3Block = await m.dataProvider.getBlockByNumber(toBlock)
@@ -711,9 +723,18 @@ proc run(m: Eth1Monitor, delayBeforeStart: Duration) {.async.} =
711723
blk = await m.dataProvider.getBlockByNumber(m.depositContractDeployedAt.number)
712724
break
713725
except CatchableError as err:
714-
error "Failed to obtain details for the starting block of the deposit contract sync. " &
715-
"The Web3 provider may still be not fully synced", error = err.msg
726+
error "Failed to obtain details for the starting block " &
727+
"of the deposit contract sync. The Web3 provider " &
728+
"may still be not fully synced", error = err.msg
716729
await sleepAsync(chronos.seconds(10))
730+
# TODO: After a single failure, the web3 object may enter a state
731+
# where it's no longer possible to make additional requests.
732+
# Until this is fixed upstream, we'll just try to recreate
733+
# the web3 provider before retrying. In case this fails,
734+
# the Eth1Monitor will be restarted.
735+
m.dataProvider = tryGet(await Web3DataProvider.new(
736+
m.depositContractAddress,
737+
m.web3Url))
717738
blk.hash.asEth2Digest
718739
Eth1Data(block_hash: deployedAtHash, deposit_count: 0)
719740

0 commit comments

Comments
 (0)