light_test_utils/
test_env.rs

1use crate::assert_address_merkle_tree::assert_address_merkle_tree_initialized;
2use crate::assert_queue::assert_address_queue_initialized;
3use crate::env_accounts;
4use crate::rpc::test_rpc::ProgramTestRpcConnection;
5use account_compression::sdk::create_initialize_address_merkle_tree_and_queue_instruction;
6use account_compression::utils::constants::GROUP_AUTHORITY_SEED;
7use account_compression::{
8    sdk::create_initialize_merkle_tree_instruction, GroupAuthority, RegisteredProgram,
9};
10use account_compression::{AddressMerkleTreeConfig, AddressQueueConfig, QueueType};
11use account_compression::{NullifierQueueConfig, StateMerkleTreeConfig};
12use forester_utils::forester_epoch::{Epoch, TreeAccounts, TreeType};
13use forester_utils::registry::register_test_forester;
14use forester_utils::{airdrop_lamports, create_account_instruction};
15use light_client::rpc::errors::RpcError;
16use light_client::rpc::solana_rpc::SolanaRpcUrl;
17use light_client::rpc::{RpcConnection, SolanaRpcConnection};
18use light_hasher::Poseidon;
19use light_macros::pubkey;
20use light_registry::account_compression_cpi::sdk::get_registered_program_pda;
21use light_registry::protocol_config::state::ProtocolConfig;
22use light_registry::sdk::{
23    create_deregister_program_instruction, create_finalize_registration_instruction,
24    create_initialize_governance_authority_instruction,
25    create_initialize_group_authority_instruction, create_register_program_instruction,
26    create_update_protocol_config_instruction,
27};
28use light_registry::utils::{
29    get_cpi_authority_pda, get_forester_pda, get_protocol_config_pda_address,
30};
31use light_registry::ForesterConfig;
32use solana_program_test::{ProgramTest, ProgramTestContext};
33use solana_sdk::signature::{read_keypair_file, Signature};
34use solana_sdk::{
35    pubkey::Pubkey, signature::Keypair, signature::Signer, system_instruction,
36    transaction::Transaction,
37};
38use std::cmp;
39use std::path::PathBuf;
40
41pub const CPI_CONTEXT_ACCOUNT_RENT: u64 = 143487360; // lamports of the cpi context account
42pub const NOOP_PROGRAM_ID: Pubkey = pubkey!("noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV");
43
44/// Setup test programs
45/// deploys:
46/// 1. light_registry program
47/// 2. account_compression program
48/// 3. light_compressed_token program
49/// 4. light_system_program program
50pub async fn setup_test_programs(
51    additional_programs: Option<Vec<(String, Pubkey)>>,
52) -> ProgramTestContext {
53    let mut program_test = ProgramTest::default();
54    let sbf_path = std::env::var("SBF_OUT_DIR").unwrap();
55    // find path to bin where light cli stores program binaries.
56    let path = find_light_bin().unwrap();
57    std::env::set_var("SBF_OUT_DIR", path.to_str().unwrap());
58    program_test.add_program("light_registry", light_registry::ID, None);
59    program_test.add_program("account_compression", account_compression::ID, None);
60    program_test.add_program("light_compressed_token", light_compressed_token::ID, None);
61    program_test.add_program("light_system_program", light_system_program::ID, None);
62    program_test.add_program("spl_noop", NOOP_PROGRAM_ID, None);
63    std::env::set_var("SBF_OUT_DIR", sbf_path);
64    let registered_program = env_accounts::get_registered_program_pda();
65    program_test.add_account(
66        get_registered_program_pda(&light_system_program::ID),
67        registered_program,
68    );
69    let registered_program = env_accounts::get_registered_registry_program_pda();
70    program_test.add_account(
71        get_registered_program_pda(&light_registry::ID),
72        registered_program,
73    );
74    if let Some(programs) = additional_programs {
75        for (name, id) in programs {
76            program_test.add_program(&name, id, None);
77        }
78    }
79    program_test.set_compute_max_units(1_400_000u64);
80    program_test.start_with_context().await
81}
82
83fn find_light_bin() -> Option<PathBuf> {
84    // Run the 'which light' command to find the location of 'light' binary
85
86    #[cfg(not(feature = "devenv"))]
87    {
88        use std::process::Command;
89        let output = Command::new("which")
90            .arg("light")
91            .output()
92            .expect("Failed to execute 'which light'");
93
94        if !output.status.success() {
95            return None;
96        }
97        // Convert the output into a string (removing any trailing newline)
98        let light_path = String::from_utf8_lossy(&output.stdout).trim().to_string();
99        // Get the parent directory of the 'light' binary
100        let mut light_bin_path = PathBuf::from(light_path);
101        light_bin_path.pop(); // Remove the 'light' binary itself
102
103        // Assuming the node_modules path starts from '/lib/node_modules/...'
104        let node_modules_bin =
105            light_bin_path.join("../lib/node_modules/@lightprotocol/zk-compression-cli/bin");
106
107        Some(node_modules_bin.canonicalize().unwrap_or(node_modules_bin))
108    }
109    #[cfg(feature = "devenv")]
110    {
111        let light_protocol_toplevel = String::from_utf8_lossy(
112            &std::process::Command::new("git")
113                .arg("rev-parse")
114                .arg("--show-toplevel")
115                .output()
116                .expect("Failed to get top-level directory")
117                .stdout,
118        )
119        .trim()
120        .to_string();
121        let light_path = PathBuf::from(format!("{}/target/deploy/", light_protocol_toplevel));
122        Some(light_path)
123    }
124}
125
126#[derive(Debug)]
127pub struct EnvAccounts {
128    pub merkle_tree_pubkey: Pubkey,
129    pub nullifier_queue_pubkey: Pubkey,
130    pub governance_authority: Keypair,
131    pub governance_authority_pda: Pubkey,
132    pub group_pda: Pubkey,
133    pub forester: Keypair,
134    pub registered_program_pda: Pubkey,
135    pub registered_registry_program_pda: Pubkey,
136    pub address_merkle_tree_pubkey: Pubkey,
137    pub address_merkle_tree_queue_pubkey: Pubkey,
138    pub cpi_context_account_pubkey: Pubkey,
139    pub registered_forester_pda: Pubkey,
140    pub forester_epoch: Option<Epoch>,
141}
142
143impl EnvAccounts {
144    pub fn get_local_test_validator_accounts() -> EnvAccounts {
145        EnvAccounts {
146            merkle_tree_pubkey: pubkey!("smt1NamzXdq4AMqS2fS2F1i5KTYPZRhoHgWx38d8WsT"),
147            nullifier_queue_pubkey: pubkey!("nfq1NvQDJ2GEgnS8zt9prAe8rjjpAW1zFkrvZoBR148"),
148            governance_authority: Keypair::from_bytes(&PAYER_KEYPAIR).unwrap(),
149            governance_authority_pda: Pubkey::default(),
150            group_pda: Pubkey::default(),
151            forester: Keypair::new(),
152            registered_program_pda: get_registered_program_pda(&light_system_program::ID),
153            registered_registry_program_pda: get_registered_program_pda(&light_registry::ID),
154            address_merkle_tree_pubkey: pubkey!("amt1Ayt45jfbdw5YSo7iz6WZxUmnZsQTYXy82hVwyC2"),
155            address_merkle_tree_queue_pubkey: pubkey!(
156                "aq1S9z4reTSQAdgWHGD2zDaS39sjGrAxbR31vxJ2F4F"
157            ),
158            cpi_context_account_pubkey: pubkey!("cpi1uHzrEhBG733DoEJNgHCyRS3XmmyVNZx5fonubE4"),
159            registered_forester_pda: Pubkey::default(),
160            forester_epoch: None, // Set to None or to an appropriate Epoch value if needed
161        }
162    }
163}
164
165#[derive(Debug)]
166pub struct EnvAccountKeypairs {
167    pub state_merkle_tree: Keypair,
168    pub nullifier_queue: Keypair,
169    pub governance_authority: Keypair,
170    pub forester: Keypair,
171    pub address_merkle_tree: Keypair,
172    pub address_merkle_tree_queue: Keypair,
173    pub cpi_context_account: Keypair,
174    pub system_program: Keypair,
175    pub registry_program: Keypair,
176}
177
178impl EnvAccountKeypairs {
179    pub fn program_test_default() -> EnvAccountKeypairs {
180        EnvAccountKeypairs {
181            state_merkle_tree: Keypair::from_bytes(&MERKLE_TREE_TEST_KEYPAIR).unwrap(),
182            nullifier_queue: Keypair::from_bytes(&NULLIFIER_QUEUE_TEST_KEYPAIR).unwrap(),
183            governance_authority: Keypair::from_bytes(&PAYER_KEYPAIR).unwrap(),
184            forester: Keypair::from_bytes(&FORESTER_TEST_KEYPAIR).unwrap(),
185            address_merkle_tree: Keypair::from_bytes(&ADDRESS_MERKLE_TREE_TEST_KEYPAIR).unwrap(),
186            address_merkle_tree_queue: Keypair::from_bytes(&ADDRESS_MERKLE_TREE_QUEUE_TEST_KEYPAIR)
187                .unwrap(),
188            cpi_context_account: Keypair::from_bytes(&SIGNATURE_CPI_TEST_KEYPAIR).unwrap(),
189            system_program: Keypair::from_bytes(&OLD_SYSTEM_PROGRAM_ID_TEST_KEYPAIR).unwrap(),
190            registry_program: Keypair::from_bytes(&OLD_REGISTRY_ID_TEST_KEYPAIR).unwrap(),
191        }
192    }
193
194    pub fn from_target_folder() -> EnvAccountKeypairs {
195        let prefix = String::from("../../../light-keypairs/");
196        let target_prefix = String::from("../../target/");
197        let state_merkle_tree = read_keypair_file(format!(
198            "{}smt1NamzXdq4AMqS2fS2F1i5KTYPZRhoHgWx38d8WsT.json",
199            prefix
200        ))
201        .unwrap();
202        let nullifier_queue = read_keypair_file(
203            "../../../light-keypairs/nfq1NvQDJ2GEgnS8zt9prAe8rjjpAW1zFkrvZoBR148.json",
204        )
205        .unwrap();
206        let governance_authority = read_keypair_file(format!(
207            "{}governance-authority-keypair.json",
208            target_prefix
209        ))
210        .unwrap();
211        let forester =
212            read_keypair_file(format!("{}forester-keypair.json", target_prefix)).unwrap();
213        let address_merkle_tree = read_keypair_file(format!(
214            "{}amt1Ayt45jfbdw5YSo7iz6WZxUmnZsQTYXy82hVwyC2.json",
215            prefix
216        ))
217        .unwrap();
218        let address_merkle_tree_queue = read_keypair_file(format!(
219            "{}aq1S9z4reTSQAdgWHGD2zDaS39sjGrAxbR31vxJ2F4F.json",
220            prefix
221        ))
222        .unwrap();
223        let cpi_context_account = read_keypair_file(format!(
224            "{}cpi1uHzrEhBG733DoEJNgHCyRS3XmmyVNZx5fonubE4.json",
225            prefix
226        ))
227        .unwrap();
228        let system_program = read_keypair_file(format!(
229            "{}SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7.json",
230            prefix
231        ))
232        .unwrap();
233        let registry_program = read_keypair_file(format!(
234            "{}Lighton6oQpVkeewmo2mcPTQQp7kYHr4fWpAgJyEmDX.json",
235            prefix
236        ))
237        .unwrap();
238        EnvAccountKeypairs {
239            state_merkle_tree,
240            nullifier_queue,
241            governance_authority,
242            forester,
243            address_merkle_tree,
244            address_merkle_tree_queue,
245            cpi_context_account,
246            system_program,
247            registry_program,
248        }
249    }
250}
251
252// Hardcoded keypairs for deterministic pubkeys for testing
253pub const MERKLE_TREE_TEST_KEYPAIR: [u8; 64] = [
254    146, 193, 80, 51, 114, 21, 221, 27, 228, 203, 43, 26, 211, 158, 183, 129, 254, 206, 249, 89,
255    121, 99, 123, 196, 106, 29, 91, 144, 50, 161, 42, 139, 68, 77, 125, 32, 76, 128, 61, 180, 1,
256    207, 69, 44, 121, 118, 153, 17, 179, 183, 115, 34, 163, 127, 102, 214, 1, 87, 175, 177, 95, 49,
257    65, 69,
258];
259pub const NULLIFIER_QUEUE_TEST_KEYPAIR: [u8; 64] = [
260    222, 130, 14, 179, 120, 234, 200, 231, 112, 214, 179, 171, 214, 95, 225, 61, 71, 61, 96, 214,
261    47, 253, 213, 178, 11, 77, 16, 2, 7, 24, 106, 218, 45, 107, 25, 100, 70, 71, 137, 47, 210, 248,
262    220, 223, 11, 204, 205, 89, 248, 48, 211, 168, 11, 25, 219, 158, 99, 47, 127, 248, 142, 107,
263    196, 110,
264];
265pub const PAYER_KEYPAIR: [u8; 64] = [
266    17, 34, 231, 31, 83, 147, 93, 173, 61, 164, 25, 0, 204, 82, 234, 91, 202, 187, 228, 110, 146,
267    97, 112, 131, 180, 164, 96, 220, 57, 207, 65, 107, 2, 99, 226, 251, 88, 66, 92, 33, 25, 216,
268    211, 185, 112, 203, 212, 238, 105, 144, 72, 121, 176, 253, 106, 168, 115, 158, 154, 188, 62,
269    255, 166, 81,
270];
271
272pub const ADDRESS_MERKLE_TREE_TEST_KEYPAIR: [u8; 64] = [
273    145, 184, 150, 187, 7, 48, 33, 191, 136, 115, 127, 243, 135, 119, 163, 99, 186, 21, 67, 161,
274    22, 211, 102, 149, 158, 51, 182, 231, 97, 28, 77, 118, 165, 62, 148, 222, 135, 123, 222, 189,
275    109, 46, 57, 112, 159, 209, 86, 59, 62, 139, 159, 208, 193, 206, 130, 48, 119, 195, 103, 235,
276    231, 94, 83, 227,
277];
278
279pub const ADDRESS_MERKLE_TREE_QUEUE_TEST_KEYPAIR: [u8; 64] = [
280    177, 80, 56, 144, 179, 178, 209, 143, 125, 134, 80, 75, 74, 156, 241, 156, 228, 50, 210, 35,
281    149, 0, 28, 198, 132, 157, 54, 197, 173, 200, 104, 156, 243, 76, 173, 207, 166, 74, 210, 59,
282    59, 211, 75, 180, 111, 40, 13, 151, 57, 237, 103, 145, 136, 105, 65, 143, 250, 50, 64, 94, 214,
283    184, 217, 99,
284];
285
286pub const SIGNATURE_CPI_TEST_KEYPAIR: [u8; 64] = [
287    189, 58, 29, 111, 77, 118, 218, 228, 64, 122, 227, 119, 148, 83, 245, 92, 107, 168, 153, 61,
288    221, 100, 243, 106, 228, 231, 147, 200, 195, 156, 14, 10, 162, 100, 133, 197, 231, 125, 178,
289    71, 33, 62, 223, 145, 136, 210, 160, 96, 75, 148, 143, 30, 41, 89, 205, 141, 248, 204, 48, 157,
290    195, 216, 81, 204,
291];
292
293pub const GROUP_PDA_SEED_TEST_KEYPAIR: [u8; 64] = [
294    97, 41, 77, 16, 152, 43, 140, 41, 11, 146, 82, 50, 38, 162, 216, 34, 95, 6, 237, 11, 74, 227,
295    221, 137, 26, 136, 52, 144, 74, 212, 215, 155, 216, 47, 98, 199, 9, 61, 213, 72, 205, 237, 76,
296    74, 119, 253, 96, 1, 140, 92, 149, 148, 250, 32, 53, 54, 186, 15, 48, 130, 222, 205, 3, 98,
297];
298// The test program id keypairs are necessary because the program id keypair needs to sign
299// to register the program to the security group.
300// The program ids should only be used for localnet testing.
301// Pubkey: H5sFv8VwWmjxHYS2GB4fTDsK7uTtnRT4WiixtHrET3bN
302pub const OLD_SYSTEM_PROGRAM_ID_TEST_KEYPAIR: [u8; 64] = [
303    10, 62, 81, 156, 201, 11, 242, 85, 89, 182, 145, 223, 214, 144, 53, 147, 242, 197, 41, 55, 203,
304    212, 70, 178, 225, 209, 4, 211, 43, 153, 222, 21, 238, 250, 35, 216, 163, 90, 82, 72, 167, 209,
305    196, 227, 210, 173, 89, 255, 142, 20, 199, 150, 144, 215, 61, 164, 34, 47, 181, 228, 226, 153,
306    208, 17,
307];
308// Pubkey: 7Z9Yuy3HkBCc2Wf3xzMGnz6qpV4n7ciwcoEMGKqhAnj1
309pub const OLD_REGISTRY_ID_TEST_KEYPAIR: [u8; 64] = [
310    43, 149, 192, 218, 153, 35, 206, 182, 230, 102, 193, 208, 163, 11, 195, 46, 228, 116, 113, 62,
311    161, 102, 207, 139, 128, 8, 120, 150, 30, 119, 150, 140, 97, 98, 96, 14, 138, 90, 82, 76, 254,
312    197, 232, 33, 204, 67, 237, 139, 100, 115, 187, 164, 115, 31, 164, 21, 246, 9, 162, 211, 227,
313    20, 96, 192,
314];
315
316pub const FORESTER_TEST_KEYPAIR: [u8; 64] = [
317    81, 4, 133, 152, 100, 67, 157, 52, 66, 70, 150, 214, 242, 90, 65, 199, 143, 192, 96, 172, 214,
318    44, 250, 77, 224, 55, 104, 35, 168, 1, 92, 200, 204, 184, 194, 21, 117, 231, 90, 62, 117, 179,
319    162, 181, 71, 36, 34, 47, 49, 195, 215, 90, 115, 3, 69, 74, 210, 75, 162, 191, 63, 51, 170,
320    204,
321];
322
323/// Setup test programs with accounts
324/// deploys:
325/// 1. light program
326/// 2. account_compression program
327/// 3. light_compressed_token program
328/// 4. light_system_program program
329///
330/// Sets up the following accounts:
331/// 5. creates and initializes governance authority
332/// 6. creates and initializes group authority
333/// 7. registers the light_system_program program with the group authority
334/// 8. initializes Merkle tree owned by
335/// Note:
336/// - registers a forester
337/// - advances to the active phase slot 2
338/// - active phase doesn't end
339// TODO(vadorovsky): Remove this function...
340pub async fn setup_test_programs_with_accounts(
341    additional_programs: Option<Vec<(String, Pubkey)>>,
342) -> (ProgramTestRpcConnection, EnvAccounts) {
343    setup_test_programs_with_accounts_with_protocol_config(
344        additional_programs,
345        ProtocolConfig {
346            // Init with an active epoch which doesn't end
347            active_phase_length: 1_000_000_000,
348            slot_length: 1_000_000_000 - 1,
349            genesis_slot: 0,
350            registration_phase_length: 2,
351            ..Default::default()
352        },
353        true,
354    )
355    .await
356}
357
358/// Setup test programs with accounts
359/// deploys:
360/// 1. light program
361/// 2. account_compression program
362/// 3. light_compressed_token program
363/// 4. light_system_program program
364///
365/// Sets up the following accounts:
366/// 5. creates and initializes governance authority
367/// 6. creates and initializes group authority
368/// 7. registers the light_system_program program with the group authority
369/// 8. initializes Merkle tree owned by
370/// Note:
371/// - registers a forester
372/// - advances to the active phase slot 2
373/// - active phase doesn't end
374// TODO(vadorovsky): ...in favor of this one.
375pub async fn setup_test_programs_with_accounts_v2(
376    additional_programs: Option<Vec<(String, Pubkey)>>,
377) -> (
378    light_client::rpc::test_rpc::ProgramTestRpcConnection,
379    EnvAccounts,
380) {
381    setup_test_programs_with_accounts_with_protocol_config_v2(
382        additional_programs,
383        ProtocolConfig {
384            // Init with an active epoch which doesn't end
385            active_phase_length: 1_000_000_000,
386            slot_length: 1_000_000_000 - 1,
387            genesis_slot: 0,
388            registration_phase_length: 2,
389            ..Default::default()
390        },
391        true,
392    )
393    .await
394}
395
396// TODO(vadorovsky): Remote this function...
397pub async fn setup_test_programs_with_accounts_with_protocol_config(
398    additional_programs: Option<Vec<(String, Pubkey)>>,
399    protocol_config: ProtocolConfig,
400    register_forester_and_advance_to_active_phase: bool,
401) -> (ProgramTestRpcConnection, EnvAccounts) {
402    let context = setup_test_programs(additional_programs).await;
403    let mut context = ProgramTestRpcConnection { context };
404    let keypairs = EnvAccountKeypairs::program_test_default();
405    airdrop_lamports(
406        &mut context,
407        &keypairs.governance_authority.pubkey(),
408        100_000_000_000,
409    )
410    .await
411    .unwrap();
412    airdrop_lamports(&mut context, &keypairs.forester.pubkey(), 10_000_000_000)
413        .await
414        .unwrap();
415    let env_accounts = initialize_accounts(
416        &mut context,
417        keypairs,
418        protocol_config,
419        register_forester_and_advance_to_active_phase,
420        true,
421    )
422    .await;
423    (context, env_accounts)
424}
425
426// TODO(vadorovsky): ...in favor of this one.
427pub async fn setup_test_programs_with_accounts_with_protocol_config_v2(
428    additional_programs: Option<Vec<(String, Pubkey)>>,
429    protocol_config: ProtocolConfig,
430    register_forester_and_advance_to_active_phase: bool,
431) -> (
432    light_client::rpc::test_rpc::ProgramTestRpcConnection,
433    EnvAccounts,
434) {
435    let context = setup_test_programs(additional_programs).await;
436    let mut context = light_client::rpc::test_rpc::ProgramTestRpcConnection { context };
437    let keypairs = EnvAccountKeypairs::program_test_default();
438    airdrop_lamports(
439        &mut context,
440        &keypairs.governance_authority.pubkey(),
441        100_000_000_000,
442    )
443    .await
444    .unwrap();
445    airdrop_lamports(&mut context, &keypairs.forester.pubkey(), 10_000_000_000)
446        .await
447        .unwrap();
448    let env_accounts = initialize_accounts(
449        &mut context,
450        keypairs,
451        protocol_config,
452        register_forester_and_advance_to_active_phase,
453        true,
454    )
455    .await;
456    (context, env_accounts)
457}
458
459pub async fn setup_accounts(keypairs: EnvAccountKeypairs, url: SolanaRpcUrl) -> EnvAccounts {
460    let mut rpc = SolanaRpcConnection::new(url, None);
461
462    initialize_accounts(&mut rpc, keypairs, ProtocolConfig::default(), false, false).await
463}
464
465pub async fn initialize_accounts<R: RpcConnection>(
466    context: &mut R,
467    keypairs: EnvAccountKeypairs,
468    protocol_config: ProtocolConfig,
469    register_forester_and_advance_to_active_phase: bool,
470    skip_register_programs: bool,
471) -> EnvAccounts {
472    let cpi_authority_pda = get_cpi_authority_pda();
473    let protocol_config_pda = get_protocol_config_pda_address();
474    let instruction = create_initialize_governance_authority_instruction(
475        keypairs.governance_authority.pubkey(),
476        keypairs.governance_authority.pubkey(),
477        protocol_config,
478    );
479    let update_instruction = create_update_protocol_config_instruction(
480        keypairs.governance_authority.pubkey(),
481        Some(keypairs.governance_authority.pubkey()),
482        None,
483    );
484    context
485        .create_and_send_transaction(
486            &[instruction, update_instruction],
487            &keypairs.governance_authority.pubkey(),
488            &[&keypairs.governance_authority],
489        )
490        .await
491        .unwrap();
492
493    let group_seed_keypair = Keypair::from_bytes(&GROUP_PDA_SEED_TEST_KEYPAIR).unwrap();
494    let group_pda = initialize_new_group(
495        &group_seed_keypair,
496        &keypairs.governance_authority,
497        context,
498        cpi_authority_pda.0,
499    )
500    .await;
501
502    let gov_authority = context
503        .get_anchor_account::<GroupAuthority>(&protocol_config_pda.0)
504        .await
505        .unwrap()
506        .unwrap();
507    assert_eq!(
508        gov_authority.authority,
509        keypairs.governance_authority.pubkey()
510    );
511
512    println!("forester: {:?}", keypairs.forester.pubkey());
513    register_test_forester(
514        context,
515        &keypairs.governance_authority,
516        &keypairs.forester.pubkey(),
517        ForesterConfig::default(),
518    )
519    .await
520    .unwrap();
521    println!("Registered register_test_forester ");
522
523    if !skip_register_programs {
524        register_program_with_registry_program(
525            context,
526            &keypairs.governance_authority,
527            &group_pda,
528            &keypairs.system_program,
529        )
530        .await
531        .unwrap();
532        register_program_with_registry_program(
533            context,
534            &keypairs.governance_authority,
535            &group_pda,
536            &keypairs.registry_program,
537        )
538        .await
539        .unwrap();
540    }
541    println!("Registered system program");
542    let merkle_tree_pubkey = keypairs.state_merkle_tree.pubkey();
543    let nullifier_queue_pubkey = keypairs.nullifier_queue.pubkey();
544    create_state_merkle_tree_and_queue_account(
545        &keypairs.governance_authority,
546        true,
547        context,
548        &keypairs.state_merkle_tree,
549        &keypairs.nullifier_queue,
550        Some(&keypairs.cpi_context_account),
551        None,
552        None,
553        1,
554        &StateMerkleTreeConfig::default(),
555        &NullifierQueueConfig::default(),
556    )
557    .await
558    .unwrap();
559
560    create_address_merkle_tree_and_queue_account(
561        &keypairs.governance_authority,
562        true,
563        context,
564        &keypairs.address_merkle_tree,
565        &keypairs.address_merkle_tree_queue,
566        None,
567        None,
568        &AddressMerkleTreeConfig::default(),
569        &AddressQueueConfig::default(),
570        0,
571    )
572    .await
573    .unwrap();
574
575    let registered_system_program_pda = get_registered_program_pda(&light_system_program::ID);
576    let registered_registry_program_pda = get_registered_program_pda(&light_registry::ID);
577    let forester_epoch = if register_forester_and_advance_to_active_phase {
578        let mut registered_epoch = Epoch::register(context, &protocol_config, &keypairs.forester)
579            .await
580            .unwrap()
581            .unwrap();
582        context
583            .warp_to_slot(registered_epoch.phases.active.start)
584            .await
585            .unwrap();
586        let tree_accounts = vec![
587            TreeAccounts {
588                tree_type: TreeType::State,
589                merkle_tree: merkle_tree_pubkey,
590                queue: nullifier_queue_pubkey,
591                is_rolledover: false,
592            },
593            TreeAccounts {
594                tree_type: TreeType::Address,
595                merkle_tree: keypairs.address_merkle_tree.pubkey(),
596                queue: keypairs.address_merkle_tree_queue.pubkey(),
597                is_rolledover: false,
598            },
599        ];
600
601        registered_epoch
602            .fetch_account_and_add_trees_with_schedule(context, &tree_accounts)
603            .await
604            .unwrap();
605        let ix = create_finalize_registration_instruction(&keypairs.forester.pubkey(), 0);
606        context
607            .create_and_send_transaction(&[ix], &keypairs.forester.pubkey(), &[&keypairs.forester])
608            .await
609            .unwrap();
610        Some(registered_epoch)
611    } else {
612        None
613    };
614    EnvAccounts {
615        merkle_tree_pubkey,
616        nullifier_queue_pubkey,
617        group_pda,
618        governance_authority: keypairs.governance_authority.insecure_clone(),
619        governance_authority_pda: protocol_config_pda.0,
620        forester: keypairs.forester.insecure_clone(),
621        registered_program_pda: registered_system_program_pda,
622        address_merkle_tree_pubkey: keypairs.address_merkle_tree.pubkey(),
623        address_merkle_tree_queue_pubkey: keypairs.address_merkle_tree_queue.pubkey(),
624        cpi_context_account_pubkey: keypairs.cpi_context_account.pubkey(),
625        registered_registry_program_pda,
626        registered_forester_pda: get_forester_pda(&keypairs.forester.pubkey()).0,
627        forester_epoch,
628    }
629}
630pub fn get_group_pda(seed: Pubkey) -> Pubkey {
631    Pubkey::find_program_address(
632        &[GROUP_AUTHORITY_SEED, seed.to_bytes().as_slice()],
633        &account_compression::ID,
634    )
635    .0
636}
637
638pub async fn initialize_new_group<R: RpcConnection>(
639    group_seed_keypair: &Keypair,
640    payer: &Keypair,
641    context: &mut R,
642    authority: Pubkey,
643) -> Pubkey {
644    let group_pda = Pubkey::find_program_address(
645        &[
646            GROUP_AUTHORITY_SEED,
647            group_seed_keypair.pubkey().to_bytes().as_slice(),
648        ],
649        &account_compression::ID,
650    )
651    .0;
652
653    let instruction = create_initialize_group_authority_instruction(
654        payer.pubkey(),
655        group_pda,
656        group_seed_keypair.pubkey(),
657        authority,
658    );
659
660    context
661        .create_and_send_transaction(
662            &[instruction],
663            &payer.pubkey(),
664            &[payer, group_seed_keypair],
665        )
666        .await
667        .unwrap();
668    let group_authority = context
669        .get_anchor_account::<GroupAuthority>(&group_pda)
670        .await
671        .unwrap()
672        .unwrap();
673    assert_eq!(group_authority.authority, authority);
674    assert_eq!(group_authority.seed, group_seed_keypair.pubkey());
675    group_pda
676}
677
678pub fn get_test_env_accounts() -> EnvAccounts {
679    let merkle_tree_keypair = Keypair::from_bytes(&MERKLE_TREE_TEST_KEYPAIR).unwrap();
680    let merkle_tree_pubkey = merkle_tree_keypair.pubkey();
681    let nullifier_queue_keypair = Keypair::from_bytes(&NULLIFIER_QUEUE_TEST_KEYPAIR).unwrap();
682    let nullifier_queue_pubkey = nullifier_queue_keypair.pubkey();
683    let group_seed_keypair = Keypair::from_bytes(&GROUP_PDA_SEED_TEST_KEYPAIR).unwrap();
684    let group_pda = get_group_pda(group_seed_keypair.pubkey());
685
686    let payer = Keypair::from_bytes(&PAYER_KEYPAIR).unwrap();
687    let protocol_config_pda = get_protocol_config_pda_address();
688    let (_, registered_program_pda) = create_register_program_instruction(
689        payer.pubkey(),
690        protocol_config_pda,
691        group_pda,
692        light_system_program::ID,
693    );
694
695    let address_merkle_tree_keypair =
696        Keypair::from_bytes(&ADDRESS_MERKLE_TREE_TEST_KEYPAIR).unwrap();
697
698    let address_merkle_tree_queue_keypair =
699        Keypair::from_bytes(&ADDRESS_MERKLE_TREE_QUEUE_TEST_KEYPAIR).unwrap();
700
701    let cpi_context_keypair = Keypair::from_bytes(&SIGNATURE_CPI_TEST_KEYPAIR).unwrap();
702    let registered_registry_program_pda = get_registered_program_pda(&light_registry::ID);
703    let forester = Keypair::from_bytes(&FORESTER_TEST_KEYPAIR).unwrap();
704    EnvAccounts {
705        merkle_tree_pubkey,
706        nullifier_queue_pubkey,
707        group_pda,
708        governance_authority: payer,
709        governance_authority_pda: protocol_config_pda.0,
710        registered_forester_pda: get_forester_pda(&forester.pubkey()).0,
711        forester,
712        registered_program_pda,
713        address_merkle_tree_pubkey: address_merkle_tree_keypair.pubkey(),
714        address_merkle_tree_queue_pubkey: address_merkle_tree_queue_keypair.pubkey(),
715        cpi_context_account_pubkey: cpi_context_keypair.pubkey(),
716        registered_registry_program_pda,
717        forester_epoch: None,
718    }
719}
720
721#[allow(clippy::too_many_arguments)]
722pub async fn create_state_merkle_tree_and_queue_account<R: RpcConnection>(
723    payer: &Keypair,
724    registry: bool,
725    rpc: &mut R,
726    merkle_tree_keypair: &Keypair,
727    nullifier_queue_keypair: &Keypair,
728    cpi_context_keypair: Option<&Keypair>,
729    program_owner: Option<Pubkey>,
730    forester: Option<Pubkey>,
731    index: u64,
732    merkle_tree_config: &StateMerkleTreeConfig,
733    queue_config: &NullifierQueueConfig,
734) -> Result<Signature, RpcError> {
735    use light_registry::account_compression_cpi::sdk::create_initialize_merkle_tree_instruction as create_initialize_merkle_tree_instruction_registry;
736    let size = account_compression::state::StateMerkleTreeAccount::size(
737        merkle_tree_config.height as usize,
738        merkle_tree_config.changelog_size as usize,
739        merkle_tree_config.roots_size as usize,
740        merkle_tree_config.canopy_depth as usize,
741    );
742
743    let merkle_tree_account_create_ix = create_account_instruction(
744        &payer.pubkey(),
745        size,
746        rpc.get_minimum_balance_for_rent_exemption(size)
747            .await
748            .unwrap(),
749        &account_compression::ID,
750        Some(merkle_tree_keypair),
751    );
752    let size =
753        account_compression::state::queue::QueueAccount::size(queue_config.capacity as usize)
754            .unwrap();
755    let nullifier_queue_account_create_ix = create_account_instruction(
756        &payer.pubkey(),
757        size,
758        rpc.get_minimum_balance_for_rent_exemption(size)
759            .await
760            .unwrap(),
761        &account_compression::ID,
762        Some(nullifier_queue_keypair),
763    );
764
765    let transaction = if registry {
766        let cpi_context_keypair = cpi_context_keypair.unwrap();
767        let rent_cpi_config = rpc
768            .get_minimum_balance_for_rent_exemption(
769                ProtocolConfig::default().cpi_context_size as usize,
770            )
771            .await
772            .unwrap();
773        let create_cpi_context_instruction = create_account_instruction(
774            &payer.pubkey(),
775            ProtocolConfig::default().cpi_context_size as usize,
776            rent_cpi_config,
777            &light_system_program::ID,
778            Some(cpi_context_keypair),
779        );
780
781        let instruction = create_initialize_merkle_tree_instruction_registry(
782            payer.pubkey(),
783            merkle_tree_keypair.pubkey(),
784            nullifier_queue_keypair.pubkey(),
785            cpi_context_keypair.pubkey(),
786            merkle_tree_config.clone(),
787            queue_config.clone(),
788            program_owner,
789            forester,
790        );
791        Transaction::new_signed_with_payer(
792            &[
793                create_cpi_context_instruction,
794                merkle_tree_account_create_ix,
795                nullifier_queue_account_create_ix,
796                instruction,
797            ],
798            Some(&payer.pubkey()),
799            &vec![
800                payer,
801                merkle_tree_keypair,
802                nullifier_queue_keypair,
803                cpi_context_keypair,
804            ],
805            rpc.get_latest_blockhash().await.unwrap(),
806        )
807    } else {
808        let instruction = create_initialize_merkle_tree_instruction(
809            payer.pubkey(),
810            None,
811            merkle_tree_keypair.pubkey(),
812            nullifier_queue_keypair.pubkey(),
813            merkle_tree_config.clone(),
814            queue_config.clone(),
815            program_owner,
816            forester,
817            index,
818        );
819        Transaction::new_signed_with_payer(
820            &[
821                merkle_tree_account_create_ix,
822                nullifier_queue_account_create_ix,
823                instruction,
824            ],
825            Some(&payer.pubkey()),
826            &vec![payer, merkle_tree_keypair, nullifier_queue_keypair],
827            rpc.get_latest_blockhash().await.unwrap(),
828        )
829    };
830
831    rpc.process_transaction(transaction.clone()).await
832}
833
834#[allow(clippy::too_many_arguments)]
835#[inline(never)]
836pub async fn create_address_merkle_tree_and_queue_account<R: RpcConnection>(
837    payer: &Keypair,
838    registry: bool,
839    context: &mut R,
840    address_merkle_tree_keypair: &Keypair,
841    address_queue_keypair: &Keypair,
842    program_owner: Option<Pubkey>,
843    forester: Option<Pubkey>,
844    merkle_tree_config: &AddressMerkleTreeConfig,
845    queue_config: &AddressQueueConfig,
846    index: u64,
847) -> Result<Signature, RpcError> {
848    use light_registry::account_compression_cpi::sdk::create_initialize_address_merkle_tree_and_queue_instruction as create_initialize_address_merkle_tree_and_queue_instruction_registry;
849
850    let size =
851        account_compression::state::QueueAccount::size(queue_config.capacity as usize).unwrap();
852    let account_create_ix = create_account_instruction(
853        &payer.pubkey(),
854        size,
855        context
856            .get_minimum_balance_for_rent_exemption(size)
857            .await
858            .unwrap(),
859        &account_compression::ID,
860        Some(address_queue_keypair),
861    );
862
863    let size = account_compression::state::AddressMerkleTreeAccount::size(
864        merkle_tree_config.height as usize,
865        merkle_tree_config.changelog_size as usize,
866        merkle_tree_config.roots_size as usize,
867        merkle_tree_config.canopy_depth as usize,
868        merkle_tree_config.address_changelog_size as usize,
869    );
870    let mt_account_create_ix = create_account_instruction(
871        &payer.pubkey(),
872        size,
873        context
874            .get_minimum_balance_for_rent_exemption(size)
875            .await
876            .unwrap(),
877        &account_compression::ID,
878        Some(address_merkle_tree_keypair),
879    );
880    let instruction = if registry {
881        create_initialize_address_merkle_tree_and_queue_instruction_registry(
882            payer.pubkey(),
883            forester,
884            program_owner,
885            address_merkle_tree_keypair.pubkey(),
886            address_queue_keypair.pubkey(),
887            merkle_tree_config.clone(),
888            queue_config.clone(),
889        )
890    } else {
891        create_initialize_address_merkle_tree_and_queue_instruction(
892            index,
893            payer.pubkey(),
894            None,
895            program_owner,
896            forester,
897            address_merkle_tree_keypair.pubkey(),
898            address_queue_keypair.pubkey(),
899            merkle_tree_config.clone(),
900            queue_config.clone(),
901        )
902    };
903    let transaction = Transaction::new_signed_with_payer(
904        &[account_create_ix, mt_account_create_ix, instruction],
905        Some(&payer.pubkey()),
906        &vec![&payer, &address_queue_keypair, &address_merkle_tree_keypair],
907        context.get_latest_blockhash().await.unwrap(),
908    );
909    let result = context.process_transaction(transaction.clone()).await;
910    #[allow(clippy::question_mark)]
911    if let Err(e) = result {
912        return Err(e);
913    }
914
915    // To initialize the indexed tree we do 4 operations:
916    // 1. insert 0 append 0 and update 0
917    // 2. insert 1 append BN254_FIELD_SIZE -1 and update 0
918    // we appended two values this the expected next index is 2;
919    // The right most leaf is the hash of the indexed array element with value FIELD_SIZE - 1
920    // index 1, next_index: 0
921    let expected_change_log_length = cmp::min(4, merkle_tree_config.changelog_size as usize);
922    let expected_roots_length = cmp::min(4, merkle_tree_config.roots_size as usize);
923    let expected_next_index = 2;
924    let expected_indexed_change_log_length =
925        cmp::min(4, merkle_tree_config.address_changelog_size as usize);
926    let mut reference_tree =
927        light_indexed_merkle_tree::reference::IndexedMerkleTree::<Poseidon, usize>::new(
928            account_compression::utils::constants::ADDRESS_MERKLE_TREE_HEIGHT as usize,
929            account_compression::utils::constants::ADDRESS_MERKLE_TREE_CANOPY_DEPTH as usize,
930        )
931        .unwrap();
932    reference_tree.init().unwrap();
933
934    let expected_right_most_leaf = reference_tree
935        .merkle_tree
936        .leaf(reference_tree.merkle_tree.rightmost_index - 1);
937
938    let _expected_right_most_leaf = [
939        30, 164, 22, 238, 180, 2, 24, 181, 64, 193, 207, 184, 219, 233, 31, 109, 84, 232, 162, 158,
940        220, 48, 163, 158, 50, 107, 64, 87, 167, 217, 99, 245,
941    ];
942    assert_eq!(expected_right_most_leaf, _expected_right_most_leaf);
943    let owner = if registry {
944        let registered_program = get_registered_program_pda(&light_registry::ID);
945        let registered_program_account = context
946            .get_anchor_account::<RegisteredProgram>(&registered_program)
947            .await
948            .unwrap()
949            .unwrap();
950        registered_program_account.group_authority_pda
951    } else {
952        payer.pubkey()
953    };
954    assert_address_merkle_tree_initialized(
955        context,
956        &address_merkle_tree_keypair.pubkey(),
957        &address_queue_keypair.pubkey(),
958        merkle_tree_config,
959        index,
960        program_owner,
961        forester,
962        expected_change_log_length,
963        expected_roots_length,
964        expected_next_index,
965        &expected_right_most_leaf,
966        &owner,
967        expected_indexed_change_log_length,
968    )
969    .await;
970
971    assert_address_queue_initialized(
972        context,
973        &address_queue_keypair.pubkey(),
974        queue_config,
975        &address_merkle_tree_keypair.pubkey(),
976        merkle_tree_config,
977        QueueType::AddressQueue,
978        index,
979        program_owner,
980        forester,
981        &owner,
982    )
983    .await;
984    result
985}
986
987pub async fn register_program_with_registry_program<R: RpcConnection>(
988    rpc: &mut R,
989    governance_authority: &Keypair,
990    group_pda: &Pubkey,
991    program_id_keypair: &Keypair,
992) -> Result<Pubkey, RpcError> {
993    let governance_authority_pda = get_protocol_config_pda_address();
994    let (instruction, token_program_registered_program_pda) = create_register_program_instruction(
995        governance_authority.pubkey(),
996        governance_authority_pda,
997        *group_pda,
998        program_id_keypair.pubkey(),
999    );
1000    let cpi_authority_pda = light_registry::utils::get_cpi_authority_pda();
1001    let transfer_instruction = system_instruction::transfer(
1002        &governance_authority.pubkey(),
1003        &cpi_authority_pda.0,
1004        rpc.get_minimum_balance_for_rent_exemption(RegisteredProgram::LEN)
1005            .await
1006            .unwrap(),
1007    );
1008
1009    rpc.create_and_send_transaction(
1010        &[transfer_instruction, instruction],
1011        &governance_authority.pubkey(),
1012        &[governance_authority, program_id_keypair],
1013    )
1014    .await?;
1015    Ok(token_program_registered_program_pda)
1016}
1017
1018pub async fn deregister_program_with_registry_program<R: RpcConnection>(
1019    rpc: &mut R,
1020    governance_authority: &Keypair,
1021    group_pda: &Pubkey,
1022    program_id_keypair: &Keypair,
1023) -> Result<Pubkey, light_client::rpc::errors::RpcError> {
1024    let governance_authority_pda = get_protocol_config_pda_address();
1025    let (instruction, token_program_registered_program_pda) = create_deregister_program_instruction(
1026        governance_authority.pubkey(),
1027        governance_authority_pda,
1028        *group_pda,
1029        program_id_keypair.pubkey(),
1030    );
1031    let cpi_authority_pda = light_registry::utils::get_cpi_authority_pda();
1032    let transfer_instruction = system_instruction::transfer(
1033        &governance_authority.pubkey(),
1034        &cpi_authority_pda.0,
1035        rpc.get_minimum_balance_for_rent_exemption(RegisteredProgram::LEN)
1036            .await
1037            .unwrap(),
1038    );
1039
1040    rpc.create_and_send_transaction(
1041        &[transfer_instruction, instruction],
1042        &governance_authority.pubkey(),
1043        &[governance_authority],
1044    )
1045    .await?;
1046    Ok(token_program_registered_program_pda)
1047}