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; pub const NOOP_PROGRAM_ID: Pubkey = pubkey!("noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV");
43
44pub 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 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 #[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 let light_path = String::from_utf8_lossy(&output.stdout).trim().to_string();
99 let mut light_bin_path = PathBuf::from(light_path);
101 light_bin_path.pop(); 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, }
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
252pub 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];
298pub 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];
308pub 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
323pub 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 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
358pub 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 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
396pub 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
426pub 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 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>(®istered_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}