Skip to content

Commit afc0029

Browse files
authored
perf: extend registered program pda account (#1698)
* perf: replaced signer derivation check with comparison * feat: add resize instruction with tests * regenerated accounts
1 parent 5bc59f6 commit afc0029

File tree

14 files changed

+342
-39
lines changed

14 files changed

+342
-39
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"pubkey":"35hkDgaAKwMCaxRz2ocSZ6NaUrtKkyNqU6c4RV3tYJRh","account":{"lamports":1392000,"data":["H/u06wN0MgQGp1X4ITkFTUQksVrwxDDPL0t/mHk62hJS1I82ZsbLzg/Y1EfToz5VLJjxHxd2rjLiDsKHFAg5RA9dMMbnV0jY","base64"],"owner":"compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq","executable":false,"rentEpoch":18446744073709551615,"space":72}}
1+
{"pubkey":"35hkDgaAKwMCaxRz2ocSZ6NaUrtKkyNqU6c4RV3tYJRh","account":{"lamports":1614720,"data":["H/u06wN0MgQGp1X4ITkFTUQksVrwxDDPL0t/mHk62hJS1I82ZsbLzg/Y1EfToz5VLJjxHxd2rjLiDsKHFAg5RA9dMMbnV0jY+7ModRBcroW1tER2B+2/4UUnv7QjkRykBCO/0VJ6JnU=","base64"],"owner":"compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq","executable":false,"rentEpoch":18446744073709551615,"space":104}}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"pubkey":"DumMsyvkaGJG4QnQ1BhTgvoRMXsgGxfpKDUCr22Xqu4w","account":{"lamports":1392000,"data":["H/u06wN0MgQFDSsTeVE2hc8C8rX9UpG9lZsrBgqlJepbNIE7Hbm3bg/Y1EfToz5VLJjxHxd2rjLiDsKHFAg5RA9dMMbnV0jY","base64"],"owner":"compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq","executable":false,"rentEpoch":18446744073709551615,"space":72}}
1+
{"pubkey":"DumMsyvkaGJG4QnQ1BhTgvoRMXsgGxfpKDUCr22Xqu4w","account":{"lamports":1614720,"data":["H/u06wN0MgQFDSsTeVE2hc8C8rX9UpG9lZsrBgqlJepbNIE7Hbm3bg/Y1EfToz5VLJjxHxd2rjLiDsKHFAg5RA9dMMbnV0jYEKZefdY5BPg4OtA83uB4uRTYcxiAOxU1gHDXkuBc/ec=","base64"],"owner":"compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq","executable":false,"rentEpoch":18446744073709551615,"space":104}}

program-tests/account-compression-test/tests/group_authority_tests.rs

Lines changed: 167 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
use std::str::FromStr;
44

