Skip to content

Commit

Permalink
SVM: add new bootstrap method (solana-labs#3203)
Browse files Browse the repository at this point in the history
* SVM: add `new` bootstrap method

* SVM: add `configure_program_runtime_environments` method
  • Loading branch information
buffalojoec authored Nov 9, 2024
1 parent a1c01a8 commit 20dde4b
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 61 deletions.
33 changes: 16 additions & 17 deletions runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5143,23 +5143,22 @@ impl Bank {
}
}

let mut program_cache = self.transaction_processor.program_cache.write().unwrap();
program_cache.latest_root_slot = self.slot();
program_cache.latest_root_epoch = self.epoch();
program_cache.environments.program_runtime_v1 = Arc::new(
create_program_runtime_environment_v1(
&self.feature_set,
&self.compute_budget().unwrap_or_default(),
false, /* deployment */
false, /* debugging_features */
)
.unwrap(),
);
program_cache.environments.program_runtime_v2 =
Arc::new(create_program_runtime_environment_v2(
&self.compute_budget().unwrap_or_default(),
false, /* debugging_features */
));
self.transaction_processor
.configure_program_runtime_environments(
Some(Arc::new(
create_program_runtime_environment_v1(
&self.feature_set,
&self.compute_budget().unwrap_or_default(),
false, /* deployment */
false, /* debugging_features */
)
.unwrap(),
)),
Some(Arc::new(create_program_runtime_environment_v2(
&self.compute_budget().unwrap_or_default(),
false, /* debugging_features */
))),
);
}

pub fn set_inflation(&self, inflation: Inflation) {
Expand Down
23 changes: 8 additions & 15 deletions svm/examples/paytube/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,16 @@ pub(crate) fn create_transaction_batch_processor<CB: TransactionProcessingCallba
// marked as "depoyed" in slot 0.
// See `solana_svm::program_loader::load_program_with_pubkey` for more
// details.
let processor = TransactionBatchProcessor::<PayTubeForkGraph>::new_uninitialized(
/* slot */ 1, /* epoch */ 1,
);

{
let mut cache = processor.program_cache.write().unwrap();

// Initialize the mocked fork graph.
cache.fork_graph = Some(Arc::downgrade(&fork_graph));

// Initialize a proper cache environment.
// (Use Loader v4 program to initialize runtime v2 if desired)
cache.environments.program_runtime_v1 = Arc::new(
let processor = TransactionBatchProcessor::<PayTubeForkGraph>::new(
/* slot */ 1,
/* epoch */ 1,
Arc::downgrade(&fork_graph),
Some(Arc::new(
create_program_runtime_environment_v1(feature_set, compute_budget, false, false)
.unwrap(),
);
}
)),
None,
);

// Add the system program builtin.
processor.add_builtin(
Expand Down
85 changes: 75 additions & 10 deletions svm/src/transaction_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ use {
invoke_context::{EnvironmentConfig, InvokeContext},
loaded_programs::{
ForkGraph, ProgramCache, ProgramCacheEntry, ProgramCacheForTxBatch,
ProgramCacheMatchCriteria,
ProgramCacheMatchCriteria, ProgramRuntimeEnvironment,
},
solana_rbpf::{
program::{BuiltinProgram, FunctionRegistry},
vm::Config as VmConfig,
},
sysvar_cache::SysvarCache,
},
Expand Down Expand Up @@ -62,6 +66,7 @@ use {
collections::{hash_map::Entry, HashMap, HashSet},
fmt::{Debug, Formatter},
rc::Rc,
sync::Weak,
},
};

Expand Down Expand Up @@ -227,6 +232,34 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
}
}

/// Create a new `TransactionBatchProcessor`.
///
/// The created processor's program cache is initialized with the provided
/// fork graph and loaders. If any loaders are omitted, a default "empty"
/// loader (no syscalls) will be used.
///
/// The cache will still not contain any builtin programs. It's advisable to
/// call `add_builtin` to add the required builtins before using the processor.
pub fn new(
slot: Slot,
epoch: Epoch,
fork_graph: Weak<RwLock<FG>>,
program_runtime_environment_v1: Option<ProgramRuntimeEnvironment>,
program_runtime_environment_v2: Option<ProgramRuntimeEnvironment>,
) -> Self {
let processor = Self::new_uninitialized(slot, epoch);
{
let mut program_cache = processor.program_cache.write().unwrap();
program_cache.set_fork_graph(fork_graph);
processor.configure_program_runtime_environments_inner(
&mut program_cache,
program_runtime_environment_v1,
program_runtime_environment_v2,
);
}
processor
}

/// Create a new `TransactionBatchProcessor` from the current instance, but
/// with the provided slot and epoch.
///
Expand All @@ -243,6 +276,41 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
}
}

fn configure_program_runtime_environments_inner(
&self,
program_cache: &mut ProgramCache<FG>,
program_runtime_environment_v1: Option<ProgramRuntimeEnvironment>,
program_runtime_environment_v2: Option<ProgramRuntimeEnvironment>,
) {
let empty_loader = || {
Arc::new(BuiltinProgram::new_loader(
VmConfig::default(),
FunctionRegistry::default(),
))
};

program_cache.latest_root_slot = self.slot;
program_cache.latest_root_epoch = self.epoch;
program_cache.environments.program_runtime_v1 =
program_runtime_environment_v1.unwrap_or(empty_loader());
program_cache.environments.program_runtime_v2 =
program_runtime_environment_v2.unwrap_or(empty_loader());
}

