259 lines
6.5 KiB
Rust
259 lines
6.5 KiB
Rust
// NVM-L0 交易定义和交易池
|
|
|
|
use crate::types::{Address, Hash, Signature};
|
|
use serde::{Deserialize, Serialize};
|
|
use std::collections::HashMap;
|
|
|
|
/// 交易类型
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
pub enum TransactionType {
|
|
/// 转账
|
|
Transfer,
|
|
/// 合约部署
|
|
ContractDeploy,
|
|
/// 合约调用
|
|
ContractCall,
|
|
}
|
|
|
|
/// 交易
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Transaction {
|
|
/// 交易哈希
|
|
pub hash: Hash,
|
|
/// 发送方
|
|
pub from: Address,
|
|
/// 接收方
|
|
pub to: Address,
|
|
/// 金额
|
|
pub value: u128,
|
|
/// Nonce
|
|
pub nonce: u64,
|
|
/// Gas限制
|
|
pub gas_limit: u64,
|
|
/// Gas价格
|
|
pub gas_price: u64,
|
|
/// 数据
|
|
pub data: Vec<u8>,
|
|
/// 交易类型
|
|
pub tx_type: TransactionType,
|
|
/// 签名
|
|
pub signature: Signature,
|
|
/// 时间戳
|
|
pub timestamp: u64,
|
|
}
|
|
|
|
impl Transaction {
|
|
/// 创建新交易
|
|
pub fn new(
|
|
from: Address,
|
|
to: Address,
|
|
value: u128,
|
|
nonce: u64,
|
|
gas_limit: u64,
|
|
gas_price: u64,
|
|
data: Vec<u8>,
|
|
tx_type: TransactionType,
|
|
) -> Self {
|
|
let mut tx = Self {
|
|
hash: Hash::zero(),
|
|
from,
|
|
to,
|
|
value,
|
|
nonce,
|
|
gas_limit,
|
|
gas_price,
|
|
data,
|
|
tx_type,
|
|
signature: Signature::empty(),
|
|
timestamp: 0,
|
|
};
|
|
tx.hash = tx.calculate_hash();
|
|
tx
|
|
}
|
|
|
|
/// 计算交易哈希
|
|
pub fn calculate_hash(&self) -> Hash {
|
|
let mut data = Vec::new();
|
|
data.extend_from_slice(self.from.as_bytes());
|
|
data.extend_from_slice(self.to.as_bytes());
|
|
data.extend_from_slice(&self.value.to_le_bytes());
|
|
data.extend_from_slice(&self.nonce.to_le_bytes());
|
|
data.extend_from_slice(&self.gas_limit.to_le_bytes());
|
|
data.extend_from_slice(&self.gas_price.to_le_bytes());
|
|
data.extend_from_slice(&self.data);
|
|
Hash::sha3_384(&data)
|
|
}
|
|
|
|
/// 签名交易
|
|
pub fn sign(&mut self, signature: Signature) {
|
|
self.signature = signature;
|
|
}
|
|
|
|
/// 验证签名
|
|
pub fn verify_signature(&self) -> bool {
|
|
self.signature.verify(self.hash.as_bytes(), &[])
|
|
}
|
|
|
|
/// 计算交易费用
|
|
pub fn calculate_fee(&self) -> u64 {
|
|
self.gas_limit * self.gas_price
|
|
}
|
|
}
|
|
|
|
/// 交易池
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct TransactionPool {
|
|
/// 待处理交易 (hash -> transaction)
|
|
pending: HashMap<Hash, Transaction>,
|
|
/// 已确认交易
|
|
confirmed: HashMap<Hash, Transaction>,
|
|
/// 最大交易数
|
|
max_size: usize,
|
|
}
|
|
|
|
impl TransactionPool {
|
|
/// 创建新交易池
|
|
pub fn new(max_size: usize) -> Self {
|
|
Self {
|
|
pending: HashMap::new(),
|
|
confirmed: HashMap::new(),
|
|
max_size,
|
|
}
|
|
}
|
|
|
|
/// 添加交易
|
|
pub fn add_transaction(&mut self, tx: Transaction) -> Result<(), String> {
|
|
if self.pending.len() >= self.max_size {
|
|
return Err("Transaction pool is full".to_string());
|
|
}
|
|
|
|
if self.pending.contains_key(&tx.hash) || self.confirmed.contains_key(&tx.hash) {
|
|
return Err("Transaction already exists".to_string());
|
|
}
|
|
|
|
if !tx.verify_signature() {
|
|
return Err("Invalid signature".to_string());
|
|
}
|
|
|
|
self.pending.insert(tx.hash, tx);
|
|
Ok(())
|
|
}
|
|
|
|
/// 获取待处理交易
|
|
pub fn get_pending_transactions(&self) -> Vec<Transaction> {
|
|
self.pending.values().cloned().collect()
|
|
}
|
|
|
|
/// 确认交易
|
|
pub fn confirm_transaction(&mut self, hash: &Hash) -> Result<(), String> {
|
|
let tx = self
|
|
.pending
|
|
.remove(hash)
|
|
.ok_or("Transaction not found in pending pool")?;
|
|
self.confirmed.insert(*hash, tx);
|
|
Ok(())
|
|
}
|
|
|
|
/// 移除交易
|
|
pub fn remove_transaction(&mut self, hash: &Hash) {
|
|
self.pending.remove(hash);
|
|
}
|
|
|
|
/// 获取交易
|
|
pub fn get_transaction(&self, hash: &Hash) -> Option<&Transaction> {
|
|
self.pending.get(hash).or_else(|| self.confirmed.get(hash))
|
|
}
|
|
|
|
/// 获取待处理交易数量
|
|
pub fn pending_count(&self) -> usize {
|
|
self.pending.len()
|
|
}
|
|
|
|
/// 获取已确认交易数量
|
|
pub fn confirmed_count(&self) -> usize {
|
|
self.confirmed.len()
|
|
}
|
|
|
|
/// 清理已确认交易
|
|
pub fn clear_confirmed(&mut self) {
|
|
self.confirmed.clear();
|
|
}
|
|
}
|
|
|
|
impl Default for TransactionPool {
|
|
fn default() -> Self {
|
|
Self::new(10000)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
fn create_test_transaction() -> Transaction {
|
|
Transaction::new(
|
|
Address::new([1u8; 32]),
|
|
Address::new([2u8; 32]),
|
|
1000,
|
|
1,
|
|
21000,
|
|
1,
|
|
Vec::new(),
|
|
TransactionType::Transfer,
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn test_transaction_creation() {
|
|
let tx = create_test_transaction();
|
|
assert_eq!(tx.value, 1000);
|
|
assert_eq!(tx.nonce, 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_transaction_hash() {
|
|
let tx = create_test_transaction();
|
|
let hash1 = tx.calculate_hash();
|
|
let hash2 = tx.calculate_hash();
|
|
assert_eq!(hash1, hash2);
|
|
}
|
|
|
|
#[test]
|
|
fn test_transaction_pool_add() {
|
|
let mut pool = TransactionPool::new(100);
|
|
let mut tx = create_test_transaction();
|
|
tx.sign(Signature::new(vec![1, 2, 3]));
|
|
|
|
assert!(pool.add_transaction(tx).is_ok());
|
|
assert_eq!(pool.pending_count(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_transaction_pool_confirm() {
|
|
let mut pool = TransactionPool::new(100);
|
|
let mut tx = create_test_transaction();
|
|
tx.sign(Signature::new(vec![1, 2, 3]));
|
|
let hash = tx.hash;
|
|
|
|
pool.add_transaction(tx).unwrap();
|
|
assert!(pool.confirm_transaction(&hash).is_ok());
|
|
assert_eq!(pool.pending_count(), 0);
|
|
assert_eq!(pool.confirmed_count(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_transaction_pool_full() {
|
|
let mut pool = TransactionPool::new(1);
|
|
let mut tx1 = create_test_transaction();
|
|
tx1.sign(Signature::new(vec![1, 2, 3]));
|
|
|
|
let mut tx2 = create_test_transaction();
|
|
tx2.nonce = 2;
|
|
tx2.hash = tx2.calculate_hash();
|
|
tx2.sign(Signature::new(vec![4, 5, 6]));
|
|
|
|
assert!(pool.add_transaction(tx1).is_ok());
|
|
assert!(pool.add_transaction(tx2).is_err());
|
|
}
|
|
}
|