UNPKG

@lodestar/beacon-node

Version:

A Typescript implementation of the beacon chain

202 lines (182 loc) 8.61 kB
import {Type} from "@chainsafe/ssz"; import {BeaconConfig} from "@lodestar/config"; import {ForkName, ForkPostAltair, ForkPostFulu, isForkPostAltair, isForkPostFulu} from "@lodestar/params"; import {Protocol, ProtocolHandler, ReqRespRequest} from "@lodestar/reqresp"; import { DataColumnSidecar, LightClientBootstrap, LightClientFinalityUpdate, LightClientOptimisticUpdate, LightClientUpdate, Metadata, Root, SignedBeaconBlock, Status, altair, deneb, fulu, gloas, phase0, ssz, sszTypesFor, } from "@lodestar/types"; import { BeaconBlocksByRootRequest, BeaconBlocksByRootRequestType, BlobSidecarsByRootRequest, BlobSidecarsByRootRequestType, DataColumnSidecarsByRootRequest, DataColumnSidecarsByRootRequestType, ExecutionPayloadEnvelopesByRootRequest, ExecutionPayloadEnvelopesByRootRequestType, } from "../../util/types.js"; export type ProtocolNoHandler = Omit<Protocol, "handler">; /** ReqResp protocol names or methods. Each ReqRespMethod can have multiple versions and encodings */ export enum ReqRespMethod { // Phase 0 Status = "status", Goodbye = "goodbye", Ping = "ping", Metadata = "metadata", BeaconBlocksByRange = "beacon_blocks_by_range", BeaconBlocksByRoot = "beacon_blocks_by_root", BeaconBlocksByHead = "beacon_blocks_by_head", BlobSidecarsByRange = "blob_sidecars_by_range", BlobSidecarsByRoot = "blob_sidecars_by_root", DataColumnSidecarsByRange = "data_column_sidecars_by_range", DataColumnSidecarsByRoot = "data_column_sidecars_by_root", ExecutionPayloadEnvelopesByRoot = "execution_payload_envelopes_by_root", ExecutionPayloadEnvelopesByRange = "execution_payload_envelopes_by_range", LightClientBootstrap = "light_client_bootstrap", LightClientUpdatesByRange = "light_client_updates_by_range", LightClientFinalityUpdate = "light_client_finality_update", LightClientOptimisticUpdate = "light_client_optimistic_update", } // To typesafe events to network export type RequestBodyByMethod = { [ReqRespMethod.Status]: Status; [ReqRespMethod.Goodbye]: phase0.Goodbye; [ReqRespMethod.Ping]: phase0.Ping; [ReqRespMethod.Metadata]: null; [ReqRespMethod.BeaconBlocksByRange]: phase0.BeaconBlocksByRangeRequest; [ReqRespMethod.BeaconBlocksByRoot]: BeaconBlocksByRootRequest; [ReqRespMethod.BeaconBlocksByHead]: fulu.BeaconBlocksByHeadRequest; [ReqRespMethod.BlobSidecarsByRange]: deneb.BlobSidecarsByRangeRequest; [ReqRespMethod.BlobSidecarsByRoot]: BlobSidecarsByRootRequest; [ReqRespMethod.DataColumnSidecarsByRange]: fulu.DataColumnSidecarsByRangeRequest; [ReqRespMethod.DataColumnSidecarsByRoot]: DataColumnSidecarsByRootRequest; [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: ExecutionPayloadEnvelopesByRootRequest; [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: gloas.ExecutionPayloadEnvelopesByRangeRequest; [ReqRespMethod.LightClientBootstrap]: Root; [ReqRespMethod.LightClientUpdatesByRange]: altair.LightClientUpdatesByRange; [ReqRespMethod.LightClientFinalityUpdate]: null; [ReqRespMethod.LightClientOptimisticUpdate]: null; }; type ResponseBodyByMethod = { [ReqRespMethod.Status]: Status; [ReqRespMethod.Goodbye]: phase0.Goodbye; [ReqRespMethod.Ping]: phase0.Ping; [ReqRespMethod.Metadata]: Metadata; // Do not matter [ReqRespMethod.BeaconBlocksByRange]: SignedBeaconBlock; [ReqRespMethod.BeaconBlocksByRoot]: SignedBeaconBlock; [ReqRespMethod.BeaconBlocksByHead]: SignedBeaconBlock; [ReqRespMethod.BlobSidecarsByRange]: deneb.BlobSidecar; [ReqRespMethod.BlobSidecarsByRoot]: deneb.BlobSidecar; [ReqRespMethod.DataColumnSidecarsByRange]: DataColumnSidecar; [ReqRespMethod.DataColumnSidecarsByRoot]: DataColumnSidecar; [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: gloas.SignedExecutionPayloadEnvelope; [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: gloas.SignedExecutionPayloadEnvelope; [ReqRespMethod.LightClientBootstrap]: LightClientBootstrap; [ReqRespMethod.LightClientUpdatesByRange]: LightClientUpdate; [ReqRespMethod.LightClientFinalityUpdate]: LightClientFinalityUpdate; [ReqRespMethod.LightClientOptimisticUpdate]: LightClientOptimisticUpdate; }; /** Request SSZ type for each method and ForkName */ export const requestSszTypeByMethod: ( fork: ForkName, config: BeaconConfig ) => { [K in ReqRespMethod]: RequestBodyByMethod[K] extends null ? null : Type<RequestBodyByMethod[K]>; } = (fork, config) => ({ // Status type should ideally be determined by protocol version and not fork but since // we only start using the new status version after the fork this is not an issue [ReqRespMethod.Status]: sszTypesFor(fork).Status, [ReqRespMethod.Goodbye]: ssz.phase0.Goodbye, [ReqRespMethod.Ping]: ssz.phase0.Ping, [ReqRespMethod.Metadata]: null, [ReqRespMethod.BeaconBlocksByRange]: ssz.phase0.BeaconBlocksByRangeRequest, [ReqRespMethod.BeaconBlocksByRoot]: BeaconBlocksByRootRequestType(fork, config), [ReqRespMethod.BeaconBlocksByHead]: ssz.fulu.BeaconBlocksByHeadRequest, [ReqRespMethod.BlobSidecarsByRange]: ssz.deneb.BlobSidecarsByRangeRequest, [ReqRespMethod.BlobSidecarsByRoot]: BlobSidecarsByRootRequestType(fork, config), [ReqRespMethod.DataColumnSidecarsByRange]: ssz.fulu.DataColumnSidecarsByRangeRequest, [ReqRespMethod.DataColumnSidecarsByRoot]: DataColumnSidecarsByRootRequestType(config), [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: ExecutionPayloadEnvelopesByRootRequestType(config), [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: ssz.gloas.ExecutionPayloadEnvelopesByRangeRequest, [ReqRespMethod.LightClientBootstrap]: ssz.Root, [ReqRespMethod.LightClientUpdatesByRange]: ssz.altair.LightClientUpdatesByRange, [ReqRespMethod.LightClientFinalityUpdate]: null, [ReqRespMethod.LightClientOptimisticUpdate]: null, }); export type ResponseTypeGetter<T> = (fork: ForkName, version: number) => Type<T>; const blocksResponseType: ResponseTypeGetter<SignedBeaconBlock> = (fork, version) => { if (version === Version.V1) { return ssz.phase0.SignedBeaconBlock; } return ssz[fork].SignedBeaconBlock; }; export const responseSszTypeByMethod: {[K in ReqRespMethod]: ResponseTypeGetter<ResponseBodyByMethod[K]>} = { [ReqRespMethod.Status]: (_, version) => (version === Version.V2 ? ssz.fulu.Status : ssz.phase0.Status), [ReqRespMethod.Goodbye]: () => ssz.phase0.Goodbye, [ReqRespMethod.Ping]: () => ssz.phase0.Ping, [ReqRespMethod.Metadata]: (_, version) => version === Version.V1 ? ssz.phase0.Metadata : version === Version.V2 ? ssz.altair.Metadata : ssz.fulu.Metadata, [ReqRespMethod.BeaconBlocksByRange]: blocksResponseType, [ReqRespMethod.BeaconBlocksByRoot]: blocksResponseType, [ReqRespMethod.BeaconBlocksByHead]: (fork) => ssz[fork].SignedBeaconBlock, [ReqRespMethod.BlobSidecarsByRange]: () => ssz.deneb.BlobSidecar, [ReqRespMethod.BlobSidecarsByRoot]: () => ssz.deneb.BlobSidecar, [ReqRespMethod.LightClientBootstrap]: (fork) => sszTypesFor(onlyPostAltairFork(fork)).LightClientBootstrap, [ReqRespMethod.LightClientUpdatesByRange]: (fork) => sszTypesFor(onlyPostAltairFork(fork)).LightClientUpdate, [ReqRespMethod.LightClientFinalityUpdate]: (fork) => sszTypesFor(onlyPostAltairFork(fork)).LightClientFinalityUpdate, [ReqRespMethod.DataColumnSidecarsByRange]: (fork) => sszTypesFor(onlyPostFuluFork(fork)).DataColumnSidecar, [ReqRespMethod.DataColumnSidecarsByRoot]: (fork) => sszTypesFor(onlyPostFuluFork(fork)).DataColumnSidecar, [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: () => ssz.gloas.SignedExecutionPayloadEnvelope, [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: () => ssz.gloas.SignedExecutionPayloadEnvelope, [ReqRespMethod.LightClientOptimisticUpdate]: (fork) => sszTypesFor(onlyPostAltairFork(fork)).LightClientOptimisticUpdate, }; function onlyPostAltairFork(fork: ForkName): ForkPostAltair { if (isForkPostAltair(fork)) { return fork; } throw Error(`Not a post-altair fork ${fork}`); } function onlyPostFuluFork(fork: ForkName): ForkPostFulu { if (isForkPostFulu(fork)) { return fork; } throw Error(`Not a post-fulu fork ${fork}`); } export type RequestTypedContainer = { [K in ReqRespMethod]: {method: K; body: RequestBodyByMethod[K]}; }[ReqRespMethod]; export enum Version { V1 = 1, V2 = 2, V3 = 3, } export type OutgoingRequestArgs = { peerId: string; method: ReqRespMethod; versions: number[]; requestData: Uint8Array; }; export type IncomingRequestArgs = { method: ReqRespMethod; req: ReqRespRequest; peerId: string; peerClient: string; }; export type GetReqRespHandlerFn = (method: ReqRespMethod) => ProtocolHandler;