Skip to content

Commit d754789

Browse files
mergify[bot]willhickey
authored andcommitted
v1.18: Fix: deploy program on last slot of epoch during environment change (backport of pyth-network#101) (#387)
1 parent f614727 commit d754789

File tree

8 files changed

+297
-54
lines changed

8 files changed

+297
-54
lines changed

ledger-tool/src/program.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,12 @@ use {
2121
},
2222
solana_runtime::bank::Bank,
2323
solana_sdk::{
24-
account::AccountSharedData,
24+
account::{create_account_shared_data_for_test, AccountSharedData},
2525
account_utils::StateMut,
2626
bpf_loader_upgradeable::{self, UpgradeableLoaderState},
2727
pubkey::Pubkey,
2828
slot_history::Slot,
29+
sysvar,
2930
transaction_context::{IndexOfAccount, InstructionAccount},
3031
},
3132
std::{
@@ -510,18 +511,16 @@ pub fn program(ledger_path: &Path, matches: &ArgMatches<'_>) {
510511
program_id, // ID of the loaded program. It can modify accounts with the same owner key
511512
AccountSharedData::new(0, 0, &loader_id),
512513
));
514+
transaction_accounts.push((
515+
sysvar::epoch_schedule::id(),
516+
create_account_shared_data_for_test(bank.epoch_schedule()),
517+
));
513518
let interpreted = matches.value_of("mode").unwrap() != "jit";
514519
with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
515520

516521
// Adding `DELAY_VISIBILITY_SLOT_OFFSET` to slots to accommodate for delay visibility of the program
517-
let mut loaded_programs = LoadedProgramsForTxBatch::new(
518-
bank.slot() + DELAY_VISIBILITY_SLOT_OFFSET,
519-
bank.loaded_programs_cache
520-
.read()
521-
.unwrap()
522-
.environments
523-
.clone(),
524-
);
522+
let mut loaded_programs =
523+
bank.new_program_cache_for_tx_batch_for_slot(bank.slot() + DELAY_VISIBILITY_SLOT_OFFSET);
525524
for key in cached_account_keys {
526525
loaded_programs.replenish(key, bank.load_program(&key, false, None));
527526
debug!("Loaded program {}", key);

program-runtime/src/invoke_context.rs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ use {
22
crate::{
33
compute_budget::ComputeBudget,
44
ic_msg,
5-
loaded_programs::{LoadedProgram, LoadedProgramType, LoadedProgramsForTxBatch},
5+
loaded_programs::{
6+
LoadedProgram, LoadedProgramType, LoadedProgramsForTxBatch, ProgramRuntimeEnvironments,
7+
},
68
log_collector::LogCollector,
79
stable_log,
810
sysvar_cache::SysvarCache,
@@ -17,15 +19,18 @@ use {
1719
vm::{Config, ContextObject, EbpfVm},
1820
},
1921
solana_sdk::{
20-
account::AccountSharedData,
22+
account::{create_account_shared_data_for_test, AccountSharedData},
2123
bpf_loader_deprecated,
24+
clock::Slot,
25+
epoch_schedule::EpochSchedule,
2226
feature_set::FeatureSet,
2327
hash::Hash,
2428
instruction::{AccountMeta, InstructionError},
2529
native_loader,
2630
pubkey::Pubkey,
2731
saturating_add_assign,
2832
stable_layout::stable_instruction::StableInstruction,
33+
sysvar,
2934
transaction_context::{
3035
IndexOfAccount, InstructionAccount, TransactionAccount, TransactionContext,
3136
},
@@ -209,6 +214,17 @@ impl<'a> InvokeContext<'a> {
209214
.or_else(|| self.programs_loaded_for_tx_batch.find(pubkey))
210215
}
211216

217+
pub fn get_environments_for_slot(
218+
&self,
219+
effective_slot: Slot,
220+
) -> Result<&ProgramRuntimeEnvironments, InstructionError> {
221+
let epoch_schedule = self.sysvar_cache.get_epoch_schedule()?;
222+
let epoch = epoch_schedule.get_epoch(effective_slot);
223+
Ok(self
224+
.programs_loaded_for_tx_batch
225+
.get_environments_for_epoch(epoch))
226+
}
227+
212228
/// Push a stack frame onto the invocation stack
213229
pub fn push(&mut self) -> Result<(), InstructionError> {
214230
let instruction_context = self
@@ -713,6 +729,18 @@ pub fn mock_process_instruction<F: FnMut(&mut InvokeContext), G: FnMut(&mut Invo
713729
program_indices.insert(0, transaction_accounts.len() as IndexOfAccount);
714730
let processor_account = AccountSharedData::new(0, 0, &native_loader::id());
715731
transaction_accounts.push((*loader_id, processor_account));
732+
let pop_epoch_schedule_account = if !transaction_accounts
733+
.iter()
734+
.any(|(key, _)| *key == sysvar::epoch_schedule::id())
735+
{
736+
transaction_accounts.push((
737+
sysvar::epoch_schedule::id(),
738+
create_account_shared_data_for_test(&EpochSchedule::default()),
739+
));
740+
true
741+
} else {
742+
false
743+
};
716744
with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
717745
let mut programs_loaded_for_tx_batch = LoadedProgramsForTxBatch::default();
718746
programs_loaded_for_tx_batch.replenish(
@@ -731,6 +759,9 @@ pub fn mock_process_instruction<F: FnMut(&mut InvokeContext), G: FnMut(&mut Invo
731759
assert_eq!(result, expected_result);
732760
post_adjustments(&mut invoke_context);
733761
let mut transaction_accounts = transaction_context.deconstruct_without_keys().unwrap();
762+
if pop_epoch_schedule_account {
763+
transaction_accounts.pop();
764+
}
734765
transaction_accounts.pop();
735766
transaction_accounts
736767
}

0 commit comments

Comments
 (0)