証明可能な公正とは?
証明可能な公正とは、各ゲームの結果がプレイヤーが独立して検証できるランダムな値によって生成されることを意味します。これにより透明性と公正性が保証され、プレイヤーもカジノも結果を操作できないことが保証されます。
仕組みは?
VRF(検証可能なランダム関数)真にランダムな値を生成するために、VRFを使用します。この関数は、ユーザーID、ゲーム名、ゲームノンス、カジノの秘密鍵を含むいくつかの入力を受け取ります。暗号計算を実行し、ランダムな値と証明の両方を出力します。この証明により、誰でも値が公正に生成され、改ざんされていないことを確認できます。安全で検証可能なランダム性のために、SECP256K1_SHA256_TAI暗号スイートを使用したRFC6979 VRF実装に従っています。
公正性の検証
プレイヤーは次のコードを使用してランダムな値を独立して検証できます:
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) }
ゲーム結果の計算
ランダムな値が検証されると、数値に変換されます:
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)); }
この変換された数値は、ゲーム固有のロジックに基づいて最終的なゲーム結果を生成するために使用されます。
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 })); }

