From 100a11f061f16b27a409f3f4b68b2523056f2f79 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 26 Feb 2020 15:49:31 -0800 Subject: [PATCH] Limit leader schedule search space (#8468) (#8485) automerge --- core/src/poh_recorder.rs | 5 ++- core/src/replay_stage.rs | 3 +- core/src/validator.rs | 10 ++++- ledger/src/leader_schedule_cache.rs | 59 ++++++++++++++++++++--------- 4 files changed, 54 insertions(+), 23 deletions(-) diff --git a/core/src/poh_recorder.rs b/core/src/poh_recorder.rs index a54708ee5a..1636473c7a 100644 --- a/core/src/poh_recorder.rs +++ b/core/src/poh_recorder.rs @@ -28,8 +28,8 @@ use std::sync::{Arc, Mutex}; use std::time::Instant; use thiserror::Error; -const GRACE_TICKS_FACTOR: u64 = 2; -const MAX_GRACE_SLOTS: u64 = 2; +pub const GRACE_TICKS_FACTOR: u64 = 2; +pub const MAX_GRACE_SLOTS: u64 = 2; #[derive(Error, Debug, Clone)] pub enum PohRecorderError { @@ -85,6 +85,7 @@ impl PohRecorder { bank.slot(), &bank, Some(&self.blockstore), + GRACE_TICKS_FACTOR * MAX_GRACE_SLOTS, ); assert_eq!(self.ticks_per_slot, bank.ticks_per_slot()); let (leader_first_tick_height, leader_last_tick_height, grace_ticks) = diff --git a/core/src/replay_stage.rs b/core/src/replay_stage.rs index e54542c8ee..69e2ebe50d 100644 --- a/core/src/replay_stage.rs +++ b/core/src/replay_stage.rs @@ -4,7 +4,7 @@ use crate::{ cluster_info::ClusterInfo, commitment::{AggregateCommitmentService, BlockCommitmentCache, CommitmentAggregationData}, consensus::{StakeLockout, Tower}, - poh_recorder::PohRecorder, + poh_recorder::{PohRecorder, GRACE_TICKS_FACTOR, MAX_GRACE_SLOTS}, result::Result, rewards_recorder_service::RewardsRecorderSender, rpc_subscriptions::RpcSubscriptions, @@ -690,6 +690,7 @@ impl ReplayStage { bank.slot(), &bank, Some(blockstore), + GRACE_TICKS_FACTOR * MAX_GRACE_SLOTS, ); poh_recorder .lock() diff --git a/core/src/validator.rs b/core/src/validator.rs index a6aff425ae..4e90dda269 100644 --- a/core/src/validator.rs +++ b/core/src/validator.rs @@ -6,7 +6,7 @@ use crate::{ commitment::BlockCommitmentCache, contact_info::ContactInfo, gossip_service::{discover_cluster, GossipService}, - poh_recorder::PohRecorder, + poh_recorder::{PohRecorder, GRACE_TICKS_FACTOR, MAX_GRACE_SLOTS}, poh_service::PohService, rewards_recorder_service::RewardsRecorderService, rpc::JsonRpcConfig, @@ -308,7 +308,13 @@ impl Validator { bank.tick_height(), bank.last_blockhash(), bank.slot(), - leader_schedule_cache.next_leader_slot(&id, bank.slot(), &bank, Some(&blockstore)), + leader_schedule_cache.next_leader_slot( + &id, + bank.slot(), + &bank, + Some(&blockstore), + GRACE_TICKS_FACTOR * MAX_GRACE_SLOTS, + ), bank.ticks_per_slot(), &id, &blockstore, diff --git a/ledger/src/leader_schedule_cache.rs b/ledger/src/leader_schedule_cache.rs index e9c65a874c..9078a24c59 100644 --- a/ledger/src/leader_schedule_cache.rs +++ b/ledger/src/leader_schedule_cache.rs @@ -106,6 +106,7 @@ impl LeaderScheduleCache { mut current_slot: Slot, bank: &Bank, blockstore: Option<&Blockstore>, + max_slot_range: u64, ) -> Option<(Slot, Slot)> { let (mut epoch, mut start_index) = bank.get_epoch_and_slot_index(current_slot + 1); let mut first_slot = None; @@ -141,9 +142,14 @@ impl LeaderScheduleCache { } } - if first_slot.is_none() { + if let Some(first_slot) = first_slot { + if current_slot - first_slot + 1 >= max_slot_range { + return Some((first_slot, current_slot)); + } + } else { first_slot = Some(current_slot); } + last_slot = current_slot; } else if first_slot.is_some() { return Some((first_slot.unwrap(), last_slot)); @@ -264,6 +270,7 @@ mod tests { staking_utils::tests::setup_vote_and_stake_accounts, }; use solana_runtime::bank::Bank; + use solana_sdk::clock::NUM_CONSECUTIVE_LEADER_SLOTS; use solana_sdk::epoch_schedule::{ EpochSchedule, DEFAULT_LEADER_SCHEDULE_SLOT_OFFSET, DEFAULT_SLOTS_PER_EPOCH, MINIMUM_SLOTS_PER_EPOCH, @@ -395,11 +402,11 @@ mod tests { pubkey ); assert_eq!( - cache.next_leader_slot(&pubkey, 0, &bank, None), + cache.next_leader_slot(&pubkey, 0, &bank, None, std::u64::MAX), Some((1, 863999)) ); assert_eq!( - cache.next_leader_slot(&pubkey, 1, &bank, None), + cache.next_leader_slot(&pubkey, 1, &bank, None, std::u64::MAX), Some((2, 863999)) ); assert_eq!( @@ -407,7 +414,8 @@ mod tests { &pubkey, 2 * genesis_config.epoch_schedule.slots_per_epoch - 1, // no schedule generated for epoch 2 &bank, - None + None, + std::u64::MAX ), None ); @@ -417,7 +425,8 @@ mod tests { &Pubkey::new_rand(), // not in leader_schedule 0, &bank, - None + None, + std::u64::MAX ), None ); @@ -450,7 +459,7 @@ mod tests { // Check that the next leader slot after 0 is slot 1 assert_eq!( cache - .next_leader_slot(&pubkey, 0, &bank, Some(&blockstore)) + .next_leader_slot(&pubkey, 0, &bank, Some(&blockstore), std::u64::MAX) .unwrap() .0, 1 @@ -462,7 +471,7 @@ mod tests { blockstore.insert_shreds(shreds, None, false).unwrap(); assert_eq!( cache - .next_leader_slot(&pubkey, 0, &bank, Some(&blockstore)) + .next_leader_slot(&pubkey, 0, &bank, Some(&blockstore), std::u64::MAX) .unwrap() .0, 1 @@ -475,7 +484,7 @@ mod tests { blockstore.insert_shreds(shreds, None, false).unwrap(); assert_eq!( cache - .next_leader_slot(&pubkey, 0, &bank, Some(&blockstore)) + .next_leader_slot(&pubkey, 0, &bank, Some(&blockstore), std::u64::MAX) .unwrap() .0, 3 @@ -487,7 +496,8 @@ mod tests { &pubkey, 2 * genesis_config.epoch_schedule.slots_per_epoch - 1, // no schedule generated for epoch 2 &bank, - Some(&blockstore) + Some(&blockstore), + std::u64::MAX ), None ); @@ -497,7 +507,8 @@ mod tests { &Pubkey::new_rand(), // not in leader_schedule 0, &bank, - Some(&blockstore) + Some(&blockstore), + std::u64::MAX ), None ); @@ -553,17 +564,29 @@ mod tests { // If the max root isn't set, we'll get None assert!(cache - .next_leader_slot(&node_pubkey, 0, &bank, None) + .next_leader_slot(&node_pubkey, 0, &bank, None, std::u64::MAX) .is_none()); cache.set_root(&bank); - assert_eq!( - cache - .next_leader_slot(&node_pubkey, 0, &bank, None) - .unwrap() - .0, - expected_slot - ); + let res = cache + .next_leader_slot(&node_pubkey, 0, &bank, None, std::u64::MAX) + .unwrap(); + + assert_eq!(res.0, expected_slot); + assert!(res.1 >= expected_slot + NUM_CONSECUTIVE_LEADER_SLOTS - 1); + + let res = cache + .next_leader_slot( + &node_pubkey, + 0, + &bank, + None, + NUM_CONSECUTIVE_LEADER_SLOTS - 1, + ) + .unwrap(); + + assert_eq!(res.0, expected_slot); + assert_eq!(res.1, expected_slot + NUM_CONSECUTIVE_LEADER_SLOTS - 2); } #[test]