شرح إثبات العمل Argon2id

· مدة القراءة: 6 د

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

ما هي Argon2id؟

إجابة مختصرة

Argon2id دالة تجزئة كثيفة الذاكرة (memory-hard) محددة في RFC 9106 لتجزئة كلمات المرور ولإثبات العمل. تملأ مساحة كبيرة من الذاكرة بكتل حجمها 1 KiB، وتبني كل كتلة من الكتلة السابقة ومن كتلة أقدم تُختار من مكان آخر في الذاكرة، فيتطلب حساب التجزئة ذاكرة حقيقية إلى جانب وقت المعالج.

يصف RFC 9106، الذي نشرته مجموعة أبحاث منتدى التشفير التابعة لـ IRTF عام 2021، «دالة Argon2 كثيفة الذاكرة لتجزئة كلمات المرور وتطبيقات إثبات العمل». تأتي Argon2 بثلاثة أنواع:

في العمق، تتعامل Argon2 مع الذاكرة كسلسلة طويلة من الكتل بحجم 1,024 بايت. كل كتلة جديدة هي ناتج دالة ضغط G تُطبَّق على مُدخلين: الكتلة التي تسبقها مباشرة وكتلة مرجعية من موضع أقدم في الذاكرة. وتُبنى G على جولات الخلط في دالة التجزئة BLAKE2b، التي تعمل على كلمات بطول 64 بت بعمليات الجمع وXOR والتدوير.

كيف يستخدم Blocknet خوارزمية Argon2id كإثبات عمل؟

يثبّت Blocknet كل إعدادات Argon2id في كود الإجماع، فيحسب كل معدِّن وكل عقدة الدالة نفسها تمامًا:

المعامل القيمة في Blocknet معناه
النوع Argon2id، الإصدار 1.3 النوع الأساسي في RFC 9106
الذاكرة 2 GiB (2,097,152 KiB) 2,097,152 كتلة بحجم 1 KiB تُملأ لكل تجزئة
التكرارات 1 مرور واحد على الذاكرة
التوازي 1 مسار واحد، فتعمل التجزئة الواحدة على خيط واحد
المُخرَج 32 بايت القيمة التي تُقارن بالهدف
كلمة المرور nonce بطول 8 بايت، little-endian الرقم الذي يغيّره المعدِّن في كل محاولة
الملح ترويسة الكتلة دون nonce يربط التجزئة بقالب كتلة واحد

التعدين عملية بحث. يأخذ المعدِّن ترويسة الكتلة التي يريد نشرها، ويختار nonce، ويحسب تجزئة Argon2id. إذا كانت النتيجة ذات الـ 32 بايت، مقروءةً كرقم، مساوية لهدف الشبكة أو أقل منه، تكون الكتلة صالحة. وإن لم تكن، يجرّب المعدِّن قيمة nonce التالية.

يأتي الهدف مباشرة من الصعوبة: فهو (2^256 − 1) مقسومًا على الصعوبة. وهذا يجعل الصعوبة مساوية تقريبًا لعدد التجزئات المتوقع أن تحسبها الشبكة كلها لإيجاد كتلة واحدة. يستهدف Blocknet كتلة كل خمس دقائق، لذا فإن معدل تجزئة الشبكة يساوي تقريبًا الصعوبة مقسومة على 300 ثانية. وتتبع الصعوبة نفسها أزمنة الكتل الأخيرة عبر متوسط متحرك مرجّح على 60 كتلة.

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

لماذا يناسب إثبات العمل كثيف الذاكرة أجهزة الكمبيوتر العادية؟

تجعل الإعدادات السابقة الذاكرة محور كل تجزئة. مع مرور واحد ومسار واحد، يعتمد النصف الثاني من المرور على البيانات: يُؤخذ موضع الكتلة المرجعية لكل كتلة من أول كلمة بطول 64 بت في الكتلة المحسوبة قبلها مباشرة. لا يستطيع المعدِّن معرفة الكتلة الأقدم التي سيحتاجها حتى لحظة احتياجه إليها، لذا يحتفظ بمساحة الـ 2 GiB كاملة في الذاكرة.

