247 lines
7.2 KiB
Rust
247 lines
7.2 KiB
Rust
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");
|
||
}
|
||
}
|