lighthouse-pulse/beacon_chain/utils/shuffling/src/lib.rs

56 lines
1.3 KiB
Rust
Raw Normal View History

2018-10-03 03:43:46 +00:00
/// A library for performing deterministic, pseudo-random shuffling on a vector.
///
/// This library is designed to confirm to the Ethereum 2.0 specification.
extern crate hashing;
2018-08-14 06:23:38 +00:00
mod rng;
use self::rng::ShuffleRng;
#[derive(Debug)]
pub enum ShuffleErr {
ExceedsListLength,
}
2018-10-03 03:43:46 +00:00
/// Performs a deterministic, in-place shuffle of a vector.
///
2018-08-14 06:23:38 +00:00
/// The final order of the shuffle is determined by successive hashes
/// of the supplied `seed`.
2018-10-03 03:43:46 +00:00
///
/// This is a Fisher-Yates-Durtstenfeld shuffle.
pub fn shuffle<T>(
2018-08-14 06:23:38 +00:00
seed: &[u8],
2018-10-03 03:43:46 +00:00
mut list: Vec<T>)
-> Result<Vec<T>, ShuffleErr>
2018-08-14 06:23:38 +00:00
{
let mut rng = ShuffleRng::new(seed);
if list.len() > rng.rand_max as usize {
return Err(ShuffleErr::ExceedsListLength);
}
2018-08-14 06:23:38 +00:00
for i in 0..(list.len() - 1) {
let n = list.len() - i;
let j = rng.rand_range(n as u32) as usize + i;
list.swap(i, j);
}
Ok(list)
}
#[cfg(test)]
mod tests {
use super::*;
use super::hashing::canonical_hash;
2018-08-14 06:23:38 +00:00
#[test]
fn test_shuffling() {
let seed = canonical_hash(b"4kn4driuctg8");
2018-08-14 06:23:38 +00:00
let list: Vec<usize> = (0..12).collect();
let s = shuffle(&seed, list).unwrap();
2018-08-14 06:23:38 +00:00
assert_eq!(
s,
vec![7, 3, 2, 5, 11, 9, 1, 0, 4, 6, 10, 8],
2018-08-14 06:23:38 +00:00
)
}
}