switchboard_solana/attestation_program/accounts/
attestation_queue.rs

1use crate::cfg_client;
2use crate::prelude::*;
3use bytemuck::{Pod, Zeroable};
4use std::cell::Ref;
5
6use crate::SWITCHBOARD_ATTESTATION_PROGRAM_ID;
7
8#[zero_copy(unsafe)]
9#[repr(packed)]
10pub struct AttestationQueueAccountData {
11    /// The address of the authority which is permitted to add/remove allowed enclave measurements.
12    pub authority: Pubkey,
13    /// Allowed enclave measurements.
14    pub mr_enclaves: [[u8; 32]; 32],
15    /// The number of allowed enclave measurements.
16    pub mr_enclaves_len: u32,
17    /// The addresses of the quote verifiers who have a valid
18    /// verification status and have heartbeated on-chain recently.
19    pub data: [Pubkey; 128],
20    /// The length of valid quote verifiers for the given attestation queue.
21    pub data_len: u32,
22    /// Allow authority to force add a node after X seconds with no heartbeat.
23    pub allow_authority_override_after: i64,
24    /// Even if a heartbeating machine quote verifies with proper measurement,
25    /// require authority signoff.
26    pub require_authority_heartbeat_permission: bool,
27    /// Require FunctionAccounts to have PermitQueueUsage before they are executed.
28    pub require_usage_permissions: bool,
29    /// The maximum allowable time until a EnclaveAccount needs to be re-verified on-chain.
30    pub max_quote_verification_age: i64,
31    /// The reward paid to quote verifiers for attesting on-chain.
32    pub reward: u32, //TODO
33    /// The unix timestamp when the last quote verifier heartbeated on-chain.
34    pub last_heartbeat: i64,
35    pub node_timeout: i64, // TODO ??
36    /// Incrementer used to track the current quote verifier permitted to run any available functions.
37    pub curr_idx: u32,
38    /// Incrementer used to garbage collect and remove stale quote verifiers.
39    pub gc_idx: u32,
40
41    /// The minimum number of lamports a quote verifier needs to lock-up in order to heartbeat and verify other quotes.
42    pub verifier_min_stake: u64,
43    /// The minimum number of lamports a function needs to lock-up in order to use a queues resources.
44    pub function_min_stake: u64,
45
46    /// Reserved.
47    pub _ebuf: [u8; 1008],
48}
49
50impl anchor_lang::AccountDeserialize for AttestationQueueAccountData {
51    fn try_deserialize(buf: &mut &[u8]) -> anchor_lang::Result<Self> {
52        if buf.len() < AttestationQueueAccountData::discriminator().len() {
53            return Err(anchor_lang::error::ErrorCode::AccountDiscriminatorNotFound.into());
54        }
55        let given_disc = &buf[..8];
56        if AttestationQueueAccountData::discriminator() != given_disc {
57            return Err(
58                anchor_lang::error::Error::from(anchor_lang::error::AnchorError {
59                    error_name: anchor_lang::error::ErrorCode::AccountDiscriminatorMismatch.name(),
60                    error_code_number: anchor_lang::error::ErrorCode::AccountDiscriminatorMismatch
61                        .into(),
62                    error_msg: anchor_lang::error::ErrorCode::AccountDiscriminatorMismatch
63                        .to_string(),
64                    error_origin: Some(anchor_lang::error::ErrorOrigin::Source(
65                        anchor_lang::error::Source {
66                            filename: "programs/attestation_program/src/lib.rs",
67                            line: 1u32,
68                        },
69                    )),
70                    compared_values: None,
71                })
72                .with_account_name("AttestationQueueAccountData"),
73            );
74        }
75        Self::try_deserialize_unchecked(buf)
76    }
77    fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result<Self> {
78        let data: &[u8] = &buf[8..];
79        bytemuck::try_from_bytes(data)
80            .map(|r: &Self| *r)
81            .map_err(|_| anchor_lang::error::ErrorCode::AccountDidNotDeserialize.into())
82    }
83}
84
85unsafe impl Pod for AttestationQueueAccountData {}
86unsafe impl Zeroable for AttestationQueueAccountData {}
87
88impl Discriminator for AttestationQueueAccountData {
89    const DISCRIMINATOR: [u8; 8] = [192, 53, 130, 67, 234, 207, 39, 171];
90}
91
92impl Owner for AttestationQueueAccountData {
93    fn owner() -> Pubkey {
94        SWITCHBOARD_ATTESTATION_PROGRAM_ID
95    }
96}
97
98impl ZeroCopy for AttestationQueueAccountData {}
99
100impl AttestationQueueAccountData {
101    pub fn size() -> usize {
102        8 + std::mem::size_of::<AttestationQueueAccountData>()
103    }
104
105    /// Returns the deserialized Switchboard AttestationQueue account
106    ///
107    /// # Arguments
108    ///
109    /// * `attestation_queue_account_info` - A Solana AccountInfo referencing an existing Switchboard AttestationQueue
110    ///
111    /// # Examples
112    ///
113    /// ```ignore
114    /// use switchboard_solana::AttestationQueueAccountData;
115    ///
116    /// let attestation_queue = AttestationQueueAccountData::new(attestation_queue_account_info)?;
117    /// ```
118    pub fn new<'info>(
119        attestation_queue_account_info: &'info AccountInfo<'info>,
120    ) -> anchor_lang::Result<Ref<'info, AttestationQueueAccountData>> {
121        let data = attestation_queue_account_info.try_borrow_data()?;
122        if data.len() < AttestationQueueAccountData::discriminator().len() {
123            return Err(ErrorCode::AccountDiscriminatorNotFound.into());
124        }
125
126        let mut disc_bytes = [0u8; 8];
127        disc_bytes.copy_from_slice(&data[..8]);
128        if disc_bytes != AttestationQueueAccountData::discriminator() {
129            return Err(ErrorCode::AccountDiscriminatorMismatch.into());
130        }
131
132        Ok(Ref::map(data, |data| {
133            bytemuck::from_bytes(&data[8..std::mem::size_of::<AttestationQueueAccountData>() + 8])
134        }))
135    }
136
137    /// Returns the deserialized Switchboard AttestationQueue account
138    ///
139    /// # Arguments
140    ///
141    /// * `data` - A Solana AccountInfo's data buffer
142    ///
143    /// # Examples
144    ///
145    /// ```ignore
146    /// use switchboard_solana::AttestationQueueAccountData;
147    ///
148    /// let attestation_queue = AttestationQueueAccountData::new(attestation_queue_account_info.try_borrow_data()?)?;
149    /// ```
150    pub fn new_from_bytes(data: &[u8]) -> anchor_lang::Result<&AttestationQueueAccountData> {
151        if data.len() < AttestationQueueAccountData::discriminator().len() {
152            return Err(ErrorCode::AccountDiscriminatorNotFound.into());
153        }
154
155        let mut disc_bytes = [0u8; 8];
156        disc_bytes.copy_from_slice(&data[..8]);
157        if disc_bytes != AttestationQueueAccountData::discriminator() {
158            return Err(ErrorCode::AccountDiscriminatorMismatch.into());
159        }
160
161        Ok(bytemuck::from_bytes(
162            &data[8..std::mem::size_of::<AttestationQueueAccountData>() + 8],
163        ))
164    }
165
166    pub fn has_mr_enclave(&self, mr_enclave: &[u8]) -> bool {
167        self.mr_enclaves[..self.mr_enclaves_len as usize]
168            .iter()
169            .any(|x| x.to_vec() == mr_enclave.to_vec())
170    }
171
172    cfg_client! {
173        pub fn fetch(
174            client: &solana_client::rpc_client::RpcClient,
175            pubkey: Pubkey,
176        ) -> std::result::Result<Self, switchboard_common::SbError> {
177            crate::client::fetch_zerocopy_account(client, pubkey)
178        }
179
180        pub async fn fetch_async(
181            client: &solana_client::nonblocking::rpc_client::RpcClient,
182            pubkey: Pubkey,
183        ) -> std::result::Result<Self, switchboard_common::SbError> {
184            crate::client::fetch_zerocopy_account_async(client, pubkey).await
185        }
186
187        pub fn fetch_sync<T: solana_sdk::client::SyncClient>(
188            client: &T,
189            pubkey: Pubkey,
190        ) -> std::result::Result<Self, switchboard_common::SbError> {
191            crate::client::fetch_zerocopy_account_sync(client, pubkey)
192        }
193    }
194}