sui_adapter_v3/static_programmable_transactions/metering/
translation_meter.rs1use crate::gas_charger::GasCharger;
5use sui_protocol_config::ProtocolConfig;
6use sui_types::error::ExecutionError;
7use sui_types::execution_status::ExecutionErrorKind;
8
9pub struct TranslationMeter<'pc, 'gas> {
16 protocol_config: &'pc ProtocolConfig,
17 charger: &'gas mut GasCharger,
18}
19
20impl<'pc, 'gas> TranslationMeter<'pc, 'gas> {
21 pub fn new(
22 protocol_config: &'pc ProtocolConfig,
23 gas_charger: &'gas mut GasCharger,
24 ) -> TranslationMeter<'pc, 'gas> {
25 TranslationMeter {
26 protocol_config,
27 charger: gas_charger,
28 }
29 }
30
31 pub fn charge_base_inputs(&mut self, num_inputs: usize) -> Result<(), ExecutionError> {
32 let amount = (num_inputs as u64)
33 .max(1)
34 .saturating_mul(self.protocol_config.translation_per_input_base_charge());
35 self.charge(amount)
36 }
37
38 pub fn charge_pure_input_bytes(&mut self, num_bytes: usize) -> Result<(), ExecutionError> {
39 let amount = (num_bytes as u64).max(1).saturating_mul(
40 self.protocol_config
41 .translation_pure_input_per_byte_charge(),
42 );
43 self.charge(amount)
44 }
45
46 pub fn charge_base_command(&mut self, num_args: usize) -> Result<(), ExecutionError> {
47 let amount = (num_args as u64)
48 .max(1)
49 .saturating_mul(self.protocol_config.translation_per_command_base_charge());
50 self.charge(amount)
51 }
52
53 pub fn charge_num_type_nodes(&mut self, num_type_nodes: u64) -> Result<(), ExecutionError> {
57 let amount = num_type_nodes
58 .max(1)
59 .saturating_mul(self.protocol_config.translation_per_type_node_charge());
60 self.charge(amount)
61 }
62
63 pub fn charge_num_type_references(
64 &mut self,
65 num_type_references: u64,
66 ) -> Result<(), ExecutionError> {
67 let amount = self.reference_cost_formula(num_type_references.max(1))?;
68 let amount =
69 amount.saturating_mul(self.protocol_config.translation_per_reference_node_charge());
70 self.charge(amount)
71 }
72
73 pub fn charge_num_linkage_entries(
74 &mut self,
75 num_linkage_entries: usize,
76 ) -> Result<(), ExecutionError> {
77 let amount = (num_linkage_entries as u64)
78 .saturating_mul(self.protocol_config.translation_per_linkage_entry_charge())
79 .max(1);
80 self.charge(amount)
81 }
82
83 fn reference_cost_formula(&self, n: u64) -> Result<u64, ExecutionError> {
89 let Some(n_succ) = n.checked_add(1) else {
90 invariant_violation!("u64 overflow when calculating type reference cost")
91 };
92 Ok(n.saturating_mul(n_succ) / 2)
93 }
94
95 fn charge(&mut self, amount: u64) -> Result<(), ExecutionError> {
98 debug_assert!(amount > 0);
99 self.charger
100 .move_gas_status_mut()
101 .deduct_gas(amount.into())
102 .map_err(Self::gas_error)
103 }
104
105 fn gas_error<E>(e: E) -> ExecutionError
106 where
107 E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
108 {
109 ExecutionError::new_with_source(ExecutionErrorKind::InsufficientGas, e)
110 }
111}