Files
nx9-chronoseal-rs/server/src/vm.rs
T
2026-05-29 14:50:45 +05:30

97 lines
3.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
use rand::Rng;
use shared::{
gene::GeneState,
vm_extensions::{self, ExecutionTrace, MutationError, MutationOrder},
};
pub fn generate_random_program(len_range: std::ops::RangeInclusive<usize>) -> Vec<u8> {
let mut rng = rand::thread_rng();
let count = rng.gen_range(len_range);
let mut ops = Vec::new();
let mut depth: i32 = 0;
for _ in 0..count {
if depth < 2 {
// Not enough operands for any binary op — push a literal.
ops.push(0x00);
let val = rng.r#gen::<u32>();
ops.extend_from_slice(&val.to_le_bytes());
depth += 1;
} else {
let op = rng.gen_range(0u8..10);
match op {
0x00 => {
// PUSH literal
ops.push(0x00);
let val = rng.r#gen::<u32>();
ops.extend_from_slice(&val.to_le_bytes());
depth += 1;
}
0x01..=0x07 => {
// Binary ops (ADD, SUB, MUL, XOR, AND, OR, ROT): pops 2, pushes 1 → net −1
ops.push(op);
depth -= 1;
}
0x08 => {
// Unary NOT: pops 1, pushes 1 → net 0; depth unchanged
ops.push(0x08);
}
0x09 => {
// HASH: collapses entire stack to one u32 → depth becomes 1
ops.push(0x09);
depth = 1;
}
_ => unreachable!(),
}
}
}
ops
}
pub fn execute_mutation_program(
state: &mut GeneState,
program: &[u8],
) -> Result<ExecutionTrace, MutationError> {
vm_extensions::execute_program(state, program)
}
pub fn execute_mutation_order(
state: &mut GeneState,
order: &MutationOrder,
) -> Result<ExecutionTrace, MutationError> {
vm_extensions::execute_program(state, &order.program)
}
#[cfg(test)]
mod tests {
use super::*;
use rand::SeedableRng;
use shared::gene::{commitment, new_state};
#[test]
fn test_execute_mutation_program_wraps_shared_engine() {
let mut state = new_state(8).unwrap();
let program = vec![vm_extensions::OP_MUTATE_POINT, 0, 0, 1];
let trace = execute_mutation_program(&mut state, &program).unwrap();
assert_eq!(state.gene[0], 1);
assert_eq!(trace.final_ip, program.len());
}
#[test]
fn test_execute_mutation_order_determinism() {
let mut rng_a = rand::rngs::StdRng::seed_from_u64(101);
let mut rng_b = rand::rngs::StdRng::seed_from_u64(101);
let order_a = vm_extensions::generate_order_with_rng(&mut rng_a, 9, 64);
let order_b = vm_extensions::generate_order_with_rng(&mut rng_b, 9, 64);
assert_eq!(order_a, order_b);
let mut state_a = new_state(64).unwrap();
let mut state_b = new_state(64).unwrap();
let trace_a = execute_mutation_order(&mut state_a, &order_a).unwrap();
let trace_b = execute_mutation_order(&mut state_b, &order_b).unwrap();
assert_eq!(state_a, state_b);
assert_eq!(trace_a.final_stack, trace_b.final_stack);
assert_eq!(commitment(&state_a), commitment(&state_b));
}
}