light_compressed_account/
lib.rs

1#![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
83// NOTE(vadorovsky): Unfortunately, we need to do it by hand.
84// `num_derive::ToPrimitive` doesn't support data-carrying enums.
85impl 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
205// from u64
206impl 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/// Configuration struct containing program ID, CPI signer, and bump for Light Protocol
219#[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}