light_registry/account_compression_cpi/
initialize_tree_and_queue.rs

1use account_compression::{
2    program::AccountCompression, utils::constants::CPI_AUTHORITY_PDA_SEED, AddressMerkleTreeConfig,
3    AddressQueueConfig, NullifierQueueConfig, StateMerkleTreeConfig,
4};
5use anchor_lang::prelude::*;
6use light_system_program::program::LightSystemProgram;
7
8use crate::{
9    errors::RegistryError,
10    protocol_config::state::{ProtocolConfig, ProtocolConfigPda},
11};
12
13#[derive(Accounts)]
14pub struct InitializeMerkleTreeAndQueue<'info> {
15    /// Anyone can create new trees just the fees cannot be set arbitrarily.
16    #[account(mut)]
17    pub authority: Signer<'info>,
18    /// CHECK: (account compression program).
19    #[account(mut)]
20    pub merkle_tree: AccountInfo<'info>,
21    /// CHECK: (account compression program).
22    #[account(mut)]
23    pub queue: AccountInfo<'info>,
24    /// CHECK: (account compression program) access control.
25    pub registered_program_pda: AccountInfo<'info>,
26    /// CHECK: (seed constraints) used to invoke account compression program via cpi.
27    #[account(mut, seeds = [CPI_AUTHORITY_PDA_SEED], bump)]
28    pub cpi_authority: AccountInfo<'info>,
29    pub account_compression_program: Program<'info, AccountCompression>,
30    pub protocol_config_pda: Account<'info, ProtocolConfigPda>,
31    /// CHECK: (system program) new cpi context account.
32    pub cpi_context_account: Option<AccountInfo<'info>>,
33    pub light_system_program: Option<Program<'info, LightSystemProgram>>,
34}
35
36pub fn process_initialize_state_merkle_tree(
37    ctx: &Context<InitializeMerkleTreeAndQueue>,
38    bump: u8,
39    index: u64,
40    program_owner: Option<Pubkey>,
41    forester: Option<Pubkey>,
42    merkle_tree_config: StateMerkleTreeConfig,
43    queue_config: NullifierQueueConfig,
44) -> Result<()> {
45    let bump = &[bump];
46    let seeds = [CPI_AUTHORITY_PDA_SEED, bump];
47    let signer_seeds = &[&seeds[..]];
48    let accounts = account_compression::cpi::accounts::InitializeStateMerkleTreeAndNullifierQueue {
49        authority: ctx.accounts.cpi_authority.to_account_info(),
50        merkle_tree: ctx.accounts.merkle_tree.to_account_info(),
51        nullifier_queue: ctx.accounts.queue.to_account_info(),
52        registered_program_pda: Some(ctx.accounts.registered_program_pda.clone()),
53    };
54    let cpi_ctx = CpiContext::new_with_signer(
55        ctx.accounts.account_compression_program.to_account_info(),
56        accounts,
57        signer_seeds,
58    );
59
60    account_compression::cpi::initialize_state_merkle_tree_and_nullifier_queue(
61        cpi_ctx,
62        index,
63        program_owner,
64        forester,
65        merkle_tree_config,
66        queue_config,
67        0,
68    )
69}
70
71pub fn process_initialize_address_merkle_tree(
72    ctx: Context<InitializeMerkleTreeAndQueue>,
73    bump: u8,
74    index: u64,
75    program_owner: Option<Pubkey>,
76    forester: Option<Pubkey>,
77    merkle_tree_config: AddressMerkleTreeConfig,
78    queue_config: AddressQueueConfig,
79) -> Result<()> {
80    let bump = &[bump];
81    let seeds = [CPI_AUTHORITY_PDA_SEED, bump];
82    let signer_seeds = &[&seeds[..]];
83    let accounts = account_compression::cpi::accounts::InitializeAddressMerkleTreeAndQueue {
84        authority: ctx.accounts.cpi_authority.to_account_info(),
85        merkle_tree: ctx.accounts.merkle_tree.to_account_info(),
86        queue: ctx.accounts.queue.to_account_info(),
87        registered_program_pda: Some(ctx.accounts.registered_program_pda.clone()),
88    };
89    let cpi_ctx = CpiContext::new_with_signer(
90        ctx.accounts.account_compression_program.to_account_info(),
91        accounts,
92        signer_seeds,
93    );
94
95    account_compression::cpi::initialize_address_merkle_tree_and_queue(
96        cpi_ctx,
97        index,
98        program_owner,
99        forester,
100        merkle_tree_config,
101        queue_config,
102    )
103}
104
105pub fn process_initialize_cpi_context<'info>(
106    bump: u8,
107    fee_payer: AccountInfo<'info>,
108    cpi_context_account: AccountInfo<'info>,
109    associated_merkle_tree: AccountInfo<'info>,
110    light_system_program: AccountInfo<'info>,
111) -> Result<()> {
112    let bump = &[bump];
113    let seeds = [CPI_AUTHORITY_PDA_SEED, bump];
114    let signer_seeds = &[&seeds[..]];
115    let accounts = light_system_program::cpi::accounts::InitializeCpiContextAccount {
116        fee_payer,
117        cpi_context_account,
118        associated_merkle_tree,
119    };
120    let cpi_ctx = CpiContext::new_with_signer(light_system_program, accounts, signer_seeds);
121
122    light_system_program::cpi::init_cpi_context_account(cpi_ctx)
123}
124
125pub fn check_cpi_context(
126    account: AccountInfo<'_>,
127    protocol_config: &ProtocolConfig,
128) -> Result<u64> {
129    let config_cpi_context_account_len = protocol_config.cpi_context_size as usize;
130    if account.data_len() != config_cpi_context_account_len {
131        msg!(
132            "CPI context account data len: {}, expected: {}",
133            account.data_len(),
134            config_cpi_context_account_len
135        );
136        return err!(RegistryError::CpiContextAccountInvalidDataLen);
137    }
138    let rent = Rent::get()?;
139    Ok(rent.minimum_balance(config_cpi_context_account_len))
140}