Refactor: fixed point arithmetic for SRML. (#3456)

* Macro-ify perthings.

* Refactor fixed64

* Half-workign phragmen refactor.

* Finalize phragmen refactor.

* Fix creation of perquintill

* Fix build errors

* Line-width

* Fix more build errors.

* Line-width

* Fix offence test

* Resolve all TODOs.

* Apply suggestions from code review

Co-Authored-By: Gavin Wood <gavin@parity.io>
Co-Authored-By: thiolliere <gui.thiolliere@gmail.com>

* Fix most of the review comments.

* Updates to multiply by rational

* Fxi build

* Fix abs issue with Fixed64

* Fix tests and improvements.

* Fix build

* Remove more tests from staking.

* Review comments.

* Add fuzzing stuff.

* Better fuzzing

* Better doc.

* Bump.

* Master.into()

* A bit more hardening.

* Final nits.

* Update lock

* Fix indent.

* Revert lock file.

* Bump.
This commit is contained in:
Kian Paimani
2019-09-25 11:21:05 +02:00
committed by GitHub
parent 87688aadaa
commit 1c15ca6ad1
19 changed files with 1909 additions and 961 deletions
+220 -4
View File
@@ -19,8 +19,9 @@
#![cfg(test)]
use crate::mock::*;
use crate::{elect, ACCURACY, PhragmenResult};
use crate::{elect, PhragmenResult};
use support::assert_eq_uvec;
use sr_primitives::Perbill;
#[test]
fn float_phragmen_poc_works() {
@@ -90,9 +91,9 @@ fn phragmen_poc_works() {
assert_eq_uvec!(
assignments,
vec![
(10, vec![(2, ACCURACY)]),
(20, vec![(3, ACCURACY)]),
(30, vec![(2, ACCURACY/2), (3, ACCURACY/2)]),
(10, vec![(2, Perbill::from_percent(100))]),
(20, vec![(3, Perbill::from_percent(100))]),
(30, vec![(2, Perbill::from_percent(100/2)), (3, Perbill::from_percent(100/2))]),
]
);
}
@@ -133,3 +134,218 @@ fn phragmen_poc_3_works() {
run_and_compare(candidates, voters, stake_of, 2, 2, true);
}
#[test]
fn phragmen_accuracy_on_large_scale_only_validators() {
// because of this particular situation we had per_u128 and now rational128. In practice, a
// candidate can have the maximum amount of tokens, and also supported by the maximum.
let candidates = vec![1, 2, 3, 4, 5];
let stake_of = create_stake_of(&[
(1, (u64::max_value() - 1).into()),
(2, (u64::max_value() - 4).into()),
(3, (u64::max_value() - 5).into()),
(4, (u64::max_value() - 3).into()),
(5, (u64::max_value() - 2).into()),
]);
let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>(
2,
2,
candidates,
vec![],
stake_of,
true,
).unwrap();
assert_eq_uvec!(winners, vec![(1, 18446744073709551614u128), (5, 18446744073709551613u128)]);
assert_eq!(assignments.len(), 0);
check_assignments(assignments);
}
#[test]
fn phragmen_accuracy_on_large_scale_validators_and_nominators() {
let candidates = vec![1, 2, 3, 4, 5];
let voters = vec![
(13, vec![1, 3, 5]),
(14, vec![2, 4]),
];
let stake_of = create_stake_of(&[
(1, (u64::max_value() - 1).into()),
(2, (u64::max_value() - 4).into()),
(3, (u64::max_value() - 5).into()),
(4, (u64::max_value() - 3).into()),
(5, (u64::max_value() - 2).into()),
(13, (u64::max_value() - 10).into()),
(14, u64::max_value().into()),
]);
let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>(
2,
2,
candidates,
voters,
stake_of,
true,
).unwrap();
assert_eq_uvec!(winners, vec![(2, 36893488147419103226u128), (1, 36893488147419103219u128)]);
assert_eq!(
assignments,
vec![(13, vec![(1, Perbill::one())]), (14, vec![(2, Perbill::one())])]
);
check_assignments(assignments);
}
#[test]
fn phragmen_accuracy_on_small_scale_self_vote() {
let candidates = vec![40, 10, 20, 30];
let voters = vec![];
let stake_of = create_stake_of(&[
(40, 0),
(10, 1),
(20, 2),
(30, 1),
]);
let PhragmenResult { winners, assignments: _ } = elect::<_, _, _, TestCurrencyToVote>(
3,
3,
candidates,
voters,
stake_of,
true,
).unwrap();
assert_eq_uvec!(winners, vec![(20, 2), (10, 1), (30, 1)]);
}
#[test]
fn phragmen_accuracy_on_small_scale_no_self_vote() {
let candidates = vec![40, 10, 20, 30];
let voters = vec![
(1, vec![10]),
(2, vec![20]),
(3, vec![30]),
(4, vec![40]),
];
let stake_of = create_stake_of(&[
(40, 1000), // don't care
(10, 1000), // don't care
(20, 1000), // don't care
(30, 1000), // don't care
(4, 0),
(1, 1),
(2, 2),
(3, 1),
]);
let PhragmenResult { winners, assignments: _ } = elect::<_, _, _, TestCurrencyToVote>(
3,
3,
candidates,
voters,
stake_of,
false,
).unwrap();
assert_eq_uvec!(winners, vec![(20, 2), (10, 1), (30, 1)]);
}
#[test]
fn phragmen_large_scale_test() {
let candidates = vec![2, 4, 6, 8, 10, 12, 14, 16 ,18, 20, 22, 24];
let voters = vec![
(50, vec![2, 4, 6, 8, 10, 12, 14, 16 ,18, 20, 22, 24]),
];
let stake_of = create_stake_of(&[
(2, 1),
(4, 100),
(6, 1000000),
(8, 100000000001000),
(10, 100000000002000),
(12, 100000000003000),
(14, 400000000000000),
(16, 400000000001000),
(18, 18000000000000000),
(20, 20000000000000000),
(22, 500000000000100000),
(24, 500000000000200000),
(50, 990000000000000000),
]);
let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>(
2,
2,
candidates,
voters,
stake_of,
true,
).unwrap();
assert_eq_uvec!(winners, vec![(24, 1490000000000200000u128), (22, 1490000000000100000u128)]);
check_assignments(assignments);
}
#[test]
fn phragmen_large_scale_test_2() {
let nom_budget: u64 = 1_000_000_000_000_000_000;
let c_budget: u64 = 4_000_000;
let candidates = vec![2, 4];
let voters = vec![(50, vec![2, 4])];
let stake_of = create_stake_of(&[
(2, c_budget.into()),
(4, c_budget.into()),
(50, nom_budget.into()),
]);
let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>(
2,
2,
candidates,
voters,
stake_of,
true,
).unwrap();
assert_eq_uvec!(winners, vec![(2, 1000000000004000000u128), (4, 1000000000004000000u128)]);
assert_eq!(
assignments,
vec![(50, vec![(2, Perbill::from_parts(500000001)), (4, Perbill::from_parts(499999999))])],
);
check_assignments(assignments);
}
#[test]
fn phragmen_linear_equalize() {
let candidates = vec![11, 21, 31, 41, 51, 61, 71];
let voters = vec![
(2, vec![11]),
(4, vec![11, 21]),
(6, vec![21, 31]),
(8, vec![31, 41]),
(110, vec![41, 51]),
(120, vec![51, 61]),
(130, vec![61, 71]),
];
let stake_of = create_stake_of(&[
(11, 1000),
(21, 1000),
(31, 1000),
(41, 1000),
(51, 1000),
(61, 1000),
(71, 1000),
(2, 2000),
(4, 1000),
(6, 1000),
(8, 1000),
(110, 1000),
(120, 1000),
(130, 1000),
]);
run_and_compare(candidates, voters, stake_of, 2, 2, true);
}