sui_adapter_latest/static_programmable_transactions/metering/
translation_meter.rs1use crate::gas_charger::GasCharger;
5use crate::static_programmable_transactions::loading::ast::{DeserializedPackage, PackagePayload};
6use sui_protocol_config::ProtocolConfig;
7use sui_types::error::ExecutionErrorTrait;
8use sui_types::execution_status::ExecutionErrorKind;
9
10pub struct TranslationMeter<'pc, 'gas> {
17 protocol_config: &'pc ProtocolConfig,
18 charger: &'gas mut GasCharger,
19}
20
21impl<'pc, 'gas> TranslationMeter<'pc, 'gas> {
22 pub fn new(
23 protocol_config: &'pc ProtocolConfig,
24 gas_charger: &'gas mut GasCharger,
25 ) -> TranslationMeter<'pc, 'gas> {
26 TranslationMeter {
27 protocol_config,
28 charger: gas_charger,
29 }
30 }
31
32 pub fn charge_base_inputs<E: ExecutionErrorTrait>(
33 &mut self,
34 num_inputs: usize,
35 ) -> Result<(), E> {
36 let amount = (num_inputs as u64)
37 .max(1)
38 .saturating_mul(self.protocol_config.translation_per_input_base_charge());
39 self.charge(amount)
40 }
41
42 pub fn charge_pure_input_bytes<E: ExecutionErrorTrait>(
43 &mut self,
44 num_bytes: usize,
45 ) -> Result<(), E> {
46 let amount = (num_bytes as u64).max(1).saturating_mul(
47 self.protocol_config
48 .translation_pure_input_per_byte_charge(),
49 );
50 self.charge(amount)
51 }
52
53 pub fn charge_base_command<E: ExecutionErrorTrait>(
54 &mut self,
55 num_args: usize,
56 ) -> Result<(), E> {
57 let amount = (num_args as u64)
58 .max(1)
59 .saturating_mul(self.protocol_config.translation_per_command_base_charge());
60 self.charge(amount)
61 }
62
63 pub fn charge_num_type_nodes<E: ExecutionErrorTrait>(
67 &mut self,
68 num_type_nodes: u64,
69 ) -> Result<(), E> {
70 let amount = num_type_nodes
71 .max(1)
72 .saturating_mul(self.protocol_config.translation_per_type_node_charge());
73 self.charge(amount)
74 }
75
76 pub fn charge_num_type_references<E: ExecutionErrorTrait>(
77 &mut self,
78 num_type_references: u64,
79 ) -> Result<(), E> {
80 let amount = self.reference_cost_formula(num_type_references.max(1))?;
81 let amount =
82 amount.saturating_mul(self.protocol_config.translation_per_reference_node_charge());
83 self.charge(amount)
84 }
85
86 pub fn charge_num_linkage_entries<E: ExecutionErrorTrait>(
87 &mut self,
88 num_linkage_entries: usize,
89 ) -> Result<(), E> {
90 let amount = (num_linkage_entries as u64)
91 .saturating_mul(self.protocol_config.translation_per_linkage_entry_charge())
92 .max(1);
93 self.charge(amount)
94 }
95
96 pub fn charge_package_load<E: ExecutionErrorTrait>(
97 &mut self,
98 payload: &PackagePayload,
99 ) -> Result<(), E> {
100 match payload {
101 PackagePayload::Serialized(_) => {
102 Ok(())
104 }
105 PackagePayload::Deserialized(DeserializedPackage { total_bytes, .. }) => {
106 self.charger.charge_publish_package(*total_bytes)?;
107 Ok(())
108 }
109 }
110 }
111
112 fn reference_cost_formula<E: ExecutionErrorTrait>(&self, n: u64) -> Result<u64, E> {
118 let Some(n_succ) = n.checked_add(1) else {
119 invariant_violation!("u64 overflow when calculating type reference cost")
120 };
121 Ok(n.saturating_mul(n_succ) / 2)
122 }
123
124 fn charge<E: ExecutionErrorTrait>(&mut self, amount: u64) -> Result<(), E> {
127 debug_assert!(amount > 0);
128 self.charger
129 .move_gas_status_mut()
130 .deduct_gas(amount.into())
131 .map_err(Self::gas_error)
132 }
133
134 fn gas_error<T, E>(e: T) -> E
135 where
136 T: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
137 E: ExecutionErrorTrait,
138 {
139 E::new_with_source(ExecutionErrorKind::InsufficientGas, e)
140 }
141}