Skip to main content

hopper_runtime/
compute.rs

1//! Compute-budget introspection helpers.
2//!
3//! These read `sol_remaining_compute_units` (SIMD-0049). That proposal is
4//! Withdrawn and its feature gate has never been activated on mainnet-beta,
5//! devnet, or testnet, so an on-chain program that references the syscall
6//! is rejected at deploy time. The module is compiled for on-chain targets
7//! only with the `remaining-compute-units-syscall` feature; host builds keep
8//! it so tests can exercise the guard logic.
9
10use crate::{ProgramError, ProgramResult};
11
12/// Read the current remaining compute units.
13///
14/// Off-chain tests return `u64::MAX`, treating local execution as unlimited.
15#[inline(always)]
16pub fn remaining_compute_units() -> u64 {
17    crate::syscalls::sol_remaining_compute_units()
18}
19
20/// Require at least `minimum` compute units and return the current balance.
21#[inline(always)]
22pub fn require_compute_units(minimum: u64) -> Result<u64, ProgramError> {
23    let remaining = remaining_compute_units();
24    if remaining < minimum {
25        return Err(ProgramError::InvalidArgument);
26    }
27    Ok(remaining)
28}
29
30/// Fail if fewer than `minimum` compute units remain.
31#[inline(always)]
32pub fn check_compute_units(minimum: u64) -> ProgramResult {
33    require_compute_units(minimum).map(|_| ())
34}
35
36#[cfg(test)]
37mod tests {
38    use super::*;
39
40    #[test]
41    fn offchain_compute_is_unlimited() {
42        assert_eq!(remaining_compute_units(), u64::MAX);
43        assert_eq!(require_compute_units(10).unwrap(), u64::MAX);
44        assert!(check_compute_units(u64::MAX).is_ok());
45    }
46}