Contractless/src/startup/connections.rs

90 lines
3.2 KiB
Rust
Raw Normal View History

2026-05-24 17:56:57 +00:00
use crate::common::network_startup::get_connections;
use crate::log::{error, info};
use crate::miner::flag::{
clear_mining_stop_request, set_mining_state, set_node_mode, MiningState, NodeMode,
};
use crate::records::memory::response_channels::Command;
use crate::rpc::client::handshake::connect_and_handshake;
use crate::rpc::client::structs::Connect;
use crate::sled::Db;
use crate::sleep;
use crate::wallets::structures::Wallet;
use crate::Arc;
2026-05-24 17:56:57 +00:00
use crate::Duration;
use crate::Mutex;
pub async fn handle_connections(
db: Db,
wallet: Arc<Wallet>,
map: Arc<Mutex<Command>>,
2026-05-24 17:56:57 +00:00
) -> Result<(), String> {
// A zero outgoing limit means this node should not open any bootstrap
// connection during startup.
let outgoing_connections = crate::Settings::load()
.map(|settings| settings.outgoing_connections)
.unwrap_or(0);
if outgoing_connections == 0 {
info!("OUTGOING_CONNECTIONS is 0; skipping startup bootstrap.");
set_node_mode(NodeMode::Normal);
clear_mining_stop_request();
set_mining_state(MiningState::Idle);
return Ok(());
}
// try the configured bootstrap peers one by one until a
// handshake succeeds or the list is exhausted
let filtered_servers = get_connections().await;
let mut last_error: Option<String> = None;
for server in filtered_servers {
// build the outbound handshake request using cloned
// shared state so each attempt can run independently
let db_clone = db.clone();
// parse the configured peer string once before spawning
2026-05-24 17:56:57 +00:00
// the outbound connection attempt
let socket_address = server.parse().expect("Failed to parse the socket address");
// Clone the Arc for use in other async functions
let map_clone = Arc::clone(&map);
let first: bool = true;
let connect_params = Connect {
addr: socket_address,
db: db_clone,
node_ip: server.to_string(),
wallet: wallet.clone(),
map: map_clone,
first,
};
2026-05-24 17:56:57 +00:00
let err_string = match connect_and_handshake(connect_params).await {
Ok(()) => {
info!("Connected to {server}");
return Ok(());
}
Err(err) => err.to_string(),
};
// A peer can reject us because it already has this connection recorded.
// In that case retrying other bootstrap peers would not fix the local duplicate state.
if err_string.contains("The connection is already in the connection manager Please wait 10 minutes and try again") {
return Err(err_string);
}
error!("Error connecting to {server}: {err_string}");
last_error = Some(err_string.clone());
sleep(Duration::from_secs(5)).await;
}
if let Some(err) = last_error {
info!("No bootstrap peers connected during startup: {err}");
} else {
info!("No bootstrap peers connected during startup.");
}
// Startup can continue as a standalone node even if no bootstrap peer is reachable.
set_node_mode(NodeMode::Normal);
clear_mining_stop_request();
set_mining_state(MiningState::Idle);
Ok(())
}