Disabled full blockchain check on start.

Fixed non-working debug version.
Fixed p2p connections handling.
Lowered ping interval to 30-60 seconds.
Fixed stuck with lower number of blocks.
This commit is contained in:
Revertron
2021-04-21 23:11:10 +02:00
parent 92b03344eb
commit 864edab203
3 changed files with 80 additions and 66 deletions
+5 -3
View File
@@ -91,9 +91,11 @@ impl Chain {
self.last_full_block = self.get_last_full_block(u64::MAX, None); self.last_full_block = self.get_last_full_block(u64::MAX, None);
} }
} }
self.check_chain(); // TODO Add env-var and commandline switches for full check
//self.check_chain();
} }
#[allow(dead_code)]
fn check_chain(&mut self) { fn check_chain(&mut self) {
let height = self.get_height(); let height = self.get_height();
info!("Local blockchain height is {}, starting full blockchain check...", height); info!("Local blockchain height is {}, starting full blockchain check...", height);
@@ -693,7 +695,7 @@ impl Chain {
} }
} }
pub fn last_hash(&self) -> Bytes { pub fn get_last_hash(&self) -> Bytes {
match &self.last_block { match &self.last_block {
None => { Bytes::default() } None => { Bytes::default() }
Some(block) => { block.hash.clone() } Some(block) => { block.hash.clone() }
@@ -988,7 +990,7 @@ impl Chain {
let mut count = 1; let mut count = 1;
let window = block.index - 1; // Without the last block let window = block.index - 1; // Without the last block
while set.len() < BLOCK_SIGNERS_ALL as usize { while set.len() < BLOCK_SIGNERS_ALL as usize {
let index = ((tail * count) % window) + 1; // We want it to start from 1 let index = (tail.wrapping_mul(count) % window) + 1; // We want it to start from 1
if let Some(b) = self.get_block(index) { if let Some(b) = self.get_block(index) {
if b.pub_key != block.pub_key && !set.contains(&b.pub_key) { if b.pub_key != block.pub_key && !set.contains(&b.pub_key) {
result.push(b.pub_key.clone()); result.push(b.pub_key.clone());
+30 -19
View File
@@ -21,7 +21,7 @@ use crate::blockchain::types::BlockQuality;
use crate::commons::*; use crate::commons::*;
const SERVER: Token = Token(0); const SERVER: Token = Token(0);
const POLL_TIMEOUT: Option<Duration> = Some(Duration::from_millis(1000)); const POLL_TIMEOUT: Option<Duration> = Some(Duration::from_millis(500));
const MAX_PACKET_SIZE: usize = 1 * 1024 * 1024; // 1 Mb const MAX_PACKET_SIZE: usize = 1 * 1024 * 1024; // 1 Mb
const MAX_READ_BLOCK_TIME: u128 = 500; const MAX_READ_BLOCK_TIME: u128 = 500;
@@ -165,7 +165,7 @@ impl Network {
} }
log_timer = Instant::now(); log_timer = Instant::now();
} }
(height, context.chain.last_hash()) (height, context.chain.get_last_hash())
}; };
peers.update(poll.registry(), height, hash); peers.update(poll.registry(), height, hash);
peers.connect_new_peers(poll.registry(), &mut unique_token, yggdrasil_only); peers.connect_new_peers(poll.registry(), &mut unique_token, yggdrasil_only);
@@ -295,7 +295,7 @@ fn handle_connection_event(context: Arc<Mutex<Context>>, peers: &mut Peers, regi
if from.elapsed().as_secs() >= 30 { if from.elapsed().as_secs() >= 30 {
let data: String = { let data: String = {
let c = context.lock().unwrap(); let c = context.lock().unwrap();
let message = Message::ping(c.chain.get_height(), c.chain.last_hash()); let message = Message::ping(c.chain.get_height(), c.chain.get_last_hash());
serde_json::to_string(&message).unwrap() serde_json::to_string(&message).unwrap()
}; };
send_message(peer.get_stream(), &data.into_bytes()).unwrap_or_else(|e| warn!("Error sending ping {}", e)); send_message(peer.get_stream(), &data.into_bytes()).unwrap_or_else(|e| warn!("Error sending ping {}", e));
@@ -371,7 +371,7 @@ fn handle_message(context: Arc<Mutex<Context>>, message: Message, peers: &mut Pe
let (my_height, my_hash, my_origin, my_version) = { let (my_height, my_hash, my_origin, my_version) = {
let context = context.lock().unwrap(); let context = context.lock().unwrap();
// TODO cache it somewhere // TODO cache it somewhere
(context.chain.get_height(), context.chain.last_hash(), &context.settings.origin.clone(), CHAIN_VERSION) (context.chain.get_height(), context.chain.get_last_hash(), &context.settings.origin.clone(), CHAIN_VERSION)
}; };
let answer = match message { let answer = match message {
Message::Hand { app_version, origin, version, public, rand} => { Message::Hand { app_version, origin, version, public, rand} => {
@@ -382,6 +382,7 @@ fn handle_message(context: Arc<Mutex<Context>>, message: Message, peers: &mut Pe
if origin.eq(my_origin) && version == my_version { if origin.eq(my_origin) && version == my_version {
let peer = peers.get_mut_peer(token).unwrap(); let peer = peers.get_mut_peer(token).unwrap();
peer.set_public(public); peer.set_public(public);
peer.set_active(true);
debug!("Hello from v{} on {}", &app_version, peer.get_addr().ip()); debug!("Hello from v{} on {}", &app_version, peer.get_addr().ip());
State::message(Message::shake(&origin, version, true, my_height)) State::message(Message::shake(&origin, version, true, my_height))
} else { } else {
@@ -404,13 +405,12 @@ fn handle_message(context: Arc<Mutex<Context>>, message: Message, peers: &mut Pe
if peer.is_higher(my_height) { if peer.is_higher(my_height) {
context.chain.update_max_height(height); context.chain.update_max_height(height);
context.bus.post(crate::event::Event::Syncing { have: my_height, height}); context.bus.post(crate::event::Event::Syncing { have: my_height, height});
if active_count > 3 { }
State::idle() if active_count < 5 || random::<u8>() < 10 {
} else { debug!("Requesting more peers from {}", peer.get_addr().ip());
State::message(Message::GetPeers)
}
} else {
State::message(Message::GetPeers) State::message(Message::GetPeers)
} else {
State::idle()
} }
} else { } else {
State::Banned State::Banned
@@ -425,15 +425,16 @@ fn handle_message(context: Arc<Mutex<Context>>, message: Message, peers: &mut Pe
let mut context = context.lock().unwrap(); let mut context = context.lock().unwrap();
context.chain.update_max_height(height); context.chain.update_max_height(height);
} }
if hash.ne(&my_hash) { if my_height == height && hash.ne(&my_hash) {
debug!("1Hashes are different, requesting block {} from {}", my_height, peer.get_addr().ip()); info!("Hashes are different, requesting block {} from {}", my_height, peer.get_addr().ip());
debug!("My hash: {:?}, their hash: {:?}", &my_hash, &hash); info!("My hash: {:?}, their hash: {:?}", &my_hash, &hash);
State::message(Message::GetBlock { index: my_height }) State::message(Message::GetBlock { index: my_height })
} else { } else {
State::message(Message::pong(my_height, my_hash)) State::message(Message::pong(my_height, my_hash))
} }
} }
Message::Pong { height, hash } => { Message::Pong { height, hash } => {
let active_count = peers.get_peers_active_count();
let peer = peers.get_mut_peer(token).unwrap(); let peer = peers.get_mut_peer(token).unwrap();
peer.set_height(height); peer.set_height(height);
peer.set_active(true); peer.set_active(true);
@@ -441,12 +442,12 @@ fn handle_message(context: Arc<Mutex<Context>>, message: Message, peers: &mut Pe
let mut context = context.lock().unwrap(); let mut context = context.lock().unwrap();
context.chain.update_max_height(height); context.chain.update_max_height(height);
} }
if hash.ne(&my_hash) { if my_height == height && hash.ne(&my_hash) {
debug!("2Hashes are different, requesting block {} from {}", my_height, peer.get_addr().ip()); info!("Hashes are different, requesting block {} from {}", my_height, peer.get_addr().ip());
debug!("My hash: {:?}, their hash: {:?}", &my_hash, &hash); info!("My hash: {:?}, their hash: {:?}", &my_hash, &hash);
State::message(Message::GetBlock { index: my_height }) State::message(Message::GetBlock { index: my_height })
} else { } else {
if random::<u8>() < 10 { if active_count < 5 || random::<u8>() < 10 {
debug!("Requesting more peers from {}", peer.get_addr().ip()); debug!("Requesting more peers from {}", peer.get_addr().ip());
State::message(Message::GetPeers) State::message(Message::GetPeers)
} else { } else {
@@ -455,14 +456,22 @@ fn handle_message(context: Arc<Mutex<Context>>, message: Message, peers: &mut Pe
} }
} }
Message::GetPeers => { Message::GetPeers => {
let peer = peers.get_peer(token).unwrap(); let addr = {
State::message(Message::Peers { peers: peers.get_peers_for_exchange(&peer.get_addr()) }) let peer = peers.get_mut_peer(token).unwrap();
peer.set_active(true);
peer.get_addr().clone()
};
State::message(Message::Peers { peers: peers.get_peers_for_exchange(&addr) })
} }
Message::Peers { peers: new_peers } => { Message::Peers { peers: new_peers } => {
let peer = peers.get_mut_peer(token).unwrap();
peer.set_active(true);
peers.add_peers_from_exchange(new_peers); peers.add_peers_from_exchange(new_peers);
State::idle() State::idle()
} }
Message::GetBlock { index } => { Message::GetBlock { index } => {
let peer = peers.get_mut_peer(token).unwrap();
peer.set_active(true);
let context = context.lock().unwrap(); let context = context.lock().unwrap();
match context.chain.get_block(index) { match context.chain.get_block(index) {
Some(block) => State::message(Message::block(block.index, serde_json::to_string(&block).unwrap())), Some(block) => State::message(Message::block(block.index, serde_json::to_string(&block).unwrap())),
@@ -470,6 +479,8 @@ fn handle_message(context: Arc<Mutex<Context>>, message: Message, peers: &mut Pe
} }
} }
Message::Block { index, block } => { Message::Block { index, block } => {
let peer = peers.get_mut_peer(token).unwrap();
peer.set_active(true);
info!("Received block {}", index); info!("Received block {}", index);
let block: Block = match serde_json::from_str(&block) { let block: Block = match serde_json::from_str(&block) {
Ok(block) => block, Ok(block) => block,
+45 -44
View File
@@ -13,19 +13,16 @@ use crate::{Bytes, commons};
use crate::commons::*; use crate::commons::*;
use crate::p2p::{Message, Peer, State}; use crate::p2p::{Message, Peer, State};
use crate::commons::next; use crate::commons::next;
use std::time::Duration;
use std::io; use std::io;
const PING_PERIOD: u64 = 60; const PING_PERIOD: u64 = 30;
const TCP_TIMEOUT: Duration = Duration::from_millis(10000);
pub struct Peers { pub struct Peers {
peers: HashMap<Token, Peer>, peers: HashMap<Token, Peer>,
new_peers: Vec<SocketAddr>, new_peers: Vec<SocketAddr>,
ignored: HashSet<IpAddr>, ignored: HashSet<IpAddr>,
my_id: String, my_id: String,
asked_block: u64, block_asked_time: i64,
asked_time: i64,
} }
impl Peers { impl Peers {
@@ -35,8 +32,7 @@ impl Peers {
new_peers: Vec::new(), new_peers: Vec::new(),
ignored: HashSet::new(), ignored: HashSet::new(),
my_id: commons::random_string(6), my_id: commons::random_string(6),
asked_block: 0, block_asked_time: 0
asked_time: 0
} }
} }
@@ -217,7 +213,6 @@ impl Peers {
} }
pub fn update(&mut self, registry: &Registry, height: u64, hash: Bytes) { pub fn update(&mut self, registry: &Registry, height: u64, hash: Bytes) {
let mut ping_sent = false;
for (token, peer) in self.peers.iter_mut() { for (token, peer) in self.peers.iter_mut() {
match peer.get_state() { match peer.get_state() {
State::Idle { from } => { State::Idle { from } => {
@@ -225,7 +220,7 @@ impl Peers {
if from.elapsed().as_secs() >= PING_PERIOD + random_time { if from.elapsed().as_secs() >= PING_PERIOD + random_time {
// Sometimes we check for new peers instead of pinging // Sometimes we check for new peers instead of pinging
let random: u8 = random(); let random: u8 = random();
let message = if random < 16 { let message = if random < 10 {
Message::GetPeers Message::GetPeers
} else { } else {
Message::ping(height, hash.clone()) Message::ping(height, hash.clone())
@@ -234,7 +229,6 @@ impl Peers {
peer.set_state(State::message(message)); peer.set_state(State::message(message));
let stream = peer.get_stream(); let stream = peer.get_stream();
registry.reregister(stream, token.clone(), Interest::WRITABLE).unwrap(); registry.reregister(stream, token.clone(), Interest::WRITABLE).unwrap();
ping_sent = true;
} }
} }
_ => {} _ => {}
@@ -242,7 +236,7 @@ impl Peers {
} }
// If someone has more blocks we sync // If someone has more blocks we sync
if self.need_ask_block(height + 1) { if self.need_ask_block() {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
let mut asked = false; let mut asked = false;
match self.peers match self.peers
@@ -254,17 +248,16 @@ impl Peers {
debug!("Found some peer higher than we are, requesting block {}, from {}", height + 1, &peer.get_addr().ip()); debug!("Found some peer higher than we are, requesting block {}, from {}", height + 1, &peer.get_addr().ip());
registry.reregister(peer.get_stream(), token.clone(), Interest::WRITABLE).unwrap(); registry.reregister(peer.get_stream(), token.clone(), Interest::WRITABLE).unwrap();
peer.set_state(State::message(Message::GetBlock { index: height + 1 })); peer.set_state(State::message(Message::GetBlock { index: height + 1 }));
ping_sent = true;
asked = true; asked = true;
} }
} }
if asked { if asked {
self.set_asked_block(height + 1); self.update_asked_block_time();
} }
} }
// If someone has less blocks (we mined a new block) we send a ping with our height // If someone has less blocks (we mined a new block) we send a ping with our height
if !ping_sent { {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
match self.peers match self.peers
.iter_mut() .iter_mut()
@@ -326,25 +319,36 @@ impl Peers {
pub fn connect_peers(&mut self, peers_addrs: &Vec<String>, registry: &Registry, unique_token: &mut Token, yggdrasil_only: bool) { pub fn connect_peers(&mut self, peers_addrs: &Vec<String>, registry: &Registry, unique_token: &mut Token, yggdrasil_only: bool) {
let mut set = HashSet::new(); let mut set = HashSet::new();
for peer in peers_addrs.iter() { for peer in peers_addrs.iter() {
info!("Resolving address {}", peer);
let mut addresses: Vec<SocketAddr> = match peer.to_socket_addrs() { let mut addresses: Vec<SocketAddr> = match peer.to_socket_addrs() {
Ok(peers) => { peers.collect() } Ok(peers) => { peers.collect() }
Err(_) => { error!("Can't resolve address {}", &peer); continue; } Err(_) => { error!("Can't resolve address {}", &peer); continue; }
}; };
info!("Got addresses: {:?}", &addresses);
// At first we connect to one peer address from every "peer" or domain // At first we connect to 5 peer addresses
let addr = addresses.remove(0); if set.len() >= 10 {
if !set.contains(&addr) { break;
match self.connect_peer(&addr, registry, unique_token, yggdrasil_only) { }
Ok(_) => {
set.insert(addr); while addresses.len() > 0 {
} let addr = addresses.remove(0);
Err(_) => { if !set.contains(&addr) {
debug!("Could not connect to {}", &addr); match self.connect_peer(&addr, registry, unique_token, yggdrasil_only) {
Ok(_) => {
set.insert(addr);
}
Err(_) => {
debug!("Could not connect to {}", &addr);
}
} }
} }
} }
// Copy others to new_peers, to connect later // Copy others to new_peers, to connect later
self.new_peers.append(&mut addresses); if addresses.len() > 0 {
self.new_peers.append(&mut addresses);
}
} }
} }
@@ -356,31 +360,28 @@ impl Peers {
debug!("Ignoring not Yggdrasil address '{}'", &addr.ip()); debug!("Ignoring not Yggdrasil address '{}'", &addr.ip());
return Err(io::Error::from(io::ErrorKind::InvalidInput)); return Err(io::Error::from(io::ErrorKind::InvalidInput));
} }
if let Ok(stream) = std::net::TcpStream::connect_timeout(&addr.clone(), TCP_TIMEOUT) { trace!("Connecting to peer {}", &addr);
stream.set_nodelay(true)?; match TcpStream::connect(addr.clone()) {
stream.set_read_timeout(Some(TCP_TIMEOUT))?; Ok(mut stream ) => {
stream.set_write_timeout(Some(TCP_TIMEOUT))?; //stream.set_nodelay(true)?;
stream.set_nonblocking(true)?; let token = next(unique_token);
trace!("Created connection {}, to peer {}", &token.0, &addr);
let mut stream = TcpStream::from_std(stream); registry.register(&mut stream, token, Interest::WRITABLE).unwrap();
let token = next(unique_token); let mut peer = Peer::new(addr.clone(), stream, State::Connecting, false);
trace!("Created connection {}, to peer {}", &token.0, &addr); peer.set_public(true);
registry.register(&mut stream, token, Interest::WRITABLE)?; self.peers.insert(token, peer);
let mut peer = Peer::new(addr.clone(), stream, State::Connecting, false); Ok(())
peer.set_public(true); }
self.peers.insert(token, peer); Err(e) => { Err(e) }
} }
Ok(())
} }
pub fn update_asked_block_time(&mut self) {
pub fn set_asked_block(&mut self, index: u64) { self.block_asked_time = Utc::now().timestamp();
self.asked_block = index;
self.asked_time = Utc::now().timestamp();
} }
pub fn need_ask_block(&self, index: u64) -> bool { pub fn need_ask_block(&self) -> bool {
index > self.asked_block || self.asked_time + 3 < Utc::now().timestamp() self.block_asked_time + 5 < Utc::now().timestamp()
} }
} }