From 2763f7bc00123b399f1431fd2d58b3e545818fec Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 3 Oct 2018 13:13:51 +1000 Subject: [PATCH 1/3] Move shuffling to its own crate, update hash fn Previously blake2s-256 was being used, now blake2b-512[:32] is being used. --- Cargo.toml | 1 + beacon_chain/utils/shuffling/Cargo.toml | 7 + .../src/common => utils}/shuffling/README.md | 0 .../mod.rs => utils/shuffling/src/lib.rs} | 14 +- .../shuffling => utils/shuffling/src}/rng.rs | 30 ++-- .../test_vectors/shuffle_test_vectors.yaml | 162 ++++++++++++++++++ 6 files changed, 185 insertions(+), 29 deletions(-) create mode 100644 beacon_chain/utils/shuffling/Cargo.toml rename beacon_chain/{types/src/common => utils}/shuffling/README.md (100%) rename beacon_chain/{types/src/common/shuffling/mod.rs => utils/shuffling/src/lib.rs} (72%) rename beacon_chain/{types/src/common/shuffling => utils/shuffling/src}/rng.rs (75%) create mode 100644 beacon_chain/utils/shuffling/test_vectors/shuffle_test_vectors.yaml diff --git a/Cargo.toml b/Cargo.toml index d9f9d14bc87..de69506de2c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ members = [ "beacon_chain/utils/bls", "beacon_chain/utils/boolean-bitfield", "beacon_chain/utils/hashing", + "beacon_chain/utils/shuffling", "beacon_chain/utils/ssz", "beacon_chain/utils/ssz_helpers", "lighthouse/db", diff --git a/beacon_chain/utils/shuffling/Cargo.toml b/beacon_chain/utils/shuffling/Cargo.toml new file mode 100644 index 00000000000..df0a108eead --- /dev/null +++ b/beacon_chain/utils/shuffling/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "shuffling" +version = "0.1.0" +authors = ["Paul Hauner "] + +[dependencies] +hashing = { path = "../hashing" } diff --git a/beacon_chain/types/src/common/shuffling/README.md b/beacon_chain/utils/shuffling/README.md similarity index 100% rename from beacon_chain/types/src/common/shuffling/README.md rename to beacon_chain/utils/shuffling/README.md diff --git a/beacon_chain/types/src/common/shuffling/mod.rs b/beacon_chain/utils/shuffling/src/lib.rs similarity index 72% rename from beacon_chain/types/src/common/shuffling/mod.rs rename to beacon_chain/utils/shuffling/src/lib.rs index 432f38ff441..b99d400a142 100644 --- a/beacon_chain/types/src/common/shuffling/mod.rs +++ b/beacon_chain/utils/shuffling/src/lib.rs @@ -1,4 +1,4 @@ -extern crate blake2_rfc; +extern crate hashing; mod rng; @@ -33,20 +33,16 @@ pub fn shuffle( #[cfg(test)] mod tests { use super::*; - use super::blake2_rfc::blake2s::{ blake2s, Blake2sResult }; - - fn hash(seed: &[u8]) -> Blake2sResult { - blake2s(32, &[], seed) - } + use super::hashing::canonical_hash; #[test] fn test_shuffling() { - let seed = hash(b"4kn4driuctg8"); + let seed = canonical_hash(b"4kn4driuctg8"); let list: Vec = (0..12).collect(); - let s = shuffle(seed.as_bytes(), list).unwrap(); + let s = shuffle(&seed, list).unwrap(); assert_eq!( s, - vec![7, 4, 8, 6, 5, 3, 0, 11, 1, 2, 10, 9], + vec![7, 3, 2, 5, 11, 9, 1, 0, 4, 6, 10, 8], ) } } diff --git a/beacon_chain/types/src/common/shuffling/rng.rs b/beacon_chain/utils/shuffling/src/rng.rs similarity index 75% rename from beacon_chain/types/src/common/shuffling/rng.rs rename to beacon_chain/utils/shuffling/src/rng.rs index e43c582ff19..7ca6f18660a 100644 --- a/beacon_chain/types/src/common/shuffling/rng.rs +++ b/beacon_chain/utils/shuffling/src/rng.rs @@ -1,4 +1,4 @@ -use super::blake2_rfc::blake2s::{ Blake2s, Blake2sResult }; +use super::hashing::canonical_hash; const SEED_SIZE_BYTES: usize = 32; const RAND_BYTES: usize = 3; // 24 / 8 @@ -7,7 +7,7 @@ const RAND_MAX: u32 = 16_777_216; // 2**24 /// A pseudo-random number generator which given a seed /// uses successive blake2s hashing to generate "entropy". pub struct ShuffleRng { - seed: Blake2sResult, + seed: Vec, idx: usize, pub rand_max: u32, } @@ -16,7 +16,7 @@ impl ShuffleRng { /// Create a new instance given some "seed" bytes. pub fn new(initial_seed: &[u8]) -> Self { Self { - seed: hash(initial_seed), + seed: canonical_hash(initial_seed), idx: 0, rand_max: RAND_MAX, } @@ -24,7 +24,7 @@ impl ShuffleRng { /// "Regenerates" the seed by hashing it. fn rehash_seed(&mut self) { - self.seed = hash(self.seed.as_bytes()); + self.seed = canonical_hash(&self.seed); self.idx = 0; } @@ -36,7 +36,7 @@ impl ShuffleRng { self.rand() } else { int_from_byte_slice( - self.seed.as_bytes(), + &self.seed, self.idx - RAND_BYTES, ) } @@ -68,13 +68,6 @@ fn int_from_byte_slice(source: &[u8], offset: usize) -> u32 { ) } -/// Peform a blake2s hash on the given bytes. -fn hash(bytes: &[u8]) -> Blake2sResult { - let mut hasher = Blake2s::new(SEED_SIZE_BYTES); - hasher.update(bytes); - hasher.finalize() -} - #[cfg(test)] mod tests { @@ -115,15 +108,12 @@ mod tests { #[test] fn test_shuffling_hash_fn() { - let digest = hash(hash(b"4kn4driuctg8").as_bytes()); // double-hash is intentional - let digest_bytes = digest.as_bytes(); + let digest = canonical_hash(&canonical_hash(&"4kn4driuctg8".as_bytes())); // double-hash is intentional let expected = [ - 0xff, 0xff, 0xff, 0x8f, 0xbb, 0xc7, 0xab, 0x64, 0x43, 0x9a, - 0xe5, 0x12, 0x44, 0xd8, 0x70, 0xcf, 0xe5, 0x79, 0xf6, 0x55, - 0x6b, 0xbd, 0x81, 0x43, 0xc5, 0xcd, 0x70, 0x2b, 0xbe, 0xe3, - 0x87, 0xc7, + 103, 21, 99, 143, 60, 75, 116, 81, 248, 175, 190, 114, 54, 65, 23, 8, 3, 116, + 160, 178, 7, 75, 63, 47, 180, 239, 191, 247, 57, 194, 144, 88 ]; - assert_eq!(digest_bytes.len(), expected.len()); - assert_eq!(digest_bytes, expected) + assert_eq!(digest.len(), expected.len()); + assert_eq!(digest, expected) } } diff --git a/beacon_chain/utils/shuffling/test_vectors/shuffle_test_vectors.yaml b/beacon_chain/utils/shuffling/test_vectors/shuffle_test_vectors.yaml new file mode 100644 index 00000000000..e96f9e2d0c6 --- /dev/null +++ b/beacon_chain/utils/shuffling/test_vectors/shuffle_test_vectors.yaml @@ -0,0 +1,162 @@ +- input: [] + output: [] + seed: !!binary "" +- input: [0] + output: [0] + seed: !!binary "" +- input: [255] + output: [255] + seed: !!binary "" +- input: [4, 6, 2, 6, 1, 4, 6, 2, 1, 5] + output: [1, 6, 4, 1, 6, 6, 2, 2, 4, 5] + seed: !!binary "" +- input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] + output: [4, 7, 10, 13, 3, 1, 2, 9, 12, 6, 11, 8, 5] + seed: !!binary "" +- input: [65, 6, 2, 6, 1, 4, 6, 2, 1, 5] + output: [1, 6, 65, 1, 6, 6, 2, 2, 4, 5] + seed: !!binary "" +- input: [] + output: [] + seed: !!binary | + JlAYJ5H2j8g7PLiPHZI/rTS1uAvKiieOrifPN6Moso0= +- input: [0] + output: [0] + seed: !!binary | + JlAYJ5H2j8g7PLiPHZI/rTS1uAvKiieOrifPN6Moso0= +- input: [255] + output: [255] + seed: !!binary | + JlAYJ5H2j8g7PLiPHZI/rTS1uAvKiieOrifPN6Moso0= +- input: [4, 6, 2, 6, 1, 4, 6, 2, 1, 5] + output: [6, 4, 2, 5, 4, 2, 6, 6, 1, 1] + seed: !!binary | + JlAYJ5H2j8g7PLiPHZI/rTS1uAvKiieOrifPN6Moso0= +- input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] + output: [13, 1, 9, 8, 3, 10, 6, 2, 5, 12, 11, 4, 7] + seed: !!binary | + JlAYJ5H2j8g7PLiPHZI/rTS1uAvKiieOrifPN6Moso0= +- input: [65, 6, 2, 6, 1, 4, 6, 2, 1, 5] + output: [6, 65, 2, 5, 4, 2, 6, 6, 1, 1] + seed: !!binary | + JlAYJ5H2j8g7PLiPHZI/rTS1uAvKiieOrifPN6Moso0= +- input: [] + output: [] + seed: !!binary | + Jlpt1sTgPixEqKaQaX4rmZgxnh48U7igzJK1EjAkK0Q= +- input: [0] + output: [0] + seed: !!binary | + Jlpt1sTgPixEqKaQaX4rmZgxnh48U7igzJK1EjAkK0Q= +- input: [255] + output: [255] + seed: !!binary | + Jlpt1sTgPixEqKaQaX4rmZgxnh48U7igzJK1EjAkK0Q= +- input: [4, 6, 2, 6, 1, 4, 6, 2, 1, 5] + output: [6, 2, 5, 1, 6, 4, 1, 2, 4, 6] + seed: !!binary | + Jlpt1sTgPixEqKaQaX4rmZgxnh48U7igzJK1EjAkK0Q= +- input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] + output: [3, 8, 10, 4, 7, 11, 6, 1, 2, 5, 13, 9, 12] + seed: !!binary | + Jlpt1sTgPixEqKaQaX4rmZgxnh48U7igzJK1EjAkK0Q= +- input: [65, 6, 2, 6, 1, 4, 6, 2, 1, 5] + output: [6, 2, 5, 1, 6, 4, 1, 2, 65, 6] + seed: !!binary | + Jlpt1sTgPixEqKaQaX4rmZgxnh48U7igzJK1EjAkK0Q= +- input: [] + output: [] + seed: !!binary | + zoulKyFpZkZG9AaUh1zxxcQ+unrNxwux10Svi4eBMmA= +- input: [0] + output: [0] + seed: !!binary | + zoulKyFpZkZG9AaUh1zxxcQ+unrNxwux10Svi4eBMmA= +- input: [255] + output: [255] + seed: !!binary | + zoulKyFpZkZG9AaUh1zxxcQ+unrNxwux10Svi4eBMmA= +- input: [4, 6, 2, 6, 1, 4, 6, 2, 1, 5] + output: [5, 6, 2, 1, 6, 4, 6, 4, 1, 2] + seed: !!binary | + zoulKyFpZkZG9AaUh1zxxcQ+unrNxwux10Svi4eBMmA= +- input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] + output: [12, 4, 11, 6, 13, 10, 9, 2, 3, 7, 8, 1, 5] + seed: !!binary | + zoulKyFpZkZG9AaUh1zxxcQ+unrNxwux10Svi4eBMmA= +- input: [65, 6, 2, 6, 1, 4, 6, 2, 1, 5] + output: [5, 6, 2, 1, 6, 65, 6, 4, 1, 2] + seed: !!binary | + zoulKyFpZkZG9AaUh1zxxcQ+unrNxwux10Svi4eBMmA= +- input: [] + output: [] + seed: !!binary | + 3gEwWl7gY5XRPg5iZgowSp9hyk4Sf/u92B+t88JdAEw= +- input: [0] + output: [0] + seed: !!binary | + 3gEwWl7gY5XRPg5iZgowSp9hyk4Sf/u92B+t88JdAEw= +- input: [255] + output: [255] + seed: !!binary | + 3gEwWl7gY5XRPg5iZgowSp9hyk4Sf/u92B+t88JdAEw= +- input: [4, 6, 2, 6, 1, 4, 6, 2, 1, 5] + output: [6, 2, 6, 5, 4, 4, 1, 6, 2, 1] + seed: !!binary | + 3gEwWl7gY5XRPg5iZgowSp9hyk4Sf/u92B+t88JdAEw= +- input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] + output: [10, 12, 13, 3, 7, 11, 2, 4, 9, 8, 6, 5, 1] + seed: !!binary | + 3gEwWl7gY5XRPg5iZgowSp9hyk4Sf/u92B+t88JdAEw= +- input: [65, 6, 2, 6, 1, 4, 6, 2, 1, 5] + output: [6, 2, 6, 5, 65, 4, 1, 6, 2, 1] + seed: !!binary | + 3gEwWl7gY5XRPg5iZgowSp9hyk4Sf/u92B+t88JdAEw= +- input: [] + output: [] + seed: !!binary | + mHQhqYMuvHeBZNa6VLLs3lZiqD1jWKP0cRzntvM5N+U= +- input: [0] + output: [0] + seed: !!binary | + mHQhqYMuvHeBZNa6VLLs3lZiqD1jWKP0cRzntvM5N+U= +- input: [255] + output: [255] + seed: !!binary | + mHQhqYMuvHeBZNa6VLLs3lZiqD1jWKP0cRzntvM5N+U= +- input: [4, 6, 2, 6, 1, 4, 6, 2, 1, 5] + output: [6, 2, 4, 1, 2, 6, 5, 1, 6, 4] + seed: !!binary | + mHQhqYMuvHeBZNa6VLLs3lZiqD1jWKP0cRzntvM5N+U= +- input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] + output: [11, 8, 12, 9, 2, 1, 10, 4, 13, 5, 7, 3, 6] + seed: !!binary | + mHQhqYMuvHeBZNa6VLLs3lZiqD1jWKP0cRzntvM5N+U= +- input: [65, 6, 2, 6, 1, 4, 6, 2, 1, 5] + output: [6, 2, 65, 1, 2, 6, 5, 1, 6, 4] + seed: !!binary | + mHQhqYMuvHeBZNa6VLLs3lZiqD1jWKP0cRzntvM5N+U= +- input: [] + output: [] + seed: !!binary | + /1mYGDx96+OeS3HV1avIeE/pPQROpuhSjAj+t+H59DE= +- input: [0] + output: [0] + seed: !!binary | + /1mYGDx96+OeS3HV1avIeE/pPQROpuhSjAj+t+H59DE= +- input: [255] + output: [255] + seed: !!binary | + /1mYGDx96+OeS3HV1avIeE/pPQROpuhSjAj+t+H59DE= +- input: [4, 6, 2, 6, 1, 4, 6, 2, 1, 5] + output: [2, 5, 1, 6, 1, 2, 6, 6, 4, 4] + seed: !!binary | + /1mYGDx96+OeS3HV1avIeE/pPQROpuhSjAj+t+H59DE= +- input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] + output: [5, 13, 9, 7, 11, 10, 12, 2, 6, 8, 3, 1, 4] + seed: !!binary | + /1mYGDx96+OeS3HV1avIeE/pPQROpuhSjAj+t+H59DE= +- input: [65, 6, 2, 6, 1, 4, 6, 2, 1, 5] + output: [2, 5, 1, 6, 1, 2, 6, 6, 65, 4] + seed: !!binary | + /1mYGDx96+OeS3HV1avIeE/pPQROpuhSjAj+t+H59DE= From 6d4a3bba11ce0f9b2feb5ace47986e4c8fe102ad Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 3 Oct 2018 13:43:46 +1000 Subject: [PATCH 2/3] Update shuffling comments --- beacon_chain/utils/shuffling/README.md | 2 -- beacon_chain/utils/shuffling/src/lib.rs | 15 +++++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) delete mode 100644 beacon_chain/utils/shuffling/README.md diff --git a/beacon_chain/utils/shuffling/README.md b/beacon_chain/utils/shuffling/README.md deleted file mode 100644 index b0f4f5245cd..00000000000 --- a/beacon_chain/utils/shuffling/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This module includes the fundamental shuffling function. It does not do the -full validator delegation amongst slots. diff --git a/beacon_chain/utils/shuffling/src/lib.rs b/beacon_chain/utils/shuffling/src/lib.rs index b99d400a142..7acb7408a4e 100644 --- a/beacon_chain/utils/shuffling/src/lib.rs +++ b/beacon_chain/utils/shuffling/src/lib.rs @@ -1,3 +1,7 @@ +/// 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; mod rng; @@ -9,13 +13,16 @@ pub enum ShuffleErr { ExceedsListLength, } -/// Performs a deterministic, in-place shuffle of a vector of bytes. +/// Performs a deterministic, in-place shuffle of a vector. +/// /// The final order of the shuffle is determined by successive hashes /// of the supplied `seed`. -pub fn shuffle( +/// +/// This is a Fisher-Yates-Durtstenfeld shuffle. +pub fn shuffle( seed: &[u8], - mut list: Vec) - -> Result, ShuffleErr> + mut list: Vec) + -> Result, ShuffleErr> { let mut rng = ShuffleRng::new(seed); if list.len() > rng.rand_max as usize { From eca4448207700c0fe59497b41318b6f284f8e2ab Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 3 Oct 2018 13:45:57 +1000 Subject: [PATCH 3/3] Remove test vectors These will be added in a future PR. --- .../test_vectors/shuffle_test_vectors.yaml | 162 ------------------ 1 file changed, 162 deletions(-) delete mode 100644 beacon_chain/utils/shuffling/test_vectors/shuffle_test_vectors.yaml diff --git a/beacon_chain/utils/shuffling/test_vectors/shuffle_test_vectors.yaml b/beacon_chain/utils/shuffling/test_vectors/shuffle_test_vectors.yaml deleted file mode 100644 index e96f9e2d0c6..00000000000 --- a/beacon_chain/utils/shuffling/test_vectors/shuffle_test_vectors.yaml +++ /dev/null @@ -1,162 +0,0 @@ -- input: [] - output: [] - seed: !!binary "" -- input: [0] - output: [0] - seed: !!binary "" -- input: [255] - output: [255] - seed: !!binary "" -- input: [4, 6, 2, 6, 1, 4, 6, 2, 1, 5] - output: [1, 6, 4, 1, 6, 6, 2, 2, 4, 5] - seed: !!binary "" -- input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] - output: [4, 7, 10, 13, 3, 1, 2, 9, 12, 6, 11, 8, 5] - seed: !!binary "" -- input: [65, 6, 2, 6, 1, 4, 6, 2, 1, 5] - output: [1, 6, 65, 1, 6, 6, 2, 2, 4, 5] - seed: !!binary "" -- input: [] - output: [] - seed: !!binary | - JlAYJ5H2j8g7PLiPHZI/rTS1uAvKiieOrifPN6Moso0= -- input: [0] - output: [0] - seed: !!binary | - JlAYJ5H2j8g7PLiPHZI/rTS1uAvKiieOrifPN6Moso0= -- input: [255] - output: [255] - seed: !!binary | - JlAYJ5H2j8g7PLiPHZI/rTS1uAvKiieOrifPN6Moso0= -- input: [4, 6, 2, 6, 1, 4, 6, 2, 1, 5] - output: [6, 4, 2, 5, 4, 2, 6, 6, 1, 1] - seed: !!binary | - JlAYJ5H2j8g7PLiPHZI/rTS1uAvKiieOrifPN6Moso0= -- input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] - output: [13, 1, 9, 8, 3, 10, 6, 2, 5, 12, 11, 4, 7] - seed: !!binary | - JlAYJ5H2j8g7PLiPHZI/rTS1uAvKiieOrifPN6Moso0= -- input: [65, 6, 2, 6, 1, 4, 6, 2, 1, 5] - output: [6, 65, 2, 5, 4, 2, 6, 6, 1, 1] - seed: !!binary | - JlAYJ5H2j8g7PLiPHZI/rTS1uAvKiieOrifPN6Moso0= -- input: [] - output: [] - seed: !!binary | - Jlpt1sTgPixEqKaQaX4rmZgxnh48U7igzJK1EjAkK0Q= -- input: [0] - output: [0] - seed: !!binary | - Jlpt1sTgPixEqKaQaX4rmZgxnh48U7igzJK1EjAkK0Q= -- input: [255] - output: [255] - seed: !!binary | - Jlpt1sTgPixEqKaQaX4rmZgxnh48U7igzJK1EjAkK0Q= -- input: [4, 6, 2, 6, 1, 4, 6, 2, 1, 5] - output: [6, 2, 5, 1, 6, 4, 1, 2, 4, 6] - seed: !!binary | - Jlpt1sTgPixEqKaQaX4rmZgxnh48U7igzJK1EjAkK0Q= -- input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] - output: [3, 8, 10, 4, 7, 11, 6, 1, 2, 5, 13, 9, 12] - seed: !!binary | - Jlpt1sTgPixEqKaQaX4rmZgxnh48U7igzJK1EjAkK0Q= -- input: [65, 6, 2, 6, 1, 4, 6, 2, 1, 5] - output: [6, 2, 5, 1, 6, 4, 1, 2, 65, 6] - seed: !!binary | - Jlpt1sTgPixEqKaQaX4rmZgxnh48U7igzJK1EjAkK0Q= -- input: [] - output: [] - seed: !!binary | - zoulKyFpZkZG9AaUh1zxxcQ+unrNxwux10Svi4eBMmA= -- input: [0] - output: [0] - seed: !!binary | - zoulKyFpZkZG9AaUh1zxxcQ+unrNxwux10Svi4eBMmA= -- input: [255] - output: [255] - seed: !!binary | - zoulKyFpZkZG9AaUh1zxxcQ+unrNxwux10Svi4eBMmA= -- input: [4, 6, 2, 6, 1, 4, 6, 2, 1, 5] - output: [5, 6, 2, 1, 6, 4, 6, 4, 1, 2] - seed: !!binary | - zoulKyFpZkZG9AaUh1zxxcQ+unrNxwux10Svi4eBMmA= -- input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] - output: [12, 4, 11, 6, 13, 10, 9, 2, 3, 7, 8, 1, 5] - seed: !!binary | - zoulKyFpZkZG9AaUh1zxxcQ+unrNxwux10Svi4eBMmA= -- input: [65, 6, 2, 6, 1, 4, 6, 2, 1, 5] - output: [5, 6, 2, 1, 6, 65, 6, 4, 1, 2] - seed: !!binary | - zoulKyFpZkZG9AaUh1zxxcQ+unrNxwux10Svi4eBMmA= -- input: [] - output: [] - seed: !!binary | - 3gEwWl7gY5XRPg5iZgowSp9hyk4Sf/u92B+t88JdAEw= -- input: [0] - output: [0] - seed: !!binary | - 3gEwWl7gY5XRPg5iZgowSp9hyk4Sf/u92B+t88JdAEw= -- input: [255] - output: [255] - seed: !!binary | - 3gEwWl7gY5XRPg5iZgowSp9hyk4Sf/u92B+t88JdAEw= -- input: [4, 6, 2, 6, 1, 4, 6, 2, 1, 5] - output: [6, 2, 6, 5, 4, 4, 1, 6, 2, 1] - seed: !!binary | - 3gEwWl7gY5XRPg5iZgowSp9hyk4Sf/u92B+t88JdAEw= -- input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] - output: [10, 12, 13, 3, 7, 11, 2, 4, 9, 8, 6, 5, 1] - seed: !!binary | - 3gEwWl7gY5XRPg5iZgowSp9hyk4Sf/u92B+t88JdAEw= -- input: [65, 6, 2, 6, 1, 4, 6, 2, 1, 5] - output: [6, 2, 6, 5, 65, 4, 1, 6, 2, 1] - seed: !!binary | - 3gEwWl7gY5XRPg5iZgowSp9hyk4Sf/u92B+t88JdAEw= -- input: [] - output: [] - seed: !!binary | - mHQhqYMuvHeBZNa6VLLs3lZiqD1jWKP0cRzntvM5N+U= -- input: [0] - output: [0] - seed: !!binary | - mHQhqYMuvHeBZNa6VLLs3lZiqD1jWKP0cRzntvM5N+U= -- input: [255] - output: [255] - seed: !!binary | - mHQhqYMuvHeBZNa6VLLs3lZiqD1jWKP0cRzntvM5N+U= -- input: [4, 6, 2, 6, 1, 4, 6, 2, 1, 5] - output: [6, 2, 4, 1, 2, 6, 5, 1, 6, 4] - seed: !!binary | - mHQhqYMuvHeBZNa6VLLs3lZiqD1jWKP0cRzntvM5N+U= -- input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] - output: [11, 8, 12, 9, 2, 1, 10, 4, 13, 5, 7, 3, 6] - seed: !!binary | - mHQhqYMuvHeBZNa6VLLs3lZiqD1jWKP0cRzntvM5N+U= -- input: [65, 6, 2, 6, 1, 4, 6, 2, 1, 5] - output: [6, 2, 65, 1, 2, 6, 5, 1, 6, 4] - seed: !!binary | - mHQhqYMuvHeBZNa6VLLs3lZiqD1jWKP0cRzntvM5N+U= -- input: [] - output: [] - seed: !!binary | - /1mYGDx96+OeS3HV1avIeE/pPQROpuhSjAj+t+H59DE= -- input: [0] - output: [0] - seed: !!binary | - /1mYGDx96+OeS3HV1avIeE/pPQROpuhSjAj+t+H59DE= -- input: [255] - output: [255] - seed: !!binary | - /1mYGDx96+OeS3HV1avIeE/pPQROpuhSjAj+t+H59DE= -- input: [4, 6, 2, 6, 1, 4, 6, 2, 1, 5] - output: [2, 5, 1, 6, 1, 2, 6, 6, 4, 4] - seed: !!binary | - /1mYGDx96+OeS3HV1avIeE/pPQROpuhSjAj+t+H59DE= -- input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] - output: [5, 13, 9, 7, 11, 10, 12, 2, 6, 8, 3, 1, 4] - seed: !!binary | - /1mYGDx96+OeS3HV1avIeE/pPQROpuhSjAj+t+H59DE= -- input: [65, 6, 2, 6, 1, 4, 6, 2, 1, 5] - output: [2, 5, 1, 6, 1, 2, 6, 6, 65, 4] - seed: !!binary | - /1mYGDx96+OeS3HV1avIeE/pPQROpuhSjAj+t+H59DE=