account_compression/instructions/
batch_append.rs

1use anchor_lang::prelude::*;
2use light_batched_merkle_tree::merkle_tree::{
3    BatchedMerkleTreeAccount, InstructionDataBatchAppendInputs,
4};
5
6use crate::{
7    emit_indexer_event,
8    utils::check_signer_is_registered_or_authority::{
9        check_signer_is_registered_or_authority, GroupAccounts,
10    },
11    RegisteredProgram,
12};
13
14#[derive(Accounts)]
15pub struct BatchAppend<'info> {
16    /// CHECK: should only be accessed by a registered program or owner.
17    pub authority: Signer<'info>,
18    pub registered_program_pda: Option<Account<'info, RegisteredProgram>>,
19    /// CHECK: when emitting event.
20    pub log_wrapper: UncheckedAccount<'info>,
21    /// CHECK: in state_from_account_info.
22    #[account(mut)]
23    pub merkle_tree: AccountInfo<'info>,
24    /// CHECK: in update_tree_from_output_queue_account_info.
25    #[account(mut)]
26    pub output_queue: AccountInfo<'info>,
27}
28
29impl<'info> GroupAccounts<'info> for BatchAppend<'info> {
30    fn get_authority(&self) -> &Signer<'info> {
31        &self.authority
32    }
33    fn get_registered_program_pda(&self) -> &Option<Account<'info, RegisteredProgram>> {
34        &self.registered_program_pda
35    }
36}
37
38/// Append a batch of leaves from the output queue
39/// to the state Merkle tree.
40/// 1. Check Merkle tree account discriminator, tree type, and program ownership.
41/// 2. Check that signer is registered or authority.
42/// 3. Append leaves from the output queue to the state Merkle tree.
43///    3.1 Checks that output queue is associated with the Merkle tree.
44///    3.2 Checks output queue discriminator, program ownership.
45///    3.3 Verifies batch zkp and updates root.
46/// 4. Emit indexer event.
47pub fn process_batch_append_leaves<'a, 'b, 'c: 'info, 'info>(
48    ctx: &'a Context<'a, 'b, 'c, 'info, BatchAppend<'info>>,
49    instruction_data: InstructionDataBatchAppendInputs,
50) -> Result<()> {
51    // 1. Check Merkle tree account discriminator, tree type, and program ownership.
52    let merkle_tree =
53        &mut BatchedMerkleTreeAccount::state_from_account_info(&ctx.accounts.merkle_tree)
54            .map_err(ProgramError::from)?;
55    // 2. Check that signer is registered or authority.
56    check_signer_is_registered_or_authority::<BatchAppend, BatchedMerkleTreeAccount>(
57        ctx,
58        merkle_tree,
59    )?;
60
61    // 3. Append leaves and check output queue account.
62    let event = merkle_tree
63        .update_tree_from_output_queue_account_info(&ctx.accounts.output_queue, instruction_data)
64        .map_err(ProgramError::from)?;
65    // 4. Emit indexer event.
66    emit_indexer_event(event.try_to_vec()?, &ctx.accounts.log_wrapper)
67}