/// Configures the program runtime environments (loaders) in the
/// transaction processor's program cache.
pub fn configure_program_runtime_environments(
&self,
program_runtime_environment_v1: Option<ProgramRuntimeEnvironment>,
program_runtime_environment_v2: Option<ProgramRuntimeEnvironment>,
) {
self.configure_program_runtime_environments_inner(
&mut self.program_cache.write().unwrap(),
program_runtime_environment_v1,
program_runtime_environment_v2,
);
}

/// Returns the current environments depending on the given epoch
/// Returns None if the call could result in a deadlock
#[cfg(feature = "dev-context-only-utils")]
Expand Down Expand Up @@ -1396,10 +1464,9 @@ mod tests {
#[should_panic = "called load_program_with_pubkey() with nonexistent account"]
fn test_replenish_program_cache_with_nonexistent_accounts() {
let mock_bank = MockBankCallback::default();
let batch_processor = TransactionBatchProcessor::<TestForkGraph>::default();
let fork_graph = Arc::new(RwLock::new(TestForkGraph {}));
batch_processor.program_cache.write().unwrap().fork_graph =
Some(Arc::downgrade(&fork_graph));
let batch_processor =
TransactionBatchProcessor::new(0, 0, Arc::downgrade(&fork_graph), None, None);
let key = Pubkey::new_unique();
let owner = Pubkey::new_unique();

Expand All @@ -1412,10 +1479,9 @@ mod tests {
#[test]
fn test_replenish_program_cache() {
let mock_bank = MockBankCallback::default();
let batch_processor = TransactionBatchProcessor::<TestForkGraph>::default();
let fork_graph = Arc::new(RwLock::new(TestForkGraph {}));
batch_processor.program_cache.write().unwrap().fork_graph =
Some(Arc::downgrade(&fork_graph));
let batch_processor =
TransactionBatchProcessor::new(0, 0, Arc::downgrade(&fork_graph), None, None);
let key = Pubkey::new_unique();
let owner = Pubkey::new_unique();

Expand Down Expand Up @@ -1901,10 +1967,9 @@ mod tests {
#[test]
fn test_add_builtin() {
let mock_bank = MockBankCallback::default();
let batch_processor = TransactionBatchProcessor::<TestForkGraph>::default();
let fork_graph = Arc::new(RwLock::new(TestForkGraph {}));
batch_processor.program_cache.write().unwrap().fork_graph =
Some(Arc::downgrade(&fork_graph));
let batch_processor =
TransactionBatchProcessor::new(0, 0, Arc::downgrade(&fork_graph), None, None);

let key = Pubkey::new_unique();
let name = "a_builtin_name";
Expand Down
4 changes: 2 additions & 2 deletions svm/tests/concurrent_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ mod transaction_builder;

fn program_cache_execution(threads: usize) {
let mut mock_bank = MockBankCallback::default();
let batch_processor = TransactionBatchProcessor::<MockForkGraph>::new_uninitialized(5, 5);
let fork_graph = Arc::new(RwLock::new(MockForkGraph {}));
batch_processor.program_cache.write().unwrap().fork_graph = Some(Arc::downgrade(&fork_graph));
let batch_processor =
TransactionBatchProcessor::new(5, 5, Arc::downgrade(&fork_graph), None, None);

const LOADER: Pubkey = bpf_loader_upgradeable::id();
let programs = vec![
Expand Down
25 changes: 8 additions & 17 deletions svm/tests/conformance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@ use {
solana_log_collector::LogCollector,
solana_program_runtime::{
invoke_context::{EnvironmentConfig, InvokeContext},
loaded_programs::{ProgramCacheEntry, ProgramCacheForTxBatch, ProgramRuntimeEnvironments},
solana_rbpf::{
program::{BuiltinProgram, FunctionRegistry},
vm::Config,
},
loaded_programs::{ProgramCacheEntry, ProgramCacheForTxBatch},
},
solana_sdk::{
account::{AccountSharedData, ReadableAccount, WritableAccount},
Expand Down Expand Up @@ -244,20 +240,15 @@ fn run_fixture(fixture: InstrFixture, filename: OsString, execute_as_instr: bool
create_program_runtime_environment_v1(&feature_set, &compute_budget, false, false).unwrap();

mock_bank.override_feature_set(feature_set);
let batch_processor = TransactionBatchProcessor::<MockForkGraph>::new_uninitialized(42, 2);

let fork_graph = Arc::new(RwLock::new(MockForkGraph {}));
{
let mut program_cache = batch_processor.program_cache.write().unwrap();
program_cache.environments = ProgramRuntimeEnvironments {
program_runtime_v1: Arc::new(v1_environment),
program_runtime_v2: Arc::new(BuiltinProgram::new_loader(
Config::default(),
FunctionRegistry::default(),
)),
};
program_cache.fork_graph = Some(Arc::downgrade(&fork_graph.clone()));
}
let batch_processor = TransactionBatchProcessor::new(
42,
2,
Arc::downgrade(&fork_graph),
Some(Arc::new(v1_environment)),
None,
);

batch_processor.fill_missing_sysvar_cache_entries(&mock_bank);
register_builtins(&batch_processor, &mock_bank);
Expand Down

0 comments on commit 20dde4b

Please sign in to comment.