UNPKG

@lodestar/beacon-node

Version:

A Typescript implementation of the beacon chain

133 lines (120 loc) 6.3 kB
import {EventEmitter} from "node:events"; import {StrictEventEmitter} from "strict-event-emitter-types"; import {routes} from "@lodestar/api"; import {CheckpointWithHex} from "@lodestar/fork-choice"; import {IBeaconStateView} from "@lodestar/state-transition"; import {DataColumnSidecar, RootHex, deneb, phase0} from "@lodestar/types"; import {PeerIdStr} from "../util/peerId.js"; import {BlockInputSource, IBlockInput} from "./blocks/blockInput/types.js"; import {PayloadEnvelopeInput} from "./blocks/payloadEnvelopeInput/payloadEnvelopeInput.js"; /** * Important chain events that occur during normal chain operation. * * Chain events can be broken into several categories: * - Clock: the chain's clock is updated * - Fork Choice: the chain's fork choice is updated * - Checkpointing: the chain processes epoch boundaries */ export enum ChainEvent { /** * This event signals that the chain has processed (or reprocessed) a checkpoint. * * This event is not tied to clock events, but rather tied to generation (or regeneration) of state. * This event is guaranteed to be called after _any_ checkpoint is processed, including skip-slot checkpoints, checkpoints that are formed as a result of processing blocks, etc. */ checkpoint = "checkpoint", /** * This event signals that the fork choice store has been updated. * * This event is guaranteed to be triggered whenever the fork choice justified checkpoint is updated. This is either in response to a newly processed block or a new clock tick. */ forkChoiceJustified = "forkChoice:justified", /** * This event signals that the fork choice store has been updated. * * This event is guaranteed to be triggered whenever the fork choice justified checkpoint is updated. This is in response to a newly processed block. */ forkChoiceFinalized = "forkChoice:finalized", /** * This event signals that dependent services (e.g. custody sampling) should update to account for the new target group count. */ updateTargetCustodyGroupCount = "updateTargetCustodyGroupCount", /** * This event signals that data columns have been fetched from the execution engine * and are ready to be published. */ publishDataColumns = "publishDataColumns", /** * This event signals that blobs have been fetched from the execution engine * and are ready to be published. */ publishBlobSidecars = "publishBlobSidecars", /** * Trigger an update of status so reqresp by peers have current earliestAvailableSlot */ updateStatus = "updateStatus", /** * Trigger BlockInputSync to find parent of a SignedBeaconBlock received * Post-gloas, missing parent could be a SignedBeaconBlock and/or a SignedExecutionPayloadEnvelope */ blockUnknownParent = "blockUnknownParent", /** * Trigger BlockInputSync to find a SignedBeaconBlock with specified block root. */ unknownBlockRoot = "unknownBlockRoot", /** * Trigger BlockInputSync to find a SignedExecutionPayloadEnvelope with specified block root. */ unknownEnvelopeBlockRoot = "unknownEnvelopeBlockRoot", /** * Trigger BlockInputSync for blocks that are partially received via gossip but are not complete by time the * cut-off window passes for waiting on gossip */ incompleteBlockInput = "incompleteBlockInput", /** * Post-gloas: trigger BlockInputSync for payload envelopes whose envelope and/or sampled columns are partially * received via gossip but are not complete by time the cut-off window passes for waiting on gossip */ incompletePayloadEnvelope = "incompletePayloadEnvelope", } export type HeadEventData = routes.events.EventData[routes.events.EventType.head]; export type ReorgEventData = routes.events.EventData[routes.events.EventType.chainReorg]; // API events are emitted through the same ChainEventEmitter for re-use internally type ApiEvents = {[K in routes.events.EventType]: (data: routes.events.EventData[K]) => void}; export type ChainEventData = { [ChainEvent.blockUnknownParent]: {blockInput: IBlockInput; peer: PeerIdStr; source: BlockInputSource}; [ChainEvent.unknownBlockRoot]: {rootHex: RootHex; peer?: PeerIdStr; source: BlockInputSource}; [ChainEvent.incompleteBlockInput]: {blockInput: IBlockInput; peer: PeerIdStr; source: BlockInputSource}; [ChainEvent.incompletePayloadEnvelope]: { payloadInput: PayloadEnvelopeInput; peer: PeerIdStr; source: BlockInputSource; }; [ChainEvent.unknownEnvelopeBlockRoot]: {rootHex: RootHex; peer?: PeerIdStr; source: BlockInputSource}; }; export type IChainEvents = ApiEvents & { [ChainEvent.checkpoint]: (checkpoint: phase0.Checkpoint, state: IBeaconStateView) => void; [ChainEvent.forkChoiceJustified]: (checkpoint: CheckpointWithHex) => void; [ChainEvent.forkChoiceFinalized]: (checkpoint: CheckpointWithHex) => void; [ChainEvent.updateTargetCustodyGroupCount]: (targetGroupCount: number) => void; [ChainEvent.publishDataColumns]: (sidecars: DataColumnSidecar[]) => void; [ChainEvent.publishBlobSidecars]: (sidecars: deneb.BlobSidecar[]) => void; [ChainEvent.updateStatus]: () => void; // Sync events that are chain->chain. Initiated from network requests but do not cross the network // barrier so are considered ChainEvent(s). [ChainEvent.blockUnknownParent]: (data: ChainEventData[ChainEvent.blockUnknownParent]) => void; [ChainEvent.unknownBlockRoot]: (data: ChainEventData[ChainEvent.unknownBlockRoot]) => void; [ChainEvent.incompleteBlockInput]: (data: ChainEventData[ChainEvent.incompleteBlockInput]) => void; [ChainEvent.incompletePayloadEnvelope]: (data: ChainEventData[ChainEvent.incompletePayloadEnvelope]) => void; [ChainEvent.unknownEnvelopeBlockRoot]: (data: ChainEventData[ChainEvent.unknownEnvelopeBlockRoot]) => void; }; /** * Emits important chain events that occur during normal chain operation. * * Chain events can be broken into several categories: * - Clock: the chain's clock is updated * - Fork Choice: the chain's fork choice is updated * - Processing: the chain processes attestations and blocks, either successfully or with an error * - Checkpointing: the chain processes epoch boundaries */ export class ChainEventEmitter extends (EventEmitter as {new (): StrictEventEmitter<EventEmitter, IChainEvents>}) {}