Created
December 15, 2021 08:05
-
-
Save borovan/64814cdb6f1aa06483545bab2ea20565 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Buffer "mo:base/Buffer"; | |
import Debug "mo:base/Debug"; | |
import Iter "mo:base/Iter"; | |
import Nat "mo:base/Nat"; | |
import Nat8 "mo:base/Nat8"; | |
import Nat16 "mo:base/Nat16"; | |
import Nat32 "mo:base/Nat32"; | |
import Nat64 "mo:base/Nat64"; | |
import RandomB "mo:base/Random"; | |
import SHA256 "mo:sha256/SHA256"; | |
import Time "mo:base/Time"; | |
import T "Types"; | |
module { | |
// Random | |
// it's a service so we can instantiate it at the top | |
// level and pass it via dependencies, otherwise we have | |
// inter-canister calls | |
public class Random() { | |
// Current sha data | |
// it gets rebuit with a new SHA256 when ever the | |
// wrapping byte counter is zero | |
var sha : [Nat8] = [ | |
0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, | |
]; | |
// byte | |
// the current read position of the sha array, 0 to 31 | |
var byte : Nat = 0; | |
// getBytes | |
// returns b bytes of pseudorandom data | |
func getBytes(b : Nat) : [Nat8] { | |
var buf = Buffer.Buffer<Nat8>(b); | |
// iterate per byte | |
for (i in Iter.range(0, b-1)) { | |
// reset | |
if (byte == 0) { | |
sha := newSha(); | |
}; | |
// add byte and increment the counter | |
buf.add(sha[byte]); | |
byte += 1; | |
if (byte >= 32) { | |
byte := 0; | |
}; | |
}; | |
buf.toArray(); | |
}; | |
// timeToBytes | |
public func timeToBytes() : [Nat8] { | |
let time : Nat64 = Nat64.fromIntWrap(Time.now()); | |
let buf = Buffer.Buffer<Nat8>(8); | |
for (i in Iter.range(0, 7)) { | |
let b = Nat64.fromNat(i*8); | |
let n = Nat8.fromNat(Nat64.toNat((time >> b) & 255)); | |
buf.add(n); | |
}; | |
buf.toArray(); | |
}; | |
// dice | |
// max 256*256 so Nat16 | |
public func dice(n : Nat8, d : Nat8) : Nat { | |
var t : Nat = 0; | |
for (i in Iter.range(0, Nat8.toNat(n)-1)) { | |
let b = getBytes(1); | |
t += Nat8.toNat(b[0] % d) + 1; | |
}; | |
t; | |
}; | |
// nat8 | |
public func nat8() : Nat8 { Nat8.fromNat(bytesToNat(1)) }; | |
public func nat8n() : Nat { bytesToNat(1) }; | |
// nat16 | |
public func nat16() : Nat16 { Nat16.fromNat(bytesToNat(2)) }; | |
public func nat16n() : Nat { bytesToNat(2) }; | |
// nat32 | |
public func nat32() : Nat32 { Nat32.fromNat(bytesToNat(4)) }; | |
public func nat32n() : Nat { bytesToNat(4) }; | |
// nat64 | |
public func nat64() : Nat64 { Nat64.fromNat(bytesToNat(8)) }; | |
public func nat64n() : Nat { bytesToNat(8) }; | |
// bytesToNat | |
// creates a Nat from b bytes of sha data | |
func bytesToNat(b : Nat) : Nat { | |
let bytes = getBytes(b); | |
var sum : Nat64 = 0; | |
for (i in Iter.range(0, b-1)) { | |
var bnat = Nat64.fromNat(Nat8.toNat(bytes[i])); | |
bnat <<= Nat64.fromNat(i*8); | |
sum += bnat; | |
}; | |
// Convert to Nat | |
let n = Nat64.toNat(sum); | |
// Debug.print("randNat generated (random) - " # Nat.toText(n)); | |
n; | |
}; | |
// newSha | |
func newSha() : [Nat8] { | |
let buf = Buffer.Buffer<Nat8>(40); | |
// current SHA | |
if (sha.size() > 0) { | |
for (i in Iter.range(0, 31)) { | |
buf.add(sha[i]); | |
}; | |
}; | |
// time | |
let ttb = timeToBytes(); | |
for (i in Iter.range(0, 7)) { | |
buf.add(ttb[i]); | |
}; | |
// update sha to new sum | |
let dig = SHA256.Digest(); | |
dig.write(buf.toArray()); | |
dig.sum(); | |
}; | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment