#![forbid(unsafe_code)]
pub mod node_type;
pub use node_type::*;
pub mod peer;
pub use peer::*;
pub mod peering;
pub use peering::*;
pub mod resolver;
pub use resolver::*;
use snarkvm::prelude::Network;
use smol_str::SmolStr;
use socket2::SockRef;
use std::{env::VarError, io, net::SocketAddr, str::FromStr, time::Duration};
use tokio::net::TcpStream;
use tracing::*;
pub mod built_info {
include!(concat!(env!("OUT_DIR"), "/built.rs"));
}
#[allow(clippy::if_same_then_else)]
pub fn bootstrap_peers<N: Network>(is_dev: bool) -> Vec<SocketAddr> {
if cfg!(feature = "test") || is_dev {
match std::env::var("TEST_BOOTSTRAP_PEERS") {
Ok(peers) => peers.split(',').map(|peer| SocketAddr::from_str(peer).unwrap()).collect(),
Err(VarError::NotPresent) => {
vec![]
}
Err(err) => {
warn!("Failed to load bootstrap peers from environment: {err}");
vec![]
}
}
} else if N::ID == snarkvm::console::network::MainnetV0::ID {
vec![
SocketAddr::from_str("35.231.67.219:4130").unwrap(),
SocketAddr::from_str("34.73.195.196:4130").unwrap(),
SocketAddr::from_str("34.23.225.202:4130").unwrap(),
SocketAddr::from_str("34.148.16.111:4130").unwrap(),
]
} else if N::ID == snarkvm::console::network::TestnetV0::ID {
vec![
SocketAddr::from_str("34.138.104.159:4130").unwrap(),
SocketAddr::from_str("35.231.46.237:4130").unwrap(),
SocketAddr::from_str("34.148.251.155:4130").unwrap(),
SocketAddr::from_str("35.190.141.234:4130").unwrap(),
]
} else if N::ID == snarkvm::console::network::CanaryV0::ID {
vec![
SocketAddr::from_str("34.139.88.58:4130").unwrap(),
SocketAddr::from_str("34.139.252.207:4130").unwrap(),
SocketAddr::from_str("35.185.98.12:4130").unwrap(),
SocketAddr::from_str("35.231.106.26:4130").unwrap(),
]
} else {
vec![]
}
}
pub fn get_repo_commit_hash() -> Option<[u8; 40]> {
built_info::GIT_COMMIT_HASH.and_then(|sha| sha.as_bytes().try_into().ok())
}
pub fn log_repo_sha_comparison(peer_addr: SocketAddr, peer_sha: &Option<[u8; 40]>, ctx: &str) {
let our_sha = get_repo_commit_hash();
let peer_sha_str: Option<&str> = peer_sha.as_ref().and_then(|h| str::from_utf8(h).ok());
let sha_cmp = match (&our_sha, peer_sha, peer_sha_str) {
(_, _, None) | (_, None, _) => " with an unknown repo SHA".to_owned(),
(None, _, Some(theirs_str)) => format!("@{theirs_str} (potentially different than us)"),
(Some(ours), Some(theirs), Some(theirs_str)) => {
if ours == theirs {
format!("@{theirs_str} (same as us)")
} else {
format!("@{theirs_str} (different than us)")
}
}
};
debug!("{ctx} Peer '{peer_addr}' uses snarkOS{sha_cmp}");
}
pub fn shorten_snarkos_sha(sha: &Option<[u8; 40]>) -> SmolStr {
if let Some(full_sha) = sha.as_ref().and_then(|s| str::from_utf8(s).ok()) {
let end_idx = full_sha.char_indices()
.nth(7) .map(|(i, _)| i)
.unwrap_or(full_sha.len());
SmolStr::from(&full_sha[..end_idx])
} else {
"unknown snarkOS SHA".into()
}
}
pub fn harden_socket(stream: &TcpStream) -> io::Result<()> {
let socket = SockRef::from(stream);
socket.set_linger(Some(Duration::from_secs(0)))?;
socket.set_tcp_nodelay(true)?;
#[cfg(target_os = "linux")]
socket.set_tcp_user_timeout(Some(Duration::from_secs(20)))?;
Ok(())
}