Skip to content

Commit

Permalink
feat: implement quicknode geth vs reth output comparison
Browse files Browse the repository at this point in the history
  • Loading branch information
jsy1218 committed Jul 1, 2024
1 parent 978db55 commit 4b625b3
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 5 deletions.
18 changes: 17 additions & 1 deletion lib/rpc/SingleJsonRpcProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ export class SingleJsonRpcProvider extends StaticJsonRpcProvider {
this.logEvaluateLatency()
this.evaluatingLatency = true
try {
await (this as any)[`${methodName}_EvaluateLatency`](...args)
return await (this as any)[`${methodName}_EvaluateLatency`](...args)
} catch (error: any) {
this.log.error({ error }, `Encounter error for shadow evaluate latency call: ${JSON.stringify(error)}`)
// Swallow the error.
Expand Down Expand Up @@ -241,6 +241,22 @@ export class SingleJsonRpcProvider extends StaticJsonRpcProvider {
metric.putMetric(`${this.metricPrefix}_send_${method}`, 1, MetricLoggerUnit.Count)
}

logRpcResponseMatch(method: string, otherProvider: SingleJsonRpcProvider) {
metric.putMetric(
`${this.metricPrefix}_other_provider_${otherProvider.providerId}_method_${method}_rpc_match`,
1,
MetricLoggerUnit.Count
)
}

logRpcResponseMismatch(method: string, otherProvider: SingleJsonRpcProvider) {
metric.putMetric(
`${this.metricPrefix}_other_provider_${otherProvider.providerId}_method_${method}_rpc_mismatch`,
1,
MetricLoggerUnit.Count
)
}

private async wrappedFunctionCall(
callType: CallType,
fnName: string,
Expand Down
40 changes: 36 additions & 4 deletions lib/rpc/UniJsonRpcProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,8 @@ export class UniJsonRpcProvider extends StaticJsonRpcProvider {
latency: number,
selectedProvider: SingleJsonRpcProvider,
methodName: string,
args: any[]
args: any[],
providerResponse: any
): Promise<void> {
const healthyProviders = this.providers.filter((provider) => provider.isHealthy())
let count = 0
Expand All @@ -230,7 +231,16 @@ export class UniJsonRpcProvider extends StaticJsonRpcProvider {
// Within each provider latency shadow evaluation, we should do block I/O,
// because NodeJS runs in single thread, so it's important to make sure
// we benchmark the latencies correctly based on the single-threaded sequential evaluation.
await provider.evaluateLatency(methodName, args)
const evaluatedProviderResponse = await provider.evaluateLatency(methodName, args)
this.compareRpcResponses(
providerResponse,
evaluatedProviderResponse,
selectedProvider,
provider,
methodName,
args
)

count++
})
)
Expand All @@ -242,6 +252,27 @@ export class UniJsonRpcProvider extends StaticJsonRpcProvider {
this.log.debug(`Evaluated ${count} other healthy providers`)
}

compareRpcResponses(
providerResponse: any,
evaluatedProviderResponse: any,
selectedProvider: SingleJsonRpcProvider,
otherProvider: SingleJsonRpcProvider,
methodName: string,
args: any[]
) {
if (providerResponse !== evaluatedProviderResponse) {
this.log.error(
{ methodName, args },
`Provider response mismatch: ${JSON.stringify(providerResponse)} from ${
selectedProvider.providerId
} vs ${JSON.stringify(evaluatedProviderResponse)} from ${otherProvider.providerId}`
)
selectedProvider.logRpcResponseMismatch(methodName, otherProvider)
} else {
selectedProvider.logRpcResponseMatch(methodName, otherProvider)
}
}

logProviderHealthiness() {
for (const provider of this.providers.filter((provider) => provider.isHealthy())) {
this.log.debug(`Healthy provider: ${provider.url}`)
Expand Down Expand Up @@ -289,9 +320,10 @@ export class UniJsonRpcProvider extends StaticJsonRpcProvider {
const selectedProvider = this.selectPreferredProvider(sessionId)
selectedProvider.logProviderSelection()
let latency = 0
let result
try {
const start = Date.now()
const result = await (selectedProvider as any)[`${fnName}`](...args)
result = await (selectedProvider as any)[`${fnName}`](...args)
latency = Date.now() - start
return result
} catch (error: any) {
Expand All @@ -308,7 +340,7 @@ export class UniJsonRpcProvider extends StaticJsonRpcProvider {
sessionId
) {
// fire and forget to evaluate latency of other healthy providers
this.checkOtherHealthyProvider(latency, selectedProvider, fnName, args)
this.checkOtherHealthyProvider(latency, selectedProvider, fnName, args, result)
}

if (Math.random() < this.healthCheckSampleProb && sessionId) {
Expand Down

0 comments on commit 4b625b3

Please sign in to comment.