ما هي العدالة القابلة للإثبات؟
العدالة القابلة للإثبات تعني أن نتيجة كل لعبة يتم إنشاؤها بواسطة قيمة عشوائية يمكن للاعبين التحقق منها بشكل مستقل. هذا يضمن الشفافية والعدالة، مما يضمن أن لا اللاعب ولا الكازينو يمكنهما التلاعب بالنتيجة.
كيف يعمل؟
VRF (وظيفة عشوائية قابلة للتحقق) لإنشاء قيمة عشوائية حقيقية، نستخدم VRF. تأخذ هذه الوظيفة عدة مدخلات، بما في ذلك معرف المستخدم واسم اللعبة ونونس اللعبة ومفتاح الكازينو السري. تقوم بإجراء حسابات تشفيرية وتخرج قيمة عشوائية وإثباتا. يسمح هذا الإثبات لأي شخص بالتحقق من أن القيمة تم إنشاؤها بشكل عادل ولم يتم العبث بها. نتبع تنفيذ RFC6979 VRF باستخدام مجموعة تشفير SECP256K1_SHA256_TAI للعشوائية الآمنة والقابلة للتحقق.
التحقق من العدالة
يمكن للاعبين التحقق بشكل مستقل من القيمة العشوائية باستخدام الكود التالي:
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 })); }

