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
[core] Fix proposals shuffling implementation #7921
Conversation
d473ee6
to
be5d9ff
Compare
chain/epoch-manager/src/proposals.rs
Outdated
let mut rng: Hc128Rng = SeedableRng::from_seed(rng_seed); | ||
dup_proposals.shuffle(&mut rng); | ||
for i in (1..dup_proposals.len()).rev() { | ||
dup_proposals.swap(i, gen_index_old(&mut rng, (i + 1) as u64) as usize); | ||
} | ||
} | ||
|
||
fn gen_index_old(rng: &mut Hc128Rng, bound: u64) -> u64 { | ||
// This is a simplified copy of the rand gen_index implementation to ensure that | ||
// upgrades to the rand library will not cause a change in the shuffling behavior. | ||
let zone = u64::MAX - (u64::MAX - bound + 1) % (bound); | ||
loop { | ||
let v = rng.next_u64(); | ||
let mul = (v as u128) * (bound as u128); | ||
let (hi, lo) = ((mul >> 64) as u64, mul as u64); | ||
if lo < zone { | ||
return hi; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we are feeling enterpisey, I'd probably extracted this code into a separate module/type EpochManagerRng
to make sure its public API doesn't expose rand
. Right now this code has an implicit invariant of "don't use any rand methods besides from_seed and next_u64", and I'd love for that invariant to have teeth.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry not exactly sure what you mean - the module is already named old_* and these two functions are not public.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, sorry, I missed two points:
- that this is already a separate module
- that we no longer relying on randomness here for the latest protocol
I was fearing that we still use rand
, and need to guard aginst future code changes.
The SliceRandom::shuffle implementation changed from rand 0.6.5 to 0.7.0 in a subtle way: rust-random/rand#809 because the underlying gen_index implementation changed. (It appears that @matklad 's concern on #7717 turns out to be quite real!)
In order to reproduce the old behavior and to make sure this never changes again, this PR replicates the gen_index implementation (it's pretty straight-forward) from 0.6.5. The test case is updated (the old test case was unfortunately incorrect from #7717). Also, @mm-near 's #7909 now passes with this change.