-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Staking module: approximate fraction into perbill to avoid overflow #2889
Conversation
This is good in terms of replacing the two potentially dangerous multiplication closures. I wonder if we have anywhere else in runtime such cases? (relating to the topic of the issue: sweep runtime..). Furthermore: I think this is enough to replace the whole if *c != n.who {
- let ratio = {
- // Full support. No need to calculate.
- if *n.load == *e.load { Perbill::one() }
- else {
- // This should not saturate. Safest is to just check
- if let Some(r) = ACCURACY.checked_mul(*e.load) {
- r / n.load.max(1)
- } else {
- // Just a simple trick.
- *e.load / (n.load.max(1) / ACCURACY)
- }
- }
- };
+ let ratio = Perbill::from_rational_approximation(*e.load() / *n.load)
e.ratio = ratio;
assignment.1.push((e.who.clone(), ratio));
} Since here the ACCURACY is already u32 it should be good to fit in Perbill. Some minor changes are then needed to the lib.rs file as well. I also thought about what to do with U128. I think unfortunately it is simply impossible to approximate it with Perbill/mill due to notorious
where c.approval_stake can, in theory (not in practice thou') be more than the max balance type and this is will be in an issue:
(^^ actually overflows, I was expecting it to collapse to zero) |
Yes I think introducing Persomething in phragmen worth it. we can introduce Perbill or create PerU32 or even create PerU64 (we can't do more easily as we need double size arithmetic, and u128 is kind of the limit. |
though in another PR |
would be nice to see a test for the overflow case (that fails on the original code) |
yes done |
Co-Authored-By: Niklas Adolfsson <niklasadolfsson1@gmail.com>
…aritytech#2889) * approximate fraction into perbill * test * fix comment * line width * bump impl version * rename test for better naming * test overflow * Apply suggestions from code review Co-Authored-By: Niklas Adolfsson <niklasadolfsson1@gmail.com>
previous strategy: #2863
related to #706 and #1572
in this PR we solve the potential overflow by approximating the fraction (nominator.value/total_exposure) into a Perbill.
This approximation is visible in tests as you can see a -1 in some reward in some test.
TODO: