import { ChainForkConfig } from "@lodestar/config";
import { ForkName } from "@lodestar/params";
import { Epoch, RootHex, Slot, gloas } from "@lodestar/types";
import { LodestarError } from "@lodestar/utils";
import { IBlockInput } from "../../chain/blocks/blockInput/types.js";
import { PayloadEnvelopeInput } from "../../chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js";
import { PeerSyncMeta } from "../../network/peers/peersData.js";
import { IClock } from "../../util/clock.js";
import { CustodyConfig } from "../../util/dataColumns.js";
import { PeerIdStr } from "../../util/peerId.js";
import { DownloadByRangeRequests, ParentPayloadCommitments } from "../utils/downloadByRange.js";
/**
 * Current state of a batch
 */
export declare enum BatchStatus {
    /** The batch has failed either downloading or processing, but can be requested again. */
    AwaitingDownload = "AwaitingDownload",
    /** The batch is being downloaded. */
    Downloading = "Downloading",
    /** The batch has been completely downloaded and is ready for processing. */
    AwaitingProcessing = "AwaitingProcessing",
    /** The batch is being processed. */
    Processing = "Processing",
    /**
     * The batch was successfully processed and is waiting to be validated.
     *
     * It is not sufficient to process a batch successfully to consider it correct. This is
     * because batches could be erroneously empty, or incomplete. Therefore, a batch is considered
     * valid, only if the next sequential batch imports at least a block.
     */
    AwaitingValidation = "AwaitingValidation"
}
export type Attempt = {
    /** The peer that made the attempt */
    peers: PeerIdStr[];
    /** The hash of the blocks of the attempt */
    hash: RootHex;
};
type TrackedRequest = {
    /** only happen for the 1st batch in checkpoint sync */
    parentPayload: boolean;
    /**
     * we always issue by_range before parent_payload, so we don't model this as null
     */
    byRangeColumns: Set<number>;
};
export type AwaitingDownloadState = {
    status: BatchStatus.AwaitingDownload;
    blocks: IBlockInput[];
    payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
};
export type DownloadSuccessState = {
    status: BatchStatus.AwaitingProcessing;
    blocks: IBlockInput[];
    payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
};
export type BatchState = AwaitingDownloadState | {
    status: BatchStatus.Downloading;
    peer: PeerIdStr;
    request: TrackedRequest;
    blocks: IBlockInput[];
    payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
} | DownloadSuccessState | {
    status: BatchStatus.Processing;
    blocks: IBlockInput[];
    payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
    attempt: Attempt;
} | {
    status: BatchStatus.AwaitingValidation;
    blocks: IBlockInput[];
    payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
    attempt: Attempt;
};
export type BatchMetadata = {
    startEpoch: Epoch;
    startSlot: Slot;
    count: number;
    status: BatchStatus;
    blocksReq?: string;
    blobsReq?: string;
    columnsReq?: string;
    envelopesReq?: string;
    downloadAttempts: number;
    processingAttempts: number;
    failedDownloadPeers?: string;
    failedProcessingPeers?: string;
};
/**
 * Batches are downloaded at the first block of the epoch.
 *
 * For example:
 *
 * Epoch boundary |                                   |
 *  ... | 30 | 31 | 32 | 33 | 34 | ... | 61 | 62 | 63 | 64 | 65 |
 *     Batch 1    |              Batch 2              |  Batch 3
 *
 * Jul2022: Offset changed from 1 to 0, see rationale in {@link BATCH_SLOT_OFFSET}
 */
