/// <reference types="node" />
import Pubsub, { InMessage } from 'libp2p-interfaces/src/pubsub';
import { MessageCache } from './message-cache';
import { RPC, IRPC } from './message/rpc';
import { Heartbeat } from './heartbeat';
import { PeerScore, PeerScoreParams, PeerScoreThresholds } from './score';
import { IWantTracer } from './tracer';
import { AddrInfo, MessageIdFunction } from './interfaces';
import { SimpleTimeCache } from './utils/time-cache';
import { Debugger } from 'debug';
import Libp2p from 'libp2p';
import PeerStreams from 'libp2p-interfaces/src/pubsub/peer-streams';
import PeerId = require('peer-id');
interface GossipInputOptions {
    emitSelf: boolean;
    canRelayMessage: boolean;
    gossipIncoming: boolean;
    fallbackToFloodsub: boolean;
    floodPublish: boolean;
    doPX: boolean;
    msgIdFn: MessageIdFunction;
    fastMsgIdFn: FastMsgIdFn;
    messageCache: MessageCache;
    globalSignaturePolicy: 'StrictSign' | 'StrictNoSign' | undefined;
    scoreParams: Partial<PeerScoreParams>;
    scoreThresholds: Partial<PeerScoreThresholds>;
    directPeers: AddrInfo[];
    /**
     * D sets the optimal degree for a Gossipsub topic mesh.
     */
    D: number;
    /**
     * Dlo sets the lower bound on the number of peers we keep in a Gossipsub topic mesh.
     */
    Dlo: number;
    /**
     * Dhi sets the upper bound on the number of peers we keep in a Gossipsub topic mesh.
     */
    Dhi: number;
    /**
     * Dscore affects how peers are selected when pruning a mesh due to over subscription.
     */
    Dscore: number;
    /**
     * Dout sets the quota for the number of outbound connections to maintain in a topic mesh.
     */
    Dout: number;
    /**
     * Dlazy affects how many peers we will emit gossip to at each heartbeat.
     */
    Dlazy: number;
    /**
     * heartbeatInterval is the time between heartbeats in milliseconds
     */
    heartbeatInterval: number;
    /**
     * fanoutTTL controls how long we keep track of the fanout state. If it's been
     * fanoutTTL milliseconds since we've published to a topic that we're not subscribed to,
     * we'll delete the fanout map for that topic.
     */
    fanoutTTL: number;
    /**
     * mcacheLength is the number of windows to retain full messages for IWANT responses
     */
    mcacheLength: number;
    /**
     * mcacheGossip is the number of windows to gossip about
     */
    mcacheGossip: number;
    /**
     * seenTTL is the number of milliseconds to retain message IDs in the seen cache
     */
    seenTTL: number;
}
interface GossipOptions extends GossipInputOptions {
    scoreParams: PeerScoreParams;
    scoreThresholds: PeerScoreThresholds;
}
interface AcceptFromWhitelistEntry {
    /** number of messages accepted since recomputing the peer's score */
    messagesAccepted: number;
    /** have to recompute score after this time */
    acceptUntil: number;
}
declare type FastMsgIdFn = (msg: InMessage) => string;
declare class Gossipsub extends Pubsub {
    peers: Map<string, PeerStreams>;
    direct: Set<string>;
    seenCache: SimpleTimeCache<void>;
    acceptFromWhitelist: Map<string, AcceptFromWhitelistEntry>;
    topics: Map<string, Set<string>>;
    mesh: Map<string, Set<string>>;
    fanout: Map<string, Set<string>>;
    lastpub: Map<string, number>;
    gossip: Map<string, RPC.IControlIHave[]>;
    control: Map<string, RPC.IControlMessage>;
    peerhave: Map<string, number>;
    iasked: Map<string, number>;
    backoff: Map<string, Map<string, number>>;
    outbound: Map<string, boolean>;
    defaultMsgIdFn: MessageIdFunction;
    getFastMsgIdStr: FastMsgIdFn | undefined;
    fastMsgIdCache: SimpleTimeCache<string> | undefined;
    messageCache: MessageCache;
    score: PeerScore;
    heartbeat: Heartbeat;
    heartbeatTicks: number;
    gossipTracer: IWantTracer;
    multicodecs: string[];
    started: boolean;
    peerId: PeerId;
    subscriptions: Set<string>;
    _libp2p: Libp2p;
    _options: GossipOptions;
    _directPeerInitial: NodeJS.Timeout;
    log: Debugger & {
        err: Debugger;
    };
    emit: (event: string | symbol, ...args: any[]) => boolean;
    static multicodec: string;
    /**
     * @param {Libp2p} libp2p
     * @param {Object} [options]
     * @param {boolean} [options.emitSelf = false] if publish should emit to self, if subscribed
     * @param {boolean} [options.canRelayMessage = false] - if can relay messages not subscribed
     * @param {boolean} [options.gossipIncoming = true] if incoming messages on a subscribed topic should be automatically gossiped
     * @param {boolean} [options.fallbackToFloodsub = true] if dial should fallback to floodsub
     * @param {boolean} [options.floodPublish = true] if self-published messages should be sent to all peers
     * @param {boolean} [options.doPX = false] whether PX is enabled; this should be enabled in bootstrappers and other well connected/trusted nodes.
     * @param {Object} [options.messageCache] override the default MessageCache
     * @param {FastMsgIdFn} [options.fastMsgIdFn] fast message id function
     * @param {string} [options.globalSignaturePolicy = "StrictSign"] signing policy to apply across all messages
     * @param {Object} [options.scoreParams] peer score parameters
     * @param {Object} [options.scoreThresholds] peer score thresholds
     * @param {AddrInfo[]} [options.directPeers] peers with which we will maintain direct connections
     * @constructor
     */
    constructor(libp2p: Libp2p, options?: Partial<GossipInputOptions>);
    /**
     * Decode a Uint8Array into an RPC object
     * Overrided to use an extended protocol-specific protobuf decoder
     * @override
     * @param {Uint8Array} bytes
     * @returns {RPC}
     */
    _decodeRpc(bytes: Uint8Array): RPC;
    /**
     * Encode an RPC object into a Uint8Array
     * Overrided to use an extended protocol-specific protobuf encoder
     * @override
     * @param {RPC} rpc
     * @returns {Uint8Array}
     */
    _encodeRpc(rpc: RPC): Uint8Array;
    /**
     * Add a peer to the router
     * @override
     * @param {PeerId} peerId
     * @param {string} protocol
     * @returns {PeerStreams}
     */
    _addPeer(peerId: PeerId, protocol: string): PeerStreams;
    /**
     * Removes a peer from the router
     * @override
     * @param {PeerId} peer
     * @returns {PeerStreams | undefined}
     */
    _removePeer(peerId: PeerId): PeerStreams | undefined;
    /**
     * Handles an rpc request from a peer
     *
     * @override
     * @param {String} idB58Str
     * @param {PeerStreams} peerStreams
     * @param {RPC} rpc
     * @returns {Promise<boolean>}
     */
    _processRpc(id: string, peerStreams: PeerStreams, rpc: RPC): Promise<boolean>;
    /**
     * Handles an rpc control message from a peer
     * @param {string} id peer id
     * @param {RPC.IControlMessage} controlMsg
     * @returns {void}
     */
    _processRpcControlMessage(id: string, controlMsg: RPC.IControlMessage): Promise<void>;
    /**
     * Process incoming message,
     * emitting locally and forwarding on to relevant floodsub and gossipsub peers
     * @override
     * @param {InMessage} msg
     * @returns {Promise<void>}
     */
    _processRpcMessage(msg: InMessage): Promise<void>;
    /**
     * Whether to accept a message from a peer
     * @override
     * @param {string} id
     * @returns {boolean}
     */
    _acceptFrom(id: string): boolean;
    /**
     * Validate incoming message
     * @override
     * @param {InMessage} msg
     * @returns {Promise<void>}
     */
    validate(msg: InMessage): Promise<void>;
    /**
     * Handles IHAVE messages
     * @param {string} id peer id
     * @param {Array<RPC.IControlIHave>} ihave
     * @returns {RPC.IControlIWant}
     */
    _handleIHave(id: string, ihave: RPC.IControlIHave[]): RPC.IControlIWant[];
    /**
     * Handles IWANT messages
     * Returns messages to send back to peer
     * @param {string} id peer id
     * @param {Array<RPC.IControlIWant>} iwant
     * @returns {Array<RPC.IMessage>}
     */
    _handleIWant(id: string, iwant: RPC.IControlIWant[]): RPC.IMessage[];
    /**
     * Handles Graft messages
     * @param {string} id peer id
     * @param {Array<RPC.IControlGraft>} graft
     * @return {Promise<RPC.IControlPrune[]>}
     */
    _handleGraft(id: string, graft: RPC.IControlGraft[]): Promise<RPC.IControlPrune[]>;
    /**
     * Handles Prune messages
     * @param {string} id peer id
     * @param {Array<RPC.IControlPrune>} prune
     * @returns {void}
     */
    _handlePrune(id: string, prune: RPC.IControlPrune[]): void;
    /**
     * Add standard backoff log for a peer in a topic
     * @param {string} id
     * @param {string} topic
     * @returns {void}
     */
    _addBackoff(id: string, topic: string): void;
    /**
     * Add backoff expiry interval for a peer in a topic
     * @param {string} id
     * @param {string} topic
     * @param {number} interval backoff duration in milliseconds
     * @returns {void}
     */
    _doAddBackoff(id: string, topic: string, interval: number): void;
    /**
     * Apply penalties from broken IHAVE/IWANT promises
     * @returns {void}
     */
    _applyIwantPenalties(): void;
    /**
     * Clear expired backoff expiries
     * @returns {void}
     */
    _clearBackoff(): void;
    /**
     * Maybe reconnect to direct peers
     * @returns {void}
     */
    _directConnect(): void;
    /**
     * Maybe attempt connection given signed peer records
     * @param {RPC.IPeerInfo[]} peers
     * @returns {Promise<void>}
     */
    _pxConnect(peers: RPC.IPeerInfo[]): Promise<void>;
    /**
     * Mounts the gossipsub protocol onto the libp2p node and sends our
     * our subscriptions to every peer connected
     * @override
     * @returns {Promise<void>}
     */
    start(): Promise<void>;
    /**
     * Unmounts the gossipsub protocol and shuts down every connection
     * @override
     * @returns {Promise<void>}
     */
    stop(): Promise<void>;
    /**
     * Connect to a peer using the gossipsub protocol
     * @param {string} id
     * @returns {void}
     */
    _connect(id: string): void;
    /**
     * Subscribes to a topic
     * @override
     * @param {string} topic
     * @returns {void}
     */
    subscribe(topic: string): void;
    /**
     * Unsubscribe to a topic
     * @override
     * @param {string} topic
     * @returns {void}
     */
    unsubscribe(topic: string): void;
    /**
     * Join topic
     * @param {string} topic
     * @returns {void}
     */
    join(topic: string): void;
    /**
     * Leave topic
     * @param {string} topic
     * @returns {void}
     */
    leave(topic: string): void;
    /**
     * Return the canonical message-id of a message as a string
     *
     * If a fast message-id is set: Try 1. the application cache 2. the fast cache 3. `getMsgId()`
     * If a fast message-id is NOT set: Just `getMsgId()`
     * @param {InMessage} msg
     * @returns {Promise<string>}
     */
    getCanonicalMsgIdStr(msg: InMessage): Promise<string>;
    /**
     * An application should override this function to return its cached message id string without computing it.
     * Return undefined if message id is not found.
     * If a fast message id function is not defined, this function is ignored.
     * @param {InMessage} msg
     * @returns {string | undefined}
     */
    getCachedMsgIdStr(msg: InMessage): string | undefined;
    /**
     * Publish messages
     *
     * @override
     * @param {InMessage} msg
     * @returns {void}
     */
    _publish(msg: InMessage): Promise<void>;
    /**
     * Sends a GRAFT message to a peer
     * @param {string} id peer id
     * @param {string} topic
     * @returns {void}
     */
    _sendGraft(id: string, topic: string): void;
    /**
     * Sends a PRUNE message to a peer
     * @param {string} id peer id
     * @param {string} topic
     * @returns {Promise<void>}
     */
    _sendPrune(id: string, topic: string): Promise<void>;
    /**
     * @override
     */
    _sendRpc(id: string, outRpc: IRPC): void;
    _piggybackControl(id: string, outRpc: IRPC, ctrl: RPC.IControlMessage): void;
    _piggybackGossip(id: string, outRpc: IRPC, ihave: RPC.IControlIHave[]): void;
    /**
     * Send graft and prune messages
     * @param {Map<string, Array<string>>} tograft peer id => topic[]
     * @param {Map<string, Array<string>>} toprune peer id => topic[]
     */
    _sendGraftPrune(tograft: Map<string, string[]>, toprune: Map<string, string[]>, noPX: Map<string, boolean>): Promise<void>;
    /**
     * Emits gossip to peers in a particular topic
     * @param {string} topic
     * @param {Set<string>} exclude peers to exclude
     * @returns {void}
     */
    _emitGossip(topic: string, exclude: Set<string>): void;
    /**
     * Flush gossip and control messages
     */
    _flush(): void;
    /**
     * Adds new IHAVE messages to pending gossip
     * @param {PeerStreams} peerStreams
     * @param {Array<RPC.IControlIHave>} controlIHaveMsgs
     * @returns {void}
     */
    _pushGossip(id: string, controlIHaveMsgs: RPC.IControlIHave): void;
    /**
     * Returns the current time in milliseconds
     * @returns {number}
     */
    _now(): number;
    /**
     * Make a PRUNE control message for a peer in a topic
     * @param {string} id
     * @param {string} topic
     * @param {boolean} doPX
     * @returns {Promise<RPC.IControlPrune>}
     */
    _makePrune(id: string, topic: string, doPX: boolean): Promise<RPC.IControlPrune>;
}
export = Gossipsub;
