import { BLOB_SIDECAR_FIXED_SIZE } from "@lodestar/params";
import { RespStatus, ResponseError } from "@lodestar/reqresp";
import { computeEpochAtSlot } from "@lodestar/state-transition";
import { toRootHex } from "@lodestar/utils";
export async function* onBlobSidecarsByRoot(requestBody, chain) {
    const finalizedSlot = chain.forkChoice.getFinalizedBlock().slot;
    // In sidecars by root request, it can be expected that sidecar requests will be come
    // clustured by blockroots, and this helps us save db lookups once we load sidecars
    // for a root
    let lastFetchedSideCars = null;
    for (const blobIdentifier of requestBody) {
        const { blockRoot, index } = blobIdentifier;
        const blockRootHex = toRootHex(blockRoot);
        const block = chain.forkChoice.getBlockHexDefaultStatus(blockRootHex);
        // NOTE: Only support non-finalized blocks.
        // SPEC: Clients MUST support requesting blocks and sidecars since the latest finalized epoch.
        // https://github.com/ethereum/consensus-specs/blob/11a037fd9227e29ee809c9397b09f8cc3383a8c0/specs/eip4844/p2p-interface.md#beaconblockandblobssidecarbyroot-v1
        if (!block || block.slot <= finalizedSlot) {
            continue;
        }
        // Check if we need to load sidecars for a new block root
        if (lastFetchedSideCars === null || lastFetchedSideCars.blockRoot !== blockRootHex) {
            const blobSidecarsBytes = await chain.getSerializedBlobSidecars(block.slot, blockRootHex);
            if (!blobSidecarsBytes) {
                // Handle the same to onBeaconBlocksByRange
                throw new ResponseError(RespStatus.SERVER_ERROR, `No item for root ${block.blockRoot} slot ${block.slot}`);
            }
            lastFetchedSideCars = { blockRoot: blockRootHex, bytes: blobSidecarsBytes };
        }
        const blobSidecarBytes = lastFetchedSideCars.bytes.slice(index * BLOB_SIDECAR_FIXED_SIZE, (index + 1) * BLOB_SIDECAR_FIXED_SIZE);
        if (blobSidecarBytes.length !== BLOB_SIDECAR_FIXED_SIZE) {
            throw Error(`Inconsistent state, blobSidecar blockRoot=${blockRootHex} index=${index} blobSidecarBytes=${blobSidecarBytes.length} expected=${BLOB_SIDECAR_FIXED_SIZE}`);
        }
        yield {
            data: blobSidecarBytes,
            boundary: chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(block.slot)),
        };
    }
}
//# sourceMappingURL=blobSidecarsByRoot.js.map