Add per-byte logging cost (#15279)
This commit is contained in:
@ -17,10 +17,10 @@ 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, pubkey_log_syscall_enabled,
|
abort_on_all_cpi_failures, limit_cpi_loader_invoke, per_byte_logging_cost,
|
||||||
ristretto_mul_syscall_enabled, sha256_syscall_enabled, sol_log_compute_units_syscall,
|
pubkey_log_syscall_enabled, ristretto_mul_syscall_enabled, sha256_syscall_enabled,
|
||||||
try_find_program_address_syscall_enabled, use_loaded_executables,
|
sol_log_compute_units_syscall, try_find_program_address_syscall_enabled,
|
||||||
use_loaded_program_accounts,
|
use_loaded_executables, use_loaded_program_accounts,
|
||||||
},
|
},
|
||||||
hash::{Hasher, HASH_BYTES},
|
hash::{Hasher, HASH_BYTES},
|
||||||
ic_msg,
|
ic_msg,
|
||||||
@ -172,9 +172,20 @@ pub fn bind_syscall_context_objects<'a>(
|
|||||||
// Syscall functions common across languages
|
// Syscall functions common across languages
|
||||||
|
|
||||||
vm.bind_syscall_context_object(Box::new(SyscallAbort {}), None)?;
|
vm.bind_syscall_context_object(Box::new(SyscallAbort {}), None)?;
|
||||||
vm.bind_syscall_context_object(Box::new(SyscallPanic { loader_id }), None)?;
|
vm.bind_syscall_context_object(
|
||||||
|
Box::new(SyscallPanic {
|
||||||
|
compute_meter: if invoke_context.is_feature_active(&per_byte_logging_cost::id()) {
|
||||||
|
Some(invoke_context.get_compute_meter())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
loader_id,
|
||||||
|
}),
|
||||||
|
None,
|
||||||
|
)?;
|
||||||
vm.bind_syscall_context_object(
|
vm.bind_syscall_context_object(
|
||||||
Box::new(SyscallLog {
|
Box::new(SyscallLog {
|
||||||
|
per_byte_cost: invoke_context.is_feature_active(&per_byte_logging_cost::id()),
|
||||||
cost: bpf_compute_budget.log_units,
|
cost: bpf_compute_budget.log_units,
|
||||||
compute_meter: invoke_context.get_compute_meter(),
|
compute_meter: invoke_context.get_compute_meter(),
|
||||||
logger: invoke_context.get_logger(),
|
logger: invoke_context.get_logger(),
|
||||||
@ -425,6 +436,7 @@ impl SyscallObject<BPFError> for SyscallAbort {
|
|||||||
/// Causes the BPF program to be halted immediately
|
/// Causes the BPF program to be halted immediately
|
||||||
/// Log a user's info message
|
/// Log a user's info message
|
||||||
pub struct SyscallPanic<'a> {
|
pub struct SyscallPanic<'a> {
|
||||||
|
compute_meter: Option<Rc<RefCell<dyn ComputeMeter>>>,
|
||||||
loader_id: &'a Pubkey,
|
loader_id: &'a Pubkey,
|
||||||
}
|
}
|
||||||
impl<'a> SyscallObject<BPFError> for SyscallPanic<'a> {
|
impl<'a> SyscallObject<BPFError> for SyscallPanic<'a> {
|
||||||
@ -438,6 +450,9 @@ impl<'a> SyscallObject<BPFError> for SyscallPanic<'a> {
|
|||||||
memory_mapping: &MemoryMapping,
|
memory_mapping: &MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BPFError>>,
|
result: &mut Result<u64, EbpfError<BPFError>>,
|
||||||
) {
|
) {
|
||||||
|
if let Some(ref mut compute_meter) = self.compute_meter {
|
||||||
|
question_mark!(compute_meter.consume(len), result);
|
||||||
|
}
|
||||||
*result = translate_string_and_do(
|
*result = translate_string_and_do(
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
file,
|
file,
|
||||||
@ -450,6 +465,7 @@ impl<'a> SyscallObject<BPFError> for SyscallPanic<'a> {
|
|||||||
|
|
||||||
/// Log a user's info message
|
/// Log a user's info message
|
||||||
pub struct SyscallLog<'a> {
|
pub struct SyscallLog<'a> {
|
||||||
|
per_byte_cost: bool,
|
||||||
cost: u64,
|
cost: u64,
|
||||||
compute_meter: Rc<RefCell<dyn ComputeMeter>>,
|
compute_meter: Rc<RefCell<dyn ComputeMeter>>,
|
||||||
logger: Rc<RefCell<dyn Logger>>,
|
logger: Rc<RefCell<dyn Logger>>,
|
||||||
@ -466,7 +482,11 @@ impl<'a> SyscallObject<BPFError> for SyscallLog<'a> {
|
|||||||
memory_mapping: &MemoryMapping,
|
memory_mapping: &MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BPFError>>,
|
result: &mut Result<u64, EbpfError<BPFError>>,
|
||||||
) {
|
) {
|
||||||
|
if self.per_byte_cost {
|
||||||
|
question_mark!(self.compute_meter.consume(len), result);
|
||||||
|
} else {
|
||||||
question_mark!(self.compute_meter.consume(self.cost), result);
|
question_mark!(self.compute_meter.consume(self.cost), result);
|
||||||
|
}
|
||||||
question_mark!(
|
question_mark!(
|
||||||
translate_string_and_do(
|
translate_string_and_do(
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
@ -2001,7 +2021,34 @@ mod tests {
|
|||||||
}],
|
}],
|
||||||
&DEFAULT_CONFIG,
|
&DEFAULT_CONFIG,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let compute_meter: Rc<RefCell<dyn ComputeMeter>> =
|
||||||
|
Rc::new(RefCell::new(MockComputeMeter {
|
||||||
|
remaining: string.len() as u64 - 1,
|
||||||
|
}));
|
||||||
let mut syscall_panic = SyscallPanic {
|
let mut syscall_panic = SyscallPanic {
|
||||||
|
compute_meter: Some(compute_meter),
|
||||||
|
loader_id: &bpf_loader::id(),
|
||||||
|
};
|
||||||
|
let mut result: Result<u64, EbpfError<BPFError>> = Ok(0);
|
||||||
|
syscall_panic.call(
|
||||||
|
100,
|
||||||
|
string.len() as u64,
|
||||||
|
42,
|
||||||
|
84,
|
||||||
|
0,
|
||||||
|
&memory_mapping,
|
||||||
|
&mut result,
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Err(EbpfError::UserError(BPFError::SyscallError(
|
||||||
|
SyscallError::InstructionError(InstructionError::ComputationalBudgetExceeded)
|
||||||
|
))),
|
||||||
|
result
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut syscall_panic = SyscallPanic {
|
||||||
|
compute_meter: None,
|
||||||
loader_id: &bpf_loader::id(),
|
loader_id: &bpf_loader::id(),
|
||||||
};
|
};
|
||||||
let mut result: Result<u64, EbpfError<BPFError>> = Ok(0);
|
let mut result: Result<u64, EbpfError<BPFError>> = Ok(0);
|
||||||
@ -2028,6 +2075,7 @@ mod tests {
|
|||||||
let logger: Rc<RefCell<dyn Logger>> =
|
let logger: Rc<RefCell<dyn Logger>> =
|
||||||
Rc::new(RefCell::new(MockLogger { log: log.clone() }));
|
Rc::new(RefCell::new(MockLogger { log: log.clone() }));
|
||||||
let mut syscall_sol_log = SyscallLog {
|
let mut syscall_sol_log = SyscallLog {
|
||||||
|
per_byte_cost: false,
|
||||||
cost: 1,
|
cost: 1,
|
||||||
compute_meter,
|
compute_meter,
|
||||||
logger,
|
logger,
|
||||||
@ -2096,6 +2144,46 @@ mod tests {
|
|||||||
))),
|
))),
|
||||||
result
|
result
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let compute_meter: Rc<RefCell<dyn ComputeMeter>> =
|
||||||
|
Rc::new(RefCell::new(MockComputeMeter {
|
||||||
|
remaining: (string.len() as u64 * 2) - 1,
|
||||||
|
}));
|
||||||
|
let logger: Rc<RefCell<dyn Logger>> = Rc::new(RefCell::new(MockLogger { log }));
|
||||||
|
let mut syscall_sol_log = SyscallLog {
|
||||||
|
per_byte_cost: true,
|
||||||
|
cost: 1,
|
||||||
|
compute_meter,
|
||||||
|
logger,
|
||||||
|
loader_id: &bpf_loader::id(),
|
||||||
|
};
|
||||||
|
let mut result: Result<u64, EbpfError<BPFError>> = Ok(0);
|
||||||
|
syscall_sol_log.call(
|
||||||
|
100,
|
||||||
|
string.len() as u64,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
&memory_mapping,
|
||||||
|
&mut result,
|
||||||
|
);
|
||||||
|
result.unwrap();
|
||||||
|
let mut result: Result<u64, EbpfError<BPFError>> = Ok(0);
|
||||||
|
syscall_sol_log.call(
|
||||||
|
100,
|
||||||
|
string.len() as u64,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
&memory_mapping,
|
||||||
|
&mut result,
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Err(EbpfError::UserError(BPFError::SyscallError(
|
||||||
|
SyscallError::InstructionError(InstructionError::ComputationalBudgetExceeded)
|
||||||
|
))),
|
||||||
|
result
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -167,6 +167,10 @@ pub mod warp_timestamp_again {
|
|||||||
solana_sdk::declare_id!("GvDsGDkH5gyzwpDhxNixx8vtx1kwYHH13RiNAPw27zXb");
|
solana_sdk::declare_id!("GvDsGDkH5gyzwpDhxNixx8vtx1kwYHH13RiNAPw27zXb");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod per_byte_logging_cost {
|
||||||
|
solana_sdk::declare_id!("59dM4SV6dPEKXPfkrkhFkRdn4K6xwKxdNAPMyXG7J1wT");
|
||||||
|
}
|
||||||
|
|
||||||
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> = [
|
||||||
@ -209,6 +213,7 @@ lazy_static! {
|
|||||||
(full_inflation::mainnet::certusone::enable::id(), "Full inflation enabled by Certus One"),
|
(full_inflation::mainnet::certusone::enable::id(), "Full inflation enabled by Certus One"),
|
||||||
(full_inflation::mainnet::certusone::vote::id(), "Community vote allowing Certus One to enable full inflation"),
|
(full_inflation::mainnet::certusone::vote::id(), "Community vote allowing Certus One to enable full inflation"),
|
||||||
(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")
|
||||||
/*************** ADD NEW FEATURES HERE ***************/
|
/*************** ADD NEW FEATURES HERE ***************/
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
|
Reference in New Issue
Block a user