Feature: `stop_sibling_instruction_search_at_parent` (#27290)
* Adds stop_sibling_instruction_search_at_parent. * Adds test_syscall_sol_get_processed_sibling_instruction().
This commit is contained in:
parent
1c4f7bcd37
commit
a8543ad992
|
@ -36,7 +36,8 @@ use {
|
|||
self, blake3_syscall_enabled, check_physical_overlapping, check_slice_translation_size,
|
||||
curve25519_syscall_enabled, disable_cpi_setting_executable_and_rent_epoch,
|
||||
disable_fees_sysvar, enable_early_verification_of_account_modifications,
|
||||
libsecp256k1_0_5_upgrade_enabled, limit_secp256k1_recovery_id, syscall_saturated_math,
|
||||
libsecp256k1_0_5_upgrade_enabled, limit_secp256k1_recovery_id,
|
||||
stop_sibling_instruction_search_at_parent, syscall_saturated_math,
|
||||
},
|
||||
hash::{Hasher, HASH_BYTES},
|
||||
instruction::{
|
||||
|
@ -1708,6 +1709,9 @@ declare_syscall!(
|
|||
.consume(budget.syscall_base_cost),
|
||||
result
|
||||
);
|
||||
let stop_sibling_instruction_search_at_parent = invoke_context
|
||||
.feature_set
|
||||
.is_active(&stop_sibling_instruction_search_at_parent::id());
|
||||
|
||||
// Reverse iterate through the instruction trace,
|
||||
// ignoring anything except instructions on the same level
|
||||
|
@ -1725,8 +1729,9 @@ declare_syscall!(
|
|||
.map_err(SyscallError::InstructionError),
|
||||
result
|
||||
);
|
||||
if instruction_context.get_stack_height() == TRANSACTION_LEVEL_STACK_HEIGHT
|
||||
&& stack_height > TRANSACTION_LEVEL_STACK_HEIGHT
|
||||
if (stop_sibling_instruction_search_at_parent
|
||||
|| instruction_context.get_stack_height() == TRANSACTION_LEVEL_STACK_HEIGHT)
|
||||
&& instruction_context.get_stack_height() < stack_height
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -3108,6 +3113,151 @@ mod tests {
|
|||
call_program_address_common(seeds, address, &mut syscall)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_syscall_sol_get_processed_sibling_instruction() {
|
||||
let transaction_accounts = (0..9)
|
||||
.map(|_| {
|
||||
(
|
||||
Pubkey::new_unique(),
|
||||
AccountSharedData::new(0, 0, &bpf_loader::id()),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let mut transaction_context = TransactionContext::new(transaction_accounts, None, 4, 1);
|
||||
for (index_in_trace, stack_height) in [1, 2, 3, 2, 2, 3, 4, 3].into_iter().enumerate() {
|
||||
while stack_height <= transaction_context.get_instruction_context_stack_height() {
|
||||
transaction_context.pop().unwrap();
|
||||
}
|
||||
if stack_height > transaction_context.get_instruction_context_stack_height() {
|
||||
let instruction_accounts = [InstructionAccount {
|
||||
index_in_transaction: index_in_trace.saturating_add(1),
|
||||
index_in_caller: 0, // This is incorrect / inconsistent but not required
|
||||
index_in_callee: 0,
|
||||
is_signer: false,
|
||||
is_writable: false,
|
||||
}];
|
||||
transaction_context
|
||||
.push(&[0], &instruction_accounts, &[index_in_trace as u8])
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
|
||||
|
||||
let syscall_base_cost = invoke_context.get_compute_budget().syscall_base_cost;
|
||||
let mut syscall_get_processed_sibling_instruction = SyscallGetProcessedSiblingInstruction {
|
||||
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
||||
};
|
||||
const VM_BASE_ADDRESS: u64 = 0x100000000;
|
||||
const META_OFFSET: usize = 0;
|
||||
const PROGRAM_ID_OFFSET: usize =
|
||||
META_OFFSET + std::mem::size_of::<ProcessedSiblingInstruction>();
|
||||
const DATA_OFFSET: usize = PROGRAM_ID_OFFSET + std::mem::size_of::<Pubkey>();
|
||||
const ACCOUNTS_OFFSET: usize = DATA_OFFSET + 0x100;
|
||||
const END_OFFSET: usize = ACCOUNTS_OFFSET + std::mem::size_of::<AccountInfo>() * 4;
|
||||
let mut memory = [0u8; END_OFFSET];
|
||||
let config = Config::default();
|
||||
let mut memory_mapping = MemoryMapping::new::<UserError>(
|
||||
vec![
|
||||
MemoryRegion::default(),
|
||||
MemoryRegion {
|
||||
host_addr: memory.as_mut_ptr() as u64,
|
||||
vm_addr: VM_BASE_ADDRESS,
|
||||
len: END_OFFSET as u64,
|
||||
vm_gap_shift: 63,
|
||||
is_writable: true,
|
||||
},
|
||||
],
|
||||
&config,
|
||||
)
|
||||
.unwrap();
|
||||
let processed_sibling_instruction = translate_type_mut::<ProcessedSiblingInstruction>(
|
||||
&memory_mapping,
|
||||
VM_BASE_ADDRESS,
|
||||
true,
|
||||
)
|
||||
.unwrap();
|
||||
processed_sibling_instruction.data_len = 1;
|
||||
processed_sibling_instruction.accounts_len = 1;
|
||||
let program_id = translate_type_mut::<Pubkey>(
|
||||
&memory_mapping,
|
||||
VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
|
||||
true,
|
||||
)
|
||||
.unwrap();
|
||||
let data = translate_slice_mut::<u8>(
|
||||
&memory_mapping,
|
||||
VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
|
||||
processed_sibling_instruction.data_len as u64,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
.unwrap();
|
||||
let accounts = translate_slice_mut::<AccountMeta>(
|
||||
&memory_mapping,
|
||||
VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
|
||||
processed_sibling_instruction.accounts_len as u64,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
syscall_get_processed_sibling_instruction
|
||||
.invoke_context
|
||||
.borrow_mut()
|
||||
.get_compute_meter()
|
||||
.borrow_mut()
|
||||
.mock_set_remaining(syscall_base_cost);
|
||||
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
||||
syscall_get_processed_sibling_instruction.call(
|
||||
0,
|
||||
VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
|
||||
VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
|
||||
VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
|
||||
VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
|
||||
&mut memory_mapping,
|
||||
&mut result,
|
||||
);
|
||||
assert_eq!(result, Ok(1));
|
||||
{
|
||||
let transaction_context = &syscall_get_processed_sibling_instruction
|
||||
.invoke_context
|
||||
.borrow()
|
||||
.transaction_context;
|
||||
assert_eq!(processed_sibling_instruction.data_len, 1);
|
||||
assert_eq!(processed_sibling_instruction.accounts_len, 1);
|
||||
assert_eq!(
|
||||
program_id,
|
||||
transaction_context.get_key_of_account_at_index(0).unwrap(),
|
||||
);
|
||||
assert_eq!(data, &[5]);
|
||||
assert_eq!(
|
||||
accounts,
|
||||
&[AccountMeta {
|
||||
pubkey: *transaction_context.get_key_of_account_at_index(6).unwrap(),
|
||||
is_signer: false,
|
||||
is_writable: false
|
||||
}]
|
||||
);
|
||||
}
|
||||
|
||||
syscall_get_processed_sibling_instruction
|
||||
.invoke_context
|
||||
.borrow_mut()
|
||||
.get_compute_meter()
|
||||
.borrow_mut()
|
||||
.mock_set_remaining(syscall_base_cost);
|
||||
syscall_get_processed_sibling_instruction.call(
|
||||
1,
|
||||
VM_BASE_ADDRESS.saturating_add(META_OFFSET as u64),
|
||||
VM_BASE_ADDRESS.saturating_add(PROGRAM_ID_OFFSET as u64),
|
||||
VM_BASE_ADDRESS.saturating_add(DATA_OFFSET as u64),
|
||||
VM_BASE_ADDRESS.saturating_add(ACCOUNTS_OFFSET as u64),
|
||||
&mut memory_mapping,
|
||||
&mut result,
|
||||
);
|
||||
assert_eq!(result, Ok(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_program_address() {
|
||||
// These tests duplicate the direct tests in solana_program::pubkey
|
||||
|
|
|
@ -506,6 +506,10 @@ pub mod relax_authority_signer_check_for_lookup_table_creation {
|
|||
solana_sdk::declare_id!("FKAcEvNgSY79RpqsPNUV5gDyumopH4cEHqUxyfm8b8Ap");
|
||||
}
|
||||
|
||||
pub mod stop_sibling_instruction_search_at_parent {
|
||||
solana_sdk::declare_id!("EYVpEP7uzH1CoXzbD6PubGhYmnxRXPeq3PPsm1ba3gpo");
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
/// Map of feature identifiers to user-visible description
|
||||
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
|
||||
|
@ -627,6 +631,7 @@ lazy_static! {
|
|||
(incremental_snapshot_only_incremental_hash_calculation::id(), "only hash accounts in incremental snapshot during incremental snapshot creation #26799"),
|
||||
(disable_cpi_setting_executable_and_rent_epoch::id(), "disable setting is_executable and_rent_epoch in CPI #26987"),
|
||||
(relax_authority_signer_check_for_lookup_table_creation::id(), "relax authority signer check for lookup table creation #27205"),
|
||||
(stop_sibling_instruction_search_at_parent::id(), "stop the search in get_processed_sibling_instruction when the parent instruction is reached #27289"),
|
||||
/*************** ADD NEW FEATURES HERE ***************/
|
||||
]
|
||||
.iter()
|
||||
|
|
Loading…
Reference in New Issue