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:
parent
274d9ea607
commit
5aca7df232
|
@ -4748,7 +4748,6 @@ dependencies = [
|
||||||
"solana-measure",
|
"solana-measure",
|
||||||
"solana-metrics",
|
"solana-metrics",
|
||||||
"solana-program-runtime",
|
"solana-program-runtime",
|
||||||
"solana-runtime",
|
|
||||||
"solana-sdk 1.15.0",
|
"solana-sdk 1.15.0",
|
||||||
"solana-zk-token-sdk 1.15.0",
|
"solana-zk-token-sdk 1.15.0",
|
||||||
"solana_rbpf",
|
"solana_rbpf",
|
||||||
|
@ -6150,6 +6149,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"solana-address-lookup-table-program",
|
"solana-address-lookup-table-program",
|
||||||
|
"solana-bpf-loader-program",
|
||||||
"solana-bucket-map",
|
"solana-bucket-map",
|
||||||
"solana-compute-budget-program",
|
"solana-compute-budget-program",
|
||||||
"solana-config-program",
|
"solana-config-program",
|
||||||
|
|
|
@ -24,7 +24,6 @@ thiserror = "1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rand = "0.7.3"
|
rand = "0.7.3"
|
||||||
solana-runtime = { path = "../../runtime", version = "=1.15.0" }
|
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["lib"]
|
crate-type = ["lib"]
|
||||||
|
|
|
@ -1525,27 +1525,19 @@ mod tests {
|
||||||
rand::Rng,
|
rand::Rng,
|
||||||
solana_program_runtime::invoke_context::mock_process_instruction,
|
solana_program_runtime::invoke_context::mock_process_instruction,
|
||||||
solana_rbpf::{ebpf::MM_INPUT_START, verifier::Verifier, vm::SyscallRegistry},
|
solana_rbpf::{ebpf::MM_INPUT_START, verifier::Verifier, vm::SyscallRegistry},
|
||||||
solana_runtime::{bank::Bank, bank_client::BankClient},
|
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
account::{
|
account::{
|
||||||
create_account_shared_data_for_test as create_account_for_test, AccountSharedData,
|
create_account_shared_data_for_test as create_account_for_test, AccountSharedData,
|
||||||
ReadableAccount, WritableAccount,
|
ReadableAccount, WritableAccount,
|
||||||
},
|
},
|
||||||
account_utils::StateMut,
|
account_utils::StateMut,
|
||||||
client::SyncClient,
|
|
||||||
clock::Clock,
|
clock::Clock,
|
||||||
feature_set::FeatureSet,
|
instruction::{AccountMeta, InstructionError},
|
||||||
genesis_config::create_genesis_config,
|
|
||||||
instruction::{AccountMeta, Instruction, InstructionError},
|
|
||||||
message::Message,
|
|
||||||
native_token::LAMPORTS_PER_SOL,
|
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
rent::Rent,
|
rent::Rent,
|
||||||
signature::{Keypair, Signer},
|
sysvar,
|
||||||
system_program, sysvar,
|
|
||||||
transaction::TransactionError,
|
|
||||||
},
|
},
|
||||||
std::{fs::File, io::Read, ops::Range, sync::Arc},
|
std::{fs::File, io::Read, ops::Range},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TestInstructionMeter {
|
struct TestInstructionMeter {
|
||||||
|
@ -2260,711 +2252,6 @@ mod tests {
|
||||||
account.set_data(data);
|
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]
|
#[test]
|
||||||
fn test_bpf_loader_upgradeable_upgrade() {
|
fn test_bpf_loader_upgradeable_upgrade() {
|
||||||
let mut file = File::open("test_elfs/out/noop_aligned.so").expect("file open failed");
|
let mut file = File::open("test_elfs/out/noop_aligned.so").expect("file open failed");
|
||||||
|
|
|
@ -5080,6 +5080,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"solana-address-lookup-table-program",
|
"solana-address-lookup-table-program",
|
||||||
|
"solana-bpf-loader-program",
|
||||||
"solana-bucket-map",
|
"solana-bucket-map",
|
||||||
"solana-compute-budget-program",
|
"solana-compute-budget-program",
|
||||||
"solana-config-program",
|
"solana-config-program",
|
||||||
|
|
|
@ -41,6 +41,7 @@ regex = "1.6.0"
|
||||||
serde = { version = "1.0.144", features = ["rc"] }
|
serde = { version = "1.0.144", features = ["rc"] }
|
||||||
serde_derive = "1.0.103"
|
serde_derive = "1.0.103"
|
||||||
solana-address-lookup-table-program = { path = "../programs/address-lookup-table", version = "=1.15.0" }
|
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-bucket-map = { path = "../bucket_map", version = "=1.15.0" }
|
||||||
solana-compute-budget-program = { path = "../programs/compute-budget", 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" }
|
solana-config-program = { path = "../programs/config", version = "=1.15.0" }
|
||||||
|
|
|
@ -87,7 +87,7 @@ use {
|
||||||
accounts_data_meter::MAX_ACCOUNTS_DATA_LEN,
|
accounts_data_meter::MAX_ACCOUNTS_DATA_LEN,
|
||||||
compute_budget::{self, ComputeBudget},
|
compute_budget::{self, ComputeBudget},
|
||||||
executor_cache::{
|
executor_cache::{
|
||||||
BankExecutorCache, TransactionExecutorCache, TxBankExecutorCacheDiff,
|
BankExecutorCache, Executor, TransactionExecutorCache, TxBankExecutorCacheDiff,
|
||||||
MAX_CACHED_EXECUTORS,
|
MAX_CACHED_EXECUTORS,
|
||||||
},
|
},
|
||||||
invoke_context::{BuiltinProgram, ProcessInstructionWithContext},
|
invoke_context::{BuiltinProgram, ProcessInstructionWithContext},
|
||||||
|
@ -101,6 +101,7 @@ use {
|
||||||
AccountSharedData, InheritableAccountFields, ReadableAccount, WritableAccount,
|
AccountSharedData, InheritableAccountFields, ReadableAccount, WritableAccount,
|
||||||
},
|
},
|
||||||
account_utils::StateMut,
|
account_utils::StateMut,
|
||||||
|
bpf_loader_upgradeable::{self, UpgradeableLoaderState},
|
||||||
clock::{
|
clock::{
|
||||||
BankId, Epoch, Slot, SlotCount, SlotIndex, UnixTimestamp, DEFAULT_TICKS_PER_SECOND,
|
BankId, Epoch, Slot, SlotCount, SlotIndex, UnixTimestamp, DEFAULT_TICKS_PER_SECOND,
|
||||||
INITIAL_RENT_EPOCH, MAX_PROCESSING_AGE, MAX_TRANSACTION_FORWARDING_DELAY,
|
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
|
/// Remove an executor from the bank's cache
|
||||||
fn remove_executor(&self, pubkey: &Pubkey) {
|
fn remove_executor(&self, pubkey: &Pubkey) {
|
||||||
let _ = self.executor_cache.write().unwrap().remove(pubkey);
|
let _ = self.executor_cache.write().unwrap().remove(pubkey);
|
||||||
|
@ -7852,6 +7920,7 @@ pub(crate) mod tests {
|
||||||
accounts_db::DEFAULT_ACCOUNTS_SHRINK_RATIO,
|
accounts_db::DEFAULT_ACCOUNTS_SHRINK_RATIO,
|
||||||
accounts_index::{AccountIndex, AccountSecondaryIndexes, ScanError, ITER_BATCH_SIZE},
|
accounts_index::{AccountIndex, AccountSecondaryIndexes, ScanError, ITER_BATCH_SIZE},
|
||||||
ancestors::Ancestors,
|
ancestors::Ancestors,
|
||||||
|
bank_client::BankClient,
|
||||||
genesis_utils::{
|
genesis_utils::{
|
||||||
self, activate_all_features, bootstrap_validator_stake_lamports,
|
self, activate_all_features, bootstrap_validator_stake_lamports,
|
||||||
create_genesis_config_with_leader, create_genesis_config_with_vote_accounts,
|
create_genesis_config_with_leader, create_genesis_config_with_vote_accounts,
|
||||||
|
@ -7866,12 +7935,14 @@ pub(crate) mod tests {
|
||||||
solana_program_runtime::{
|
solana_program_runtime::{
|
||||||
compute_budget::MAX_COMPUTE_UNIT_LIMIT,
|
compute_budget::MAX_COMPUTE_UNIT_LIMIT,
|
||||||
executor_cache::Executor,
|
executor_cache::Executor,
|
||||||
invoke_context::InvokeContext,
|
invoke_context::{mock_process_instruction, InvokeContext},
|
||||||
prioritization_fee::{PrioritizationFeeDetails, PrioritizationFeeType},
|
prioritization_fee::{PrioritizationFeeDetails, PrioritizationFeeType},
|
||||||
},
|
},
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
account::Account,
|
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},
|
clock::{DEFAULT_SLOTS_PER_EPOCH, DEFAULT_TICKS_PER_SLOT, MAX_RECENT_BLOCKHASHES},
|
||||||
compute_budget::ComputeBudgetInstruction,
|
compute_budget::ComputeBudgetInstruction,
|
||||||
entrypoint::MAX_PERMITTED_DATA_INCREASE,
|
entrypoint::MAX_PERMITTED_DATA_INCREASE,
|
||||||
|
@ -7880,6 +7951,7 @@ pub(crate) mod tests {
|
||||||
genesis_config::create_genesis_config,
|
genesis_config::create_genesis_config,
|
||||||
hash,
|
hash,
|
||||||
instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
|
instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
|
||||||
|
loader_upgradeable_instruction::UpgradeableLoaderInstruction,
|
||||||
message::{Message, MessageHeader},
|
message::{Message, MessageHeader},
|
||||||
native_token::LAMPORTS_PER_SOL,
|
native_token::LAMPORTS_PER_SOL,
|
||||||
nonce,
|
nonce,
|
||||||
|
@ -7907,7 +7979,8 @@ pub(crate) mod tests {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
std::{
|
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,
|
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(&key2));
|
||||||
assert!(stored_executors.borrow().executors.contains_key(&key3));
|
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
|
// Remove all
|
||||||
bank.remove_executor(&key1);
|
bank.remove_executor(&key1);
|
||||||
bank.remove_executor(&key2);
|
bank.remove_executor(&key2);
|
||||||
|
@ -15200,6 +15306,721 @@ pub(crate) mod tests {
|
||||||
assert_eq!(executors.borrow().executors.len(), 1);
|
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]
|
#[test]
|
||||||
fn test_compute_active_feature_set() {
|
fn test_compute_active_feature_set() {
|
||||||
let bank0 = create_simple_test_arc_bank(100_000);
|
let bank0 = create_simple_test_arc_bank(100_000);
|
||||||
|
|
Loading…
Reference in New Issue