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

206 lines
5.4 KiB
Rust

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