Use consistent naming for compute unit limit (#25229)

* Use consistent naming for compute unit limit

* feedback
This commit is contained in:
Justin Starry 2022-05-18 13:14:31 +08:00 committed by GitHub
parent 66c9513eb0
commit a1522d0024
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 173 additions and 134 deletions

View File

@ -115,11 +115,11 @@ Compute Budget instructions don't require any accounts and don't consume any
compute units to process. Transactions can only contain one of each type of
compute budget instruction, duplicate types will result in an error.
The `ComputeBudgetInstruction::request_units` function can be used to create
The `ComputeBudgetInstruction::set_compute_unit_limit` function can be used to create
these instructions:
```rust
let instruction = ComputeBudgetInstruction::request_units(300_000);
let instruction = ComputeBudgetInstruction::set_compute_unit_limit(300_000);
```
## Transaction-wide Compute Budget

View File

@ -10,8 +10,8 @@ use {
},
};
pub const DEFAULT_UNITS: u32 = 200_000;
pub const MAX_UNITS: u32 = 1_400_000;
pub const DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT: u32 = 200_000;
pub const MAX_COMPUTE_UNIT_LIMIT: u32 = 1_400_000;
const MAX_HEAP_FRAME_BYTES: u32 = 256 * 1024;
#[cfg(RUSTC_WITH_SPECIALIZATION)]
@ -24,9 +24,10 @@ impl ::solana_frozen_abi::abi_example::AbiExample for ComputeBudget {
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct ComputeBudget {
/// Number of compute units that an instruction is allowed. Compute units
/// are consumed by program execution, resources they use, etc...
pub max_units: u64,
/// Number of compute units that a transaction or individual instruction is
/// allowed to consume. Compute units are consumed by program execution,
/// resources they use, etc...
pub compute_unit_limit: u64,
/// Number of compute units consumed by a log_u64 call
pub log_64_units: u64,
/// Number of compute units consumed by a create_program_address call
@ -87,14 +88,14 @@ pub struct ComputeBudget {
impl Default for ComputeBudget {
fn default() -> Self {
Self::new(MAX_UNITS)
Self::new(MAX_COMPUTE_UNIT_LIMIT as u64)
}
}
impl ComputeBudget {
pub fn new(max_units: u32) -> Self {
pub fn new(compute_unit_limit: u64) -> Self {
ComputeBudget {
max_units: max_units as u64,
compute_unit_limit,
log_64_units: 100,
create_program_address_units: 1500,
invoke_units: 1000,
@ -133,7 +134,7 @@ impl ComputeBudget {
support_set_compute_unit_price_ix: bool,
) -> Result<PrioritizationFeeDetails, TransactionError> {
let mut num_non_compute_budget_instructions: usize = 0;
let mut requested_units = None;
let mut updated_compute_unit_limit = None;
let mut requested_heap_size = None;
let mut prioritization_fee = None;
@ -149,16 +150,16 @@ impl ComputeBudget {
match try_from_slice_unchecked(&instruction.data) {
Ok(ComputeBudgetInstruction::RequestUnitsDeprecated {
units,
units: compute_unit_limit,
additional_fee,
}) => {
if requested_units.is_some() {
if updated_compute_unit_limit.is_some() {
return Err(duplicate_instruction_error);
}
if prioritization_fee.is_some() {
return Err(duplicate_instruction_error);
}
requested_units = Some(units as u64);
updated_compute_unit_limit = Some(compute_unit_limit);
prioritization_fee =
Some(PrioritizationFeeType::Deprecated(additional_fee as u64));
}
@ -168,11 +169,11 @@ impl ComputeBudget {
}
requested_heap_size = Some((bytes, i as u8));
}
Ok(ComputeBudgetInstruction::RequestUnits(units)) => {
if requested_units.is_some() {
Ok(ComputeBudgetInstruction::SetComputeUnitLimit(compute_unit_limit)) => {
if updated_compute_unit_limit.is_some() {
return Err(duplicate_instruction_error);
}
requested_units = Some(units as u64);
updated_compute_unit_limit = Some(compute_unit_limit);
}
Ok(ComputeBudgetInstruction::SetComputeUnitPrice(micro_lamports)) => {
if prioritization_fee.is_some() {
@ -186,10 +187,10 @@ impl ComputeBudget {
} else if i < 3 {
match try_from_slice_unchecked(&instruction.data) {
Ok(ComputeBudgetInstruction::RequestUnitsDeprecated {
units,
units: compute_unit_limit,
additional_fee,
}) => {
requested_units = Some(units as u64);
updated_compute_unit_limit = Some(compute_unit_limit);
prioritization_fee =
Some(PrioritizationFeeType::Deprecated(additional_fee as u64));
}
@ -225,21 +226,21 @@ impl ComputeBudget {
self.heap_size = Some(bytes as usize);
}
self.max_units = if default_units_per_instruction {
requested_units.or_else(|| {
self.compute_unit_limit = if default_units_per_instruction {
updated_compute_unit_limit.or_else(|| {
Some(
num_non_compute_budget_instructions.saturating_mul(DEFAULT_UNITS as usize)
as u64,
(num_non_compute_budget_instructions as u32)
.saturating_mul(DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT),
)
})
} else {
requested_units
updated_compute_unit_limit
}
.unwrap_or(MAX_UNITS as u64)
.min(MAX_UNITS as u64);
.unwrap_or(MAX_COMPUTE_UNIT_LIMIT)
.min(MAX_COMPUTE_UNIT_LIMIT) as u64;
Ok(prioritization_fee
.map(|fee_type| PrioritizationFeeDetails::new(fee_type, self.max_units))
.map(|fee_type| PrioritizationFeeDetails::new(fee_type, self.compute_unit_limit))
.unwrap_or_default())
}
}
@ -300,40 +301,40 @@ mod tests {
&[],
Ok(PrioritizationFeeDetails::default()),
ComputeBudget {
max_units: 0,
compute_unit_limit: 0,
..ComputeBudget::default()
}
);
test!(
&[
ComputeBudgetInstruction::request_units(1),
ComputeBudgetInstruction::set_compute_unit_limit(1),
Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]),
],
Ok(PrioritizationFeeDetails::default()),
ComputeBudget {
max_units: 1,
compute_unit_limit: 1,
..ComputeBudget::default()
}
);
test!(
&[
ComputeBudgetInstruction::request_units(MAX_UNITS + 1),
ComputeBudgetInstruction::set_compute_unit_limit(MAX_COMPUTE_UNIT_LIMIT + 1),
Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]),
],
Ok(PrioritizationFeeDetails::default()),
ComputeBudget {
max_units: MAX_UNITS as u64,
compute_unit_limit: MAX_COMPUTE_UNIT_LIMIT as u64,
..ComputeBudget::default()
}
);
test!(
&[
Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]),
ComputeBudgetInstruction::request_units(MAX_UNITS),
ComputeBudgetInstruction::set_compute_unit_limit(MAX_COMPUTE_UNIT_LIMIT),
],
Ok(PrioritizationFeeDetails::default()),
ComputeBudget {
max_units: MAX_UNITS as u64,
compute_unit_limit: MAX_COMPUTE_UNIT_LIMIT as u64,
..ComputeBudget::default()
}
);
@ -342,11 +343,11 @@ mod tests {
Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]),
Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]),
Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]),
ComputeBudgetInstruction::request_units(1),
ComputeBudgetInstruction::set_compute_unit_limit(1),
],
Ok(PrioritizationFeeDetails::default()),
ComputeBudget {
max_units: 1,
compute_unit_limit: 1,
..ComputeBudget::default()
}
);
@ -356,11 +357,11 @@ mod tests {
Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]),
Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]),
Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]),
ComputeBudgetInstruction::request_units(1), // ignored
ComputeBudgetInstruction::set_compute_unit_limit(1), // ignored
],
Ok(PrioritizationFeeDetails::default()),
ComputeBudget {
max_units: DEFAULT_UNITS as u64 * 3,
compute_unit_limit: DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64 * 3,
..ComputeBudget::default()
},
false
@ -374,7 +375,7 @@ mod tests {
1,
)),
ComputeBudget {
max_units: 1,
compute_unit_limit: 1,
..ComputeBudget::default()
},
false
@ -382,7 +383,7 @@ mod tests {
test!(
&[
ComputeBudgetInstruction::request_units(1),
ComputeBudgetInstruction::set_compute_unit_limit(1),
ComputeBudgetInstruction::set_compute_unit_price(42)
],
Ok(PrioritizationFeeDetails::new(
@ -390,7 +391,7 @@ mod tests {
1
)),
ComputeBudget {
max_units: 1,
compute_unit_limit: 1,
..ComputeBudget::default()
}
);
@ -402,7 +403,7 @@ mod tests {
1
)),
ComputeBudget {
max_units: 1,
compute_unit_limit: 1,
..ComputeBudget::default()
},
false
@ -413,7 +414,7 @@ mod tests {
&[],
Ok(PrioritizationFeeDetails::default()),
ComputeBudget {
max_units: 0,
compute_unit_limit: 0,
..ComputeBudget::default()
}
);
@ -424,7 +425,7 @@ mod tests {
],
Ok(PrioritizationFeeDetails::default()),
ComputeBudget {
max_units: DEFAULT_UNITS as u64,
compute_unit_limit: DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64,
heap_size: Some(40 * 1024),
..ComputeBudget::default()
}
@ -469,7 +470,7 @@ mod tests {
],
Ok(PrioritizationFeeDetails::default()),
ComputeBudget {
max_units: DEFAULT_UNITS as u64,
compute_unit_limit: DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64,
heap_size: Some(MAX_HEAP_FRAME_BYTES as usize),
..ComputeBudget::default()
}
@ -501,7 +502,7 @@ mod tests {
],
Ok(PrioritizationFeeDetails::default()),
ComputeBudget {
max_units: DEFAULT_UNITS as u64 * 7,
compute_unit_limit: DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64 * 7,
..ComputeBudget::default()
}
);
@ -511,15 +512,15 @@ mod tests {
&[
Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]),
ComputeBudgetInstruction::request_heap_frame(MAX_HEAP_FRAME_BYTES),
ComputeBudgetInstruction::request_units(MAX_UNITS),
ComputeBudgetInstruction::set_compute_unit_limit(MAX_COMPUTE_UNIT_LIMIT),
ComputeBudgetInstruction::set_compute_unit_price(u64::MAX),
],
Ok(PrioritizationFeeDetails::new(
PrioritizationFeeType::ComputeUnitPrice(u64::MAX),
MAX_UNITS as u64,
MAX_COMPUTE_UNIT_LIMIT as u64,
)),
ComputeBudget {
max_units: MAX_UNITS as u64,
compute_unit_limit: MAX_COMPUTE_UNIT_LIMIT as u64,
heap_size: Some(MAX_HEAP_FRAME_BYTES as usize),
..ComputeBudget::default()
}
@ -529,7 +530,7 @@ mod tests {
&[
Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]),
ComputeBudgetInstruction::request_heap_frame(MAX_HEAP_FRAME_BYTES),
ComputeBudgetInstruction::request_units(MAX_UNITS),
ComputeBudgetInstruction::set_compute_unit_limit(MAX_COMPUTE_UNIT_LIMIT),
ComputeBudgetInstruction::set_compute_unit_price(u64::MAX),
],
Err(TransactionError::InstructionError(
@ -543,7 +544,7 @@ mod tests {
test!(
&[
Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]),
ComputeBudgetInstruction::request_units(1),
ComputeBudgetInstruction::set_compute_unit_limit(1),
ComputeBudgetInstruction::request_heap_frame(MAX_HEAP_FRAME_BYTES),
ComputeBudgetInstruction::set_compute_unit_price(u64::MAX),
],
@ -552,7 +553,7 @@ mod tests {
1
)),
ComputeBudget {
max_units: 1,
compute_unit_limit: 1,
heap_size: Some(MAX_HEAP_FRAME_BYTES as usize),
..ComputeBudget::default()
}
@ -561,15 +562,15 @@ mod tests {
test!(
&[
Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]),
request_units_deprecated(MAX_UNITS, u32::MAX),
request_units_deprecated(MAX_COMPUTE_UNIT_LIMIT, u32::MAX),
ComputeBudgetInstruction::request_heap_frame(MIN_HEAP_FRAME_BYTES as u32),
],
Ok(PrioritizationFeeDetails::new(
PrioritizationFeeType::Deprecated(u32::MAX as u64),
MAX_UNITS as u64,
MAX_COMPUTE_UNIT_LIMIT as u64,
)),
ComputeBudget {
max_units: MAX_UNITS as u64,
compute_unit_limit: MAX_COMPUTE_UNIT_LIMIT as u64,
heap_size: Some(MIN_HEAP_FRAME_BYTES as usize),
..ComputeBudget::default()
},
@ -580,8 +581,8 @@ mod tests {
test!(
&[
Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]),
ComputeBudgetInstruction::request_units(MAX_UNITS),
ComputeBudgetInstruction::request_units(MAX_UNITS - 1),
ComputeBudgetInstruction::set_compute_unit_limit(MAX_COMPUTE_UNIT_LIMIT),
ComputeBudgetInstruction::set_compute_unit_limit(MAX_COMPUTE_UNIT_LIMIT - 1),
],
Err(TransactionError::DuplicateInstruction(2)),
ComputeBudget::default()

View File

@ -255,7 +255,7 @@ impl<'a> InvokeContext<'a> {
log_collector,
current_compute_budget: compute_budget,
compute_budget,
compute_meter: ComputeMeter::new_ref(compute_budget.max_units),
compute_meter: ComputeMeter::new_ref(compute_budget.compute_unit_limit),
accounts_data_meter: AccountsDataMeter::new(initial_accounts_data_len),
executors,
feature_set,
@ -351,7 +351,7 @@ impl<'a> InvokeContext<'a> {
&& program_id == Some(&crate::neon_evm_program::id())
{
// Bump the compute budget for neon_evm
compute_budget.max_units = compute_budget.max_units.max(500_000);
compute_budget.compute_unit_limit = compute_budget.compute_unit_limit.max(500_000);
}
if !self.feature_set.is_active(&requestable_heap_size::id())
&& self.feature_set.is_active(&neon_evm_compute_budget::id())
@ -363,7 +363,8 @@ impl<'a> InvokeContext<'a> {
self.current_compute_budget = compute_budget;
if !self.feature_set.is_active(&tx_wide_compute_cap::id()) {
self.compute_meter = ComputeMeter::new_ref(self.current_compute_budget.max_units);
self.compute_meter =
ComputeMeter::new_ref(self.current_compute_budget.compute_unit_limit);
}
self.pre_accounts = Vec::with_capacity(instruction_accounts.len());
@ -1760,20 +1761,21 @@ mod tests {
let mut transaction_context = TransactionContext::new(accounts, 1, 3);
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
invoke_context.feature_set = Arc::new(feature_set);
invoke_context.compute_budget = ComputeBudget::new(compute_budget::DEFAULT_UNITS);
invoke_context.compute_budget =
ComputeBudget::new(compute_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64);
invoke_context.push(&[], &[0], &[]).unwrap();
assert_eq!(
*invoke_context.get_compute_budget(),
ComputeBudget::new(compute_budget::DEFAULT_UNITS)
ComputeBudget::new(compute_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64)
);
invoke_context.pop().unwrap();
invoke_context.push(&[], &[1], &[]).unwrap();
let expected_compute_budget = ComputeBudget {
max_units: 500_000,
compute_unit_limit: 500_000,
heap_size: Some(256_usize.saturating_mul(1024)),
..ComputeBudget::new(compute_budget::DEFAULT_UNITS)
..ComputeBudget::new(compute_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64)
};
assert_eq!(
*invoke_context.get_compute_budget(),
@ -1784,7 +1786,7 @@ mod tests {
invoke_context.push(&[], &[0], &[]).unwrap();
assert_eq!(
*invoke_context.get_compute_budget(),
ComputeBudget::new(compute_budget::DEFAULT_UNITS)
ComputeBudget::new(compute_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64)
);
invoke_context.pop().unwrap();
}

View File

@ -15,15 +15,15 @@ pub struct PrioritizationFeeDetails {
}
impl PrioritizationFeeDetails {
pub fn new(fee_type: PrioritizationFeeType, max_compute_units: u64) -> Self {
pub fn new(fee_type: PrioritizationFeeType, compute_unit_limit: u64) -> Self {
match fee_type {
PrioritizationFeeType::Deprecated(fee) => {
let priority = if max_compute_units == 0 {
let priority = if compute_unit_limit == 0 {
0
} else {
let micro_lamport_fee: MicroLamports =
(fee as u128).saturating_mul(MICRO_LAMPORTS_PER_LAMPORT as u128);
let priority = micro_lamport_fee.saturating_div(max_compute_units as u128);
let priority = micro_lamport_fee.saturating_div(compute_unit_limit as u128);
u64::try_from(priority).unwrap_or(u64::MAX)
};
@ -32,7 +32,7 @@ impl PrioritizationFeeDetails {
PrioritizationFeeType::ComputeUnitPrice(cu_price) => {
let fee = {
let micro_lamport_fee: MicroLamports =
(cu_price as u128).saturating_mul(max_compute_units as u128);
(cu_price as u128).saturating_mul(compute_unit_limit as u128);
let fee = micro_lamport_fee
.saturating_add(MICRO_LAMPORTS_PER_LAMPORT.saturating_sub(1) as u128)
.saturating_div(MICRO_LAMPORTS_PER_LAMPORT as u128);

View File

@ -802,7 +802,7 @@ impl ProgramTest {
bank.set_capitalization();
if let Some(max_units) = self.compute_max_units {
bank.set_compute_budget(Some(ComputeBudget {
max_units,
compute_unit_limit: max_units,
..ComputeBudget::default()
}));
}

View File

@ -1398,7 +1398,7 @@ fn test_program_bpf_compute_budget() {
);
let message = Message::new(
&[
ComputeBudgetInstruction::request_units(1),
ComputeBudgetInstruction::set_compute_unit_limit(1),
Instruction::new_with_bincode(program_id, &0, vec![]),
],
Some(&mint_keypair.pubkey()),

View File

@ -4382,12 +4382,12 @@ impl Bank {
compute_budget
} else {
let tx_wide_compute_cap = feature_set.is_active(&tx_wide_compute_cap::id());
let compute_budget_max_units = if tx_wide_compute_cap {
compute_budget::MAX_UNITS
let compute_unit_limit = if tx_wide_compute_cap {
compute_budget::MAX_COMPUTE_UNIT_LIMIT
} else {
compute_budget::DEFAULT_UNITS
compute_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT
};
let mut compute_budget = ComputeBudget::new(compute_budget_max_units);
let mut compute_budget = ComputeBudget::new(compute_unit_limit as u64);
if tx_wide_compute_cap {
let mut compute_budget_process_transaction_time =
Measure::start("compute_budget_process_transaction_time");
@ -4640,7 +4640,7 @@ impl Bank {
let compute_fee = fee_structure
.compute_fee_bins
.iter()
.find(|bin| compute_budget.max_units <= bin.limit)
.find(|bin| compute_budget.compute_unit_limit <= bin.limit)
.map(|bin| bin.fee)
.unwrap_or_else(|| {
fee_structure
@ -7251,7 +7251,7 @@ pub(crate) mod tests {
},
crossbeam_channel::{bounded, unbounded},
solana_program_runtime::{
compute_budget::MAX_UNITS,
compute_budget::MAX_COMPUTE_UNIT_LIMIT,
invoke_context::InvokeContext,
prioritization_fee::{PrioritizationFeeDetails, PrioritizationFeeType},
},
@ -16424,7 +16424,7 @@ pub(crate) mod tests {
assert_eq!(
*compute_budget,
ComputeBudget {
max_units: 200_000,
compute_unit_limit: 200_000,
heap_size: None,
..ComputeBudget::default()
}
@ -16436,7 +16436,7 @@ pub(crate) mod tests {
let message = Message::new(
&[
ComputeBudgetInstruction::request_units(1),
ComputeBudgetInstruction::set_compute_unit_limit(1),
ComputeBudgetInstruction::request_heap_frame(48 * 1024),
Instruction::new_with_bincode(program_id, &0, vec![]),
],
@ -16468,7 +16468,7 @@ pub(crate) mod tests {
assert_eq!(
*compute_budget,
ComputeBudget {
max_units: 1,
compute_unit_limit: 1,
heap_size: Some(48 * 1024),
..ComputeBudget::default()
}
@ -16480,7 +16480,7 @@ pub(crate) mod tests {
let message = Message::new(
&[
ComputeBudgetInstruction::request_units(1),
ComputeBudgetInstruction::set_compute_unit_limit(1),
ComputeBudgetInstruction::request_heap_frame(48 * 1024),
Instruction::new_with_bincode(program_id, &0, vec![]),
],
@ -16519,7 +16519,7 @@ pub(crate) mod tests {
assert_eq!(
*compute_budget,
ComputeBudget {
max_units: 1,
compute_unit_limit: 1,
heap_size: Some(48 * 1024),
..ComputeBudget::default()
}
@ -16540,7 +16540,7 @@ pub(crate) mod tests {
// This message will be processed successfully
let message1 = Message::new(
&[
ComputeBudgetInstruction::request_units(1),
ComputeBudgetInstruction::set_compute_unit_limit(1),
ComputeBudgetInstruction::request_heap_frame(48 * 1024),
Instruction::new_with_bincode(program_id, &0, vec![]),
],
@ -16778,8 +16778,17 @@ pub(crate) mod tests {
// Explicit fee schedule
for requested_compute_units in [
0, 5_000, 10_000, 100_000, 300_000, 500_000, 700_000, 900_000, 1_100_000, 1_300_000,
MAX_UNITS,
0,
5_000,
10_000,
100_000,
300_000,
500_000,
700_000,
900_000,
1_100_000,
1_300_000,
MAX_COMPUTE_UNIT_LIMIT,
] {
const PRIORITIZATION_FEE_RATE: u64 = 42;
let prioritization_fee_details = PrioritizationFeeDetails::new(
@ -16788,7 +16797,7 @@ pub(crate) mod tests {
);
let message = SanitizedMessage::try_from(Message::new(
&[
ComputeBudgetInstruction::request_units(requested_compute_units),
ComputeBudgetInstruction::set_compute_unit_limit(requested_compute_units),
ComputeBudgetInstruction::set_compute_unit_price(PRIORITIZATION_FEE_RATE),
Instruction::new_with_bincode(Pubkey::new_unique(), &0, vec![]),
],
@ -17633,9 +17642,9 @@ pub(crate) mod tests {
None,
);
let compute_budget = bank
.compute_budget
.unwrap_or_else(|| ComputeBudget::new(compute_budget::DEFAULT_UNITS));
let compute_budget = bank.compute_budget.unwrap_or_else(|| {
ComputeBudget::new(compute_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64)
});
let transaction_context = TransactionContext::new(
loaded_txs[0].0.as_ref().unwrap().accounts.clone(),
compute_budget.max_invoke_depth.saturating_add(1),

View File

@ -117,7 +117,9 @@ impl CostModel {
match self.instruction_execution_cost_table.get_cost(program_key) {
Some(cost) => *cost,
None => {
let default_value = self.instruction_execution_cost_table.get_default_units();
let default_value = self
.instruction_execution_cost_table
.get_default_compute_unit_limit();
debug!(
"Program {:?} does not have aggregated cost, using default value {}",
program_key, default_value
@ -286,7 +288,9 @@ mod tests {
// unknown program is assigned with default cost
assert_eq!(
testee.instruction_execution_cost_table.get_default_units(),
testee
.instruction_execution_cost_table
.get_default_compute_unit_limit(),
testee.find_instruction_cost(
&Pubkey::from_str("unknown111111111111111111111111111111111111").unwrap()
)
@ -421,7 +425,10 @@ mod tests {
debug!("many random transaction {:?}", tx);
let testee = CostModel::default();
let expected_cost = testee.instruction_execution_cost_table.get_default_units() * 2;
let expected_cost = testee
.instruction_execution_cost_table
.get_default_compute_unit_limit()
* 2;
let mut tx_cost = TransactionCost::default();
testee.get_transaction_cost(&mut tx_cost, &tx);
assert_eq!(0, tx_cost.builtins_execution_cost);
@ -471,7 +478,7 @@ mod tests {
assert_eq!(
cost_model
.instruction_execution_cost_table
.get_default_units(),
.get_default_compute_unit_limit(),
cost_model.find_instruction_cost(&key1)
);

View File

@ -4,8 +4,8 @@
/// When its capacity limit is reached, it prunes old and less-used programs
/// to make room for new ones.
use {
log::*, solana_program_runtime::compute_budget::DEFAULT_UNITS, solana_sdk::pubkey::Pubkey,
std::collections::HashMap,
log::*, solana_program_runtime::compute_budget::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT,
solana_sdk::pubkey::Pubkey, std::collections::HashMap,
};
// prune is rather expensive op, free up bulk space in each operation
@ -44,24 +44,24 @@ impl ExecuteCostTable {
self.table.len()
}
/// default program cost, set to ComputeBudget::DEFAULT_UNITS
pub fn get_default_units(&self) -> u64 {
DEFAULT_UNITS as u64
/// default program cost, set to ComputeBudget::DEFAULT_COMPUTE_UNIT_LIMIT
pub fn get_default_compute_unit_limit(&self) -> u64 {
DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT as u64
}
/// average cost of all recorded programs
pub fn get_global_average_units(&self) -> u64 {
pub fn get_global_average_program_cost(&self) -> u64 {
if self.table.is_empty() {
self.get_default_units()
self.get_default_compute_unit_limit()
} else {
self.table.iter().map(|(_, value)| value).sum::<u64>() / self.get_count() as u64
}
}
/// the most frequently occurring program's cost
pub fn get_statistical_mode_units(&self) -> u64 {
pub fn get_statistical_mode_program_cost(&self) -> u64 {
if self.occurrences.is_empty() {
self.get_default_units()
self.get_default_compute_unit_limit()
} else {
let key = self
.occurrences
@ -75,8 +75,9 @@ impl ExecuteCostTable {
}
/// returns None if program doesn't exist in table. In this case,
/// `get_default_units()`, `get_global_average_units()` or `get_statistical_mode_units()`
/// can be used to assign a value to new program.
/// `get_default_compute_unit_limit()`, `get_global_average_program_cost()`
/// or `get_statistical_mode_program_cost()` can be used to assign a value
/// to new program.
pub fn get_cost(&self, key: &Pubkey) -> Option<&u64> {
self.table.get(key)
}
@ -225,15 +226,18 @@ mod tests {
// insert one record
testee.upsert(&key1, cost1);
assert_eq!(1, testee.get_count());
assert_eq!(cost1, testee.get_global_average_units());
assert_eq!(cost1, testee.get_statistical_mode_units());
assert_eq!(cost1, testee.get_global_average_program_cost());
assert_eq!(cost1, testee.get_statistical_mode_program_cost());
assert_eq!(&cost1, testee.get_cost(&key1).unwrap());
// insert 2nd record
testee.upsert(&key2, cost2);
assert_eq!(2, testee.get_count());
assert_eq!((cost1 + cost2) / 2_u64, testee.get_global_average_units());
assert_eq!(cost2, testee.get_statistical_mode_units());
assert_eq!(
(cost1 + cost2) / 2_u64,
testee.get_global_average_program_cost()
);
assert_eq!(cost2, testee.get_statistical_mode_program_cost());
assert_eq!(&cost1, testee.get_cost(&key1).unwrap());
assert_eq!(&cost2, testee.get_cost(&key2).unwrap());
@ -242,9 +246,12 @@ mod tests {
assert_eq!(2, testee.get_count());
assert_eq!(
((cost1 + cost2) / 2 + cost2) / 2_u64,
testee.get_global_average_units()
testee.get_global_average_program_cost()
);
assert_eq!(
(cost1 + cost2) / 2,
testee.get_statistical_mode_program_cost()
);
assert_eq!((cost1 + cost2) / 2, testee.get_statistical_mode_units());
assert_eq!(&((cost1 + cost2) / 2), testee.get_cost(&key1).unwrap());
assert_eq!(&cost2, testee.get_cost(&key2).unwrap());
}
@ -278,8 +285,11 @@ mod tests {
// insert 3rd record, pushes out the oldest (eg 1st) record
testee.upsert(&key3, cost3);
assert_eq!(2, testee.get_count());
assert_eq!((cost2 + cost3) / 2_u64, testee.get_global_average_units());
assert_eq!(cost3, testee.get_statistical_mode_units());
assert_eq!(
(cost2 + cost3) / 2_u64,
testee.get_global_average_program_cost()
);
assert_eq!(cost3, testee.get_statistical_mode_program_cost());
assert!(testee.get_cost(&key1).is_none());
assert_eq!(&cost2, testee.get_cost(&key2).unwrap());
assert_eq!(&cost3, testee.get_cost(&key3).unwrap());
@ -290,9 +300,12 @@ mod tests {
testee.upsert(&key4, cost4);
assert_eq!(
((cost1 + cost2) / 2 + cost4) / 2_u64,
testee.get_global_average_units()
testee.get_global_average_program_cost()
);
assert_eq!(
(cost1 + cost2) / 2,
testee.get_statistical_mode_program_cost()
);
assert_eq!((cost1 + cost2) / 2, testee.get_statistical_mode_units());
assert_eq!(2, testee.get_count());
assert!(testee.get_cost(&key1).is_none());
assert_eq!(&((cost1 + cost2) / 2), testee.get_cost(&key2).unwrap());

View File

@ -32,9 +32,8 @@ pub enum ComputeBudgetInstruction {
/// size applies to each program executed in the transaction, including all
/// calls to CPIs.
RequestHeapFrame(u32),
/// Request a specific maximum number of compute units the transaction is
/// allowed to consume and an additional fee to pay.
RequestUnits(u32),
/// Set a specific compute unit limit that the transaction is allowed to consume.
SetComputeUnitLimit(u32),
/// Set a compute unit price in "micro-lamports" to pay a higher transaction
/// fee for higher transaction prioritization.
SetComputeUnitPrice(u64),
@ -46,9 +45,9 @@ impl ComputeBudgetInstruction {
Instruction::new_with_borsh(id(), &Self::RequestHeapFrame(bytes), vec![])
}
/// Create a `ComputeBudgetInstruction::RequestUnits` `Instruction`
pub fn request_units(units: u32) -> Instruction {
Instruction::new_with_borsh(id(), &Self::RequestUnits(units), vec![])
/// Create a `ComputeBudgetInstruction::SetComputeUnitLimit` `Instruction`
pub fn set_compute_unit_limit(units: u32) -> Instruction {
Instruction::new_with_borsh(id(), &Self::SetComputeUnitLimit(units), vec![])
}
/// Create a `ComputeBudgetInstruction::SetComputeUnitPrice` `Instruction`

View File

@ -113,7 +113,7 @@ pub struct TestValidatorGenesis {
pub geyser_plugin_config_files: Option<Vec<PathBuf>>,
pub accounts_db_caching_enabled: bool,
deactivate_feature_set: HashSet<Pubkey>,
max_compute_units: Option<u64>,
compute_unit_limit: Option<u64>,
}
impl Default for TestValidatorGenesis {
@ -141,7 +141,7 @@ impl Default for TestValidatorGenesis {
geyser_plugin_config_files: Option::<Vec<PathBuf>>::default(),
accounts_db_caching_enabled: bool::default(),
deactivate_feature_set: HashSet::<Pubkey>::default(),
max_compute_units: Option::<u64>::default(),
compute_unit_limit: Option::<u64>::default(),
}
}
}
@ -239,11 +239,16 @@ impl TestValidatorGenesis {
self
}
pub fn max_compute_units(&mut self, max_compute_units: u64) -> &mut Self {
self.max_compute_units = Some(max_compute_units);
pub fn compute_unit_limit(&mut self, compute_unit_limit: u64) -> &mut Self {
self.compute_unit_limit = Some(compute_unit_limit);
self
}
#[deprecated(note = "Please use `compute_unit_limit` instead")]
pub fn max_compute_units(&mut self, max_compute_units: u64) -> &mut Self {
self.compute_unit_limit(max_compute_units)
}
/// Add an account to the test environment
pub fn add_account(&mut self, address: Pubkey, account: AccountSharedData) -> &mut Self {
self.accounts.insert(address, account);
@ -686,10 +691,12 @@ impl TestValidator {
let runtime_config = RuntimeConfig {
bpf_jit: !config.no_bpf_jit,
compute_budget: config.max_compute_units.map(|max_units| ComputeBudget {
max_units,
..ComputeBudget::default()
}),
compute_budget: config
.compute_unit_limit
.map(|compute_unit_limit| ComputeBudget {
compute_unit_limit,
..ComputeBudget::default()
}),
};
let mut validator_config = ValidatorConfig {

View File

@ -369,12 +369,13 @@ fn main() {
.help("deactivate this feature in genesis.")
)
.arg(
Arg::with_name("max_compute_units")
.long("max-compute-units")
Arg::with_name("compute_unit_limit")
.long("compute-unit-limit")
.alias("max-compute-units")
.value_name("COMPUTE_UNITS")
.validator(is_parsable::<u64>)
.takes_value(true)
.help("Override the runtime's maximum compute units")
.help("Override the runtime's compute unit limit per transaction")
)
.get_matches();
@ -484,7 +485,7 @@ fn main() {
exit(1);
})
});
let max_compute_units = value_t!(matches, "max_compute_units", u64).ok();
let compute_unit_limit = value_t!(matches, "compute_unit_limit", u64).ok();
let faucet_addr = Some(SocketAddr::new(
IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)),
@ -762,8 +763,8 @@ fn main() {
);
}
if let Some(max_compute_units) = max_compute_units {
genesis.max_compute_units(max_compute_units);
if let Some(compute_unit_limit) = compute_unit_limit {
genesis.compute_unit_limit(compute_unit_limit);
}
match genesis.start_with_mint_address(mint_address, socket_addr_space) {