diff --git a/.gitignore b/.gitignore index 5bd6240..6323725 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,6 @@ Cargo.lock /bak *.gz -massif* \ No newline at end of file +massif* + +.vscode/ diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..32a9786 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1 @@ +edition = "2018" diff --git a/README.md b/README.md index 81b371c..9589235 100644 --- a/README.md +++ b/README.md @@ -7,18 +7,18 @@ Tolerant consensus algorithm](https://github.com/poanetwork/hbbft). ### Running a test peer -1. `git clone https://github.com/poanetwork/hydrabadger` -2. `cd hydrabadger` -3. `./run-node 0` +1. `git clone https://github.com/poanetwork/hydrabadger` +2. `cd hydrabadger` +3. `./run-node 0` #### Additional peers -1. Open a new terminal window. -2. `cd {...}/hydrabadger` -3. `./run-node 1` -4. (Repeat 1 and 2), `./run-node 2`, `./run-node 3`, `./run-node 4` - * Note: If your terminal has tabs, open multiple tabs and use - ctrl-pgup/pgdown to cycle between tabs quickly. +1. Open a new terminal window. +2. `cd {...}/hydrabadger` +3. `./run-node 1` +4. (Repeat 1 and 2), `./run-node 2`, `./run-node 3`, `./run-node 4` + - Note: If your terminal has tabs, open multiple tabs and use + ctrl-pgup/pgdown to cycle between tabs quickly. Each peer will generate a number of random transactions at regular intervals, process them accordingly, and output complete batches. If your terminal is @@ -43,16 +43,16 @@ very well yet. ### Unimplemented -* **Many edge cases and exceptions:** disconnects, reconnects, etc. - * Connecting to a network which is in the process of key generation causes - the entire network to fail. For now, wait until the network starts - outputting batches before connecting additional peer nodes. -* **Error handling** is atrocious, most errors are simply printed to the log. -* **Usage as a library** is still a work in progress as the API settles. -* **Much, much more...** +- **Many edge cases and exceptions:** disconnects, reconnects, etc. + - Connecting to a network which is in the process of key generation causes + the entire network to fail. For now, wait until the network starts + outputting batches before connecting additional peer nodes. +- **Error handling** is atrocious, most errors are simply printed to the log. +- **Usage as a library** is still a work in progress as the API settles. +- **Much, much more...** ### License [![License: LGPL v3.0](https://img.shields.io/badge/License-LGPL%20v3-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0) -This project is licensed under the GNU Lesser General Public License v3.0. See the [LICENSE](LICENSE) file for details. \ No newline at end of file +This project is licensed under the GNU Lesser General Public License v3.0. See the [LICENSE](LICENSE) file for details. diff --git a/src/bin/peer_node.rs b/src/bin/peer_node.rs index 925fc6c..8cd2177 100644 --- a/src/bin/peer_node.rs +++ b/src/bin/peer_node.rs @@ -11,7 +11,7 @@ extern crate serde_derive; use chrono::Local; use clap::{App, Arg, ArgMatches}; use hydrabadger::{Blockchain, Config, Hydrabadger, MiningError, Uid}; -use rand::{Rng, distributions::Standard}; +use rand::{distributions::Standard, Rng}; use std::collections::HashSet; use std::env; use std::io::Write; @@ -97,7 +97,12 @@ pub struct Transaction(pub Vec); impl Transaction { fn random(len: usize) -> Transaction { - Transaction(rand::thread_rng().sample_iter(&Standard).take(len).collect()) + Transaction( + rand::thread_rng() + .sample_iter(&Standard) + .take(len) + .collect(), + ) } } diff --git a/src/hydrabadger/handler.rs b/src/hydrabadger/handler.rs index 51147f0..3034542 100644 --- a/src/hydrabadger/handler.rs +++ b/src/hydrabadger/handler.rs @@ -9,7 +9,7 @@ use super::{Error, Hydrabadger, InputOrMessage, State, StateDsct, StateMachine}; use crate::peer::Peers; use crate::{ key_gen, BatchTx, Contribution, InAddr, InternalMessage, InternalMessageKind, InternalRx, - NetworkState, OutAddr, Step, Uid, WireMessage, WireMessageKind, NodeId, + NetworkState, NodeId, OutAddr, Step, Uid, WireMessage, WireMessageKind, }; use crossbeam::queue::SegQueue; use hbbft::{ @@ -90,7 +90,11 @@ impl Handler { Ok(()) } - fn handle_iom(&self, iom: InputOrMessage, state: &mut StateMachine) -> Result<(), Error> { + fn handle_iom( + &self, + iom: InputOrMessage, + state: &mut StateMachine, + ) -> Result<(), Error> { trace!("hydrabadger::Handler: About to handle_iom: {:?}", iom); if let Some(step_res) = state.handle_iom(iom) { let step = step_res.map_err(Error::HbStep)?; @@ -518,7 +522,7 @@ impl Handler { let peers = self.hdb.peers(); let new_id = Uid::new(); // tx.unbounded_send(key_gen::Message::instance_id().unwrap(); - let instance_id = key_gen::InstanceId::User(new_id.clone()); + let instance_id = key_gen::InstanceId::User(new_id); let key_gen = key_gen::Machine::generate( self.hdb.node_id(), self.hdb.secret_key().clone(), @@ -541,9 +545,10 @@ impl Handler { ) => { debug!("Received hello from {:?}", src_nid_new); let mut peers = self.hdb.peers_mut(); - match peers - .establish_validator(src_out_addr, (src_nid_new.clone(), src_in_addr, src_pk)) - { + match peers.establish_validator( + src_out_addr, + (src_nid_new.clone(), src_in_addr, src_pk), + ) { true => debug_assert!(src_nid_new == src_nid.unwrap()), false => debug_assert!(src_nid.is_none()), } @@ -738,7 +743,10 @@ impl Future for Handler { ); } Target::All => { - peers.wire_to_all(WireMessage::message(self.hdb.node_id().clone(), hb_msg.message)); + peers.wire_to_all(WireMessage::message( + self.hdb.node_id().clone(), + hb_msg.message, + )); } } } diff --git a/src/hydrabadger/hydrabadger.rs b/src/hydrabadger/hydrabadger.rs index d56f0a4..eb04c54 100644 --- a/src/hydrabadger/hydrabadger.rs +++ b/src/hydrabadger/hydrabadger.rs @@ -1,12 +1,11 @@ //! A hydrabadger consensus node. //! -use serde::de::DeserializeOwned; use super::{Error, Handler, StateDsct, StateMachine}; use crate::peer::{PeerHandler, Peers}; use crate::{ key_gen, BatchRx, Change, Contribution, EpochRx, EpochTx, InAddr, InternalMessage, InternalTx, - OutAddr, WireMessage, WireMessageKind, WireMessages, NodeId, + NodeId, OutAddr, WireMessage, WireMessageKind, WireMessages, }; use futures::{ future::{self, Either}, @@ -14,7 +13,7 @@ use futures::{ }; use hbbft::crypto::{PublicKey, SecretKey}; use parking_lot::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard}; -use rand::{self, Rng}; +use serde::de::DeserializeOwned; use std::{ collections::HashSet, net::SocketAddr, @@ -122,7 +121,7 @@ pub struct Hydrabadger { impl Hydrabadger { /// Returns a new Hydrabadger node. pub fn new(addr: SocketAddr, cfg: Config, nid: N) -> Self { - let secret_key: SecretKey = rand::rngs::OsRng::new().expect("Unable to create rng").gen(); + let secret_key = SecretKey::random(); let (peer_internal_tx, peer_internal_rx) = mpsc::unbounded(); let (batch_tx, batch_rx) = mpsc::unbounded(); @@ -310,7 +309,8 @@ impl Hydrabadger /// Returns a future that handles incoming connections on `socket`. fn handle_incoming(self, socket: TcpStream) -> impl Future { info!("Incoming connection from '{}'", socket.peer_addr().unwrap()); - let wire_msgs: WireMessages = WireMessages::new(socket, self.inner.secret_key.clone()); + let wire_msgs: WireMessages = + WireMessages::new(socket, self.inner.secret_key.clone()); wire_msgs .into_future() diff --git a/src/hydrabadger/key_gen.rs b/src/hydrabadger/key_gen.rs index 74fdf84..376fc46 100644 --- a/src/hydrabadger/key_gen.rs +++ b/src/hydrabadger/key_gen.rs @@ -3,7 +3,7 @@ use super::Error; use crate::hydrabadger::hydrabadger::Hydrabadger; use crate::peer::Peers; -use crate::{Contribution, NetworkState, Uid, WireMessage, NodeId}; +use crate::{Contribution, NetworkState, NodeId, Uid, WireMessage}; use crossbeam::queue::SegQueue; use futures::sync::mpsc; use hbbft::{ @@ -64,7 +64,6 @@ pub(super) enum State { sync_key_gen: Option>, public_key: Option, public_keys: BTreeMap, - part_count: usize, ack_count: usize, }, @@ -75,7 +74,12 @@ pub(super) enum State { } /// Forwards an `Ack` to a `SyncKeyGen` instance. -fn handle_ack(nid: &N, ack: Ack, ack_count: &mut usize, sync_key_gen: &mut SyncKeyGen) { +fn handle_ack( + nid: &N, + ack: Ack, + ack_count: &mut usize, + sync_key_gen: &mut SyncKeyGen, +) { trace!("KEY GENERATION: Handling ack from '{:?}'...", nid); let ack_outcome = sync_key_gen .handle_ack(nid, ack.clone()) diff --git a/src/hydrabadger/state.rs b/src/hydrabadger/state.rs index e8eaafd..907695e 100644 --- a/src/hydrabadger/state.rs +++ b/src/hydrabadger/state.rs @@ -7,7 +7,7 @@ use super::{key_gen, Config, Error, InputOrMessage}; use crate::peer::Peers; -use crate::{ActiveNetworkInfo, Contribution, NetworkNodeInfo, NetworkState, Step, NodeId}; +use crate::{ActiveNetworkInfo, Contribution, NetworkNodeInfo, NetworkState, NodeId, Step}; use crossbeam::queue::SegQueue; use hbbft::{ crypto::{PublicKey, SecretKey}, @@ -208,8 +208,12 @@ impl StateMachine { State::DeterminingNetworkState { ref mut iom_queue, .. } => { - let (dhb, dhb_step) = - DynamicHoneyBadger::new_joining(local_nid, local_sk, jp, &mut StdRng::from_entropy())?; + let (dhb, dhb_step) = DynamicHoneyBadger::new_joining( + local_nid, + local_sk, + jp, + &mut StdRng::from_entropy(), + )?; step_queue.push(dhb_step); iom_queue_ret = iom_queue.take().unwrap(); @@ -275,7 +279,12 @@ impl StateMachine { let mut node_ids: BTreeMap = peers .validators() - .map(|p| (p.node_id().cloned().unwrap(), p.public_key().cloned().unwrap())) + .map(|p| { + ( + p.node_id().cloned().unwrap(), + p.public_key().cloned().unwrap(), + ) + }) .collect(); node_ids.insert(local_nid.clone(), local_sk.public_key()); @@ -391,8 +400,11 @@ impl StateMachine { let peer_infos = peers .peers() .filter_map(|peer| { - peer.pub_info() - .map(|(nid, &in_addr, &pk)| NetworkNodeInfo { nid: nid.clone(), in_addr, pk }) + peer.pub_info().map(|(nid, &in_addr, &pk)| NetworkNodeInfo { + nid: nid.clone(), + in_addr, + pk, + }) }) .collect::>(); match self.state { @@ -467,7 +479,9 @@ impl StateMachine { match iom { InputOrMessage::Contribution(contrib) => dhb.propose(contrib, &mut rng), InputOrMessage::Change(change) => dhb.vote_for(change), - InputOrMessage::Message(src_nid, msg) => dhb.handle_message(&src_nid, msg, &mut rng), + InputOrMessage::Message(src_nid, msg) => { + dhb.handle_message(&src_nid, msg, &mut rng) + } } }); diff --git a/src/lib.rs b/src/lib.rs index 0935202..adeb8a7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,8 +23,8 @@ extern crate env_logger; extern crate log; #[macro_use] extern crate failure; -extern crate crossbeam; extern crate chrono; +extern crate crossbeam; extern crate crypto; extern crate num_bigint; extern crate num_traits; @@ -69,7 +69,10 @@ use hbbft::{ sync_key_gen::{Ack, Part}, Contribution as HbbftContribution, CpStep as MessagingStep, NodeIdT, }; -use rand::{distributions::{Standard, Distribution}, Rng}; +use rand::{ + distributions::{Distribution, Standard}, + Rng, +}; use serde::{de::DeserializeOwned, Serialize}; use std::{ collections::BTreeMap, @@ -146,8 +149,14 @@ pub struct Uid(pub(crate) Uuid); impl Uid { /// Returns a new, random `Uid`. - pub fn new() -> Uid { - Uid(Uuid::new_v4()) + pub fn new() -> Self { + Self::default() + } +} + +impl Default for Uid { + fn default() -> Self { + Self(Uuid::new_v4()) } } @@ -215,7 +224,11 @@ pub struct NetworkNodeInfo { pub(crate) pk: PublicKey, } -type ActiveNetworkInfo = (Vec>, PublicKeySet, BTreeMap); +type ActiveNetworkInfo = ( + Vec>, + PublicKeySet, + BTreeMap, +); /// The current state of the network. #[derive(Clone, Debug, Serialize, Deserialize)] @@ -474,7 +487,10 @@ impl InternalMessage { } /// Returns a new `InternalMessage` without a uid. - pub fn new_without_uid(src_addr: OutAddr, kind: InternalMessageKind) -> InternalMessage { + pub fn new_without_uid( + src_addr: OutAddr, + kind: InternalMessageKind, + ) -> InternalMessage { InternalMessage::new(None, src_addr, kind) } diff --git a/src/peer.rs b/src/peer.rs index f2b6334..413e21b 100644 --- a/src/peer.rs +++ b/src/peer.rs @@ -4,14 +4,11 @@ use crate::hydrabadger::{Error, Hydrabadger}; use crate::{ - Contribution, InAddr, InternalMessage, OutAddr, Uid, WireMessage, WireMessageKind, - WireMessages, WireRx, WireTx, NodeId, + Contribution, InAddr, InternalMessage, NodeId, OutAddr, Uid, WireMessage, WireMessageKind, + WireMessages, WireRx, WireTx, }; use futures::sync::mpsc; -use hbbft::{ - crypto::PublicKey, - dynamic_honey_badger::Input as HbInput, -}; +use hbbft::{crypto::PublicKey, dynamic_honey_badger::Input as HbInput}; use serde::{Deserialize, Serialize}; use std::{ borrow::Borrow, @@ -135,7 +132,11 @@ impl Future for PeerHandler { self.hdb.send_internal(InternalMessage::wire( Some(src_nid.clone()), self.out_addr, - WireMessage::welcome_received_change_add(src_nid.clone(), pk, net_state), + WireMessage::welcome_received_change_add( + src_nid.clone(), + pk, + net_state, + ), )); } WireMessageKind::HelloFromValidator(src_nid, in_addr, pk, net_state) => { @@ -144,7 +145,12 @@ impl Future for PeerHandler { self.hdb.send_internal(InternalMessage::wire( Some(src_nid.clone()), self.out_addr, - WireMessage::hello_from_validator(src_nid.clone(), in_addr, pk, net_state), + WireMessage::hello_from_validator( + src_nid.clone(), + in_addr, + pk, + net_state, + ), )); } WireMessageKind::Message(src_nid, msg) => { @@ -274,9 +280,15 @@ impl Peer { /// Sets a peer state to `State::EstablishedObserver` and stores public info. fn establish_observer(&mut self) { self.state = match self.state { - State::PendingJoinInfo { ref nid, in_addr, pk } => { - State::EstablishedObserver { nid: nid.clone(), in_addr, pk } - } + State::PendingJoinInfo { + ref nid, + in_addr, + pk, + } => State::EstablishedObserver { + nid: nid.clone(), + in_addr, + pk, + }, _ => panic!( "Peer::establish_observer: Can only establish observer when \ peer state is`PendingJoinInfo`." @@ -300,14 +312,22 @@ impl Peer { ); } }, - State::EstablishedObserver { ref nid, in_addr, pk } => { + State::EstablishedObserver { + ref nid, + in_addr, + pk, + } => { if pub_info.is_some() { panic!( "Peer::establish_validator: `pub_info` must be `None` \ when upgrading an observer node." ); } - State::EstablishedValidator { nid: nid.clone(), in_addr, pk } + State::EstablishedValidator { + nid: nid.clone(), + in_addr, + pk, + } } _ => panic!( "Peer::establish_validator: Can only establish validator when \ @@ -457,7 +477,10 @@ impl Peers { No peer found with outgoing address: {}", out_addr.borrow() )); - match self.out_addrs.insert(pub_info.0.clone(), *out_addr.borrow()) { + match self + .out_addrs + .insert(pub_info.0.clone(), *out_addr.borrow()) + { Some(_out_addr_pub) => { let pi_pub = peer .pub_info() @@ -512,7 +535,10 @@ impl Peers { No peer found with outgoing address: {}", out_addr.borrow() )); - match self.out_addrs.insert(pub_info.0.clone(), *out_addr.borrow()) { + match self + .out_addrs + .insert(pub_info.0.clone(), *out_addr.borrow()) + { Some(_out_addr_pub) => { let pi_pub = peer .pub_info()