Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create a separate type for absolute time + some related fixes and refactoring #1235

Merged
merged 8 commits into from
Sep 28, 2023

Conversation

TheQuantumPhysicist
Copy link
Contributor

Please check the code relevant to your work and see if it makes sense.

There's a test broken in block production because it used the wrong time source and modified the global mocked time. That's gonna be fixed in this PR before merging it.

Copy link
Contributor

@ImplOfAnImpl ImplOfAnImpl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yay!

Comment on lines +79 to +89
pub const fn saturating_duration_add(&self, duration: Duration) -> Self {
Self {
time: self.time.saturating_add(duration),
}
}

pub const fn saturating_duration_sub(&self, t: Duration) -> Self {
Self {
time: self.time.saturating_sub(t),
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest to name these methods just saturating_add and saturating_sub, so that Duration is implied as the type of the operand, because it's implied in operator + and for consistency with standard types like SystemTime.
Instead, I'd rename the current saturating_sub to saturating_diff.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also occurred to me, and I'm not insistent about it. My only issue with it is that usually saturating_sub usually takes Self. Using something other than Self seems unnatural.

Copy link
Contributor

@iljakuklic iljakuklic Sep 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the problems you hit when coming up with a name for this is that both Time - Duration (returning Time) and Time - Time (returning Duration or something similar) are sensible operations. Plain saturating_sub should probably be reserved for the latter, even if it's never implemented.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's pretty much my thought process... saturating_sub should be reserved for Time - Time. It's kind of the norm in rust.

Comment on lines +96 to +102
impl std::ops::Add<Duration> for Time {
type Output = Option<Self>;

fn add(self, other: Duration) -> Option<Self> {
self.time.checked_add(other).map(|time| Self { time })
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest to make Add implementation panic, just like it does for Duration and SystemTime.
For returning an Option, I'd add a separate method checked_add.

Same for Sub (also, taking into account the suggestion above, we could have both checked_sub for subtracting durations and checked_diff for subtracting times).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't take this the wrong way... but... the irony... comparing this to issue #1221... 😄

Having said that: I do prefer enforcing checked math wherever possible... especially when it's global like this one.

I do understand there are many expects, but I'm OK with that as long as it's fully controlled. In fact, for uint, we're moving to further checked_add by default everywhere.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you say, but I'd argue that this comment and the mentioned issue have nothing in common.
Here we talking about whether to panic implicitly or explicitly. IMO for types like Duration implicit panics are OK and since with explicit ones we lose convenience (quite a lot of it IMO), I'd go with the former. But I can see your point too.
In the issue though, the question is whether we should panic in certain situations or not.

Comment on lines +59 to +66
pub const fn from_time(time: Time) -> Self {
Self::from_duration_since_epoch(time.as_duration_since_epoch())
}

pub const fn into_time(self) -> Time {
Time::from_duration_since_epoch(self.as_duration_since_epoch())
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether we should have impl From<BlockTimestamp> for Time and impl From<Time> for BlockTimestamp instead of these functions (or in addition to them).
Some of the conversions would become less verbose.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about that, but the reason I didn't go for it was that Time and BlockTimestamp don't necessarily have 1:1 equivalence. In fact, I was thinking of calling the function in BlockTimestamp "approximate_from_time()".

common/src/primitives/time.rs Outdated Show resolved Hide resolved
common/src/primitives/time.rs Outdated Show resolved Hide resolved
p2p/src/peer_manager/peerdb/mod.rs Outdated Show resolved Hide resolved
p2p/src/peer_manager/peerdb/mod.rs Outdated Show resolved Hide resolved
Comment on lines +562 to 568
let max_block_timestamp = BlockTimestamp::from_time(max_accepted_time);
if block_timestamp > max_block_timestamp {
let block_timestamp = block_timestamp.as_duration_since_epoch();
let max_block_timestamp = max_block_timestamp.as_duration_since_epoch();

let clock_diff =
block_timestamp.checked_sub(max_block_timestamp).unwrap_or_else(|| {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest to implement checked subtraction for Time (which I'd call checked_diff) and use it here directly instead of converting times to durations.

Same for the V2 peer.

Comment on lines +1525 to +1526
next_time_resend_own_address = (next_time_resend_own_address + delay)
.expect("Time derived from local clock; cannot fail");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, AddAssign would be nice to have.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't work with Option<_>

@@ -77,11 +77,11 @@ fn reachable_reconnects(#[case] seed: Seed) {
address.transition_to(AddressStateTransitionTo::ConnectionFailed, now, &mut rng);
connection_attempts += 1;
}
now += Duration::from_secs(60);
now = (now + Duration::from_secs(60)).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment about AddAssign

Comment on lines -34 to 36
/// Table for banned addresses
/// Table for banned addresses vs when they can be unbanned (Duration is timestamp since UNIX Epoch)
pub DBBannedAddresses: Map<String, Duration>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like Duration is not quite appropriate here (but not sure Time is).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Time cannot be be encoded, so Duration is just something that can be encoded. It's an implementation detail. It's converted to Time when loaded.

@TheQuantumPhysicist TheQuantumPhysicist merged commit 7cc4918 into master Sep 28, 2023
23 checks passed
@TheQuantumPhysicist TheQuantumPhysicist deleted the feat/separate_abs_time_type branch September 28, 2023 09:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants