بعد ذلك ، سنبحث بالتفصيل الخصائص الرئيسية للغة Move وما هي اختلافاتها الرئيسية مع لغة أخرى مشهورة بالفعل للعقود الذكية - Solidity (على منصة Ethereum). تعتمد المادة على دراسة حول ورقة بيضاء متاحة على الإنترنت من 26 صفحة.
مقدمة
تعد Move لغة لغة تنفيذية قابلة للتنفيذ يتم استخدامها لتنفيذ معاملات المستخدم والعقود الذكية. إيلاء الاهتمام لنقطتين:
- في حين أن Move عبارة عن لغة رمز ثانوي يمكن تنفيذها مباشرة على الجهاز الظاهري Move ، فإن Solidity (لغة التعاقد الذكية في Ethereum) هي لغة ذات مستوى أعلى يتم تجميعها أولاً في bytecode قبل تنفيذها في EVM (Ethereum Virtual Machine ).
- يمكن استخدام النقل ليس فقط لتنفيذ العقود الذكية ، ولكن أيضًا لمعاملات المستخدم (المزيد حول هذا لاحقًا) ، في حين أن Solidity هي لغة للعقود الذكية فقط.
الترجمة التي قدمها فريق مشروع بروتوكول INDEX. لقد ترجمنا سابقًا الكثير من المواد التي تصف مشروع الميزان ، والآن حان الوقت للنظر في لغة Move أكثر عمقًا بقليل. تمت الترجمة بالتزامن مع coolsiuتتمثل الميزة الرئيسية لـ Move في القدرة على تحديد أنواع الموارد المخصصة باستخدام دلالات المنطق الخطي: لا يمكن أبدًا نسخ مورد أو حذفه ضمنيًا أو نقله فقط. وظيفيا ، وهذا يشبه قدرات لغة الصدأ. لا يمكن تعيين القيم في Rust إلا إلى اسم واحد في كل مرة. إن تعيين قيمة إلى اسم آخر يجعل الوصول إليها دون الاسم السابق.

على سبيل المثال ، سوف يلقي جزء الكود التالي خطأ:
استخدام القيمة المنقولة 'x'. هذا لأنه لا يوجد جمع القمامة في الصدأ. عندما تخرج المتغيرات عن نطاقها ، يتم تحرير الذاكرة التي تشير إليها أيضًا. ببساطة ، لا يمكن أن يكون هناك سوى "مالك" واحد للبيانات. في هذا المثال ،
x هو المالك الأصلي ، ثم تصبح
y المالك الجديد.
اقرأ المزيد عن هذا السلوك هنا .
تمثيل الأصول الرقمية في النظم المفتوحة
هناك خاصيتان للأصول المادية يصعب تمثيلهما رقميًا:
- ندرة (ندرة ، في الأصل - ندرة). يجب التحكم في كمية الأصول (المشكلة) في النظام. يجب حظر ازدواج الأصول الحالية ، وإنشاء أصول جديدة هو عملية مميزة.
- التحكم في الوصول . يجب أن يكون المشارك في النظام قادرًا على حماية الأصول باستخدام سياسات التحكم في الوصول.
هذه الخصائص ، وهما أمران طبيعيان للأصول المادية ، يجب تنفيذها للأشياء الرقمية ، إذا أردنا اعتبارها أصولًا. على سبيل المثال ، يحتوي المعدن النادر على عجز طبيعي ، ويمكنك فقط الوصول إليه (التمسك بيديك ، على سبيل المثال) ويمكنك بيعه أو إنفاقه.
لتوضيح كيف وصلنا إلى هاتين الخاصيتين ، دعنا نبدأ بالجمل التالية:
الاقتراح 1: أبسط حكم دون ندرة والتحكم في الوصول

- G [K]: = n يعني تحديث الرقم الذي يمكن الوصول إليه بواسطة المفتاح K في حالة الكتل blockchain العالمية بالقيمة الجديدة n .
- المعاملة ⟨Alice ، 100⟩ تعني تعيين رصيد حساب Alice على 100.
الحل أعلاه لديه العديد من المشاكل الخطيرة:
- يمكن أن تحصل أليس على عدد غير محدود من القطع النقدية ببساطة عن طريق إرسال المعاملة "أليس ، 100".
- العملات المعدنية التي ترسلها أليس إلى بوب عديمة الفائدة ، حيث يمكن أن يرسل بوب لنفسه عددًا غير محدود من العملات باستخدام نفس التقنية.
الاقتراح رقم 2: نحن نأخذ بعين الاعتبار العجز

