Skip to content

Commit 1a4a039

Browse files
authored
Adds feature reject_empty_instruction_without_program. (solana-labs#21591)
1 parent 015250f commit 1a4a039

File tree

3 files changed

+25
-5
lines changed

3 files changed

+25
-5
lines changed

program-runtime/src/invoke_context.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ use solana_sdk::{
99
compute_budget::ComputeBudget,
1010
feature_set::{
1111
demote_program_write_locks, do_support_realloc, neon_evm_compute_budget,
12-
remove_native_loader, requestable_heap_size, tx_wide_compute_cap, FeatureSet,
12+
reject_empty_instruction_without_program, remove_native_loader, requestable_heap_size,
13+
tx_wide_compute_cap, FeatureSet,
1314
},
1415
hash::Hash,
1516
instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
@@ -218,6 +219,13 @@ impl<'a> InvokeContext<'a> {
218219
let program_id = program_indices
219220
.last()
220221
.map(|index_of_program_id| &self.accounts[*index_of_program_id].0);
222+
if program_id.is_none()
223+
&& self
224+
.feature_set
225+
.is_active(&reject_empty_instruction_without_program::id())
226+
{
227+
return Err(InstructionError::UnsupportedProgramId);
228+
}
221229
if self.invoke_stack.is_empty() {
222230
let mut compute_budget = self.compute_budget;
223231
if !self.feature_set.is_active(&tx_wide_compute_cap::id())

runtime/src/bank.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -6506,6 +6506,7 @@ pub(crate) mod tests {
65066506
compute_budget::ComputeBudgetInstruction,
65076507
epoch_schedule::MINIMUM_SLOTS_PER_EPOCH,
65086508
feature::Feature,
6509+
feature_set::reject_empty_instruction_without_program,
65096510
genesis_config::create_genesis_config,
65106511
hash,
65116512
instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
@@ -15445,17 +15446,23 @@ pub(crate) mod tests {
1544515446
}
1544615447

1544715448
#[test]
15448-
fn test_an_empty_transaction_without_program() {
15449+
fn test_an_empty_instruction_without_program() {
1544915450
let (genesis_config, mint_keypair) = create_genesis_config(1);
15450-
let bank = Bank::new_for_tests(&genesis_config);
15451-
1545215451
let destination = solana_sdk::pubkey::new_rand();
1545315452
let mut ix = system_instruction::transfer(&mint_keypair.pubkey(), &destination, 0);
1545415453
ix.program_id = native_loader::id(); // Empty executable account chain
15455-
1545615454
let message = Message::new(&[ix], Some(&mint_keypair.pubkey()));
1545715455
let tx = Transaction::new(&[&mint_keypair], message, genesis_config.hash());
15456+
15457+
let bank = Bank::new_for_tests(&genesis_config);
1545815458
bank.process_transaction(&tx).unwrap();
15459+
15460+
let mut bank = Bank::new_for_tests(&genesis_config);
15461+
bank.activate_feature(&reject_empty_instruction_without_program::id());
15462+
assert_eq!(
15463+
bank.process_transaction(&tx).unwrap_err(),
15464+
TransactionError::InstructionError(0, InstructionError::UnsupportedProgramId),
15465+
);
1545915466
}
1546015467

1546115468
#[test]

sdk/src/feature_set.rs

+5
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,10 @@ pub mod leave_nonce_on_success {
257257
solana_sdk::declare_id!("E8MkiWZNNPGU6n55jkGzyj8ghUmjCHRmDFdYYFYHxWhQ");
258258
}
259259

260+
pub mod reject_empty_instruction_without_program {
261+
solana_sdk::declare_id!("9kdtFSrXHQg3hKkbXkQ6trJ3Ja1xpJ22CTFSNAciEwmL");
262+
}
263+
260264
lazy_static! {
261265
/// Map of feature identifiers to user-visible description
262266
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
@@ -316,6 +320,7 @@ lazy_static! {
316320
(nonce_must_be_writable::id(), "nonce must be writable"),
317321
(spl_token_v3_3_0_release::id(), "spl-token v3.3.0 release"),
318322
(leave_nonce_on_success::id(), "leave nonce as is on success"),
323+
(reject_empty_instruction_without_program::id(), "fail instructions which have native_loader as program_id directly"),
319324
/*************** ADD NEW FEATURES HERE ***************/
320325
]
321326
.iter()

0 commit comments

Comments
 (0)