Skip to content

Commit

Permalink
[Consensus] avoid subtracting from current Instant (#18939)
Browse files Browse the repository at this point in the history
## Description 

On Windows, `Instant::now()` can be close to 0 and we cannot subtract
from that.

## Test plan 

CI. Verified on a Windows machine.

---

## Release notes

Check each box that your changes affect. If none of the boxes relate to
your changes, release notes aren't required.

For each box you select, include information after the relevant heading
that describes the impact of your changes that a user might notice and
any actions they must take to implement updates.

- [ ] Protocol: 
- [ ] Nodes (Validators and Full nodes): 
- [ ] Indexer: 
- [ ] JSON-RPC: 
- [ ] GraphQL: 
- [ ] CLI: 
- [ ] Rust SDK:
- [ ] REST API:
  • Loading branch information
mwtian authored and suiwombat committed Sep 16, 2024
1 parent 475c94d commit 43c1156
Showing 1 changed file with 32 additions and 16 deletions.
48 changes: 32 additions & 16 deletions consensus/core/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,34 +96,50 @@ impl Context {
}
}

/// A clock that allows to derive the current UNIX system timestamp while guaranteeing that
/// timestamp will be monotonically incremented having tolerance to ntp and system clock changes and corrections.
/// A clock that allows to derive the current UNIX system timestamp while guaranteeing that timestamp
/// will be monotonically incremented, tolerating ntp and system clock changes and corrections.
/// Explicitly avoid to make `[Clock]` cloneable to ensure that a single instance is shared behind an `[Arc]`
/// wherever is needed in order to make sure that consecutive calls to receive the system timestamp
/// will remain monotonically increasing.
pub(crate) struct Clock {
unix_epoch_instant: Instant,
initial_instant: Instant,
initial_system_time: SystemTime,
}

impl Clock {
pub fn new() -> Self {
let now = Instant::now();
let duration_since_unix_epoch =
match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
Ok(d) => d,
Err(e) => panic!("SystemTime before UNIX EPOCH! {e}"),
};
let unix_epoch_instant = now.checked_sub(duration_since_unix_epoch).unwrap();

Self { unix_epoch_instant }
Self {
initial_instant: Instant::now(),
initial_system_time: SystemTime::now(),
}
}

// Returns the current time expressed as UNIX timestamp in milliseconds.
// Calculated with Rust Instant to ensure monotonicity.
// Calculated with Tokio Instant to ensure monotonicity,
// and to allow testing with tokio clock.
pub(crate) fn timestamp_utc_ms(&self) -> BlockTimestampMs {
Instant::now()
.checked_duration_since(self.unix_epoch_instant)
.unwrap()
let now: Instant = Instant::now();
let monotonic_system_time = self
.initial_system_time
.checked_add(
now.checked_duration_since(self.initial_instant)
.unwrap_or_else(|| {
panic!(
"current instant ({:?}) < initial instant ({:?})",
now, self.initial_instant
)
}),
)
.expect("Computing system time should not overflow");
monotonic_system_time
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap_or_else(|_| {
panic!(
"system time ({:?}) < UNIX_EPOCH ({:?})",
monotonic_system_time,
SystemTime::UNIX_EPOCH,
)
})
.as_millis() as BlockTimestampMs
}
}

0 comments on commit 43c1156

Please sign in to comment.