I’m trying to create an RNG in Motoko, and I want to seed it with a Blob from Random.blob(). In Motoko, there is a method to convert a Blob to a [Nat8], but for the RNG I want to implement (Xoshiro256ss) I need a [Nat64]. Since [Nat8] would have length 32, the [Nat64] array should have length 4.
Here is my code:
private func initState(seed : Blob) : [var Nat64] {
let blobArray : [Nat8] = Blob.toArray(seed);
let state0 : [var Nat64] = [var 0, 0, 0, 0];
for (i in Iter.range(0, 3)) {
let first : Nat64 = Nat64.fromNat(Prim.nat8ToNat(blobArray[i * 8]));
let second : Nat64 = Nat64.fromNat(Prim.nat8ToNat(blobArray[i * 8 + 1])) << 8;
let third : Nat64 = Nat64.fromNat(Prim.nat8ToNat(blobArray[i * 8] + 2)) << 16;
let fourth : Nat64 = Nat64.fromNat(Prim.nat8ToNat(blobArray[i * 8] + 3)) << 24;
let fifth : Nat64 = Nat64.fromNat(Prim.nat8ToNat(blobArray[i * 8] + 4)) << 32;
let sixth : Nat64 = Nat64.fromNat(Prim.nat8ToNat(blobArray[i * 8] + 5)) << 40;
let seventh : Nat64 = Nat64.fromNat(Prim.nat8ToNat(blobArray[i * 8] + 6)) << 48;
let eighth : Nat64 = Nat64.fromNat(Prim.nat8ToNat(blobArray[i * 8] + 7)) << 56;
let newState : Nat64 = first | second | third | fourth | fifth | sixth | seventh | eighth;
state0[i] := newState;
};
return state0;
};
When debugging with print statements, I see that for the first three iterations of the loop the code works fine, but on the last iteration, specifically in the line
state0[i] := newState;
I get an arithmetic overflow error.
Reject code: 5
Reject text: Canister rrkah-fqaaa-aaaaa-aaaaq-cai trapped explicitly: arithmetic overflow
I’m not sure if this is a bug in Motoko, or if I have errors in my code.