Skip to content

Commit b16bcee

Browse files
authored
fix(floodsub): remove rand 0.7 dependency
Replace floodsub's cuckoo filter with a bounded cache of 64-bit message hashes. The new cache preserves the previous approximate limit of 2^20 entries, refreshes the eviction order when a duplicate is observed, and evicts the least recently seen hash when full. This keeps duplicate suppression bounded without retaining complete messages. Removing `cuckoofilter` also removes its transitive dependency on `rand` 0.7.3, which is flagged by RUSTSEC-2026-0097. There are no public API changes. Fixes #6419. Pull-Request: #6524.
1 parent ed23295 commit b16bcee

4 files changed

Lines changed: 18 additions & 100 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 70 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

protocols/floodsub/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
## 0.48.0
22

3+
- Replace the duplicate-message cuckoo filter with a bounded cache, removing the `rand` 0.7.3 dependency.
4+
See [issue 6419](https://github.com/libp2p/rust-libp2p/issues/6419).
5+
36
- Raise MSRV to 1.88.0.
47
See [PR 6273](https://github.com/libp2p/rust-libp2p/pull/6273).
58

protocols/floodsub/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ categories = ["network-programming", "asynchronous"]
1212

1313
[dependencies]
1414
asynchronous-codec = { workspace = true }
15-
cuckoofilter = "0.5.0"
16-
fnv = "1.0"
1715
bytes.workspace = true
16+
fnv = "1.0"
1817
futures = { workspace = true }
18+
hashlink = { workspace = true }
1919
libp2p-core = { workspace = true }
2020
libp2p-swarm = { workspace = true }
2121
libp2p-identity = { workspace = true }

protocols/floodsub/src/layer.rs

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,14 @@
1919
// DEALINGS IN THE SOFTWARE.
2020

2121
use std::{
22-
collections::{
23-
VecDeque,
24-
hash_map::{DefaultHasher, HashMap},
25-
},
22+
collections::{HashMap, VecDeque},
2623
iter,
2724
task::{Context, Poll},
2825
};
2926

3027
use bytes::Bytes;
31-
use cuckoofilter::{CuckooError, CuckooFilter};
3228
use fnv::FnvHashSet;
29+
use hashlink::LruCache;
3330
use libp2p_core::{Endpoint, Multiaddr, transport::PortUse};
3431
use libp2p_identity::PeerId;
3532
use libp2p_swarm::{
@@ -49,6 +46,9 @@ use crate::{
4946
topic::Topic,
5047
};
5148

49+
// Limit the number of received messages retained for deduplication.
50+
const RECEIVED_CACHE_CAPACITY: usize = 1 << 16;
51+
5252
#[deprecated = "Use `Behaviour` instead."]
5353
pub type Floodsub = Behaviour;
5454

@@ -71,9 +71,9 @@ pub struct Behaviour {
7171
// erroneously.
7272
subscribed_topics: SmallVec<[Topic; 16]>,
7373

74-
// We keep track of the messages we received (in the format `hash(source ID, seq_no)`) so that
75-
// we don't dispatch the same message twice if we receive it twice on the network.
76-
received: CuckooFilter<DefaultHasher>,
74+
// We keep track of the messages we received so that we don't dispatch the same message twice
75+
// if we receive it twice on the network.
76+
received: LruCache<FloodsubMessage, ()>,
7777
}
7878

7979
impl Behaviour {
@@ -90,7 +90,7 @@ impl Behaviour {
9090
target_peers: FnvHashSet::default(),
9191
connected_peers: HashMap::new(),
9292
subscribed_topics: SmallVec::new(),
93-
received: CuckooFilter::new(),
93+
received: LruCache::new(RECEIVED_CACHE_CAPACITY),
9494
}
9595
}
9696

@@ -235,13 +235,7 @@ impl Behaviour {
235235
.iter()
236236
.any(|t| message.topics.iter().any(|u| t == u));
237237
if self_subscribed {
238-
if let Err(e @ CuckooError::NotEnoughSpace) = self.received.add(&message) {
239-
tracing::warn!(
240-
"Message was added to 'received' Cuckoofilter but some \
241-
other message was removed as a consequence: {}",
242-
e,
243-
);
244-
}
238+
self.received.insert(message.clone(), ());
245239
if self.config.subscribe_local_messages {
246240
self.events
247241
.push_back(ToSwarm::GenerateEvent(Event::Message(message.clone())));
@@ -420,18 +414,8 @@ impl NetworkBehaviour for Behaviour {
420414

421415
for message in event.messages {
422416
// Use `self.received` to skip the messages that we have already received in the past.
423-
// Note that this can result in false positives.
424-
match self.received.test_and_add(&message) {
425-
Ok(true) => {} // Message was added.
426-
Ok(false) => continue, // Message already existed.
427-
Err(e @ CuckooError::NotEnoughSpace) => {
428-
// Message added, but some other removed.
429-
tracing::warn!(
430-
"Message was added to 'received' Cuckoofilter but some \
431-
other message was removed as a consequence: {}",
432-
e,
433-
);
434-
}
417+
if self.received.insert(message.clone(), ()).is_some() {
418+
continue;
435419
}
436420

437421
// Add the message to be dispatched to the user.

0 commit comments

Comments
 (0)