Added config option to ignore all nodes except from Yggdrasil.
This commit is contained in:
+29
-1
@@ -3,6 +3,7 @@ use rand::Rng;
|
||||
|
||||
pub mod constants;
|
||||
pub use constants::*;
|
||||
use std::net::IpAddr;
|
||||
|
||||
/// Convert bytes array to HEX format
|
||||
pub fn to_hex(buf: &[u8]) -> String {
|
||||
@@ -80,9 +81,20 @@ pub fn random_string(length: usize) -> String {
|
||||
result
|
||||
}
|
||||
|
||||
/// Checks if this IP is from Yggdrasil network
|
||||
/// https://yggdrasil-network.github.io
|
||||
pub fn is_yggdrasil(addr: &IpAddr) -> bool {
|
||||
if let IpAddr::V6(ipv6) = addr {
|
||||
let first_byte = ipv6.octets()[0];
|
||||
return first_byte == 2 || first_byte == 3;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::check_domain;
|
||||
use crate::{check_domain, is_yggdrasil};
|
||||
use std::net::IpAddr;
|
||||
|
||||
#[test]
|
||||
fn test_check_domain() {
|
||||
@@ -98,4 +110,20 @@ mod test {
|
||||
assert!(!check_domain(".ab.c", true));
|
||||
assert!(!check_domain("ab.c-", true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_yggdrasil() {
|
||||
let addr: IpAddr = "200::1".parse().unwrap();
|
||||
assert!(is_yggdrasil(&addr));
|
||||
let addr: IpAddr = "226::1".parse().unwrap();
|
||||
assert!(is_yggdrasil(&addr));
|
||||
let addr: IpAddr = "300::1".parse().unwrap();
|
||||
assert!(is_yggdrasil(&addr));
|
||||
let addr: IpAddr = "326::1".parse().unwrap();
|
||||
assert!(is_yggdrasil(&addr));
|
||||
let addr: IpAddr = "2001::1".parse().unwrap();
|
||||
assert!(!is_yggdrasil(&addr));
|
||||
let addr: IpAddr = "2201::1".parse().unwrap();
|
||||
assert!(!is_yggdrasil(&addr));
|
||||
}
|
||||
}
|
||||
|
||||
+14
-7
@@ -15,7 +15,7 @@ use log::{trace, debug, info, warn, error};
|
||||
|
||||
use std::net::{SocketAddr, IpAddr, SocketAddrV4, Shutdown};
|
||||
use std::collections::HashSet;
|
||||
use crate::{Context, Block, p2p::Message, p2p::State, p2p::Peer, p2p::Peers, Bytes};
|
||||
use crate::{Context, Block, p2p::Message, p2p::State, p2p::Peer, p2p::Peers, Bytes, is_yggdrasil};
|
||||
use crate::blockchain::enums::BlockQuality;
|
||||
use crate::commons::CHAIN_VERSION;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
@@ -36,9 +36,9 @@ impl Network {
|
||||
}
|
||||
|
||||
pub fn start(&mut self) -> Result<(), String> {
|
||||
let (listen_addr, peers_addrs) = {
|
||||
let (listen_addr, peers_addrs, yggdrasil_only) = {
|
||||
let c = self.context.lock().unwrap();
|
||||
(c.settings.listen.clone(), c.settings.peers.clone())
|
||||
(c.settings.net.listen.clone(), c.settings.net.peers.clone(), c.settings.net.yggdrasil_only)
|
||||
};
|
||||
|
||||
let running = Arc::new(AtomicBool::new(true));
|
||||
@@ -61,7 +61,7 @@ impl Network {
|
||||
// States of peer connections, and some data to send when sockets become writable
|
||||
let mut peers = Peers::new();
|
||||
// Starting peer connections to bootstrap nodes
|
||||
peers.connect_peers(peers_addrs, &poll.registry(), &mut unique_token);
|
||||
peers.connect_peers(peers_addrs, &poll.registry(), &mut unique_token, yggdrasil_only);
|
||||
|
||||
loop {
|
||||
// Poll Mio for events, blocking until we get an event.
|
||||
@@ -89,6 +89,13 @@ impl Network {
|
||||
}
|
||||
}
|
||||
|
||||
if yggdrasil_only && !is_yggdrasil(&address.ip()) {
|
||||
info!("Dropping connection from Internet");
|
||||
stream.shutdown(Shutdown::Both).unwrap_or_else(|e|{ warn!("Error in shutdown, {}", e); });
|
||||
let _ = poll.registry().reregister(&mut server, SERVER, Interest::READABLE);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If connection is from the same IP and not from loopback we ignore it to avoid connection loops
|
||||
let local_ip = stream.local_addr().unwrap_or("0.0.0.0:0".parse().unwrap());
|
||||
if !local_ip.ip().is_loopback() && local_ip.ip() == address.ip() {
|
||||
@@ -104,7 +111,7 @@ impl Network {
|
||||
}
|
||||
Err(_) => {}
|
||||
}
|
||||
poll.registry().reregister(&mut server, SERVER, Interest::READABLE).expect("Error reregistering server");
|
||||
let _ = poll.registry().reregister(&mut server, SERVER, Interest::READABLE);
|
||||
}
|
||||
token => {
|
||||
if !handle_connection_event(Arc::clone(&context), &mut peers, &poll.registry(), &event) {
|
||||
@@ -130,7 +137,7 @@ impl Network {
|
||||
};
|
||||
mine_locker_block(Arc::clone(&context));
|
||||
peers.send_pings(poll.registry(), height, hash);
|
||||
peers.connect_new_peers(poll.registry(), &mut unique_token);
|
||||
peers.connect_new_peers(poll.registry(), &mut unique_token, yggdrasil_only);
|
||||
}
|
||||
info!("Network loop finished");
|
||||
});
|
||||
@@ -209,7 +216,7 @@ fn handle_connection_event(context: Arc<Mutex<Context>>, peers: &mut Peers, regi
|
||||
debug!("Sending hello to {}", &peer.get_addr());
|
||||
let data: String = {
|
||||
let c = context.lock().unwrap();
|
||||
let message = Message::hand(&c.app_version, &c.settings.origin, CHAIN_VERSION, c.settings.public, peer.get_rand());
|
||||
let message = Message::hand(&c.app_version, &c.settings.origin, CHAIN_VERSION, c.settings.net.public, peer.get_rand());
|
||||
serde_json::to_string(&message).unwrap()
|
||||
};
|
||||
send_message(peer.get_stream(), &data.into_bytes()).unwrap_or_else(|e| warn!("Error sending hello {}", e));
|
||||
|
||||
+11
-3
@@ -9,7 +9,7 @@ use rand::random;
|
||||
use rand::seq::IteratorRandom;
|
||||
#[allow(unused_imports)]
|
||||
use log::{trace, debug, info, warn, error};
|
||||
use crate::Bytes;
|
||||
use crate::{Bytes, is_yggdrasil};
|
||||
use crate::commons::MAX_RECONNECTS;
|
||||
|
||||
pub struct Peers {
|
||||
@@ -252,7 +252,7 @@ impl Peers {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn connect_new_peers(&mut self, registry: &Registry, unique_token: &mut Token) {
|
||||
pub fn connect_new_peers(&mut self, registry: &Registry, unique_token: &mut Token, yggdrasil_only: bool) {
|
||||
if self.new_peers.is_empty() {
|
||||
return;
|
||||
}
|
||||
@@ -260,6 +260,10 @@ impl Peers {
|
||||
if self.ignored.contains(&addr.ip()) {
|
||||
continue;
|
||||
}
|
||||
if yggdrasil_only && !is_yggdrasil(&addr.ip()) {
|
||||
info!("Ignoring not Yggdrasil address '{}'", &addr.ip());
|
||||
continue;
|
||||
}
|
||||
match TcpStream::connect(addr.clone()) {
|
||||
Ok(mut stream) => {
|
||||
info!("Created connection to peer {}", &addr);
|
||||
@@ -278,7 +282,7 @@ impl Peers {
|
||||
}
|
||||
|
||||
/// Connecting to configured (bootstrap) peers
|
||||
pub fn connect_peers(&mut self, peers_addrs: Vec<String>, registry: &Registry, unique_token: &mut Token) {
|
||||
pub fn connect_peers(&mut self, peers_addrs: Vec<String>, registry: &Registry, unique_token: &mut Token, yggdrasil_only: bool) {
|
||||
for peer in peers_addrs.iter() {
|
||||
let addresses: Vec<SocketAddr> = match peer.to_socket_addrs() {
|
||||
Ok(peers) => { peers.collect() }
|
||||
@@ -286,6 +290,10 @@ impl Peers {
|
||||
};
|
||||
|
||||
for addr in addresses {
|
||||
if yggdrasil_only && !is_yggdrasil(&addr.ip()) {
|
||||
info!("Ignoring not Yggdrasil address '{}'", &addr.ip());
|
||||
continue;
|
||||
}
|
||||
match TcpStream::connect(addr.clone()) {
|
||||
Ok(mut stream) => {
|
||||
info!("Created connection to peer {}", &addr);
|
||||
|
||||
+32
-11
@@ -13,12 +13,8 @@ pub struct Settings {
|
||||
pub origin: String,
|
||||
#[serde(default)]
|
||||
pub key_file: String,
|
||||
#[serde(default = "default_listen")]
|
||||
pub listen: String,
|
||||
#[serde(default)]
|
||||
pub public: bool,
|
||||
#[serde(default)]
|
||||
pub peers: Vec<String>,
|
||||
pub net: Net,
|
||||
#[serde(default)]
|
||||
pub dns: Dns,
|
||||
#[serde(default)]
|
||||
@@ -66,11 +62,9 @@ impl Settings {
|
||||
impl Default for Settings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
origin: "".to_string(),
|
||||
key_file: "".to_string(),
|
||||
listen: String::from("[::]:4244"),
|
||||
public: false,
|
||||
peers: vec![],
|
||||
origin: String::from("00000102C2F9BFD2803284D93327F089D60FC72A06F19AF2384567F2646B8348"),
|
||||
key_file: String::from("default.key"),
|
||||
net: Net::default(),
|
||||
dns: Default::default(),
|
||||
mining: Mining::default()
|
||||
}
|
||||
@@ -88,7 +82,11 @@ pub struct Dns {
|
||||
|
||||
impl Default for Dns {
|
||||
fn default() -> Self {
|
||||
Dns { listen: String::from("0.0.0.0:53"), threads: 20, forwarders: vec!["94.140.14.14:53".to_owned(), "94.140.15.15:53".to_owned()] }
|
||||
Dns {
|
||||
listen: String::from("127.0.0.1:53"),
|
||||
threads: 20,
|
||||
forwarders: vec![String::from("94.140.14.14:53"), String::from("94.140.15.15:53")]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,6 +96,29 @@ pub struct Mining {
|
||||
pub threads: usize
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Net {
|
||||
#[serde(default)]
|
||||
pub peers: Vec<String>,
|
||||
#[serde(default = "default_listen")]
|
||||
pub listen: String,
|
||||
#[serde(default)]
|
||||
pub public: bool,
|
||||
#[serde(default)]
|
||||
pub yggdrasil_only: bool,
|
||||
}
|
||||
|
||||
impl Default for Net {
|
||||
fn default() -> Self {
|
||||
Net {
|
||||
peers: vec![String::from("test-ip4.alfis.name:4244"), String::from("test-ip6.alfis.name:4244")],
|
||||
listen: String::from("[::]:4244"),
|
||||
public: true,
|
||||
yggdrasil_only: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn default_listen() -> String {
|
||||
String::from("[::]:4244")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user