diff --git a/core/src/replay_stage.rs b/core/src/replay_stage.rs index 04f42e6674e176..a728ed5d6709f4 100644 --- a/core/src/replay_stage.rs +++ b/core/src/replay_stage.rs @@ -293,6 +293,8 @@ impl ReplayStage { let mut partition_exists = false; let mut skipped_slots_info = SkippedSlotsInfo::default(); let mut replay_timing = ReplayTiming::default(); + let mut has_voted = false; + let mut first_voted_slot = Slot::MAX; loop { let allocated = thread_mem_usage::Allocatedp::default(); @@ -375,6 +377,8 @@ impl ReplayStage { &cluster_slots, &bank_forks, &mut heaviest_subtree_fork_choice, + &mut has_voted, + first_voted_slot, ); compute_bank_stats_time.stop(); @@ -479,6 +483,7 @@ impl ReplayStage { &mut heaviest_subtree_fork_choice, &cache_block_time_sender, &bank_notification_sender, + &mut first_voted_slot, ); }; voting_time.stop(); @@ -570,6 +575,7 @@ impl ReplayStage { &progress, &retransmit_slots_sender, &mut skipped_slots_info, + has_voted, ); let poh_bank = poh_recorder.lock().unwrap().bank(); @@ -885,7 +891,12 @@ impl ReplayStage { progress_map: &ProgressMap, retransmit_slots_sender: &RetransmitSlotsSender, skipped_slots_info: &mut SkippedSlotsInfo, + has_voted: bool, ) { + if !has_voted { + info!("Haven't landed a vote, so skipping my leader slot"); + return; + } // all the individual calls to poh_recorder.lock() are designed to // increase granularity, decrease contention @@ -1077,6 +1088,7 @@ impl ReplayStage { heaviest_subtree_fork_choice: &mut HeaviestSubtreeForkChoice, cache_block_time_sender: &Option, bank_notification_sender: &Option, + first_voted_slot: &mut Slot, ) { if bank.is_empty() { inc_new_counter_info!("replay_stage-voted_empty_bank", 1); @@ -1158,6 +1170,7 @@ impl ReplayStage { last_vote, &tower_slots, switch_fork_decision, + first_voted_slot, ); } @@ -1169,6 +1182,7 @@ impl ReplayStage { vote: Vote, tower: &[Slot], switch_fork_decision: &SwitchForkDecision, + first_voted_slot: &mut Slot, ) { if authorized_voter_keypairs.is_empty() { return; @@ -1238,6 +1252,9 @@ impl ReplayStage { let mut vote_tx = Transaction::new_with_payer(&[vote_ix], Some(&node_keypair.pubkey())); + if *first_voted_slot != Slot::MAX { + *first_voted_slot = bank.slot(); + } let blockhash = bank.last_blockhash(); vote_tx.partial_sign(&[node_keypair.as_ref()], blockhash); vote_tx.partial_sign(&[authorized_voter_keypair.as_ref()], blockhash); @@ -1423,6 +1440,8 @@ impl ReplayStage { cluster_slots: &ClusterSlots, bank_forks: &RwLock, heaviest_subtree_fork_choice: &mut dyn ForkChoice, + has_voted: &mut bool, + first_voted_slot: Slot, ) -> Vec { frozen_banks.sort_by_key(|bank| bank.slot()); let mut new_stats = vec![]; @@ -1499,6 +1518,9 @@ impl ReplayStage { tower.check_vote_stake_threshold(bank_slot, &stats.voted_stakes, stats.total_stake); stats.is_locked_out = tower.is_locked_out(bank_slot, &ancestors); stats.has_voted = tower.has_voted(bank_slot); + if bank_slot > first_voted_slot && stats.has_voted { + *has_voted = true; + } stats.is_recent = tower.is_recent(bank_slot); } new_stats