Featured image of post صلابة مقدمة في اللغة

صلابة مقدمة في اللغة

نموذج لمقالة تعرض مفاهيم وبناء جملة Solidity الأساسية.

الصلابة - الأساسيات

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

يجب أن يكون لدى القراء فهم أساسي لكيفية عمل Ethereum and Salidity.

مقدمة

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

  • العقد الجديد يعمل على النحو المقصود.
  • تم الانتهاء من جميع المكالمات التي تم إجراؤها أثناء إجراء الاستبدال بنجاح.
  • استبدال العقد ليس له آثار جانبية في أجزاء أخرى من النظام.

ومع ذلك ، فإن أول شيء يجب التحقق منه هو أن الترقية ممكنة على الإطلاق. هذا ليس هو الحال دائمًا بسبب الطريقة التي تعمل بها حسابات Ethereum.

الحسابات والرمز والتخزين

خاصية مهمة للغاية لعقود Etheruem هي أنه بمجرد تحميل العقد على السلسلة ، لم يعد من الممكن تغيير الرمز.يتم تخزين العقود في كائنات حساب خاصة تحتوي على إشارات إلى رمز العقد (بايت) ، قاعدة البيانات ، وبعض الأشياء الأخرى.قاعدة البيانات عبارة عن مخزن مفتاح وقيمة ، يُعرف أيضًا باسم “المتجر” ، وهذا هو المكان الذي يتم فيه تخزين البيانات مثل قيم حقل العقد.

!

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

دعونا نلقي نظرة على مثال على عقد بسيط للغاية:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
contract Data {

    uint public data;

    function addData(uint data_) {
        if(msg.sender == 0x692a70d2e424a56d2c6c27aa97d1a86395877b3a)
            data = data_;
    }
    
}

يسمح هذا العقد للمستخدم بإضافة وقراءة عدد صحيح غير موقّع.الحساب الوحيد المسموح به لإضافة البيانات هو الحساب مع العنوان 0x692a ....هذا العنوان هو حرفي سداسي عشري ، لذلك تتم إضافته إلى رمز bytecode عند تجميع العقد.

ولكن ماذا لو أردنا استبدال هذا العنوان لاحقًا؟

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
contract DataOwnerSettable {
    
    uint public data;
    
    address public owner = msg.sender;

    function addData(uint data_) {
        if(msg.sender == owner)
            data = data_;
    }
    
    function setOwner(address owner_) {
        if(msg.sender == owner)
            owner = owner_;
    }
    
}

يحتوي هذا العقد على حقل “مالك” (تم تعيينه إلى المتجر). تتم تهيئته بعنوان الحساب الذي ينشئ العقد ، ويمكن تغييره لاحقًا بواسطة المالك الحالي عن طريق الاتصال بـ SetOwner. يبقى الأمن داخل Adddata كما هو. الشيء الوحيد الذي تغير هو أن عنوان المالك ليس متشددًا.

وفد

ولكن ماذا لو لم يكن المالك المحدد كافيًا؟ ماذا لو أردنا أن نكون قادرين على تحديث ليس فقط عنوان المالك ، ولكن عملية التحقق بأكملها؟

في الواقع ، هناك طريقة لاستبدال الكود ، وهي توصيل العديد من مكالمات العقد لتشكيل سلسلة مكالمات واحدة. العقد “يمكن أن يطلق على عقد آخر” d “كجزء من وظيفته ، مما يعني أن المعاملة التي ترفع” C ستنفذ الكود ليس فقط في "C ولكن أيضًا في" D “. بالإضافة إلى ذلك ، يمكننا أيضًا إدخال عنوان “قابل للتسوية ، أي يمكننا تغيير مثيل” D “الذي أشار إليه”. مثال على ذلك سيكون عقدًا مصرفيًا يدعو عقدًا آخر للمصادقة.

!

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

سنقوم الآن بتحديث عقد البيانات للعمل بهذه الطريقة ، ويبدأ بنقل التحقق من صحة الحساب إلى عقد آخر.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
contract AccountValidator {
    
    address public owner = msg.sender;
    
    function validate(address addr) constant returns (bool) {
        return addr == owner;
    }
    
    function setOwner(address owner_) {
        if(msg.sender == owner)
           owner = owner_;
    }
    
}


