cronos_network/state/
rotator.rs

1use {
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/**
15 * Rotator
16 */
17
18#[account]
19#[derive(Debug)]
20pub struct Rotator {
21    pub last_slot: u64, // Slot of the last cycle
22    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
38/**
39 * RotatorAccount
40 */
41
42pub 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        // Start the nonce on a hash of the rotator's pubkey. This is an arbitrary value.
57        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        // Return true if the sample is within the entry's stake range
70        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        // Hash the nonce
79        let mut hasher = DefaultHasher::new();
80        self.nonce.hash(&mut hasher);
81        self.nonce = hasher.finish();
82
83        // Record the slot value
84        self.last_slot = slot;
85        Ok(())
86    }
87}