UNPKG

@lodestar/beacon-node

Version:

A Typescript implementation of the beacon chain

114 lines 5.16 kB
import { ExecutionStatus } from "@lodestar/fork-choice"; import { ZERO_HASH_HEX, isForkPostDeneb, isForkPostFulu } from "@lodestar/params"; import { sszTypesFor } from "@lodestar/types"; import { toRootHex } from "@lodestar/utils"; import { getBlobKzgCommitments } from "../../../util/dataColumns.js"; import { isOptimisticBlock } from "../../../util/forkChoice.js"; import { getStateSlotFromBytes } from "../../../util/multifork.js"; import { getBlockResponse } from "../beacon/blocks/utils.js"; import { getStateResponseWithRegen } from "../beacon/state/utils.js"; import { assertUniqueItems } from "../utils.js"; export function getDebugApi({ chain, config, }) { return { async getDebugChainHeadsV2() { const heads = chain.forkChoice.getHeads(); return { data: heads.map((block) => ({ slot: block.slot, root: block.blockRoot, executionOptimistic: isOptimisticBlock(block), })), }; }, async getDebugForkChoice() { return { data: { justifiedCheckpoint: chain.forkChoice.getJustifiedCheckpoint(), finalizedCheckpoint: chain.forkChoice.getFinalizedCheckpoint(), forkChoiceNodes: chain.forkChoice.getAllNodes().map((node) => ({ slot: node.slot, blockRoot: node.blockRoot, parentRoot: node.parentRoot, justifiedEpoch: node.justifiedEpoch, finalizedEpoch: node.finalizedEpoch, weight: node.weight, validity: (() => { switch (node.executionStatus) { case ExecutionStatus.Valid: return "valid"; case ExecutionStatus.Invalid: return "invalid"; case ExecutionStatus.Syncing: case ExecutionStatus.PreMerge: return "optimistic"; } })(), executionBlockHash: node.executionPayloadBlockHash ?? ZERO_HASH_HEX, })), }, }; }, async getProtoArrayNodes() { const nodes = chain.forkChoice.getAllNodes().map((node) => ({ // if node has executionPayloadNumber, it will overwrite the below default executionPayloadNumber: 0, ...node, executionPayloadBlockHash: node.executionPayloadBlockHash ?? "", parent: String(node.parent), bestChild: String(node.bestChild), bestDescendant: String(node.bestDescendant), })); return { data: nodes }; }, async getStateV2({ stateId }, context) { const { state, executionOptimistic, finalized } = await getStateResponseWithRegen(chain, stateId); let slot, data; if (state instanceof Uint8Array) { slot = getStateSlotFromBytes(state); data = state; } else { slot = state.slot; data = context?.returnBytes ? state.serialize() : state.toValue(); } return { data, meta: { version: config.getForkName(slot), executionOptimistic, finalized, }, }; }, async getDebugDataColumnSidecars({ blockId, indices }) { assertUniqueItems(indices, "Duplicate indices provided"); const { block, executionOptimistic, finalized } = await getBlockResponse(chain, blockId); const fork = config.getForkName(block.message.slot); const blockRoot = sszTypesFor(fork).BeaconBlock.hashTreeRoot(block.message); let dataColumnSidecars; const blobCount = isForkPostDeneb(fork) ? getBlobKzgCommitments(fork, block).length : 0; if (isForkPostFulu(fork) && blobCount > 0) { dataColumnSidecars = await chain.getDataColumnSidecars(block.message.slot, toRootHex(blockRoot)); if (dataColumnSidecars.length === 0) { throw Error(`dataColumnSidecars not found in db for slot=${block.message.slot} root=${toRootHex(blockRoot)} blobs=${blobCount}`); } } else { dataColumnSidecars = []; } return { data: (indices ? dataColumnSidecars.filter(({ index }) => indices.includes(index)) : dataColumnSidecars), meta: { executionOptimistic, finalized, version: fork, }, }; }, }; } //# sourceMappingURL=index.js.map