From a37f282c235b69435bd831c6bab520c3bbf3977d Mon Sep 17 00:00:00 2001 From: lklynet Date: Fri, 2 Jan 2026 22:02:27 -0500 Subject: [PATCH] feat(p2p): I added a connection rotation and limited max connections Implement connection rotation to periodically close oldest connections when exceeding half of MAX_CONNECTIONS. Also enforce MAX_CONNECTIONS limit by rejecting new connections when limit is reached (32). This improves network stability and resource management. I also changed max relay hops from 3 to 2. With the connection rotation I think these more conservative numbers should suffice and save on resources. --- src/config/constants.js | 6 +++++- src/p2p/swarm.js | 32 +++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/config/constants.js b/src/config/constants.js index 7ba02cc..b7a691d 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -15,9 +15,11 @@ const POW_PREFIX = "0000"; const MAX_PEERS = parseInt(process.env.MAX_PEERS) || 10000; const MAX_MESSAGE_SIZE = 2048; -const MAX_RELAY_HOPS = 3; +const MAX_RELAY_HOPS = 2; +const MAX_CONNECTIONS = 32; const HEARTBEAT_INTERVAL = 5000; +const CONNECTION_ROTATION_INTERVAL = 30000; const PEER_TIMEOUT = 15000; const BROADCAST_THROTTLE = 1000; const DIAGNOSTICS_INTERVAL = 10000; @@ -30,7 +32,9 @@ module.exports = { MAX_PEERS, MAX_MESSAGE_SIZE, MAX_RELAY_HOPS, + MAX_CONNECTIONS, HEARTBEAT_INTERVAL, + CONNECTION_ROTATION_INTERVAL, PEER_TIMEOUT, BROADCAST_THROTTLE, DIAGNOSTICS_INTERVAL, diff --git a/src/p2p/swarm.js b/src/p2p/swarm.js index 6c4292b..a9b3fc9 100644 --- a/src/p2p/swarm.js +++ b/src/p2p/swarm.js @@ -1,6 +1,6 @@ const Hyperswarm = require("hyperswarm"); const { signMessage } = require("../core/security"); -const { TOPIC, TOPIC_NAME, HEARTBEAT_INTERVAL } = require("../config/constants"); +const { TOPIC, TOPIC_NAME, HEARTBEAT_INTERVAL, MAX_CONNECTIONS, CONNECTION_ROTATION_INTERVAL } = require("../config/constants"); class SwarmManager { constructor(identity, peerManager, diagnostics, messageHandler, relayFn, broadcastFn) { @@ -13,6 +13,7 @@ class SwarmManager { this.swarm = new Hyperswarm(); this.heartbeatInterval = null; + this.rotationInterval = null; } async start() { @@ -22,9 +23,17 @@ class SwarmManager { await discovery.flushed(); this.startHeartbeat(); + this.startRotation(); } handleConnection(socket) { + if (this.swarm.connections.size > MAX_CONNECTIONS) { + socket.destroy(); + return; + } + + socket.connectedAt = Date.now(); + const sig = signMessage(`seq:${this.peerManager.getSeq()}`, this.identity.privateKey); const hello = JSON.stringify({ type: "HEARTBEAT", @@ -88,6 +97,23 @@ class SwarmManager { }, HEARTBEAT_INTERVAL); } + startRotation() { + this.rotationInterval = setInterval(() => { + if (this.swarm.connections.size < MAX_CONNECTIONS / 2) return; + + let oldest = null; + for (const socket of this.swarm.connections) { + if (!oldest || socket.connectedAt < oldest.connectedAt) { + oldest = socket; + } + } + + if (oldest) { + oldest.destroy(); + } + }, CONNECTION_ROTATION_INTERVAL); + } + shutdown() { const sig = signMessage(`type:LEAVE:${this.identity.id}`, this.identity.privateKey); const goodbye = JSON.stringify({ @@ -105,6 +131,10 @@ class SwarmManager { clearInterval(this.heartbeatInterval); } + if (this.rotationInterval) { + clearInterval(this.rotationInterval); + } + setTimeout(() => { process.exit(0); }, 500);