620 lines
17 KiB
Rust
620 lines
17 KiB
Rust
// Enhanced Cross-Chain Bridge
|
||
// 跨链资产桥接增强 - 基于ACC-CrossChain扩展
|
||
|
||
use serde::{Deserialize, Serialize};
|
||
use std::collections::HashMap;
|
||
|
||
use super::crosschain_message::{ChainId, CrossChainMessage, MessageType};
|
||
|
||
/// 桥接资产类型
|
||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||
pub enum BridgeAssetType {
|
||
/// 原生代币
|
||
NativeToken,
|
||
/// 资产TOKEN
|
||
AssetToken,
|
||
/// 权益代币
|
||
EquityToken,
|
||
/// NFT
|
||
NFT,
|
||
}
|
||
|
||
/// 桥接操作类型
|
||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||
pub enum BridgeOperation {
|
||
/// 锁定(源链)
|
||
Lock,
|
||
/// 铸造(目标链)
|
||
Mint,
|
||
/// 销毁(目标链)
|
||
Burn,
|
||
/// 解锁(源链)
|
||
Unlock,
|
||
}
|
||
|
||
/// 桥接状态
|
||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||
pub enum BridgeStatus {
|
||
/// 初始化
|
||
Initialized,
|
||
/// 已锁定
|
||
Locked,
|
||
/// 已铸造
|
||
Minted,
|
||
/// 已销毁
|
||
Burned,
|
||
/// 已解锁
|
||
Unlocked,
|
||
/// 失败
|
||
Failed,
|
||
}
|
||
|
||
/// 桥接交易
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct BridgeTransaction {
|
||
/// 交易ID
|
||
pub tx_id: String,
|
||
/// 源链
|
||
pub source_chain: ChainId,
|
||
/// 目标链
|
||
pub target_chain: ChainId,
|
||
/// 资产类型
|
||
pub asset_type: BridgeAssetType,
|
||
/// 资产ID(对于TOKEN/NFT)
|
||
pub asset_id: String,
|
||
/// 数量(18位小数)
|
||
pub amount: u128,
|
||
/// 发送者
|
||
pub sender: String,
|
||
/// 接收者
|
||
pub receiver: String,
|
||
/// 桥接状态
|
||
pub status: BridgeStatus,
|
||
/// 锁定交易哈希
|
||
pub lock_tx_hash: Option<String>,
|
||
/// 铸造交易哈希
|
||
pub mint_tx_hash: Option<String>,
|
||
/// 销毁交易哈希
|
||
pub burn_tx_hash: Option<String>,
|
||
/// 解锁交易哈希
|
||
pub unlock_tx_hash: Option<String>,
|
||
/// 创建时间
|
||
pub created_at: u64,
|
||
/// 完成时间
|
||
pub completed_at: Option<u64>,
|
||
/// 手续费
|
||
pub fee: u128,
|
||
}
|
||
|
||
impl BridgeTransaction {
|
||
pub fn new(
|
||
tx_id: String,
|
||
source_chain: ChainId,
|
||
target_chain: ChainId,
|
||
asset_type: BridgeAssetType,
|
||
asset_id: String,
|
||
amount: u128,
|
||
sender: String,
|
||
receiver: String,
|
||
fee: u128,
|
||
) -> Self {
|
||
let now = std::time::SystemTime::now()
|
||
.duration_since(std::time::UNIX_EPOCH)
|
||
.unwrap()
|
||
.as_secs();
|
||
|
||
Self {
|
||
tx_id,
|
||
source_chain,
|
||
target_chain,
|
||
asset_type,
|
||
asset_id,
|
||
amount,
|
||
sender,
|
||
receiver,
|
||
status: BridgeStatus::Initialized,
|
||
lock_tx_hash: None,
|
||
mint_tx_hash: None,
|
||
burn_tx_hash: None,
|
||
unlock_tx_hash: None,
|
||
created_at: now,
|
||
completed_at: None,
|
||
fee,
|
||
}
|
||
}
|
||
|
||
/// 标记为已锁定
|
||
pub fn mark_locked(&mut self, tx_hash: String) {
|
||
self.status = BridgeStatus::Locked;
|
||
self.lock_tx_hash = Some(tx_hash);
|
||
}
|
||
|
||
/// 标记为已铸造
|
||
pub fn mark_minted(&mut self, tx_hash: String) {
|
||
self.status = BridgeStatus::Minted;
|
||
self.mint_tx_hash = Some(tx_hash);
|
||
self.completed_at = Some(
|
||
std::time::SystemTime::now()
|
||
.duration_since(std::time::UNIX_EPOCH)
|
||
.unwrap()
|
||
.as_secs(),
|
||
);
|
||
}
|
||
|
||
/// 标记为已销毁
|
||
pub fn mark_burned(&mut self, tx_hash: String) {
|
||
self.status = BridgeStatus::Burned;
|
||
self.burn_tx_hash = Some(tx_hash);
|
||
}
|
||
|
||
/// 标记为已解锁
|
||
pub fn mark_unlocked(&mut self, tx_hash: String) {
|
||
self.status = BridgeStatus::Unlocked;
|
||
self.unlock_tx_hash = Some(tx_hash);
|
||
self.completed_at = Some(
|
||
std::time::SystemTime::now()
|
||
.duration_since(std::time::UNIX_EPOCH)
|
||
.unwrap()
|
||
.as_secs(),
|
||
);
|
||
}
|
||
|
||
/// 标记为失败
|
||
pub fn mark_failed(&mut self) {
|
||
self.status = BridgeStatus::Failed;
|
||
self.completed_at = Some(
|
||
std::time::SystemTime::now()
|
||
.duration_since(std::time::UNIX_EPOCH)
|
||
.unwrap()
|
||
.as_secs(),
|
||
);
|
||
}
|
||
}
|
||
|
||
/// 流动性池
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct LiquidityPool {
|
||
/// 池ID
|
||
pub pool_id: String,
|
||
/// 链ID
|
||
pub chain_id: ChainId,
|
||
/// 资产ID
|
||
pub asset_id: String,
|
||
/// 总流动性
|
||
pub total_liquidity: u128,
|
||
/// 已锁定金额
|
||
pub locked_amount: u128,
|
||
/// 可用金额
|
||
pub available_amount: u128,
|
||
}
|
||
|
||
impl LiquidityPool {
|
||
pub fn new(pool_id: String, chain_id: ChainId, asset_id: String, initial_liquidity: u128) -> Self {
|
||
Self {
|
||
pool_id,
|
||
chain_id,
|
||
asset_id,
|
||
total_liquidity: initial_liquidity,
|
||
locked_amount: 0,
|
||
available_amount: initial_liquidity,
|
||
}
|
||
}
|
||
|
||
/// 锁定流动性
|
||
pub fn lock(&mut self, amount: u128) -> Result<(), String> {
|
||
if amount > self.available_amount {
|
||
return Err("Insufficient liquidity".to_string());
|
||
}
|
||
|
||
self.locked_amount += amount;
|
||
self.available_amount -= amount;
|
||
Ok(())
|
||
}
|
||
|
||
/// 解锁流动性
|
||
pub fn unlock(&mut self, amount: u128) -> Result<(), String> {
|
||
if amount > self.locked_amount {
|
||
return Err("Insufficient locked amount".to_string());
|
||
}
|
||
|
||
self.locked_amount -= amount;
|
||
self.available_amount += amount;
|
||
Ok(())
|
||
}
|
||
|
||
/// 添加流动性
|
||
pub fn add_liquidity(&mut self, amount: u128) {
|
||
self.total_liquidity += amount;
|
||
self.available_amount += amount;
|
||
}
|
||
|
||
/// 移除流动性
|
||
pub fn remove_liquidity(&mut self, amount: u128) -> Result<(), String> {
|
||
if amount > self.available_amount {
|
||
return Err("Insufficient available liquidity".to_string());
|
||
}
|
||
|
||
self.total_liquidity -= amount;
|
||
self.available_amount -= amount;
|
||
Ok(())
|
||
}
|
||
}
|
||
|
||
/// 增强型跨链桥接系统
|
||
pub struct EnhancedCrossChainBridge {
|
||
/// 桥接交易 (tx_id -> BridgeTransaction)
|
||
transactions: HashMap<String, BridgeTransaction>,
|
||
/// 流动性池 (chain_id, asset_id) -> LiquidityPool
|
||
liquidity_pools: HashMap<(ChainId, String), LiquidityPool>,
|
||
/// 支持的资产 (chain_id -> Vec<asset_id>)
|
||
supported_assets: HashMap<ChainId, Vec<String>>,
|
||
/// 手续费率(基点,1基点=0.01%)
|
||
fee_rate: u16,
|
||
/// 最小桥接金额
|
||
min_bridge_amount: u128,
|
||
/// 最大桥接金额
|
||
max_bridge_amount: u128,
|
||
/// 统计信息
|
||
stats: BridgeStats,
|
||
}
|
||
|
||
/// 桥接统计
|
||
#[derive(Debug, Clone, Default)]
|
||
pub struct BridgeStats {
|
||
/// 总交易数
|
||
pub total_transactions: u64,
|
||
/// 成功交易数
|
||
pub successful_transactions: u64,
|
||
/// 失败交易数
|
||
pub failed_transactions: u64,
|
||
/// 总桥接金额
|
||
pub total_volume: u128,
|
||
/// 总手续费
|
||
pub total_fees: u128,
|
||
}
|
||
|
||
impl EnhancedCrossChainBridge {
|
||
/// 创建新的桥接系统
|
||
pub fn new(fee_rate: u16, min_amount: u128, max_amount: u128) -> Self {
|
||
Self {
|
||
transactions: HashMap::new(),
|
||
liquidity_pools: HashMap::new(),
|
||
supported_assets: HashMap::new(),
|
||
fee_rate,
|
||
min_bridge_amount: min_amount,
|
||
max_bridge_amount: max_amount,
|
||
stats: BridgeStats::default(),
|
||
}
|
||
}
|
||
|
||
/// 添加支持的资产
|
||
pub fn add_supported_asset(&mut self, chain_id: ChainId, asset_id: String) {
|
||
self.supported_assets
|
||
.entry(chain_id)
|
||
.or_insert_with(Vec::new)
|
||
.push(asset_id);
|
||
}
|
||
|
||
/// 创建流动性池
|
||
pub fn create_liquidity_pool(
|
||
&mut self,
|
||
chain_id: ChainId,
|
||
asset_id: String,
|
||
initial_liquidity: u128,
|
||
) -> Result<String, String> {
|
||
let pool_id = format!("pool_{}_{}", chain_id.0, asset_id);
|
||
|
||
if self.liquidity_pools.contains_key(&(chain_id.clone(), asset_id.clone())) {
|
||
return Err("Pool already exists".to_string());
|
||
}
|
||
|
||
let pool = LiquidityPool::new(pool_id.clone(), chain_id.clone(), asset_id.clone(), initial_liquidity);
|
||
self.liquidity_pools.insert((chain_id, asset_id), pool);
|
||
|
||
Ok(pool_id)
|
||
}
|
||
|
||
/// 初始化桥接交易
|
||
pub fn initiate_bridge(
|
||
&mut self,
|
||
source_chain: ChainId,
|
||
target_chain: ChainId,
|
||
asset_type: BridgeAssetType,
|
||
asset_id: String,
|
||
amount: u128,
|
||
sender: String,
|
||
receiver: String,
|
||
) -> Result<String, String> {
|
||
// 验证金额范围
|
||
if amount < self.min_bridge_amount {
|
||
return Err(format!("Amount below minimum: {}", self.min_bridge_amount));
|
||
}
|
||
if amount > self.max_bridge_amount {
|
||
return Err(format!("Amount exceeds maximum: {}", self.max_bridge_amount));
|
||
}
|
||
|
||
// 验证资产支持
|
||
if let Some(assets) = self.supported_assets.get(&source_chain) {
|
||
if !assets.contains(&asset_id) {
|
||
return Err("Asset not supported on source chain".to_string());
|
||
}
|
||
} else {
|
||
return Err("Source chain not supported".to_string());
|
||
}
|
||
|
||
// 计算手续费
|
||
let fee = (amount * self.fee_rate as u128) / 10000;
|
||
|
||
let now = std::time::SystemTime::now()
|
||
.duration_since(std::time::UNIX_EPOCH)
|
||
.unwrap()
|
||
.as_secs();
|
||
|
||
let tx_id = format!("bridge_{}_{}", source_chain.0, now);
|
||
|
||
let transaction = BridgeTransaction::new(
|
||
tx_id.clone(),
|
||
source_chain,
|
||
target_chain,
|
||
asset_type,
|
||
asset_id,
|
||
amount,
|
||
sender,
|
||
receiver,
|
||
fee,
|
||
);
|
||
|
||
self.transactions.insert(tx_id.clone(), transaction);
|
||
self.stats.total_transactions += 1;
|
||
|
||
Ok(tx_id)
|
||
}
|
||
|
||
/// 执行锁定操作
|
||
pub fn execute_lock(&mut self, tx_id: &str, lock_tx_hash: String) -> Result<(), String> {
|
||
let tx = self.transactions.get_mut(tx_id)
|
||
.ok_or("Transaction not found")?;
|
||
|
||
if tx.status != BridgeStatus::Initialized {
|
||
return Err(format!("Invalid status: {:?}", tx.status));
|
||
}
|
||
|
||
// 锁定流动性池
|
||
if let Some(pool) = self.liquidity_pools.get_mut(&(tx.source_chain.clone(), tx.asset_id.clone())) {
|
||
pool.lock(tx.amount)?;
|
||
}
|
||
|
||
tx.mark_locked(lock_tx_hash);
|
||
Ok(())
|
||
}
|
||
|
||
/// 执行铸造操作
|
||
pub fn execute_mint(&mut self, tx_id: &str, mint_tx_hash: String) -> Result<(), String> {
|
||
let tx = self.transactions.get_mut(tx_id)
|
||
.ok_or("Transaction not found")?;
|
||
|
||
if tx.status != BridgeStatus::Locked {
|
||
return Err(format!("Invalid status: {:?}", tx.status));
|
||
}
|
||
|
||
tx.mark_minted(mint_tx_hash);
|
||
self.stats.successful_transactions += 1;
|
||
self.stats.total_volume += tx.amount;
|
||
self.stats.total_fees += tx.fee;
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 执行销毁操作(反向桥接)
|
||
pub fn execute_burn(&mut self, tx_id: &str, burn_tx_hash: String) -> Result<(), String> {
|
||
let tx = self.transactions.get_mut(tx_id)
|
||
.ok_or("Transaction not found")?;
|
||
|
||
if tx.status != BridgeStatus::Initialized {
|
||
return Err(format!("Invalid status: {:?}", tx.status));
|
||
}
|
||
|
||
tx.mark_burned(burn_tx_hash);
|
||
Ok(())
|
||
}
|
||
|
||
/// 执行解锁操作(反向桥接)
|
||
pub fn execute_unlock(&mut self, tx_id: &str, unlock_tx_hash: String) -> Result<(), String> {
|
||
let tx = self.transactions.get_mut(tx_id)
|
||
.ok_or("Transaction not found")?;
|
||
|
||
if tx.status != BridgeStatus::Burned {
|
||
return Err(format!("Invalid status: {:?}", tx.status));
|
||
}
|
||
|
||
// 解锁流动性池
|
||
if let Some(pool) = self.liquidity_pools.get_mut(&(tx.target_chain.clone(), tx.asset_id.clone())) {
|
||
pool.unlock(tx.amount)?;
|
||
}
|
||
|
||
tx.mark_unlocked(unlock_tx_hash);
|
||
self.stats.successful_transactions += 1;
|
||
self.stats.total_volume += tx.amount;
|
||
self.stats.total_fees += tx.fee;
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 标记交易失败
|
||
pub fn mark_transaction_failed(&mut self, tx_id: &str) -> Result<(), String> {
|
||
let tx = self.transactions.get_mut(tx_id)
|
||
.ok_or("Transaction not found")?;
|
||
|
||
// 如果已锁定,需要解锁
|
||
if tx.status == BridgeStatus::Locked {
|
||
if let Some(pool) = self.liquidity_pools.get_mut(&(tx.source_chain.clone(), tx.asset_id.clone())) {
|
||
pool.unlock(tx.amount)?;
|
||
}
|
||
}
|
||
|
||
tx.mark_failed();
|
||
self.stats.failed_transactions += 1;
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 获取交易
|
||
pub fn get_transaction(&self, tx_id: &str) -> Option<&BridgeTransaction> {
|
||
self.transactions.get(tx_id)
|
||
}
|
||
|
||
/// 获取流动性池
|
||
pub fn get_liquidity_pool(&self, chain_id: &ChainId, asset_id: &str) -> Option<&LiquidityPool> {
|
||
self.liquidity_pools.get(&(chain_id.clone(), asset_id.to_string()))
|
||
}
|
||
|
||
/// 添加流动性
|
||
pub fn add_liquidity(
|
||
&mut self,
|
||
chain_id: &ChainId,
|
||
asset_id: &str,
|
||
amount: u128,
|
||
) -> Result<(), String> {
|
||
let pool = self.liquidity_pools.get_mut(&(chain_id.clone(), asset_id.to_string()))
|
||
.ok_or("Pool not found")?;
|
||
|
||
pool.add_liquidity(amount);
|
||
Ok(())
|
||
}
|
||
|
||
/// 获取统计信息
|
||
pub fn get_stats(&self) -> &BridgeStats {
|
||
&self.stats
|
||
}
|
||
}
|
||
|
||
impl Default for EnhancedCrossChainBridge {
|
||
fn default() -> Self {
|
||
Self::new(
|
||
30, // 0.3% 手续费
|
||
1_000_000_000_000_000_000, // 最小1个TOKEN
|
||
1_000_000_000_000_000_000_000, // 最大1000个TOKEN
|
||
)
|
||
}
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[test]
|
||
fn test_bridge_creation() {
|
||
let bridge = EnhancedCrossChainBridge::default();
|
||
assert_eq!(bridge.fee_rate, 30);
|
||
}
|
||
|
||
#[test]
|
||
fn test_add_supported_asset() {
|
||
let mut bridge = EnhancedCrossChainBridge::default();
|
||
bridge.add_supported_asset(ChainId::nac(), "XTZH".to_string());
|
||
|
||
assert!(bridge.supported_assets.contains_key(&ChainId::nac()));
|
||
}
|
||
|
||
#[test]
|
||
fn test_create_liquidity_pool() {
|
||
let mut bridge = EnhancedCrossChainBridge::default();
|
||
|
||
let pool_id = bridge.create_liquidity_pool(
|
||
ChainId::nac(),
|
||
"XTZH".to_string(),
|
||
1000_000_000_000_000_000_000,
|
||
).unwrap();
|
||
|
||
assert!(pool_id.starts_with("pool_"));
|
||
assert!(bridge.get_liquidity_pool(&ChainId::nac(), "XTZH").is_some());
|
||
}
|
||
|
||
#[test]
|
||
fn test_initiate_bridge() {
|
||
let mut bridge = EnhancedCrossChainBridge::default();
|
||
let eth_chain = ChainId::new("ETH".to_string());
|
||
|
||
bridge.add_supported_asset(ChainId::nac(), "XTZH".to_string());
|
||
|
||
let tx_id = bridge.initiate_bridge(
|
||
ChainId::nac(),
|
||
eth_chain,
|
||
BridgeAssetType::NativeToken,
|
||
"XTZH".to_string(),
|
||
100_000_000_000_000_000_000,
|
||
"sender".to_string(),
|
||
"receiver".to_string(),
|
||
).unwrap();
|
||
|
||
assert!(bridge.get_transaction(&tx_id).is_some());
|
||
assert_eq!(bridge.stats.total_transactions, 1);
|
||
}
|
||
|
||
#[test]
|
||
fn test_bridge_lifecycle() {
|
||
let mut bridge = EnhancedCrossChainBridge::default();
|
||
let eth_chain = ChainId::new("ETH".to_string());
|
||
|
||
bridge.add_supported_asset(ChainId::nac(), "XTZH".to_string());
|
||
bridge.create_liquidity_pool(ChainId::nac(), "XTZH".to_string(), 1000_000_000_000_000_000_000).unwrap();
|
||
|
||
let tx_id = bridge.initiate_bridge(
|
||
ChainId::nac(),
|
||
eth_chain,
|
||
BridgeAssetType::NativeToken,
|
||
"XTZH".to_string(),
|
||
100_000_000_000_000_000_000,
|
||
"sender".to_string(),
|
||
"receiver".to_string(),
|
||
).unwrap();
|
||
|
||
// 锁定
|
||
bridge.execute_lock(&tx_id, "lock_hash".to_string()).unwrap();
|
||
assert_eq!(bridge.get_transaction(&tx_id).unwrap().status, BridgeStatus::Locked);
|
||
|
||
// 铸造
|
||
bridge.execute_mint(&tx_id, "mint_hash".to_string()).unwrap();
|
||
assert_eq!(bridge.get_transaction(&tx_id).unwrap().status, BridgeStatus::Minted);
|
||
assert_eq!(bridge.stats.successful_transactions, 1);
|
||
}
|
||
|
||
#[test]
|
||
fn test_liquidity_pool_operations() {
|
||
let mut pool = LiquidityPool::new(
|
||
"pool1".to_string(),
|
||
ChainId::nac(),
|
||
"XTZH".to_string(),
|
||
1000,
|
||
);
|
||
|
||
// 锁定
|
||
pool.lock(300).unwrap();
|
||
assert_eq!(pool.locked_amount, 300);
|
||
assert_eq!(pool.available_amount, 700);
|
||
|
||
// 解锁
|
||
pool.unlock(100).unwrap();
|
||
assert_eq!(pool.locked_amount, 200);
|
||
assert_eq!(pool.available_amount, 800);
|
||
|
||
// 添加流动性
|
||
pool.add_liquidity(500);
|
||
assert_eq!(pool.total_liquidity, 1500);
|
||
assert_eq!(pool.available_amount, 1300);
|
||
}
|
||
|
||
#[test]
|
||
fn test_insufficient_liquidity() {
|
||
let mut pool = LiquidityPool::new(
|
||
"pool1".to_string(),
|
||
ChainId::nac(),
|
||
"XTZH".to_string(),
|
||
100,
|
||
);
|
||
|
||
let result = pool.lock(200);
|
||
assert!(result.is_err());
|
||
}
|
||
}
|