Implementation

Random Number Generation

For each verifiable bet, a client seed, a server seed, a nonce and a cursor are used as the input parameters for the random number generation function. This function utilises the cryptographic hash function HMAC_SHA256 to generate bytes which are then used as the foundation for how we generate provably fair random outcomes on our platform.

you also can run your own verify at codepen

import * as _ from 'lodash-es';
import { sha256 } from 'js-sha256';

export interface SeedPair {
  serverSeed: string;
  clientSeed: string;
  nonce: number;
  cursor?: number;
  count?: number;
}

export interface MultiPlayerSeed {
  gameHash: string;
  salt: string;
  houseEdge?: number;
}

export function genByte({
  serverSeed = '',
  clientSeed = '',
  nonce = 0,
  cursor = 0,
}: SeedPair): number {
  const round = Math.floor(cursor / 32);
  cursor -= round * 32;
  const hmac = sha256.hmac.create(serverSeed);
  hmac.update(`${clientSeed}:${nonce}:${round}`);
  const buffer = hmac.digest();

  return buffer[cursor];
}

export function genFloats({
  serverSeed = '',
  clientSeed = '',
  nonce = 0,
  cursor = 0,
  count = 1,
}: SeedPair): number[] {
  const bytes = [];
  for (let i = 0; i < count * 4; i++) {
    const v = genByte({
      serverSeed,
      clientSeed,
      nonce,
      cursor: cursor + i,
    });
    bytes.push(v);
  }

  return _.chunk(bytes, 4).map((bytesChunk) =>
    bytesChunk.reduce((result, value, i) => {
      const divider = 256 ** (i + 1);

      return result + value / divider;
    }, 0)
  );
}

export function diceRoll(p: SeedPair): number {
  const f = genFloats(p)[0];
  return Math.floor(f * 10001) / 100;
}

export function crashPoint(s: MultiPlayerSeed): number {
  const hmac = sha256.hmac.create(s.gameHash);
  hmac.update(s.salt);
  const hex = hmac.hex().substring(0, 8);
  const int = parseInt(hex, 16);
  const p = Math.max(1, (2 ** 32 / (int + 1)) * (1 - (s.houseEdge || 0.05)));
  return Math.floor(p * 100) / 100;
}

export function drawCards(p: SeedPair): PokerCard[] {
  const fs = genFloats(p);
  return fs.map((f) => cards[Math.floor(f * cards.length)]);
}

Server Seed

The server seed is generated by our system as a random 64-character hex string. You are then provided with an encrypted hash of that generated server seed before you place any bets. The reason we provide you with the encrypted form of the server seed is to ensure that the un-hashed server seed cannot be changed by the casino operator, and that the player cannot calculate the results beforehand.

To reveal the server seed from its hashed version, the seed must be rotated by the player, which triggers the replacement with a newly generated one.

From this point you are able to verify that the hashed server seed matches that of the un-hashed server seed. This process can be verified via our un-hashed server seed function found in the menu above.

Client Seed

The client seed belongs to the player and is used to ensure the player also has influence on the randomness of the outcomes generated. Without this component of the algorithm, the server seed alone would have complete leverage over the outcome of each bet.

All players are free to edit and change their client seed regularly to create a new chain of random upcoming outcomes. This ensures the player has absolute control over the generation of the result, similar to cutting the deck at a brick and mortar casino.

During registration, a client seed is created for you by your browser, to ensure your initial experience with the site goes uninterrupted. Whilst this randomly generated client seed is considered suitable, we highly recommend that you choose your own, so that your influence is included in the randomness.

You can do this via the fairness modal.

Nonce

The nonce is simply a number that increments as every new bet is made. Due to the nature of the SHA256 cryptographic function, this creates a completely new result each time, without having to generate a new client seed and server seed.

The implementation of nonce, ensures we remain committed to your client seed and server seed pair, whilst generating new results for each bet placed.

Cursor (Incremental Number)

We use 4 bytes of data to generate a single game result, and because SHA256 is limited to 32 bytes, we utilise this implementation of a cursor to give us the ability to create more game events without having to modify our provable fair algorithm.

The cursor is only iterated over when the game being played requires the generation of more than 8 (32 bytes / 4 bytes) possible outcomes. For example: when we need to use more than 8 cards in a game of blackjack.

The cursor starts as 0 and gets increased by 1 every time the 32 bytes are returned by the HMAC_SHA256 function. If we don’t require more than 8 random numbers to be generated for the game events, then the curser does not increment as there is no need to generate any additional possible game outcomes.

Last updated