diff --git a/core/src/replay_stage.rs b/core/src/replay_stage.rs index b8575f2cae89b7..4c5329af41dab7 100644 --- a/core/src/replay_stage.rs +++ b/core/src/replay_stage.rs @@ -258,7 +258,7 @@ impl ReplayStage { } } - let (heaviest_bank, votable_bank_on_same_fork) = + let (heaviest_bank, heaviest_bank_on_same_fork) = Self::select_forks(&frozen_banks, &tower, &progress, &ancestors); Self::report_memory(&allocated, "select_fork", start); @@ -266,7 +266,7 @@ impl ReplayStage { let (vote_bank, reset_bank, failure_reasons) = Self::select_vote_and_reset_forks( &heaviest_bank, - &votable_bank_on_same_fork, + &heaviest_bank_on_same_fork, &ancestors, &descendants, &progress, @@ -1135,7 +1135,8 @@ impl ReplayStage { .count(); let last_vote = tower.last_vote().slots.last().cloned(); - let mut last_votable_on_same_fork = None; + let mut heaviest_bank_on_same_fork = None; + let mut heaviest_same_fork_weight = 0; let stats: Vec<&ForkStats> = frozen_banks .iter() .map(|bank| { @@ -1151,7 +1152,6 @@ impl ReplayStage { .get(&bank.slot()) .expect("Entry in frozen banks must exist in ancestors") .contains(&last_vote) - && stats.vote_threshold { // Descendant of last vote cannot be locked out assert!(!stats.is_locked_out); @@ -1159,7 +1159,13 @@ impl ReplayStage { // ancestors(slot) should not contain the slot itself, // so we should never get the same bank as the last vote assert_ne!(bank.slot(), last_vote); - last_votable_on_same_fork = Some(bank.clone()); + // highest weight, lowest slot first. frozen_banks is sorted + // from least slot to greatest slot, so if two banks have + // the same fork weight, the lower slot will be picked + if stats.fork_weight > heaviest_same_fork_weight { + heaviest_bank_on_same_fork = Some(bank.clone()); + heaviest_same_fork_weight = stats.fork_weight; + } } } @@ -1210,15 +1216,15 @@ impl ReplayStage { ("tower_duration", ms as i64, i64), ); - (rv.map(|x| x.0.clone()), last_votable_on_same_fork) + (rv.map(|x| x.0.clone()), heaviest_bank_on_same_fork) } // Given a heaviest bank, `heaviest_bank` and the next votable bank - // `votable_bank_on_same_fork` as the validator's last vote, return + // `heaviest_bank_on_same_fork` as the validator's last vote, return // a bank to vote on, a bank to reset to, pub(crate) fn select_vote_and_reset_forks( heaviest_bank: &Option>, - votable_bank_on_same_fork: &Option>, + heaviest_bank_on_same_fork: &Option>, ancestors: &HashMap>, descendants: &HashMap>, progress: &ProgressMap, @@ -1260,10 +1266,10 @@ impl ReplayStage { info!( "Waiting to switch to {}, voting on {:?} on same fork for now", bank.slot(), - votable_bank_on_same_fork.as_ref().map(|b| b.slot()) + heaviest_bank_on_same_fork.as_ref().map(|b| b.slot()) ); failure_reasons.push(HeaviestForkFailures::FailedSwitchThreshold(bank.slot())); - votable_bank_on_same_fork + heaviest_bank_on_same_fork .as_ref() .map(|b| (b, switch_threshold)) } else {