@ -5,14 +5,15 @@ use crate::snapshot_utils::{self, SnapshotError};
|
||||
use log::*;
|
||||
use solana_measure::measure::Measure;
|
||||
use solana_metrics::inc_new_counter_info;
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_runtime::status_cache::MAX_CACHE_ENTRIES;
|
||||
use solana_sdk::timing;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::ops::Index;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
use solana_runtime::{bank::Bank, status_cache::MAX_CACHE_ENTRIES};
|
||||
use solana_sdk::{clock::Slot, timing};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
ops::Index,
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct SnapshotConfig {
|
||||
@ -46,22 +47,22 @@ impl std::convert::From<SnapshotPackageSendError> for BankForksError {
|
||||
}
|
||||
|
||||
pub struct BankForks {
|
||||
pub banks: HashMap<u64, Arc<Bank>>,
|
||||
pub banks: HashMap<Slot, Arc<Bank>>,
|
||||
working_bank: Arc<Bank>,
|
||||
root: u64,
|
||||
root: Slot,
|
||||
pub snapshot_config: Option<SnapshotConfig>,
|
||||
last_snapshot_slot: u64,
|
||||
last_snapshot_slot: Slot,
|
||||
}
|
||||
|
||||
impl Index<u64> for BankForks {
|
||||
type Output = Arc<Bank>;
|
||||
fn index(&self, bank_slot: u64) -> &Arc<Bank> {
|
||||
fn index(&self, bank_slot: Slot) -> &Arc<Bank> {
|
||||
&self.banks[&bank_slot]
|
||||
}
|
||||
}
|
||||
|
||||
impl BankForks {
|
||||
pub fn new(bank_slot: u64, bank: Bank) -> Self {
|
||||
pub fn new(bank_slot: Slot, bank: Bank) -> Self {
|
||||
let mut banks = HashMap::new();
|
||||
let working_bank = Arc::new(bank);
|
||||
banks.insert(bank_slot, working_bank.clone());
|
||||
@ -75,11 +76,11 @@ impl BankForks {
|
||||
}
|
||||
|
||||
/// Create a map of bank slot id to the set of ancestors for the bank slot.
|
||||
pub fn ancestors(&self) -> HashMap<u64, HashSet<u64>> {
|
||||
pub fn ancestors(&self) -> HashMap<Slot, HashSet<Slot>> {
|
||||
let mut ancestors = HashMap::new();
|
||||
let root = self.root;
|
||||
for bank in self.banks.values() {
|
||||
let mut set: HashSet<u64> = bank
|
||||
let mut set: HashSet<Slot> = bank
|
||||
.ancestors
|
||||
.keys()
|
||||
.filter(|k| **k >= root)
|
||||
@ -93,11 +94,11 @@ impl BankForks {
|
||||
|
||||
/// Create a map of bank slot id to the set of all of its descendants
|
||||
#[allow(clippy::or_fun_call)]
|
||||
pub fn descendants(&self) -> HashMap<u64, HashSet<u64>> {
|
||||
pub fn descendants(&self) -> HashMap<Slot, HashSet<Slot>> {
|
||||
let mut descendants = HashMap::new();
|
||||
for bank in self.banks.values() {
|
||||
let _ = descendants.entry(bank.slot()).or_insert(HashSet::new());
|
||||
let mut set: HashSet<u64> = bank.ancestors.keys().cloned().collect();
|
||||
let mut set: HashSet<Slot> = bank.ancestors.keys().cloned().collect();
|
||||
set.remove(&bank.slot());
|
||||
for parent in set {
|
||||
descendants
|
||||
@ -109,7 +110,7 @@ impl BankForks {
|
||||
descendants
|
||||
}
|
||||
|
||||
pub fn frozen_banks(&self) -> HashMap<u64, Arc<Bank>> {
|
||||
pub fn frozen_banks(&self) -> HashMap<Slot, Arc<Bank>> {
|
||||
self.banks
|
||||
.iter()
|
||||
.filter(|(_, b)| b.is_frozen())
|
||||
@ -117,7 +118,7 @@ impl BankForks {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn active_banks(&self) -> Vec<u64> {
|
||||
pub fn active_banks(&self) -> Vec<Slot> {
|
||||
self.banks
|
||||
.iter()
|
||||
.filter(|(_, v)| !v.is_frozen())
|
||||
@ -125,11 +126,11 @@ impl BankForks {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn get(&self, bank_slot: u64) -> Option<&Arc<Bank>> {
|
||||
pub fn get(&self, bank_slot: Slot) -> Option<&Arc<Bank>> {
|
||||
self.banks.get(&bank_slot)
|
||||
}
|
||||
|
||||
pub fn new_from_banks(initial_forks: &[Arc<Bank>], rooted_path: Vec<u64>) -> Self {
|
||||
pub fn new_from_banks(initial_forks: &[Arc<Bank>], rooted_path: Vec<Slot>) -> Self {
|
||||
let mut banks = HashMap::new();
|
||||
let working_bank = initial_forks[0].clone();
|
||||
|
||||
@ -169,7 +170,11 @@ impl BankForks {
|
||||
self.working_bank.clone()
|
||||
}
|
||||
|
||||
pub fn set_root(&mut self, root: u64, snapshot_package_sender: &Option<SnapshotPackageSender>) {
|
||||
pub fn set_root(
|
||||
&mut self,
|
||||
root: Slot,
|
||||
snapshot_package_sender: &Option<SnapshotPackageSender>,
|
||||
) {
|
||||
self.root = root;
|
||||
let set_root_start = Instant::now();
|
||||
let root_bank = self
|
||||
@ -190,7 +195,7 @@ impl BankForks {
|
||||
if self.snapshot_config.is_some() && snapshot_package_sender.is_some() {
|
||||
let config = self.snapshot_config.as_ref().unwrap();
|
||||
info!("setting snapshot root: {}", root);
|
||||
if root - self.last_snapshot_slot >= config.snapshot_interval_slots as u64 {
|
||||
if root - self.last_snapshot_slot >= config.snapshot_interval_slots as Slot {
|
||||
let mut snapshot_time = Measure::start("total-snapshot-ms");
|
||||
let r = self.generate_snapshot(
|
||||
root,
|
||||
@ -223,7 +228,7 @@ impl BankForks {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn root(&self) -> u64 {
|
||||
pub fn root(&self) -> Slot {
|
||||
self.root
|
||||
}
|
||||
|
||||
@ -242,8 +247,8 @@ impl BankForks {
|
||||
|
||||
pub fn generate_snapshot<P: AsRef<Path>>(
|
||||
&self,
|
||||
root: u64,
|
||||
slots_to_snapshot: &[u64],
|
||||
root: Slot,
|
||||
slots_to_snapshot: &[Slot],
|
||||
snapshot_package_sender: &SnapshotPackageSender,
|
||||
tar_output_file: P,
|
||||
) -> Result<()> {
|
||||
@ -281,7 +286,7 @@ impl BankForks {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prune_non_root(&mut self, root: u64) {
|
||||
fn prune_non_root(&mut self, root: Slot) {
|
||||
let descendants = self.descendants();
|
||||
self.banks
|
||||
.retain(|slot, _| slot == &root || descendants[&root].contains(slot));
|
||||
|
@ -201,11 +201,11 @@ impl Blocktree {
|
||||
Database::destroy(&blocktree_path)
|
||||
}
|
||||
|
||||
pub fn meta(&self, slot: u64) -> Result<Option<SlotMeta>> {
|
||||
pub fn meta(&self, slot: Slot) -> Result<Option<SlotMeta>> {
|
||||
self.meta_cf.get(slot)
|
||||
}
|
||||
|
||||
pub fn is_full(&self, slot: u64) -> bool {
|
||||
pub fn is_full(&self, slot: Slot) -> bool {
|
||||
if let Ok(meta) = self.meta_cf.get(slot) {
|
||||
if let Some(meta) = meta {
|
||||
return meta.is_full();
|
||||
@ -293,17 +293,17 @@ impl Blocktree {
|
||||
Ok(end)
|
||||
}
|
||||
|
||||
pub fn erasure_meta(&self, slot: u64, set_index: u64) -> Result<Option<ErasureMeta>> {
|
||||
pub fn erasure_meta(&self, slot: Slot, set_index: u64) -> Result<Option<ErasureMeta>> {
|
||||
self.erasure_meta_cf.get((slot, set_index))
|
||||
}
|
||||
|
||||
pub fn orphan(&self, slot: u64) -> Result<Option<bool>> {
|
||||
pub fn orphan(&self, slot: Slot) -> Result<Option<bool>> {
|
||||
self.orphans_cf.get(slot)
|
||||
}
|
||||
|
||||
pub fn slot_meta_iterator<'a>(
|
||||
&'a self,
|
||||
slot: u64,
|
||||
slot: Slot,
|
||||
) -> Result<impl Iterator<Item = (u64, SlotMeta)> + 'a> {
|
||||
let meta_iter = self
|
||||
.db
|
||||
@ -319,7 +319,7 @@ impl Blocktree {
|
||||
|
||||
pub fn slot_data_iterator<'a>(
|
||||
&'a self,
|
||||
slot: u64,
|
||||
slot: Slot,
|
||||
) -> Result<impl Iterator<Item = ((u64, u64), Box<[u8]>)> + 'a> {
|
||||
let slot_iterator = self
|
||||
.db
|
||||
@ -837,13 +837,13 @@ impl Blocktree {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_data_shred(&self, slot: u64, index: u64) -> Result<Option<Vec<u8>>> {
|
||||
pub fn get_data_shred(&self, slot: Slot, index: u64) -> Result<Option<Vec<u8>>> {
|
||||
self.data_shred_cf.get_bytes((slot, index))
|
||||
}
|
||||
|
||||
pub fn get_data_shreds(
|
||||
&self,
|
||||
slot: u64,
|
||||
slot: Slot,
|
||||
from_index: u64,
|
||||
to_index: u64,
|
||||
buffer: &mut [u8],
|
||||
@ -880,13 +880,13 @@ impl Blocktree {
|
||||
Ok((last_index, buffer_offset))
|
||||
}
|
||||
|
||||
pub fn get_coding_shred(&self, slot: u64, index: u64) -> Result<Option<Vec<u8>>> {
|
||||
pub fn get_coding_shred(&self, slot: Slot, index: u64) -> Result<Option<Vec<u8>>> {
|
||||
self.code_shred_cf.get_bytes((slot, index))
|
||||
}
|
||||
|
||||
pub fn write_entries(
|
||||
&self,
|
||||
start_slot: u64,
|
||||
start_slot: Slot,
|
||||
num_ticks_in_start_slot: u64,
|
||||
start_index: u32,
|
||||
ticks_per_slot: u64,
|
||||
@ -946,14 +946,14 @@ impl Blocktree {
|
||||
Ok(num_shreds)
|
||||
}
|
||||
|
||||
pub fn get_index(&self, slot: u64) -> Result<Option<Index>> {
|
||||
pub fn get_index(&self, slot: Slot) -> Result<Option<Index>> {
|
||||
self.index_cf.get(slot)
|
||||
}
|
||||
|
||||
/// Manually update the meta for a slot.
|
||||
/// Can interfere with automatic meta update and potentially break chaining.
|
||||
/// Dangerous. Use with care.
|
||||
pub fn put_meta_bytes(&self, slot: u64, bytes: &[u8]) -> Result<()> {
|
||||
pub fn put_meta_bytes(&self, slot: Slot, bytes: &[u8]) -> Result<()> {
|
||||
self.meta_cf.put_bytes(slot, bytes)
|
||||
}
|
||||
|
||||
@ -962,7 +962,7 @@ impl Blocktree {
|
||||
// for the slot with the specified slot
|
||||
fn find_missing_indexes<C>(
|
||||
db_iterator: &mut DBRawIterator,
|
||||
slot: u64,
|
||||
slot: Slot,
|
||||
start_index: u64,
|
||||
end_index: u64,
|
||||
max_missing: usize,
|
||||
@ -1027,7 +1027,7 @@ impl Blocktree {
|
||||
|
||||
pub fn find_missing_data_indexes(
|
||||
&self,
|
||||
slot: u64,
|
||||
slot: Slot,
|
||||
start_index: u64,
|
||||
end_index: u64,
|
||||
max_missing: usize,
|
||||
@ -1051,7 +1051,7 @@ impl Blocktree {
|
||||
/// Returns the entry vector for the slot starting with `shred_start_index`
|
||||
pub fn get_slot_entries(
|
||||
&self,
|
||||
slot: u64,
|
||||
slot: Slot,
|
||||
shred_start_index: u64,
|
||||
_max_entries: Option<u64>,
|
||||
) -> Result<Vec<Entry>> {
|
||||
@ -1061,7 +1061,7 @@ impl Blocktree {
|
||||
|
||||
pub fn get_slot_entries_with_shred_count(
|
||||
&self,
|
||||
slot: u64,
|
||||
slot: Slot,
|
||||
start_index: u64,
|
||||
) -> Result<(Vec<Entry>, usize)> {
|
||||
let slot_meta_cf = self.db.column::<cf::SlotMeta>();
|
||||
@ -1127,7 +1127,7 @@ impl Blocktree {
|
||||
|
||||
fn get_entries_in_data_block(
|
||||
&self,
|
||||
slot: u64,
|
||||
slot: Slot,
|
||||
start_index: u32,
|
||||
end_index: u32,
|
||||
) -> Result<Vec<Entry>> {
|
||||
@ -1196,7 +1196,7 @@ impl Blocktree {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn is_root(&self, slot: u64) -> bool {
|
||||
pub fn is_root(&self, slot: Slot) -> bool {
|
||||
if let Ok(Some(true)) = self.db.get::<cf::Root>(slot) {
|
||||
true
|
||||
} else {
|
||||
@ -1220,7 +1220,7 @@ impl Blocktree {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn is_dead(&self, slot: u64) -> bool {
|
||||
pub fn is_dead(&self, slot: Slot) -> bool {
|
||||
if let Some(true) = self
|
||||
.db
|
||||
.get::<cf::DeadSlots>(slot)
|
||||
@ -1232,7 +1232,7 @@ impl Blocktree {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_dead_slot(&self, slot: u64) -> Result<()> {
|
||||
pub fn set_dead_slot(&self, slot: Slot) -> Result<()> {
|
||||
self.dead_slots_cf.put(slot, &true)
|
||||
}
|
||||
|
||||
@ -1258,7 +1258,7 @@ impl Blocktree {
|
||||
|
||||
/// Prune blocktree such that slots higher than `target_slot` are deleted and all references to
|
||||
/// higher slots are removed
|
||||
pub fn prune(&self, target_slot: u64) {
|
||||
pub fn prune(&self, target_slot: Slot) {
|
||||
let mut meta = self
|
||||
.meta(target_slot)
|
||||
.expect("couldn't read slot meta")
|
||||
@ -1332,7 +1332,7 @@ fn update_slot_meta(
|
||||
|
||||
fn get_index_meta_entry<'a>(
|
||||
db: &Database,
|
||||
slot: u64,
|
||||
slot: Slot,
|
||||
index_working_set: &'a mut HashMap<u64, IndexMetaWorkingSetEntry>,
|
||||
index_meta_time: &mut u64,
|
||||
) -> &'a mut IndexMetaWorkingSetEntry {
|
||||
@ -1356,8 +1356,8 @@ fn get_index_meta_entry<'a>(
|
||||
fn get_slot_meta_entry<'a>(
|
||||
db: &Database,
|
||||
slot_meta_working_set: &'a mut HashMap<u64, SlotMetaWorkingSetEntry>,
|
||||
slot: u64,
|
||||
parent_slot: u64,
|
||||
slot: Slot,
|
||||
parent_slot: Slot,
|
||||
) -> &'a mut SlotMetaWorkingSetEntry {
|
||||
let meta_cf = db.column::<cf::SlotMeta>();
|
||||
|
||||
@ -1384,7 +1384,7 @@ fn get_slot_meta_entry<'a>(
|
||||
})
|
||||
}
|
||||
|
||||
fn is_valid_write_to_slot_0(slot_to_write: u64, parent_slot: u64, last_root: u64) -> bool {
|
||||
fn is_valid_write_to_slot_0(slot_to_write: u64, parent_slot: Slot, last_root: u64) -> bool {
|
||||
slot_to_write == 0 && last_root == 0 && parent_slot == 0
|
||||
}
|
||||
|
||||
@ -1475,7 +1475,7 @@ fn find_slot_meta_else_create<'a>(
|
||||
// create a dummy orphan slot in the database
|
||||
fn find_slot_meta_in_db_else_create<'a>(
|
||||
db: &Database,
|
||||
slot: u64,
|
||||
slot: Slot,
|
||||
insert_map: &'a mut HashMap<u64, Rc<RefCell<SlotMeta>>>,
|
||||
) -> Result<Rc<RefCell<SlotMeta>>> {
|
||||
if let Some(slot_meta) = db.column::<cf::SlotMeta>().get(slot)? {
|
||||
@ -1497,7 +1497,7 @@ fn find_slot_meta_in_db_else_create<'a>(
|
||||
fn find_slot_meta_in_cached_state<'a>(
|
||||
working_set: &'a HashMap<u64, SlotMetaWorkingSetEntry>,
|
||||
chained_slots: &'a HashMap<u64, Rc<RefCell<SlotMeta>>>,
|
||||
slot: u64,
|
||||
slot: Slot,
|
||||
) -> Result<Option<Rc<RefCell<SlotMeta>>>> {
|
||||
if let Some(entry) = working_set.get(&slot) {
|
||||
Ok(Some(entry.new_slot_meta.clone()))
|
||||
@ -1535,7 +1535,7 @@ fn handle_chaining_for_slot(
|
||||
write_batch: &mut WriteBatch,
|
||||
working_set: &HashMap<u64, SlotMetaWorkingSetEntry>,
|
||||
new_chained_slots: &mut HashMap<u64, Rc<RefCell<SlotMeta>>>,
|
||||
slot: u64,
|
||||
slot: Slot,
|
||||
) -> Result<()> {
|
||||
let slot_meta_entry = working_set
|
||||
.get(&slot)
|
||||
@ -1614,7 +1614,7 @@ fn handle_chaining_for_slot(
|
||||
|
||||
fn traverse_children_mut<F>(
|
||||
db: &Database,
|
||||
slot: u64,
|
||||
slot: Slot,
|
||||
slot_meta: &Rc<RefCell<(SlotMeta)>>,
|
||||
working_set: &HashMap<u64, SlotMetaWorkingSetEntry>,
|
||||
new_chained_slots: &mut HashMap<u64, Rc<RefCell<SlotMeta>>>,
|
||||
@ -1654,7 +1654,7 @@ fn is_orphan(meta: &SlotMeta) -> bool {
|
||||
// 2) Determine whether to set the is_connected flag
|
||||
fn chain_new_slot_to_prev_slot(
|
||||
prev_slot_meta: &mut SlotMeta,
|
||||
current_slot: u64,
|
||||
current_slot: Slot,
|
||||
current_slot_meta: &mut SlotMeta,
|
||||
) {
|
||||
prev_slot_meta.next_slots.push(current_slot);
|
||||
@ -1747,7 +1747,7 @@ macro_rules! create_new_tmp_ledger {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn verify_shred_slots(slot: u64, parent_slot: u64, last_root: u64) -> bool {
|
||||
pub fn verify_shred_slots(slot: Slot, parent_slot: Slot, last_root: u64) -> bool {
|
||||
if !is_valid_write_to_slot_0(slot, parent_slot, last_root) {
|
||||
// Check that the parent_slot < slot
|
||||
if parent_slot >= slot {
|
||||
@ -1777,8 +1777,8 @@ pub fn create_new_tmp_ledger(name: &str, genesis_block: &GenesisBlock) -> (PathB
|
||||
|
||||
pub fn entries_to_test_shreds(
|
||||
entries: Vec<Entry>,
|
||||
slot: u64,
|
||||
parent_slot: u64,
|
||||
slot: Slot,
|
||||
parent_slot: Slot,
|
||||
is_full_slot: bool,
|
||||
) -> Vec<Shred> {
|
||||
let shredder = Shredder::new(slot, parent_slot, 0.0, Arc::new(Keypair::new()))
|
||||
@ -1789,8 +1789,8 @@ pub fn entries_to_test_shreds(
|
||||
|
||||
// used for tests only
|
||||
pub fn make_slot_entries(
|
||||
slot: u64,
|
||||
parent_slot: u64,
|
||||
slot: Slot,
|
||||
parent_slot: Slot,
|
||||
num_entries: u64,
|
||||
) -> (Vec<Shred>, Vec<Entry>) {
|
||||
let entries = create_ticks(num_entries, 0, Hash::default());
|
||||
@ -1800,7 +1800,7 @@ pub fn make_slot_entries(
|
||||
|
||||
// used for tests only
|
||||
pub fn make_many_slot_entries(
|
||||
start_slot: u64,
|
||||
start_slot: Slot,
|
||||
num_slots: u64,
|
||||
entries_per_slot: u64,
|
||||
) -> (Vec<Shred>, Vec<Entry>) {
|
||||
|
@ -299,7 +299,7 @@ impl Column for columns::Index {
|
||||
const NAME: &'static str = INDEX_CF;
|
||||
type Index = u64;
|
||||
|
||||
fn key(slot: u64) -> Vec<u8> {
|
||||
fn key(slot: Slot) -> Vec<u8> {
|
||||
let mut key = vec![0; 8];
|
||||
BigEndian::write_u64(&mut key[..], slot);
|
||||
key
|
||||
@ -326,7 +326,7 @@ impl Column for columns::DeadSlots {
|
||||
const NAME: &'static str = DEAD_SLOTS_CF;
|
||||
type Index = u64;
|
||||
|
||||
fn key(slot: u64) -> Vec<u8> {
|
||||
fn key(slot: Slot) -> Vec<u8> {
|
||||
let mut key = vec![0; 8];
|
||||
BigEndian::write_u64(&mut key[..], slot);
|
||||
key
|
||||
@ -353,7 +353,7 @@ impl Column for columns::Orphans {
|
||||
const NAME: &'static str = ORPHANS_CF;
|
||||
type Index = u64;
|
||||
|
||||
fn key(slot: u64) -> Vec<u8> {
|
||||
fn key(slot: Slot) -> Vec<u8> {
|
||||
let mut key = vec![0; 8];
|
||||
BigEndian::write_u64(&mut key[..], slot);
|
||||
key
|
||||
@ -380,7 +380,7 @@ impl Column for columns::Root {
|
||||
const NAME: &'static str = ROOT_CF;
|
||||
type Index = u64;
|
||||
|
||||
fn key(slot: u64) -> Vec<u8> {
|
||||
fn key(slot: Slot) -> Vec<u8> {
|
||||
let mut key = vec![0; 8];
|
||||
BigEndian::write_u64(&mut key[..], slot);
|
||||
key
|
||||
@ -407,7 +407,7 @@ impl Column for columns::SlotMeta {
|
||||
const NAME: &'static str = META_CF;
|
||||
type Index = u64;
|
||||
|
||||
fn key(slot: u64) -> Vec<u8> {
|
||||
fn key(slot: Slot) -> Vec<u8> {
|
||||
let mut key = vec![0; 8];
|
||||
BigEndian::write_u64(&mut key[..], slot);
|
||||
key
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::erasure::ErasureConfig;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use solana_metrics::datapoint;
|
||||
use solana_sdk::clock::Slot;
|
||||
use std::{collections::BTreeSet, ops::RangeBounds};
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize, Eq, PartialEq)]
|
||||
@ -8,7 +9,7 @@ use std::{collections::BTreeSet, ops::RangeBounds};
|
||||
pub struct SlotMeta {
|
||||
// The number of slots above the root (the genesis block). The first
|
||||
// slot has slot 0.
|
||||
pub slot: u64,
|
||||
pub slot: Slot,
|
||||
// The total number of consecutive blobs starting from index 0
|
||||
// we have received for this slot.
|
||||
pub consumed: u64,
|
||||
@ -19,10 +20,10 @@ pub struct SlotMeta {
|
||||
// The index of the blob that is flagged as the last blob for this slot.
|
||||
pub last_index: u64,
|
||||
// The slot height of the block this one derives from.
|
||||
pub parent_slot: u64,
|
||||
// The list of slot heights, each of which contains a block that derives
|
||||
pub parent_slot: Slot,
|
||||
// The list of slots, each of which contains a block that derives
|
||||
// from this one.
|
||||
pub next_slots: Vec<u64>,
|
||||
pub next_slots: Vec<Slot>,
|
||||
// True if this slot is full (consumed == last_index + 1) and if every
|
||||
// slot that is a parent of this slot is also connected.
|
||||
pub is_connected: bool,
|
||||
@ -33,7 +34,7 @@ pub struct SlotMeta {
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq)]
|
||||
/// Index recording presence/absence of blobs
|
||||
pub struct Index {
|
||||
pub slot: u64,
|
||||
pub slot: Slot,
|
||||
data: DataIndex,
|
||||
coding: CodingIndex,
|
||||
}
|
||||
@ -70,7 +71,7 @@ pub enum ErasureMetaStatus {
|
||||
}
|
||||
|
||||
impl Index {
|
||||
pub(crate) fn new(slot: u64) -> Self {
|
||||
pub(crate) fn new(slot: Slot) -> Self {
|
||||
Index {
|
||||
slot,
|
||||
data: DataIndex::default(),
|
||||
@ -174,7 +175,7 @@ impl SlotMeta {
|
||||
self.parent_slot != std::u64::MAX
|
||||
}
|
||||
|
||||
pub(crate) fn new(slot: u64, parent_slot: u64) -> Self {
|
||||
pub(crate) fn new(slot: Slot, parent_slot: Slot) -> Self {
|
||||
SlotMeta {
|
||||
slot,
|
||||
consumed: 0,
|
||||
|
@ -132,6 +132,7 @@ impl Default for Session {
|
||||
pub mod test {
|
||||
use super::*;
|
||||
use log::*;
|
||||
use solana_sdk::clock::Slot;
|
||||
|
||||
/// Specifies the contents of a 16-data-blob and 4-coding-blob erasure set
|
||||
/// Exists to be passed to `generate_blocktree_with_coding`
|
||||
@ -147,7 +148,7 @@ pub mod test {
|
||||
/// Exists to be passed to `generate_blocktree_with_coding`
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SlotSpec {
|
||||
pub slot: u64,
|
||||
pub slot: Slot,
|
||||
pub set_specs: Vec<ErasureSpec>,
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,17 @@
|
||||
use crate::{blocktree::Blocktree, leader_schedule::LeaderSchedule, leader_schedule_utils};
|
||||
use log::*;
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_sdk::{epoch_schedule::EpochSchedule, pubkey::Pubkey};
|
||||
use solana_sdk::{
|
||||
clock::{Epoch, Slot},
|
||||
epoch_schedule::EpochSchedule,
|
||||
pubkey::Pubkey,
|
||||
};
|
||||
use std::{
|
||||
collections::{hash_map::Entry, HashMap, VecDeque},
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
type CachedSchedules = (HashMap<u64, Arc<LeaderSchedule>>, VecDeque<u64>);
|
||||
type CachedSchedules = (HashMap<Epoch, Arc<LeaderSchedule>>, VecDeque<u64>);
|
||||
const MAX_SCHEDULES: usize = 10;
|
||||
|
||||
struct CacheCapacity(usize);
|
||||
@ -22,7 +26,7 @@ pub struct LeaderScheduleCache {
|
||||
// Map from an epoch to a leader schedule for that epoch
|
||||
pub cached_schedules: RwLock<CachedSchedules>,
|
||||
epoch_schedule: EpochSchedule,
|
||||
max_epoch: RwLock<u64>,
|
||||
max_epoch: RwLock<Epoch>,
|
||||
max_schedules: CacheCapacity,
|
||||
}
|
||||
|
||||
@ -79,7 +83,7 @@ impl LeaderScheduleCache {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn slot_leader_at(&self, slot: u64, bank: Option<&Bank>) -> Option<Pubkey> {
|
||||
pub fn slot_leader_at(&self, slot: Slot, bank: Option<&Bank>) -> Option<Pubkey> {
|
||||
if let Some(bank) = bank {
|
||||
self.slot_leader_at_else_compute(slot, bank)
|
||||
} else if self.epoch_schedule.slots_per_epoch == 0 {
|
||||
@ -93,10 +97,10 @@ impl LeaderScheduleCache {
|
||||
pub fn next_leader_slot(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
mut current_slot: u64,
|
||||
mut current_slot: Slot,
|
||||
bank: &Bank,
|
||||
blocktree: Option<&Blocktree>,
|
||||
) -> Option<(u64, u64)> {
|
||||
) -> Option<(Slot, Slot)> {
|
||||
let (mut epoch, mut start_index) = bank.get_epoch_and_slot_index(current_slot + 1);
|
||||
let mut first_slot = None;
|
||||
let mut last_slot = current_slot;
|
||||
@ -149,7 +153,7 @@ impl LeaderScheduleCache {
|
||||
first_slot.and_then(|slot| Some((slot, last_slot)))
|
||||
}
|
||||
|
||||
fn slot_leader_at_no_compute(&self, slot: u64) -> Option<Pubkey> {
|
||||
fn slot_leader_at_no_compute(&self, slot: Slot) -> Option<Pubkey> {
|
||||
let (epoch, slot_index) = self.epoch_schedule.get_epoch_and_slot_index(slot);
|
||||
self.cached_schedules
|
||||
.read()
|
||||
@ -159,7 +163,7 @@ impl LeaderScheduleCache {
|
||||
.map(|schedule| schedule[slot_index])
|
||||
}
|
||||
|
||||
fn slot_leader_at_else_compute(&self, slot: u64, bank: &Bank) -> Option<Pubkey> {
|
||||
fn slot_leader_at_else_compute(&self, slot: Slot, bank: &Bank) -> Option<Pubkey> {
|
||||
let cache_result = self.slot_leader_at_no_compute(slot);
|
||||
// Forbid asking for slots in an unconfirmed epoch
|
||||
let bank_epoch = self.epoch_schedule.get_epoch_and_slot_index(slot).0;
|
||||
@ -184,7 +188,7 @@ impl LeaderScheduleCache {
|
||||
|
||||
fn get_epoch_schedule_else_compute(
|
||||
&self,
|
||||
epoch: u64,
|
||||
epoch: Epoch,
|
||||
bank: &Bank,
|
||||
) -> Option<Arc<LeaderSchedule>> {
|
||||
let epoch_schedule = self.cached_schedules.read().unwrap().0.get(&epoch).cloned();
|
||||
@ -198,7 +202,7 @@ impl LeaderScheduleCache {
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_epoch_schedule(&self, epoch: u64, bank: &Bank) -> Option<Arc<LeaderSchedule>> {
|
||||
fn compute_epoch_schedule(&self, epoch: Epoch, bank: &Bank) -> Option<Arc<LeaderSchedule>> {
|
||||
let leader_schedule = leader_schedule_utils::leader_schedule(epoch, bank);
|
||||
leader_schedule.map(|leader_schedule| {
|
||||
let leader_schedule = Arc::new(leader_schedule);
|
||||
@ -216,7 +220,7 @@ impl LeaderScheduleCache {
|
||||
}
|
||||
|
||||
fn retain_latest(
|
||||
schedules: &mut HashMap<u64, Arc<LeaderSchedule>>,
|
||||
schedules: &mut HashMap<Epoch, Arc<LeaderSchedule>>,
|
||||
order: &mut VecDeque<u64>,
|
||||
max_schedules: usize,
|
||||
) {
|
||||
|
@ -1,11 +1,13 @@
|
||||
use crate::leader_schedule::LeaderSchedule;
|
||||
use crate::staking_utils;
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_sdk::clock::NUM_CONSECUTIVE_LEADER_SLOTS;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::{
|
||||
clock::{Epoch, Slot, NUM_CONSECUTIVE_LEADER_SLOTS},
|
||||
pubkey::Pubkey,
|
||||
};
|
||||
|
||||
/// Return the leader schedule for the given epoch.
|
||||
pub fn leader_schedule(epoch: u64, bank: &Bank) -> Option<LeaderSchedule> {
|
||||
pub fn leader_schedule(epoch: Epoch, bank: &Bank) -> Option<LeaderSchedule> {
|
||||
staking_utils::staked_nodes_at_epoch(bank, epoch).map(|stakes| {
|
||||
let mut seed = [0u8; 32];
|
||||
seed[0..8].copy_from_slice(&epoch.to_le_bytes());
|
||||
@ -21,7 +23,7 @@ pub fn leader_schedule(epoch: u64, bank: &Bank) -> Option<LeaderSchedule> {
|
||||
}
|
||||
|
||||
/// Return the leader for the given slot.
|
||||
pub fn slot_leader_at(slot: u64, bank: &Bank) -> Option<Pubkey> {
|
||||
pub fn slot_leader_at(slot: Slot, bank: &Bank) -> Option<Pubkey> {
|
||||
let (epoch, slot_index) = bank.get_epoch_and_slot_index(slot);
|
||||
|
||||
leader_schedule(epoch, bank).map(|leader_schedule| leader_schedule[slot_index])
|
||||
|
@ -1,14 +1,14 @@
|
||||
use crate::blocktree::*;
|
||||
use crate::blocktree_meta::SlotMeta;
|
||||
use crate::{blocktree::*, blocktree_meta::SlotMeta};
|
||||
use log::*;
|
||||
use solana_sdk::clock::Slot;
|
||||
|
||||
pub struct RootedSlotIterator<'a> {
|
||||
next_slots: Vec<u64>,
|
||||
next_slots: Vec<Slot>,
|
||||
blocktree: &'a Blocktree,
|
||||
}
|
||||
|
||||
impl<'a> RootedSlotIterator<'a> {
|
||||
pub fn new(start_slot: u64, blocktree: &'a Blocktree) -> Result<Self> {
|
||||
pub fn new(start_slot: Slot, blocktree: &'a Blocktree) -> Result<Self> {
|
||||
if blocktree.is_root(start_slot) {
|
||||
Ok(Self {
|
||||
next_slots: vec![start_slot],
|
||||
@ -20,7 +20,7 @@ impl<'a> RootedSlotIterator<'a> {
|
||||
}
|
||||
}
|
||||
impl<'a> Iterator for RootedSlotIterator<'a> {
|
||||
type Item = (u64, SlotMeta);
|
||||
type Item = (Slot, SlotMeta);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
// Clone b/c passing the closure to the map below requires exclusive access to
|
||||
|
@ -1,19 +1,25 @@
|
||||
//! The `shred` module defines data structures and methods to pull MTU sized data frames from the network.
|
||||
use crate::entry::{create_ticks, Entry};
|
||||
use crate::erasure::Session;
|
||||
use crate::{
|
||||
entry::{create_ticks, Entry},
|
||||
erasure::Session,
|
||||
};
|
||||
use core::cell::RefCell;
|
||||
use rayon::iter::{IndexedParallelIterator, IntoParallelRefMutIterator, ParallelIterator};
|
||||
use rayon::slice::ParallelSlice;
|
||||
use rayon::ThreadPool;
|
||||
use rayon::{
|
||||
iter::{IndexedParallelIterator, IntoParallelRefMutIterator, ParallelIterator},
|
||||
slice::ParallelSlice,
|
||||
ThreadPool,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use solana_metrics::datapoint_debug;
|
||||
use solana_rayon_threadlimit::get_thread_count;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::packet::PACKET_DATA_SIZE;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
use solana_sdk::{
|
||||
clock::Slot,
|
||||
hash::Hash,
|
||||
packet::PACKET_DATA_SIZE,
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, KeypairUtil, Signature},
|
||||
};
|
||||
use std::{sync::Arc, time::Instant};
|
||||
|
||||
/// The following constants are computed by hand, and hardcoded.
|
||||
/// `test_shred_constants` ensures that the values are correct.
|
||||
@ -52,7 +58,7 @@ pub const DATA_COMPLETE_SHRED: u8 = 0b0000_0010;
|
||||
pub enum ShredError {
|
||||
InvalidShredType,
|
||||
InvalidFecRate(f32), // FEC rate must be more than 0.0 and less than 1.0
|
||||
SlotTooLow { slot: u64, parent_slot: u64 }, // "Current slot must be > Parent slot, but the difference must not be > u16::MAX
|
||||
SlotTooLow { slot: Slot, parent_slot: Slot }, // "Current slot must be > Parent slot, but the difference must not be > u16::MAX
|
||||
Serialize(std::boxed::Box<bincode::ErrorKind>),
|
||||
}
|
||||
|
||||
@ -77,7 +83,7 @@ impl Default for ShredType {
|
||||
pub struct ShredCommonHeader {
|
||||
pub signature: Signature,
|
||||
pub shred_type: ShredType,
|
||||
pub slot: u64,
|
||||
pub slot: Slot,
|
||||
pub index: u32,
|
||||
}
|
||||
|
||||
@ -129,7 +135,7 @@ impl Shred {
|
||||
}
|
||||
|
||||
pub fn new_from_data(
|
||||
slot: u64,
|
||||
slot: Slot,
|
||||
index: u32,
|
||||
parent_offset: u16,
|
||||
data: Option<&[u8]>,
|
||||
@ -256,11 +262,11 @@ impl Shred {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn slot(&self) -> u64 {
|
||||
pub fn slot(&self) -> Slot {
|
||||
self.common_header.slot
|
||||
}
|
||||
|
||||
pub fn parent(&self) -> u64 {
|
||||
pub fn parent(&self) -> Slot {
|
||||
if self.is_data() {
|
||||
self.common_header.slot - u64::from(self.data_header.parent_offset)
|
||||
} else {
|
||||
@ -280,7 +286,7 @@ impl Shred {
|
||||
|
||||
/// This is not a safe function. It only changes the meta information.
|
||||
/// Use this only for test code which doesn't care about actual shred
|
||||
pub fn set_slot(&mut self, slot: u64) {
|
||||
pub fn set_slot(&mut self, slot: Slot) {
|
||||
self.common_header.slot = slot
|
||||
}
|
||||
|
||||
@ -335,15 +341,20 @@ impl Shred {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Shredder {
|
||||
slot: u64,
|
||||
parent_slot: u64,
|
||||
slot: Slot,
|
||||
parent_slot: Slot,
|
||||
fec_rate: f32,
|
||||
keypair: Arc<Keypair>,
|
||||
pub signing_coding_time: u128,
|
||||
}
|
||||
|
||||
impl Shredder {
|
||||
pub fn new(slot: u64, parent_slot: u64, fec_rate: f32, keypair: Arc<Keypair>) -> Result<Self> {
|
||||
pub fn new(
|
||||
slot: Slot,
|
||||
parent_slot: Slot,
|
||||
fec_rate: f32,
|
||||
keypair: Arc<Keypair>,
|
||||
) -> Result<Self> {
|
||||
if fec_rate > 1.0 || fec_rate < 0.0 {
|
||||
Err(ShredError::InvalidFecRate(fec_rate))
|
||||
} else if slot < parent_slot || slot - parent_slot > u64::from(std::u16::MAX) {
|
||||
@ -450,7 +461,7 @@ impl Shredder {
|
||||
}
|
||||
|
||||
pub fn new_coding_shred_header(
|
||||
slot: u64,
|
||||
slot: Slot,
|
||||
index: u32,
|
||||
num_data: usize,
|
||||
num_code: usize,
|
||||
@ -472,7 +483,7 @@ impl Shredder {
|
||||
|
||||
/// Generates coding shreds for the data shreds in the current FEC set
|
||||
pub fn generate_coding_shreds(
|
||||
slot: u64,
|
||||
slot: Slot,
|
||||
fec_rate: f32,
|
||||
data_shred_batch: &[Shred],
|
||||
) -> Vec<Shred> {
|
||||
@ -583,7 +594,7 @@ impl Shredder {
|
||||
num_data: usize,
|
||||
num_coding: usize,
|
||||
first_index: usize,
|
||||
slot: u64,
|
||||
slot: Slot,
|
||||
) -> std::result::Result<Vec<Shred>, reed_solomon_erasure::Error> {
|
||||
let mut recovered_data = vec![];
|
||||
let fec_set_size = num_data + num_coding;
|
||||
@ -760,8 +771,8 @@ pub mod tests {
|
||||
fn verify_test_data_shred(
|
||||
shred: &Shred,
|
||||
index: u32,
|
||||
slot: u64,
|
||||
parent: u64,
|
||||
slot: Slot,
|
||||
parent: Slot,
|
||||
pk: &Pubkey,
|
||||
verify: bool,
|
||||
is_last_in_slot: bool,
|
||||
@ -785,7 +796,7 @@ pub mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_test_code_shred(shred: &Shred, index: u32, slot: u64, pk: &Pubkey, verify: bool) {
|
||||
fn verify_test_code_shred(shred: &Shred, index: u32, slot: Slot, pk: &Pubkey, verify: bool) {
|
||||
assert_eq!(shred.payload.len(), PACKET_DATA_SIZE);
|
||||
assert!(!shred.is_data());
|
||||
assert_eq!(shred.index(), index);
|
||||
|
@ -4,14 +4,15 @@ use bzip2::bufread::BzDecoder;
|
||||
use fs_extra::dir::CopyOptions;
|
||||
use log::*;
|
||||
use solana_measure::measure::Measure;
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_runtime::status_cache::SlotDelta;
|
||||
use solana_sdk::transaction;
|
||||
use std::cmp::Ordering;
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, BufWriter, Error as IOError, ErrorKind};
|
||||
use std::path::{Path, PathBuf};
|
||||
use solana_runtime::{bank::Bank, status_cache::SlotDelta};
|
||||
use solana_sdk::{clock::Slot, transaction};
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
fs,
|
||||
fs::File,
|
||||
io::{BufReader, BufWriter, Error as IOError, ErrorKind},
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use tar::Archive;
|
||||
|
||||
pub const SNAPSHOT_STATUS_CACHE_FILE_NAME: &str = "status_cache";
|
||||
@ -20,7 +21,7 @@ pub const TAR_ACCOUNTS_DIR: &str = "accounts";
|
||||
|
||||
#[derive(PartialEq, Ord, Eq, Debug)]
|
||||
pub struct SlotSnapshotPaths {
|
||||
pub slot: u64,
|
||||
pub slot: Slot,
|
||||
pub snapshot_file_path: PathBuf,
|
||||
}
|
||||
|
||||
@ -77,7 +78,7 @@ pub fn package_snapshot<P: AsRef<Path>, Q: AsRef<Path>>(
|
||||
snapshot_files: &SlotSnapshotPaths,
|
||||
snapshot_package_output_file: P,
|
||||
snapshot_path: Q,
|
||||
slots_to_snapshot: &[u64],
|
||||
slots_to_snapshot: &[Slot],
|
||||
) -> Result<SnapshotPackage> {
|
||||
// Hard link all the snapshots we need for this package
|
||||
let snapshot_hard_links_dir = tempfile::tempdir_in(snapshot_path)?;
|
||||
@ -183,7 +184,7 @@ pub fn add_snapshot<P: AsRef<Path>>(snapshot_path: P, bank: &Bank) -> Result<()>
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn remove_snapshot<P: AsRef<Path>>(slot: u64, snapshot_path: P) -> Result<()> {
|
||||
pub fn remove_snapshot<P: AsRef<Path>>(slot: Slot, snapshot_path: P) -> Result<()> {
|
||||
let slot_snapshot_dir = get_bank_snapshot_dir(&snapshot_path, slot);
|
||||
// Remove the snapshot directory for this slot
|
||||
fs::remove_dir_all(slot_snapshot_dir)?;
|
||||
@ -295,11 +296,11 @@ where
|
||||
Ok(bank)
|
||||
}
|
||||
|
||||
fn get_snapshot_file_name(slot: u64) -> String {
|
||||
fn get_snapshot_file_name(slot: Slot) -> String {
|
||||
slot.to_string()
|
||||
}
|
||||
|
||||
fn get_bank_snapshot_dir<P: AsRef<Path>>(path: P, slot: u64) -> PathBuf {
|
||||
fn get_bank_snapshot_dir<P: AsRef<Path>>(path: P, slot: Slot) -> PathBuf {
|
||||
path.as_ref().join(slot.to_string())
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,17 @@
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_sdk::{account::Account, pubkey::Pubkey};
|
||||
use solana_sdk::{
|
||||
account::Account,
|
||||
clock::{Epoch, Slot},
|
||||
pubkey::Pubkey,
|
||||
};
|
||||
use solana_vote_api::vote_state::VoteState;
|
||||
use std::{borrow::Borrow, collections::HashMap};
|
||||
|
||||
/// Looks through vote accounts, and finds the latest slot that has achieved
|
||||
/// supermajority lockout
|
||||
pub fn get_supermajority_slot(bank: &Bank, epoch_height: u64) -> Option<u64> {
|
||||
pub fn get_supermajority_slot(bank: &Bank, epoch: Epoch) -> Option<u64> {
|
||||
// Find the amount of stake needed for supermajority
|
||||
let stakes_and_lockouts = epoch_stakes_and_lockouts(bank, epoch_height);
|
||||
let stakes_and_lockouts = epoch_stakes_and_lockouts(bank, epoch);
|
||||
let total_stake: u64 = stakes_and_lockouts.iter().map(|s| s.0).sum();
|
||||
let supermajority_stake = total_stake * 2 / 3;
|
||||
|
||||
@ -29,8 +33,8 @@ pub fn staked_nodes(bank: &Bank) -> HashMap<Pubkey, u64> {
|
||||
|
||||
/// At the specified epoch, collect the delegate account balance and vote states for delegates
|
||||
/// that have non-zero balance in any of their managed staking accounts
|
||||
pub fn staked_nodes_at_epoch(bank: &Bank, epoch_height: u64) -> Option<HashMap<Pubkey, u64>> {
|
||||
bank.epoch_vote_accounts(epoch_height)
|
||||
pub fn staked_nodes_at_epoch(bank: &Bank, epoch: Epoch) -> Option<HashMap<Pubkey, u64>> {
|
||||
bank.epoch_vote_accounts(epoch)
|
||||
.map(|vote_accounts| to_staked_nodes(to_vote_states(vote_accounts.iter())))
|
||||
}
|
||||
|
||||
@ -58,9 +62,9 @@ fn to_staked_nodes(
|
||||
map
|
||||
}
|
||||
|
||||
fn epoch_stakes_and_lockouts(bank: &Bank, epoch_height: u64) -> Vec<(u64, Option<u64>)> {
|
||||
fn epoch_stakes_and_lockouts(bank: &Bank, epoch: Epoch) -> Vec<(u64, Option<u64>)> {
|
||||
let node_staked_accounts = bank
|
||||
.epoch_vote_accounts(epoch_height)
|
||||
.epoch_vote_accounts(epoch)
|
||||
.expect("Bank state for epoch is missing")
|
||||
.iter();
|
||||
|
||||
@ -69,7 +73,7 @@ fn epoch_stakes_and_lockouts(bank: &Bank, epoch_height: u64) -> Vec<(u64, Option
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn find_supermajority_slot<'a, I>(supermajority_stake: u64, stakes_and_lockouts: I) -> Option<u64>
|
||||
fn find_supermajority_slot<'a, I>(supermajority_stake: u64, stakes_and_lockouts: I) -> Option<Slot>
|
||||
where
|
||||
I: Iterator<Item = &'a (u64, Option<u64>)>,
|
||||
{
|
||||
@ -111,7 +115,7 @@ pub(crate) mod tests {
|
||||
use solana_vote_api::{vote_instruction, vote_state::VoteInit};
|
||||
use std::sync::Arc;
|
||||
|
||||
fn new_from_parent(parent: &Arc<Bank>, slot: u64) -> Bank {
|
||||
fn new_from_parent(parent: &Arc<Bank>, slot: Slot) -> Bank {
|
||||
Bank::new_from_parent(parent, &Pubkey::default(), slot)
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user