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

219 lines
5.0 KiB
Rust

// NVM-L1 合约定义
use crate::types::{Address, Hash};
use serde::{Deserialize, Serialize};
/// 合约代码
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContractCode {
/// 字节码
pub bytecode: Vec<u8>,
/// 代码哈希
pub code_hash: Hash,
}
impl ContractCode {
/// 创建新的合约代码
pub fn new(bytecode: Vec<u8>) -> Self {
let code_hash = Hash::sha3_384(&bytecode);
Self {
bytecode,
code_hash,
}
}
/// 获取字节码
pub fn bytecode(&self) -> &[u8] {
&self.bytecode
}
/// 获取代码哈希
pub fn code_hash(&self) -> &Hash {
&self.code_hash
}
/// 获取代码大小
pub fn size(&self) -> usize {
self.bytecode.len()
}
}
/// 合约元数据
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContractMetadata {
/// 合约名称
pub name: String,
/// 合约版本
pub version: String,
/// 合约作者
pub author: String,
/// 合约描述
pub description: String,
/// 创建时间
pub created_at: u64,
}
impl Default for ContractMetadata {
fn default() -> Self {
Self {
name: String::new(),
version: "1.0.0".to_string(),
author: String::new(),
description: String::new(),
created_at: 0,
}
}
}
/// 合约状态
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum ContractState {
/// 活跃
Active,
/// 暂停
Paused,
/// 已销毁
Destroyed,
}
/// 合约
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Contract {
/// 合约地址
pub address: Address,
/// 合约代码
pub code: ContractCode,
/// 合约元数据
pub metadata: ContractMetadata,
/// 合约状态
pub state: ContractState,
/// 合约所有者
pub owner: Address,
/// 合约余额
pub holdings: u128,
/// 存储根哈希
pub storage_root: Hash,
/// Nonce
pub nonce: u64,
}
impl Contract {
/// 创建新合约
pub fn new(
address: Address,
code: ContractCode,
owner: Address,
metadata: ContractMetadata,
) -> Self {
Self {
address,
code,
metadata,
state: ContractState::Active,
owner,
holdings: 0,
storage_root: Hash::zero(),
nonce: 0,
}
}
/// 检查合约是否活跃
pub fn is_active(&self) -> bool {
self.state == ContractState::Active
}
/// 暂停合约
pub fn pause(&mut self) {
self.state = ContractState::Paused;
}
/// 恢复合约
pub fn resume(&mut self) {
self.state = ContractState::Active;
}
/// 销毁合约
pub fn destroy(&mut self) {
self.state = ContractState::Destroyed;
}
/// 增加余额
pub fn add_balance(&mut self, amount: u128) {
self.holdings = self.holdings.saturating_add(amount);
}
/// 减少余额
pub fn sub_balance(&mut self, amount: u128) -> Result<(), String> {
if self.holdings < amount {
return Err("Insufficient holdings".to_string());
}
self.holdings -= amount;
Ok(())
}
/// 增加nonce
pub fn increment_nonce(&mut self) {
self.nonce = self.nonce.saturating_add(1);
}
/// 更新存储根
pub fn update_storage_root(&mut self, root: Hash) {
self.storage_root = root;
}
}
#[cfg(test)]
mod tests {
use super::*;
fn create_test_contract() -> Contract {
let address = Address::new([1u8; 20]);
let owner = Address::new([2u8; 20]);
let code = ContractCode::new(vec![0x60, 0x60, 0x60, 0x40]);
let metadata = ContractMetadata::default();
Contract::new(address, code, owner, metadata)
}
#[test]
fn test_contract_creation() {
let contract = create_test_contract();
assert!(contract.is_active());
assert_eq!(contract.holdings, 0);
assert_eq!(contract.nonce, 0);
}
#[test]
fn test_contract_pause_resume() {
let mut contract = create_test_contract();
contract.pause();
assert!(!contract.is_active());
contract.resume();
assert!(contract.is_active());
}
#[test]
fn test_contract_balance() {
let mut contract = create_test_contract();
contract.add_balance(1000);
assert_eq!(contract.holdings, 1000);
assert!(contract.sub_balance(500).is_ok());
assert_eq!(contract.holdings, 500);
}
#[test]
fn test_contract_nonce() {
let mut contract = create_test_contract();
contract.increment_nonce();
assert_eq!(contract.nonce, 1);
contract.increment_nonce();
assert_eq!(contract.nonce, 2);
}
#[test]
fn test_contract_destroy() {
let mut contract = create_test_contract();
contract.destroy();
assert_eq!(contract.state, ContractState::Destroyed);
}
}