Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test-validator: Verify program ELFs #4192

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions test-validator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ log = { workspace = true }
serde_derive = { workspace = true }
serde_json = { workspace = true }
solana-accounts-db = { workspace = true }
solana-bpf-loader-program = { workspace = true }
solana-cli-output = { workspace = true }
solana-compute-budget = { workspace = true }
solana-core = { workspace = true }
Expand All @@ -31,6 +32,7 @@ solana-rpc = { workspace = true }
solana-rpc-client = { workspace = true }
solana-rpc-client-api = { workspace = true }
solana-runtime = { workspace = true }
solana-sbpf = { workspace = true }
solana-sdk = { workspace = true, features = ["openssl-vendored"] }
solana-streamer = { workspace = true }
solana-tpu-client = { workspace = true }
Expand Down
22 changes: 22 additions & 0 deletions test-validator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use {
hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
utils::create_accounts_run_and_snapshot_dirs,
},
solana_bpf_loader_program::syscalls::create_program_runtime_environment_v1,
solana_cli_output::CliAccount,
solana_compute_budget::compute_budget::ComputeBudget,
solana_core::{
Expand All @@ -30,6 +31,7 @@ use {
create_new_tmp_ledger,
},
solana_net_utils::PortRange,
solana_program_test::InvokeContext,
solana_rpc::{rpc::JsonRpcConfig, rpc_pubsub_service::PubSubConfig},
solana_rpc_client::{nonblocking, rpc_client::RpcClient},
solana_rpc_client_api::request::MAX_MULTIPLE_ACCOUNTS,
Expand All @@ -39,6 +41,7 @@ use {
runtime_config::RuntimeConfig,
snapshot_config::SnapshotConfig,
},
solana_sbpf::{elf::Executable, verifier::RequisiteVerifier},
solana_sdk::{
account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
bpf_loader_upgradeable::UpgradeableLoaderState,
Expand Down Expand Up @@ -790,12 +793,31 @@ impl TestValidator {
let validator_stake_lamports = sol_to_lamports(1_000_000.);
let mint_lamports = sol_to_lamports(500_000_000.);

let mut feature_set = FeatureSet::all_enabled();
for feature in &config.deactivate_feature_set {
feature_set.deactivate(feature);
}
Comment on lines +796 to +799
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This duplicates a similar logic below:

// Only activate features which are not explicitly deactivated.
let mut feature_set = FeatureSet::default().inactive;
for feature in &config.deactivate_feature_set {
if feature_set.remove(feature) {
info!("Feature for {:?} deactivated", feature)
} else {
warn!(
"Feature {:?} set for deactivation is not a known Feature public key",
feature,
)
}
}

I wanted to avoid making changes to the existing code to make it easier to review. Would it be better to refactor this to avoid duplicating the logic, or should I keep it as is?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think it might be better to add a little refactoring like you said. It looks to me like you could slide the block you've linked up a bit, refactor it to use a FeatureSet instance, and then plug a reference to that into the ELF's program runtime environment. Then we can use the same FeatureSet instance to activate features in the genesis config.

let program_runtime_environment = create_program_runtime_environment_v1(
&feature_set,
&ComputeBudget::default(),
true,
false,
)?;
let program_runtime_environment = Arc::new(program_runtime_environment);

let mut accounts = config.accounts.clone();
for (address, account) in solana_program_test::programs::spl_programs(&config.rent) {
accounts.entry(address).or_insert(account);
}
for upgradeable_program in &config.upgradeable_programs {
let data = solana_program_test::read_file(&upgradeable_program.program_path);
let executable =
Executable::<InvokeContext>::from_elf(&data, program_runtime_environment.clone())
.map_err(|err| format!("ELF error: {err}"))?;
executable
.verify::<RequisiteVerifier>()
.map_err(|err| format!("ELF error: {err}"))?;

let (programdata_address, _) = Pubkey::find_program_address(
&[upgradeable_program.program_id.as_ref()],
&upgradeable_program.loader,
Expand Down