Skip to content

Commit

Permalink
chore: add rollover to e2e tests (#910)
Browse files Browse the repository at this point in the history
* chore: add rollovers to e2e test env

* enabled rollovers in e2e tests

* chore: increase aidrops in forester

* unify check sufficient rollover fee in function
  • Loading branch information
ananas-block authored Jun 29, 2024
1 parent 31afe7b commit 43a3aa6
Show file tree
Hide file tree
Showing 28 changed files with 647 additions and 122 deletions.
5 changes: 3 additions & 2 deletions forester/tests/e2e_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ async fn test_state_tree_nullifier() {

let mut rpc = SolanaRpcConnection::new(SolanaRpcUrl::Localnet, None);

rpc.airdrop_lamports(&rpc.get_payer().pubkey(), LAMPORTS_PER_SOL * 1000)
rpc.airdrop_lamports(&rpc.get_payer().pubkey(), LAMPORTS_PER_SOL * 100_000)
.await
.unwrap();

Expand Down Expand Up @@ -101,7 +101,7 @@ async fn test_1_all() {
let env_accounts = get_test_env_accounts();
let mut rpc = SolanaRpcConnection::new(SolanaRpcUrl::Localnet, None);

rpc.airdrop_lamports(&rpc.get_payer().pubkey(), LAMPORTS_PER_SOL * 1000)
rpc.airdrop_lamports(&rpc.get_payer().pubkey(), LAMPORTS_PER_SOL * 100_000)
.await
.unwrap();

Expand All @@ -126,6 +126,7 @@ async fn test_1_all() {
create_address_mt: Some(1.0),
nullify_compressed_accounts: Some(1.0),
empty_address_queue: Some(1.0),
rollover: None,
},
1,
None,
Expand Down
3 changes: 2 additions & 1 deletion forester/tests/empty_address_tree_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ async fn empty_address_tree_test() {

let mut rpc = SolanaRpcConnection::new(SolanaRpcUrl::Localnet, None);

rpc.airdrop_lamports(&rpc.get_payer().pubkey(), LAMPORTS_PER_SOL * 1000)
rpc.airdrop_lamports(&rpc.get_payer().pubkey(), LAMPORTS_PER_SOL * 100_000)
.await
.unwrap();

Expand All @@ -84,6 +84,7 @@ async fn empty_address_tree_test() {
create_address_mt: Some(1.0),
nullify_compressed_accounts: Some(0.0),
empty_address_queue: Some(0.0),
rollover: None,
},
0,
None,
Expand Down
3 changes: 2 additions & 1 deletion forester/tests/interop_address_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ async fn test_photon_interop_address() {
let mut rpc = SolanaRpcConnection::new(services_config.rpc_url, None);

// Airdrop because currently TestEnv.new() transfers funds from get_payer.
rpc.airdrop_lamports(&rpc.get_payer().pubkey(), LAMPORTS_PER_SOL * 1000)
rpc.airdrop_lamports(&rpc.get_payer().pubkey(), LAMPORTS_PER_SOL * 100_000)
.await
.unwrap();

Expand All @@ -140,6 +140,7 @@ async fn test_photon_interop_address() {
add_keypair: None,
create_state_mt: None,
create_address_mt: None,
rollover: None,
},
0,
Some(1),
Expand Down
1 change: 1 addition & 0 deletions forester/tests/interop_nullify_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ async fn test_photon_interop_nullify_account() {
add_keypair: None,
create_state_mt: None,
create_address_mt: None,
rollover: None,
},
0,
Some(1),
Expand Down
18 changes: 14 additions & 4 deletions js/stateless.js/src/idls/account_compression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ export type AccountCompression = {
accounts: [
{
name: 'feePayer';
isMut: false;
isMut: true;
isSigner: true;
docs: [
'Signer used to receive rollover accounts rentexemption reimbursement.',
Expand Down Expand Up @@ -590,7 +590,7 @@ export type AccountCompression = {
accounts: [
{
name: 'feePayer';
isMut: false;
isMut: true;
isSigner: true;
docs: [
'Signer used to receive rollover accounts rentexemption reimbursement.',
Expand Down Expand Up @@ -1075,6 +1075,11 @@ export type AccountCompression = {
name: 'SizeMismatch';
msg: 'SizeMismatch';
},
{
code: 6020;
name: 'InsufficientRolloverFee';
msg: 'InsufficientRolloverFee';
},
];
};

Expand Down Expand Up @@ -1333,7 +1338,7 @@ export const IDL: AccountCompression = {
accounts: [
{
name: 'feePayer',
isMut: false,
isMut: true,
isSigner: true,
docs: [
'Signer used to receive rollover accounts rentexemption reimbursement.',
Expand Down Expand Up @@ -1670,7 +1675,7 @@ export const IDL: AccountCompression = {
accounts: [
{
name: 'feePayer',
isMut: false,
isMut: true,
isSigner: true,
docs: [
'Signer used to receive rollover accounts rentexemption reimbursement.',
Expand Down Expand Up @@ -2155,5 +2160,10 @@ export const IDL: AccountCompression = {
name: 'SizeMismatch',
msg: 'SizeMismatch',
},
{
code: 6020,
name: 'InsufficientRolloverFee',
msg: 'InsufficientRolloverFee',
},
],
};
8 changes: 4 additions & 4 deletions js/stateless.js/src/idls/light_registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ export type LightRegistry = {
},
{
name: 'authority';
isMut: false;
isMut: true;
isSigner: true;
},
{
Expand Down Expand Up @@ -360,7 +360,7 @@ export type LightRegistry = {
},
{
name: 'authority';
isMut: false;
isMut: true;
isSigner: true;
},
{
Expand Down Expand Up @@ -840,7 +840,7 @@ export const IDL: LightRegistry = {
},
{
name: 'authority',
isMut: false,
isMut: true,
isSigner: true,
},
{
Expand Down Expand Up @@ -896,7 +896,7 @@ export const IDL: LightRegistry = {
},
{
name: 'authority',
isMut: false,
isMut: true,
isSigner: true,
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ pub fn process_initialize_address_merkle_tree_and_queue<'info>(
merkle_tree_config: AddressMerkleTreeConfig,
queue_config: AddressQueueConfig,
) -> Result<()> {
if merkle_tree_config.close_threshold.is_some() {
unimplemented!("Close threshold not supported.");
}

let merkle_tree_rent = ctx.accounts.merkle_tree.get_lamports();
process_initialize_address_queue(
&ctx.accounts.queue.to_account_info(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,8 @@ pub fn process_initialize_state_merkle_tree_and_nullifier_queue(
nullifier_queue_config: NullifierQueueConfig,
additional_rent: u64,
) -> Result<()> {
// Will be used to configure rollover fees for additional accounts (cpi
// context account).
if additional_rent != 0 {
unimplemented!("Additional rent is not supported.");
if state_merkle_tree_config.close_threshold.is_some() {
unimplemented!("Close threshold not supported.");
}

process_initialize_state_merkle_tree(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use anchor_lang::{prelude::*, solana_program::pubkey::Pubkey};

#[derive(Accounts)]
pub struct RolloverAddressMerkleTreeAndQueue<'info> {
#[account(mut)]
/// Signer used to receive rollover accounts rentexemption reimbursement.
pub fee_payer: Signer<'info>,
pub authority: Signer<'info>,
Expand Down Expand Up @@ -52,10 +53,12 @@ pub fn process_rollover_address_merkle_tree_and_queue<'a, 'b, 'c: 'info, 'info>(
assert_size_equal(
&ctx.accounts.old_queue.to_account_info(),
&ctx.accounts.new_queue.to_account_info(),
"Queue size mismatch",
)?;
assert_size_equal(
&ctx.accounts.old_address_merkle_tree.to_account_info(),
&ctx.accounts.new_address_merkle_tree.to_account_info(),
"Merkle tree size mismatch",
)?;
let (queue_metadata, height) = {
let (merkle_tree_metadata, queue_metadata) = {
Expand Down Expand Up @@ -143,8 +146,11 @@ pub fn process_rollover_address_merkle_tree_and_queue<'a, 'b, 'c: 'info, 'info>(
Ok(())
}

pub fn assert_size_equal(a: &AccountInfo, b: &AccountInfo) -> Result<()> {
pub fn assert_size_equal(a: &AccountInfo, b: &AccountInfo, err_str: &str) -> Result<()> {
if a.data_len() != b.data_len() {
msg!("a: {}", a.data_len());
msg!("b: {}", b.data_len());
msg!("{}", err_str);
return err!(crate::errors::AccountCompressionErrorCode::SizeMismatch);
}
Ok(())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use anchor_lang::{prelude::*, solana_program::pubkey::Pubkey};

#[derive(Accounts)]
pub struct RolloverStateMerkleTreeAndNullifierQueue<'info> {
#[account(mut)]
/// Signer used to receive rollover accounts rentexemption reimbursement.
pub fee_payer: Signer<'info>,
pub authority: Signer<'info>,
Expand Down Expand Up @@ -57,10 +58,12 @@ pub fn process_rollover_state_merkle_tree_nullifier_queue_pair<'a, 'b, 'c: 'info
assert_size_equal(
&ctx.accounts.old_nullifier_queue.to_account_info(),
&ctx.accounts.new_nullifier_queue.to_account_info(),
"Queue size mismatch",
)?;
assert_size_equal(
&ctx.accounts.old_state_merkle_tree.to_account_info(),
&ctx.accounts.new_state_merkle_tree.to_account_info(),
"Merkle tree size mismatch",
)?;
let queue_metadata = {
let (merkle_tree_metadata, queue_metadata) = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ pub fn process_initialize_address_queue<'info>(
.map_err(ProgramError::from)?
+ compute_rollover_fee(rollover_threshold, height, queue_rent)
.map_err(ProgramError::from)?;
if (rollover_fee * rollover_threshold * (2u64.pow(height))) / 100
<= queue_rent + merkle_tree_rent
{
return err!(crate::errors::AccountCompressionErrorCode::InsufficientRolloverFee);
}
check_rollover_fee_sufficient(
rollover_fee,
queue_rent,
merkle_tree_rent,
rollover_threshold,
height,
)?;
rollover_fee
} else {
0
Expand Down Expand Up @@ -70,3 +72,29 @@ pub fn process_initialize_address_queue<'info>(

Ok(())
}

pub fn check_rollover_fee_sufficient(
rollover_fee: u64,
queue_rent: u64,
merkle_tree_rent: u64,
rollover_threshold: u64,
height: u32,
) -> Result<()> {
if rollover_fee != queue_rent + merkle_tree_rent
&& (rollover_fee * rollover_threshold * (2u64.pow(height))) / 100
< queue_rent + merkle_tree_rent
{
msg!("rollover_fee: {}", rollover_fee);
msg!("rollover_threshold: {}", rollover_threshold);
msg!("height: {}", height);
msg!("merkle_tree_rent: {}", merkle_tree_rent);
msg!("queue_rent: {}", queue_rent);
msg!(
"((rollover_fee * rollover_threshold * (2u64.pow(height))) / 100): {} < {} rent",
((rollover_fee * rollover_threshold * (2u64.pow(height))) / 100),
queue_rent + merkle_tree_rent
);
return err!(crate::errors::AccountCompressionErrorCode::InsufficientRolloverFee);
}
Ok(())
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use anchor_lang::prelude::*;
use light_utils::fee::compute_rollover_fee;

use crate::{
state::StateMerkleTreeAccount, state_merkle_tree_from_bytes_zero_copy_init, AccessMetadata,
RolloverMetadata,
initialize_address_queue::check_rollover_fee_sufficient, state::StateMerkleTreeAccount,
state_merkle_tree_from_bytes_zero_copy_init, AccessMetadata, RolloverMetadata,
};

#[allow(unused_variables)]
Expand Down Expand Up @@ -34,22 +34,13 @@ pub fn process_initialize_state_merkle_tree(
.map_err(ProgramError::from)?
+ compute_rollover_fee(rollover_threshold, *height, queue_rent)
.map_err(ProgramError::from)?;
if (rollover_fee * rollover_threshold * (2u64.pow(*height))) / 100
<= queue_rent + merkle_tree_rent
{
msg!("rollover_fee: {}", rollover_fee);
msg!("rollover_threshold: {}", rollover_threshold);
msg!("height: {}", height);
msg!("merkle_tree_rent: {}", merkle_tree_rent);
msg!("queue_rent: {}", queue_rent);
msg!(
"((rollover_fee * rollover_threshold * (2u64.pow(height))) / 100): {} < {} rent",
((rollover_fee * rollover_threshold * (2u64.pow(*height))) / 100), queue_rent + merkle_tree_rent
);
return err!(
crate::errors::AccountCompressionErrorCode::InsufficientRolloverFee
);
}
check_rollover_fee_sufficient(
rollover_fee,
queue_rent,
merkle_tree_rent,
rollover_threshold,
*height,
)?;
rollover_fee
}
None => 0,
Expand Down
4 changes: 2 additions & 2 deletions programs/account-compression/src/state/rollover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ impl RolloverMetadata {
Self {
index,
rollover_fee,
rollover_threshold: rollover_threshold.unwrap_or_default(),
rollover_threshold: rollover_threshold.unwrap_or(u64::MAX),
network_fee,
rolledover_slot: u64::MAX,
close_threshold: close_threshold.unwrap_or(u64::MAX),
}
}

pub fn rollover(&mut self) -> Result<()> {
if self.rollover_threshold == 0 {
if self.rollover_threshold == u64::MAX {
return err!(crate::errors::AccountCompressionErrorCode::RolloverNotConfigured);
}
if self.rolledover_slot != u64::MAX {
Expand Down
1 change: 1 addition & 0 deletions programs/registry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ pub struct RolloverMerkleTreeAndQueue<'info> {
#[account(mut)]
pub registered_forester_pda: Account<'info, ForesterEpoch>,
/// CHECK: unchecked for now logic that regulates forester access is yet to be added.
#[account(mut)]
pub authority: Signer<'info>,
/// CHECK:
#[account(seeds = [CPI_AUTHORITY_PDA_SEED], bump)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -883,8 +883,9 @@ async fn address_merkle_tree_and_queue_rollover(
)
.await
.unwrap();

let payer: Keypair = context.get_payer().insecure_clone();
assert_rolled_over_address_merkle_tree_and_queue(
&payer.pubkey(),
&mut context,
&signer_prior_balance,
&address_merkle_tree_pubkey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -827,8 +827,9 @@ async fn test_init_and_rollover_state_merkle_tree(
)
.await
.unwrap();

let payer: Keypair = context.get_payer().insecure_clone();
assert_rolled_over_pair(
&payer.pubkey(),
&mut context,
&signer_prior_balance,
&merkle_tree_pubkey,
Expand Down
Loading

0 comments on commit 43a3aa6

Please sign in to comment.