Skip to content

Commit

Permalink
don't serialize executable accounts
Browse files Browse the repository at this point in the history
  • Loading branch information
seanyoung committed Feb 26, 2024
1 parent e74d5cc commit 51f6be2
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 16 deletions.
3 changes: 3 additions & 0 deletions ledger-tool/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use {
account_utils::StateMut,
bpf_loader_upgradeable::{self, UpgradeableLoaderState},
pubkey::Pubkey,
rent_collector::RENT_EXEMPT_RENT_EPOCH,
slot_history::Slot,
transaction_context::{IndexOfAccount, InstructionAccount},
},
Expand Down Expand Up @@ -337,6 +338,8 @@ fn load_program<'a>(
&contents,
&loader_key,
account_size,
RENT_EXEMPT_RENT_EPOCH,
1,
slot,
Arc::new(program_runtime_environment),
false,
Expand Down
40 changes: 39 additions & 1 deletion program-runtime/src/loaded_programs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use {
clock::{Epoch, Slot},
loader_v4,
pubkey::Pubkey,
rent_collector::RENT_EXEMPT_RENT_EPOCH,
saturating_add_assign,
},
std::{
Expand Down Expand Up @@ -133,6 +134,10 @@ pub struct LoadedProgram {
pub program: LoadedProgramType,
/// Size of account that stores the program and program data
pub account_size: usize,
/// lamoports for the program account
pub lamports: u64,
/// rent epoch for the program account
pub rent_epoch: u64,
/// Slot in which the program was (re)deployed
pub deployment_slot: Slot,
/// Slot in which this entry will become active (can be in the future)
Expand Down Expand Up @@ -282,6 +287,8 @@ impl LoadedProgram {
effective_slot: Slot,
elf_bytes: &[u8],
account_size: usize,
rent_epoch: u64,
lamports: u64,
metrics: &mut LoadProgramMetrics,
) -> Result<Self, Box<dyn std::error::Error>> {
Self::new_internal(
Expand All @@ -291,6 +298,8 @@ impl LoadedProgram {
effective_slot,
elf_bytes,
account_size,
rent_epoch,
lamports,
metrics,
false, /* reloading */
)
Expand All @@ -311,6 +320,8 @@ impl LoadedProgram {
effective_slot: Slot,
elf_bytes: &[u8],
account_size: usize,
rent_epoch: u64,
lamports: u64,
metrics: &mut LoadProgramMetrics,
) -> Result<Self, Box<dyn std::error::Error>> {
Self::new_internal(
Expand All @@ -320,18 +331,23 @@ impl LoadedProgram {
effective_slot,
elf_bytes,
account_size,
rent_epoch,
lamports,
metrics,
true, /* reloading */
)
}

#[allow(clippy::too_many_arguments)]
fn new_internal(
loader_key: &Pubkey,
program_runtime_environment: Arc<BuiltinProgram<InvokeContext<'static>>>,
deployment_slot: Slot,
effective_slot: Slot,
elf_bytes: &[u8],
account_size: usize,
rent_epoch: u64,
lamports: u64,
metrics: &mut LoadProgramMetrics,
reloading: bool,
) -> Result<Self, Box<dyn std::error::Error>> {
Expand Down Expand Up @@ -371,6 +387,8 @@ impl LoadedProgram {
Ok(Self {
deployment_slot,
account_size,
rent_epoch,
lamports,
effective_slot,
tx_usage_counter: AtomicU64::new(0),
program,
Expand Down Expand Up @@ -402,6 +420,8 @@ impl LoadedProgram {
tx_usage_counter: AtomicU64::new(self.tx_usage_counter.load(Ordering::Relaxed)),
ix_usage_counter: AtomicU64::new(self.ix_usage_counter.load(Ordering::Relaxed)),
latest_access_slot: AtomicU64::new(self.latest_access_slot.load(Ordering::Relaxed)),
rent_epoch: self.rent_epoch,
lamports: self.lamports,
})
}

Expand All @@ -423,6 +443,8 @@ impl LoadedProgram {
program: LoadedProgramType::Builtin(BuiltinProgram::new_builtin(function_registry)),
ix_usage_counter: AtomicU64::new(0),
latest_access_slot: AtomicU64::new(0),
lamports: 0,
rent_epoch: RENT_EXEMPT_RENT_EPOCH,
}
}

Expand All @@ -435,6 +457,8 @@ impl LoadedProgram {
tx_usage_counter: AtomicU64::default(),
ix_usage_counter: AtomicU64::default(),
latest_access_slot: AtomicU64::new(0),
lamports: 0,
rent_epoch: 0,
};
debug_assert!(tombstone.is_tombstone());
tombstone
Expand All @@ -449,6 +473,10 @@ impl LoadedProgram {
)
}

pub fn is_builtin(&self) -> bool {
matches!(self.program, LoadedProgramType::Builtin(..))
}

fn is_implicit_delay_visibility_tombstone(&self, slot: Slot) -> bool {
!matches!(self.program, LoadedProgramType::Builtin(_))
&& self.effective_slot.saturating_sub(self.deployment_slot)
Expand Down Expand Up @@ -1143,7 +1171,7 @@ mod tests {
assert_matches::assert_matches,
percentage::Percentage,
solana_rbpf::program::BuiltinProgram,
solana_sdk::{clock::Slot, pubkey::Pubkey},
solana_sdk::{clock::Slot, pubkey::Pubkey, rent_collector::RENT_EXEMPT_RENT_EPOCH},
std::{
ops::ControlFlow,
sync::{
Expand Down Expand Up @@ -1182,6 +1210,8 @@ mod tests {
tx_usage_counter: usage_counter,
ix_usage_counter: AtomicU64::default(),
latest_access_slot: AtomicU64::new(deployment_slot),
rent_epoch: 0,
lamports: 0,
})
}

Expand All @@ -1194,6 +1224,8 @@ mod tests {
tx_usage_counter: AtomicU64::default(),
ix_usage_counter: AtomicU64::default(),
latest_access_slot: AtomicU64::default(),
rent_epoch: RENT_EXEMPT_RENT_EPOCH,
lamports: 0,
})
}

Expand Down Expand Up @@ -1224,6 +1256,8 @@ mod tests {
tx_usage_counter: AtomicU64::default(),
ix_usage_counter: AtomicU64::default(),
latest_access_slot: AtomicU64::default(),
rent_epoch: 0,
lamports: 0,
}
.to_unloaded()
.expect("Failed to unload the program"),
Expand Down Expand Up @@ -1856,6 +1890,8 @@ mod tests {
tx_usage_counter: AtomicU64::default(),
ix_usage_counter: AtomicU64::default(),
latest_access_slot: AtomicU64::default(),
rent_epoch: RENT_EXEMPT_RENT_EPOCH,
lamports: 0,
});
cache.assign_program(program1, updated_program.clone());

Expand Down Expand Up @@ -2392,6 +2428,8 @@ mod tests {
account_size: 0,
deployment_slot: 0,
effective_slot: 0,
lamports: 0,
rent_epoch: 0,
tx_usage_counter: AtomicU64::default(),
ix_usage_counter: AtomicU64::default(),
latest_access_slot: AtomicU64::default(),
Expand Down
29 changes: 26 additions & 3 deletions programs/bpf_loader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ use {
native_loader,
program_utils::limited_deserialize,
pubkey::Pubkey,
rent_collector::RENT_EXEMPT_RENT_EPOCH,
saturating_add_assign,
system_instruction::{self, MAX_PERMITTED_DATA_LENGTH},
transaction_context::{IndexOfAccount, InstructionContext, TransactionContext},
Expand All @@ -66,6 +67,8 @@ pub fn load_program_from_bytes(
programdata: &[u8],
loader_key: &Pubkey,
account_size: usize,
rent_epoch: u64,
lamports: u64,
deployment_slot: Slot,
program_runtime_environment: Arc<BuiltinProgram<InvokeContext<'static>>>,
reloading: bool,
Expand All @@ -81,6 +84,8 @@ pub fn load_program_from_bytes(
effective_slot,
programdata,
account_size,
rent_epoch,
lamports,
load_program_metrics,
)
}
Expand All @@ -92,6 +97,8 @@ pub fn load_program_from_bytes(
effective_slot,
programdata,
account_size,
rent_epoch,
lamports,
load_program_metrics,
)
}
Expand All @@ -104,7 +111,8 @@ pub fn load_program_from_bytes(

macro_rules! deploy_program {
($invoke_context:expr, $program_id:expr, $loader_key:expr,
$account_size:expr, $slot:expr, $drop:expr, $new_programdata:expr $(,)?) => {{
$account_size:expr, $lamports:expr,
$slot:expr, $drop:expr, $new_programdata:expr $(,)?) => {{
let mut load_program_metrics = LoadProgramMetrics::default();
let mut register_syscalls_time = Measure::start("register_syscalls_time");
let deployment_program_runtime_environment = create_program_runtime_environment_v1(
Expand Down Expand Up @@ -143,6 +151,8 @@ macro_rules! deploy_program {
$new_programdata,
$loader_key,
$account_size,
RENT_EXEMPT_RENT_EPOCH,
$lamports,
$slot,
$invoke_context.programs_modified_by_tx.environments.program_runtime_v1.clone(),
true,
Expand Down Expand Up @@ -526,7 +536,8 @@ fn process_loader_upgradeable_instruction(
ic_logger_msg!(log_collector, "Program account too small");
return Err(InstructionError::AccountDataTooSmall);
}
if program.get_lamports() < rent.minimum_balance(program.get_data().len()) {
let lamports = program.get_lamports();
if lamports < rent.minimum_balance(program.get_data().len()) {
ic_logger_msg!(log_collector, "Program account not rent-exempt");
return Err(InstructionError::ExecutableAccountNotRentExempt);
}
Expand Down Expand Up @@ -626,6 +637,7 @@ fn process_loader_upgradeable_instruction(
new_program_id,
&owner_id,
UpgradeableLoaderState::size_of_program().saturating_add(programdata_len),
lamports,
clock.slot,
{
drop(buffer);
Expand Down Expand Up @@ -734,6 +746,7 @@ fn process_loader_upgradeable_instruction(
return Err(InstructionError::InvalidAccountData);
}
let new_program_id = *program.get_key();
let lamports = program.get_lamports();
drop(program);

// Verify Buffer account
Expand Down Expand Up @@ -822,6 +835,7 @@ fn process_loader_upgradeable_instruction(
new_program_id,
program_id,
UpgradeableLoaderState::size_of_program().saturating_add(programdata_len),
lamports,
clock.slot,
{
drop(buffer);
Expand Down Expand Up @@ -1187,6 +1201,7 @@ fn process_loader_upgradeable_instruction(
return Err(InstructionError::InvalidAccountOwner);
}
let program_key = *program_account.get_key();
let lamports = program_account.get_lamports();
match program_account.get_state()? {
UpgradeableLoaderState::Program {
programdata_address,
Expand Down Expand Up @@ -1285,6 +1300,7 @@ fn process_loader_upgradeable_instruction(
program_key,
&program_id,
UpgradeableLoaderState::size_of_program().saturating_add(new_len),
lamports,
clock_slot,
{
drop(programdata_account);
Expand Down Expand Up @@ -1558,6 +1574,8 @@ pub mod test_utils {
account.data(),
owner,
account.data().len(),
account.rent_epoch(),
account.lamports(),
0,
program_runtime_environment.clone(),
false,
Expand Down Expand Up @@ -3779,9 +3797,10 @@ mod tests {
program_id,
&bpf_loader_upgradeable::id(),
elf.len(),
102,
2,
{},
&elf
&elf,
);
Ok(())
}
Expand All @@ -3800,6 +3819,8 @@ mod tests {
tx_usage_counter: AtomicU64::new(100),
ix_usage_counter: AtomicU64::new(100),
latest_access_slot: AtomicU64::new(0),
rent_epoch: 0,
lamports: 0,
};
invoke_context
.programs_modified_by_tx
Expand Down Expand Up @@ -3840,6 +3861,8 @@ mod tests {
tx_usage_counter: AtomicU64::new(100),
ix_usage_counter: AtomicU64::new(100),
latest_access_slot: AtomicU64::new(0),
rent_epoch: 0,
lamports: 0,
};
invoke_context
.programs_modified_by_tx
Expand Down
8 changes: 7 additions & 1 deletion programs/loader-v4/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use {
loader_v4_instruction::LoaderV4Instruction,
program_utils::limited_deserialize,
pubkey::Pubkey,
rent_collector::RENT_EXEMPT_RENT_EPOCH,
saturating_add_assign,
transaction_context::{BorrowedAccount, InstructionContext},
},
Expand Down Expand Up @@ -410,7 +411,7 @@ pub fn process_instruction_deploy(
program_id: buffer.get_key().to_string(),
..LoadProgramMetrics::default()
};
let executor = LoadedProgram::new(
let mut executor = LoadedProgram::new(
&loader_v4::id(),
invoke_context
.programs_modified_by_tx
Expand All @@ -421,6 +422,8 @@ pub fn process_instruction_deploy(
effective_slot,
programdata,
buffer.get_data().len(),
RENT_EXEMPT_RENT_EPOCH,
program.get_lamports(),
&mut load_program_metrics,
)
.map_err(|err| {
Expand All @@ -436,6 +439,7 @@ pub fn process_instruction_deploy(
source_program.set_data_length(0, &invoke_context.feature_set)?;
source_program.checked_sub_lamports(transfer_lamports, &invoke_context.feature_set)?;
program.checked_add_lamports(transfer_lamports, &invoke_context.feature_set)?;
executor.lamports = program.get_lamports();
}
let state = get_state_mut(program.get_data_mut(&invoke_context.feature_set)?)?;
state.slot = current_slot;
Expand Down Expand Up @@ -661,6 +665,8 @@ mod tests {
0,
programdata,
account.data().len(),
account.rent_epoch(),
account.lamports(),
&mut load_program_metrics,
) {
invoke_context.programs_modified_by_tx.set_slot_for_tests(0);
Expand Down
1 change: 1 addition & 0 deletions programs/sbf/tests/programs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4434,6 +4434,7 @@ fn test_deny_executable_write() {
if !direct_mapping {
feature_set.deactivate(&feature_set::bpf_account_data_direct_mapping::id());
}
feature_set.deactivate(&feature_set::dont_load_executable_accounts::id());
let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
let mut bank_client = BankClient::new_shared(bank);
let authority_keypair = Keypair::new();
Expand Down
Loading

0 comments on commit 51f6be2

Please sign in to comment.