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

Adjustments of loader-v4 #2630

Merged
merged 1 commit into from
Aug 20, 2024
Merged
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
75 changes: 44 additions & 31 deletions programs/loader-v4/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use {
solana_program_runtime::{
invoke_context::InvokeContext,
loaded_programs::{
LoadProgramMetrics, ProgramCacheEntry, ProgramCacheEntryType,
LoadProgramMetrics, ProgramCacheEntry, ProgramCacheEntryOwner, ProgramCacheEntryType,
DELAY_VISIBILITY_SLOT_OFFSET,
},
stable_log,
Expand Down Expand Up @@ -199,10 +199,6 @@ fn check_program_account(
ic_logger_msg!(log_collector, "Program not owned by loader");
return Err(InstructionError::InvalidAccountOwner);
}
if program.get_data().is_empty() {
ic_logger_msg!(log_collector, "Program is uninitialized");
return Err(InstructionError::InvalidAccountData);
}
let state = get_state(program.get_data())?;
if !program.is_writable() {
ic_logger_msg!(log_collector, "Program is not writeable");
Expand Down Expand Up @@ -488,12 +484,22 @@ pub fn process_instruction_retract(
);
return Err(InstructionError::InvalidArgument);
}
if matches!(state.status, LoaderV4Status::Retracted) {
if !matches!(state.status, LoaderV4Status::Deployed) {
ic_logger_msg!(log_collector, "Program is not deployed");
pgarg66 marked this conversation as resolved.
Show resolved Hide resolved
return Err(InstructionError::InvalidArgument);
}
let state = get_state_mut(program.get_data_mut()?)?;
state.status = LoaderV4Status::Retracted;
invoke_context
.program_cache_for_tx_batch
.store_modified_entry(
*program.get_key(),
Arc::new(ProgramCacheEntry::new_tombstone(
current_slot,
ProgramCacheEntryOwner::LoaderV4,
ProgramCacheEntryType::Closed,
)),
);
Ok(())
}

Expand All @@ -518,12 +524,16 @@ pub fn process_instruction_transfer_authority(
&program,
authority_address,
)?;
if new_authority_address.is_some() && !instruction_context.is_instruction_account_signer(2)? {
ic_logger_msg!(log_collector, "New authority did not sign");
return Err(InstructionError::MissingRequiredSignature);
}
let state = get_state_mut(program.get_data_mut()?)?;
if let Some(new_authority_address) = new_authority_address {
if !instruction_context.is_instruction_account_signer(2)? {
ic_logger_msg!(log_collector, "New authority did not sign");
return Err(InstructionError::MissingRequiredSignature);
}
if state.authority_address == new_authority_address {
ic_logger_msg!(log_collector, "No change");
return Err(InstructionError::InvalidArgument);
}
state.authority_address = new_authority_address;
} else if matches!(state.status, LoaderV4Status::Deployed) {
state.status = LoaderV4Status::Finalized;
Expand Down Expand Up @@ -575,26 +585,18 @@ pub fn process_instruction_inner(
.map_err(|err| Box::new(err) as Box<dyn std::error::Error>)
} else {
let program = instruction_context.try_borrow_last_program_account(transaction_context)?;
if !loader_v4::check_id(program.get_owner()) {
pgarg66 marked this conversation as resolved.
Show resolved Hide resolved
ic_logger_msg!(log_collector, "Program not owned by loader");
return Err(Box::new(InstructionError::InvalidAccountOwner));
}
if program.get_data().is_empty() {
ic_logger_msg!(log_collector, "Program is uninitialized");
return Err(Box::new(InstructionError::InvalidAccountData));
}
let state = get_state(program.get_data())?;
if matches!(state.status, LoaderV4Status::Retracted) {
ic_logger_msg!(log_collector, "Program is not deployed");
return Err(Box::new(InstructionError::InvalidArgument));
ic_logger_msg!(log_collector, "Program is retracted");
return Err(Box::new(InstructionError::UnsupportedProgramId));
}
let mut get_or_create_executor_time = Measure::start("get_or_create_executor_time");
let loaded_program = invoke_context
.program_cache_for_tx_batch
.find(program.get_key())
.ok_or_else(|| {
ic_logger_msg!(log_collector, "Program is not cached");
InstructionError::InvalidAccountData
InstructionError::UnsupportedProgramId
})?;
get_or_create_executor_time.stop();
saturating_add_assign!(
Expand All @@ -610,10 +612,12 @@ pub fn process_instruction_inner(
| ProgramCacheEntryType::Closed
| ProgramCacheEntryType::DelayVisibility => {
ic_logger_msg!(log_collector, "Program is not deployed");
Err(Box::new(InstructionError::InvalidAccountData) as Box<dyn std::error::Error>)
Err(Box::new(InstructionError::UnsupportedProgramId) as Box<dyn std::error::Error>)
}
ProgramCacheEntryType::Loaded(executable) => execute(invoke_context, executable),
_ => Err(Box::new(InstructionError::IncorrectProgramId) as Box<dyn std::error::Error>),
_ => {
Err(Box::new(InstructionError::UnsupportedProgramId) as Box<dyn std::error::Error>)
}
}
}
.map(|_| 0)
Expand Down Expand Up @@ -1157,7 +1161,7 @@ mod tests {
&bincode::serialize(&LoaderV4Instruction::Truncate { new_size: 0 }).unwrap(),
transaction_accounts.clone(),
&[(3, false, true), (1, true, false), (2, true, true)],
Err(InstructionError::InvalidAccountData),
Err(InstructionError::AccountDataTooSmall),
);

// Error: Program is not retracted
Expand Down Expand Up @@ -1331,7 +1335,7 @@ mod tests {
&bincode::serialize(&LoaderV4Instruction::Deploy).unwrap(),
transaction_accounts.clone(),
&[(3, false, true), (1, true, false)],
Err(InstructionError::InvalidAccountData),
Err(InstructionError::AccountDataTooSmall),
);

// Error: Program fails verification
Expand Down Expand Up @@ -1410,7 +1414,7 @@ mod tests {
&bincode::serialize(&LoaderV4Instruction::Retract).unwrap(),
transaction_accounts.clone(),
&[(2, false, true), (1, true, false)],
Err(InstructionError::InvalidAccountData),
Err(InstructionError::AccountDataTooSmall),
);

// Error: Program is not deployed
Expand Down Expand Up @@ -1520,18 +1524,27 @@ mod tests {
&bincode::serialize(&LoaderV4Instruction::TransferAuthority).unwrap(),
transaction_accounts.clone(),
&[(2, false, true), (3, true, false), (4, true, false)],
Err(InstructionError::InvalidAccountData),
Err(InstructionError::AccountDataTooSmall),
);

// Error: New authority did not sign
process_instruction(
vec![],
&bincode::serialize(&LoaderV4Instruction::TransferAuthority).unwrap(),
transaction_accounts,
transaction_accounts.clone(),
&[(0, false, true), (3, true, false), (4, false, false)],
Err(InstructionError::MissingRequiredSignature),
);

// Error: Authority did not change
process_instruction(
vec![],
&bincode::serialize(&LoaderV4Instruction::TransferAuthority).unwrap(),
transaction_accounts,
&[(0, false, true), (3, true, false), (3, true, false)],
Err(InstructionError::InvalidArgument),
);

test_loader_instruction_general_errors(LoaderV4Instruction::TransferAuthority);
}

Expand Down Expand Up @@ -1598,7 +1611,7 @@ mod tests {
&[0, 1, 2, 3],
transaction_accounts.clone(),
&[(1, false, true)],
Err(InstructionError::InvalidAccountData),
Err(InstructionError::AccountDataTooSmall),
);

// Error: Program is not deployed
Expand All @@ -1607,7 +1620,7 @@ mod tests {
&[0, 1, 2, 3],
transaction_accounts.clone(),
&[(1, false, true)],
Err(InstructionError::InvalidArgument),
Err(InstructionError::UnsupportedProgramId),
);

// Error: Program fails verification
Expand All @@ -1616,7 +1629,7 @@ mod tests {
&[0, 1, 2, 3],
transaction_accounts,
&[(1, false, true)],
Err(InstructionError::InvalidAccountData),
Err(InstructionError::UnsupportedProgramId),
);
}
}