From 984f6fa155fca08ebec2353c75ee0a0b974e8568 Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Thu, 18 May 2023 16:52:47 -0400 Subject: [PATCH] More robust defaultProvider start-up when a backend fails on bootstrap (#3979). --- src.ts/providers/provider-fallback.ts | 28 ++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src.ts/providers/provider-fallback.ts b/src.ts/providers/provider-fallback.ts index 6be29c95da..624c8a4e02 100644 --- a/src.ts/providers/provider-fallback.ts +++ b/src.ts/providers/provider-fallback.ts @@ -97,12 +97,15 @@ interface Config extends FallbackProviderState { _updateNumber: null | Promise; _network: null | Network; _totalTime: number; + _lastFatalError: null | Error; + _lastFatalErrorTimestamp: number; } const defaultState = { blockNumber: -2, requests: 0, lateResponses: 0, errorResponses: 0, outOfSync: -1, unsupportedEvents: 0, rollingDuration: 0, score: 0, - _network: null, _updateNumber: null, _totalTime: 0 + _network: null, _updateNumber: null, _totalTime: 0, + _lastFatalError: null, _lastFatalErrorTimestamp: 0 }; @@ -110,15 +113,22 @@ async function waitForSync(config: Config, blockNumber: number): Promise { while (config.blockNumber < 0 || config.blockNumber < blockNumber) { if (!config._updateNumber) { config._updateNumber = (async () => { - const blockNumber = await config.provider.getBlockNumber(); - if (blockNumber > config.blockNumber) { - config.blockNumber = blockNumber; + try { + const blockNumber = await config.provider.getBlockNumber(); + if (blockNumber > config.blockNumber) { + config.blockNumber = blockNumber; + } + } catch (error: any) { + config.blockNumber = -2; + config._lastFatalError = error; + config._lastFatalErrorTimestamp = getTime(); } config._updateNumber = null; })(); } await config._updateNumber; config.outOfSync++; + if (config._lastFatalError) { break; } } } @@ -413,6 +423,7 @@ export class FallbackProvider extends AbstractProvider { allConfigs.sort((a, b) => (b.priority - a.priority)); for (const config of allConfigs) { + if (config._lastFatalError) { continue; } if (configs.indexOf(config) === -1) { return config; } } @@ -471,9 +482,11 @@ export class FallbackProvider extends AbstractProvider { if (!initialSync) { const promises: Array> = [ ]; this.#configs.forEach((config) => { - promises.push(waitForSync(config, 0)); promises.push((async () => { - config._network = await config.provider.getNetwork(); + await waitForSync(config, 0); + if (!config._lastFatalError) { + config._network = await config.provider.getNetwork(); + } })()); }); @@ -484,6 +497,7 @@ export class FallbackProvider extends AbstractProvider { // Check all the networks match let chainId: null | bigint = null; for (const config of this.#configs) { + if (config._lastFatalError) { continue; } const network = (config._network); if (chainId == null) { chainId = network.chainId; @@ -519,7 +533,7 @@ export class FallbackProvider extends AbstractProvider { case "getBlockNumber": { // We need to get the bootstrap block height if (this.#height === -2) { - this.#height = Math.ceil(getNumber(getMedian(this.quorum, this.#configs.map((c) => ({ + this.#height = Math.ceil(getNumber(getMedian(this.quorum, this.#configs.filter((c) => (!c._lastFatalError)).map((c) => ({ value: c.blockNumber, tag: getNumber(c.blockNumber).toString(), weight: c.weight