//! 交易构造模块 //! //! NAC交易包含两部分:交易体 + 宪法收据(CR) use crate::constitutional_receipt::ConstitutionalReceipt; use serde::{Deserialize, Serialize}; use sha3::{Digest, Sha3_256}; /// 交易类型 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[repr(u8)] pub enum TransactionType { /// XTZH转账 XTZHTransfer = 0, /// XIC转账 XICTransfer = 1, /// ACC-20代币转账 ACC20Transfer = 2, /// ACC-1400证券型代币转账 ACC1400Transfer = 3, /// 合约部署 ContractDeploy = 4, /// 合约调用 ContractCall = 5, /// 资产发行 AssetIssuance = 6, } /// 交易载荷(原始交易数据) #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TransactionPayload { /// 交易类型 pub tx_type: TransactionType, /// 发送方地址 pub from: [u8; 32], /// 接收方地址 pub to: [u8; 32], /// 金额(对于XTZH/XIC/ACC-20) pub amount: u64, /// 资产GNACS编码(对于ACC-20/ACC-1400) pub asset_gnacs: Option<[u8; 6]>, /// 分区ID(对于ACC-1400) pub partition_id: Option<[u8; 32]>, /// 附加数据(合约调用参数等) pub data: Vec, /// Nonce(防重放) pub nonce: u64, /// Gas限制 pub gas_limit: u64, /// Gas价格(XIC) pub gas_price: u64, /// 时间戳 pub timestamp: u64, } impl TransactionPayload { /// 创建XTZH转账交易 pub fn new_xtzh_transfer( from: [u8; 32], to: [u8; 32], amount: u64, nonce: u64, ) -> Self { Self { tx_type: TransactionType::XTZHTransfer, from, to, amount, asset_gnacs: None, partition_id: None, data: Vec::new(), nonce, gas_limit: 21000, // 基础转账Gas gas_price: 1, timestamp: Self::current_timestamp(), } } /// 创建XIC转账交易 pub fn new_xic_transfer( from: [u8; 32], to: [u8; 32], amount: u64, nonce: u64, ) -> Self { Self { tx_type: TransactionType::XICTransfer, from, to, amount, asset_gnacs: None, partition_id: None, data: Vec::new(), nonce, gas_limit: 21000, gas_price: 1, timestamp: Self::current_timestamp(), } } /// 创建ACC-20代币转账交易 pub fn new_acc20_transfer( from: [u8; 32], to: [u8; 32], amount: u64, asset_gnacs: [u8; 6], nonce: u64, ) -> Self { Self { tx_type: TransactionType::ACC20Transfer, from, to, amount, asset_gnacs: Some(asset_gnacs), partition_id: None, data: Vec::new(), nonce, gas_limit: 50000, // 代币转账需要更多Gas gas_price: 1, timestamp: Self::current_timestamp(), } } /// 创建ACC-1400证券型代币转账交易 pub fn new_acc1400_transfer( from: [u8; 32], to: [u8; 32], amount: u64, asset_gnacs: [u8; 6], partition_id: [u8; 32], nonce: u64, ) -> Self { Self { tx_type: TransactionType::ACC1400Transfer, from, to, amount, asset_gnacs: Some(asset_gnacs), partition_id: Some(partition_id), data: Vec::new(), nonce, gas_limit: 80000, // 证券型代币需要更多Gas(合规检查) gas_price: 1, timestamp: Self::current_timestamp(), } } /// 计算交易哈希 pub fn hash(&self) -> [u8; 32] { let serialized = bincode::serialize(self).unwrap_or_default(); let mut hasher = Sha3_256::new(); hasher.update(&serialized); let result = hasher.finalize(); let mut hash = [0u8; 32]; hash.copy_from_slice(&result); hash } /// 获取当前时间戳 fn current_timestamp() -> u64 { // TODO: 使用系统时间 0 } /// 估算Gas费用(XIC) pub fn estimate_gas_fee(&self) -> u64 { self.gas_limit * self.gas_price } } /// 完整交易(包含CR) #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Transaction { /// 交易载荷 pub payload: TransactionPayload, /// 宪法收据 pub receipt: Option, /// 签名 pub signature: Vec, } impl Transaction { /// 创建新交易(未签名) pub fn new(payload: TransactionPayload) -> Self { Self { payload, receipt: None, signature: Vec::new(), } } /// 附加宪法收据 pub fn attach_receipt(&mut self, receipt: ConstitutionalReceipt) { self.receipt = Some(receipt); } /// 签名交易 pub fn sign(&mut self, signature: Vec) { self.signature = signature; } /// 计算签名消息(交易体+CR的联合哈希) pub fn signing_message(&self) -> [u8; 32] { let mut hasher = Sha3_256::new(); // 添加交易载荷哈希 hasher.update(&self.payload.hash()); // 如果有CR,添加CR哈希 if let Some(ref receipt) = self.receipt { hasher.update(&receipt.transaction_hash); } let result = hasher.finalize(); let mut hash = [0u8; 32]; hash.copy_from_slice(&result); hash } /// 验证交易完整性 pub fn verify(&self) -> Result<(), String> { // 检查是否有CR if self.receipt.is_none() { return Err("Missing constitutional receipt".to_string()); } // 检查是否已签名 if self.signature.is_empty() { return Err("Transaction not signed".to_string()); } // 验证CR if let Some(ref receipt) = self.receipt { if !receipt.verify() { return Err("Invalid constitutional receipt".to_string()); } // 验证CR的交易哈希是否匹配 if receipt.transaction_hash != self.payload.hash() { return Err("Constitutional receipt hash mismatch".to_string()); } } Ok(()) } /// 序列化为字节(用于广播) pub fn to_bytes(&self) -> Result, String> { bincode::serialize(self).map_err(|e| format!("Serialization error: {}", e)) } /// 从字节反序列化 pub fn from_bytes(bytes: &[u8]) -> Result { bincode::deserialize(bytes).map_err(|e| format!("Deserialization error: {}", e)) } } /// 交易构造器(Builder模式) pub struct TransactionBuilder { tx_type: TransactionType, from: Option<[u8; 32]>, to: Option<[u8; 32]>, amount: u64, asset_gnacs: Option<[u8; 6]>, partition_id: Option<[u8; 32]>, data: Vec, nonce: u64, gas_limit: u64, gas_price: u64, } impl TransactionBuilder { /// 创建新的构造器 pub fn new(tx_type: TransactionType) -> Self { let default_gas = match tx_type { TransactionType::XTZHTransfer | TransactionType::XICTransfer => 21000, TransactionType::ACC20Transfer => 50000, TransactionType::ACC1400Transfer => 80000, TransactionType::ContractDeploy => 200000, TransactionType::ContractCall => 100000, TransactionType::AssetIssuance => 150000, }; Self { tx_type, from: None, to: None, amount: 0, asset_gnacs: None, partition_id: None, data: Vec::new(), nonce: 0, gas_limit: default_gas, gas_price: 1, } } /// 设置发送方 pub fn from(mut self, from: [u8; 32]) -> Self { self.from = Some(from); self } /// 设置接收方 pub fn to(mut self, to: [u8; 32]) -> Self { self.to = Some(to); self } /// 设置金额 pub fn amount(mut self, amount: u64) -> Self { self.amount = amount; self } /// 设置资产GNACS pub fn asset_gnacs(mut self, gnacs: [u8; 6]) -> Self { self.asset_gnacs = Some(gnacs); self } /// 设置分区ID pub fn partition_id(mut self, partition_id: [u8; 32]) -> Self { self.partition_id = Some(partition_id); self } /// 设置附加数据 pub fn data(mut self, data: Vec) -> Self { self.data = data; self } /// 设置nonce pub fn nonce(mut self, nonce: u64) -> Self { self.nonce = nonce; self } /// 设置Gas限制 pub fn gas_limit(mut self, gas_limit: u64) -> Self { self.gas_limit = gas_limit; self } /// 设置Gas价格 pub fn gas_price(mut self, gas_price: u64) -> Self { self.gas_price = gas_price; self } /// 构建交易 pub fn build(self) -> Result { let from = self.from.ok_or("Missing 'from' address")?; let to = self.to.ok_or("Missing 'to' address")?; let payload = TransactionPayload { tx_type: self.tx_type, from, to, amount: self.amount, asset_gnacs: self.asset_gnacs, partition_id: self.partition_id, data: self.data, nonce: self.nonce, gas_limit: self.gas_limit, gas_price: self.gas_price, timestamp: TransactionPayload::current_timestamp(), }; Ok(Transaction::new(payload)) } } #[cfg(test)] mod tests { use super::*; #[test] fn test_xtzh_transfer() { let from = [1u8; 32]; let to = [2u8; 32]; let payload = TransactionPayload::new_xtzh_transfer(from, to, 1000000, 1); assert_eq!(payload.tx_type, TransactionType::XTZHTransfer); assert_eq!(payload.amount, 1000000); assert_eq!(payload.gas_limit, 21000); } #[test] fn test_transaction_builder() { let from = [1u8; 32]; let to = [2u8; 32]; let tx = TransactionBuilder::new(TransactionType::XTZHTransfer) .from(from) .to(to) .amount(1000000) .nonce(1) .build() .unwrap(); assert_eq!(tx.payload.amount, 1000000); } #[test] fn test_transaction_hash() { let from = [1u8; 32]; let to = [2u8; 32]; let payload = TransactionPayload::new_xtzh_transfer(from, to, 1000000, 1); let hash1 = payload.hash(); let hash2 = payload.hash(); assert_eq!(hash1, hash2); // 相同输入应产生相同哈希 } }