كيفية حفظ مستخدمي Ethereum DApp من دفع الغاز للمعاملات

وبدلاً من ذلك ، أنت كمالك DApp يدفع ثمنها

Crosspost: تم نشر هذا المنشور في الأصل ، هنا. وتم نشره مع المؤلف ، إذن ماهيش مورثي. [معرفة المزيد في Zastrin.com. المكافأة: استخدم الكود "BlockChannel" لتوفير 50 ​​٪ من جميع الدورات.]

واحدة من نقاط الاحتكاك لاعتماد Ethereum dapp هو أن على المستخدمين دفع رسوم الغاز (المعاملة (txn)) للحصول على معاملاتهم المسجلة على blockchain. على سبيل المثال ، لديّ dapp للتصويت البسيط الذي يسمح لأي شخص بالتصويت للمرشحين ، ويتم تخزين الأصوات على blockchain. على المستخدم الذي يريد تسجيل تصويته على blockchain أن يدفع رسوم معاملة / غاز. هذا ليس مثاليًا لأنك بصفتك مالك dapp ، تتوقع من مستخدمي التطبيق أن يدفعوا لـ Ether ثمن الغاز عندما يكون كل ما يريدون فعله هو إجراء بسيط لا علاقة له بتحويل الأموال. ولكن إذا كانت هناك حاجة إلى تنفيذ الصفقة على blockchain ، فلا يوجد خيار آخر سوى دفع الرسوم. ماذا لو كان هناك طريقة للمستخدمين لتنفيذ المعاملات بأمان (التصويت لمرشح ، كما في مثالنا) والسماح لشخص آخر (يحتمل أن يكون صاحب العقد) بتسجيل المعاملة على blockchain ودفع ثمنها بأنفسهم؟

بفضل هذه التغريدة من John Backus ، كان لديّ معلومات كافية لمساعدتي في تطبيق مثل هذا الحل من أجل dapp للتصويت.

كنت أرغب في مشاركة التفاصيل حول كيفية تطبيق هذا الحل من أجل dapp البسيطة الخاصة بي حتى يتمكن المزيد من الأشخاص من اعتماد هذه التقنية في dapps الخاصة بهم ونأمل في تحسينها. يغطي هذا المنشور ما يلي:

  1. نظرة عامة عالية المستوى على تشفير المفتاح العمومي والتوقيعات الرقمية ، وهي مفتاح فهم هذا الحل.
  2. تفاصيل الحل وتدفق التطبيق الجديد.
  3. تفاصيل التنفيذ (الواجهة الأمامية js ورمز عقد Solidity).
  4. مناقشة القضايا المحتملة والتحسينات.

التوقيعات الرقمية

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

تشفير المفتاح العام هو نظام تشفير حيث لديك مفتاحين - مفتاح عمومي (Pu) ومفتاح خاص (Pr). أنت تعطي مفتاحك العام للعالم بأسره وتحتفظ بالمفتاح الخاص لنفسك. على سبيل المثال: يعد عنوان Ethereum الخاص بك مفتاحًا عامًا (وهو مشتق فعليًا من المفتاح العمومي ، ولكن في هذا التمرين ، دعنا فقط نفكر في الأمر على أنه مفتاح عام) ويتم تخزين مفتاحك الخاص إما في متصفحك أو على هاتفك / جهاز الكمبيوتر الخاص بك. كما تعلمون ، لكي يرسل إليك شخص ما الأثير ، يحتاج فقط إلى معرفة عنوانك العام (الحساب). ومع ذلك ، يمكنك فقط الوصول إلى الأموال التي تملكها لأنك الشخص الوحيد الذي يعرف مفتاحك الخاص.

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

دعونا نرى ماذا يعني توقيع رسالة والتحقق منها من خلال مثال. دعنا نقول للمستخدم كيم لديه زوج من المفاتيح العامة / الخاصة

Pu = "0x44ac12c1e3dfd8edaf83b6f65918229d5279a6f5"

Pr = "dbc226043e390cf39280e5edfd418d7ad61931c76509270867d300f110c46506"

لتوقيع رسالة ، ينفذ كيم علامة دالة ("التصويت لصالح Alice" ، Pr) والتي تنتج سلسلة أبجدية رقمية

التوقيع = 0x9127112de0033555c7f6508d963d484965a953844dfcff092712102c236467a25af57edc53b63880ea39af8ce7334f6d77a8206e805305e7c6ad919d12bfae5c1b

هذا هو التوقيع الرقمي لرسالة "التصويت لصالح أليس" الموقعة من كيم باستخدام مفتاحها الخاص Pr.

الآن يمكن لأي شخص التحقق من أن الرسالة "Vote for Alice" قد تم توقيعها بواسطة Kim من خلال تنفيذ وظيفة التحقق ، والتحقق من ("Vote for Alice" ، التوقيع) الذي ينتج "0x44ac12c1e3dfd8edaf83b6f65918229d5279a6f5". إذا لاحظت أن هذا الإخراج هو مفتاح كيم العام بو (تذكر ، يعلم الجميع أنه مفتاح كيم العام) مما يعني أن كيم قد وقع الرسالة بالتأكيد. إذا قمت بالعبث بالتوقيع أو الرسالة (عن طريق تغيير حرف واحد) ، فإن خوارزمية التحقق تقوم بإخراج مفتاح عام مختلف تمامًا وستعرف أنه تم العبث بالرسالة ، لأن المفتاح العمومي سيكون مختلفًا عن PU.

