@lodestar/beacon-node
Version:
A Typescript implementation of the beacon chain
76 lines • 2.96 kB
JavaScript
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