{"version":3,"sources":["jsdelivr-header.js","/npm/libp2p-gossipsub@0.13.0/src/index.js"],"names":[],"mappings":"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","file":"/npm/libp2p-gossipsub@0.13.0/src/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.19.2.\n * Original file: /npm/libp2p-gossipsub@0.13.0/src/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n    if (k2 === undefined) k2 = k;\n    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\n}) : (function(o, m, k, k2) {\n    if (k2 === undefined) k2 = k;\n    o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n    Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n    o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n    if (mod && mod.__esModule) return mod;\n    var result = {};\n    if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n    __setModuleDefault(result, mod);\n    return result;\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nconst pubsub_1 = __importStar(require(\"libp2p-interfaces/src/pubsub\"));\nconst message_cache_1 = require(\"./message-cache\");\nconst rpc_1 = require(\"./message/rpc\");\nconst constants = __importStar(require(\"./constants\"));\nconst heartbeat_1 = require(\"./heartbeat\");\nconst get_gossip_peers_1 = require(\"./get-gossip-peers\");\nconst utils_1 = require(\"./utils\");\nconst score_1 = require(\"./score\");\nconst tracer_1 = require(\"./tracer\");\nconst time_cache_1 = require(\"./utils/time-cache\");\nconst PeerId = require(\"peer-id\");\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nconst Envelope = require(\"libp2p/src/record/envelope\");\nconst constants_1 = require(\"./constants\");\nclass Gossipsub extends pubsub_1.default {\n    // TODO: add remaining props\n    /**\n     * @param {Libp2p} libp2p\n     * @param {Object} [options]\n     * @param {boolean} [options.emitSelf = false] if publish should emit to self, if subscribed\n     * @param {boolean} [options.canRelayMessage = false] - if can relay messages not subscribed\n     * @param {boolean} [options.gossipIncoming = true] if incoming messages on a subscribed topic should be automatically gossiped\n     * @param {boolean} [options.fallbackToFloodsub = true] if dial should fallback to floodsub\n     * @param {boolean} [options.floodPublish = true] if self-published messages should be sent to all peers\n     * @param {boolean} [options.doPX = false] whether PX is enabled; this should be enabled in bootstrappers and other well connected/trusted nodes.\n     * @param {Object} [options.messageCache] override the default MessageCache\n     * @param {FastMsgIdFn} [options.fastMsgIdFn] fast message id function\n     * @param {string} [options.globalSignaturePolicy = \"StrictSign\"] signing policy to apply across all messages\n     * @param {Object} [options.scoreParams] peer score parameters\n     * @param {Object} [options.scoreThresholds] peer score thresholds\n     * @param {AddrInfo[]} [options.directPeers] peers with which we will maintain direct connections\n     * @constructor\n     */\n    constructor(libp2p, options = {}) {\n        var _a;\n        const multicodecs = [constants.GossipsubIDv11, constants.GossipsubIDv10];\n        const opts = Object.assign(Object.assign({ gossipIncoming: true, fallbackToFloodsub: true, floodPublish: true, doPX: false, directPeers: [], D: constants.GossipsubD, Dlo: constants.GossipsubDlo, Dhi: constants.GossipsubDhi, Dscore: constants.GossipsubDscore, Dout: constants.GossipsubDout, Dlazy: constants.GossipsubDlazy, heartbeatInterval: constants.GossipsubHeartbeatInterval, fanoutTTL: constants.GossipsubFanoutTTL, mcacheLength: constants.GossipsubHistoryLength, mcacheGossip: constants.GossipsubHistoryGossip, seenTTL: constants.GossipsubSeenTTL }, options), { scoreParams: score_1.createPeerScoreParams(options.scoreParams), scoreThresholds: score_1.createPeerScoreThresholds(options.scoreThresholds) });\n        // Also wants to get notified of peers connected using floodsub\n        if (opts.fallbackToFloodsub) {\n            multicodecs.push(constants.FloodsubID);\n        }\n        super(Object.assign({ debugName: 'libp2p:gossipsub', multicodecs,\n            libp2p }, opts));\n        this._options = opts;\n        /**\n         * Direct peers\n         * @type {Set<string>}\n         */\n        this.direct = new Set(opts.directPeers.map(p => p.id.toB58String()));\n        /**\n         * Map of peer id and AcceptRequestWhileListEntry\n         *\n         * @type {Map<string, AcceptFromWhitelistEntry}\n         */\n        this.acceptFromWhitelist = new Map();\n        // set direct peer addresses in the address book\n        opts.directPeers.forEach(p => {\n            libp2p.peerStore.addressBook.add(p.id, p.addrs);\n        });\n        /**\n         * Cache of seen messages\n         *\n         * @type {SimpleTimeCache}\n         */\n        this.seenCache = new time_cache_1.SimpleTimeCache({ validityMs: opts.seenTTL });\n        /**\n         * Map of topic meshes\n         * topic => peer id set\n         *\n         * @type {Map<string, Set<string>>}\n         */\n        this.mesh = new Map();\n        /**\n         * Map of topics to set of peers. These mesh peers are the ones to which we are publishing without a topic membership\n         * topic => peer id set\n         *\n         * @type {Map<string, Set<string>>}\n         */\n        this.fanout = new Map();\n        /**\n         * Map of last publish time for fanout topics\n         * topic => last publish time\n         *\n         * @type {Map<string, number>}\n         */\n        this.lastpub = new Map();\n        /**\n         * Map of pending messages to gossip\n         * peer id => control messages\n         *\n         * @type {Map<string, Array<RPC.IControlIHave object>> }\n         */\n        this.gossip = new Map();\n        /**\n         * Map of control messages\n         * peer id => control message\n         *\n         * @type {Map<string, RPC.IControlMessage object>}\n         */\n        this.control = new Map();\n        /**\n         * Number of IHAVEs received from peer in the last heartbeat\n         * @type {Map<string, number>}\n         */\n        this.peerhave = new Map();\n        /**\n         * Number of messages we have asked from peer in the last heartbeat\n         * @type {Map<string, number>}\n         */\n        this.iasked = new Map();\n        /**\n         * Prune backoff map\n         */\n        this.backoff = new Map();\n        /**\n         * Connection direction cache, marks peers with outbound connections\n         * peer id => direction\n         *\n         * @type {Map<string, boolean>}\n         */\n        this.outbound = new Map();\n        /**\n         * A message cache that contains the messages for last few hearbeat ticks\n         */\n        this.messageCache = options.messageCache || new message_cache_1.MessageCache(opts.mcacheGossip, opts.mcacheLength);\n        /**\n         * A fast message id function used for internal message de-duplication\n         */\n        this.getFastMsgIdStr = (_a = options.fastMsgIdFn) !== null && _a !== void 0 ? _a : undefined;\n        /**\n         * Maps fast message-id to canonical message-id\n         */\n        this.fastMsgIdCache = options.fastMsgIdFn ? new time_cache_1.SimpleTimeCache({ validityMs: opts.seenTTL }) : undefined;\n        /**\n         * A heartbeat timer that maintains the mesh\n         */\n        this.heartbeat = new heartbeat_1.Heartbeat(this);\n        /**\n         * Number of heartbeats since the beginning of time\n         * This allows us to amortize some resource cleanup -- eg: backoff cleanup\n         */\n        this.heartbeatTicks = 0;\n        /**\n         * Tracks IHAVE/IWANT promises broken by peers\n         */\n        this.gossipTracer = new tracer_1.IWantTracer();\n        /**\n         * libp2p\n         */\n        this._libp2p = libp2p;\n        /**\n         * Peer score tracking\n         */\n        this.score = new score_1.PeerScore(this._options.scoreParams, libp2p.connectionManager);\n    }\n    /**\n     * Decode a Uint8Array into an RPC object\n     * Overrided to use an extended protocol-specific protobuf decoder\n     * @override\n     * @param {Uint8Array} bytes\n     * @returns {RPC}\n     */\n    _decodeRpc(bytes) {\n        return rpc_1.RPC.decode(bytes);\n    }\n    /**\n     * Encode an RPC object into a Uint8Array\n     * Overrided to use an extended protocol-specific protobuf encoder\n     * @override\n     * @param {RPC} rpc\n     * @returns {Uint8Array}\n     */\n    _encodeRpc(rpc) {\n        return rpc_1.RPC.encode(rpc).finish();\n    }\n    /**\n     * Add a peer to the router\n     * @override\n     * @param {PeerId} peerId\n     * @param {string} protocol\n     * @returns {PeerStreams}\n     */\n    _addPeer(peerId, protocol) {\n        const p = super._addPeer(peerId, protocol);\n        // Add to peer scoring\n        this.score.addPeer(peerId.toB58String());\n        // track the connection direction\n        let outbound = false;\n        for (const c of this._libp2p.connectionManager.getAll(peerId)) {\n            if (c.stat.direction === 'outbound') {\n                if (Array.from(c.registry.values()).some(rvalue => protocol === rvalue.protocol)) {\n                    outbound = true;\n                    break;\n                }\n            }\n        }\n        this.outbound.set(p.id.toB58String(), outbound);\n        return p;\n    }\n    /**\n     * Removes a peer from the router\n     * @override\n     * @param {PeerId} peer\n     * @returns {PeerStreams | undefined}\n     */\n    _removePeer(peerId) {\n        const peerStreams = super._removePeer(peerId);\n        const id = peerId.toB58String();\n        // Remove this peer from the mesh\n        // eslint-disable-next-line no-unused-vars\n        for (const peers of this.mesh.values()) {\n            peers.delete(id);\n        }\n        // Remove this peer from the fanout\n        // eslint-disable-next-line no-unused-vars\n        for (const peers of this.fanout.values()) {\n            peers.delete(id);\n        }\n        // Remove from gossip mapping\n        this.gossip.delete(id);\n        // Remove from control mapping\n        this.control.delete(id);\n        // Remove from backoff mapping\n        this.outbound.delete(id);\n        // Remove from peer scoring\n        this.score.removePeer(id);\n        this.acceptFromWhitelist.delete(id);\n        return peerStreams;\n    }\n    /**\n     * Handles an rpc request from a peer\n     *\n     * @override\n     * @param {String} idB58Str\n     * @param {PeerStreams} peerStreams\n     * @param {RPC} rpc\n     * @returns {Promise<boolean>}\n     */\n    _processRpc(id, peerStreams, rpc) {\n        const _super = Object.create(null, {\n            _processRpc: { get: () => super._processRpc }\n        });\n        return __awaiter(this, void 0, void 0, function* () {\n            if (yield _super._processRpc.call(this, id, peerStreams, rpc)) {\n                if (rpc.control) {\n                    yield this._processRpcControlMessage(id, rpc.control);\n                }\n                return true;\n            }\n            return false;\n        });\n    }\n    /**\n     * Handles an rpc control message from a peer\n     * @param {string} id peer id\n     * @param {RPC.IControlMessage} controlMsg\n     * @returns {void}\n     */\n    _processRpcControlMessage(id, controlMsg) {\n        return __awaiter(this, void 0, void 0, function* () {\n            if (!controlMsg) {\n                return;\n            }\n            const iwant = controlMsg.ihave ? this._handleIHave(id, controlMsg.ihave) : [];\n            const ihave = controlMsg.iwant ? this._handleIWant(id, controlMsg.iwant) : [];\n            const prune = controlMsg.graft ? yield this._handleGraft(id, controlMsg.graft) : [];\n            controlMsg.prune && this._handlePrune(id, controlMsg.prune);\n            if (!iwant.length && !ihave.length && !prune.length) {\n                return;\n            }\n            const outRpc = utils_1.createGossipRpc(ihave, { iwant, prune });\n            this._sendRpc(id, outRpc);\n        });\n    }\n    /**\n     * Process incoming message,\n     * emitting locally and forwarding on to relevant floodsub and gossipsub peers\n     * @override\n     * @param {InMessage} msg\n     * @returns {Promise<void>}\n     */\n    _processRpcMessage(msg) {\n        const _super = Object.create(null, {\n            _processRpcMessage: { get: () => super._processRpcMessage }\n        });\n        return __awaiter(this, void 0, void 0, function* () {\n            let canonicalMsgIdStr;\n            if (this.getFastMsgIdStr && this.fastMsgIdCache) {\n                // check duplicate\n                const fastMsgIdStr = yield this.getFastMsgIdStr(msg);\n                canonicalMsgIdStr = this.fastMsgIdCache.get(fastMsgIdStr);\n                if (canonicalMsgIdStr !== undefined) {\n                    this.score.duplicateMessage(msg, canonicalMsgIdStr);\n                    return;\n                }\n                canonicalMsgIdStr = utils_1.messageIdToString(yield this.getMsgId(msg));\n                this.fastMsgIdCache.put(fastMsgIdStr, canonicalMsgIdStr);\n            }\n            else {\n                // check duplicate\n                canonicalMsgIdStr = utils_1.messageIdToString(yield this.getMsgId(msg));\n                if (this.seenCache.has(canonicalMsgIdStr)) {\n                    this.score.duplicateMessage(msg, canonicalMsgIdStr);\n                    return;\n                }\n            }\n            // put in cache\n            this.seenCache.put(canonicalMsgIdStr);\n            yield this.score.validateMessage(canonicalMsgIdStr);\n            yield _super._processRpcMessage.call(this, msg);\n        });\n    }\n    /**\n     * Whether to accept a message from a peer\n     * @override\n     * @param {string} id\n     * @returns {boolean}\n     */\n    _acceptFrom(id) {\n        if (this.direct.has(id)) {\n            return true;\n        }\n        const now = Date.now();\n        const entry = this.acceptFromWhitelist.get(id);\n        if (entry &&\n            entry.messagesAccepted < constants_1.ACCEPT_FROM_WHITELIST_MAX_MESSAGES &&\n            entry.acceptUntil >= now) {\n            entry.messagesAccepted += 1;\n            return true;\n        }\n        const score = this.score.score(id);\n        if (score >= constants_1.ACCEPT_FROM_WHITELIST_THRESHOLD_SCORE) {\n            // peer is unlikely to be able to drop its score to `graylistThreshold`\n            // after 128 messages or 1s\n            this.acceptFromWhitelist.set(id, {\n                messagesAccepted: 0,\n                acceptUntil: now + constants_1.ACCEPT_FROM_WHITELIST_DURATION_MS\n            });\n        }\n        else {\n            this.acceptFromWhitelist.delete(id);\n        }\n        return score >= this._options.scoreThresholds.graylistThreshold;\n    }\n    /**\n     * Validate incoming message\n     * @override\n     * @param {InMessage} msg\n     * @returns {Promise<void>}\n     */\n    validate(msg) {\n        const _super = Object.create(null, {\n            validate: { get: () => super.validate }\n        });\n        return __awaiter(this, void 0, void 0, function* () {\n            try {\n                yield _super.validate.call(this, msg);\n            }\n            catch (e) {\n                const canonicalMsgIdStr = yield this.getCanonicalMsgIdStr(msg);\n                this.score.rejectMessage(msg, canonicalMsgIdStr, e.code);\n                this.gossipTracer.rejectMessage(canonicalMsgIdStr, e.code);\n                throw e;\n            }\n        });\n    }\n    /**\n     * Handles IHAVE messages\n     * @param {string} id peer id\n     * @param {Array<RPC.IControlIHave>} ihave\n     * @returns {RPC.IControlIWant}\n     */\n    _handleIHave(id, ihave) {\n        if (!ihave.length) {\n            return [];\n        }\n        // we ignore IHAVE gossip from any peer whose score is below the gossips threshold\n        const score = this.score.score(id);\n        if (score < this._options.scoreThresholds.gossipThreshold) {\n            this.log('IHAVE: ignoring peer %s with score below threshold [ score = %d ]', id, score);\n            return [];\n        }\n        // IHAVE flood protection\n        const peerhave = (this.peerhave.get(id) || 0) + 1;\n        this.peerhave.set(id, peerhave);\n        if (peerhave > constants.GossipsubMaxIHaveMessages) {\n            this.log('IHAVE: peer %s has advertised too many times (%d) within this heartbeat interval; ignoring', id, peerhave);\n            return [];\n        }\n        const iasked = this.iasked.get(id) || 0;\n        if (iasked >= constants.GossipsubMaxIHaveLength) {\n            this.log('IHAVE: peer %s has already advertised too many messages (%d); ignoring', id, iasked);\n            return [];\n        }\n        // string msgId => msgId\n        const iwant = new Map();\n        ihave.forEach(({ topicID, messageIDs }) => {\n            if (!topicID || !messageIDs || !this.mesh.has(topicID)) {\n                return;\n            }\n            messageIDs.forEach((msgId) => {\n                const msgIdStr = utils_1.messageIdToString(msgId);\n                if (this.seenCache.has(msgIdStr)) {\n                    return;\n                }\n                iwant.set(msgIdStr, msgId);\n            });\n        });\n        if (!iwant.size) {\n            return [];\n        }\n        let iask = iwant.size;\n        if (iask + iasked > constants.GossipsubMaxIHaveLength) {\n            iask = constants.GossipsubMaxIHaveLength - iasked;\n        }\n        this.log('IHAVE: Asking for %d out of %d messages from %s', iask, iwant.size, id);\n        let iwantList = Array.from(iwant.values());\n        // ask in random order\n        utils_1.shuffle(iwantList);\n        // truncate to the messages we are actually asking for and update the iasked counter\n        iwantList = iwantList.slice(0, iask);\n        this.iasked.set(id, iasked + iask);\n        this.gossipTracer.addPromise(id, iwantList);\n        return [{\n                messageIDs: iwantList\n            }];\n    }\n    /**\n     * Handles IWANT messages\n     * Returns messages to send back to peer\n     * @param {string} id peer id\n     * @param {Array<RPC.IControlIWant>} iwant\n     * @returns {Array<RPC.IMessage>}\n     */\n    _handleIWant(id, iwant) {\n        if (!iwant.length) {\n            return [];\n        }\n        // we don't respond to IWANT requests from any per whose score is below the gossip threshold\n        const score = this.score.score(id);\n        if (score < this._options.scoreThresholds.gossipThreshold) {\n            this.log('IWANT: ignoring peer %s with score below threshold [score = %d]', id, score);\n            return [];\n        }\n        // @type {Map<string, Message>}\n        const ihave = new Map();\n        iwant.forEach(({ messageIDs }) => {\n            messageIDs && messageIDs.forEach((msgId) => {\n                const msgIdStr = utils_1.messageIdToString(msgId);\n                const [msg, count] = this.messageCache.getForPeer(msgIdStr, id);\n                if (!msg) {\n                    return;\n                }\n                if (count > constants.GossipsubGossipRetransmission) {\n                    this.log('IWANT: Peer %s has asked for message %s too many times: ignoring request', id, msgId);\n                    return;\n                }\n                ihave.set(msgIdStr, msg);\n            });\n        });\n        if (!ihave.size) {\n            return [];\n        }\n        this.log('IWANT: Sending %d messages to %s', ihave.size, id);\n        return Array.from(ihave.values()).map(pubsub_1.utils.normalizeOutRpcMessage);\n    }\n    /**\n     * Handles Graft messages\n     * @param {string} id peer id\n     * @param {Array<RPC.IControlGraft>} graft\n     * @return {Promise<RPC.IControlPrune[]>}\n     */\n    _handleGraft(id, graft) {\n        return __awaiter(this, void 0, void 0, function* () {\n            const prune = [];\n            const score = this.score.score(id);\n            const now = this._now();\n            let doPX = this._options.doPX;\n            graft.forEach(({ topicID }) => {\n                var _a;\n                if (!topicID) {\n                    return;\n                }\n                const peersInMesh = this.mesh.get(topicID);\n                if (!peersInMesh) {\n                    // don't do PX when there is an unknown topic to avoid leaking our peers\n                    doPX = false;\n                    // spam hardening: ignore GRAFTs for unknown topics\n                    return;\n                }\n                // check if peer is already in the mesh; if so do nothing\n                if (peersInMesh.has(id)) {\n                    return;\n                }\n                // we don't GRAFT to/from direct peers; complain loudly if this happens\n                if (this.direct.has(id)) {\n                    this.log('GRAFT: ignoring request from direct peer %s', id);\n                    // this is possibly a bug from a non-reciprical configuration; send a PRUNE\n                    prune.push(topicID);\n                    // but don't px\n                    doPX = false;\n                    return;\n                }\n                // make sure we are not backing off that peer\n                const expire = (_a = this.backoff.get(topicID)) === null || _a === void 0 ? void 0 : _a.get(id);\n                if (typeof expire === 'number' && now < expire) {\n                    this.log('GRAFT: ignoring backed off peer %s', id);\n                    // add behavioral penalty\n                    this.score.addPenalty(id, 1);\n                    // no PX\n                    doPX = false;\n                    // check the flood cutoff -- is the GRAFT coming too fast?\n                    const floodCutoff = expire + constants.GossipsubGraftFloodThreshold - constants.GossipsubPruneBackoff;\n                    if (now < floodCutoff) {\n                        // extra penalty\n                        this.score.addPenalty(id, 1);\n                    }\n                    // refresh the backoff\n                    this._addBackoff(id, topicID);\n                    prune.push(topicID);\n                    return;\n                }\n                // check the score\n                if (score < 0) {\n                    // we don't GRAFT peers with negative score\n                    this.log('GRAFT: ignoring peer %s with negative score: score=%d, topic=%s', id, score, topicID);\n                    // we do send them PRUNE however, because it's a matter of protocol correctness\n                    prune.push(topicID);\n                    // but we won't PX to them\n                    doPX = false;\n                    // add/refresh backoff so that we don't reGRAFT too early even if the score decays\n                    this._addBackoff(id, topicID);\n                    return;\n                }\n                // check the number of mesh peers; if it is at (or over) Dhi, we only accept grafts\n                // from peers with outbound connections; this is a defensive check to restrict potential\n                // mesh takeover attacks combined with love bombing\n                if (peersInMesh.size >= this._options.Dhi && !this.outbound.get(id)) {\n                    prune.push(topicID);\n                    this._addBackoff(id, topicID);\n                    return;\n                }\n                this.log('GRAFT: Add mesh link from %s in %s', id, topicID);\n                this.score.graft(id, topicID);\n                peersInMesh.add(id);\n            });\n            if (!prune.length) {\n                return [];\n            }\n            return Promise.all(prune.map(topic => this._makePrune(id, topic, doPX)));\n        });\n    }\n    /**\n     * Handles Prune messages\n     * @param {string} id peer id\n     * @param {Array<RPC.IControlPrune>} prune\n     * @returns {void}\n     */\n    _handlePrune(id, prune) {\n        const score = this.score.score(id);\n        prune.forEach(({ topicID, backoff, peers }) => {\n            if (!topicID) {\n                return;\n            }\n            const peersInMesh = this.mesh.get(topicID);\n            if (!peersInMesh) {\n                return;\n            }\n            this.log('PRUNE: Remove mesh link to %s in %s', id, topicID);\n            this.score.prune(id, topicID);\n            peersInMesh.delete(id);\n            // is there a backoff specified by the peer? if so obey it\n            if (typeof backoff === 'number' && backoff > 0) {\n                this._doAddBackoff(id, topicID, backoff * 1000);\n            }\n            else {\n                this._addBackoff(id, topicID);\n            }\n            // PX\n            if (peers && peers.length) {\n                // we ignore PX from peers with insufficient scores\n                if (score < this._options.scoreThresholds.acceptPXThreshold) {\n                    this.log('PRUNE: ignoring PX from peer %s with insufficient score [score = %d, topic = %s]', id, score, topicID);\n                    return;\n                }\n                this._pxConnect(peers);\n            }\n        });\n    }\n    /**\n     * Add standard backoff log for a peer in a topic\n     * @param {string} id\n     * @param {string} topic\n     * @returns {void}\n     */\n    _addBackoff(id, topic) {\n        this._doAddBackoff(id, topic, constants.GossipsubPruneBackoff);\n    }\n    /**\n     * Add backoff expiry interval for a peer in a topic\n     * @param {string} id\n     * @param {string} topic\n     * @param {number} interval backoff duration in milliseconds\n     * @returns {void}\n     */\n    _doAddBackoff(id, topic, interval) {\n        let backoff = this.backoff.get(topic);\n        if (!backoff) {\n            backoff = new Map();\n            this.backoff.set(topic, backoff);\n        }\n        const expire = this._now() + interval;\n        const existingExpire = backoff.get(id) || 0;\n        if (existingExpire < expire) {\n            backoff.set(id, expire);\n        }\n    }\n    /**\n     * Apply penalties from broken IHAVE/IWANT promises\n     * @returns {void}\n     */\n    _applyIwantPenalties() {\n        this.gossipTracer.getBrokenPromises().forEach((count, p) => {\n            this.log('peer %s didn\\'t follow up in %d IWANT requests; adding penalty', p, count);\n            this.score.addPenalty(p, count);\n        });\n    }\n    /**\n     * Clear expired backoff expiries\n     * @returns {void}\n     */\n    _clearBackoff() {\n        // we only clear once every GossipsubPruneBackoffTicks ticks to avoid iterating over the maps too much\n        if (this.heartbeatTicks % constants.GossipsubPruneBackoffTicks !== 0) {\n            return;\n        }\n        const now = this._now();\n        this.backoff.forEach((backoff, topic) => {\n            backoff.forEach((expire, id) => {\n                if (expire < now) {\n                    backoff.delete(id);\n                }\n            });\n            if (backoff.size === 0) {\n                this.backoff.delete(topic);\n            }\n        });\n    }\n    /**\n     * Maybe reconnect to direct peers\n     * @returns {void}\n     */\n    _directConnect() {\n        // we only do this every few ticks to allow pending connections to complete and account for\n        // restarts/downtime\n        if (this.heartbeatTicks % constants.GossipsubDirectConnectTicks !== 0) {\n            return;\n        }\n        const toconnect = [];\n        this.direct.forEach(id => {\n            const peer = this.peers.get(id);\n            if (!peer || !peer.isWritable) {\n                toconnect.push(id);\n            }\n        });\n        if (toconnect.length) {\n            toconnect.forEach(id => {\n                this._connect(id);\n            });\n        }\n    }\n    /**\n     * Maybe attempt connection given signed peer records\n     * @param {RPC.IPeerInfo[]} peers\n     * @returns {Promise<void>}\n     */\n    _pxConnect(peers) {\n        return __awaiter(this, void 0, void 0, function* () {\n            if (peers.length > constants.GossipsubPrunePeers) {\n                utils_1.shuffle(peers);\n                peers = peers.slice(0, constants.GossipsubPrunePeers);\n            }\n            const toconnect = [];\n            yield Promise.all(peers.map((pi) => __awaiter(this, void 0, void 0, function* () {\n                if (!pi.peerID) {\n                    return;\n                }\n                const p = PeerId.createFromBytes(pi.peerID);\n                const id = p.toB58String();\n                if (this.peers.has(id)) {\n                    return;\n                }\n                if (!pi.signedPeerRecord) {\n                    toconnect.push(id);\n                    return;\n                }\n                // The peer sent us a signed record\n                // This is not a record from the peer who sent the record, but another peer who is connected with it\n                // Ensure that it is valid\n                try {\n                    const envelope = yield Envelope.openAndCertify(pi.signedPeerRecord, 'libp2p-peer-record');\n                    const eid = envelope.peerId.toB58String();\n                    if (id !== eid) {\n                        this.log('bogus peer record obtained through px: peer ID %s doesn\\'t match expected peer %s', eid, id);\n                        return;\n                    }\n                    if (!this._libp2p.peerStore.addressBook.consumePeerRecord(envelope)) {\n                        this.log('bogus peer record obtained through px: could not add peer record to address book');\n                        return;\n                    }\n                    toconnect.push(id);\n                }\n                catch (e) {\n                    this.log('bogus peer record obtained through px: invalid signature or not a peer record');\n                }\n            })));\n            if (!toconnect.length) {\n                return;\n            }\n            toconnect.forEach(id => this._connect(id));\n        });\n    }\n    /**\n     * Mounts the gossipsub protocol onto the libp2p node and sends our\n     * our subscriptions to every peer connected\n     * @override\n     * @returns {Promise<void>}\n     */\n    start() {\n        const _super = Object.create(null, {\n            start: { get: () => super.start }\n        });\n        return __awaiter(this, void 0, void 0, function* () {\n            yield _super.start.call(this);\n            this.heartbeat.start();\n            this.score.start();\n            // connect to direct peers\n            this._directPeerInitial = setTimeout(() => {\n                this.direct.forEach(id => {\n                    this._connect(id);\n                });\n            }, constants.GossipsubDirectConnectInitialDelay);\n        });\n    }\n    /**\n     * Unmounts the gossipsub protocol and shuts down every connection\n     * @override\n     * @returns {Promise<void>}\n     */\n    stop() {\n        const _super = Object.create(null, {\n            stop: { get: () => super.stop }\n        });\n        return __awaiter(this, void 0, void 0, function* () {\n            yield _super.stop.call(this);\n            this.heartbeat.stop();\n            this.score.stop();\n            this.mesh = new Map();\n            this.fanout = new Map();\n            this.lastpub = new Map();\n            this.gossip = new Map();\n            this.control = new Map();\n            this.peerhave = new Map();\n            this.iasked = new Map();\n            this.backoff = new Map();\n            this.outbound = new Map();\n            this.gossipTracer.clear();\n            this.seenCache.clear();\n            if (this.fastMsgIdCache)\n                this.fastMsgIdCache.clear();\n            clearTimeout(this._directPeerInitial);\n        });\n    }\n    /**\n     * Connect to a peer using the gossipsub protocol\n     * @param {string} id\n     * @returns {void}\n     */\n    _connect(id) {\n        this.log('Initiating connection with %s', id);\n        this._libp2p.dialProtocol(PeerId.createFromB58String(id), this.multicodecs);\n    }\n    /**\n     * Subscribes to a topic\n     * @override\n     * @param {string} topic\n     * @returns {void}\n     */\n    subscribe(topic) {\n        super.subscribe(topic);\n        this.join(topic);\n    }\n    /**\n     * Unsubscribe to a topic\n     * @override\n     * @param {string} topic\n     * @returns {void}\n     */\n    unsubscribe(topic) {\n        super.unsubscribe(topic);\n        this.leave(topic);\n    }\n    /**\n     * Join topic\n     * @param {string} topic\n     * @returns {void}\n     */\n    join(topic) {\n        if (!this.started) {\n            throw new Error('Gossipsub has not started');\n        }\n        this.log('JOIN %s', topic);\n        const fanoutPeers = this.fanout.get(topic);\n        if (fanoutPeers) {\n            // these peers have a score above the publish threshold, which may be negative\n            // so drop the ones with a negative score\n            fanoutPeers.forEach(id => {\n                if (this.score.score(id) < 0) {\n                    fanoutPeers.delete(id);\n                }\n            });\n            if (fanoutPeers.size < this._options.D) {\n                // we need more peers; eager, as this would get fixed in the next heartbeat\n                get_gossip_peers_1.getGossipPeers(this, topic, this._options.D - fanoutPeers.size, (id) => {\n                    // filter our current peers, direct peers, and peers with negative scores\n                    return !fanoutPeers.has(id) && !this.direct.has(id) && this.score.score(id) >= 0;\n                }).forEach(id => fanoutPeers.add(id));\n            }\n            this.mesh.set(topic, fanoutPeers);\n            this.fanout.delete(topic);\n            this.lastpub.delete(topic);\n        }\n        else {\n            const peers = get_gossip_peers_1.getGossipPeers(this, topic, this._options.D, (id) => {\n                // filter direct peers and peers with negative score\n                return !this.direct.has(id) && this.score.score(id) >= 0;\n            });\n            this.mesh.set(topic, peers);\n        }\n        this.mesh.get(topic).forEach((id) => {\n            this.log('JOIN: Add mesh link to %s in %s', id, topic);\n            this._sendGraft(id, topic);\n        });\n    }\n    /**\n     * Leave topic\n     * @param {string} topic\n     * @returns {void}\n     */\n    leave(topic) {\n        if (!this.started) {\n            throw new Error('Gossipsub has not started');\n        }\n        this.log('LEAVE %s', topic);\n        // Send PRUNE to mesh peers\n        const meshPeers = this.mesh.get(topic);\n        if (meshPeers) {\n            meshPeers.forEach((id) => {\n                this.log('LEAVE: Remove mesh link to %s in %s', id, topic);\n                this._sendPrune(id, topic);\n            });\n            this.mesh.delete(topic);\n        }\n    }\n    /**\n     * Return the canonical message-id of a message as a string\n     *\n     * If a fast message-id is set: Try 1. the application cache 2. the fast cache 3. `getMsgId()`\n     * If a fast message-id is NOT set: Just `getMsgId()`\n     * @param {InMessage} msg\n     * @returns {Promise<string>}\n     */\n    getCanonicalMsgIdStr(msg) {\n        var _a, _b;\n        return __awaiter(this, void 0, void 0, function* () {\n            return (this.fastMsgIdCache && this.getFastMsgIdStr)\n                ? (_b = (_a = this.getCachedMsgIdStr(msg)) !== null && _a !== void 0 ? _a : this.fastMsgIdCache.get(this.getFastMsgIdStr(msg))) !== null && _b !== void 0 ? _b : utils_1.messageIdToString(yield this.getMsgId(msg)) : utils_1.messageIdToString(yield this.getMsgId(msg));\n        });\n    }\n    /**\n     * An application should override this function to return its cached message id string without computing it.\n     * Return undefined if message id is not found.\n     * If a fast message id function is not defined, this function is ignored.\n     * @param {InMessage} msg\n     * @returns {string | undefined}\n     */\n    getCachedMsgIdStr(msg) {\n        return undefined;\n    }\n    /**\n     * Publish messages\n     *\n     * @override\n     * @param {InMessage} msg\n     * @returns {void}\n     */\n    _publish(msg) {\n        return __awaiter(this, void 0, void 0, function* () {\n            const msgIdStr = yield this.getCanonicalMsgIdStr(msg);\n            if (msg.receivedFrom !== this.peerId.toB58String()) {\n                this.score.deliverMessage(msg, msgIdStr);\n                this.gossipTracer.deliverMessage(msgIdStr);\n            }\n            // put in seen cache\n            this.seenCache.put(msgIdStr);\n            this.messageCache.put(msg, msgIdStr);\n            const tosend = new Set();\n            msg.topicIDs.forEach((topic) => {\n                const peersInTopic = this.topics.get(topic);\n                if (!peersInTopic) {\n                    return;\n                }\n                if (this._options.floodPublish && msg.from === this.peerId.toB58String()) {\n                    // flood-publish behavior\n                    // send to direct peers and _all_ peers meeting the publishThreshold\n                    peersInTopic.forEach(id => {\n                        if (this.direct.has(id) || this.score.score(id) >= this._options.scoreThresholds.publishThreshold) {\n                            tosend.add(id);\n                        }\n                    });\n                }\n                else {\n                    // non-flood-publish behavior\n                    // send to direct peers, subscribed floodsub peers\n                    // and some mesh peers above publishThreshold\n                    // direct peers\n                    this.direct.forEach(id => {\n                        tosend.add(id);\n                    });\n                    // floodsub peers\n                    peersInTopic.forEach((id) => {\n                        const score = this.score.score(id);\n                        const peerStreams = this.peers.get(id);\n                        if (!peerStreams) {\n                            return;\n                        }\n                        if (peerStreams.protocol === constants.FloodsubID && score >= this._options.scoreThresholds.publishThreshold) {\n                            tosend.add(id);\n                        }\n                    });\n                    // Gossipsub peers handling\n                    let meshPeers = this.mesh.get(topic);\n                    if (!meshPeers || !meshPeers.size) {\n                        // We are not in the mesh for topic, use fanout peers\n                        meshPeers = this.fanout.get(topic);\n                        if (!meshPeers) {\n                            // If we are not in the fanout, then pick peers in topic above the publishThreshold\n                            const peers = get_gossip_peers_1.getGossipPeers(this, topic, this._options.D, id => {\n                                return this.score.score(id) >= this._options.scoreThresholds.publishThreshold;\n                            });\n                            if (peers.size > 0) {\n                                meshPeers = peers;\n                                this.fanout.set(topic, peers);\n                            }\n                            else {\n                                meshPeers = new Set();\n                            }\n                        }\n                        // Store the latest publishing time\n                        this.lastpub.set(topic, this._now());\n                    }\n                    meshPeers.forEach((peer) => {\n                        tosend.add(peer);\n                    });\n                }\n            });\n            // Publish messages to peers\n            const rpc = utils_1.createGossipRpc([\n                pubsub_1.utils.normalizeOutRpcMessage(msg)\n            ]);\n            tosend.forEach((id) => {\n                if (id === msg.from) {\n                    return;\n                }\n                this._sendRpc(id, rpc);\n            });\n        });\n    }\n    /**\n     * Sends a GRAFT message to a peer\n     * @param {string} id peer id\n     * @param {string} topic\n     * @returns {void}\n     */\n    _sendGraft(id, topic) {\n        const graft = [{\n                topicID: topic\n            }];\n        const out = utils_1.createGossipRpc([], { graft });\n        this._sendRpc(id, out);\n    }\n    /**\n     * Sends a PRUNE message to a peer\n     * @param {string} id peer id\n     * @param {string} topic\n     * @returns {Promise<void>}\n     */\n    _sendPrune(id, topic) {\n        return __awaiter(this, void 0, void 0, function* () {\n            const prune = [\n                yield this._makePrune(id, topic, this._options.doPX)\n            ];\n            const out = utils_1.createGossipRpc([], { prune });\n            this._sendRpc(id, out);\n        });\n    }\n    /**\n     * @override\n     */\n    _sendRpc(id, outRpc) {\n        const peerStreams = this.peers.get(id);\n        if (!peerStreams || !peerStreams.isWritable) {\n            return;\n        }\n        // piggyback control message retries\n        const ctrl = this.control.get(id);\n        if (ctrl) {\n            this._piggybackControl(id, outRpc, ctrl);\n            this.control.delete(id);\n        }\n        // piggyback gossip\n        const ihave = this.gossip.get(id);\n        if (ihave) {\n            this._piggybackGossip(id, outRpc, ihave);\n            this.gossip.delete(id);\n        }\n        peerStreams.write(rpc_1.RPC.encode(outRpc).finish());\n    }\n    _piggybackControl(id, outRpc, ctrl) {\n        const tograft = (ctrl.graft || [])\n            .filter(({ topicID }) => (topicID && this.mesh.get(topicID) || new Set()).has(id));\n        const toprune = (ctrl.prune || [])\n            .filter(({ topicID }) => !(topicID && this.mesh.get(topicID) || new Set()).has(id));\n        if (!tograft.length && !toprune.length) {\n            return;\n        }\n        if (outRpc.control) {\n            outRpc.control.graft = outRpc.control.graft && outRpc.control.graft.concat(tograft);\n            outRpc.control.prune = outRpc.control.prune && outRpc.control.prune.concat(toprune);\n        }\n        else {\n            outRpc.control = { ihave: [], iwant: [], graft: tograft, prune: toprune };\n        }\n    }\n    _piggybackGossip(id, outRpc, ihave) {\n        if (!outRpc.control) {\n            outRpc.control = { ihave: [], iwant: [], graft: [], prune: [] };\n        }\n        outRpc.control.ihave = ihave;\n    }\n    /**\n     * Send graft and prune messages\n     * @param {Map<string, Array<string>>} tograft peer id => topic[]\n     * @param {Map<string, Array<string>>} toprune peer id => topic[]\n     */\n    _sendGraftPrune(tograft, toprune, noPX) {\n        return __awaiter(this, void 0, void 0, function* () {\n            const doPX = this._options.doPX;\n            for (const [id, topics] of tograft) {\n                const graft = topics.map((topicID) => ({ topicID }));\n                let prune = [];\n                // If a peer also has prunes, process them now\n                const pruning = toprune.get(id);\n                if (pruning) {\n                    prune = yield Promise.all(pruning.map((topicID) => this._makePrune(id, topicID, doPX && !noPX.get(id))));\n                    toprune.delete(id);\n                }\n                const outRpc = utils_1.createGossipRpc([], { graft, prune });\n                this._sendRpc(id, outRpc);\n            }\n            for (const [id, topics] of toprune) {\n                const prune = yield Promise.all(topics.map((topicID) => this._makePrune(id, topicID, doPX && !noPX.get(id))));\n                const outRpc = utils_1.createGossipRpc([], { prune });\n                this._sendRpc(id, outRpc);\n            }\n        });\n    }\n    /**\n     * Emits gossip to peers in a particular topic\n     * @param {string} topic\n     * @param {Set<string>} exclude peers to exclude\n     * @returns {void}\n     */\n    _emitGossip(topic, exclude) {\n        const messageIDs = this.messageCache.getGossipIDs(topic);\n        if (!messageIDs.length) {\n            return;\n        }\n        // shuffle to emit in random order\n        utils_1.shuffle(messageIDs);\n        // if we are emitting more than GossipsubMaxIHaveLength ids, truncate the list\n        if (messageIDs.length > constants.GossipsubMaxIHaveLength) {\n            // we do the truncation (with shuffling) per peer below\n            this.log('too many messages for gossip; will truncate IHAVE list (%d messages)', messageIDs.length);\n        }\n        // Send gossip to GossipFactor peers above threshold with a minimum of D_lazy\n        // First we collect the peers above gossipThreshold that are not in the exclude set\n        // and then randomly select from that set\n        // We also exclude direct peers, as there is no reason to emit gossip to them\n        const peersToGossip = [];\n        const topicPeers = this.topics.get(topic);\n        if (!topicPeers) {\n            // no topic peers, no gossip\n            return;\n        }\n        topicPeers.forEach(id => {\n            const peerStreams = this.peers.get(id);\n            if (!peerStreams) {\n                return;\n            }\n            if (!exclude.has(id) &&\n                !this.direct.has(id) &&\n                utils_1.hasGossipProtocol(peerStreams.protocol) &&\n                this.score.score(id) >= this._options.scoreThresholds.gossipThreshold) {\n                peersToGossip.push(id);\n            }\n        });\n        let target = this._options.Dlazy;\n        const factor = constants.GossipsubGossipFactor * peersToGossip.length;\n        if (factor > target) {\n            target = factor;\n        }\n        if (target > peersToGossip.length) {\n            target = peersToGossip.length;\n        }\n        else {\n            utils_1.shuffle(peersToGossip);\n        }\n        // Emit the IHAVE gossip to the selected peers up to the target\n        peersToGossip.slice(0, target).forEach(id => {\n            let peerMessageIDs = messageIDs;\n            if (messageIDs.length > constants.GossipsubMaxIHaveLength) {\n                // shuffle and slice message IDs per peer so that we emit a different set for each peer\n                // we have enough reduncancy in the system that this will significantly increase the message\n                // coverage when we do truncate\n                peerMessageIDs = utils_1.shuffle(peerMessageIDs.slice()).slice(0, constants.GossipsubMaxIHaveLength);\n            }\n            this._pushGossip(id, {\n                topicID: topic,\n                messageIDs: peerMessageIDs\n            });\n        });\n    }\n    /**\n     * Flush gossip and control messages\n     */\n    _flush() {\n        // send gossip first, which will also piggyback control\n        for (const [peer, ihave] of this.gossip.entries()) {\n            this.gossip.delete(peer);\n            const out = utils_1.createGossipRpc([], { ihave });\n            this._sendRpc(peer, out);\n        }\n        // send the remaining control messages\n        for (const [peer, control] of this.control.entries()) {\n            this.control.delete(peer);\n            const out = utils_1.createGossipRpc([], { graft: control.graft, prune: control.prune });\n            this._sendRpc(peer, out);\n        }\n    }\n    /**\n     * Adds new IHAVE messages to pending gossip\n     * @param {PeerStreams} peerStreams\n     * @param {Array<RPC.IControlIHave>} controlIHaveMsgs\n     * @returns {void}\n     */\n    _pushGossip(id, controlIHaveMsgs) {\n        this.log('Add gossip to %s', id);\n        const gossip = this.gossip.get(id) || [];\n        this.gossip.set(id, gossip.concat(controlIHaveMsgs));\n    }\n    /**\n     * Returns the current time in milliseconds\n     * @returns {number}\n     */\n    _now() {\n        return Date.now();\n    }\n    /**\n     * Make a PRUNE control message for a peer in a topic\n     * @param {string} id\n     * @param {string} topic\n     * @param {boolean} doPX\n     * @returns {Promise<RPC.IControlPrune>}\n     */\n    _makePrune(id, topic, doPX) {\n        return __awaiter(this, void 0, void 0, function* () {\n            if (this.peers.get(id).protocol === constants.GossipsubIDv10) {\n                // Gossipsub v1.0 -- no backoff, the peer won't be able to parse it anyway\n                return {\n                    topicID: topic,\n                    peers: []\n                };\n            }\n            // backoff is measured in seconds\n            // GossipsubPruneBackoff is measured in milliseconds\n            const backoff = constants.GossipsubPruneBackoff / 1000;\n            if (!doPX) {\n                return {\n                    topicID: topic,\n                    peers: [],\n                    backoff: backoff\n                };\n            }\n            // select peers for Peer eXchange\n            const peers = get_gossip_peers_1.getGossipPeers(this, topic, constants.GossipsubPrunePeers, (xid) => {\n                return xid !== id && this.score.score(xid) >= 0;\n            });\n            const px = yield Promise.all(Array.from(peers).map((p) => __awaiter(this, void 0, void 0, function* () {\n                // see if we have a signed record to send back; if we don't, just send\n                // the peer ID and let the pruned peer find them in the DHT -- we can't trust\n                // unsigned address records through PX anyways\n                // Finding signed records in the DHT is not supported at the time of writing in js-libp2p\n                const peerId = PeerId.createFromB58String(p);\n                return {\n                    peerID: peerId.toBytes(),\n                    signedPeerRecord: yield this._libp2p.peerStore.addressBook.getRawEnvelope(peerId)\n                };\n            })));\n            return {\n                topicID: topic,\n                peers: px,\n                backoff: backoff\n            };\n        });\n    }\n}\nGossipsub.multicodec = constants.GossipsubIDv11;\nmodule.exports = Gossipsub;\n"]}