**How is Provably Fair Implemented in code?**

Assuming that the game is finished and we have the un-hashed server seed, client seed, and nonce, here is how it works.

Three main steps will be required to generate game results.

byteGenerator (Random Bytes Generation)

generateFloats (Converting Bytes to Float (digits))

Float to game events (Converting floats to actual events in original games)

**ByteGenerator Function as a Random** Bytes **Generator**

The `byteGenerator`

function serves as a random byte generator.

It takes unique values of `clientSeed`

, `serverSeed`

, `nonce`

, and `cursor`

to generate a random and unique SHA-256 hashed value using the cryptographic HMAC_SHA256 function.

The SHA-256 value generated is 32 bytes in size. To ensure a balance between a sufficiently random game outcome and computational intensity, the 32 bytes is split into 8 sections of 4 bytes* each to generate every game result.

In certain games where more than 8 game result is required, we will utilize the `cursor`

. The cursor initially starts at 0, and increases to 1,2,3,4 to satisfy the result requirement,

For games where we do not require more than 8 random outcomes, the cursor does not increment in value.

*4 bytes of data will give us 2^32 (4,294,967,296) possible outcomes which is a sufficiently large pool for randomness.

function* byteGenerator({ serverSeed, clientSeed, nonce, cursor }: ByteGeneratorInterface) {

// Setup cursor variables let currentRound = Math.floor(cursor / 32);

let currentRoundCursor = cursor;

currentRoundCursor -= currentRound * 32;

// Generate outputs until cursor requirement fullfilled

while (true) {

// HMAC function used to output provided inputs into bytes

const hmac = crypto.createHmac('sha256', serverSeed);

hmac.update(`${clientSeed}:${nonce}:${currentRound}`);

const buffer = hmac.digest();

// Update curser for next iteration of loop

while (currentRoundCursor < 32) {

yield Number(buffer[currentRoundCursor]);

currentRoundCursor += 1;

}

currentRoundCursor = 0;

currentRound += 1;

}

}

## G**enerateFloats Function To Convert Bytes to Floats**

This function converts the SHA-256 hexadecimal value from bytes into floats for use in further calculations for Game Events.

Below illustrates how a SHA-256 hexadecimal value is converted from byte to float. The final output, numArr contains all the possible outcomes required by the game. If only 1 outcome is required, the list will contain only one value.

It returns an array of numbers between 0-1. if the count represents the number of elements in the returned array.

Code:

// Convert the hash output from the rng byteGenerator to floats

export function generateFloats({

serverSeed,

clientSeed,

nonce,

cursor,

count,

}: GenerateFloatsInterface) {

// Random number generator function

const rng = byteGenerator({ serverSeed, clientSeed, nonce, cursor });

// Declare bytes as empty array

const bytes = [];

// Populate bytes array with sets of 4 from RNG output

while (bytes.length < count * 4) {

bytes.push(rng.next().value!);

}

// Return bytes as floats using lodash reduce function

const numArr = chunk(bytes, 4).map(bytesChunk =>

bytesChunk.reduce((result, value, i) => {

const divider = 256 ** (i + 1);

const partialResult = value / divider;

return result + partialResult;

}, 0),

);

return numArr;

}

All our original games utilize both **ByteGenerator and** G**enerateFloats functions** to generate random floats between 0 to 1. However, it is from here onwards that each game takes a unique procedure to determine the game event from the float generated.

The unique procedure will be explained in detail in **Game Events.**

## Illustrated Example

Here we will illustrate how inputs are used to generate a dice game event

Input Values: Given some random input values

serverSeed, clientSeed, nonce, cursor

Step 1: byteGenerator creates a SHA-256 byte

"a3f4e0ac7c7e8e9b5f16106c6b1d14e87c2c5a8d59b1d1c6a0b5f3e5a7d4c9a8”

Step 2: 256 bytes is split into 8 equal set of 32 bytes

"a3f4e0ac”, “7c7e8e9b”, “5f16106c”, “6b1d14e8”,

“7c2c5a8d”, “59b1d1c6”, “a0b5f3e5”, “a7d4c9a8”

Step 3: Each set is broken down into 2 bytes each

(only first 2 sets is shown)

set 1: a3-f4-e0-ac

set 2: 7c-7e-8e-9b

......

Step 4: Each of the 2 bytes represent a number from 0 to 255

set 1: [163, 244, 224, 172]

set 2: [124, 126, 142, 155]

......

Step 5: Using the formula in the code to generate numArr

Float 1 = (163 / (256^1)) + (244 / (256^2)) + (224 / (256^3))

+ (172 / (256^4)) = 0.64045528601

Float 2 = (124 / (256^1)) + (126 / (256^2)) + (142 / (256^3))

+ (155 / (256^4)) = 0.48630610737 Float 3 ......

Step 6: Output the floats in a list

numArr = [0.64045528601, 0.48630610737, ...... ]

*** Game Event Generation ***

Step 7: The numArr output will be used to generate game events,

depending on the game requirement

Example 7: Using dice as an example.

The game event is generated using the first numArr value.

const resultValue = floats.map(val => Math.floor(floats * 10001) / 100);

resultValue = Math.floor(0.64045528601 * 10001) / 100

= 64.05

Note: In reality when a game is active, the server seed is hashed, hence the player and operator will not be able to view the individual output of this process during the game.

Since the same algorithm and functions are used during gameplay and after gameplay, the users is always prove the outcome given the same input