Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions program/benches/compute_units.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,44 @@
#### Compute Units: 2024-11-01 15:31:11.543055 UTC

| Name | CUs | Delta |
|------|------|-------|
| config_small_init_0_keys | 580 | -4 |
| config_small_init_1_keys | 1211 | -4 |
| config_small_init_5_keys | 2830 | -4 |
| config_small_init_10_keys | 4900 | -4 |
| config_small_init_25_keys | 11742 | -4 |
| config_small_init_37_keys | 16745 | -4 |
| config_small_store_0_keys | 580 | -4 |
| config_small_store_1_keys | 1465 | -4 |
| config_small_store_5_keys | 4000 | -4 |
| config_small_store_10_keys | 7215 | -4 |
| config_small_store_25_keys | 17492 | -4 |
| config_small_store_37_keys | 25243 | -4 |
| config_medium_init_0_keys | 571 | -4 |
| config_medium_init_1_keys | 1158 | -4 |
| config_medium_init_5_keys | 2830 | -4 |
| config_medium_init_10_keys | 4900 | -4 |
| config_medium_init_25_keys | 11742 | -4 |
| config_medium_init_37_keys | 16745 | -4 |
| config_medium_store_0_keys | 571 | -4 |
| config_medium_store_1_keys | 1412 | -4 |
| config_medium_store_5_keys | 4000 | -4 |
| config_medium_store_10_keys | 7215 | -4 |
| config_medium_store_25_keys | 17492 | -4 |
| config_medium_store_37_keys | 25243 | -4 |
| config_large_init_0_keys | 692 | -4 |
| config_large_init_1_keys | 1279 | -4 |
| config_large_init_5_keys | 2951 | -4 |
| config_large_init_10_keys | 5022 | -4 |
| config_large_init_25_keys | 11866 | -4 |
| config_large_init_37_keys | 16870 | -4 |
| config_large_store_0_keys | 692 | -4 |
| config_large_store_1_keys | 1533 | -4 |
| config_large_store_5_keys | 4121 | -4 |
| config_large_store_10_keys | 7337 | -4 |
| config_large_store_25_keys | 17616 | -4 |
| config_large_store_37_keys | 25368 | -4 |

#### Compute Units: 2024-10-31 17:22:37.667457 UTC

