Skip to main content

javm_exec/
gas.rs

1//! Gas counter: a non-negative u64 representing remaining budget.
2//!
3//! The execution engine decrements the counter per instruction (or
4//! per ecall, etc.) and reports `ExitReason::OutOfGas` when it
5//! would go negative. The actual gas-per-instruction cost table
6//! lives at a higher layer (v3 spec: per-instruction debit happens
7//! against the active Instance's gas slot's meter; the engine just
8//! receives a single counter to decrement).
9
10/// Gas type: `u64` remaining budget.
11pub type Gas = u64;
12
13/// Sentinel returned by `GasCounter::charge` on exhaustion.
14#[derive(Clone, Copy, Debug, PartialEq, Eq)]
15pub struct OutOfGas;
16
17/// Mutable gas counter with structured charge / check semantics.
18#[derive(Clone, Debug, PartialEq, Eq)]
19pub struct GasCounter {
20    remaining: Gas,
21}
22
23impl GasCounter {
24    /// Construct with the given initial budget.
25    pub fn new(initial: Gas) -> Self {
26        Self { remaining: initial }
27    }
28
29    /// Current remaining gas.
30    pub fn remaining(&self) -> Gas {
31        self.remaining
32    }
33
34    /// Try to deduct `cost`. Returns `Ok(())` on success or
35    /// `Err(OutOfGas)` if the counter would go negative (caller
36    /// should produce `ExitReason::OutOfGas`).
37    #[inline(always)]
38    pub fn charge(&mut self, cost: Gas) -> Result<(), OutOfGas> {
39        match self.remaining.checked_sub(cost) {
40            Some(new) => {
41                self.remaining = new;
42                Ok(())
43            }
44            None => {
45                // Exhaust the counter so subsequent charges also fail.
46                self.remaining = 0;
47                Err(OutOfGas)
48            }
49        }
50    }
51
52    /// Set remaining gas explicitly (used by the higher layer's
53    /// SetGasMeter operation for top-ups).
54    pub fn set(&mut self, value: Gas) {
55        self.remaining = value;
56    }
57}