UNPKG

@lodestar/prover

Version:

A Typescript implementation of the Ethereum Consensus light client

79 lines 3.31 kB
import { MAX_PAYLOAD_HISTORY } from "../constants.js"; import { hexToBuffer } from "./conversion.js"; export async function fetchBlock(api, slot) { const res = await api.beacon.getBlockV2({ blockId: slot }); if (res.ok) return res.value(); return; } export async function fetchNearestBlock(api, slot, direction = "down") { const res = await api.beacon.getBlockV2({ blockId: slot }); if (res.ok) return res.value(); if (!res.ok && res.status === 404) { return fetchNearestBlock(api, direction === "down" ? slot - 1 : slot + 1); } throw new Error(`Can not fetch nearest block for slot=${slot}`); } export async function getUnFinalizedRangeForPayloads(lightClient) { const headSlot = lightClient.getHead().beacon.slot; const finalizeSlot = lightClient.getFinalized().beacon.slot; const endSlot = headSlot - MAX_PAYLOAD_HISTORY; return { start: headSlot, end: endSlot < finalizeSlot ? finalizeSlot : endSlot, }; } export async function getExecutionPayloads({ api, startSlot, endSlot, logger, }) { [startSlot, endSlot] = [Math.min(startSlot, endSlot), Math.max(startSlot, endSlot)]; if (startSlot === endSlot) { logger.debug("Fetching EL payload", { slot: startSlot }); } else { logger.debug("Fetching EL payloads", { startSlot, endSlot }); } const payloads = new Map(); let slot = endSlot; let block = await fetchNearestBlock(api, slot); payloads.set(block.message.slot, block.message.body.executionPayload); slot = block.message.slot - 1; while (slot >= startSlot) { const previousBlock = await fetchNearestBlock(api, block.message.slot - 1); if (block.message.body.executionPayload.parentHash === previousBlock.message.body.executionPayload.blockHash) { payloads.set(block.message.slot, block.message.body.executionPayload); } slot = block.message.slot - 1; block = previousBlock; } return payloads; } export async function getExecutionPayloadForBlockNumber(api, startSlot, blockNumber) { const payloads = new Map(); let block = await fetchNearestBlock(api, startSlot); payloads.set(block.message.slot, block.message.body.executionPayload); while (payloads.get(block.message.slot)?.blockNumber !== blockNumber) { const previousBlock = await fetchNearestBlock(api, block.message.slot - 1); block = previousBlock; payloads.set(block.message.slot, block.message.body.executionPayload); } return payloads; } export async function getGenesisData(api) { const { genesisTime, genesisValidatorsRoot } = (await api.beacon.getGenesis()).value(); return { genesisTime, genesisValidatorsRoot, }; } export async function getSyncCheckpoint(api, checkpoint) { let syncCheckpoint = checkpoint ? hexToBuffer(checkpoint) : undefined; if (syncCheckpoint && syncCheckpoint.byteLength !== 32) { throw Error(`Checkpoint root must be 32 bytes. length=${syncCheckpoint.byteLength}`); } if (!syncCheckpoint) { const res = await api.beacon.getStateFinalityCheckpoints({ stateId: "head" }); syncCheckpoint = res.value().finalized.root; } return syncCheckpoint; } //# sourceMappingURL=consensus.js.map