* Charge compute budget for bytes passed via cpi (#15874)
(cherry picked from commit ad9901d7c6
)
# Conflicts:
# programs/bpf_loader/src/syscalls.rs
# sdk/src/feature_set.rs
# sdk/src/process_instruction.rs
* fix conflicts
* nudge
Co-authored-by: Jack May <jack@solana.com>
This commit is contained in:
@ -1119,6 +1119,7 @@ mod tests {
|
|||||||
stack_frame_size: 4096,
|
stack_frame_size: 4096,
|
||||||
log_pubkey_units: 100,
|
log_pubkey_units: 100,
|
||||||
max_cpi_instruction_size: usize::MAX,
|
max_cpi_instruction_size: usize::MAX,
|
||||||
|
cpi_bytes_per_unit: 250,
|
||||||
},
|
},
|
||||||
Rc::new(RefCell::new(Executors::default())),
|
Rc::new(RefCell::new(Executors::default())),
|
||||||
None,
|
None,
|
||||||
|
@ -17,7 +17,7 @@ use solana_sdk::{
|
|||||||
bpf_loader_upgradeable::{self, UpgradeableLoaderState},
|
bpf_loader_upgradeable::{self, UpgradeableLoaderState},
|
||||||
entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS},
|
entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS},
|
||||||
feature_set::{
|
feature_set::{
|
||||||
abort_on_all_cpi_failures, limit_cpi_loader_invoke, per_byte_logging_cost,
|
abort_on_all_cpi_failures, cpi_data_cost, limit_cpi_loader_invoke, per_byte_logging_cost,
|
||||||
pubkey_log_syscall_enabled, ristretto_mul_syscall_enabled, sha256_syscall_enabled,
|
pubkey_log_syscall_enabled, ristretto_mul_syscall_enabled, sha256_syscall_enabled,
|
||||||
sol_log_compute_units_syscall, try_find_program_address_syscall_enabled,
|
sol_log_compute_units_syscall, try_find_program_address_syscall_enabled,
|
||||||
use_loaded_executables, use_loaded_program_accounts,
|
use_loaded_executables, use_loaded_program_accounts,
|
||||||
@ -989,7 +989,8 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> {
|
|||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
|
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
|
||||||
|
|
||||||
let translate = |account_info: &AccountInfo| {
|
let translate = |account_info: &AccountInfo,
|
||||||
|
invoke_context: &Ref<&mut dyn InvokeContext>| {
|
||||||
// Translate the account from user space
|
// Translate the account from user space
|
||||||
|
|
||||||
let lamports = {
|
let lamports = {
|
||||||
@ -1006,6 +1007,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> {
|
|||||||
account_info.owner as *const _ as u64,
|
account_info.owner as *const _ as u64,
|
||||||
self.loader_id,
|
self.loader_id,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let (data, vm_data_addr, ref_to_len_in_vm, serialized_len_ptr) = {
|
let (data, vm_data_addr, ref_to_len_in_vm, serialized_len_ptr) = {
|
||||||
// Double translate data out of RefCell
|
// Double translate data out of RefCell
|
||||||
let data = *translate_type::<&[u8]>(
|
let data = *translate_type::<&[u8]>(
|
||||||
@ -1013,6 +1015,14 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> {
|
|||||||
account_info.data.as_ptr() as *const _ as u64,
|
account_info.data.as_ptr() as *const _ as u64,
|
||||||
self.loader_id,
|
self.loader_id,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
if invoke_context.is_feature_active(&cpi_data_cost::id()) {
|
||||||
|
invoke_context.get_compute_meter().consume(
|
||||||
|
data.len() as u64
|
||||||
|
/ invoke_context.get_bpf_compute_budget().cpi_bytes_per_unit,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
let translated = translate(
|
let translated = translate(
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
AccessType::Store,
|
AccessType::Store,
|
||||||
@ -1283,7 +1293,8 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> {
|
|||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
|
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
|
||||||
|
|
||||||
let translate = |account_info: &SolAccountInfo| {
|
let translate = |account_info: &SolAccountInfo,
|
||||||
|
invoke_context: &Ref<&mut dyn InvokeContext>| {
|
||||||
// Translate the account from user space
|
// Translate the account from user space
|
||||||
|
|
||||||
let lamports = translate_type_mut::<u64>(
|
let lamports = translate_type_mut::<u64>(
|
||||||
@ -1297,6 +1308,14 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> {
|
|||||||
self.loader_id,
|
self.loader_id,
|
||||||
)?;
|
)?;
|
||||||
let vm_data_addr = account_info.data_addr;
|
let vm_data_addr = account_info.data_addr;
|
||||||
|
|
||||||
|
if invoke_context.is_feature_active(&cpi_data_cost::id()) {
|
||||||
|
invoke_context.get_compute_meter().consume(
|
||||||
|
account_info.data_len
|
||||||
|
/ invoke_context.get_bpf_compute_budget().cpi_bytes_per_unit,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
let data = translate_slice_mut::<u8>(
|
let data = translate_slice_mut::<u8>(
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
vm_data_addr,
|
vm_data_addr,
|
||||||
@ -1436,7 +1455,7 @@ fn get_translated_accounts<'a, T, F>(
|
|||||||
do_translate: F,
|
do_translate: F,
|
||||||
) -> Result<TranslatedAccounts<'a>, EbpfError<BpfError>>
|
) -> Result<TranslatedAccounts<'a>, EbpfError<BpfError>>
|
||||||
where
|
where
|
||||||
F: Fn(&T) -> Result<TranslatedAccount<'a>, EbpfError<BpfError>>,
|
F: Fn(&T, &Ref<&mut dyn InvokeContext>) -> Result<TranslatedAccount<'a>, EbpfError<BpfError>>,
|
||||||
{
|
{
|
||||||
let mut accounts = Vec::with_capacity(account_keys.len());
|
let mut accounts = Vec::with_capacity(account_keys.len());
|
||||||
let mut refs = Vec::with_capacity(account_keys.len());
|
let mut refs = Vec::with_capacity(account_keys.len());
|
||||||
@ -1470,7 +1489,7 @@ where
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
let (account, account_ref) = do_translate(account_info)?;
|
let (account, account_ref) = do_translate(account_info, invoke_context)?;
|
||||||
accounts.push(account);
|
accounts.push(account);
|
||||||
refs.push(account_ref);
|
refs.push(account_ref);
|
||||||
} else {
|
} else {
|
||||||
|
@ -171,6 +171,10 @@ pub mod check_program_owner {
|
|||||||
solana_sdk::declare_id!("5XnbR5Es9YXEARRuP6mdvoxiW3hx5atNNeBmwVd8P3QD");
|
solana_sdk::declare_id!("5XnbR5Es9YXEARRuP6mdvoxiW3hx5atNNeBmwVd8P3QD");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod cpi_data_cost {
|
||||||
|
solana_sdk::declare_id!("Hrg5bXePPGiAVWZfDHbvjqytSeyBDPAGAQ7v6N5i4gCX");
|
||||||
|
}
|
||||||
|
|
||||||
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> = [
|
||||||
@ -213,7 +217,8 @@ lazy_static! {
|
|||||||
(warp_timestamp_again::id(), "warp timestamp again, adjust bounding to 25% fast 80% slow #15204"),
|
(warp_timestamp_again::id(), "warp timestamp again, adjust bounding to 25% fast 80% slow #15204"),
|
||||||
(per_byte_logging_cost::id(), "charge the compute budget per byte for logging"),
|
(per_byte_logging_cost::id(), "charge the compute budget per byte for logging"),
|
||||||
(check_init_vote_data::id(), "check initialized Vote data"),
|
(check_init_vote_data::id(), "check initialized Vote data"),
|
||||||
(check_program_owner::id(), "limit programs to operating on accounts owned by itself")
|
(check_program_owner::id(), "limit programs to operating on accounts owned by itself"),
|
||||||
|
(cpi_data_cost::id(), "charge the compute budger for data passed via CPI"),
|
||||||
/*************** ADD NEW FEATURES HERE ***************/
|
/*************** ADD NEW FEATURES HERE ***************/
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -124,6 +124,8 @@ pub struct BpfComputeBudget {
|
|||||||
pub log_pubkey_units: u64,
|
pub log_pubkey_units: u64,
|
||||||
/// Maximum cross-program invocation instruction size
|
/// Maximum cross-program invocation instruction size
|
||||||
pub max_cpi_instruction_size: usize,
|
pub max_cpi_instruction_size: usize,
|
||||||
|
/// Number of account data bytes per conpute unit charged during a cross-program invocation
|
||||||
|
pub cpi_bytes_per_unit: u64,
|
||||||
}
|
}
|
||||||
impl Default for BpfComputeBudget {
|
impl Default for BpfComputeBudget {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
@ -147,6 +149,7 @@ impl BpfComputeBudget {
|
|||||||
stack_frame_size: 4_096,
|
stack_frame_size: 4_096,
|
||||||
log_pubkey_units: 0,
|
log_pubkey_units: 0,
|
||||||
max_cpi_instruction_size: std::usize::MAX,
|
max_cpi_instruction_size: std::usize::MAX,
|
||||||
|
cpi_bytes_per_unit: 250,
|
||||||
};
|
};
|
||||||
|
|
||||||
if feature_set.is_active(&bpf_compute_budget_balancing::id()) {
|
if feature_set.is_active(&bpf_compute_budget_balancing::id()) {
|
||||||
|
Reference in New Issue
Block a user