Add more duplicate account tests (#15746)

This commit is contained in:
Jack May 2021-03-05 20:36:27 -08:00 committed by GitHub
parent d09112fa6d
commit efcb58092e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 148 additions and 46 deletions

View File

@ -1,5 +1,5 @@
/** /**
* @brief Example C-based BPF program that exercises duplicate keyed ka * @brief Example C-based BPF program that exercises duplicate keyed accounts
* passed to it * passed to it
*/ */
#include <solana_sdk.h> #include <solana_sdk.h>
@ -9,46 +9,87 @@
*/ */
extern uint64_t entrypoint(const uint8_t *input) { extern uint64_t entrypoint(const uint8_t *input) {
SolAccountInfo ka[4]; SolAccountInfo accounts[5];
SolParameters params = (SolParameters) { .ka = ka }; SolParameters params = (SolParameters){.ka = accounts};
if (!sol_deserialize(input, &params, SOL_ARRAY_SIZE(ka))) { if (!sol_deserialize(input, &params, SOL_ARRAY_SIZE(accounts))) {
return ERROR_INVALID_ARGUMENT; return ERROR_INVALID_ARGUMENT;
} }
switch (params.data[0]) { switch (params.data[0]) {
case(1): case (1):
sol_log("modify first account data"); sol_log("modify first account data");
ka[2].data[0] = 1; accounts[2].data[0] = 1;
break; break;
case(2): case (2):
sol_log("modify first account data"); sol_log("modify first account data");
ka[3].data[0] = 2; accounts[3].data[0] = 2;
break; break;
case(3): case (3):
sol_log("modify both account data"); sol_log("modify both account data");
ka[2].data[0] += 1; accounts[2].data[0] += 1;
ka[3].data[0] += 2; accounts[3].data[0] += 2;
break; break;
case(4): case (4):
sol_log("modify first account lamports"); sol_log("modify first account lamports");
*ka[1].lamports -= 1; *accounts[1].lamports -= 1;
*ka[2].lamports += 1; *accounts[2].lamports += 1;
break; break;
case(5): case (5):
sol_log("modify first account lamports"); sol_log("modify first account lamports");
*ka[1].lamports -= 2; *accounts[1].lamports -= 2;
*ka[3].lamports += 2; *accounts[3].lamports += 2;
break; break;
case(6): case (6):
sol_log("modify both account lamports"); sol_log("modify both account lamports");
*ka[1].lamports -= 3; *accounts[1].lamports -= 3;
*ka[2].lamports += 1; *accounts[2].lamports += 1;
*ka[3].lamports += 2; *accounts[3].lamports += 2;
break; break;
default: case (7):
sol_log("Unrecognized command"); sol_log("check account (0,1,2,3) privs");
return ERROR_INVALID_INSTRUCTION_DATA; sol_assert(accounts[0].is_signer);
sol_assert(!accounts[1].is_signer);
sol_assert(accounts[2].is_signer);
sol_assert(accounts[3].is_signer);
sol_assert(accounts[0].is_writable);
sol_assert(accounts[1].is_writable);
sol_assert(accounts[2].is_writable);
sol_assert(accounts[3].is_writable);
if (params.ka_num > 4) {
{
SolAccountMeta arguments[] = {{accounts[0].key, true, true},
{accounts[1].key, true, false},
{accounts[2].key, true, false},
{accounts[3].key, false, true}};
uint8_t data[] = {7};
const SolInstruction instruction = {
(SolPubkey *)params.program_id, arguments,
SOL_ARRAY_SIZE(arguments), data, SOL_ARRAY_SIZE(data)};
sol_assert(SUCCESS ==
sol_invoke(&instruction, accounts, params.ka_num));
}
{
SolAccountMeta arguments[] = {{accounts[0].key, true, true},
{accounts[1].key, true, false},
{accounts[2].key, true, false},
{accounts[3].key, true, false}};
uint8_t data[] = {3};
const SolInstruction instruction = {
(SolPubkey *)params.program_id, arguments,
SOL_ARRAY_SIZE(arguments), data, SOL_ARRAY_SIZE(data)};
sol_assert(SUCCESS ==
sol_invoke(&instruction, accounts, params.ka_num));
}
sol_assert(accounts[2].data[0] == 3);
sol_assert(accounts[3].data[0] == 3);
}
break;
default:
sol_log("Unrecognized command");
return ERROR_INVALID_INSTRUCTION_DATA;
} }
return SUCCESS; return SUCCESS;
} }

View File

@ -2,46 +2,92 @@
extern crate solana_program; extern crate solana_program;
use solana_program::{ use solana_program::{
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, msg, account_info::AccountInfo,
program_error::ProgramError, pubkey::Pubkey, entrypoint,
entrypoint::ProgramResult,
instruction::{AccountMeta, Instruction},
msg,
program::invoke,
program_error::ProgramError,
pubkey::Pubkey,
}; };
entrypoint!(process_instruction); entrypoint!(process_instruction);
fn process_instruction( fn process_instruction(
_program_id: &Pubkey, program_id: &Pubkey,
accounts: &[AccountInfo], accounts: &[AccountInfo],
instruction_data: &[u8], instruction_data: &[u8],
) -> ProgramResult { ) -> ProgramResult {
match instruction_data[0] { match instruction_data[0] {
1 => { 1 => {
msg!("modify first account data"); msg!("modify account (2) data");
accounts[2].data.borrow_mut()[0] = 1; accounts[2].data.borrow_mut()[0] = 1;
} }
2 => { 2 => {
msg!("modify first account data"); msg!("modify account (3) data");
accounts[3].data.borrow_mut()[0] = 2; accounts[3].data.borrow_mut()[0] = 2;
} }
3 => { 3 => {
msg!("modify both account data"); msg!("modify account (2,3) data");
accounts[2].data.borrow_mut()[0] += 1; accounts[2].data.borrow_mut()[0] += 1;
accounts[3].data.borrow_mut()[0] += 2; accounts[3].data.borrow_mut()[0] += 2;
} }
4 => { 4 => {
msg!("modify first account lamports"); msg!("modify account (1,2) lamports");
**accounts[1].lamports.borrow_mut() -= 1; **accounts[1].lamports.borrow_mut() -= 1;
**accounts[2].lamports.borrow_mut() += 1; **accounts[2].lamports.borrow_mut() += 1;
} }
5 => { 5 => {
msg!("modify first account lamports"); msg!("modify account (1,3) lamports");
**accounts[1].lamports.borrow_mut() -= 2; **accounts[1].lamports.borrow_mut() -= 2;
**accounts[3].lamports.borrow_mut() += 2; **accounts[3].lamports.borrow_mut() += 2;
} }
6 => { 6 => {
msg!("modify both account lamports"); msg!("modify account (1,2,3) lamports");
**accounts[1].lamports.borrow_mut() -= 3; **accounts[1].lamports.borrow_mut() -= 3;
**accounts[2].lamports.borrow_mut() += 1; **accounts[2].lamports.borrow_mut() += 1;
**accounts[3].lamports.borrow_mut() += 2; **accounts[3].lamports.borrow_mut() += 2;
} }
7 => {
msg!("check account (0,1,2,3) privs");
assert!(accounts[0].is_signer);
assert!(!accounts[1].is_signer);
assert!(accounts[2].is_signer);
assert!(accounts[3].is_signer);
assert!(accounts[0].is_writable);
assert!(accounts[1].is_writable);
assert!(accounts[2].is_writable);
assert!(accounts[3].is_writable);
if accounts.len() > 4 {
let instruction = Instruction::new_with_bytes(
*program_id,
&[7],
vec![
AccountMeta::new(*accounts[0].key, true),
AccountMeta::new(*accounts[1].key, false),
AccountMeta::new(*accounts[2].key, false),
AccountMeta::new_readonly(*accounts[3].key, true),
],
);
invoke(&instruction, &accounts)?;
let instruction = Instruction::new_with_bytes(
*program_id,
&[3],
vec![
AccountMeta::new(*accounts[0].key, true),
AccountMeta::new(*accounts[1].key, false),
AccountMeta::new(*accounts[2].key, false),
AccountMeta::new(*accounts[3].key, false),
],
);
invoke(&instruction, &accounts)?;
assert_eq!(accounts[2].try_borrow_mut_data()?[0], 3);
assert_eq!(accounts[3].try_borrow_mut_data()?[0], 3);
}
}
_ => { _ => {
msg!("Unrecognized command"); msg!("Unrecognized command");
return Err(ProgramError::InvalidArgument); return Err(ProgramError::InvalidArgument);

View File

@ -547,8 +547,8 @@ fn test_program_bpf_duplicate_accounts() {
let payee_account = Account::new(10, 1, &program_id); let payee_account = Account::new(10, 1, &program_id);
let payee_pubkey = solana_sdk::pubkey::new_rand(); let payee_pubkey = solana_sdk::pubkey::new_rand();
bank.store_account(&payee_pubkey, &payee_account); bank.store_account(&payee_pubkey, &payee_account);
let account = Account::new(10, 1, &program_id); let account = Account::new(10, 1, &program_id);
let pubkey = solana_sdk::pubkey::new_rand(); let pubkey = solana_sdk::pubkey::new_rand();
let account_metas = vec![ let account_metas = vec![
AccountMeta::new(mint_keypair.pubkey(), true), AccountMeta::new(mint_keypair.pubkey(), true),
@ -598,6 +598,21 @@ fn test_program_bpf_duplicate_accounts() {
let lamports = bank_client.get_balance(&pubkey).unwrap(); let lamports = bank_client.get_balance(&pubkey).unwrap();
assert!(result.is_ok()); assert!(result.is_ok());
assert_eq!(lamports, 13); assert_eq!(lamports, 13);
let keypair = Keypair::new();
let pubkey = keypair.pubkey();
let account_metas = vec![
AccountMeta::new(mint_keypair.pubkey(), true),
AccountMeta::new(payee_pubkey, false),
AccountMeta::new(pubkey, false),
AccountMeta::new_readonly(pubkey, true),
AccountMeta::new_readonly(program_id, false),
];
bank.store_account(&pubkey, &account);
let instruction = Instruction::new_with_bytes(program_id, &[7], account_metas.clone());
let message = Message::new(&[instruction], Some(&mint_keypair.pubkey()));
let result = bank_client.send_and_confirm_message(&[&mint_keypair, &keypair], message);
assert!(result.is_ok());
} }
} }