342 lines
9.5 KiB
Rust
342 lines
9.5 KiB
Rust
// NVM-L0 虚拟机集成层
|
||
// 将L0和L1层整合,提供统一的虚拟机接口
|
||
|
||
use crate::block::{Block, BlockHeader};
|
||
use crate::consensus::{ConsensusEngine, DagConsensus};
|
||
use crate::state_tree::StateTree;
|
||
use crate::transaction::{Transaction, TransactionPool};
|
||
use crate::types::{Address, Hash};
|
||
use serde::{Deserialize, Serialize};
|
||
|
||
/// 虚拟机配置
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct VMConfig {
|
||
/// 区块Gas限制
|
||
pub block_gas_limit: u64,
|
||
/// 交易池大小
|
||
pub tx_pool_size: usize,
|
||
/// 共识难度
|
||
pub consensus_difficulty: u64,
|
||
/// 区块时间(秒)
|
||
pub block_time: u64,
|
||
}
|
||
|
||
impl Default for VMConfig {
|
||
fn default() -> Self {
|
||
Self {
|
||
block_gas_limit: 10_000_000,
|
||
tx_pool_size: 10_000,
|
||
consensus_difficulty: 1000,
|
||
block_time: 6,
|
||
}
|
||
}
|
||
}
|
||
|
||
/// NVM虚拟机
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct NVM {
|
||
/// 配置
|
||
config: VMConfig,
|
||
/// 状态树
|
||
state: StateTree,
|
||
/// 交易池
|
||
tx_pool: TransactionPool,
|
||
/// 共识引擎
|
||
consensus: DagConsensus,
|
||
/// 当前区块号
|
||
current_block: u64,
|
||
/// 最新区块哈希
|
||
latest_block_hash: Hash,
|
||
}
|
||
|
||
impl NVM {
|
||
/// 创建新的虚拟机实例
|
||
pub fn new(config: VMConfig) -> Self {
|
||
Self {
|
||
tx_pool: TransactionPool::new(config.tx_pool_size),
|
||
consensus: DagConsensus::new(config.consensus_difficulty),
|
||
config,
|
||
state: StateTree::new(),
|
||
current_block: 0,
|
||
latest_block_hash: Hash::zero(),
|
||
}
|
||
}
|
||
|
||
/// 使用默认配置创建
|
||
pub fn with_defaults() -> Self {
|
||
Self::new(VMConfig::default())
|
||
}
|
||
|
||
/// 提交交易到交易池
|
||
pub fn submit_transaction(&mut self, tx: Transaction) -> Result<Hash, String> {
|
||
// 验证交易
|
||
if !tx.verify_signature() {
|
||
return Err("Invalid transaction signature".to_string());
|
||
}
|
||
|
||
// 检查余额
|
||
let balance = self.state.get_balance(&tx.from);
|
||
let total_cost = tx.value + (tx.gas_limit * tx.gas_price) as u128;
|
||
if balance < total_cost {
|
||
return Err("Insufficient balance".to_string());
|
||
}
|
||
|
||
// 检查nonce
|
||
let expected_nonce = self.state.get_nonce(&tx.from);
|
||
if tx.nonce != expected_nonce {
|
||
return Err(format!(
|
||
"Invalid nonce: expected {}, got {}",
|
||
expected_nonce, tx.nonce
|
||
));
|
||
}
|
||
|
||
let hash = tx.hash;
|
||
self.tx_pool.add_transaction(tx)?;
|
||
Ok(hash)
|
||
}
|
||
|
||
/// 生成新区块
|
||
pub fn produce_block(&mut self, miner: Address) -> Result<Block, String> {
|
||
// 获取待处理交易
|
||
let transactions = self.tx_pool.get_pending_transactions();
|
||
if transactions.is_empty() {
|
||
return Err("No pending transactions".to_string());
|
||
}
|
||
|
||
// 创建区块头
|
||
let header = BlockHeader {
|
||
number: self.current_block + 1,
|
||
timestamp: self.get_current_timestamp(),
|
||
parent_hash: self.latest_block_hash,
|
||
state_root: self.state.root_hash(),
|
||
tx_root: self.calculate_tx_root(&transactions),
|
||
miner,
|
||
};
|
||
|
||
// 创建区块
|
||
let block = Block::new(header, transactions.clone());
|
||
|
||
// 验证区块
|
||
if !self.consensus.validate_block(&block) {
|
||
return Err("Block validation failed".to_string());
|
||
}
|
||
|
||
// 执行交易
|
||
self.execute_transactions(&transactions)?;
|
||
|
||
// 确认交易
|
||
for tx in &transactions {
|
||
self.tx_pool.confirm_transaction(&tx.hash)?;
|
||
}
|
||
|
||
// 更新区块信息
|
||
self.current_block = block.header.number;
|
||
self.latest_block_hash = block.hash;
|
||
|
||
Ok(block)
|
||
}
|
||
|
||
/// 执行交易列表
|
||
fn execute_transactions(&mut self, transactions: &[Transaction]) -> Result<(), String> {
|
||
for tx in transactions {
|
||
self.execute_transaction(tx)?;
|
||
}
|
||
Ok(())
|
||
}
|
||
|
||
/// 执行单个交易
|
||
fn execute_transaction(&mut self, tx: &Transaction) -> Result<(), String> {
|
||
// 扣除Gas费用
|
||
let gas_cost = (tx.gas_limit * tx.gas_price) as u128;
|
||
self.state.sub_balance(tx.from, gas_cost)?;
|
||
|
||
// 执行转账
|
||
if tx.value > 0 {
|
||
self.state.transfer(tx.from, tx.to, tx.value)?;
|
||
}
|
||
|
||
// 增加nonce
|
||
self.state.increment_nonce(tx.from);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 计算交易根哈希
|
||
fn calculate_tx_root(&self, transactions: &[Transaction]) -> Hash {
|
||
if transactions.is_empty() {
|
||
return Hash::zero();
|
||
}
|
||
|
||
let mut data = Vec::new();
|
||
for tx in transactions {
|
||
data.extend_from_slice(tx.hash.as_bytes());
|
||
}
|
||
Hash::sha3_384(&data)
|
||
}
|
||
|
||
/// 获取当前时间戳
|
||
fn get_current_timestamp(&self) -> u64 {
|
||
use std::time::{SystemTime, UNIX_EPOCH};
|
||
SystemTime::now()
|
||
.duration_since(UNIX_EPOCH)
|
||
.expect("mainnet: handle error")
|
||
.as_secs()
|
||
}
|
||
|
||
/// 获取账户余额
|
||
pub fn get_balance(&self, address: &Address) -> u128 {
|
||
self.state.get_balance(address)
|
||
}
|
||
|
||
/// 获取账户nonce
|
||
pub fn get_nonce(&self, address: &Address) -> u64 {
|
||
self.state.get_nonce(address)
|
||
}
|
||
|
||
/// 获取当前区块号
|
||
pub fn get_block_number(&self) -> u64 {
|
||
self.current_block
|
||
}
|
||
|
||
/// 获取状态根哈希
|
||
pub fn get_state_root(&self) -> Hash {
|
||
self.state.root_hash()
|
||
}
|
||
|
||
/// 获取待处理交易数量
|
||
pub fn pending_transaction_count(&self) -> usize {
|
||
self.tx_pool.pending_count()
|
||
}
|
||
|
||
/// 设置账户余额(仅用于测试)
|
||
#[cfg(test)]
|
||
pub fn set_balance(&mut self, address: Address, balance: u128) {
|
||
self.state.set_balance(address, balance);
|
||
}
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
use crate::transaction::TransactionType;
|
||
use crate::types::Signature;
|
||
|
||
fn create_test_vm() -> NVM {
|
||
NVM::with_defaults()
|
||
}
|
||
|
||
fn create_test_transaction(from: Address, to: Address, value: u128, nonce: u64) -> Transaction {
|
||
let mut tx = Transaction::new(
|
||
from,
|
||
to,
|
||
value,
|
||
nonce,
|
||
21000,
|
||
1,
|
||
Vec::new(),
|
||
TransactionType::Transfer,
|
||
);
|
||
tx.sign(Signature::new(vec![1, 2, 3]));
|
||
tx
|
||
}
|
||
|
||
#[test]
|
||
fn test_vm_creation() {
|
||
let vm = create_test_vm();
|
||
assert_eq!(vm.get_block_number(), 0);
|
||
}
|
||
|
||
#[test]
|
||
fn test_submit_transaction() {
|
||
let mut vm = create_test_vm();
|
||
let from = Address::new([1u8; 32]);
|
||
let to = Address::new([2u8; 32]);
|
||
|
||
// 设置初始余额
|
||
vm.set_balance(from, 100000);
|
||
|
||
let tx = create_test_transaction(from, to, 1000, 0);
|
||
assert!(vm.submit_transaction(tx).is_ok());
|
||
assert_eq!(vm.pending_transaction_count(), 1);
|
||
}
|
||
|
||
#[test]
|
||
fn test_insufficient_balance() {
|
||
let mut vm = create_test_vm();
|
||
let from = Address::new([1u8; 32]);
|
||
let to = Address::new([2u8; 32]);
|
||
|
||
// 不设置余额
|
||
let tx = create_test_transaction(from, to, 1000, 0);
|
||
assert!(vm.submit_transaction(tx).is_err());
|
||
}
|
||
|
||
#[test]
|
||
fn test_produce_block() {
|
||
let mut vm = create_test_vm();
|
||
let from = Address::new([1u8; 32]);
|
||
let to = Address::new([2u8; 32]);
|
||
let miner = Address::new([3u8; 32]);
|
||
|
||
// 设置初始余额
|
||
vm.set_balance(from, 100000);
|
||
|
||
// 提交交易
|
||
let tx = create_test_transaction(from, to, 1000, 0);
|
||
vm.submit_transaction(tx).expect("mainnet: handle error");
|
||
|
||
// 生成区块
|
||
let block = vm.produce_block(miner).expect("mainnet: handle error");
|
||
assert_eq!(block.header.number, 1);
|
||
assert_eq!(block.transactions.len(), 1);
|
||
|
||
// 验证余额变化
|
||
assert_eq!(vm.get_balance(&to), 1000);
|
||
assert_eq!(vm.get_nonce(&from), 1);
|
||
}
|
||
|
||
#[test]
|
||
fn test_invalid_nonce() {
|
||
let mut vm = create_test_vm();
|
||
let from = Address::new([1u8; 32]);
|
||
let to = Address::new([2u8; 32]);
|
||
|
||
vm.set_balance(from, 100000);
|
||
|
||
// 使用错误的nonce
|
||
let tx = create_test_transaction(from, to, 1000, 5);
|
||
assert!(vm.submit_transaction(tx).is_err());
|
||
}
|
||
|
||
#[test]
|
||
fn test_multiple_transactions() {
|
||
let mut vm = create_test_vm();
|
||
let from = Address::new([1u8; 32]);
|
||
let to1 = Address::new([2u8; 32]);
|
||
let to2 = Address::new([3u8; 32]);
|
||
let miner = Address::new([4u8; 32]);
|
||
|
||
vm.set_balance(from, 100000);
|
||
|
||
// 提交第一个交易
|
||
let tx1 = create_test_transaction(from, to1, 1000, 0);
|
||
vm.submit_transaction(tx1).expect("mainnet: handle error");
|
||
|
||
// 生成第一个区块
|
||
let block1 = vm.produce_block(miner).expect("mainnet: handle error");
|
||
assert_eq!(block1.transactions.len(), 1);
|
||
assert_eq!(vm.get_balance(&to1), 1000);
|
||
assert_eq!(vm.get_nonce(&from), 1);
|
||
|
||
// 现在nonce是1,可以提交第二个交易
|
||
let tx2 = create_test_transaction(from, to2, 2000, 1);
|
||
vm.submit_transaction(tx2).expect("mainnet: handle error");
|
||
|
||
// 生成第二个区块
|
||
let block2 = vm.produce_block(miner).expect("mainnet: handle error");
|
||
assert_eq!(block2.transactions.len(), 1);
|
||
assert_eq!(vm.get_balance(&to2), 2000);
|
||
assert_eq!(vm.get_nonce(&from), 2);
|
||
}
|
||
}
|