soroban_env_host/budget/
util.rs1#[cfg(any(
2 test,
3 feature = "testutils",
4 feature = "bench",
5 feature = "recording_mode"
6))]
7use crate::{budget::Budget, HostError};
8
9#[cfg(any(test, feature = "testutils", feature = "bench"))]
10use crate::host::error::TryBorrowOrErr;
11
12#[cfg(any(test, feature = "testutils"))]
13use crate::{budget::model::ScaledU64, xdr::ContractCostType};
14
15#[cfg(any(test, feature = "testutils", feature = "bench"))]
16impl Budget {
17 pub fn reset_models(&self) -> Result<(), HostError> {
18 self.with_mut_budget(|mut b| {
19 b.cpu_insns.reset_models();
20 b.mem_bytes.reset_models();
21 Ok(())
22 })
23 }
24
25 pub(crate) fn track_wasm_mem_alloc(&self, delta: u64) -> Result<(), HostError> {
26 let mut bgt = self.0.try_borrow_mut_or_err()?;
27 bgt.tracker.wasm_memory = bgt.tracker.wasm_memory.saturating_add(delta);
28 Ok(())
29 }
30
31 pub fn get_wasm_mem_alloc(&self) -> Result<u64, HostError> {
32 Ok(self.0.try_borrow_or_err()?.tracker.wasm_memory)
33 }
34
35 pub fn reset_unlimited(&self) -> Result<(), HostError> {
36 self.reset_unlimited_cpu()?;
37 self.reset_unlimited_mem()?;
38 Ok(())
39 }
40
41 pub fn reset_unlimited_cpu(&self) -> Result<(), HostError> {
42 self.with_mut_budget(|mut b| {
43 b.cpu_insns.reset(u64::MAX);
44 Ok(())
45 })?; self.reset_tracker()
47 }
48
49 pub fn reset_unlimited_mem(&self) -> Result<(), HostError> {
50 self.with_mut_budget(|mut b| {
51 b.mem_bytes.reset(u64::MAX);
52 Ok(())
53 })?;
54 self.reset_tracker()
55 }
56
57 pub fn cpu_limit_exceeded(&self) -> Result<bool, HostError> {
58 let cpu = &self.0.try_borrow_or_err()?.cpu_insns;
59 Ok(cpu.total_count > cpu.limit)
60 }
61
62 pub fn mem_limit_exceeded(&self) -> Result<bool, HostError> {
63 let mem = &self.0.try_borrow_or_err()?.mem_bytes;
64 Ok(mem.total_count > mem.limit)
65 }
66
67 pub fn reset_tracker(&self) -> Result<(), HostError> {
68 self.0.try_borrow_mut_or_err()?.tracker.reset();
69 Ok(())
70 }
71
72 pub fn reset(&self) -> Result<(), HostError> {
73 self.with_mut_budget(|mut b| {
74 b.cpu_insns.reset_count();
75 b.mem_bytes.reset_count();
76 Ok(())
77 })?;
78 self.reset_tracker()
79 }
80
81 pub fn reset_cpu_limit(&self, cpu: u64) -> Result<(), HostError> {
82 self.with_mut_budget(|mut b| {
83 b.cpu_insns.reset(cpu);
84 Ok(())
85 })?;
86 self.reset_tracker()
87 }
88
89 pub fn reset_limits(&self, cpu: u64, mem: u64) -> Result<(), HostError> {
90 self.with_mut_budget(|mut b| {
91 b.cpu_insns.reset(cpu);
92 b.mem_bytes.reset(mem);
93 Ok(())
94 })?;
95 self.reset_tracker()
96 }
97
98 pub fn reset_fuel_config(&self) -> Result<(), HostError> {
106 self.0.try_borrow_mut_or_err()?.fuel_costs = wasmi::FuelCosts::default();
107 Ok(())
108 }
109
110 pub fn get_shadow_cpu_insns_consumed(&self) -> Result<u64, HostError> {
111 Ok(self.0.try_borrow_or_err()?.cpu_insns.shadow_total_count)
112 }
113
114 pub fn get_shadow_mem_bytes_consumed(&self) -> Result<u64, HostError> {
115 Ok(self.0.try_borrow_or_err()?.mem_bytes.shadow_total_count)
116 }
117
118 #[allow(unused)]
119 pub fn shadow_cpu_limit_exceeded(&self) -> Result<bool, HostError> {
120 let cpu = &self.0.try_borrow_or_err()?.cpu_insns;
121 Ok(cpu.shadow_total_count > cpu.shadow_limit)
122 }
123
124 pub fn shadow_mem_limit_exceeded(&self) -> Result<bool, HostError> {
125 let mem = &self.0.try_borrow_or_err()?.mem_bytes;
126 Ok(mem.shadow_total_count > mem.shadow_limit)
127 }
128}
129
130#[cfg(any(test, feature = "testutils"))]
131impl Budget {
132 pub(crate) fn override_model_with_scaled_params(
133 &self,
134 ty: ContractCostType,
135 const_cpu: u64,
136 lin_cpu: ScaledU64,
137 const_mem: u64,
138 lin_mem: ScaledU64,
139 ) -> Result<(), HostError> {
140 let mut bgt = self.0.try_borrow_mut_or_err()?;
141 let cpu_model = bgt.cpu_insns.get_cost_model_mut(ty)?;
142 cpu_model.const_term = const_cpu;
143 cpu_model.lin_term = lin_cpu;
144
145 let mem_model = bgt.mem_bytes.get_cost_model_mut(ty)?;
146 mem_model.const_term = const_mem;
147 mem_model.lin_term = lin_mem;
148 Ok(())
149 }
150
151 pub(crate) fn override_model_with_unscaled_params(
152 &self,
153 ty: ContractCostType,
154 const_cpu: u64,
155 lin_cpu: u64,
156 const_mem: u64,
157 lin_mem: u64,
158 ) -> Result<(), HostError> {
159 self.override_model_with_scaled_params(
160 ty,
161 const_cpu,
162 ScaledU64::from_unscaled_u64(lin_cpu),
163 const_mem,
164 ScaledU64::from_unscaled_u64(lin_mem),
165 )
166 }
167}
168
169#[cfg(any(test, feature = "recording_mode", feature = "testutils"))]
170impl Budget {
171 pub(crate) fn with_observable_shadow_mode<T, F>(&self, f: F) -> Result<T, HostError>
191 where
192 F: FnOnce() -> Result<T, HostError>,
193 {
194 let mut prev = false;
195 let should_execute = self.with_mut_budget(|mut b| {
196 prev = b.is_in_shadow_mode;
197 b.is_in_shadow_mode = true;
198 b.cpu_insns
199 .check_budget_limit(super::dimension::IsShadowMode(true))?;
200 b.mem_bytes
201 .check_budget_limit(super::dimension::IsShadowMode(true))
202 });
203
204 let rt = match should_execute {
205 Ok(_) => f(),
206 Err(e) => Err(e),
207 };
208
209 self.with_mut_budget(|mut b| {
210 b.is_in_shadow_mode = prev;
211 Ok(())
212 })?;
213
214 rt
215 }
216}