Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor - LoadedProgramType::Loaded and LoadedProgramOwner #606

Merged
merged 2 commits into from
Apr 17, 2024
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
2 changes: 1 addition & 1 deletion ledger-tool/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ fn load_program<'a>(
);
match result {
Ok(loaded_program) => match loaded_program.program {
LoadedProgramType::LegacyV1(program) => Ok(program),
LoadedProgramType::Loaded(program) => Ok(program),
_ => unreachable!(),
},
Err(err) => Err(format!("Loading executable failed: {err:?}")),
Expand Down
229 changes: 141 additions & 88 deletions program-runtime/src/loaded_programs.rs

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions programs/bpf_loader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ use {
ic_logger_msg, ic_msg,
invoke_context::{BpfAllocator, InvokeContext, SerializedAccountMetadata, SyscallContext},
loaded_programs::{
LoadProgramMetrics, LoadedProgram, LoadedProgramType, DELAY_VISIBILITY_SLOT_OFFSET,
LoadProgramMetrics, LoadedProgram, LoadedProgramOwner, LoadedProgramType,
DELAY_VISIBILITY_SLOT_OFFSET,
},
log_collector::LogCollector,
stable_log,
Expand Down Expand Up @@ -456,8 +457,7 @@ pub fn process_instruction_inner(
ic_logger_msg!(log_collector, "Program is not deployed");
Err(Box::new(InstructionError::InvalidAccountData) as Box<dyn std::error::Error>)
}
LoadedProgramType::LegacyV0(executable) => execute(executable, invoke_context),
LoadedProgramType::LegacyV1(executable) => execute(executable, invoke_context),
LoadedProgramType::Loaded(executable) => execute(executable, invoke_context),
_ => Err(Box::new(InstructionError::IncorrectProgramId) as Box<dyn std::error::Error>),
}
.map(|_| 0)
Expand Down Expand Up @@ -1113,6 +1113,7 @@ fn process_loader_upgradeable_instruction(
program_key,
Arc::new(LoadedProgram::new_tombstone(
clock.slot,
LoadedProgramOwner::LoaderV3,
LoadedProgramType::Closed,
)),
);
Expand Down Expand Up @@ -3761,6 +3762,7 @@ mod tests {
let env = Arc::new(BuiltinProgram::new_mock());
let program = LoadedProgram {
program: LoadedProgramType::Unloaded(env),
account_owner: LoadedProgramOwner::LoaderV2,
account_size: 0,
deployment_slot: 0,
effective_slot: 0,
Expand Down Expand Up @@ -3804,6 +3806,7 @@ mod tests {
let env = Arc::new(BuiltinProgram::new_mock());
let program = LoadedProgram {
program: LoadedProgramType::Unloaded(env),
account_owner: LoadedProgramOwner::LoaderV2,
account_size: 0,
deployment_slot: 0,
effective_slot: 0,
Expand Down
2 changes: 1 addition & 1 deletion programs/loader-v4/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ pub fn process_instruction_inner(
ic_logger_msg!(log_collector, "Program is not deployed");
Err(Box::new(InstructionError::InvalidAccountData) as Box<dyn std::error::Error>)
}
LoadedProgramType::Typed(executable) => execute(invoke_context, executable),
LoadedProgramType::Loaded(executable) => execute(invoke_context, executable),
_ => Err(Box::new(InstructionError::IncorrectProgramId) as Box<dyn std::error::Error>),
}
}
Expand Down
9 changes: 7 additions & 2 deletions runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ use {
compute_budget_processor::process_compute_budget_instructions,
invoke_context::BuiltinFunctionWithContext,
loaded_programs::{
LoadedProgram, LoadedProgramMatchCriteria, LoadedProgramType, ProgramCache,
LoadedProgram, LoadedProgramMatchCriteria, LoadedProgramOwner, LoadedProgramType,
ProgramCache,
},
timings::{ExecuteTimingType, ExecuteTimings},
},
Expand Down Expand Up @@ -6400,7 +6401,11 @@ impl Bank {
self,
program_id,
name,
LoadedProgram::new_tombstone(self.slot, LoadedProgramType::Closed),
LoadedProgram::new_tombstone(
self.slot,
LoadedProgramOwner::NativeLoader,
LoadedProgramType::Closed,
),
);
debug!("Removed program {}", program_id);
}
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/bank/builtins/core_bpf_migration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ mod tests {
assert_eq!(target_entry.latest_access_slot.load(Relaxed), bank.slot());

// The target program entry should now be a BPF program.
assert_matches!(target_entry.program, LoadedProgramType::LegacyV1(..));
assert_matches!(target_entry.program, LoadedProgramType::Loaded(..));
}
}

Expand Down
4 changes: 2 additions & 2 deletions runtime/src/bank/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7101,7 +7101,7 @@ fn test_bank_load_program() {
bank.store_account_and_update_capitalization(&key1, &program_account);
bank.store_account_and_update_capitalization(&programdata_key, &programdata_account);
let program = bank.load_program(&key1, false, bank.epoch()).unwrap();
assert_matches!(program.program, LoadedProgramType::LegacyV1(_));
assert_matches!(program.program, LoadedProgramType::Loaded(_));
assert_eq!(
program.account_size,
program_account.data().len() + programdata_account.data().len()
Expand Down Expand Up @@ -7347,7 +7347,7 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() {
assert_eq!(slot_versions[1].effective_slot, 1);
assert!(matches!(
slot_versions[1].program,
LoadedProgramType::LegacyV1(_),
LoadedProgramType::Loaded(_),
));
}

Expand Down
80 changes: 55 additions & 25 deletions svm/src/transaction_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ use {
invoke_context::InvokeContext,
loaded_programs::{
ForkGraph, LoadProgramMetrics, LoadedProgram, LoadedProgramMatchCriteria,
LoadedProgramType, LoadedProgramsForTxBatch, ProgramCache, ProgramRuntimeEnvironment,
DELAY_VISIBILITY_SLOT_OFFSET,
LoadedProgramOwner, LoadedProgramType, LoadedProgramsForTxBatch, ProgramCache,
ProgramRuntimeEnvironment, DELAY_VISIBILITY_SLOT_OFFSET,
},
log_collector::LogCollector,
sysvar_cache::SysvarCache,
Expand All @@ -30,6 +30,7 @@ use {
solana_sdk::{
account::{AccountSharedData, ReadableAccount, PROGRAM_OWNERS},
account_utils::StateMut,
bpf_loader, bpf_loader_deprecated,
bpf_loader_upgradeable::{self, UpgradeableLoaderState},
clock::{Epoch, Slot},
epoch_schedule::EpochSchedule,
Expand Down Expand Up @@ -114,8 +115,9 @@ pub trait TransactionProcessingCallback {

#[derive(Debug)]
enum ProgramAccountLoadResult {
InvalidAccountData,
ProgramOfLoaderV1orV2(AccountSharedData),
InvalidAccountData(LoadedProgramOwner),
ProgramOfLoaderV1(AccountSharedData),
ProgramOfLoaderV2(AccountSharedData),
ProgramOfLoaderV3(AccountSharedData, AccountSharedData, Slot),
ProgramOfLoaderV4(AccountSharedData, Slot),
}
Expand Down Expand Up @@ -411,12 +413,11 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
};

let mut loaded_program = match self.load_program_accounts(callbacks, pubkey)? {
ProgramAccountLoadResult::InvalidAccountData => Ok(LoadedProgram::new_tombstone(
self.slot,
LoadedProgramType::Closed,
)),
ProgramAccountLoadResult::InvalidAccountData(owner) => Ok(
LoadedProgram::new_tombstone(self.slot, owner, LoadedProgramType::Closed),
),

ProgramAccountLoadResult::ProgramOfLoaderV1orV2(program_account) => {
ProgramAccountLoadResult::ProgramOfLoaderV1(program_account) => {
Self::load_program_from_bytes(
&mut load_program_metrics,
program_account.data(),
Expand All @@ -426,7 +427,20 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
environments.program_runtime_v1.clone(),
reload,
)
.map_err(|_| (0, environments.program_runtime_v1.clone()))
.map_err(|_| (0, LoadedProgramOwner::LoaderV1))
}

ProgramAccountLoadResult::ProgramOfLoaderV2(program_account) => {
Self::load_program_from_bytes(
&mut load_program_metrics,
program_account.data(),
program_account.owner(),
program_account.data().len(),
0,
environments.program_runtime_v1.clone(),
reload,
)
.map_err(|_| (0, LoadedProgramOwner::LoaderV2))
}

ProgramAccountLoadResult::ProgramOfLoaderV3(
Expand All @@ -451,7 +465,7 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
reload,
)
})
.map_err(|_| (slot, environments.program_runtime_v1.clone())),
.map_err(|_| (slot, LoadedProgramOwner::LoaderV3)),

ProgramAccountLoadResult::ProgramOfLoaderV4(program_account, slot) => program_account
.data()
Expand All @@ -468,10 +482,15 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
reload,
)
})
.map_err(|_| (slot, environments.program_runtime_v2.clone())),
.map_err(|_| (slot, LoadedProgramOwner::LoaderV4)),
}
.unwrap_or_else(|(slot, env)| {
LoadedProgram::new_tombstone(slot, LoadedProgramType::FailedVerification(env))
.unwrap_or_else(|(slot, owner)| {
let env = if let LoadedProgramOwner::LoaderV4 = &owner {
environments.program_runtime_v2.clone()
} else {
environments.program_runtime_v1.clone()
};
LoadedProgram::new_tombstone(slot, owner, LoadedProgramType::FailedVerification(env))
});

let mut timings = ExecuteDetailsTimings::default();
Expand Down Expand Up @@ -856,14 +875,18 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
(!matches!(state.status, LoaderV4Status::Retracted)).then_some(state.slot)
})
.map(|slot| ProgramAccountLoadResult::ProgramOfLoaderV4(program_account, slot))
.unwrap_or(ProgramAccountLoadResult::InvalidAccountData),
.unwrap_or(ProgramAccountLoadResult::InvalidAccountData(
LoadedProgramOwner::LoaderV4,
)),
);
}

