A hacky work-around for a web3 issue that may cause the client to go into a loop of failing requests

This commit is contained in:
Zahary Karadjov 2020-11-17 21:50:07 +02:00
parent ebfacf597c
commit 11e1a9e8e8
No known key found for this signature in database
GPG Key ID: C8936F8A3073D609
1 changed files with 33 additions and 12 deletions

View File

@ -391,6 +391,21 @@ proc getBlockProposalData*(m: Eth1Monitor,
swap(result[1], deposits) swap(result[1], deposits)
proc new(T: type Web3DataProvider,
depositContractAddress: Eth1Address,
web3Url: string): Future[Result[Web3DataProviderRef, string]] {.async.} =
let web3Fut = newWeb3(web3Url)
yield web3Fut or sleepAsync(chronos.seconds(5))
if (not web3Fut.finished) or web3Fut.failed:
await cancelAndWait(web3Fut)
return err "Failed to setup web3 connection"
let
web3 = web3Fut.read
ns = web3.contractSender(DepositContract, depositContractAddress)
return ok Web3DataProviderRef(url: web3Url, web3: web3, ns: ns)
proc init*(T: type Eth1Monitor, proc init*(T: type Eth1Monitor,
db: BeaconChainDB, db: BeaconChainDB,
preset: RuntimePreset, preset: RuntimePreset,
@ -401,16 +416,13 @@ proc init*(T: type Eth1Monitor,
var web3Url = web3Url var web3Url = web3Url
fixupWeb3Urls web3Url fixupWeb3Urls web3Url
let web3Fut = newWeb3(web3Url) let dataProviderRes = await Web3DataProvider.new(depositContractAddress, web3Url)
yield web3Fut or sleepAsync(chronos.seconds(5)) if dataProviderRes.isErr:
if (not web3Fut.finished) or web3Fut.failed: return err(dataProviderRes.error)
await cancelAndWait(web3Fut)
return err "Failed to setup web3 connection"
let let
web3 = web3Fut.read dataProvider = dataProviderRes.get
ns = web3.contractSender(DepositContract, depositContractAddress) web3 = dataProvider.web3
dataProvider = Web3DataProviderRef(url: web3Url, web3: web3, ns: ns)
if eth1Network.isSome: if eth1Network.isSome:
let let
@ -711,9 +723,18 @@ proc run(m: Eth1Monitor, delayBeforeStart: Duration) {.async.} =
blk = await m.dataProvider.getBlockByNumber(m.depositContractDeployedAt.number) blk = await m.dataProvider.getBlockByNumber(m.depositContractDeployedAt.number)
break break
except CatchableError as err: except CatchableError as err:
error "Failed to obtain details for the starting block of the deposit contract sync. " & error "Failed to obtain details for the starting block " &
"The Web3 provider may still be not fully synced", error = err.msg "of the deposit contract sync. The Web3 provider " &
"may still be not fully synced", error = err.msg
await sleepAsync(chronos.seconds(10)) await sleepAsync(chronos.seconds(10))
# TODO: After a single failure, the web3 object may enter a state
# where it's no longer possible to make additional requests.
# Until this is fixed upstream, we'll just try to recreate
# the web3 provider before retrying. In case this fails,
# the Eth1Monitor will be restarted.
m.dataProvider = tryGet(await Web3DataProvider.new(
m.depositContractAddress,
m.web3Url))
blk.hash.asEth2Digest blk.hash.asEth2Digest
Eth1Data(block_hash: deployedAtHash, deposit_count: 0) Eth1Data(block_hash: deployedAtHash, deposit_count: 0)