diff --git a/.gitignore b/.gitignore index b7e754f3b1..9943415324 100644 --- a/.gitignore +++ b/.gitignore @@ -86,3 +86,4 @@ output1.txt .zed **/.claude/**/* +**/~/ diff --git a/Cargo.lock b/Cargo.lock index 541c1c22cf..301eae03fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3554,14 +3554,13 @@ dependencies = [ [[package]] name = "light-program-test" -version = "0.13.1" +version = "0.13.2" dependencies = [ "account-compression", "anchor-lang", "async-trait", "borsh 0.10.4", "bytemuck", - "forester-utils", "light-batched-merkle-tree", "light-client", "light-compressed-account", diff --git a/Cargo.toml b/Cargo.toml index 176115adb1..b58870a631 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -184,7 +184,7 @@ light-registry = { path = "programs/registry", version = "2.0.0", features = [ create-address-test-program = { path = "program-tests/create-address-test-program", version = "1.0.0", features = [ "cpi", ] } -light-program-test = { path = "sdk-libs/program-test", version = "0.13.1" } +light-program-test = { path = "sdk-libs/program-test", version = "0.13.2" } light-batched-merkle-tree = { path = "program-libs/batched-merkle-tree", version = "0.3.0" } light-merkle-tree-metadata = { path = "program-libs/merkle-tree-metadata", version = "0.3.0" } aligned-sized = { path = "program-libs/aligned-sized", version = "1.1.0" } diff --git a/forester-utils/src/registry.rs b/forester-utils/src/registry.rs index b52547d398..532774d690 100644 --- a/forester-utils/src/registry.rs +++ b/forester-utils/src/registry.rs @@ -11,7 +11,7 @@ use light_registry::{ create_rollover_state_merkle_tree_instruction, CreateRolloverMerkleTreeInstructionInputs, }, protocol_config::state::ProtocolConfig, - sdk::{create_register_forester_instruction, create_update_forester_pda_instruction}, + sdk::create_update_forester_pda_instruction, utils::get_forester_pda, ForesterConfig, ForesterPda, }; @@ -27,38 +27,6 @@ use crate::{ instructions::create_account::create_account_instruction, }; -/// Creates and asserts forester account creation. -pub async fn register_test_forester( - rpc: &mut R, - governance_authority: &Keypair, - forester_authority: &Pubkey, - config: ForesterConfig, -) -> Result<(), RpcError> { - let ix = create_register_forester_instruction( - &governance_authority.pubkey(), - &governance_authority.pubkey(), - forester_authority, - config, - ); - rpc.create_and_send_transaction( - &[ix], - &governance_authority.pubkey(), - &[governance_authority], - ) - .await?; - assert_registered_forester( - rpc, - forester_authority, - ForesterPda { - authority: *forester_authority, - config, - active_weight: 1, - ..Default::default() - }, - ) - .await -} - pub async fn update_test_forester( rpc: &mut R, forester_authority: &Keypair, diff --git a/forester/tests/legacy/batched_address_test.rs b/forester/tests/legacy/batched_address_test.rs index 3f239f1d7e..a9ba71b6ab 100644 --- a/forester/tests/legacy/batched_address_test.rs +++ b/forester/tests/legacy/batched_address_test.rs @@ -2,7 +2,7 @@ use std::{sync::Arc, time::Duration}; use forester::run_pipeline; use forester_utils::{ - registry::{register_test_forester, update_test_forester}, + registry::update_test_forester, rpc_pool::SolanaRpcPoolBuilder, }; use light_batched_merkle_tree::{ diff --git a/program-tests/registry-test/tests/tests.rs b/program-tests/registry-test/tests/tests.rs index 2b41e6c9e6..4b4765ec1e 100644 --- a/program-tests/registry-test/tests/tests.rs +++ b/program-tests/registry-test/tests/tests.rs @@ -74,6 +74,7 @@ use light_test_utils::{ e2e_test_env::init_program_test_env, register_test_forester, setup_accounts::setup_accounts, + setup_forester_and_advance_to_epoch, test_batch_forester::{ assert_perform_state_mt_roll_over, create_append_batch_ix_data, create_batch_update_address_tree_instruction_data_with_proof, perform_batch_append, @@ -193,6 +194,7 @@ async fn test_initialize_protocol_config() { payer, config: ProgramTestConfig::default(), }; + let payer = rpc.get_payer().insecure_clone(); let program_account_keypair = Keypair::from_bytes(&OLD_REGISTRY_ID_TEST_KEYPAIR).unwrap(); let protocol_config = ProtocolConfig::default(); @@ -550,6 +552,10 @@ async fn test_custom_forester() { let mut rpc = LightProgramTest::new(ProgramTestConfig::default_with_batched_trees(true)) .await .unwrap(); + let protocol_config = rpc.config.protocol_config; + setup_forester_and_advance_to_epoch(&mut rpc, &protocol_config) + .await + .unwrap(); rpc.indexer = None; let env = rpc.test_accounts.clone(); @@ -629,6 +635,10 @@ async fn test_custom_forester_batched() { let mut rpc = LightProgramTest::new(ProgramTestConfig::default_test_forester(true)) .await .unwrap(); + let protocol_config = rpc.config.protocol_config; + setup_forester_and_advance_to_epoch(&mut rpc, &protocol_config) + .await + .unwrap(); rpc.indexer = None; let env = rpc.test_accounts.clone(); let tree_params = ProgramTestConfig::default_with_batched_trees(true) @@ -749,7 +759,6 @@ async fn test_register_and_update_forester_pda() { let config = ProgramTestConfig { protocol_config: ProtocolConfig::default(), with_prover: false, - register_forester_and_advance_to_active_phase: false, ..Default::default() }; @@ -1018,6 +1027,10 @@ async fn failing_test_forester() { let mut rpc = LightProgramTest::new(ProgramTestConfig::default_with_batched_trees(true)) .await .unwrap(); + let protocol_config = rpc.config.protocol_config; + setup_forester_and_advance_to_epoch(&mut rpc, &protocol_config) + .await + .unwrap(); rpc.indexer = None; let env = rpc.test_accounts.clone(); let payer = rpc.get_payer().insecure_clone(); @@ -1409,6 +1422,10 @@ async fn test_migrate_state() { let mut rpc = LightProgramTest::new(ProgramTestConfig::default_with_batched_trees(true)) .await .unwrap(); + let protocol_config = rpc.config.protocol_config; + setup_forester_and_advance_to_epoch(&mut rpc, &protocol_config) + .await + .unwrap(); rpc.indexer = None; let test_accounts = rpc.test_accounts.clone(); let payer = rpc.get_payer().insecure_clone(); @@ -1678,6 +1695,10 @@ async fn test_rollover_batch_state_tree() { config.v2_state_tree_config = Some(params); let mut rpc = LightProgramTest::new(config).await.unwrap(); + let protocol_config = rpc.config.protocol_config; + setup_forester_and_advance_to_epoch(&mut rpc, &protocol_config) + .await + .unwrap(); rpc.indexer = None; let test_accounts = rpc.test_accounts.clone(); let payer = rpc.get_payer().insecure_clone(); @@ -1869,6 +1890,11 @@ async fn test_batch_address_tree() { CREATE_ADDRESS_TEST_PROGRAM_ID, )]); let mut rpc = LightProgramTest::new(config).await.unwrap(); + let protocol_config = rpc.config.protocol_config; + setup_forester_and_advance_to_epoch(&mut rpc, &protocol_config) + .await + .unwrap(); + rpc.indexer = None; let env = rpc.test_accounts.clone(); @@ -2044,6 +2070,10 @@ async fn test_rollover_batch_address_tree() { )]); config.v2_address_tree_config = Some(tree_params); let mut rpc = LightProgramTest::new(config).await.unwrap(); + let protocol_config = rpc.config.protocol_config; + setup_forester_and_advance_to_epoch(&mut rpc, &protocol_config) + .await + .unwrap(); rpc.indexer = None; let env = rpc.test_accounts.clone(); diff --git a/program-tests/system-cpi-test/tests/test_program_owned_trees.rs b/program-tests/system-cpi-test/tests/test_program_owned_trees.rs index ddbdda14de..1fdf5636d0 100644 --- a/program-tests/system-cpi-test/tests/test_program_owned_trees.rs +++ b/program-tests/system-cpi-test/tests/test_program_owned_trees.rs @@ -31,8 +31,8 @@ use light_registry::{ }; use light_test_utils::{ airdrop_lamports, assert_custom_error_or_program_error, create_account_instruction, - get_concurrent_merkle_tree, spl::create_mint_helper, FeeConfig, Rpc, RpcError, - TransactionParams, + get_concurrent_merkle_tree, setup_forester_and_advance_to_epoch, spl::create_mint_helper, + FeeConfig, Rpc, RpcError, TransactionParams, }; use serial_test::serial; use solana_sdk::{ @@ -211,6 +211,13 @@ async fn test_invalid_registered_program() { airdrop_lamports(&mut rpc, &payer.pubkey(), 100_000_000_000) .await .unwrap(); + + // Setup forester to ensure registered_forester_pda is initialized + let protocol_config = rpc.config.protocol_config; + setup_forester_and_advance_to_epoch(&mut rpc, &protocol_config) + .await + .unwrap(); + let group_seed_keypair = Keypair::new(); let program_id_keypair = Keypair::from_bytes(&CPI_SYSTEM_TEST_PROGRAM_ID_KEYPAIR).unwrap(); println!("program_id_keypair: {:?}", program_id_keypair.pubkey()); diff --git a/program-tests/system-test/tests/test.rs b/program-tests/system-test/tests/test.rs index e6270e776d..f1cfba0f1f 100644 --- a/program-tests/system-test/tests/test.rs +++ b/program-tests/system-test/tests/test.rs @@ -34,7 +34,7 @@ use light_system_program::{ use light_test_utils::{ airdrop_lamports, assert_compressed_tx::assert_created_compressed_accounts, - assert_custom_error_or_program_error, + assert_custom_error_or_program_error, setup_forester_and_advance_to_epoch, system_program::{ compress_sol_test, create_addresses_test, create_invoke_instruction, create_invoke_instruction_data_and_remaining_accounts, decompress_sol_test, @@ -1674,6 +1674,11 @@ async fn regenerate_accounts() { .unwrap(); let keypairs = for_regenerate_accounts(); + // Setup forester and get epoch information + let forester_epoch = setup_forester_and_advance_to_epoch(&mut rpc, &protocol_config) + .await + .unwrap(); + // List of public keys to fetch and export let pubkeys = vec![ ("merkle_tree_pubkey", env.v1_state_trees[0].merkle_tree), @@ -1707,18 +1712,8 @@ async fn regenerate_accounts() { "registered_forester_pda", env.protocol.registered_forester_pda, ), - ( - "forester_epoch_pda", - env.protocol - .forester_epoch - .as_ref() - .unwrap() - .forester_epoch_pda, - ), - ( - "epoch_pda", - env.protocol.forester_epoch.as_ref().unwrap().epoch_pda, - ), + ("forester_epoch_pda", forester_epoch.forester_epoch_pda), + ("epoch_pda", forester_epoch.epoch_pda), ("batch_state_merkle_tree", env.v2_state_trees[0].merkle_tree), ("batched_output_queue", env.v2_state_trees[0].output_queue), ("batch_address_merkle_tree", env.v2_address_trees[0]), @@ -1845,6 +1840,10 @@ async fn batch_invoke_test() { let config = ProgramTestConfig::default_test_forester(false); let mut rpc = LightProgramTest::new(config).await.unwrap(); + let protocol_config = rpc.config.protocol_config; + setup_forester_and_advance_to_epoch(&mut rpc, &protocol_config) + .await + .unwrap(); let env = rpc.test_accounts.clone(); let payer = rpc.get_payer().insecure_clone(); diff --git a/program-tests/utils/src/e2e_test_env.rs b/program-tests/utils/src/e2e_test_env.rs index 0225ca225f..59396c6887 100644 --- a/program-tests/utils/src/e2e_test_env.rs +++ b/program-tests/utils/src/e2e_test_env.rs @@ -76,7 +76,6 @@ use forester_utils::{ account_zero_copy::AccountZeroCopy, address_merkle_tree_config::{address_tree_ready_for_rollover, state_tree_ready_for_rollover}, forester_epoch::{Epoch, Forester, TreeAccounts}, - registry::register_test_forester, utils::airdrop_lamports, }; use light_batched_merkle_tree::{ @@ -132,6 +131,7 @@ use light_program_test::{ TestIndexerExtensions, }, program_test::{LightProgramTest, TestRpc}, + utils::register_test_forester::register_test_forester, }; use light_prover_client::{ constants::{PROVE_PATH, SERVER_ADDRESS}, @@ -394,23 +394,9 @@ where .config; // TODO: add clear test env enum // register foresters is only compatible with ProgramTest environment - let (foresters, epoch_config) = - if let Some(registered_epoch) = test_accounts.protocol.forester_epoch.as_ref() { - let _forester = Forester { - registration: registered_epoch.clone(), - active: registered_epoch.clone(), - ..Default::default() - }; - // Forester epoch account is assumed to exist (is inited with test program deployment) - let forester = TestForester { - keypair: test_accounts.protocol.forester.insecure_clone(), - forester: _forester.clone(), - is_registered: Some(0), - }; - (vec![forester], _forester) - } else { - (Vec::::new(), Forester::default()) - }; + // Default forester setup - tests that need forester functionality should call + // setup_forester_and_advance_to_epoch explicitly and manage their own forester state + let (foresters, epoch_config) = (Vec::::new(), Forester::default()); Self { payer, indexer, diff --git a/program-tests/utils/src/lib.rs b/program-tests/utils/src/lib.rs index 889b6556a7..5a581bbb4b 100644 --- a/program-tests/utils/src/lib.rs +++ b/program-tests/utils/src/lib.rs @@ -32,6 +32,7 @@ pub mod mock_batched_forester; pub mod pack; pub mod registered_program_accounts_v1; pub mod setup_accounts; +pub mod setup_forester; #[allow(unused)] pub mod spl; pub mod state_tree_rollover; @@ -46,8 +47,7 @@ pub use forester_utils::{ forester_epoch::{Epoch, TreeAccounts}, registry::{ create_rollover_address_merkle_tree_instructions, - create_rollover_state_merkle_tree_instructions, register_test_forester, - update_test_forester, + create_rollover_state_merkle_tree_instructions, update_test_forester, }, }; pub use light_client::{ @@ -56,7 +56,9 @@ pub use light_client::{ }; use light_hasher::Poseidon; use light_program_test::accounts::address_tree::create_address_merkle_tree_and_queue_account; +pub use light_program_test::utils::register_test_forester::register_test_forester; use light_registry::account_compression_cpi::sdk::get_registered_program_pda; +pub use setup_forester::setup_forester_and_advance_to_epoch; use crate::assert_queue::assert_address_queue_initialized; diff --git a/program-tests/utils/src/setup_forester.rs b/program-tests/utils/src/setup_forester.rs new file mode 100644 index 0000000000..6f1fc17630 --- /dev/null +++ b/program-tests/utils/src/setup_forester.rs @@ -0,0 +1,87 @@ +use forester_utils::forester_epoch::{Epoch, TreeAccounts}; +use light_client::rpc::{Rpc, RpcError}; +use light_compressed_account::TreeType; +use light_program_test::{ + accounts::test_keypairs::TestKeypairs, program_test::TestRpc, + utils::register_test_forester::register_test_forester, +}; +use light_registry::{ + protocol_config::state::ProtocolConfig, sdk::create_finalize_registration_instruction, + ForesterConfig, +}; +use solana_sdk::signature::Signer; + +/// Sets up a forester, registers it, and advances to the active epoch phase. +/// This function encapsulates all forester-related setup that was previously +/// done conditionally in light-program-test. +/// +/// # Arguments +/// * `context` - The test RPC context +/// * `protocol_config` - Protocol configuration +/// +/// # Returns +/// * `Result` - The registered and activated epoch +pub async fn setup_forester_and_advance_to_epoch( + context: &mut R, + protocol_config: &ProtocolConfig, +) -> Result { + let test_keypairs = TestKeypairs::program_test_default(); + // Register the test forester + register_test_forester( + context, + &test_keypairs.governance_authority, + &test_keypairs.forester.pubkey(), + ForesterConfig::default(), + ) + .await?; + + // Register the epoch + let mut registered_epoch = Epoch::register( + context, + protocol_config, + &test_keypairs.forester, + &test_keypairs.forester.pubkey(), + ) + .await? + .ok_or_else(|| RpcError::CustomError("Failed to register epoch".to_string()))?; + + // Advance to active phase + context.warp_to_slot(registered_epoch.phases.active.start)?; + + // Create tree accounts for the epoch using test keypairs + let tree_accounts = vec![ + TreeAccounts::new( + test_keypairs.state_merkle_tree.pubkey(), + test_keypairs.nullifier_queue.pubkey(), + TreeType::StateV1, + false, + ), + TreeAccounts::new( + test_keypairs.address_merkle_tree.pubkey(), + test_keypairs.address_merkle_tree_queue.pubkey(), + TreeType::AddressV1, + false, + ), + ]; + + // Add trees to the epoch with schedule + registered_epoch + .fetch_account_and_add_trees_with_schedule(context, &tree_accounts) + .await?; + + // Finalize registration + let ix = create_finalize_registration_instruction( + &test_keypairs.forester.pubkey(), + &test_keypairs.forester.pubkey(), + 0, + ); + context + .create_and_send_transaction( + &[ix], + &test_keypairs.forester.pubkey(), + &[&test_keypairs.forester], + ) + .await?; + + Ok(registered_epoch) +} diff --git a/program-tests/utils/src/update_test_forester.rs b/program-tests/utils/src/update_test_forester.rs new file mode 100644 index 0000000000..57afe6eeaa --- /dev/null +++ b/program-tests/utils/src/update_test_forester.rs @@ -0,0 +1,60 @@ +use light_client::rpc::{Rpc, RpcError}; +use light_registry::{ + sdk::create_update_forester_pda_instruction, utils::get_forester_pda, ForesterConfig, + ForesterPda, +}; +use solana_sdk::{ + pubkey::Pubkey, + signature::{Keypair, Signer}, +}; + +pub async fn update_test_forester( + rpc: &mut R, + forester_authority: &Keypair, + derivation_key: &Pubkey, + new_forester_authority: Option<&Keypair>, + config: ForesterConfig, +) -> Result<(), RpcError> { + let mut pre_account_state = rpc + .get_anchor_account::(&get_forester_pda(derivation_key).0) + .await? + .unwrap(); + let (signers, new_forester_authority) = if let Some(new_authority) = new_forester_authority { + pre_account_state.authority = new_authority.pubkey(); + + ( + vec![forester_authority, &new_authority], + Some(new_authority.pubkey()), + ) + } else { + (vec![forester_authority], None) + }; + let ix = create_update_forester_pda_instruction( + &forester_authority.pubkey(), + derivation_key, + new_forester_authority, + Some(config), + ); + + rpc.create_and_send_transaction(&[ix], &forester_authority.pubkey(), &signers) + .await?; + + pre_account_state.config = config; + assert_registered_forester(rpc, derivation_key, pre_account_state).await +} + +async fn assert_registered_forester( + rpc: &mut R, + forester: &Pubkey, + expected_account: ForesterPda, +) -> Result<(), RpcError> { + let pda = get_forester_pda(forester).0; + let account_data = rpc.get_anchor_account::(&pda).await?.unwrap(); + if account_data != expected_account { + return Err(RpcError::AssertRpcError(format!( + "Expected account data: {:?}, got: {:?}", + expected_account, account_data + ))); + } + Ok(()) +} diff --git a/programs/registry/src/protocol_config/state.rs b/programs/registry/src/protocol_config/state.rs index e938d8c9f1..3c65b897ca 100644 --- a/programs/registry/src/protocol_config/state.rs +++ b/programs/registry/src/protocol_config/state.rs @@ -176,10 +176,9 @@ impl ProtocolConfig { } pub fn get_current_active_epoch_progress(&self, slot: u64) -> u64 { - (slot - .checked_sub(self.genesis_slot + self.registration_phase_length) - .unwrap()) - % self.active_phase_length + slot.checked_sub(self.genesis_slot + self.registration_phase_length) + .map(|s| s % self.active_phase_length) + .unwrap_or(0) } /// In the last part of the active phase the registration phase starts. diff --git a/sdk-libs/program-test/Cargo.toml b/sdk-libs/program-test/Cargo.toml index a202154304..c9a826ebc7 100644 --- a/sdk-libs/program-test/Cargo.toml +++ b/sdk-libs/program-test/Cargo.toml @@ -1,19 +1,14 @@ [package] name = "light-program-test" -version = "0.13.1" +version = "0.13.2" description = "A fast local test environment for Solana programs using compressed accounts and tokens." license = "MIT" edition = "2021" [features] default = [] -devenv = [ - "v2", - "light-client/devenv", - "forester-utils/devenv", - "light-prover-client/devenv", -] -v2 = ["light-client/v2", "forester-utils/v2"] +devenv = ["v2", "light-client/devenv", "light-prover-client/devenv"] +v2 = ["light-client/v2"] [dependencies] light-sdk = { workspace = true, features = ["anchor"] } @@ -28,7 +23,6 @@ light-batched-merkle-tree = { workspace = true, features = ["test-only"] } # unreleased light-client = { workspace = true, features = ["program-test"] } -forester-utils = { workspace = true } light-prover-client = { workspace = true } litesvm = { workspace = true } diff --git a/sdk-libs/program-test/src/accounts/address_tree.rs b/sdk-libs/program-test/src/accounts/address_tree.rs index 93252f114e..0807e352af 100644 --- a/sdk-libs/program-test/src/accounts/address_tree.rs +++ b/sdk-libs/program-test/src/accounts/address_tree.rs @@ -2,7 +2,6 @@ use account_compression::{ instruction::InitializeAddressMerkleTreeAndQueue, AddressMerkleTreeConfig, AddressQueueConfig, }; use anchor_lang::InstructionData; -use forester_utils::instructions::create_account::create_account_instruction; use light_client::rpc::{errors::RpcError, Rpc}; use solana_sdk::{ compute_budget::ComputeBudgetInstruction, @@ -12,6 +11,8 @@ use solana_sdk::{ transaction::Transaction, }; +use crate::utils::create_account::create_account_instruction; + #[allow(clippy::too_many_arguments)] pub fn create_initialize_address_merkle_tree_and_queue_instruction( index: u64, diff --git a/sdk-libs/program-test/src/accounts/address_tree_v2.rs b/sdk-libs/program-test/src/accounts/address_tree_v2.rs index db5e677149..fe9bccee9b 100644 --- a/sdk-libs/program-test/src/accounts/address_tree_v2.rs +++ b/sdk-libs/program-test/src/accounts/address_tree_v2.rs @@ -1,4 +1,3 @@ -use forester_utils::instructions::create_account_instruction; use light_batched_merkle_tree::{ initialize_address_tree::InitAddressTreeAccountsInstructionData, merkle_tree::get_merkle_tree_account_size, @@ -7,6 +6,8 @@ use light_client::rpc::{Rpc, RpcError}; use light_registry::account_compression_cpi::sdk::create_initialize_batched_address_merkle_tree_instruction; use solana_sdk::signature::{Keypair, Signature, Signer}; +use crate::utils::create_account::create_account_instruction; + pub async fn create_batch_address_merkle_tree( rpc: &mut R, payer: &Keypair, diff --git a/sdk-libs/program-test/src/accounts/initialize.rs b/sdk-libs/program-test/src/accounts/initialize.rs index c70e3f8ba7..7781a87af9 100644 --- a/sdk-libs/program-test/src/accounts/initialize.rs +++ b/sdk-libs/program-test/src/accounts/initialize.rs @@ -1,22 +1,15 @@ use account_compression::{utils::constants::GROUP_AUTHORITY_SEED, GroupAuthority}; -use forester_utils::{ - forester_epoch::{Epoch, TreeAccounts}, - registry::register_test_forester, -}; use light_client::{ indexer::{AddressMerkleTreeAccounts, StateMerkleTreeAccounts}, rpc::{Rpc, RpcError}, }; -use light_compressed_account::TreeType; use light_registry::{ account_compression_cpi::sdk::get_registered_program_pda, sdk::{ - create_finalize_registration_instruction, create_initialize_governance_authority_instruction, create_initialize_group_authority_instruction, create_update_protocol_config_instruction, }, utils::{get_cpi_authority_pda, get_forester_pda, get_protocol_config_pda_address}, - ForesterConfig, }; use solana_sdk::{ pubkey::Pubkey, @@ -49,7 +42,6 @@ pub async fn initialize_accounts( ) -> Result { let ProgramTestConfig { protocol_config, - register_forester_and_advance_to_active_phase, v2_state_tree_config, v2_address_tree_config, skip_register_programs, @@ -107,14 +99,6 @@ pub async fn initialize_accounts( )); } - register_test_forester( - context, - &keypairs.governance_authority, - &keypairs.forester.pubkey(), - ForesterConfig::default(), - ) - .await?; - #[cfg(feature = "devenv")] if !_skip_register_programs { register_program_with_registry_program( @@ -208,46 +192,6 @@ pub async fn initialize_accounts( let registered_system_program_pda = get_registered_program_pda(&Pubkey::from(light_sdk::constants::LIGHT_SYSTEM_PROGRAM_ID)); let registered_registry_program_pda = get_registered_program_pda(&light_registry::ID); - let forester_epoch = if *register_forester_and_advance_to_active_phase { - let mut registered_epoch = Epoch::register( - context, - protocol_config, - &keypairs.forester, - &keypairs.forester.pubkey(), - ) - .await? - .unwrap(); - context.warp_to_slot(registered_epoch.phases.active.start)?; - let tree_accounts = vec![ - TreeAccounts { - tree_type: TreeType::StateV1, - merkle_tree: merkle_tree_pubkey, - queue: nullifier_queue_pubkey, - is_rolledover: false, - }, - TreeAccounts { - tree_type: TreeType::AddressV1, - merkle_tree: keypairs.address_merkle_tree.pubkey(), - queue: keypairs.address_merkle_tree_queue.pubkey(), - is_rolledover: false, - }, - ]; - - registered_epoch - .fetch_account_and_add_trees_with_schedule(context, &tree_accounts) - .await?; - let ix = create_finalize_registration_instruction( - &keypairs.forester.pubkey(), - &keypairs.forester.pubkey(), - 0, - ); - context - .create_and_send_transaction(&[ix], &keypairs.forester.pubkey(), &[&keypairs.forester]) - .await?; - Some(registered_epoch) - } else { - None - }; Ok(TestAccounts { protocol: ProtocolAccounts { governance_authority: keypairs.governance_authority.insecure_clone(), @@ -257,7 +201,6 @@ pub async fn initialize_accounts( registered_program_pda: registered_system_program_pda, registered_registry_program_pda, registered_forester_pda: get_forester_pda(&keypairs.forester.pubkey()).0, - forester_epoch, }, v1_state_trees: vec![StateMerkleTreeAccounts { merkle_tree: merkle_tree_pubkey, diff --git a/sdk-libs/program-test/src/accounts/state_tree.rs b/sdk-libs/program-test/src/accounts/state_tree.rs index 8f5d226934..d43f7f768e 100644 --- a/sdk-libs/program-test/src/accounts/state_tree.rs +++ b/sdk-libs/program-test/src/accounts/state_tree.rs @@ -3,7 +3,6 @@ use account_compression::{ StateMerkleTreeConfig, }; use anchor_lang::{InstructionData, ToAccountMetas}; -use forester_utils::instructions::create_account::create_account_instruction; use light_client::rpc::{errors::RpcError, Rpc}; use light_compressed_account::instruction_data::insert_into_queues::InsertIntoQueuesInstructionDataMut; use light_registry::protocol_config::state::ProtocolConfig; @@ -14,6 +13,8 @@ use solana_sdk::{ transaction::Transaction, }; +use crate::utils::create_account::create_account_instruction; + #[allow(clippy::too_many_arguments)] pub fn create_initialize_merkle_tree_instruction( payer: Pubkey, diff --git a/sdk-libs/program-test/src/accounts/state_tree_v2.rs b/sdk-libs/program-test/src/accounts/state_tree_v2.rs index a6458015ac..b3c4bb6184 100644 --- a/sdk-libs/program-test/src/accounts/state_tree_v2.rs +++ b/sdk-libs/program-test/src/accounts/state_tree_v2.rs @@ -1,5 +1,4 @@ use anchor_lang::{AnchorSerialize, InstructionData, ToAccountMetas}; -use forester_utils::instructions::create_account_instruction; use light_batched_merkle_tree::{ initialize_state_tree::InitStateTreeAccountsInstructionData, merkle_tree::get_merkle_tree_account_size, queue::get_output_queue_account_size, @@ -13,6 +12,8 @@ use solana_instruction::Instruction; use solana_pubkey::Pubkey; use solana_sdk::signature::{Keypair, Signature, Signer}; +use crate::utils::create_account::create_account_instruction; + pub async fn create_batched_state_merkle_tree( payer: &Keypair, registry: bool, diff --git a/sdk-libs/program-test/src/accounts/test_accounts.rs b/sdk-libs/program-test/src/accounts/test_accounts.rs index 115577c71c..ea4284c30d 100644 --- a/sdk-libs/program-test/src/accounts/test_accounts.rs +++ b/sdk-libs/program-test/src/accounts/test_accounts.rs @@ -1,4 +1,3 @@ -use forester_utils::forester_epoch::Epoch; use light_client::indexer::{AddressMerkleTreeAccounts, StateMerkleTreeAccounts, TreeInfo}; use light_compressed_account::TreeType; use light_registry::{ @@ -25,7 +24,6 @@ pub struct ProtocolAccounts { pub registered_program_pda: Pubkey, pub registered_registry_program_pda: Pubkey, pub registered_forester_pda: Pubkey, - pub forester_epoch: Option, } #[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)] @@ -69,7 +67,6 @@ impl TestAccounts { )), registered_registry_program_pda: get_registered_program_pda(&light_registry::ID), registered_forester_pda: Pubkey::default(), - forester_epoch: None, // Set to None or to an appropriate Epoch value if needed }, v1_state_trees: vec![StateMerkleTreeAccounts { merkle_tree: pubkey!("smt1NamzXdq4AMqS2fS2F1i5KTYPZRhoHgWx38d8WsT"), @@ -120,7 +117,6 @@ impl TestAccounts { registered_program_pda, registered_registry_program_pda, registered_forester_pda: get_forester_pda(&forester_pubkey).0, - forester_epoch: None, }, v1_state_trees: vec![StateMerkleTreeAccounts { merkle_tree: merkle_tree_keypair.pubkey(), @@ -165,7 +161,6 @@ impl Clone for TestAccounts { registered_program_pda: self.protocol.registered_program_pda, registered_registry_program_pda: self.protocol.registered_registry_program_pda, registered_forester_pda: self.protocol.registered_forester_pda, - forester_epoch: self.protocol.forester_epoch.clone(), }, v1_state_trees: self.v1_state_trees.clone(), v1_address_trees: self.v1_address_trees.clone(), diff --git a/sdk-libs/program-test/src/program_test/config.rs b/sdk-libs/program-test/src/program_test/config.rs index ade109c29e..33d8262b50 100644 --- a/sdk-libs/program-test/src/program_test/config.rs +++ b/sdk-libs/program-test/src/program_test/config.rs @@ -13,7 +13,6 @@ use solana_sdk::pubkey::Pubkey; pub struct ProgramTestConfig { pub additional_programs: Option>, pub protocol_config: ProtocolConfig, - pub register_forester_and_advance_to_active_phase: bool, pub with_prover: bool, pub prover_config: Option, pub skip_register_programs: bool, @@ -105,7 +104,6 @@ impl Default for ProgramTestConfig { registration_phase_length: 2, ..Default::default() }, - register_forester_and_advance_to_active_phase: true, with_prover: true, prover_config: None, skip_second_v1_tree: false, diff --git a/sdk-libs/program-test/src/utils/create_account.rs b/sdk-libs/program-test/src/utils/create_account.rs new file mode 100644 index 0000000000..55cecf673e --- /dev/null +++ b/sdk-libs/program-test/src/utils/create_account.rs @@ -0,0 +1,17 @@ +use account_compression::processor::initialize_address_merkle_tree::Pubkey; +use anchor_lang::solana_program::{instruction::Instruction, system_instruction}; +use solana_sdk::signature::{Keypair, Signer}; + +pub fn create_account_instruction( + payer: &Pubkey, + size: usize, + rent: u64, + id: &Pubkey, + keypair: Option<&Keypair>, +) -> Instruction { + let keypair = match keypair { + Some(keypair) => keypair.insecure_clone(), + None => Keypair::new(), + }; + system_instruction::create_account(payer, &keypair.pubkey(), rent, size as u64, id) +} diff --git a/sdk-libs/program-test/src/utils/mod.rs b/sdk-libs/program-test/src/utils/mod.rs index 5419aa40a4..e1b9d7be63 100644 --- a/sdk-libs/program-test/src/utils/mod.rs +++ b/sdk-libs/program-test/src/utils/mod.rs @@ -1,3 +1,6 @@ pub mod assert; +pub mod create_account; pub mod find_light_bin; +pub mod register_test_forester; pub mod setup_light_programs; +pub mod tree_accounts; diff --git a/sdk-libs/program-test/src/utils/register_test_forester.rs b/sdk-libs/program-test/src/utils/register_test_forester.rs new file mode 100644 index 0000000000..41cbe8a063 --- /dev/null +++ b/sdk-libs/program-test/src/utils/register_test_forester.rs @@ -0,0 +1,56 @@ +use light_client::rpc::{Rpc, RpcError}; +use light_registry::{ + sdk::create_register_forester_instruction, utils::get_forester_pda, ForesterConfig, ForesterPda, +}; +use solana_sdk::{ + pubkey::Pubkey, + signature::{Keypair, Signer}, +}; + +/// Creates and asserts forester account creation. +pub async fn register_test_forester( + rpc: &mut R, + governance_authority: &Keypair, + forester_authority: &Pubkey, + config: ForesterConfig, +) -> Result<(), RpcError> { + let ix = create_register_forester_instruction( + &governance_authority.pubkey(), + &governance_authority.pubkey(), + forester_authority, + config, + ); + rpc.create_and_send_transaction( + &[ix], + &governance_authority.pubkey(), + &[governance_authority], + ) + .await?; + assert_registered_forester( + rpc, + forester_authority, + ForesterPda { + authority: *forester_authority, + config, + active_weight: 1, + ..Default::default() + }, + ) + .await +} + +async fn assert_registered_forester( + rpc: &mut R, + forester: &Pubkey, + expected_account: ForesterPda, +) -> Result<(), RpcError> { + let pda = get_forester_pda(forester).0; + let account_data = rpc.get_anchor_account::(&pda).await?.unwrap(); + if account_data != expected_account { + return Err(RpcError::AssertRpcError(format!( + "Expected account data: {:?}, got: {:?}", + expected_account, account_data + ))); + } + Ok(()) +} diff --git a/sdk-libs/program-test/src/utils/tree_accounts.rs b/sdk-libs/program-test/src/utils/tree_accounts.rs new file mode 100644 index 0000000000..61ef8ff33a --- /dev/null +++ b/sdk-libs/program-test/src/utils/tree_accounts.rs @@ -0,0 +1,26 @@ +use light_compressed_account::TreeType; +use solana_sdk::pubkey::Pubkey; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct TreeAccounts { + pub merkle_tree: Pubkey, + pub queue: Pubkey, + pub is_rolledover: bool, + pub tree_type: TreeType, +} + +impl TreeAccounts { + pub fn new( + merkle_tree: Pubkey, + queue: Pubkey, + tree_type: TreeType, + is_rolledover: bool, + ) -> Self { + Self { + merkle_tree, + queue, + tree_type, + is_rolledover, + } + } +} diff --git a/xtask/src/new_deployment.rs b/xtask/src/new_deployment.rs index ff9a61b7a4..14d13788e3 100644 --- a/xtask/src/new_deployment.rs +++ b/xtask/src/new_deployment.rs @@ -168,7 +168,6 @@ pub async fn init_new_deployment(options: Options) -> anyhow::Result<()> { v1_state_tree_config: StateMerkleTreeConfig::default(), v2_state_tree_config: Some(InitStateTreeAccountsInstructionData::default()), v2_address_tree_config: Some(InitAddressTreeAccountsInstructionData::default()), - register_forester_and_advance_to_active_phase: false, ..Default::default() }; initialize_accounts(&mut rpc, &config, &test_keypairs)