55
use account_compression::{
6-
self, errors::AccountCompressionErrorCode, utils::constants::GROUP_AUTHORITY_SEED,
7-
GroupAuthority, RegisteredProgram, ID,
6+
self,
7+
errors::AccountCompressionErrorCode,
8+
utils::constants::{CPI_AUTHORITY_PDA_SEED, GROUP_AUTHORITY_SEED},
9+
GroupAuthority, RegisteredProgram, RegisteredProgramV1, ID,
810
};
9-
use anchor_lang::{system_program, InstructionData, ToAccountMetas};
11+
use anchor_lang::{system_program, AnchorDeserialize, InstructionData, ToAccountMetas};
1012
use light_program_test::{
13+
env_accounts_v1::get_registered_program_pda,
1114
test_env::{get_group_pda, OLD_SYSTEM_PROGRAM_ID_TEST_KEYPAIR},
1215
test_rpc::ProgramTestRpcConnection,
1316
};
@@ -331,3 +334,164 @@ async fn test_create_and_update_group() {
331334
assert_eq!(recipient_balance, rent_exemption);
332335
}
333336
}
337+
338+
#[tokio::test]
339+
async fn test_resize_registered_program_pda() {
340+
let mut program_test = ProgramTest::default();
341+
program_test.add_program("account_compression", ID, None);
342+
let system_program_id =
343+
Pubkey::from_str("SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7").unwrap();
344+
let registered_program = Pubkey::find_program_address(
345+
&[system_program_id.to_bytes().as_slice()],
346+
&account_compression::ID,
347+
)
348+
.0;
349+
program_test.add_account(registered_program, get_registered_program_pda());
350+
program_test.set_compute_max_units(1_400_000u64);
351+
let context = program_test.start_with_context().await;
352+
let mut context = ProgramTestRpcConnection::new(context);
353+
let payer = context.get_payer().insecure_clone();
354+
355+
let instruction_data = account_compression::instruction::ResizeRegisteredProgramPda {};
356+
let accounts = account_compression::accounts::ResizeRegisteredProgramPda {
357+
authority: context.get_payer().pubkey(),
358+
registered_program_pda: registered_program,
359+
system_program: Pubkey::default(),
360+
};
361+
let instruction = Instruction {
362+
program_id: account_compression::ID,
363+
accounts: accounts.to_account_metas(Some(true)),
364+
data: instruction_data.data(),
365+
};
366+
// Resize
367+
{
368+
let pre_account = context
369+
.get_account(registered_program)
370+
.await
371+
.unwrap()
372+
.unwrap();
373+
assert_eq!(pre_account.data.len(), RegisteredProgramV1::LEN);
374+
let account_data = RegisteredProgramV1::deserialize(&mut &pre_account.data[8..]).unwrap();
375+
println!("account_data: {:?}", account_data);
376+
let mut transaction =
377+
Transaction::new_with_payer(&[instruction.clone()], Some(&payer.pubkey()));
378+
let recent_blockhash = context.get_latest_blockhash().await.unwrap();
379+
transaction.sign(&[&payer], recent_blockhash);
380+
context.process_transaction(transaction).await.unwrap();
381+
382+
let account = context
383+
.get_account(registered_program)
384+
.await
385+
.unwrap()
386+
.unwrap();
387+
assert_eq!(account.data.len(), RegisteredProgram::LEN);
388+
let expected_registered_program = RegisteredProgram {
389+
registered_program_id: system_program_id,
390+
group_authority_pda: account_data.group_authority_pda,
391+
registered_program_signer_pda: Pubkey::find_program_address(
392+
&[CPI_AUTHORITY_PDA_SEED],
393+
&system_program_id,
394+
)
395+
.0,
396+
};
397+
let account_des = RegisteredProgram::deserialize(&mut &account.data[8..]).unwrap();
398+
assert_eq!(expected_registered_program, account_des);
399+
}
400+
// Resize again should fail.
401+
{
402+
let mut transaction =
403+
Transaction::new_with_payer(&[instruction.clone()], Some(&payer.pubkey()));
404+
let recent_blockhash = context.get_latest_blockhash().await.unwrap();
405+
transaction.sign(&[&payer], recent_blockhash);
406+
let result = context.process_transaction(transaction).await;
407+
assert_rpc_error(
408+
result,
409+
0,
410+
anchor_lang::error::ErrorCode::ConstraintRaw.into(),
411+
)
412+
.unwrap();
413+
}
414+
415+
// Invalid program owner.
416+
{
417+
let mut account = get_registered_program_pda();
418+
account.owner = Pubkey::new_unique();
419+
let mut program_test = ProgramTest::default();
420+
program_test.add_program("account_compression", ID, None);
421+
let system_program_id =
422+
Pubkey::from_str("SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7").unwrap();
423+
let registered_program = Pubkey::find_program_address(
424+
&[system_program_id.to_bytes().as_slice()],
425+
&account_compression::ID,
426+
)
427+
.0;
428+
program_test.add_account(registered_program, account);
429+
program_test.set_compute_max_units(1_400_000u64);
430+
let context = program_test.start_with_context().await;
431+
let mut context = ProgramTestRpcConnection::new(context);
432+
let payer = context.get_payer().insecure_clone();
433+
434+
let instruction_data = account_compression::instruction::ResizeRegisteredProgramPda {};
435+
let accounts = account_compression::accounts::ResizeRegisteredProgramPda {
436+
authority: context.get_payer().pubkey(),
437+
registered_program_pda: registered_program,
438+
system_program: Pubkey::default(),
439+
};
440+
let instruction = Instruction {
441+
program_id: account_compression::ID,
442+
accounts: accounts.to_account_metas(Some(true)),
443+
data: instruction_data.data(),
444+
};
445+
let mut transaction =
446+
Transaction::new_with_payer(&[instruction.clone()], Some(&payer.pubkey()));
447+
let recent_blockhash = context.get_latest_blockhash().await.unwrap();
448+
transaction.sign(&[&payer], recent_blockhash);
449+
let result = context.process_transaction(transaction).await;
450+
assert_rpc_error(
451+
result,
452+
0,
453+
light_account_checks::error::AccountError::AccountOwnedByWrongProgram.into(),
454+
)
455+
.unwrap();
456+
}
457+
// Invalid account discriminator.
458+
{
459+
let mut account = get_registered_program_pda();
460+
account.data[0..8].copy_from_slice(&[1u8; 8]);
461+
let mut program_test = ProgramTest::default();
462+
program_test.add_program("account_compression", ID, None);
463+
let system_program_id =
464+
Pubkey::from_str("SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7").unwrap();
465+
let registered_program = Pubkey::find_program_address(
466+
&[system_program_id.to_bytes().as_slice()],
467+
&account_compression::ID,
468+
)
469+
.0;
470+
program_test.add_account(registered_program, account);
471+
program_test.set_compute_max_units(1_400_000u64);
472+
let context = program_test.start_with_context().await;
473+
let mut context = ProgramTestRpcConnection::new(context);
474+
let payer = context.get_payer().insecure_clone();
475+
let instruction_data = account_compression::instruction::ResizeRegisteredProgramPda {};
476+
let accounts = account_compression::accounts::ResizeRegisteredProgramPda {
477+
authority: context.get_payer().pubkey(),
478+
registered_program_pda: registered_program,
479+
system_program: Pubkey::default(),
480+
};
481+
let instruction = Instruction {
482+
program_id: account_compression::ID,
483+
accounts: accounts.to_account_metas(Some(true)),
484+
data: instruction_data.data(),
485+
};
486+
let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
487+
let recent_blockhash = context.get_latest_blockhash().await.unwrap();
488+
transaction.sign(&[&payer], recent_blockhash);
489+
let result = context.process_transaction(transaction).await;
490+
assert_rpc_error(
491+
result,
492+
0,
493+
anchor_lang::error::ErrorCode::AccountDiscriminatorMismatch.into(),
494+
)
495+
.unwrap();
496+
}
497+
}

