clock.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. use url::Url;
  2. use log::debug;
  3. use async_trait::async_trait;
  4. use crate::{
  5. util::{time,Timestamp},
  6. error,
  7. Result,
  8. error::Error
  9. };
  10. pub enum Ticks {
  11. GENESIS{e: u64, sl: u64}, //genesis epoch
  12. NEWSLOT{e: u64, sl: u64}, // new slot
  13. NEWEPOCH{e: u64, sl: u64}, // new epoch
  14. TOCKS, //tocks, or slot is ending
  15. IDLE, // idle clock state
  16. OUTOFSYNC, //clock, and blockchain are out of sync
  17. }
  18. const BB_SL : u64 = u64::MAX; //big bang slot time (need to be negative value)
  19. const BB_E : u64 = 0; //big bang epoch time.
  20. const GENESIS_TIME : i64 = 0;
  21. #[derive(Debug)]
  22. pub struct Clock {
  23. pub sl : u64, // relative slot index (zero-based) [0-len[
  24. pub e : u64, //epoch index (zero-based) [0-\inf[
  25. pub tick_len: u64, // tick length in time
  26. pub sl_len: u64, // slot length in ticks
  27. pub e_len: u64, // epoch length in slots
  28. pub peers: Vec<Url>,
  29. }
  30. impl Clock {
  31. pub fn new(e_len: Option<u64>, sl_len: Option<u64>, tick_len: Option<u64>, peers: Vec<Url>) -> Self{
  32. Self { sl: BB_SL, //necessary for genesis slot
  33. e: BB_E,
  34. tick_len: tick_len.unwrap_or(22), // 22 seconds
  35. sl_len: sl_len.unwrap_or(22),// ~8 minutes
  36. e_len: e_len.unwrap_or(3), // 24.2 minutes
  37. peers: peers,
  38. }
  39. }
  40. pub fn get_sl_len(&self) -> u64 {
  41. self.sl_len
  42. }
  43. pub fn get_e_len(&self) -> u64 {
  44. self.e_len
  45. }
  46. async fn time(&self) -> Result<Timestamp> {
  47. match time::check_clock(self.peers.clone()).await {
  48. Ok(t) => {
  49. Ok(time::ntp_request().await?)
  50. },
  51. Err(e) => {
  52. Err(Error::ClockOutOfSync(e.to_string()
  53. ))
  54. }
  55. }
  56. }
  57. /// time since genesis
  58. async fn time_to_genesis(&self) -> Timestamp {
  59. let genesis_time : i64 = GENESIS_TIME;
  60. let abs_time = self.time().await.unwrap();
  61. Timestamp(abs_time.0 - genesis_time)
  62. }
  63. async fn tick_time(&self) -> (u64, u64) {
  64. let time = self.time_to_genesis().await;
  65. let time_i = time.0 as u64;
  66. let tick_abs: u64 = time_i / self.tick_len;
  67. let tick_rel: u64 = time_i % self.tick_len;
  68. (tick_abs, tick_rel)
  69. }
  70. /// return true if the clock is at the begining (before 2/3 of the slot).
  71. async fn ticking(&self) -> bool {
  72. let (abs, rel) = self.tick_time().await;
  73. rel < (self.tick_len) /3
  74. }
  75. pub async fn sync(& mut self) -> Result<()> {
  76. let e = self.epoch_abs().await;
  77. let sl = self.slot_relative().await;
  78. self.sl = sl;
  79. self.e = e;
  80. Ok(())
  81. }
  82. /// absolute zero based slot index
  83. async fn slot_abs(&self) -> u64 {
  84. let sl_abs = self.tick_time().await.0 / self.sl_len;
  85. sl_abs
  86. }
  87. /// relative zero based slot index
  88. async fn slot_relative(&self) -> u64 {
  89. let e_abs = self.slot_abs().await % self.e_len;
  90. e_abs
  91. }
  92. /// absolute zero based epoch index.
  93. async fn epoch_abs(&self) -> u64 {
  94. let res = self.slot_abs().await / self.e_len;
  95. res
  96. }
  97. /// clock ticks return the ticks phase with corresponding phase parameters
  98. pub async fn ticks(&mut self) -> Ticks {
  99. let prev_e = self.e;
  100. let prev_sl = self.sl;
  101. let e = self.epoch_abs().await;
  102. let sl = self.slot_relative().await;
  103. if self.ticking().await {
  104. if e==prev_e&&e==BB_E && sl==prev_sl && sl==BB_SL {
  105. self.sl=sl; // 0
  106. self.e=e; // 0
  107. Ticks::GENESIS{e:e, sl:sl}
  108. } else if e==prev_e&&sl==prev_sl+1 {
  109. self.sl=sl;
  110. Ticks::NEWSLOT{e:e, sl:sl}
  111. } else if e==prev_e+1 && sl==0 {
  112. self.e=e;
  113. self.sl=sl;
  114. Ticks::NEWEPOCH{e:e, sl:sl}
  115. }
  116. else if e==prev_e && sl==prev_sl {
  117. Ticks::IDLE
  118. }
  119. else {
  120. //clock is out of sync
  121. Ticks::OUTOFSYNC
  122. }
  123. } else {
  124. Ticks::TOCKS
  125. }
  126. }
  127. }