UNPKG

@lodestar/beacon-node

Version:

A Typescript implementation of the beacon chain

76 lines (64 loc) 2.29 kB
import {routes} from "@lodestar/api"; import {ChainForkConfig} from "@lodestar/config"; import {IForkChoice} from "@lodestar/fork-choice"; import {blockToHeader} from "@lodestar/state-transition"; import {RootHex, SignedBeaconBlock, Slot} from "@lodestar/types"; import {IBeaconChain} from "../../../../chain/interface.js"; import {GENESIS_SLOT} from "../../../../constants/index.js"; import {rootHexRegex} from "../../../../execution/engine/utils.js"; import {ApiError, ValidationError} from "../../errors.js"; export function toBeaconHeaderResponse( config: ChainForkConfig, block: SignedBeaconBlock, canonical = false ): routes.beacon.BlockHeaderResponse { return { root: config.getForkTypes(block.message.slot).BeaconBlock.hashTreeRoot(block.message), canonical, header: { message: blockToHeader(config, block.message), signature: block.signature, }, }; } export function resolveBlockId(forkChoice: IForkChoice, blockId: routes.beacon.BlockId): RootHex | Slot { blockId = String(blockId).toLowerCase(); if (blockId === "head") { return forkChoice.getHead().blockRoot; } if (blockId === "genesis") { return GENESIS_SLOT; } if (blockId === "finalized") { return forkChoice.getFinalizedBlock().blockRoot; } if (blockId === "justified") { return forkChoice.getJustifiedBlock().blockRoot; } if (blockId.startsWith("0x")) { if (!rootHexRegex.test(blockId)) { throw new ValidationError(`Invalid block id '${blockId}'`, "blockId"); } return blockId; } // block id must be slot const blockSlot = parseInt(blockId, 10); if (Number.isNaN(blockSlot) && Number.isNaN(blockSlot - 0)) { throw new ValidationError(`Invalid block id '${blockId}'`, "blockId"); } return blockSlot; } export async function getBlockResponse( chain: IBeaconChain, blockId: routes.beacon.BlockId ): Promise<{block: SignedBeaconBlock; executionOptimistic: boolean; finalized: boolean}> { const rootOrSlot = resolveBlockId(chain.forkChoice, blockId); const res = typeof rootOrSlot === "string" ? await chain.getBlockByRoot(rootOrSlot) : await chain.getCanonicalBlockAtSlot(rootOrSlot); if (!res) { throw new ApiError(404, `Block not found for id '${blockId}'`); } return res; }