Dice Provably Fair Verifier

MintDice's provably fair verifier for their dice game. Learn more about cryptocurrency and bitcoin gambling here.

by Mint Dice

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/hmac-sha256.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-sha512/0.8.0/sha512.min.js"></script>
<h1> <span class="green">MintDice</span> Provably Fair Verifier</h1>
<h2>Dice</h2>
<p>This is the <a href="https://www.mintdice.com" target="_blank" rel="noopener noreferrer">MintDice</a> provably fair verifier for their dice game. To learn more about provably fair, <a href="https://provablyfair.org/" target="_blank" rel="noopener noreferrer">refer here</a>. </p>
<div class="inputs group">
  <div>
    <div class="input">
      <label for="server-seed">Server Seed:</label>
      <input type="text" id="server-seed">
    </div>
    <div class="input">
      <label for="user-seed">User Seed (Nonced):</label>
      <input type="text" id="user-seed">
    </div>
  </div>
  <button class="calculate" id="button">
    Calculate
  </button>
</div>
<br />
<div class="outputs group">
  <div class="input">
    <label for="result">Result:</label>
    <input type="text" readonly id="result">
  </div>
  <div class="input">
    <label for="server-hash">Server Seed Hash:</label>
    <input type="text" readonly id="server-hash">
  </div>
  <div class="input">
    <label for="hash">Provably String:</label>
    <input type="text" readonly id="hash">
  </div>
</div>

CSS

h1,
h2 {
  text-align: center;
}

.green {
  color: #37bd64;
}

.blue {
  color: #4fafd9;
}


.input {
  display: flex;
  justify-content: space-between;
  width: 650px;
  margin: 2px 0px;
}

.group {
  padding: 10px;
  border: 3px solid black;
  border-radius: 10px;
}

.inputs {
  border-color: #37bd64;
  display: flex;
}

.inputs label {
  cursor: pointer;
}

.outputs {
  border-color: #4fafd9;
}

.calculate {
  margin-left: 10px;
  cursor: pointer;
}

input {
  width: 500px;
}

JavaScript

document.getElementById('button').onclick = calculate;

function calculate() {
  const serverSeed = document.getElementById('server-seed').value.trim();
  
  // this should be the concated userSeed + nonce with a '-' inbetween
  // so if your user seed is: "aHDF3sdf234sdf" and your nonce is: 3, the expected userSeed would be: "ahjfasdf234sdf-3"
  const userSeed = document.getElementById('user-seed').value.trim();

  const {
    result,
    serverHash,
    hash
  } = provablyCalculate(serverSeed, userSeed);

  document.getElementById('result').value = result;
  document.getElementById('server-hash').value = serverHash;
  document.getElementById('hash').value = hash;
}

function provablyCalculate(serverSeed, userSeed) {
  const serverHash = CryptoJS.SHA256(serverSeed).toString();
  
  // The library used to compute a HMAC SHA512 is here: https://github.com/emn178/js-sha512
  // While it almost certainly will always work properly, as it is not the library MintDice uses
  // to calculate the results, there is always a small chance of inconsistency between the calculated values.
  // If there are any issues, please email [email protected]
  const hash = sha512.hmac.create(serverSeed).update(userSeed).hex();
  const result = provablyCalculator(hash);

  return {
    result,
    serverHash,
    hash
  };
}

function provablyCalculator(hash) {
  const LENGTH = 5;
  const HASH_LENGTH = hash.length;

  const HASH_COMPARISON = 10 ** 6;
  const MODULUS_FACTOR = 10 ** 4;
  const DIVISION_FACTOR = 10 ** 2;

  let i = 0;
  let hashSegment;
  let positionEnd;

  do {
    const positionStart = i * LENGTH;
    positionEnd = positionStart + LENGTH;

    if (positionEnd > HASH_LENGTH) return 99.99;

    i++;
    hashSegment = parseInt(hash.substring(positionStart, positionEnd), 16);
  } while (hashSegment >= HASH_COMPARISON);

  return hashSegment % MODULUS_FACTOR / DIVISION_FACTOR;
}