Prevent the invoke and upgrade of programs in the same tx batch (#14653)

* Prevent the invoke and upgrade of programs in the same tx batch

* Pass program address as writable in the upgrade instruction
This commit is contained in:
Jack May 2021-01-19 16:24:44 -08:00 committed by GitHub
parent 4964b0fe61
commit e3bd9e5300
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 1544 additions and 162 deletions

1242
programs/bpf/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -22,14 +22,18 @@ walkdir = "2"
bincode = "1.1.4"
byteorder = "1.3.2"
elf = "0.0.10"
itertools = "0.10.0"
miow = "0.2.2"
net2 = "0.2.37"
solana-bpf-loader-program = { path = "../bpf_loader", version = "1.6.0" }
solana-cli-output = { path = "../../cli-output", version = "1.6.0" }
solana-logger = { path = "../../logger", version = "1.6.0" }
solana-measure = { path = "../../measure", version = "1.6.0" }
solana_rbpf = "=0.2.3"
solana-runtime = { path = "../../runtime", version = "1.6.0" }
solana-sdk = { path = "../../sdk", version = "1.6.0" }
solana_rbpf = "=0.2.3"
solana-transaction-status = { path = "../../transaction-status", version = "1.6.0" }
[[bench]]
name = "bpf_loader"

View File

@ -3,15 +3,17 @@
#[macro_use]
extern crate solana_bpf_loader_program;
use itertools::izip;
use solana_bpf_loader_program::{
create_vm,
serialization::{deserialize_parameters, serialize_parameters},
syscalls::register_syscalls,
ThisInstructionMeter,
};
use solana_cli_output::display::println_transaction;
use solana_rbpf::vm::{Config, Executable, Tracer};
use solana_runtime::{
bank::{Bank, ExecuteTimings},
bank::{Bank, ExecuteTimings, NonceRollbackInfo, TransactionBalancesSet, TransactionResults},
bank_client::BankClient,
genesis_utils::{create_genesis_config, GenesisConfigInfo},
loader_utils::{
@ -30,11 +32,16 @@ use solana_sdk::{
message::Message,
process_instruction::{InvokeContext, MockInvokeContext},
pubkey::Pubkey,
signature::{Keypair, Signer},
signature::{keypair_from_seed, Keypair, Signer},
system_instruction,
sysvar::{clock, fees, rent, slot_hashes, stake_history},
transaction::{Transaction, TransactionError},
};
use std::{cell::RefCell, env, fs::File, io::Read, path::PathBuf, sync::Arc};
use solana_transaction_status::{
token_balances::collect_token_balances, ConfirmedTransaction, InnerInstructions,
TransactionStatusMeta, TransactionWithStatusMeta, UiTransactionEncoding,
};
use std::{cell::RefCell, collections::HashMap, env, fs::File, io::Read, path::PathBuf, sync::Arc};
/// BPF program file extension
const PLATFORM_FILE_EXTENSION_BPF: &str = "so";
@ -100,20 +107,31 @@ fn write_bpf_program(
fn load_upgradeable_bpf_program(
bank_client: &BankClient,
payer_keypair: &Keypair,
buffer_keypair: &Keypair,
executable_keypair: &Keypair,
authority_keypair: &Keypair,
name: &str,
) -> (Pubkey, Keypair) {
) {
let path = create_bpf_path(name);
let mut file = File::open(&path).unwrap_or_else(|err| {
panic!("Failed to open {}: {}", path.display(), err);
});
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
load_upgradeable_program(bank_client, payer_keypair, elf)
load_upgradeable_program(
bank_client,
payer_keypair,
buffer_keypair,
executable_keypair,
authority_keypair,
elf,
);
}
fn upgrade_bpf_program(
bank_client: &BankClient,
payer_keypair: &Keypair,
buffer_keypair: &Keypair,
executable_pubkey: &Pubkey,
authority_keypair: &Keypair,
name: &str,
@ -124,15 +142,15 @@ fn upgrade_bpf_program(
});
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
let buffer_pubkey = load_buffer_account(bank_client, payer_keypair, &elf);
load_buffer_account(bank_client, payer_keypair, &buffer_keypair, &elf);
upgrade_program(
bank_client,
payer_keypair,
executable_pubkey,
&buffer_pubkey,
&buffer_keypair.pubkey(),
&authority_keypair,
&payer_keypair.pubkey(),
)
);
}
fn run_program(
@ -242,6 +260,108 @@ fn process_transaction_and_record_inner(
)
}
fn execute_transactions(bank: &Bank, txs: &[Transaction]) -> Vec<ConfirmedTransaction> {
let batch = bank.prepare_batch(txs, None);
let mut timings = ExecuteTimings::default();
let mut mint_decimals = HashMap::new();
let tx_pre_token_balances = collect_token_balances(&bank, &batch, &mut mint_decimals);
let (
TransactionResults {
execution_results, ..
},
TransactionBalancesSet {
pre_balances,
post_balances,
..
},
mut inner_instructions,
mut transaction_logs,
) = bank.load_execute_and_commit_transactions(
&batch,
std::usize::MAX,
true,
true,
true,
&mut timings,
);
let tx_post_token_balances = collect_token_balances(&bank, &batch, &mut mint_decimals);
for _ in 0..(txs.len() - transaction_logs.len()) {
transaction_logs.push(vec![]);
}
for _ in 0..(txs.len() - inner_instructions.len()) {
inner_instructions.push(None);
}
izip!(
txs.iter(),
execution_results.into_iter(),
inner_instructions.into_iter(),
pre_balances.into_iter(),
post_balances.into_iter(),
tx_pre_token_balances.into_iter(),
tx_post_token_balances.into_iter(),
transaction_logs.into_iter(),
)
.map(
|(
tx,
(execute_result, nonce_rollback),
inner_instructions,
pre_balances,
post_balances,
pre_token_balances,
post_token_balances,
log_messages,
)| {
let fee_calculator = nonce_rollback
.map(|nonce_rollback| nonce_rollback.fee_calculator())
.unwrap_or_else(|| bank.get_fee_calculator(&tx.message().recent_blockhash))
.expect("FeeCalculator must exist");
let fee = fee_calculator.calculate_fee(tx.message());
let inner_instructions = inner_instructions.map(|inner_instructions| {
inner_instructions
.into_iter()
.enumerate()
.map(|(index, instructions)| InnerInstructions {
index: index as u8,
instructions,
})
.filter(|i| !i.instructions.is_empty())
.collect()
});
let tx_status_meta = TransactionStatusMeta {
status: execute_result,
fee,
pre_balances,
post_balances,
pre_token_balances: Some(pre_token_balances),
post_token_balances: Some(post_token_balances),
inner_instructions,
log_messages: Some(log_messages),
};
ConfirmedTransaction {
slot: bank.slot(),
transaction: TransactionWithStatusMeta {
transaction: tx.clone(),
meta: Some(tx_status_meta),
},
}
},
)
.collect()
}
fn print_confirmed_tx(name: &str, confirmed_tx: ConfirmedTransaction) {
let tx = confirmed_tx.transaction.transaction.clone();
let encoded = confirmed_tx.encode(UiTransactionEncoding::JsonParsed);
println!("EXECUTE {} (slot {})", name, encoded.slot);
println_transaction(&tx, &encoded.transaction.meta, " ");
}
#[test]
#[cfg(any(feature = "bpf_c", feature = "bpf_rust"))]
fn test_program_bpf_sanity() {
@ -1572,8 +1692,18 @@ fn test_program_bpf_upgrade() {
let bank_client = BankClient::new(bank);
// Deploy upgrade program
let (program_id, authority_keypair) =
load_upgradeable_bpf_program(&bank_client, &mint_keypair, "solana_bpf_rust_upgradeable");
let buffer_keypair = Keypair::new();
let program_keypair = Keypair::new();
let program_id = program_keypair.pubkey();
let authority_keypair = Keypair::new();
load_upgradeable_bpf_program(
&bank_client,
&mint_keypair,
&buffer_keypair,
&program_keypair,
&authority_keypair,
"solana_bpf_rust_upgradeable",
);
let mut instruction = Instruction::new(
program_id,
@ -1593,9 +1723,11 @@ fn test_program_bpf_upgrade() {
);
// Upgrade program
let buffer_keypair = Keypair::new();
upgrade_bpf_program(
&bank_client,
&mint_keypair,
&buffer_keypair,
&program_id,
&authority_keypair,
"solana_bpf_rust_upgraded",
@ -1620,9 +1752,11 @@ fn test_program_bpf_upgrade() {
);
// Upgrade back to the original program
let buffer_keypair = Keypair::new();
upgrade_bpf_program(
&bank_client,
&mint_keypair,
&buffer_keypair,
&program_id,
&new_authority_keypair,
"solana_bpf_rust_upgradeable",
@ -1661,8 +1795,18 @@ fn test_program_bpf_invoke_upgradeable_via_cpi() {
);
// Deploy upgradeable program
let (program_id, authority_keypair) =
load_upgradeable_bpf_program(&bank_client, &mint_keypair, "solana_bpf_rust_upgradeable");
let buffer_keypair = Keypair::new();
let program_keypair = Keypair::new();
let program_id = program_keypair.pubkey();
let authority_keypair = Keypair::new();
load_upgradeable_bpf_program(
&bank_client,
&mint_keypair,
&buffer_keypair,
&program_keypair,
&authority_keypair,
"solana_bpf_rust_upgradeable",
);
let mut instruction = Instruction::new(
invoke_and_return,
@ -1684,9 +1828,11 @@ fn test_program_bpf_invoke_upgradeable_via_cpi() {
);
// Upgrade program
let buffer_keypair = Keypair::new();
upgrade_bpf_program(
&bank_client,
&mint_keypair,
&buffer_keypair,
&program_id,
&authority_keypair,
"solana_bpf_rust_upgraded",
@ -1711,9 +1857,11 @@ fn test_program_bpf_invoke_upgradeable_via_cpi() {
);
// Upgrade back to the original program
let buffer_keypair = Keypair::new();
upgrade_bpf_program(
&bank_client,
&mint_keypair,
&buffer_keypair,
&program_id,
&new_authority_keypair,
"solana_bpf_rust_upgradeable",
@ -1794,8 +1942,18 @@ fn test_program_bpf_upgrade_via_cpi() {
);
// Deploy upgradeable program
let (program_id, authority_keypair) =
load_upgradeable_bpf_program(&bank_client, &mint_keypair, "solana_bpf_rust_upgradeable");
let buffer_keypair = Keypair::new();
let program_keypair = Keypair::new();
let program_id = program_keypair.pubkey();
let authority_keypair = Keypair::new();
load_upgradeable_bpf_program(
&bank_client,
&mint_keypair,
&buffer_keypair,
&program_keypair,
&authority_keypair,
"solana_bpf_rust_upgradeable",
);
let mut instruction = Instruction::new(
invoke_and_return,
@ -1823,12 +1981,13 @@ fn test_program_bpf_upgrade_via_cpi() {
});
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
let buffer_pubkey = load_buffer_account(&bank_client, &mint_keypair, &elf);
let buffer_keypair = Keypair::new();
load_buffer_account(&bank_client, &mint_keypair, &buffer_keypair, &elf);
// Upgrade program via CPI
let mut upgrade_instruction = bpf_loader_upgradeable::upgrade(
&program_id,
&buffer_pubkey,
&buffer_keypair.pubkey(),
&authority_keypair.pubkey(),
&mint_keypair.pubkey(),
);
@ -1849,3 +2008,137 @@ fn test_program_bpf_upgrade_via_cpi() {
TransactionError::InstructionError(0, InstructionError::Custom(43))
);
}
#[cfg(feature = "bpf_rust")]
#[test]
fn test_program_upgradeable_locks() {
fn setup_program_upgradeable_locks(
payer_keypair: &Keypair,
buffer_keypair: &Keypair,
program_keypair: &Keypair,
) -> (Arc<Bank>, Transaction, Transaction) {
solana_logger::setup();
let GenesisConfigInfo {
genesis_config,
mint_keypair,
..
} = create_genesis_config(2_000_000_000);
let mut bank = Bank::new(&genesis_config);
let (name, id, entrypoint) = solana_bpf_loader_upgradeable_program!();
bank.add_builtin(&name, id, entrypoint);
let bank = Arc::new(bank);
let bank_client = BankClient::new_shared(&bank);
load_upgradeable_bpf_program(
&bank_client,
&mint_keypair,
buffer_keypair,
program_keypair,
payer_keypair,
"solana_bpf_rust_panic",
);
// Load the buffer account
let path = create_bpf_path("solana_bpf_rust_noop");
let mut file = File::open(&path).unwrap_or_else(|err| {
panic!("Failed to open {}: {}", path.display(), err);
});
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
load_buffer_account(&bank_client, &mint_keypair, buffer_keypair, &elf);
bank_client
.send_and_confirm_instruction(
&mint_keypair,
system_instruction::transfer(
&mint_keypair.pubkey(),
&payer_keypair.pubkey(),
1_000_000_000,
),
)
.unwrap();
let invoke_tx = Transaction::new(
&[payer_keypair],
Message::new(
&[Instruction::new(
program_keypair.pubkey(),
&[0u8; 0],
vec![],
)],
Some(&payer_keypair.pubkey()),
),
bank.last_blockhash(),
);
let upgrade_tx = Transaction::new(
&[payer_keypair],
Message::new(
&[bpf_loader_upgradeable::upgrade(
&program_keypair.pubkey(),
&buffer_keypair.pubkey(),
&payer_keypair.pubkey(),
&payer_keypair.pubkey(),
)],
Some(&payer_keypair.pubkey()),
),
bank.last_blockhash(),
);
(bank, invoke_tx, upgrade_tx)
}
let payer_keypair = keypair_from_seed(&[56u8; 32]).unwrap();
let buffer_keypair = keypair_from_seed(&[11; 32]).unwrap();
let program_keypair = keypair_from_seed(&[77u8; 32]).unwrap();
let results1 = {
let (bank, invoke_tx, upgrade_tx) =
setup_program_upgradeable_locks(&payer_keypair, &buffer_keypair, &program_keypair);
execute_transactions(&bank, &[upgrade_tx, invoke_tx])
};
let results2 = {
let (bank, invoke_tx, upgrade_tx) =
setup_program_upgradeable_locks(&payer_keypair, &buffer_keypair, &program_keypair);
execute_transactions(&bank, &[invoke_tx, upgrade_tx])
};
if false {
println!("upgrade and invoke");
for result in &results1 {
print_confirmed_tx("result", result.clone());
}
println!("invoke and upgrade");
for result in &results2 {
print_confirmed_tx("result", result.clone());
}
}
if let Some(ref meta) = results1[0].transaction.meta {
assert_eq!(meta.status, Ok(()));
} else {
panic!("no meta");
}
if let Some(ref meta) = results1[1].transaction.meta {
assert_eq!(meta.status, Err(TransactionError::AccountInUse));
} else {
panic!("no meta");
}
if let Some(ref meta) = results2[0].transaction.meta {
assert_eq!(
meta.status,
Err(TransactionError::InstructionError(
0,
InstructionError::ProgramFailedToComplete
))
);
} else {
panic!("no meta");
}
if let Some(ref meta) = results2[1].transaction.meta {
assert_eq!(meta.status, Err(TransactionError::AccountInUse));
} else {
panic!("no meta");
}
}

View File

@ -26,7 +26,7 @@ use solana_sdk::{
bpf_loader_upgradeable::{self, UpgradeableLoaderState},
clock::Clock,
entrypoint::SUCCESS,
feature_set::bpf_compute_budget_balancing,
feature_set::{bpf_compute_budget_balancing, prevent_upgrade_and_invoke},
instruction::InstructionError,
keyed_account::{from_keyed_account, next_keyed_account, KeyedAccount},
loader_instruction::LoaderInstruction,
@ -470,6 +470,12 @@ fn process_loader_upgradeable_instruction(
log!(logger, "Program account not executable");
return Err(InstructionError::AccountNotExecutable);
}
if !program.is_writable()
&& invoke_context.is_feature_active(&prevent_upgrade_and_invoke::id())
{
log!(logger, "Program account not writeable");
return Err(InstructionError::InvalidArgument);
}
if &program.owner()? != program_id {
log!(logger, "Program account not owned by loader");
return Err(InstructionError::IncorrectProgramId);
@ -2000,7 +2006,7 @@ mod tests {
&bpf_loader_upgradeable::id(),
&[
KeyedAccount::new(&programdata_address, false, &programdata_account),
KeyedAccount::new_readonly(&program_address, false, &program_account),
KeyedAccount::new(&program_address, false, &program_account),
KeyedAccount::new(&buffer_address, false, &buffer_account),
KeyedAccount::new(&spill_address, false, &spill_account),
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
@ -2062,7 +2068,7 @@ mod tests {
&bpf_loader_upgradeable::id(),
&[
KeyedAccount::new(&programdata_address, false, &programdata_account),
KeyedAccount::new_readonly(&program_address, false, &program_account),
KeyedAccount::new(&program_address, false, &program_account),
KeyedAccount::new(&buffer_address, false, &buffer_account),
KeyedAccount::new(&spill_address, false, &spill_account),
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
@ -2095,7 +2101,7 @@ mod tests {
&bpf_loader_upgradeable::id(),
&[
KeyedAccount::new(&programdata_address, false, &programdata_account),
KeyedAccount::new_readonly(&program_address, false, &program_account),
KeyedAccount::new(&program_address, false, &program_account),
KeyedAccount::new(&buffer_address, false, &buffer_account),
KeyedAccount::new(&spill_address, false, &spill_account),
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
@ -2128,7 +2134,7 @@ mod tests {
&bpf_loader_upgradeable::id(),
&[
KeyedAccount::new(&programdata_address, false, &programdata_account),
KeyedAccount::new_readonly(&program_address, false, &program_account),
KeyedAccount::new(&program_address, false, &program_account),
KeyedAccount::new(&buffer_address, false, &buffer_account),
KeyedAccount::new(&spill_address, false, &spill_account),
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
@ -2162,7 +2168,7 @@ mod tests {
&bpf_loader_upgradeable::id(),
&[
KeyedAccount::new(&programdata_address, false, &programdata_account),
KeyedAccount::new_readonly(&program_address, false, &program_account),
KeyedAccount::new(&program_address, false, &program_account),
KeyedAccount::new(&buffer_address, false, &buffer_account),
KeyedAccount::new(&spill_address, false, &spill_account),
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
@ -2192,6 +2198,39 @@ mod tests {
program_account.borrow_mut().owner = Pubkey::new_unique();
assert_eq!(
Err(InstructionError::IncorrectProgramId),
process_instruction(
&bpf_loader_upgradeable::id(),
&[
KeyedAccount::new(&programdata_address, false, &programdata_account),
KeyedAccount::new(&program_address, false, &program_account),
KeyedAccount::new(&buffer_address, false, &buffer_account),
KeyedAccount::new(&spill_address, false, &spill_account),
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
KeyedAccount::new_readonly(&sysvar::clock::id(), false, &clock_account),
KeyedAccount::new_readonly(
&upgrade_authority_address,
true,
&upgrade_authority_account
)
],
&instruction,
&mut MockInvokeContext::default()
)
);
// Case: Program account not writable
let (buffer_account, program_account, programdata_account, spill_account) = get_accounts(
&buffer_address,
&programdata_address,
&upgrade_authority_address,
slot,
&elf_orig,
&elf_new,
min_program_balance,
min_programdata_balance,
);
assert_eq!(
Err(InstructionError::InvalidArgument),
process_instruction(
&bpf_loader_upgradeable::id(),
&[
@ -2233,7 +2272,7 @@ mod tests {
&bpf_loader_upgradeable::id(),
&[
KeyedAccount::new(&programdata_address, false, &programdata_account),
KeyedAccount::new_readonly(&program_address, false, &program_account),
KeyedAccount::new(&program_address, false, &program_account),
KeyedAccount::new(&buffer_address, false, &buffer_account),
KeyedAccount::new(&spill_address, false, &spill_account),
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
@ -2270,7 +2309,7 @@ mod tests {
&bpf_loader_upgradeable::id(),
&[
KeyedAccount::new(&programdata_address, false, &programdata_account),
KeyedAccount::new_readonly(&program_address, false, &program_account),
KeyedAccount::new(&program_address, false, &program_account),
KeyedAccount::new(&buffer_address, false, &buffer_account),
KeyedAccount::new(&spill_address, false, &spill_account),
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
@ -2303,7 +2342,7 @@ mod tests {
&bpf_loader_upgradeable::id(),
&[
KeyedAccount::new(&Pubkey::new_unique(), false, &programdata_account),
KeyedAccount::new_readonly(&program_address, false, &program_account),
KeyedAccount::new(&program_address, false, &program_account),
KeyedAccount::new(&buffer_address, false, &buffer_account),
KeyedAccount::new(&spill_address, false, &spill_account),
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
@ -2340,7 +2379,7 @@ mod tests {
&bpf_loader_upgradeable::id(),
&[
KeyedAccount::new(&programdata_address, false, &programdata_account),
KeyedAccount::new_readonly(&program_address, false, &program_account),
KeyedAccount::new(&program_address, false, &program_account),
KeyedAccount::new(&buffer_address, false, &buffer_account),
KeyedAccount::new(&spill_address, false, &spill_account),
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
@ -2384,7 +2423,7 @@ mod tests {
&bpf_loader_upgradeable::id(),
&[
KeyedAccount::new(&programdata_address, false, &programdata_account),
KeyedAccount::new_readonly(&program_address, false, &program_account),
KeyedAccount::new(&program_address, false, &program_account),
KeyedAccount::new(&buffer_address, false, &buffer_account),
KeyedAccount::new(&spill_address, false, &spill_account),
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),
@ -2419,7 +2458,7 @@ mod tests {
&bpf_loader_upgradeable::id(),
&[
KeyedAccount::new(&programdata_address, false, &programdata_account),
KeyedAccount::new_readonly(&program_address, false, &program_account),
KeyedAccount::new(&program_address, false, &program_account),
KeyedAccount::new(&buffer_address, false, &buffer_account),
KeyedAccount::new(&spill_address, false, &spill_account),
KeyedAccount::new_readonly(&sysvar::rent::id(), false, &rent_account),

View File

@ -57,9 +57,9 @@ pub fn load_program<T: Client>(
pub fn load_buffer_account<T: Client>(
bank_client: &T,
from_keypair: &Keypair,
buffer_keypair: &Keypair,
program: &[u8],
) -> Pubkey {
let buffer_keypair = Keypair::new();
) {
let buffer_pubkey = buffer_keypair.pubkey();
bank_client
@ -100,26 +100,26 @@ pub fn load_buffer_account<T: Client>(
.unwrap();
offset += chunk_size as u32;
}
buffer_keypair.pubkey()
}
pub fn load_upgradeable_program<T: Client>(
bank_client: &T,
from_keypair: &Keypair,
buffer_keypair: &Keypair,
executable_keypair: &Keypair,
authority_keypair: &Keypair,
program: Vec<u8>,
) -> (Pubkey, Keypair) {
let executable_keypair = Keypair::new();
) {
let program_pubkey = executable_keypair.pubkey();
let authority_keypair = Keypair::new();
let authority_pubkey = authority_keypair.pubkey();
let buffer_pubkey = load_buffer_account(bank_client, &from_keypair, &program);
load_buffer_account(bank_client, &from_keypair, buffer_keypair, &program);
let message = Message::new(
&bpf_loader_upgradeable::deploy_with_max_program_len(
&from_keypair.pubkey(),
&program_pubkey,
&buffer_pubkey,
&buffer_keypair.pubkey(),
Some(&authority_pubkey),
1.max(
bank_client
@ -136,8 +136,6 @@ pub fn load_upgradeable_program<T: Client>(
bank_client
.send_and_confirm_message(&[from_keypair, &executable_keypair], message)
.unwrap();
(executable_keypair.pubkey(), authority_keypair)
}
pub fn upgrade_program<T: Client>(

View File

@ -182,7 +182,7 @@ pub fn upgrade(
&UpgradeableLoaderInstruction::Upgrade,
vec![
AccountMeta::new(programdata_address, false),
AccountMeta::new_readonly(*program_address, false),
AccountMeta::new(*program_address, false),
AccountMeta::new(*buffer_address, false),
AccountMeta::new(*spill_address, false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
@ -250,4 +250,45 @@ mod tests {
UpgradeableLoaderState::programdata_len(42).unwrap()
);
}
#[test]
fn test_is_upgrade_instruction() {
assert_eq!(
false,
is_upgrade_instruction(
&bincode::serialize(&UpgradeableLoaderInstruction::InitializeBuffer).unwrap()
)
);
assert_eq!(
false,
is_upgrade_instruction(
&bincode::serialize(&UpgradeableLoaderInstruction::Write {
offset: 0,
bytes: vec![],
})
.unwrap()
)
);
assert_eq!(
false,
is_upgrade_instruction(
&bincode::serialize(&UpgradeableLoaderInstruction::DeployWithMaxDataLen {
max_data_len: 0,
})
.unwrap()
)
);
assert_eq!(
true,
is_upgrade_instruction(
&bincode::serialize(&UpgradeableLoaderInstruction::Upgrade).unwrap()
)
);
assert_eq!(
false,
is_upgrade_instruction(
&bincode::serialize(&UpgradeableLoaderInstruction::SetAuthority).unwrap()
)
);
}
}

View File

@ -86,7 +86,7 @@ pub enum UpgradeableLoaderInstruction {
///
/// # Account references
/// 0. [writable] The ProgramData account.
/// 1. [] The Program account.
/// 1. [writable] The Program account.
/// 2. [Writable] The Buffer account where the program data has been
/// written.
/// 3. [writable] The spill account.

View File

@ -142,6 +142,10 @@ pub mod turbine_retransmit_peers_patch {
solana_sdk::declare_id!("5Lu3JnWSFwRYpXzwDMkanWSk6XqSuF2i5fpnVhzB5CTc");
}
pub mod prevent_upgrade_and_invoke {
solana_sdk::declare_id!("BiNjYd8jCYDgAwMqP91uwZs6skWpuHtKrZbckuKESs8N");
}
lazy_static! {
/// Map of feature identifiers to user-visible description
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
@ -179,6 +183,7 @@ lazy_static! {
(abort_on_all_cpi_failures::id(), "Abort on all CPI failures"),
(use_loaded_executables::id(), "Use loaded executable accounts"),
(turbine_retransmit_peers_patch::id(), "turbine retransmit peers patch #14631"),
(prevent_upgrade_and_invoke::id(), "Prevent upgrade and invoke in same tx batch"),
/*************** ADD NEW FEATURES HERE ***************/
]
.iter()

View File

@ -359,7 +359,7 @@ pub struct EncodedConfirmedBlock {
pub block_time: Option<UnixTimestamp>,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ConfirmedTransaction {
pub slot: Slot,