diff --git a/tests/pubsub/testgossipsubmeshmanagement.nim b/tests/pubsub/testgossipsubmeshmanagement.nim index cffefc163..28ae7c89b 100644 --- a/tests/pubsub/testgossipsubmeshmanagement.nim +++ b/tests/pubsub/testgossipsubmeshmanagement.nim @@ -22,7 +22,7 @@ suite "GossipSub Mesh Management": asyncTest "subscribe/unsubscribeAll": let topic = "foobar" let (gossipSub, conns, peers) = - setupGossipSubWithPeers(15, topic, populateGossipsub = true) + setupGossipSubWithPeers(15, topic, populateGossipsub = true, populateMesh = true) defer: await teardownGossipSub(gossipSub, conns) diff --git a/tests/pubsub/testgossipsubscoring.nim b/tests/pubsub/testgossipsubscoring.nim index 96b2999a5..66ccd1f8a 100644 --- a/tests/pubsub/testgossipsubscoring.nim +++ b/tests/pubsub/testgossipsubscoring.nim @@ -12,10 +12,11 @@ import std/[sequtils] import stew/byteutils import utils -import ../../libp2p/protocols/pubsub/[gossipsub, peertable, pubsubpeer] +import ../../libp2p/protocols/pubsub/[gossipsub, mcache, peertable, pubsubpeer] import ../../libp2p/protocols/pubsub/rpc/[messages] import ../../libp2p/muxers/muxer -import ../helpers, ../utils/[futures] +import ../helpers +import ../utils/[futures] suite "GossipSub Scoring": teardown: @@ -404,3 +405,140 @@ suite "GossipSub Scoring": check: nodes[0].peerStats[nodes[1].peerInfo.peerId].topicInfos[topic].meshMessageDeliveries in 50.0 .. 66.0 + + asyncTest "GossipThreshold - do not handle IHave if peer score is below threshold": + const + topic = "foobar" + gossipThreshold = -100.0 + let + (gossipSub, conns, peers) = setupGossipSubWithPeers(1, topic) + peer = peers[0] + defer: + await teardownGossipSub(gossipSub, conns) + + # Given peer with score below GossipThreshold + gossipSub.parameters.gossipThreshold = gossipThreshold + peer.score = gossipThreshold - 100.0 + + # and IHave message + let id = @[0'u8, 1, 2, 3] + let msg = ControlIHave(topicID: topic, messageIDs: @[id]) + + # When IHave is handled + let iWant = gossipSub.handleIHave(peer, @[msg]) + + # Then IHave is ignored + check: + iWant.messageIDs.len == 0 + + asyncTest "GossipThreshold - do not handle IWant if peer score is below threshold": + const + topic = "foobar" + gossipThreshold = -100.0 + let + (gossipSub, conns, peers) = setupGossipSubWithPeers(1, topic) + peer = peers[0] + defer: + await teardownGossipSub(gossipSub, conns) + + # Given peer with score below GossipThreshold + gossipSub.parameters.gossipThreshold = gossipThreshold + peer.score = gossipThreshold - 100.0 + + # and IWant message with MsgId in mcache and sentIHaves + let id = @[0'u8, 1, 2, 3] + gossipSub.mcache.put(id, Message()) + peer.sentIHaves[0].incl(id) + let msg = ControlIWant(messageIDs: @[id]) + + # When IWant is handled + let messages = gossipSub.handleIWant(peer, @[msg]) + + # Then IWant is ignored + check: + messages.len == 0 + + asyncTest "GossipThreshold - do not trigger PeerExchange on Prune": + const + topic = "foobar" + gossipThreshold = -100.0 + let + (gossipSub, conns, peers) = setupGossipSubWithPeers(1, topic) + peer = peers[0] + defer: + await teardownGossipSub(gossipSub, conns) + + # Given peer with score below GossipThreshold + gossipSub.parameters.gossipThreshold = gossipThreshold + peer.score = gossipThreshold - 100.0 + + # and RoutingRecordsHandler added + var routingRecordsFut = newFuture[void]() + gossipSub.routingRecordsHandler.add( + proc(peer: PeerId, tag: string, peers: seq[RoutingRecordsPair]) = + routingRecordsFut.complete() + ) + + # and Prune message + let msg = ControlPrune( + topicID: topic, peers: @[PeerInfoMsg(peerId: peer.peerId)], backoff: 123'u64 + ) + + # When Prune is handled + gossipSub.handlePrune(peer, @[msg]) + + # Then handler is not triggered + let result = await waitForState(routingRecordsFut, HEARTBEAT_TIMEOUT) + check: + result.isCancelled() + + asyncTest "GossipThreshold - do not select peer for IHave broadcast if peer score is below threshold": + const + topic = "foobar" + gossipThreshold = -100.0 + let + (gossipSub, conns, peers) = + setupGossipSubWithPeers(1, topic, populateGossipsub = true) + peer = peers[0] + defer: + await teardownGossipSub(gossipSub, conns) + + # Given peer with score below GossipThreshold + gossipSub.parameters.gossipThreshold = gossipThreshold + peer.score = gossipThreshold - 100.0 + + # and message in cache + let id = @[0'u8, 1, 2, 3] + gossipSub.mcache.put(id, Message(topic: topic)) + + # When Node selects peers for IHave broadcast + let gossipPeers = gossipSub.getGossipPeers() + + # Then peer is not selected + check: + gossipPeers.len == 0 + + asyncTest "PublishThreshold - do not graft when peer score below threshold": + const + topic = "foobar" + publishThreshold = -100.0 + let + (gossipSub, conns, peers) = setupGossipSubWithPeers(1, topic) + peer = peers[0] + defer: + await teardownGossipSub(gossipSub, conns) + + # Given peer with score below publishThreshold + gossipSub.parameters.publishThreshold = publishThreshold + peer.score = publishThreshold - 100.0 + + # and Graft message + let msg = ControlGraft(topicID: topic) + + # When Graft is handled + let prunes = gossipSub.handleGraft(peer, @[msg]) + + # Then peer is ignored and not added to prunes + check: + gossipSub.mesh[topic].len == 0 + prunes.len == 0 diff --git a/tests/pubsub/utils.nim b/tests/pubsub/utils.nim index a11c4fecc..fa9e98a6f 100644 --- a/tests/pubsub/utils.nim +++ b/tests/pubsub/utils.nim @@ -96,6 +96,7 @@ proc setupGossipSubWithPeers*( let gossipSub = TestGossipSub.init(newStandardSwitch()) for topic in topics: + gossipSub.subscribe(topic, voidTopicHandler) gossipSub.topicParams[topic] = TopicParams.init() gossipSub.mesh[topic] = initHashSet[PubSubPeer]() gossipSub.gossipsub[topic] = initHashSet[PubSubPeer]()