كما لو أننا لم نكتل

كيف نستخدم العقد الذكي لبناء نظام لاختيار أفضل المشاريع التكنولوجية في IT MTS؟ وما هي "الفخاخ" التي وقعنا فيها ، ولكننا استطعنا الخروج منها ، مما يثبت في النهاية أنه من الممكن الاحتفاظ بسجل موزع على الأجهزة المحمولة!



لماذا كانت هناك حاجة إلى نظام قائم على blockchain؟


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

تم اختيار أفضل مشروع دائمًا في عدة مراحل:

  • تطبيق الفرق
  • يتم التصويت للخبراء الفنيين المحترمين
  • بعد الخبراء ، يتم اختيار المشاريع من قبل المديرين
  • عند الانتهاء من جميع المراحل ، يختار المدير الكبير أفضل مشروع.

قررنا أن هذا المخطط ليس شفافًا بما يكفي بالنسبة للمشاركين وفكرنا: لماذا لا نعطي جميع الخبراء في الشركة الفرصة لاختيار أفضل مشروع تكنولوجي؟ 


إذا قمنا بتنفيذ هذه الفرصة مباشرة على الهاتف ، فسنرى التصنيف الحالي للمشاريع ومن يصوت لصالحه - وهذا سيضمن الشفافية الكاملة للعملية.

قرأنا العديد من المقالات حول blockchain ، وفكرة بناء نظام تسجيل موزع استقرت بقوة في رؤوسنا. ولكن ماذا لو طبقنا العقد الذكي هنا ؟

لقد جذبنا الخصائص التالية:

  • الانفتاح - لا يوجد خادم واحد حيث يمكنك معالجة المعلومات ؛
  • تظل المعلومات التي يتم وضعها في سجل موزع موجودة إلى الأبد ؛
  • لا يمكن تزوير المعلومات (حسنا ... عمليا)

لا بلوكشين




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

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

ما هي البدائل


البروتوكول الأكثر شهرة هو PAXOS. يفتقر إلى قائد صريح ، وجميع التغييرات تمر عبر التزام على مرحلتين. يحدث الاقتراح في بداية كل تغيير. إذا كان ناجحًا ، فسيتم إرسال Accept.


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

يتم استخدام الخوارزمية في العديد من الأماكن ، على سبيل المثال ، في Cassandra DBMS. لم نحب هذا البروتوكول من حيث تعقيد تنفيذه للمهمة. لكن الخيار الثاني جاء إلينا - إنه RAFT. في الواقع ، هذا تطور لبروتوكول PAXOS مع قائد واضح.

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

اقرأ عن البروتوكول هنا .

تنفيذنا


ماذا نفعل ولماذا العالم دراجة أخرى؟ 


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

دعونا نرى ما هي "الفخاخ" التي دخلنا فيها ، لكننا تمكنا من الخروج ...

فخ رقم 1: "عنواني ليس في المنزل وليس في الشارع"


"فجأة" اتضح أنه لبناء شبكة P2P التي تنفذ تسجيلًا موزعًا باستخدام بروتوكول RAFT لنسخ البيانات ، يمكن لكل جهاز الاتصال ببعضه البعض ، مما يعني أنه عميل وخادم. لذلك ، نحتاج إلى عنوان IP "أبيض" عام لكل هاتف محمول (قد لا يكون).

عدد IPv4s الحقيقي محدود للغاية ، لذلك يستخدم مشغلو الاتصالات تقنية NAT (ترجمة عنوان الشبكة) في وضع PAT (ترجمة عنوان المنفذ) ، ويترجمون عدة عناوين IP للشبكة الداخلية (التي يتم توزيعها على المشتركين) إلى عنوان IP عام خارجي واحد. وبالتالي ، يتم استبعاد القدرة على قبول الاتصالات الواردة من الإنترنت.

الخبر السار هو أن هناك الكثير من IPv6! 


لدينا دعم IPv6 مدرج في الحزمة الأساسية. أيضًا ، تدعم جميع الهواتف الحديثة IPv6 ، ويقوم المشغل بتعيين المشترك بعنوان v6 "أبيض" عام. خيارنا هو IPv6.

فخ رقم 2: ذهب الجميع إلى النوم


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

3: 



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

4: Android 
 



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

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

سيتم التنفيذ قبل الانتهاء من سرد طلبك! لدينا SourceSet واحد مع شفرة المصدر ، والتي نجمع منها الثنائيات لجميع المنصات (!) ، باستخدام ميزة "يعتمد" . رائع؟ رائع جدا!

فخ رقم 5: حركة مرور الهاتف المحمول ليست مجانية 



