310 lines
10 KiB
Rust
310 lines
10 KiB
Rust
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(×tamp.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);
|
||
}
|
||
}
|