light_compressed_account/instruction_data/
traits.rs1use core::fmt::Debug;
2
3#[cfg(all(feature = "std", feature = "anchor"))]
4use anchor_lang::AnchorSerialize;
5#[allow(unused_imports)]
6#[cfg(not(all(feature = "std", feature = "anchor")))]
7use borsh::BorshSerialize as AnchorSerialize;
8use light_program_profiler::profile;
9use tinyvec::ArrayVec;
10use zerocopy::Ref;
11
12use super::{
13 compressed_proof::CompressedProof,
14 cpi_context::CompressedCpiContext,
15 zero_copy::{ZPackedMerkleContext, ZPackedReadOnlyAddress, ZPackedReadOnlyCompressedAccount},
16};
17use crate::{compressed_account::CompressedAccountData, pubkey::Pubkey, CompressedAccountError};
18
19pub trait InstructionDiscriminator {
20 fn discriminator(&self) -> &'static [u8];
21}
22
23pub trait LightInstructionData: InstructionDiscriminator + AnchorSerialize {
24 #[cfg(feature = "alloc")]
25 #[profile]
26 #[inline(never)]
27 fn data(&self) -> Result<crate::Vec<u8>, CompressedAccountError> {
28 let inputs = AnchorSerialize::try_to_vec(self)
29 .map_err(|_| CompressedAccountError::InvalidArgument)?;
30 let mut data = crate::Vec::with_capacity(8 + inputs.len());
31 data.extend_from_slice(self.discriminator());
32
33 data.extend_from_slice(inputs.as_slice());
34 Ok(data)
35 }
36
37 #[profile]
38 fn data_array<const N: usize>(&self) -> Result<ArrayVec<[u8; N]>, CompressedAccountError> {
39 let mut data = ArrayVec::new();
40 data.extend_from_slice(self.discriminator());
42 self.serialize(&mut data.as_mut_slice())
43 .map_err(|_e| CompressedAccountError::InputTooLarge(data.len().saturating_sub(N)))?;
44
45 Ok(data)
46 }
47}
48
49pub trait InstructionData<'a> {
50 fn owner(&self) -> Pubkey;
51 fn new_addresses(&self) -> &[impl NewAddress<'a>];
52 fn input_accounts(&self) -> &[impl InputAccount<'a>];
53 fn output_accounts(&self) -> &[impl OutputAccount<'a>];
54 fn read_only_accounts(&self) -> Option<&[ZPackedReadOnlyCompressedAccount]>;
55 fn read_only_addresses(&self) -> Option<&[ZPackedReadOnlyAddress]>;
56 fn is_compress(&self) -> bool;
57 fn compress_or_decompress_lamports(&self) -> Option<u64>;
58 fn proof(&self) -> Option<Ref<&'a [u8], CompressedProof>>;
59 fn cpi_context(&self) -> Option<CompressedCpiContext>;
60 fn bump(&self) -> Option<u8>;
61 fn account_option_config(&self) -> Result<AccountOptions, CompressedAccountError>;
62 fn with_transaction_hash(&self) -> bool;
63}
64
65pub trait NewAddress<'a>
66where
67 Self: Debug,
68{
69 fn seed(&self) -> [u8; 32];
70 fn address_queue_index(&self) -> u8;
71 fn address_merkle_tree_account_index(&self) -> u8;
72 fn address_merkle_tree_root_index(&self) -> u16;
73 fn assigned_compressed_account_index(&self) -> Option<usize>;
74 fn owner(&self) -> Option<&[u8; 32]> {
75 None
76 }
77}
78
79pub trait InputAccount<'a>
80where
81 Self: Debug,
82{
83 fn owner(&self) -> &crate::pubkey::Pubkey;
84 fn lamports(&self) -> u64;
85 fn address(&self) -> Option<[u8; 32]>;
86 fn merkle_context(&self) -> ZPackedMerkleContext;
87 fn has_data(&self) -> bool;
88 fn data(&self) -> Option<CompressedAccountData>;
89 fn skip(&self) -> bool;
90 fn hash_with_hashed_values(
91 &self,
92 owner_hashed: &[u8; 32],
93 merkle_tree_hashed: &[u8; 32],
94 leaf_index: &u32,
95 is_batched: bool,
96 ) -> Result<[u8; 32], CompressedAccountError>;
97
98 fn root_index(&self) -> u16;
99}
100
101pub trait OutputAccount<'a>
102where
103 Self: Debug,
104{
105 fn lamports(&self) -> u64;
106 fn address(&self) -> Option<[u8; 32]>;
107 fn has_data(&self) -> bool;
108 fn skip(&self) -> bool;
109 fn data(&self) -> Option<CompressedAccountData>;
110 fn owner(&self) -> Pubkey;
111 fn merkle_tree_index(&self) -> u8;
112 fn hash_with_hashed_values(
113 &self,
114 owner_hashed: &[u8; 32],
115 merkle_tree_hashed: &[u8; 32],
116 leaf_index: &u32,
117 is_batched: bool,
118 ) -> Result<[u8; 32], CompressedAccountError>;
119}
120
121#[derive(Debug, Clone, Copy, PartialEq, Eq)]
122pub struct AccountOptions {
123 pub sol_pool_pda: bool,
124 pub decompression_recipient: bool,
125 pub cpi_context_account: bool,
126 pub write_to_cpi_context: bool,
127}