-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9580741
commit b0c3bb1
Showing
9 changed files
with
547 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
#[cfg(test)] | ||
use arbitrary::{Arbitrary, Unstructured}; | ||
use { | ||
serde::{Deserialize, Serialize}, | ||
solana_frozen_abi_macro::AbiExample, | ||
}; | ||
|
||
// this is how many epochs a voter can be remembered for slashing | ||
const MAX_ITEMS: usize = 32; | ||
|
||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, AbiExample)] | ||
pub struct CircBuf<I> { | ||
buf: [I; MAX_ITEMS], | ||
/// next pointer | ||
idx: usize, | ||
is_empty: bool, | ||
} | ||
|
||
impl<I: Default + Copy> Default for CircBuf<I> { | ||
fn default() -> Self { | ||
Self { | ||
buf: [I::default(); MAX_ITEMS], | ||
idx: MAX_ITEMS | ||
.checked_sub(1) | ||
.expect("`MAX_ITEMS` should be positive"), | ||
is_empty: true, | ||
} | ||
} | ||
} | ||
|
||
impl<I> CircBuf<I> { | ||
pub fn append(&mut self, item: I) { | ||
// remember prior delegate and when we switched, to support later slashing | ||
self.idx = self | ||
.idx | ||
.checked_add(1) | ||
.and_then(|idx| idx.checked_rem(MAX_ITEMS)) | ||
.expect("`self.idx` should be < `MAX_ITEMS` which should be non-zero"); | ||
|
||
self.buf[self.idx] = item; | ||
self.is_empty = false; | ||
} | ||
|
||
pub fn buf(&self) -> &[I; MAX_ITEMS] { | ||
&self.buf | ||
} | ||
|
||
pub fn last(&self) -> Option<&I> { | ||
if !self.is_empty { | ||
Some(&self.buf[self.idx]) | ||
} else { | ||
None | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
impl<'a, I: Default + Copy> Arbitrary<'a> for CircBuf<I> | ||
where | ||
I: Arbitrary<'a>, | ||
{ | ||
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> { | ||
let mut circbuf = Self::default(); | ||
|
||
let len = u.arbitrary_len::<I>()?; | ||
for _ in 0..len { | ||
circbuf.append(I::arbitrary(u)?); | ||
} | ||
|
||
Ok(circbuf) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
#[cfg(test)] | ||
use arbitrary::Arbitrary; | ||
use { | ||
serde::{Deserialize, Serialize}, | ||
solana_frozen_abi_macro::AbiExample, | ||
solana_program::clock::Slot, | ||
}; | ||
|
||
// Maximum number of votes to keep around, tightly coupled with | ||
// epoch_schedule::MINIMUM_SLOTS_PER_EPOCH | ||
pub const MAX_LOCKOUT_HISTORY: usize = 31; | ||
pub const INITIAL_LOCKOUT: usize = 2; | ||
|
||
#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Copy, Clone, AbiExample)] | ||
#[cfg_attr(test, derive(Arbitrary))] | ||
pub struct Lockout { | ||
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, | ||
} | ||
} | ||
|
||
// The number of slots for which this vote is locked | ||
pub fn lockout(&self) -> u64 { | ||
(INITIAL_LOCKOUT as u64).pow(self.confirmation_count()) | ||
} | ||
|
||
// The last slot at which a vote is still locked out. Validators should not | ||
// vote on a slot in another fork which is less than or equal to this slot | ||
// to avoid having their stake slashed. | ||
pub fn last_locked_out_slot(&self) -> Slot { | ||
self.slot.saturating_add(self.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) | ||
} | ||
} | ||
|
||
#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Copy, Clone, AbiExample)] | ||
#[cfg_attr(test, derive(Arbitrary))] | ||
pub struct LandedVote { | ||
// Latency is the difference in slot number between the slot that was voted on (lockout.slot) | ||
// and the slot in which the vote that added this Lockout landed. For votes which were | ||
// cast before versions of the validator software which recorded vote latencies, latency is | ||
// recorded as 0. | ||
pub latency: u8, | ||
pub lockout: Lockout, | ||
} | ||
|
||
impl LandedVote { | ||
pub fn slot(&self) -> Slot { | ||
self.lockout.slot | ||
} | ||
|
||
pub fn confirmation_count(&self) -> u32 { | ||
self.lockout.confirmation_count | ||
} | ||
} | ||
|
||
impl From<LandedVote> for Lockout { | ||
fn from(landed_vote: LandedVote) -> Self { | ||
landed_vote.lockout | ||
} | ||
} | ||
|
||
impl From<Lockout> for LandedVote { | ||
fn from(lockout: Lockout) -> Self { | ||
Self { | ||
latency: 0, | ||
lockout, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
//! Vote Program state types. | ||
pub mod circ_buf; | ||
pub mod lockout; | ||
pub mod tower_sync; | ||
pub mod vote; | ||
pub mod vote_state_update; |
Oops, something went wrong.