| Name | CUs | Delta |
Expand Down
10 changes: 3 additions & 7 deletions program/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
use {
crate::state::ConfigKeys,
solana_program::{
account_info::{next_account_info, AccountInfo},
entrypoint::ProgramResult,
msg,
program_error::ProgramError,
account_info::AccountInfo, entrypoint::ProgramResult, msg, program_error::ProgramError,
pubkey::Pubkey,
},
std::collections::BTreeSet,
Expand Down Expand Up @@ -56,8 +53,7 @@ fn safe_deserialize_config_keys(input: &[u8]) -> Result<ConfigKeys, ProgramError
pub fn process(program_id: &Pubkey, accounts: &[AccountInfo], input: &[u8]) -> ProgramResult {
let key_list = safe_deserialize_config_keys(input)?;

let mut accounts_iter = accounts.iter();
let config_account = next_account_info(&mut accounts_iter)?;
let config_account = accounts.first().ok_or(ProgramError::NotEnoughAccountKeys)?;

if config_account.owner != program_id {
msg!("Config account is not owned by the config program");
Expand Down Expand Up @@ -89,7 +85,7 @@ pub fn process(program_id: &Pubkey, accounts: &[AccountInfo], input: &[u8]) -> P
for (signer, _) in key_list.keys.iter().filter(|(_, is_signer)| *is_signer) {
counter = counter.saturating_add(1);
if signer != config_account.key {
let signer_account = next_account_info(&mut accounts_iter).map_err(|_| {
let signer_account = accounts.get(counter).ok_or_else(|| {
msg!("account {:?} is not in account list", signer);
ProgramError::MissingRequiredSignature
})?;
Expand Down
88 changes: 77 additions & 11 deletions program/tests/functional.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ fn test_process_create_ok() {
&[(config, config_account)],
&[
Check::success(),
Check::compute_units(584),
Check::compute_units(580),
Check::account(&config)
.data(
&bincode::serialize(&(ConfigKeys { keys: vec![] }, MyConfig::default()))
Expand Down Expand Up @@ -111,7 +111,7 @@ fn test_process_store_ok() {
&[(config, config_account)],
&[
Check::success(),
Check::compute_units(584),
Check::compute_units(580),
Check::account(&config)
.data(&bincode::serialize(&(ConfigKeys { keys }, my_config)).unwrap())
.build(),
Expand Down Expand Up @@ -186,7 +186,7 @@ fn test_process_store_with_additional_signers() {
],
&[
Check::success(),
Check::compute_units(3_253),
Check::compute_units(3_234),
Check::account(&config)
.data(&bincode::serialize(&(ConfigKeys { keys }, my_config)).unwrap())
.build(),
Expand Down Expand Up @@ -262,6 +262,55 @@ fn test_process_store_with_bad_additional_signer() {
);
}

#[test]
fn test_store_requiring_config() {
let mollusk = setup();

let config = Pubkey::new_unique();

// New keys contains the config account, as well as another signer.
let signer = Pubkey::new_unique();
let new_keys = vec![(config, true), (signer, true)];
let my_config = MyConfig::new(42);

let config_account = {
// Allocate enough space for they `new_keys`, but leave the account
// uninitalized.
let space = get_config_space(new_keys.len());
let lamports = mollusk.sysvars.rent.minimum_balance(space);
AccountSharedData::new(lamports, space, &solana_config_program::id())
};

let mut instruction = config_instruction::store(&config, true, new_keys, &my_config);
mollusk.process_and_validate_instruction(
&instruction,
&[
(config, config_account.clone()),
(signer, AccountSharedData::default()),
],
&[Check::err(ProgramError::MissingRequiredSignature)],
);

// This is kind of strange, since the `store` helper was taken directly
// from the builtin crate, and it's designed to only add the config account
// once, even if it's a signer.
// However, if you include it in the instruction twice, the loop-counter
// mechanism of the processor actually works...
instruction.accounts = vec![
AccountMeta::new(config, true),
AccountMeta::new(config, true),
AccountMeta::new(signer, true),
];
mollusk.process_and_validate_instruction(
&instruction,
&[
(config, config_account),
(signer, AccountSharedData::default()),
],
&[Check::success()],
);
}

#[test]
fn test_config_updates() {
let mollusk = setup();
Expand All @@ -285,7 +334,7 @@ fn test_config_updates() {
(signer0, AccountSharedData::default()),
(signer1, AccountSharedData::default()),
],
&[Check::success(), Check::compute_units(3_253)],
&[Check::success(), Check::compute_units(3_234)],
);

// Use this for next invoke.
Expand All @@ -303,7 +352,7 @@ fn test_config_updates() {
],
&[
Check::success(),
Check::compute_units(3_254),
Check::compute_units(3_235),
Check::account(&config)
.data(&bincode::serialize(&(ConfigKeys { keys }, new_config)).unwrap())
.build(),
Expand All @@ -314,6 +363,22 @@ fn test_config_updates() {
let updated_config_account = result.get_account(&config).unwrap();

// Attempt update with incomplete signatures.
let keys = vec![
(pubkey, false),
(signer1, true), // Missing signer0.
];
let instruction = config_instruction::store(&config, false, keys, &my_config);
mollusk.process_and_validate_instruction(
&instruction,
&[
(config, updated_config_account.clone()),
// Missing signer0.
(signer1, AccountSharedData::default()),
],
&[Check::err(ProgramError::MissingRequiredSignature)],
);

// Do it again, this time missing signer1.
let keys = vec![
(pubkey, false),
(signer0, true), // Missing signer1.
Expand All @@ -323,7 +388,8 @@ fn test_config_updates() {
&instruction,
&[
(config, updated_config_account.clone()),
(signer0, AccountSharedData::default()), // Missing signer1.
(signer0, AccountSharedData::default()),
// Missing signer1.
],
&[Check::err(ProgramError::MissingRequiredSignature)],
);
Expand Down Expand Up @@ -399,7 +465,7 @@ fn test_config_update_contains_duplicates_fails() {
(signer0, AccountSharedData::default()),
(signer1, AccountSharedData::default()),
],
&[Check::success(), Check::compute_units(3_253)],
&[Check::success(), Check::compute_units(3_234)],
);

// Attempt update with duplicate signer inputs.
Expand Down Expand Up @@ -443,7 +509,7 @@ fn test_config_updates_requiring_config() {
],
&[
Check::success(),
Check::compute_units(3_352),
Check::compute_units(3_330),
Check::account(&config)
.data(&bincode::serialize(&(ConfigKeys { keys: keys.clone() }, my_config)).unwrap())
.build(),
Expand All @@ -464,7 +530,7 @@ fn test_config_updates_requiring_config() {
],
&[
Check::success(),
Check::compute_units(3_352),
Check::compute_units(3_330),
Check::account(&config)
.data(&bincode::serialize(&(ConfigKeys { keys }, new_config)).unwrap())
.build(),
Expand Down Expand Up @@ -558,7 +624,7 @@ fn test_maximum_keys_input() {
let result = mollusk.process_and_validate_instruction(
&instruction,
&[(config, config_account)],
&[Check::success(), Check::compute_units(25_247)],
&[Check::success(), Check::compute_units(25_243)],
);

// Use this for next invoke.
Expand All @@ -571,7 +637,7 @@ fn test_maximum_keys_input() {
let result = mollusk.process_and_validate_instruction(
&instruction,
&[(config, updated_config_account)],
&[Check::success(), Check::compute_units(25_247)],
&[Check::success(), Check::compute_units(25_243)],
);

// Use this for next invoke.
Expand Down