Skip to content

Commit 20e6693

Browse files
authored
Alternative Solution: Fix ConnectionId hashmap key bug (#930)
1 parent 7aaf0e7 commit 20e6693

File tree

1 file changed

+24
-1
lines changed

1 file changed

+24
-1
lines changed

portalnet/src/discovery.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::socket;
1616
use ethportal_api::types::enr::Enr;
1717
use ethportal_api::utils::bytes::hex_encode;
1818
use ethportal_api::NodeInfo;
19+
use std::hash::{Hash, Hasher};
1920
use std::net::Ipv4Addr;
2021
use std::str::FromStr;
2122
use std::{convert::TryFrom, fmt, io, net::SocketAddr, sync::Arc};
@@ -290,7 +291,7 @@ impl Discv5UdpSocket {
290291
}
291292

292293
/// A wrapper around `Enr` that implements `ConnectionPeer`.
293-
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
294+
#[derive(Clone, Debug)]
294295
pub struct UtpEnr(pub Enr);
295296

296297
impl UtpEnr {
@@ -305,6 +306,28 @@ impl UtpEnr {
305306
}
306307
}
307308

309+
// Why are we implementing Hash, PartialEq, Eq for UtpEnr?
310+
// UtpEnr is used as an element of the key for a Connections HashTable in our uTP library.
311+
// Enr's can change and are not stable, so if we initiate a ``connect_with_cid`` we are inserting
312+
// our known Enr for the peer, but if the peer has a more upto date Enr, values will be different
313+
// and the Hash for the old Enr and New Enr will be different, along with equating the two structs will return false.
314+
// This leads us to a situation where our peer sends us a uTP messages back and our code thinks the same peer
315+
// is instead 2 different peers causing uTP to ignore the messages. We fixed this by implementing Eq and
316+
// Hash only using the NodeId of the Enr as it is the only stable non-updatable field in the Enr.
317+
impl Hash for UtpEnr {
318+
fn hash<H: Hasher>(&self, state: &mut H) {
319+
self.0.node_id().hash(state);
320+
}
321+
}
322+
323+
impl PartialEq for UtpEnr {
324+
fn eq(&self, other: &Self) -> bool {
325+
self.0.node_id() == other.0.node_id()
326+
}
327+
}
328+
329+
impl Eq for UtpEnr {}
330+
308331
impl ConnectionPeer for UtpEnr {}
309332

310333
#[async_trait]

0 commit comments

Comments
 (0)