RSA blockchain عشوائي

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

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



في البداية ، خططنا لإنشاء رقم بناءً على معلومات من blockchain. ومع ذلك ، فقد أصبح من الواضح: يمكن تزوير الرقم ، مما يعني أن الحل لا يصلح.

لقد توصلنا إلى حل بديل: استخدم نظام الالتزام بالإفصاح. قام الخادم "بتخمين" عدد من 1 إلى 5 ، وأضاف "ملح" إليه ، ثم قام بتجزئة النتيجة باستخدام وظيفة Keccak . قام الخادم بنشر العقد الذكي مسبقًا مع رقم محفوظ بالفعل. اتضح أن اللعبة تم تخفيضها إلى حقيقة أن المستخدم خمن الرقم المخفي بواسطة التجزئة.

قام اللاعب برهان ، وأرسل الخادم الرقم المطلوب و "الملح" إلى العقد الذكي. في لغة واضحة ، كشف البطاقات. بعد ذلك ، تحقق الخادم من الأرقام وقرر ما إذا كان المستخدم قد فاز أم خسر.

إذا لم يرسل الخادم رقمًا أو "ملحًا" للتحقق ، فقد فاز المستخدم. في هذه الحالة ، كان من الضروري بالنسبة لكل لعبة نشر عقد ذكي مقدمًا ووضع مكاسب محتملة فيه. اتضح أن تكون غير مريحة وطويلة ومكلفة. في ذلك الوقت ، لم يكن هناك حل آمن آخر.

في الآونة الأخيرة ، اقترح فريق Tradisys إضافة وظيفة rsaVerify () إلى بروتوكول Waves. يتحقق من صحة توقيع RSA استنادًا إلى المفتاح العام والخاص. نتيجة لذلك ، تمت إضافة الوظيفة.

قمنا بتطوير ثلاث مباريات: Dice Roller و Coin Flip و Ride On Waves . كل تطبيق تكنولوجيا رقم عشوائي. دعونا نرى كيف يعمل.



النظر في توليد عدد عشوائي باستخدام Ride on Waves كمثال. يمكن العثور على عقد ذكي هنا .

انتقل إلى علامة التبويب Script وحدد Decompiled . انظر رمز العقد الذكي (الملقب النصي).



يحتوي رمز العقد الذكي على مجموعة من الوظائف. يمكن تشغيل تلك التي تحمل علامةCallable باستخدام معاملات الاحتجاج. نحن مهتمون بوظيفتين: الرهان والسحب :

  • رهان func (playerChoice)
  • سحب func (gameId ، rsaSign)

1. يحدد المستخدم طول المقطع وحجم الرهان.



2. العميل يشكل وظيفة الرهان. بالنسبة إلى الصورة أعلاه ، سيكون هذا هو الرهان ("50") .

3. يرسل العميل معاملة الاحتجاج إلى عنوان العقد الذكي (بث InvocationTx). تحتوي المعاملة كمعلمة Call على وظيفة الرهان. هذا يعني أن معاملة الاحتجاج تبدأ في تنفيذ وظيفة الرهان (الاختيار: سلسلة) على العقد الذكي.



4. النظر في وظيفة الرهان:

@Callable(i) func bet (playerChoice) = { let newGameNum = IncrementGameNum() let gameId = toBase58String(i.transactionId) let pmt = extract(i.payment) let betNotInWaves = isDefined(pmt.assetId) let feeNotInWaves = isDefined(pmt.assetId) let winAmt = ValidateBetAndDefineWinAmt(pmt.amount, playerChoice) let txIdUsed = isDefined(getString(this, gameId)) if (betNotInWaves) then throw ("Bet amount must be in Waves") else if (feeNotInWaves) then throw ("Transaction's fee must be in Waves") else if (txIdUsed) then throw ("Passed txId had been used before. Game aborted.") else { let playerPubKey58 = toBase58String(i.callerPublicKey) let gameDataStr = FormatGameDataStr(STATESUBMITTED, playerChoice, playerPubKey58, height, winAmt, "") ScriptResult(WriteSet(cons(DataEntry(RESERVATIONKEY, ValidateAndIncreaseReservedAmt(winAmt)), cons(DataEntry(GAMESCOUNTERKEY, newGameNum), cons(DataEntry(gameId, gameDataStr), nil)))), TransferSet(cons(ScriptTransfer(SERVER, COMMISSION, unit), nil))) } } 

وظيفة يكتب لعبة جديدة إلى حالة العقد الذكية. وهي:

  • معرف فريد لعبة جديدة (معرف اللعبة)
  • حالة اللعبة = المقدمة
  • اختيار اللاعب (طول الخط 50)
  • المفتاح العام
  • المكاسب المحتملة (يعتمد على رهان اللاعب)



هذه هي الطريقة التي يبدو بها سجل البيانات في blockchain (القيمة الرئيسية):

 { "type": "string", "value": "03WON_0283_448t8Jn9P3717UnXFEVD5VWjfeGE5gBNeWg58H2aJeQEgJ_06574069_09116020000_0229", "key": "2GKTX6NLTgUrE4iy9HtpSSHpZ3G8W4cMfdjyvvnc21dx" } 

"مفتاح" (مفتاح) - معرف اللعبة للعبة الجديدة. توجد البيانات المتبقية في سطر الحقل "القيمة" (القيمة). يتم تخزين هذه الإدخالات في علامة تبويب البيانات في العقد الذكي:





