@derin-n/provablyfair
Version:
A provably fair algorithm
115 lines (96 loc) • 3.93 kB
JavaScript
const crypto = require('crypto');
const fs = require('fs');
//WARNING
//do not forget to reverse the game order in the database or in the json file such that the last game saved is the first game played
//if you do not reverse the order, people can just generate the continuation of the games which will give them the results
//all generated rounds will be put into this array then will be written to a json file
//if desired, and ideally you should save the rounds into a database
let counter = {};
//total number of games
counter['total'] = 0;
//house edge:
//shift the median to the losing side
//you will need to generate your own host seed and first game seed, you can generate them via the method below
//generate two seeds, one of them will be your host seed, the other will be the first game seed, these will be random and you should hold onto them
const generateRandomSeed = function (callback) {
//randomly generate 1000 bytes of data
crypto.randomBytes(1000, (err, randomData) => {
if (err) throw err;
//define hasher
let hashedSeed = crypto.createHash("sha512");
//convert the data to string and hash it
hashedSeed.update(randomData.toString('hex'));
//digest the hash into a string
let digestSeed = hashedSeed.digest('hex');
callback(digestSeed);
});
}
//counter of hashes generated
let chainCounter = 0;
//generate a chain of seeds
const generateChainSeeds = function (seed, maxGames, callback) {
//define the hasher
let hasher = crypto.createHash("sha512");
//hash the seed
hasher.update(seed);
//digest the hash into a string
let hexSeed = hasher.digest('hex');
//turn the round into json object
let saveRound = { gameSeed: hexSeed };
//add the game hash to the array
counter[chainCounter] = saveRound;
//if there is enough games, callback with the array
if (chainCounter == maxGames) {
counter['total'] = chainCounter;
callback(counter);
return;
}
//add one to the counter
chainCounter++;
//recursively generate hashes using the hash last generated
generateChainSeeds(hexSeed, maxGames, callback);
}
//house edge:
//you can manipulate the calculations below in your favour
//for roulette: check if first number is below 4, so either 0, 1, 2 or 3 and the second number below 8, if not look for another char
//for coin flip: decrease 1 from each result, giving you a 1% house edge, player wins 49% of the time
//generate results from hashes
const generateResult = function (hostSeed, gameSeed, callback) {
//create hasher
let combinedHash = crypto.createHash('sha512');
//combine the host seed with the game seed
let concatHash = hostSeed + gameSeed;
//hash the combination
combinedHash.update(concatHash);
//digest the hash into a string
let combinedHashHex = combinedHash.digest('hex');
//define result
let result = "";
//result will be converted into numbers
let numberResult;
//for every char in the string
for (let i = 0; i < combinedHashHex.length; i++) {
//get the char
let singleChar = combinedHashHex.charAt(i);
//check if number and result has less than 2 number chars
if (!(isNaN(singleChar)) && result.length < 2) {
//turn char into number
numberChar = parseInt(singleChar);
//add the char to result
result += singleChar;
}
//when result has two numbers, the first one can be zero
if (result.length == 2) {
//convert into number
numberResult = parseInt(result);
//callback with the numerical result
callback(numberResult);
return;
}
}
}
module.exports = {
generateRandomSeed: generateRandomSeed,
generateChainSeeds: generateChainSeeds,
generateResult: generateResult
};