use crate::error::{VmError, VmResult};
use crate::state::VmState;
pub fn handle_nop_n(state: &mut VmState) -> VmResult<()> {
let count = state.read_u8()?;
state.ip += count as usize;
if state.ip > state.code.len() {
return Err(VmError::InvalidJumpTarget);
}
Ok(())
}
pub fn handle_opaque_true(state: &mut VmState) -> VmResult<()> {
let x = state.instruction_count;
let product = x.wrapping_mul(x.wrapping_add(1));
#[allow(clippy::manual_is_multiple_of)]
let result = if product % 2 == 0 {
1u64
} else {
0u64 };
state.push(result)
}
pub fn handle_opaque_false(state: &mut VmState) -> VmResult<()> {
let x = state.instruction_count;
let product = x.wrapping_mul(x.wrapping_add(1));
#[allow(clippy::manual_is_multiple_of)]
let result = if product % 2 != 0 {
1u64 } else {
0u64
};
state.push(result)
}
pub fn handle_hash_check(state: &mut VmState) -> VmResult<()> {
let expected = state.read_u32()?;
let mut hash = crate::build_config::FNV_BASIS_32;
for &byte in state.code {
hash ^= byte as u32;
hash = hash.wrapping_mul(crate::build_config::FNV_PRIME_32);
}
if hash != expected {
return Err(VmError::IntegrityFailed);
}
Ok(())
}
pub fn handle_timing_check(state: &mut VmState) -> VmResult<()> {
#[cfg(feature = "vm_debug")]
{
let _ = state;
return Ok(());
}
#[cfg(not(feature = "vm_debug"))]
{
let current_ns = state.current_time_ns();
if state.last_timing_ns == 0 {
state.last_timing_ns = current_ns;
return Ok(());
}
let delta_ns = current_ns.saturating_sub(state.last_timing_ns);
const MAX_DELTA_NS: u64 = 100_000_000;
if delta_ns > MAX_DELTA_NS {
return Err(VmError::TimingAnomaly);
}
state.last_timing_ns = current_ns;
Ok(())
}
}