// NVM-L1 Gas计量系统 use serde::{Deserialize, Serialize}; /// Gas配置 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct GasConfig { /// 基础交易Gas pub base_tx_gas: u64, /// 合约创建Gas pub contract_creation_gas: u64, /// 合约调用Gas pub contract_call_gas: u64, /// 存储写入Gas (每字节) pub storage_write_gas_per_byte: u64, /// 存储读取Gas (每字节) pub storage_read_gas_per_byte: u64, /// 计算Gas (每操作) pub compute_gas_per_op: u64, /// 内存扩展Gas (每字节) pub memory_expansion_gas_per_byte: u64, } impl Default for GasConfig { fn default() -> Self { Self { base_tx_gas: 21000, contract_creation_gas: 53000, contract_call_gas: 25000, storage_write_gas_per_byte: 20, storage_read_gas_per_byte: 5, compute_gas_per_op: 3, memory_expansion_gas_per_byte: 3, } } } /// Gas计量器 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct GasMeter { /// Gas配置 config: GasConfig, /// Gas限制 gas_limit: u64, /// 已使用Gas gas_used: u64, } /// Gas错误 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum GasError { /// Gas不足 OutOfGas, /// Gas限制过低 GasLimitTooLow, /// 无效的Gas价格 InvalidGasPrice, } impl GasMeter { /// 创建新的Gas计量器 pub fn new(gas_limit: u64) -> Self { Self::with_config(gas_limit, GasConfig::default()) } /// 使用自定义配置创建Gas计量器 pub fn with_config(gas_limit: u64, config: GasConfig) -> Self { Self { config, gas_limit, gas_used: 0, } } /// 获取Gas限制 pub fn gas_limit(&self) -> u64 { self.gas_limit } /// 获取已使用Gas pub fn gas_used(&self) -> u64 { self.gas_used } /// 获取剩余Gas pub fn gas_remaining(&self) -> u64 { self.gas_limit.saturating_sub(self.gas_used) } /// 消耗Gas pub fn consume_gas(&mut self, amount: u64) -> Result<(), GasError> { if self.gas_used + amount > self.gas_limit { return Err(GasError::OutOfGas); } self.gas_used += amount; Ok(()) } /// 消耗基础交易Gas pub fn consume_base_tx_gas(&mut self) -> Result<(), GasError> { self.consume_gas(self.config.base_tx_gas) } /// 消耗合约创建Gas pub fn consume_contract_creation_gas(&mut self) -> Result<(), GasError> { self.consume_gas(self.config.contract_creation_gas) } /// 消耗合约调用Gas pub fn consume_contract_call_gas(&mut self) -> Result<(), GasError> { self.consume_gas(self.config.contract_call_gas) } /// 消耗存储写入Gas pub fn consume_storage_write_gas(&mut self, bytes: usize) -> Result<(), GasError> { let gas = self.config.storage_write_gas_per_byte * bytes as u64; self.consume_gas(gas) } /// 消耗存储读取Gas pub fn consume_storage_read_gas(&mut self, bytes: usize) -> Result<(), GasError> { let gas = self.config.storage_read_gas_per_byte * bytes as u64; self.consume_gas(gas) } /// 消耗计算Gas pub fn consume_compute_gas(&mut self, ops: usize) -> Result<(), GasError> { let gas = self.config.compute_gas_per_op * ops as u64; self.consume_gas(gas) } /// 消耗内存扩展Gas pub fn consume_memory_expansion_gas(&mut self, bytes: usize) -> Result<(), GasError> { let gas = self.config.memory_expansion_gas_per_byte * bytes as u64; self.consume_gas(gas) } /// 重置Gas计量器 pub fn reset(&mut self) { self.gas_used = 0; } /// 检查是否有足够的Gas pub fn has_gas(&self, amount: u64) -> bool { self.gas_used + amount <= self.gas_limit } } #[cfg(test)] mod tests { use super::*; #[test] fn test_gas_meter_creation() { let meter = GasMeter::new(100000); assert_eq!(meter.gas_limit(), 100000); assert_eq!(meter.gas_used(), 0); assert_eq!(meter.gas_remaining(), 100000); } #[test] fn test_consume_gas() { let mut meter = GasMeter::new(100000); assert!(meter.consume_gas(50000).is_ok()); assert_eq!(meter.gas_used(), 50000); assert_eq!(meter.gas_remaining(), 50000); } #[test] fn test_out_of_gas() { let mut meter = GasMeter::new(100000); assert!(meter.consume_gas(100001).is_err()); } #[test] fn test_consume_base_tx_gas() { let mut meter = GasMeter::new(100000); assert!(meter.consume_base_tx_gas().is_ok()); assert_eq!(meter.gas_used(), 21000); } #[test] fn test_consume_storage_gas() { let mut meter = GasMeter::new(100000); assert!(meter.consume_storage_write_gas(100).is_ok()); assert_eq!(meter.gas_used(), 2000); // 20 * 100 } #[test] fn test_has_gas() { let mut meter = GasMeter::new(100000); meter.consume_gas(50000).unwrap(); assert!(meter.has_gas(50000)); assert!(!meter.has_gas(50001)); } #[test] fn test_reset() { let mut meter = GasMeter::new(100000); meter.consume_gas(50000).unwrap(); meter.reset(); assert_eq!(meter.gas_used(), 0); assert_eq!(meter.gas_remaining(), 100000); } }