import type { MessageStreamDirection, PeerId } from "@libp2p/interface";
import { ChainConfig } from "@lodestar/config";
import { CustodyIndex, Status, SubnetID, altair, phase0 } from "@lodestar/types";
import { NetworkCoreMetrics } from "../../core/metrics.js";
import { RequestedSubnet } from "./subnetMap.js";
type SubnetDiscvQuery = {
    subnet: SubnetID;
    toSlot: number;
    maxPeersToDiscover: number;
};
/**
 * A map of das custody group index to maxPeersToDiscover
 */
export type CustodyGroupQueries = Map<CustodyIndex, number>;
/**
 * Comparison of our status vs a peer's status.
 *
 * The main usage of this score is to feed into peer priorization during syncing, and especially when the node is having trouble finding data during syncing
 *
 * For network stability, we DON'T distinguish peers that are far behind us vs peers that are close to us.
 */
declare enum StatusScore {
    /** The peer is close to our chain */
    CLOSE_TO_US = -1,
    /** The peer is far ahead of chain */
    FAR_AHEAD = 0
}
type PeerInfo = {
    id: PeerId;
    direction: MessageStreamDirection | null;
    statusScore: StatusScore;
    attnets: phase0.AttestationSubnets;
    syncnets: altair.SyncSubnets;
    samplingGroups: CustodyIndex[];
    attnetsTrueBitIndices: number[];
    syncnetsTrueBitIndices: number[];
    score: number;
};
export type PrioritizePeersOpts = {
    targetPeers: number;
    maxPeers: number;
    targetGroupPeers: number;
    status: Status;
    starved: boolean;
    starvationPruneRatio: number;
    starvationThresholdSlots: number;
    outboundPeersRatio?: number;
    targetSubnetPeers?: number;
};
export declare enum ExcessPeerDisconnectReason {
    LOW_SCORE = "low_score",
    NO_LONG_LIVED_SUBNET = "no_long_lived_subnet",
    TOO_GROUPED_SUBNET = "too_grouped_subnet",
    FIND_BETTER_PEERS = "find_better_peers"
}
/**
 * Prioritize which peers to disconect and which to connect. Conditions:
 * - Reach `targetPeers`
 *   - If we're starved for data, prune additional peers
 * - Don't exceed `maxPeers`
 * - Ensure there are enough peers per column subnets, attestation subnets and sync committee subnets
 * - Prioritize peers with good score
 *
 * pre-fulu samplingGroups is not used and this function returns empty custodyGroupQueries
 */
export declare function prioritizePeers(connectedPeersInfo: {
    id: PeerId;
    direction: MessageStreamDirection | null;
    status: Status | null;
    attnets: phase0.AttestationSubnets | null;
    syncnets: altair.SyncSubnets | null;
    samplingGroups: CustodyIndex[] | null;
    score: number;
}[], activeAttnets: RequestedSubnet[], activeSyncnets: RequestedSubnet[], samplingGroups: CustodyIndex[] | undefined, opts: PrioritizePeersOpts, config: ChainConfig, metrics: NetworkCoreMetrics | null): {
    peersToConnect: number;
    peersToDisconnect: Map<ExcessPeerDisconnectReason, PeerId[]>;
    attnetQueries: SubnetDiscvQuery[];
    syncnetQueries: SubnetDiscvQuery[];
    custodyGroupQueries: CustodyGroupQueries;
};
/**
 * Sort peers ascending, peer-0 has the most chance to prune, peer-n has the least.
 * Shuffling first to break ties.
 * prefer sorting by status score (applicable during syncing), then dutied subnets, then number of long lived subnets, then peer score
 * peer score is the last criteria since they are supposed to be in the same score range,
 * bad score peers are removed by peer manager anyway
 */
export declare function sortPeersToPrune(connectedPeers: PeerInfo[], dutiesByPeer: Map<PeerInfo, number>): PeerInfo[];
export {};
//# sourceMappingURL=prioritizePeers.d.ts.map