sui_adapter_latest/static_programmable_transactions/metering/
translation_meter.rs1use crate::gas_charger::GasCharger;
5use sui_protocol_config::ProtocolConfig;
6use sui_types::error::ExecutionErrorTrait;
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<E: ExecutionErrorTrait>(
32 &mut self,
33 num_inputs: usize,
34 ) -> Result<(), E> {
35 let amount = (num_inputs as u64)
36 .max(1)
37 .saturating_mul(self.protocol_config.translation_per_input_base_charge());
38 self.charge(amount)
39 }
40
41 pub fn charge_pure_input_bytes<E: ExecutionErrorTrait>(
42 &mut self,
43 num_bytes: usize,
44 ) -> Result<(), E> {
45 let amount = (num_bytes as u64).max(1).saturating_mul(
46 self.protocol_config
47 .translation_pure_input_per_byte_charge(),
48 );
49 self.charge(amount)
50 }
51
52 pub fn charge_base_command<E: ExecutionErrorTrait>(
53 &mut self,
54 num_args: usize,
55 ) -> Result<(), E> {
56 let amount = (num_args as u64)
57 .max(1)
58 .saturating_mul(self.protocol_config.translation_per_command_base_charge());
59 self.charge(amount)
60 }
61
62 pub fn charge_num_type_nodes<E: ExecutionErrorTrait>(
66 &mut self,
67 num_type_nodes: u64,
68 ) -> Result<(), E> {
69 let amount = num_type_nodes
70 .max(1)
71 .saturating_mul(self.protocol_config.translation_per_type_node_charge());
72 self.charge(amount)
73 }
74
75 pub fn charge_num_type_references<E: ExecutionErrorTrait>(
76 &mut self,
77 num_type_references: u64,
78 ) -> Result<(), E> {
79 let amount = self.reference_cost_formula(num_type_references.max(1))?;
80 let amount =
81 amount.saturating_mul(self.protocol_config.translation_per_reference_node_charge());
82 self.charge(amount)
83 }
84
85 pub fn charge_num_linkage_entries<E: ExecutionErrorTrait>(
86 &mut self,
87 num_linkage_entries: usize,
88 ) -> Result<(), E> {
89 let amount = (num_linkage_entries as u64)
90 .saturating_mul(self.protocol_config.translation_per_linkage_entry_charge())
91 .max(1);
92 self.charge(amount)
93 }
94
95 fn reference_cost_formula<E: ExecutionErrorTrait>(&self, n: u64) -> Result<u64, E> {
101 let Some(n_succ) = n.checked_add(1) else {
102 invariant_violation!("u64 overflow when calculating type reference cost")
103 };
104 Ok(n.saturating_mul(n_succ) / 2)
105 }
106
107 fn charge<E: ExecutionErrorTrait>(&mut self, amount: u64) -> Result<(), E> {
110 debug_assert!(amount > 0);
111 self.charger
112 .move_gas_status_mut()
113 .deduct_gas(amount.into())
114 .map_err(Self::gas_error)
115 }
116
117 fn gas_error<T, E>(e: T) -> E
118 where
119 T: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
120 E: ExecutionErrorTrait,
121 {
122 E::new_with_source(ExecutionErrorKind::InsufficientGas, e)
123 }
124}