कस्टम गेम्स - प्रमाणित निष्पक्ष
कस्टम गेम्स में इसका उपयोग कैसे किया जाता है
YEET Original में हर बेट एक राउंड सीड से शुरू होती है। राउंड सीड आपके क्लाइंट सीड और बेट के नॉनस (nonce) का HMAC-SHA256 है, जिसे YEET द्वारा चुने गए सर्वर सीड से की (key) किया गया है। इसके बाद गेम उस राउंड सीड से बेट के लिए जरूरी हर रैंडम वैल्यू निकालता है। सर्वर सीड खेलने से पहले आपको हैश करके दिखाया जाता है और आपके सीड पेयर को रोटेट करने पर इसे रिवील किया जाता है, ताकि आप पिछली किसी भी बेट की राउंड सीड को दोबारा कैलकुलेट कर सकें और चेक कर सकें कि बेट लगाने के बाद उसका रिजल्ट बदला नहीं गया है।
अन्य वेरिफायर मैच नहीं कर सकते
दूसरे कैसीनो के लिए बनाई गई वेरिफिकेशन साइटें रैंडम नंबर अलग तरह से जनरेट कर सकती हैं, इसलिए वहां YEET बेट को चेक करने पर रिजल्ट अलग मिल सकता है। YEET बेट्स को गेम की फेयरनेस विंडो के 'वेरिफाई' टैब में, या इस पेज पर दिए गए कोड के साथ वेरिफाई करें।
रैंडम नंबर जनरेशन
हर बेट दो स्टेप्स में जनरेट होती है। पहले, आपकी सीड पेयर और बेट का नॉनस एक राउंड सीड देते हैं। दूसरा, राउंड सीड रैंडम बाइट्स की एक स्ट्रीम तैयार करता है, और गेम उस स्ट्रीम से अनबायस्ड होल नंबर्स पढ़ता है। एक जैसे इनपुट हमेशा एक जैसे नंबर देते हैं, यही वो चीज है जो रिजल्ट को वेरिफिएबल बनाती है।
1. इनपुट्स
- हमारे सर्वर द्वारा जेनरेट किया गया एक रैंडम 64-कैरेक्टर हेक्साडेसिमल स्ट्रिंग
- एक स्ट्रिंग जिसे किसी भी समय संशोधित किया जा सकता है
- एक काउंटर जो खेले जाने वाले प्रत्येक गेम के साथ बढ़ता है
- कर्सर — राउंड सीड मैसेज का आखिरी हिस्सा। यह हमेशा 0 होता है।
2. राउंड सीड
राउंड सीड सर्वर सीड (32 बाइट्स के रूप में) के साथ clientSeed:nonce:0 टेक्स्ट पर की (key) किया गया HMAC-SHA256 है। रिजल्ट 32 बाइट्स का होता है, जिसे 64 हेक्स कैरेक्टर्स के रूप में लिखा जाता है। एक बेट की सिर्फ एक ही राउंड सीड होती है।
async function deriveGameSeed(serverSeed, clientSeed, nonce) {
const seedBytes = hexToBytes(serverSeed);
if (seedBytes.length !== 32) {
throw new Error(`Server seed must be 32 bytes (64 hex characters), got ${seedBytes.length}.`);
}
const key = await crypto.subtle.importKey(
'raw', toArrayBuffer(seedBytes), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign'],
);
const message = new TextEncoder().encode(`${clientSeed}:${nonce}:0`);
return bytesToHex(new Uint8Array(await crypto.subtle.sign('HMAC', key, message)));
}3. राउंड सीड से एंट्रॉपी
राउंड सीड दूसरे HMAC-SHA256 की की (key) है। हर कॉल 8-बाइट काउंटर (लिटिल-एंडियन, 0 से शुरू) को साइन करती है और 32 बाइट्स का एक ब्लॉक देती है; काउंटर हर ब्लॉक के साथ एक बढ़ता है। रीड्स वर्तमान ब्लॉक से क्रम में बाइट्स लेती हैं। जब किसी रीड को ब्लॉक में बचे बाइट्स से ज्यादा बाइट्स की जरूरत होती है, तो ब्लॉक का बाकी हिस्सा छोड़ दिया जाता है और अगला ब्लॉक जनरेट किया जाता है।
class GameEntropy {
constructor(seedBytes) {
if (seedBytes.length !== 32) throw new Error('Seed must be exactly 32 bytes (64 hex characters).');
this.buffer = new Uint8Array(32);
this.offset = 32;
this.cursor = 0;
this.key = crypto.subtle.importKey(
'raw', toArrayBuffer(seedBytes), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign'],
);
}
async next(count) {
if (count < 1 || count > 32) throw new RangeError('count must be between 1 and 32');
if (this.offset + count > 32) {
const message = new ArrayBuffer(8);
const view = new DataView(message);
view.setUint32(0, this.cursor >>> 0, true);
view.setUint32(4, Math.floor(this.cursor / 0x100000000) >>> 0, true);
const hash = await crypto.subtle.sign('HMAC', await this.key, message);
this.buffer.set(new Uint8Array(hash));
this.cursor++;
this.offset = 0;
}
const slice = this.buffer.slice(this.offset, this.offset + count);
this.offset += count;
return slice;
}
}4. निष्पक्ष संख्याएं
परिणाम पूर्ण संख्याओं के रूप में निकाले जाते हैं। readUint32 4 बाइट्स को एक अनसाइंड 32-बिट पूर्णांक (लिटिल-एंडियन) के रूप में पढ़ता है। unbiasedUint(entropy, n) 0 से n − 1 तक की एक संख्या देता है, जिसमें प्रत्येक की संभावना समान होती है। जब n दो की घात (power of two) होता है, तो यह सीधे शेषफल ले लेता है। अन्यथा, यह केवल उन मानों को स्वीकार करता है जो 32 बिट्स में फिट होने वाले n के सबसे बड़े गुणक से कम हैं, और यदि मान उससे अधिक या बराबर होता है, तो यह फिर से पढ़ता है, ताकि किसी परिणाम को प्राथमिकता न मिले।
async function readUint32(entropy) {
const bytes = await entropy.next(4);
return new DataView(bytes.buffer, bytes.byteOffset, 4).getUint32(0, true);
}
async function unbiasedUint(entropy, range) {
if (range <= 0) throw new Error('Range must be positive');
if (range === 1) return 0;
if ((range & (range - 1)) === 0) {
return (await readUint32(entropy)) % range;
}
const maxValue = 0xffffffff;
const threshold = maxValue - (maxValue % range) - 1;
for (;;) {
const raw = await readUint32(entropy);
if (raw <= threshold) return raw % range;
}
}5. सहायक (Helpers)
function hexToBytes(hex) {
if (typeof hex !== 'string') throw new TypeError('Hex value must be a string.');
const clean = hex.trim().replace(/^0x/i, '');
if (clean.length % 2 !== 0) throw new Error('Hex value must have an even length.');
if (!/^[0-9a-fA-F]*$/.test(clean)) throw new Error('Hex value contains non-hex characters.');
const bytes = new Uint8Array(clean.length / 2);
for (let i = 0; i < bytes.length; i++) {
bytes[i] = parseInt(clean.substring(i * 2, i * 2 + 2), 16);
}
return bytes;
}
function bytesToHex(bytes) {
return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
}
function toArrayBuffer(bytes) {
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
}6. दांव सत्यापित करना
- अपने इतिहास से दांव खोलें और क्लाइंट सीड, नॉनस और हैश किए गए सर्वर सीड को कॉपी करें।
- सर्वर सीड को प्रकट करने के लिए अपने सीड पेयर को रोटेट करें, और जांचें कि इसका SHA-256 हैश उस हैश से मेल खाता है जिसे आपने दांव लगाने से पहले देखा था।
- राउंड सीड प्राप्त करने के लिए सर्वर सीड, क्लाइंट सीड और नॉनस के साथ
deriveGameSeedचलाएं। - राउंड सीड से एक
GameEntropyबनाएं, गेम का रूपांतरण (रूपांतरण देखें) लागू करें और परिणाम की अपने दांव से तुलना करें।
