UNPKG

xud

Version:
227 lines (226 loc) 11.2 kB
/// <reference types="node" /> import { EventEmitter } from 'events'; import { DisconnectionReason, ReputationEvent, XuNetwork } from '../constants/enums'; import { Models } from '../db/DB'; import Logger from '../Logger'; import NodeKey from '../nodekey/NodeKey'; import { IncomingOrder, OrderInvalidation, OrderPortion, OutgoingOrder } from '../orderbook/types'; import { Packet } from './packets'; import * as packets from './packets/types'; import Peer, { PeerInfo } from './Peer'; import { Address, PoolConfig } from './types'; declare type NodeReputationInfo = { reputationScore: ReputationEvent; banned?: boolean; }; interface Pool { on(event: 'packet.order', listener: (order: IncomingOrder) => void): this; on(event: 'packet.getOrders', listener: (peer: Peer, reqId: string, pairIds: string[]) => void): this; on(event: 'packet.orderInvalidation', listener: (orderInvalidation: OrderInvalidation, peer: string) => void): this; on(event: 'peer.active', listener: (peerPubKey: string) => void): this; on(event: 'peer.close', listener: (peerPubKey?: string) => void): this; /** Adds a listener to be called when a peer's advertised but inactive pairs should be verified. */ on(event: 'peer.verifyPairs', listener: (peer: Peer) => void): this; /** Adds a listener to be called when a previously active pair is dropped by the peer or deactivated. */ on(event: 'peer.pairDropped', listener: (peerPubKey: string, pairId: string) => void): this; on(event: 'peer.nodeStateUpdate', listener: (peer: Peer) => void): this; on(event: 'packet.sanitySwapInit', listener: (packet: packets.SanitySwapInitPacket, peer: Peer) => void): this; on(event: 'packet.swapRequest', listener: (packet: packets.SwapRequestPacket, peer: Peer) => void): this; on(event: 'packet.swapAccepted', listener: (packet: packets.SwapAcceptedPacket, peer: Peer) => void): this; on(event: 'packet.swapFailed', listener: (packet: packets.SwapFailedPacket) => void): this; emit(event: 'packet.order', order: IncomingOrder): boolean; emit(event: 'packet.getOrders', peer: Peer, reqId: string, pairIds: string[]): boolean; emit(event: 'packet.orderInvalidation', orderInvalidation: OrderInvalidation, peer: string): boolean; emit(event: 'peer.active', peerPubKey: string): boolean; emit(event: 'peer.close', peerPubKey?: string): boolean; /** Notifies listeners that a peer's advertised but inactive pairs should be verified. */ emit(event: 'peer.verifyPairs', peer: Peer): boolean; /** Notifies listeners that a previously active pair was dropped by the peer or deactivated. */ emit(event: 'peer.pairDropped', peerPubKey: string, pairId: string): boolean; emit(event: 'peer.nodeStateUpdate', peer: Peer): boolean; emit(event: 'packet.sanitySwapInit', packet: packets.SanitySwapInitPacket, peer: Peer): boolean; emit(event: 'packet.swapRequest', packet: packets.SwapRequestPacket, peer: Peer): boolean; emit(event: 'packet.swapAccepted', packet: packets.SwapAcceptedPacket, peer: Peer): boolean; emit(event: 'packet.swapFailed', packet: packets.SwapFailedPacket): boolean; } /** * Represents a pool of peers that handles all p2p network activity. This tracks all active and * pending peers, optionally runs a server to listen for incoming connections, and is the primary * interface for other modules to interact with the p2p layer. */ declare class Pool extends EventEmitter { /** The version of xud we are using. */ version: string; /** Our node pub key. */ nodePubKey: string; /** Our alias. */ alias: string; /** The local handshake data to be sent to newly connected peers. */ private nodeState; /** A map of pub keys to nodes for which we have pending outgoing connections. */ private pendingOutboundPeers; /** A set of peers for which we have pending incoming connections. */ private pendingInboundPeers; /** A collection of known nodes on the XU network. */ private nodes; private loadingNodesPromise?; /** A collection of opened, active peers. */ private peers; private server?; private disconnecting; private connected; /** The port on which to listen for peer connections, undefined if this node is not listening. */ private listenPort?; /** Points to config comes during construction. */ private config; private strict; private repository; private network; private logger; private nodeKey; /** The minimum version of xud we accept for peers */ private minCompatibleVersion; constructor({ config, xuNetwork, logger, models, nodeKey, version, strict, minCompatibleVersion }: { config: PoolConfig; xuNetwork: XuNetwork; logger: Logger; models: Models; nodeKey: NodeKey; version: string; strict?: boolean; minCompatibleVersion?: string; }); get peerCount(): number; get addresses(): Address[]; getTokenIdentifier: (currency: string) => string | undefined; getNodePubKeyById: (nodeId: number) => string | undefined; getNodeId: (nodePubKey: string) => number | undefined; getNodeAlias: (nodePubKey: string) => string | undefined; /** * Initialize the Pool by connecting to known nodes and listening to incoming peer connections, if configured to do so. */ init: () => Promise<void>; private detectExternalIpAddress; /** * Updates our active trading pairs and sends a node state update packet to currently connected * peers to notify them of the change. */ updatePairs: (pairIds: string[]) => void; /** * Updates our connext public key and supported token addresses, then sends a node state update * packet to currently connected peers to notify them of the change. */ updateConnextState: (tokenAddresses: Map<string, string>, pubKey?: string | undefined) => void; /** * Updates our lnd pub key and chain identifier for a given currency and sends a node state * update packet to currently connected peers to notify them of the change. */ updateLndState: ({ currency, pubKey, chain, uris }: { currency: string; pubKey: string; chain?: string | undefined; uris?: string[] | undefined; }) => void; private sendNodeStateUpdate; disconnect: () => Promise<void>; private bindNodeList; private verifyReachability; /** * Iterate over a collection of nodes and attempt to connect to them. * If the node is banned, already connected, or has no listening addresses, then do nothing. * Additionally, if we're already trying to connect to a given node also do nothing. * @param nodes a collection of nodes with a `forEach` iterator to attempt to connect to * @param allowKnown whether to allow connecting to nodes we are already aware of, defaults to true * @param retryConnecting whether to attempt retry connecting, defaults to false * @returns a promise that will resolve when all outbound connections resolve */ private connectNodes; /** * Attempt to create an outbound connection to a node using its known listening addresses. */ private tryConnectNode; private tryConnectWithLastAddress; private tryConnectWithAdvertisedAddresses; /** * Gets the active XU network as specified by the configuration. * * @returns the active XU network */ getNetwork: () => XuNetwork; /** * Gets a node's reputation score and whether it is banned * @param nodePubKey The node pub key of the node for which to get reputation information * @return true if the specified node exists and the event was added, false otherwise */ getNodeReputation: (nodePubKey: string) => Promise<NodeReputationInfo>; /** * Attempt to add an outbound peer by connecting to a given socket address and nodePubKey. * Throws an error if a socket connection to or the handshake with the node fails for any reason. * @param address the socket address of the node to connect to * @param nodePubKey the nodePubKey of the node to connect to * @returns a promise that resolves to the connected and opened peer */ addOutbound: (address: Address, nodePubKey: string, retryConnecting: boolean, revokeConnectionRetries: boolean) => Promise<Peer>; listPeers: () => PeerInfo[]; rawPeers: () => Map<string, Peer>; private addressIsSelf; private tryOpenPeer; /** * Opens a connection to a peer and performs a routine for newly opened peers that includes * requesting open orders and updating the database with the peer's information. * @returns a promise that resolves once the connection has opened and the newly opened peer * routine is complete */ private openPeer; private handleOpenedPeer; closePeer: (nodePubKey: string, reason?: DisconnectionReason | undefined, reasonPayload?: string | undefined) => Promise<void>; banNode: (nodePubKey: string) => Promise<void>; unbanNode: (nodePubKey: string, reconnect: boolean) => Promise<void>; discoverNodes: (peerPubKey: string) => Promise<number>; addReputationEvent: (nodePubKey: string, event: ReputationEvent) => Promise<void>; sendToPeer: (nodePubKey: string, packet: Packet) => Promise<void>; /** * Gets a peer by its node pub key or alias. Throws a [[NOT_CONNECTED]] error if the supplied identifier does not * match any currently connected peer. */ getPeer: (peerPubKey: string) => Peer; tryGetPeer: (peerPubKey: string) => Peer | undefined; broadcastOrder: (order: OutgoingOrder) => void; /** * Broadcasts an [[OrderInvalidationPacket]] to all currently connected peers. * @param nodeToExclude the node pub key of a node to exclude from the packet broadcast */ broadcastOrderInvalidation: ({ id, pairId, quantity }: OrderPortion, nodeToExclude?: string | undefined) => void; private addInbound; private handleSocket; private handlePacket; /** Validates a peer. If a check fails, closes the peer and throws a p2p error. */ private validatePeer; /** * Responds to a [[GetNodesPacket]] by populating and sending a [[NodesPacket]]. */ private handleGetNodes; private bindServer; private bindPeer; private handlePeerClose; private closePeers; private closePendingConnections; /** * Starts listening for incoming p2p connections on the configured host and port. If `this.listenPort` is 0 or undefined, * a random available port is used and will be assigned to `this.listenPort`. * @return a promise that resolves once the server is listening, or rejects if it fails to listen */ private listen; /** * Stops listening for incoming p2p connections. * @return a promise that resolves once the server is no longer listening */ private unlisten; /** * Resolves an alias to a known node's public key. Throws an error if a unique * pub key cannot be found for the provided alias. */ resolveAlias: (alias: string) => string; } export default Pool; export { PoolConfig };