Skip to content

Commit eed38e8

Browse files
authored
Merge pull request #745 from LIT-Protocol/feature/lit-4083-use-an-even-older-blockhash-from-providers-v6
feat: optimize and delay even more fallback rpcs for blockhash - v6
2 parents 283f073 + 4bc6dd5 commit eed38e8

File tree

2 files changed

+54
-31
lines changed

2 files changed

+54
-31
lines changed

packages/core/src/lib/lit-core.spec.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,16 +96,21 @@ describe('LitCore', () => {
9696
timestamp: currentTime,
9797
}),
9898
};
99+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
99100
jest.spyOn(core as any, '_getProviderWithFallback').mockResolvedValue({
100-
...mockProvider,
101+
provider: mockProvider,
102+
testResult: {
103+
hash: mockBlockhash,
104+
number: 12345,
105+
timestamp: currentTime,
106+
},
101107
});
102108

103109
// Execute
104110
const result = await core.getLatestBlockhash();
105111

106112
// Assert
107113
expect(fetch).toHaveBeenCalledWith(mockBlockhashUrl);
108-
expect(mockProvider.getBlock).toHaveBeenCalledWith(-1); // safety margin
109114
expect(result).toBe(mockBlockhash);
110115
});
111116

@@ -130,16 +135,21 @@ describe('LitCore', () => {
130135
timestamp: currentTime,
131136
}),
132137
};
138+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
133139
jest.spyOn(core as any, '_getProviderWithFallback').mockResolvedValue({
134-
...mockProvider,
140+
provider: mockProvider,
141+
testResult: {
142+
hash: mockBlockhash,
143+
number: 12345,
144+
timestamp: currentTime,
145+
},
135146
});
136147

137148
// Execute
138149
const result = await core.getLatestBlockhash();
139150

140151
// Assert
141152
expect(fetch).toHaveBeenCalledWith(mockBlockhashUrl);
142-
expect(mockProvider.getBlock).toHaveBeenCalledWith(-1); // safety margin
143153
expect(result).toBe(mockBlockhash);
144154
});
145155

@@ -162,8 +172,10 @@ describe('LitCore', () => {
162172
getBlock: jest.fn().mockResolvedValue(null), // Provider also fails
163173
};
164174

175+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
165176
jest.spyOn(core as any, '_getProviderWithFallback').mockResolvedValue({
166-
...mockProvider,
177+
provider: mockProvider,
178+
testResult: null,
167179
});
168180

169181
// Execute & Assert

packages/core/src/lib/lit-core.ts

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ import { composeLitUrl } from './endpoint-version';
7575
// eslint-disable-next-line @typescript-eslint/no-explicit-any
7676
type Listener = (...args: any[]) => void;
7777

78+
type providerTest<T> = (
79+
provider: ethers.providers.JsonRpcProvider
80+
) => Promise<T>;
81+
7882
interface CoreNodeConfig {
7983
subnetPubKey: string;
8084
networkPubKey: string;
@@ -112,8 +116,8 @@ export type LitNodeClientConfigWithDefaults = Required<
112116
const EPOCH_PROPAGATION_DELAY = 45_000;
113117
// This interval is responsible for keeping latest block hash up to date
114118
const BLOCKHASH_SYNC_INTERVAL = 30_000;
115-
// When fetching the blockhash from a provider (not lit), we use a previous block to avoid a nodes not knowing about the new block yet
116-
const BLOCKHASH_COUNT_PROVIDER_DELAY = -1;
119+
// When fetching the blockhash from a provider (not lit), we use a 5 minutes old block to ensure the nodes centralized indexer has it
120+
const BLOCKHASH_COUNT_PROVIDER_DELAY = -30; // 30 blocks ago. Eth block are mined every 12s. 30 blocks is 6 minutes, indexer/nodes must have it by now
117121

118122
// Intentionally not including datil-dev here per discussion with Howard
119123
const NETWORKS_REQUIRING_SEV: string[] = [
@@ -778,24 +782,31 @@ export class LitCore {
778782
};
779783
}
780784

781-
private _getProviderWithFallback =
782-
async (): Promise<ethers.providers.JsonRpcProvider | null> => {
783-
for (const url of FALLBACK_RPC_URLS) {
784-
try {
785-
const provider = new ethers.providers.JsonRpcProvider({
786-
url: url,
785+
private _getProviderWithFallback = async <T>(
786+
providerTest: providerTest<T>
787+
): Promise<{
788+
provider: ethers.providers.JsonRpcProvider;
789+
testResult: T;
790+
} | null> => {
791+
for (const url of FALLBACK_RPC_URLS) {
792+
try {
793+
const provider = new ethers.providers.JsonRpcProvider({
794+
url: url,
787795

788-
// https://docs.ethers.org/v5/api/utils/web/#ConnectionInfo
789-
timeout: 60000,
790-
});
791-
await provider.getBlockNumber(); // Simple check to see if the provider is working
792-
return provider;
793-
} catch (error) {
794-
logError(`RPC URL failed: ${url}`);
795-
}
796+
// https://docs.ethers.org/v5/api/utils/web/#ConnectionInfo
797+
timeout: 60000,
798+
});
799+
const testResult = await providerTest(provider); // Check to see if the provider is working
800+
return {
801+
provider,
802+
testResult,
803+
};
804+
} catch (error) {
805+
logError(`RPC URL failed: ${url}`);
796806
}
797-
return null;
798-
};
807+
}
808+
return null;
809+
};
799810

800811
/**
801812
* Fetches the latest block hash and log any errors that are returned
@@ -862,20 +873,20 @@ export class LitCore {
862873
log(
863874
'Attempting to fetch blockhash manually using ethers with fallback RPC URLs...'
864875
);
865-
const provider = await this._getProviderWithFallback();
876+
const { testResult } =
877+
(await this._getProviderWithFallback<ethers.providers.Block>(
878+
// We use a previous block to avoid nodes not having received the latest block yet
879+
(provider) => provider.getBlock(BLOCKHASH_COUNT_PROVIDER_DELAY)
880+
)) || {};
866881

867-
if (!provider) {
882+
if (!testResult || !testResult.hash) {
868883
logError('All fallback RPC URLs failed. Unable to retrieve blockhash.');
869884
return;
870885
}
871886

872887
try {
873-
// We use a previous block to avoid nodes not having received the latest block yet
874-
const priorBlock = await provider.getBlock(
875-
BLOCKHASH_COUNT_PROVIDER_DELAY
876-
);
877-
this.latestBlockhash = priorBlock.hash;
878-
this.lastBlockHashRetrieved = priorBlock.timestamp;
888+
this.latestBlockhash = testResult.hash;
889+
this.lastBlockHashRetrieved = testResult.timestamp;
879890
log(
880891
'Successfully retrieved blockhash manually: ',
881892
this.latestBlockhash

0 commit comments

Comments
 (0)