proposal.rs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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::{constants, 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 last finalization syncing period, 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 sync_offset = Duration::new(constants::FINAL_SYNC_DUR + 1, 0);
  32. loop {
  33. if seconds_until_next_epoch > sync_offset {
  34. seconds_until_next_epoch -= sync_offset;
  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. // Node sleeps until finalization sync period start (2 seconds before next slot)
  57. let seconds_sync_period = (state.read().await.next_n_slot_start(1) -
  58. Duration::new(constants::FINAL_SYNC_DUR, 0))
  59. .as_secs();
  60. info!("consensus: Waiting for finalization sync period ({} sec)", seconds_sync_period);
  61. sleep(seconds_sync_period).await;
  62. // Check if any forks can be finalized
  63. match state.write().await.chain_finalization().await {
  64. Ok(to_broadcast) => {
  65. // Broadcast finalized blocks info, if any:
  66. if to_broadcast.len() > 0 {
  67. info!("consensus: Broadcasting finalized blocks");
  68. for info in to_broadcast {
  69. match sync_p2p.broadcast(info).await {
  70. Ok(()) => info!("consensus: Broadcasted block"),
  71. Err(e) => error!("consensus: Failed broadcasting block: {}", e),
  72. }
  73. }
  74. } else {
  75. info!("consensus: No finalized blocks to broadcast");
  76. }
  77. }
  78. Err(e) => {
  79. error!("consensus: Finalization check failed: {}", e);
  80. }
  81. }
  82. // Node sleeps until next slot
  83. let seconds_next_slot = state.read().await.next_n_slot_start(1).as_secs();
  84. info!("consensus: Waiting for next slot ({} sec)", seconds_next_slot);
  85. sleep(seconds_next_slot).await;
  86. // Retrieve slot sigmas
  87. let (sigma1, sigma2) = state.write().await.sigmas();
  88. // Node checks if epoch has changed, to generate new epoch coins
  89. let epoch_changed = state.write().await.epoch_changed(sigma1, sigma2).await;
  90. match epoch_changed {
  91. Ok(changed) => {
  92. if changed {
  93. info!("consensus: New epoch started: {}", state.read().await.consensus.epoch);
  94. }
  95. }
  96. Err(e) => {
  97. error!("consensus: Epoch check failed: {}", e);
  98. continue
  99. }
  100. };
  101. // Node checks if it's the slot leader to generate a new proposal
  102. // for that slot.
  103. let (won, idx) = state.write().await.is_slot_leader(sigma1, sigma2);
  104. let result = if won { state.write().await.propose(idx, sigma1, sigma2) } else { Ok(None) };
  105. let proposal = match result {
  106. Ok(prop) => {
  107. if prop.is_none() {
  108. info!("consensus: Node is not the slot lead");
  109. continue
  110. }
  111. prop.unwrap()
  112. }
  113. Err(e) => {
  114. error!("consensus: Block proposal failed: {}", e);
  115. continue
  116. }
  117. };
  118. // Node stores the proposal and broadcast to rest nodes
  119. info!("consensus: Node is the slot leader: Proposed block: {}", proposal);
  120. debug!("consensus: Full proposal: {:?}", proposal);
  121. match state.write().await.receive_proposal(&proposal).await {
  122. Ok(()) => {
  123. info!("consensus: Block proposal saved successfully");
  124. // Broadcast proposal to other consensus nodes
  125. match consensus_p2p.broadcast(proposal).await {
  126. Ok(()) => info!("consensus: Proposal broadcasted successfully"),
  127. Err(e) => error!("consensus: Failed broadcasting proposal: {}", e),
  128. }
  129. }
  130. Err(e) => {
  131. error!("consensus: Block proposal save failed: {}", e);
  132. }
  133. }
  134. }
  135. }