soroban_env_host/budget/
wasmi_helper.rs1use crate::{
2 budget::{AsBudget, Budget},
3 host::error::TryBorrowOrErr,
4 xdr::ContractCostType,
5 Host, HostError,
6};
7use wasmi::{errors, FuelConsumptionMode, FuelCosts, ResourceLimiter};
8
9pub(crate) struct WasmiLimits {
10 pub table_elements: u32,
11 pub instances: usize,
12 pub tables: usize,
14 pub memories: usize,
17}
18
19pub(crate) const WASMI_LIMITS_CONFIG: WasmiLimits = WasmiLimits {
20 table_elements: 1000,
21 instances: 1,
22 tables: 1,
23 memories: 1,
24};
25
26impl ResourceLimiter for Host {
27 fn memory_growing(
28 &mut self,
29 current: usize,
30 desired: usize,
31 maximum: Option<usize>,
32 ) -> Result<bool, errors::MemoryError> {
33 let host_limit = self
34 .as_budget()
35 .get_mem_bytes_remaining()
36 .map_err(|_| errors::MemoryError::OutOfBoundsGrowth)?;
37
38 let delta = (desired as u64).saturating_sub(current as u64);
39 let allow = if delta > host_limit {
40 false
41 } else {
42 match maximum {
43 Some(max) => desired <= max,
44 None => true,
45 }
46 };
47
48 if allow {
49 #[cfg(any(test, feature = "testutils", feature = "bench"))]
50 {
51 self.as_budget()
52 .track_wasm_mem_alloc(delta)
53 .map_err(|_| errors::MemoryError::OutOfBoundsGrowth)?;
54 }
55
56 self.as_budget()
57 .charge(ContractCostType::MemAlloc, Some(delta))
58 .map(|_| true)
59 .map_err(|_| errors::MemoryError::OutOfBoundsGrowth)
60 } else {
61 Err(errors::MemoryError::OutOfBoundsGrowth)
62 }
63 }
64
65 fn table_growing(
66 &mut self,
67 current: u32,
68 desired: u32,
69 maximum: Option<u32>,
70 ) -> Result<bool, errors::TableError> {
71 let allow = if desired > WASMI_LIMITS_CONFIG.table_elements {
72 false
73 } else {
74 match maximum {
75 Some(max) => desired <= max,
76 None => true,
77 }
78 };
79 if allow {
80 Ok(allow)
81 } else {
82 Err(errors::TableError::GrowOutOfBounds {
83 maximum: maximum.unwrap_or(u32::MAX),
84 current,
85 delta: desired - current,
86 })
87 }
88 }
89
90 fn instances(&self) -> usize {
91 WASMI_LIMITS_CONFIG.instances
92 }
93
94 fn tables(&self) -> usize {
95 WASMI_LIMITS_CONFIG.tables
96 }
97
98 fn memories(&self) -> usize {
99 WASMI_LIMITS_CONFIG.memories
100 }
101}
102
103pub(crate) fn load_calibrated_fuel_costs() -> FuelCosts {
107 let mut fuel_costs = FuelCosts::default();
108 fuel_costs.base = 1;
109 fuel_costs.entity = 3;
110 fuel_costs.load = 2;
111 fuel_costs.store = 1;
112 fuel_costs.call = 67;
113 fuel_costs
114}
115
116pub(crate) fn get_wasmi_config(budget: &Budget) -> Result<wasmi::Config, HostError> {
117 let mut config = wasmi::Config::default();
118 let fuel_costs = budget.0.try_borrow_or_err()?.fuel_costs;
119
120 config
125 .consume_fuel(true)
126 .wasm_bulk_memory(true)
127 .wasm_mutable_global(true)
128 .wasm_sign_extension(true)
129 .wasm_saturating_float_to_int(false)
130 .wasm_multi_value(false)
131 .wasm_reference_types(false)
132 .wasm_tail_call(false)
133 .wasm_extended_const(false)
134 .floats(false)
135 .fuel_consumption_mode(FuelConsumptionMode::Eager)
136 .set_fuel_costs(fuel_costs);
137
138 Ok(config)
139}