|
@@ -3,7 +3,11 @@ use std::{thread, time::Duration};
|
|
|
use log::debug;
|
|
use log::debug;
|
|
|
use url::Url;
|
|
use url::Url;
|
|
|
|
|
|
|
|
-use crate::{util::time::Timestamp, Result};
|
|
|
|
|
|
|
+use crate::{util::time,
|
|
|
|
|
+ util::time::Timestamp,
|
|
|
|
|
+ error::Error,
|
|
|
|
|
+ Result};
|
|
|
|
|
+
|
|
|
|
|
|
|
|
pub enum Ticks {
|
|
pub enum Ticks {
|
|
|
GENESIS { e: u64, sl: u64 }, //genesis epoch
|
|
GENESIS { e: u64, sl: u64 }, //genesis epoch
|
|
@@ -20,8 +24,8 @@ const BB_E: u64 = 0; //big bang epoch time.
|
|
|
#[derive(Debug)]
|
|
#[derive(Debug)]
|
|
|
pub struct Clock {
|
|
pub struct Clock {
|
|
|
pub sl: u64, // relative slot index (zero-based) [0-len[
|
|
pub sl: u64, // relative slot index (zero-based) [0-len[
|
|
|
- pub e: u64, //epoch index (zero-based) [0-\inf[
|
|
|
|
|
- pub tick_len: u64, // tick length in time
|
|
|
|
|
|
|
+ pub e: u64, // epoch index (zero-based) [0-\inf[
|
|
|
|
|
+ pub tick_len: u64, // tick length in time (seconds)
|
|
|
pub sl_len: u64, // slot length in ticks
|
|
pub sl_len: u64, // slot length in ticks
|
|
|
pub e_len: u64, // epoch length in slots
|
|
pub e_len: u64, // epoch length in slots
|
|
|
pub peers: Vec<Url>,
|
|
pub peers: Vec<Url>,
|
|
@@ -57,20 +61,10 @@ impl Clock {
|
|
|
|
|
|
|
|
async fn time(&self) -> Result<Timestamp> {
|
|
async fn time(&self) -> Result<Timestamp> {
|
|
|
//TODO (fix) add more than ntp server to time, and take the avg
|
|
//TODO (fix) add more than ntp server to time, and take the avg
|
|
|
- /*
|
|
|
|
|
- match time::check_clock(self.peers.clone()).await {
|
|
|
|
|
- Ok(t) => {
|
|
|
|
|
- Ok(time::ntp_request().await?)
|
|
|
|
|
- },
|
|
|
|
|
- Err(e) => {
|
|
|
|
|
- Err(Error::ClockOutOfSync(e.to_string()))
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- */
|
|
|
|
|
Ok(Timestamp::current_time())
|
|
Ok(Timestamp::current_time())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// time since genesis
|
|
|
|
|
|
|
+ /// returns time since genesis in seconds.
|
|
|
async fn time_to_genesis(&self) -> Timestamp {
|
|
async fn time_to_genesis(&self) -> Timestamp {
|
|
|
//TODO this value need to be assigned to kickoff time.
|
|
//TODO this value need to be assigned to kickoff time.
|
|
|
let genesis_time: i64 = self.genesis_time.0;
|
|
let genesis_time: i64 = self.genesis_time.0;
|
|
@@ -78,18 +72,18 @@ impl Clock {
|
|
|
Timestamp(abs_time.0 - genesis_time)
|
|
Timestamp(abs_time.0 - genesis_time)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- async fn tick_time(&self) -> (u64, u64) {
|
|
|
|
|
- let time = self.time_to_genesis().await;
|
|
|
|
|
- let time_i = time.0 as u64;
|
|
|
|
|
- //let tick_abs: u64 = time_i / self.tick_len;
|
|
|
|
|
- let tick_rel: u64 = time_i % self.tick_len;
|
|
|
|
|
- (time_i, tick_rel)
|
|
|
|
|
|
|
+ /// return absolute tick to genesis, and relative tick index in the slot.
|
|
|
|
|
+ async fn tick_time(&self) -> (u64, u64,u64) {
|
|
|
|
|
+ let time = self.time_to_genesis().await.0 as u64;
|
|
|
|
|
+ let tick_abs: u64 = time / self.tick_len;
|
|
|
|
|
+ let tick_rel: u64 = time % self.tick_len;
|
|
|
|
|
+ (time, tick_rel, tick_abs)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// return true if the clock is at the begining (before 2/3 of the slot).
|
|
/// return true if the clock is at the begining (before 2/3 of the slot).
|
|
|
async fn ticking(&self) -> bool {
|
|
async fn ticking(&self) -> bool {
|
|
|
- let (abs, rel) = self.tick_time().await;
|
|
|
|
|
- debug!("abs ticks: {}, rel ticks: {}", abs, rel);
|
|
|
|
|
|
|
+ let (abs, rel, _) = self.tick_time().await;
|
|
|
|
|
+ debug!("abs time to genesis ticks: {}, rel ticks: {}", abs, rel);
|
|
|
rel < (self.tick_len) / 3
|
|
rel < (self.tick_len) / 3
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -101,35 +95,42 @@ impl Clock {
|
|
|
Ok(())
|
|
Ok(())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// absolute zero based slot index
|
|
|
|
|
|
|
+ /// returns absolute zero based slot index
|
|
|
async fn slot_abs(&self) -> u64 {
|
|
async fn slot_abs(&self) -> u64 {
|
|
|
let sl_abs = self.tick_time().await.0 / self.sl_len;
|
|
let sl_abs = self.tick_time().await.0 / self.sl_len;
|
|
|
debug!("[slot_abs] slot len: {} - slot abs: {}", self.sl_len, sl_abs);
|
|
debug!("[slot_abs] slot len: {} - slot abs: {}", self.sl_len, sl_abs);
|
|
|
sl_abs
|
|
sl_abs
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// relative zero based slot index
|
|
|
|
|
|
|
+ /// returns relative zero based slot index
|
|
|
async fn slot_relative(&self) -> u64 {
|
|
async fn slot_relative(&self) -> u64 {
|
|
|
let e_abs = self.slot_abs().await % self.e_len;
|
|
let e_abs = self.slot_abs().await % self.e_len;
|
|
|
debug!("[slot_relative] slot len: {} - slot relative: {}", self.sl_len, e_abs);
|
|
debug!("[slot_relative] slot len: {} - slot relative: {}", self.sl_len, e_abs);
|
|
|
e_abs
|
|
e_abs
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// absolute zero based epoch index.
|
|
|
|
|
|
|
+ /// returns absolute zero based epoch index.
|
|
|
async fn epoch_abs(&self) -> u64 {
|
|
async fn epoch_abs(&self) -> u64 {
|
|
|
let res = self.slot_abs().await / self.e_len;
|
|
let res = self.slot_abs().await / self.e_len;
|
|
|
debug!("[epoch_abs] epoch len: {} - epoch abs: {}", self.e_len, res);
|
|
debug!("[epoch_abs] epoch len: {} - epoch abs: {}", self.e_len, res);
|
|
|
res
|
|
res
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// clock ticks return the ticks phase with corresponding phase parameters
|
|
|
|
|
|
|
+ /// return the ticks phase with corresponding phase parameters
|
|
|
|
|
+ ///
|
|
|
|
|
+ /// the Ticks enum can include epoch index, and relative slot index (zero-based)
|
|
|
pub async fn ticks(&mut self) -> Ticks {
|
|
pub async fn ticks(&mut self) -> Ticks {
|
|
|
|
|
+ // also debug the failing function.
|
|
|
let e = self.epoch_abs().await;
|
|
let e = self.epoch_abs().await;
|
|
|
let sl = self.slot_relative().await;
|
|
let sl = self.slot_relative().await;
|
|
|
if self.ticking().await {
|
|
if self.ticking().await {
|
|
|
- debug!(
|
|
|
|
|
- "e/e`: {}/{} sl/sl`: {}/{}, BB_E/BB_SL: {}/{}",
|
|
|
|
|
- e, self.e, sl, self.sl, BB_E, BB_SL
|
|
|
|
|
|
|
+ debug!("e/e`: {}/{} sl/sl`: {}/{}, BB_E/BB_SL: {}/{}",
|
|
|
|
|
+ e,
|
|
|
|
|
+ self.e,
|
|
|
|
|
+ sl,
|
|
|
|
|
+ self.sl,
|
|
|
|
|
+ BB_E,
|
|
|
|
|
+ BB_SL
|
|
|
);
|
|
);
|
|
|
if e == self.e && e == BB_E && self.sl == BB_SL {
|
|
if e == self.e && e == BB_E && self.sl == BB_SL {
|
|
|
self.sl = sl + 1; // 0
|
|
self.sl = sl + 1; // 0
|
|
@@ -160,3 +161,51 @@ impl Clock {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+#[cfg(test)]
|
|
|
|
|
+mod tests {
|
|
|
|
|
+ use std::{thread, time::Duration};
|
|
|
|
|
+ use crate::util::clock::{Clock,Ticks};
|
|
|
|
|
+ use futures::executor::block_on;
|
|
|
|
|
+ use crate::util::time;
|
|
|
|
|
+ #[test]
|
|
|
|
|
+ fn clock_works() {
|
|
|
|
|
+ let clock = Clock::new(Some(9),
|
|
|
|
|
+ Some(9),
|
|
|
|
|
+ Some(9),
|
|
|
|
|
+ vec![]
|
|
|
|
|
+ );
|
|
|
|
|
+ //block th for 3 secs
|
|
|
|
|
+ thread::sleep(Duration::from_millis(1000));
|
|
|
|
|
+ let ttg = block_on(clock.time_to_genesis()).0;
|
|
|
|
|
+ assert!(ttg>=1 && ttg<2);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ fn clock_ticking() {
|
|
|
|
|
+ let clock = Clock::new(Some(9),
|
|
|
|
|
+ Some(9),
|
|
|
|
|
+ Some(9),
|
|
|
|
|
+ vec![]
|
|
|
|
|
+ );
|
|
|
|
|
+ //block th for 3 secs
|
|
|
|
|
+ thread::sleep(Duration::from_millis(1000));
|
|
|
|
|
+ assert!(block_on(clock.ticking()));
|
|
|
|
|
+ thread::sleep(Duration::from_millis(1000));
|
|
|
|
|
+ assert!(block_on(clock.ticking()));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ fn clock_ticks() {
|
|
|
|
|
+ let mut clock = Clock::new(Some(9),
|
|
|
|
|
+ Some(9),
|
|
|
|
|
+ Some(9),
|
|
|
|
|
+ vec![]
|
|
|
|
|
+ );
|
|
|
|
|
+ //
|
|
|
|
|
+ let tick : Ticks = block_on(clock.ticks());
|
|
|
|
|
+ assert_eq!(matches!(tick, Ticks::GENESIS{e:0,sl:0}), true);
|
|
|
|
|
+ thread::sleep(Duration::from_millis(3000));
|
|
|
|
|
+ let tock : Ticks = block_on(clock.ticks());
|
|
|
|
|
+ assert_eq!(matches!(tock, Ticks::TOCKS), true);
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+}
|