قابل للإثبات

نرد لا تحتاج أن تصدّق كلامنا عنه

قبل أن تبدأ المباراة نقفل رقمًا سريًا وننشر بصمته. وعند انتهائها ننشر الرقم نفسه. بين هاتين اللحظتين تكون كل رمية محسومة سلفًا — وبعدها يستطيع أي شخص إعادة حسابها كلها والتأكد أن شيئًا لم يتغيّر.

افتح السجل

الجزء الذي لا يصلحه أي مولّد أرقام عشوائية مهما كان جيدًا

نردنا يأتي من المولّد التعمياني لنظام التشغيل — المصدر نفسه الذي يحمي تسجيل الدخول إلى البنك، لا الاختصار الذي تستخدمه معظم الألعاب. هذا يحسم مدى عشوائية الأرقام. ولا يحسم شيئًا من السؤال الذي يطرحه اللاعبون فعلًا.

الرمية النزيهة والرمية المختارة عمدًا تبدوان متطابقتين بعد وقوعهما. كلتاهما مجرد رقم في سجل.

فالسؤال المفيد ليس "هل مولّدكم جيد؟" بل "هل أستطيع التحقق؟" كل ما يلي موجود ليكون الجواب نعم، من دون أن نطلب منك تصديق كلمة واحدة نقولها.

مختوم قبلها، مفتوح بعدها

أربع خطوات. تستطيع تنفيذ اثنتين منها بنفسك، وهاتان هما اللتان تكشفاننا.

  1. 1

    الختم

    قبل الرمية الأولى يسحب الخادم رقمًا سريًا من ٣٢ بايت — بذرة الخادم — وينشر بصمة SHA-256 الخاصة بها للاعبَين. البصمة لا تكشف شيئًا، لكن البذرة صارت مقفلة: أي بذرة أخرى تعطي بصمة أخرى.

    commit0df0916cb0…2904e706
  2. 2

    المزج

    تطبيقك يولّد بذرة عشوائية خاصة به ويرسلها حين تجلس إلى الطاولة. بذرتا اللاعبَين تدخلان في كل رمية، فلا نستطيع البحث مسبقًا عن بذرة تناسب رمياتها مصلحتنا — لحظة الختم لا نعرف ما الذي ستضيفه أنت.

    clientSeeda26460084a0ef89b:d4f28bac6efd1b6e
  3. 3

    الاشتقاق

    كل رمية تُقرأ من HMAC-SHA256 للبذرتين ورقم الرمية. لا شيء يُخزَّن ولا شيء يُختار: المدخلات الثلاثة نفسها تعطي الرمية نفسها دائمًا، ولا مدخلات أخرى تعطيها.

    die(n) = (HMAC-SHA256(serverSeed, "clientSeed:n:round")[0] < 252) % 6 + 1
  4. 4

    الفتح

    عند انتهاء المباراة ننشر بذرة الخادم. جزّئها وقارن مع البصمة التي أُعطيت لك قبل الرمية الأولى، ثم أعد حساب كل رمية. خادم اختار رمية واحدة فقط يسقط في أحد هذين الفحصين.

    serverSeed5cde3365be…7b6b2bd5

القيم أعلاه هي الإثبات الحقيقي للمباراة رقم 148، وهي مباراة منتهية يستطيع أي أحد الاطلاع عليها. ضع الرقم في الصندوق أدناه وراقب النتيجة.

تحقّق من مباراة — هنا، الآن

اكتب رقم مباراة. تجلب الصفحة إثباتها، ثم تعيد تجزئة البذرة وحساب كل رمية باستخدام تعمية متصفحك أنت.

الحساب يجري على جهازك. لا شيء مما تكتبه يُرسَل إلينا، ولا علامة صحّ في هذه الصفحة قيمةٌ أرسلناها — لو كانت كذلك لكنا نطلب منك أن تثق بنا بشأن ما إذا كان يمكنك الوثوق بنا.
أو الصق القيم الثلاث بنفسك

لماذا لا يكون أي وجه أرجح ولو قليلًا

البايت رقم من ٠ إلى ٢٥٥ — ٢٥٦ احتمالًا. و٢٥٦ ليس من مضاعفات الستة؛ هو ٦ × ٤٢ ويبقى ٤. لو أخذت باقي قسمة البايت على ستة لحصلت أربعة أوجه بهدوء على ٤٣ فرصة من ٢٥٦ بينما يحصل الوجهان الآخران على ٤٢. انحياز ضئيل، وعلى مليون رمية يصبح أفضلية حقيقية. لذلك تُرمى تلك القيم الأربع.

٢٥٢ = ٦ × ٤٢. كل وجه ينال العدد نفسه من البايتات تمامًا، فكل وجه واحد من ستة بالضبط.

