light_compressed_account/
lib.rs1#![allow(unexpected_cfgs)]
21#![cfg_attr(not(feature = "std"), no_std)]
22
23#[cfg(not(feature = "std"))]
24extern crate alloc;
25
26#[cfg(not(feature = "std"))]
27pub use alloc::{vec, vec::Vec};
28use core::fmt::Display;
29#[cfg(feature = "std")]
30pub use std::{vec, vec::Vec};
31
32use light_hasher::HasherError;
33use thiserror::Error;
34
35pub mod address;
36pub mod compressed_account;
37pub mod constants;
38pub mod discriminators;
39pub use light_hasher::hash_chain;
40pub mod instruction_data;
41pub mod nullifier;
42pub mod pubkey;
43pub mod tx_hash;
44pub use instruction_data::traits::{InstructionDiscriminator, LightInstructionData};
45pub use light_hasher::bigint::bigint_to_be_bytes_array;
46#[cfg(feature = "alloc")]
47pub use light_hasher::hash_to_field_size::{
48 hash_to_bn254_field_size_be, hashv_to_bn254_field_size_be,
49};
50pub use pubkey::Pubkey;
51
52#[derive(Debug, Error, PartialEq)]
53pub enum CompressedAccountError {
54 #[error("Invalid input size, expected at most {0}")]
55 InputTooLarge(usize),
56 #[error("Invalid chunk size")]
57 InvalidChunkSize,
58 #[error("Invalid seeds")]
59 InvalidSeeds,
60 #[error("Invalid rollover threshold")]
61 InvalidRolloverThreshold,
62 #[error("Invalid input length")]
63 InvalidInputLength,
64 #[error("Hasher error {0}")]
65 HasherError(#[from] HasherError),
66 #[error("Invalid Account size.")]
67 InvalidAccountSize,
68 #[error("Account is mutable.")]
69 AccountMutable,
70 #[error("Account is already initialized.")]
71 AlreadyInitialized,
72 #[error("Invalid account balance.")]
73 InvalidAccountBalance,
74 #[error("Failed to borrow rent sysvar.")]
75 FailedBorrowRentSysvar,
76 #[error("Derive address error.")]
77 DeriveAddressError,
78 #[error("Invalid argument.")]
79 InvalidArgument,
80 #[error("Expected address for compressed account got None.")]
81 ZeroCopyExpectedAddress,
82 #[error("Expected address for compressed account got None.")]
83 InstructionDataExpectedAddress,
84 #[error("Compressed account data not initialized.")]
85 CompressedAccountDataNotInitialized,
86 #[error(
87 "Invalid CPI context configuration: cannot write to CPI context without valid context"
88 )]
89 InvalidCpiContext,
90 #[error("Expected discriminator for compressed account got None.")]
91 ExpectedDiscriminator,
92 #[error("Expected data hash for compressed account got None.")]
93 ExpectedDataHash,
94 #[error("Expected proof for compressed account got None.")]
95 InstructionDataExpectedProof,
96 #[error("Expected proof for compressed account got None.")]
97 ZeroCopyExpectedProof,
98 #[error("Invalid proof size: expected 128 bytes, got {0}")]
99 InvalidProofSize(usize),
100}
101
102impl From<CompressedAccountError> for u32 {
105 fn from(e: CompressedAccountError) -> u32 {
106 match e {
107 CompressedAccountError::InputTooLarge(_) => 12001,
108 CompressedAccountError::InvalidChunkSize => 12002,
109 CompressedAccountError::InvalidSeeds => 12003,
110 CompressedAccountError::InvalidRolloverThreshold => 12004,
111 CompressedAccountError::InvalidInputLength => 12005,
112 CompressedAccountError::InvalidAccountSize => 12010,
113 CompressedAccountError::AccountMutable => 12011,
114 CompressedAccountError::AlreadyInitialized => 12012,
115 CompressedAccountError::InvalidAccountBalance => 12013,
116 CompressedAccountError::FailedBorrowRentSysvar => 12014,
117 CompressedAccountError::DeriveAddressError => 12015,
118 CompressedAccountError::InvalidArgument => 12016,
119 CompressedAccountError::ZeroCopyExpectedAddress => 12017,
120 CompressedAccountError::InstructionDataExpectedAddress => 12018,
121 CompressedAccountError::CompressedAccountDataNotInitialized => 12019,
122 CompressedAccountError::ExpectedDiscriminator => 12020,
123 CompressedAccountError::InstructionDataExpectedProof => 12021,
124 CompressedAccountError::ZeroCopyExpectedProof => 12022,
125 CompressedAccountError::ExpectedDataHash => 12023,
126 CompressedAccountError::InvalidCpiContext => 12024,
127 CompressedAccountError::InvalidProofSize(_) => 12025,
128 CompressedAccountError::HasherError(e) => u32::from(e),
129 }
130 }
131}
132
133#[cfg(feature = "solana")]
134impl From<CompressedAccountError> for solana_program_error::ProgramError {
135 fn from(e: CompressedAccountError) -> Self {
136 solana_program_error::ProgramError::Custom(e.into())
137 }
138}
139
140#[cfg(feature = "pinocchio")]
141impl From<CompressedAccountError> for pinocchio::program_error::ProgramError {
142 fn from(e: CompressedAccountError) -> Self {
143 pinocchio::program_error::ProgramError::Custom(e.into())
144 }
145}
146
147pub const NULLIFIER_QUEUE_TYPE_V1: u64 = 1;
148pub const ADDRESS_QUEUE_TYPE_V1: u64 = 2;
149pub const INPUT_STATE_QUEUE_TYPE_V2: u64 = 3;
150pub const ADDRESS_QUEUE_TYPE_V2: u64 = 4;
151pub const OUTPUT_STATE_QUEUE_TYPE_V2: u64 = 5;
152
153#[cfg_attr(
154 all(feature = "std", feature = "anchor"),
155 derive(anchor_lang::AnchorDeserialize, anchor_lang::AnchorSerialize)
156)]
157#[cfg_attr(
158 not(feature = "anchor"),
159 derive(borsh::BorshDeserialize, borsh::BorshSerialize)
160)]
161#[derive(Debug, PartialEq, Clone, Copy)]
162#[repr(u64)]
163pub enum QueueType {
164 NullifierV1 = NULLIFIER_QUEUE_TYPE_V1,
165 AddressV1 = ADDRESS_QUEUE_TYPE_V1,
166 InputStateV2 = INPUT_STATE_QUEUE_TYPE_V2,
167 AddressV2 = ADDRESS_QUEUE_TYPE_V2,
168 OutputStateV2 = OUTPUT_STATE_QUEUE_TYPE_V2,
169}
170
171impl From<u64> for QueueType {
172 fn from(value: u64) -> Self {
173 match value {
174 1 => QueueType::NullifierV1,
175 2 => QueueType::AddressV1,
176 3 => QueueType::InputStateV2,
177 4 => QueueType::AddressV2,
178 5 => QueueType::OutputStateV2,
179 _ => panic!("Invalid queue type"),
180 }
181 }
182}
183
184pub const STATE_MERKLE_TREE_TYPE_V1: u64 = 1;
185pub const ADDRESS_MERKLE_TREE_TYPE_V1: u64 = 2;
186pub const STATE_MERKLE_TREE_TYPE_V2: u64 = 3;
187pub const ADDRESS_MERKLE_TREE_TYPE_V2: u64 = 4;
188
189#[cfg_attr(
190 all(feature = "std", feature = "anchor"),
191 derive(anchor_lang::AnchorDeserialize, anchor_lang::AnchorSerialize)
192)]
193#[cfg_attr(
194 not(feature = "anchor"),
195 derive(borsh::BorshDeserialize, borsh::BorshSerialize)
196)]
197#[derive(Debug, Ord, PartialEq, PartialOrd, Eq, Clone, Copy)]
198#[repr(u64)]
199pub enum TreeType {
200 StateV1 = STATE_MERKLE_TREE_TYPE_V1,
201 AddressV1 = ADDRESS_MERKLE_TREE_TYPE_V1,
202 StateV2 = STATE_MERKLE_TREE_TYPE_V2,
203 AddressV2 = ADDRESS_MERKLE_TREE_TYPE_V2,
204 Unknown = 255,
205}
206
207impl Display for TreeType {
208 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
209 match self {
210 TreeType::StateV1 => write!(f, "StateV1"),
211 TreeType::AddressV1 => write!(f, "AddressV1"),
212 TreeType::StateV2 => write!(f, "StateV2"),
213 TreeType::AddressV2 => write!(f, "AddressV2"),
214 TreeType::Unknown => write!(f, "Unknown"),
215 }
216 }
217}
218
219#[allow(clippy::derivable_impls)]
220impl core::default::Default for TreeType {
221 fn default() -> Self {
222 TreeType::StateV2
223 }
224}
225
226impl From<u64> for TreeType {
228 fn from(value: u64) -> Self {
229 match value {
230 1 => TreeType::StateV1,
231 2 => TreeType::AddressV1,
232 3 => TreeType::StateV2,
233 4 => TreeType::AddressV2,
234 255 => TreeType::Unknown,
235 _ => panic!("Invalid TreeType"),
236 }
237 }
238}
239
240#[derive(Debug, Clone, Copy, PartialEq, Eq)]
242pub struct CpiSigner {
243 pub program_id: [u8; 32],
244 pub cpi_signer: [u8; 32],
245 pub bump: u8,
246}