solana_compute_budget/
compute_budget_limits.rs1use {
2 solana_fee_structure::FeeBudgetLimits, solana_program_entrypoint::HEAP_LENGTH,
3 std::num::NonZeroU32,
4};
5
6pub const DEFAULT_HEAP_COST: u64 = 8;
9pub const DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT: u32 = 200_000;
10pub const MAX_BUILTIN_ALLOCATION_COMPUTE_UNIT_LIMIT: u32 = 3_000;
13pub const MAX_COMPUTE_UNIT_LIMIT: u32 = 1_400_000;
14pub const MAX_HEAP_FRAME_BYTES: u32 = 256 * 1024;
15pub const MIN_HEAP_FRAME_BYTES: u32 = HEAP_LENGTH as u32;
16
17type MicroLamports = u128;
18
19const MICRO_LAMPORTS_PER_LAMPORT: u64 = 1_000_000;
21
22pub const MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES: NonZeroU32 =
25 unsafe { NonZeroU32::new_unchecked(64 * 1024 * 1024) };
26
27#[derive(Clone, Copy, Debug, PartialEq, Eq)]
28pub struct ComputeBudgetLimits {
29 pub updated_heap_bytes: u32,
30 pub compute_unit_limit: u32,
31 pub compute_unit_price: u64,
32 pub loaded_accounts_bytes: NonZeroU32,
33}
34
35impl Default for ComputeBudgetLimits {
36 fn default() -> Self {
37 ComputeBudgetLimits {
38 updated_heap_bytes: MIN_HEAP_FRAME_BYTES,
39 compute_unit_limit: MAX_COMPUTE_UNIT_LIMIT,
40 compute_unit_price: 0,
41 loaded_accounts_bytes: MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES,
42 }
43 }
44}
45
46fn get_prioritization_fee(compute_unit_price: u64, compute_unit_limit: u64) -> u64 {
47 let micro_lamport_fee: MicroLamports =
48 (compute_unit_price as u128).saturating_mul(compute_unit_limit as u128);
49 micro_lamport_fee
50 .saturating_add(MICRO_LAMPORTS_PER_LAMPORT.saturating_sub(1) as u128)
51 .checked_div(MICRO_LAMPORTS_PER_LAMPORT as u128)
52 .and_then(|fee| u64::try_from(fee).ok())
53 .unwrap_or(u64::MAX)
54}
55
56impl From<ComputeBudgetLimits> for FeeBudgetLimits {
57 fn from(val: ComputeBudgetLimits) -> Self {
58 let prioritization_fee =
59 get_prioritization_fee(val.compute_unit_price, u64::from(val.compute_unit_limit));
60
61 FeeBudgetLimits {
62 loaded_accounts_data_size_limit: val.loaded_accounts_bytes,
63 heap_cost: DEFAULT_HEAP_COST,
64 compute_unit_limit: u64::from(val.compute_unit_limit),
65 prioritization_fee,
66 }
67 }
68}
69
70#[cfg(test)]
71mod test {
72 use super::*;
73
74 #[test]
75 fn test_new_with_no_fee() {
76 for compute_units in [0, 1, MICRO_LAMPORTS_PER_LAMPORT, u64::MAX] {
77 assert_eq!(get_prioritization_fee(0, compute_units), 0);
78 }
79 }
80
81 #[test]
82 fn test_new_with_compute_unit_price() {
83 assert_eq!(
84 get_prioritization_fee(MICRO_LAMPORTS_PER_LAMPORT - 1, 1),
85 1,
86 "should round up (<1.0) lamport fee to 1 lamport"
87 );
88
89 assert_eq!(get_prioritization_fee(MICRO_LAMPORTS_PER_LAMPORT, 1), 1);
90
91 assert_eq!(
92 get_prioritization_fee(MICRO_LAMPORTS_PER_LAMPORT + 1, 1),
93 2,
94 "should round up (>1.0) lamport fee to 2 lamports"
95 );
96
97 assert_eq!(get_prioritization_fee(200, 100_000), 20);
98
99 assert_eq!(
100 get_prioritization_fee(MICRO_LAMPORTS_PER_LAMPORT, u64::MAX),
101 u64::MAX
102 );
103
104 assert_eq!(get_prioritization_fee(u64::MAX, u64::MAX), u64::MAX);
105 }
106}