Skip to content

Commit

Permalink
feat(relay): Add fallback node structure
Browse files Browse the repository at this point in the history
  • Loading branch information
Dimo99 committed Jun 29, 2023
1 parent 77d6e76 commit c259d28
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 21 deletions.
2 changes: 1 addition & 1 deletion beacon-light-client/solidity/tasks/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ task('deploy', 'Deploy the beacon light client contract')
console.log('Deploying contracts with the account:', deployer.address);
console.log('Account balance:', (await deployer.getBalance()).toString());

const beaconApi = new BeaconApi(currentConfig.BEACON_REST_API);
const beaconApi = new BeaconApi([currentConfig.BEACON_REST_API]);

const beaconLightClient = await (
await ethers.getContractFactory('BeaconLightClient')
Expand Down
2 changes: 1 addition & 1 deletion beacon-light-client/solidity/tasks/start-publishing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ task('start-publishing', 'Run relayer')
}

const redis = new Redis(config.REDIS_HOST!, config.REDIS_PORT);
const beaconApi = new BeaconApi(currentConfig.BEACON_REST_API);
const beaconApi = new BeaconApi([currentConfig.BEACON_REST_API]);
const contract = new SolidityContract(
lightClientContract,
(network.config as any).url,
Expand Down
2 changes: 1 addition & 1 deletion beacon-light-client/solidity/tasks/verify-contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ task('verify-contracts', 'Verify')

const currentConfig = networkConfig[args.follownetwork] as Config;

const beaconApi = new BeaconApi(currentConfig.BEACON_REST_API!);
const beaconApi = new BeaconApi([currentConfig.BEACON_REST_API!]);

await run('verify:verify', {
address: args.lightclient,
Expand Down
81 changes: 64 additions & 17 deletions relay/implementations/beacon-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import { computeSyncCommitteePeriodAt } from '../../libs/typescript/ts-utils/ssz
import path from 'path';

export class BeaconApi implements IBeaconApi {
private beaconRestApi: string;
private beaconRestApis: string[];
private currentApiIndex: number;

constructor(beaconRestApi: string) {
this.beaconRestApi = beaconRestApi;
constructor(beaconRestApis: string[]) {
this.beaconRestApis = beaconRestApis;
this.currentApiIndex = 0;
}

async getHashiAdapterInfo(slot: number): Promise<{
Expand All @@ -26,7 +28,9 @@ export class BeaconApi implements IBeaconApi {
blockHashProof: string[];
}> {
const currentBlock = await (
await fetch(this.concatUrl(`/eth/v2/beacon/blocks/${slot}`))
await this.fetchWithFallback(
this.concatUrl(`/eth/v2/beacon/blocks/${slot}`),
)
).json();

const { ssz } = await import('@lodestar/types');
Expand Down Expand Up @@ -78,15 +82,19 @@ export class BeaconApi implements IBeaconApi {

async getCurrentHeadSlot(): Promise<number> {
const currentHead = await (
await fetch(this.concatUrl('/eth/v1/beacon/headers/head'))
await this.fetchWithFallback(
this.concatUrl('/eth/v1/beacon/headers/head'),
)
).json();

return Number(currentHead.data.header.message.slot);
}

async getBlockSlot(blockHash: string): Promise<number> {
const headResult = await (
await fetch(this.concatUrl(`/eth/v1/beacon/headers/${blockHash}`))
await this.fetchWithFallback(
this.concatUrl(`/eth/v1/beacon/headers/${blockHash}`),
)
).json();

return Number(headResult.data.header.message.slot);
Expand All @@ -104,7 +112,9 @@ export class BeaconApi implements IBeaconApi {
const { ssz } = await import('@lodestar/types');

const headResult = await (
await fetch(this.concatUrl(`/eth/v1/beacon/headers/${slot}`))
await this.fetchWithFallback(
this.concatUrl(`/eth/v1/beacon/headers/${slot}`),
)
).json();

return ssz.phase0.BeaconBlockHeader.fromJson(
Expand All @@ -130,7 +140,9 @@ export class BeaconApi implements IBeaconApi {

while (slot <= limitSlot) {
blockHeaderResult = await (
await fetch(this.concatUrl(`/eth/v1/beacon/headers/${slot}`))
await this.fetchWithFallback(
this.concatUrl(`/eth/v1/beacon/headers/${slot}`),
)
).json();

if (blockHeaderResult.code !== 404) {
Expand All @@ -155,7 +167,9 @@ export class BeaconApi implements IBeaconApi {

while (slot <= limitSlot) {
blockHeaderBodyResult = await (
await fetch(this.concatUrl(`/eth/v2/beacon/blocks/${slot}`))
await this.fetchWithFallback(
this.concatUrl(`/eth/v2/beacon/blocks/${slot}`),
)
).json();

if (blockHeaderBodyResult.code !== 404) {
Expand Down Expand Up @@ -195,7 +209,7 @@ export class BeaconApi implements IBeaconApi {
await this.getBeaconState(prevSlot);

const prevFinalizedHeaderResult = await (
await fetch(
await this.fetchWithFallback(
this.concatUrl(
`/eth/v1/beacon/headers/${
'0x' + bytesToHex(prevBeaconSate.finalizedCheckpoint.root)
Expand Down Expand Up @@ -275,7 +289,7 @@ export class BeaconApi implements IBeaconApi {
const { beaconState, stateTree } = await this.getBeaconState(slot);

const finalizedHeaderResult = await (
await fetch(
await this.fetchWithFallback(
this.concatUrl(
`/eth/v1/beacon/headers/${
'0x' + bytesToHex(beaconState.finalizedCheckpoint.root)
Expand Down Expand Up @@ -305,7 +319,9 @@ export class BeaconApi implements IBeaconApi {
const { ssz } = await import('@lodestar/types');

const finalizedBlockBodyResult = await (
await fetch(this.concatUrl(`/eth/v2/beacon/blocks/${slot}`))
await this.fetchWithFallback(
this.concatUrl(`/eth/v2/beacon/blocks/${slot}`),
)
).json();

const finalizedBlockBody = ssz.capella.BeaconBlockBody.fromJson(
Expand Down Expand Up @@ -345,13 +361,13 @@ export class BeaconApi implements IBeaconApi {
const { ssz } = await import('@lodestar/types');

const finality_checkpoints = await (
await fetch(
await this.fetchWithFallback(
this.concatUrl(`/eth/v1/beacon/states/${slot}/finality_checkpoints`),
)
).json();

const finalizedHeadResult = await (
await fetch(
await this.fetchWithFallback(
this.concatUrl(
`/eth/v1/beacon/headers/${finality_checkpoints.data.finalized.root}`,
),
Expand All @@ -365,7 +381,9 @@ export class BeaconApi implements IBeaconApi {

async getExecutionStateRoot(slot: number): Promise<string> {
const block = await (
await fetch(this.concatUrl(`/eth/v2/beacon/blocks/${slot}`))
await this.fetchWithFallback(
this.concatUrl(`/eth/v2/beacon/blocks/${slot}`),
)
).json();

return block.data.message.body.execution_payload.state_root;
Expand All @@ -374,7 +392,7 @@ export class BeaconApi implements IBeaconApi {
private async getBeaconState(slot: number) {
const { ssz } = await import('@lodestar/types');

const beaconStateSZZ = await fetch(
const beaconStateSZZ = await this.fetchWithFallback(
this.concatUrl(`/eth/v2/debug/beacon/states/${slot}`),
{
headers: {
Expand All @@ -392,8 +410,37 @@ export class BeaconApi implements IBeaconApi {
return { beaconState, stateTree };
}

private nextApi(): void {
this.currentApiIndex =
(this.currentApiIndex + 1) % this.beaconRestApis.length;
}

private getCurrentApi(): string {
return this.beaconRestApis[this.currentApiIndex];
}

private async fetchWithFallback(
input: RequestInfo | URL,
init?: RequestInit,
): Promise<Response> {
let retries = 0;
while (true) {
try {
return await fetch(input, init);
} catch (error) {
if (retries >= this.beaconRestApis.length) {
throw error;
}

retries++;

this.nextApi();
}
}
}

private concatUrl(urlPath: string): string {
const url = new URL(this.beaconRestApi);
const url = new URL(this.getCurrentApi());
url.pathname = path.join(url.pathname, urlPath);

return url.href;
Expand Down
2 changes: 1 addition & 1 deletion relay/workers/poll-updates/poll-updates-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import { checkConfig } from '../../../libs/typescript/ts-utils/common-utils';

doUpdate(
redis,
new BeaconApi(job.data.beaconRestApi),
new BeaconApi([job.data.beaconRestApi]),
proofGenertorQueue,
job.data.lastDownloadedUpdateKey,
job.data.slotsJump,
Expand Down

0 comments on commit c259d28

Please sign in to comment.