Skip to content

Commit f615f41

Browse files
v2.0: checks for duplicate instances using the new ContactInfo (backport of #2506) (#2510)
* checks for duplicate instances using the new ContactInfo (#2506) Working towards deprecating NodeInstance CRDS value, the commit adds check for duplicate instances using the new ContactInfo. (cherry picked from commit 1d825df) * removes unwarp --------- Co-authored-by: behzad nouri <[email protected]>
1 parent 54d08d7 commit f615f41

File tree

2 files changed

+76
-8
lines changed

2 files changed

+76
-8
lines changed

gossip/src/cluster_info.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2495,16 +2495,21 @@ impl ClusterInfo {
24952495

24962496
// Check if there is a duplicate instance of
24972497
// this node with more recent timestamp.
2498-
let instance = self.instance.read().unwrap();
2499-
let check_duplicate_instance = |values: &[CrdsValue]| {
2500-
if should_check_duplicate_instance {
2501-
for value in values {
2502-
if instance.check_duplicate(value) {
2503-
return Err(GossipError::DuplicateNodeInstance);
2504-
}
2498+
let check_duplicate_instance = {
2499+
let instance = self.instance.read().unwrap();
2500+
let my_contact_info = self.my_contact_info();
2501+
move |values: &[CrdsValue]| {
2502+
if should_check_duplicate_instance
2503+
&& values.iter().any(|value| {
2504+
instance.check_duplicate(value)
2505+
|| matches!(&value.data, CrdsData::ContactInfo(other)
2506+
if my_contact_info.check_duplicate(other))
2507+
})
2508+
{
2509+
return Err(GossipError::DuplicateNodeInstance);
25052510
}
2511+
Ok(())
25062512
}
2507-
Ok(())
25082513
};
25092514
let mut pings = Vec::new();
25102515
let mut rng = rand::thread_rng();

gossip/src/contact_info.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,14 @@ impl ContactInfo {
434434
node.set_serve_repair_quic((addr, port + 4)).unwrap();
435435
node
436436
}
437+
438+
// Returns true if the other contact-info is a duplicate instance of this
439+
// node, with a more recent `outset` timestamp.
440+
#[inline]
441+
#[must_use]
442+
pub(crate) fn check_duplicate(&self, other: &ContactInfo) -> bool {
443+
self.pubkey == other.pubkey && self.outset < other.outset
444+
}
437445
}
438446

439447
impl Default for ContactInfo {
@@ -1015,4 +1023,59 @@ mod tests {
10151023
Err(Error::InvalidPort(0))
10161024
);
10171025
}
1026+
1027+
#[test]
1028+
fn test_check_duplicate() {
1029+
let mut rng = rand::thread_rng();
1030+
let mut node = ContactInfo::new(
1031+
Keypair::new().pubkey(),
1032+
rng.gen(), // wallclock
1033+
rng.gen(), // shred_version
1034+
);
1035+
// Same contact-info is not a duplicate instance.
1036+
{
1037+
let other = node.clone();
1038+
assert!(!node.check_duplicate(&other));
1039+
assert!(!other.check_duplicate(&node));
1040+
}
1041+
// Updated socket address is not a duplicate instance.
1042+
{
1043+
let mut other = node.clone();
1044+
while other.set_gossip(new_rand_socket(&mut rng)).is_err() {}
1045+
while other.set_serve_repair(new_rand_socket(&mut rng)).is_err() {}
1046+
assert!(!node.check_duplicate(&other));
1047+
assert!(!other.check_duplicate(&node));
1048+
other.remove_serve_repair();
1049+
assert!(!node.check_duplicate(&other));
1050+
assert!(!other.check_duplicate(&node));
1051+
}
1052+
// Updated wallclock is not a duplicate instance.
1053+
{
1054+
let other = node.clone();
1055+
node.set_wallclock(rng.gen());
1056+
assert!(!node.check_duplicate(&other));
1057+
assert!(!other.check_duplicate(&node));
1058+
}
1059+
// Different pubkey is not a duplicate instance.
1060+
{
1061+
let other = ContactInfo::new(
1062+
Keypair::new().pubkey(),
1063+
rng.gen(), // wallclock
1064+
rng.gen(), // shred_version
1065+
);
1066+
assert!(!node.check_duplicate(&other));
1067+
assert!(!other.check_duplicate(&node));
1068+
}
1069+
// Same pubkey, more recent outset timestamp is a duplicate instance.
1070+
{
1071+
let other = ContactInfo::new(
1072+
node.pubkey,
1073+
rng.gen(), // wallclock
1074+
rng.gen(), // shred_version
1075+
);
1076+
assert!(node.outset < other.outset);
1077+
assert!(node.check_duplicate(&other));
1078+
assert!(!other.check_duplicate(&node));
1079+
}
1080+
}
10181081
}

0 commit comments

Comments
 (0)