Skip to content
This repository has been archived by the owner on Jan 22, 2025. It is now read-only.

Remove redundant check during loading upgradeable program for writing #30561

Merged
merged 2 commits into from
Mar 28, 2023
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
64 changes: 51 additions & 13 deletions runtime/src/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ use {
self, add_set_tx_loaded_accounts_data_size_instruction, enable_request_heap_frame_ix,
include_loaded_accounts_data_size_in_fee_calculation,
remove_congestion_multiplier_from_fee_calculation, remove_deprecated_request_unit_ix,
use_default_units_in_fee_calculation, FeatureSet,
simplify_writable_program_account_check, use_default_units_in_fee_calculation,
FeatureSet,
},
fee::FeeStructure,
genesis_config::ClusterType,
Expand Down Expand Up @@ -393,7 +394,10 @@ impl Accounts {
}

if bpf_loader_upgradeable::check_id(account.owner()) {
if message.is_writable(i) && !message.is_upgradeable_loader_present() {
if !feature_set.is_active(&simplify_writable_program_account_check::id())
&& message.is_writable(i)
&& !message.is_upgradeable_loader_present()
{
error_counters.invalid_writable_account += 1;
return Err(TransactionError::InvalidWritableAccount);
}
Expand Down Expand Up @@ -2500,8 +2504,12 @@ mod tests {
instructions,
);
let tx = Transaction::new(&[&keypair], message.clone(), Hash::default());
let loaded_accounts =
load_accounts_with_excluded_features(tx, &accounts, &mut error_counters, None);
let loaded_accounts = load_accounts_with_excluded_features(
tx.clone(),
&accounts,
&mut error_counters,
Some(&[simplify_writable_program_account_check::id()]),
);

assert_eq!(error_counters.invalid_writable_account, 1);
assert_eq!(loaded_accounts.len(), 1);
Expand All @@ -2510,11 +2518,22 @@ mod tests {
(Err(TransactionError::InvalidWritableAccount), None)
);

// Solution 0: Include feature simplify_writable_program_account_check
let loaded_accounts =
load_accounts_with_excluded_features(tx, &accounts, &mut error_counters, None);

assert_eq!(error_counters.invalid_writable_account, 1);
assert_eq!(loaded_accounts.len(), 1);

// Solution 1: include bpf_loader_upgradeable account
message.account_keys = vec![key0, key1, bpf_loader_upgradeable::id()];
let tx = Transaction::new(&[&keypair], message.clone(), Hash::default());
let loaded_accounts =
load_accounts_with_excluded_features(tx, &accounts, &mut error_counters, None);
let loaded_accounts = load_accounts_with_excluded_features(
tx,
&accounts,
&mut error_counters,
Some(&[simplify_writable_program_account_check::id()]),
);

assert_eq!(error_counters.invalid_writable_account, 1);
assert_eq!(loaded_accounts.len(), 1);
Expand All @@ -2529,8 +2548,12 @@ mod tests {
message.account_keys = vec![key0, key1, key2]; // revert key change
message.header.num_readonly_unsigned_accounts = 2; // mark both executables as readonly
let tx = Transaction::new(&[&keypair], message, Hash::default());
let loaded_accounts =
load_accounts_with_excluded_features(tx, &accounts, &mut error_counters, None);
let loaded_accounts = load_accounts_with_excluded_features(
tx,
&accounts,
&mut error_counters,
Some(&[simplify_writable_program_account_check::id()]),
);

assert_eq!(error_counters.invalid_writable_account, 1);
assert_eq!(loaded_accounts.len(), 1);
Expand Down Expand Up @@ -2588,8 +2611,12 @@ mod tests {
instructions,
);
let tx = Transaction::new(&[&keypair], message.clone(), Hash::default());
let loaded_accounts =
load_accounts_with_excluded_features(tx, &accounts, &mut error_counters, None);
let loaded_accounts = load_accounts_with_excluded_features(
tx.clone(),
&accounts,
&mut error_counters,
Some(&[simplify_writable_program_account_check::id()]),
);

assert_eq!(error_counters.invalid_writable_account, 1);
assert_eq!(loaded_accounts.len(), 1);
Expand All @@ -2598,6 +2625,13 @@ mod tests {
(Err(TransactionError::InvalidWritableAccount), None)
);

// Solution 0: Include feature simplify_writable_program_account_check
let loaded_accounts =
load_accounts_with_excluded_features(tx, &accounts, &mut error_counters, None);

assert_eq!(error_counters.invalid_writable_account, 1);
assert_eq!(loaded_accounts.len(), 1);

// Solution 1: include bpf_loader_upgradeable account
let mut account = AccountSharedData::new(40, 1, &native_loader::id()); // create mock bpf_loader_upgradeable
account.set_executable(true);
Expand All @@ -2613,7 +2647,7 @@ mod tests {
tx,
&accounts_with_upgradeable_loader,
&mut error_counters,
None,
Some(&[simplify_writable_program_account_check::id()]),
);

assert_eq!(error_counters.invalid_writable_account, 1);
Expand All @@ -2629,8 +2663,12 @@ mod tests {
message.account_keys = vec![key0, key1, key2]; // revert key change
message.header.num_readonly_unsigned_accounts = 2; // extend readonly set to include programdata
let tx = Transaction::new(&[&keypair], message, Hash::default());
let loaded_accounts =
load_accounts_with_excluded_features(tx, &accounts, &mut error_counters, None);
let loaded_accounts = load_accounts_with_excluded_features(
tx,
&accounts,
&mut error_counters,
Some(&[simplify_writable_program_account_check::id()]),
);

assert_eq!(error_counters.invalid_writable_account, 1);
assert_eq!(loaded_accounts.len(), 1);
Expand Down
4 changes: 4 additions & 0 deletions sdk/src/feature_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,9 @@ pub mod include_loaded_accounts_data_size_in_fee_calculation {
pub mod native_programs_consume_cu {
solana_sdk::declare_id!("8pgXCMNXC8qyEFypuwpXyRxLXZdpM4Qo72gJ6k87A6wL");
}
pub mod simplify_writable_program_account_check {
solana_sdk::declare_id!("5ZCcFAzJ1zsFKe1KSZa9K92jhx7gkcKj97ci2DBo1vwj");
}

lazy_static! {
/// Map of feature identifiers to user-visible description
Expand Down Expand Up @@ -797,6 +800,7 @@ lazy_static! {
(remove_bpf_loader_incorrect_program_id::id(), "stop incorrectly throwing IncorrectProgramId in bpf_loader #30747"),
(include_loaded_accounts_data_size_in_fee_calculation::id(), "include transaction loaded accounts data size in base fee calculation #30657"),
(native_programs_consume_cu::id(), "Native program should consume compute units #30620"),
(simplify_writable_program_account_check::id(), "Simplify checks performed for writable upgradeable program accounts #30559"),
/*************** ADD NEW FEATURES HERE ***************/
]
.iter()
Expand Down