UNPKG

@lodestar/beacon-node

Version:

A Typescript implementation of the beacon chain

76 lines 2.96 kB
import { DataAvailabilityStatus, ExecutionPayloadStatus, createCachedBeaconState, stateTransition, } from "@lodestar/state-transition"; import { RegenErrorType } from "./types.js"; /** * Populate a PubkeyIndexMap with any new entries based on a BeaconState */ export function syncPubkeyCache(state, pubkey2index) { // Get the validators sub tree once for all the loop const validators = state.validators; const newCount = state.validators.length; for (let i = pubkey2index.size; i < newCount; i++) { const pubkey = validators.getReadonly(i).pubkey; pubkey2index.set(pubkey, i); } } /** * Get the nearest BeaconState at or before a slot */ export async function getNearestState(slot, config, db, pubkey2index) { const states = await db.stateArchive.values({ limit: 1, lte: slot, reverse: true }); if (!states.length) { throw new Error("No near state found in the database"); } const state = states[0]; syncPubkeyCache(state, pubkey2index); return createCachedBeaconState(state, { config, pubkey2index, index2pubkey: [], }, { skipSyncPubkeys: true, }); } /** * Get and regenerate a historical state */ export async function getHistoricalState(slot, config, db, pubkey2index, metrics) { const regenTimer = metrics?.regenTime.startTimer(); const loadStateTimer = metrics?.loadStateTime.startTimer(); let state = await getNearestState(slot, config, db, pubkey2index).catch((e) => { metrics?.regenErrorCount.inc({ reason: RegenErrorType.loadState }); throw e; }); loadStateTimer?.(); const transitionTimer = metrics?.stateTransitionTime.startTimer(); let blockCount = 0; for await (const block of db.blockArchive.valuesStream({ gt: state.slot, lte: slot })) { try { state = stateTransition(state, block, { verifyProposer: false, verifySignatures: false, verifyStateRoot: false, executionPayloadStatus: ExecutionPayloadStatus.valid, dataAvailabilityStatus: DataAvailabilityStatus.Available, }, { metrics }); } catch (e) { metrics?.regenErrorCount.inc({ reason: RegenErrorType.blockProcessing }); throw e; } blockCount++; if (Buffer.compare(state.hashTreeRoot(), block.message.stateRoot) !== 0) { metrics?.regenErrorCount.inc({ reason: RegenErrorType.invalidStateRoot }); } } metrics?.stateTransitionBlocks.observe(blockCount); transitionTimer?.(); if (state.slot !== slot) { throw Error(`Failed to generate historical state for slot ${slot}`); } const serializeTimer = metrics?.stateSerializationTime.startTimer(); const stateBytes = state.serialize(); serializeTimer?.(); regenTimer?.(); return stateBytes; } //# sourceMappingURL=getHistoricalState.js.map