cronos_network/state/
registry.rs

1use anchor_spl::token::TokenAccount;
2
3use {
4    super::{Node, Snapshot},
5    crate::{
6        errors::CronosError,
7        pda::PDA,
8        state::{NodeAccount, SnapshotAccount, SnapshotStatus},
9    },
10    anchor_lang::{prelude::*, AnchorDeserialize},
11    std::convert::TryFrom,
12};
13
14pub const SEED_REGISTRY: &[u8] = b"registry";
15
16/**
17 * Registry
18 */
19
20#[account]
21#[derive(Debug)]
22pub struct Registry {
23    pub is_locked: bool,
24    pub node_count: u64,
25    pub snapshot_count: u64,
26}
27
28impl Registry {
29    pub fn pda() -> PDA {
30        Pubkey::find_program_address(&[SEED_REGISTRY], &crate::ID)
31    }
32}
33
34impl TryFrom<Vec<u8>> for Registry {
35    type Error = Error;
36    fn try_from(data: Vec<u8>) -> std::result::Result<Self, Self::Error> {
37        Registry::try_deserialize(&mut data.as_slice())
38    }
39}
40
41/**
42 * RegistryAccount
43 */
44
45pub trait RegistryAccount {
46    fn new(&mut self) -> Result<()>;
47
48    fn new_node(
49        &mut self,
50        delegate: &Signer,
51        owner: &mut Signer,
52        node: &mut Account<Node>,
53        stake: &mut Account<TokenAccount>,
54    ) -> Result<()>;
55
56    fn new_snapshot(&mut self, snapshot: &mut Account<Snapshot>) -> Result<()>;
57
58    fn rotate_snapshot(
59        &mut self,
60        clock: &Sysvar<Clock>,
61        current_snapshot: Option<&mut Account<Snapshot>>,
62        next_snapshot: &mut Account<Snapshot>,
63    ) -> Result<()>;
64
65    fn lock(&mut self) -> Result<()>;
66
67    fn unlock(&mut self) -> Result<()>;
68}
69
70impl RegistryAccount for Account<'_, Registry> {
71    fn new(&mut self) -> Result<()> {
72        self.is_locked = false;
73        self.node_count = 0;
74        self.snapshot_count = 0;
75        Ok(())
76    }
77
78    fn new_node(
79        &mut self,
80        delegate: &Signer,
81        owner: &mut Signer,
82        node: &mut Account<Node>,
83        stake: &mut Account<TokenAccount>,
84    ) -> Result<()> {
85        require!(!self.is_locked, CronosError::RegistryLocked);
86        node.new(delegate, self.node_count, owner, stake)?;
87        self.node_count = self.node_count.checked_add(1).unwrap();
88        Ok(())
89    }
90
91    fn new_snapshot(&mut self, snapshot: &mut Account<Snapshot>) -> Result<()> {
92        require!(!self.is_locked, CronosError::RegistryLocked);
93        self.lock()?;
94        snapshot.new(self.snapshot_count)?;
95        Ok(())
96    }
97
98    fn rotate_snapshot(
99        &mut self,
100        clock: &Sysvar<Clock>,
101        current_snapshot: Option<&mut Account<Snapshot>>,
102        next_snapshot: &mut Account<Snapshot>,
103    ) -> Result<()> {
104        // Require the registry is locked
105        require!(self.is_locked, CronosError::RegistryMustBeLocked);
106
107        // Validate the next snapshot is in progress
108        require!(
109            next_snapshot.status == SnapshotStatus::InProgress,
110            CronosError::SnapshotNotInProgress
111        );
112
113        // Validate the snapshot has captured the entire registry
114        require!(
115            next_snapshot.node_count == self.node_count,
116            CronosError::SnapshotIncomplete
117        );
118
119        // Archive the current snapshot
120        match current_snapshot {
121            Some(current_snapshot) => {
122                // Validate the snapshot is current
123                require!(
124                    current_snapshot.status == SnapshotStatus::Current,
125                    CronosError::SnapshotNotCurrent
126                );
127
128                // Mark the current snapshot as archived
129                current_snapshot.status = SnapshotStatus::Archived {
130                    ts: clock.unix_timestamp,
131                };
132            }
133            None => require!(self.snapshot_count == 0, CronosError::SnapshotNotCurrent),
134        }
135
136        // Mark the next snapshot as current
137        next_snapshot.status = SnapshotStatus::Current;
138
139        // Increment snapshot counter
140        self.snapshot_count = self.snapshot_count.checked_add(1).unwrap();
141
142        // Unlock the registry
143        self.unlock()?;
144
145        Ok(())
146    }
147
148    fn lock(&mut self) -> Result<()> {
149        self.is_locked = true;
150        Ok(())
151    }
152
153    fn unlock(&mut self) -> Result<()> {
154        self.is_locked = false;
155        Ok(())
156    }
157}