Browse Source

script/research/clock_sync: moved to src/util/time.rs and src/error.rs, updated cargo dependencies, darkfid2: added system time check at start

aggstam 4 years ago
parent
commit
90cda47154

+ 69 - 30
Cargo.lock

@@ -157,7 +157,7 @@ dependencies = [
  "concurrent-queue",
  "futures-lite",
  "libc",
- "log",
+ "log 0.4.16",
  "once_cell",
  "parking",
  "polling",
@@ -256,7 +256,7 @@ dependencies = [
  "futures-lite",
  "gloo-timers",
  "kv-log-macro",
- "log",
+ "log 0.4.16",
  "memchr",
  "num_cpus",
  "once_cell",
@@ -291,7 +291,7 @@ checksum = "a1b71b31561643aa8e7df3effe284fa83ab1a840e52294c5f4bd7bfd8b2becbb"
 dependencies = [
  "futures-io",
  "futures-util",
- "log",
+ "log 0.4.16",
  "pin-project-lite",
  "tungstenite",
 ]
@@ -783,6 +783,15 @@ version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
 
+[[package]]
+name = "conv"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299"
+dependencies = [
+ "custom_derive",
+]
+
 [[package]]
 name = "core-foundation"
 version = "0.9.3"
@@ -865,7 +874,7 @@ dependencies = [
  "cranelift-codegen-shared",
  "cranelift-entity",
  "gimli 0.25.0",
- "log",
+ "log 0.4.16",
  "regalloc",
  "smallvec",
  "target-lexicon",
@@ -900,7 +909,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "279afcc0d3e651b773f94837c3d581177b348c8d69e928104b2e9fccb226f921"
 dependencies = [
  "cranelift-codegen",
- "log",
+ "log 0.4.16",
  "smallvec",
  "target-lexicon",
 ]
@@ -1127,6 +1136,12 @@ dependencies = [
  "zeroize",
 ]
 
+[[package]]
+name = "custom_derive"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9"
+
 [[package]]
 name = "dao-cli"
 version = "0.3.0"
@@ -1138,7 +1153,7 @@ dependencies = [
  "clap 3.1.12",
  "darkfi",
  "futures",
- "log",
+ "log 0.4.16",
  "num_cpus",
  "serde_json",
  "simplelog",
@@ -1157,7 +1172,7 @@ dependencies = [
  "darkfi",
  "easy-parallel",
  "futures",
- "log",
+ "log 0.4.16",
  "num_cpus",
  "serde_json",
  "simplelog",
@@ -1204,8 +1219,9 @@ dependencies = [
  "lazy_static",
  "libc",
  "libsqlite3-sys",
- "log",
+ "log 0.4.16",
  "native-tls",
+ "ntp",
  "num-bigint",
  "pasta_curves",
  "rand",
@@ -1269,7 +1285,7 @@ dependencies = [
  "futures-lite",
  "fxhash",
  "lazy-init",
- "log",
+ "log 0.4.16",
  "num-bigint",
  "pasta_curves",
  "rand",
@@ -1469,7 +1485,7 @@ dependencies = [
  "darkfi",
  "easy-parallel",
  "fxhash",
- "log",
+ "log 0.4.16",
  "num_cpus",
  "rand",
  "serde",
@@ -1495,7 +1511,7 @@ dependencies = [
  "async-std",
  "clap 3.1.12",
  "darkfi",
- "log",
+ "log 0.4.16",
  "serde_json",
  "simplelog",
  "url",
@@ -1656,7 +1672,7 @@ dependencies = [
  "anyhow",
  "async-std",
  "futures",
- "log",
+ "log 0.4.16",
  "thiserror",
 ]
 
@@ -1685,7 +1701,7 @@ dependencies = [
  "futures-lite",
  "hex",
  "lazy-init",
- "log",
+ "log 0.4.16",
  "num-bigint",
  "rand",
  "serde",
@@ -1750,7 +1766,7 @@ dependencies = [
  "freetype",
  "lazy_static",
  "libc",
- "log",
+ "log 0.4.16",
  "pathfinder_geometry",
  "pathfinder_simd",
  "servo-fontconfig",
@@ -2251,7 +2267,7 @@ dependencies = [
  "futures",
  "futures-rustls",
  "fxhash",
- "log",
+ "log 0.4.16",
  "rand",
  "serde",
  "serde_json",
@@ -2304,7 +2320,7 @@ version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
 dependencies = [
- "log",
+ "log 0.4.16",
 ]
 
 [[package]]
@@ -2362,6 +2378,15 @@ dependencies = [
  "scopeguard",
 ]
 
+[[package]]
+name = "log"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
+dependencies = [
+ "log 0.4.16",
+]
+
 [[package]]
 name = "log"
 version = "0.4.16"
@@ -2469,7 +2494,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc"
 dependencies = [
  "libc",
- "log",
+ "log 0.4.16",
  "miow",
  "ntapi",
  "winapi",
@@ -2498,7 +2523,7 @@ checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9"
 dependencies = [
  "lazy_static",
  "libc",
- "log",
+ "log 0.4.16",
  "openssl",
  "openssl-probe",
  "openssl-sys",
@@ -2540,6 +2565,20 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "ntp"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06b0d2de4a2cd60c3ac85c98a1fc23668bc97bef2b10b706bccd88efb229497d"
+dependencies = [
+ "byteorder",
+ "conv",
+ "custom_derive",
+ "error-chain",
+ "log 0.3.9",
+ "time 0.1.44",
+]
+
 [[package]]
 name = "num-bigint"
 version = "0.4.3"
@@ -2745,7 +2784,7 @@ version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0b7b7e7b4ea703700ce73ebf128e1450eb69c3a8329199ffbfb9b2a0418e5ad3"
 dependencies = [
- "log",
+ "log 0.4.16",
  "pathfinder_simd",
 ]
 
@@ -2886,7 +2925,7 @@ checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259"
 dependencies = [
  "cfg-if 1.0.0",
  "libc",
- "log",
+ "log 0.4.16",
  "wepoll-ffi",
  "winapi",
 ]
@@ -3191,7 +3230,7 @@ version = "0.0.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "571f7f397d61c4755285cd37853fe8e03271c243424a907415909379659381c5"
 dependencies = [
- "log",
+ "log 0.4.16",
  "rustc-hash",
  "smallvec",
 ]
@@ -3328,7 +3367,7 @@ version = "0.20.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921"
 dependencies = [
- "log",
+ "log 0.4.16",
  "ring",
  "sct",
  "webpki",
@@ -3587,7 +3626,7 @@ version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "48dfff04aade74dd495b007c831cd6f4e0cee19c344dd9dc0884c0289b70a786"
 dependencies = [
- "log",
+ "log 0.4.16",
  "termcolor",
  "time 0.3.9",
 ]
@@ -3625,7 +3664,7 @@ dependencies = [
  "fs2",
  "fxhash",
  "libc",
- "log",
+ "log 0.4.16",
  "parking_lot",
 ]
 
@@ -3726,7 +3765,7 @@ dependencies = [
  "itoa 1.0.1",
  "libc",
  "libsqlite3-sys",
- "log",
+ "log 0.4.16",
  "memchr",
  "once_cell",
  "paste",
@@ -3925,7 +3964,7 @@ dependencies = [
  "clap 3.1.12",
  "darkfi",
  "futures",
- "log",
+ "log 0.4.16",
  "num_cpus",
  "prettytable-rs",
  "rand",
@@ -3954,7 +3993,7 @@ dependencies = [
  "easy-parallel",
  "futures",
  "hex",
- "log",
+ "log 0.4.16",
  "num_cpus",
  "rand",
  "serde",
@@ -4117,7 +4156,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09"
 dependencies = [
  "cfg-if 1.0.0",
- "log",
+ "log 0.4.16",
  "pin-project-lite",
  "tracing-attributes",
  "tracing-core",
@@ -4174,7 +4213,7 @@ dependencies = [
  "bytes",
  "http",
  "httparse",
- "log",
+ "log 0.4.16",
  "rand",
  "sha-1",
  "thiserror",
@@ -4387,7 +4426,7 @@ checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4"
 dependencies = [
  "bumpalo",
  "lazy_static",
- "log",
+ "log 0.4.16",
  "proc-macro2",
  "quote",
  "syn",

+ 5 - 2
Cargo.toml

@@ -59,6 +59,7 @@ native-tls = {version = "0.2.10", optional = true}
 # Networking
 socket2 = {version = "0.4.4", optional = true}
 futures-rustls = {version = "0.22.1", features = ["dangerous_configuration"], optional = true}
+ntp = {version = "0.5.0", optional = true}
 
 # TLS cert utilities
 ed25519-compact = {version = "1.0.11", features = ["pem"], optional = true}
@@ -118,7 +119,6 @@ incrementalmerkletree = {version = "0.3.0-beta.2", optional = true}
 halo2_proofs = {git = "https://github.com/parazyd/halo2", branch = "clone-impls-keys", features = ["dev-graph", "gadget-traces", "sanity-checks"], optional = true}
 halo2_gadgets = {git = "https://github.com/parazyd/halo2", branch = "clone-impls-keys", features = ["dev-graph", "test-dependencies"], optional = true}
 
-
 # Smart contract runtime
 drk-sdk = {path = "src/sdk", optional = true}
 wasmer = {version = "2.2.1", optional = true}
@@ -166,8 +166,11 @@ util = [
 	"dirs",
 	"num-bigint",
 	"fxhash",
+	"chrono",
+	"ntp",
 
-
+    "async-net",
+    "async-runtime",
 	"darkfi-derive",
 	"darkfi-derive-internal",
 ]

+ 7 - 0
bin/darkfid2/src/main.rs

@@ -40,6 +40,7 @@ use darkfi::{
         cli::{log_config, spawn_config},
         expand_path,
         path::get_config_path,
+        time::check_clock,
     },
     wallet::walletdb::init_wallet,
     Error, Result,
@@ -199,6 +200,12 @@ impl Darkfid {
 
 async_daemonize!(realmain);
 async fn realmain(args: Args, ex: Arc<Executor<'_>>) -> Result<()> {
+    // We verify that the system clock is valid before initializing
+    if let Err(_) = check_clock().await {
+        error!("System clock is invalid, terminating...");
+        return Err(Error::InvalidClock)
+    };
+
     // We use this handler to block this function after detaching all
     // tasks, and to catch a shutdown signal, where we can clean up and
     // exit gracefully.

+ 0 - 2
script/research/clock_sync/.gitignore

@@ -1,2 +0,0 @@
-/target
-Cargo.lock

+ 0 - 23
script/research/clock_sync/Cargo.toml

@@ -1,23 +0,0 @@
-[package]
-name = "clock_sync"
-version = "0.1.0"
-edition = "2021"
-
-[dependencies.darkfi]
-path = "../../../"
-features = ["async-runtime", "rpc"]
-
-[dependencies]
-
-# Ntp request
-ntp = "0.5.0"
-
-# Misc
-async-std = "1.11.0"
-async-native-tls = "0.4.0"
-log = "0.4.16"
-serde_json = "1.0.81"
-simplelog = "0.12.0"
-thiserror = "1.0.24"
-
-[workspace]

+ 0 - 55
script/research/clock_sync/src/error.rs

@@ -1,55 +0,0 @@
-#[derive(Debug, thiserror::Error)]
-pub enum ClockError {
-    #[error("AsyncNativeTls error: '{0}'")]
-    AsyncNativeTlsError(String),
-    #[error("FromUtf8 error: '{0}'")]
-    FromUtf8Error(String),
-    #[error("System clock is not correct!")]
-    InvalidClock,
-    #[error("Io error: '{0}'")]
-    IoError(String),
-    #[error("NTP error: '{0}'")]
-    NtpError(String),
-    #[error("SerdeJson error: '{0}'")]
-    SerdeJsonError(String),
-    #[error("SystemTime error: '{0}'")]
-    SysTimeError(String),
-}
-
-pub type ClockResult<T> = std::result::Result<T, ClockError>;
-
-impl From<async_native_tls::Error> for ClockError {
-    fn from(err: async_native_tls::Error) -> ClockError {
-        ClockError::AsyncNativeTlsError(err.to_string())
-    }
-}
-
-impl From<std::string::FromUtf8Error> for ClockError {
-    fn from(err: std::string::FromUtf8Error) -> ClockError {
-        ClockError::FromUtf8Error(err.to_string())
-    }
-}
-
-impl From<ntp::errors::Error> for ClockError {
-    fn from(err: ntp::errors::Error) -> ClockError {
-        ClockError::NtpError(err.to_string())
-    }
-}
-
-impl From<serde_json::Error> for ClockError {
-    fn from(err: serde_json::Error) -> ClockError {
-        ClockError::SerdeJsonError(err.to_string())
-    }
-}
-
-impl From<std::io::Error> for ClockError {
-    fn from(err: std::io::Error) -> ClockError {
-        ClockError::IoError(err.to_string())
-    }
-}
-
-impl From<std::time::SystemTimeError> for ClockError {
-    fn from(err: std::time::SystemTimeError) -> ClockError {
-        ClockError::SysTimeError(err.to_string())
-    }
-}

+ 0 - 131
script/research/clock_sync/src/main.rs

@@ -1,131 +0,0 @@
-use async_std::{
-    io::{ReadExt, WriteExt},
-    net::TcpStream,
-};
-use std::{
-    thread,
-    time::{Duration, Instant, SystemTime, UNIX_EPOCH},
-};
-
-use log::{debug, error, info};
-use serde_json::Value;
-use simplelog::{ColorChoice, Config, LevelFilter, TermLogger, TerminalMode};
-
-use darkfi::Result;
-
-mod error;
-
-use crate::error::{ClockError, ClockResult};
-
-// Execution parameters
-const RETRIES: u8 = 5;
-const WORLDTIMEAPI_ADDRESS: &str = "worldtimeapi.org";
-const WORLDTIMEAPI_ADDRESS_WITH_PORT: &str = "worldtimeapi.org:443";
-const WORLDTIMEAPI_PAYLOAD: &[u8; 88] = b"GET /api/timezone/Etc/UTC HTTP/1.1\r\nHost: worldtimeapi.org\r\nAccept: application/json\r\n\r\n";
-const NTP_ADDRESS: &str = "0.pool.ntp.org:123";
-const EPOCH: u64 = 2208988800; //1900
-
-// Raw https request execution for worldtimeapi
-async fn worldtimeapi_request() -> ClockResult<Value> {
-    // Create connection
-    let stream = TcpStream::connect(WORLDTIMEAPI_ADDRESS_WITH_PORT).await?;
-    let mut stream = async_native_tls::connect(WORLDTIMEAPI_ADDRESS, stream).await?;
-    stream.write_all(WORLDTIMEAPI_PAYLOAD).await?;
-
-    // Execute request
-    let mut res = vec![0_u8; 1024];
-    stream.read(&mut res).await?;
-
-    // Parse response
-    let reply = String::from_utf8(res)?;
-    let lines = reply.split('\n');
-    // JSON data exist in last row of response
-    let last = lines.last().unwrap().trim_matches(char::from(0));
-    debug!("worldtimeapi json response: {}", last);
-    let reply = serde_json::from_str(last)?;
-    Ok(reply)
-}
-
-// This is a very simple check to verify that system time is correct.
-// Retry loop is used to in case discrepancies are found.
-// If all retries fail, system clock is considered invalid.
-// TODO: 1. Add proxy functionality in order not to leak connections
-//       2. Improve requests and/or add extra protocols
-async fn check_clock() -> ClockResult<()> {
-    debug!("System clock check started...");
-    let mut r = 0;
-    while r < RETRIES {
-        if let Err(e) = clock_check().await {
-            error!("Error during clock check: {}", e);
-            r += 1;
-            continue
-        };
-        break        
-    }
-
-    debug!("System clock check finished. Retries: {}", r);    
-    match r {
-        RETRIES => Err(ClockError::InvalidClock),
-        _ => Ok(()),
-    }
-}
-
-async fn clock_check() -> ClockResult<()> {
-    // Start elapsed time counter to cover for all requests and processing time
-    let requests_start = Instant::now();
-    // Poll worldtimeapi.org for current UTC timestamp
-    let worldtimeapi_response = worldtimeapi_request().await?;
-
-    // Start elapsed time counter to cover for ntp request and processing time
-    let ntp_request_start = Instant::now();
-    // Poll ntp.org for current timestamp
-    let ntp_response: ntp::packet::Packet = ntp::request(NTP_ADDRESS)?;
-
-    // Extract worldtimeapi timestamp from json
-    let mut worldtimeapi_time = worldtimeapi_response["unixtime"].as_u64().unwrap();
-
-    // Remove 1900 epoch to reach UTC timestamp for ntp timestamp
-    let mut ntp_time = ntp_response.transmit_time.sec as u64 - EPOCH;
-
-    // Add elapsed time to respone times
-    ntp_time += ntp_request_start.elapsed().as_secs();
-    worldtimeapi_time += requests_start.elapsed().as_secs();
-
-    // To simulate wrong clock, we sleep some time
-    //let one_sec = Duration::new(1, 0);
-    //thread::sleep(one_sec);
-
-    // Current system time
-    let system_time = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs();
-
-    debug!("worldtimeapi_time: {}", worldtimeapi_time);
-    debug!("ntp_time: {}", ntp_time);
-    debug!("system_time: {}", system_time);
-
-    // We verify that system time is equal to worldtimeapi and ntp
-    let check = (system_time == worldtimeapi_time) && (system_time == ntp_time);
-    match check {
-        true => Ok(()),
-        false => Err(ClockError::InvalidClock),
-    }
-}
-
-#[async_std::main]
-async fn main() -> Result<()> {
-    TermLogger::init(
-        LevelFilter::Debug,
-        Config::default(),
-        TerminalMode::Mixed,
-        ColorChoice::Auto,
-    )?;
-
-    match check_clock().await {
-        Ok(()) => info!("System clock is correct!"),
-        Err(_) => {
-            error!("System clock is invalid, terminating...");
-            return Err(darkfi::Error::OperationFailed)
-        }
-    };
-
-    Ok(())
-}

+ 15 - 0
src/error.rs

@@ -149,6 +149,10 @@ pub enum Error {
     #[error("async_native_tls error: {0}")]
     AsyncNativeTlsError(String),
 
+    #[cfg(feature = "util")]
+    #[error("NTP error: {0}")]
+    NtpError(String),
+
     // =============
     // Crypto errors
     // =============
@@ -288,6 +292,10 @@ pub enum Error {
     #[cfg(feature = "regex")]
     #[error(transparent)]
     RegexError(#[from] regex::Error),
+    
+    #[cfg(feature = "util")]
+    #[error("System clock is not correct!")]
+    InvalidClock,
 
     // ==============================================
     // Wrappers for other error types in this library
@@ -501,3 +509,10 @@ impl From<wasmer::InstantiationError> for Error {
         Self::WasmerInstantiationError(err.to_string())
     }
 }
+
+#[cfg(feature = "util")]
+impl From<ntp::errors::Error> for Error {
+    fn from(err: ntp::errors::Error) -> Self {
+        Self::NtpError(err.to_string())
+    }
+}

+ 1 - 1
src/util/mod.rs

@@ -17,4 +17,4 @@ pub use async_util::sleep;
 pub use net_name::NetworkName;
 pub use parse::{decode_base10, encode_base10};
 pub use path::{expand_path, join_config_path, load_keypair_to_str};
-pub use time::Timestamp;
+pub use time::{check_clock, Timestamp};

+ 105 - 1
src/util/time.rs

@@ -1,6 +1,15 @@
+use async_std::{
+    io::{ReadExt, WriteExt},
+    net::TcpStream,
+};
 use chrono::{NaiveDateTime, Utc};
+use log::debug;
+use serde_json::Value;
 
-use crate::util::serial::{SerialDecodable, SerialEncodable};
+use crate::{
+    util::serial::{SerialDecodable, SerialEncodable},
+    Error, Result,
+};
 
 /// Wrapper struct to represent [`chrono`] UTC timestamps.
 #[derive(Debug, Copy, Clone, PartialEq, SerialDecodable, SerialEncodable)]
@@ -19,4 +28,99 @@ impl Timestamp {
         let diff = end_time - start_time;
         diff.num_seconds() as u64
     }
+
+    /// Increment a 'Timestamp'.
+    pub fn add(&mut self, inc: i64) {
+        self.0 += inc;
+    }
+}
+
+// Clock sync parameters
+const RETRIES: u8 = 5;
+const WORLDTIMEAPI_ADDRESS: &str = "worldtimeapi.org";
+const WORLDTIMEAPI_ADDRESS_WITH_PORT: &str = "worldtimeapi.org:443";
+const WORLDTIMEAPI_PAYLOAD: &[u8; 88] = b"GET /api/timezone/Etc/UTC HTTP/1.1\r\nHost: worldtimeapi.org\r\nAccept: application/json\r\n\r\n";
+const NTP_ADDRESS: &str = "0.pool.ntp.org:123";
+const EPOCH: i64 = 2208988800; //1900
+
+// Raw https request execution for worldtimeapi
+async fn worldtimeapi_request() -> Result<Value> {
+    // Create connection
+    let stream = TcpStream::connect(WORLDTIMEAPI_ADDRESS_WITH_PORT).await?;
+    let mut stream = async_native_tls::connect(WORLDTIMEAPI_ADDRESS, stream).await?;
+    stream.write_all(WORLDTIMEAPI_PAYLOAD).await?;
+
+    // Execute request
+    let mut res = vec![0_u8; 1024];
+    stream.read(&mut res).await?;
+
+    // Parse response
+    let reply = String::from_utf8(res)?;
+    let lines = reply.split('\n');
+    // JSON data exist in last row of response
+    let last = lines.last().unwrap().trim_matches(char::from(0));
+    debug!("worldtimeapi json response: {:#?}", last);
+    let reply = serde_json::from_str(last)?;
+
+    Ok(reply)
+}
+
+// This is a very simple check to verify that system time is correct.
+// Retry loop is used to in case discrepancies are found.
+// If all retries fail, system clock is considered invalid.
+// TODO: 1. Add proxy functionality in order not to leak connections
+//       2. Improve requests and/or add extra protocols
+pub async fn check_clock() -> Result<()> {
+    debug!("System clock check started...");
+    let mut r = 0;
+    while r < RETRIES {
+        if let Err(e) = clock_check().await {
+            debug!("Error during clock check: {:#?}", e);
+            r += 1;
+            continue
+        };
+        break
+    }
+
+    debug!("System clock check finished. Retries: {:#?}", r);
+    match r {
+        RETRIES => Err(Error::InvalidClock),
+        _ => Ok(()),
+    }
+}
+
+async fn clock_check() -> Result<()> {
+    // Start elapsed time counter to cover for all requests and processing time
+    let requests_start = Timestamp::current_time();
+    // Poll worldtimeapi.org for current UTC timestamp
+    let worldtimeapi_response = worldtimeapi_request().await?;
+
+    // Start elapsed time counter to cover for ntp request and processing time
+    let ntp_request_start = Timestamp::current_time();
+    // Poll ntp.org for current timestamp
+    let ntp_response: ntp::packet::Packet = ntp::request(NTP_ADDRESS)?;
+
+    // Extract worldtimeapi timestamp from json
+    let mut worldtimeapi_time = Timestamp(worldtimeapi_response["unixtime"].as_i64().unwrap());
+
+    // Remove 1900 epoch to reach UTC timestamp for ntp timestamp
+    let mut ntp_time = Timestamp(ntp_response.transmit_time.sec as i64 - EPOCH);
+
+    // Add elapsed time to respone times
+    ntp_time.add(ntp_request_start.elapsed() as i64);
+    worldtimeapi_time.add(requests_start.elapsed() as i64);
+
+    // Current system time
+    let system_time = Timestamp::current_time();
+
+    debug!("worldtimeapi_time: {:#?}", worldtimeapi_time);
+    debug!("ntp_time: {:#?}", ntp_time);
+    debug!("system_time: {:#?}", system_time);
+
+    // We verify that system time is equal to worldtimeapi and ntp
+    let check = (system_time == worldtimeapi_time) && (system_time == ntp_time);
+    match check {
+        true => Ok(()),
+        false => Err(Error::InvalidClock),
+    }
 }