diff --git a/client/network-gossip/src/state_machine.rs b/client/network-gossip/src/state_machine.rs index 48a1a2e53352b..7cd5b5613b073 100644 --- a/client/network-gossip/src/state_machine.rs +++ b/client/network-gossip/src/state_machine.rs @@ -354,7 +354,15 @@ impl ConsensusGossip { protocol = %self.protocol, "Ignored already known message", ); - network.report_peer(who, rep::DUPLICATE_GOSSIP); + + // If the peer already send us the message once, let's report them. + if self + .peers + .get_mut(&who) + .map_or(false, |p| !p.known_messages.insert(message_hash)) + { + network.report_peer(who, rep::DUPLICATE_GOSSIP); + } continue } @@ -814,4 +822,30 @@ mod tests { to_forward, ); } + + // Two peers can send us the same gossip message. We should not report the second peer + // sending the gossip message as long as its the first time the peer send us this message. + #[test] + fn do_not_report_peer_for_first_time_duplicate_gossip_message() { + let mut consensus = ConsensusGossip::::new(Arc::new(AllowAll), "/foo".into(), None); + + let mut network = NoOpNetwork::default(); + + let peer_id = PeerId::random(); + consensus.new_peer(&mut network, peer_id, ObservedRole::Full); + assert!(consensus.peers.contains_key(&peer_id)); + + let peer_id2 = PeerId::random(); + consensus.new_peer(&mut network, peer_id2, ObservedRole::Full); + assert!(consensus.peers.contains_key(&peer_id2)); + + let message = vec![vec![1, 2, 3]]; + consensus.on_incoming(&mut network, peer_id, message.clone()); + consensus.on_incoming(&mut network, peer_id2, message.clone()); + + assert_eq!( + vec![(peer_id, rep::GOSSIP_SUCCESS)], + network.inner.lock().unwrap().peer_reports + ); + } }