NAC_Blockchain/nvm_v2/nvm-l1/src/executor.rs

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);
}
}