diff options
author | Alex Auvolat <alex@adnab.me> | 2024-03-21 09:47:04 +0100 |
---|---|---|
committer | Alex Auvolat <alex@adnab.me> | 2024-03-21 09:47:04 +0100 |
commit | 5225a81dee21603950e7944cd93c40fdb1bd8feb (patch) | |
tree | 7481c041aaf367cc80bc12730399ef6fce333463 /src/net | |
parent | ce69dc302c6eaad4fe5268cca3511620fcca12f8 (diff) | |
download | garage-5225a81dee21603950e7944cd93c40fdb1bd8feb.tar.gz garage-5225a81dee21603950e7944cd93c40fdb1bd8feb.zip |
[net-fixes] peering: only count node IDs and not addresses in hash
Diffstat (limited to 'src/net')
-rw-r--r-- | src/net/peering.rs | 45 |
1 files changed, 28 insertions, 17 deletions
diff --git a/src/net/peering.rs b/src/net/peering.rs index 61882a18..f4283683 100644 --- a/src/net/peering.rs +++ b/src/net/peering.rs @@ -164,29 +164,40 @@ struct KnownHosts { impl KnownHosts { fn new() -> Self { let list = HashMap::new(); - let hash = Self::calculate_hash(vec![]); - Self { list, hash } + let mut ret = Self { + list, + hash: hash::Digest::from_slice(&[0u8; 64][..]).unwrap(), + }; + ret.update_hash(); + ret } fn update_hash(&mut self) { - self.hash = Self::calculate_hash(self.connected_peers_vec()); - } - fn connected_peers_vec(&self) -> Vec<(NodeID, SocketAddr)> { - let mut list = Vec::with_capacity(self.list.len()); - for (id, peer) in self.list.iter() { - if peer.state.is_up() { - list.push((*id, peer.addr)); - } - } - list - } - fn calculate_hash(mut list: Vec<(NodeID, SocketAddr)>) -> hash::Digest { + // The hash is a value that is exchanged between nodes when they ping one + // another. Nodes compare their known hosts hash to know if they are connected + // to the same set of nodes. If the hashes differ, they are connected to + // different nodes and they trigger an exchange of the full list of active + // connections. The hash value only represents the set of node IDs and not + // their actual socket addresses, because nodes can be connected via different + // addresses and that shouldn't necessarily trigger a full peer exchange. + let mut list = self + .list + .iter() + .filter(|(_, peer)| peer.state.is_up()) + .map(|(id, _)| *id) + .collect::<Vec<_>>(); list.sort(); let mut hash_state = hash::State::new(); - for (id, addr) in list { + for id in list { hash_state.update(&id[..]); - hash_state.update(&format!("{}\n", addr).into_bytes()[..]); } - hash_state.finalize() + self.hash = hash_state.finalize(); + } + fn connected_peers_vec(&self) -> Vec<(NodeID, SocketAddr)> { + self.list + .iter() + .filter(|(_, peer)| peer.state.is_up()) + .map(|(id, peer)| (*id, peer.addr)) + .collect::<Vec<_>>() } } |