import { BeaconStateAllForks, EpochShuffling, IShufflingCache, ShufflingBuildProps } from "@lodestar/state-transition";
import { Epoch, RootHex } from "@lodestar/types";
import { LodestarError, Logger } from "@lodestar/utils";
import { Metrics } from "../metrics/metrics.js";
export type ShufflingCacheOpts = {
    maxShufflingCacheEpochs?: number;
};
/**
 * A shuffling cache to help:
 * - get committee quickly for attestation verification
 * - if a shuffling is not available (which does not happen with default chain option of maxSkipSlots = 32), track a promise to make sure we don't compute the same shuffling twice
 * - skip computing shuffling when loading state bytes from disk
 */
export declare class ShufflingCache implements IShufflingCache {
    readonly metrics: Metrics | null;
    readonly logger: Logger | null;
    /** LRU cache implemented as a map, pruned every time we add an item */
    private readonly itemsByDecisionRootByEpoch;
    private readonly maxEpochs;
    constructor(metrics?: Metrics | null, logger?: Logger | null, opts?: ShufflingCacheOpts, precalculatedShufflings?: {
        shuffling: EpochShuffling | null;
        decisionRoot: RootHex;
    }[]);
    /**
     * Insert a promise to make sure we don't regen state for the same shuffling.
     * Bound by MAX_SHUFFLING_PROMISE to make sure our node does not blow up.
     */
    insertPromise(epoch: Epoch, decisionRoot: RootHex): void;
    /**
     * Most of the time, this should return a shuffling immediately.
     * If there's a promise, it means we are computing the same shuffling, so we wait for the promise to resolve.
     * Return null if we don't have a shuffling for this epoch and dependentRootHex.
     */
    get(epoch: Epoch, decisionRoot: RootHex): Promise<EpochShuffling | null>;
    /**
     * Gets a cached shuffling via the epoch and decision root.  If the shuffling is not
     * available it will build it synchronously and return the shuffling.
     *
     * NOTE: If a shuffling is already queued and not calculated it will build and resolve
     * the promise but the already queued build will happen at some later time
     */
    getSync<T extends ShufflingBuildProps | undefined>(epoch: Epoch, decisionRoot: RootHex, buildProps?: T): T extends ShufflingBuildProps ? EpochShuffling : EpochShuffling | null;
    /**
     * Queue asynchronous build for an EpochShuffling, triggered from state-transition
     */
    build(epoch: number, decisionRoot: string, state: BeaconStateAllForks, activeIndices: Uint32Array): void;
    /**
     * Add an EpochShuffling to the ShufflingCache. If a promise for the shuffling is present it will
     * resolve the promise with the built shuffling
     */
    private set;
}
export declare enum ShufflingCacheErrorCode {
    NO_SHUFFLING_FOUND = "SHUFFLING_CACHE_ERROR_NO_SHUFFLING_FOUND"
}
type ShufflingCacheErrorType = {
    code: ShufflingCacheErrorCode.NO_SHUFFLING_FOUND;
    epoch: Epoch;
    decisionRoot: RootHex;
};
export declare class ShufflingCacheError extends LodestarError<ShufflingCacheErrorType> {
}
export {};
//# sourceMappingURL=shufflingCache.d.ts.map