80 lines
2.4 KiB
Rust
80 lines
2.4 KiB
Rust
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<u32> = 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,
|
|
}
|
|
}
|