sui_verifier_latest/
meter.rs1use move_binary_format::errors::{PartialVMError, PartialVMResult};
5use move_bytecode_verifier_meter::{Meter, Scope};
6use move_core_types::vm_status::StatusCode;
7use move_vm_config::verifier::MeterConfig;
8
9struct SuiVerifierMeterBounds {
10 name: String,
11 ticks: u128,
12 max_ticks: Option<u128>,
13}
14
15impl SuiVerifierMeterBounds {
16 fn add(&mut self, ticks: u128) -> PartialVMResult<()> {
17 let max_ticks = self.max_ticks.unwrap_or(u128::MAX);
18
19 let new_ticks = self.ticks.saturating_add(ticks);
20 if new_ticks >= max_ticks {
21 return Err(PartialVMError::new(StatusCode::PROGRAM_TOO_COMPLEX)
22 .with_message(format!(
23 "program too complex. Ticks exceeded `{}` will exceed limits: `{} current + {} new > {} max`)",
24 self.name, self.ticks, ticks, max_ticks
25 )));
26 }
27 self.ticks = new_ticks;
28 Ok(())
29 }
30}
31
32pub struct SuiVerifierMeter {
33 transaction_bounds: SuiVerifierMeterBounds,
34 package_bounds: SuiVerifierMeterBounds,
35 module_bounds: SuiVerifierMeterBounds,
36 function_bounds: SuiVerifierMeterBounds,
37}
38
39impl SuiVerifierMeter {
40 pub fn new(config: MeterConfig) -> Self {
41 Self {
42 transaction_bounds: SuiVerifierMeterBounds {
43 name: "<unknown>".to_string(),
44 ticks: 0,
45 max_ticks: None,
46 },
47 package_bounds: SuiVerifierMeterBounds {
48 name: "<unknown>".to_string(),
49 ticks: 0,
50 max_ticks: config.max_per_pkg_meter_units,
51 },
52 module_bounds: SuiVerifierMeterBounds {
53 name: "<unknown>".to_string(),
54 ticks: 0,
55 max_ticks: config.max_per_mod_meter_units,
56 },
57 function_bounds: SuiVerifierMeterBounds {
58 name: "<unknown>".to_string(),
59 ticks: 0,
60 max_ticks: config.max_per_fun_meter_units,
61 },
62 }
63 }
64
65 fn get_bounds_mut(&mut self, scope: Scope) -> &mut SuiVerifierMeterBounds {
66 match scope {
67 Scope::Transaction => &mut self.transaction_bounds,
68 Scope::Package => &mut self.package_bounds,
69 Scope::Module => &mut self.module_bounds,
70 Scope::Function => &mut self.function_bounds,
71 }
72 }
73
74 fn get_bounds(&self, scope: Scope) -> &SuiVerifierMeterBounds {
75 match scope {
76 Scope::Transaction => &self.transaction_bounds,
77 Scope::Package => &self.package_bounds,
78 Scope::Module => &self.module_bounds,
79 Scope::Function => &self.function_bounds,
80 }
81 }
82
83 pub fn get_usage(&self, scope: Scope) -> u128 {
84 self.get_bounds(scope).ticks
85 }
86
87 pub fn get_limit(&self, scope: Scope) -> Option<u128> {
88 self.get_bounds(scope).max_ticks
89 }
90}
91
92impl Meter for SuiVerifierMeter {
93 fn enter_scope(&mut self, name: &str, scope: Scope) {
94 let bounds = self.get_bounds_mut(scope);
95 bounds.name = name.into();
96 bounds.ticks = 0;
97 }
98
99 fn transfer(&mut self, from: Scope, to: Scope, factor: f32) -> PartialVMResult<()> {
100 let ticks = (self.get_bounds_mut(from).ticks as f32 * factor) as u128;
101 self.add(to, ticks)
102 }
103
104 fn add(&mut self, scope: Scope, ticks: u128) -> PartialVMResult<()> {
105 self.get_bounds_mut(scope).add(ticks)
106 }
107}