Implemented P2P traffic encryption.

Changed serialization format of P2P messages.
Refactored P2P network code.
This commit is contained in:
Revertron
2021-05-30 00:33:13 +02:00
parent 5398410d8d
commit 319051edbd
15 changed files with 857 additions and 493 deletions
+10 -28
View File
@@ -7,8 +7,8 @@ use crate::Bytes;
#[derive(Debug, Serialize, Deserialize)]
pub enum Message {
Error,
Hand { #[serde(default = "default_version")] app_version: String, origin: String, version: u32, public: bool, #[serde(default)] rand: String },
Shake { #[serde(default = "default_version")] app_version: String, origin: String, version: u32, ok: bool, height: u64 },
Hand { app_version: String, origin: String, version: u32, public: bool, rand_id: String, },
Shake { app_version: String, origin: String, version: u32, public: bool, rand_id: String, height: u64 },
Ping { height: u64, hash: Bytes },
Pong { height: u64, hash: Bytes },
Twin,
@@ -16,24 +16,23 @@ pub enum Message {
GetPeers,
Peers { peers: Vec<String> },
GetBlock { index: u64 },
Block { index: u64, block: String },
Block { index: u64, block: Vec<u8> },
}
impl Message {
pub fn from_bytes(bytes: Vec<u8>) -> Result<Self, ()> {
let text = String::from_utf8(bytes).unwrap_or(String::from("Error{}"));
match serde_json::from_str(&text) {
match serde_cbor::from_slice(bytes.as_slice()) {
Ok(cmd) => Ok(cmd),
Err(_) => Err(())
}
}
pub fn hand(app_version: &str, origin: &str, version: u32, public: bool, rand: &str) -> Self {
Message::Hand { app_version: app_version.to_owned(), origin: origin.to_owned(), version, public, rand: rand.to_owned() }
pub fn hand(app_version: &str, origin: &str, version: u32, public: bool, rand_id: &str) -> Self {
Message::Hand { app_version: app_version.to_owned(), origin: origin.to_owned(), version, public, rand_id: rand_id.to_owned() }
}
pub fn shake(app_version: &str, origin: &str, version: u32, ok: bool, height: u64) -> Self {
Message::Shake { app_version: app_version.to_owned(), origin: origin.to_owned(), version, ok, height }
pub fn shake(app_version: &str, origin: &str, version: u32, public: bool, rand_id: &str, height: u64) -> Self {
Message::Shake { app_version: app_version.to_owned(), origin: origin.to_owned(), version, public, rand_id: rand_id.to_owned(), height }
}
pub fn ping(height: u64, hash: Bytes) -> Self {
@@ -44,24 +43,7 @@ impl Message {
Message::Pong { height, hash }
}
pub fn block(height: u64, str: String) -> Self {
Message::Block { index: height, block: str }
pub fn block(height: u64, block: Vec<u8>) -> Self {
Message::Block { index: height, block }
}
}
fn default_version() -> String {
String::from("0.0.0")
}
#[cfg(test)]
mod tests {
use crate::p2p::Message;
#[test]
pub fn test_hand() {
assert!(serde_json::from_str::<Message>("\"Error\"").is_ok());
assert!(serde_json::from_str::<Message>("{\"Hand\":{\"origin\":\"\",\"version\":1,\"public\":false,\"rand\":\"123\"}}").is_ok());
assert!(serde_json::from_str::<Message>("{\"Hand\":{\"origin\":\"\",\"version\":1,\"public\":false}}").is_ok());
}
}
+683 -441
View File
File diff suppressed because it is too large Load Diff
+18
View File
@@ -3,6 +3,7 @@ use std::collections::HashMap;
use mio::net::TcpStream;
use crate::p2p::State;
use crate::Block;
use crate::crypto::Chacha;
#[derive(Debug)]
pub struct Peer {
@@ -16,6 +17,7 @@ pub struct Peer {
active: bool,
reconnects: u32,
received_block: u64,
cipher: Option<Chacha>,
fork: HashMap<u64, Block>
}
@@ -32,10 +34,26 @@ impl Peer {
active: false,
reconnects: 0,
received_block: 0,
cipher: None,
fork: HashMap::new()
}
}
pub fn set_cipher(&mut self, cipher: Chacha) {
self.cipher = Some(cipher);
}
pub fn get_cipher(&self) -> &Option<Chacha> {
&self.cipher
}
pub fn get_nonce(&self) -> &[u8; 12] {
match &self.cipher {
None => { &crate::crypto::ZERO_NONCE }
Some(chacha) => { chacha.get_nonce() }
}
}
pub fn get_addr(&self) -> SocketAddr {
self.addr.clone()
}
+22 -1
View File
@@ -12,7 +12,6 @@ use rand::seq::IteratorRandom;
use crate::{Bytes, commons};
use crate::commons::*;
use crate::p2p::{Message, Peer, State};
use crate::commons::next;
use std::io;
const PING_PERIOD: u64 = 30;
@@ -84,6 +83,12 @@ impl Peers {
State::Twin => {
info!("Peer connection {} to {:?} is a twin", &token.0, &peer.get_addr());
}
State::ServerHandshake => {
info!("Peer connection {} from {:?} didn't shake hands", &token.0, &peer.get_addr());
}
State::HandshakeFinished => {
info!("Peer connection {} from {:?} shaked hands, but then failed", &token.0, &peer.get_addr());
}
}
self.peers.remove(token);
@@ -193,6 +198,15 @@ impl Peers {
count
}
pub fn is_tween_connect(&self, id: &str) -> bool {
for (_, peer) in self.peers.iter() {
if peer.active() && peer.get_id() == id {
return true;
}
}
false
}
pub fn get_peers_banned_count(&self) -> usize {
self.ignored.len()
}
@@ -401,6 +415,13 @@ impl Peers {
}
}
/// Gets new token from old token, mutating the last
pub fn next(current: &mut Token) -> Token {
let next = current.0;
current.0 += 1;
Token(next)
}
fn skip_private_addr(addr: &SocketAddr) -> bool {
if addr.ip().is_loopback() {
return true;
+4 -2
View File
@@ -5,6 +5,8 @@ use crate::p2p::Message;
pub enum State {
Connecting,
Connected,
ServerHandshake,
HandshakeFinished,
Idle { from: Instant },
Message { data: Vec<u8> },
Error,
@@ -25,8 +27,8 @@ impl State {
}
pub fn message(message: Message) -> Self {
let response = serde_json::to_string(&message).unwrap();
State::Message {data: Vec::from(response.as_bytes()) }
let data = serde_cbor::to_vec(&message).unwrap();
State::Message { data }
}
pub fn is_idle(&self) -> bool {