Roulette provably fair
In roulette the outcome of games have already been determined ahead of round start and can be verified using the following values.
- public seed – a randomly generated string of text by the server. It is made public ahead of any rolls and rotates after a while.
- server seed – a randomly generated string of text by the server. Its encrypted value is shown, to proof that we do not tamper with the value and will be decrypted once the public and server seed have rotated, at which point the rolls have become verifiable.
- nonce – a counter value that increases every round and is equal to the total number of rounds played (round identifier).
It is important to know that the server seed only becomes available to the user when it is no longer in use (i.e. rotated). Whenever the seeds rotate the user can verify the previous games to ensure they have not been tampered with.
Code Workflow
Whenever the seeds rotate, and are no longer in use, new values will be generated by the server. It runs the following code on the server-side.
const crypto = require("crypto"); const ChanceJs = require('chance') function getRandomBytes(size, encoding) { return crypto.randomBytes(size).toString(encoding); } function getHash(data, algorithm = "sha512", encoding = "hex") { return crypto.createHash(algorithm).update(data).digest(encoding); } const server_seed = getRandomBytes(24, "hex"); const public_seed = getRandomBytes(24, "hex");
A calculation can now be made, as all the required values are there. At round start we run a version of the sample code to determine the winning number.
const round_id = 89192; const hash = getHash(`${server_seed}-${public_seed}-${round_id}`); const isGoldenRound = new Chance(hash).integer({ min: 1, max: 100 }) <= 2; const result = () => { const number = parseInt(hash.substr(0, 8), 16); return Math.abs(number) % 15; } console.log(`Number: ${result} | Is golden round?: ${isGoldenRound}`);