UNPKG

@lodestar/beacon-node

Version:

A Typescript implementation of the beacon chain

320 lines (286 loc) • 13 kB
import {Type} from "@chainsafe/ssz"; import {BeaconConfig} from "@lodestar/config"; import {CheckpointWithHex, IForkChoice, ProtoBlock} from "@lodestar/fork-choice"; import {EpochShuffling, IBeaconStateView, PubkeyCache} from "@lodestar/state-transition"; import { BeaconBlock, BlindedBeaconBlock, DataColumnSidecar, Epoch, Root, RootHex, SignedBeaconBlock, Slot, Status, UintNum64, ValidatorIndex, Wei, altair, capella, deneb, electra, gloas, phase0, rewards, } from "@lodestar/types"; import {Logger} from "@lodestar/utils"; import {IExecutionBuilder, IExecutionEngine} from "../execution/index.js"; import {Metrics} from "../metrics/metrics.js"; import {BufferPool} from "../util/bufferPool.js"; import {IClock} from "../util/clock.js"; import {CustodyConfig} from "../util/dataColumns.js"; import {SerializedCache} from "../util/serializedCache.js"; import {IArchiveStore} from "./archiveStore/interface.js"; import {CheckpointBalancesCache} from "./balancesCache.js"; import {BeaconProposerCache, ProposerPreparationData} from "./beaconProposerCache.js"; import {IBlockInput} from "./blocks/blockInput/index.js"; import {ImportBlockOpts, ImportPayloadOpts} from "./blocks/types.js"; import {IBlsVerifier} from "./bls/index.js"; import {ColumnReconstructionTracker} from "./ColumnReconstructionTracker.js"; import {ChainEventEmitter} from "./emitter.js"; import {ForkchoiceCaller} from "./forkChoice/index.js"; import {GetBlobsTracker} from "./GetBlobsTracker.js"; import {LightClientServer} from "./lightClient/index.js"; import {AggregatedAttestationPool} from "./opPools/aggregatedAttestationPool.js"; import { AttestationPool, ExecutionPayloadBidPool, OpPool, PayloadAttestationPool, SyncCommitteeMessagePool, SyncContributionAndProofPool, } from "./opPools/index.js"; import {IChainOptions} from "./options.js"; import {AssembledBlockType, BlockAttributes, BlockType, ProduceResult} from "./produceBlock/produceBlockBody.js"; import {IStateRegenerator, RegenCaller} from "./regen/index.js"; import {ReprocessController} from "./reprocess.js"; import { SeenAggregators, SeenAttesters, SeenBlockProposers, SeenContributionAndProof, SeenExecutionPayloadBids, SeenPayloadAttesters, SeenProposerPreferences, SeenSyncCommitteeMessages, } from "./seenCache/index.js"; import {SeenAggregatedAttestations} from "./seenCache/seenAggregateAndProof.js"; import {SeenAttestationDatas} from "./seenCache/seenAttestationData.js"; import {SeenBlockAttesters} from "./seenCache/seenBlockAttesters.js"; import {SeenBlockInput} from "./seenCache/seenGossipBlockInput.js"; import {PayloadEnvelopeInput, SeenPayloadEnvelopeInput} from "./seenCache/seenPayloadEnvelopeInput.js"; import {ShufflingCache} from "./shufflingCache.js"; import {ValidatorMonitor} from "./validatorMonitor.js"; export {BlockType, type AssembledBlockType}; export {type ProposerPreparationData}; export type BlockHash = RootHex; export type StateGetOpts = { allowRegen: boolean; }; export enum FindHeadFnName { recomputeForkChoiceHead = "recomputeForkChoiceHead", predictProposerHead = "predictProposerHead", getProposerHead = "getProposerHead", } /** * The IBeaconChain service deals with processing incoming blocks, advancing a state transition * and applying the fork choice rule to update the chain head */ export interface IBeaconChain { readonly genesisTime: UintNum64; readonly genesisValidatorsRoot: Root; readonly earliestAvailableSlot: Slot; readonly executionEngine: IExecutionEngine; readonly executionBuilder?: IExecutionBuilder; // Expose config for convenience in modularized functions readonly config: BeaconConfig; readonly custodyConfig: CustodyConfig; readonly logger: Logger; readonly metrics: Metrics | null; readonly validatorMonitor: ValidatorMonitor | null; readonly bufferPool: BufferPool | null; /** The initial slot that the chain is started with */ readonly anchorStateLatestBlockSlot: Slot; readonly bls: IBlsVerifier; readonly forkChoice: IForkChoice; readonly clock: IClock; readonly emitter: ChainEventEmitter; readonly regen: IStateRegenerator; readonly lightClientServer?: LightClientServer; readonly reprocessController: ReprocessController; readonly pubkeyCache: PubkeyCache; readonly archiveStore: IArchiveStore; // Ops pool readonly attestationPool: AttestationPool; readonly aggregatedAttestationPool: AggregatedAttestationPool; readonly syncCommitteeMessagePool: SyncCommitteeMessagePool; readonly syncContributionAndProofPool: SyncContributionAndProofPool; readonly executionPayloadBidPool: ExecutionPayloadBidPool; readonly payloadAttestationPool: PayloadAttestationPool; readonly opPool: OpPool; // Gossip seen cache readonly seenAttesters: SeenAttesters; readonly seenAggregators: SeenAggregators; readonly seenPayloadAttesters: SeenPayloadAttesters; readonly seenAggregatedAttestations: SeenAggregatedAttestations; readonly seenExecutionPayloadBids: SeenExecutionPayloadBids; readonly seenProposerPreferences: SeenProposerPreferences; readonly seenBlockProposers: SeenBlockProposers; readonly seenSyncCommitteeMessages: SeenSyncCommitteeMessages; readonly seenContributionAndProof: SeenContributionAndProof; readonly seenAttestationDatas: SeenAttestationDatas; readonly seenBlockInputCache: SeenBlockInput; readonly seenPayloadEnvelopeInputCache: SeenPayloadEnvelopeInput; // Seen cache for liveness checks readonly seenBlockAttesters: SeenBlockAttesters; readonly beaconProposerCache: BeaconProposerCache; readonly checkpointBalancesCache: CheckpointBalancesCache; readonly blockProductionCache: Map<RootHex, ProduceResult>; readonly shufflingCache: ShufflingCache; readonly blacklistedBlocks: Map<RootHex, Slot | null>; // Cache for serialized objects readonly serializedCache: SerializedCache; readonly getBlobsTracker: GetBlobsTracker; readonly columnReconstructionTracker: ColumnReconstructionTracker; readonly opts: IChainOptions; /** Start the processing of chain and load state from disk and related actions */ init(): Promise<void>; /** Stop beacon chain processing */ close(): Promise<void>; /** Chain has seen the specified block root or not. The block may not be processed yet, use forkchoice.hasBlock to check it */ seenBlock(blockRoot: RootHex): boolean; /** Chain has seen a SignedExecutionPayloadEnvelope for this block root (via seenCache or fork choice FULL variant) */ seenPayloadEnvelope(blockRoot: RootHex): boolean; /** Populate in-memory caches with persisted data. Call at least once on startup */ loadFromDisk(): Promise<void>; /** Persist in-memory data to the DB. Call at least once before stopping the process */ persistToDisk(): Promise<void>; validatorSeenAtEpoch(index: ValidatorIndex, epoch: Epoch): boolean; getHeadState(): IBeaconStateView; getHeadStateAtCurrentEpoch(regenCaller: RegenCaller): Promise<IBeaconStateView>; getHeadStateAtEpoch(epoch: Epoch, regenCaller: RegenCaller): Promise<IBeaconStateView>; getHistoricalStateBySlot( slot: Slot ): Promise<{state: Uint8Array; executionOptimistic: boolean; finalized: boolean} | null>; /** Returns a local state canonical at `slot` */ getStateBySlot( slot: Slot, opts?: StateGetOpts ): Promise<{state: IBeaconStateView; executionOptimistic: boolean; finalized: boolean} | null>; /** Returns a local state by state root */ getStateByStateRoot( stateRoot: RootHex, opts?: StateGetOpts ): Promise<{state: IBeaconStateView | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null>; /** Return serialized bytes of a persisted checkpoint state */ getPersistedCheckpointState(checkpoint?: phase0.Checkpoint): Promise<Uint8Array | null>; /** Returns a cached state by checkpoint */ getStateByCheckpoint( checkpoint: CheckpointWithHex ): {state: IBeaconStateView; executionOptimistic: boolean; finalized: boolean} | null; /** Return state bytes by checkpoint */ getStateOrBytesByCheckpoint( checkpoint: CheckpointWithHex ): Promise<{state: IBeaconStateView | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null>; /** * Since we can have multiple parallel chains, * this methods returns blocks in current chain head according to * forkchoice. Works for finalized slots as well */ getCanonicalBlockAtSlot( slot: Slot ): Promise<{block: SignedBeaconBlock; executionOptimistic: boolean; finalized: boolean} | null>; /** * Get local block by root, does not fetch from the network */ getSerializedBlockByRoot( root: RootHex ): Promise<{block: Uint8Array; executionOptimistic: boolean; finalized: boolean; slot: Slot} | null>; /** * Get local block by root, does not fetch from the network */ getBlockByRoot( root: RootHex ): Promise<{block: SignedBeaconBlock; executionOptimistic: boolean; finalized: boolean} | null>; getBlobSidecars(blockSlot: Slot, blockRootHex: string): Promise<deneb.BlobSidecars | null>; getSerializedBlobSidecars(blockSlot: Slot, blockRootHex: string): Promise<Uint8Array | null>; getDataColumnSidecars(blockSlot: Slot, blockRootHex: string): Promise<DataColumnSidecar[]>; getSerializedDataColumnSidecars( blockSlot: Slot, blockRootHex: string, indices: number[] ): Promise<(Uint8Array | undefined)[]>; getSerializedExecutionPayloadEnvelope(blockSlot: Slot, blockRootHex: string): Promise<Uint8Array | null>; getExecutionPayloadEnvelope( blockSlot: Slot, blockRootHex: string ): Promise<gloas.SignedExecutionPayloadEnvelope | null>; getParentExecutionRequests(parentBlockSlot: Slot, parentBlockRootHex: RootHex): Promise<electra.ExecutionRequests>; produceCommonBlockBody(blockAttributes: BlockAttributes): Promise<CommonBlockBody>; produceBlock(blockAttributes: BlockAttributes & {commonBlockBodyPromise: Promise<CommonBlockBody>}): Promise<{ block: BeaconBlock; executionPayloadValue: Wei; consensusBlockValue: Wei; shouldOverrideBuilder?: boolean; }>; produceBlindedBlock(blockAttributes: BlockAttributes & {commonBlockBodyPromise: Promise<CommonBlockBody>}): Promise<{ block: BlindedBeaconBlock; executionPayloadValue: Wei; consensusBlockValue: Wei; }>; /** Process a block until complete */ processBlock(block: IBlockInput, opts?: ImportBlockOpts): Promise<void>; /** Process a chain of blocks until complete */ processChainSegment( blocks: IBlockInput[], payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null, opts?: ImportBlockOpts ): Promise<void>; /** Process execution payload envelope: verify, import to fork choice, and persist to DB */ processExecutionPayload(payloadInput: PayloadEnvelopeInput, opts?: ImportPayloadOpts): Promise<void>; getStatus(): Status; recomputeForkChoiceHead(caller: ForkchoiceCaller): ProtoBlock; /** When proposerBoostReorg is enabled, this is called at slot n-1 to predict the head block to build on if we are proposing at slot n */ predictProposerHead(slot: Slot): ProtoBlock; /** When proposerBoostReorg is enabled and we are proposing a block, this is called to determine which head block to build on */ getProposerHead(slot: Slot): ProtoBlock; waitForBlock(slot: Slot, root: RootHex): Promise<boolean>; updateBeaconProposerData(epoch: Epoch, proposers: ProposerPreparationData[]): Promise<void>; persistBlock(data: BeaconBlock | BlindedBeaconBlock, suffix?: string): void; persistInvalidStateRoot( preState: IBeaconStateView, postState: IBeaconStateView, block: SignedBeaconBlock ): Promise<void>; persistInvalidSszValue<T>(type: Type<T>, sszObject: T | Uint8Array, suffix?: string): void; persistInvalidSszBytes(type: string, sszBytes: Uint8Array, suffix?: string): void; regenStateForAttestationVerification( attEpoch: Epoch, shufflingDependentRoot: RootHex, attHeadBlock: ProtoBlock, regenCaller: RegenCaller ): Promise<EpochShuffling>; updateBuilderStatus(clockSlot: Slot): void; regenCanAcceptWork(): boolean; blsThreadPoolCanAcceptWork(): boolean; getBlockRewards(blockRef: BeaconBlock | BlindedBeaconBlock): Promise<rewards.BlockRewards>; getAttestationsRewards( epoch: Epoch, validatorIds?: (ValidatorIndex | string)[] ): Promise<{rewards: rewards.AttestationsRewards; executionOptimistic: boolean; finalized: boolean}>; getSyncCommitteeRewards( blockRef: BeaconBlock | BlindedBeaconBlock, validatorIds?: (ValidatorIndex | string)[] ): Promise<rewards.SyncCommitteeRewards>; } export type SSZObjectType = | "state" | "signedBlock" | "block" | "attestation" | "signedAggregatedAndProof" | "syncCommittee" | "contributionAndProof"; export type CommonBlockBody = phase0.BeaconBlockBody & Pick<capella.BeaconBlockBody, "blsToExecutionChanges"> & Pick<altair.BeaconBlockBody, "syncAggregate">;