Qu'est-ce que l'équitable et vérifiable ?
L'équitable et vérifiable signifie que le résultat de chaque jeu est généré par une valeur aléatoire que les joueurs peuvent indépendamment vérifier. Cela garantit la transparence et l'équité, assurant que ni le joueur ni le casino ne peut manipuler le résultat.
Comment ça marche ?
VRF (fonction aléatoire vérifiable) pour générer une valeur véritablement aléatoire, nous utilisons une VRF. Cette fonction prend plusieurs entrées, y compris l'ID utilisateur, le nom du jeu, le nonce du jeu et la clé secrète du casino. Elle effectue des calculs cryptographiques et génère à la fois une valeur aléatoire et une preuve. Cette preuve permet à quiconque de vérifier que la valeur a été générée de manière équitable et n'a pas été falsifiée. Nous suivons l'implémentation RFC6979 VRF en utilisant la suite de chiffrement SECP256K1_SHA256_TAI pour la génération aléatoire sécurisée et vérifiable.
Vérification de l'équité
Les joueurs peuvent indépendamment vérifier la valeur aléatoire en utilisant le code suivant :
const { verify } = require('@roamin/ecvrf') const toHex = require('string-hex') const publicKey = '03c41192ba26b7efafa9c69c941f759690d4fd46761c8424edbad1d5fc2c5c0947' const request = 'e1bc2c47-9b42-4409-8a21-d4c4f46455be|rollbit:mines|25|1234costam' const random = 'e2983665217b5aaebf11c886ef31e001c9615362b0aa6c3e49de9057f8979e1d' const proof = '03008cd333b153dddcffc64abf357222d31cd6e6f85ddbbe9227a60d2d0edcf9e6ab0f088c1f4402e6b4fa0ef430612d3ca86a686fc857ff412a8fe1553c821f47fcc21f4b2ca1d4c3b09b59a7e4fe1b8a' try { const result = verify(publicKey, proof, toHex(request)) console.log(result === random ? 'Is Verified' : 'Not Verified') } catch (error) { console.log(error) }
Calcul du résultat du jeu
Une fois la valeur aléatoire vérifiée, elle est convertie en nombre :
import * as crypto from 'crypto'; function bytesToUniformFloat(xs) { const hash = crypto.createHash('blake2b512').update(xs).digest(); const value = hash.readBigUInt64LE(0); return Number(value) / Number(BigInt(2 ** 64 - 1)); }
Ce nombre converti est ensuite utilisé pour générer le résultat final du jeu en fonction de la logique spécifique du jeu.
function calcMinesIxs({ size, mines, randomValue }) { const remainingIxs = Array.from({ length: size }, (_, i) => i); const mineIxs = []; for (let i = 0; i < mines; i++) { const seedI = Buffer.from(randomValue + '-' + i, 'ascii'); const ixI = Math.floor(bytesToUniformFloat(seedI) * remainingIxs.length); mineIxs.push(remainingIxs[ixI]); remainingIxs.splice(ixI, 1); } return mineIxs; } const calcMinesWin = ({ size, mines, reveals, bet }) => { let mult = 1.0; for (let i = 0; i < reveals; i++) { const lossProbability = mines / (size - i); mult *= 1.0 / (1.0 - lossProbability); } return Math.floor(100.0 * bet * mult * 0.98) / 100.0; }; function generateBoard({ size, mines, randomValue }) { const mineIxs = calcMinesIxs({ size, mines, randomValue }); const sizeSqrt = Math.sqrt(size); const board = Array.from({ length: sizeSqrt }).map(() => Array(sizeSqrt).fill(0)); for (const index of mineIxs) { const row = Math.floor(index / sizeSqrt); const col = index % sizeSqrt; if (row < sizeSqrt && col < sizeSqrt) { board[row][col] = -1; } } console.log('Board:', board); return board; } generateBoard({ size: 25, mines: 2, randomValue: 'be87e890f696aad0aad28bef78a3f2322c7687a76ff6f86b6dadb4f2aa00eeb9' }); console.log('Multipliers:'); for (let i = 1; i < 24; i++) { console.log(i, ': ', calcMinesWin({ size: 25, mines: 2, reveals: i, bet: 1 })); }

