protocol_block.rs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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 async_std::sync::Arc;
  19. use async_trait::async_trait;
  20. use log::debug;
  21. use smol::Executor;
  22. use url::Url;
  23. use darkfi::{
  24. blockchain::BlockInfo,
  25. impl_p2p_message,
  26. net::{
  27. ChannelPtr, Message, MessageSubscription, P2pPtr, ProtocolBase, ProtocolBasePtr,
  28. ProtocolJobsManager, ProtocolJobsManagerPtr,
  29. },
  30. rpc::jsonrpc::JsonSubscriber,
  31. validator::ValidatorPtr,
  32. Result,
  33. };
  34. use darkfi_serial::{SerialDecodable, SerialEncodable};
  35. /// Auxiliary [`BlockInfo`] wrapper structure used for messaging.
  36. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
  37. pub struct BlockInfoMessage(BlockInfo);
  38. impl From<&BlockInfo> for BlockInfoMessage {
  39. fn from(block: &BlockInfo) -> Self {
  40. BlockInfoMessage(block.clone())
  41. }
  42. }
  43. impl_p2p_message!(BlockInfoMessage, "block");
  44. pub struct ProtocolBlock {
  45. block_sub: MessageSubscription<BlockInfoMessage>,
  46. jobsman: ProtocolJobsManagerPtr,
  47. validator: ValidatorPtr,
  48. p2p: P2pPtr,
  49. channel_address: Url,
  50. subscriber: JsonSubscriber,
  51. }
  52. impl ProtocolBlock {
  53. pub async fn init(
  54. channel: ChannelPtr,
  55. validator: ValidatorPtr,
  56. p2p: P2pPtr,
  57. subscriber: JsonSubscriber,
  58. ) -> Result<ProtocolBasePtr> {
  59. debug!(
  60. target: "validator::protocol_block::init",
  61. "Adding ProtocolBlock to the protocol registry"
  62. );
  63. let msg_subsystem = channel.message_subsystem();
  64. msg_subsystem.add_dispatch::<BlockInfoMessage>().await;
  65. let block_sub = channel.subscribe_msg::<BlockInfoMessage>().await?;
  66. Ok(Arc::new(Self {
  67. block_sub,
  68. jobsman: ProtocolJobsManager::new("BlockProtocol", channel.clone()),
  69. validator,
  70. p2p,
  71. channel_address: channel.address().clone(),
  72. subscriber,
  73. }))
  74. }
  75. async fn handle_receive_block(self: Arc<Self>) -> Result<()> {
  76. debug!(target: "consensus::protocol_block::handle_receive_block", "START");
  77. let exclude_list = vec![self.channel_address.clone()];
  78. loop {
  79. let block = match self.block_sub.receive().await {
  80. Ok(v) => v,
  81. Err(e) => {
  82. debug!(
  83. target: "validator::protocol_block::handle_receive_block",
  84. "recv fail: {}",
  85. e
  86. );
  87. continue
  88. }
  89. };
  90. // Check if node has finished syncing its blockchain
  91. if !self.validator.read().await.synced {
  92. debug!(
  93. target: "validator::protocol_block::handle_receive_block",
  94. "Node still syncing blockchain, skipping..."
  95. );
  96. continue
  97. }
  98. // Check if node started participating in consensus.
  99. // Consensus-mode enabled nodes have already performed these steps,
  100. // during proposal finalization. They still listen to this sub,
  101. // in case they go out of sync and become a none-consensus node.
  102. if self.validator.read().await.consensus.participating {
  103. debug!(
  104. target: "validator::protocol_block::handle_receive_block",
  105. "Node is participating in consensus, skipping..."
  106. );
  107. continue
  108. }
  109. let block_copy = (*block).clone();
  110. match self.validator.write().await.append_block(&block_copy.0).await {
  111. Ok(()) => {
  112. self.p2p.broadcast_with_exclude(&block_copy, &exclude_list).await;
  113. self.subscriber.notify(&[block_copy]).await;
  114. }
  115. Err(e) => {
  116. debug!(
  117. target: "validator::protocol_block::handle_receive_block",
  118. "append_block fail: {}",
  119. e
  120. );
  121. }
  122. };
  123. }
  124. }
  125. }
  126. #[async_trait]
  127. impl ProtocolBase for ProtocolBlock {
  128. async fn start(self: Arc<Self>, executor: Arc<Executor<'_>>) -> Result<()> {
  129. debug!(target: "validator::protocol_block::start", "START");
  130. self.jobsman.clone().start(executor.clone());
  131. self.jobsman.clone().spawn(self.clone().handle_receive_block(), executor.clone()).await;
  132. debug!(target: "validator::protocol_block::start", "END");
  133. Ok(())
  134. }
  135. fn name(&self) -> &'static str {
  136. "ProtocolBlock"
  137. }
  138. }