Skip to content
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");
Comment thread
pgarg66 marked this conversation as 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()) {
Comment thread
pgarg66 marked this conversation as 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),
);
}
}