vote: encapsulate `Lockout` (#29753)
This commit is contained in:
parent
4973fe18f1
commit
c4e43f1de4
|
@ -22,8 +22,8 @@ pub fn parse_vote(data: &[u8]) -> Result<VoteAccountType, ParseAccountError> {
|
|||
.votes
|
||||
.iter()
|
||||
.map(|lockout| UiLockout {
|
||||
slot: lockout.slot,
|
||||
confirmation_count: lockout.confirmation_count,
|
||||
slot: lockout.slot(),
|
||||
confirmation_count: lockout.confirmation_count(),
|
||||
})
|
||||
.collect();
|
||||
let authorized_voters = vote_state
|
||||
|
@ -92,8 +92,8 @@ struct UiLockout {
|
|||
impl From<&Lockout> for UiLockout {
|
||||
fn from(lockout: &Lockout) -> Self {
|
||||
Self {
|
||||
slot: lockout.slot,
|
||||
confirmation_count: lockout.confirmation_count,
|
||||
slot: lockout.slot(),
|
||||
confirmation_count: lockout.confirmation_count(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1536,8 +1536,8 @@ pub struct CliLockout {
|
|||
impl From<&Lockout> for CliLockout {
|
||||
fn from(lockout: &Lockout) -> Self {
|
||||
Self {
|
||||
slot: lockout.slot,
|
||||
confirmation_count: lockout.confirmation_count,
|
||||
slot: lockout.slot(),
|
||||
confirmation_count: lockout.confirmation_count(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -227,11 +227,11 @@ impl AggregateCommitmentService {
|
|||
}
|
||||
|
||||
for vote in &vote_state.votes {
|
||||
while ancestors[ancestors_index] <= vote.slot {
|
||||
while ancestors[ancestors_index] <= vote.slot() {
|
||||
commitment
|
||||
.entry(ancestors[ancestors_index])
|
||||
.or_insert_with(BlockCommitment::default)
|
||||
.increase_confirmation_stake(vote.confirmation_count as usize, lamports);
|
||||
.increase_confirmation_stake(vote.confirmation_count() as usize, lamports);
|
||||
ancestors_index += 1;
|
||||
|
||||
if ancestors_index == ancestors.len() {
|
||||
|
|
|
@ -304,22 +304,22 @@ impl Tower {
|
|||
lockout_intervals
|
||||
.entry(vote.last_locked_out_slot())
|
||||
.or_insert_with(Vec::new)
|
||||
.push((vote.slot, key));
|
||||
.push((vote.slot(), key));
|
||||
}
|
||||
|
||||
if key == *vote_account_pubkey {
|
||||
my_latest_landed_vote = vote_state.nth_recent_vote(0).map(|v| v.slot);
|
||||
my_latest_landed_vote = vote_state.nth_recent_vote(0).map(|v| v.slot());
|
||||
debug!("vote state {:?}", vote_state);
|
||||
debug!(
|
||||
"observed slot {}",
|
||||
vote_state.nth_recent_vote(0).map(|v| v.slot).unwrap_or(0) as i64
|
||||
vote_state.nth_recent_vote(0).map(|v| v.slot()).unwrap_or(0) as i64
|
||||
);
|
||||
debug!("observed root {}", vote_state.root_slot.unwrap_or(0) as i64);
|
||||
datapoint_info!(
|
||||
"tower-observed",
|
||||
(
|
||||
"slot",
|
||||
vote_state.nth_recent_vote(0).map(|v| v.slot).unwrap_or(0),
|
||||
vote_state.nth_recent_vote(0).map(|v| v.slot()).unwrap_or(0),
|
||||
i64
|
||||
),
|
||||
("root", vote_state.root_slot.unwrap_or(0), i64)
|
||||
|
@ -341,27 +341,22 @@ impl Tower {
|
|||
|
||||
for vote in &vote_state.votes {
|
||||
bank_weight += vote.lockout() as u128 * voted_stake as u128;
|
||||
vote_slots.insert(vote.slot);
|
||||
vote_slots.insert(vote.slot());
|
||||
}
|
||||
|
||||
if start_root != vote_state.root_slot {
|
||||
if let Some(root) = start_root {
|
||||
let vote = Lockout {
|
||||
confirmation_count: MAX_LOCKOUT_HISTORY as u32,
|
||||
slot: root,
|
||||
};
|
||||
trace!("ROOT: {}", vote.slot);
|
||||
let vote =
|
||||
Lockout::new_with_confirmation_count(root, MAX_LOCKOUT_HISTORY as u32);
|
||||
trace!("ROOT: {}", vote.slot());
|
||||
bank_weight += vote.lockout() as u128 * voted_stake as u128;
|
||||
vote_slots.insert(vote.slot);
|
||||
vote_slots.insert(vote.slot());
|
||||
}
|
||||
}
|
||||
if let Some(root) = vote_state.root_slot {
|
||||
let vote = Lockout {
|
||||
confirmation_count: MAX_LOCKOUT_HISTORY as u32,
|
||||
slot: root,
|
||||
};
|
||||
let vote = Lockout::new_with_confirmation_count(root, MAX_LOCKOUT_HISTORY as u32);
|
||||
bank_weight += vote.lockout() as u128 * voted_stake as u128;
|
||||
vote_slots.insert(vote.slot);
|
||||
vote_slots.insert(vote.slot());
|
||||
}
|
||||
|
||||
// The last vote in the vote stack is a simulated vote on bank_slot, which
|
||||
|
@ -374,14 +369,14 @@ impl Tower {
|
|||
// this vote stack is the simulated vote, so this fetch should be sufficient
|
||||
// to find the last unsimulated vote.
|
||||
assert_eq!(
|
||||
vote_state.nth_recent_vote(0).map(|l| l.slot),
|
||||
vote_state.nth_recent_vote(0).map(|l| l.slot()),
|
||||
Some(bank_slot)
|
||||
);
|
||||
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
|
||||
Self::update_ancestor_voted_stakes(
|
||||
&mut voted_stakes,
|
||||
vote.slot,
|
||||
vote.slot(),
|
||||
voted_stake,
|
||||
ancestors,
|
||||
);
|
||||
|
@ -443,11 +438,11 @@ impl Tower {
|
|||
local_vote_state
|
||||
.votes
|
||||
.iter()
|
||||
.map(|v| v.slot)
|
||||
.map(|v| v.slot())
|
||||
.skip_while(|s| *s <= last_voted_slot)
|
||||
.collect()
|
||||
} else {
|
||||
local_vote_state.votes.iter().map(|v| v.slot).collect()
|
||||
local_vote_state.votes.iter().map(|v| v.slot()).collect()
|
||||
};
|
||||
VoteTransaction::from(Vote::new(slots, hash))
|
||||
}
|
||||
|
@ -523,7 +518,7 @@ impl Tower {
|
|||
/// Used for tests
|
||||
pub fn increase_lockout(&mut self, confirmation_count_increase: u32) {
|
||||
for vote in self.vote_state.votes.iter_mut() {
|
||||
vote.confirmation_count += confirmation_count_increase;
|
||||
vote.increase_confirmation_count(confirmation_count_increase);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -591,7 +586,7 @@ impl Tower {
|
|||
|
||||
pub fn has_voted(&self, slot: Slot) -> bool {
|
||||
for vote in &self.vote_state.votes {
|
||||
if slot == vote.slot {
|
||||
if slot == vote.slot() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -610,7 +605,7 @@ impl Tower {
|
|||
let mut vote_state = self.vote_state.clone();
|
||||
process_slot_vote_unchecked(&mut vote_state, slot);
|
||||
for vote in &vote_state.votes {
|
||||
if slot != vote.slot && !ancestors.contains(&vote.slot) {
|
||||
if slot != vote.slot() && !ancestors.contains(&vote.slot()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -993,16 +988,16 @@ impl Tower {
|
|||
process_slot_vote_unchecked(&mut vote_state, slot);
|
||||
let vote = vote_state.nth_recent_vote(self.threshold_depth);
|
||||
if let Some(vote) = vote {
|
||||
if let Some(fork_stake) = voted_stakes.get(&vote.slot) {
|
||||
if let Some(fork_stake) = voted_stakes.get(&vote.slot()) {
|
||||
let lockout = *fork_stake as f64 / total_stake as f64;
|
||||
trace!(
|
||||
"fork_stake slot: {}, vote slot: {}, lockout: {} fork_stake: {} total_stake: {}",
|
||||
slot, vote.slot, lockout, fork_stake, total_stake
|
||||
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.vote_state.votes {
|
||||
if old_vote.slot == vote.slot
|
||||
&& old_vote.confirmation_count == vote.confirmation_count
|
||||
if old_vote.slot() == vote.slot()
|
||||
&& old_vote.confirmation_count() == vote.confirmation_count()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -1058,7 +1053,7 @@ impl Tower {
|
|||
self.vote_state
|
||||
.votes
|
||||
.iter()
|
||||
.map(|lockout| lockout.slot)
|
||||
.map(|lockout| lockout.slot())
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -1270,7 +1265,7 @@ impl Tower {
|
|||
.expect("vote_account isn't a VoteState?")
|
||||
.clone();
|
||||
self.initialize_root(root);
|
||||
self.initialize_lockouts(|v| v.slot > root);
|
||||
self.initialize_lockouts(|v| v.slot() > root);
|
||||
trace!(
|
||||
"Lockouts in tower for {} is initialized using bank {}",
|
||||
self.vote_state.node_pubkey,
|
||||
|
@ -1554,9 +1549,9 @@ pub mod test {
|
|||
}
|
||||
|
||||
for i in 1..5 {
|
||||
assert_eq!(tower.vote_state.votes[i - 1].slot as usize, i);
|
||||
assert_eq!(tower.vote_state.votes[i - 1].slot() as usize, i);
|
||||
assert_eq!(
|
||||
tower.vote_state.votes[i - 1].confirmation_count as usize,
|
||||
tower.vote_state.votes[i - 1].confirmation_count() as usize,
|
||||
6 - i
|
||||
);
|
||||
}
|
||||
|
@ -2166,10 +2161,7 @@ pub mod test {
|
|||
tower.record_vote(i as u64, Hash::default());
|
||||
ancestors.insert(i as u64, (0..i as u64).collect());
|
||||
}
|
||||
let root = Lockout {
|
||||
confirmation_count: MAX_LOCKOUT_HISTORY as u32,
|
||||
slot: 0,
|
||||
};
|
||||
let root = Lockout::new_with_confirmation_count(0, MAX_LOCKOUT_HISTORY as u32);
|
||||
let root_weight = root.lockout() as u128;
|
||||
let vote_account_expected_weight = tower
|
||||
.vote_state
|
||||
|
@ -2200,7 +2192,8 @@ pub mod test {
|
|||
|
||||
// should be the sum of all the weights for root
|
||||
assert_eq!(bank_weight, expected_bank_weight);
|
||||
let mut new_votes = latest_validator_votes_for_frozen_banks.take_votes_dirty_set(root.slot);
|
||||
let mut new_votes =
|
||||
latest_validator_votes_for_frozen_banks.take_votes_dirty_set(root.slot());
|
||||
new_votes.sort();
|
||||
assert_eq!(new_votes, account_latest_votes);
|
||||
}
|
||||
|
@ -2325,10 +2318,10 @@ pub mod test {
|
|||
tower.record_vote(1, Hash::default());
|
||||
assert!(!tower.is_locked_out(4, &ancestors));
|
||||
tower.record_vote(4, Hash::default());
|
||||
assert_eq!(tower.vote_state.votes[0].slot, 0);
|
||||
assert_eq!(tower.vote_state.votes[0].confirmation_count, 2);
|
||||
assert_eq!(tower.vote_state.votes[1].slot, 4);
|
||||
assert_eq!(tower.vote_state.votes[1].confirmation_count, 1);
|
||||
assert_eq!(tower.vote_state.votes[0].slot(), 0);
|
||||
assert_eq!(tower.vote_state.votes[0].confirmation_count(), 2);
|
||||
assert_eq!(tower.vote_state.votes[1].slot(), 4);
|
||||
assert_eq!(tower.vote_state.votes[1].confirmation_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -2515,9 +2508,8 @@ pub mod test {
|
|||
let mut tower = Tower::new_for_tests(1, 0.67);
|
||||
let slots = if num_votes > 0 {
|
||||
{ 0..num_votes }
|
||||
.map(|i| Lockout {
|
||||
slot: i as u64,
|
||||
confirmation_count: (num_votes as u32) - (i as u32),
|
||||
.map(|i| {
|
||||
Lockout::new_with_confirmation_count(i as Slot, (num_votes as u32) - (i as u32))
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
|
|
|
@ -2840,7 +2840,7 @@ impl ReplayStage {
|
|||
bank_vote_state.root_slot = Some(local_root);
|
||||
bank_vote_state
|
||||
.votes
|
||||
.retain(|lockout| lockout.slot > local_root);
|
||||
.retain(|lockout| lockout.slot() > local_root);
|
||||
info!(
|
||||
"Local root is larger than on chain root,
|
||||
overwrote bank root {:?} and updated votes {:?}",
|
||||
|
@ -2849,7 +2849,7 @@ impl ReplayStage {
|
|||
|
||||
if let Some(first_vote) = bank_vote_state.votes.front() {
|
||||
assert!(ancestors
|
||||
.get(&first_vote.slot)
|
||||
.get(&first_vote.slot())
|
||||
.expect(
|
||||
"Ancestors map must contain an
|
||||
entry for all slots on this fork
|
||||
|
|
|
@ -713,9 +713,8 @@ mod tests {
|
|||
// Now send some new votes
|
||||
for i in 101..201 {
|
||||
let slots = std::iter::zip((i - 30)..(i + 1), (1..32).rev())
|
||||
.map(|(slot, confirmation_count)| Lockout {
|
||||
slot,
|
||||
confirmation_count,
|
||||
.map(|(slot, confirmation_count)| {
|
||||
Lockout::new_with_confirmation_count(slot, confirmation_count)
|
||||
})
|
||||
.collect::<VecDeque<Lockout>>();
|
||||
let vote = VoteTransaction::from(VoteStateUpdate::new(
|
||||
|
|
|
@ -111,7 +111,7 @@ impl VoteSimulator {
|
|||
.unwrap()
|
||||
.votes
|
||||
.iter()
|
||||
.any(|lockout| lockout.slot == parent));
|
||||
.any(|lockout| lockout.slot() == parent));
|
||||
}
|
||||
}
|
||||
while new_bank.tick_height() < new_bank.max_tick_height() {
|
||||
|
|
|
@ -516,13 +516,13 @@ fn graph_forks(bank_forks: &BankForks, config: &GraphConfig) -> String {
|
|||
let vote_state = vote_state.as_ref().unwrap_or(&default_vote_state);
|
||||
if let Some(last_vote) = vote_state.votes.iter().last() {
|
||||
let entry = last_votes.entry(vote_state.node_pubkey).or_insert((
|
||||
last_vote.slot,
|
||||
last_vote.slot(),
|
||||
vote_state.clone(),
|
||||
*stake,
|
||||
total_stake,
|
||||
));
|
||||
if entry.0 < last_vote.slot {
|
||||
*entry = (last_vote.slot, vote_state.clone(), *stake, total_stake);
|
||||
if entry.0 < last_vote.slot() {
|
||||
*entry = (last_vote.slot(), vote_state.clone(), *stake, total_stake);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -558,7 +558,7 @@ fn graph_forks(bank_forks: &BankForks, config: &GraphConfig) -> String {
|
|||
if let Some(last_vote) = vote_state.votes.iter().last() {
|
||||
let validator_votes = all_votes.entry(vote_state.node_pubkey).or_default();
|
||||
validator_votes
|
||||
.entry(last_vote.slot)
|
||||
.entry(last_vote.slot())
|
||||
.or_insert_with(|| vote_state.clone());
|
||||
}
|
||||
}
|
||||
|
@ -662,7 +662,8 @@ fn graph_forks(bank_forks: &BankForks, config: &GraphConfig) -> String {
|
|||
.iter()
|
||||
.map(|vote| format!(
|
||||
"slot {} (conf={})",
|
||||
vote.slot, vote.confirmation_count
|
||||
vote.slot(),
|
||||
vote.confirmation_count()
|
||||
))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
|
@ -673,7 +674,7 @@ fn graph_forks(bank_forks: &BankForks, config: &GraphConfig) -> String {
|
|||
vote_state
|
||||
.votes
|
||||
.back()
|
||||
.map(|vote| vote.slot.to_string())
|
||||
.map(|vote| vote.slot().to_string())
|
||||
.unwrap_or_else(|| "none".to_string())
|
||||
)
|
||||
};
|
||||
|
@ -721,7 +722,7 @@ fn graph_forks(bank_forks: &BankForks, config: &GraphConfig) -> String {
|
|||
vote_state
|
||||
.votes
|
||||
.iter()
|
||||
.map(|vote| format!("slot {} (conf={})", vote.slot, vote.confirmation_count))
|
||||
.map(|vote| format!("slot {} (conf={})", vote.slot(), vote.confirmation_count()))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
));
|
||||
|
|
|
@ -51,7 +51,7 @@ impl VoteTransaction {
|
|||
VoteTransaction::Vote(vote) => vote.slots[i],
|
||||
VoteTransaction::VoteStateUpdate(vote_state_update)
|
||||
| VoteTransaction::CompactVoteStateUpdate(vote_state_update) => {
|
||||
vote_state_update.lockouts[i].slot
|
||||
vote_state_update.lockouts[i].slot()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -152,8 +152,8 @@ fn check_update_vote_state_slots_are_valid(
|
|||
}
|
||||
|
||||
// If the vote state update is not new enough, return
|
||||
if let Some(last_vote_slot) = vote_state.votes.back().map(|lockout| lockout.slot) {
|
||||
if vote_state_update.lockouts.back().unwrap().slot <= last_vote_slot {
|
||||
if let Some(last_vote_slot) = vote_state.votes.back().map(|lockout| lockout.slot()) {
|
||||
if vote_state_update.lockouts.back().unwrap().slot() <= last_vote_slot {
|
||||
return Err(VoteError::VoteTooOld);
|
||||
}
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ fn check_update_vote_state_slots_are_valid(
|
|||
.lockouts
|
||||
.back()
|
||||
.expect("must be nonempty, checked above")
|
||||
.slot;
|
||||
.slot();
|
||||
|
||||
if slot_hashes.is_empty() {
|
||||
return Err(VoteError::SlotsMismatch);
|
||||
|
@ -193,16 +193,16 @@ fn check_update_vote_state_slots_are_valid(
|
|||
let current_root = vote_state_update.root;
|
||||
for lockout in vote_state.votes.iter().rev() {
|
||||
let is_slot_bigger_than_root = current_root
|
||||
.map(|current_root| lockout.slot > current_root)
|
||||
.map(|current_root| lockout.slot() > current_root)
|
||||
.unwrap_or(true);
|
||||
// Ensure we're iterating from biggest to smallest vote in the
|
||||
// current vote state
|
||||
assert!(lockout.slot < prev_slot && is_slot_bigger_than_root);
|
||||
if lockout.slot <= new_proposed_root {
|
||||
vote_state_update.root = Some(lockout.slot);
|
||||
assert!(lockout.slot() < prev_slot && is_slot_bigger_than_root);
|
||||
if lockout.slot() <= new_proposed_root {
|
||||
vote_state_update.root = Some(lockout.slot());
|
||||
break;
|
||||
}
|
||||
prev_slot = lockout.slot;
|
||||
prev_slot = lockout.slot();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -236,11 +236,11 @@ fn check_update_vote_state_slots_are_valid(
|
|||
let proposed_vote_slot = if let Some(root) = root_to_check {
|
||||
root
|
||||
} else {
|
||||
vote_state_update.lockouts[vote_state_update_index].slot
|
||||
vote_state_update.lockouts[vote_state_update_index].slot()
|
||||
};
|
||||
if root_to_check.is_none()
|
||||
&& vote_state_update_index > 0
|
||||
&& proposed_vote_slot <= vote_state_update.lockouts[vote_state_update_index - 1].slot
|
||||
&& proposed_vote_slot <= vote_state_update.lockouts[vote_state_update_index - 1].slot()
|
||||
{
|
||||
return Err(VoteError::SlotsNotOrdered);
|
||||
}
|
||||
|
@ -530,12 +530,12 @@ pub fn process_new_vote_state(
|
|||
// 2) The confirmations are strictly decreasing
|
||||
// 3) Not zero confirmation votes
|
||||
for vote in &new_state {
|
||||
if vote.confirmation_count == 0 {
|
||||
if vote.confirmation_count() == 0 {
|
||||
return Err(VoteError::ZeroConfirmations);
|
||||
} else if vote.confirmation_count > MAX_LOCKOUT_HISTORY as u32 {
|
||||
} else if vote.confirmation_count() > MAX_LOCKOUT_HISTORY as u32 {
|
||||
return Err(VoteError::ConfirmationTooLarge);
|
||||
} else if let Some(new_root) = new_root {
|
||||
if vote.slot <= new_root
|
||||
if vote.slot() <= new_root
|
||||
&&
|
||||
// This check is necessary because
|
||||
// https://github.com/ryoqun/solana/blob/df55bfb46af039cbc597cd60042d49b9d90b5961/core/src/consensus.rs#L120
|
||||
|
@ -548,11 +548,11 @@ pub fn process_new_vote_state(
|
|||
}
|
||||
|
||||
if let Some(previous_vote) = previous_vote {
|
||||
if previous_vote.slot >= vote.slot {
|
||||
if previous_vote.slot() >= vote.slot() {
|
||||
return Err(VoteError::SlotsNotOrdered);
|
||||
} else if previous_vote.confirmation_count <= vote.confirmation_count {
|
||||
} else if previous_vote.confirmation_count() <= vote.confirmation_count() {
|
||||
return Err(VoteError::ConfirmationsNotOrdered);
|
||||
} else if vote.slot > previous_vote.last_locked_out_slot() {
|
||||
} else if vote.slot() > previous_vote.last_locked_out_slot() {
|
||||
return Err(VoteError::NewVoteStateLockoutMismatch);
|
||||
}
|
||||
}
|
||||
|
@ -576,9 +576,9 @@ pub fn process_new_vote_state(
|
|||
for current_vote in &vote_state.votes {
|
||||
// Find the first vote in the current vote state for a slot greater
|
||||
// than the new proposed root
|
||||
if current_vote.slot <= new_root {
|
||||
if current_vote.slot() <= new_root {
|
||||
current_vote_state_index += 1;
|
||||
if current_vote.slot != new_root {
|
||||
if current_vote.slot() != new_root {
|
||||
finalized_slot_count += 1;
|
||||
}
|
||||
continue;
|
||||
|
@ -599,9 +599,9 @@ pub fn process_new_vote_state(
|
|||
// If the current slot is less than the new proposed slot, then the
|
||||
// new slot must have popped off the old slot, so check that the
|
||||
// lockouts are corrects.
|
||||
match current_vote.slot.cmp(&new_vote.slot) {
|
||||
match current_vote.slot().cmp(&new_vote.slot()) {
|
||||
Ordering::Less => {
|
||||
if current_vote.last_locked_out_slot() >= new_vote.slot {
|
||||
if current_vote.last_locked_out_slot() >= new_vote.slot() {
|
||||
return Err(VoteError::LockoutConflict);
|
||||
}
|
||||
current_vote_state_index += 1;
|
||||
|
@ -609,7 +609,7 @@ pub fn process_new_vote_state(
|
|||
Ordering::Equal => {
|
||||
// The new vote state should never have less lockout than
|
||||
// the previous vote state for the same slot
|
||||
if new_vote.confirmation_count < current_vote.confirmation_count {
|
||||
if new_vote.confirmation_count() < current_vote.confirmation_count() {
|
||||
return Err(VoteError::ConfirmationRollBack);
|
||||
}
|
||||
|
||||
|
@ -640,7 +640,7 @@ pub fn process_new_vote_state(
|
|||
}
|
||||
}
|
||||
if let Some(timestamp) = timestamp {
|
||||
let last_slot = new_state.back().unwrap().slot;
|
||||
let last_slot = new_state.back().unwrap().slot();
|
||||
vote_state.process_timestamp(last_slot, timestamp)?;
|
||||
}
|
||||
vote_state.root_slot = new_root;
|
||||
|
@ -1095,7 +1095,7 @@ mod tests {
|
|||
// One more vote that confirms the entire stack,
|
||||
// the root_slot should change to the
|
||||
// second vote
|
||||
let top_vote = vote_state.votes.front().unwrap().slot;
|
||||
let top_vote = vote_state.votes.front().unwrap().slot();
|
||||
let slot = vote_state.last_lockout().unwrap().last_locked_out_slot();
|
||||
process_slot_vote_unchecked(&mut vote_state, slot);
|
||||
assert_eq!(Some(top_vote), vote_state.root_slot);
|
||||
|
@ -1144,26 +1144,26 @@ mod tests {
|
|||
process_slot_vote_unchecked(&mut vote_state, i as u64);
|
||||
}
|
||||
|
||||
assert_eq!(vote_state.votes[0].confirmation_count, 3);
|
||||
assert_eq!(vote_state.votes[0].confirmation_count(), 3);
|
||||
|
||||
// Expire the second and third votes
|
||||
let expire_slot = vote_state.votes[1].slot + vote_state.votes[1].lockout() + 1;
|
||||
let expire_slot = vote_state.votes[1].slot() + vote_state.votes[1].lockout() + 1;
|
||||
process_slot_vote_unchecked(&mut vote_state, expire_slot);
|
||||
assert_eq!(vote_state.votes.len(), 2);
|
||||
|
||||
// Check that the old votes expired
|
||||
assert_eq!(vote_state.votes[0].slot, 0);
|
||||
assert_eq!(vote_state.votes[1].slot, expire_slot);
|
||||
assert_eq!(vote_state.votes[0].slot(), 0);
|
||||
assert_eq!(vote_state.votes[1].slot(), expire_slot);
|
||||
|
||||
// Process one more vote
|
||||
process_slot_vote_unchecked(&mut vote_state, expire_slot + 1);
|
||||
|
||||
// Confirmation count for the older first vote should remain unchanged
|
||||
assert_eq!(vote_state.votes[0].confirmation_count, 3);
|
||||
assert_eq!(vote_state.votes[0].confirmation_count(), 3);
|
||||
|
||||
// The later votes should still have increasing confirmation counts
|
||||
assert_eq!(vote_state.votes[1].confirmation_count, 2);
|
||||
assert_eq!(vote_state.votes[2].confirmation_count, 1);
|
||||
assert_eq!(vote_state.votes[1].confirmation_count(), 2);
|
||||
assert_eq!(vote_state.votes[2].confirmation_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1192,8 +1192,8 @@ mod tests {
|
|||
process_slot_vote_unchecked(&mut vote_state, 0);
|
||||
process_slot_vote_unchecked(&mut vote_state, 1);
|
||||
process_slot_vote_unchecked(&mut vote_state, 0);
|
||||
assert_eq!(vote_state.nth_recent_vote(0).unwrap().slot, 1);
|
||||
assert_eq!(vote_state.nth_recent_vote(1).unwrap().slot, 0);
|
||||
assert_eq!(vote_state.nth_recent_vote(0).unwrap().slot(), 1);
|
||||
assert_eq!(vote_state.nth_recent_vote(1).unwrap().slot(), 0);
|
||||
assert!(vote_state.nth_recent_vote(2).is_none());
|
||||
}
|
||||
|
||||
|
@ -1206,7 +1206,7 @@ mod tests {
|
|||
}
|
||||
for i in 0..(MAX_LOCKOUT_HISTORY - 1) {
|
||||
assert_eq!(
|
||||
vote_state.nth_recent_vote(i).unwrap().slot as usize,
|
||||
vote_state.nth_recent_vote(i).unwrap().slot() as usize,
|
||||
MAX_LOCKOUT_HISTORY - i - 1,
|
||||
);
|
||||
}
|
||||
|
@ -1223,7 +1223,12 @@ mod tests {
|
|||
fn recent_votes(vote_state: &VoteState) -> Vec<Vote> {
|
||||
let start = vote_state.votes.len().saturating_sub(MAX_RECENT_VOTES);
|
||||
(start..vote_state.votes.len())
|
||||
.map(|i| Vote::new(vec![vote_state.votes.get(i).unwrap().slot], Hash::default()))
|
||||
.map(|i| {
|
||||
Vote::new(
|
||||
vec![vote_state.votes.get(i).unwrap().slot()],
|
||||
Hash::default(),
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -1511,9 +1516,11 @@ mod tests {
|
|||
fn test_process_new_vote_too_many_votes() {
|
||||
let mut vote_state1 = VoteState::default();
|
||||
let bad_votes: VecDeque<Lockout> = (0..=MAX_LOCKOUT_HISTORY)
|
||||
.map(|slot| Lockout {
|
||||
slot: slot as Slot,
|
||||
confirmation_count: (MAX_LOCKOUT_HISTORY - slot + 1) as u32,
|
||||
.map(|slot| {
|
||||
Lockout::new_with_confirmation_count(
|
||||
slot as Slot,
|
||||
(MAX_LOCKOUT_HISTORY - slot + 1) as u32,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -1574,14 +1581,8 @@ mod tests {
|
|||
let current_epoch = vote_state1.current_epoch();
|
||||
|
||||
let bad_votes: VecDeque<Lockout> = vec![
|
||||
Lockout {
|
||||
slot: 0,
|
||||
confirmation_count: 0,
|
||||
},
|
||||
Lockout {
|
||||
slot: 1,
|
||||
confirmation_count: 1,
|
||||
},
|
||||
Lockout::new_with_confirmation_count(0, 0),
|
||||
Lockout::new_with_confirmation_count(1, 1),
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
@ -1591,14 +1592,8 @@ mod tests {
|
|||
);
|
||||
|
||||
let bad_votes: VecDeque<Lockout> = vec![
|
||||
Lockout {
|
||||
slot: 0,
|
||||
confirmation_count: 2,
|
||||
},
|
||||
Lockout {
|
||||
slot: 1,
|
||||
confirmation_count: 0,
|
||||
},
|
||||
Lockout::new_with_confirmation_count(0, 2),
|
||||
Lockout::new_with_confirmation_count(1, 0),
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
@ -1613,10 +1608,10 @@ mod tests {
|
|||
let mut vote_state1 = VoteState::default();
|
||||
let current_epoch = vote_state1.current_epoch();
|
||||
|
||||
let good_votes: VecDeque<Lockout> = vec![Lockout {
|
||||
slot: 0,
|
||||
confirmation_count: MAX_LOCKOUT_HISTORY as u32,
|
||||
}]
|
||||
let good_votes: VecDeque<Lockout> = vec![Lockout::new_with_confirmation_count(
|
||||
0,
|
||||
MAX_LOCKOUT_HISTORY as u32,
|
||||
)]
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
||||
|
@ -1631,10 +1626,10 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
let mut vote_state1 = VoteState::default();
|
||||
let bad_votes: VecDeque<Lockout> = vec![Lockout {
|
||||
slot: 0,
|
||||
confirmation_count: MAX_LOCKOUT_HISTORY as u32 + 1,
|
||||
}]
|
||||
let bad_votes: VecDeque<Lockout> = vec![Lockout::new_with_confirmation_count(
|
||||
0,
|
||||
MAX_LOCKOUT_HISTORY as u32 + 1,
|
||||
)]
|
||||
.into_iter()
|
||||
.collect();
|
||||
assert_eq!(
|
||||
|
@ -1650,14 +1645,8 @@ mod tests {
|
|||
let root_slot = 5;
|
||||
|
||||
let bad_votes: VecDeque<Lockout> = vec![
|
||||
Lockout {
|
||||
slot: root_slot,
|
||||
confirmation_count: 2,
|
||||
},
|
||||
Lockout {
|
||||
slot: root_slot + 1,
|
||||
confirmation_count: 1,
|
||||
},
|
||||
Lockout::new_with_confirmation_count(root_slot, 2),
|
||||
Lockout::new_with_confirmation_count(root_slot + 1, 1),
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
@ -1674,14 +1663,8 @@ mod tests {
|
|||
);
|
||||
|
||||
let bad_votes: VecDeque<Lockout> = vec![
|
||||
Lockout {
|
||||
slot: root_slot - 1,
|
||||
confirmation_count: 2,
|
||||
},
|
||||
Lockout {
|
||||
slot: root_slot + 1,
|
||||
confirmation_count: 1,
|
||||
},
|
||||
Lockout::new_with_confirmation_count(root_slot - 1, 2),
|
||||
Lockout::new_with_confirmation_count(root_slot + 1, 1),
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
@ -1704,14 +1687,8 @@ mod tests {
|
|||
let current_epoch = vote_state1.current_epoch();
|
||||
|
||||
let bad_votes: VecDeque<Lockout> = vec![
|
||||
Lockout {
|
||||
slot: 1,
|
||||
confirmation_count: 2,
|
||||
},
|
||||
Lockout {
|
||||
slot: 0,
|
||||
confirmation_count: 1,
|
||||
},
|
||||
Lockout::new_with_confirmation_count(1, 2),
|
||||
Lockout::new_with_confirmation_count(0, 1),
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
@ -1721,14 +1698,8 @@ mod tests {
|
|||
);
|
||||
|
||||
let bad_votes: VecDeque<Lockout> = vec![
|
||||
Lockout {
|
||||
slot: 1,
|
||||
confirmation_count: 2,
|
||||
},
|
||||
Lockout {
|
||||
slot: 1,
|
||||
confirmation_count: 1,
|
||||
},
|
||||
Lockout::new_with_confirmation_count(1, 2),
|
||||
Lockout::new_with_confirmation_count(1, 1),
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
@ -1744,14 +1715,8 @@ mod tests {
|
|||
let current_epoch = vote_state1.current_epoch();
|
||||
|
||||
let bad_votes: VecDeque<Lockout> = vec![
|
||||
Lockout {
|
||||
slot: 0,
|
||||
confirmation_count: 1,
|
||||
},
|
||||
Lockout {
|
||||
slot: 1,
|
||||
confirmation_count: 2,
|
||||
},
|
||||
Lockout::new_with_confirmation_count(0, 1),
|
||||
Lockout::new_with_confirmation_count(1, 2),
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
@ -1761,14 +1726,8 @@ mod tests {
|
|||
);
|
||||
|
||||
let bad_votes: VecDeque<Lockout> = vec![
|
||||
Lockout {
|
||||
slot: 0,
|
||||
confirmation_count: 1,
|
||||
},
|
||||
Lockout {
|
||||
slot: 1,
|
||||
confirmation_count: 1,
|
||||
},
|
||||
Lockout::new_with_confirmation_count(0, 1),
|
||||
Lockout::new_with_confirmation_count(1, 1),
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
@ -1784,14 +1743,8 @@ mod tests {
|
|||
let current_epoch = vote_state1.current_epoch();
|
||||
|
||||
let bad_votes: VecDeque<Lockout> = vec![
|
||||
Lockout {
|
||||
slot: 0,
|
||||
confirmation_count: 2,
|
||||
},
|
||||
Lockout {
|
||||
slot: 7,
|
||||
confirmation_count: 1,
|
||||
},
|
||||
Lockout::new_with_confirmation_count(0, 2),
|
||||
Lockout::new_with_confirmation_count(7, 1),
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
@ -1808,33 +1761,18 @@ mod tests {
|
|||
let mut vote_state1 = VoteState::default();
|
||||
let current_epoch = vote_state1.current_epoch();
|
||||
let votes: VecDeque<Lockout> = vec![
|
||||
Lockout {
|
||||
slot: 0,
|
||||
confirmation_count: 4,
|
||||
},
|
||||
Lockout {
|
||||
slot: 1,
|
||||
confirmation_count: 3,
|
||||
},
|
||||
Lockout::new_with_confirmation_count(0, 4),
|
||||
Lockout::new_with_confirmation_count(1, 3),
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
process_new_vote_state(&mut vote_state1, votes, None, None, current_epoch, None).unwrap();
|
||||
|
||||
let votes: VecDeque<Lockout> = vec![
|
||||
Lockout {
|
||||
slot: 0,
|
||||
confirmation_count: 4,
|
||||
},
|
||||
Lockout {
|
||||
slot: 1,
|
||||
Lockout::new_with_confirmation_count(0, 4),
|
||||
// Confirmation count lowered illegally
|
||||
confirmation_count: 2,
|
||||
},
|
||||
Lockout {
|
||||
slot: 2,
|
||||
confirmation_count: 1,
|
||||
},
|
||||
Lockout::new_with_confirmation_count(1, 2),
|
||||
Lockout::new_with_confirmation_count(2, 1),
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
@ -1906,7 +1844,7 @@ mod tests {
|
|||
vote_state1
|
||||
.votes
|
||||
.iter()
|
||||
.map(|vote| vote.slot)
|
||||
.map(|vote| vote.slot())
|
||||
.collect::<Vec<Slot>>(),
|
||||
vec![1, 5]
|
||||
);
|
||||
|
@ -1918,7 +1856,7 @@ mod tests {
|
|||
vote_state2
|
||||
.votes
|
||||
.iter()
|
||||
.map(|vote| vote.slot)
|
||||
.map(|vote| vote.slot())
|
||||
.collect::<Vec<Slot>>(),
|
||||
vec![1, 2, 3, 5, 7]
|
||||
);
|
||||
|
@ -1946,7 +1884,7 @@ mod tests {
|
|||
vote_state1
|
||||
.votes
|
||||
.iter()
|
||||
.map(|vote| vote.slot)
|
||||
.map(|vote| vote.slot())
|
||||
.collect::<Vec<Slot>>(),
|
||||
vec![1, 2, 4, 5]
|
||||
);
|
||||
|
@ -1959,7 +1897,7 @@ mod tests {
|
|||
vote_state2
|
||||
.votes
|
||||
.iter()
|
||||
.map(|vote| vote.slot)
|
||||
.map(|vote| vote.slot())
|
||||
.collect::<Vec<Slot>>(),
|
||||
vec![1, 2, 3, 5, 7]
|
||||
);
|
||||
|
@ -1987,7 +1925,7 @@ mod tests {
|
|||
vote_state1
|
||||
.votes
|
||||
.iter()
|
||||
.map(|vote| vote.slot)
|
||||
.map(|vote| vote.slot())
|
||||
.collect::<Vec<Slot>>(),
|
||||
vec![1, 5, 6, 7]
|
||||
);
|
||||
|
@ -2000,7 +1938,7 @@ mod tests {
|
|||
vote_state2
|
||||
.votes
|
||||
.iter()
|
||||
.map(|vote| vote.slot)
|
||||
.map(|vote| vote.slot())
|
||||
.collect::<Vec<Slot>>(),
|
||||
vec![1, 2, 3, 5, 6, 8]
|
||||
);
|
||||
|
@ -2029,7 +1967,7 @@ mod tests {
|
|||
vote_state1
|
||||
.votes
|
||||
.iter()
|
||||
.map(|vote| vote.slot)
|
||||
.map(|vote| vote.slot())
|
||||
.collect::<Vec<Slot>>(),
|
||||
vec![1, 9]
|
||||
);
|
||||
|
@ -2041,13 +1979,13 @@ mod tests {
|
|||
|
||||
// Slot 1 has been expired by 10, but is kept alive by its descendant
|
||||
// 9 which has not been expired yet.
|
||||
assert_eq!(vote_state2.votes[0].slot, 1);
|
||||
assert_eq!(vote_state2.votes[0].slot(), 1);
|
||||
assert_eq!(vote_state2.votes[0].last_locked_out_slot(), 9);
|
||||
assert_eq!(
|
||||
vote_state2
|
||||
.votes
|
||||
.iter()
|
||||
.map(|vote| vote.slot)
|
||||
.map(|vote| vote.slot())
|
||||
.collect::<Vec<Slot>>(),
|
||||
vec![1, 9, 10]
|
||||
);
|
||||
|
@ -2073,22 +2011,16 @@ mod tests {
|
|||
vote_state1
|
||||
.votes
|
||||
.iter()
|
||||
.map(|vote| vote.slot)
|
||||
.map(|vote| vote.slot())
|
||||
.collect::<Vec<Slot>>(),
|
||||
vec![6, 7, 8]
|
||||
);
|
||||
|
||||
// Try to process something with lockout violations
|
||||
let bad_votes: VecDeque<Lockout> = vec![
|
||||
Lockout {
|
||||
slot: 2,
|
||||
confirmation_count: 5,
|
||||
},
|
||||
Lockout {
|
||||
Lockout::new_with_confirmation_count(2, 5),
|
||||
// Slot 14 could not have popped off slot 6 yet
|
||||
slot: 14,
|
||||
confirmation_count: 1,
|
||||
},
|
||||
Lockout::new_with_confirmation_count(14, 1),
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
@ -2101,14 +2033,8 @@ mod tests {
|
|||
);
|
||||
|
||||
let good_votes: VecDeque<Lockout> = vec![
|
||||
Lockout {
|
||||
slot: 2,
|
||||
confirmation_count: 5,
|
||||
},
|
||||
Lockout {
|
||||
slot: 15,
|
||||
confirmation_count: 1,
|
||||
},
|
||||
Lockout::new_with_confirmation_count(2, 5),
|
||||
Lockout::new_with_confirmation_count(15, 1),
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
@ -2157,10 +2083,7 @@ mod tests {
|
|||
process_vote(&mut vote_state, &vote, &slot_hashes, 0, Some(&feature_set)).unwrap();
|
||||
assert_eq!(
|
||||
vote_state.votes.into_iter().collect::<Vec<Lockout>>(),
|
||||
vec![Lockout {
|
||||
slot: vote_slot,
|
||||
confirmation_count: 1,
|
||||
}]
|
||||
vec![Lockout::new_with_confirmation_count(vote_slot, 1)]
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2341,10 +2264,7 @@ mod tests {
|
|||
let vote_state_update_slots_and_lockouts = vec![(5, 1)];
|
||||
let vote_state_update_root = 4;
|
||||
let expected_root = Some(4);
|
||||
let expected_vote_state = vec![Lockout {
|
||||
slot: 5,
|
||||
confirmation_count: 1,
|
||||
}];
|
||||
let expected_vote_state = vec![Lockout::new_with_confirmation_count(5, 1)];
|
||||
run_test_check_update_vote_state_older_than_history_root(
|
||||
earliest_slot_in_history,
|
||||
current_vote_state_slots,
|
||||
|
@ -2363,10 +2283,7 @@ mod tests {
|
|||
let vote_state_update_slots_and_lockouts = vec![(5, 1)];
|
||||
let vote_state_update_root = 4;
|
||||
let expected_root = Some(4);
|
||||
let expected_vote_state = vec![Lockout {
|
||||
slot: 5,
|
||||
confirmation_count: 1,
|
||||
}];
|
||||
let expected_vote_state = vec![Lockout::new_with_confirmation_count(5, 1)];
|
||||
run_test_check_update_vote_state_older_than_history_root(
|
||||
earliest_slot_in_history,
|
||||
current_vote_state_slots,
|
||||
|
@ -2386,14 +2303,8 @@ mod tests {
|
|||
let vote_state_update_root = 3;
|
||||
let expected_root = Some(3);
|
||||
let expected_vote_state = vec![
|
||||
Lockout {
|
||||
slot: 4,
|
||||
confirmation_count: 2,
|
||||
},
|
||||
Lockout {
|
||||
slot: 5,
|
||||
confirmation_count: 1,
|
||||
},
|
||||
Lockout::new_with_confirmation_count(4, 2),
|
||||
Lockout::new_with_confirmation_count(5, 1),
|
||||
];
|
||||
run_test_check_update_vote_state_older_than_history_root(
|
||||
earliest_slot_in_history,
|
||||
|
@ -2413,14 +2324,8 @@ mod tests {
|
|||
let vote_state_update_root = 3;
|
||||
let expected_root = Some(2);
|
||||
let expected_vote_state = vec![
|
||||
Lockout {
|
||||
slot: 4,
|
||||
confirmation_count: 2,
|
||||
},
|
||||
Lockout {
|
||||
slot: 5,
|
||||
confirmation_count: 1,
|
||||
},
|
||||
Lockout::new_with_confirmation_count(4, 2),
|
||||
Lockout::new_with_confirmation_count(5, 1),
|
||||
];
|
||||
run_test_check_update_vote_state_older_than_history_root(
|
||||
earliest_slot_in_history,
|
||||
|
@ -2441,18 +2346,9 @@ mod tests {
|
|||
let vote_state_update_root = 2;
|
||||
let expected_root = None;
|
||||
let expected_vote_state = vec![
|
||||
Lockout {
|
||||
slot: 3,
|
||||
confirmation_count: 3,
|
||||
},
|
||||
Lockout {
|
||||
slot: 4,
|
||||
confirmation_count: 2,
|
||||
},
|
||||
Lockout {
|
||||
slot: 5,
|
||||
confirmation_count: 1,
|
||||
},
|
||||
Lockout::new_with_confirmation_count(3, 3),
|
||||
Lockout::new_with_confirmation_count(4, 2),
|
||||
Lockout::new_with_confirmation_count(5, 1),
|
||||
];
|
||||
run_test_check_update_vote_state_older_than_history_root(
|
||||
earliest_slot_in_history,
|
||||
|
@ -2471,10 +2367,7 @@ mod tests {
|
|||
let vote_state_update_slots_and_lockouts = vec![(5, 1)];
|
||||
let vote_state_update_root = 2;
|
||||
let expected_root = None;
|
||||
let expected_vote_state = vec![Lockout {
|
||||
slot: 5,
|
||||
confirmation_count: 1,
|
||||
}];
|
||||
let expected_vote_state = vec![Lockout::new_with_confirmation_count(5, 1)];
|
||||
run_test_check_update_vote_state_older_than_history_root(
|
||||
earliest_slot_in_history,
|
||||
current_vote_state_slots,
|
||||
|
@ -2564,14 +2457,8 @@ mod tests {
|
|||
.into_iter()
|
||||
.collect::<Vec<Lockout>>(),
|
||||
vec![
|
||||
Lockout {
|
||||
slot: 1,
|
||||
confirmation_count: 4,
|
||||
},
|
||||
Lockout {
|
||||
slot: vote_slot,
|
||||
confirmation_count: 3,
|
||||
}
|
||||
Lockout::new_with_confirmation_count(1, 4),
|
||||
Lockout::new_with_confirmation_count(vote_slot, 3)
|
||||
]
|
||||
);
|
||||
assert!(do_process_vote_state_update(
|
||||
|
@ -2621,14 +2508,8 @@ mod tests {
|
|||
.into_iter()
|
||||
.collect::<Vec<Lockout>>(),
|
||||
vec![
|
||||
Lockout {
|
||||
slot: existing_older_than_history_slot,
|
||||
confirmation_count: 3,
|
||||
},
|
||||
Lockout {
|
||||
slot: vote_slot,
|
||||
confirmation_count: 2,
|
||||
}
|
||||
Lockout::new_with_confirmation_count(existing_older_than_history_slot, 3),
|
||||
Lockout::new_with_confirmation_count(vote_slot, 2)
|
||||
]
|
||||
);
|
||||
assert!(do_process_vote_state_update(
|
||||
|
@ -2690,18 +2571,9 @@ mod tests {
|
|||
.into_iter()
|
||||
.collect::<Vec<Lockout>>(),
|
||||
vec![
|
||||
Lockout {
|
||||
slot: existing_older_than_history_slot,
|
||||
confirmation_count: 3,
|
||||
},
|
||||
Lockout {
|
||||
slot: 12,
|
||||
confirmation_count: 2,
|
||||
},
|
||||
Lockout {
|
||||
slot: vote_slot,
|
||||
confirmation_count: 1,
|
||||
}
|
||||
Lockout::new_with_confirmation_count(existing_older_than_history_slot, 3),
|
||||
Lockout::new_with_confirmation_count(12, 2),
|
||||
Lockout::new_with_confirmation_count(vote_slot, 1)
|
||||
]
|
||||
);
|
||||
assert!(do_process_vote_state_update(
|
||||
|
@ -2728,7 +2600,7 @@ mod tests {
|
|||
|
||||
// Have to vote for a slot greater than the last vote in the vote state to avoid VoteTooOld
|
||||
// errors
|
||||
let vote_slot = vote_state.votes.back().unwrap().slot + 2;
|
||||
let vote_slot = vote_state.votes.back().unwrap().slot() + 2;
|
||||
let vote_slot_hash = slot_hashes
|
||||
.iter()
|
||||
.find(|(slot, _hash)| *slot == vote_slot)
|
||||
|
@ -2838,7 +2710,7 @@ mod tests {
|
|||
|
||||
// Have to vote for a slot greater than the last vote in the vote state to avoid VoteTooOld
|
||||
// errors
|
||||
let vote_slot = vote_state.votes.back().unwrap().slot + 2;
|
||||
let vote_slot = vote_state.votes.back().unwrap().slot() + 2;
|
||||
let vote_slot_hash = slot_hashes
|
||||
.iter()
|
||||
.find(|(slot, _hash)| *slot == vote_slot)
|
||||
|
@ -2863,22 +2735,10 @@ mod tests {
|
|||
.into_iter()
|
||||
.collect::<Vec<Lockout>>(),
|
||||
vec![
|
||||
Lockout {
|
||||
slot: 2,
|
||||
confirmation_count: 4,
|
||||
},
|
||||
Lockout {
|
||||
slot: 4,
|
||||
confirmation_count: 3,
|
||||
},
|
||||
Lockout {
|
||||
slot: 6,
|
||||
confirmation_count: 2,
|
||||
},
|
||||
Lockout {
|
||||
slot: vote_slot,
|
||||
confirmation_count: 1,
|
||||
}
|
||||
Lockout::new_with_confirmation_count(2, 4),
|
||||
Lockout::new_with_confirmation_count(4, 3),
|
||||
Lockout::new_with_confirmation_count(6, 2),
|
||||
Lockout::new_with_confirmation_count(vote_slot, 1)
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -2902,7 +2762,7 @@ mod tests {
|
|||
|
||||
// Have to vote for a slot greater than the last vote in the vote state to avoid VoteTooOld
|
||||
// errors
|
||||
let vote_slot = vote_state.votes.back().unwrap().slot + 2;
|
||||
let vote_slot = vote_state.votes.back().unwrap().slot() + 2;
|
||||
let vote_slot_hash = slot_hashes
|
||||
.iter()
|
||||
.find(|(slot, _hash)| *slot == vote_slot)
|
||||
|
@ -2926,14 +2786,8 @@ mod tests {
|
|||
.into_iter()
|
||||
.collect::<Vec<Lockout>>(),
|
||||
vec![
|
||||
Lockout {
|
||||
slot: 4,
|
||||
confirmation_count: 2,
|
||||
},
|
||||
Lockout {
|
||||
slot: vote_slot,
|
||||
confirmation_count: 1,
|
||||
}
|
||||
Lockout::new_with_confirmation_count(4, 2),
|
||||
Lockout::new_with_confirmation_count(vote_slot, 1)
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -2961,7 +2815,7 @@ mod tests {
|
|||
|
||||
// Have to vote for a slot greater than the last vote in the vote state to avoid VoteTooOld
|
||||
// errors
|
||||
let vote_slot = vote_state.votes.back().unwrap().slot + 2;
|
||||
let vote_slot = vote_state.votes.back().unwrap().slot() + 2;
|
||||
let vote_slot_hash = Hash::new_unique();
|
||||
let mut vote_state_update =
|
||||
VoteStateUpdate::from(vec![(2, 4), (4, 3), (6, 2), (vote_slot, 1)]);
|
||||
|
|
|
@ -936,7 +936,7 @@ impl JsonRpcRequestProcessor {
|
|||
let vote_state = account.vote_state();
|
||||
let vote_state = vote_state.as_ref().unwrap_or(&default_vote_state);
|
||||
let last_vote = if let Some(vote) = vote_state.votes.iter().last() {
|
||||
vote.slot
|
||||
vote.slot()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
|
|
@ -19,7 +19,7 @@ impl VoteTransaction {
|
|||
VoteTransaction::VoteStateUpdate(vote_state_update) => vote_state_update
|
||||
.lockouts
|
||||
.iter()
|
||||
.map(|lockout| lockout.slot)
|
||||
.map(|lockout| lockout.slot())
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ impl VoteTransaction {
|
|||
match self {
|
||||
VoteTransaction::Vote(vote) => vote.slots.last().copied(),
|
||||
VoteTransaction::VoteStateUpdate(vote_state_update) => {
|
||||
Some(vote_state_update.lockouts.back()?.slot)
|
||||
Some(vote_state_update.lockouts.back()?.slot())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,21 +58,25 @@ impl Vote {
|
|||
|
||||
#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Copy, Clone, AbiExample)]
|
||||
pub struct Lockout {
|
||||
pub slot: Slot,
|
||||
pub confirmation_count: u32,
|
||||
slot: Slot,
|
||||
confirmation_count: u32,
|
||||
}
|
||||
|
||||
impl Lockout {
|
||||
pub fn new(slot: Slot) -> Self {
|
||||
Self::new_with_confirmation_count(slot, 1)
|
||||
}
|
||||
|
||||
pub fn new_with_confirmation_count(slot: Slot, confirmation_count: u32) -> Self {
|
||||
Self {
|
||||
slot,
|
||||
confirmation_count: 1,
|
||||
confirmation_count,
|
||||
}
|
||||
}
|
||||
|
||||
// The number of slots for which this vote is locked
|
||||
pub fn lockout(&self) -> u64 {
|
||||
(INITIAL_LOCKOUT as u64).pow(self.confirmation_count)
|
||||
(INITIAL_LOCKOUT as u64).pow(self.confirmation_count())
|
||||
}
|
||||
|
||||
// The last slot at which a vote is still locked out. Validators should not
|
||||
|
@ -86,6 +90,18 @@ impl Lockout {
|
|||
pub fn is_locked_out_at_slot(&self, slot: Slot) -> bool {
|
||||
self.last_locked_out_slot() >= slot
|
||||
}
|
||||
|
||||
pub fn slot(&self) -> Slot {
|
||||
self.slot
|
||||
}
|
||||
|
||||
pub fn confirmation_count(&self) -> u32 {
|
||||
self.confirmation_count
|
||||
}
|
||||
|
||||
pub fn increase_confirmation_count(&mut self, by: u32) {
|
||||
self.confirmation_count = self.confirmation_count.saturating_add(by)
|
||||
}
|
||||
}
|
||||
|
||||
#[frozen_abi(digest = "GwJfVFsATSj7nvKwtUkHYzqPRaPY6SLxPGXApuCya3x5")]
|
||||
|
@ -105,9 +121,8 @@ impl From<Vec<(Slot, u32)>> for VoteStateUpdate {
|
|||
fn from(recent_slots: Vec<(Slot, u32)>) -> Self {
|
||||
let lockouts: VecDeque<Lockout> = recent_slots
|
||||
.into_iter()
|
||||
.map(|(slot, confirmation_count)| Lockout {
|
||||
slot,
|
||||
confirmation_count,
|
||||
.map(|(slot, confirmation_count)| {
|
||||
Lockout::new_with_confirmation_count(slot, confirmation_count)
|
||||
})
|
||||
.collect();
|
||||
Self {
|
||||
|
@ -130,11 +145,11 @@ impl VoteStateUpdate {
|
|||
}
|
||||
|
||||
pub fn slots(&self) -> Vec<Slot> {
|
||||
self.lockouts.iter().map(|lockout| lockout.slot).collect()
|
||||
self.lockouts.iter().map(|lockout| lockout.slot()).collect()
|
||||
}
|
||||
|
||||
pub fn last_voted_slot(&self) -> Option<Slot> {
|
||||
self.lockouts.back().map(|l| l.slot)
|
||||
self.lockouts.back().map(|l| l.slot())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -329,7 +344,7 @@ impl VoteState {
|
|||
/// Returns if the vote state contains a slot `candidate_slot`
|
||||
pub fn contains_slot(&self, candidate_slot: Slot) -> bool {
|
||||
self.votes
|
||||
.binary_search_by(|lockout| lockout.slot.cmp(&candidate_slot))
|
||||
.binary_search_by(|lockout| lockout.slot().cmp(&candidate_slot))
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
|
@ -365,7 +380,7 @@ impl VoteState {
|
|||
// Once the stack is full, pop the oldest lockout and distribute rewards
|
||||
if self.votes.len() == MAX_LOCKOUT_HISTORY {
|
||||
let vote = self.votes.pop_front().unwrap();
|
||||
self.root_slot = Some(vote.slot);
|
||||
self.root_slot = Some(vote.slot());
|
||||
|
||||
self.increment_credits(epoch, 1);
|
||||
}
|
||||
|
@ -417,13 +432,13 @@ impl VoteState {
|
|||
}
|
||||
|
||||
pub fn last_voted_slot(&self) -> Option<Slot> {
|
||||
self.last_lockout().map(|v| v.slot)
|
||||
self.last_lockout().map(|v| v.slot())
|
||||
}
|
||||
|
||||
// Upto MAX_LOCKOUT_HISTORY many recent unexpired
|
||||
// vote slots pushed onto the stack.
|
||||
pub fn tower(&self) -> Vec<Slot> {
|
||||
self.votes.iter().map(|v| v.slot).collect()
|
||||
self.votes.iter().map(|v| v.slot()).collect()
|
||||
}
|
||||
|
||||
pub fn current_epoch(&self) -> Epoch {
|
||||
|
@ -544,8 +559,8 @@ impl VoteState {
|
|||
for (i, v) in self.votes.iter_mut().enumerate() {
|
||||
// Don't increase the lockout for this vote until we get more confirmations
|
||||
// than the max number of confirmations this vote has seen
|
||||
if stack_depth > i + v.confirmation_count as usize {
|
||||
v.confirmation_count += 1;
|
||||
if stack_depth > i + v.confirmation_count() as usize {
|
||||
v.increase_confirmation_count(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -612,11 +627,11 @@ pub mod serde_compact_vote_state_update {
|
|||
let lockout_offsets = vote_state_update.lockouts.iter().scan(
|
||||
vote_state_update.root.unwrap_or_default(),
|
||||
|slot, lockout| {
|
||||
let offset = match lockout.slot.checked_sub(*slot) {
|
||||
let offset = match lockout.slot().checked_sub(*slot) {
|
||||
None => return Some(Err(serde::ser::Error::custom("Invalid vote lockout"))),
|
||||
Some(offset) => offset,
|
||||
};
|
||||
let confirmation_count = match u8::try_from(lockout.confirmation_count) {
|
||||
let confirmation_count = match u8::try_from(lockout.confirmation_count()) {
|
||||
Ok(confirmation_count) => confirmation_count,
|
||||
Err(_) => {
|
||||
return Some(Err(serde::ser::Error::custom("Invalid confirmation count")))
|
||||
|
@ -626,7 +641,7 @@ pub mod serde_compact_vote_state_update {
|
|||
offset,
|
||||
confirmation_count,
|
||||
};
|
||||
*slot = lockout.slot;
|
||||
*slot = lockout.slot();
|
||||
Some(Ok(lockout_offset))
|
||||
},
|
||||
);
|
||||
|
@ -660,10 +675,10 @@ pub mod serde_compact_vote_state_update {
|
|||
}
|
||||
Some(slot) => slot,
|
||||
};
|
||||
let lockout = Lockout {
|
||||
slot: *slot,
|
||||
confirmation_count: u32::from(lockout_offset.confirmation_count),
|
||||
};
|
||||
let lockout = Lockout::new_with_confirmation_count(
|
||||
*slot,
|
||||
u32::from(lockout_offset.confirmation_count),
|
||||
);
|
||||
Some(Ok(lockout))
|
||||
});
|
||||
Ok(VoteStateUpdate {
|
||||
|
@ -1132,16 +1147,17 @@ mod tests {
|
|||
|
||||
#[allow(clippy::integer_arithmetic)]
|
||||
fn run_serde_compact_vote_state_update<R: Rng>(rng: &mut R) {
|
||||
let lockouts: VecDeque<_> = std::iter::repeat_with(|| Lockout {
|
||||
slot: 149_303_885 + rng.gen_range(0, 10_000),
|
||||
confirmation_count: rng.gen_range(0, 33),
|
||||
let lockouts: VecDeque<_> = std::iter::repeat_with(|| {
|
||||
let slot = 149_303_885 + rng.gen_range(0, 10_000);
|
||||
let confirmation_count = rng.gen_range(0, 33);
|
||||
Lockout::new_with_confirmation_count(slot, confirmation_count)
|
||||
})
|
||||
.take(32)
|
||||
.sorted_by_key(|lockout| lockout.slot)
|
||||
.sorted_by_key(|lockout| lockout.slot())
|
||||
.collect();
|
||||
let root = rng
|
||||
.gen_ratio(1, 2)
|
||||
.then(|| lockouts[0].slot - rng.gen_range(0, 1_000));
|
||||
.then(|| lockouts[0].slot() - rng.gen_range(0, 1_000));
|
||||
let timestamp = rng.gen_ratio(1, 2).then(|| rng.gen());
|
||||
let hash = Hash::from(rng.gen::<[u8; 32]>());
|
||||
let vote_state_update = VoteStateUpdate {
|
||||
|
|
Loading…
Reference in New Issue