program-tests/sdk-anchor-test/programs/sdk-anchor-test/tests/test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// #![cfg(feature = "test-sbf")]
1+
#![cfg(feature = "test-sbf")]
22

33
use anchor_lang::{AnchorDeserialize, InstructionData, ToAccountMetas};
44
use light_client::{

program-tests/system-cpi-test/tests/test_program_owned_trees.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -359,8 +359,7 @@ async fn test_invalid_registered_program() {
359359
let result = rpc
360360
.create_and_send_transaction(&[instruction], &payer.pubkey(), &[&payer])
361361
.await;
362-
let expected_error_code =
363-
account_compression::errors::AccountCompressionErrorCode::InvalidAuthority.into();
362+
let expected_error_code = light_account_checks::error::AccountError::InvalidSigner.into();
364363

365364
assert_rpc_error(result, 0, expected_error_code).unwrap();
366365
}
@@ -619,8 +618,7 @@ async fn test_invalid_registered_program() {
619618
let result = rpc
620619
.create_and_send_transaction(&[instruction], &payer.pubkey(), &[&payer])
621620
.await;
622-
let expected_error_code =
623-
account_compression::errors::AccountCompressionErrorCode::InvalidAuthority.into();
621+
let expected_error_code = light_account_checks::error::AccountError::InvalidSigner.into();
624622

625623
assert_rpc_error(result, 0, expected_error_code).unwrap();
626624
}
@@ -655,8 +653,7 @@ async fn test_invalid_registered_program() {
655653
let result = rpc
656654
.create_and_send_transaction(&[instruction], &payer.pubkey(), &[&payer])
657655
.await;
658-
let expected_error_code =
659-
account_compression::errors::AccountCompressionErrorCode::InvalidAuthority.into();
656+
let expected_error_code = light_account_checks::error::AccountError::InvalidSigner.into();
660657

661658
assert_rpc_error(result, 0, expected_error_code).unwrap();
662659
}

programs/account-compression/src/context.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,8 @@ use crate::{
1616
address_merkle_tree_from_bytes_zero_copy_mut,
1717
errors::AccountCompressionErrorCode,
1818
state_merkle_tree_from_bytes_zero_copy_mut,
19-
utils::{
20-
check_signer_is_registered_or_authority::{
21-
manual_check_signer_is_registered_or_authority, GroupAccess,
22-
},
23-
constants::CPI_AUTHORITY_PDA_SEED,
19+
utils::check_signer_is_registered_or_authority::{
20+
manual_check_signer_is_registered_or_authority, GroupAccess,
2421
},
2522
AddressMerkleTreeAccount, QueueAccount, StateMerkleTreeAccount,
2623
};
@@ -68,7 +65,8 @@ impl<'a, 'info> AcpAccount<'a, 'info> {
6865
account_infos: &'info [AccountInfo<'info>],
6966
authority: &'a AccountInfo<'info>,
7067
invoked_by_program: bool,
71-
bump: u8,
68+
// TODO: remove in separate pr because it impacts photon derivation.
69+
_bump: u8,
7270
) -> std::result::Result<Vec<AcpAccount<'a, 'info>>, ProgramError> {
7371
let mut vec = Vec::with_capacity(account_infos.len());
7472
let mut skip = 0;
@@ -83,14 +81,15 @@ impl<'a, 'info> AcpAccount<'a, 'info> {
8381
return Err(AccountError::AccountOwnedByWrongProgram.into());
8482
}
8583
let account = bytemuck::from_bytes::<RegisteredProgram>(&data[8..]);
86-
// 1,670 CU
87-
// TODO: get from RegisteredProgram account and compare
88-
let derived_address = Pubkey::create_program_address(
89-
&[CPI_AUTHORITY_PDA_SEED, &[bump]],
90-
&account.registered_program_id,
91-
)?;
84+
85+
if account.registered_program_signer_pda != *authority.key {
86+
return Err(AccountError::InvalidSigner.into());
87+
}
9288
skip += 1;
93-
Some((derived_address, account.group_authority_pda))
89+
Some((
90+
account.registered_program_signer_pda,
91+
account.group_authority_pda,
92+
))
9493
}
9594
false => None,
9695
};

