Skip to content

Commit 8f0a509

Browse files
committed
Added customizable quorum to FallbackProvider (#4160).
1 parent 229145d commit 8f0a509

File tree

2 files changed

+44
-9
lines changed

2 files changed

+44
-9
lines changed

src.ts/providers/default-provider.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { QuickNodeProvider } from "./provider-quicknode.js";
1111

1212
import { FallbackProvider } from "./provider-fallback.js";
1313
import { JsonRpcProvider } from "./provider-jsonrpc.js";
14+
import { Network } from "./network.js";
1415
import { WebSocketProvider } from "./provider-websocket.js";
1516

1617
import type { AbstractProvider } from "./abstract-provider.js";
@@ -22,6 +23,8 @@ function isWebSocketLike(value: any): value is WebSocketLike {
2223
typeof(value.close) === "function");
2324
}
2425

26+
const Testnets = "goerli kovan sepolia classicKotti optimism-goerli arbitrum-goerli matic-mumbai bnbt".split(" ");
27+
2528
export function getDefaultProvider(network: string | Networkish | WebSocketLike, options?: any): AbstractProvider {
2629
if (options == null) { options = { }; }
2730

@@ -33,6 +36,13 @@ export function getDefaultProvider(network: string | Networkish | WebSocketLike,
3336
return new WebSocketProvider(network);
3437
}
3538

39+
// Get the network name, if possible
40+
let name: null | string = null;
41+
try {
42+
name = Network.from(network).name;
43+
} catch (error) { }
44+
45+
3646
const providers: Array<AbstractProvider> = [ ];
3747

3848
if (options.alchemy !== "-") {
@@ -96,7 +106,19 @@ export function getDefaultProvider(network: string | Networkish | WebSocketLike,
96106
operation: "getDefaultProvider"
97107
});
98108

109+
// No need for a FallbackProvider
99110
if (providers.length === 1) { return providers[0]; }
100111

101-
return new FallbackProvider(providers);
112+
// We use the floor because public third-party providers can be unreliable,
113+
// so a low number of providers with a large quorum will fail too often
114+
let quorum = Math.floor(providers.length / 2);
115+
116+
// Testnets don't need as strong a security gaurantee and speed is
117+
// more useful during testing
118+
if (name && Testnets.indexOf(name) !== -1) { quorum = 1; }
119+
120+
// Provided override qorum takes priority
121+
if (options && options.quorum) { quorum = options.quorum; }
122+
123+
return new FallbackProvider(providers, undefined, { quorum });
102124
}

src.ts/providers/provider-fallback.ts

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -165,16 +165,20 @@ async function waitForSync(config: Config, blockNumber: number): Promise<void> {
165165
export type FallbackProviderOptions = {
166166
// How many providers must agree on a value before reporting
167167
// back the response
168-
quorum: number;
168+
quorum?: number;
169169

170170
// How many providers must have reported the same event
171-
// for it to be emitted
172-
eventQuorum: number;
171+
// for it to be emitted (currently unimplmented)
172+
eventQuorum?: number;
173173

174174
// How many providers to dispatch each event to simultaneously.
175175
// Set this to 0 to use getLog polling, which implies eventQuorum
176-
// is equal to quorum.
177-
eventWorkers: number;
176+
// is equal to quorum. (currently unimplemented)
177+
eventWorkers?: number;
178+
179+
cacheTimeout?: number;
180+
181+
pollingInterval?: number;
178182
};
179183

180184
type RunnerResult = { result: any } | { error: Error };
@@ -380,8 +384,9 @@ export class FallbackProvider extends AbstractProvider {
380384
* If a [[Provider]] is included in %%providers%%, defaults are used
381385
* for the configuration.
382386
*/
383-
constructor(providers: Array<AbstractProvider | FallbackProviderConfig>, network?: Networkish) {
384-
super(network);
387+
constructor(providers: Array<AbstractProvider | FallbackProviderConfig>, network?: Networkish, options?: FallbackProviderOptions) {
388+
super(network, options);
389+
385390
this.#configs = providers.map((p) => {
386391
if (p instanceof AbstractProvider) {
387392
return Object.assign({ provider: p }, defaultConfig, defaultState );
@@ -393,7 +398,15 @@ export class FallbackProvider extends AbstractProvider {
393398
this.#height = -2;
394399
this.#initialSyncPromise = null;
395400

396-
this.quorum = 2; //Math.ceil(providers.length / 2);
401+
if (options && options.quorum != null) {
402+
this.quorum = options.quorum;
403+
} else {
404+
this.quorum = Math.ceil(this.#configs.reduce((accum, config) => {
405+
accum += config.weight;
406+
return accum;
407+
}, 0) / 2);
408+
}
409+
397410
this.eventQuorum = 1;
398411
this.eventWorkers = 1;
399412

0 commit comments

Comments
 (0)