Remove unused StakeLockout::lockout (#10719)
* Remove unused StakeLockout::lockout * Revert... * Really revert to the original behavior... * Use consistent naming after StakeLockout removal * Furhter clean up * Missed type aliases... * More... * Even more...
This commit is contained in:
@ -1,5 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
commitment::{BlockCommitment, BlockCommitmentCache, VOTE_THRESHOLD_SIZE},
|
commitment::{BlockCommitment, BlockCommitmentCache, VOTE_THRESHOLD_SIZE},
|
||||||
|
consensus::Stake,
|
||||||
rpc_subscriptions::{CacheSlotInfo, RpcSubscriptions},
|
rpc_subscriptions::{CacheSlotInfo, RpcSubscriptions},
|
||||||
};
|
};
|
||||||
use solana_measure::measure::Measure;
|
use solana_measure::measure::Measure;
|
||||||
@ -19,15 +20,15 @@ use std::{
|
|||||||
pub struct CommitmentAggregationData {
|
pub struct CommitmentAggregationData {
|
||||||
bank: Arc<Bank>,
|
bank: Arc<Bank>,
|
||||||
root: Slot,
|
root: Slot,
|
||||||
total_staked: u64,
|
total_stake: Stake,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommitmentAggregationData {
|
impl CommitmentAggregationData {
|
||||||
pub fn new(bank: Arc<Bank>, root: Slot, total_staked: u64) -> Self {
|
pub fn new(bank: Arc<Bank>, root: Slot, total_stake: Stake) -> Self {
|
||||||
Self {
|
Self {
|
||||||
bank,
|
bank,
|
||||||
root,
|
root,
|
||||||
total_staked,
|
total_stake,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,12 +108,12 @@ impl AggregateCommitmentService {
|
|||||||
Self::aggregate_commitment(&ancestors, &aggregation_data.bank);
|
Self::aggregate_commitment(&ancestors, &aggregation_data.bank);
|
||||||
|
|
||||||
let largest_confirmed_root =
|
let largest_confirmed_root =
|
||||||
get_largest_confirmed_root(rooted_stake, aggregation_data.total_staked);
|
get_largest_confirmed_root(rooted_stake, aggregation_data.total_stake);
|
||||||
|
|
||||||
let mut new_block_commitment = BlockCommitmentCache::new(
|
let mut new_block_commitment = BlockCommitmentCache::new(
|
||||||
block_commitment,
|
block_commitment,
|
||||||
largest_confirmed_root,
|
largest_confirmed_root,
|
||||||
aggregation_data.total_staked,
|
aggregation_data.total_stake,
|
||||||
aggregation_data.bank,
|
aggregation_data.bank,
|
||||||
block_commitment_cache.read().unwrap().blockstore.clone(),
|
block_commitment_cache.read().unwrap().blockstore.clone(),
|
||||||
aggregation_data.root,
|
aggregation_data.root,
|
||||||
|
@ -60,27 +60,12 @@ impl SwitchForkDecision {
|
|||||||
pub const VOTE_THRESHOLD_DEPTH: usize = 8;
|
pub const VOTE_THRESHOLD_DEPTH: usize = 8;
|
||||||
pub const SWITCH_FORK_THRESHOLD: f64 = 0.38;
|
pub const SWITCH_FORK_THRESHOLD: f64 = 0.38;
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone)]
|
pub type Stake = u64;
|
||||||
pub struct StakeLockout {
|
pub type VotedStakes = HashMap<Slot, Stake>;
|
||||||
lockout: u64,
|
|
||||||
stake: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl StakeLockout {
|
|
||||||
pub fn new(lockout: u64, stake: u64) -> Self {
|
|
||||||
Self { lockout, stake }
|
|
||||||
}
|
|
||||||
pub fn lockout(&self) -> u64 {
|
|
||||||
self.lockout
|
|
||||||
}
|
|
||||||
pub fn stake(&self) -> u64 {
|
|
||||||
self.stake
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct ComputedBankState {
|
pub(crate) struct ComputedBankState {
|
||||||
pub stake_lockouts: HashMap<Slot, StakeLockout>,
|
pub voted_stakes: VotedStakes,
|
||||||
pub total_staked: u64,
|
pub total_stake: Stake,
|
||||||
pub bank_weight: u128,
|
pub bank_weight: u128,
|
||||||
pub lockout_intervals: LockoutIntervals,
|
pub lockout_intervals: LockoutIntervals,
|
||||||
pub pubkey_votes: Vec<(Pubkey, Slot)>,
|
pub pubkey_votes: Vec<(Pubkey, Slot)>,
|
||||||
@ -147,8 +132,8 @@ impl Tower {
|
|||||||
where
|
where
|
||||||
F: Iterator<Item = (Pubkey, (u64, Account))>,
|
F: Iterator<Item = (Pubkey, (u64, Account))>,
|
||||||
{
|
{
|
||||||
let mut stake_lockouts = HashMap::new();
|
let mut voted_stakes = HashMap::new();
|
||||||
let mut total_staked = 0;
|
let mut total_stake = 0;
|
||||||
let mut bank_weight = 0;
|
let mut bank_weight = 0;
|
||||||
// Tree of intervals of lockouts of the form [slot, slot + slot.lockout],
|
// Tree of intervals of lockouts of the form [slot, slot + slot.lockout],
|
||||||
// keyed by end of the range
|
// keyed by end of the range
|
||||||
@ -209,7 +194,7 @@ impl Tower {
|
|||||||
|
|
||||||
for vote in &vote_state.votes {
|
for vote in &vote_state.votes {
|
||||||
bank_weight += vote.lockout() as u128 * lamports as u128;
|
bank_weight += vote.lockout() as u128 * lamports as u128;
|
||||||
Self::update_ancestor_lockouts(&mut stake_lockouts, &vote, ancestors);
|
Self::populate_ancestor_voted_stakes(&mut voted_stakes, &vote, ancestors);
|
||||||
}
|
}
|
||||||
|
|
||||||
if start_root != vote_state.root_slot {
|
if start_root != vote_state.root_slot {
|
||||||
@ -220,7 +205,7 @@ impl Tower {
|
|||||||
};
|
};
|
||||||
trace!("ROOT: {}", vote.slot);
|
trace!("ROOT: {}", vote.slot);
|
||||||
bank_weight += vote.lockout() as u128 * lamports as u128;
|
bank_weight += vote.lockout() as u128 * lamports as u128;
|
||||||
Self::update_ancestor_lockouts(&mut stake_lockouts, &vote, ancestors);
|
Self::populate_ancestor_voted_stakes(&mut voted_stakes, &vote, ancestors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(root) = vote_state.root_slot {
|
if let Some(root) = vote_state.root_slot {
|
||||||
@ -229,7 +214,7 @@ impl Tower {
|
|||||||
slot: root,
|
slot: root,
|
||||||
};
|
};
|
||||||
bank_weight += vote.lockout() as u128 * lamports as u128;
|
bank_weight += vote.lockout() as u128 * lamports as u128;
|
||||||
Self::update_ancestor_lockouts(&mut stake_lockouts, &vote, ancestors);
|
Self::populate_ancestor_voted_stakes(&mut voted_stakes, &vote, ancestors);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The last vote in the vote stack is a simulated vote on bank_slot, which
|
// The last vote in the vote stack is a simulated vote on bank_slot, which
|
||||||
@ -247,14 +232,19 @@ impl Tower {
|
|||||||
);
|
);
|
||||||
if let Some(vote) = vote_state.nth_recent_vote(1) {
|
if let Some(vote) = vote_state.nth_recent_vote(1) {
|
||||||
// Update all the parents of this last vote with the stake of this vote account
|
// Update all the parents of this last vote with the stake of this vote account
|
||||||
Self::update_ancestor_stakes(&mut stake_lockouts, vote.slot, lamports, ancestors);
|
Self::update_ancestor_voted_stakes(
|
||||||
|
&mut voted_stakes,
|
||||||
|
vote.slot,
|
||||||
|
lamports,
|
||||||
|
ancestors,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
total_staked += lamports;
|
total_stake += lamports;
|
||||||
}
|
}
|
||||||
|
|
||||||
ComputedBankState {
|
ComputedBankState {
|
||||||
stake_lockouts,
|
voted_stakes,
|
||||||
total_staked,
|
total_stake,
|
||||||
bank_weight,
|
bank_weight,
|
||||||
lockout_intervals,
|
lockout_intervals,
|
||||||
pubkey_votes,
|
pubkey_votes,
|
||||||
@ -263,13 +253,13 @@ impl Tower {
|
|||||||
|
|
||||||
pub fn is_slot_confirmed(
|
pub fn is_slot_confirmed(
|
||||||
&self,
|
&self,
|
||||||
slot: u64,
|
slot: Slot,
|
||||||
lockouts: &HashMap<u64, StakeLockout>,
|
voted_stakes: &VotedStakes,
|
||||||
total_staked: u64,
|
total_stake: Stake,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
lockouts
|
voted_stakes
|
||||||
.get(&slot)
|
.get(&slot)
|
||||||
.map(|lockout| (lockout.stake as f64 / total_staked as f64) > self.threshold_size)
|
.map(|stake| (*stake as f64 / total_stake as f64) > self.threshold_size)
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -501,18 +491,18 @@ impl Tower {
|
|||||||
pub fn check_vote_stake_threshold(
|
pub fn check_vote_stake_threshold(
|
||||||
&self,
|
&self,
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
stake_lockouts: &HashMap<u64, StakeLockout>,
|
voted_stakes: &VotedStakes,
|
||||||
total_staked: u64,
|
total_stake: Stake,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut lockouts = self.lockouts.clone();
|
let mut lockouts = self.lockouts.clone();
|
||||||
lockouts.process_slot_vote_unchecked(slot);
|
lockouts.process_slot_vote_unchecked(slot);
|
||||||
let vote = lockouts.nth_recent_vote(self.threshold_depth);
|
let vote = lockouts.nth_recent_vote(self.threshold_depth);
|
||||||
if let Some(vote) = vote {
|
if let Some(vote) = vote {
|
||||||
if let Some(fork_stake) = stake_lockouts.get(&vote.slot) {
|
if let Some(fork_stake) = voted_stakes.get(&vote.slot) {
|
||||||
let lockout = fork_stake.stake as f64 / total_staked as f64;
|
let lockout = *fork_stake as f64 / total_stake as f64;
|
||||||
trace!(
|
trace!(
|
||||||
"fork_stake slot: {}, vote slot: {}, lockout: {} fork_stake: {} total_stake: {}",
|
"fork_stake slot: {}, vote slot: {}, lockout: {} fork_stake: {} total_stake: {}",
|
||||||
slot, vote.slot, lockout, fork_stake.stake, total_staked
|
slot, vote.slot, lockout, fork_stake, total_stake
|
||||||
);
|
);
|
||||||
if vote.confirmation_count as usize > self.threshold_depth {
|
if vote.confirmation_count as usize > self.threshold_depth {
|
||||||
for old_vote in &self.lockouts.votes {
|
for old_vote in &self.lockouts.votes {
|
||||||
@ -533,8 +523,8 @@ impl Tower {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Update lockouts for all the ancestors
|
/// Update lockouts for all the ancestors
|
||||||
pub(crate) fn update_ancestor_lockouts(
|
pub(crate) fn populate_ancestor_voted_stakes(
|
||||||
stake_lockouts: &mut HashMap<Slot, StakeLockout>,
|
voted_stakes: &mut VotedStakes,
|
||||||
vote: &Lockout,
|
vote: &Lockout,
|
||||||
ancestors: &HashMap<Slot, HashSet<Slot>>,
|
ancestors: &HashMap<Slot, HashSet<Slot>>,
|
||||||
) {
|
) {
|
||||||
@ -548,8 +538,7 @@ impl Tower {
|
|||||||
let mut slot_with_ancestors = vec![vote.slot];
|
let mut slot_with_ancestors = vec![vote.slot];
|
||||||
slot_with_ancestors.extend(vote_slot_ancestors.unwrap());
|
slot_with_ancestors.extend(vote_slot_ancestors.unwrap());
|
||||||
for slot in slot_with_ancestors {
|
for slot in slot_with_ancestors {
|
||||||
let entry = &mut stake_lockouts.entry(slot).or_default();
|
voted_stakes.entry(slot).or_default();
|
||||||
entry.lockout += vote.lockout();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -577,8 +566,8 @@ impl Tower {
|
|||||||
|
|
||||||
/// Update stake for all the ancestors.
|
/// Update stake for all the ancestors.
|
||||||
/// Note, stake is the same for all the ancestor.
|
/// Note, stake is the same for all the ancestor.
|
||||||
fn update_ancestor_stakes(
|
fn update_ancestor_voted_stakes(
|
||||||
stake_lockouts: &mut HashMap<Slot, StakeLockout>,
|
voted_stakes: &mut VotedStakes,
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
lamports: u64,
|
lamports: u64,
|
||||||
ancestors: &HashMap<Slot, HashSet<Slot>>,
|
ancestors: &HashMap<Slot, HashSet<Slot>>,
|
||||||
@ -592,8 +581,8 @@ impl Tower {
|
|||||||
let mut slot_with_ancestors = vec![slot];
|
let mut slot_with_ancestors = vec![slot];
|
||||||
slot_with_ancestors.extend(vote_slot_ancestors.unwrap());
|
slot_with_ancestors.extend(vote_slot_ancestors.unwrap());
|
||||||
for slot in slot_with_ancestors {
|
for slot in slot_with_ancestors {
|
||||||
let entry = &mut stake_lockouts.entry(slot).or_default();
|
let current = voted_stakes.entry(slot).or_default();
|
||||||
entry.stake += lamports;
|
*current += lamports;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1359,8 +1348,8 @@ pub mod test {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.collect();
|
.collect();
|
||||||
let ComputedBankState {
|
let ComputedBankState {
|
||||||
stake_lockouts,
|
voted_stakes,
|
||||||
total_staked,
|
total_stake,
|
||||||
bank_weight,
|
bank_weight,
|
||||||
mut pubkey_votes,
|
mut pubkey_votes,
|
||||||
..
|
..
|
||||||
@ -1371,9 +1360,8 @@ pub mod test {
|
|||||||
&ancestors,
|
&ancestors,
|
||||||
&mut PubkeyReferences::default(),
|
&mut PubkeyReferences::default(),
|
||||||
);
|
);
|
||||||
assert_eq!(stake_lockouts[&0].stake, 2);
|
assert_eq!(voted_stakes[&0], 2);
|
||||||
assert_eq!(stake_lockouts[&0].lockout, 2 + 2 + 4 + 4);
|
assert_eq!(total_stake, 2);
|
||||||
assert_eq!(total_staked, 2);
|
|
||||||
pubkey_votes.sort();
|
pubkey_votes.sort();
|
||||||
assert_eq!(pubkey_votes, account_latest_votes);
|
assert_eq!(pubkey_votes, account_latest_votes);
|
||||||
|
|
||||||
@ -1413,7 +1401,7 @@ pub mod test {
|
|||||||
let expected_bank_weight = 2 * vote_account_expected_weight;
|
let expected_bank_weight = 2 * vote_account_expected_weight;
|
||||||
assert_eq!(tower.lockouts.root_slot, Some(0));
|
assert_eq!(tower.lockouts.root_slot, Some(0));
|
||||||
let ComputedBankState {
|
let ComputedBankState {
|
||||||
stake_lockouts,
|
voted_stakes,
|
||||||
bank_weight,
|
bank_weight,
|
||||||
mut pubkey_votes,
|
mut pubkey_votes,
|
||||||
..
|
..
|
||||||
@ -1425,11 +1413,10 @@ pub mod test {
|
|||||||
&mut PubkeyReferences::default(),
|
&mut PubkeyReferences::default(),
|
||||||
);
|
);
|
||||||
for i in 0..MAX_LOCKOUT_HISTORY {
|
for i in 0..MAX_LOCKOUT_HISTORY {
|
||||||
assert_eq!(stake_lockouts[&(i as u64)].stake, 2);
|
assert_eq!(voted_stakes[&(i as u64)], 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// should be the sum of all the weights for root
|
// should be the sum of all the weights for root
|
||||||
assert!(stake_lockouts[&0].lockout > (2 * (1 << MAX_LOCKOUT_HISTORY)));
|
|
||||||
assert_eq!(bank_weight, expected_bank_weight);
|
assert_eq!(bank_weight, expected_bank_weight);
|
||||||
pubkey_votes.sort();
|
pubkey_votes.sort();
|
||||||
assert_eq!(pubkey_votes, account_latest_votes);
|
assert_eq!(pubkey_votes, account_latest_votes);
|
||||||
@ -1438,15 +1425,7 @@ pub mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_check_vote_threshold_without_votes() {
|
fn test_check_vote_threshold_without_votes() {
|
||||||
let tower = Tower::new_for_tests(1, 0.67);
|
let tower = Tower::new_for_tests(1, 0.67);
|
||||||
let stakes = vec![(
|
let stakes = vec![(0, 1 as Stake)].into_iter().collect();
|
||||||
0,
|
|
||||||
StakeLockout {
|
|
||||||
stake: 1,
|
|
||||||
lockout: 8,
|
|
||||||
},
|
|
||||||
)]
|
|
||||||
.into_iter()
|
|
||||||
.collect();
|
|
||||||
assert!(tower.check_vote_stake_threshold(0, &stakes, 2));
|
assert!(tower.check_vote_stake_threshold(0, &stakes, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1456,13 +1435,7 @@ pub mod test {
|
|||||||
let mut tower = Tower::new_for_tests(4, 0.67);
|
let mut tower = Tower::new_for_tests(4, 0.67);
|
||||||
let mut stakes = HashMap::new();
|
let mut stakes = HashMap::new();
|
||||||
for i in 0..(MAX_LOCKOUT_HISTORY as u64 + 1) {
|
for i in 0..(MAX_LOCKOUT_HISTORY as u64 + 1) {
|
||||||
stakes.insert(
|
stakes.insert(i, 1 as Stake);
|
||||||
i,
|
|
||||||
StakeLockout {
|
|
||||||
stake: 1,
|
|
||||||
lockout: 8,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
tower.record_vote(i, Hash::default());
|
tower.record_vote(i, Hash::default());
|
||||||
}
|
}
|
||||||
assert!(!tower.check_vote_stake_threshold(MAX_LOCKOUT_HISTORY as u64 + 1, &stakes, 2,));
|
assert!(!tower.check_vote_stake_threshold(MAX_LOCKOUT_HISTORY as u64 + 1, &stakes, 2,));
|
||||||
@ -1471,15 +1444,7 @@ pub mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_is_slot_confirmed_not_enough_stake_failure() {
|
fn test_is_slot_confirmed_not_enough_stake_failure() {
|
||||||
let tower = Tower::new_for_tests(1, 0.67);
|
let tower = Tower::new_for_tests(1, 0.67);
|
||||||
let stakes = vec![(
|
let stakes = vec![(0, 1 as Stake)].into_iter().collect();
|
||||||
0,
|
|
||||||
StakeLockout {
|
|
||||||
stake: 1,
|
|
||||||
lockout: 8,
|
|
||||||
},
|
|
||||||
)]
|
|
||||||
.into_iter()
|
|
||||||
.collect();
|
|
||||||
assert!(!tower.is_slot_confirmed(0, &stakes, 2));
|
assert!(!tower.is_slot_confirmed(0, &stakes, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1493,15 +1458,7 @@ pub mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_is_slot_confirmed_pass() {
|
fn test_is_slot_confirmed_pass() {
|
||||||
let tower = Tower::new_for_tests(1, 0.67);
|
let tower = Tower::new_for_tests(1, 0.67);
|
||||||
let stakes = vec![(
|
let stakes = vec![(0, 2 as Stake)].into_iter().collect();
|
||||||
0,
|
|
||||||
StakeLockout {
|
|
||||||
stake: 2,
|
|
||||||
lockout: 8,
|
|
||||||
},
|
|
||||||
)]
|
|
||||||
.into_iter()
|
|
||||||
.collect();
|
|
||||||
assert!(tower.is_slot_confirmed(0, &stakes, 2));
|
assert!(tower.is_slot_confirmed(0, &stakes, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1614,30 +1571,14 @@ pub mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_check_vote_threshold_below_threshold() {
|
fn test_check_vote_threshold_below_threshold() {
|
||||||
let mut tower = Tower::new_for_tests(1, 0.67);
|
let mut tower = Tower::new_for_tests(1, 0.67);
|
||||||
let stakes = vec![(
|
let stakes = vec![(0, 1 as Stake)].into_iter().collect();
|
||||||
0,
|
|
||||||
StakeLockout {
|
|
||||||
stake: 1,
|
|
||||||
lockout: 8,
|
|
||||||
},
|
|
||||||
)]
|
|
||||||
.into_iter()
|
|
||||||
.collect();
|
|
||||||
tower.record_vote(0, Hash::default());
|
tower.record_vote(0, Hash::default());
|
||||||
assert!(!tower.check_vote_stake_threshold(1, &stakes, 2));
|
assert!(!tower.check_vote_stake_threshold(1, &stakes, 2));
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_check_vote_threshold_above_threshold() {
|
fn test_check_vote_threshold_above_threshold() {
|
||||||
let mut tower = Tower::new_for_tests(1, 0.67);
|
let mut tower = Tower::new_for_tests(1, 0.67);
|
||||||
let stakes = vec![(
|
let stakes = vec![(0, 2 as Stake)].into_iter().collect();
|
||||||
0,
|
|
||||||
StakeLockout {
|
|
||||||
stake: 2,
|
|
||||||
lockout: 8,
|
|
||||||
},
|
|
||||||
)]
|
|
||||||
.into_iter()
|
|
||||||
.collect();
|
|
||||||
tower.record_vote(0, Hash::default());
|
tower.record_vote(0, Hash::default());
|
||||||
assert!(tower.check_vote_stake_threshold(1, &stakes, 2));
|
assert!(tower.check_vote_stake_threshold(1, &stakes, 2));
|
||||||
}
|
}
|
||||||
@ -1645,15 +1586,7 @@ pub mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_check_vote_threshold_above_threshold_after_pop() {
|
fn test_check_vote_threshold_above_threshold_after_pop() {
|
||||||
let mut tower = Tower::new_for_tests(1, 0.67);
|
let mut tower = Tower::new_for_tests(1, 0.67);
|
||||||
let stakes = vec![(
|
let stakes = vec![(0, 2 as Stake)].into_iter().collect();
|
||||||
0,
|
|
||||||
StakeLockout {
|
|
||||||
stake: 2,
|
|
||||||
lockout: 8,
|
|
||||||
},
|
|
||||||
)]
|
|
||||||
.into_iter()
|
|
||||||
.collect();
|
|
||||||
tower.record_vote(0, Hash::default());
|
tower.record_vote(0, Hash::default());
|
||||||
tower.record_vote(1, Hash::default());
|
tower.record_vote(1, Hash::default());
|
||||||
tower.record_vote(2, Hash::default());
|
tower.record_vote(2, Hash::default());
|
||||||
@ -1672,24 +1605,7 @@ pub mod test {
|
|||||||
fn test_check_vote_threshold_lockouts_not_updated() {
|
fn test_check_vote_threshold_lockouts_not_updated() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let mut tower = Tower::new_for_tests(1, 0.67);
|
let mut tower = Tower::new_for_tests(1, 0.67);
|
||||||
let stakes = vec![
|
let stakes = vec![(0, 1 as Stake), (1, 2 as Stake)].into_iter().collect();
|
||||||
(
|
|
||||||
0,
|
|
||||||
StakeLockout {
|
|
||||||
stake: 1,
|
|
||||||
lockout: 8,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
(
|
|
||||||
1,
|
|
||||||
StakeLockout {
|
|
||||||
stake: 2,
|
|
||||||
lockout: 8,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]
|
|
||||||
.into_iter()
|
|
||||||
.collect();
|
|
||||||
tower.record_vote(0, Hash::default());
|
tower.record_vote(0, Hash::default());
|
||||||
tower.record_vote(1, Hash::default());
|
tower.record_vote(1, Hash::default());
|
||||||
tower.record_vote(2, Hash::default());
|
tower.record_vote(2, Hash::default());
|
||||||
@ -1698,15 +1614,15 @@ pub mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_stake_is_updated_for_entire_branch() {
|
fn test_stake_is_updated_for_entire_branch() {
|
||||||
let mut stake_lockouts = HashMap::new();
|
let mut voted_stakes = HashMap::new();
|
||||||
let mut account = Account::default();
|
let mut account = Account::default();
|
||||||
account.lamports = 1;
|
account.lamports = 1;
|
||||||
let set: HashSet<u64> = vec![0u64, 1u64].into_iter().collect();
|
let set: HashSet<u64> = vec![0u64, 1u64].into_iter().collect();
|
||||||
let ancestors: HashMap<u64, HashSet<u64>> = [(2u64, set)].iter().cloned().collect();
|
let ancestors: HashMap<u64, HashSet<u64>> = [(2u64, set)].iter().cloned().collect();
|
||||||
Tower::update_ancestor_stakes(&mut stake_lockouts, 2, account.lamports, &ancestors);
|
Tower::update_ancestor_voted_stakes(&mut voted_stakes, 2, account.lamports, &ancestors);
|
||||||
assert_eq!(stake_lockouts[&0].stake, 1);
|
assert_eq!(voted_stakes[&0], 1);
|
||||||
assert_eq!(stake_lockouts[&1].stake, 1);
|
assert_eq!(voted_stakes[&1], 1);
|
||||||
assert_eq!(stake_lockouts[&2].stake, 1);
|
assert_eq!(voted_stakes[&2], 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1790,8 +1706,8 @@ pub mod test {
|
|||||||
tower.record_vote(*vote, Hash::default());
|
tower.record_vote(*vote, Hash::default());
|
||||||
}
|
}
|
||||||
let ComputedBankState {
|
let ComputedBankState {
|
||||||
stake_lockouts,
|
voted_stakes,
|
||||||
total_staked,
|
total_stake,
|
||||||
..
|
..
|
||||||
} = Tower::collect_vote_lockouts(
|
} = Tower::collect_vote_lockouts(
|
||||||
&Pubkey::default(),
|
&Pubkey::default(),
|
||||||
@ -1800,15 +1716,15 @@ pub mod test {
|
|||||||
&ancestors,
|
&ancestors,
|
||||||
&mut PubkeyReferences::default(),
|
&mut PubkeyReferences::default(),
|
||||||
);
|
);
|
||||||
assert!(tower.check_vote_stake_threshold(vote_to_evaluate, &stake_lockouts, total_staked,));
|
assert!(tower.check_vote_stake_threshold(vote_to_evaluate, &voted_stakes, total_stake,));
|
||||||
|
|
||||||
// CASE 2: Now we want to evaluate a vote for slot VOTE_THRESHOLD_DEPTH + 1. This slot
|
// CASE 2: Now we want to evaluate a vote for slot VOTE_THRESHOLD_DEPTH + 1. This slot
|
||||||
// will expire the vote in one of the vote accounts, so we should have insufficient
|
// will expire the vote in one of the vote accounts, so we should have insufficient
|
||||||
// stake to pass the threshold
|
// stake to pass the threshold
|
||||||
let vote_to_evaluate = VOTE_THRESHOLD_DEPTH as u64 + 1;
|
let vote_to_evaluate = VOTE_THRESHOLD_DEPTH as u64 + 1;
|
||||||
let ComputedBankState {
|
let ComputedBankState {
|
||||||
stake_lockouts,
|
voted_stakes,
|
||||||
total_staked,
|
total_stake,
|
||||||
..
|
..
|
||||||
} = Tower::collect_vote_lockouts(
|
} = Tower::collect_vote_lockouts(
|
||||||
&Pubkey::default(),
|
&Pubkey::default(),
|
||||||
@ -1817,7 +1733,7 @@ pub mod test {
|
|||||||
&ancestors,
|
&ancestors,
|
||||||
&mut PubkeyReferences::default(),
|
&mut PubkeyReferences::default(),
|
||||||
);
|
);
|
||||||
assert!(!tower.check_vote_stake_threshold(vote_to_evaluate, &stake_lockouts, total_staked,));
|
assert!(!tower.check_vote_stake_threshold(vote_to_evaluate, &voted_stakes, total_stake,));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vote_and_check_recent(num_votes: usize) {
|
fn vote_and_check_recent(num_votes: usize) {
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
cluster_info_vote_listener::SlotVoteTracker, cluster_slots::SlotPubkeys,
|
cluster_info_vote_listener::SlotVoteTracker,
|
||||||
consensus::StakeLockout, pubkey_references::PubkeyReferences,
|
cluster_slots::SlotPubkeys,
|
||||||
|
pubkey_references::PubkeyReferences,
|
||||||
replay_stage::SUPERMINORITY_THRESHOLD,
|
replay_stage::SUPERMINORITY_THRESHOLD,
|
||||||
|
{consensus::Stake, consensus::VotedStakes},
|
||||||
};
|
};
|
||||||
use solana_ledger::blockstore_processor::{ConfirmationProgress, ConfirmationTiming};
|
use solana_ledger::blockstore_processor::{ConfirmationProgress, ConfirmationTiming};
|
||||||
use solana_runtime::{bank::Bank, bank_forks::BankForks};
|
use solana_runtime::{bank::Bank, bank_forks::BankForks};
|
||||||
@ -190,14 +192,14 @@ impl ForkProgress {
|
|||||||
pub(crate) struct ForkStats {
|
pub(crate) struct ForkStats {
|
||||||
pub(crate) weight: u128,
|
pub(crate) weight: u128,
|
||||||
pub(crate) fork_weight: u128,
|
pub(crate) fork_weight: u128,
|
||||||
pub(crate) total_staked: u64,
|
pub(crate) total_stake: Stake,
|
||||||
pub(crate) block_height: u64,
|
pub(crate) block_height: u64,
|
||||||
pub(crate) has_voted: bool,
|
pub(crate) has_voted: bool,
|
||||||
pub(crate) is_recent: bool,
|
pub(crate) is_recent: bool,
|
||||||
pub(crate) is_empty: bool,
|
pub(crate) is_empty: bool,
|
||||||
pub(crate) vote_threshold: bool,
|
pub(crate) vote_threshold: bool,
|
||||||
pub(crate) is_locked_out: bool,
|
pub(crate) is_locked_out: bool,
|
||||||
pub(crate) stake_lockouts: HashMap<u64, StakeLockout>,
|
pub(crate) voted_stakes: VotedStakes,
|
||||||
pub(crate) confirmation_reported: bool,
|
pub(crate) confirmation_reported: bool,
|
||||||
pub(crate) computed: bool,
|
pub(crate) computed: bool,
|
||||||
pub(crate) lockout_intervals: LockoutIntervals,
|
pub(crate) lockout_intervals: LockoutIntervals,
|
||||||
|
@ -8,7 +8,7 @@ use crate::{
|
|||||||
cluster_slots::ClusterSlots,
|
cluster_slots::ClusterSlots,
|
||||||
commitment::BlockCommitmentCache,
|
commitment::BlockCommitmentCache,
|
||||||
commitment_service::{AggregateCommitmentService, CommitmentAggregationData},
|
commitment_service::{AggregateCommitmentService, CommitmentAggregationData},
|
||||||
consensus::{ComputedBankState, StakeLockout, SwitchForkDecision, Tower},
|
consensus::{ComputedBankState, Stake, SwitchForkDecision, Tower, VotedStakes},
|
||||||
fork_choice::{ForkChoice, SelectVoteAndResetForkResult},
|
fork_choice::{ForkChoice, SelectVoteAndResetForkResult},
|
||||||
heaviest_subtree_fork_choice::HeaviestSubtreeForkChoice,
|
heaviest_subtree_fork_choice::HeaviestSubtreeForkChoice,
|
||||||
poh_recorder::{PohRecorder, GRACE_TICKS_FACTOR, MAX_GRACE_SLOTS},
|
poh_recorder::{PohRecorder, GRACE_TICKS_FACTOR, MAX_GRACE_SLOTS},
|
||||||
@ -321,8 +321,8 @@ impl ReplayStage {
|
|||||||
let fork_stats = progress.get_fork_stats(slot).unwrap();
|
let fork_stats = progress.get_fork_stats(slot).unwrap();
|
||||||
let confirmed_forks = Self::confirm_forks(
|
let confirmed_forks = Self::confirm_forks(
|
||||||
&tower,
|
&tower,
|
||||||
&fork_stats.stake_lockouts,
|
&fork_stats.voted_stakes,
|
||||||
fork_stats.total_staked,
|
fork_stats.total_stake,
|
||||||
&progress,
|
&progress,
|
||||||
&bank_forks,
|
&bank_forks,
|
||||||
);
|
);
|
||||||
@ -948,7 +948,7 @@ impl ReplayStage {
|
|||||||
Self::update_commitment_cache(
|
Self::update_commitment_cache(
|
||||||
bank.clone(),
|
bank.clone(),
|
||||||
bank_forks.read().unwrap().root(),
|
bank_forks.read().unwrap().root(),
|
||||||
progress.get_fork_stats(bank.slot()).unwrap().total_staked,
|
progress.get_fork_stats(bank.slot()).unwrap().total_stake,
|
||||||
lockouts_sender,
|
lockouts_sender,
|
||||||
);
|
);
|
||||||
Self::push_vote(
|
Self::push_vote(
|
||||||
@ -1049,11 +1049,11 @@ impl ReplayStage {
|
|||||||
fn update_commitment_cache(
|
fn update_commitment_cache(
|
||||||
bank: Arc<Bank>,
|
bank: Arc<Bank>,
|
||||||
root: Slot,
|
root: Slot,
|
||||||
total_staked: u64,
|
total_stake: Stake,
|
||||||
lockouts_sender: &Sender<CommitmentAggregationData>,
|
lockouts_sender: &Sender<CommitmentAggregationData>,
|
||||||
) {
|
) {
|
||||||
if let Err(e) =
|
if let Err(e) =
|
||||||
lockouts_sender.send(CommitmentAggregationData::new(bank, root, total_staked))
|
lockouts_sender.send(CommitmentAggregationData::new(bank, root, total_stake))
|
||||||
{
|
{
|
||||||
trace!("lockouts_sender failed: {:?}", e);
|
trace!("lockouts_sender failed: {:?}", e);
|
||||||
}
|
}
|
||||||
@ -1233,16 +1233,16 @@ impl ReplayStage {
|
|||||||
&computed_bank_state,
|
&computed_bank_state,
|
||||||
);
|
);
|
||||||
let ComputedBankState {
|
let ComputedBankState {
|
||||||
stake_lockouts,
|
voted_stakes,
|
||||||
total_staked,
|
total_stake,
|
||||||
lockout_intervals,
|
lockout_intervals,
|
||||||
..
|
..
|
||||||
} = computed_bank_state;
|
} = computed_bank_state;
|
||||||
let stats = progress
|
let stats = progress
|
||||||
.get_fork_stats_mut(bank_slot)
|
.get_fork_stats_mut(bank_slot)
|
||||||
.expect("All frozen banks must exist in the Progress map");
|
.expect("All frozen banks must exist in the Progress map");
|
||||||
stats.total_staked = total_staked;
|
stats.total_stake = total_stake;
|
||||||
stats.stake_lockouts = stake_lockouts;
|
stats.voted_stakes = voted_stakes;
|
||||||
stats.lockout_intervals = lockout_intervals;
|
stats.lockout_intervals = lockout_intervals;
|
||||||
stats.block_height = bank.block_height();
|
stats.block_height = bank.block_height();
|
||||||
stats.computed = true;
|
stats.computed = true;
|
||||||
@ -1277,11 +1277,8 @@ impl ReplayStage {
|
|||||||
.get_fork_stats_mut(bank_slot)
|
.get_fork_stats_mut(bank_slot)
|
||||||
.expect("All frozen banks must exist in the Progress map");
|
.expect("All frozen banks must exist in the Progress map");
|
||||||
|
|
||||||
stats.vote_threshold = tower.check_vote_stake_threshold(
|
stats.vote_threshold =
|
||||||
bank_slot,
|
tower.check_vote_stake_threshold(bank_slot, &stats.voted_stakes, stats.total_stake);
|
||||||
&stats.stake_lockouts,
|
|
||||||
stats.total_staked,
|
|
||||||
);
|
|
||||||
stats.is_locked_out = tower.is_locked_out(bank_slot, &ancestors);
|
stats.is_locked_out = tower.is_locked_out(bank_slot, &ancestors);
|
||||||
stats.has_voted = tower.has_voted(bank_slot);
|
stats.has_voted = tower.has_voted(bank_slot);
|
||||||
stats.is_recent = tower.is_recent(bank_slot);
|
stats.is_recent = tower.is_recent(bank_slot);
|
||||||
@ -1590,8 +1587,8 @@ impl ReplayStage {
|
|||||||
|
|
||||||
fn confirm_forks(
|
fn confirm_forks(
|
||||||
tower: &Tower,
|
tower: &Tower,
|
||||||
stake_lockouts: &HashMap<u64, StakeLockout>,
|
voted_stakes: &VotedStakes,
|
||||||
total_staked: u64,
|
total_stake: Stake,
|
||||||
progress: &ProgressMap,
|
progress: &ProgressMap,
|
||||||
bank_forks: &RwLock<BankForks>,
|
bank_forks: &RwLock<BankForks>,
|
||||||
) -> Vec<Slot> {
|
) -> Vec<Slot> {
|
||||||
@ -1605,8 +1602,7 @@ impl ReplayStage {
|
|||||||
.expect("bank in progress must exist in BankForks")
|
.expect("bank in progress must exist in BankForks")
|
||||||
.clone();
|
.clone();
|
||||||
let duration = prog.replay_stats.started.elapsed().as_millis();
|
let duration = prog.replay_stats.started.elapsed().as_millis();
|
||||||
if bank.is_frozen() && tower.is_slot_confirmed(*slot, stake_lockouts, total_staked)
|
if bank.is_frozen() && tower.is_slot_confirmed(*slot, voted_stakes, total_stake) {
|
||||||
{
|
|
||||||
info!("validator fork confirmed {} {}ms", *slot, duration);
|
info!("validator fork confirmed {} {}ms", *slot, duration);
|
||||||
datapoint_info!("validator-confirmation", ("duration_ms", duration, i64));
|
datapoint_info!("validator-confirmation", ("duration_ms", duration, i64));
|
||||||
confirmed_forks.push(*slot);
|
confirmed_forks.push(*slot);
|
||||||
@ -1615,7 +1611,7 @@ impl ReplayStage {
|
|||||||
"validator fork not confirmed {} {}ms {:?}",
|
"validator fork not confirmed {} {}ms {:?}",
|
||||||
*slot,
|
*slot,
|
||||||
duration,
|
duration,
|
||||||
stake_lockouts.get(slot)
|
voted_stakes.get(slot)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2595,8 +2591,8 @@ pub(crate) mod tests {
|
|||||||
let fork_progress = progress.get(&0).unwrap();
|
let fork_progress = progress.get(&0).unwrap();
|
||||||
let confirmed_forks = ReplayStage::confirm_forks(
|
let confirmed_forks = ReplayStage::confirm_forks(
|
||||||
&tower,
|
&tower,
|
||||||
&fork_progress.fork_stats.stake_lockouts,
|
&fork_progress.fork_stats.voted_stakes,
|
||||||
fork_progress.fork_stats.total_staked,
|
fork_progress.fork_stats.total_stake,
|
||||||
&progress,
|
&progress,
|
||||||
&bank_forks,
|
&bank_forks,
|
||||||
);
|
);
|
||||||
@ -2637,8 +2633,8 @@ pub(crate) mod tests {
|
|||||||
let fork_progress = progress.get(&1).unwrap();
|
let fork_progress = progress.get(&1).unwrap();
|
||||||
let confirmed_forks = ReplayStage::confirm_forks(
|
let confirmed_forks = ReplayStage::confirm_forks(
|
||||||
&tower,
|
&tower,
|
||||||
&fork_progress.fork_stats.stake_lockouts,
|
&fork_progress.fork_stats.voted_stakes,
|
||||||
fork_progress.fork_stats.total_staked,
|
fork_progress.fork_stats.total_stake,
|
||||||
&progress,
|
&progress,
|
||||||
&bank_forks,
|
&bank_forks,
|
||||||
);
|
);
|
||||||
|
@ -23,13 +23,12 @@ this array, representing all the possible number of confirmations from 1 to
|
|||||||
Building this `BlockCommitment` struct leverages the computations already being
|
Building this `BlockCommitment` struct leverages the computations already being
|
||||||
performed for building consensus. The `collect_vote_lockouts` function in
|
performed for building consensus. The `collect_vote_lockouts` function in
|
||||||
`consensus.rs` builds a HashMap, where each entry is of the form `(b, s)`
|
`consensus.rs` builds a HashMap, where each entry is of the form `(b, s)`
|
||||||
where `s` is a `StakeLockout` struct representing the amount of stake and
|
where `s` is the amount of stake on a bank `b`.
|
||||||
lockout on a bank `b`.
|
|
||||||
|
|
||||||
This computation is performed on a votable candidate bank `b` as follows.
|
This computation is performed on a votable candidate bank `b` as follows.
|
||||||
|
|
||||||
```text
|
```text
|
||||||
let output: HashMap<b, StakeLockout> = HashMap::new();
|
let output: HashMap<b, Stake> = HashMap::new();
|
||||||
for vote_account in b.vote_accounts {
|
for vote_account in b.vote_accounts {
|
||||||
for v in vote_account.vote_stack {
|
for v in vote_account.vote_stack {
|
||||||
for a in ancestors(v) {
|
for a in ancestors(v) {
|
||||||
@ -39,7 +38,7 @@ This computation is performed on a votable candidate bank `b` as follows.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
where `f` is some accumulation function that modifies the `StakeLockout` entry
|
where `f` is some accumulation function that modifies the `Stake` entry
|
||||||
for slot `a` with some data derivable from vote `v` and `vote_account`
|
for slot `a` with some data derivable from vote `v` and `vote_account`
|
||||||
(stake, lockout, etc.). Note here that the `ancestors` here only includes
|
(stake, lockout, etc.). Note here that the `ancestors` here only includes
|
||||||
slots that are present in the current status cache. Signatures for banks earlier
|
slots that are present in the current status cache. Signatures for banks earlier
|
||||||
@ -63,7 +62,7 @@ votes > v as the number of confirmations will be lower).
|
|||||||
Now more specifically, we augment the above computation to:
|
Now more specifically, we augment the above computation to:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
let output: HashMap<b, StakeLockout> = HashMap::new();
|
let output: HashMap<b, Stake> = HashMap::new();
|
||||||
let fork_commitment_cache = ForkCommitmentCache::default();
|
let fork_commitment_cache = ForkCommitmentCache::default();
|
||||||
for vote_account in b.vote_accounts {
|
for vote_account in b.vote_accounts {
|
||||||
// vote stack is sorted from oldest vote to newest vote
|
// vote stack is sorted from oldest vote to newest vote
|
||||||
@ -78,12 +77,12 @@ Now more specifically, we augment the above computation to:
|
|||||||
where `f'` is defined as:
|
where `f'` is defined as:
|
||||||
```text
|
```text
|
||||||
fn f`(
|
fn f`(
|
||||||
stake_lockout: &mut StakeLockout,
|
stake: &mut Stake,
|
||||||
some_ancestor: &mut BlockCommitment,
|
some_ancestor: &mut BlockCommitment,
|
||||||
vote_account: VoteAccount,
|
vote_account: VoteAccount,
|
||||||
v: Vote, total_stake: u64
|
v: Vote, total_stake: u64
|
||||||
){
|
){
|
||||||
f(stake_lockout, vote_account, v);
|
f(stake, vote_account, v);
|
||||||
*some_ancestor.commitment[v.num_confirmations] += vote_account.stake;
|
*some_ancestor.commitment[v.num_confirmations] += vote_account.stake;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
Reference in New Issue
Block a user