From d25d3896d74b4aa80555ea5de88bd86c2ccd50f4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <bkchr@users.noreply.github.com>
Date: Mon, 18 Oct 2021 10:18:13 +0200
Subject: [PATCH] Make duration calculation robust against clock drift (#10042)

It is possible that `Instant::now()` is returning an earlier clock time when being called a second
time. To guard against this, we should use `saturating_duration_since`.
---
 substrate/client/db/src/lib.rs | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/substrate/client/db/src/lib.rs b/substrate/client/db/src/lib.rs
index 549ef4012a7..3b8936c0f7b 100644
--- a/substrate/client/db/src/lib.rs
+++ b/substrate/client/db/src/lib.rs
@@ -1076,13 +1076,14 @@ impl<T: Clone> FrozenForDuration<T> {
 		F: FnOnce() -> T,
 	{
 		let mut lock = self.value.lock();
-		if lock.at.elapsed() > self.duration || lock.value.is_none() {
+		let now = std::time::Instant::now();
+		if now.saturating_duration_since(lock.at) > self.duration || lock.value.is_none() {
 			let new_value = f();
-			lock.at = std::time::Instant::now();
+			lock.at = now;
 			lock.value = Some(new_value.clone());
 			new_value
 		} else {
-			lock.value.as_ref().expect("checked with lock above").clone()
+			lock.value.as_ref().expect("Checked with in branch above; qed").clone()
 		}
 	}
 }
-- 
GitLab