تفاصيل الحل

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

  1. يشير الناخب إلى نيته التصويت لمرشح من خلال توقيع رسالة باستخدام المفتاح الخاص. لن يقدموا معاملاتهم إلى blockchain ، لذلك لا يتم دفع أي رسوم txn. قائمة انتظار الرسائل في الرسم البياني أعلاه هي مجرد موقع خارج السلسلة حيث يتم تخزين جميع تفاصيل التصويت.
  2. أي شخص على استعداد لدفع رسوم txn (عادة ما يكون صاحب العقد) يأخذ التوقيع واسم المرشح وعنوان حساب الناخب ويرسلهم إلى blockchain.
  3. يستخدم العقد الذكي وظيفة التحقق لاشتقاق المفتاح العمومي (عنوان حساب Ethereum) بناءً على اسم المرشح وتوقيعه. إذا كان المفتاح العمومي المشتق يتطابق مع عنوان المستخدم الذي وقّع الرسالة ، فإنه يسجل التصويت وإلا يفشل في المعاملة.

تفاصيل التنفيذ

دعونا الآن نلقي نظرة على التنفيذ الفعلي وكيف تتناسب جميع الأجزاء معًا.

الخطوة 1: توقيع الرسالة

الخطوة الأولى هي توقيع الرسالة كناخب. سوف نستخدم الدالة eth_signTypedData لتوقيع رسالتنا. تم تنفيذ هذه الوظيفة في Metamask مما يجعل من السهل توقيع الرسائل. يمكنك العثور على مزيد من التفاصيل والمناقشة حول هذا الاقتراح هنا: https://github.com/ethereum/EIPs/pull/712. يمكنك العثور على الرمز لتوقيع الرسالة أدناه.

شيء واحد مهم حقا هو أن نلاحظ ، داخليا eth_signTypedData تجزئة الرسالة والرسالة المجزأة هي ما يتم توقيعه. يمكنك الرجوع إلى وظيفة typedSignatureHash هنا لمزيد من التفاصيل حول التجزئة.

الخطوة 2: إرسال التصويت الموقع إلى blockchain

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

الخطوة 3: تحقق من تفاصيل التصويت في العقد الذكي

نحن نتحقق الآن من خلال العقد الذكي إذا كانت معلومات التصويت المقدمة صالحة ثم نقوم بتسجيل التصويت.

يحتوي Zeppelin على مكتبة مفيدة تسمى ECRecovery يمكننا استخدامها للتحقق من الرسالة الموقعة. تقوم الدالة VoteForCandidate بالتحقق من الرسالة الموقعة (وظيفة الاسترداد) وتحديث عدد الأصوات في حالة نجاح عملية التحقق.

إذا كنت تتذكر ، ذكرت في وقت سابق أن eth_signTypedData يقوم بتجزئة الرسالة ("التصويت لصالح أليس") قبل التوقيع عليها؟ لا تتمتع وظيفة الاستعادة المتينة بأي معرفة بوظيفة التجزئة المستخدمة داخل eth_signTypedData وبالتالي لا يمكنها التحقق من رسالة "التصويت لصالح أليس". يجب أن يقوم بتوليد تجزئة رسالة "التصويت لصالح Alice" ثم التحقق منها. بدلاً من إنشاء علامة التجزئة داخل العقد ، نقوم مسبقًا بتجميع جميع الرسائل مسبقًا ونمررها في المُنشئ بحيث يكون من السهل البحث عند التحقق. رمز إنشاء التجزئة في ملف الترحيل أدناه

هذا هو كل الكود الذي تحتاجه لتشغيل التطبيق الجديد!

لقد قمت بإنشاء عرض توضيحي سريع لإظهار كيفية عمل هذا التطبيق

رمز العمل بالكامل موجود هنا: https://github.com/maheshmurthy/ethereum_voting_dapp/tree/master/chapter4

التطبيق التجريبي هنا: https://www.zastrin.com/voting-dapp-without-paying-gas.html

القضايا المحتملة للتصدي

هناك بعض المشكلات التي يجب مراعاتها عند إنشاء dapp حقيقي باستخدام هذه التقنية. بعضها مدرج أدناه:

  1. أين يتم تخزين الرسائل الموقعة؟ يمكنك استخدام نوع من نظام قائمة الانتظار لتخزين هذه الرسائل.
  2. ما هو الضمان أن الرسالة الموقعة يتم تقديمها في النهاية إلى blockchain؟
  3. تخزين تجزئة جميع الرسائل في blockchain ليس مثاليًا ، فما هو الحل الأفضل لذلك؟

إذا كانت لديك أفكار حول كيفية معالجة هذه المشكلات أو إذا رأيت أي عيوب في هذا الحل ، فيرجى ترك تعليق!

ملاحظة: على ما يبدو ، لا تزال واجهة برمجة تطبيقات eth_signTypedData غير مستقرة وتم تنفيذها من خلال علامة metamask فقط. يرجى الحذر من هذا إذا كنت تخطط لاستخدام هذه التقنية في mainnet / الإنتاج.

قراءة متعمقة

https://en.wikipedia.org/wiki/Public-key_cryptography

https://en.wikipedia.org/wiki/Digital_signature

https://github.com/danfinlay/js-eth-personal-sign-examples/

https://danfinlay.github.io/js-eth-personal-sign-examples/

https://github.com/ethereum/EIPs/pull/712

شكراً لكريس وينفري وفوبين جون جيمس على مراجعة مسودات هذه المقالة.

أعرف أكثر

إذا كنت مهتمًا بتعلم كيفية إنشاء تطبيقات Ethereum اللامركزية ، فلدي بعض الدورات المثيرة للاهتمام في www.zastrin.com