proposal.rs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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 std::time::Duration;
  19. use log::{debug, error, info};
  20. use super::consensus_sync_task;
  21. use crate::{
  22. consensus::{Participant, ValidatorStatePtr},
  23. net::P2pPtr,
  24. util::async_util::sleep,
  25. };
  26. /// async task used for participating in the consensus protocol
  27. pub async fn proposal_task(consensus_p2p: P2pPtr, sync_p2p: P2pPtr, state: ValidatorStatePtr) {
  28. // Node waits just before the current or next epoch end, so it can
  29. // start syncing latest state.
  30. let mut seconds_until_next_epoch = state.read().await.next_n_epoch_start(1);
  31. let one_sec = Duration::new(1, 0);
  32. loop {
  33. if seconds_until_next_epoch > one_sec {
  34. seconds_until_next_epoch -= one_sec;
  35. break
  36. }
  37. info!("consensus: Waiting for next epoch ({:?} sec)", seconds_until_next_epoch);
  38. sleep(seconds_until_next_epoch.as_secs()).await;
  39. seconds_until_next_epoch = state.read().await.next_n_epoch_start(1);
  40. }
  41. info!("consensus: Waiting for next epoch ({:?} sec)", seconds_until_next_epoch);
  42. sleep(seconds_until_next_epoch.as_secs()).await;
  43. // Node syncs its consensus state
  44. if let Err(e) = consensus_sync_task(consensus_p2p.clone(), state.clone()).await {
  45. error!("consensus: Failed syncing consensus state: {}. Quitting consensus.", e);
  46. // TODO: Perhaps notify over a channel in order to
  47. // stop consensus p2p protocols.
  48. return
  49. };
  50. // Node modifies its participating slot to next.
  51. match state.write().await.set_participating() {
  52. Ok(()) => info!("consensus: Node will start participating in the next slot"),
  53. Err(e) => error!("consensus: Failed to set participation slot: {}", e),
  54. }
  55. loop {
  56. let seconds_next_slot = state.read().await.next_n_slot_start(1).as_secs();
  57. info!("consensus: Waiting for next slot ({} sec)", seconds_next_slot);
  58. sleep(seconds_next_slot).await;
  59. // Node checks if epoch has changed, to broadcast a new participation message
  60. let epoch_changed = state.write().await.epoch_changed().await;
  61. match epoch_changed {
  62. Ok(changed) => {
  63. if changed {
  64. info!("consensus: New epoch started: {}", state.read().await.current_epoch());
  65. let public_key = state.read().await.public_key;
  66. let mut coins = vec![];
  67. for slot_coins in &state.read().await.consensus.coins {
  68. let mut slot_coins_inputs = vec![];
  69. for slot_coin in slot_coins {
  70. slot_coins_inputs.push(slot_coin.public_inputs());
  71. }
  72. coins.push(slot_coins_inputs);
  73. }
  74. let participant = Participant::new(public_key, coins);
  75. state.write().await.append_participant(&participant);
  76. match consensus_p2p.broadcast(participant).await {
  77. Ok(()) => {
  78. info!("consensus: Participation message broadcasted successfully.")
  79. }
  80. Err(e) => {
  81. error!("consensus: Failed broadcasting consensus participation: {}", e)
  82. }
  83. }
  84. // Node sleeps 2 seconds so all nodes can have the new epoch participants
  85. //TODO: optimize this
  86. sleep(2).await;
  87. }
  88. }
  89. Err(e) => {
  90. error!("consensus: Epoch check failed: {}", e);
  91. continue
  92. }
  93. };
  94. // Node checks if it's the slot leader to generate a new proposal
  95. // for that slot.
  96. let (won, idx) = state.read().await.is_slot_leader();
  97. let result = if won { state.write().await.propose(idx) } else { Ok(None) };
  98. let proposal = match result {
  99. Ok(prop) => {
  100. if prop.is_none() {
  101. info!("consensus: Node is not the slot lead");
  102. continue
  103. }
  104. prop.unwrap()
  105. }
  106. Err(e) => {
  107. error!("consensus: Block proposal failed: {}", e);
  108. continue
  109. }
  110. };
  111. info!("consensus: Node is the slot leader: Proposed block: {}", proposal);
  112. debug!("consensus: Full proposal: {:?}", proposal);
  113. match state.write().await.receive_proposal(&proposal).await {
  114. Ok(to_broadcast) => {
  115. info!("consensus: Block proposal saved successfully");
  116. // Broadcast block to other consensus nodes
  117. match consensus_p2p.broadcast(proposal).await {
  118. Ok(()) => info!("consensus: Proposal broadcasted successfully"),
  119. Err(e) => error!("consensus: Failed broadcasting proposal: {}", e),
  120. }
  121. // Broadcast finalized blocks info, if any:
  122. if let Some(blocks) = to_broadcast {
  123. if blocks.len() > 0 {
  124. info!("consensus: Broadcasting finalized blocks");
  125. for info in blocks {
  126. match sync_p2p.broadcast(info).await {
  127. Ok(()) => info!("consensus: Broadcasted block"),
  128. Err(e) => error!("consensus: Failed broadcasting block: {}", e),
  129. }
  130. }
  131. }
  132. } else {
  133. info!("consensus: No finalized blocks to broadcast");
  134. }
  135. }
  136. Err(e) => {
  137. error!("consensus: Block proposal save failed: {}", e);
  138. }
  139. }
  140. }
  141. }