كيف يمكننا تنفيذ التفاعل بين عُقد الشبكة بشكل أكثر فاعلية حتى لا ننفق جميع زيارات المشترك ولا نستنزف بطارية الجهاز المحمول؟ نفترض أن الشبكة قد تتكون من 1000 جهاز أو أكثر! الخيار الأكثر وضوحًا هو استخدام UDP بدلاً من TCP ، على سبيل المثال ، في إجراء الاختيار "الرائد" أو عند إرسال نبضات القلب بدون بيانات. يعد بروتوكول UDP أكثر اقتصادا لأنه يستخدم نموذج بسيط لنقل البيانات ، دون "المصافحة" والتأكيدات. غرامة! ماذا بعد؟ بالطبع ، I / O غير متزامن!

قرأنا بعناية وثائق Kotlin Native.

بالنسبة لجميع الأهداف التي تستند إلى Unix أو Windows (بما في ذلك Android و iPhone) ، فإننا نقدم نظام الأساسيات posix lib. يحتوي على روابط لتطبيق النظام الأساسي لمعيار POSIX.

ثم نقرأ أيضًا وثائق POSIX القياسية بعناية ونجد وظيفة رائعة تسمح لنا بمعالجة أحداث مأخذ التوصيل في وضع عدم الحظر! بعد أن انغمس بشدة في عالم رائع من المقابس والمآخذ و C Interop ، تمكنا من تحقيق نقل فعال للغاية. ممتاز!

وبأي شكل لإرسال البيانات؟ 



بالطبع CBOR!

تنسيق بيانات ثنائي مضغوط ، والذي ، بحسن الحظ ، يتم تنفيذه في مكتبة kotlinx.serialization مكتبة متعددة المنصات . مذهل!

الفخ رقم 6: التسلسل 



هذه المرة ، اتضح بشكل غير متوقع حقًا أن kotlinx.serialization ليس تحت androidNative (تحت androidJvm ، بالطبع هناك). أكد زملائي الأعزاء من JetBrains أنهم في الوقت الحالي لا يقومون ببناء مكتبة لـ androidNative ، وقبل إصدار Kotlin 1.4 لم يعد هناك مكان لهذه المهمة في خريطة الطريق. 


ماذا أفعل؟ إذا لم يذهب الجبل إلى محمد ، يذهب محمد إلى الجبل!

قمنا بأنفسنا بتجميع kotlinx.serialization لجميع المنصات ، بما في ذلك androidNative! أكثر شيء مدهش هو أنه نجح! 


المصيدة رقم 7: أين يتم تخزين السجل؟ 



من الواضح ، في تخزين القيمة الرئيسية المضمنة ، ولكن في أي؟ لقد اخترنا lmdbx لضغط الشفرة ، والسرعة ، والمنصات المتعددة ، ونقص ملف WAL. تم تطوير هذه المكتبة من قبل الرجال من Techlologies الإيجابية وتنبع من مكتبة LMDB الأسطورية من أحد مؤلفي OpenLDAP Howard Chu. وهذا بدوره متجذر في تنفيذ شجرة B + من Martin Hedenfalk. بالمناسبة ، خارج الصندوق ، لم يتم بناء المكتبة ل androidNative. لقد جمعنا بعناية جميع الأخطاء ، وقدم المؤلفون على الفور إصلاحات - والتي شكر خاص لهم!

فخ رقم 8: C Interop 



ثبت أن وضع كل ذلك معًا مهمة غير تافهة للغاية. بالإضافة إلى مآخذ lmdbx و posix ، قمنا بدمج مكتبات لإنشاء / التحقق من صحة التوقيعات الرقمية على المنحنيات الناقصية وحساب SHA256 باستخدام آلية C Interop المذهلة . بكلمات بسيطة - من تطبيق أصلي على Kotlin ، يمكنك استدعاء وظيفة مكتبة C ، بما في ذلك مع المؤشرات إلى المؤشرات وغيرها من السحر ، كل ذلك يبدو غريبًا بعض الشيء.

على سبيل المثال ، استدعاء getaddrinfo للحصول على sockaddr.



كيف تحب Ilon Mask؟

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

عن الانتخابات


الانتخابات الرئيسية التي أجريناها خلال اليوم. شارك ما يزيد قليلاً عن 20 خبيراً في الاختبار باستخدام شبكتنا. تم تقييم 21 مشروعًا في 5 فئات ، أي تمت إضافة أكثر من 100 إدخال مع تصويت لمشاريع إلى السجل.

استنتاج


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

مؤلفو المقال: المهندسون المعماريون والمطورون في مركز البحث والتطوير التابع لـ MTS Dmitry Dzyuba و Alexey Vasilenko و Semen Nevrev

All Articles