contract DataExternalValidation {
    
    uint public data;

    AccountValidator _validator;

    function DataExternalValidation(address validator) {
        _validator = AccountValidator(validator);
    }

    function addData(uint data_) {
        if(_validator.validate(msg.sender))
            data = data_;
    }
    
    function setValidator(address validator) {
        if(_validator.validate(msg.sender))
            _validator = AccountValidator(validator);
    }
}

لاستخدام هذا العقد على السلسلة ، سنقوم أولاً بإنشاء عقد accountValIdator ، ثم إنشاءdataexternalvalidationوضخت عنوان المدقق من خلال مُنشئ العقد.عندما يحاول شخص ما الكتابة إلى “البيانات” ، فإنه سيتصل بـ “التحقق” على عقد التحقق الحالي للقيام بشيك المالك.

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

لا يزال هناك شيء واحد.ما زلنا لا نستطيع استبدال الرمز!كل ما فعلناه هو نقل رمز التحقق من العقد.لا يمكن تغيير مدونة عقد “حساب الحساب” بعد الآن ثم بعقد البيانات.لحسن الحظ ، توفر الصلابة حلًا بسيطًا وقويًا للغاية - وظائف مجردة.

وظائف الملخص

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
contract AccountValidator {
    function validate(address addr) constant returns (bool);
}


contract SingleAccountValidator is AccountValidator {
    
    address public owner = msg.sender;
    
    function validate(address addr) constant returns (bool) {
        return addr == owner;
    }
    
    function setOwner(address owner_) {
        if(msg.sender == owner)
            owner = owner_;
    }
    
}

من خلال هذه العقود ، لم يعد عقد البيانات يعمل مع عقد مدقق ملموس ولكن تمثيل مجردة (واجهة) بدلاً من ذلك ، مما يعني أنه يمكننا اختيار التنفيذ الذي نريد تقديمه.يعمل هذا بنفس الطريقة التي تعمل بها بلغات مثل Java و C ++.دعنا نقول أننا نريد السماح لمزيد من حسابات المالك ثم حساب واحد فقط.يمكننا بعد ذلك تزويدها بهذا العقد:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
contract MultiAccountValidator is AccountValidator {
    
    mapping(address => bool) public owners;
    
    function MultiAccountValidator() {
        owners[msg.sender] = true;
    }
    
    function validate(address addr) constant returns (bool) {
        return owners[addr];
    }
    
    function addOwner(address addr) {
        if(owners[msg.sender])
            owners[addr] = true;
    }
}

أخيرًا ، تجدر الإشارة إلى أنه يمكنك بالفعل تمرير عقد ليس “حسابًا”. لا يوجد فحص نوع عند تحويل عنوان إلى نوع العقد ، لذلك لن يظهر إلا عندما يتم استدعاء العقد فعليًا ؛ وفي الواقع ، طالما أن العقد يحتوي على الطريقة المطلوبة ستعمل المكالمة - حتى لو لم يتم تمديد “حساب AccountValIdator” بالفعل.

بالطبع لا ينصح باستخدام العقود بهذه الطريقة.

ملخص

يعد التفويض المناسب جزءًا مهمًا من أنظمة العقد الذكي ، لأنه يعني أنه يمكن استبدال العقود. هناك بعض الأشياء التي يجب وضعها في الاعتبار ، على الرغم من:

  • يتطلب التفويض تحويل نوع غير آمن ، مما يعني أن المرء يجب أن يكون حذراً عند إعداد/تغيير مرجع العقد.

  • كلما زاد عدد العقود الموجودة في النظام ، أصبح من الصعب إدارتها ، وقد لا تكون الإستراتيجية التي تجعل عمل النظام الصغير مناسبة لمادة متوسطة الحجم أو كبيرة.

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

comments powered by Disqus
مبني بستخدام Hugo
قالب Stack مصمم من Jimmy