Post
Topic
Board Gambling discussion
Re: MoneyPot.com Provably Fair Seeding Event
by
blockage
on 12/01/2015, 23:01:44 UTC
Welcome to the first provably fair seeding event. One of the most requested features of Money Pot has been to create a provably distribution of game crashes, to replace our provably predetermined multipliers.

The original scheme of turning a multiplayer game in which peers do not trust each other was first proposed by Dooglus, refined by Eric and solidified into code by Steve.

In order to ensure fairness, we need to select a client seed in a verifiable way, after we have publicised all details and cannot control the outcome of the client seed picking. This is where the seeding event comes in, we need you to witness the process to ensure nothing has changed. A good way to do this might be save the post, quote it somewhere, save a copy in some archiving services. If anyone wants me to email them a copy, PM me your email address.

Our plan is to use hash of the bitcoin block 339300 as the client seed. If anyone finds any flaws in the code or methodology, we will push the block back to accommodate.  

The technical details are as follows:

The method to convert a serverSeed and clientSeed to a game hash is quite simple:
Code:
function genGameHash(serverSeed, clientSeed) {
  return crypto.createHmac('sha256', serverSeed).update(clientSeed).digest('hex');
}

The method to convert a game hash to a money pot multiplier is a bit more complex:
Code:
function crashPointFromHash(hash) {
  // Returns an integers corresponding to the game crash. 123 = Game crashes at 1.23x

  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 - inc : 0; i < hash.length; i += 4) {
      val = ((val << 16) + parseInt(hash.substring(i, i+4), 16)) % mod;
    }

    return val === 0;
  }

  /* 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);

  /* Assuming the 52-bit prefix is uniformly distributed
     then r is uniformly distributed over [0,1). */
  var r = h / e;

  /* Perfect is the perfectly continuous distributed
     multiplier for a zero sum game. */
  var perfect    = 1 / (1 - r);

  /* Apply a house edge to the perfect distribution. */
  var houseEdge  = (perfect-1) * 0.01;
  var multiplier = perfect - houseEdge;

  // return Math.floor(multiplier * 100);

  /* Inlining and simplifying the above yields the following version
     which is slightly more numerically stable. The multiplication
     100 * e still leaves the exactly representable integers.
  */
  return Math.floor((100 * e - h) / (e - h));
}

The chain could be generated with code such as:

Code:
var serverSeed = 'If you knew this, you could steal all my money'; // example
var clientSeed = '000000000000000012e8c0efdff2b8f67282e211749cc5530bd6e709f70279e1'; // determined by this seeding event

var gamesToGenerate = 100; // It'll be much larger in reality

for (var game = gamesToGenerate; game > 0; --game) {
  serverSeed = genGameHash(serverSeed, clientSeed);
  console.log('Game ' +  game + ' has a crash point of ' + (crashPointFromHash(serverSeed) / 100).toFixed(2) +'x', '\t\tHash: ' + serverSeed);
}


Using our chosen starting serverSeed, the hash chain terminating with the hash 7ebfb0e6cbfbdb4de6940fb954f4c554f388de114e04caeb5a26144458b551c1


Just a quote to have a copy not editable by OP. Maybe somebody with higher trust can re-quote Wink