From 0ad063f4e97796eaad2cc2be77f1a12f3f4b12ad Mon Sep 17 00:00:00 2001 From: behzad nouri Date: Wed, 3 Feb 2021 16:26:17 +0000 Subject: [PATCH] adds flag to disable duplicate instance check (#15006) --- core/src/cluster_info.rs | 13 ++++++++++--- core/src/gossip_service.rs | 31 ++++++++++++++++++++++++++---- core/src/test_validator.rs | 1 + core/src/validator.rs | 4 ++++ core/tests/gossip.rs | 11 +++++++++-- local-cluster/src/local_cluster.rs | 3 +++ validator/src/main.rs | 15 ++++++++++++++- 7 files changed, 68 insertions(+), 10 deletions(-) diff --git a/core/src/cluster_info.rs b/core/src/cluster_info.rs index 5168c51a8a..320a02e29d 100644 --- a/core/src/cluster_info.rs +++ b/core/src/cluster_info.rs @@ -2540,6 +2540,7 @@ impl ClusterInfo { stakes: HashMap, feature_set: Option<&FeatureSet>, epoch_time_ms: u64, + should_check_duplicate_instance: bool, ) -> Result<()> { let _st = ScopedTimer::from(&self.stats.process_gossip_packets_time); let packets: Vec<_> = thread_pool.install(|| { @@ -2557,9 +2558,11 @@ impl ClusterInfo { // Check if there is a duplicate instance of // this node with more recent timestamp. let check_duplicate_instance = |values: &[CrdsValue]| { - for value in values { - if self.instance.check_duplicate(value) { - return Err(Error::DuplicateNodeInstance); + if should_check_duplicate_instance { + for value in values { + if self.instance.check_duplicate(value) { + return Err(Error::DuplicateNodeInstance); + } } } Ok(()) @@ -2620,6 +2623,7 @@ impl ClusterInfo { response_sender: &PacketSender, thread_pool: &ThreadPool, last_print: &mut Instant, + should_check_duplicate_instance: bool, ) -> Result<()> { const RECV_TIMEOUT: Duration = Duration::from_secs(1); let packets: Vec<_> = requests_receiver.recv_timeout(RECV_TIMEOUT)?.packets.into(); @@ -2655,6 +2659,7 @@ impl ClusterInfo { stakes, feature_set.as_deref(), epoch_time_ms, + should_check_duplicate_instance, )?; self.print_reset_stats(last_print); @@ -2900,6 +2905,7 @@ impl ClusterInfo { bank_forks: Option>>, requests_receiver: PacketReceiver, response_sender: PacketSender, + should_check_duplicate_instance: bool, exit: &Arc, ) -> JoinHandle<()> { let exit = exit.clone(); @@ -2921,6 +2927,7 @@ impl ClusterInfo { &response_sender, &thread_pool, &mut last_print, + should_check_duplicate_instance, ) { match err { Error::RecvTimeoutError(_) => { diff --git a/core/src/gossip_service.rs b/core/src/gossip_service.rs index d5bf6b2ad1..e8b321cd59 100644 --- a/core/src/gossip_service.rs +++ b/core/src/gossip_service.rs @@ -33,6 +33,7 @@ impl GossipService { bank_forks: Option>>, gossip_socket: UdpSocket, gossip_validators: Option>, + should_check_duplicate_instance: bool, exit: &Arc, ) -> Self { let (request_sender, request_receiver) = channel(); @@ -56,6 +57,7 @@ impl GossipService { bank_forks.clone(), request_receiver, response_sender.clone(), + should_check_duplicate_instance, exit, ); let t_gossip = ClusterInfo::gossip( @@ -108,8 +110,14 @@ pub fn discover( let keypair = keypair.unwrap_or_else(|| Arc::new(Keypair::new())); let exit = Arc::new(AtomicBool::new(false)); - let (gossip_service, ip_echo, spy_ref) = - make_gossip_node(keypair, entrypoint, &exit, my_gossip_addr, my_shred_version); + let (gossip_service, ip_echo, spy_ref) = make_gossip_node( + keypair, + entrypoint, + &exit, + my_gossip_addr, + my_shred_version, + true, // should_check_duplicate_instance, + ); let id = spy_ref.id(); info!("Entrypoint: {:?}", entrypoint); @@ -268,6 +276,7 @@ fn make_gossip_node( exit: &Arc, gossip_addr: Option<&SocketAddr>, shred_version: u16, + should_check_duplicate_instance: bool, ) -> (GossipService, Option, Arc) { let (node, gossip_socket, ip_echo) = if let Some(gossip_addr) = gossip_addr { ClusterInfo::gossip_node(&keypair.pubkey(), gossip_addr, shred_version) @@ -279,7 +288,14 @@ fn make_gossip_node( cluster_info.set_entrypoint(ContactInfo::new_gossip_entry_point(entrypoint)); } let cluster_info = Arc::new(cluster_info); - let gossip_service = GossipService::new(&cluster_info, None, gossip_socket, None, &exit); + let gossip_service = GossipService::new( + &cluster_info, + None, + gossip_socket, + None, + should_check_duplicate_instance, + &exit, + ); (gossip_service, ip_echo, cluster_info) } @@ -298,7 +314,14 @@ mod tests { let tn = Node::new_localhost(); let cluster_info = ClusterInfo::new_with_invalid_keypair(tn.info.clone()); let c = Arc::new(cluster_info); - let d = GossipService::new(&c, None, tn.sockets.gossip, None, &exit); + let d = GossipService::new( + &c, + None, + tn.sockets.gossip, + None, + true, // should_check_duplicate_instance + &exit, + ); exit.store(true, Ordering::Relaxed); d.join().unwrap(); } diff --git a/core/src/test_validator.rs b/core/src/test_validator.rs index 5518a2b169..3ddadf36c6 100644 --- a/core/src/test_validator.rs +++ b/core/src/test_validator.rs @@ -405,6 +405,7 @@ impl TestValidator { vec![Arc::new(validator_vote_account)], vec![], &validator_config, + true, // should_check_duplicate_instance )); // Needed to avoid panics in `solana-responder-gossip` in tests that create a number of diff --git a/core/src/validator.rs b/core/src/validator.rs index 8b182a5ae9..b0062f3c7c 100644 --- a/core/src/validator.rs +++ b/core/src/validator.rs @@ -247,6 +247,7 @@ impl Validator { mut authorized_voter_keypairs: Vec>, cluster_entrypoints: Vec, config: &ValidatorConfig, + should_check_duplicate_instance: bool, ) -> Self { let id = identity_keypair.pubkey(); assert_eq!(id, node.info.id); @@ -517,6 +518,7 @@ impl Validator { Some(bank_forks.clone()), node.sockets.gossip, config.gossip_validators.clone(), + should_check_duplicate_instance, &exit, ); let serve_repair = Arc::new(RwLock::new(ServeRepair::new(cluster_info.clone()))); @@ -1419,6 +1421,7 @@ mod tests { vec![voting_keypair.clone()], vec![leader_node.info], &config, + true, // should_check_duplicate_instance ); validator.close(); remove_dir_all(validator_ledger_path).unwrap(); @@ -1489,6 +1492,7 @@ mod tests { vec![Arc::new(vote_account_keypair)], vec![leader_node.info.clone()], &config, + true, // should_check_duplicate_instance ) }) .collect(); diff --git a/core/tests/gossip.rs b/core/tests/gossip.rs index 839926182e..66e0c444d9 100644 --- a/core/tests/gossip.rs +++ b/core/tests/gossip.rs @@ -25,8 +25,14 @@ fn test_node(exit: &Arc) -> (Arc, GossipService, UdpSoc let keypair = Arc::new(Keypair::new()); let mut test_node = Node::new_localhost_with_pubkey(&keypair.pubkey()); let cluster_info = Arc::new(ClusterInfo::new(test_node.info.clone(), keypair)); - let gossip_service = - GossipService::new(&cluster_info, None, test_node.sockets.gossip, None, exit); + let gossip_service = GossipService::new( + &cluster_info, + None, + test_node.sockets.gossip, + None, + true, // should_check_duplicate_instance + exit, + ); let _ = cluster_info.my_contact_info(); ( cluster_info, @@ -47,6 +53,7 @@ fn test_node_with_bank( Some(bank_forks), test_node.sockets.gossip, None, + true, // should_check_duplicate_instance exit, ); let _ = cluster_info.my_contact_info(); diff --git a/local-cluster/src/local_cluster.rs b/local-cluster/src/local_cluster.rs index 97297de155..4716116ca9 100644 --- a/local-cluster/src/local_cluster.rs +++ b/local-cluster/src/local_cluster.rs @@ -207,6 +207,7 @@ impl LocalCluster { vec![leader_vote_keypair.clone()], vec![], &leader_config, + true, // should_check_duplicate_instance ); let mut validators = HashMap::new(); @@ -350,6 +351,7 @@ impl LocalCluster { vec![voting_keypair.clone()], vec![self.entry_point_info.clone()], &config, + true, // should_check_duplicate_instance ); let validator_pubkey = validator_keypair.pubkey(); @@ -665,6 +667,7 @@ impl Cluster for LocalCluster { .map(|entry_point_info| vec![entry_point_info]) .unwrap_or_default(), &cluster_validator_info.config, + true, // should_check_duplicate_instance ); cluster_validator_info.validator = Some(restarted_node); cluster_validator_info diff --git a/validator/src/main.rs b/validator/src/main.rs index 80a9be57ec..d2616469e0 100644 --- a/validator/src/main.rs +++ b/validator/src/main.rs @@ -121,6 +121,7 @@ fn start_gossip_node( gossip_socket: UdpSocket, expected_shred_version: Option, gossip_validators: Option>, + should_check_duplicate_instance: bool, ) -> (Arc, Arc, GossipService) { let mut cluster_info = ClusterInfo::new( ClusterInfo::gossip_contact_info( @@ -140,6 +141,7 @@ fn start_gossip_node( None, gossip_socket, gossip_validators, + should_check_duplicate_instance, &gossip_exit_flag, ); (cluster_info, gossip_exit_flag, gossip_service) @@ -577,6 +579,7 @@ fn rpc_bootstrap( no_port_check: bool, use_progress_bar: bool, maximum_local_snapshot_age: Slot, + should_check_duplicate_instance: bool, ) { if !no_port_check { let mut order: Vec<_> = (0..cluster_entrypoints.len()).collect(); @@ -605,6 +608,7 @@ fn rpc_bootstrap( node.sockets.gossip.try_clone().unwrap(), validator_config.expected_shred_version, validator_config.gossip_validators.clone(), + should_check_duplicate_instance, )); } @@ -1421,6 +1425,13 @@ pub fn main() { .conflicts_with("no_accounts_db_caching") .hidden(true) ) + .arg( + Arg::with_name("no_duplicate_instance_check") + .long("no-duplicate-instance-check") + .takes_value(false) + .help("Disables duplicate instance check") + .hidden(true), + ) .after_help("The default subcommand is run") .subcommand( SubCommand::with_name("init") @@ -1896,6 +1907,7 @@ pub fn main() { solana_ledger::entry::init_poh(); solana_runtime::snapshot_utils::remove_tmp_snapshot_archives(&ledger_path); + let should_check_duplicate_instance = !matches.is_present("no_duplicate_instance_check"); if !cluster_entrypoints.is_empty() { rpc_bootstrap( &node, @@ -1909,6 +1921,7 @@ pub fn main() { no_port_check, use_progress_bar, maximum_local_snapshot_age, + should_check_duplicate_instance, ); } @@ -1916,7 +1929,6 @@ pub fn main() { info!("Validator ledger initialization complete"); return; } - let validator = Validator::new( node, &identity_keypair, @@ -1925,6 +1937,7 @@ pub fn main() { authorized_voter_keypairs, cluster_entrypoints, &validator_config, + should_check_duplicate_instance, ); if let Some(filename) = init_complete_file {