programs/account-compression/src/instructions/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,6 @@ pub mod insert_into_queues;
5656

5757
pub mod generic;
5858
pub use generic::*;
59+
60+
pub mod resize_registered_program_account;
61+
pub use resize_registered_program_account::*;

programs/account-compression/src/instructions/register_program.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@ use aligned_sized::aligned_sized;
22
use anchor_lang::prelude::*;
33
use bytemuck::{Pod, Zeroable};
44

5-
use crate::{errors::AccountCompressionErrorCode, GroupAuthority};
5+
use crate::{
6+
errors::AccountCompressionErrorCode, utils::constants::CPI_AUTHORITY_PDA_SEED, GroupAuthority,
7+
};
68

79
#[repr(C)]
8-
#[derive(Debug, Pod, Zeroable, Copy)]
10+
#[derive(Debug, Pod, Zeroable, Copy, PartialEq)]
911
#[account]
1012
#[aligned_sized(anchor)]
1113
pub struct RegisteredProgram {
1214
pub registered_program_id: Pubkey,
1315
pub group_authority_pda: Pubkey,
16+
pub registered_program_signer_pda: Pubkey,
1417
}
1518

1619
#[derive(Accounts)]
@@ -37,5 +40,12 @@ pub fn process_register_program(ctx: Context<RegisterProgramToGroup>) -> Result<
3740
ctx.accounts.program_to_be_registered.key();
3841
ctx.accounts.registered_program_pda.group_authority_pda =
3942
ctx.accounts.group_authority_pda.key();
43+
ctx.accounts
44+
.registered_program_pda
45+
.registered_program_signer_pda = Pubkey::find_program_address(
46+
&[CPI_AUTHORITY_PDA_SEED],
47+
&ctx.accounts.program_to_be_registered.key(),
48+
)
49+
.0;
4050
Ok(())
4151
}

0 commit comments

Comments
 (0)