solana_zk_token_sdk/
zk_token_proof_state.rs

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