use crate::protocol::StackState; /// Executes a raw VM mathematical instruction program bytecode slice. /// /// This implements the mathematical stack machine interpreter used by the client /// to generate the attestation stack state. /// /// # Arguments /// * `program` - The raw VM instruction program bytecode. pub fn execute(program: &[u8]) -> StackState { let mut stack: Vec = Vec::new(); let mut ip: usize = 0; while ip < program.len() { let op = program[ip]; ip += 1; match op { 0x00 => { if ip + 4 > program.len() { break; } let val = u32::from_le_bytes([ program[ip], program[ip + 1], program[ip + 2], program[ip + 3], ]); ip += 4; if stack.len() >= crate::constants::MAX_STACK_DEPTH { break; } stack.push(val); } 0x01..=0x07 => { if stack.len() < 2 { break; } let b = stack.pop().unwrap(); let a = stack.pop().unwrap(); let r = match op { 0x01 => a.wrapping_add(b), 0x02 => a.wrapping_sub(b), 0x03 => a.wrapping_mul(b), 0x04 => a ^ b, 0x05 => a & b, 0x06 => a | b, 0x07 => a.rotate_left(b % 32), _ => unreachable!(), }; if stack.len() >= crate::constants::MAX_STACK_DEPTH { break; } stack.push(r); } 0x08 => { if stack.is_empty() { break; } let a = stack.pop().unwrap(); if stack.len() >= crate::constants::MAX_STACK_DEPTH { break; } stack.push(!a); } 0x09 => { let r = crate::hashing::hash_stack(&stack); stack.clear(); if stack.len() >= crate::constants::MAX_STACK_DEPTH { break; } stack.push(r); } _ => break, } } StackState { stack, ip: ip as u16, } }