diff --git a/substrate/primitives/sr-primitives/src/lib.rs b/substrate/primitives/sr-primitives/src/lib.rs
index f98a06fbef..1bbf5ad55a 100644
--- a/substrate/primitives/sr-primitives/src/lib.rs
+++ b/substrate/primitives/sr-primitives/src/lib.rs
@@ -52,6 +52,7 @@ pub mod offchain;
pub mod testing;
pub mod traits;
pub mod transaction_validity;
+pub mod random_number_generator;
/// Re-export these since they're only "kind of" generic.
pub use generic::{DigestItem, Digest};
@@ -70,6 +71,8 @@ pub use arithmetic::helpers_128bit;
/// Re-export big_uint stuff.
pub use arithmetic::biguint;
+pub use random_number_generator::RandomNumberGenerator;
+
/// An abstraction over justification for a block's validity under a consensus algorithm.
///
/// Essentially a finality proof. The exact formulation will vary between consensus
diff --git a/substrate/primitives/sr-primitives/src/random_number_generator.rs b/substrate/primitives/sr-primitives/src/random_number_generator.rs
new file mode 100644
index 0000000000..cb9acfa028
--- /dev/null
+++ b/substrate/primitives/sr-primitives/src/random_number_generator.rs
@@ -0,0 +1,103 @@
+// Copyright 2017-2019 Parity Technologies (UK) Ltd.
+// This file is part of Substrate.
+
+// Substrate is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Substrate is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Substrate. If not, see .
+
+//! A simple pseudo random number generator that allows a stream of random numbers to be efficiently
+//! created from a single initial seed hash.
+
+use codec::{Encode, Decode};
+use crate::traits::{Hash, TrailingZeroInput};
+
+/// Pseudo-random number streamer. This retains the state of the random number stream. It's as
+/// secure as the combination of the seed with which it is constructed and the hash function it uses
+/// to cycle elements.
+///
+/// It can be saved and later reloaded using the Codec traits.
+///
+/// Example:
+/// ```
+/// use sr_primitives::traits::{Hash, BlakeTwo256};
+/// use sr_primitives::RandomNumberGenerator;
+/// let random_seed = BlakeTwo256::hash(b"Sixty-nine");
+/// let mut rng = >::new(random_seed);
+/// assert_eq!(rng.pick_u32(100), 59);
+/// assert_eq!(rng.pick_item(&[1, 2, 3]), Some(&1));
+/// ```
+///
+/// This can use any cryptographic `Hash` function as the means of entropy-extension, and avoids
+/// needless extensions of entropy.
+///
+/// If you're persisting it over blocks, be aware that the sequence will start to repeat. This won't
+/// be a practical issue unless you're using tiny hash types (e.g. 64-bit) and pulling hundred of
+/// megabytes of data from it.
+#[derive(Encode, Decode)]
+pub struct RandomNumberGenerator {
+ current: Hashing::Output,
+ offset: u32,
+}
+
+impl RandomNumberGenerator {
+ /// A new source of random data.
+ pub fn new(seed: Hashing::Output) -> Self {
+ Self {
+ current: seed,
+ offset: 0,
+ }
+ }
+
+ fn offset(&self) -> usize { self.offset as usize }
+
+ /// Returns a number at least zero, at most `max`.
+ pub fn pick_u32(&mut self, max: u32) -> u32 {
+ let needed = (4 - max.leading_zeros() / 8) as usize;
+ let top = ((1 << (needed as u64 * 8)) / ((max + 1) as u64) * ((max + 1) as u64) - 1) as u32;
+ loop {
+ if self.offset() + needed > self.current.as_ref().len() {
+ // rehash
+ self.current = Hashing::hash(self.current.as_ref());
+ self.offset = 0;
+ }
+ let data = &self.current.as_ref()[self.offset()..self.offset() + needed];
+ self.offset += needed as u32;
+ let raw = u32::decode(&mut TrailingZeroInput::new(data)).unwrap_or(0);
+ if raw <= top {
+ break if max < u32::max_value() {
+ raw % (max + 1)
+ } else {
+ raw
+ }
+ }
+ }
+ }
+
+ /// Returns a number at least zero, at most `max`.
+ ///
+ /// This returns a `usize`, but internally it only uses `u32` so avoid consensus problems.
+ pub fn pick_usize(&mut self, max: usize) -> usize {
+ self.pick_u32(max as u32) as usize
+ }
+
+ /// Pick a random element from an array of `items`.
+ ///
+ /// This is guaranteed to return `Some` except in the case that the given array `items` is
+ /// empty.
+ pub fn pick_item<'a, T>(&mut self, items: &'a [T]) -> Option<&'a T> {
+ if items.is_empty() {
+ None
+ } else {
+ Some(&items[self.pick_usize(items.len() - 1)])
+ }
+ }
+}
diff --git a/substrate/primitives/sr-primitives/src/traits.rs b/substrate/primitives/sr-primitives/src/traits.rs
index 2b2bed53a4..84ac039a1d 100644
--- a/substrate/primitives/sr-primitives/src/traits.rs
+++ b/substrate/primitives/sr-primitives/src/traits.rs
@@ -1026,7 +1026,14 @@ pub trait OpaqueKeys: Clone {
}
/// Input that adds infinite number of zero after wrapped input.
-struct TrailingZeroInput<'a>(&'a [u8]);
+pub struct TrailingZeroInput<'a>(&'a [u8]);
+
+impl<'a> TrailingZeroInput<'a> {
+ /// Create a new instance from the given byte array.
+ pub fn new(data: &'a [u8]) -> Self {
+ Self(data)
+ }
+}
impl<'a> codec::Input for TrailingZeroInput<'a> {
fn remaining_len(&mut self) -> Result