NAC_Blockchain/nac-bridge-ethereum/src/lock_unlock.rs

310 lines
8.4 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! 资产锁定/解锁模块
use crate::error::{BridgeError, BridgeResult};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
/// 锁定记录
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LockRecord {
/// 锁定ID
pub lock_id: String,
/// 以太坊交易哈希
pub eth_tx_hash: String,
/// 锁定金额
pub amount: u128,
/// Token地址None表示ETH
pub token_address: Option<String>,
/// NAC目标地址
pub nac_target_address: [u8; 32],
/// 锁定时间戳
pub locked_at: u64,
/// 状态
pub status: LockStatus,
/// 签名列表(多签)
pub signatures: Vec<Signature>,
}
/// 锁定状态
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum LockStatus {
/// 待确认
Pending,
/// 已确认
Confirmed,
/// 已解锁
Unlocked,
/// 已取消
Cancelled,
}
/// 签名
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Signature {
/// 签名者地址
pub signer: String,
/// 签名数据
pub signature: Vec<u8>,
/// 签名时间
pub signed_at: u64,
}
/// 解锁请求
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UnlockRequest {
/// 解锁ID
pub unlock_id: String,
/// NAC交易哈希
pub nac_tx_hash: String,
/// 解锁金额
pub amount: u128,
/// Token地址None表示ETH
pub token_address: Option<String>,
/// 以太坊目标地址
pub eth_target_address: String,
/// 请求时间戳
pub requested_at: u64,
/// 状态
pub status: UnlockStatus,
/// 签名列表(多签)
pub signatures: Vec<Signature>,
}
/// 解锁状态
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum UnlockStatus {
/// 待审批
PendingApproval,
/// 已批准
Approved,
/// 已执行
Executed,
/// 已拒绝
Rejected,
}
/// 锁定/解锁管理器
pub struct LockUnlockManager {
/// 锁定记录
locks: HashMap<String, LockRecord>,
/// 解锁请求
unlocks: HashMap<String, UnlockRequest>,
/// 多签阈值
multisig_threshold: usize,
/// 授权签名者列表
authorized_signers: Vec<String>,
}
impl LockUnlockManager {
/// 创建新的管理器
pub fn new(multisig_threshold: usize, authorized_signers: Vec<String>) -> Self {
Self {
locks: HashMap::new(),
unlocks: HashMap::new(),
multisig_threshold,
authorized_signers,
}
}
/// 记录锁定
pub fn record_lock(&mut self, lock: LockRecord) -> BridgeResult<()> {
if self.locks.contains_key(&lock.lock_id) {
return Err(BridgeError::ValidationError(
"Lock ID already exists".to_string()
));
}
self.locks.insert(lock.lock_id.clone(), lock);
Ok(())
}
/// 获取锁定记录
pub fn get_lock(&self, lock_id: &str) -> Option<&LockRecord> {
self.locks.get(lock_id)
}
/// 添加锁定签名
pub fn add_lock_signature(
&mut self,
lock_id: &str,
signature: Signature,
) -> BridgeResult<()> {
// 验证签名者
if !self.authorized_signers.contains(&signature.signer) {
return Err(BridgeError::SecurityError(
"Unauthorized signer".to_string()
));
}
let lock = self.locks.get_mut(lock_id)
.ok_or_else(|| BridgeError::ValidationError("Lock not found".to_string()))?;
// 检查是否已签名
if lock.signatures.iter().any(|s| s.signer == signature.signer) {
return Err(BridgeError::ValidationError(
"Signer already signed".to_string()
));
}
lock.signatures.push(signature);
// 检查是否达到阈值
if lock.signatures.len() >= self.multisig_threshold {
lock.status = LockStatus::Confirmed;
}
Ok(())
}
/// 记录解锁请求
pub fn record_unlock(&mut self, unlock: UnlockRequest) -> BridgeResult<()> {
if self.unlocks.contains_key(&unlock.unlock_id) {
return Err(BridgeError::ValidationError(
"Unlock ID already exists".to_string()
));
}
self.unlocks.insert(unlock.unlock_id.clone(), unlock);
Ok(())
}
/// 获取解锁请求
pub fn get_unlock(&self, unlock_id: &str) -> Option<&UnlockRequest> {
self.unlocks.get(unlock_id)
}
/// 添加解锁签名
pub fn add_unlock_signature(
&mut self,
unlock_id: &str,
signature: Signature,
) -> BridgeResult<()> {
// 验证签名者
if !self.authorized_signers.contains(&signature.signer) {
return Err(BridgeError::SecurityError(
"Unauthorized signer".to_string()
));
}
let unlock = self.unlocks.get_mut(unlock_id)
.ok_or_else(|| BridgeError::ValidationError("Unlock not found".to_string()))?;
// 检查是否已签名
if unlock.signatures.iter().any(|s| s.signer == signature.signer) {
return Err(BridgeError::ValidationError(
"Signer already signed".to_string()
));
}
unlock.signatures.push(signature);
// 检查是否达到阈值
if unlock.signatures.len() >= self.multisig_threshold {
unlock.status = UnlockStatus::Approved;
}
Ok(())
}
/// 执行解锁
pub fn execute_unlock(&mut self, unlock_id: &str) -> BridgeResult<()> {
let unlock = self.unlocks.get_mut(unlock_id)
.ok_or_else(|| BridgeError::ValidationError("Unlock not found".to_string()))?;
if unlock.status != UnlockStatus::Approved {
return Err(BridgeError::ValidationError(
"Unlock not approved".to_string()
));
}
unlock.status = UnlockStatus::Executed;
Ok(())
}
/// 获取所有待确认的锁定
pub fn get_pending_locks(&self) -> Vec<&LockRecord> {
self.locks.values()
.filter(|lock| lock.status == LockStatus::Pending)
.collect()
}
/// 获取所有待审批的解锁
pub fn get_pending_unlocks(&self) -> Vec<&UnlockRequest> {
self.unlocks.values()
.filter(|unlock| unlock.status == UnlockStatus::PendingApproval)
.collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_lock_unlock_manager() {
let signers = vec!["signer1".to_string(), "signer2".to_string()];
let mut manager = LockUnlockManager::new(2, signers);
// 测试锁定
let lock = LockRecord {
lock_id: "lock1".to_string(),
eth_tx_hash: "0x123".to_string(),
amount: 1000,
token_address: None,
nac_target_address: [0u8; 32],
locked_at: 1234567890,
status: LockStatus::Pending,
signatures: vec![],
};
assert!(manager.record_lock(lock).is_ok());
assert!(manager.get_lock("lock1").is_some());
// 测试签名
let sig1 = Signature {
signer: "signer1".to_string(),
signature: vec![1, 2, 3],
signed_at: 1234567891,
};
assert!(manager.add_lock_signature("lock1", sig1).is_ok());
assert_eq!(manager.get_lock("lock1").unwrap().signatures.len(), 1);
let sig2 = Signature {
signer: "signer2".to_string(),
signature: vec![4, 5, 6],
signed_at: 1234567892,
};
assert!(manager.add_lock_signature("lock1", sig2).is_ok());
assert_eq!(manager.get_lock("lock1").unwrap().status, LockStatus::Confirmed);
}
#[test]
fn test_unauthorized_signer() {
let signers = vec!["signer1".to_string()];
let mut manager = LockUnlockManager::new(1, signers);
let lock = LockRecord {
lock_id: "lock1".to_string(),
eth_tx_hash: "0x123".to_string(),
amount: 1000,
token_address: None,
nac_target_address: [0u8; 32],
locked_at: 1234567890,
status: LockStatus::Pending,
signatures: vec![],
};
manager.record_lock(lock).unwrap();
let sig = Signature {
signer: "unauthorized".to_string(),
signature: vec![1, 2, 3],
signed_at: 1234567891,
};
assert!(manager.add_lock_signature("lock1", sig).is_err());
}
}