featurize loader sat math (#23516)
This commit is contained in:
@ -26,7 +26,7 @@ use {
|
|||||||
disable_fees_sysvar, do_support_realloc, fixed_memcpy_nonoverlapping_check,
|
disable_fees_sysvar, do_support_realloc, fixed_memcpy_nonoverlapping_check,
|
||||||
libsecp256k1_0_5_upgrade_enabled, prevent_calling_precompiles_as_programs,
|
libsecp256k1_0_5_upgrade_enabled, prevent_calling_precompiles_as_programs,
|
||||||
return_data_syscall_enabled, secp256k1_recover_syscall_enabled,
|
return_data_syscall_enabled, secp256k1_recover_syscall_enabled,
|
||||||
sol_log_data_syscall_enabled, update_syscall_base_costs,
|
sol_log_data_syscall_enabled, syscall_saturated_math, update_syscall_base_costs,
|
||||||
},
|
},
|
||||||
hash::{Hasher, HASH_BYTES},
|
hash::{Hasher, HASH_BYTES},
|
||||||
instruction::{
|
instruction::{
|
||||||
@ -1544,10 +1544,20 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallMemcmp<'a, 'b> {
|
|||||||
let a = s1[i];
|
let a = s1[i];
|
||||||
let b = s2[i];
|
let b = s2[i];
|
||||||
if a != b {
|
if a != b {
|
||||||
*cmp_result = (a as i32).saturating_sub(b as i32);
|
*cmp_result = if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&syscall_saturated_math::id())
|
||||||
|
{
|
||||||
|
(a as i32).saturating_sub(b as i32)
|
||||||
|
} else {
|
||||||
|
#[allow(clippy::integer_arithmetic)]
|
||||||
|
{
|
||||||
|
a as i32 - b as i32
|
||||||
|
}
|
||||||
|
};
|
||||||
*result = Ok(0);
|
*result = Ok(0);
|
||||||
return;
|
return;
|
||||||
}
|
};
|
||||||
i = i.saturating_add(1);
|
i = i.saturating_add(1);
|
||||||
}
|
}
|
||||||
*cmp_result = 0;
|
*cmp_result = 0;
|
||||||
@ -1933,10 +1943,18 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallBlake3<'a, 'b> {
|
|||||||
.sha256_byte_cost
|
.sha256_byte_cost
|
||||||
.saturating_mul((val.len() as u64).saturating_div(2)),
|
.saturating_mul((val.len() as u64).saturating_div(2)),
|
||||||
)
|
)
|
||||||
} else {
|
} else if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&syscall_saturated_math::id())
|
||||||
|
{
|
||||||
compute_budget
|
compute_budget
|
||||||
.sha256_byte_cost
|
.sha256_byte_cost
|
||||||
.saturating_mul((val.len() as u64).saturating_div(2))
|
.saturating_mul((val.len() as u64).saturating_div(2))
|
||||||
|
} else {
|
||||||
|
#[allow(clippy::integer_arithmetic)]
|
||||||
|
{
|
||||||
|
compute_budget.sha256_byte_cost * (val.len() as u64 / 2)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
||||||
hasher.hash(bytes);
|
hasher.hash(bytes);
|
||||||
@ -2376,7 +2394,17 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
|
|||||||
|
|
||||||
let first_info_addr = &account_infos[0] as *const _ as u64;
|
let first_info_addr = &account_infos[0] as *const _ as u64;
|
||||||
let addr = &account_info.data_len as *const u64 as u64;
|
let addr = &account_info.data_len as *const u64 as u64;
|
||||||
let vm_addr = account_infos_addr.saturating_add(addr.saturating_sub(first_info_addr));
|
let vm_addr = if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&syscall_saturated_math::id())
|
||||||
|
{
|
||||||
|
account_infos_addr.saturating_add(addr.saturating_sub(first_info_addr))
|
||||||
|
} else {
|
||||||
|
#[allow(clippy::integer_arithmetic)]
|
||||||
|
{
|
||||||
|
account_infos_addr + (addr - first_info_addr)
|
||||||
|
}
|
||||||
|
};
|
||||||
let _ = translate(
|
let _ = translate(
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
AccessType::Store,
|
AccessType::Store,
|
||||||
@ -2592,9 +2620,18 @@ fn check_account_infos(
|
|||||||
len: usize,
|
len: usize,
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &mut InvokeContext,
|
||||||
) -> Result<(), EbpfError<BpfError>> {
|
) -> Result<(), EbpfError<BpfError>> {
|
||||||
if len.saturating_mul(size_of::<Pubkey>())
|
let adjusted_len = if invoke_context
|
||||||
> invoke_context.get_compute_budget().max_cpi_instruction_size
|
.feature_set
|
||||||
|
.is_active(&syscall_saturated_math::id())
|
||||||
{
|
{
|
||||||
|
len.saturating_mul(size_of::<Pubkey>())
|
||||||
|
} else {
|
||||||
|
#[allow(clippy::integer_arithmetic)]
|
||||||
|
{
|
||||||
|
len * size_of::<Pubkey>()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if adjusted_len > invoke_context.get_compute_budget().max_cpi_instruction_size {
|
||||||
// Cap the number of account_infos a caller can pass to approximate
|
// Cap the number of account_infos a caller can pass to approximate
|
||||||
// maximum that accounts that could be passed in an instruction
|
// maximum that accounts that could be passed in an instruction
|
||||||
return Err(SyscallError::TooManyAccounts.into());
|
return Err(SyscallError::TooManyAccounts.into());
|
||||||
@ -2724,16 +2761,34 @@ fn call<'a, 'b: 'a>(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
let data_overflow = if do_support_realloc {
|
let data_overflow = if do_support_realloc {
|
||||||
new_len
|
if invoke_context
|
||||||
> caller_account
|
.feature_set
|
||||||
.original_data_len
|
.is_active(&syscall_saturated_math::id())
|
||||||
.saturating_add(MAX_PERMITTED_DATA_INCREASE)
|
{
|
||||||
} else {
|
new_len
|
||||||
|
> caller_account
|
||||||
|
.original_data_len
|
||||||
|
.saturating_add(MAX_PERMITTED_DATA_INCREASE)
|
||||||
|
} else {
|
||||||
|
#[allow(clippy::integer_arithmetic)]
|
||||||
|
{
|
||||||
|
new_len > caller_account.original_data_len + MAX_PERMITTED_DATA_INCREASE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&syscall_saturated_math::id())
|
||||||
|
{
|
||||||
new_len
|
new_len
|
||||||
> caller_account
|
> caller_account
|
||||||
.data
|
.data
|
||||||
.len()
|
.len()
|
||||||
.saturating_add(MAX_PERMITTED_DATA_INCREASE)
|
.saturating_add(MAX_PERMITTED_DATA_INCREASE)
|
||||||
|
} else {
|
||||||
|
#[allow(clippy::integer_arithmetic)]
|
||||||
|
{
|
||||||
|
new_len > caller_account.data.len() + MAX_PERMITTED_DATA_INCREASE
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if data_overflow {
|
if data_overflow {
|
||||||
ic_msg!(
|
ic_msg!(
|
||||||
@ -2790,13 +2845,19 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallSetReturnData<'a, 'b> {
|
|||||||
let loader_id = &question_mark!(get_current_loader_key(&invoke_context), result);
|
let loader_id = &question_mark!(get_current_loader_key(&invoke_context), result);
|
||||||
let budget = invoke_context.get_compute_budget();
|
let budget = invoke_context.get_compute_budget();
|
||||||
|
|
||||||
question_mark!(
|
let cost = if invoke_context
|
||||||
invoke_context.get_compute_meter().consume(
|
.feature_set
|
||||||
len.saturating_div(budget.cpi_bytes_per_unit)
|
.is_active(&syscall_saturated_math::id())
|
||||||
.saturating_add(budget.syscall_base_cost)
|
{
|
||||||
),
|
len.saturating_div(budget.cpi_bytes_per_unit)
|
||||||
result
|
.saturating_add(budget.syscall_base_cost)
|
||||||
);
|
} else {
|
||||||
|
#[allow(clippy::integer_arithmetic)]
|
||||||
|
{
|
||||||
|
len / budget.cpi_bytes_per_unit + budget.syscall_base_cost
|
||||||
|
}
|
||||||
|
};
|
||||||
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
||||||
|
|
||||||
if len > MAX_RETURN_DATA as u64 {
|
if len > MAX_RETURN_DATA as u64 {
|
||||||
*result = Err(SyscallError::ReturnDataTooLarge(len, MAX_RETURN_DATA as u64).into());
|
*result = Err(SyscallError::ReturnDataTooLarge(len, MAX_RETURN_DATA as u64).into());
|
||||||
@ -2866,13 +2927,20 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallGetReturnData<'a, 'b> {
|
|||||||
let (program_id, return_data) = invoke_context.transaction_context.get_return_data();
|
let (program_id, return_data) = invoke_context.transaction_context.get_return_data();
|
||||||
length = length.min(return_data.len() as u64);
|
length = length.min(return_data.len() as u64);
|
||||||
if length != 0 {
|
if length != 0 {
|
||||||
question_mark!(
|
let cost = if invoke_context
|
||||||
invoke_context.get_compute_meter().consume(
|
.feature_set
|
||||||
(length.saturating_add(size_of::<Pubkey>() as u64))
|
.is_active(&syscall_saturated_math::id())
|
||||||
.saturating_div(budget.cpi_bytes_per_unit)
|
{
|
||||||
),
|
length
|
||||||
result
|
.saturating_add(size_of::<Pubkey>() as u64)
|
||||||
);
|
.saturating_div(budget.cpi_bytes_per_unit)
|
||||||
|
} else {
|
||||||
|
#[allow(clippy::integer_arithmetic)]
|
||||||
|
{
|
||||||
|
(length + size_of::<Pubkey>() as u64) / budget.cpi_bytes_per_unit
|
||||||
|
}
|
||||||
|
};
|
||||||
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
||||||
|
|
||||||
let return_data_result = question_mark!(
|
let return_data_result = question_mark!(
|
||||||
translate_slice_mut::<u8>(memory_mapping, return_data_addr, length, loader_id),
|
translate_slice_mut::<u8>(memory_mapping, return_data_addr, length, loader_id),
|
||||||
|
@ -315,6 +315,10 @@ pub mod record_instruction_in_transaction_context_push {
|
|||||||
solana_sdk::declare_id!("3aJdcZqxoLpSBxgeYGjPwaYS1zzcByxUDqJkbzWAH1Zb");
|
solana_sdk::declare_id!("3aJdcZqxoLpSBxgeYGjPwaYS1zzcByxUDqJkbzWAH1Zb");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod syscall_saturated_math {
|
||||||
|
solana_sdk::declare_id!("HyrbKftCdJ5CrUfEti6x26Cj7rZLNe32weugk7tLcWb8");
|
||||||
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
/// Map of feature identifiers to user-visible description
|
/// Map of feature identifiers to user-visible description
|
||||||
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
|
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
|
||||||
@ -384,10 +388,11 @@ lazy_static! {
|
|||||||
(spl_associated_token_account_v1_0_4::id(), "SPL Associated Token Account Program release version 1.0.4, tied to token 3.3.0 #22648"),
|
(spl_associated_token_account_v1_0_4::id(), "SPL Associated Token Account Program release version 1.0.4, tied to token 3.3.0 #22648"),
|
||||||
(reject_vote_account_close_unless_zero_credit_epoch::id(), "fail vote account withdraw to 0 unless account earned 0 credits in last completed epoch"),
|
(reject_vote_account_close_unless_zero_credit_epoch::id(), "fail vote account withdraw to 0 unless account earned 0 credits in last completed epoch"),
|
||||||
(add_get_processed_sibling_instruction_syscall::id(), "add add_get_processed_sibling_instruction_syscall"),
|
(add_get_processed_sibling_instruction_syscall::id(), "add add_get_processed_sibling_instruction_syscall"),
|
||||||
(bank_tranaction_count_fix::id(), "Fixes Bank::transaction_count to include all committed transactions, not just successful ones"),
|
(bank_tranaction_count_fix::id(), "fixes Bank::transaction_count to include all committed transactions, not just successful ones"),
|
||||||
(disable_bpf_deprecated_load_instructions::id(), "Disable ldabs* and ldind* BPF instructions"),
|
(disable_bpf_deprecated_load_instructions::id(), "disable ldabs* and ldind* BPF instructions"),
|
||||||
(disable_bpf_unresolved_symbols_at_runtime::id(), "Disable reporting of unresolved BPF symbols at runtime"),
|
(disable_bpf_unresolved_symbols_at_runtime::id(), "disable reporting of unresolved BPF symbols at runtime"),
|
||||||
(record_instruction_in_transaction_context_push::id(), "Move the CPI stack overflow check to the end of push"),
|
(record_instruction_in_transaction_context_push::id(), "move the CPI stack overflow check to the end of push"),
|
||||||
|
(syscall_saturated_math::id(), "Syscalls use saturated math"),
|
||||||
/*************** ADD NEW FEATURES HERE ***************/
|
/*************** ADD NEW FEATURES HERE ***************/
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
|
Reference in New Issue
Block a user