From 59df68d7c702272c5962c1350bca81b08739ea5e Mon Sep 17 00:00:00 2001 From: Revertron Date: Tue, 2 Mar 2021 19:35:12 +0100 Subject: [PATCH] Added hash of last block to Ping/Pong messages. --- src/blockchain/blockchain.rs | 12 +++++++++--- src/p2p/message.rs | 13 +++++++------ src/p2p/network.rs | 27 ++++++++++++++++----------- src/p2p/peers.rs | 5 +++-- src/settings.rs | 1 - src/utils.rs | 1 - 6 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/blockchain/blockchain.rs b/src/blockchain/blockchain.rs index 6d3b0de..fe63417 100644 --- a/src/blockchain/blockchain.rs +++ b/src/blockchain/blockchain.rs @@ -9,7 +9,7 @@ use std::cell::RefCell; use chrono::Utc; use crate::blockchain::transaction::hash_identity; use crate::blockchain::blockchain::BlockQuality::*; -use crate::blockchain::BLOCK_DIFFICULTY; +use crate::blockchain::{BLOCK_DIFFICULTY, CHAIN_VERSION}; const DB_NAME: &str = "blockchain.db"; @@ -26,10 +26,9 @@ pub struct Blockchain { impl Blockchain { pub fn new(settings: &Settings) -> Self { let origin = settings.get_origin(); - let version = settings.version; let db = sqlite::open(DB_NAME).expect("Unable to open blockchain DB"); - let mut blockchain = Blockchain{ origin, version, blocks: Vec::new(), last_block: None, max_height: 0, db, zones: RefCell::new(HashSet::new()) }; + let mut blockchain = Blockchain{ origin, version: CHAIN_VERSION, blocks: Vec::new(), last_block: None, max_height: 0, db, zones: RefCell::new(HashSet::new()) }; blockchain.init_db(); blockchain } @@ -231,6 +230,13 @@ impl Blockchain { } } + pub fn last_hash(&self) -> Bytes { + match &self.last_block { + None => { Bytes::default() } + Some(block) => { block.hash.clone() } + } + } + pub fn max_height(&self) -> u64 { self.max_height } diff --git a/src/p2p/message.rs b/src/p2p/message.rs index 8309d72..97bc8cf 100644 --- a/src/p2p/message.rs +++ b/src/p2p/message.rs @@ -2,14 +2,15 @@ extern crate serde; extern crate serde_json; use serde::{Deserialize, Serialize}; +use crate::Bytes; #[derive(Debug, Serialize, Deserialize)] pub enum Message { Error, Hand { origin: String, version: u32, public: bool }, Shake { origin: String, version: u32, ok: bool, height: u64 }, - Ping { height: u64 }, - Pong { height: u64 }, + Ping { height: u64, hash: Bytes }, + Pong { height: u64, hash: Bytes }, GetPeers, Peers { peers: Vec }, GetBlock { index: u64 }, @@ -33,12 +34,12 @@ impl Message { Message::Shake { origin: origin.to_owned(), version, ok, height } } - pub fn ping(height: u64) -> Self { - Message::Ping { height } + pub fn ping(height: u64, hash: Bytes) -> Self { + Message::Ping { height, hash } } - pub fn pong(height: u64) -> Self { - Message::Pong { height } + pub fn pong(height: u64, hash: Bytes) -> Self { + Message::Pong { height, hash } } pub fn block(height: u64, str: String) -> Self { diff --git a/src/p2p/network.rs b/src/p2p/network.rs index 4873094..a23ecdd 100644 --- a/src/p2p/network.rs +++ b/src/p2p/network.rs @@ -16,6 +16,7 @@ use log::{trace, debug, info, warn, error}; use crate::{Context, Block, p2p::Message, p2p::State, p2p::Peer, p2p::Peers}; use std::net::{SocketAddr, IpAddr, SocketAddrV4, ToSocketAddrs}; use crate::blockchain::blockchain::BlockQuality; +use crate::blockchain::CHAIN_VERSION; const SERVER: Token = Token(0); const POLL_TIMEOUT: Option = Some(Duration::from_millis(3000)); @@ -102,8 +103,11 @@ impl Network { events.clear(); // Send pings to idle peers - let height = { context.lock().unwrap().blockchain.height() }; - peers.send_pings(poll.registry(), height); + let (height, hash) = { + let context = context.lock().unwrap(); + (context.blockchain.height(), context.blockchain.last_hash()) + }; + peers.send_pings(poll.registry(), height, hash); peers.connect_new_peers(poll.registry(), &mut unique_token); } }); @@ -171,7 +175,7 @@ fn handle_connection_event(context: Arc>, peers: &mut Peers, regi debug!("Sending hello to {}", &peer.get_addr()); let data: String = { let c = context.lock().unwrap(); - let message = Message::hand(&c.settings.origin, c.settings.version, c.settings.public); + let message = Message::hand(&c.settings.origin, CHAIN_VERSION, c.settings.public); serde_json::to_string(&message).unwrap() }; send_message(peer.get_stream(), &data.into_bytes()); @@ -187,7 +191,7 @@ fn handle_connection_event(context: Arc>, peers: &mut Peers, regi if from.elapsed().as_secs() >= 30 { let data: String = { let c = context.lock().unwrap(); - let message = Message::ping(c.blockchain.height()); + let message = Message::ping(c.blockchain.height(), c.blockchain.last_hash()); serde_json::to_string(&message).unwrap() }; send_message(peer.get_stream(), &data.into_bytes()); @@ -258,9 +262,10 @@ fn send_message(connection: &mut TcpStream, data: &Vec) { } fn handle_message(context: Arc>, message: Message, peers: &mut Peers, token: &Token) -> State { - let (my_height, my_origin, my_version) = { + let (my_height, my_hash, my_origin, my_version) = { let context = context.lock().unwrap(); - (context.blockchain.height(), &context.settings.origin.clone(), context.settings.version) + // TODO cache it somewhere + (context.blockchain.height(), context.blockchain.last_hash(), &context.settings.origin.clone(), CHAIN_VERSION) }; match message { Message::Hand { origin, version, public } => { @@ -297,21 +302,21 @@ fn handle_message(context: Arc>, message: Message, peers: &mut Pe } } Message::Error => { State::Error } - Message::Ping { height } => { + Message::Ping { height, hash } => { let peer = peers.get_mut_peer(token).unwrap(); peer.set_height(height); peer.set_active(true); - if peer.is_higher(my_height) { + if peer.is_higher(my_height) || my_hash.ne(&hash) { State::message(Message::GetBlock { index: my_height }) } else { - State::message(Message::pong(my_height)) + State::message(Message::pong(my_height, my_hash)) } } - Message::Pong { height } => { + Message::Pong { height, hash } => { let peer = peers.get_mut_peer(token).unwrap(); peer.set_height(height); peer.set_active(true); - if peer.is_higher(my_height) { + if peer.is_higher(my_height) || my_hash.ne(&hash) { State::message(Message::GetBlock { index: my_height }) } else { let mut context = context.lock().unwrap(); diff --git a/src/p2p/peers.rs b/src/p2p/peers.rs index 8696928..5ccb09b 100644 --- a/src/p2p/peers.rs +++ b/src/p2p/peers.rs @@ -9,6 +9,7 @@ use rand::random; use rand::seq::IteratorRandom; #[allow(unused_imports)] use log::{trace, debug, info, warn, error}; +use crate::Bytes; pub struct Peers { peers: HashMap, @@ -132,7 +133,7 @@ impl Peers { false } - pub fn send_pings(&mut self, registry: &Registry, height: u64) { + pub fn send_pings(&mut self, registry: &Registry, height: u64, hash: Bytes) { let mut ping_sent = false; for (token, peer) in self.peers.iter_mut() { match peer.get_state() { @@ -143,7 +144,7 @@ impl Peers { let message = if random < 16 { Message::GetPeers } else { - Message::ping(height) + Message::ping(height, hash.clone()) }; peer.set_state(State::message(message)); diff --git a/src/settings.rs b/src/settings.rs index 2f50aa1..3fc8140 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -8,7 +8,6 @@ use crate::Bytes; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Settings { pub origin: String, - pub version: u32, pub key_file: String, pub listen: String, pub public: bool, diff --git a/src/utils.rs b/src/utils.rs index 77cf2bc..6de4033 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,5 +1,4 @@ use std::num; -use rand::Rng; use num_bigint::BigUint; use num_traits::One;