if !bpf_loader_upgradeable::check_id(program_account.owner()) {
return Some(ProgramAccountLoadResult::ProgramOfLoaderV1orV2(
program_account,
));
if bpf_loader_deprecated::check_id(program_account.owner()) {
return Some(ProgramAccountLoadResult::ProgramOfLoaderV1(program_account));
}

if bpf_loader::check_id(program_account.owner()) {
return Some(ProgramAccountLoadResult::ProgramOfLoaderV2(program_account));
}

if let Ok(UpgradeableLoaderState::Program {
Expand All @@ -886,7 +909,9 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
}
}
}
Some(ProgramAccountLoadResult::InvalidAccountData)
Some(ProgramAccountLoadResult::InvalidAccountData(
LoadedProgramOwner::LoaderV3,
))
}

/// Extract the InnerInstructionsList from a TransactionContext
Expand Down Expand Up @@ -1131,7 +1156,7 @@ mod tests {
let result = batch_processor.load_program_accounts(&mock_bank, &key);
assert!(matches!(
result,
Some(ProgramAccountLoadResult::InvalidAccountData)
Some(ProgramAccountLoadResult::InvalidAccountData(_))
));

account_data.set_data(Vec::new());
Expand All @@ -1144,7 +1169,7 @@ mod tests {

assert!(matches!(
result,
Some(ProgramAccountLoadResult::InvalidAccountData)
Some(ProgramAccountLoadResult::InvalidAccountData(_))
));
}

Expand All @@ -1163,7 +1188,7 @@ mod tests {
let result = batch_processor.load_program_accounts(&mock_bank, &key);
assert!(matches!(
result,
Some(ProgramAccountLoadResult::InvalidAccountData)
Some(ProgramAccountLoadResult::InvalidAccountData(_))
));

account_data.set_data(vec![0; 64]);
Expand All @@ -1174,7 +1199,7 @@ mod tests {
let result = batch_processor.load_program_accounts(&mock_bank, &key);
assert!(matches!(
result,
Some(ProgramAccountLoadResult::InvalidAccountData)
Some(ProgramAccountLoadResult::InvalidAccountData(_))
));

let loader_data = LoaderV4State {
Expand Down Expand Up @@ -1219,7 +1244,8 @@ mod tests {

let result = batch_processor.load_program_accounts(&mock_bank, &key);
match result {
Some(ProgramAccountLoadResult::ProgramOfLoaderV1orV2(data)) => {
Some(ProgramAccountLoadResult::ProgramOfLoaderV1(data))
| Some(ProgramAccountLoadResult::ProgramOfLoaderV2(data)) => {
assert_eq!(data, account_data);
}
_ => panic!("Invalid result"),
Expand Down Expand Up @@ -1343,6 +1369,7 @@ mod tests {

let loaded_program = LoadedProgram::new_tombstone(
0,
LoadedProgramOwner::LoaderV4,
LoadedProgramType::FailedVerification(
batch_processor
.program_cache
Expand Down Expand Up @@ -1372,6 +1399,7 @@ mod tests {
let result = batch_processor.load_program_with_pubkey(&mock_bank, &key, false, 20);
let loaded_program = LoadedProgram::new_tombstone(
0,
LoadedProgramOwner::LoaderV2,
LoadedProgramType::FailedVerification(
batch_processor
.program_cache
Expand Down Expand Up @@ -1442,6 +1470,7 @@ mod tests {
let result = batch_processor.load_program_with_pubkey(&mock_bank, &key1, false, 0);
let loaded_program = LoadedProgram::new_tombstone(
0,
LoadedProgramOwner::LoaderV3,
LoadedProgramType::FailedVerification(
batch_processor
.program_cache
Expand Down Expand Up @@ -1518,6 +1547,7 @@ mod tests {
let result = batch_processor.load_program_with_pubkey(&mock_bank, &key, false, 0);
let loaded_program = LoadedProgram::new_tombstone(
0,
LoadedProgramOwner::LoaderV4,
LoadedProgramType::FailedVerification(
batch_processor
.program_cache
Expand Down
Loading