أين يتوقف الإثبات

نوعان من النرد في هذا الموقع خارج السلسلة. مذكوران هنا بدل حذفهما، لأن ادعاء نزاهة فيه ثغرة صامتة أقل قيمة من عدم الادعاء أصلًا.

  • تيليجرامالنرد المرمي في محادثة البوتإن رميت برسوم النرد الخاصة بتيليجرام فذلك الرقم من تيليجرام لا منّا؛ ولا بذرة عندنا تعيد إنتاجه. الإثبات المنشور يذكر بدقة أي المواضع كانت كذلك، والسجل يضع رمز تيليجرام مكان وجه النرد. للحصول على مباراة قابلة للفحص بالكامل، ارمِ داخل التطبيق.
  • تدريبالمباريات ضد الحاسوبمباراة التدريب دون اتصال ترمي على جهازك، بلا بذرة وبلا إثبات. لا خصم ولا رهان، فلا شيء يُثبَت ولا شيء معرَّض للخطر.

كل ما عدا ذلك — ١v١ عبر الإنترنت وغرف الأصدقاء والبطولات، مجانًا أو برهان — يجري على السلسلة الموصوفة أعلاه.

الفحص نفسه، بلا هذه الصفحة

اثنا عشر سطرًا وبلا أي مكتبة. الصقها في وحدة تحكم أي متصفح مع القيم الثلاث لمباراة، وستقول لك ما تقوله هذه الصفحة بالضبط — وهذا هو معنى نشر الطريقة لا النتيجة وحدها.

JavaScript
const enc = new TextEncoder();
const hex = (b) => [...new Uint8Array(b)].map((x) => x.toString(16).padStart(2, '0')).join('');

// 1. the seed we revealed must hash to the commitment you were given first
const commitOk = hex(await crypto.subtle.digest('SHA-256', enc.encode(serverSeed))) === commit;

// 2. every die, re-derived from that seed
const key = await crypto.subtle.importKey(
  'raw', enc.encode(serverSeed), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);

async function die(n) {
  for (let round = 0; round < 16; round++) {
    const mac = new Uint8Array(
      await crypto.subtle.sign('HMAC', key, enc.encode(`${clientSeed}:${n}:${round}`)));
    for (const b of mac) if (b < 252) return (b % 6) + 1;
  }
}

كل إثبات علني على /fair/<id> — بلا مفتاح ولا حساب ولا أسماء لاعبين ولا مبالغ. النرد فقط.

أسئلة يطرحها الناس فعلًا

خسرت أربع مباريات متتالية. هل النرد ضدي؟

لا يمكن أن يكون. كل رمية في مباراة منتهية كانت محسومة قبل بدايتها ببذرة مختومة سلفًا، وتستطيع إعادة حسابها كلها أعلاه. سلسلة الخسائر تبدو مقصودة وليست كذلك: مع نردين، أن يتفوق خصمك عليك أربع مباريات متتالية يحدث أكثر بكثير مما يتوقع الناس.

هل يستطيع الخادم اختيار رمية في اللحظة الحاسمة؟

سيكون عليه كسر أحد فحصين. إما ينشر بذرة لا تُجزَّأ إلى البصمة التي أعطاك إياها قبل المباراة — وهذا يراه الجميع — أو ينشر البذرة الحقيقية، وعندها فالنرد الذي تنتجه هو النرد الذي لعبته ولم يكن هناك ما يُختار.

ماذا لو لم يرسل تطبيقي بذرة خاصة به؟

تُولَّد بذرة عشوائية مكانها، فتبقى السلسلة سليمة دائمًا. هذا يضعف مساهمتك أنت فقط؛ أما الختم وكل الفحوص أعلاه فتبقى قائمة.

هل تؤثر بذرة منشورة على مباراتي التالية؟

لا. تُسحب بذرة جديدة وتُنشر بصمة جديدة لكل مباراة، بما فيها إعادة المباراة. البذرة التي نُشرت لا تحدد رمية أخرى أبدًا.

لماذا بعض النرد عليه رمز تيليجرام؟

تلك رُميت برسوم نرد تيليجرام في محادثة البوت، فجاءت من تيليجرام ولا بذرة عندنا تعيد إنتاجها. هي مُعلَّمة لا مخفية، والرقم الذي كانت سلسلتنا ستنتجه في ذلك الموضع لا يُعرض عمدًا — فهو ليس النرد الذي رماه أحد.

يفتح تلغرام للتأكد من أنك أنت. لا نرى كلمة مرورك أبدًا.

العب كزائر

بالمتابعة أنت توافق على الشروط وتؤكد أن عمرك 18 عامًا أو أكثر.
الشروطالخصوصيةاللعب المسؤول