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