UNPKG

@lodestar/beacon-node

Version:

A Typescript implementation of the beacon chain

99 lines 3.86 kB
import { GENESIS_SLOT } from "@lodestar/params"; import { getValidatorStatus } from "@lodestar/types"; import { fromHex } from "@lodestar/utils"; import { ApiError, ValidationError } from "../../errors.js"; export function resolveStateId(forkChoice, stateId) { if (stateId === "head") { return forkChoice.getHead().stateRoot; } if (stateId === "genesis") { return GENESIS_SLOT; } if (stateId === "finalized") { return forkChoice.getFinalizedCheckpoint(); } if (stateId === "justified") { return forkChoice.getJustifiedCheckpoint(); } if (typeof stateId === "string" && stateId.startsWith("0x")) { return stateId; } // id must be slot const blockSlot = parseInt(String(stateId), 10); if (Number.isNaN(blockSlot) && Number.isNaN(blockSlot - 0)) { throw new ValidationError(`Invalid block id '${stateId}'`, "blockId"); } return blockSlot; } export async function getStateResponseWithRegen(chain, inStateId) { const stateId = resolveStateId(chain.forkChoice, inStateId); const res = typeof stateId === "string" ? await chain.getStateByStateRoot(stateId, { allowRegen: true }) : typeof stateId === "number" ? stateId > chain.clock.currentSlot ? null // Don't try to serve future slots : stateId >= chain.forkChoice.getFinalizedBlock().slot ? await chain.getStateBySlot(stateId, { allowRegen: true }) : await chain.getHistoricalStateBySlot(stateId) : await chain.getStateOrBytesByCheckpoint(stateId); if (!res) { throw new ApiError(404, `State not found for id '${inStateId}'`); } return res; } export function toValidatorResponse(index, validator, balance, currentEpoch) { return { index, status: getValidatorStatus(validator, currentEpoch), balance, validator, }; } export function filterStateValidatorsByStatus(statuses, state, pubkeyCache, currentEpoch) { const responses = []; const validators = state.getValidatorsByStatus(new Set(statuses), currentEpoch); for (const validator of validators) { const resp = getStateValidatorIndex(validator.pubkey, state, pubkeyCache); if (resp.valid) { responses.push(toValidatorResponse(resp.validatorIndex, validator, state.getBalance(resp.validatorIndex), currentEpoch)); } } return responses; } export function getStateValidatorIndex(id, state, pubkeyCache) { if (typeof id === "string") { // mutate `id` and fallthrough to below if (id.startsWith("0x")) { try { id = fromHex(id); } catch (_e) { return { valid: false, code: 400, reason: "Invalid pubkey hex encoding" }; } } else { id = Number(id); } } if (typeof id === "number") { const validatorIndex = id; // validator is invalid or added later than given stateId if (!Number.isSafeInteger(validatorIndex)) { return { valid: false, code: 400, reason: "Invalid validator index" }; } if (validatorIndex >= state.validatorCount) { return { valid: false, code: 404, reason: "Validator index from future state" }; } return { valid: true, validatorIndex }; } // typeof id === Uint8Array const validatorIndex = pubkeyCache.getIndex(id); if (validatorIndex === null) { return { valid: false, code: 404, reason: "Validator pubkey not found in state" }; } if (validatorIndex >= state.validatorCount) { return { valid: false, code: 404, reason: "Validator pubkey from future state" }; } return { valid: true, validatorIndex }; } //# sourceMappingURL=utils.js.map