343 lines
11 KiB
Rust
343 lines
11 KiB
Rust
//! 虚拟机执行器
|
|
|
|
use crate::bytecode::{Bytecode, Opcode};
|
|
use crate::stack::{Stack, StackError};
|
|
use crate::memory::{Memory, MemoryError};
|
|
use crate::gas::{GasMetering, GasError};
|
|
use thiserror::Error;
|
|
use sha3::{Digest, Sha3_256};
|
|
|
|
#[derive(Debug, Error)]
|
|
pub enum ExecutionError {
|
|
#[error("栈错误: {0}")]
|
|
Stack(#[from] StackError),
|
|
#[error("内存错误: {0}")]
|
|
Memory(#[from] MemoryError),
|
|
#[error("Gas错误: {0}")]
|
|
Gas(#[from] GasError),
|
|
#[error("除零错误")]
|
|
DivisionByZero,
|
|
#[error("无效的程序计数器: {0}")]
|
|
InvalidPC(usize),
|
|
#[error("执行已停止")]
|
|
Halted,
|
|
}
|
|
|
|
/// 执行结果
|
|
#[derive(Debug, Clone)]
|
|
pub struct ExecutionResult {
|
|
pub success: bool,
|
|
pub gas_used: u64,
|
|
pub return_value: Option<u64>,
|
|
pub error: Option<String>,
|
|
}
|
|
|
|
/// 虚拟机执行器
|
|
#[derive(Debug)]
|
|
pub struct Executor {
|
|
stack: Stack,
|
|
memory: Memory,
|
|
gas: GasMetering,
|
|
pc: usize, // 程序计数器
|
|
halted: bool,
|
|
}
|
|
|
|
impl Executor {
|
|
pub fn new() -> Self {
|
|
Executor {
|
|
stack: Stack::new(),
|
|
memory: Memory::new(),
|
|
gas: GasMetering::new(1_000_000),
|
|
pc: 0,
|
|
halted: false,
|
|
}
|
|
}
|
|
|
|
pub fn with_gas_limit(gas_limit: u64) -> Self {
|
|
Executor {
|
|
stack: Stack::new(),
|
|
memory: Memory::new(),
|
|
gas: GasMetering::new(gas_limit),
|
|
pc: 0,
|
|
halted: false,
|
|
}
|
|
}
|
|
|
|
pub fn is_ready(&self) -> bool {
|
|
!self.halted
|
|
}
|
|
|
|
/// 执行字节码
|
|
pub fn execute(&mut self, bytecode: &Bytecode) -> ExecutionResult {
|
|
self.reset();
|
|
|
|
while self.pc < bytecode.instructions.len() && !self.halted {
|
|
let instruction = &bytecode.instructions[self.pc];
|
|
|
|
// 消耗Gas
|
|
if let Err(e) = self.gas.consume_opcode(instruction.opcode) {
|
|
return ExecutionResult {
|
|
success: false,
|
|
gas_used: self.gas.used(),
|
|
return_value: None,
|
|
error: Some(e.to_string()),
|
|
};
|
|
}
|
|
|
|
// 执行指令
|
|
if let Err(e) = self.execute_instruction(instruction.opcode, &instruction.operands) {
|
|
return ExecutionResult {
|
|
success: false,
|
|
gas_used: self.gas.used(),
|
|
return_value: None,
|
|
error: Some(e.to_string()),
|
|
};
|
|
}
|
|
|
|
self.pc += 1;
|
|
}
|
|
|
|
// 尝试获取返回值
|
|
let return_value = self.stack.pop().ok();
|
|
|
|
ExecutionResult {
|
|
success: true,
|
|
gas_used: self.gas.used(),
|
|
return_value,
|
|
error: None,
|
|
}
|
|
}
|
|
|
|
fn execute_instruction(&mut self, opcode: Opcode, operands: &[u64]) -> Result<(), ExecutionError> {
|
|
match opcode {
|
|
// 栈操作
|
|
Opcode::Push => {
|
|
let value = operands.get(0).copied().unwrap_or(0);
|
|
self.stack.push(value)?;
|
|
}
|
|
Opcode::Pop => {
|
|
self.stack.pop()?;
|
|
}
|
|
Opcode::Dup => {
|
|
self.stack.dup()?;
|
|
}
|
|
Opcode::Swap => {
|
|
self.stack.swap()?;
|
|
}
|
|
|
|
// 算术运算
|
|
Opcode::Add => {
|
|
let b = self.stack.pop()?;
|
|
let a = self.stack.pop()?;
|
|
self.stack.push(a.wrapping_add(b))?;
|
|
}
|
|
Opcode::Sub => {
|
|
let b = self.stack.pop()?;
|
|
let a = self.stack.pop()?;
|
|
self.stack.push(a.wrapping_sub(b))?;
|
|
}
|
|
Opcode::Mul => {
|
|
let b = self.stack.pop()?;
|
|
let a = self.stack.pop()?;
|
|
self.stack.push(a.wrapping_mul(b))?;
|
|
}
|
|
Opcode::Div => {
|
|
let b = self.stack.pop()?;
|
|
let a = self.stack.pop()?;
|
|
if b == 0 {
|
|
return Err(ExecutionError::DivisionByZero);
|
|
}
|
|
self.stack.push(a / b)?;
|
|
}
|
|
Opcode::Mod => {
|
|
let b = self.stack.pop()?;
|
|
let a = self.stack.pop()?;
|
|
if b == 0 {
|
|
return Err(ExecutionError::DivisionByZero);
|
|
}
|
|
self.stack.push(a % b)?;
|
|
}
|
|
|
|
// 比较运算
|
|
Opcode::Eq => {
|
|
let b = self.stack.pop()?;
|
|
let a = self.stack.pop()?;
|
|
self.stack.push(if a == b { 1 } else { 0 })?;
|
|
}
|
|
Opcode::Ne => {
|
|
let b = self.stack.pop()?;
|
|
let a = self.stack.pop()?;
|
|
self.stack.push(if a != b { 1 } else { 0 })?;
|
|
}
|
|
Opcode::Lt => {
|
|
let b = self.stack.pop()?;
|
|
let a = self.stack.pop()?;
|
|
self.stack.push(if a < b { 1 } else { 0 })?;
|
|
}
|
|
Opcode::Le => {
|
|
let b = self.stack.pop()?;
|
|
let a = self.stack.pop()?;
|
|
self.stack.push(if a <= b { 1 } else { 0 })?;
|
|
}
|
|
Opcode::Gt => {
|
|
let b = self.stack.pop()?;
|
|
let a = self.stack.pop()?;
|
|
self.stack.push(if a > b { 1 } else { 0 })?;
|
|
}
|
|
Opcode::Ge => {
|
|
let b = self.stack.pop()?;
|
|
let a = self.stack.pop()?;
|
|
self.stack.push(if a >= b { 1 } else { 0 })?;
|
|
}
|
|
|
|
// 逻辑运算
|
|
Opcode::And => {
|
|
let b = self.stack.pop()?;
|
|
let a = self.stack.pop()?;
|
|
self.stack.push(if a != 0 && b != 0 { 1 } else { 0 })?;
|
|
}
|
|
Opcode::Or => {
|
|
let b = self.stack.pop()?;
|
|
let a = self.stack.pop()?;
|
|
self.stack.push(if a != 0 || b != 0 { 1 } else { 0 })?;
|
|
}
|
|
Opcode::Not => {
|
|
let a = self.stack.pop()?;
|
|
self.stack.push(if a == 0 { 1 } else { 0 })?;
|
|
}
|
|
|
|
// 内存操作
|
|
Opcode::Load => {
|
|
let address = self.stack.pop()?;
|
|
let value = self.memory.load(address)?;
|
|
self.stack.push(value)?;
|
|
}
|
|
Opcode::Store => {
|
|
let address = self.stack.pop()?;
|
|
let value = self.stack.pop()?;
|
|
self.memory.store(address, value)?;
|
|
}
|
|
|
|
// 控制流
|
|
Opcode::Jump => {
|
|
let target = operands.get(0).copied().unwrap_or(0) as usize;
|
|
self.pc = target.saturating_sub(1); // -1因为循环会+1
|
|
}
|
|
Opcode::JumpIf => {
|
|
let condition = self.stack.pop()?;
|
|
if condition != 0 {
|
|
let target = operands.get(0).copied().unwrap_or(0) as usize;
|
|
self.pc = target.saturating_sub(1);
|
|
}
|
|
}
|
|
Opcode::Halt => {
|
|
self.halted = true;
|
|
}
|
|
|
|
// 区块链操作(模拟)
|
|
Opcode::GetBalance => {
|
|
self.stack.push(1000000)?; // 模拟余额
|
|
}
|
|
Opcode::Transfer => {
|
|
let _amount = self.stack.pop()?;
|
|
let _to = self.stack.pop()?;
|
|
self.stack.push(1)?; // 成功
|
|
}
|
|
Opcode::GetCaller => {
|
|
self.stack.push(0x1234567890)?; // 模拟调用者地址
|
|
}
|
|
Opcode::GetTimestamp => {
|
|
self.stack.push(1708272000)?; // 模拟时间戳
|
|
}
|
|
Opcode::GetBlockNumber => {
|
|
self.stack.push(1000000)?; // 模拟区块号
|
|
}
|
|
|
|
// 加密操作
|
|
Opcode::Sha3 => {
|
|
let value = self.stack.pop()?;
|
|
let hash = Sha3_256::digest(value.to_le_bytes());
|
|
let hash_u64 = u64::from_le_bytes(hash[0..8].try_into().unwrap());
|
|
self.stack.push(hash_u64)?;
|
|
}
|
|
Opcode::VerifySignature => {
|
|
self.stack.push(1)?; // 模拟签名验证成功
|
|
}
|
|
|
|
_ => {}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn reset(&mut self) {
|
|
self.stack.clear();
|
|
self.memory.clear();
|
|
self.gas.reset();
|
|
self.pc = 0;
|
|
self.halted = false;
|
|
}
|
|
}
|
|
|
|
impl Default for Executor {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::bytecode::Instruction;
|
|
|
|
#[test]
|
|
fn test_executor_arithmetic() {
|
|
let mut executor = Executor::new();
|
|
let mut bytecode = Bytecode::new();
|
|
|
|
// 计算 10 + 20
|
|
bytecode.add_instruction(Instruction::with_operand(Opcode::Push, 10));
|
|
bytecode.add_instruction(Instruction::with_operand(Opcode::Push, 20));
|
|
bytecode.add_instruction(Instruction::new(Opcode::Add));
|
|
bytecode.add_instruction(Instruction::new(Opcode::Halt));
|
|
|
|
let result = executor.execute(&bytecode);
|
|
assert!(result.success);
|
|
assert_eq!(result.return_value, Some(30));
|
|
}
|
|
|
|
#[test]
|
|
fn test_executor_comparison() {
|
|
let mut executor = Executor::new();
|
|
let mut bytecode = Bytecode::new();
|
|
|
|
// 测试 10 < 20
|
|
bytecode.add_instruction(Instruction::with_operand(Opcode::Push, 10));
|
|
bytecode.add_instruction(Instruction::with_operand(Opcode::Push, 20));
|
|
bytecode.add_instruction(Instruction::new(Opcode::Lt));
|
|
bytecode.add_instruction(Instruction::new(Opcode::Halt));
|
|
|
|
let result = executor.execute(&bytecode);
|
|
assert!(result.success);
|
|
assert_eq!(result.return_value, Some(1)); // true
|
|
}
|
|
|
|
#[test]
|
|
fn test_executor_memory() {
|
|
let mut executor = Executor::new();
|
|
let mut bytecode = Bytecode::new();
|
|
|
|
// 存储和加载
|
|
bytecode.add_instruction(Instruction::with_operand(Opcode::Push, 42));
|
|
bytecode.add_instruction(Instruction::with_operand(Opcode::Push, 0x100));
|
|
bytecode.add_instruction(Instruction::new(Opcode::Store));
|
|
bytecode.add_instruction(Instruction::with_operand(Opcode::Push, 0x100));
|
|
bytecode.add_instruction(Instruction::new(Opcode::Load));
|
|
bytecode.add_instruction(Instruction::new(Opcode::Halt));
|
|
|
|
let result = executor.execute(&bytecode);
|
|
assert!(result.success);
|
|
assert_eq!(result.return_value, Some(42));
|
|
}
|
|
}
|