use anchor_lang::prelude::*;
use light_batched_merkle_tree::{
merkle_tree::BatchedMerkleTreeAccount,
rollover_state_tree::rollover_batched_state_tree_from_account_info,
};
use light_merkle_tree_metadata::errors::MerkleTreeMetadataError;
use crate::{
utils::{
check_signer_is_registered_or_authority::{
check_signer_is_registered_or_authority, GroupAccounts,
},
transfer_lamports::transfer_lamports,
},
RegisteredProgram,
};
#[derive(Accounts)]
pub struct RolloverBatchedStateMerkleTree<'info> {
#[account(mut)]
pub fee_payer: Signer<'info>,
pub authority: Signer<'info>,
pub registered_program_pda: Option<Account<'info, RegisteredProgram>>,
#[account(mut)]
pub new_state_merkle_tree: AccountInfo<'info>,
#[account(mut)]
pub old_state_merkle_tree: AccountInfo<'info>,
#[account(mut)]
pub new_output_queue: AccountInfo<'info>,
#[account(mut)]
pub old_output_queue: AccountInfo<'info>,
}
impl<'info> GroupAccounts<'info> for RolloverBatchedStateMerkleTree<'info> {
fn get_authority(&self) -> &Signer<'info> {
&self.authority
}
fn get_registered_program_pda(&self) -> &Option<Account<'info, RegisteredProgram>> {
&self.registered_program_pda
}
}
pub fn process_rollover_batched_state_merkle_tree<'a, 'b, 'c: 'info, 'info>(
ctx: Context<'a, 'b, 'c, 'info, RolloverBatchedStateMerkleTree<'info>>,
additional_bytes: u64,
network_fee: Option<u64>,
) -> Result<()> {
msg!(
"old state Merkle tree {:?}",
ctx.accounts.old_state_merkle_tree.key()
);
let old_merkle_tree_account =
&mut BatchedMerkleTreeAccount::state_from_account_info(&ctx.accounts.old_state_merkle_tree)
.map_err(ProgramError::from)?;
check_signer_is_registered_or_authority::<
RolloverBatchedStateMerkleTree,
BatchedMerkleTreeAccount,
>(&ctx, old_merkle_tree_account)?;
let rent = rollover_batched_state_tree_from_account_info(
&ctx.accounts.old_state_merkle_tree,
&ctx.accounts.new_state_merkle_tree,
&ctx.accounts.old_output_queue,
&ctx.accounts.new_output_queue,
additional_bytes,
network_fee,
)
.map_err(ProgramError::from)?;
transfer_lamports(
&ctx.accounts.old_output_queue.to_account_info(),
&ctx.accounts.fee_payer.to_account_info(),
rent,
)?;
if ctx.accounts.old_output_queue.to_account_info().lamports() == 0 {
return Err(ProgramError::from(MerkleTreeMetadataError::NotReadyForRollover).into());
}
Ok(())
}