Added hash of last block to Ping/Pong messages.
This commit is contained in:
@@ -9,7 +9,7 @@ use std::cell::RefCell;
|
|||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use crate::blockchain::transaction::hash_identity;
|
use crate::blockchain::transaction::hash_identity;
|
||||||
use crate::blockchain::blockchain::BlockQuality::*;
|
use crate::blockchain::blockchain::BlockQuality::*;
|
||||||
use crate::blockchain::BLOCK_DIFFICULTY;
|
use crate::blockchain::{BLOCK_DIFFICULTY, CHAIN_VERSION};
|
||||||
|
|
||||||
const DB_NAME: &str = "blockchain.db";
|
const DB_NAME: &str = "blockchain.db";
|
||||||
|
|
||||||
@@ -26,10 +26,9 @@ pub struct Blockchain {
|
|||||||
impl Blockchain {
|
impl Blockchain {
|
||||||
pub fn new(settings: &Settings) -> Self {
|
pub fn new(settings: &Settings) -> Self {
|
||||||
let origin = settings.get_origin();
|
let origin = settings.get_origin();
|
||||||
let version = settings.version;
|
|
||||||
|
|
||||||
let db = sqlite::open(DB_NAME).expect("Unable to open blockchain DB");
|
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.init_db();
|
||||||
blockchain
|
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 {
|
pub fn max_height(&self) -> u64 {
|
||||||
self.max_height
|
self.max_height
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-6
@@ -2,14 +2,15 @@ extern crate serde;
|
|||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use crate::Bytes;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
Error,
|
Error,
|
||||||
Hand { origin: String, version: u32, public: bool },
|
Hand { origin: String, version: u32, public: bool },
|
||||||
Shake { origin: String, version: u32, ok: bool, height: u64 },
|
Shake { origin: String, version: u32, ok: bool, height: u64 },
|
||||||
Ping { height: u64 },
|
Ping { height: u64, hash: Bytes },
|
||||||
Pong { height: u64 },
|
Pong { height: u64, hash: Bytes },
|
||||||
GetPeers,
|
GetPeers,
|
||||||
Peers { peers: Vec<String> },
|
Peers { peers: Vec<String> },
|
||||||
GetBlock { index: u64 },
|
GetBlock { index: u64 },
|
||||||
@@ -33,12 +34,12 @@ impl Message {
|
|||||||
Message::Shake { origin: origin.to_owned(), version, ok, height }
|
Message::Shake { origin: origin.to_owned(), version, ok, height }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ping(height: u64) -> Self {
|
pub fn ping(height: u64, hash: Bytes) -> Self {
|
||||||
Message::Ping { height }
|
Message::Ping { height, hash }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pong(height: u64) -> Self {
|
pub fn pong(height: u64, hash: Bytes) -> Self {
|
||||||
Message::Pong { height }
|
Message::Pong { height, hash }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn block(height: u64, str: String) -> Self {
|
pub fn block(height: u64, str: String) -> Self {
|
||||||
|
|||||||
+16
-11
@@ -16,6 +16,7 @@ use log::{trace, debug, info, warn, error};
|
|||||||
use crate::{Context, Block, p2p::Message, p2p::State, p2p::Peer, p2p::Peers};
|
use crate::{Context, Block, p2p::Message, p2p::State, p2p::Peer, p2p::Peers};
|
||||||
use std::net::{SocketAddr, IpAddr, SocketAddrV4, ToSocketAddrs};
|
use std::net::{SocketAddr, IpAddr, SocketAddrV4, ToSocketAddrs};
|
||||||
use crate::blockchain::blockchain::BlockQuality;
|
use crate::blockchain::blockchain::BlockQuality;
|
||||||
|
use crate::blockchain::CHAIN_VERSION;
|
||||||
|
|
||||||
const SERVER: Token = Token(0);
|
const SERVER: Token = Token(0);
|
||||||
const POLL_TIMEOUT: Option<Duration> = Some(Duration::from_millis(3000));
|
const POLL_TIMEOUT: Option<Duration> = Some(Duration::from_millis(3000));
|
||||||
@@ -102,8 +103,11 @@ impl Network {
|
|||||||
events.clear();
|
events.clear();
|
||||||
|
|
||||||
// Send pings to idle peers
|
// Send pings to idle peers
|
||||||
let height = { context.lock().unwrap().blockchain.height() };
|
let (height, hash) = {
|
||||||
peers.send_pings(poll.registry(), height);
|
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);
|
peers.connect_new_peers(poll.registry(), &mut unique_token);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -171,7 +175,7 @@ fn handle_connection_event(context: Arc<Mutex<Context>>, peers: &mut Peers, regi
|
|||||||
debug!("Sending hello to {}", &peer.get_addr());
|
debug!("Sending hello to {}", &peer.get_addr());
|
||||||
let data: String = {
|
let data: String = {
|
||||||
let c = context.lock().unwrap();
|
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()
|
serde_json::to_string(&message).unwrap()
|
||||||
};
|
};
|
||||||
send_message(peer.get_stream(), &data.into_bytes());
|
send_message(peer.get_stream(), &data.into_bytes());
|
||||||
@@ -187,7 +191,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.blockchain.height());
|
let message = Message::ping(c.blockchain.height(), c.blockchain.last_hash());
|
||||||
serde_json::to_string(&message).unwrap()
|
serde_json::to_string(&message).unwrap()
|
||||||
};
|
};
|
||||||
send_message(peer.get_stream(), &data.into_bytes());
|
send_message(peer.get_stream(), &data.into_bytes());
|
||||||
@@ -258,9 +262,10 @@ fn send_message(connection: &mut TcpStream, data: &Vec<u8>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_message(context: Arc<Mutex<Context>>, message: Message, peers: &mut Peers, token: &Token) -> State {
|
fn handle_message(context: Arc<Mutex<Context>>, 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();
|
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 {
|
match message {
|
||||||
Message::Hand { origin, version, public } => {
|
Message::Hand { origin, version, public } => {
|
||||||
@@ -297,21 +302,21 @@ fn handle_message(context: Arc<Mutex<Context>>, message: Message, peers: &mut Pe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::Error => { State::Error }
|
Message::Error => { State::Error }
|
||||||
Message::Ping { height } => {
|
Message::Ping { height, hash } => {
|
||||||
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);
|
||||||
if peer.is_higher(my_height) {
|
if peer.is_higher(my_height) || my_hash.ne(&hash) {
|
||||||
State::message(Message::GetBlock { index: my_height })
|
State::message(Message::GetBlock { index: my_height })
|
||||||
} else {
|
} 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();
|
let peer = peers.get_mut_peer(token).unwrap();
|
||||||
peer.set_height(height);
|
peer.set_height(height);
|
||||||
peer.set_active(true);
|
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 })
|
State::message(Message::GetBlock { index: my_height })
|
||||||
} else {
|
} else {
|
||||||
let mut context = context.lock().unwrap();
|
let mut context = context.lock().unwrap();
|
||||||
|
|||||||
+3
-2
@@ -9,6 +9,7 @@ use rand::random;
|
|||||||
use rand::seq::IteratorRandom;
|
use rand::seq::IteratorRandom;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use log::{trace, debug, info, warn, error};
|
use log::{trace, debug, info, warn, error};
|
||||||
|
use crate::Bytes;
|
||||||
|
|
||||||
pub struct Peers {
|
pub struct Peers {
|
||||||
peers: HashMap<Token, Peer>,
|
peers: HashMap<Token, Peer>,
|
||||||
@@ -132,7 +133,7 @@ impl Peers {
|
|||||||
false
|
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;
|
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() {
|
||||||
@@ -143,7 +144,7 @@ impl Peers {
|
|||||||
let message = if random < 16 {
|
let message = if random < 16 {
|
||||||
Message::GetPeers
|
Message::GetPeers
|
||||||
} else {
|
} else {
|
||||||
Message::ping(height)
|
Message::ping(height, hash.clone())
|
||||||
};
|
};
|
||||||
|
|
||||||
peer.set_state(State::message(message));
|
peer.set_state(State::message(message));
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ use crate::Bytes;
|
|||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
pub origin: String,
|
pub origin: String,
|
||||||
pub version: u32,
|
|
||||||
pub key_file: String,
|
pub key_file: String,
|
||||||
pub listen: String,
|
pub listen: String,
|
||||||
pub public: bool,
|
pub public: bool,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use std::num;
|
use std::num;
|
||||||
use rand::Rng;
|
|
||||||
use num_bigint::BigUint;
|
use num_bigint::BigUint;
|
||||||
use num_traits::One;
|
use num_traits::One;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user