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:
Alexander Meißner 2022-08-23 23:55:56 +02:00 committed by GitHub
parent 1c4f7bcd37
commit a8543ad992
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 158 additions and 3 deletions

View File

@ -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

View File

@ -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()