يمكن للمعدِّن أن يحاول تخزين كتل أقل وإعادة حساب الناقص منها عند الطلب. يسمي RFC 9106 ذلك مقايضات الوقت بالذاكرة: فهي توفر الذاكرة «على حساب مزيد من الاستدعاءات لدالة الضغط الداخلية». وكل كتلة تُحذف من المساحة يجب دفع ثمنها مجددًا بحسابات إضافية.

وهذا ما يجعل التصميم مناسبًا للأجهزة العادية. فأجهزة سطح المكتب والحواسيب المحمولة والخوادم تأتي أصلًا بغيغابايتات من RAM ومتحكمات ذاكرة مصممة لتغذيتها. أما الشريحة المصممة للتجزئة فقط فستظل بحاجة إلى غيغابايتات من الذاكرة السريعة بجانب أنوية التجزئة. أول إعداد يوصي به RFC 9106 هو Argon2id بمرور واحد على 2 GiB من الذاكرة، وهو عدد المرور وحجم الذاكرة نفسهما اللذان يستخدمهما Blocknet، ويقول الـ RFC إن هذا الإعداد «يرفع تكاليف الخصم إلى أقصى حد على أجهزة القوة الغاشمة المخصصة». ويصف كود برنامج العقدة في Blocknet اختياره بأنه إثبات عمل كثيف الذاكرة «لمقاومة أجهزة ASIC وضمان تعدين عادل». صُممت Argon2id لمقاومة أجهزة ASIC، ويضع إعداد الـ 2 GiB هذا التصميم موضع التنفيذ، فيبقى التعدين متاحًا لأجهزة الكمبيوتر التي يملكها الناس بالفعل. ويشرح دليل إثبات العمل مقابل إثبات الحصة كيف يُقارن ذلك بالتخزين (staking).

لماذا تحدد ذاكرة RAM وعرض نطاقها معدل التجزئة؟

إجابة مختصرة

يحتفظ كل خيط تعدين بمساحة ذاكرة خاصة به بحجم 2 GiB، لذا تحدد ذاكرة RAM لديك عدد الخيوط الذي يمكنك تشغيله. وتكتب كل تجزئة أيضًا 2 GiB وتقرأ قدرًا مماثلًا تقريبًا من مواضع متفرقة، لذا تحدد سرعة ذاكرتك وزمن استجابتها مدى سرعة إنهاء تلك الخيوط لعملها. الذاكرة مهمة بقدر عدد الأنوية.

ذاكرة RAM تحدد عدد الخيوط. التوازي بقيمة 1 يعني أن التجزئة الواحدة تعمل على خيط واحد، ويحتاج كل خيط إلى مساحة كاملة خاصة به بحجم 2 GiB. يستطيع جهاز بذاكرة 16 GB تشغيل ستة إلى سبعة خيوط تقريبًا بعد ترك مساحة للنظام. يقيس seine ذاكرتك، ويحتفظ بـ 5% احتياطيًا، ويختار عدد الخيوط نيابةً عنك.

عرض النطاق وزمن الاستجابة يحددان سرعة كل خيط. تنشئ التجزئة الواحدة 2,097,152 كتلة جديدة، وتقرأ كل منها كتلة مرجعية بحجم 1 KiB من مكان ما في المساحة. وهذا يعني نحو 2 GiB مكتوبة ونحو 2 GiB مقروءة لكل تجزئة. عند 10 H/s، ينقل الجهاز نحو 40 GiB من البيانات عبر الذاكرة كل ثانية. وفي النصف المعتمد على البيانات، لا يُعرف عنوان كل قراءة إلا بعد اكتمال الكتلة السابقة، لذا يهم الوقت الذي تستغرقه الذاكرة للاستجابة بقدر ما يهم معدل النقل الخام.

لهذا تقول صفحة الأداء الخاصة بـ seine إن معدل التجزئة «يعتمد على عرض نطاق الذاكرة وزمن استجابتها بقدر ما يعتمد على عدد الأنوية». ويعرض دليل أجهزة تعدين Blocknet أفضل نتيجة لكل جيل من الأجهزة.

