programs/config: Disallow duplicate signers

This commit is contained in:
Trent Nelson
2021-06-03 11:36:39 -06:00
parent 86ff6f82f8
commit 37f618fc62
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!(
@ -505,6 +515,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

@ -150,6 +150,10 @@ pub mod memory_ops_syscalls {
solana_sdk::declare_id!("ENQi37wsVhTvFz2gUiZAAbqFEWGN2jwFsqdEDTE8A4MU");
}
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> = [
@ -186,6 +190,7 @@ lazy_static! {
(stake_program_v4::id(), "solana_stake_program v4"),
(system_transfer_zero_check::id(), "perform all checks for transfers of 0 lamports"),
(memory_ops_syscalls::id(), "add syscalls for memory operations"),
(dedupe_config_program_signers::id(), "dedupe config program signers"),
/*************** ADD NEW FEATURES HERE ***************/
]
.iter()