1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//! Implements the Aleph BFT Consensus protocol as a "finality gadget". The [Member] struct
//! requires access to a network layer, a cryptographic primitive, and a data provider that
//! gives appropriate access to the set of available data that we need to make consensus on.

use codec::{Decode, Encode};
use futures::{channel::mpsc, Future};
use std::{fmt::Debug, hash::Hash as StdHash, pin::Pin};

use crate::nodes::{NodeCount, NodeMap};

pub use config::{default_config, Config, DelayConfig};
pub use member::Member;
pub use network::{Network, NetworkData};
pub use nodes::NodeIndex;

mod alerts;
mod consensus;
mod creator;
mod extender;
mod member;
mod network;
mod nodes;
mod signed;
pub use signed::*;
mod config;
pub mod rmc;
mod terminal;
mod testing;
mod units;

/// The number of a session for which the consensus is run.
pub type SessionId = u64;

/// The source of data items that consensus should order.
///
/// AlephBFT internally calls [`DataIO::get_data`] whenever a new unit is created and data needs to be placed inside.
/// The [`DataIO::send_ordered_batch`] method is called whenever a new round has been decided and thus a new batch of units
/// (or more precisely the data they carry) is available. Finally, [`DataIO::check_availability is used to validate and check availability of data.
/// The meaning of the latter might be unclear if we think of `Data` as being the actual data that is being ordered,
/// but in applications one often wants to use hashes of data (for instance block hashes) in which case it is crucial
/// for security that there is access to the actual data, cryptographically represented by a hash.
/// It is assumed that the implementation of DataIO makes best effort of fetch the data in case it is unavailable.
pub trait DataIO<Data> {
    type Error: Debug + 'static;
    /// Outputs a new data item to be ordered
    fn get_data(&self) -> Data;
    /// Returns future that indicates when the data becomes available or None if the data is already available.
    /// For applications where `Data` is actually a real data and not some reprentation of it, this may be trivially
    /// implemented to return always `None`.
    fn check_availability(
        &self,
        data: &Data,
    ) -> Option<Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send>>>;
    /// Takes a new ordered batch of data item.
    fn send_ordered_batch(&mut self, data: OrderedBatch<Data>) -> Result<(), Self::Error>;
}

/// Indicates that an implementor has been assigned some index.
pub trait Index {
    fn index(&self) -> NodeIndex;
}

/// A hasher, used for creating identifiers for blocks or units.
pub trait Hasher: Eq + Clone + Send + Sync + Debug + 'static {
    /// A hash, as an identifier for a block or unit.
    type Hash: AsRef<[u8]> + Eq + Ord + Copy + Clone + Send + Debug + StdHash + Encode + Decode;

    fn hash(s: &[u8]) -> Self::Hash;
}

/// Data type that we want to order.
pub trait Data: Eq + Clone + Send + Sync + Debug + StdHash + Encode + Decode + 'static {}

impl<T> Data for T where T: Eq + Clone + Send + Sync + Debug + StdHash + Encode + Decode + 'static {}

/// An asynchronous round of the protocol.
pub type Round = usize;

/// Type for sending a new ordered batch of data items.
pub type OrderedBatch<Data> = Vec<Data>;

/// An abstraction for an execution engine for Rust's asynchronous tasks.
pub trait SpawnHandle: Clone + Send + 'static {
    /// Run a new task.
    fn spawn(&self, name: &'static str, task: impl Future<Output = ()> + Send + 'static);
}

pub(crate) type Receiver<T> = mpsc::UnboundedReceiver<T>;
pub(crate) type Sender<T> = mpsc::UnboundedSender<T>;