Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: move rollover completely into batched crate #1510

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion program-libs/batched-merkle-tree/src/rollover_address_tree.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use light_merkle_tree_metadata::utils::if_equals_none;
use light_utils::pubkey::Pubkey;
use light_utils::{account::check_account_balance_is_rent_exempt, pubkey::Pubkey};
use solana_program::account_info::AccountInfo;

use crate::{
errors::BatchedMerkleTreeError,
Expand All @@ -10,6 +11,24 @@ use crate::{
rollover_state_tree::batched_tree_is_ready_for_rollover,
};

pub fn rollover_batched_address_tree_from_account_info<'a>(
old_account: &AccountInfo<'a>,
new_account: &AccountInfo<'a>,
network_fee: Option<u64>,
) -> Result<u64, BatchedMerkleTreeError> {
let new_mt_rent = check_account_balance_is_rent_exempt(new_account, old_account.data_len())?;
let mut old_merkle_tree = BatchedMerkleTreeAccount::address_from_account_info(old_account)?;
let mut new_mt_data = new_account.try_borrow_mut_data()?;
rollover_batched_address_tree(
&mut old_merkle_tree,
&mut new_mt_data,
new_mt_rent,
(*new_account.key).into(),
network_fee,
)?;
Ok(new_mt_rent)
}

/// Rollover an almost full batched address tree,
/// ie create a new batched Merkle tree account
/// with the same parameters, and mark the old account as rolled over.
Expand Down
75 changes: 73 additions & 2 deletions program-libs/batched-merkle-tree/src/rollover_state_tree.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use light_merkle_tree_metadata::{errors::MerkleTreeMetadataError, utils::if_equals_none};
use light_utils::pubkey::Pubkey;
use solana_program::msg;
use light_utils::{account::check_account_balance_is_rent_exempt, pubkey::Pubkey};
use solana_program::{account_info::AccountInfo, msg};

use crate::{
errors::BatchedMerkleTreeError,
Expand Down Expand Up @@ -30,6 +30,77 @@ pub struct RolloverBatchStateTreeParams<'a> {
pub network_fee: Option<u64>,
}

/// Rollover an almost full batched state tree,
/// ie create a new batched Merkle tree and output queue
/// with the same parameters, and mark the old accounts as rolled over.
/// The old tree and queue can be used until these are completely full.
///
/// 1. Check Merkle tree account discriminator, tree type, and program ownership.
/// 2. Check Queue account discriminator, and program ownership.
/// 3. Check that new Merkle tree account is exactly rent exempt.
/// 4. Check that new Queue account is exactly rent exempt.
/// 5. Rollover the old Merkle tree and queue to new Merkle tree and queue.
///
/// Note, reimbursed rent for additional bytes is calculated from old Merkle tree accounts
/// additional bytes since those are the basis for the old trees rollover fee.
/// If new additional_bytes is greater than old additional_bytes additional
/// rent reimbursements need to be calculated outside of this function.
pub fn rollover_batched_state_tree_from_account_info<'a>(
old_state_merkle_tree: &AccountInfo<'a>,
new_state_merkle_tree: &AccountInfo<'a>,
old_output_queue: &AccountInfo<'a>,
new_output_queue: &AccountInfo<'a>,
additional_bytes: u64,
network_fee: Option<u64>,
) -> Result<u64, BatchedMerkleTreeError> {
// 1. Check Merkle tree account discriminator, tree type, and program ownership.
let old_merkle_tree_account =
&mut BatchedMerkleTreeAccount::state_from_account_info(old_state_merkle_tree)?;

// 2. Check Queue account discriminator, and program ownership.
let old_output_queue_account =
&mut BatchedQueueAccount::output_from_account_info(old_output_queue)?;

// 3. Check that new Merkle tree account is exactly rent exempt.
let merkle_tree_rent = check_account_balance_is_rent_exempt(
new_state_merkle_tree,
old_state_merkle_tree.data_len(),
)?;
// 4. Check that new Queue account is exactly rent exempt.
let queue_rent =
check_account_balance_is_rent_exempt(new_output_queue, old_output_queue.data_len())?;

use solana_program::sysvar::Sysvar;
let additional_bytes_rent = solana_program::rent::Rent::get()?.minimum_balance(
old_output_queue_account
.metadata
.rollover_metadata
.additional_bytes as usize,
);

let new_mt_data = &mut new_state_merkle_tree.try_borrow_mut_data()?;
let params = RolloverBatchStateTreeParams {
old_merkle_tree: old_merkle_tree_account,
old_mt_pubkey: (*old_state_merkle_tree.key).into(),
new_mt_data,
new_mt_rent: merkle_tree_rent,
new_mt_pubkey: (*new_state_merkle_tree.key).into(),
old_output_queue: old_output_queue_account,
old_queue_pubkey: (*old_output_queue.key).into(),
new_output_queue_data: &mut new_output_queue.try_borrow_mut_data()?,
new_output_queue_rent: queue_rent,
new_output_queue_pubkey: (*new_output_queue.key).into(),
additional_bytes_rent,
additional_bytes,
network_fee,
};

// 5. Rollover the old Merkle tree and queue to new Merkle tree and queue.
rollover_batched_state_tree(params)?;
let rent = merkle_tree_rent + queue_rent + additional_bytes_rent;
Ok(rent)
}

