Skip to content

Commit

Permalink
fix: spend program owned account with program keypair, create program…
Browse files Browse the repository at this point in the history
… owned account without data (#1029)
  • Loading branch information
ananas-block authored Jul 25, 2024
1 parent 1fc1a2f commit 203296b
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 4 deletions.
1 change: 1 addition & 0 deletions programs/system/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ pub enum SystemProgramError {
#[msg("Output merkle tree indices are not in ascending order.")]
OutputMerkleTreeIndicesNotInOrder,
OutputMerkleTreeNotUnique,
DataFieldUndefined,
}
12 changes: 9 additions & 3 deletions programs/system/src/invoke/verify_signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,19 @@ pub fn input_compressed_accounts_signer_check(
.iter()
.try_for_each(
|compressed_account_with_context: &PackedCompressedAccountWithMerkleContext| {
if compressed_account_with_context.compressed_account.owner == *authority {
if compressed_account_with_context.compressed_account.owner == *authority
&& compressed_account_with_context
.compressed_account
.data
.is_none()
{
Ok(())
} else {
msg!(
"signer check failed compressed account owner {} != authority {}",
"signer check failed compressed account owner {} != authority {} or data is not none {} (only programs can own compressed accounts with data)",
compressed_account_with_context.compressed_account.owner,
authority
authority,
compressed_account_with_context.compressed_account.data.is_none()
);
err!(SystemProgramError::SignerCheckFailed)
}
Expand Down
7 changes: 7 additions & 0 deletions programs/system/src/invoke_cpi/verify_signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ pub fn output_compressed_accounts_write_access_check(
msg!("compressed_account: {:?}", compressed_account);
return err!(SystemProgramError::WriteAccessCheckFailed);
}
if compressed_account.compressed_account.data.is_none()
&& compressed_account.compressed_account.owner == invoking_program_id.key()
{
msg!("For program owned compressed accounts the data field needs to be defined.");
msg!("compressed_account: {:?}", compressed_account);
return err!(SystemProgramError::DataFieldUndefined);
}
}
Ok(())
}
Expand Down
18 changes: 18 additions & 0 deletions test-programs/system-cpi-test/src/create_pda.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub enum CreatePdaMode {
InvalidSignerSeeds,
InvalidInvokingProgram,
WriteToAccountNotOwned,
NoData,
}

pub fn process_create_pda<'info>(
Expand Down Expand Up @@ -87,6 +88,17 @@ pub fn process_create_pda<'info>(
CreatePdaMode::WriteToAccountNotOwned,
)?;
}
CreatePdaMode::NoData => {
cpi_compressed_pda_transfer_as_program(
&ctx,
proof,
new_address_params,
compressed_pda,
cpi_context,
bump,
CreatePdaMode::NoData,
)?;
}
}
Ok(())
}
Expand Down Expand Up @@ -163,6 +175,12 @@ fn cpi_compressed_pda_transfer_as_program<'info>(
compressed_pda.compressed_account.owner = ctx.accounts.signer.key();
compressed_pda
}
CreatePdaMode::NoData => {
let mut compressed_pda = compressed_pda;

compressed_pda.compressed_account.data = None;
compressed_pda
}
_ => compressed_pda,
};

Expand Down
41 changes: 41 additions & 0 deletions test-programs/system-cpi-test/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use anchor_lang::AnchorDeserialize;
use light_compressed_token::process_transfer::InputTokenDataWithContext;
use light_compressed_token::token_data::AccountState;
use light_hasher::{Hasher, Poseidon};
use light_system_program::errors::SystemProgramError;
use light_system_program::sdk::address::derive_address;
use light_system_program::sdk::compressed_account::{
CompressedAccountWithMerkleContext, PackedCompressedAccountWithMerkleContext,
Expand All @@ -17,6 +18,7 @@ use light_test_utils::indexer::{Indexer, TestIndexer, TokenDataWithContext};
use light_test_utils::rpc::errors::{assert_rpc_error, RpcError};
use light_test_utils::rpc::rpc_connection::RpcConnection;
use light_test_utils::spl::{create_mint_helper, mint_tokens_helper};
use light_test_utils::system_program::transfer_compressed_sol_test;
use light_test_utils::test_env::{setup_test_programs_with_accounts, EnvAccounts};
use light_utils::hash_to_bn254_field_size_be;
use solana_sdk::signature::Keypair;
Expand Down Expand Up @@ -44,6 +46,8 @@ use system_cpi_test::{CreatePdaMode, ID};
/// 9. test signer checks trying to insert into cpi context account (invalid signer seeds)
/// 10. provide cpi context account but cpi context has a different fee payer (CpiContextFeePayerMismatch)
/// 11. write data to an account that it doesn't own (WriteAccessCheckFailed)
/// 12. Spend Program owned account with program keypair (SignerCheckFailed)
/// 13. Create program owned account without data (DataFieldUndefined)
#[tokio::test]
async fn only_test_create_pda() {
let (mut rpc, env) =
Expand Down Expand Up @@ -259,6 +263,43 @@ async fn only_test_create_pda() {
)
.await
.unwrap();

// Failing 12 Spend with program keypair
{
const CPI_SYSTEM_TEST_PROGRAM_ID_KEYPAIR: [u8; 64] = [
57, 80, 188, 3, 162, 80, 232, 181, 222, 192, 247, 98, 140, 227, 70, 15, 169, 202,
73, 184, 23, 90, 69, 95, 211, 74, 128, 232, 155, 216, 5, 230, 213, 158, 155, 203,
26, 211, 193, 195, 11, 219, 9, 155, 58, 172, 58, 200, 254, 75, 231, 106, 31, 168,
183, 76, 179, 113, 234, 101, 191, 99, 156, 98,
];
let compressed_account = test_indexer.get_compressed_accounts_by_owner(&ID)[0].clone();
let keypair = Keypair::from_bytes(&CPI_SYSTEM_TEST_PROGRAM_ID_KEYPAIR).unwrap();
let result = transfer_compressed_sol_test(
&mut rpc,
&mut test_indexer,
&keypair,
&[compressed_account],
&[Pubkey::new_unique()],
&[env.merkle_tree_pubkey],
None,
)
.await;
assert_rpc_error(result, 0, SystemProgramError::SignerCheckFailed.into()).unwrap();
}
// Failing 13 DataFieldUndefined ----------------------------------------------
perform_create_pda_failing(
&mut test_indexer,
&mut rpc,
&env,
&payer,
seed,
&data,
&ID,
CreatePdaMode::NoData,
light_system_program::errors::SystemProgramError::DataFieldUndefined.into(),
)
.await
.unwrap();
}
}

Expand Down
2 changes: 1 addition & 1 deletion test-programs/system-test/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ pub async fn failing_transaction_inputs_inner(
payer,
inputs_struct,
remaining_accounts.clone(),
VerifierError::ProofVerificationFailed.into(),
SystemProgramError::SignerCheckFailed.into(),
)
.await
.unwrap();
Expand Down

0 comments on commit 203296b

Please sign in to comment.