@@ -360,11 +360,6 @@ func getNode*(p: PortalProtocol, id: NodeId): Opt[Node] =
360
360
func localNode* (p: PortalProtocol): Node =
361
361
p.baseProtocol.localNode
362
362
363
- template neighbours* (
364
- p: PortalProtocol, id: NodeId, k: int = BUCKET_SIZE, seenOnly = false
365
- ): seq [Node] =
366
- p.routingTable.neighbours(id, k, seenOnly)
367
-
368
363
func distance(p: PortalProtocol, a, b: NodeId): UInt256 =
369
364
p.routingTable.distance(a, b)
370
365
@@ -380,6 +375,34 @@ func inRange(
380
375
template inRange* (p: PortalProtocol, contentId: ContentId): bool =
381
376
p.inRange(p.localNode.id, p.dataRadius(), contentId)
382
377
378
+ func neighbours* (
379
+ p: PortalProtocol,
380
+ id: NodeId,
381
+ k: int = BUCKET_SIZE,
382
+ seenOnly = false ,
383
+ excluding = initHashSet[NodeId](),
384
+ ): seq [Node] =
385
+ func nodeNotExcluded(nodeId: NodeId): bool =
386
+ not excluding.contains(nodeId)
387
+
388
+ p.routingTable.neighbours(id, k, seenOnly, nodeNotExcluded)
389
+
390
+ func neighboursInRange*(
391
+ p: PortalProtocol,
392
+ id: ContentId,
393
+ k: int = BUCKET_SIZE,
394
+ seenOnly = false,
395
+ excluding = initHashSet[NodeId](),
396
+ ): seq [Node] =
397
+ func nodeNotExcludedAndInRange(nodeId: NodeId): bool =
398
+ if excluding.contains(nodeId):
399
+ return false
400
+ let radius = p.radiusCache.get(nodeId).valueOr:
401
+ return false
402
+ p.inRange(nodeId, radius, id)
403
+
404
+ p.routingTable.neighbours(id, k, seenOnly, nodeNotExcludedAndInRange)
405
+
383
406
func truncateEnrs(
384
407
nodes: seq [Node], maxSize: int , enrOverhead: int
385
408
): List[ByteList[204 8], 32 ] =
@@ -542,8 +565,10 @@ proc handleFindContent(
542
565
543
566
# Node does not have the content, or content is not even in radius,
544
567
# send closest neighbours to the requested content id.
568
+
545
569
let
546
- closestNodes = p.neighbours(NodeId(contentId), seenOnly = true )
570
+ closestNodes =
571
+ p.neighbours(contentId, seenOnly = true , excluding = toHashSet([srcId]))
547
572
enrs = truncateEnrs(closestNodes, maxPayloadSize, enrOverhead)
548
573
portal_content_enrs_packed.observe(enrs.len().int64 , labelValues = [$ p.protocolId])
549
574
@@ -1751,28 +1776,24 @@ proc neighborhoodGossip*(
1751
1776
# table, but at the same time avoid unnecessary node lookups.
1752
1777
# It might still cause issues in data getting propagated in a wider id range.
1753
1778
1779
+ var excluding: HashSet[NodeId]
1780
+ if srcNodeId.isSome():
1781
+ excluding.incl(srcNodeId.get())
1782
+
1754
1783
var closestLocalNodes =
1755
- p.routingTable.neighbours(NodeId( contentId) , BUCKET_SIZE, seenOnly = true )
1784
+ p.neighboursInRange( contentId, BUCKET_SIZE, seenOnly = true , excluding )
1756
1785
1757
1786
# Shuffling the order of the nodes in order to not always hit the same node
1758
1787
# first for the same request.
1759
1788
p.baseProtocol.rng[].shuffle(closestLocalNodes)
1760
1789
1761
- var gossipNodes: seq [Node]
1762
- for node in closestLocalNodes:
1763
- let radius = p.radiusCache.get(node.id).valueOr:
1764
- continue
1765
- if p.inRange(node.id, radius, contentId):
1766
- if srcNodeId.isNone() or node.id != srcNodeId.get():
1767
- gossipNodes.add(node)
1768
-
1769
1790
var numberOfGossipedNodes = 0
1770
1791
1771
- if not enableNodeLookup or gossipNodes .len() >= p.config.maxGossipNodes:
1792
+ if not enableNodeLookup or closestLocalNodes .len() >= p.config.maxGossipNodes:
1772
1793
# use local nodes for gossip
1773
1794
portal_gossip_without_lookup.inc(labelValues = [$ p.protocolId])
1774
1795
1775
- for node in gossipNodes :
1796
+ for node in closestLocalNodes :
1776
1797
let req = OfferRequest(dst: node, kind: Direct, contentList: contentList)
1777
1798
await p.offerQueue.addLast(req)
1778
1799
inc numberOfGossipedNodes
0 commit comments