solana_zk_sdk/zk_elgamal_proof_program/
state.rs

1use {
2    crate::zk_elgamal_proof_program::proof_data::{pod::PodProofType, ProofType},
3    bytemuck::{bytes_of, Pod, Zeroable},
4    num_traits::ToPrimitive,
5    solana_instruction::error::{InstructionError, InstructionError::InvalidAccountData},
6    solana_pubkey::Pubkey,
7    std::mem::size_of,
8};
9
10/// The proof context account state
11#[derive(Clone, Copy, Debug, PartialEq)]
12#[repr(C)]
13pub struct ProofContextState<T: Pod> {
14    /// The proof context authority that can close the account
15    pub context_state_authority: Pubkey,
16    /// The proof type for the context data
17    pub proof_type: PodProofType,
18    /// The proof context data
19    pub proof_context: T,
20}
21
22// `bytemuck::Pod` cannot be derived for generic structs unless the struct is marked
23// `repr(packed)`, which may cause unnecessary complications when referencing its fields. Directly
24// mark `ProofContextState` as `Zeroable` and `Pod` since since none of its fields has an alignment
25// requirement greater than 1 and therefore, guaranteed to be `packed`.
26unsafe impl<T: Pod> Zeroable for ProofContextState<T> {}
27unsafe impl<T: Pod> Pod for ProofContextState<T> {}
28
29impl<T: Pod> ProofContextState<T> {
30    pub fn encode(
31        context_state_authority: &Pubkey,
32        proof_type: ProofType,
33        proof_context: &T,
34    ) -> Vec<u8> {
35        let mut buf = Vec::with_capacity(size_of::<Self>());
36        buf.extend_from_slice(context_state_authority.as_ref());
37        buf.push(ToPrimitive::to_u8(&proof_type).unwrap());
38        buf.extend_from_slice(bytes_of(proof_context));
39        buf
40    }
41
42    /// Interpret a slice as a `ProofContextState`.
43    ///
44    /// This function requires a generic parameter. To access only the generic-independent fields
45    /// in `ProofContextState` without a generic parameter, use
46    /// `ProofContextStateMeta::try_from_bytes` instead.
47    pub fn try_from_bytes(input: &[u8]) -> Result<&Self, InstructionError> {
48        bytemuck::try_from_bytes(input).map_err(|_| InvalidAccountData)
49    }
50}
51
52/// The `ProofContextState` without the proof context itself. This struct exists to facilitate the
53/// decoding of generic-independent fields in `ProofContextState`.
54#[derive(Clone, Copy, Debug, PartialEq, bytemuck_derive::Pod, bytemuck_derive::Zeroable)]
55#[repr(C)]
56pub struct ProofContextStateMeta {
57    /// The proof context authority that can close the account
58    pub context_state_authority: Pubkey,
59    /// The proof type for the context data
60    pub proof_type: PodProofType,
61}
62
63impl ProofContextStateMeta {
64    pub fn try_from_bytes(input: &[u8]) -> Result<&Self, InstructionError> {
65        input
66            .get(..size_of::<ProofContextStateMeta>())
67            .and_then(|data| bytemuck::try_from_bytes(data).ok())
68            .ok_or(InvalidAccountData)
69    }
70}