Skip to content

Commit

Permalink
Merge branch 'unstable' into nh/types-refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
nflaig committed Jun 21, 2024
2 parents 6374b0a + a2c389f commit 2661efc
Show file tree
Hide file tree
Showing 22 changed files with 129 additions and 303 deletions.
3 changes: 2 additions & 1 deletion packages/api/src/beacon/client/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ export function getClient(config: ChainForkConfig, baseUrl: string): ApiClient {

// Ignore noisy errors due to beacon node being offline
if (!errEs.message?.includes("ECONNREFUSED")) {
onError?.(new Error(errEs.message));
// If there is no message it likely indicates that the server closed the connection
onError?.(new Error(errEs.message ?? "Server closed connection"));
}

// Consider 400 and 500 status errors unrecoverable, close the eventsource
Expand Down
25 changes: 1 addition & 24 deletions packages/api/src/beacon/routes/beacon/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
ssz,
RootHex,
deneb,
phase0,
isSignedBlockContents,
SignedBeaconBlock,
BeaconBlockBody,
Expand All @@ -15,7 +14,7 @@ import {
} from "@lodestar/types";
import {ForkName, ForkSeq} from "@lodestar/params";
import {Endpoint, RequestCodec, RouteDefinitions, Schema} from "../../../utils/index.js";
import {EmptyMeta, EmptyMetaCodec, EmptyResponseCodec, EmptyResponseData, WithVersion} from "../../../utils/codecs.js";
import {EmptyMeta, EmptyResponseCodec, EmptyResponseData, WithVersion} from "../../../utils/codecs.js";
import {
ExecutionOptimisticAndFinalizedCodec,
ExecutionOptimisticAndFinalizedMeta,
Expand Down Expand Up @@ -77,19 +76,6 @@ export enum BroadcastValidation {
}

export type Endpoints = {
/**
* Get block
* Returns the complete `SignedBeaconBlock` for a given block ID.
*/
getBlock: Endpoint<
// ⏎
"GET",
BlockArgs,
{params: {block_id: string}},
phase0.SignedBeaconBlock,
EmptyMeta
>;

/**
* Get block
* Retrieves block details for given block id.
Expand Down Expand Up @@ -231,15 +217,6 @@ const blockIdOnlyReq: RequestCodec<Endpoint<"GET", {blockId: BlockId}, {params:

export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoints> {
return {
getBlock: {
url: "/eth/v1/beacon/blocks/{block_id}",
method: "GET",
req: blockIdOnlyReq,
resp: {
data: ssz.phase0.SignedBeaconBlock,
meta: EmptyMetaCodec,
},
},
getBlockV2: {
url: "/eth/v2/beacon/blocks/{block_id}",
method: "GET",
Expand Down
92 changes: 13 additions & 79 deletions packages/api/src/beacon/routes/debug.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/naming-convention */
import {ContainerType, Type, ValueOf} from "@chainsafe/ssz";
import {ChainForkConfig} from "@lodestar/config";
import {ssz, StringType, phase0, BeaconState} from "@lodestar/types";
import {ssz, StringType, BeaconState} from "@lodestar/types";
import {
ArrayOf,
EmptyArgs,
Expand All @@ -14,8 +14,6 @@ import {
import {
ExecutionOptimisticFinalizedAndVersionCodec,
ExecutionOptimisticFinalizedAndVersionMeta,
ExecutionOptimisticAndFinalizedCodec,
ExecutionOptimisticAndFinalizedMeta,
} from "../../utils/metadata.js";
import {Endpoint, RouteDefinitions} from "../../utils/types.js";
import {WireFormat} from "../../utils/wireFormat.js";
Expand All @@ -25,7 +23,7 @@ import {StateArgs} from "./beacon/state.js";
// See /packages/api/src/routes/index.ts for reasoning and instructions to add new routes

const stringType = new StringType();
const ProtoNodeResponseType = new ContainerType(
const ProtoNodeType = new ContainerType(
{
executionPayloadBlockHash: stringType,
executionPayloadNumber: ssz.UintNum64,
Expand All @@ -51,14 +49,7 @@ const ProtoNodeResponseType = new ContainerType(
},
{jsonCase: "eth2"}
);
const SlotRootType = new ContainerType(
{
slot: ssz.Slot,
root: stringType,
},
{jsonCase: "eth2"}
);
const SlotRootExecutionOptimisticType = new ContainerType(
const DebugChainHeadType = new ContainerType(
{
slot: ssz.Slot,
root: stringType,
Expand All @@ -67,27 +58,13 @@ const SlotRootExecutionOptimisticType = new ContainerType(
{jsonCase: "eth2"}
);

const ProtoNodeResponseListType = ArrayOf(ProtoNodeResponseType);
const SlotRootListType = ArrayOf(SlotRootType);
const SlotRootExecutionOptimisticListType = ArrayOf(SlotRootExecutionOptimisticType);
const ProtoNodeListType = ArrayOf(ProtoNodeType);
const DebugChainHeadListType = ArrayOf(DebugChainHeadType);

type ProtoNodeResponseList = ValueOf<typeof ProtoNodeResponseListType>;
type SlotRootList = ValueOf<typeof SlotRootListType>;
type SlotRootExecutionOptimisticList = ValueOf<typeof SlotRootExecutionOptimisticListType>;
type ProtoNodeList = ValueOf<typeof ProtoNodeListType>;
type DebugChainHeadList = ValueOf<typeof DebugChainHeadListType>;

export type Endpoints = {
/**
* Retrieves all possible chain heads (leaves of fork choice tree).
*/
getDebugChainHeads: Endpoint<
// ⏎
"GET",
EmptyArgs,
EmptyRequest,
SlotRootList,
EmptyMeta
>;

/**
* Retrieves all possible chain heads (leaves of fork choice tree).
*/
Expand All @@ -96,7 +73,7 @@ export type Endpoints = {
"GET",
EmptyArgs,
EmptyRequest,
SlotRootExecutionOptimisticList,
DebugChainHeadList,
EmptyMeta
>;

Expand All @@ -108,23 +85,10 @@ export type Endpoints = {
"GET",
EmptyArgs,
EmptyRequest,
ProtoNodeResponseList,
ProtoNodeList,
EmptyMeta
>;

/**
* Get full BeaconState object
* Returns full BeaconState object for given stateId.
* Depending on `Accept` header it can be returned either as json or as bytes serialized by SSZ
*/
getState: Endpoint<
"GET",
StateArgs,
{params: {state_id: string}},
phase0.BeaconState,
ExecutionOptimisticAndFinalizedMeta
>;

/**
* Get full BeaconState object
* Returns full BeaconState object for given stateId.
Expand All @@ -139,27 +103,14 @@ export type Endpoints = {
>;
};

// Default timeout is not sufficient to download state as JSON
const GET_STATE_TIMEOUT_MS = 5 * 60 * 1000;

export function getDefinitions(_config: ChainForkConfig): RouteDefinitions<Endpoints> {
return {
getDebugChainHeads: {
url: "/eth/v1/debug/beacon/heads",
method: "GET",
req: EmptyRequestCodec,
resp: {
data: SlotRootListType,
meta: EmptyMetaCodec,
onlySupport: WireFormat.json,
},
},
getDebugChainHeadsV2: {
url: "/eth/v2/debug/beacon/heads",
method: "GET",
req: EmptyRequestCodec,
resp: {
data: SlotRootExecutionOptimisticListType,
data: DebugChainHeadListType,
meta: EmptyMetaCodec,
onlySupport: WireFormat.json,
},
Expand All @@ -169,29 +120,11 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions<Endpo
method: "GET",
req: EmptyRequestCodec,
resp: {
data: ProtoNodeResponseListType,
data: ProtoNodeListType,
meta: EmptyMetaCodec,
onlySupport: WireFormat.json,
},
},
getState: {
url: "/eth/v1/debug/beacon/states/{state_id}",
method: "GET",
req: {
writeReq: ({stateId}) => ({params: {state_id: stateId.toString()}}),
parseReq: ({params}) => ({stateId: params.state_id}),
schema: {
params: {state_id: Schema.StringRequired},
},
},
resp: {
data: ssz.phase0.BeaconState,
meta: ExecutionOptimisticAndFinalizedCodec,
},
init: {
timeoutMs: GET_STATE_TIMEOUT_MS,
},
},
getStateV2: {
url: "/eth/v2/debug/beacon/states/{state_id}",
method: "GET",
Expand All @@ -207,7 +140,8 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions<Endpo
meta: ExecutionOptimisticFinalizedAndVersionCodec,
},
init: {
timeoutMs: GET_STATE_TIMEOUT_MS,
// Default timeout is not sufficient to download state as JSON
timeoutMs: 5 * 60 * 1000,
},
},
};
Expand Down
46 changes: 0 additions & 46 deletions packages/api/src/beacon/routes/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
ValidatorIndex,
ProducedBlockSource,
stringType,
BeaconBlock,
BeaconBlockOrContents,
BlindedBeaconBlock,
} from "@lodestar/types";
Expand Down Expand Up @@ -292,25 +291,6 @@ export type Endpoints = {
ExecutionOptimisticMeta
>;

/**
* Produce a new block, without signature.
* Requests a beacon node to produce a valid block, which can then be signed by a validator.
*/
produceBlock: Endpoint<
"GET",
{
/** The slot for which the block should be proposed. */
slot: Slot;
/** The validator's randao reveal value */
randaoReveal: BLSSignature;
/** Arbitrary data validator wants to include in block */
graffiti: string;
},
{params: {slot: number}; query: {randao_reveal: string; graffiti: string}},
BeaconBlock,
VersionMeta
>;

/**
* Requests a beacon node to produce a valid block, which can then be signed by a validator.
* Metadata in the response indicates the type of block produced, and the supported types of block
Expand Down Expand Up @@ -609,32 +589,6 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions<Endpo
meta: ExecutionOptimisticCodec,
},
},
produceBlock: {
url: "/eth/v1/validator/blocks/{slot}",
method: "GET",
req: {
writeReq: ({slot, randaoReveal, graffiti}) => ({
params: {slot},
query: {randao_reveal: toHexString(randaoReveal), graffiti: toGraffitiHex(graffiti)},
}),
parseReq: ({params, query}) => ({
slot: params.slot,
randaoReveal: fromHexString(query.randao_reveal),
graffiti: fromGraffitiHex(query.graffiti),
}),
schema: {
params: {slot: Schema.UintRequired},
query: {
randao_reveal: Schema.StringRequired,
graffiti: Schema.String,
},
},
},
resp: {
data: WithVersion((fork) => ssz[fork].BeaconBlock),
meta: VersionCodec,
},
},
produceBlockV2: {
url: "/eth/v2/validator/blocks/{slot}",
method: "GET",
Expand Down
27 changes: 14 additions & 13 deletions packages/api/src/utils/client/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,11 @@ export class ApiResponse<E extends Endpoint> extends Response {
return null;
}

return new ApiError(getErrorMessage(this.resolvedErrorBody()), this.status, this.definition.operationId);
return new ApiError(this.getErrorMessage(), this.status, this.definition.operationId);
}

async errorBody(): Promise<string> {
if (!this._errorBody) {
if (this._errorBody === undefined) {
this._errorBody = await this.text();
}
return this._errorBody;
Expand All @@ -179,23 +179,24 @@ export class ApiResponse<E extends Endpoint> extends Response {
}

private resolvedErrorBody(): string {
if (!this._errorBody) {
if (this._errorBody === undefined) {
throw Error("errorBody() must be called first");
}

return this._errorBody;
}
}

function getErrorMessage(errBody: string): string {
try {
const errJson = JSON.parse(errBody) as {message?: string};
if (errJson.message) {
return errJson.message;
} else {
return errBody;
private getErrorMessage(): string {
const errBody = this.resolvedErrorBody();
try {
const errJson = JSON.parse(errBody) as {message?: string};
if (errJson.message) {
return errJson.message;
} else {
return errBody;
}
} catch (e) {
return errBody || this.statusText;
}
} catch (e) {
return errBody;
}
}
Loading

0 comments on commit 2661efc

Please sign in to comment.