وتساعد الصفحات الكبيرة (huge pages) للسبب نفسه. فمساحة 2 GiB تمتد على 524,288 صفحة عادية بحجم 4 KiB، أو على 1,024 صفحة بحجم 2 MiB. وتعني صفحات أقل وأكبر عددًا أقل من إخفاقات ترجمة العناوين في تلك القراءات المتفرقة، وهو ما أضاف نحو 4–6% على جهاز الاختبار الخاص بـ seine. يحتوي دليل الصفحات الكبيرة على طريقة الإعداد.

كيف تستفيد النوى الحسابية في seine من Argon2id إلى أقصى حد؟

النواة الحسابية هي الحلقة الداخلية التي تحسب الكتل. تحمل إصدارات seine لمعمارية x86 نوى scalar وAVX2 وAVX-512 إضافة إلى نسخة بث (streaming)، وتحمل إصداراته لمعمارية Arm نواة NEON مع مسار سريع بتعليمات SHA3. وتتعامل كل منها مع العمل المرتبط بالذاكرة بطريقة مختلفة:

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

الجهاز تغيير النواة التحسّن
AWS Graviton4 (Neoverse V2)، 16 خيطًا من NEON إلى SHA3 مع الجلب المسبق +56% (من 13.80 إلى 21.50 H/s)
AWS Graviton3 (Neoverse V1)، 16 خيطًا من NEON إلى SHA3 مع الجلب المسبق +45% (من 12.52 إلى 18.17 H/s)
AMD EPYC 9R45 (Zen 5)، 24 خيطًا من AVX2 إلى البث +30% (من 34.47 إلى 44.74 H/s)
Intel Xeon 8375C (Ice Lake)، 1–4 خيوط من AVX2 إلى AVX-512 +21–29%

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

لتشغيل ذاكرتك في التعدين، نزّل seine، وشغّله، والصق عنوانك. ويشرح دليل التعدين بقية الخطوات.

الأسئلة الشائعة

ما معاملات Argon2id التي يستخدمها Blocknet لإثبات العمل؟

يشغّل Blocknet خوارزمية Argon2id الإصدار 1.3 بذاكرة 2 GiB، وتكرار واحد، وتوازٍ بقيمة 1، ومُخرَج بطول 32 بايت. القيمة nonce ذات الثماني بايتات هي كلمة المرور، وترويسة الكتلة دون nonce هي الملح. تفوز التجزئة بالكتلة عندما تكون مساوية للهدف الذي تحدده صعوبة الشبكة أو أقل منه.

لماذا يحتاج كل خيط لتعدين Blocknet إلى 2 GB من ذاكرة RAM؟

تملأ كل تجزئة Argon2id مساحة ذاكرة بحجم 2 GiB مكوّنة من كتل بحجم 1 KiB، وفي النصف الثاني من هذا المرور تقرأ كل كتلة جديدة كتلة سابقة تختارها بيانات لا يستطيع المعدِّن توقعها. على الخيط أن يحتفظ بمساحته كاملة في الذاكرة، لذا يحتاج كل خيط تشغّله إلى نحو 2 GB من ذاكرة RAM.

لماذا صُممت Argon2id لمقاومة أجهزة ASIC؟

تجعل Argon2id الذاكرة الجزء الأغلى في كل تجزئة. تحتاج كل تجزئة في Blocknet إلى 2 GiB من الذاكرة السريعة وتنقل عبرها غيغابايتات من البيانات، لذا فإن شريحة مصممة للتجزئة فقط ستظل بحاجة إلى كميات كبيرة من RAM لكل نواة. ويصف كود برنامج العقدة هذا الاختيار بأنه إثبات عمل كثيف الذاكرة لمقاومة أجهزة ASIC وضمان تعدين عادل.

هل يمكن لبطاقة رسومية تعدين Argon2id الخاصة بـ Blocknet؟

نعم. على Windows وLinux، يعدّن seine على جميع بطاقات NVIDIA الرسومية في الجهاز في الوقت نفسه مع المعالج، ويُجمع معدل التجزئة. تُترجَم النوى الحسابية عند بدء التشغيل، ويضبط التشغيل الأول كل بطاقة ويحفظ النتيجة، فلا يوجد ما تُعدّه قبل أن تبدأ.