/// Rollover an almost full batched state tree,
/// ie create a new batched Merkle tree and output queue
/// with the same parameters, and mark the old accounts as rolled over.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use anchor_lang::{prelude::*, solana_program::pubkey::Pubkey};
use light_batched_merkle_tree::{
merkle_tree::BatchedMerkleTreeAccount, rollover_address_tree::rollover_batched_address_tree,
merkle_tree::BatchedMerkleTreeAccount,
rollover_address_tree::rollover_batched_address_tree_from_account_info,
};
use light_utils::account::check_account_balance_is_rent_exempt;

use crate::{
utils::{
Expand Down Expand Up @@ -41,9 +41,9 @@ impl<'info> GroupAccounts<'info> for RolloverBatchedAddressMerkleTree<'info> {
/// Rollover the old address Merkle tree to the new address Merkle tree.
/// 1. Check Merkle tree account discriminator, tree type, and program ownership.
/// 2. Check that signer is registered or authority.
/// 3. Check that new address Merkle tree account is exactly rent exempt.
/// 4. Rollover the old address Merkle tree to the new address Merkle tree.
/// 5. Transfer rent exemption for new Merkle tree
/// 3. Rollover the old address Merkle tree to the new address Merkle tree.
/// 3.1. Check that new address Merkle tree account is exactly rent exempt.
/// 4. Transfer rent exemption for new Merkle tree
/// from old address Merkle tree to fee payer.
pub fn process_rollover_batched_address_merkle_tree<'a, 'b, 'c: 'info, 'info>(
ctx: Context<'a, 'b, 'c, 'info, RolloverBatchedAddressMerkleTree<'info>>,
Expand All @@ -60,27 +60,16 @@ pub fn process_rollover_batched_address_merkle_tree<'a, 'b, 'c: 'info, 'info>(
BatchedMerkleTreeAccount,
>(&ctx, old_merkle_tree_account)?;

// 3. Check that new address Merkle tree account is exactly rent exempt.
let merkle_tree_rent = check_account_balance_is_rent_exempt(
&ctx.accounts.new_address_merkle_tree.to_account_info(),
ctx.accounts
.old_address_merkle_tree
.to_account_info()
.data_len(),
)
.map_err(ProgramError::from)?;
// 4. Rollover the old address Merkle tree to the new address Merkle tree.
let new_mt_data = &mut ctx.accounts.new_address_merkle_tree.try_borrow_mut_data()?;
rollover_batched_address_tree(
old_merkle_tree_account,
new_mt_data,
merkle_tree_rent,
ctx.accounts.new_address_merkle_tree.key().into(),
// 3. Rollover the old address Merkle tree to the new address Merkle tree.
// 3.1. Check that new address Merkle tree account is exactly rent exempt.
let merkle_tree_rent = rollover_batched_address_tree_from_account_info(
&ctx.accounts.old_address_merkle_tree,
&ctx.accounts.new_address_merkle_tree,
network_fee,
)
.map_err(ProgramError::from)?;

// 5. Transfer rent exemption for new Merkle tree
// 4. Transfer rent exemption for new Merkle tree
// from old address Merkle tree to fee payer.
transfer_lamports(
&ctx.accounts.old_address_merkle_tree.to_account_info(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use anchor_lang::{prelude::*, solana_program::pubkey::Pubkey};
use light_batched_merkle_tree::{
merkle_tree::BatchedMerkleTreeAccount,
queue::BatchedQueueAccount,
rollover_state_tree::{rollover_batched_state_tree, RolloverBatchStateTreeParams},
rollover_state_tree::rollover_batched_state_tree_from_account_info,
};
use light_utils::account::check_account_balance_is_rent_exempt;

use crate::{
utils::{
Expand Down Expand Up @@ -49,12 +47,9 @@ impl<'info> GroupAccounts<'info> for RolloverBatchedStateMerkleTree<'info> {
/// Rollover the old state Merkle tree and output queue to
/// new state Merkle tree and output queue.
/// 1. Check Merkle tree account discriminator, tree type, and program ownership.
/// 2. Check Queue account discriminator, and program ownership.
/// 3. Check that signer is registered or authority.
/// 4. Check that new Merkle tree account is exactly rent exempt.
/// 5. Check that new Queue account is exactly rent exempt.
/// 6. Rollover the old Merkle tree and queue to new Merkle tree and queue.
/// 7. Transfer rent exemption for new accounts
/// 2. Check that signer is registered or authority.
/// 3. Rollover the old Merkle tree and queue to new Merkle tree and queue.
/// 4. Transfer rent exemption for new accounts
/// from old output queue to fee payer.
pub fn process_rollover_batched_state_merkle_tree<'a, 'b, 'c: 'info, 'info>(
ctx: Context<'a, 'b, 'c, 'info, RolloverBatchedStateMerkleTree<'info>>,
Expand All @@ -66,59 +61,29 @@ pub fn process_rollover_batched_state_merkle_tree<'a, 'b, 'c: 'info, 'info>(
&mut BatchedMerkleTreeAccount::state_from_account_info(&ctx.accounts.old_state_merkle_tree)
.map_err(ProgramError::from)?;

// 2. Check Queue account discriminator, and program ownership.
let old_output_queue =
&mut BatchedQueueAccount::output_from_account_info(&ctx.accounts.old_output_queue)
.map_err(ProgramError::from)?;

// 3. Check that signer is registered or authority.
// 2. Check that signer is registered or authority.
check_signer_is_registered_or_authority::<
RolloverBatchedStateMerkleTree,
BatchedMerkleTreeAccount,
>(&ctx, old_merkle_tree_account)?;

// 4. Check that new Merkle tree account is exactly rent exempt.
let merkle_tree_rent = check_account_balance_is_rent_exempt(
&ctx.accounts.new_state_merkle_tree.to_account_info(),
ctx.accounts
.old_state_merkle_tree
.to_account_info()
.data_len(),
)
.map_err(ProgramError::from)?;
// 5. Check that new Queue account is exactly rent exempt.
let queue_rent = check_account_balance_is_rent_exempt(
&ctx.accounts.new_output_queue.to_account_info(),
ctx.accounts.old_output_queue.to_account_info().data_len(),
)
.map_err(ProgramError::from)?;
let additional_bytes_rent = Rent::get()?.minimum_balance(additional_bytes as usize);
let new_mt_data = &mut ctx.accounts.new_state_merkle_tree.try_borrow_mut_data()?;
let params = RolloverBatchStateTreeParams {
old_merkle_tree: old_merkle_tree_account,
old_mt_pubkey: ctx.accounts.old_state_merkle_tree.key().into(),
new_mt_data,
new_mt_rent: merkle_tree_rent,
new_mt_pubkey: ctx.accounts.new_state_merkle_tree.key().into(),
old_output_queue,
old_queue_pubkey: ctx.accounts.old_output_queue.key().into(),
new_output_queue_data: &mut ctx.accounts.new_output_queue.try_borrow_mut_data()?,
new_output_queue_rent: queue_rent,
new_output_queue_pubkey: ctx.accounts.new_output_queue.key().into(),
additional_bytes_rent,
// 3. Rollover the old Merkle tree and queue to new Merkle tree and queue.
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,
};

// 6. Rollover the old Merkle tree and queue to new Merkle tree and queue.
rollover_batched_state_tree(params).map_err(ProgramError::from)?;
)
.map_err(ProgramError::from)?;

// 7. Transfer rent exemption for new accounts
// 4. Transfer rent exemption for new accounts
// from old output queue to fee payer.
transfer_lamports(
&ctx.accounts.old_output_queue.to_account_info(),
&ctx.accounts.fee_payer.to_account_info(),
merkle_tree_rent + queue_rent + additional_bytes_rent,
rent,
)?;

Ok(())
Expand Down
Loading