protocol_sync.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2022 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 async_std::sync::Arc;
  19. use async_trait::async_trait;
  20. use log::{debug, error, info};
  21. use smol::Executor;
  22. use crate::{
  23. consensus::{
  24. block::{BlockInfo, BlockOrder, BlockResponse},
  25. state::{SlotCheckpoint, SlotCheckpointRequest, SlotCheckpointResponse},
  26. ValidatorStatePtr,
  27. },
  28. net::{
  29. ChannelPtr, MessageSubscription, P2pPtr, ProtocolBase, ProtocolBasePtr,
  30. ProtocolJobsManager, ProtocolJobsManagerPtr,
  31. },
  32. Result,
  33. };
  34. // Constant defining how many blocks we send during syncing.
  35. const BATCH: u64 = 10;
  36. pub struct ProtocolSync {
  37. channel: ChannelPtr,
  38. request_sub: MessageSubscription<BlockOrder>,
  39. slot_checkpoin_request_sub: MessageSubscription<SlotCheckpointRequest>,
  40. block_sub: MessageSubscription<BlockInfo>,
  41. slot_checkpoints_sub: MessageSubscription<SlotCheckpoint>,
  42. jobsman: ProtocolJobsManagerPtr,
  43. state: ValidatorStatePtr,
  44. p2p: P2pPtr,
  45. consensus_mode: bool,
  46. }
  47. impl ProtocolSync {
  48. pub async fn init(
  49. channel: ChannelPtr,
  50. state: ValidatorStatePtr,
  51. p2p: P2pPtr,
  52. consensus_mode: bool,
  53. ) -> Result<ProtocolBasePtr> {
  54. let msg_subsystem = channel.get_message_subsystem();
  55. msg_subsystem.add_dispatch::<BlockOrder>().await;
  56. msg_subsystem.add_dispatch::<SlotCheckpointRequest>().await;
  57. msg_subsystem.add_dispatch::<BlockInfo>().await;
  58. msg_subsystem.add_dispatch::<SlotCheckpoint>().await;
  59. let request_sub = channel.subscribe_msg::<BlockOrder>().await?;
  60. let slot_checkpoin_request_sub = channel.subscribe_msg::<SlotCheckpointRequest>().await?;
  61. let block_sub = channel.subscribe_msg::<BlockInfo>().await?;
  62. let slot_checkpoints_sub = channel.subscribe_msg::<SlotCheckpoint>().await?;
  63. Ok(Arc::new(Self {
  64. channel: channel.clone(),
  65. request_sub,
  66. slot_checkpoin_request_sub,
  67. block_sub,
  68. slot_checkpoints_sub,
  69. jobsman: ProtocolJobsManager::new("SyncProtocol", channel),
  70. state,
  71. p2p,
  72. consensus_mode,
  73. }))
  74. }
  75. async fn handle_receive_request(self: Arc<Self>) -> Result<()> {
  76. debug!("ProtocolSync::handle_receive_request() [START]");
  77. loop {
  78. let order = match self.request_sub.receive().await {
  79. Ok(v) => v,
  80. Err(e) => {
  81. debug!("ProtocolSync::handle_receive_request(): recv fail: {}", e);
  82. continue
  83. }
  84. };
  85. debug!("ProtocolSync::handle_receive_request() received {:?}", order);
  86. // Extra validations can be added here
  87. let key = order.slot;
  88. let blocks = match self.state.read().await.blockchain.get_blocks_after(key, BATCH) {
  89. Ok(v) => v,
  90. Err(e) => {
  91. error!("ProtocolSync::handle_receive_request(): get_blocks_after fail: {}", e);
  92. continue
  93. }
  94. };
  95. debug!("ProtocolSync::handle_receive_request(): Found {} blocks", blocks.len());
  96. let response = BlockResponse { blocks };
  97. if let Err(e) = self.channel.send(response).await {
  98. error!("ProtocolSync::handle_receive_request(): channel send fail: {}", e)
  99. };
  100. }
  101. }
  102. async fn handle_receive_block(self: Arc<Self>) -> Result<()> {
  103. debug!("ProtocolSync::handle_receive_block() [START]");
  104. let exclude_list = vec![self.channel.address()];
  105. loop {
  106. let info = match self.block_sub.receive().await {
  107. Ok(v) => v,
  108. Err(e) => {
  109. debug!("ProtocolSync::handle_receive_block(): recv fail: {}", e);
  110. continue
  111. }
  112. };
  113. // Check if node started participating in consensus.
  114. // Consensus-mode enabled nodes have already performed these steps,
  115. // during proposal finalization. They still listen to this sub,
  116. // in case they go out of sync and become a none-consensus node.
  117. if self.consensus_mode {
  118. let lock = self.state.read().await;
  119. let current = lock.consensus.current_slot();
  120. let participating = lock.consensus.participating;
  121. if participating.is_some() {
  122. let slot = participating.unwrap();
  123. if current >= slot {
  124. debug!(
  125. "ProtocolSync::handle_receive_block(): node runs in consensus mode, skipping..."
  126. );
  127. continue
  128. }
  129. }
  130. }
  131. info!("ProtocolSync::handle_receive_block(): Received block: {}", info.blockhash());
  132. debug!("ProtocolSync::handle_receive_block(): Processing received block");
  133. let info_copy = (*info).clone();
  134. match self.state.write().await.receive_finalized_block(info_copy.clone()).await {
  135. Ok(v) => {
  136. if v {
  137. debug!("ProtocolProposal::handle_receive_block(): block processed successfully, broadcasting...");
  138. if let Err(e) =
  139. self.p2p.broadcast_with_exclude(info_copy, &exclude_list).await
  140. {
  141. error!(
  142. "ProtocolSync::handle_receive_block(): p2p broadcast fail: {}",
  143. e
  144. );
  145. };
  146. }
  147. }
  148. Err(e) => {
  149. debug!("ProtocolSync::handle_receive_block(): error processing finalized block: {}", e);
  150. }
  151. };
  152. }
  153. }
  154. async fn handle_receive_slot_checkpoint_request(self: Arc<Self>) -> Result<()> {
  155. debug!("ProtocolSync::handle_receive_slot_checkpoint_request() [START]");
  156. loop {
  157. let request = match self.slot_checkpoin_request_sub.receive().await {
  158. Ok(v) => v,
  159. Err(e) => {
  160. debug!(
  161. "ProtocolSync::handle_receive_slot_checkpoint_request(): recv fail: {}",
  162. e
  163. );
  164. continue
  165. }
  166. };
  167. debug!("ProtocolSync::handle_receive_slot_checkpoint_request() received {:?}", request);
  168. // Extra validations can be added here
  169. let key = request.slot;
  170. let slot_checkpoints = match self
  171. .state
  172. .read()
  173. .await
  174. .blockchain
  175. .get_slot_checkpoints_after(key, BATCH)
  176. {
  177. Ok(v) => v,
  178. Err(e) => {
  179. error!("ProtocolSync::handle_receive_slot_checkpoint_request(): get_slot_checkpoints_after fail: {}", e);
  180. continue
  181. }
  182. };
  183. debug!(
  184. "ProtocolSync::handle_receive_slot_checkpoint_request(): Found {} slot checkpoints",
  185. slot_checkpoints.len()
  186. );
  187. let response = SlotCheckpointResponse { slot_checkpoints };
  188. if let Err(e) = self.channel.send(response).await {
  189. error!(
  190. "ProtocolSync::handle_receive_slot_checkpoint_request(): channel send fail: {}",
  191. e
  192. )
  193. };
  194. }
  195. }
  196. async fn handle_receive_slot_checkpoint(self: Arc<Self>) -> Result<()> {
  197. debug!("ProtocolSync::handle_receive_slot_checkpoint() [START]");
  198. let exclude_list = vec![self.channel.address()];
  199. loop {
  200. let slot_checkpoint = match self.slot_checkpoints_sub.receive().await {
  201. Ok(v) => v,
  202. Err(e) => {
  203. debug!("ProtocolSync::handle_receive_slot_checkpoint(): recv fail: {}", e);
  204. continue
  205. }
  206. };
  207. // Check if node started participating in consensus.
  208. // Consensus-mode enabled nodes have already performed these steps,
  209. // during proposal finalization. They still listen to this sub,
  210. // in case they go out of sync and become a none-consensus node.
  211. if self.consensus_mode {
  212. let lock = self.state.read().await;
  213. let current = lock.consensus.current_slot();
  214. let participating = lock.consensus.participating;
  215. if participating.is_some() {
  216. let slot = participating.unwrap();
  217. if current >= slot {
  218. debug!(
  219. "ProtocolSync::handle_receive_block(): node runs in consensus mode, skipping..."
  220. );
  221. continue
  222. }
  223. }
  224. }
  225. info!(
  226. "ProtocolSync::handle_receive_slot_checkpoint(): Received slot checkpoint: {}",
  227. slot_checkpoint.slot
  228. );
  229. debug!("ProtocolSync::handle_receive_slot_checkpoint(): Processing received slot checkpoint");
  230. let slot_checkpoint_copy = (*slot_checkpoint).clone();
  231. match self
  232. .state
  233. .write()
  234. .await
  235. .receive_finalized_slot_checkpoints(slot_checkpoint_copy.clone())
  236. .await
  237. {
  238. Ok(v) => {
  239. if v {
  240. debug!("ProtocolProposal::handle_receive_slot_checkpoint(): slot checkpoint processed successfully, broadcasting...");
  241. if let Err(e) = self
  242. .p2p
  243. .broadcast_with_exclude(slot_checkpoint_copy, &exclude_list)
  244. .await
  245. {
  246. error!(
  247. "ProtocolSync::handle_receive_slot_checkpoint(): p2p broadcast fail: {}",
  248. e
  249. );
  250. };
  251. }
  252. }
  253. Err(e) => {
  254. debug!("ProtocolSync::handle_receive_slot_checkpoint(): error processing finalized slot checkpoint: {}", e);
  255. }
  256. };
  257. }
  258. }
  259. }
  260. #[async_trait]
  261. impl ProtocolBase for ProtocolSync {
  262. async fn start(self: Arc<Self>, executor: Arc<Executor<'_>>) -> Result<()> {
  263. debug!("ProtocolSync::start() [START]");
  264. self.jobsman.clone().start(executor.clone());
  265. self.jobsman.clone().spawn(self.clone().handle_receive_request(), executor.clone()).await;
  266. self.jobsman
  267. .clone()
  268. .spawn(self.clone().handle_receive_slot_checkpoint_request(), executor.clone())
  269. .await;
  270. self.jobsman.clone().spawn(self.clone().handle_receive_block(), executor.clone()).await;
  271. self.jobsman
  272. .clone()
  273. .spawn(self.clone().handle_receive_slot_checkpoint(), executor.clone())
  274. .await;
  275. debug!("ProtocolSync::start() [END]");
  276. Ok(())
  277. }
  278. fn name(&self) -> &'static str {
  279. "ProtocolSync"
  280. }
  281. }