Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Make perthings operate in type operator#2501

Merged
gavofyork merged 17 commits intomasterfrom
gui-perthings-operate-in-type
May 15, 2019
Merged

Make perthings operate in type operator#2501
gavofyork merged 17 commits intomasterfrom
gui-perthings-operate-in-type

Conversation

@gui1117
Copy link
Contributor

@gui1117 gui1117 commented May 8, 2019

#2441

Done:

  • implementation of Mul for Perthings now requires more traits
  • new implementation work this way (let's say for bill=1_000_000 and part is part per million)
    (b / bill) * part + ((b.rem(bill)) * part) / bill
    first term operate in N arithmetic thus it is ensure to be OK, second term operate in u64 arithmetic but as remainder is less that a billion and billion*billion operation does fit in u64 it is OK.

TODO:

  • also implement PerU128

@gui1117 gui1117 added the A3-in_progress Pull request is in progress. No review needed at this stage. label May 8, 2019
@gui1117 gui1117 changed the title perthings operate in type operator Perthings operate in type operator May 8, 2019
@gui1117 gui1117 changed the title Perthings operate in type operator Make perthings operate in type operator May 8, 2019
@bkchr
Copy link
Member

bkchr commented May 8, 2019

Can we add a test?

@gui1117
Copy link
Contributor Author

gui1117 commented May 9, 2019

I don't have strong opinion but I want to break the test saturating_mul for those reasons:

  • ops::Mul in Rust does panic on overflow, and if user want a saturating_mul user should call the function explicitely.
    such a function can be provided on Per* structure as well.

  • implementating the current behavior while making operation happening in N arithmetic space imply requiring CheckMul on N. which looks strange to me to require checkedmul to implement mul.

But could be confinced as:

  • operation is more likely to overflow than at first glance as user might not expect to be implemented this way.

@kianenigma
Copy link
Contributor

Categorically agreeing on panicking on normal Ops, if overflow happens, except if explicitly saturating_xxx.

As for the test case, I would say it should go away over the normal Mul. It is essentially testing that data is lost and no error is emitted (maybe replaced with a tailored one for saturating if we implement it).

@gui1117
Copy link
Contributor Author

gui1117 commented May 10, 2019

well CheckedMul trait cannot be implemented because it is too restrictive (we don't want to multiply Perbills but Perbill with another type)
But still functions can be implemented.

The question is: to we want Mul implementation to do saturation or panic on overlfow. I don't know.

@gui1117 gui1117 requested a review from kianenigma May 10, 2019 12:12
@gui1117 gui1117 added A0-please_review Pull request needs code review. and removed A3-in_progress Pull request is in progress. No review needed at this stage. A4-gotissues labels May 10, 2019
@gui1117
Copy link
Contributor Author

gui1117 commented May 10, 2019

implementation updated to be valid even for number near the maximum value allowed

@gui1117 gui1117 added A3-in_progress Pull request is in progress. No review needed at this stage. and removed A4-gotissues A0-please_review Pull request needs code review. labels May 10, 2019
@gavofyork
Copy link
Member

given this is exclusively for the runtime, and thus panicking can cause economic weaknesses (or worse), i think we want to saturate.

@gui1117
Copy link
Contributor Author

gui1117 commented May 13, 2019

ok so current implementation operates without loss and without overflow by seperating operation on quotient and remainder.

This come with the cost of some more operation but nothing huge (just remainder operation in arithmetic of N, some division and some multiplication in arithmetic of N and u64).

I think it is ready to review, we still want to implement operation for PerU128 but it is not as straightforward as we cannot do easily the remainder operation of b with u128::MAX because b type might not overset u128.
So I can make a similar implementation by bounding As<u128> which could only be used by type bigger than u128 or I might be able to make more precise bound on operation with some TryFrom things, but could be done in another PR

@gui1117 gui1117 added A0-please_review Pull request needs code review. and removed A3-in_progress Pull request is in progress. No review needed at this stage. A4-gotissues labels May 13, 2019
@kianenigma
Copy link
Contributor

I think the current new implementations are much better and should be kept.

You can, for now, ignore PerU128; as you mentioned you cannot do the same with it atm. I will create an issue for my self and be done in the foreseeable future to re-think how PerU128 is used in staking and if it can be capped back to maybe Perquintill? At the time I made PerU128 be able to handle this:

c.score = Fraction::from_xth(c.approval_stake);

where approval_stake is the sum of a few balances stored as a u128. It can easily be more than balance::max_value(), hence, at the time with As<u64>, more than u64. Perquintill would have not been enough for this. But maybe with the new insight, you have an idea of how this can be improved?

Copy link
Contributor

@kianenigma kianenigma left a comment

Choose a reason for hiding this comment

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

I tried adding some more test cases locally for the edge cases but the impl seems to okay.

Given that this eliminates the chance of overflow then there's also no more dilemma regarding saturating or panicking.

@gui1117
Copy link
Contributor Author

gui1117 commented May 13, 2019

@kianenigma you can add new test to this PR if you want

@gavofyork
Copy link
Member

will wait for the additional test from @kianenigma

@gavofyork gavofyork added A3-in_progress Pull request is in progress. No review needed at this stage. and removed A0-please_review Pull request needs code review. labels May 13, 2019
@kianenigma kianenigma added A0-please_review Pull request needs code review. and removed A3-in_progress Pull request is in progress. No review needed at this stage. A4-gotissues labels May 14, 2019
@kianenigma
Copy link
Contributor

  • All per-things now have the minimum api of one(), zero(), from_parts(), from_percent(). Open to debate. Rest can be deemed optional and if needed. Also removed some of the unused ones.
  • New test kinda contains the old ones so if you agree @thiolliere I can remove them.
  • A test to demonstrate that now all operations happen in the scope of the output type N. The panic in the test is expected; maybe we should safeguard against it?


assert_eq!(Perbill::one() * 255_u64, 255);
// panics
assert_ne!(Perbill::one() * 255_u8, 255);
Copy link
Contributor Author

@gui1117 gui1117 May 15, 2019

Choose a reason for hiding this comment

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

hmm yes I expect As<u64> to be a type that contains u64 which is false. maybe we should bound From<u32> as well so it can't panic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

maybe we shouldn't bound As but only From<u32> and TryInto<u32> actually it would work and never panic: we convert to u32 the remainder which is less that a billion.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the thing is also that From<u32> is not implemented for simple arithmetic nor balance generic. And bounding a new trait to Currency::Balance is not super handy. Though we will want this at some point when we get rid of As

Copy link
Contributor Author

Choose a reason for hiding this comment

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

or we could also bound some stuff like Rem<u32, Output=N>

Copy link
Contributor

Choose a reason for hiding this comment

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

All of the above additional bounds though would have to be enforced to Balance, right? if so then I would say we should leave it as it is (test can also stay as a demonstration), as I don't see this as really our concern.

These are utilities that we use and provide to substrate users as well. In our case, our balance types are actually big enough to work fine with this impl; And as for the users, this seems to be the most generally safe approach. There will always be anomalies, but in this case, it will be a balance type of u16 and u8 which is not really realistic.

What we could ultimately do to favor these group (or they can just do it themselves) is to create an actual struct percent(u8). In this case, all u16 and u8 balances will also have sane arithmetic (I haven't done this but it looks to work).

Unless if there is an obvious simple way that we don't see, I see the current code as okay.

Copy link
Contributor

Choose a reason for hiding this comment

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

Noting that if, for example, if your balance is u8, the granularity of a per-thing being more than 1/255 is actually pointless as there is no way to reflect it on the actual data type.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not really it can be bound on module side by having an associated type Balance: From<u32> and write Curreny associated type like Currency<Balance=Self::Balance> but it creates a new associated type which is not beautiful.

@gavofyork gavofyork merged commit 528db6e into master May 15, 2019
@gavofyork gavofyork deleted the gui-perthings-operate-in-type branch May 15, 2019 16:49
MTDK1 pushed a commit to bdevux/substrate that referenced this pull request Jul 10, 2019
* perthings operate in type operator

* implementation with rem

* fmt

* doc

* better fmt

* bump version

* Tests for pet-things

* demonstrate output as type of operation

* Remove redundant assertions.

* rename test

* update lock

* bump impl version
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

A0-please_review Pull request needs code review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants