overlord/
lib.rs

1//! Overlord Consensus Protocol is a Byzantine fault tolerance (BFT) consensus algorithm aiming to
2//! support thousands of transactions per second under hundreds of consensus nodes, with transaction
3//! delays of no more than a few seconds. Simply put, it is a high-performance consensus algorithm
4//! able to meets most of the real business needs.
5
6#![deny(missing_docs)]
7#![recursion_limit = "512"]
8#![allow(clippy::mutable_key_type)]
9
10/// A module that impl rlp encodable and decodable trait for types that need to save wal.
11mod codec;
12/// Overlord error module.
13pub mod error;
14/// Create and run the overlord consensus process.
15pub mod overlord;
16/// serialize Bytes in hex format
17pub mod serde_hex;
18/// serialize Vec<Bytes> in hex format
19mod serde_multi_hex;
20/// State machine replicas module to do state changes.
21mod smr;
22/// The state module to storage proposals and votes.
23mod state;
24/// The timer module to ensure the protocol liveness.
25mod timer;
26/// Message types using in the overlord consensus protocol.
27pub mod types;
28/// Some utility functions.
29mod utils;
30/// Write ahead log module.
31mod wal;
32
33pub use self::overlord::Overlord;
34pub use self::overlord::OverlordHandler;
35pub use self::utils::auth_manage::{extract_voters, get_leader};
36pub use creep::Context;
37pub use wal::WalInfo;
38
39use std::error::Error;
40use std::fmt::Debug;
41
42use async_trait::async_trait;
43use bytes::Bytes;
44use serde::{Deserialize, Serialize};
45
46use crate::error::ConsensusError;
47use crate::types::{Address, Commit, Hash, Node, OverlordMsg, Signature, Status, ViewChangeReason};
48
49/// Overlord consensus result.
50pub type ConsensusResult<T> = std::result::Result<T, ConsensusError>;
51
52const INIT_HEIGHT: u64 = 0;
53const INIT_ROUND: u64 = 0;
54
55/// Trait for some functions that consensus needs.
56#[async_trait]
57pub trait Consensus<T: Codec>: Send + Sync {
58    /// Get a block of the given height and return the block with its hash.
59    async fn get_block(
60        &self,
61        ctx: Context,
62        height: u64,
63    ) -> Result<(T, Hash), Box<dyn Error + Send>>;
64
65    /// Check the correctness of a block. If is passed, return the integrated transcations to do
66    /// data persistence.
67    async fn check_block(
68        &self,
69        ctx: Context,
70        height: u64,
71        hash: Hash,
72        block: T,
73    ) -> Result<(), Box<dyn Error + Send>>;
74
75    /// Commit a given height to execute and return the rich status.
76    async fn commit(
77        &self,
78        ctx: Context,
79        height: u64,
80        commit: Commit<T>,
81    ) -> Result<Status, Box<dyn Error + Send>>;
82
83    /// Get an authority list of the given height.
84    async fn get_authority_list(
85        &self,
86        ctx: Context,
87        height: u64,
88    ) -> Result<Vec<Node>, Box<dyn Error + Send>>;
89
90    /// Broadcast a message to other replicas.
91    async fn broadcast_to_other(
92        &self,
93        ctx: Context,
94        msg: OverlordMsg<T>,
95    ) -> Result<(), Box<dyn Error + Send>>;
96
97    /// Transmit a message to the Relayer, the third argument is the relayer's address.
98    async fn transmit_to_relayer(
99        &self,
100        ctx: Context,
101        addr: Address,
102        msg: OverlordMsg<T>,
103    ) -> Result<(), Box<dyn Error + Send>>;
104
105    /// Report the overlord error with the corresponding context.
106    fn report_error(&self, ctx: Context, error: ConsensusError);
107
108    /// Report the overlord view change reason.
109    fn report_view_change(&self, ctx: Context, height: u64, round: u64, reason: ViewChangeReason);
110}
111
112/// Trait for doing serialize and deserialize.
113pub trait Codec: Clone + Debug + Send + PartialEq + Eq {
114    /// Serialize self into bytes.
115    fn encode(&self) -> Result<Bytes, Box<dyn Error + Send>>;
116
117    /// Deserialize date into self.
118    fn decode(data: Bytes) -> Result<Self, Box<dyn Error + Send>>;
119}
120
121/// Trait for save and load wal information.
122#[async_trait]
123pub trait Wal {
124    /// Save wal information.
125    async fn save(&self, info: Bytes) -> Result<(), Box<dyn Error + Send>>;
126
127    /// Load wal information.
128    async fn load(&self) -> Result<Option<Bytes>, Box<dyn Error + Send>>;
129}
130
131/// Trait for some crypto methods.
132pub trait Crypto: Send {
133    /// Hash a message bytes.
134    fn hash(&self, msg: Bytes) -> Hash;
135
136    /// Sign to the given hash by private key and return the signature if success.
137    fn sign(&self, hash: Hash) -> Result<Signature, Box<dyn Error + Send>>;
138
139    /// Aggregate the given signatures into an aggregated signature according to the given bitmap.
140    fn aggregate_signatures(
141        &self,
142        signatures: Vec<Signature>,
143        voters: Vec<Address>,
144    ) -> Result<Signature, Box<dyn Error + Send>>;
145
146    /// Verify a signature and return the recovered address.
147    fn verify_signature(
148        &self,
149        signature: Signature,
150        hash: Hash,
151        voter: Address,
152    ) -> Result<(), Box<dyn Error + Send>>;
153
154    /// Verify an aggregated signature.
155    fn verify_aggregated_signature(
156        &self,
157        aggregate_signature: Signature,
158        msg_hash: Hash,
159        voters: Vec<Address>,
160    ) -> Result<(), Box<dyn Error + Send>>;
161}
162
163/// The setting of the timeout interval of each step.
164#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
165pub struct DurationConfig {
166    /// The proportion of propose timeout to the height interval.
167    pub propose_ratio: u64,
168    /// The proportion of prevote timeout to the height interval.
169    pub prevote_ratio: u64,
170    /// The proportion of precommit timeout to the height interval.
171    pub precommit_ratio: u64,
172    /// The proportion of retry choke message timeout to the height interval.
173    pub brake_ratio: u64,
174}
175
176impl DurationConfig {
177    /// Create a consensus timeout configuration.
178    pub fn new(
179        propose_ratio: u64,
180        prevote_ratio: u64,
181        precommit_ratio: u64,
182        brake_ratio: u64,
183    ) -> Self {
184        DurationConfig {
185            propose_ratio,
186            prevote_ratio,
187            precommit_ratio,
188            brake_ratio,
189        }
190    }
191
192    pub(crate) fn get_propose_config(&self) -> (u64, u64) {
193        (self.propose_ratio, 10u64)
194    }
195
196    pub(crate) fn get_prevote_config(&self) -> (u64, u64) {
197        (self.prevote_ratio, 10u64)
198    }
199
200    pub(crate) fn get_precommit_config(&self) -> (u64, u64) {
201        (self.precommit_ratio, 10u64)
202    }
203
204    pub(crate) fn get_brake_config(&self) -> (u64, u64) {
205        (self.brake_ratio, 10u64)
206    }
207}
208
209#[cfg(test)]
210mod test {
211    use super::DurationConfig;
212
213    #[test]
214    fn test_duration_config() {
215        let config = DurationConfig::new(1, 2, 3, 4);
216        assert_eq!(config.get_propose_config(), (1, 10));
217        assert_eq!(config.get_prevote_config(), (2, 10));
218        assert_eq!(config.get_precommit_config(), (3, 10));
219        assert_eq!(config.get_brake_config(), (4, 10));
220    }
221}