account_compression/instructions/
batch_append.rs1use 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 pub authority: Signer<'info>,
18 pub registered_program_pda: Option<Account<'info, RegisteredProgram>>,
19 pub log_wrapper: UncheckedAccount<'info>,
21 #[account(mut)]
23 pub merkle_tree: AccountInfo<'info>,
24 #[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
38pub 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 let merkle_tree =
53 &mut BatchedMerkleTreeAccount::state_from_account_info(&ctx.accounts.merkle_tree)
54 .map_err(ProgramError::from)?;
55 check_signer_is_registered_or_authority::<BatchAppend, BatchedMerkleTreeAccount>(
57 ctx,
58 merkle_tree,
59 )?;
60
61 let event = merkle_tree
63 .update_tree_from_output_queue_account_info(&ctx.accounts.output_queue, instruction_data)
64 .map_err(ProgramError::from)?;
65 emit_indexer_event(event.try_to_vec()?, &ctx.accounts.log_wrapper)
67}