cronos_network/instructions/
snapshot_capture.rs

1use {
2    crate::{errors::CronosError, state::*},
3    anchor_lang::{prelude::*, solana_program::system_program},
4    anchor_spl::token::TokenAccount,
5    cronos_scheduler::{responses::ExecResponse, state::Manager},
6    std::mem::size_of,
7};
8
9#[derive(Accounts)]
10pub struct SnapshotCapture<'info> {
11    #[account(seeds = [SEED_AUTHORITY], bump, has_one = manager)]
12    pub authority: Box<Account<'info, Authority>>,
13
14    #[account(seeds = [SEED_CONFIG], bump)]
15    pub config: Box<Account<'info, Config>>,
16
17    #[account(
18        init,
19        seeds = [
20            SEED_SNAPSHOT_ENTRY,
21            snapshot.key().as_ref(),
22            snapshot.node_count.to_be_bytes().as_ref()
23        ],
24        bump,
25        payer = payer,
26        space = 8 + size_of::<SnapshotEntry>()
27    )]
28    pub entry: Account<'info, SnapshotEntry>,
29
30    #[account(
31        seeds = [
32            SEED_NODE,
33            node.delegate.as_ref(),
34        ],
35        bump,
36        constraint = node.id == snapshot.node_count @ CronosError::InvalidNode
37    )]
38    pub node: Box<Account<'info, Node>>,
39
40    #[account(mut)]
41    pub payer: Signer<'info>,
42
43    #[account(signer, constraint = manager.authority == authority.key())]
44    pub manager: Box<Account<'info, Manager>>, // TODO this should be the queue
45
46    #[account(seeds = [SEED_REGISTRY], bump)]
47    pub registry: Box<Account<'info, Registry>>,
48
49    #[account(
50        mut,
51        seeds = [
52            SEED_SNAPSHOT,
53            registry.snapshot_count.to_be_bytes().as_ref()
54        ],
55        bump,
56        constraint = snapshot.status == SnapshotStatus::InProgress @ CronosError::SnapshotNotInProgress,
57        constraint = snapshot.node_count < registry.node_count,
58    )]
59    pub snapshot: Account<'info, Snapshot>,
60
61    #[account(
62        associated_token::authority = node,
63        associated_token::mint = config.mint,
64    )]
65    pub stake: Account<'info, TokenAccount>,
66
67    #[account(address = system_program::ID)]
68    pub system_program: Program<'info, System>,
69}
70
71pub fn handler(ctx: Context<SnapshotCapture>) -> Result<ExecResponse> {
72    // Get accounts
73    let entry = &mut ctx.accounts.entry;
74    let node = &ctx.accounts.node;
75    let stake = &ctx.accounts.stake;
76    let snapshot = &mut ctx.accounts.snapshot;
77
78    // Capture the snapshot entry
79    snapshot.capture(entry, node, stake)?;
80
81    // Use dynamic accounts to run the next invocation with the new current snapshot
82    let entry_pubkey = entry.key();
83    let snapshot_pubkey = snapshot.key();
84    let next_snapshot_pubkey = Snapshot::pda(snapshot.id.checked_add(1).unwrap()).0;
85    let next_entry_pubkey = SnapshotEntry::pda(next_snapshot_pubkey, entry.id).0;
86    Ok(ExecResponse {
87        dynamic_accounts: Some(
88            ctx.accounts
89                .to_account_metas(None)
90                .iter()
91                .map(|acc| match acc.pubkey {
92                    _ if acc.pubkey == entry_pubkey => next_entry_pubkey,
93                    _ if acc.pubkey == snapshot_pubkey => next_snapshot_pubkey,
94                    _ => acc.pubkey,
95                })
96                .collect(),
97        ),
98    })
99}