@lodestar/prover
Version:
A Typescript implementation of the Ethereum Consensus light client
79 lines • 3.31 kB
JavaScript
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