@lodestar/beacon-node
Version:
A Typescript implementation of the beacon chain
61 lines • 2.96 kB
JavaScript
import { GENESIS_EPOCH, GENESIS_SLOT, isForkPostDeneb } from "@lodestar/params";
import { RespStatus, ResponseError } from "@lodestar/reqresp";
import { computeEpochAtSlot, computeStartSlotAtEpoch } from "@lodestar/state-transition";
import { toRootHex } from "@lodestar/utils";
import { getParentRootFromSignedBeaconBlockSerialized } from "../../../util/sszBytes.js";
import { prettyPrintPeerId } from "../../util.js";
// See https://github.com/ethereum/consensus-specs/pull/5181
export async function* onBeaconBlocksByHead(request, chain, peerId, peerClient) {
const currentFork = chain.config.getForkName(chain.clock.currentSlot);
const { beaconRoot, count } = validateBeaconBlocksByHeadRequest(currentFork, chain.config, request);
const requestedRootHex = toRootHex(beaconRoot);
let blockRootHex = requestedRootHex;
const minimumRequestEpoch = Math.max(GENESIS_EPOCH, chain.clock.currentEpoch - chain.config.MIN_EPOCHS_FOR_BLOCK_REQUESTS);
const minimumRequestSlot = computeStartSlotAtEpoch(minimumRequestEpoch);
for (let blocksSent = 0; blocksSent < count; blocksSent++) {
const blockBytes = await chain.getSerializedBlockByRoot(blockRootHex);
if (!blockBytes) {
if (blocksSent === 0) {
throw new ResponseError(RespStatus.RESOURCE_UNAVAILABLE, `Unknown block root ${requestedRootHex}`);
}
return;
}
if (blockBytes.slot < minimumRequestSlot) {
if (blocksSent === 0) {
chain.logger.verbose("Peer requested unavailable block for BeaconBlocksByHead", {
peer: prettyPrintPeerId(peerId),
client: peerClient,
requestedRoot: requestedRootHex,
slot: blockBytes.slot,
minimumRequestSlot,
});
}
return;
}
yield {
data: blockBytes.block,
boundary: chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(blockBytes.slot)),
};
if (blockBytes.slot === GENESIS_SLOT) {
return;
}
const parentRootHex = getParentRootFromSignedBeaconBlockSerialized(blockBytes.block);
if (parentRootHex === null) {
throw new ResponseError(RespStatus.SERVER_ERROR, `Invalid block bytes for root ${blockRootHex} slot ${blockBytes.slot}`);
}
blockRootHex = parentRootHex;
}
}
export function validateBeaconBlocksByHeadRequest(fork, config, request) {
const { beaconRoot } = request;
let { count } = request;
if (count < 1) {
throw new ResponseError(RespStatus.INVALID_REQUEST, "count < 1");
}
const maxRequestBlocks = isForkPostDeneb(fork) ? config.MAX_REQUEST_BLOCKS_DENEB : config.MAX_REQUEST_BLOCKS;
if (count > maxRequestBlocks) {
count = maxRequestBlocks;
}
return { beaconRoot, count };
}
//# sourceMappingURL=beaconBlocksByHead.js.map