Skip to content

Commit 624da53

Browse files
committed
- Removes the empty program account check (InvalidAccountData).
- Adjusts checks of program.state.status to conform to error messages. - Adds check to prevent authority transfer to itself. - Adjusts most execution errors to UnsupportedProgramId. - Removes the redundant owner check in execution. - Adds a tombstone in the program cache upon retraction.
1 parent c66a8fb commit 624da53

File tree

1 file changed

+44
-31
lines changed

1 file changed

+44
-31
lines changed

programs/loader-v4/src/lib.rs

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use {
55
solana_program_runtime::{
66
invoke_context::InvokeContext,
77
loaded_programs::{
8-
LoadProgramMetrics, ProgramCacheEntry, ProgramCacheEntryType,
8+
LoadProgramMetrics, ProgramCacheEntry, ProgramCacheEntryOwner, ProgramCacheEntryType,
99
DELAY_VISIBILITY_SLOT_OFFSET,
1010
},
1111
stable_log,
@@ -199,10 +199,6 @@ fn check_program_account(
199199
ic_logger_msg!(log_collector, "Program not owned by loader");
200200
return Err(InstructionError::InvalidAccountOwner);
201201
}
202-
if program.get_data().is_empty() {
203-
ic_logger_msg!(log_collector, "Program is uninitialized");
204-
return Err(InstructionError::InvalidAccountData);
205-
}
206202
let state = get_state(program.get_data())?;
207203
if !program.is_writable() {
208204
ic_logger_msg!(log_collector, "Program is not writeable");
@@ -488,12 +484,22 @@ pub fn process_instruction_retract(
488484
);
489485
return Err(InstructionError::InvalidArgument);
490486
}
491-
if matches!(state.status, LoaderV4Status::Retracted) {
487+
if !matches!(state.status, LoaderV4Status::Deployed) {
492488
ic_logger_msg!(log_collector, "Program is not deployed");
493489
return Err(InstructionError::InvalidArgument);
494490
}
495491
let state = get_state_mut(program.get_data_mut()?)?;
496492
state.status = LoaderV4Status::Retracted;
493+
invoke_context
494+
.program_cache_for_tx_batch
495+
.store_modified_entry(
496+
*program.get_key(),
497+
Arc::new(ProgramCacheEntry::new_tombstone(
498+
current_slot,
499+
ProgramCacheEntryOwner::LoaderV4,
500+
ProgramCacheEntryType::Closed,
501+
)),
502+
);
497503
Ok(())
498504
}
499505

@@ -518,12 +524,16 @@ pub fn process_instruction_transfer_authority(
518524
&program,
519525
authority_address,
520526
)?;
521-
if new_authority_address.is_some() && !instruction_context.is_instruction_account_signer(2)? {
522-
ic_logger_msg!(log_collector, "New authority did not sign");
523-
return Err(InstructionError::MissingRequiredSignature);
524-
}
525527
let state = get_state_mut(program.get_data_mut()?)?;
526528
if let Some(new_authority_address) = new_authority_address {
529+
if !instruction_context.is_instruction_account_signer(2)? {
530+
ic_logger_msg!(log_collector, "New authority did not sign");
531+
return Err(InstructionError::MissingRequiredSignature);
532+
}
533+
if state.authority_address == new_authority_address {
534+
ic_logger_msg!(log_collector, "No change");
535+
return Err(InstructionError::InvalidArgument);
536+
}
527537
state.authority_address = new_authority_address;
528538
} else if matches!(state.status, LoaderV4Status::Deployed) {
529539
state.status = LoaderV4Status::Finalized;
@@ -575,26 +585,18 @@ pub fn process_instruction_inner(
575585
.map_err(|err| Box::new(err) as Box<dyn std::error::Error>)
576586
} else {
577587
let program = instruction_context.try_borrow_last_program_account(transaction_context)?;
578-
if !loader_v4::check_id(program.get_owner()) {
579-
ic_logger_msg!(log_collector, "Program not owned by loader");
580-
return Err(Box::new(InstructionError::InvalidAccountOwner));
581-
}
582-
if program.get_data().is_empty() {
583-
ic_logger_msg!(log_collector, "Program is uninitialized");
584-
return Err(Box::new(InstructionError::InvalidAccountData));
585-
}
586588
let state = get_state(program.get_data())?;
587589
if matches!(state.status, LoaderV4Status::Retracted) {
588-
ic_logger_msg!(log_collector, "Program is not deployed");
589-
return Err(Box::new(InstructionError::InvalidArgument));
590+
ic_logger_msg!(log_collector, "Program is retracted");
591+
return Err(Box::new(InstructionError::UnsupportedProgramId));
590592
}
591593
let mut get_or_create_executor_time = Measure::start("get_or_create_executor_time");
592594
let loaded_program = invoke_context
593595
.program_cache_for_tx_batch
594596
.find(program.get_key())
595597
.ok_or_else(|| {
596598
ic_logger_msg!(log_collector, "Program is not cached");
597-
InstructionError::InvalidAccountData
599+
InstructionError::UnsupportedProgramId
598600
})?;
599601
get_or_create_executor_time.stop();
600602
saturating_add_assign!(
@@ -610,10 +612,12 @@ pub fn process_instruction_inner(
610612
| ProgramCacheEntryType::Closed
611613
| ProgramCacheEntryType::DelayVisibility => {
612614
ic_logger_msg!(log_collector, "Program is not deployed");
613-
Err(Box::new(InstructionError::InvalidAccountData) as Box<dyn std::error::Error>)
615+
Err(Box::new(InstructionError::UnsupportedProgramId) as Box<dyn std::error::Error>)
614616
}
615617
ProgramCacheEntryType::Loaded(executable) => execute(invoke_context, executable),
616-
_ => Err(Box::new(InstructionError::IncorrectProgramId) as Box<dyn std::error::Error>),
618+
_ => {
619+
Err(Box::new(InstructionError::UnsupportedProgramId) as Box<dyn std::error::Error>)
620+
}
617621
}
618622
}
619623
.map(|_| 0)
@@ -1157,7 +1161,7 @@ mod tests {
11571161
&bincode::serialize(&LoaderV4Instruction::Truncate { new_size: 0 }).unwrap(),
11581162
transaction_accounts.clone(),
11591163
&[(3, false, true), (1, true, false), (2, true, true)],
1160-
Err(InstructionError::InvalidAccountData),
1164+
Err(InstructionError::AccountDataTooSmall),
11611165
);
11621166

11631167
// Error: Program is not retracted
@@ -1331,7 +1335,7 @@ mod tests {
13311335
&bincode::serialize(&LoaderV4Instruction::Deploy).unwrap(),
13321336
transaction_accounts.clone(),
13331337
&[(3, false, true), (1, true, false)],
1334-
Err(InstructionError::InvalidAccountData),
1338+
Err(InstructionError::AccountDataTooSmall),
13351339
);
13361340

13371341
// Error: Program fails verification
@@ -1410,7 +1414,7 @@ mod tests {
14101414
&bincode::serialize(&LoaderV4Instruction::Retract).unwrap(),
14111415
transaction_accounts.clone(),
14121416
&[(2, false, true), (1, true, false)],
1413-
Err(InstructionError::InvalidAccountData),
1417+
Err(InstructionError::AccountDataTooSmall),
14141418
);
14151419

14161420
// Error: Program is not deployed
@@ -1520,18 +1524,27 @@ mod tests {
15201524
&bincode::serialize(&LoaderV4Instruction::TransferAuthority).unwrap(),
15211525
transaction_accounts.clone(),
15221526
&[(2, false, true), (3, true, false), (4, true, false)],
1523-
Err(InstructionError::InvalidAccountData),
1527+
Err(InstructionError::AccountDataTooSmall),
15241528
);
15251529

15261530
// Error: New authority did not sign
15271531
process_instruction(
15281532
vec![],
15291533
&bincode::serialize(&LoaderV4Instruction::TransferAuthority).unwrap(),
1530-
transaction_accounts,
1534+
transaction_accounts.clone(),
15311535
&[(0, false, true), (3, true, false), (4, false, false)],
15321536
Err(InstructionError::MissingRequiredSignature),
15331537
);
15341538

1539+
// Error: Authority did not change
1540+
process_instruction(
1541+
vec![],
1542+
&bincode::serialize(&LoaderV4Instruction::TransferAuthority).unwrap(),
1543+
transaction_accounts,
1544+
&[(0, false, true), (3, true, false), (3, true, false)],
1545+
Err(InstructionError::InvalidArgument),
1546+
);
1547+
15351548
test_loader_instruction_general_errors(LoaderV4Instruction::TransferAuthority);
15361549
}
15371550

@@ -1598,7 +1611,7 @@ mod tests {
15981611
&[0, 1, 2, 3],
15991612
transaction_accounts.clone(),
16001613
&[(1, false, true)],
1601-
Err(InstructionError::InvalidAccountData),
1614+
Err(InstructionError::AccountDataTooSmall),
16021615
);
16031616

16041617
// Error: Program is not deployed
@@ -1607,7 +1620,7 @@ mod tests {
16071620
&[0, 1, 2, 3],
16081621
transaction_accounts.clone(),
16091622
&[(1, false, true)],
1610-
Err(InstructionError::InvalidArgument),
1623+
Err(InstructionError::UnsupportedProgramId),
16111624
);
16121625

16131626
// Error: Program fails verification
@@ -1616,7 +1629,7 @@ mod tests {
16161629
&[0, 1, 2, 3],
16171630
transaction_accounts,
16181631
&[(1, false, true)],
1619-
Err(InstructionError::InvalidAccountData),
1632+
Err(InstructionError::UnsupportedProgramId),
16201633
);
16211634
}
16221635
}

0 commit comments

Comments
 (0)