2018-03-16 11:12:14 -07:00
|
|
|
//! Networking controls of the consensus node.
|
2018-04-01 14:29:12 -07:00
|
|
|
use std::collections::HashSet;
|
2018-03-16 11:12:14 -07:00
|
|
|
use std::fmt::Debug;
|
2018-03-22 15:47:44 -07:00
|
|
|
use std::hash::Hash;
|
2018-03-16 14:04:06 -07:00
|
|
|
use std::marker::{Send, Sync};
|
2018-04-02 13:26:40 -07:00
|
|
|
use std::net::SocketAddr;
|
2018-03-20 09:32:19 -07:00
|
|
|
use crossbeam;
|
2018-04-02 13:26:40 -07:00
|
|
|
use crossbeam_channel as channel;
|
2018-03-20 09:32:19 -07:00
|
|
|
|
2018-04-01 14:29:12 -07:00
|
|
|
use connection;
|
2018-03-19 10:12:20 -07:00
|
|
|
use broadcast;
|
2018-03-16 14:04:06 -07:00
|
|
|
use proto::Message;
|
2018-03-19 10:12:20 -07:00
|
|
|
use commst;
|
2018-03-16 11:12:14 -07:00
|
|
|
|
|
|
|
/// This is a structure to start a consensus node.
|
2018-03-27 13:59:38 -07:00
|
|
|
pub struct Node<T> {
|
2018-03-16 11:12:14 -07:00
|
|
|
/// Incoming connection socket.
|
|
|
|
addr: SocketAddr,
|
2018-03-16 17:36:32 -07:00
|
|
|
/// Sockets of remote nodes. TODO.
|
2018-04-01 14:29:12 -07:00
|
|
|
remotes: HashSet<SocketAddr>,
|
2018-03-27 13:59:38 -07:00
|
|
|
/// Optionally, a value to be broadcast by this node.
|
|
|
|
value: Option<T>
|
2018-03-16 11:12:14 -07:00
|
|
|
}
|
|
|
|
|
2018-03-27 13:59:38 -07:00
|
|
|
impl<T: Clone + Debug + Eq + Hash + Send + Sync + From<Vec<u8>> + AsRef<[u8]>>
|
|
|
|
Node<T>
|
|
|
|
where Vec<u8>: From<T>
|
|
|
|
{
|
|
|
|
/// Consensus node constructor. It only initialises initial parameters.
|
2018-04-01 14:29:12 -07:00
|
|
|
pub fn new(addr: SocketAddr,
|
|
|
|
remotes: HashSet<SocketAddr>,
|
|
|
|
value: Option<T>) -> Self
|
2018-03-27 13:59:38 -07:00
|
|
|
{
|
|
|
|
Node {addr, remotes, value}
|
2018-03-16 11:12:14 -07:00
|
|
|
}
|
|
|
|
|
2018-03-27 13:59:38 -07:00
|
|
|
/// Consensus node procedure implementing HoneyBadgerBFT.
|
|
|
|
pub fn run(&self) -> Result<T, ()>
|
2018-03-19 10:12:20 -07:00
|
|
|
{
|
2018-04-02 13:26:40 -07:00
|
|
|
// Multiple-producer, multiple-consumer channel from comms tasks to
|
2018-04-03 04:53:59 -07:00
|
|
|
// all algorithm actor tasks such as Reliable Broadcast.
|
2018-04-02 13:26:40 -07:00
|
|
|
let (from_comms_tx, from_comms_rx):
|
|
|
|
(
|
2018-04-03 15:08:26 -07:00
|
|
|
channel::Sender<(usize, Message<T>)>,
|
|
|
|
channel::Receiver<(usize, Message<T>)>
|
2018-04-02 13:26:40 -07:00
|
|
|
) = channel::unbounded();
|
|
|
|
let (from_comms_tx, from_comms_rx) = (&from_comms_tx, &from_comms_rx);
|
|
|
|
|
|
|
|
// Multiple-producer, multiple-consumer channel from algorithm actor
|
2018-04-03 04:53:59 -07:00
|
|
|
// tasks such as Reliable Broadcast to all comms tasks.
|
2018-04-02 13:26:40 -07:00
|
|
|
let (to_comms_tx, to_comms_rx):
|
|
|
|
(
|
|
|
|
channel::Sender<Message<T>>,
|
|
|
|
channel::Receiver<Message<T>>
|
|
|
|
) = channel::unbounded();
|
|
|
|
let (to_comms_tx, to_comms_rx) = (&to_comms_tx, &to_comms_rx);
|
|
|
|
|
2018-04-03 04:53:59 -07:00
|
|
|
let value = &self.value;
|
2018-04-01 14:29:12 -07:00
|
|
|
let connections = connection::make(&self.addr, &self.remotes);
|
2018-03-16 11:12:14 -07:00
|
|
|
|
2018-04-03 04:53:59 -07:00
|
|
|
// Single-consumer channels from algorithm actor tasks to comms tasks.
|
|
|
|
let to_comms_1: Vec<(channel::Sender<Message<T>>,
|
2018-04-03 15:08:26 -07:00
|
|
|
channel::Receiver<Message<T>>)> =
|
|
|
|
(0 .. connections.len() + 1)
|
|
|
|
.map(|_| channel::unbounded())
|
|
|
|
.collect();
|
|
|
|
// All transmit sides of channels to comms tasks are collected together
|
|
|
|
// for sending messages to particular remote nodes.
|
|
|
|
let to_comms_1_txs: Vec<channel::Sender<Message<T>>> =
|
|
|
|
to_comms_1.iter().map(|(tx, _)| tx.to_owned()).collect();
|
2018-04-03 04:53:59 -07:00
|
|
|
let to_comms_1 = &to_comms_1;
|
|
|
|
let to_comms_1_txs = &to_comms_1_txs;
|
|
|
|
|
2018-03-20 09:32:19 -07:00
|
|
|
// All spawned threads will have exited by the end of the scope.
|
|
|
|
crossbeam::scope(|scope| {
|
2018-04-03 15:08:26 -07:00
|
|
|
|
|
|
|
// Associate a broadcast instance with this node. This instance will
|
|
|
|
// broadcast the proposed value. There is no remote node
|
|
|
|
// corresponding to this instance, and no dedicated comms task. The
|
|
|
|
// node index is 0.
|
|
|
|
scope.spawn(move || {
|
|
|
|
match broadcast::Instance::new(to_comms_tx,
|
|
|
|
from_comms_rx,
|
|
|
|
to_comms_1_txs,
|
|
|
|
value.to_owned(),
|
|
|
|
0)
|
|
|
|
.run()
|
|
|
|
{
|
|
|
|
Ok(_) => debug!("Sender broadcast instance succeeded"),
|
|
|
|
Err(_) => error!("Sender broadcast instance failed")
|
|
|
|
}
|
|
|
|
});
|
2018-03-16 11:12:14 -07:00
|
|
|
|
2018-04-01 14:29:12 -07:00
|
|
|
// Start a comms task for each connection.
|
2018-04-02 13:26:40 -07:00
|
|
|
for (i, c) in connections.iter().enumerate() {
|
2018-04-03 04:53:59 -07:00
|
|
|
|
|
|
|
// Receive side of a single-consumer channel from algorithm
|
|
|
|
// actor tasks to the comms task.
|
|
|
|
let ref to_comms_1_rx = to_comms_1[i].1;
|
2018-04-02 13:26:40 -07:00
|
|
|
|
|
|
|
info!("Creating a comms task #{} for {:?}", i,
|
2018-04-01 14:29:12 -07:00
|
|
|
c.stream.peer_addr().unwrap());
|
|
|
|
scope.spawn(move || {
|
2018-04-02 13:26:40 -07:00
|
|
|
commst::CommsTask::new(from_comms_tx,
|
|
|
|
to_comms_rx,
|
2018-04-03 04:53:59 -07:00
|
|
|
to_comms_1_rx,
|
2018-04-03 15:08:26 -07:00
|
|
|
&c.stream,
|
|
|
|
i + 1)
|
2018-04-02 13:26:40 -07:00
|
|
|
.run();
|
2018-04-01 14:29:12 -07:00
|
|
|
});
|
2018-03-19 10:12:20 -07:00
|
|
|
|
2018-04-02 13:26:40 -07:00
|
|
|
// Associate a broadcast instance to the above comms task.
|
|
|
|
scope.spawn(move || {
|
|
|
|
match broadcast::Instance::new(to_comms_tx,
|
|
|
|
from_comms_rx,
|
2018-04-03 04:53:59 -07:00
|
|
|
to_comms_1_txs,
|
2018-04-03 15:08:26 -07:00
|
|
|
None,
|
|
|
|
i + 1)
|
2018-04-02 13:26:40 -07:00
|
|
|
.run()
|
|
|
|
{
|
|
|
|
Ok(_) => debug!("Broadcast instance #{} succeeded", i),
|
|
|
|
Err(_) => error!("Broadcast instance #{} failed", i)
|
|
|
|
}
|
|
|
|
});
|
2018-03-20 09:32:19 -07:00
|
|
|
}
|
|
|
|
|
2018-04-02 13:26:40 -07:00
|
|
|
// TODO: continue the implementation of the asynchronous common
|
|
|
|
// subset algorithm.
|
2018-03-19 10:12:20 -07:00
|
|
|
|
2018-03-20 09:32:19 -07:00
|
|
|
}); // end of thread scope
|
2018-03-27 13:59:38 -07:00
|
|
|
|
|
|
|
Err(())
|
2018-03-16 11:12:14 -07:00
|
|
|
}
|
|
|
|
}
|