fix(rendezvous): peer registration limit (#1656)

This commit is contained in:
Radosław Kamiński
2025-09-03 18:01:23 +01:00
committed by GitHub
parent dbf60b74c7
commit 8add5aaaab
3 changed files with 41 additions and 3 deletions

View File

@@ -43,7 +43,7 @@ const
MaximumMessageLen = 1 shl 22 # 4MB
MinimumNamespaceLen = 1
MaximumNamespaceLen = 255
RegistrationLimitPerPeer = 1000
RegistrationLimitPerPeer* = 1000
DiscoverLimit = 1000'u64
SemaphoreDefaultSize = 5
@@ -397,9 +397,8 @@ proc sendDiscoverResponseError(
await conn.writeLp(msg.buffer)
proc countRegister(rdv: RendezVous, peerId: PeerId): int =
let n = Moment.now()
for data in rdv.registered:
if data.peerId == peerId and data.expiration > n:
if data.peerId == peerId:
result.inc()
proc save(

View File

@@ -424,6 +424,29 @@ suite "RendezVous":
# Returns only one record
check (await peerRdvs[0].request(Opt.some(namespace))).len == 1
asyncTest "Peer registration is ignored if limit of 1000 registrations is reached":
let (rendezvousNode, peerNodes, peerRdvs, rendezvousRdv) =
setupRendezvousNodeWithPeerNodes(1)
(rendezvousNode & peerNodes).startAndDeferStop()
await connectNodes(peerNodes[0], rendezvousNode)
const namespace = "foo"
let peerRdv = peerRdvs[0]
# Create 999 registrations
await populatePeerRegistrations(
peerRdv, rendezvousRdv, namespace, RegistrationLimitPerPeer - 1
)
# 1000th registration allowed
await peerRdv.advertise(namespace)
check rendezvousRdv.registered.s.len == RegistrationLimitPerPeer
# 1001st registration ignored, limit reached
await peerRdv.advertise(namespace)
check rendezvousRdv.registered.s.len == RegistrationLimitPerPeer
asyncTest "Various local error":
let rdv = RendezVous.new(minDuration = 1.minutes, maxDuration = 72.hours)
expect AdvertiseError:

View File

@@ -65,3 +65,19 @@ proc injectCookieForPeer*(
rdv: RendezVous, peerId: PeerId, namespace: string, cookie: seq[byte]
) =
discard rdv.cookiesSaved.hasKeyOrPut(peerId, {namespace: cookie}.toTable())
proc populatePeerRegistrations*(
peerRdv: RendezVous, targetRdv: RendezVous, namespace: string, count: int
) {.async.} =
# Test helper: quickly populate many registrations for a peer.
# We first create a single real registration, then clone that record
# directly into the rendezvous registry to reach the desired count fast.
#
# Notes:
# - Calling advertise() concurrently results in bufferstream defect.
# - Calling advertise() sequentially is too slow for large counts.
await peerRdv.advertise(namespace)
let record = targetRdv.registered.s[0]
for i in 0 ..< count - 1:
targetRdv.registered.s.add(record)