546 lines
16 KiB
Rust
546 lines
16 KiB
Rust
// NVM-L1 合约执行器
|
|
|
|
use crate::contract::Contract;
|
|
use crate::gas::{GasError, GasMeter};
|
|
use crate::state::StateManager;
|
|
use crate::types::{Address, Hash};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
/// 执行上下文
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ExecutionContext {
|
|
/// 调用者地址
|
|
pub caller: Address,
|
|
/// 合约地址
|
|
pub contract_address: Address,
|
|
/// 交易发起者
|
|
pub origin: Address,
|
|
/// Gas价格
|
|
pub gas_price: u64,
|
|
/// 区块号
|
|
pub block_number: u64,
|
|
/// 区块时间戳
|
|
pub block_timestamp: u64,
|
|
/// 调用数据
|
|
pub call_data: Vec<u8>,
|
|
/// 调用值
|
|
pub call_value: u128,
|
|
}
|
|
|
|
impl ExecutionContext {
|
|
/// 创建新的执行上下文
|
|
pub fn new(
|
|
caller: Address,
|
|
contract_address: Address,
|
|
origin: Address,
|
|
call_data: Vec<u8>,
|
|
call_value: u128,
|
|
) -> Self {
|
|
Self {
|
|
caller,
|
|
contract_address,
|
|
origin,
|
|
gas_price: 1,
|
|
block_number: 0,
|
|
block_timestamp: 0,
|
|
call_data,
|
|
call_value,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 执行结果
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ExecutionResult {
|
|
/// 是否成功
|
|
pub success: bool,
|
|
/// 返回数据
|
|
pub return_data: Vec<u8>,
|
|
/// 使用的Gas
|
|
pub gas_used: u64,
|
|
/// 错误信息
|
|
pub error: Option<String>,
|
|
/// 状态变更
|
|
pub state_changes: Vec<StateChange>,
|
|
}
|
|
|
|
/// 状态变更
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub enum StateChange {
|
|
/// 余额变更
|
|
BalanceChange {
|
|
address: Address,
|
|
old_balance: u128,
|
|
new_balance: u128,
|
|
},
|
|
/// 存储变更
|
|
StorageChange {
|
|
address: Address,
|
|
key: Hash,
|
|
old_value: Option<Vec<u8>>,
|
|
new_value: Vec<u8>,
|
|
},
|
|
/// 合约创建
|
|
ContractCreation {
|
|
address: Address,
|
|
code_hash: Hash,
|
|
},
|
|
/// 合约销毁
|
|
ContractDestruction {
|
|
address: Address,
|
|
},
|
|
}
|
|
|
|
/// 执行错误
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
pub enum ExecutionError {
|
|
/// Gas相关错误
|
|
Gas(GasError),
|
|
/// 合约不存在
|
|
ContractNotFound,
|
|
/// 合约已暂停
|
|
ContractPaused,
|
|
/// 合约已销毁
|
|
ContractDestroyed,
|
|
/// 余额不足
|
|
InsufficientBalance,
|
|
/// 调用深度超限
|
|
CallDepthExceeded,
|
|
/// 无效操作码
|
|
InvalidOpcode(u8),
|
|
/// 栈溢出
|
|
StackOverflow,
|
|
/// 栈下溢
|
|
StackUnderflow,
|
|
/// 内存访问越界
|
|
MemoryAccessOutOfBounds,
|
|
/// 除零错误
|
|
DivisionByZero,
|
|
/// 其他错误
|
|
Other(String),
|
|
}
|
|
|
|
impl From<GasError> for ExecutionError {
|
|
fn from(error: GasError) -> Self {
|
|
ExecutionError::Gas(error)
|
|
}
|
|
}
|
|
|
|
/// 简化的操作码
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum Opcode {
|
|
/// 停止执行
|
|
STOP = 0x00,
|
|
/// 加法
|
|
ADD = 0x01,
|
|
/// 乘法
|
|
MUL = 0x02,
|
|
/// 减法
|
|
SUB = 0x03,
|
|
/// 除法
|
|
DIV = 0x04,
|
|
/// 模运算
|
|
MOD = 0x05,
|
|
/// 压栈
|
|
PUSH1 = 0x60,
|
|
/// 弹栈
|
|
POP = 0x50,
|
|
/// 存储写入
|
|
SSTORE = 0x55,
|
|
/// 存储读取
|
|
SLOAD = 0x54,
|
|
/// 返回
|
|
RETURN = 0xf3,
|
|
}
|
|
|
|
impl Opcode {
|
|
/// 从字节转换为操作码
|
|
pub fn from_byte(byte: u8) -> Option<Self> {
|
|
match byte {
|
|
0x00 => Some(Opcode::STOP),
|
|
0x01 => Some(Opcode::ADD),
|
|
0x02 => Some(Opcode::MUL),
|
|
0x03 => Some(Opcode::SUB),
|
|
0x04 => Some(Opcode::DIV),
|
|
0x05 => Some(Opcode::MOD),
|
|
0x50 => Some(Opcode::POP),
|
|
0x54 => Some(Opcode::SLOAD),
|
|
0x55 => Some(Opcode::SSTORE),
|
|
0x60 => Some(Opcode::PUSH1),
|
|
0xf3 => Some(Opcode::RETURN),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 合约执行器
|
|
#[derive(Debug)]
|
|
pub struct ContractExecutor {
|
|
/// 状态管理器
|
|
state_manager: StateManager,
|
|
/// 调用栈深度限制
|
|
#[allow(dead_code)]
|
|
max_call_depth: usize,
|
|
/// 栈大小限制
|
|
max_stack_size: usize,
|
|
}
|
|
|
|
impl ContractExecutor {
|
|
/// 创建新的合约执行器
|
|
pub fn new() -> Self {
|
|
Self {
|
|
state_manager: StateManager::new(),
|
|
max_call_depth: 1024,
|
|
max_stack_size: 1024,
|
|
}
|
|
}
|
|
|
|
/// 获取状态管理器
|
|
pub fn state_manager(&self) -> &StateManager {
|
|
&self.state_manager
|
|
}
|
|
|
|
/// 获取可变状态管理器
|
|
pub fn state_manager_mut(&mut self) -> &mut StateManager {
|
|
&mut self.state_manager
|
|
}
|
|
|
|
/// 执行合约调用
|
|
pub fn call(
|
|
&mut self,
|
|
context: ExecutionContext,
|
|
gas_limit: u64,
|
|
) -> ExecutionResult {
|
|
let mut gas_meter = GasMeter::new(gas_limit);
|
|
let state_changes = Vec::new();
|
|
|
|
// 创建状态快照
|
|
self.state_manager.snapshot();
|
|
|
|
// 消耗基础调用Gas
|
|
if let Err(e) = gas_meter.consume_contract_call_gas() {
|
|
return ExecutionResult {
|
|
success: false,
|
|
return_data: Vec::new(),
|
|
gas_used: gas_meter.gas_used(),
|
|
error: Some(format!("Gas error: {:?}", e)),
|
|
state_changes,
|
|
};
|
|
}
|
|
|
|
// 获取合约
|
|
let contract = match self.state_manager.current_state().get_contract(&context.contract_address) {
|
|
Some(contract) => contract.clone(),
|
|
None => {
|
|
return ExecutionResult {
|
|
success: false,
|
|
return_data: Vec::new(),
|
|
gas_used: gas_meter.gas_used(),
|
|
error: Some("Contract not found".to_string()),
|
|
state_changes,
|
|
};
|
|
}
|
|
};
|
|
|
|
// 检查合约状态
|
|
if !contract.is_active() {
|
|
return ExecutionResult {
|
|
success: false,
|
|
return_data: Vec::new(),
|
|
gas_used: gas_meter.gas_used(),
|
|
error: Some("Contract is not active".to_string()),
|
|
state_changes,
|
|
};
|
|
}
|
|
|
|
// 执行字节码
|
|
match self.execute_bytecode(&contract, &context, &mut gas_meter) {
|
|
Ok(return_data) => {
|
|
self.state_manager.commit();
|
|
ExecutionResult {
|
|
success: true,
|
|
return_data,
|
|
gas_used: gas_meter.gas_used(),
|
|
error: None,
|
|
state_changes,
|
|
}
|
|
}
|
|
Err(e) => {
|
|
self.state_manager.revert().ok();
|
|
ExecutionResult {
|
|
success: false,
|
|
return_data: Vec::new(),
|
|
gas_used: gas_meter.gas_used(),
|
|
error: Some(format!("{:?}", e)),
|
|
state_changes,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 部署合约
|
|
pub fn deploy(
|
|
&mut self,
|
|
contract: Contract,
|
|
gas_limit: u64,
|
|
) -> ExecutionResult {
|
|
let mut gas_meter = GasMeter::new(gas_limit);
|
|
let mut state_changes = Vec::new();
|
|
|
|
// 消耗合约创建Gas
|
|
if let Err(e) = gas_meter.consume_contract_creation_gas() {
|
|
return ExecutionResult {
|
|
success: false,
|
|
return_data: Vec::new(),
|
|
gas_used: gas_meter.gas_used(),
|
|
error: Some(format!("Gas error: {:?}", e)),
|
|
state_changes,
|
|
};
|
|
}
|
|
|
|
// 部署合约
|
|
match self.state_manager.current_state_mut().deploy_contract(contract.clone()) {
|
|
Ok(()) => {
|
|
state_changes.push(StateChange::ContractCreation {
|
|
address: contract.address,
|
|
code_hash: *contract.code.code_hash(),
|
|
});
|
|
|
|
ExecutionResult {
|
|
success: true,
|
|
return_data: Vec::new(),
|
|
gas_used: gas_meter.gas_used(),
|
|
error: None,
|
|
state_changes,
|
|
}
|
|
}
|
|
Err(e) => ExecutionResult {
|
|
success: false,
|
|
return_data: Vec::new(),
|
|
gas_used: gas_meter.gas_used(),
|
|
error: Some(e),
|
|
state_changes,
|
|
},
|
|
}
|
|
}
|
|
|
|
/// 执行字节码(简化版本)
|
|
fn execute_bytecode(
|
|
&mut self,
|
|
contract: &Contract,
|
|
context: &ExecutionContext,
|
|
gas_meter: &mut GasMeter,
|
|
) -> Result<Vec<u8>, ExecutionError> {
|
|
let bytecode = contract.code.bytecode();
|
|
let mut pc = 0; // 程序计数器
|
|
let mut stack: Vec<u64> = Vec::new();
|
|
let mut memory = Vec::new();
|
|
|
|
while pc < bytecode.len() {
|
|
let opcode_byte = bytecode[pc];
|
|
let opcode = Opcode::from_byte(opcode_byte)
|
|
.ok_or(ExecutionError::InvalidOpcode(opcode_byte))?;
|
|
|
|
// 消耗计算Gas
|
|
gas_meter.consume_compute_gas(1)?;
|
|
|
|
match opcode {
|
|
Opcode::STOP => break,
|
|
|
|
Opcode::ADD => {
|
|
if stack.len() < 2 {
|
|
return Err(ExecutionError::StackUnderflow);
|
|
}
|
|
let b = stack.pop().unwrap();
|
|
let a = stack.pop().unwrap();
|
|
stack.push(a.wrapping_add(b));
|
|
}
|
|
|
|
Opcode::SUB => {
|
|
if stack.len() < 2 {
|
|
return Err(ExecutionError::StackUnderflow);
|
|
}
|
|
let b = stack.pop().unwrap();
|
|
let a = stack.pop().unwrap();
|
|
stack.push(a.wrapping_sub(b));
|
|
}
|
|
|
|
Opcode::MUL => {
|
|
if stack.len() < 2 {
|
|
return Err(ExecutionError::StackUnderflow);
|
|
}
|
|
let b = stack.pop().unwrap();
|
|
let a = stack.pop().unwrap();
|
|
stack.push(a.wrapping_mul(b));
|
|
}
|
|
|
|
Opcode::DIV => {
|
|
if stack.len() < 2 {
|
|
return Err(ExecutionError::StackUnderflow);
|
|
}
|
|
let b = stack.pop().unwrap();
|
|
let a = stack.pop().unwrap();
|
|
if b == 0 {
|
|
return Err(ExecutionError::DivisionByZero);
|
|
}
|
|
stack.push(a / b);
|
|
}
|
|
|
|
Opcode::PUSH1 => {
|
|
if pc + 1 >= bytecode.len() {
|
|
return Err(ExecutionError::Other("Invalid PUSH1".to_string()));
|
|
}
|
|
pc += 1;
|
|
let value = bytecode[pc] as u64;
|
|
stack.push(value);
|
|
}
|
|
|
|
Opcode::POP => {
|
|
if stack.is_empty() {
|
|
return Err(ExecutionError::StackUnderflow);
|
|
}
|
|
stack.pop();
|
|
}
|
|
|
|
Opcode::SLOAD => {
|
|
if stack.is_empty() {
|
|
return Err(ExecutionError::StackUnderflow);
|
|
}
|
|
let key_bytes = stack.pop().unwrap().to_le_bytes();
|
|
let mut key_array = [0u8; 48];
|
|
key_array[..8].copy_from_slice(&key_bytes);
|
|
let key = Hash::new(key_array);
|
|
|
|
gas_meter.consume_storage_read_gas(32)?;
|
|
|
|
let value = self.state_manager
|
|
.current_state()
|
|
.get_storage(&context.contract_address, &key)
|
|
.unwrap_or_default();
|
|
|
|
let value_u64 = if value.len() >= 8 {
|
|
u64::from_le_bytes([
|
|
value[0], value[1], value[2], value[3],
|
|
value[4], value[5], value[6], value[7],
|
|
])
|
|
} else {
|
|
0
|
|
};
|
|
stack.push(value_u64);
|
|
}
|
|
|
|
Opcode::SSTORE => {
|
|
if stack.len() < 2 {
|
|
return Err(ExecutionError::StackUnderflow);
|
|
}
|
|
let value = stack.pop().unwrap();
|
|
let key_bytes = stack.pop().unwrap().to_le_bytes();
|
|
let mut key_array = [0u8; 48];
|
|
key_array[..8].copy_from_slice(&key_bytes);
|
|
let key = Hash::new(key_array);
|
|
|
|
gas_meter.consume_storage_write_gas(32)?;
|
|
|
|
let value_bytes = value.to_le_bytes().to_vec();
|
|
self.state_manager
|
|
.current_state_mut()
|
|
.set_storage(&context.contract_address, key, value_bytes);
|
|
}
|
|
|
|
Opcode::RETURN => {
|
|
if stack.len() < 2 {
|
|
return Err(ExecutionError::StackUnderflow);
|
|
}
|
|
let size = stack.pop().unwrap() as usize;
|
|
let offset = stack.pop().unwrap() as usize;
|
|
|
|
if offset + size > memory.len() {
|
|
memory.resize(offset + size, 0);
|
|
gas_meter.consume_memory_expansion_gas(offset + size - memory.len())?;
|
|
}
|
|
|
|
return Ok(memory[offset..offset + size].to_vec());
|
|
}
|
|
|
|
_ => {
|
|
return Err(ExecutionError::InvalidOpcode(opcode_byte));
|
|
}
|
|
}
|
|
|
|
if stack.len() > self.max_stack_size {
|
|
return Err(ExecutionError::StackOverflow);
|
|
}
|
|
|
|
pc += 1;
|
|
}
|
|
|
|
Ok(Vec::new())
|
|
}
|
|
}
|
|
|
|
impl Default for ContractExecutor {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::contract::{ContractCode, ContractMetadata};
|
|
|
|
fn create_test_executor() -> ContractExecutor {
|
|
ContractExecutor::new()
|
|
}
|
|
|
|
fn create_test_contract() -> Contract {
|
|
let address = Address::new([1u8; 20]);
|
|
let owner = Address::new([2u8; 20]);
|
|
// 简单的字节码: PUSH1 42, PUSH1 0, SSTORE, STOP
|
|
let bytecode = vec![0x60, 42, 0x60, 0, 0x55, 0x00];
|
|
let code = ContractCode::new(bytecode);
|
|
let metadata = ContractMetadata::default();
|
|
Contract::new(address, code, owner, metadata)
|
|
}
|
|
|
|
#[test]
|
|
fn test_contract_deployment() {
|
|
let mut executor = create_test_executor();
|
|
let contract = create_test_contract();
|
|
|
|
let result = executor.deploy(contract, 100000);
|
|
assert!(result.success);
|
|
}
|
|
|
|
#[test]
|
|
fn test_contract_call() {
|
|
let mut executor = create_test_executor();
|
|
let contract = create_test_contract();
|
|
let address = contract.address;
|
|
|
|
// 先部署合约
|
|
executor.deploy(contract, 100000);
|
|
|
|
// 调用合约
|
|
let context = ExecutionContext::new(
|
|
Address::new([3u8; 20]),
|
|
address,
|
|
Address::new([3u8; 20]),
|
|
Vec::new(),
|
|
0,
|
|
);
|
|
|
|
let result = executor.call(context, 100000);
|
|
assert!(result.success);
|
|
}
|
|
|
|
#[test]
|
|
fn test_opcode_execution() {
|
|
let opcode = Opcode::from_byte(0x01);
|
|
assert_eq!(opcode, Some(Opcode::ADD));
|
|
|
|
let invalid_opcode = Opcode::from_byte(0xff);
|
|
assert_eq!(invalid_opcode, None);
|
|
}
|
|
}
|