Return implicit delay visibility tombstone (#31493)

This commit is contained in:
Pankaj Garg 2023-05-05 06:08:57 -07:00 committed by GitHub
parent c5e071c7fe
commit 9c6e7e0435
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 49 additions and 10 deletions

View File

@ -25,6 +25,7 @@ use {
};
const MAX_LOADED_ENTRY_COUNT: usize = 256;
const DELAY_VISIBILITY_SLOT_OFFSET: Slot = 1;
/// Relationship between two fork IDs
#[derive(Copy, Clone, PartialEq)]
@ -231,8 +232,8 @@ impl LoadedProgram {
}
pub fn new_tombstone(slot: Slot, reason: LoadedProgramType) -> Self {
let maybe_expiration_slot =
matches!(reason, LoadedProgramType::DelayVisibility).then_some(slot.saturating_add(1));
let maybe_expiration_slot = matches!(reason, LoadedProgramType::DelayVisibility)
.then_some(slot.saturating_add(DELAY_VISIBILITY_SLOT_OFFSET));
let tombstone = Self {
program: reason,
account_size: 0,
@ -429,6 +430,18 @@ impl LoadedPrograms {
if current_slot >= entry.effective_slot {
return Some((key, entry.clone()));
} else if entry.effective_slot.saturating_sub(entry.deployment_slot)
== DELAY_VISIBILITY_SLOT_OFFSET
&& current_slot >= entry.deployment_slot
{
// Found a program entry on the current fork, but it's not effective
// yet. It indicates that the program has delayed visibility. Return
// the tombstone to reflect that.
let delay_visibility = LoadedProgram::new_tombstone(
entry.deployment_slot,
LoadedProgramType::DelayVisibility,
);
return Some((key, Arc::new(delay_visibility)));
}
}
}
@ -533,7 +546,7 @@ mod tests {
use {
crate::loaded_programs::{
BlockRelation, ForkGraph, LoadedProgram, LoadedProgramMatchCriteria, LoadedProgramType,
LoadedPrograms, LoadedProgramsForTxBatch, WorkingSlot,
LoadedPrograms, LoadedProgramsForTxBatch, WorkingSlot, DELAY_VISIBILITY_SLOT_OFFSET,
},
percentage::Percentage,
solana_rbpf::vm::BuiltInProgram,
@ -1100,7 +1113,14 @@ mod tests {
let program2 = Pubkey::new_unique();
assert!(!cache.replenish(program2, new_test_loaded_program(5, 6)).0);
assert!(!cache.replenish(program2, new_test_loaded_program(11, 12)).0);
assert!(
!cache
.replenish(
program2,
new_test_loaded_program(11, 11 + DELAY_VISIBILITY_SLOT_OFFSET)
)
.0
);
let program3 = Pubkey::new_unique();
assert!(!cache.replenish(program3, new_test_loaded_program(25, 26)).0);
@ -1109,7 +1129,14 @@ mod tests {
assert!(!cache.replenish(program4, new_test_loaded_program(0, 1)).0);
assert!(!cache.replenish(program4, new_test_loaded_program(5, 6)).0);
// The following is a special case, where effective slot is 3 slots in the future
assert!(!cache.replenish(program4, new_test_loaded_program(15, 18)).0);
assert!(
!cache
.replenish(
program4,
new_test_loaded_program(15, 15 + DELAY_VISIBILITY_SLOT_OFFSET)
)
.0
);
// Current fork graph
// 0
@ -1146,7 +1173,7 @@ mod tests {
assert!(missing.contains(&program3));
// Testing fork 0 - 5 - 11 - 15 - 16 with current slot at 16
let mut working_slot = TestWorkingSlot::new(16, &[0, 5, 11, 15, 16, 18, 19, 23]);
let mut working_slot = TestWorkingSlot::new(15, &[0, 5, 11, 15, 16, 18, 19, 23]);
let (found, missing) = cache.extract(
&working_slot,
vec![
@ -1158,11 +1185,17 @@ mod tests {
.into_iter(),
);
assert!(match_slot(&found, &program1, 0, 16));
assert!(match_slot(&found, &program2, 11, 16));
assert!(match_slot(&found, &program1, 0, 15));
assert!(match_slot(&found, &program2, 11, 15));
// The effective slot of program4 deployed in slot 15 is 19. So it should not be usable in slot 16.
assert!(match_slot(&found, &program4, 5, 16));
// A delay visibility tombstone should be returned here.
let tombstone = found.find(program4).expect("Failed to find the tombstone");
assert!(matches!(
tombstone.program,
LoadedProgramType::DelayVisibility
));
assert_eq!(tombstone.deployment_slot, 15);
assert!(missing.contains(&program3));
@ -1222,7 +1255,13 @@ mod tests {
);
assert!(match_slot(&found, &program1, 0, 11));
assert!(match_slot(&found, &program2, 5, 11));
// program2 was updated at slot 11, but is not effective till slot 12. The result should contain a tombstone.
let tombstone = found.find(program2).expect("Failed to find the tombstone");
assert!(matches!(
tombstone.program,
LoadedProgramType::DelayVisibility
));
assert_eq!(tombstone.deployment_slot, 11);
assert!(match_slot(&found, &program4, 5, 11));
assert!(missing.contains(&program3));