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