A module for obtaining randomness on the Internet Computer (IC).
This module provides the fundamentals for user abstractions to build on.
Dealing with randomness on a deterministic computing platform, such as the IC, is intricate. Some basic rules need to be followed by the user of this module to obtain (and maintain) the benefits of crypto- graphic randomness:
Blobs).Blob) - or surplus entropy
not utilised yet - cannot be used for a new round of bets without
losing the cryptographic guarantees.Concretely, the below class Finite, as well as the
*From methods risk the carrying-over of state from previous rounds.
These are provided for performance (and convenience) reasons, and need
special care when used. Similar caveats apply for user-defined (pseudo)
random number generators.
Usage:
motoko no-repl
import Random "mo:base/Random";public func blob() : async BlobObtains a full blob (32 bytes) worth of fresh entropy.
Example:
motoko no-repl
let random = Random.Finite(await Random.blob());public func byte() : ?Nat8Uniformly distributes outcomes in the numeric range [0 .. 255]. Consumes 1 byte of entropy.
Example:
motoko no-repl
let seed : Blob = "\14\C9\72\09\03\D4\D5\72\82\95\E5\43\AF\FA\A9\44\49\2F\25\56\13\F3\6E\C7\B0\87\DC\76\08\69\14\CF";
let random = Random.Finite(seed);
random.byte() // => ?20public func coin() : ?BoolSimulates a coin toss. Both outcomes have equal probability. Consumes 1 bit of entropy (amortised).
Example:
motoko no-repl
let seed : Blob = "\14\C9\72\09\03\D4\D5\72\82\95\E5\43\AF\FA\A9\44\49\2F\25\56\13\F3\6E\C7\B0\87\DC\76\08\69\14\CF";
let random = Random.Finite(seed);
random.coin() // => ?falsepublic func range(p : Nat8) : ?NatUniformly distributes outcomes in the numeric range [0 .. 2^p - 1]. Consumes ⌈p/8⌉ bytes of entropy.
Example:
motoko no-repl
let seed : Blob = "\14\C9\72\09\03\D4\D5\72\82\95\E5\43\AF\FA\A9\44\49\2F\25\56\13\F3\6E\C7\B0\87\DC\76\08\69\14\CF";
let random = Random.Finite(seed);
random.range(32) // => ?348746249public func binomial(n : Nat8) : ?Nat8Counts the number of heads in n fair coin tosses.
Consumes ⌈n/8⌉ bytes of entropy.
Example:
motoko no-repl
let seed : Blob = "\14\C9\72\09\03\D4\D5\72\82\95\E5\43\AF\FA\A9\44\49\2F\25\56\13\F3\6E\C7\B0\87\DC\76\08\69\14\CF";
let random = Random.Finite(seed);
random.binomial(5) // => ?1Drawing from a finite supply of entropy, Finite provides
methods to obtain random values. When the entropy is used up,
null is returned. Otherwise the outcomes' distributions are
stated for each method. The uniformity of outcomes is
guaranteed only when the supplied entropy is originally obtained
by the blob() call, and is never reused.
Example:
motoko no-repl
import Random "mo:base/Random";
let random = Random.Finite(await Random.blob());
let seed : Blob = "\14\C9\72\09\03\D4\D5\72\82\95\E5\43\AF\FA\A9\44\49\2F\25\56\13\F3\6E\C7\B0\87\DC\76\08\69\14\CF";
let seedRandom = Random.Finite(seed);public func byteFrom(seed : Blob) : Nat8Distributes outcomes in the numeric range [0 .. 255]. Seed blob must contain at least a byte.
Example:
motoko no-repl
let seed : Blob = "\14\C9\72\09\03\D4\D5\72\82\95\E5\43\AF\FA\A9\44\49\2F\25\56\13\F3\6E\C7\B0\87\DC\76\08\69\14\CF";
Random.byteFrom(seed) // => 20public func coinFrom(seed : Blob) : BoolSimulates a coin toss. Seed blob must contain at least a byte.
Example:
motoko no-repl
let seed : Blob = "\14\C9\72\09\03\D4\D5\72\82\95\E5\43\AF\FA\A9\44\49\2F\25\56\13\F3\6E\C7\B0\87\DC\76\08\69\14\CF";
Random.coinFrom(seed) // => falsepublic func rangeFrom(p : Nat8, seed : Blob) : NatDistributes outcomes in the numeric range [0 .. 2^p - 1]. Seed blob must contain at least ((p+7) / 8) bytes.
Example:
motoko no-repl
let seed : Blob = "\14\C9\72\09\03\D4\D5\72\82\95\E5\43\AF\FA\A9\44\49\2F\25\56\13\F3\6E\C7\B0\87\DC\76\08\69\14\CF";
Random.rangeFrom(32, seed) // => 348746249public func binomialFrom(n : Nat8, seed : Blob) : Nat8Counts the number of heads in n coin tosses.
Seed blob must contain at least ((n+7) / 8) bytes.
Example:
motoko no-repl
let seed : Blob = "\14\C9\72\09\03\D4\D5\72\82\95\E5\43\AF\FA\A9\44\49\2F\25\56\13\F3\6E\C7\B0\87\DC\76\08\69\14\CF";
Random.binomialFrom(5, seed) // => 1