5. "ينظر" الخادم إلى العقد الذكي ويجد المعاملة المرسلة (لعبة جديدة) باستخدام blockchain Api. معرف اللعبة الخاص باللعبة الجديدة مسجل بالفعل على blockchain ، مما يعني أنه لم يعد من الممكن تغييره أو التأثير عليه

6. يشكل الخادم وظيفة سحب (gameId ، rsaSign). على سبيل المثال ، هذا:

 withdraw ("FwsuaaShC6DMWdSWQ5osGWtYkVbTEZrsnxqDbVx5oUpq", "base64:Gy69dKdmXUEsAmUrpoWxDLTQOGj5/qO8COA+QjyPVYTAjxXYvEESJbSiCSBRRCOAliqCWwaS161nWqoTL/TltiIvw3nKyd4RJIBNSIgEWGM1tEtNwwnRwSVHs7ToNfZ2Dvk/GgPUqLFDSjnRQpTHdHUPj9mQ8erWw0r6cJXrzfcagKg3yY/0wJ6AyIrflR35mUCK4cO7KumdvC9Mx0hr/ojlHhN732nuG8ps4CUlRw3CkNjNIajBUlyKQwpBKmmiy3yJa/QM5PLxqdppmfFS9y0sxgSlfLOgZ51xRDYuS8NViOA7c1JssH48ZtDbBT5yqzRJXs3RnmZcMDr/q0x6Bg==") 

7. يرسل الخادم معاملة Invocation إلى العقد الذكي (بث InvocationTx). تحتوي المعاملة على استدعاء لوظيفة السحب التي تم إنشاؤها (gameId ، rsaSign):



تحتوي الوظيفة على معرف اللعبة الخاص باللعبة الجديدة ونتيجة توقيع RSA الخاص بالمعرف الفريد بمفتاح خاص. نتيجة التوقيع لم تتغير.

ماذا يعني هذا؟

نأخذ نفس القيمة (معرف اللعبة) ونطبق طريقة توقيع RSA عليها. سنحصل دائمًا على نفس النتيجة. هذه هي الطريقة التي تعمل خوارزمية RSA. لا يمكنك معالجة الرقم النهائي ، لأن معرف اللعبة ونتيجة استخدام RSA غير معروفين. مطابقة عدد هو أيضا غير المجدي.

8. يقبل blockchain المعاملة. يتم تشغيل وظيفة السحب (gameId ، rsaSign)

9. داخل وظيفة السحب ، يتم تصدير وظيفة GenerateRandInt (gameId ، rsaSign). هذا هو مولد رقم عشوائي


 # @return 1 ... 100 func GenerateRandInt (gameId,rsaSign) = { # verify RSA signature to proof random let rsaSigValid = rsaVerify (SHA256, toBytes(gameId), rsaSign, RSAPUBLIC) if (rsaSigValid) then { let rand = (toInt(sha256(rsaSign)) % 100) if ((0 > rand)) then ((-1 * rand) + 1) else (rand + 1) } else throw ("Invalid RSA signature") } 

راند - وهناك عدد عشوائي.

أولاً ، يتم أخذ سلسلة ، وهي نتيجة توقيع RSA لمعرف اللعبة باستخدام المفتاح الخاص ( rsaSign ). ثم يتم تجزئة باستخدام SHA-256 ( sha256 (rsaSign) ).

لا يمكننا التنبؤ بنتيجة التوقيع والتجزئة اللاحقة. لذلك ، من المستحيل التأثير على توليد رقم عشوائي. للحصول على رقم في نطاق معين (على سبيل المثال ، من 1 إلى 100) ، يتم استخدام دالة التحويل toInt و٪ 100 (من التماثلية إلى التهيئة ).

في بداية المقال ، ذكرنا وظيفة rsaVerify () ، والتي تتيح لك التحقق من صلاحية توقيعات RSA باستخدام مفتاح خاص باستخدام مفتاح عمومي. هنا جزء GenerateRandInt (gameId ، rsaSign):

 rsaVerify (SHA256, toBytes(gameId), rsaSign, RSAPUBLIC) 

يتم تمرير المفتاح العمومي RSAPUBLIC وسلسلة rsaSign إلى الإدخال. يتم التحقق من صحة التوقيع. يتم إنشاء رقم إذا نجح التحقق. خلاف ذلك ، يعتبر النظام أن التوقيع غير صالح (توقيع RSA غير صالح).

يجب أن يقوم الخادم بتوقيع معرف اللعبة باستخدام المفتاح الخاص وإرسال توقيع Rsa صالح ضمن 2880 قطعة. يتم تكوين المعلمة عند نشر عقد ذكي. إذا لم يحدث شيء خلال الوقت المخصص ، يفوز المستخدم. في هذه الحالة ، يجب إرسال الجائزة إلى عنوانك بنفسك. اتضح أن الخادم "غير مربح للغش" ، لأن هذا يؤدي إلى خسارة. أدناه مثال.



مستخدم يلعب النرد الرول . اخترت 2 من أصل 6 وجوه من المكعب ، والرهان هو 14 WAVES. إذا لم يرسل الخادم توقيع RSA صالحًا على العقد الذكي خلال الوقت المحدد (2880 قطعة) ، فسيأخذ المستخدم 34.44 WAVES.

لإنشاء أرقام في الألعاب ، نستخدم نظام oracle - وهو نظام خارجي غير قابل للحظر. يقوم الخادم بتنفيذ توقيع RSA الخاص بمعرف اللعبة. يتحقق العقد الذكي من صحة التوقيع ويحدد الفائز. إذا لم يرسل الخادم أي شيء ، فسيفوز المستخدم تلقائيًا.

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

Source: https://habr.com/ru/post/ar464357/


All Articles