Bank::create_executor() (#28474)

* Moves the integration test test_bpf_loader_upgradeable_deploy_with_max_len() from the bpf_loader into the runtime.

* Adds Bank::create_executor().

* Adds a test for Bank::create_executor().
This commit is contained in:
Alexander Meißner 2022-10-19 22:28:57 +02:00 committed by GitHub
parent 274d9ea607
commit 5aca7df232
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 831 additions and 722 deletions

2
Cargo.lock generated
View File

@ -4748,7 +4748,6 @@ dependencies = [
"solana-measure",
"solana-metrics",
"solana-program-runtime",
"solana-runtime",
"solana-sdk 1.15.0",
"solana-zk-token-sdk 1.15.0",
"solana_rbpf",
@ -6150,6 +6149,7 @@ dependencies = [
"serde",
"serde_derive",
"solana-address-lookup-table-program",
"solana-bpf-loader-program",
"solana-bucket-map",
"solana-compute-budget-program",
"solana-config-program",

View File

@ -24,7 +24,6 @@ thiserror = "1.0"
[dev-dependencies]
rand = "0.7.3"
solana-runtime = { path = "../../runtime", version = "=1.15.0" }
[lib]
crate-type = ["lib"]

View File

@ -1525,27 +1525,19 @@ mod tests {
rand::Rng,
solana_program_runtime::invoke_context::mock_process_instruction,
solana_rbpf::{ebpf::MM_INPUT_START, verifier::Verifier, vm::SyscallRegistry},
solana_runtime::{bank::Bank, bank_client::BankClient},
solana_sdk::{
account::{
create_account_shared_data_for_test as create_account_for_test, AccountSharedData,
ReadableAccount, WritableAccount,
},
account_utils::StateMut,
client::SyncClient,
clock::Clock,
feature_set::FeatureSet,
genesis_config::create_genesis_config,
instruction::{AccountMeta, Instruction, InstructionError},
message::Message,
native_token::LAMPORTS_PER_SOL,
instruction::{AccountMeta, InstructionError},
pubkey::Pubkey,
rent::Rent,
signature::{Keypair, Signer},
system_program, sysvar,
transaction::TransactionError,
sysvar,
},
std::{fs::File, io::Read, ops::Range, sync::Arc},
std::{fs::File, io::Read, ops::Range},
};
struct TestInstructionMeter {
@ -2260,711 +2252,6 @@ mod tests {
account.set_data(data);
}
#[test]
fn test_bpf_loader_upgradeable_deploy_with_max_len() {
let (genesis_config, mint_keypair) = create_genesis_config(1_000_000_000);
let mut bank = Bank::new_for_tests(&genesis_config);
bank.feature_set = Arc::new(FeatureSet::all_enabled());
bank.add_builtin(
"solana_bpf_loader_upgradeable_program",
&bpf_loader_upgradeable::id(),
super::process_instruction,
);
let bank = Arc::new(bank);
let bank_client = BankClient::new_shared(&bank);
// Setup keypairs and addresses
let payer_keypair = Keypair::new();
let program_keypair = Keypair::new();
let buffer_address = Pubkey::new_unique();
let (programdata_address, _) = Pubkey::find_program_address(
&[program_keypair.pubkey().as_ref()],
&bpf_loader_upgradeable::id(),
);
let upgrade_authority_keypair = Keypair::new();
// Load program file
let mut file = File::open("test_elfs/out/noop_aligned.so").expect("file open failed");
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
// Compute rent exempt balances
let program_len = elf.len();
let min_program_balance =
bank.get_minimum_balance_for_rent_exemption(UpgradeableLoaderState::size_of_program());
let min_buffer_balance = bank.get_minimum_balance_for_rent_exemption(
UpgradeableLoaderState::size_of_buffer(program_len),
);
let min_programdata_balance = bank.get_minimum_balance_for_rent_exemption(
UpgradeableLoaderState::size_of_programdata(program_len),
);
// Setup accounts
let buffer_account = {
let mut account = AccountSharedData::new(
min_buffer_balance,
UpgradeableLoaderState::size_of_buffer(elf.len()),
&bpf_loader_upgradeable::id(),
);
account
.set_state(&UpgradeableLoaderState::Buffer {
authority_address: Some(upgrade_authority_keypair.pubkey()),
})
.unwrap();
account
.data_as_mut_slice()
.get_mut(UpgradeableLoaderState::size_of_buffer_metadata()..)
.unwrap()
.copy_from_slice(&elf);
account
};
let program_account = AccountSharedData::new(
min_programdata_balance,
UpgradeableLoaderState::size_of_program(),
&bpf_loader_upgradeable::id(),
);
let programdata_account = AccountSharedData::new(
1,
UpgradeableLoaderState::size_of_programdata(elf.len()),
&bpf_loader_upgradeable::id(),
);
// Test successful deploy
let payer_base_balance = LAMPORTS_PER_SOL;
let deploy_fees = {
let fee_calculator = genesis_config.fee_rate_governor.create_fee_calculator();
3 * fee_calculator.lamports_per_signature
};
let min_payer_balance = min_program_balance
.saturating_add(min_programdata_balance)
.saturating_sub(min_buffer_balance.saturating_add(deploy_fees));
bank.store_account(
&payer_keypair.pubkey(),
&AccountSharedData::new(
payer_base_balance.saturating_add(min_payer_balance),
0,
&system_program::id(),
),
);
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&payer_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap(),
Some(&payer_keypair.pubkey()),
);
assert!(bank_client
.send_and_confirm_message(
&[&payer_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.is_ok());
assert_eq!(
bank.get_balance(&payer_keypair.pubkey()),
payer_base_balance
);
assert_eq!(bank.get_balance(&buffer_address), 0);
assert_eq!(None, bank.get_account(&buffer_address));
let post_program_account = bank.get_account(&program_keypair.pubkey()).unwrap();
assert_eq!(post_program_account.lamports(), min_program_balance);
assert_eq!(post_program_account.owner(), &bpf_loader_upgradeable::id());
assert_eq!(
post_program_account.data().len(),
UpgradeableLoaderState::size_of_program()
);
let state: UpgradeableLoaderState = post_program_account.state().unwrap();
assert_eq!(
state,
UpgradeableLoaderState::Program {
programdata_address
}
);
let post_programdata_account = bank.get_account(&programdata_address).unwrap();
assert_eq!(post_programdata_account.lamports(), min_programdata_balance);
assert_eq!(
post_programdata_account.owner(),
&bpf_loader_upgradeable::id()
);
let state: UpgradeableLoaderState = post_programdata_account.state().unwrap();
assert_eq!(
state,
UpgradeableLoaderState::ProgramData {
slot: bank_client.get_slot().unwrap(),
upgrade_authority_address: Some(upgrade_authority_keypair.pubkey())
}
);
for (i, byte) in post_programdata_account
.data()
.get(UpgradeableLoaderState::size_of_programdata_metadata()..)
.unwrap()
.iter()
.enumerate()
{
assert_eq!(*elf.get(i).unwrap(), *byte);
}
// Invoke deployed program
process_instruction(
&bpf_loader_upgradeable::id(),
&[0, 1],
&[],
vec![
(programdata_address, post_programdata_account),
(program_keypair.pubkey(), post_program_account),
],
Vec::new(),
Ok(()),
);
// Test initialized program account
bank.clear_signatures();
bank.store_account(&buffer_address, &buffer_account);
let message = Message::new(
&[Instruction::new_with_bincode(
bpf_loader_upgradeable::id(),
&UpgradeableLoaderInstruction::DeployWithMaxDataLen {
max_data_len: elf.len(),
},
vec![
AccountMeta::new(mint_keypair.pubkey(), true),
AccountMeta::new(programdata_address, false),
AccountMeta::new(program_keypair.pubkey(), false),
AccountMeta::new(buffer_address, false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(system_program::id(), false),
AccountMeta::new_readonly(upgrade_authority_keypair.pubkey(), true),
],
)],
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(0, InstructionError::AccountAlreadyInitialized),
bank_client
.send_and_confirm_message(&[&mint_keypair, &upgrade_authority_keypair], message)
.unwrap_err()
.unwrap()
);
// Test initialized ProgramData account
bank.clear_signatures();
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::Custom(0)),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Test deploy no authority
bank.clear_signatures();
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &program_account);
bank.store_account(&programdata_address, &programdata_account);
let message = Message::new(
&[Instruction::new_with_bincode(
bpf_loader_upgradeable::id(),
&UpgradeableLoaderInstruction::DeployWithMaxDataLen {
max_data_len: elf.len(),
},
vec![
AccountMeta::new(mint_keypair.pubkey(), true),
AccountMeta::new(programdata_address, false),
AccountMeta::new(program_keypair.pubkey(), false),
AccountMeta::new(buffer_address, false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(system_program::id(), false),
],
)],
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(0, InstructionError::NotEnoughAccountKeys),
bank_client
.send_and_confirm_message(&[&mint_keypair], message)
.unwrap_err()
.unwrap()
);
// Test deploy authority not a signer
bank.clear_signatures();
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &program_account);
bank.store_account(&programdata_address, &programdata_account);
let message = Message::new(
&[Instruction::new_with_bincode(
bpf_loader_upgradeable::id(),
&UpgradeableLoaderInstruction::DeployWithMaxDataLen {
max_data_len: elf.len(),
},
vec![
AccountMeta::new(mint_keypair.pubkey(), true),
AccountMeta::new(programdata_address, false),
AccountMeta::new(program_keypair.pubkey(), false),
AccountMeta::new(buffer_address, false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(system_program::id(), false),
AccountMeta::new_readonly(upgrade_authority_keypair.pubkey(), false),
],
)],
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(0, InstructionError::MissingRequiredSignature),
bank_client
.send_and_confirm_message(&[&mint_keypair], message)
.unwrap_err()
.unwrap()
);
// Test invalid Buffer account state
bank.clear_signatures();
bank.store_account(&buffer_address, &AccountSharedData::default());
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::InvalidAccountData),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Test program account not rent exempt
bank.clear_signatures();
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance.saturating_sub(1),
elf.len(),
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::ExecutableAccountNotRentExempt),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Test program account not rent exempt because data is larger than needed
bank.clear_signatures();
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let mut instructions = bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap();
*instructions.get_mut(0).unwrap() = system_instruction::create_account(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
min_program_balance,
(UpgradeableLoaderState::size_of_program() as u64).saturating_add(1),
&id(),
);
let message = Message::new(&instructions, Some(&mint_keypair.pubkey()));
assert_eq!(
TransactionError::InstructionError(1, InstructionError::ExecutableAccountNotRentExempt),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Test program account too small
bank.clear_signatures();
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let mut instructions = bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap();
*instructions.get_mut(0).unwrap() = system_instruction::create_account(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
min_program_balance,
(UpgradeableLoaderState::size_of_program() as u64).saturating_sub(1),
&id(),
);
let message = Message::new(&instructions, Some(&mint_keypair.pubkey()));
assert_eq!(
TransactionError::InstructionError(1, InstructionError::AccountDataTooSmall),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Test Insufficient payer funds (need more funds to cover the
// difference between buffer lamports and programdata lamports)
bank.clear_signatures();
bank.store_account(
&mint_keypair.pubkey(),
&AccountSharedData::new(
deploy_fees.saturating_add(min_program_balance),
0,
&system_program::id(),
),
);
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::Custom(1)),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
bank.store_account(
&mint_keypair.pubkey(),
&AccountSharedData::new(1_000_000_000, 0, &system_program::id()),
);
// Test max_data_len
bank.clear_signatures();
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len().saturating_sub(1),
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::AccountDataTooSmall),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Test max_data_len too large
bank.clear_signatures();
bank.store_account(
&mint_keypair.pubkey(),
&AccountSharedData::new(u64::MAX / 2, 0, &system_program::id()),
);
let mut modified_buffer_account = buffer_account.clone();
modified_buffer_account.set_lamports(u64::MAX / 2);
bank.store_account(&buffer_address, &modified_buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
usize::MAX,
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::InvalidArgument),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Test not the system account
bank.clear_signatures();
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let mut instructions = bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap();
*instructions
.get_mut(1)
.unwrap()
.accounts
.get_mut(6)
.unwrap() = AccountMeta::new_readonly(Pubkey::new_unique(), false);
let message = Message::new(&instructions, Some(&mint_keypair.pubkey()));
assert_eq!(
TransactionError::InstructionError(1, InstructionError::MissingAccount),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Test Bad ELF data
bank.clear_signatures();
let mut modified_buffer_account = buffer_account;
truncate_data(
&mut modified_buffer_account,
UpgradeableLoaderState::size_of_buffer(1),
);
bank.store_account(&buffer_address, &modified_buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::InvalidAccountData),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Test small buffer account
bank.clear_signatures();
let mut modified_buffer_account = AccountSharedData::new(
min_programdata_balance,
UpgradeableLoaderState::size_of_buffer(elf.len()),
&bpf_loader_upgradeable::id(),
);
modified_buffer_account
.set_state(&UpgradeableLoaderState::Buffer {
authority_address: Some(upgrade_authority_keypair.pubkey()),
})
.unwrap();
modified_buffer_account
.data_as_mut_slice()
.get_mut(UpgradeableLoaderState::size_of_buffer_metadata()..)
.unwrap()
.copy_from_slice(&elf);
truncate_data(&mut modified_buffer_account, 5);
bank.store_account(&buffer_address, &modified_buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::InvalidAccountData),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Mismatched buffer and program authority
bank.clear_signatures();
let mut modified_buffer_account = AccountSharedData::new(
min_programdata_balance,
UpgradeableLoaderState::size_of_buffer(elf.len()),
&bpf_loader_upgradeable::id(),
);
modified_buffer_account
.set_state(&UpgradeableLoaderState::Buffer {
authority_address: Some(buffer_address),
})
.unwrap();
modified_buffer_account
.data_as_mut_slice()
.get_mut(UpgradeableLoaderState::size_of_buffer_metadata()..)
.unwrap()
.copy_from_slice(&elf);
bank.store_account(&buffer_address, &modified_buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::IncorrectAuthority),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Deploy buffer with mismatched None authority
bank.clear_signatures();
let mut modified_buffer_account = AccountSharedData::new(
min_programdata_balance,
UpgradeableLoaderState::size_of_buffer(elf.len()),
&bpf_loader_upgradeable::id(),
);
modified_buffer_account
.set_state(&UpgradeableLoaderState::Buffer {
authority_address: None,
})
.unwrap();
modified_buffer_account
.data_as_mut_slice()
.get_mut(UpgradeableLoaderState::size_of_buffer_metadata()..)
.unwrap()
.copy_from_slice(&elf);
bank.store_account(&buffer_address, &modified_buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::IncorrectAuthority),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
}
#[test]
fn test_bpf_loader_upgradeable_upgrade() {
let mut file = File::open("test_elfs/out/noop_aligned.so").expect("file open failed");

View File

@ -5080,6 +5080,7 @@ dependencies = [
"serde",
"serde_derive",
"solana-address-lookup-table-program",
"solana-bpf-loader-program",
"solana-bucket-map",
"solana-compute-budget-program",
"solana-config-program",

View File

@ -41,6 +41,7 @@ regex = "1.6.0"
serde = { version = "1.0.144", features = ["rc"] }
serde_derive = "1.0.103"
solana-address-lookup-table-program = { path = "../programs/address-lookup-table", version = "=1.15.0" }
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.15.0" }
solana-bucket-map = { path = "../bucket_map", version = "=1.15.0" }
solana-compute-budget-program = { path = "../programs/compute-budget", version = "=1.15.0" }
solana-config-program = { path = "../programs/config", version = "=1.15.0" }

View File

@ -87,7 +87,7 @@ use {
accounts_data_meter::MAX_ACCOUNTS_DATA_LEN,
compute_budget::{self, ComputeBudget},
executor_cache::{
BankExecutorCache, TransactionExecutorCache, TxBankExecutorCacheDiff,
BankExecutorCache, Executor, TransactionExecutorCache, TxBankExecutorCacheDiff,
MAX_CACHED_EXECUTORS,
},
invoke_context::{BuiltinProgram, ProcessInstructionWithContext},
@ -101,6 +101,7 @@ use {
AccountSharedData, InheritableAccountFields, ReadableAccount, WritableAccount,
},
account_utils::StateMut,
bpf_loader_upgradeable::{self, UpgradeableLoaderState},
clock::{
BankId, Epoch, Slot, SlotCount, SlotIndex, UnixTimestamp, DEFAULT_TICKS_PER_SECOND,
INITIAL_RENT_EPOCH, MAX_PROCESSING_AGE, MAX_TRANSACTION_FORWARDING_DELAY,
@ -4044,6 +4045,73 @@ impl Bank {
});
}
#[allow(dead_code)] // Preparation for BankExecutorCache rework
fn create_executor(&self, pubkey: &Pubkey) -> Result<Arc<dyn Executor>> {
let program = if let Some(program) = self.get_account_with_fixed_root(pubkey) {
program
} else {
return Err(TransactionError::ProgramAccountNotFound);
};
let mut transaction_accounts = vec![(*pubkey, program)];
let is_upgradeable_loader =
bpf_loader_upgradeable::check_id(transaction_accounts[0].1.owner());
if is_upgradeable_loader {
if let Ok(UpgradeableLoaderState::Program {
programdata_address,
}) = transaction_accounts[0].1.state()
{
if let Some(programdata_account) =
self.get_account_with_fixed_root(&programdata_address)
{
transaction_accounts.push((programdata_address, programdata_account));
} else {
return Err(TransactionError::ProgramAccountNotFound);
}
} else {
return Err(TransactionError::ProgramAccountNotFound);
}
}
let mut transaction_context = TransactionContext::new(
transaction_accounts,
Some(sysvar::rent::Rent::default()),
1,
1,
);
let instruction_context = transaction_context
.get_next_instruction_context()
.map_err(|err| TransactionError::InstructionError(0, err))?;
instruction_context.configure(if is_upgradeable_loader { &[0, 1] } else { &[0] }, &[], &[]);
transaction_context
.push()
.map_err(|err| TransactionError::InstructionError(0, err))?;
let instruction_context = transaction_context
.get_current_instruction_context()
.map_err(|err| TransactionError::InstructionError(0, err))?;
let program = instruction_context
.try_borrow_program_account(&transaction_context, 0)
.map_err(|err| TransactionError::InstructionError(0, err))?;
let programdata = if is_upgradeable_loader {
Some(
instruction_context
.try_borrow_program_account(&transaction_context, 1)
.map_err(|err| TransactionError::InstructionError(0, err))?,
)
} else {
None
};
solana_bpf_loader_program::create_executor_from_account(
&self.feature_set,
&self.runtime_config.compute_budget.unwrap_or_default(),
None, // log_collector
None, // tx_executor_cache
&program,
programdata.as_ref().unwrap_or(&program),
self.runtime_config.bpf_jit,
)
.map(|(executor, _create_executor_metrics)| executor)
.map_err(|err| TransactionError::InstructionError(0, err))
}
/// Remove an executor from the bank's cache
fn remove_executor(&self, pubkey: &Pubkey) {
let _ = self.executor_cache.write().unwrap().remove(pubkey);
@ -7852,6 +7920,7 @@ pub(crate) mod tests {
accounts_db::DEFAULT_ACCOUNTS_SHRINK_RATIO,
accounts_index::{AccountIndex, AccountSecondaryIndexes, ScanError, ITER_BATCH_SIZE},
ancestors::Ancestors,
bank_client::BankClient,
genesis_utils::{
self, activate_all_features, bootstrap_validator_stake_lamports,
create_genesis_config_with_leader, create_genesis_config_with_vote_accounts,
@ -7866,12 +7935,14 @@ pub(crate) mod tests {
solana_program_runtime::{
compute_budget::MAX_COMPUTE_UNIT_LIMIT,
executor_cache::Executor,
invoke_context::InvokeContext,
invoke_context::{mock_process_instruction, InvokeContext},
prioritization_fee::{PrioritizationFeeDetails, PrioritizationFeeType},
},
solana_sdk::{
account::Account,
bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable,
bpf_loader, bpf_loader_deprecated,
bpf_loader_upgradeable::{self, UpgradeableLoaderState},
client::SyncClient,
clock::{DEFAULT_SLOTS_PER_EPOCH, DEFAULT_TICKS_PER_SLOT, MAX_RECENT_BLOCKHASHES},
compute_budget::ComputeBudgetInstruction,
entrypoint::MAX_PERMITTED_DATA_INCREASE,
@ -7880,6 +7951,7 @@ pub(crate) mod tests {
genesis_config::create_genesis_config,
hash,
instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
loader_upgradeable_instruction::UpgradeableLoaderInstruction,
message::{Message, MessageHeader},
native_token::LAMPORTS_PER_SOL,
nonce,
@ -7907,7 +7979,8 @@ pub(crate) mod tests {
},
},
std::{
result, str::FromStr, sync::atomic::Ordering::Release, thread::Builder, time::Duration,
fs::File, io::Read, result, str::FromStr, sync::atomic::Ordering::Release,
thread::Builder, time::Duration,
},
test_utils::goto_end_of_slot,
};
@ -15136,6 +15209,39 @@ pub(crate) mod tests {
assert!(stored_executors.borrow().executors.contains_key(&key2));
assert!(stored_executors.borrow().executors.contains_key(&key3));
// Force compilation of an executor
let mut file = File::open("../programs/bpf_loader/test_elfs/out/noop_aligned.so").unwrap();
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
let programdata_key = solana_sdk::pubkey::new_rand();
let mut program_account = AccountSharedData::new_data(
40,
&UpgradeableLoaderState::Program {
programdata_address: programdata_key,
},
&bpf_loader_upgradeable::id(),
)
.unwrap();
program_account.set_executable(true);
program_account.set_rent_epoch(1);
let programdata_data_offset = UpgradeableLoaderState::size_of_programdata_metadata();
let mut programdata_account = AccountSharedData::new(
40,
programdata_data_offset + elf.len(),
&bpf_loader_upgradeable::id(),
);
programdata_account
.set_state(&UpgradeableLoaderState::ProgramData {
slot: 42,
upgrade_authority_address: None,
})
.unwrap();
programdata_account.data_mut()[programdata_data_offset..].copy_from_slice(&elf);
programdata_account.set_rent_epoch(1);
bank.store_account_and_update_capitalization(&key1, &program_account);
bank.store_account_and_update_capitalization(&programdata_key, &programdata_account);
bank.create_executor(&key1).unwrap();
// Remove all
bank.remove_executor(&key1);
bank.remove_executor(&key2);
@ -15200,6 +15306,721 @@ pub(crate) mod tests {
assert_eq!(executors.borrow().executors.len(), 1);
}
#[test]
fn test_bpf_loader_upgradeable_deploy_with_max_len() {
let (genesis_config, mint_keypair) = create_genesis_config(1_000_000_000);
let mut bank = Bank::new_for_tests(&genesis_config);
bank.feature_set = Arc::new(FeatureSet::all_enabled());
bank.add_builtin(
"solana_bpf_loader_upgradeable_program",
&bpf_loader_upgradeable::id(),
solana_bpf_loader_program::process_instruction,
);
let bank = Arc::new(bank);
let bank_client = BankClient::new_shared(&bank);
// Setup keypairs and addresses
let payer_keypair = Keypair::new();
let program_keypair = Keypair::new();
let buffer_address = Pubkey::new_unique();
let (programdata_address, _) = Pubkey::find_program_address(
&[program_keypair.pubkey().as_ref()],
&bpf_loader_upgradeable::id(),
);
let upgrade_authority_keypair = Keypair::new();
// Load program file
let mut file = File::open("../programs/bpf_loader/test_elfs/out/noop_aligned.so")
.expect("file open failed");
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
// Compute rent exempt balances
let program_len = elf.len();
let min_program_balance =
bank.get_minimum_balance_for_rent_exemption(UpgradeableLoaderState::size_of_program());
let min_buffer_balance = bank.get_minimum_balance_for_rent_exemption(
UpgradeableLoaderState::size_of_buffer(program_len),
);
let min_programdata_balance = bank.get_minimum_balance_for_rent_exemption(
UpgradeableLoaderState::size_of_programdata(program_len),
);
// Setup accounts
let buffer_account = {
let mut account = AccountSharedData::new(
min_buffer_balance,
UpgradeableLoaderState::size_of_buffer(elf.len()),
&bpf_loader_upgradeable::id(),
);
account
.set_state(&UpgradeableLoaderState::Buffer {
authority_address: Some(upgrade_authority_keypair.pubkey()),
})
.unwrap();
account
.data_as_mut_slice()
.get_mut(UpgradeableLoaderState::size_of_buffer_metadata()..)
.unwrap()
.copy_from_slice(&elf);
account
};
let program_account = AccountSharedData::new(
min_programdata_balance,
UpgradeableLoaderState::size_of_program(),
&bpf_loader_upgradeable::id(),
);
let programdata_account = AccountSharedData::new(
1,
UpgradeableLoaderState::size_of_programdata(elf.len()),
&bpf_loader_upgradeable::id(),
);
// Test successful deploy
let payer_base_balance = LAMPORTS_PER_SOL;
let deploy_fees = {
let fee_calculator = genesis_config.fee_rate_governor.create_fee_calculator();
3 * fee_calculator.lamports_per_signature
};
let min_payer_balance = min_program_balance
.saturating_add(min_programdata_balance)
.saturating_sub(min_buffer_balance.saturating_add(deploy_fees));
bank.store_account(
&payer_keypair.pubkey(),
&AccountSharedData::new(
payer_base_balance.saturating_add(min_payer_balance),
0,
&system_program::id(),
),
);
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&payer_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap(),
Some(&payer_keypair.pubkey()),
);
assert!(bank_client
.send_and_confirm_message(
&[&payer_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.is_ok());
assert_eq!(
bank.get_balance(&payer_keypair.pubkey()),
payer_base_balance
);
assert_eq!(bank.get_balance(&buffer_address), 0);
assert_eq!(None, bank.get_account(&buffer_address));
let post_program_account = bank.get_account(&program_keypair.pubkey()).unwrap();
assert_eq!(post_program_account.lamports(), min_program_balance);
assert_eq!(post_program_account.owner(), &bpf_loader_upgradeable::id());
assert_eq!(
post_program_account.data().len(),
UpgradeableLoaderState::size_of_program()
);
let state: UpgradeableLoaderState = post_program_account.state().unwrap();
assert_eq!(
state,
UpgradeableLoaderState::Program {
programdata_address
}
);
let post_programdata_account = bank.get_account(&programdata_address).unwrap();
assert_eq!(post_programdata_account.lamports(), min_programdata_balance);
assert_eq!(
post_programdata_account.owner(),
&bpf_loader_upgradeable::id()
);
let state: UpgradeableLoaderState = post_programdata_account.state().unwrap();
assert_eq!(
state,
UpgradeableLoaderState::ProgramData {
slot: bank_client.get_slot().unwrap(),
upgrade_authority_address: Some(upgrade_authority_keypair.pubkey())
}
);
for (i, byte) in post_programdata_account
.data()
.get(UpgradeableLoaderState::size_of_programdata_metadata()..)
.unwrap()
.iter()
.enumerate()
{
assert_eq!(*elf.get(i).unwrap(), *byte);
}
// Invoke deployed program
mock_process_instruction(
&bpf_loader_upgradeable::id(),
vec![0, 1],
&[],
vec![
(programdata_address, post_programdata_account),
(program_keypair.pubkey(), post_program_account),
],
Vec::new(),
None,
None,
Ok(()),
solana_bpf_loader_program::process_instruction,
);
// Test initialized program account
bank.clear_signatures();
bank.store_account(&buffer_address, &buffer_account);
let message = Message::new(
&[Instruction::new_with_bincode(
bpf_loader_upgradeable::id(),
&UpgradeableLoaderInstruction::DeployWithMaxDataLen {
max_data_len: elf.len(),
},
vec![
AccountMeta::new(mint_keypair.pubkey(), true),
AccountMeta::new(programdata_address, false),
AccountMeta::new(program_keypair.pubkey(), false),
AccountMeta::new(buffer_address, false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(system_program::id(), false),
AccountMeta::new_readonly(upgrade_authority_keypair.pubkey(), true),
],
)],
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(0, InstructionError::AccountAlreadyInitialized),
bank_client
.send_and_confirm_message(&[&mint_keypair, &upgrade_authority_keypair], message)
.unwrap_err()
.unwrap()
);
// Test initialized ProgramData account
bank.clear_signatures();
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::Custom(0)),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Test deploy no authority
bank.clear_signatures();
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &program_account);
bank.store_account(&programdata_address, &programdata_account);
let message = Message::new(
&[Instruction::new_with_bincode(
bpf_loader_upgradeable::id(),
&UpgradeableLoaderInstruction::DeployWithMaxDataLen {
max_data_len: elf.len(),
},
vec![
AccountMeta::new(mint_keypair.pubkey(), true),
AccountMeta::new(programdata_address, false),
AccountMeta::new(program_keypair.pubkey(), false),
AccountMeta::new(buffer_address, false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(system_program::id(), false),
],
)],
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(0, InstructionError::NotEnoughAccountKeys),
bank_client
.send_and_confirm_message(&[&mint_keypair], message)
.unwrap_err()
.unwrap()
);
// Test deploy authority not a signer
bank.clear_signatures();
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &program_account);
bank.store_account(&programdata_address, &programdata_account);
let message = Message::new(
&[Instruction::new_with_bincode(
bpf_loader_upgradeable::id(),
&UpgradeableLoaderInstruction::DeployWithMaxDataLen {
max_data_len: elf.len(),
},
vec![
AccountMeta::new(mint_keypair.pubkey(), true),
AccountMeta::new(programdata_address, false),
AccountMeta::new(program_keypair.pubkey(), false),
AccountMeta::new(buffer_address, false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(system_program::id(), false),
AccountMeta::new_readonly(upgrade_authority_keypair.pubkey(), false),
],
)],
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(0, InstructionError::MissingRequiredSignature),
bank_client
.send_and_confirm_message(&[&mint_keypair], message)
.unwrap_err()
.unwrap()
);
// Test invalid Buffer account state
bank.clear_signatures();
bank.store_account(&buffer_address, &AccountSharedData::default());
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::InvalidAccountData),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Test program account not rent exempt
bank.clear_signatures();
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance.saturating_sub(1),
elf.len(),
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::ExecutableAccountNotRentExempt),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Test program account not rent exempt because data is larger than needed
bank.clear_signatures();
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let mut instructions = bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap();
*instructions.get_mut(0).unwrap() = system_instruction::create_account(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
min_program_balance,
(UpgradeableLoaderState::size_of_program() as u64).saturating_add(1),
&bpf_loader_upgradeable::id(),
);
let message = Message::new(&instructions, Some(&mint_keypair.pubkey()));
assert_eq!(
TransactionError::InstructionError(1, InstructionError::ExecutableAccountNotRentExempt),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Test program account too small
bank.clear_signatures();
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let mut instructions = bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap();
*instructions.get_mut(0).unwrap() = system_instruction::create_account(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
min_program_balance,
(UpgradeableLoaderState::size_of_program() as u64).saturating_sub(1),
&bpf_loader_upgradeable::id(),
);
let message = Message::new(&instructions, Some(&mint_keypair.pubkey()));
assert_eq!(
TransactionError::InstructionError(1, InstructionError::AccountDataTooSmall),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Test Insufficient payer funds (need more funds to cover the
// difference between buffer lamports and programdata lamports)
bank.clear_signatures();
bank.store_account(
&mint_keypair.pubkey(),
&AccountSharedData::new(
deploy_fees.saturating_add(min_program_balance),
0,
&system_program::id(),
),
);
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::Custom(1)),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
bank.store_account(
&mint_keypair.pubkey(),
&AccountSharedData::new(1_000_000_000, 0, &system_program::id()),
);
// Test max_data_len
bank.clear_signatures();
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len().saturating_sub(1),
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::AccountDataTooSmall),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Test max_data_len too large
bank.clear_signatures();
bank.store_account(
&mint_keypair.pubkey(),
&AccountSharedData::new(u64::MAX / 2, 0, &system_program::id()),
);
let mut modified_buffer_account = buffer_account.clone();
modified_buffer_account.set_lamports(u64::MAX / 2);
bank.store_account(&buffer_address, &modified_buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
usize::MAX,
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::InvalidArgument),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Test not the system account
bank.clear_signatures();
bank.store_account(&buffer_address, &buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let mut instructions = bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap();
*instructions
.get_mut(1)
.unwrap()
.accounts
.get_mut(6)
.unwrap() = AccountMeta::new_readonly(Pubkey::new_unique(), false);
let message = Message::new(&instructions, Some(&mint_keypair.pubkey()));
assert_eq!(
TransactionError::InstructionError(1, InstructionError::MissingAccount),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
fn truncate_data(account: &mut AccountSharedData, len: usize) {
let mut data = account.data().to_vec();
data.truncate(len);
account.set_data(data);
}
// Test Bad ELF data
bank.clear_signatures();
let mut modified_buffer_account = buffer_account;
truncate_data(
&mut modified_buffer_account,
UpgradeableLoaderState::size_of_buffer(1),
);
bank.store_account(&buffer_address, &modified_buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::InvalidAccountData),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Test small buffer account
bank.clear_signatures();
let mut modified_buffer_account = AccountSharedData::new(
min_programdata_balance,
UpgradeableLoaderState::size_of_buffer(elf.len()),
&bpf_loader_upgradeable::id(),
);
modified_buffer_account
.set_state(&UpgradeableLoaderState::Buffer {
authority_address: Some(upgrade_authority_keypair.pubkey()),
})
.unwrap();
modified_buffer_account
.data_as_mut_slice()
.get_mut(UpgradeableLoaderState::size_of_buffer_metadata()..)
.unwrap()
.copy_from_slice(&elf);
truncate_data(&mut modified_buffer_account, 5);
bank.store_account(&buffer_address, &modified_buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::InvalidAccountData),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Mismatched buffer and program authority
bank.clear_signatures();
let mut modified_buffer_account = AccountSharedData::new(
min_programdata_balance,
UpgradeableLoaderState::size_of_buffer(elf.len()),
&bpf_loader_upgradeable::id(),
);
modified_buffer_account
.set_state(&UpgradeableLoaderState::Buffer {
authority_address: Some(buffer_address),
})
.unwrap();
modified_buffer_account
.data_as_mut_slice()
.get_mut(UpgradeableLoaderState::size_of_buffer_metadata()..)
.unwrap()
.copy_from_slice(&elf);
bank.store_account(&buffer_address, &modified_buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::IncorrectAuthority),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
// Deploy buffer with mismatched None authority
bank.clear_signatures();
let mut modified_buffer_account = AccountSharedData::new(
min_programdata_balance,
UpgradeableLoaderState::size_of_buffer(elf.len()),
&bpf_loader_upgradeable::id(),
);
modified_buffer_account
.set_state(&UpgradeableLoaderState::Buffer {
authority_address: None,
})
.unwrap();
modified_buffer_account
.data_as_mut_slice()
.get_mut(UpgradeableLoaderState::size_of_buffer_metadata()..)
.unwrap()
.copy_from_slice(&elf);
bank.store_account(&buffer_address, &modified_buffer_account);
bank.store_account(&program_keypair.pubkey(), &AccountSharedData::default());
bank.store_account(&programdata_address, &AccountSharedData::default());
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&mint_keypair.pubkey(),
&program_keypair.pubkey(),
&buffer_address,
&upgrade_authority_keypair.pubkey(),
min_program_balance,
elf.len(),
)
.unwrap(),
Some(&mint_keypair.pubkey()),
);
assert_eq!(
TransactionError::InstructionError(1, InstructionError::IncorrectAuthority),
bank_client
.send_and_confirm_message(
&[&mint_keypair, &program_keypair, &upgrade_authority_keypair],
message
)
.unwrap_err()
.unwrap()
);
}
#[test]
fn test_compute_active_feature_set() {
let bank0 = create_simple_test_arc_bank(100_000);