protocol_tx.rs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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::sync::Arc;
  19. use async_trait::async_trait;
  20. use log::debug;
  21. use smol::Executor;
  22. use tinyjson::JsonValue;
  23. use url::Url;
  24. use darkfi::{
  25. impl_p2p_message,
  26. net::{
  27. ChannelPtr, Message, MessageSubscription, P2pPtr, ProtocolBase, ProtocolBasePtr,
  28. ProtocolJobsManager, ProtocolJobsManagerPtr,
  29. },
  30. rpc::jsonrpc::JsonSubscriber,
  31. tx::Transaction,
  32. util::encoding::base64,
  33. validator::ValidatorPtr,
  34. Result,
  35. };
  36. use darkfi_serial::{serialize, SerialDecodable, SerialEncodable};
  37. /// Auxiliary [`Transaction`] wrapper structure used for messaging.
  38. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
  39. struct TransactionMessage(Transaction);
  40. impl_p2p_message!(TransactionMessage, "tx");
  41. pub struct ProtocolTx {
  42. tx_sub: MessageSubscription<TransactionMessage>,
  43. jobsman: ProtocolJobsManagerPtr,
  44. validator: ValidatorPtr,
  45. p2p: P2pPtr,
  46. channel_address: Url,
  47. subscriber: JsonSubscriber,
  48. }
  49. impl ProtocolTx {
  50. pub async fn init(
  51. channel: ChannelPtr,
  52. validator: ValidatorPtr,
  53. p2p: P2pPtr,
  54. subscriber: JsonSubscriber,
  55. ) -> Result<ProtocolBasePtr> {
  56. debug!(
  57. target: "validator::protocol_tx::init",
  58. "Adding ProtocolTx to the protocol registry"
  59. );
  60. let msg_subsystem = channel.message_subsystem();
  61. msg_subsystem.add_dispatch::<TransactionMessage>().await;
  62. let tx_sub = channel.subscribe_msg::<TransactionMessage>().await?;
  63. Ok(Arc::new(Self {
  64. tx_sub,
  65. jobsman: ProtocolJobsManager::new("TxProtocol", channel.clone()),
  66. validator,
  67. p2p,
  68. channel_address: channel.address().clone(),
  69. subscriber,
  70. }))
  71. }
  72. async fn handle_receive_tx(self: Arc<Self>) -> Result<()> {
  73. debug!(
  74. target: "validator::protocol_tx::handle_receive_tx",
  75. "START"
  76. );
  77. let exclude_list = vec![self.channel_address.clone()];
  78. loop {
  79. let tx = match self.tx_sub.receive().await {
  80. Ok(v) => v,
  81. Err(e) => {
  82. debug!(
  83. target: "validator::protocol_tx::handle_receive_tx",
  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_tx::handle_receive_tx",
  94. "Node still syncing blockchain, skipping..."
  95. );
  96. continue
  97. }
  98. let tx_copy = (*tx).clone();
  99. // Nodes use unconfirmed_txs vector as seen_txs pool.
  100. match self.validator.write().await.append_tx(&tx_copy.0).await {
  101. Ok(()) => {
  102. self.p2p.broadcast_with_exclude(&tx_copy, &exclude_list).await;
  103. let encoded_tx = JsonValue::String(base64::encode(&serialize(&tx_copy)));
  104. self.subscriber.notify(vec![encoded_tx]).await;
  105. }
  106. Err(e) => {
  107. debug!(
  108. target: "validator::protocol_tx::handle_receive_tx",
  109. "append_tx fail: {}",
  110. e
  111. );
  112. }
  113. }
  114. }
  115. }
  116. }
  117. #[async_trait]
  118. impl ProtocolBase for ProtocolTx {
  119. async fn start(self: Arc<Self>, executor: Arc<Executor<'_>>) -> Result<()> {
  120. debug!(target: "validator::protocol_tx::start", "START");
  121. self.jobsman.clone().start(executor.clone());
  122. self.jobsman.clone().spawn(self.clone().handle_receive_tx(), executor.clone()).await;
  123. debug!(target: "validator::protocol_tx::start", "END");
  124. Ok(())
  125. }
  126. fn name(&self) -> &'static str {
  127. "ProtocolTx"
  128. }
  129. }