Disclamer: I was hired by winxrp.com to make this seeding event and therefor set up the provably fair on the game. I will not be part of the team that manage this site.
This will reuse
the idea posted by Ryan and used for Bustabit.
- A chain of 10 million sha256 hashes was generated, starting with a Server Secret that has been repeatedly fed the output of sha256 hash back into itself 10 million times.
The final hash in the chain is: d760e15075a3c29537ac2159cf15aec017ca039b8b114180d02e67040dd6b65e, by publicizing it here we are preventing any ability to pick an alternate sha256 chain. - winxrp will play through that chain of hashes, in reverse order, and use the hashes to determine the crash point.
- To avoid criticism that the Server Secret used in step 1 was carefully chosen to generate lots of "bad" crash points, each hash in the chain will be salted with a client seed, which we have no control of.
The client seed will be the block hash of a Bitcoin block that hasn't yet been mined: block 482030.
The reference code (javascript) is as follows:
The method to create the hash chain is simply sha256:
function genGameHash(serverSeed) {
return crypto.createHash('sha256').update(serverSeed).digest('hex');
}
The method to convert a game hash, mix it with the picked client seed to a money pot multiplier:
function crashPointFromHash(serverSeed, clientSeed) {
function divisible(hash, mod) {
// We will read in 4 hex at a time, but the first chunk might be a bit smaller
// So ABCDEFGHIJ should be chunked like AB CDEF GHIJ
var val = 0;
var o = hash.length % 4;
for (var i = o > 0 ? o - 4 : 0; i < hash.length; i += 4) {
val = ((val << 16) + parseInt(hash.substring(i, i+4), 16)) % mod;
}
return val === 0;
}
var hash = crypto.createHmac('sha256', serverSeed).update(clientSeed).digest('hex');
/* In 1 of 101 games the game crashes instantly. */
if (divisible(hash, 101))
return 0;
/* Use the most significant 52-bit from the hash
to calculate the crash point */
var h = parseInt(hash.slice(0,52/4),16);
var e = Math.pow(2,52);
return Math.floor((100 * e - h) / (e - h));
}
The chain could be generated with code such as:
var serverSecret = 'If you knew this, you could steal all my money';
var clientSeed = '0000examplehash';
var gamesToGenerate = 1e7;
var serverSeed = serverSecret;
for (var game = gamesToGenerate; game > 0; --game) {
serverSeed = genGameHash(serverSeed);
console.log('Game ' + game + ' has a crash point of ' + (crashPointFromHash(serverSeed, clientSeed) / 100).toFixed(2) +'x', '\t\tHash: ' + serverSeed);
}
var terminatingHash = genGameHash(serverSeed);
console.log('The final hash is: ', terminatingHash);
Using our chosen starting serverSeed, the hash terminating the chain is
d760e15075a3c29537ac2159cf15aec017ca039b8b114180d02e67040dd6b65e. That is to say, the first game's hash played under the new provably fair scheme, when hashed will be d760e15075a3c29537ac2159cf15aec017ca039b8b114180d02e67040dd6b65e.