Brackitplace | Provably Fair

Provably Fair Float Generator System

This system is designed to provide a secure, tamper-proof method for generating random numbers (as floating-point numbers between 0 and 1) using a Provably Fair algorithm. The core principle is to ensure that neither the server nor the player can predict or control the outcome of a giveaway or objective generation ahead of time. Upon completion, the server will reveal its secret seed, allowing players to verify the fairness of the results.

How It Works

The float generation system uses a combination of:

  • Server Main Seed: A secret string known only to the server until results are revealed.
  • Public Seed: A string chosen by the client (user), which they can modify.
  • Nonce: A number incremented after each event or round to prevent repetition.
  • Cursor: Determines how many 32-byte hashes to generate for chaining randomness.

These inputs are combined via HMACSHA256 to produce cryptographically strong, deterministic random data.

GenerateBytes Function

This function takes the server main seed, public seed, nonce, and cursor, then produces a byte array by chaining HMAC-SHA256 hashes. Each hash uses the server main seed as a key and a message built from the public seed, nonce, and iteration index.

public static byte[] GenerateBytes(string serverSeed, string player(s)Seed, int nonce, int cursor)
{
    byte[] result = new byte[32 * (cursor + 1)];
    int byteIndex = 0;

    for (int i = 0; i < cursor + 1; i++)
    {
        using (HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(serverSeed)))
        {
            byte[] inputBytes = Encoding.UTF8.GetBytes($"{player(s)Seed}:{nonce}:{i}");
            byte[] hashBytes = hmac.ComputeHash(inputBytes);

            int bytesCopied = Math.Min(32, hashBytes.Length);
            Array.Copy(hashBytes, 0, result, byteIndex, bytesCopied);
            byteIndex += bytesCopied;
        }
    }

    return result;
}

This produces a reliable, deterministic sequence of bytes, used as the foundation for fair and transparent random number generation.

GenerateFloats Function

This function takes the generated bytes from GenerateBytes and converts them into floating-point numbers between 0 and 1. Each float is created by combining four sequential bytes and scaling them based on their position to ensure even distribution.

public static List<double> GenerateFloats(string serverSeed, string player(s)Seed, int nonce, int cursor, int count)
{
    List<double> floatList = new List<double>();
    byte[] bytes = GenerateBytes(serverSeed, player(s)Seed, nonce, cursor);

    for (int i = 0; i < count * 4; i += 4)
    {
        byte[] chunk = new byte[4];
        Array.Copy(bytes, i, chunk, 0, 4);
        double floatValue = 0;

        for (int j = 0; j < 4; j++)
        {
            floatValue += chunk[j] / Math.Pow(256, j + 1);
        }

        floatList.Add(floatValue);
    }

    return floatList;
}

The result is a list of provably fair, pseudorandom floating-point numbers ready for use in generating giveaway outcomes, objectives, or other random logic-driven applications.

Provable Fairness Verification Process

By combining a server main seed (revealed after use), a public player(s) seed (always publically displayed and changeable in account settings), and a nonce (unique per event), this system ensures that neither party can alter or influence generation after seeing the other’s input.

Players can verify fairness by:

  1. Recording their public seed and nonce before the event begins.
  2. Waiting for the server to reveal its server main seed after the results are final.
  3. Running the same algorithm locally to reproduce the float values from the seeds and nonce.
  4. Confirming that the generated numbers match the results exactly.