export declare class Batch {
    readonly forkName: ForkName;
    readonly startEpoch: Epoch;
    readonly startSlot: Slot;
    readonly count: number;
    /** Block, blob and column requests that are used to determine the best peer and are used in downloadByRange */
    requests: DownloadByRangeRequests;
    /** State of the batch. */
    state: BatchState;
    /** Peers that provided good data, with column coverage for by_range requests */
    private readonly successfulDownloads;
    /** The `Attempts` that have been made and failed to send us this batch. */
    readonly failedProcessingAttempts: Attempt[];
    /** The `Attempts` that have been made and failed because of execution malfunction. */
    readonly executionErrorAttempts: Attempt[];
    /** The number of download retries this batch has undergone due to a failed request. */
    private readonly failedDownloadAttempts;
    private readonly config;
    private readonly clock;
    private readonly custodyConfig;
    private readonly isFirstBatchInChain;
    private readonly latestBid;
    constructor(startEpoch: Epoch, config: ChainForkConfig, clock: IClock, custodyConfig: CustodyConfig, isFirstBatchInChain: boolean, latestBid: gloas.ExecutionPayloadBid | undefined, targetSlot: Slot);
    private shouldDownloadParentEnvelope;
    getParentPayloadCommitments(parentBlockRoot: Uint8Array): ParentPayloadCommitments;
    /**
     * Builds ByRange requests for block, blobs and columns
     */
    private getRequests;
    /**
     * Post-fulu we should only get columns that peer has advertised
     */
    getRequestsForPeer(peer: PeerSyncMeta): DownloadByRangeRequests;
    /**
     * Gives a list of peers from which this batch has had a failed download or processing attempt.
     */
    getFailedPeers(): PeerIdStr[];
    /**
     * True only if the peer has already returned a successful response for the current request.
     * A by_range success may update `this.requests` to parent_payload, and the same peer is then
     * still eligible for the newly discovered parent payload data.
     * For by_range, a peer that previously succeeded with a superset of requested columns is skipped.
     */
    hasPeerSucceededCurrentRequest(peer: PeerSyncMeta): boolean;
    private getSuccessfulPeers;
    getMetadata(): BatchMetadata;
    getBlocks(): IBlockInput[];
    getPayloadEnvelopes(): Map<Slot, PayloadEnvelopeInput> | null;
    /**
     * AwaitingDownload -> Downloading
     */
    startDownloading(peer: PeerSyncMeta): void;
    /**
     * Downloading -> AwaitingProcessing
     */
    downloadingSuccess(peer: PeerIdStr, blocks: IBlockInput[], payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null): DownloadSuccessState;
    /**
     * Downloading -> AwaitingDownload
     */
    downloadingError(peer: PeerIdStr): void;
    /**
     * Downloading -> AwaitingDownload (without counting as a failed attempt).
     * Used when the peer rate-limited us — the request was never actually served.
     */
    downloadingRateLimited(): void;
    /**
     * AwaitingProcessing -> Processing
     */
    startProcessing(): {
        blocks: IBlockInput[];
        payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
        peers: PeerIdStr[];
    };
    /**
     * Processing -> AwaitingValidation
     */
    processingSuccess(): void;
    /**
     * Processing -> AwaitingDownload
     */
    processingError(err: Error): void;
    /**
     * AwaitingValidation -> AwaitingDownload
     */
    validationError(err: Error): void;
    /**
     * AwaitingValidation -> Done
     */
    validationSuccess(): Attempt;
    private onExecutionEngineError;
    private onProcessingError;
    /** Helper to construct typed BatchError. Stack traces are correct as the error is thrown above */
    private errorType;
    private wrongStatusErrorType;
}
export declare enum BatchErrorCode {
    WRONG_STATUS = "BATCH_ERROR_WRONG_STATUS",
    INVALID_COUNT = "BATCH_ERROR_INVALID_COUNT",
    MAX_DOWNLOAD_ATTEMPTS = "BATCH_ERROR_MAX_DOWNLOAD_ATTEMPTS",
    MAX_PROCESSING_ATTEMPTS = "BATCH_ERROR_MAX_PROCESSING_ATTEMPTS",
    MAX_EXECUTION_ENGINE_ERROR_ATTEMPTS = "MAX_EXECUTION_ENGINE_ERROR_ATTEMPTS"
}
type BatchErrorType = {
    code: BatchErrorCode.WRONG_STATUS;
    expectedStatus: BatchStatus;
} | {
    code: BatchErrorCode.INVALID_COUNT;
    count: number;
    expected: number;
} | {
    code: BatchErrorCode.MAX_DOWNLOAD_ATTEMPTS;
} | {
    code: BatchErrorCode.MAX_PROCESSING_ATTEMPTS;
} | {
    code: BatchErrorCode.MAX_EXECUTION_ENGINE_ERROR_ATTEMPTS;
};
type BatchErrorMetadata = {
    startEpoch: number;
    status: BatchStatus;
};
export declare class BatchError extends LodestarError<BatchErrorType & BatchErrorMetadata> {
}
export {};
//# sourceMappingURL=batch.d.ts.map