الآن نحن نراقب الموقف بحيث يكون عدد العملات المعدنية
Ka على الأقل قبل نقل الصفقة. ومع ذلك ، على الرغم من أن هذا يحل مشكلة النقص ، لا توجد معلومات حول من يمكنه إرسال عملات أليس (حتى الآن يمكن للجميع القيام بذلك ، والشيء الرئيسي هو عدم انتهاك قاعدة حدود الكمية).
الاقتراح 3: الجمع بين العجز والتحكم في الوصول

نقوم بحل هذه المشكلة باستخدام
آلية التوقيع الرقمي
ver_sig قبل التحقق من الرصيد ، مما يعني أن Alice تستخدم مفتاحها الخاص لتوقيع المعاملة والتأكيد على أنها تمتلك عملاتها المعدنية.
لغات البرمجة Blockchain
تواجه لغات blockchain الحالية المشكلات التالية (تم حلها جميعًا في Move (ملاحظة:
لسوء الحظ ، فإن مؤلف المقال يناشد Ethereum فقط في مقارناته ، لذلك يجب أن تأخذها فقط في هذا السياق. على سبيل المثال ، يتم حل معظم ما يلي أيضًا في EOS )):
التمثيل غير المباشر للأصول . يتم تشفير الأصل باستخدام عدد صحيح ، ولكن قيمة عدد صحيح ليست هي نفس الأصل. في الواقع ، لا يوجد نوع أو قيمة تمثل البيتكوين / الأثير / <أي عملة>! هذا يجعل كتابة البرامج التي تستخدم الأصول صعبة وعرضة للخطأ. تتطلب أنماط مثل نقل الأصول من / إلى الإجراءات أو تخزين الأصول في الهياكل دعمًا لغويًا خاصًا.
العجز غير قابل للتوسيع . تمثل اللغة مادة شحيحة واحدة فقط. بالإضافة إلى ذلك ، فإن وسائل الانتصاف من العجز يتم توصيلها مباشرة إلى دلالات اللغة نفسها. يجب على المطور ، إذا أراد إنشاء أصل مستخدم ، أن يراقب جميع جوانب المورد بعناية. هذه فقط مشاكل Ethereum العقود الذكية.
يقوم المستخدمون بإصدار أصولهم ، الرموز المميزة ERC-20 ، باستخدام الأعداد الصحيحة لتحديد كلاً من التكلفة والإصدار الإجمالي. عندما يتم إنشاء رموز جديدة ، يجب أن يتحقق رمز العقد الذكي بشكل مستقل من الامتثال لقواعد الانبعاثات. بالإضافة إلى ذلك ، يؤدي التمثيل غير المباشر للأصول ، في بعض الحالات ، إلى أخطاء جسيمة - الازدواجية ، والإنفاق المزدوج أو حتى الخسارة الكاملة للأصول.
عدم وجود تحكم مرن في الوصول . سياسة التحكم في الوصول الوحيدة المستخدمة حاليًا هي نظام التوقيع باستخدام تشفير غير متماثل. مثل حماية العجز ، فإن سياسات التحكم في الوصول متأصلة بعمق في دلالات اللغة. لكن كيفية توسيع اللغة للسماح للمبرمجين بتحديد سياسات التحكم في الوصول الخاصة بهم غالبًا ما تكون مهمة غير تافهة للغاية.
ينطبق هذا أيضًا على Ethereum ، حيث لا تحتوي العقود الذكية على دعم تشفير أصلي للتحكم في الوصول. يجب على المطورين أن يصفوا التحكم في الوصول يدويًا ، على سبيل المثال ، باستخدام معدل onlyOwner.
على الرغم من أنني معجب كبير بـ Ethereum ، إلا أنني أعتقد أن خصائص الأصول يجب أن تكون مدعومة أصليًا من قبل اللغة لأسباب أمنية. على وجه الخصوص ، نقل الأثير إلى عقد ذكي ينطوي على إيفاد ديناميكي ، مما أدى إلى ظهور فئة جديدة من الأخطاء المعروفة باسم نقاط الضعف في إعادة الدخول. إرسال ديناميكي هنا يعني أن منطق تنفيذ التعليمات البرمجية سيتم تحديده في وقت التشغيل (ديناميكي) ، وليس في وقت التحويل البرمجي (ثابت).
وهكذا ، في Solidity ، عندما يستدعي العقد A وظيفة العقد B ، يمكن للعقد B تشغيل التعليمات البرمجية التي لم يتم توفيرها من قِبل مطور العقد A ، مما قد يؤدي إلى
ثغرات أمنية في العودة (العقد A يؤدي وظيفة الخطأ B لسحب الأموال قبل الخصم الفعلي) أرصدة الحسابات).
نقل أساسيات تصميم اللغة
موارد النظام الأول
عند التحدث على مستوى أعلى ، يكون التفاعل بين الوحدات / الموارد / الإجراءات في لغة Move مشابهًا جدًا للعلاقات بين الفئات / الكائنات والأساليب بلغات OOP.
الوحدات النمطية في النقل مماثلة للعقود الذكية في المجموعات الأخرى. تعلن الوحدة النمطية عن أنواع الموارد والإجراءات التي تحدد قواعد إنشاء الموارد المعلنة وتدميرها وتحديثها. لكن كل هذا هو مجرد اصطلاحات ("
المصطلحات ") قيد التنفيذ. بعد قليل سنوضح هذه النقطة.
مرونة
نقل يضيف مرونة الميزان من خلال البرمجة النصية. تتضمن كل معاملة في الميزان برنامج نصي ، وهو في الواقع إجراء المعاملة الرئيسي. يمكن للبرنامج النصي إما إجراء محددًا واحدًا ، على سبيل المثال ، المدفوعات وفقًا لقائمة المستلمين المحددة ، أو إعادة استخدام الموارد الأخرى - على سبيل المثال ، عن طريق استدعاء إجراء يتم فيه تحديد المنطق العام. هذا هو السبب في توفير تحركات البرامج النصية للمعركة مرونة أكبر. يمكن للبرنامج النصي استخدام كل من السلوكيات المتكررة لمرة واحدة ، بينما لا تستطيع Ethereum تنفيذ البرامج النصية المتكررة فقط (استدعاء طريقة عقد ذكية عن طريق استدعاء طريقة واحدة). السبب الذي يطلق عليه "متعددة" هو أنه يمكن تنفيذ وظائف العقد الذكي عدة مرات. (ملحوظة:
هذه اللحظة حساسة للغاية هنا. فمن ناحية ، توجد نصوص المعاملات في شكل رمز زائف في Bitcoin. من ناحية أخرى ، كما أفهمها ، تقوم Move بنقل هذه اللغة ، في الواقع ، إلى مستوى لغة العقد الذكية الكاملة ).
سلامة
التنسيق القابل للتنفيذ Move هو bytecode ، والذي ، من ناحية ، هو لغة ذات مستوى أعلى من المجمّع ، ولكنها أقل من الشفرة المصدر. يتم التحقق من bytecode في السلسلة لمعرفة مدى توفر الموارد وأنواعها وأمن الذاكرة باستخدام أداة التحقق bytecode ، ثم يتم تنفيذها بواسطة المترجم الفوري. يسمح هذا الأسلوب لـ Move بتوفير أمان خاص بالكود المصدر ، ولكن بدون عملية التحويل البرمجي والحاجة إلى إضافة برنامج التحويل البرمجي إلى النظام. جعل نقل لغة bytecode هو حل جيد حقًا. ليست هناك حاجة لتجميعها من المصدر ، كما هو الحال مع Solidity ، فلا داعي للقلق بشأن أي أعطال أو هجمات محتملة على البنية الأساسية لبرنامج التحويل البرمجي.
التحقق
نحن نهدف إلى إجراء عمليات فحص سهلة قدر الإمكان ، لأن كل هذا يتم على الإنترنت (ملاحظة:
عبر الإنترنت ، في عملية كل معاملة ، وبالتالي فإن أي تأخير يؤدي إلى تباطؤ الشبكة بالكامل ) ، ومع ذلك ، فإن تصميم اللغة جاهز في البداية للاستخدام و وسيلة خارج السلسلة للتحقق ثابت. على الرغم من أن هذا أفضل ، إلا أنه تم تأجيل تطوير أدوات التحقق (كمجموعة أدوات منفصلة) للمستقبل ، والآن يتم دعم التحقق الديناميكي فقط على السلسلة.
نمطية
توفر وحدات النقل تجريد البيانات وتوطين العمليات الحيوية على الموارد. يضمن التغليف الذي توفره الوحدة النمطية ، بالإضافة إلى الحماية التي يوفرها نظام Move type ، أن الخصائص المحددة لأنواع الوحدة النمطية لا يمكن انتهاكها بواسطة رمز خارج الوحدة النمطية. هذا تصميم مدروس جيدًا للتجريد ، مما يعني أنه لا يمكن تغيير البيانات الموجودة داخل العقد إلا في إطار العقد ، ولكن ليس من الخارج.

نقل مراجعة
يوضح أحد أمثلة المعاملات النصية أن الإجراءات الخبيثة أو المتهورة للمبرمج خارج الوحدة النمطية لا يمكن أن تنتهك أمان موارد الوحدة النمطية. بعد ذلك ، سوف نلقي نظرة على أمثلة حول كيفية استخدام الوحدات والموارد والإجراءات لبرمجة blockra Libra.
مدفوعات نظير إلى نظير

سيتم تحويل مبلغ العملات المحددة في المبلغ من رصيد المرسل إلى المستلم.
هناك عدة نقاط جديدة (مظللة باللون الأحمر):
- 0x0 : عنوان الحساب حيث يتم تخزين الوحدة النمطية
- العملة : اسم الوحدة
- عملة : نوع المورد
- قيمة العملة التي يتم إرجاعها بواسطة الإجراء هي قيمة مورد يكون نوعها هو 0x0.Currency.Coin
- move () : لا يمكن استخدام القيمة مرة أخرى
- copy () : يمكن استخدام القيمة لاحقًا
نقوم بتحليل الكود: في الخطوة الأولى ، يستدعي المرسل إجراءً يسمى
pull_from_sender من الوحدة النمطية المخزنة في
0x0.Currency . في المرحلة الثانية ، يقوم المرسل بتحويل الأموال إلى المستلم ، مما يؤدي إلى نقل قيمة مورد العملة إلى إجراء إيداع الوحدة النمطية
0x0.Currency .
فيما يلي ثلاثة أمثلة على أخطاء التعليمات البرمجية التي سيتم رفضها بواسطة الاختبارات:
ازدواجية الأموال عن طريق تغيير الدعوة إلى التحرك (عملة) لنسخ (عملة) . يمكن نقل الموارد فقط. محاولة تكرار مقدار مورد (على سبيل المثال ، عن طريق استدعاء
نسخة (عملة) في المثال أعلاه) سيؤدي إلى خطأ أثناء التحقق من الرمز الفرعي.
إعادة استخدام الأموال عن طريق تحديد الخطوة (عملة) مرتين .
ستؤدي إضافة السطر
0x0.Currency.deposit (copy (some_other_payee) ، move (coin)) للمثال أعلاه إلى السماح للمرسل بـ "إنفاق" القطع النقدية مرتين - أول مرة مع payee ، والثاني مع
some_other_payee . هذا هو سلوك غير مرغوب فيه ، مستحيل مع الأصول المادية. لحسن الحظ ، سيرفض Move هذا البرنامج.
خسارة الأموال بسبب الفشل في الحركة (عملة) . إذا لم تقم بنقل المورد (على سبيل المثال ، عن طريق حذف السطر الذي يحتوي على
نقل (عملة معدنية) ) ، فسيتم إنشاء خطأ عن طريق التحقق من الرمز البريدي. هذا يحمي نقل المبرمجين من خسارة عرضية أو ضارة للأموال.
وحدة العملة

يمكن أن يحتوي كل حساب على 0 وحدة أو أكثر (كما هو موضح في المستطيلات) وقيمة واحدة أو أكثر من الموارد (كما هو موضح في صورة أسطوانات). على سبيل المثال ، يحتوي الحساب عند
0x0 على وحدة نمطية
للعملة 0x0. وقيمة مورد من النوع
0x0.Currency.Coin . لدى الحساب في
0x1 موارد اثنين ووحدة نمطية واحدة؛ يحتوي الحساب عند
0x2 على وحدتين وقيمة مورد واحدة.
بعض النقاط:
- النص البرمجي للمعاملات هو ذري - إما أنه تم تنفيذه بالكامل أو لا يتم تنفيذه على الإطلاق.
- الوحدة النمطية عبارة عن قطعة طويلة العمر من التعليمات البرمجية المتوفرة عالميًا.
- يتم تنظيم الحالة العامة كجدول تجزئة ، حيث سيكون المفتاح هو عنوان الحساب
- لا يمكن أن تحتوي الحسابات على أكثر من قيمة مورد واحدة من هذا النوع ولا تزيد عن وحدة نمطية واحدة باسم محدد (لا يمكن أن يحتوي الحساب في 0x0 على مورد إضافي 0x0.Currency.Coin أو وحدة نمطية أخرى باسم العملة )
- عنوان الوحدة النمطية المُعلنة جزء من النوع ( 0x0.Currency.Coin و 0x1.Currency.Coin نوعان منفصلان لا يمكن استخدامهما بالتبادل)
- يمكن للمبرمجين تخزين مثيلات متعددة من هذا النوع من الموارد في الحساب عن طريق تحديد موردهم المخصص - ( مورد TwoCoins {c1: 0x0.Currency.Coin ، c2: 0x0.Currency.Coin} )
- يمكنك الرجوع إلى مورد باسمه دون تعارضات ، على سبيل المثال ، يمكنك الرجوع إلى مصدرين باستخدام TwoCoins.c1 و TwoCoins.c2 .
عملة مورد الموارد

وحدة نمطية باسم
العملة ونوع مورد اسمه
عملةبعض النقاط:
- العملة هي بنية حقل واحد من النوع u64 (عدد صحيح 64 بت غير موقعة)
- يمكن فقط لإجراءات الوحدة النمطية للعملة إنشاء أو إتلاف قيم العملة .
- يمكن للوحدات النمطية والبرامج النصية الأخرى كتابة أو الرجوع إلى حقل القيمة فقط من خلال الإجراءات المفتوحة التي توفرها الوحدة النمطية.
تنفيذ الودائع

يأخذ هذا الإجراء مورد
Coin كمدخلات ويجمعه مع مورد
Coin المخزن في حساب المستلم:
- تدمير مورد الإدخال Coin وتسجيل قيمته.
- الحصول على رابط لمورد Coin فريد ومخزن على حساب المستلم.
- تغيير قيمة المبلغ Coin بالقيمة التي تم تمريرها في المعلمة عند استدعاء الإجراء.
بعض النقاط:
- فك ، BorrowGlobal - الإجراءات المضمنة
- Unpack <T> هي الطريقة الوحيدة لحذف مورد من النوع T. يأخذ الإجراء المورد إلى الإدخال ، ويدمره ويعيد القيمة المرتبطة بحقول المورد.
- BorrowGlobal <T> يقبل العنوان كمدخلات وإرجاع رابط إلى مثيل فريد من T المنشورة (مملوكة) بواسطة هذا العنوان
- & mut Coin هو رابط لمورد Coin
تطبيق pull_from_sender

هذا الإجراء:
- الحصول على رابط لمورد Coin فريد مرتبط بحساب المرسل
- يقلل من قيمة مورد العملة بالرجوع إلى المبلغ المحدد
- إنشاء وإرجاع مورد عملة جديد مع رصيد محدث.
بعض النقاط:
- يمكن لأي شخص الاتصال بالإيداع ، ولكن لا يمكن لـ pull_from_sender الوصول إلا إلى العملات المعدنية لحساب الاتصال
- يشبه GetTxnSenderAddress msg.sender في Solidity
- RejectUnless يشبه تتطلب في صلابة. في حالة فشل عملية التحقق هذه ، يتم إيقاف المعاملة وتراجع كل التغييرات.
- تعد حزمة <T> أيضًا إجراء مضمن يقوم بإنشاء مورد جديد من النوع T.
- مثل Unpack <T> ، لا يمكن استدعاء Pack <T> إلا داخل الوحدة النمطية حيث يتم وصف المورد T
استنتاج
درسنا الخصائص الرئيسية للغة Move ، وقمنا بمقارنتها بـ Ethereum ، وتعرّفنا أيضًا على التركيب الأساسي للنصوص. في الختام ، أوصي بشدة بالبحث في
الورقة البيضاء الأصلية . يتضمن العديد من التفاصيل المتعلقة بمبادئ تصميم لغة البرمجة ، بالإضافة إلى العديد من الروابط المفيدة.