Generalize access to staked nodes
This commit is contained in:
@ -101,9 +101,8 @@ pub struct Bank {
|
|||||||
/// The number of slots in each epoch.
|
/// The number of slots in each epoch.
|
||||||
slots_per_epoch: u64,
|
slots_per_epoch: u64,
|
||||||
|
|
||||||
// A number of slots before slot_index 0. Used to generate the current
|
// A number of slots before slot_index 0. Used to calculate finalized staked nodes.
|
||||||
// epoch's leader schedule.
|
stakers_slot_offset: u64,
|
||||||
leader_schedule_slot_offset: u64,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bank {
|
impl Bank {
|
||||||
@ -120,7 +119,7 @@ impl Bank {
|
|||||||
bank.last_id_queue = RwLock::new(parent.last_id_queue.read().unwrap().clone());
|
bank.last_id_queue = RwLock::new(parent.last_id_queue.read().unwrap().clone());
|
||||||
bank.ticks_per_slot = parent.ticks_per_slot;
|
bank.ticks_per_slot = parent.ticks_per_slot;
|
||||||
bank.slots_per_epoch = parent.slots_per_epoch;
|
bank.slots_per_epoch = parent.slots_per_epoch;
|
||||||
bank.leader_schedule_slot_offset = parent.leader_schedule_slot_offset;
|
bank.stakers_slot_offset = parent.stakers_slot_offset;
|
||||||
|
|
||||||
bank.parent = Some(parent.clone());
|
bank.parent = Some(parent.clone());
|
||||||
if *parent.hash.read().unwrap() == Hash::default() {
|
if *parent.hash.read().unwrap() == Hash::default() {
|
||||||
@ -201,7 +200,7 @@ impl Bank {
|
|||||||
|
|
||||||
self.ticks_per_slot = genesis_block.ticks_per_slot;
|
self.ticks_per_slot = genesis_block.ticks_per_slot;
|
||||||
self.slots_per_epoch = genesis_block.slots_per_epoch;
|
self.slots_per_epoch = genesis_block.slots_per_epoch;
|
||||||
self.leader_schedule_slot_offset = genesis_block.leader_schedule_slot_offset;
|
self.stakers_slot_offset = genesis_block.stakers_slot_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_native_program(&self, name: &str, program_id: &Pubkey) {
|
pub fn add_native_program(&self, name: &str, program_id: &Pubkey) {
|
||||||
@ -685,22 +684,25 @@ impl Bank {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return the checkpointed stakes that should be used to generate a leader schedule.
|
/// Return the checkpointed stakes that should be used to generate a leader schedule.
|
||||||
fn leader_schedule_stakes(&self, epoch_height: u64) -> HashMap<Pubkey, u64> {
|
fn staked_nodes_at_epoch(&self, epoch_height: u64) -> HashMap<Pubkey, u64> {
|
||||||
let epoch_slot_height = epoch_height * self.slots_per_epoch();
|
let epoch_slot_height = epoch_height * self.slots_per_epoch();
|
||||||
let expected = epoch_slot_height.saturating_sub(self.leader_schedule_slot_offset);
|
let expected = epoch_slot_height.saturating_sub(self.stakers_slot_offset);
|
||||||
if self.slot_height() <= expected {
|
|
||||||
return self.staked_nodes();
|
let parents = self.parents();
|
||||||
}
|
let mut banks = vec![self];
|
||||||
self.parents()
|
banks.extend(parents.iter().map(|x| x.as_ref()));
|
||||||
.into_iter()
|
|
||||||
|
let bank = banks
|
||||||
|
.iter()
|
||||||
.find(|bank| bank.slot_height() <= expected)
|
.find(|bank| bank.slot_height() <= expected)
|
||||||
.map(|bank| bank.staked_nodes())
|
.unwrap_or_else(|| banks.last().unwrap());
|
||||||
.unwrap()
|
|
||||||
|
bank.staked_nodes()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the leader schedule for the given epoch.
|
/// Return the leader schedule for the given epoch.
|
||||||
fn leader_schedule(&self, epoch_height: u64) -> LeaderSchedule {
|
fn leader_schedule(&self, epoch_height: u64) -> LeaderSchedule {
|
||||||
let stakes = self.leader_schedule_stakes(epoch_height);
|
let stakes = self.staked_nodes_at_epoch(epoch_height);
|
||||||
let mut seed = [0u8; 32];
|
let mut seed = [0u8; 32];
|
||||||
seed[0..8].copy_from_slice(&epoch_height.to_le_bytes());
|
seed[0..8].copy_from_slice(&epoch_height.to_le_bytes());
|
||||||
let stakes: Vec<_> = stakes.into_iter().collect();
|
let stakes: Vec<_> = stakes.into_iter().collect();
|
||||||
@ -1194,24 +1196,24 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_leader_schedule_stakes() {
|
fn test_bank_staked_nodes_at_epoch() {
|
||||||
let pubkey = Keypair::new().pubkey();
|
let pubkey = Keypair::new().pubkey();
|
||||||
let bootstrap_tokens = 2;
|
let bootstrap_tokens = 2;
|
||||||
let (genesis_block, _) = GenesisBlock::new_with_leader(2, pubkey, bootstrap_tokens);
|
let (genesis_block, _) = GenesisBlock::new_with_leader(2, pubkey, bootstrap_tokens);
|
||||||
let bank = Bank::new(&genesis_block);
|
let bank = Bank::new(&genesis_block);
|
||||||
let bank = Bank::new_from_parent(&Arc::new(bank));
|
let bank = Bank::new_from_parent(&Arc::new(bank));
|
||||||
let ticks_per_offset = bank.leader_schedule_slot_offset * bank.ticks_per_slot();
|
let ticks_per_offset = bank.stakers_slot_offset * bank.ticks_per_slot();
|
||||||
register_ticks(&bank, ticks_per_offset);
|
register_ticks(&bank, ticks_per_offset);
|
||||||
assert_eq!(bank.slot_height(), bank.leader_schedule_slot_offset);
|
assert_eq!(bank.slot_height(), bank.stakers_slot_offset);
|
||||||
|
|
||||||
let mut expected = HashMap::new();
|
let mut expected = HashMap::new();
|
||||||
expected.insert(pubkey, bootstrap_tokens - 1);
|
expected.insert(pubkey, bootstrap_tokens - 1);
|
||||||
let bank = Bank::new_from_parent(&Arc::new(bank));
|
let bank = Bank::new_from_parent(&Arc::new(bank));
|
||||||
assert_eq!(bank.leader_schedule_stakes(bank.epoch_height()), expected,);
|
assert_eq!(bank.staked_nodes_at_epoch(bank.epoch_height()), expected,);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_leader_schedule_basic() {
|
fn test_bank_leader_schedule_basic() {
|
||||||
let pubkey = Keypair::new().pubkey();
|
let pubkey = Keypair::new().pubkey();
|
||||||
let (genesis_block, _mint_keypair) = GenesisBlock::new_with_leader(2, pubkey, 2);
|
let (genesis_block, _mint_keypair) = GenesisBlock::new_with_leader(2, pubkey, 2);
|
||||||
let bank = Bank::new(&genesis_block);
|
let bank = Bank::new(&genesis_block);
|
||||||
|
@ -22,7 +22,7 @@ pub struct GenesisBlock {
|
|||||||
pub tokens: u64,
|
pub tokens: u64,
|
||||||
pub ticks_per_slot: u64,
|
pub ticks_per_slot: u64,
|
||||||
pub slots_per_epoch: u64,
|
pub slots_per_epoch: u64,
|
||||||
pub leader_schedule_slot_offset: u64,
|
pub stakers_slot_offset: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GenesisBlock {
|
impl GenesisBlock {
|
||||||
@ -50,7 +50,7 @@ impl GenesisBlock {
|
|||||||
tokens,
|
tokens,
|
||||||
ticks_per_slot: DEFAULT_TICKS_PER_SLOT,
|
ticks_per_slot: DEFAULT_TICKS_PER_SLOT,
|
||||||
slots_per_epoch: DEFAULT_SLOTS_PER_EPOCH,
|
slots_per_epoch: DEFAULT_SLOTS_PER_EPOCH,
|
||||||
leader_schedule_slot_offset: DEFAULT_SLOTS_PER_EPOCH,
|
stakers_slot_offset: DEFAULT_SLOTS_PER_EPOCH,
|
||||||
},
|
},
|
||||||
mint_keypair,
|
mint_keypair,
|
||||||
)
|
)
|
||||||
|
Reference in New Issue
Block a user