Skip to content

Commit

Permalink
Fix operationId of light_client routes
Browse files Browse the repository at this point in the history
  • Loading branch information
jeluard committed Dec 8, 2023
1 parent 4b9647f commit 91cd2af
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 64 deletions.
52 changes: 26 additions & 26 deletions packages/api/src/beacon/routes/lightclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export type Api = {
* - Has most bits
* - Oldest update
*/
getUpdates(
getLightClientUpdatesByRange(
startPeriod: SyncPeriod,
count: number
): Promise<
Expand All @@ -39,15 +39,15 @@ export type Api = {
* Returns the latest optimistic head update available. Clients should use the SSE type `light_client_optimistic_update`
* unless to get the very first head update after syncing, or if SSE are not supported by the server.
*/
getOptimisticUpdate(): Promise<
getLightClientOptimisticUpdate(): Promise<
ApiClientResponse<{
[HttpStatusCode.OK]: {
version: ForkName;
data: allForks.LightClientOptimisticUpdate;
};
}>
>;
getFinalityUpdate(): Promise<
getLightClientFinalityUpdate(): Promise<
ApiClientResponse<{
[HttpStatusCode.OK]: {
version: ForkName;
Expand All @@ -60,7 +60,7 @@ export type Api = {
* The trusted block root should be fetched with similar means to a weak subjectivity checkpoint.
* Only block roots for checkpoints are guaranteed to be available.
*/
getBootstrap(blockRoot: string): Promise<
getLightClientBootstrap(blockRoot: string): Promise<
ApiClientResponse<{
[HttpStatusCode.OK]: {
version: ForkName;
Expand All @@ -71,7 +71,7 @@ export type Api = {
/**
* Returns an array of sync committee hashes based on the provided period and count
*/
getCommitteeRoot(
getLightClientCommitteeRoot(
startPeriod: SyncPeriod,
count: number
): Promise<
Expand All @@ -87,39 +87,39 @@ export type Api = {
* Define javascript values for each route
*/
export const routesData: RoutesData<Api> = {
getUpdates: {url: "/eth/v1/beacon/light_client/updates", method: "GET"},
getOptimisticUpdate: {url: "/eth/v1/beacon/light_client/optimistic_update", method: "GET"},
getFinalityUpdate: {url: "/eth/v1/beacon/light_client/finality_update", method: "GET"},
getBootstrap: {url: "/eth/v1/beacon/light_client/bootstrap/{block_root}", method: "GET"},
getCommitteeRoot: {url: "/eth/v0/beacon/light_client/committee_root", method: "GET"},
getLightClientUpdatesByRange: {url: "/eth/v1/beacon/light_client/updates", method: "GET"},
getLightClientOptimisticUpdate: {url: "/eth/v1/beacon/light_client/optimistic_update", method: "GET"},
getLightClientFinalityUpdate: {url: "/eth/v1/beacon/light_client/finality_update", method: "GET"},
getLightClientBootstrap: {url: "/eth/v1/beacon/light_client/bootstrap/{block_root}", method: "GET"},
getLightClientCommitteeRoot: {url: "/eth/v0/beacon/light_client/committee_root", method: "GET"},
};

/* eslint-disable @typescript-eslint/naming-convention */
export type ReqTypes = {
getUpdates: {query: {start_period: number; count: number}};
getOptimisticUpdate: ReqEmpty;
getFinalityUpdate: ReqEmpty;
getBootstrap: {params: {block_root: string}};
getCommitteeRoot: {query: {start_period: number; count: number}};
getLightClientUpdatesByRange: {query: {start_period: number; count: number}};
getLightClientOptimisticUpdate: ReqEmpty;
getLightClientFinalityUpdate: ReqEmpty;
getLightClientBootstrap: {params: {block_root: string}};
getLightClientCommitteeRoot: {query: {start_period: number; count: number}};
};

export function getReqSerializers(): ReqSerializers<Api, ReqTypes> {
return {
getUpdates: {
getLightClientUpdatesByRange: {
writeReq: (start_period, count) => ({query: {start_period, count}}),
parseReq: ({query}) => [query.start_period, query.count],
schema: {query: {start_period: Schema.UintRequired, count: Schema.UintRequired}},
},

getOptimisticUpdate: reqEmpty,
getFinalityUpdate: reqEmpty,
getLightClientOptimisticUpdate: reqEmpty,
getLightClientFinalityUpdate: reqEmpty,

getBootstrap: {
getLightClientBootstrap: {
writeReq: (block_root) => ({params: {block_root}}),
parseReq: ({params}) => [params.block_root],
schema: {params: {block_root: Schema.StringRequired}},
},
getCommitteeRoot: {
getLightClientCommitteeRoot: {
writeReq: (start_period, count) => ({query: {start_period, count}}),
parseReq: ({query}) => [query.start_period, query.count],
schema: {query: {start_period: Schema.UintRequired, count: Schema.UintRequired}},
Expand All @@ -132,27 +132,27 @@ export function getReturnTypes(): ReturnTypes<Api> {
const VersionedUpdate = WithVersion((fork: ForkName) =>
isForkLightClient(fork) ? ssz.allForksLightClient[fork].LightClientUpdate : ssz.altair.LightClientUpdate
);
const getUpdates = {
const getLightClientUpdatesByRange = {
toJson: (updates: {version: ForkName; data: allForks.LightClientUpdate}[]) =>
updates.map((data) => VersionedUpdate.toJson(data)),
fromJson: (updates: unknown[]) => updates.map((data) => VersionedUpdate.fromJson(data)),
};

return {
getUpdates,
getOptimisticUpdate: WithVersion((fork: ForkName) =>
getLightClientUpdatesByRange,
getLightClientOptimisticUpdate: WithVersion((fork: ForkName) =>
isForkLightClient(fork)
? ssz.allForksLightClient[fork].LightClientOptimisticUpdate
: ssz.altair.LightClientOptimisticUpdate
),
getFinalityUpdate: WithVersion((fork: ForkName) =>
getLightClientFinalityUpdate: WithVersion((fork: ForkName) =>
isForkLightClient(fork)
? ssz.allForksLightClient[fork].LightClientFinalityUpdate
: ssz.altair.LightClientFinalityUpdate
),
getBootstrap: WithVersion((fork: ForkName) =>
getLightClientBootstrap: WithVersion((fork: ForkName) =>
isForkLightClient(fork) ? ssz.allForksLightClient[fork].LightClientBootstrap : ssz.altair.LightClientBootstrap
),
getCommitteeRoot: ContainerData(ArrayOf(ssz.Root)),
getLightClientCommitteeRoot: ContainerData(ArrayOf(ssz.Root)),
};
}
10 changes: 5 additions & 5 deletions packages/api/test/unit/beacon/testData/lightclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ const header = ssz.altair.LightClientHeader.defaultValue();
const signatureSlot = ssz.Slot.defaultValue();

export const testData: GenericServerTestCases<Api> = {
getUpdates: {
getLightClientUpdatesByRange: {
args: [1, 2],
res: [{version: ForkName.bellatrix, data: lightClientUpdate}],
},
getOptimisticUpdate: {
getLightClientOptimisticUpdate: {
args: [],
res: {version: ForkName.bellatrix, data: {syncAggregate, attestedHeader: header, signatureSlot}},
},
getFinalityUpdate: {
getLightClientFinalityUpdate: {
args: [],
res: {
version: ForkName.bellatrix,
Expand All @@ -33,7 +33,7 @@ export const testData: GenericServerTestCases<Api> = {
},
},
},
getBootstrap: {
getLightClientBootstrap: {
args: [toHexString(root)],
res: {
version: ForkName.bellatrix,
Expand All @@ -44,7 +44,7 @@ export const testData: GenericServerTestCases<Api> = {
},
},
},
getCommitteeRoot: {
getLightClientCommitteeRoot: {
args: [1, 2],
res: {data: [Buffer.alloc(32, 0), Buffer.alloc(32, 1)]},
},
Expand Down
10 changes: 5 additions & 5 deletions packages/beacon-node/src/api/impl/lightclient/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function getLightclientApi({
config,
}: Pick<ApiModules, "chain" | "config">): ServerApi<routes.lightclient.Api> {
return {
async getUpdates(startPeriod: SyncPeriod, count: number) {
async getLightClientUpdatesByRange(startPeriod: SyncPeriod, count: number) {
const maxAllowedCount = Math.min(MAX_REQUEST_LIGHT_CLIENT_UPDATES, count);
const periods = Array.from({length: maxAllowedCount}, (_ignored, i) => i + startPeriod);
const updates = await Promise.all(periods.map((period) => chain.lightClientServer.getUpdate(period)));
Expand All @@ -21,28 +21,28 @@ export function getLightclientApi({
}));
},

async getOptimisticUpdate() {
async getLightClientOptimisticUpdate() {
const data = chain.lightClientServer.getOptimisticUpdate();
if (data === null) {
throw Error("No optimistic update available");
}
return {version: config.getForkName(data.attestedHeader.beacon.slot), data};
},

async getFinalityUpdate() {
async getLightClientFinalityUpdate() {
const data = chain.lightClientServer.getFinalityUpdate();
if (data === null) {
throw Error("No finality update available");
}
return {version: config.getForkName(data.attestedHeader.beacon.slot), data};
},

async getBootstrap(blockRoot) {
async getLightClientBootstrap(blockRoot) {
const bootstrapProof = await chain.lightClientServer.getBootstrap(fromHexString(blockRoot));
return {version: config.getForkName(bootstrapProof.header.beacon.slot), data: bootstrapProof};
},

async getCommitteeRoot(startPeriod: SyncPeriod, count: number) {
async getLightClientCommitteeRoot(startPeriod: SyncPeriod, count: number) {
const maxAllowedCount = Math.min(MAX_REQUEST_LIGHT_CLIENT_COMMITTEE_HASHES, count);
const periods = Array.from({length: maxAllowedCount}, (_ignored, i) => i + startPeriod);
const committeeHashes = await Promise.all(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ describe("lightclient api", function () {
await sleep(2 * SECONDS_PER_SLOT * 1000);
};

it("getUpdates()", async function () {
it("getLightClientUpdatesByRange()", async function () {
const client = getClient({baseUrl: `http://127.0.0.1:${restPort}`}, {config}).lightclient;
await waitForBestUpdate();
const res = await client.getUpdates(0, 1);
const res = await client.getLightClientUpdatesByRange(0, 1);
ApiError.assert(res);
const updates = res.response;
expect(updates.length).toBe(1);
Expand All @@ -93,10 +93,10 @@ describe("lightclient api", function () {
expect(updates[0].version).toBe(ForkName.altair);
});

it("getOptimisticUpdate()", async function () {
it("getLightClientOptimisticUpdate()", async function () {
await waitForBestUpdate();
const client = getClient({baseUrl: `http://127.0.0.1:${restPort}`}, {config}).lightclient;
const res = await client.getOptimisticUpdate();
const res = await client.getLightClientOptimisticUpdate();
ApiError.assert(res);
const update = res.response;
const slot = bn.chain.clock.currentSlot;
Expand All @@ -106,21 +106,21 @@ describe("lightclient api", function () {
expect(update.version).toBe(ForkName.altair);
});

it.skip("getFinalityUpdate()", async function () {
it.skip("getLightClientFinalityUpdate()", async function () {
// TODO: not sure how this causes subsequent tests failed
await waitForEvent<phase0.Checkpoint>(bn.chain.emitter, routes.events.EventType.finalizedCheckpoint, 240000);
await sleep(SECONDS_PER_SLOT * 1000);
const client = getClient({baseUrl: `http://127.0.0.1:${restPort}`}, {config}).lightclient;
const res = await client.getFinalityUpdate();
const res = await client.getLightClientFinalityUpdate();
ApiError.assert(res);
expect(res.response).toBeDefined();
});

it("getCommitteeRoot() for the 1st period", async function () {
it("getLightClientCommitteeRoot() for the 1st period", async function () {
await waitForBestUpdate();

const lightclient = getClient({baseUrl: `http://127.0.0.1:${restPort}`}, {config}).lightclient;
const committeeRes = await lightclient.getCommitteeRoot(0, 1);
const committeeRes = await lightclient.getLightClientCommitteeRoot(0, 1);
ApiError.assert(committeeRes);
const client = getClient({baseUrl: `http://127.0.0.1:${restPort}`}, {config}).beacon;
const validatorResponse = await client.getStateValidators("head");
Expand Down
6 changes: 3 additions & 3 deletions packages/light-client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ export class Lightclient {
await initBls(isNode ? "blst-native" : "herumi");

// Fetch bootstrap state with proof at the trusted block root
const {data: bootstrap} = await transport.getBootstrap(toHexString(checkpointRoot));
const {data: bootstrap} = await transport.getLightClientBootstrap(toHexString(checkpointRoot));

validateLightClientBootstrap(args.config, checkpointRoot, bootstrap);

Expand Down Expand Up @@ -199,7 +199,7 @@ export class Lightclient {

for (const [fromPeriodRng, toPeriodRng] of periodRanges) {
const count = toPeriodRng + 1 - fromPeriodRng;
const updates = await this.transport.getUpdates(fromPeriodRng, count);
const updates = await this.transport.getLightClientUpdatesByRange(fromPeriodRng, count);
for (const update of updates) {
this.processSyncCommitteeUpdate(update.data);
this.logger.debug("processed sync update", {slot: update.data.attestedHeader.beacon.slot});
Expand Down Expand Up @@ -253,7 +253,7 @@ export class Lightclient {
// Fetch latest optimistic head to prevent a potential 12 seconds lag between syncing and getting the first head,
// Don't retry, this is a non-critical UX improvement
try {
const update = await this.transport.getOptimisticUpdate();
const update = await this.transport.getLightClientOptimisticUpdate();
this.processOptimisticUpdate(update.data);
} catch (e) {
this.logger.error("Error fetching getLatestHeadUpdate", {currentPeriod}, e as Error);
Expand Down
8 changes: 4 additions & 4 deletions packages/light-client/src/transport/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {allForks, SyncPeriod} from "@lodestar/types";
import {ForkName} from "@lodestar/params";

export interface LightClientTransport {
getUpdates(
getLightClientUpdatesByRange(
startPeriod: SyncPeriod,
count: number
): Promise<
Expand All @@ -15,14 +15,14 @@ export interface LightClientTransport {
* Returns the latest optimistic head update available. Clients should use the SSE type `light_client_optimistic_update`
* unless to get the very first head update after syncing, or if SSE are not supported by the server.
*/
getOptimisticUpdate(): Promise<{version: ForkName; data: allForks.LightClientOptimisticUpdate}>;
getFinalityUpdate(): Promise<{version: ForkName; data: allForks.LightClientFinalityUpdate}>;
getLightClientOptimisticUpdate(): Promise<{version: ForkName; data: allForks.LightClientOptimisticUpdate}>;
getLightClientFinalityUpdate(): Promise<{version: ForkName; data: allForks.LightClientFinalityUpdate}>;
/**
* Fetch a bootstrapping state with a proof to a trusted block root.
* The trusted block root should be fetched with similar means to a weak subjectivity checkpoint.
* Only block roots for checkpoints are guaranteed to be available.
*/
getBootstrap(blockRoot: string): Promise<{version: ForkName; data: allForks.LightClientBootstrap}>;
getLightClientBootstrap(blockRoot: string): Promise<{version: ForkName; data: allForks.LightClientBootstrap}>;

// registers handler for LightClientOptimisticUpdate. This can come either via sse or p2p
onOptimisticUpdate(handler: (optimisticUpdate: allForks.LightClientOptimisticUpdate) => void): void;
Expand Down
16 changes: 8 additions & 8 deletions packages/light-client/src/transport/rest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class LightClientRestTransport extends (EventEmitter as {new (): RestEven
super();
}

async getUpdates(
async getLightClientUpdatesByRange(
startPeriod: SyncPeriod,
count: number
): Promise<
Expand All @@ -30,25 +30,25 @@ export class LightClientRestTransport extends (EventEmitter as {new (): RestEven
data: allForks.LightClientUpdate;
}[]
> {
const res = await this.api.lightclient.getUpdates(startPeriod, count);
const res = await this.api.lightclient.getLightClientUpdatesByRange(startPeriod, count);
ApiError.assert(res);
return res.response;
}

async getOptimisticUpdate(): Promise<{version: ForkName; data: allForks.LightClientOptimisticUpdate}> {
const res = await this.api.lightclient.getOptimisticUpdate();
async getLightClientOptimisticUpdate(): Promise<{version: ForkName; data: allForks.LightClientOptimisticUpdate}> {
const res = await this.api.lightclient.getLightClientOptimisticUpdate();
ApiError.assert(res);
return res.response;
}

async getFinalityUpdate(): Promise<{version: ForkName; data: allForks.LightClientFinalityUpdate}> {
const res = await this.api.lightclient.getFinalityUpdate();
async getLightClientFinalityUpdate(): Promise<{version: ForkName; data: allForks.LightClientFinalityUpdate}> {
const res = await this.api.lightclient.getLightClientFinalityUpdate();
ApiError.assert(res);
return res.response;
}

async getBootstrap(blockRoot: string): Promise<{version: ForkName; data: allForks.LightClientBootstrap}> {
const res = await this.api.lightclient.getBootstrap(blockRoot);
async getLightClientBootstrap(blockRoot: string): Promise<{version: ForkName; data: allForks.LightClientBootstrap}> {
const res = await this.api.lightclient.getLightClientBootstrap(blockRoot);
ApiError.assert(res);
return res.response;
}
Expand Down
10 changes: 5 additions & 5 deletions packages/light-client/test/mocks/LightclientServerApiMock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class LightclientServerApiMock implements ServerApi<routes.lightclient.Ap
latestHeadUpdate: altair.LightClientOptimisticUpdate | null = null;
finalized: altair.LightClientFinalityUpdate | null = null;

async getUpdates(from: SyncPeriod, to: SyncPeriod): Promise<VersionedLightClientUpdate[]> {
async getLightClientUpdatesByRange(from: SyncPeriod, to: SyncPeriod): Promise<VersionedLightClientUpdate[]> {
const updates: VersionedLightClientUpdate[] = [];
for (let period = parseInt(String(from)); period <= parseInt(String(to)); period++) {
const update = this.updates.get(period);
Expand All @@ -46,23 +46,23 @@ export class LightclientServerApiMock implements ServerApi<routes.lightclient.Ap
return updates;
}

async getOptimisticUpdate(): Promise<{version: ForkName; data: altair.LightClientOptimisticUpdate}> {
async getLightClientOptimisticUpdate(): Promise<{version: ForkName; data: altair.LightClientOptimisticUpdate}> {
if (!this.latestHeadUpdate) throw Error("No latest head update");
return {version: ForkName.bellatrix, data: this.latestHeadUpdate};
}

async getFinalityUpdate(): Promise<{version: ForkName; data: altair.LightClientFinalityUpdate}> {
async getLightClientFinalityUpdate(): Promise<{version: ForkName; data: altair.LightClientFinalityUpdate}> {
if (!this.finalized) throw Error("No finalized head update");
return {version: ForkName.bellatrix, data: this.finalized};
}

async getBootstrap(blockRoot: string): Promise<{version: ForkName; data: altair.LightClientBootstrap}> {
async getLightClientBootstrap(blockRoot: string): Promise<{version: ForkName; data: altair.LightClientBootstrap}> {
const snapshot = this.snapshots.get(blockRoot);
if (!snapshot) throw Error(`snapshot for blockRoot ${blockRoot} not available`);
return {version: ForkName.bellatrix, data: snapshot};
}

async getCommitteeRoot(startPeriod: SyncPeriod, count: number): Promise<{data: Uint8Array[]}> {
async getLightClientCommitteeRoot(startPeriod: SyncPeriod, count: number): Promise<{data: Uint8Array[]}> {
const periods = Array.from({length: count}, (_ignored, i) => i + startPeriod);
const committeeHashes = periods
.map((period) => this.updates.get(period)?.nextSyncCommittee.pubkeys)
Expand Down

0 comments on commit 91cd2af

Please sign in to comment.