NAC_Blockchain/nac-cross-chain-bridge/src/bin/relay.rs

247 lines
7.2 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 nac_cross_chain_bridge::{
init_logger,
manager::{BridgeManager, BridgeManagerImpl},
eth_listener::EthereumListener,
ChainId,
VERSION,
};
use std::sync::Arc;
use tokio::signal;
/// 中继节点配置
#[derive(Debug, Clone)]
struct RelayConfig {
/// 数据库路径
db_path: String,
/// NAC RPC URL
nac_rpc_url: String,
/// 以太坊 RPC URL
eth_rpc_url: String,
/// BSC RPC URL
bsc_rpc_url: Option<String>,
/// NAC桥接合约地址
nac_bridge_address: [u8; 32],
/// 以太坊桥接合约地址
eth_bridge_address: [u8; 32],
}
impl Default for RelayConfig {
fn default() -> Self {
Self {
db_path: "./bridge_data".to_string(),
nac_rpc_url: "http://localhost:8545".to_string(),
eth_rpc_url: "http://localhost:8546".to_string(),
bsc_rpc_url: None,
nac_bridge_address: [0u8; 32],
eth_bridge_address: [0u8; 32],
}
}
}
/// 从环境变量加载配置
fn load_config_from_env() -> RelayConfig {
let mut config = RelayConfig::default();
if let Ok(db_path) = std::env::var("BRIDGE_DB_PATH") {
config.db_path = db_path;
}
if let Ok(nac_rpc) = std::env::var("NAC_RPC_URL") {
config.nac_rpc_url = nac_rpc;
}
if let Ok(eth_rpc) = std::env::var("ETH_RPC_URL") {
config.eth_rpc_url = eth_rpc;
}
if let Ok(bsc_rpc) = std::env::var("BSC_RPC_URL") {
config.bsc_rpc_url = Some(bsc_rpc);
}
// TODO: 从环境变量加载合约地址
config
}
/// 初始化桥接管理器
async fn initialize_bridge(config: &RelayConfig) -> anyhow::Result<Arc<BridgeManagerImpl>> {
log::info!("Initializing bridge manager...");
log::info!("Database path: {}", config.db_path);
log::info!("NAC RPC: {}", config.nac_rpc_url);
log::info!("Ethereum RPC: {}", config.eth_rpc_url);
// 创建桥接管理器
let manager = Arc::new(BridgeManagerImpl::new(&config.db_path)?);
// 初始化
manager.initialize().await?;
// 注册以太坊监听器
let eth_listener = Arc::new(EthereumListener::new(
ChainId::Ethereum,
config.eth_rpc_url.clone(),
config.eth_bridge_address,
));
manager.register_listener(ChainId::Ethereum, eth_listener).await?;
// 如果配置了BSC也注册BSC监听器
if let Some(bsc_rpc) = &config.bsc_rpc_url {
let bsc_listener = Arc::new(EthereumListener::new(
ChainId::BSC,
bsc_rpc.clone(),
config.eth_bridge_address, // TODO: 使用独立的BSC合约地址
));
manager.register_listener(ChainId::BSC, bsc_listener).await?;
}
log::info!("Bridge manager initialized successfully");
Ok(manager)
}
/// 启动中继节点
async fn start_relay(manager: Arc<BridgeManagerImpl>) -> anyhow::Result<()> {
log::info!("Starting relay node...");
// 启动桥接
manager.start().await?;
log::info!("Relay node started successfully");
log::info!("Press Ctrl+C to stop");
// 等待退出信号
signal::ctrl_c().await?;
log::info!("Received shutdown signal, stopping relay node...");
// 停止桥接
manager.stop().await?;
log::info!("Relay node stopped");
Ok(())
}
/// 显示状态
async fn show_status(manager: &BridgeManagerImpl) -> anyhow::Result<()> {
let status = manager.get_status().await?;
println!("=== NAC Bridge Relay Status ===");
println!("Running: {}", status.is_running);
println!("Paused: {}", status.is_paused);
println!("Total Locked: {}", status.total_locked);
println!("Total Unlocked: {}", status.total_unlocked);
println!("Active Validators: {}", status.active_validators);
println!("Active Relayers: {}", status.active_relayers);
println!("==============================");
Ok(())
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// 初始化日志
init_logger();
log::info!("NAC Bridge Relay v{}", VERSION);
log::info!("=================================");
// 加载配置
let config = load_config_from_env();
// 解析命令行参数
let args: Vec<String> = std::env::args().collect();
let command = args.get(1).map(|s| s.as_str()).unwrap_or("start");
match command {
"start" => {
// 初始化桥接
let manager = initialize_bridge(&config).await?;
// 启动中继节点
start_relay(manager).await?;
}
"status" => {
// 创建桥接管理器(只读模式)
let manager = BridgeManagerImpl::new(&config.db_path)?;
manager.initialize().await?;
// 显示状态
show_status(&manager).await?;
}
"pause" => {
let manager = BridgeManagerImpl::new(&config.db_path)?;
manager.initialize().await?;
manager.pause().await?;
log::info!("Bridge paused");
}
"resume" => {
let manager = BridgeManagerImpl::new(&config.db_path)?;
manager.initialize().await?;
manager.resume().await?;
log::info!("Bridge resumed");
}
"version" => {
println!("NAC Bridge Relay v{}", VERSION);
}
"help" | "--help" | "-h" => {
println!("NAC Bridge Relay v{}", VERSION);
println!("\nUsage: nac-bridge-relay [COMMAND]");
println!("\nCommands:");
println!(" start Start the relay node (default)");
println!(" status Show bridge status");
println!(" pause Pause the bridge");
println!(" resume Resume the bridge");
println!(" version Show version");
println!(" help Show this help message");
println!("\nEnvironment Variables:");
println!(" BRIDGE_DB_PATH Database path (default: ./bridge_data)");
println!(" NAC_RPC_URL NAC RPC URL (default: http://localhost:8545)");
println!(" ETH_RPC_URL Ethereum RPC URL (default: http://localhost:8546)");
println!(" BSC_RPC_URL BSC RPC URL (optional)");
}
_ => {
eprintln!("Unknown command: {}", command);
eprintln!("Run 'nac-bridge-relay help' for usage");
std::process::exit(1);
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = RelayConfig::default();
assert_eq!(config.db_path, "./bridge_data");
assert_eq!(config.nac_rpc_url, "http://localhost:8545");
}
#[test]
fn test_load_config_from_env() {
std::env::set_var("BRIDGE_DB_PATH", "/tmp/test_bridge");
std::env::set_var("NAC_RPC_URL", "http://test:8545");
let config = load_config_from_env();
assert_eq!(config.db_path, "/tmp/test_bridge");
assert_eq!(config.nac_rpc_url, "http://test:8545");
std::env::remove_var("BRIDGE_DB_PATH");
std::env::remove_var("NAC_RPC_URL");
}
}