programs/config: Disallow duplicate signers

This commit is contained in:
Trent Nelson 2021-06-03 11:36:39 -06:00 committed by Trent Nelson
parent 2fe211c5e0
commit e0d679b319
2 changed files with 105 additions and 0 deletions

View File

@ -11,6 +11,7 @@ use solana_sdk::{
program_utils::limited_deserialize,
pubkey::Pubkey,
};
use std::collections::BTreeSet;
pub fn process_instruction(
_program_id: &Pubkey,
@ -101,6 +102,15 @@ pub fn process_instruction(
}
}
if invoke_context.is_feature_active(&feature_set::dedupe_config_program_signers::id()) {
let total_new_keys = key_list.keys.len();
let unique_new_keys = key_list.keys.into_iter().collect::<BTreeSet<_>>();
if unique_new_keys.len() != total_new_keys {
ic_msg!(invoke_context, "new config contains duplicate keys");
return Err(InstructionError::InvalidArgument);
}
}
// Check for Config data signers not present in incoming account update
if current_signer_keys.len() > counter {
ic_msg!(
@ -493,6 +503,96 @@ mod tests {
);
}
#[test]
fn test_config_initialize_contains_duplicates_fails() {
solana_logger::setup();
let config_address = Pubkey::new_unique();
let signer0_pubkey = Pubkey::new_unique();
let signer0_account = RefCell::new(AccountSharedData::default());
let keys = vec![
(config_address, false),
(signer0_pubkey, true),
(signer0_pubkey, true),
];
let (config_keypair, config_account) = create_config_account(keys.clone());
let config_pubkey = config_keypair.pubkey();
let my_config = MyConfig::new(42);
// Attempt initialization with duplicate signer inputs
let instruction = config_instruction::store(&config_pubkey, true, keys, &my_config);
let accounts = vec![
(true, false, &config_pubkey, &config_account),
(true, false, &signer0_pubkey, &signer0_account),
(true, false, &signer0_pubkey, &signer0_account),
];
let keyed_accounts = create_keyed_accounts_unified(&accounts);
assert_eq!(
process_instruction(
&id(),
&instruction.data,
&mut MockInvokeContext::new(keyed_accounts)
),
Err(InstructionError::InvalidArgument),
);
}
#[test]
fn test_config_update_contains_duplicates_fails() {
solana_logger::setup();
let config_address = Pubkey::new_unique();
let signer0_pubkey = Pubkey::new_unique();
let signer1_pubkey = Pubkey::new_unique();
let signer0_account = RefCell::new(AccountSharedData::default());
let signer1_account = RefCell::new(AccountSharedData::default());
let keys = vec![
(config_address, false),
(signer0_pubkey, true),
(signer1_pubkey, true),
];
let (config_keypair, config_account) = create_config_account(keys.clone());
let config_pubkey = config_keypair.pubkey();
let my_config = MyConfig::new(42);
let instruction = config_instruction::store(&config_pubkey, true, keys, &my_config);
let accounts = vec![
(true, false, &config_pubkey, &config_account),
(true, false, &signer0_pubkey, &signer0_account),
(true, false, &signer1_pubkey, &signer1_account),
];
let keyed_accounts = create_keyed_accounts_unified(&accounts);
assert_eq!(
process_instruction(
&id(),
&instruction.data,
&mut MockInvokeContext::new(keyed_accounts)
),
Ok(()),
);
// Attempt update with duplicate signer inputs
let new_config = MyConfig::new(84);
let dupe_keys = vec![
(config_address, false),
(signer0_pubkey, true),
(signer0_pubkey, true),
];
let instruction = config_instruction::store(&config_pubkey, false, dupe_keys, &new_config);
let accounts = vec![
(false, false, &config_pubkey, &config_account),
(true, false, &signer0_pubkey, &signer0_account),
(true, false, &signer0_pubkey, &signer0_account),
];
let keyed_accounts = create_keyed_accounts_unified(&accounts);
assert_eq!(
process_instruction(
&id(),
&instruction.data,
&mut MockInvokeContext::new(keyed_accounts)
),
Err(InstructionError::InvalidArgument),
);
}
#[test]
fn test_config_updates_requiring_config() {
solana_logger::setup();

View File

@ -151,6 +151,10 @@ pub mod blake3_syscall_enabled {
solana_sdk::declare_id!("HTW2pSyErTj4BV6KBM9NZ9VBUJVxt7sacNWcf76wtzb3");
}
pub mod dedupe_config_program_signers {
solana_sdk::declare_id!("8kEuAshXLsgkUEdcFVLqrjCGGHVWFW99ZZpxvAzzMtBp");
}
lazy_static! {
/// Map of feature identifiers to user-visible description
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
@ -189,6 +193,7 @@ lazy_static! {
(add_missing_program_error_mappings::id(), "add missing program error mappings"),
(system_transfer_zero_check::id(), "perform all checks for transfers of 0 lamports"),
(blake3_syscall_enabled::id(), "blake3 syscall"),
(dedupe_config_program_signers::id(), "dedupe config program signers"),
/*************** ADD NEW FEATURES HERE ***************/
]
.iter()