clockwork_network/state/
registry.rs

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