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}