light_merkle_tree_program/
lib.rs

1use 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    /// Initializes a new Merkle tree from config bytes.
45    /// Can only be called from the merkle_tree_authority.
46    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        // Transaction Merkle Tree
66        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        // Event Merkle Tree
82        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    /// Initializes a new merkle tree authority which can register new verifiers and configure
94    /// permissions to create new pools.
95    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    /// Updates the merkle tree authority to a new authority.
118    pub fn update_merkle_tree_authority(ctx: Context<UpdateMerkleTreeAuthority>) -> Result<()> {
119        // account is checked in ctx struct
120        ctx.accounts.merkle_tree_authority_pda.pubkey = ctx.accounts.new_authority.key();
121        Ok(())
122    }
123
124    /// Updates the lock duration for a specific merkle tree.
125    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    /// Enables anyone to create token pools.
137    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    // Unactivated feature listed for completeness.
148    // pub fn enable_permissionless_merkle_tree_registration(ctx: Context<UpdateMerkleTreeAuthorityConfig>, enable_permissionless: bool) -> Result<()> {
149    //     ctx.accounts.merkle_tree_authority_pda.enable_permissionless_merkle_tree_registration = enable_permissionless;
150    //     Ok(())
151    // }
152
153    /// Registers a new verifier which can unshield tokens, insert new nullifiers, add new leaves.
154    /// These functions can only be invoked from registered verifiers.
155    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    /// Registers a new pooltype.
172    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    /// Creates a new spl token pool which can be used by any registered verifier.
186    pub fn register_spl_pool(ctx: Context<RegisterSplPool>) -> Result<()> {
187        // any token enabled
188        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    /// Creates a new sol pool which can be used by any registered verifier.
212    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    /// Initializes a merkle tree update state pda. This pda stores the leaves to be inserted
237    /// and state of the computation of poseidon hashes to update the Merkle tree.
238    /// A maximum of 16 pairs of leaves can be passed in as leaves accounts as remaining accounts.
239    /// Every leaf is copied into this account such that no further accounts or data have to be
240    /// passed in during the following instructions which compute the poseidon hashes to update the tree.
241    /// The hashes are computed with the update merkle tree instruction and the new root is inserted
242    /// with the insert root merkle tree instruction.
243    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    /// Computes poseidon hashes to update the Merkle tree.
250    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    /// This is the last step of a Merkle tree update which inserts the prior computed Merkle tree
258    /// root.
259    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    /// Closes the Merkle tree update state.
267    /// A relayer can only close its own update state account.
268    pub fn close_merkle_tree_update_state(
269        _ctx: Context<CloseUpdateState>,
270    ) -> anchor_lang::Result<()> {
271        Ok(())
272    }
273
274    /// Creates and initializes a pda which stores two merkle tree leaves and encrypted Utxos.
275    /// The inserted leaves are not part of the Merkle tree yet and marked accordingly.
276    /// The Merkle tree has to be updated after.
277    /// Can only be called from a registered verifier program.
278    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    /// Unshields sol from a liquidity pool.
296    /// An arbitrary number of recipients can be passed in with remaining accounts.
297    /// Can only be called from a registered verifier program.
298    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    /// Unshields spl tokens from a liquidity pool.
310    /// An arbitrary number of recipients can be passed in with remaining accounts.
311    /// Can only be called from a registered verifier program.
312    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}