consensus.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2023 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::{collections::HashMap, time::Duration};
  19. use async_std::{
  20. sync::{Arc, Mutex},
  21. task::sleep,
  22. };
  23. use chrono::Utc;
  24. use darkfi_serial::{deserialize, serialize, Decodable, Encodable};
  25. use futures::{select, FutureExt};
  26. use log::{debug, error, warn};
  27. use rand::{distributions::Alphanumeric, rngs::OsRng, thread_rng, Rng, RngCore};
  28. use smol::Executor;
  29. use crate::{net, Error, Result};
  30. use super::{
  31. p2p_send_loop,
  32. primitives::{
  33. BroadcastMsgRequest, Channel, Log, LogRequest, LogResponse, Logs, MapLength, NetMsg,
  34. NetMsgMethod, NodeId, NodeIdMsg, Role, Sender, VoteRequest, VoteResponse,
  35. },
  36. prune_map, DataStore, RaftSettings,
  37. };
  38. async fn send_loop(sender: smol::channel::Sender<()>, timeout: Duration) -> Result<()> {
  39. loop {
  40. sleep(timeout).await;
  41. sender.send(()).await?;
  42. }
  43. }
  44. pub fn gen_id(len: usize) -> String {
  45. thread_rng().sample_iter(&Alphanumeric).take(len).map(char::from).collect()
  46. }
  47. pub struct Raft<T> {
  48. id: NodeId,
  49. pub(super) role: Role,
  50. pub(super) current_leader: NodeId,
  51. pub(super) votes_received: Vec<NodeId>,
  52. pub(super) sent_length: MapLength,
  53. pub(super) acked_length: MapLength,
  54. pub(super) nodes: Arc<Mutex<HashMap<NodeId, i64>>>,
  55. pub(super) last_term: u64,
  56. pub(super) last_heartbeat: i64,
  57. p2p_sender: Sender,
  58. msgs_channel: Channel<T>,
  59. commits_channel: Channel<T>,
  60. datastore: DataStore<T>,
  61. seen_msgs: Arc<Mutex<HashMap<String, i64>>>,
  62. pub(super) settings: RaftSettings,
  63. pending_msgs: Vec<T>,
  64. }
  65. impl<T: Decodable + Encodable + Clone> Raft<T> {
  66. pub fn new(
  67. settings: RaftSettings,
  68. seen_msgs: Arc<Mutex<HashMap<String, i64>>>,
  69. ) -> Result<Self> {
  70. if settings.datastore_path.to_str().is_none() {
  71. error!(target: "raft::consensus", "datastore path is incorrect");
  72. return Err(Error::ParseFailed("unable to parse pathbuf to str"))
  73. };
  74. let datastore = DataStore::new(settings.datastore_path.to_str().unwrap())?;
  75. // broadcasting channels
  76. let msgs_channel = smol::channel::unbounded::<T>();
  77. let commits_channel = smol::channel::unbounded::<T>();
  78. let p2p_sender = smol::channel::unbounded::<NetMsg>();
  79. let id = match datastore.id.get_last()? {
  80. Some(_id) => _id,
  81. None => {
  82. // FIXME: This should be a big number, like a hash.
  83. let id = NodeId(gen_id(30));
  84. datastore.id.insert(&id)?;
  85. id
  86. }
  87. };
  88. let role = Role::Follower;
  89. Ok(Self {
  90. id,
  91. role,
  92. current_leader: NodeId("".into()),
  93. votes_received: vec![],
  94. sent_length: MapLength(HashMap::default()),
  95. acked_length: MapLength(HashMap::default()),
  96. nodes: Arc::new(Mutex::new(HashMap::default())),
  97. last_term: 0,
  98. last_heartbeat: Utc::now().timestamp(),
  99. p2p_sender,
  100. msgs_channel,
  101. commits_channel,
  102. datastore,
  103. seen_msgs,
  104. settings,
  105. pending_msgs: vec![],
  106. })
  107. }
  108. ///
  109. /// Run raft consensus and wait stop_signal channel to terminate
  110. ///
  111. pub async fn run(
  112. &mut self,
  113. p2p: net::P2pPtr,
  114. p2p_recv_channel: smol::channel::Receiver<NetMsg>,
  115. executor: Arc<Executor<'_>>,
  116. stop_signal: smol::channel::Receiver<()>,
  117. ) -> Result<()> {
  118. let p2p_send_task = executor.spawn(p2p_send_loop(self.p2p_sender.1.clone(), p2p.clone()));
  119. let prune_seen_messages_task = executor
  120. .spawn(prune_map::<String>(self.seen_msgs.clone(), self.settings.prun_duration));
  121. let prune_nodes_id_task =
  122. executor.spawn(prune_map::<NodeId>(self.nodes.clone(), self.settings.prun_duration));
  123. let (id_sx, id_rv) = smol::channel::unbounded::<()>();
  124. let (heartbeat_sx, heartbeat_rv) = smol::channel::unbounded::<()>();
  125. let (timeout_sx, timeout_rv) = smol::channel::unbounded::<()>();
  126. let id_timeout = Duration::from_secs(self.settings.id_timeout);
  127. let send_id_task = executor.spawn(send_loop(id_sx, id_timeout));
  128. let heartbeat_timeout = Duration::from_millis(self.settings.heartbeat_timeout);
  129. let send_heartbeat_task = executor.spawn(send_loop(heartbeat_sx, heartbeat_timeout));
  130. let rng = &mut OsRng;
  131. let timeout =
  132. Duration::from_secs(rng.gen_range(0..self.settings.timeout) + self.settings.timeout);
  133. let send_timeout_task = executor.spawn(send_loop(timeout_sx, timeout));
  134. let broadcast_msg_rv = self.msgs_channel.1.clone();
  135. loop {
  136. let mut result = select! {
  137. m = p2p_recv_channel.recv().fuse() => self.handle_method(m?).await,
  138. m = broadcast_msg_rv.recv().fuse() => self.broadcast_msg(&m?,None).await,
  139. _ = id_rv.recv().fuse() => self.send_id_msg().await,
  140. _ = heartbeat_rv.recv().fuse() => self.send_heartbeat().await,
  141. _ = timeout_rv.recv().fuse() => self.send_vote_request().await,
  142. _ = stop_signal.recv().fuse() => break,
  143. };
  144. // send pending messages
  145. if !self.pending_msgs.is_empty() && self.role != Role::Candidate {
  146. let pending_msgs = self.pending_msgs.clone();
  147. for m in &pending_msgs {
  148. result = self.broadcast_msg(m, None).await;
  149. }
  150. self.pending_msgs = vec![];
  151. }
  152. if let Err(e) = result {
  153. warn!(target: "raft::consensus", "warn: {}", e);
  154. }
  155. }
  156. warn!(target: "raft::consensus", "Raft Terminating...");
  157. p2p_send_task.cancel().await;
  158. prune_seen_messages_task.cancel().await;
  159. prune_nodes_id_task.cancel().await;
  160. send_id_task.cancel().await;
  161. send_heartbeat_task.cancel().await;
  162. send_timeout_task.cancel().await;
  163. self.datastore.flush().await?;
  164. Ok(())
  165. }
  166. ///
  167. /// Return async receiver channel which can be used to receive T Messages
  168. /// from raft consensus
  169. ///
  170. pub fn receiver(&self) -> smol::channel::Receiver<T> {
  171. self.commits_channel.1.clone()
  172. }
  173. ///
  174. /// Return async sender channel which can be used to broadcast T Messages
  175. /// to raft consensus
  176. ///
  177. pub fn sender(&self) -> smol::channel::Sender<T> {
  178. self.msgs_channel.0.clone()
  179. }
  180. ///
  181. /// Return the raft node id
  182. ///
  183. pub fn id(&self) -> NodeId {
  184. self.id.clone()
  185. }
  186. async fn send_id_msg(&self) -> Result<()> {
  187. let id_msg = serialize(&NodeIdMsg { id: self.id.clone() });
  188. self.send(None, &id_msg, NetMsgMethod::NodeIdMsg, None).await?;
  189. Ok(())
  190. }
  191. async fn broadcast_msg(&mut self, msg: &T, msg_id: Option<u64>) -> Result<()> {
  192. match self.role {
  193. Role::Leader => {
  194. let msg = serialize(msg);
  195. let log = Log { msg, term: self.current_term()? };
  196. self.push_log(&log)?;
  197. self.acked_length.insert(&self.id, self.logs_len());
  198. }
  199. Role::Follower => {
  200. let b_msg = BroadcastMsgRequest(serialize(msg));
  201. self.send(
  202. Some(self.current_leader.clone()),
  203. &serialize(&b_msg),
  204. NetMsgMethod::BroadcastRequest,
  205. msg_id,
  206. )
  207. .await?;
  208. }
  209. Role::Candidate => {
  210. self.pending_msgs.push(msg.clone());
  211. }
  212. }
  213. debug!(target: "raft::consensus", "Role: {:?} Id: {:?}, broadcast a msg id: {:?} ", self.role, self.id, msg_id);
  214. Ok(())
  215. }
  216. async fn handle_method(&mut self, msg: NetMsg) -> Result<()> {
  217. match msg.method {
  218. NetMsgMethod::LogResponse => {
  219. let lr: LogResponse = deserialize(&msg.payload)?;
  220. self.receive_log_response(lr).await?;
  221. }
  222. NetMsgMethod::LogRequest => {
  223. self.last_heartbeat = Utc::now().timestamp();
  224. let lr: LogRequest = deserialize(&msg.payload)?;
  225. self.receive_log_request(lr).await?;
  226. }
  227. NetMsgMethod::VoteResponse => {
  228. let vr: VoteResponse = deserialize(&msg.payload)?;
  229. self.receive_vote_response(vr).await?;
  230. }
  231. NetMsgMethod::VoteRequest => {
  232. let vr: VoteRequest = deserialize(&msg.payload)?;
  233. self.receive_vote_request(vr).await?;
  234. }
  235. NetMsgMethod::BroadcastRequest => {
  236. let vr: BroadcastMsgRequest = deserialize(&msg.payload)?;
  237. let d: T = deserialize(&vr.0)?;
  238. self.broadcast_msg(&d, Some(msg.id)).await?;
  239. }
  240. NetMsgMethod::NodeIdMsg => {
  241. let node_id_msg: NodeIdMsg = deserialize(&msg.payload)?;
  242. if node_id_msg.id != self.id {
  243. self.nodes.lock().await.insert(node_id_msg.id, Utc::now().timestamp());
  244. }
  245. }
  246. }
  247. debug!(target: "raft::consensus", "Role: {:?} Id: {:?}, receive a msg with id: {} recipient_id: {:?} method: {:?} ",
  248. self.role, self.id, msg.id, &msg.recipient_id, &msg.method);
  249. Ok(())
  250. }
  251. pub(super) async fn send(
  252. &self,
  253. recipient_id: Option<NodeId>,
  254. payload: &[u8],
  255. method: NetMsgMethod,
  256. msg_id: Option<u64>,
  257. ) -> Result<()> {
  258. let random_id = if msg_id.is_some() { msg_id.unwrap() } else { OsRng.next_u64() };
  259. debug!(target: "raft::consensus","Role: {:?} Id: {:?}, send a msg with id: {} recipient_id: {:?} method: {:?} ",
  260. self.role, self.id, random_id, &recipient_id, &method);
  261. let net_msg = NetMsg { id: random_id, recipient_id, payload: payload.to_vec(), method };
  262. self.seen_msgs.lock().await.insert(random_id.to_string(), Utc::now().timestamp());
  263. self.p2p_sender.0.send(net_msg).await?;
  264. Ok(())
  265. }
  266. pub(super) fn reset_last_term(&mut self) -> Result<()> {
  267. self.last_term = 0;
  268. if let Some(log) = self.last_log()? {
  269. self.last_term = log.term;
  270. }
  271. Ok(())
  272. }
  273. pub(super) fn set_current_term(&mut self, i: &u64) -> Result<()> {
  274. self.datastore.current_term.insert(i)
  275. }
  276. pub(super) fn set_voted_for(&mut self, i: &Option<NodeId>) -> Result<()> {
  277. self.datastore.voted_for.insert(i)
  278. }
  279. pub(super) async fn push_commit(&mut self, commit: &[u8]) -> Result<()> {
  280. let commit: T = deserialize(commit)?;
  281. self.commits_channel.0.send(commit.clone()).await?;
  282. self.datastore.commits.insert(&commit)
  283. }
  284. pub(super) fn push_log(&mut self, log: &Log) -> Result<()> {
  285. self.datastore.logs.insert(log)
  286. }
  287. pub(super) fn push_logs(&mut self, logs: &Logs) -> Result<()> {
  288. self.datastore.logs.wipe_insert_all(&logs.to_vec())
  289. }
  290. pub(super) fn current_term(&self) -> Result<u64> {
  291. Ok(self.datastore.current_term.get_last()?.unwrap_or(0))
  292. }
  293. pub(super) fn voted_for(&self) -> Result<Option<NodeId>> {
  294. Ok(self.datastore.voted_for.get_last()?.flatten())
  295. }
  296. pub(super) fn commits_len(&self) -> u64 {
  297. self.datastore.commits.len()
  298. }
  299. fn logs(&self) -> Result<Logs> {
  300. Ok(Logs(self.datastore.logs.get_all()?))
  301. }
  302. pub(super) fn logs_len(&self) -> u64 {
  303. self.datastore.logs.len()
  304. }
  305. fn last_log(&self) -> Result<Option<Log>> {
  306. self.datastore.logs.get_last()
  307. }
  308. pub(super) fn get_log(&self, index: u64) -> Result<Log> {
  309. self.datastore.logs.get(index)
  310. }
  311. pub(super) fn slice_logs_from(&self, index: u64) -> Result<Option<Logs>> {
  312. let logs = self.logs()?;
  313. Ok(logs.slice_from(index))
  314. }
  315. pub(super) fn slice_logs_to(&self, index: u64) -> Result<Logs> {
  316. let logs = self.logs()?;
  317. Ok(logs.slice_to(index))
  318. }
  319. }