cronos_network/state/
rotator.rs1use {
2 super::Snapshot,
3 crate::{pda::PDA, state::SnapshotEntry},
4 anchor_lang::{prelude::*, AnchorDeserialize},
5 std::{
6 collections::hash_map::DefaultHasher,
7 convert::TryFrom,
8 hash::{Hash, Hasher},
9 },
10};
11
12pub const SEED_ROTATOR: &[u8] = b"rotator";
13
14#[account]
19#[derive(Debug)]
20pub struct Rotator {
21 pub last_slot: u64, pub nonce: u64,
23}
24
25impl Rotator {
26 pub fn pda() -> PDA {
27 Pubkey::find_program_address(&[SEED_ROTATOR], &crate::ID)
28 }
29}
30
31impl TryFrom<Vec<u8>> for Rotator {
32 type Error = Error;
33 fn try_from(data: Vec<u8>) -> std::result::Result<Self, Self::Error> {
34 Rotator::try_deserialize(&mut data.as_slice())
35 }
36}
37
38pub trait RotatorAccount {
43 fn new(&mut self) -> Result<()>;
44
45 fn is_valid_entry(
46 &mut self,
47 entry: &Account<SnapshotEntry>,
48 snapshot: &Account<Snapshot>,
49 ) -> Result<bool>;
50
51 fn hash_nonce(&mut self, slot: u64) -> Result<()>;
52}
53
54impl RotatorAccount for Account<'_, Rotator> {
55 fn new(&mut self) -> Result<()> {
56 let mut hasher = DefaultHasher::new();
58 self.key().hash(&mut hasher);
59 self.nonce = hasher.finish();
60 self.last_slot = 0;
61 Ok(())
62 }
63
64 fn is_valid_entry(
65 &mut self,
66 entry: &Account<SnapshotEntry>,
67 snapshot: &Account<Snapshot>,
68 ) -> Result<bool> {
69 match self.nonce.checked_rem(snapshot.stake_total) {
71 None => Ok(false),
72 Some(sample) => Ok(sample >= entry.stake_offset
73 && sample < entry.stake_offset.checked_add(entry.stake_amount).unwrap()),
74 }
75 }
76
77 fn hash_nonce(&mut self, slot: u64) -> Result<()> {
78 let mut hasher = DefaultHasher::new();
80 self.nonce.hash(&mut hasher);
81 self.nonce = hasher.finish();
82
83 self.last_slot = slot;
85 Ok(())
86 }
87}