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

Loans: Moment as Seconds & Millis explicitly #1575

Merged
merged 14 commits into from
Oct 16, 2023
Merged

Conversation

lemunozm
Copy link
Contributor

@lemunozm lemunozm commented Sep 29, 2023

Description

Fixes: #1360

Instead of having an agnostic Moment type, this PR modifies the codebase to reason about Seconds or Millis and avoid mixing them in pallets.

Changes and Descriptions

  • New trait when the intention is to obtain the seconds, and another to convert into it.
  • Added Seconds and Millis types (by now, there are in cfg_traits, but all this machinery should be moved to a future cfg_utils: Internal dependencies organization #1380).
  • Remove the Moment type, which is a too-open name. The name is still used for traits agnostic of the time unit.
  • Refactor some pallets to explicitly reason about seconds.
  • Fixed some time bug found in pallet-loans

Checklist

  • pallet-loans impl
  • pallet-loans tests
  • pallet-interest-accrual impl
  • pallet-pools impl
  • pallet-pools tests
  • permission types => Because internally it retrived seconds, I modify them to use directly the new Seconds type. But I'm not sure if a more correct solution would be to make permission types more independent from secs. Although it would require a refactor to use it from pallet-pool-system correctly I guess. By now, I think using Seconds directly simplifies things.
  • pallet-liquidity-pools
  • pallet-registry
  • update runtime configurations with new time types.

mustermeiszer
mustermeiszer previously approved these changes Sep 29, 2023
Copy link
Collaborator

@mustermeiszer mustermeiszer left a comment

Choose a reason for hiding this comment

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

Do you in the same run change it for all pallets?

@lemunozm
Copy link
Contributor Author

Until I get exhausted 😆

Comment on lines +258 to +262
ActivePricing::External(pricing) => Ok(now
>= pricing
.last_updated(pool_id)?
.into_seconds()
.ensure_add(*secs)?),
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 was actually a bug. Test were unable to catch this, because we were treating the oracle as seconds too.

Now, since the Moment type coming from the oracles and Seconds from loans are different types we are protected. This kind of issue can be checked now at compile time, forcing you to call into_seconds() to convert among them.

I think is not a severe bug, but not sure if we need to make an upgrade to this.
cc @hieronx @mustermeiszer

Copy link
Collaborator

Choose a reason for hiding this comment

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

What was the bug here? Oracles are actually millies?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Assuming we hit this, this means

  • now is given in seconds
  • last_updated is given in milli-seconds
  • secs is given in seconds

The widest false positive in the Ok(bool) logic we can get will then be at most 0.999 seconds, and as we are not caring for that in the compatrison we will anyways never hit that, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, orml_oracle sets the timestamp as milliseconds.

Exactly, so right now, this trigger can not be triggered.

Comment on lines +639 to +643
/// Type to represent milliseconds
pub type Millis = u64;

/// Type to represent seconds
pub type Seconds = u64;
Copy link
Contributor Author

@lemunozm lemunozm Oct 9, 2023

Choose a reason for hiding this comment

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

An interesting improvement for this would be having them as wrapper types to avoid mixing them in the runtimes. By now, for pallets that use both as pallet-loans, having one by Config solves this issue, forcing to convert them though into_seconds()

@lemunozm lemunozm changed the title Loans: moment as secs explicitelly Loans: Moment as Seconds & Millis explicitly Oct 9, 2023
@lemunozm lemunozm self-assigned this Oct 9, 2023
@lemunozm lemunozm added I2-bug The code fails to follow expected behaviour. Q3-medium Can be done with good experience in the language, but little knowledge of the codebase. labels Oct 9, 2023
@lemunozm
Copy link
Contributor Author

This is finished and can be merged

Copy link
Collaborator

@mustermeiszer mustermeiszer left a comment

Choose a reason for hiding this comment

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

Thanks! That was tedious.


impl IntoSeconds for Millis {
fn into_seconds(self) -> Seconds {
self / 1000
Copy link
Collaborator

Choose a reason for hiding this comment

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

Safe-math?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A division by 1000 can never crash

Comment on lines +258 to +262
ActivePricing::External(pricing) => Ok(now
>= pricing
.last_updated(pool_id)?
.into_seconds()
.ensure_add(*secs)?),
Copy link
Collaborator

Choose a reason for hiding this comment

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

What was the bug here? Oracles are actually millies?

Comment on lines +258 to +262
ActivePricing::External(pricing) => Ok(now
>= pricing
.last_updated(pool_id)?
.into_seconds()
.ensure_add(*secs)?),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Assuming we hit this, this means

  • now is given in seconds
  • last_updated is given in milli-seconds
  • secs is given in seconds

The widest false positive in the Ok(bool) logic we can get will then be at most 0.999 seconds, and as we are not caring for that in the compatrison we will anyways never hit that, right?

@lemunozm
Copy link
Contributor Author

lemunozm commented Oct 16, 2023

Thanks for the review!

As a note aside, related to this PR #1380, probably Seconds / Millis (and maybe even the traits) would be in cfg-utils in the future, because they're generic and runtime-unrelated types

@lemunozm lemunozm merged commit 470298d into main Oct 16, 2023
10 checks passed
@lemunozm lemunozm deleted the loans/moment-as-secs branch October 16, 2023 10:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
I2-bug The code fails to follow expected behaviour. Q3-medium Can be done with good experience in the language, but little knowledge of the codebase.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Traits: Add TimeAsSecs trait
2 participants