light_merkle_tree_program/
lib.rs1use anchor_lang::prelude::*;
2
3declare_id!("JA5cjkRJ1euVi9xLWsCJVzsRzEkT8vcC4rqw9sVAo5d6");
4
5#[cfg(not(feature = "no-entrypoint"))]
6solana_security_txt::security_txt! {
7 name: "light_protocol_merkle_tree",
8 project_url: "lightprotocol.com",
9 contacts: "email:security@lightprotocol.com",
10 policy: "https://github.com/Lightprotocol/light-protocol-program/blob/main/SECURITY.md",
11 source_code: "https://github.com/Lightprotocol/light-protocol-program/program_merkle_tree"
12}
13
14pub mod event_merkle_tree;
15pub use event_merkle_tree::*;
16pub mod instructions;
17pub use instructions::*;
18pub mod indexed_merkle_tree;
19pub mod transaction_merkle_tree;
20pub use transaction_merkle_tree::*;
21pub mod verifier_invoked_instructions;
22pub use verifier_invoked_instructions::*;
23pub mod errors;
24pub use errors::*;
25pub mod utils;
26
27pub mod config_accounts;
28pub use config_accounts::*;
29
30use crate::{
31 errors::ErrorCode,
32 transaction_merkle_tree::state::TransactionMerkleTree,
33 utils::{
34 accounts::deserialize_and_update_old_merkle_tree,
35 config::{self, MERKLE_TREE_HEIGHT, ZERO_BYTES_MERKLE_TREE_18},
36 constants::{EVENT_MERKLE_TREE_SEED, TRANSACTION_MERKLE_TREE_SEED},
37 },
38};
39
40#[program]
41pub mod light_merkle_tree_program {
42 use super::*;
43
44 pub fn initialize_new_merkle_trees(
47 ctx: Context<InitializeNewMerkleTrees>,
48 lock_duration: u64,
49 ) -> Result<()> {
50 if !ctx
51 .accounts
52 .merkle_tree_authority_pda
53 .enable_permissionless_merkle_tree_registration
54 && ctx.accounts.authority.key() != ctx.accounts.merkle_tree_authority_pda.pubkey
55 {
56 return err!(ErrorCode::InvalidAuthority);
57 }
58
59 if ctx.remaining_accounts.len() != 2 {
60 return err!(ErrorCode::ExpectedOldMerkleTrees);
61 }
62
63 let merkle_tree_authority = &mut ctx.accounts.merkle_tree_authority_pda;
64
65 deserialize_and_update_old_merkle_tree::<TransactionMerkleTree>(
67 &ctx.remaining_accounts[0],
68 TRANSACTION_MERKLE_TREE_SEED,
69 ctx.program_id,
70 )?;
71 let new_transaction_merkle_tree =
72 &mut ctx.accounts.new_transaction_merkle_tree.load_init()?;
73 process_initialize_new_merkle_tree_18(
74 new_transaction_merkle_tree,
75 merkle_tree_authority,
76 MERKLE_TREE_HEIGHT,
77 ZERO_BYTES_MERKLE_TREE_18.to_vec(),
78 );
79 new_transaction_merkle_tree.lock_duration = lock_duration;
80
81 deserialize_and_update_old_merkle_tree::<event_merkle_tree::EventMerkleTree>(
83 &ctx.remaining_accounts[1],
84 EVENT_MERKLE_TREE_SEED,
85 ctx.program_id,
86 )?;
87 let new_event_merkle_tree = &mut ctx.accounts.new_event_merkle_tree.load_init()?;
88 process_initialize_new_event_merkle_tree(new_event_merkle_tree, merkle_tree_authority);
89
90 Ok(())
91 }
92
93 pub fn initialize_merkle_tree_authority(
96 ctx: Context<InitializeMerkleTreeAuthority>,
97 ) -> Result<()> {
98 ctx.accounts.merkle_tree_authority_pda.pubkey = ctx.accounts.authority.key();
99
100 let merkle_tree = &mut ctx.accounts.transaction_merkle_tree.load_init()?;
101 let merkle_tree_authority = &mut ctx.accounts.merkle_tree_authority_pda;
102 process_initialize_new_merkle_tree_18(
103 merkle_tree,
104 merkle_tree_authority,
105 MERKLE_TREE_HEIGHT,
106 ZERO_BYTES_MERKLE_TREE_18.to_vec(),
107 );
108
109 let event_merkle_tree = &mut ctx.accounts.event_merkle_tree.load_init()?;
110 let merkle_tree_authority = &mut ctx.accounts.merkle_tree_authority_pda;
111
112 process_initialize_new_event_merkle_tree(event_merkle_tree, merkle_tree_authority);
113
114 Ok(())
115 }
116
117 pub fn update_merkle_tree_authority(ctx: Context<UpdateMerkleTreeAuthority>) -> Result<()> {
119 ctx.accounts.merkle_tree_authority_pda.pubkey = ctx.accounts.new_authority.key();
121 Ok(())
122 }
123
124 pub fn update_lock_duration(
126 ctx: Context<UpdateLockDuration>,
127 lock_duration: u64,
128 ) -> Result<()> {
129 ctx.accounts
130 .transaction_merkle_tree
131 .load_mut()?
132 .lock_duration = lock_duration;
133 Ok(())
134 }
135
136 pub fn enable_permissionless_spl_tokens(
138 ctx: Context<UpdateMerkleTreeAuthorityConfig>,
139 enable_permissionless: bool,
140 ) -> Result<()> {
141 ctx.accounts
142 .merkle_tree_authority_pda
143 .enable_permissionless_spl_tokens = enable_permissionless;
144 Ok(())
145 }
146
147 pub fn register_verifier(
156 ctx: Context<RegisterVerifier>,
157 verifier_pubkey: Pubkey,
158 ) -> Result<()> {
159 if !ctx
160 .accounts
161 .merkle_tree_authority_pda
162 .enable_permissionless_merkle_tree_registration
163 && ctx.accounts.authority.key() != ctx.accounts.merkle_tree_authority_pda.pubkey
164 {
165 return err!(ErrorCode::InvalidAuthority);
166 }
167 ctx.accounts.registered_verifier_pda.pubkey = verifier_pubkey;
168 Ok(())
169 }
170
171 pub fn register_pool_type(ctx: Context<RegisterPoolType>, pool_type: [u8; 32]) -> Result<()> {
173 if !ctx
174 .accounts
175 .merkle_tree_authority_pda
176 .enable_permissionless_spl_tokens
177 && ctx.accounts.authority.key() != ctx.accounts.merkle_tree_authority_pda.pubkey
178 {
179 return err!(ErrorCode::InvalidAuthority);
180 }
181 ctx.accounts.registered_pool_type_pda.pool_type = pool_type;
182 Ok(())
183 }
184
185 pub fn register_spl_pool(ctx: Context<RegisterSplPool>) -> Result<()> {
187 if !ctx
189 .accounts
190 .merkle_tree_authority_pda
191 .enable_permissionless_spl_tokens
192 && ctx.accounts.authority.key() != ctx.accounts.merkle_tree_authority_pda.pubkey
193 {
194 return err!(ErrorCode::InvalidAuthority);
195 }
196
197 ctx.accounts.registered_asset_pool_pda.asset_pool_pubkey =
198 ctx.accounts.merkle_tree_pda_token.key();
199 ctx.accounts.registered_asset_pool_pda.pool_type =
200 ctx.accounts.registered_pool_type_pda.pool_type;
201 ctx.accounts.registered_asset_pool_pda.index = ctx
202 .accounts
203 .merkle_tree_authority_pda
204 .registered_asset_index;
205 ctx.accounts
206 .merkle_tree_authority_pda
207 .registered_asset_index += 1;
208 Ok(())
209 }
210
211 pub fn register_sol_pool(ctx: Context<RegisterSolPool>) -> Result<()> {
213 if !ctx
214 .accounts
215 .merkle_tree_authority_pda
216 .enable_permissionless_spl_tokens
217 && ctx.accounts.authority.key() != ctx.accounts.merkle_tree_authority_pda.pubkey
218 {
219 return err!(ErrorCode::InvalidAuthority);
220 }
221
222 ctx.accounts.registered_asset_pool_pda.asset_pool_pubkey =
223 ctx.accounts.registered_asset_pool_pda.key();
224 ctx.accounts.registered_asset_pool_pda.pool_type =
225 ctx.accounts.registered_pool_type_pda.pool_type;
226 ctx.accounts.registered_asset_pool_pda.index = ctx
227 .accounts
228 .merkle_tree_authority_pda
229 .registered_asset_index;
230 ctx.accounts
231 .merkle_tree_authority_pda
232 .registered_asset_index += 1;
233 Ok(())
234 }
235
236 pub fn initialize_merkle_tree_update_state<'info>(
244 ctx: Context<'_, '_, '_, 'info, InitializeUpdateState<'info>>,
245 ) -> Result<()> {
246 process_initialize_update_state(ctx)
247 }
248
249 pub fn update_transaction_merkle_tree<'info>(
251 mut ctx: Context<'_, '_, '_, 'info, UpdateTransactionMerkleTree<'info>>,
252 _bump: u64,
253 ) -> Result<()> {
254 process_update_merkle_tree(&mut ctx)
255 }
256
257 pub fn insert_root_merkle_tree<'info>(
260 mut ctx: Context<'_, '_, '_, 'info, InsertRoot<'info>>,
261 _bump: u64,
262 ) -> Result<()> {
263 process_insert_root(&mut ctx)
264 }
265
266 pub fn close_merkle_tree_update_state(
269 _ctx: Context<CloseUpdateState>,
270 ) -> anchor_lang::Result<()> {
271 Ok(())
272 }
273
274 pub fn insert_two_leaves<'info>(
279 ctx: Context<'_, '_, '_, 'info, InsertTwoLeaves<'info>>,
280 leaf_left: [u8; 32],
281 leaf_right: [u8; 32],
282 encrypted_utxo: [u8; 256],
283 ) -> Result<()> {
284 process_insert_two_leaves(ctx, leaf_left, leaf_right, encrypted_utxo)
285 }
286
287 pub fn insert_two_leaves_event<'info>(
288 ctx: Context<'_, '_, '_, 'info, InsertTwoLeavesEvent<'info>>,
289 leaf_left: [u8; 32],
290 leaf_right: [u8; 32],
291 ) -> Result<()> {
292 process_insert_two_leaves_event(ctx, leaf_left, leaf_right)
293 }
294
295 pub fn unshield_sol<'info>(
299 ctx: Context<'_, '_, '_, 'info, UnshieldSol<'info>>,
300 amount: u64,
301 ) -> Result<()> {
302 process_sol_transfer(
303 &ctx.accounts.merkle_tree_token.to_account_info(),
304 &ctx.accounts.recipient.to_account_info(),
305 amount,
306 )
307 }
308
309 pub fn unshield_spl<'info>(
313 ctx: Context<'_, '_, '_, 'info, UnshieldSpl<'info>>,
314 amount: u64,
315 ) -> Result<()> {
316 process_spl_transfer(ctx, amount)
317 }
318
319 pub fn initialize_nullifiers<'info>(
320 ctx: Context<'_, '_, '_, 'info, InitializeNullifiers<'info>>,
321 nullifiers: Vec<[u8; 32]>,
322 ) -> Result<()> {
323 process_insert_nullifiers(ctx, nullifiers)
324 }
325}