Nachweislich fair
Jedes Ergebnis bei Crash, Dice und Plinko auf Aurion entsteht aus drei Werten: einem Server-Seed, auf den wir uns vor dem Spiel festlegen, einem Client-Seed und einer Nonce. Du kannst jedes Ergebnis selbst nachrechnen – auf dieser Seite, in deinem eigenen Browser – und prüfen, dass wir es nicht ändern konnten.
So funktioniert es
- Vor dem Spiel veröffentlichen wir den SHA-256-Hash eines geheimen Server-Seeds. Der Hash legt fest, welcher Seed verwendet wird, ohne ihn zu verraten.
- Das Ergebnis ist HMAC-SHA256(Server-Seed, Client-Seed : Nonce). Bei Dice und Plinko kannst du deinen eigenen Client-Seed setzen; die Nonce zählt deine Wetten. Crash-Runden nutzen einen öffentlichen zufälligen Client-Seed und einen Rundenzähler.
- Danach legen wir den Server-Seed offen. Hashe ihn: Er muss zur Festlegung passen. Rechne das Ergebnis nach: Es muss mit dem Geschehenen übereinstimmen.
Ergebnis prüfen
Der genaue Algorithmus
const enc = new TextEncoder()
// HMAC-SHA256(key = serverSeed, message), via the browser's Web Crypto API
async function hmac(key, message) {
const k = await crypto.subtle.importKey('raw', enc.encode(key), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign'])
return new Uint8Array(await crypto.subtle.sign('HMAC', k, enc.encode(message)))
}
async function floatStream(serverSeed, clientSeed, nonce, count) {
const out = []
for (let cursor = 0; out.length < count; cursor++) {
const block = await hmac(serverSeed, `${clientSeed}:${nonce}:${cursor}`)
for (let i = 0; i < 32 && out.length < count; i += 4) {
out.push(block[i] / 256 + block[i + 1] / 256 ** 2 + block[i + 2] / 256 ** 3 + block[i + 3] / 256 ** 4)
}
}
return out
}
async function diceRoll(serverSeed, clientSeed, nonce) {
const [f] = await floatStream(serverSeed, clientSeed, nonce, 1)
return Math.floor(f * 10000) // 0..9999
}
async function plinkoPath(serverSeed, clientSeed, nonce, rows) {
const floats = await floatStream(serverSeed, clientSeed, nonce, rows)
return floats.map((f) => (f < 0.5 ? 1 : -1)) // +1 right, -1 left
}
async function crashPoint(serverSeed, clientSeed, nonce) { // no cursor
const digest = await hmac(serverSeed, `${clientSeed}:${nonce}`)
const hex = Array.from(digest, (b) => b.toString(16).padStart(2, '0')).join('')
const h = BigInt('0x' + hex.slice(0, 52)) % 2n ** 52n
const e = 2n ** 52n
if (h % 33n === 0n) return 1 // instant crash
const mult = Number((100n * e - h) / (e - h)) / 100 // exact integer floor
return Math.min(mult, 1000)
}