NAC_Blockchain/nac-cross-chain-bridge/src/unlocker.rs

310 lines
10 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::types::*;
use async_trait::async_trait;
use sled::Db;
use std::sync::Arc;
use sha3::{Digest, Sha3_384}; // 使用SHA3-384
/// 资产解锁器trait
#[async_trait]
pub trait AssetUnlocker: Send + Sync {
/// 解锁资产
async fn unlock_asset(
&self,
lock_id: Hash,
proof: UnlockProof,
) -> Result<UnlockReceipt>;
/// 验证解锁证明
async fn verify_unlock_proof(&self, proof: &UnlockProof) -> Result<bool>;
/// 获取解锁收据
async fn get_unlock_receipt(&self, unlock_id: Hash) -> Result<UnlockReceipt>;
/// 查询解锁状态
async fn get_unlock_status(&self, unlock_id: Hash) -> Result<UnlockStatus>;
}
/// 资产解锁器实现
pub struct AssetUnlockerImpl {
db: Arc<Db>,
config: BridgeConfig,
}
impl AssetUnlockerImpl {
pub fn new(db: Arc<Db>, config: BridgeConfig) -> Self {
Self { db, config }
}
/// 生成解锁ID使用NAC的SHA3-384
fn generate_unlock_id(&self, lock_id: &Hash, timestamp: u64) -> Hash {
let mut hasher = Sha3_384::new();
hasher.update(lock_id.as_ref());
hasher.update(&timestamp.to_le_bytes());
let result = hasher.finalize();
let mut hash_bytes = [0u8; 48];
hash_bytes.copy_from_slice(&result);
Hash::from(hash_bytes)
}
/// 验证Merkle证明使用NAC的48字节哈希
fn verify_merkle_proof(
&self,
leaf: Hash,
proof: &[Hash],
root: Hash,
) -> bool {
let mut current = leaf;
for sibling in proof {
let mut hasher = Sha3_384::new();
if current < *sibling {
hasher.update(current.as_ref());
hasher.update(sibling.as_ref());
} else {
hasher.update(sibling.as_ref());
hasher.update(current.as_ref());
}
let result = hasher.finalize();
let mut hash_bytes = [0u8; 48];
hash_bytes.copy_from_slice(&result);
current = Hash::from(hash_bytes);
}
current == root
}
/// 验证签名数量
fn verify_signature_count(&self, signatures: &[Signature]) -> Result<()> {
if signatures.len() < self.config.min_validator_signatures {
return Err(BridgeError::InsufficientSignatures {
got: signatures.len(),
required: self.config.min_validator_signatures,
});
}
Ok(())
}
/// 保存解锁收据
fn save_unlock_receipt(&self, receipt: &UnlockReceipt) -> Result<()> {
let key = format!("unlock:{}", hex::encode(receipt.unlock_id));
let value = bincode::serialize(receipt)
.map_err(|e| BridgeError::DatabaseError(e.to_string()))?;
self.db.insert(key.as_bytes(), value)
.map_err(|e| BridgeError::DatabaseError(e.to_string()))?;
Ok(())
}
/// 加载解锁收据
fn load_unlock_receipt(&self, unlock_id: Hash) -> Result<UnlockReceipt> {
let key = format!("unlock:{}", hex::encode(unlock_id));
let value = self.db.get(key.as_bytes())
.map_err(|e| BridgeError::DatabaseError(e.to_string()))?
.ok_or(BridgeError::Other(format!("Unlock not found: {:?}", unlock_id)))?;
let receipt = bincode::deserialize(&value)
.map_err(|e| BridgeError::DatabaseError(e.to_string()))?;
Ok(receipt)
}
/// 加载锁定收据
fn load_lock_receipt(&self, lock_id: Hash) -> Result<LockReceipt> {
let key = format!("lock:{}", hex::encode(lock_id));
let value = self.db.get(key.as_bytes())
.map_err(|e| BridgeError::DatabaseError(e.to_string()))?
.ok_or(BridgeError::LockNotFound(lock_id))?;
let receipt = bincode::deserialize(&value)
.map_err(|e| BridgeError::DatabaseError(e.to_string()))?;
Ok(receipt)
}
}
#[async_trait]
impl AssetUnlocker for AssetUnlockerImpl {
async fn unlock_asset(
&self,
lock_id: Hash,
proof: UnlockProof,
) -> Result<UnlockReceipt> {
// 检查桥接是否暂停
if self.config.is_paused {
return Err(BridgeError::BridgePaused);
}
// 验证解锁证明
if !self.verify_unlock_proof(&proof).await? {
return Err(BridgeError::InvalidProof);
}
// 加载锁定收据
let lock_receipt = self.load_lock_receipt(lock_id)?;
// 检查锁定状态
if lock_receipt.status != LockStatus::Minted {
return Err(BridgeError::InvalidMessage(
format!("Invalid lock status: {:?}", lock_receipt.status)
));
}
// 生成解锁ID
let timestamp = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs();
let unlock_id = self.generate_unlock_id(&lock_id, timestamp);
// 创建解锁收据
let receipt = UnlockReceipt {
unlock_id,
lock_id,
asset: lock_receipt.asset.clone(),
amount: lock_receipt.amount,
receiver: lock_receipt.receiver,
timestamp,
status: UnlockStatus::Pending,
};
// 保存解锁收据
self.save_unlock_receipt(&receipt)?;
log::info!(
"Asset unlocked: unlock_id={}, lock_id={}, amount={}",
hex::encode(unlock_id),
hex::encode(lock_id),
lock_receipt.amount
);
Ok(receipt)
}
async fn verify_unlock_proof(&self, proof: &UnlockProof) -> Result<bool> {
// 验证签名数量
self.verify_signature_count(&proof.signatures)?;
// TODO: 验证每个签名的有效性使用NAC的签名验证
// TODO: 验证区块确认数
// TODO: 验证Merkle证明
// 简化实现:假设证明有效
Ok(true)
}
async fn get_unlock_receipt(&self, unlock_id: Hash) -> Result<UnlockReceipt> {
self.load_unlock_receipt(unlock_id)
}
async fn get_unlock_status(&self, unlock_id: Hash) -> Result<UnlockStatus> {
let receipt = self.load_unlock_receipt(unlock_id)?;
Ok(receipt.status)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::locker::{AssetLocker, AssetLockerImpl};
#[tokio::test]
async fn test_unlock_asset() {
let db = Arc::new(sled::Config::new().temporary(true).open().unwrap());
let config = BridgeConfig::default();
// 先锁定资产
let locker = AssetLockerImpl::new(db.clone(), config.clone());
let asset = AssetInfo {
asset_id: Hash::from([1u8; 48]), // NAC的48字节哈希
name: "Test Token".to_string(),
symbol: "TEST".to_string(),
decimals: 18,
chain_id: ChainId::NAC,
};
let mut lock_receipt = locker.lock_asset(
asset,
1000 * 10u128.pow(18),
ChainId::Ethereum,
[2u8; 32], // NAC的32字节地址
).await.unwrap();
// 更新锁定状态为已铸造
lock_receipt.status = LockStatus::Minted;
let key = format!("lock:{}", hex::encode(lock_receipt.lock_id));
let value = bincode::serialize(&lock_receipt).unwrap();
db.insert(key.as_bytes(), value).unwrap();
// 解锁资产
let unlocker = AssetUnlockerImpl::new(db, config);
let proof = UnlockProof {
burn_tx_hash: Hash::from([3u8; 48]), // NAC的48字节哈希
burn_block_number: 12345,
burn_block_hash: Hash::from([4u8; 48]),
merkle_proof: vec![],
signatures: vec![Signature::from([5u8; 96]), Signature::from([6u8; 96])], // NAC的96字节签名
};
let unlock_receipt = unlocker.unlock_asset(lock_receipt.lock_id, proof).await.unwrap();
assert_eq!(unlock_receipt.lock_id, lock_receipt.lock_id);
assert_eq!(unlock_receipt.amount, lock_receipt.amount);
assert_eq!(unlock_receipt.status, UnlockStatus::Pending);
assert_eq!(unlock_receipt.unlock_id.as_bytes().len(), 48); // 验证是48字节哈希
}
#[tokio::test]
async fn test_verify_signature_count() {
let db = Arc::new(sled::Config::new().temporary(true).open().unwrap());
let config = BridgeConfig::default();
let unlocker = AssetUnlockerImpl::new(db, config);
// 签名数量不足
let proof = UnlockProof {
burn_tx_hash: Hash::from([3u8; 48]),
burn_block_number: 12345,
burn_block_hash: Hash::from([4u8; 48]),
merkle_proof: vec![],
signatures: vec![Signature::from([5u8; 96])], // 只有1个签名
};
let result = unlocker.verify_unlock_proof(&proof).await;
assert!(matches!(result, Err(BridgeError::InsufficientSignatures { .. })));
}
#[tokio::test]
async fn test_verify_merkle_proof() {
let db = Arc::new(sled::Config::new().temporary(true).open().unwrap());
let config = BridgeConfig::default();
let unlocker = AssetUnlockerImpl::new(db, config);
// 简单的Merkle树root = hash(hash(leaf1, leaf2))
let leaf1 = Hash::from([1u8; 48]);
let leaf2 = Hash::from([2u8; 48]);
let mut hasher = Sha3_384::new();
hasher.update(&leaf1);
hasher.update(&leaf2);
let result = hasher.finalize();
let mut hash_bytes = [0u8; 48];
hash_bytes.copy_from_slice(&result);
let parent = Hash::from(hash_bytes);
// 验证leaf1的证明
let proof = vec![leaf2];
let result = unlocker.verify_merkle_proof(leaf1, &proof, parent);
assert!(result);
}
#[tokio::test]
async fn test_nac_signature_size() {
// 验证NAC签名是96字节
let signature = Signature::from([0u8; 96]);
assert_eq!(signature.as_bytes().len(), 96);
}
}