add epoch_schedule sysvar (#6256)
* add epoch_schedule sysvar * book sheesh!
This commit is contained in:
@ -462,20 +462,21 @@ fn process_pending_slots(
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
use crate::blocktree::create_new_tmp_ledger;
|
||||
use crate::entry::{create_ticks, next_entry, next_entry_mut, Entry};
|
||||
use crate::genesis_utils::{
|
||||
create_genesis_block, create_genesis_block_with_leader, GenesisBlockInfo,
|
||||
use crate::{
|
||||
blocktree::create_new_tmp_ledger,
|
||||
entry::{create_ticks, next_entry, next_entry_mut, Entry},
|
||||
genesis_utils::{create_genesis_block, create_genesis_block_with_leader, GenesisBlockInfo},
|
||||
};
|
||||
use rand::{thread_rng, Rng};
|
||||
use solana_runtime::epoch_schedule::EpochSchedule;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::instruction::InstructionError;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::system_transaction;
|
||||
use solana_sdk::transaction::Transaction;
|
||||
use solana_sdk::transaction::TransactionError;
|
||||
use solana_sdk::{
|
||||
epoch_schedule::EpochSchedule,
|
||||
hash::Hash,
|
||||
instruction::InstructionError,
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, KeypairUtil},
|
||||
system_transaction,
|
||||
transaction::{Transaction, TransactionError},
|
||||
};
|
||||
use std::sync::RwLock;
|
||||
|
||||
pub fn fill_blocktree_slot_with_ticks(
|
||||
|
@ -62,7 +62,7 @@ impl BroadcastRun for FailEntryVerificationBroadcastRun {
|
||||
.expect("Failed to insert shreds in blocktree");
|
||||
|
||||
// 3) Start broadcast step
|
||||
let bank_epoch = bank.get_stakers_epoch(bank.slot());
|
||||
let bank_epoch = bank.get_leader_schedule_epoch(bank.slot());
|
||||
let stakes = staking_utils::staked_nodes_at_epoch(&bank, bank_epoch);
|
||||
|
||||
let all_shred_bufs: Vec<Vec<u8>> = data_shreds
|
||||
|
@ -192,7 +192,7 @@ impl BroadcastRun for StandardBroadcastRun {
|
||||
|
||||
// 3) Start broadcast step
|
||||
let broadcast_start = Instant::now();
|
||||
let bank_epoch = bank.get_stakers_epoch(bank.slot());
|
||||
let bank_epoch = bank.get_leader_schedule_epoch(bank.slot());
|
||||
let stakes = staking_utils::staked_nodes_at_epoch(&bank, bank_epoch);
|
||||
|
||||
let all_shred_bufs: Vec<Vec<u8>> = data_shreds
|
||||
|
@ -8,17 +8,18 @@ use rand::seq::SliceRandom;
|
||||
use rand::SeedableRng;
|
||||
use rand_chacha::ChaChaRng;
|
||||
use solana_metrics::datapoint;
|
||||
use solana_runtime::epoch_schedule::EpochSchedule;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::cmp;
|
||||
use std::collections::HashMap;
|
||||
use std::mem;
|
||||
use std::net::SocketAddr;
|
||||
use std::net::UdpSocket;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::thread::{self, sleep, Builder, JoinHandle};
|
||||
use std::time::Duration;
|
||||
use solana_sdk::{epoch_schedule::EpochSchedule, pubkey::Pubkey};
|
||||
use std::{
|
||||
cmp,
|
||||
collections::HashMap,
|
||||
mem,
|
||||
net::SocketAddr,
|
||||
net::UdpSocket,
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
sync::{Arc, RwLock},
|
||||
thread::{self, sleep, Builder, JoinHandle},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
pub const REPAIRMEN_SLEEP_MILLIS: usize = 100;
|
||||
pub const REPAIR_REDUNDANCY: usize = 1;
|
||||
@ -278,7 +279,7 @@ impl ClusterInfoRepairListener {
|
||||
let mut total_coding_blobs_sent = 0;
|
||||
let mut num_slots_repaired = 0;
|
||||
let max_confirmed_repairee_epoch =
|
||||
epoch_schedule.get_stakers_epoch(repairee_epoch_slots.root);
|
||||
epoch_schedule.get_leader_schedule_epoch(repairee_epoch_slots.root);
|
||||
let max_confirmed_repairee_slot =
|
||||
epoch_schedule.get_last_slot_in_epoch(max_confirmed_repairee_epoch);
|
||||
|
||||
@ -655,7 +656,7 @@ mod tests {
|
||||
let eligible_repairmen_refs: Vec<_> = eligible_repairmen.iter().collect();
|
||||
|
||||
// Have all the repairman send the repairs
|
||||
let epoch_schedule = EpochSchedule::new(32, 16, false);
|
||||
let epoch_schedule = EpochSchedule::custom(32, 16, false);
|
||||
let num_missing_slots = num_slots / 2;
|
||||
for repairman_pubkey in &eligible_repairmen {
|
||||
ClusterInfoRepairListener::serve_repairs_to_repairee(
|
||||
@ -699,7 +700,7 @@ mod tests {
|
||||
let blocktree = Blocktree::open(&blocktree_path).unwrap();
|
||||
let stakers_slot_offset = 16;
|
||||
let slots_per_epoch = stakers_slot_offset * 2;
|
||||
let epoch_schedule = EpochSchedule::new(slots_per_epoch, stakers_slot_offset, false);
|
||||
let epoch_schedule = EpochSchedule::custom(slots_per_epoch, stakers_slot_offset, false);
|
||||
|
||||
// Create blobs for first two epochs and write them to blocktree
|
||||
let total_slots = slots_per_epoch * 2;
|
||||
|
@ -1,12 +1,10 @@
|
||||
use crate::blocktree::Blocktree;
|
||||
use crate::leader_schedule::LeaderSchedule;
|
||||
use crate::leader_schedule_utils;
|
||||
use crate::{blocktree::Blocktree, leader_schedule::LeaderSchedule, leader_schedule_utils};
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_runtime::epoch_schedule::EpochSchedule;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::sync::{Arc, RwLock};
|
||||
use solana_sdk::{epoch_schedule::EpochSchedule, pubkey::Pubkey};
|
||||
use std::{
|
||||
collections::{hash_map::Entry, HashMap, VecDeque},
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
type CachedSchedules = (HashMap<u64, Arc<LeaderSchedule>>, VecDeque<u64>);
|
||||
const MAX_SCHEDULES: usize = 10;
|
||||
@ -40,11 +38,11 @@ impl LeaderScheduleCache {
|
||||
max_schedules: CacheCapacity::default(),
|
||||
};
|
||||
|
||||
// This sets the root and calculates the schedule at stakers_epoch(root)
|
||||
// This sets the root and calculates the schedule at leader_schedule_epoch(root)
|
||||
cache.set_root(root_bank);
|
||||
|
||||
// Calculate the schedule for all epochs between 0 and stakers_epoch(root)
|
||||
let stakers_epoch = epoch_schedule.get_stakers_epoch(root_bank.slot());
|
||||
// Calculate the schedule for all epochs between 0 and leader_schedule_epoch(root)
|
||||
let stakers_epoch = epoch_schedule.get_leader_schedule_epoch(root_bank.slot());
|
||||
for epoch in 0..stakers_epoch {
|
||||
let first_slot_in_epoch = epoch_schedule.get_first_slot_in_epoch(epoch);
|
||||
cache.slot_leader_at(first_slot_in_epoch, Some(root_bank));
|
||||
@ -63,7 +61,9 @@ impl LeaderScheduleCache {
|
||||
}
|
||||
|
||||
pub fn set_root(&self, root_bank: &Bank) {
|
||||
let new_max_epoch = self.epoch_schedule.get_stakers_epoch(root_bank.slot());
|
||||
let new_max_epoch = self
|
||||
.epoch_schedule
|
||||
.get_leader_schedule_epoch(root_bank.slot());
|
||||
let old_max_epoch = {
|
||||
let mut max_epoch = self.max_epoch.write().unwrap();
|
||||
let old_max_epoch = *max_epoch;
|
||||
@ -229,19 +229,20 @@ impl LeaderScheduleCache {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::blocktree::tests::make_slot_entries;
|
||||
use crate::genesis_utils::create_genesis_block;
|
||||
use crate::genesis_utils::{
|
||||
create_genesis_block_with_leader, GenesisBlockInfo, BOOTSTRAP_LEADER_LAMPORTS,
|
||||
use crate::{
|
||||
blocktree::{get_tmp_ledger_path, tests::make_slot_entries},
|
||||
genesis_utils::{
|
||||
create_genesis_block, create_genesis_block_with_leader, GenesisBlockInfo,
|
||||
BOOTSTRAP_LEADER_LAMPORTS,
|
||||
},
|
||||
staking_utils::tests::setup_vote_and_stake_accounts,
|
||||
};
|
||||
use crate::staking_utils::tests::setup_vote_and_stake_accounts;
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_runtime::epoch_schedule::{EpochSchedule, MINIMUM_SLOTS_PER_EPOCH};
|
||||
use std::sync::mpsc::channel;
|
||||
use std::sync::Arc;
|
||||
use std::thread::Builder;
|
||||
|
||||
use crate::blocktree::get_tmp_ledger_path;
|
||||
use solana_sdk::epoch_schedule::{
|
||||
EpochSchedule, DEFAULT_LEADER_SCHEDULE_SLOT_OFFSET, DEFAULT_SLOTS_PER_EPOCH,
|
||||
MINIMUM_SLOTS_PER_EPOCH,
|
||||
};
|
||||
use std::{sync::mpsc::channel, sync::Arc, thread::Builder};
|
||||
|
||||
#[test]
|
||||
fn test_new_cache() {
|
||||
@ -255,7 +256,7 @@ mod tests {
|
||||
// [0, stakers_epoch(bank.slot())] should
|
||||
// be calculated by constructor
|
||||
let epoch_schedule = bank.epoch_schedule();
|
||||
let stakers_epoch = bank.get_stakers_epoch(bank.slot());
|
||||
let stakers_epoch = bank.get_leader_schedule_epoch(bank.slot());
|
||||
for epoch in 0..=stakers_epoch {
|
||||
let first_slot_in_stakers_epoch = epoch_schedule.get_first_slot_in_epoch(epoch);
|
||||
let last_slot_in_stakers_epoch = epoch_schedule.get_last_slot_in_epoch(epoch);
|
||||
@ -307,7 +308,7 @@ mod tests {
|
||||
|
||||
fn run_thread_race() {
|
||||
let slots_per_epoch = MINIMUM_SLOTS_PER_EPOCH as u64;
|
||||
let epoch_schedule = EpochSchedule::new(slots_per_epoch, slots_per_epoch / 2, true);
|
||||
let epoch_schedule = EpochSchedule::custom(slots_per_epoch, slots_per_epoch / 2, true);
|
||||
let GenesisBlockInfo { genesis_block, .. } = create_genesis_block(2);
|
||||
let bank = Arc::new(Bank::new(&genesis_block));
|
||||
let cache = Arc::new(LeaderScheduleCache::new(epoch_schedule, &bank));
|
||||
@ -353,7 +354,11 @@ mod tests {
|
||||
BOOTSTRAP_LEADER_LAMPORTS,
|
||||
)
|
||||
.genesis_block;
|
||||
genesis_block.epoch_warmup = false;
|
||||
genesis_block.epoch_schedule = EpochSchedule::custom(
|
||||
DEFAULT_SLOTS_PER_EPOCH,
|
||||
DEFAULT_LEADER_SCHEDULE_SLOT_OFFSET,
|
||||
false,
|
||||
);
|
||||
|
||||
let bank = Bank::new(&genesis_block);
|
||||
let cache = Arc::new(LeaderScheduleCache::new_from_bank(&bank));
|
||||
@ -373,7 +378,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
cache.next_leader_slot(
|
||||
&pubkey,
|
||||
2 * genesis_block.slots_per_epoch - 1, // no schedule generated for epoch 2
|
||||
2 * genesis_block.epoch_schedule.slots_per_epoch - 1, // no schedule generated for epoch 2
|
||||
&bank,
|
||||
None
|
||||
),
|
||||
@ -400,7 +405,7 @@ mod tests {
|
||||
BOOTSTRAP_LEADER_LAMPORTS,
|
||||
)
|
||||
.genesis_block;
|
||||
genesis_block.epoch_warmup = false;
|
||||
genesis_block.epoch_schedule.warmup = false;
|
||||
|
||||
let bank = Bank::new(&genesis_block);
|
||||
let cache = Arc::new(LeaderScheduleCache::new_from_bank(&bank));
|
||||
@ -452,7 +457,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
cache.next_leader_slot(
|
||||
&pubkey,
|
||||
2 * genesis_block.slots_per_epoch - 1, // no schedule generated for epoch 2
|
||||
2 * genesis_block.epoch_schedule.slots_per_epoch - 1, // no schedule generated for epoch 2
|
||||
&bank,
|
||||
Some(&blocktree)
|
||||
),
|
||||
@ -479,7 +484,7 @@ mod tests {
|
||||
mint_keypair,
|
||||
..
|
||||
} = create_genesis_block(10_000);
|
||||
genesis_block.epoch_warmup = false;
|
||||
genesis_block.epoch_schedule.warmup = false;
|
||||
|
||||
let bank = Bank::new(&genesis_block);
|
||||
let cache = Arc::new(LeaderScheduleCache::new_from_bank(&bank));
|
||||
@ -498,14 +503,14 @@ mod tests {
|
||||
// Have to wait until the epoch at after the epoch stakes generated at genesis
|
||||
// for the new votes to take effect.
|
||||
let mut target_slot = 1;
|
||||
let epoch = bank.get_stakers_epoch(0);
|
||||
while bank.get_stakers_epoch(target_slot) == epoch {
|
||||
let epoch = bank.get_leader_schedule_epoch(0);
|
||||
while bank.get_leader_schedule_epoch(target_slot) == epoch {
|
||||
target_slot += 1;
|
||||
}
|
||||
|
||||
let bank = Bank::new_from_parent(&Arc::new(bank), &Pubkey::default(), target_slot);
|
||||
let mut expected_slot = 0;
|
||||
let epoch = bank.get_stakers_epoch(target_slot);
|
||||
let epoch = bank.get_leader_schedule_epoch(target_slot);
|
||||
for i in 0..epoch {
|
||||
expected_slot += bank.get_slots_in_epoch(i);
|
||||
}
|
||||
@ -514,7 +519,7 @@ mod tests {
|
||||
let mut index = 0;
|
||||
while schedule[index] != node_pubkey {
|
||||
index += 1;
|
||||
assert_ne!(index, genesis_block.slots_per_epoch);
|
||||
assert_ne!(index, genesis_block.epoch_schedule.slots_per_epoch);
|
||||
}
|
||||
expected_slot += index;
|
||||
|
||||
|
@ -69,7 +69,7 @@ mod tests {
|
||||
let leader_schedule = LeaderSchedule::new(
|
||||
&pubkeys_and_stakes,
|
||||
seed,
|
||||
genesis_block.slots_per_epoch,
|
||||
genesis_block.epoch_schedule.slots_per_epoch,
|
||||
NUM_CONSECUTIVE_LEADER_SLOTS,
|
||||
);
|
||||
|
||||
|
@ -1,22 +1,24 @@
|
||||
//! The `repair_service` module implements the tools necessary to generate a thread which
|
||||
//! regularly finds missing blobs in the ledger and sends repair requests for those blobs
|
||||
use crate::bank_forks::BankForks;
|
||||
use crate::blocktree::{Blocktree, CompletedSlotsReceiver, SlotMeta};
|
||||
use crate::cluster_info::ClusterInfo;
|
||||
use crate::cluster_info_repair_listener::ClusterInfoRepairListener;
|
||||
use crate::result::Result;
|
||||
use crate::service::Service;
|
||||
use solana_metrics::datapoint_debug;
|
||||
use solana_runtime::epoch_schedule::EpochSchedule;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::collections::BTreeSet;
|
||||
use std::net::UdpSocket;
|
||||
use std::ops::Bound::{Excluded, Unbounded};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::thread::sleep;
|
||||
use std::thread::{self, Builder, JoinHandle};
|
||||
use std::time::Duration;
|
||||
use crate::{
|
||||
bank_forks::BankForks,
|
||||
blocktree::{Blocktree, CompletedSlotsReceiver, SlotMeta},
|
||||
cluster_info::ClusterInfo,
|
||||
cluster_info_repair_listener::ClusterInfoRepairListener,
|
||||
result::Result,
|
||||
service::Service,
|
||||
};
|
||||
use solana_sdk::{epoch_schedule::EpochSchedule, pubkey::Pubkey};
|
||||
use std::{
|
||||
collections::BTreeSet,
|
||||
net::UdpSocket,
|
||||
ops::Bound::{Excluded, Unbounded},
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
sync::{Arc, RwLock},
|
||||
thread::sleep,
|
||||
thread::{self, Builder, JoinHandle},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
pub const MAX_REPAIR_LENGTH: usize = 16;
|
||||
pub const REPAIR_MS: u64 = 100;
|
||||
@ -299,7 +301,7 @@ impl RepairService {
|
||||
root: u64,
|
||||
epoch_schedule: &EpochSchedule,
|
||||
) {
|
||||
let last_confirmed_epoch = epoch_schedule.get_stakers_epoch(root);
|
||||
let last_confirmed_epoch = epoch_schedule.get_leader_schedule_epoch(root);
|
||||
let last_epoch_slot = epoch_schedule.get_last_slot_in_epoch(last_confirmed_epoch);
|
||||
|
||||
let meta_iter = blocktree
|
||||
@ -652,7 +654,7 @@ mod test {
|
||||
.unwrap();
|
||||
|
||||
// Test that only slots > root from fork1 were included
|
||||
let epoch_schedule = EpochSchedule::new(32, 32, false);
|
||||
let epoch_schedule = EpochSchedule::custom(32, 32, false);
|
||||
|
||||
RepairService::get_completed_slots_past_root(
|
||||
&blocktree,
|
||||
@ -665,7 +667,7 @@ mod test {
|
||||
assert_eq!(full_slots, expected);
|
||||
|
||||
// Test that slots past the last confirmed epoch boundary don't get included
|
||||
let last_epoch = epoch_schedule.get_stakers_epoch(root);
|
||||
let last_epoch = epoch_schedule.get_leader_schedule_epoch(root);
|
||||
let last_slot = epoch_schedule.get_last_slot_in_epoch(last_epoch);
|
||||
let fork3 = vec![last_slot, last_slot + 1];
|
||||
let fork3_shreds: Vec<_> = make_chaining_slot_entries(&fork3, num_entries_per_slot)
|
||||
|
@ -1005,7 +1005,7 @@ mod test {
|
||||
create_genesis_block_with_leader(50, &leader_pubkey, leader_lamports);
|
||||
let mut genesis_block = genesis_block_info.genesis_block;
|
||||
let leader_voting_pubkey = genesis_block_info.voting_keypair.pubkey();
|
||||
genesis_block.epoch_warmup = false;
|
||||
genesis_block.epoch_schedule.warmup = false;
|
||||
genesis_block.ticks_per_slot = 4;
|
||||
let bank0 = Bank::new(&genesis_block);
|
||||
for _ in 1..genesis_block.ticks_per_slot {
|
||||
|
@ -1,28 +1,32 @@
|
||||
//! The `retransmit_stage` retransmits blobs between validators
|
||||
|
||||
use crate::bank_forks::BankForks;
|
||||
use crate::blocktree::{Blocktree, CompletedSlotsReceiver};
|
||||
use crate::cluster_info::{compute_retransmit_peers, ClusterInfo, DATA_PLANE_FANOUT};
|
||||
use crate::leader_schedule_cache::LeaderScheduleCache;
|
||||
use crate::repair_service::RepairStrategy;
|
||||
use crate::result::{Error, Result};
|
||||
use crate::service::Service;
|
||||
use crate::staking_utils;
|
||||
use crate::streamer::PacketReceiver;
|
||||
use crate::window_service::{should_retransmit_and_persist, WindowService};
|
||||
use crate::{
|
||||
bank_forks::BankForks,
|
||||
blocktree::{Blocktree, CompletedSlotsReceiver},
|
||||
cluster_info::{compute_retransmit_peers, ClusterInfo, DATA_PLANE_FANOUT},
|
||||
leader_schedule_cache::LeaderScheduleCache,
|
||||
repair_service::RepairStrategy,
|
||||
result::{Error, Result},
|
||||
service::Service,
|
||||
staking_utils,
|
||||
streamer::PacketReceiver,
|
||||
window_service::{should_retransmit_and_persist, WindowService},
|
||||
};
|
||||
use rand::SeedableRng;
|
||||
use rand_chacha::ChaChaRng;
|
||||
use solana_measure::measure::Measure;
|
||||
use solana_metrics::{datapoint_debug, inc_new_counter_error};
|
||||
use solana_runtime::epoch_schedule::EpochSchedule;
|
||||
use std::cmp;
|
||||
use std::net::UdpSocket;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::mpsc::channel;
|
||||
use std::sync::mpsc::RecvTimeoutError;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::thread::{self, Builder, JoinHandle};
|
||||
use std::time::Duration;
|
||||
use solana_metrics::inc_new_counter_error;
|
||||
use solana_sdk::epoch_schedule::EpochSchedule;
|
||||
use std::{
|
||||
cmp,
|
||||
net::UdpSocket,
|
||||
sync::atomic::AtomicBool,
|
||||
sync::mpsc::channel,
|
||||
sync::mpsc::RecvTimeoutError,
|
||||
sync::{Arc, RwLock},
|
||||
thread::{self, Builder, JoinHandle},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
pub fn retransmit(
|
||||
bank_forks: &Arc<RwLock<BankForks>>,
|
||||
@ -42,7 +46,7 @@ pub fn retransmit(
|
||||
}
|
||||
|
||||
let r_bank = bank_forks.read().unwrap().working_bank();
|
||||
let bank_epoch = r_bank.get_stakers_epoch(r_bank.slot());
|
||||
let bank_epoch = r_bank.get_leader_schedule_epoch(r_bank.slot());
|
||||
let mut peers_len = 0;
|
||||
let stakes = staking_utils::staked_nodes_at_epoch(&r_bank, bank_epoch);
|
||||
let (peers, stakes_and_index) = cluster_info
|
||||
|
@ -211,27 +211,27 @@ pub(crate) mod tests {
|
||||
..Stake::default()
|
||||
};
|
||||
|
||||
let first_stakers_epoch = bank.get_stakers_epoch(bank.slot());
|
||||
// find the first slot in the next staker's epoch
|
||||
let first_leader_schedule_epoch = bank.get_leader_schedule_epoch(bank.slot());
|
||||
// find the first slot in the next leader schedule epoch
|
||||
let mut slot = bank.slot();
|
||||
loop {
|
||||
slot += 1;
|
||||
if bank.get_stakers_epoch(slot) != first_stakers_epoch {
|
||||
if bank.get_leader_schedule_epoch(slot) != first_leader_schedule_epoch {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let bank = new_from_parent(&Arc::new(bank), slot);
|
||||
let next_stakers_epoch = bank.get_stakers_epoch(slot);
|
||||
let next_leader_schedule_epoch = bank.get_leader_schedule_epoch(slot);
|
||||
|
||||
let result: Vec<_> = epoch_stakes_and_lockouts(&bank, first_stakers_epoch);
|
||||
let result: Vec<_> = epoch_stakes_and_lockouts(&bank, first_leader_schedule_epoch);
|
||||
assert_eq!(
|
||||
result,
|
||||
vec![(leader_stake.stake(first_stakers_epoch, None), None)]
|
||||
vec![(leader_stake.stake(first_leader_schedule_epoch, None), None)]
|
||||
);
|
||||
|
||||
// epoch stakes and lockouts are saved off for the future epoch, should
|
||||
// match current bank state
|
||||
let mut result: Vec<_> = epoch_stakes_and_lockouts(&bank, next_stakers_epoch);
|
||||
let mut result: Vec<_> = epoch_stakes_and_lockouts(&bank, next_leader_schedule_epoch);
|
||||
result.sort();
|
||||
let stake_history =
|
||||
StakeHistory::from_account(&bank.get_account(&stake_history::id()).unwrap()).unwrap();
|
||||
|
@ -296,8 +296,8 @@ mod test {
|
||||
shred::SIZE_OF_SHRED_TYPE,
|
||||
};
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
use solana_runtime::epoch_schedule::MINIMUM_SLOTS_PER_EPOCH;
|
||||
use solana_sdk::{
|
||||
epoch_schedule::MINIMUM_SLOTS_PER_EPOCH,
|
||||
hash::Hash,
|
||||
signature::{Keypair, KeypairUtil},
|
||||
};
|
||||
|
Reference in New Issue
Block a user