Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ledger/src/leader_schedule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use {
rand::distributions::{Distribution, WeightedIndex},
rand_chacha::{rand_core::SeedableRng, ChaChaRng},
solana_clock::Epoch,
solana_pubkey::Pubkey,
solana_pubkey::{Pubkey, PubkeyHasherBuilder},
std::{collections::HashMap, convert::identity, ops::Index, sync::Arc},
};

Expand All @@ -26,7 +26,7 @@ pub trait LeaderScheduleVariant:
std::fmt::Debug + Send + Sync + Index<u64, Output = Pubkey>
{
fn get_slot_leaders(&self) -> &[Pubkey];
fn get_leader_slots_map(&self) -> &HashMap<Pubkey, Vec<usize>>;
fn get_leader_slots_map(&self) -> &HashMap<Pubkey, Vec<usize>, PubkeyHasherBuilder>;

/// Get the vote account address for the given epoch slot index. This is
/// guaranteed to be Some if the leader schedule is keyed by vote account
Expand Down
45 changes: 32 additions & 13 deletions ledger/src/leader_schedule/identity_keyed.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
#[cfg(feature = "dev-context-only-utils")]
use qualifier_attr::qualifiers;
use {
super::{stake_weighted_slot_leaders, LeaderScheduleVariant},
itertools::Itertools,
solana_clock::Epoch,
solana_pubkey::Pubkey,
solana_pubkey::{Pubkey, PubkeyHasherBuilder},
std::{collections::HashMap, ops::Index},
};

#[derive(Default, Debug, PartialEq, Eq, Clone)]
pub struct LeaderSchedule {
slot_leaders: Vec<Pubkey>,
// Inverted index from pubkeys to indices where they are the leader.
leader_slots_map: HashMap<Pubkey, Vec<usize>>,
leader_slots_map: HashMap<Pubkey, Vec<usize>, PubkeyHasherBuilder>,
}

impl LeaderSchedule {
Expand All @@ -26,22 +27,40 @@ impl LeaderSchedule {
.map(|(pubkey, stake)| (pubkey, *stake))
.collect();
let slot_leaders = stake_weighted_slot_leaders(keyed_stakes, epoch, len, repeat);
Self::new_from_schedule(slot_leaders)
Self {
leader_slots_map: Self::invert_slot_leaders(
&slot_leaders,
Some(epoch_staked_nodes.len()),
),
slot_leaders,
}
}

#[cfg_attr(feature = "dev-context-only-utils", qualifiers(pub))]
pub fn new_from_schedule(slot_leaders: Vec<Pubkey>) -> Self {
Self {
leader_slots_map: Self::invert_slot_leaders(&slot_leaders),
leader_slots_map: Self::invert_slot_leaders(&slot_leaders, None),
slot_leaders,
}
}

fn invert_slot_leaders(slot_leaders: &[Pubkey]) -> HashMap<Pubkey, Vec<usize>> {
slot_leaders
.iter()
.enumerate()
.map(|(i, pk)| (*pk, i))
.into_group_map()
fn invert_slot_leaders(
slot_leaders: &[Pubkey],
nodes_len: Option<usize>,
) -> HashMap<Pubkey, Vec<usize>, PubkeyHasherBuilder> {
let mut grouped_slot_leaders = match nodes_len {
Some(nodes_len) => {
HashMap::with_capacity_and_hasher(nodes_len, PubkeyHasherBuilder::default())
}
None => HashMap::with_hasher(PubkeyHasherBuilder::default()),
};
for (slot, leader) in slot_leaders.iter().enumerate() {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kamil's comment made me realize that slot_leaders will always be setup so that the same leader will always the same for 4 consecutive slots. We could use that fact to do more optimizing

grouped_slot_leaders
.entry(*leader)
.and_modify(|slots: &mut Vec<usize>| slots.push(slot))
.or_insert(vec![slot]);
}
grouped_slot_leaders
}

pub fn get_slot_leaders(&self) -> &[Pubkey] {
Expand All @@ -54,7 +73,7 @@ impl LeaderScheduleVariant for LeaderSchedule {
&self.slot_leaders
}

fn get_leader_slots_map(&self) -> &HashMap<Pubkey, Vec<usize>> {
fn get_leader_slots_map(&self) -> &HashMap<Pubkey, Vec<usize>, PubkeyHasherBuilder> {
&self.leader_slots_map
}
}
Expand Down Expand Up @@ -180,7 +199,7 @@ mod tests {
victor_pubkey,
];

let grouped_slot_leaders = LeaderSchedule::invert_slot_leaders(leaders);
let grouped_slot_leaders = LeaderSchedule::invert_slot_leaders(leaders, Some(4));
assert_eq!(
grouped_slot_leaders.get(&alice_pubkey).unwrap().as_slice(),
&[0, 2, 5],
Expand Down
4 changes: 2 additions & 2 deletions ledger/src/leader_schedule/vote_keyed.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use {
super::{stake_weighted_slot_leaders, IdentityKeyedLeaderSchedule, LeaderScheduleVariant},
solana_clock::Epoch,
solana_pubkey::Pubkey,
solana_pubkey::{Pubkey, PubkeyHasherBuilder},
solana_vote::vote_account::VoteAccountsHashMap,
std::{collections::HashMap, ops::Index},
};
Expand Down Expand Up @@ -80,7 +80,7 @@ impl LeaderScheduleVariant for LeaderSchedule {
self.identity_keyed_leader_schedule.get_slot_leaders()
}

fn get_leader_slots_map(&self) -> &HashMap<Pubkey, Vec<usize>> {
fn get_leader_slots_map(&self) -> &HashMap<Pubkey, Vec<usize>, PubkeyHasherBuilder> {
self.identity_keyed_leader_schedule.get_leader_slots_map()
}

Expand Down
Loading