clock.rs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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. async fn time(&self) -> Result<Timestamp> {
  41. match time::check_clock(self.peers.clone()).await {
  42. Ok(t) => {
  43. Ok(time::ntp_request().await?)
  44. },
  45. Err(e) => {
  46. Err(Error::ClockOutOfSync(e.to_string()
  47. ))
  48. }
  49. }
  50. }
  51. /// time since genesis
  52. async fn time_to_genesis(&self) -> Timestamp {
  53. let genesis_time : i64 = GENESIS_TIME;
  54. let abs_time = self.time().await.unwrap();
  55. Timestamp(abs_time.0 - genesis_time)
  56. }
  57. async fn tick_time(&self) -> (u64, u64) {
  58. let time = self.time_to_genesis().await;
  59. let time_i = time.0 as u64;
  60. let tick_abs: u64 = time_i / self.tick_len;
  61. let tick_rel: u64 = time_i % self.tick_len;
  62. (tick_abs, tick_rel)
  63. }
  64. /// return true if the clock is at the begining (before 2/3 of the slot).
  65. async fn ticking(&self) -> bool {
  66. let (abs, rel) = self.tick_time().await;
  67. rel < (self.tick_len) /3
  68. }
  69. pub async fn sync(& mut self) -> Result<()> {
  70. let e = self.epoch_abs().await;
  71. let sl = self.slot_relative().await;
  72. self.sl = sl;
  73. self.e = e;
  74. Ok(())
  75. }
  76. /// absolute zero based slot index
  77. async fn slot_abs(&self) -> u64 {
  78. let sl_abs = self.tick_time().await.0 / self.sl_len;
  79. sl_abs
  80. }
  81. /// relative zero based slot index
  82. async fn slot_relative(&self) -> u64 {
  83. let e_abs = self.slot_abs().await % self.e_len;
  84. e_abs
  85. }
  86. /// absolute zero based epoch index.
  87. async fn epoch_abs(&self) -> u64 {
  88. let res = self.slot_abs().await / self.e_len;
  89. res
  90. }
  91. /// clock ticks return the ticks phase with corresponding phase parameters
  92. pub async fn ticks(&mut self) -> Ticks {
  93. let prev_e = self.e;
  94. let prev_sl = self.sl;
  95. let e = self.epoch_abs().await;
  96. let sl = self.slot_relative().await;
  97. if self.ticking().await {
  98. if e==prev_e&&e==BB_E && sl==prev_sl && sl==BB_SL {
  99. self.sl=sl; // 0
  100. self.e=e; // 0
  101. Ticks::GENESIS{e:e, sl:sl}
  102. } else if e==prev_e&&sl==prev_sl+1 {
  103. self.sl=sl;
  104. Ticks::NEWSLOT{e:e, sl:sl}
  105. } else if e==prev_e+1 && sl==0 {
  106. self.e=e;
  107. self.sl=sl;
  108. Ticks::NEWEPOCH{e:e, sl:sl}
  109. }
  110. else if e==prev_e && sl==prev_sl {
  111. Ticks::IDLE
  112. }
  113. else {
  114. //clock is out of sync
  115. Ticks::OUTOFSYNC
  116. }
  117. } else {
  118. Ticks::TOCKS
  119. }
  120. }
  121. }