Skip to content

Commit

Permalink
updates ContactInfo.outset when hot-swapping identity (solana-labs#2613)
Browse files Browse the repository at this point in the history
When hot-swapping identity, ContactInfo.outset should be updated so that
the new ContactInfo overrides older node with the same pubkey.
  • Loading branch information
behzadnouri authored Aug 16, 2024
1 parent 28cbac1 commit 1871e2c
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 21 deletions.
25 changes: 13 additions & 12 deletions core/src/cluster_slots_service/cluster_slots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,6 @@ mod tests {
#[test]
fn test_best_peer_2() {
let cs = ClusterSlots::default();
let mut c1 = ContactInfo::default();
let mut c2 = ContactInfo::default();
let mut map = HashMap::new();
let k1 = solana_sdk::pubkey::new_rand();
let k2 = solana_sdk::pubkey::new_rand();
Expand All @@ -289,16 +287,14 @@ mod tests {
.write()
.unwrap()
.insert(0, Arc::new(RwLock::new(map)));
c1.set_pubkey(k1);
c2.set_pubkey(k2);
let c1 = ContactInfo::new(k1, /*wallclock:*/ 0, /*shred_version:*/ 0);
let c2 = ContactInfo::new(k2, /*wallclock:*/ 0, /*shred_version:*/ 0);
assert_eq!(cs.compute_weights(0, &[c1, c2]), vec![u64::MAX / 4, 1]);
}

#[test]
fn test_best_peer_3() {
let cs = ClusterSlots::default();
let mut c1 = ContactInfo::default();
let mut c2 = ContactInfo::default();
let mut map = HashMap::new();
let k1 = solana_sdk::pubkey::new_rand();
let k2 = solana_sdk::pubkey::new_rand();
Expand All @@ -318,18 +314,23 @@ mod tests {
.into_iter()
.collect();
*cs.validator_stakes.write().unwrap() = Arc::new(validator_stakes);
c1.set_pubkey(k1);
c2.set_pubkey(k2);
let c1 = ContactInfo::new(k1, /*wallclock:*/ 0, /*shred_version:*/ 0);
let c2 = ContactInfo::new(k2, /*wallclock:*/ 0, /*shred_version:*/ 0);
assert_eq!(cs.compute_weights(0, &[c1, c2]), vec![u64::MAX / 4 + 1, 1]);
}

#[test]
fn test_best_completed_slot_peer() {
let cs = ClusterSlots::default();
let mut contact_infos = vec![ContactInfo::default(); 2];
for ci in contact_infos.iter_mut() {
ci.set_pubkey(solana_sdk::pubkey::new_rand());
}
let contact_infos: Vec<_> = std::iter::repeat_with(|| {
ContactInfo::new(
solana_sdk::pubkey::new_rand(),
0, // wallclock
0, // shred_version
)
})
.take(2)
.collect();
let slot = 9;

// None of these validators have completed slot 9, so should
Expand Down
2 changes: 1 addition & 1 deletion gossip/src/cluster_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,7 @@ impl ClusterInfo {
*instance = NodeInstance::new(&mut thread_rng(), id, timestamp());
}
*self.keypair.write().unwrap() = new_keypair;
self.my_contact_info.write().unwrap().set_pubkey(id);
self.my_contact_info.write().unwrap().hot_swap_pubkey(id);

self.refresh_my_gossip_contact_info();
self.push_message(CrdsValue::new_signed(
Expand Down
32 changes: 25 additions & 7 deletions gossip/src/contact_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,7 @@ impl ContactInfo {
Self {
pubkey,
wallclock,
outset: {
let now = SystemTime::now();
let elapsed = now.duration_since(UNIX_EPOCH).unwrap();
u64::try_from(elapsed.as_micros()).unwrap()
},
outset: get_node_outset(),
shred_version,
version: solana_version::Version::default(),
addrs: Vec::<IpAddr>::default(),
Expand Down Expand Up @@ -216,8 +212,11 @@ impl ContactInfo {
&self.version
}

pub fn set_pubkey(&mut self, pubkey: Pubkey) {
self.pubkey = pubkey
pub(crate) fn hot_swap_pubkey(&mut self, pubkey: Pubkey) {
self.pubkey = pubkey;
// Need to update ContactInfo.outset so that this node's contact-info
// will override older node with the same pubkey.
self.outset = get_node_outset();
}

pub fn set_wallclock(&mut self, wallclock: u64) {
Expand Down Expand Up @@ -464,6 +463,12 @@ impl ContactInfo {
}
}

fn get_node_outset() -> u64 {
let now = SystemTime::now();
let elapsed = now.duration_since(UNIX_EPOCH).unwrap();
u64::try_from(elapsed.as_micros()).unwrap()
}

impl Default for ContactInfo {
fn default() -> Self {
Self::new(
Expand Down Expand Up @@ -649,6 +654,7 @@ mod tests {
iter::repeat_with,
net::{Ipv4Addr, Ipv6Addr},
ops::Range,
time::Duration,
},
};

Expand Down Expand Up @@ -1101,9 +1107,21 @@ mod tests {
assert!(!other.check_duplicate(&node));
assert_eq!(node.overrides(&other), None);
assert_eq!(other.overrides(&node), None);

// Need to sleep here so that get_node_outset
// returns a larger value.
std::thread::sleep(Duration::from_millis(1));

node.hot_swap_pubkey(*other.pubkey());
assert!(node.outset > other.outset);
assert!(!node.check_duplicate(&other));
assert!(other.check_duplicate(&node));
assert_eq!(node.overrides(&other), Some(true));
assert_eq!(other.overrides(&node), Some(false));
}
// Same pubkey, more recent outset timestamp is a duplicate instance.
{
std::thread::sleep(Duration::from_millis(1));
let other = ContactInfo::new(
node.pubkey,
rng.gen(), // wallclock
Expand Down
2 changes: 1 addition & 1 deletion turbine/src/cluster_nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ pub fn make_test_cluster<R: Rng>(
.collect();
nodes.shuffle(rng);
let keypair = Arc::new(Keypair::new());
nodes[0].set_pubkey(keypair.pubkey());
nodes[0] = ContactInfo::new_localhost(&keypair.pubkey(), /*wallclock:*/ timestamp());
let this_node = nodes[0].clone();
let mut stakes: HashMap<Pubkey, u64> = nodes
.iter()
Expand Down

0 comments on commit 1871e2c

Please sign in to comment.