تخطي إلى المحتوى الرئيسي
Change page

التسلسل البسيط

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

كيف يعمل SSZ؟

التسلسل

SSZ هو مخطط تسلسل لا يصف نفسه - بل يعتمد على مخطط (schema) يجب أن يكون معروفًا مسبقًا. الهدف من تسلسل SSZ هو تمثيل الكائنات ذات التعقيد العشوائي كسلاسل من البايتات. هذه عملية بسيطة جدًا لـ "الأنواع الأساسية". يتم ببساطة تحويل العنصر إلى بايتات سداسية عشرية. تشمل الأنواع الأساسية ما يلي:

  • الأعداد الصحيحة غير الموقعة
  • القيم المنطقية (Booleans)

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

بالنسبة للأنواع ذات الأطوال المتغيرة، يتم استبدال البيانات الفعلية بقيمة "إزاحة" (offset) في موضع ذلك العنصر في الكائن المتسلسل. تتم إضافة البيانات الفعلية إلى كومة (heap) في نهاية الكائن المتسلسل. قيمة الإزاحة هي المؤشر لبداية البيانات الفعلية في الكومة، وتعمل كمؤشر (pointer) للبايتات ذات الصلة.

يوضح المثال أدناه كيف تعمل الإزاحة لحاوية تحتوي على عناصر ثابتة ومتغيرة الطول:

سيكون لـ serialized البنية التالية (مبطنة إلى 4 bits فقط هنا، ومبطنة إلى 32 bits في الواقع، مع الاحتفاظ بتمثيل int للتوضيح):

[37, 0, 0, 0, 55, 0, 0, 0, 16, 0, 0, 0, 22, 0, 0, 0, 1, 2, 3, 4]
------------  -----------  -----------  -----------  ----------
      |             |            |           |            |
   الرقم 1       الرقم 2       إزاحة      الرقم 3       قيمة
                               المتجه                   المتجه

مقسمة على أسطر للتوضيح:

[
  37, 0, 0, 0,  # ترميز النهاية الصغيرة (little-endian) لـ `number1`.
  55, 0, 0, 0,  # ترميز النهاية الصغيرة لـ `number2`.
  16, 0, 0, 0,  # "الإزاحة" التي تشير إلى مكان بدء قيمة `vector` (النهاية الصغيرة 16).
  22, 0, 0, 0,  # ترميز النهاية الصغيرة لـ `number3`.
  1, 2, 3, 4,   # القيم الفعلية في `vector`.
]

هذا لا يزال تبسيطًا - الأعداد الصحيحة والأصفار في المخططات أعلاه سيتم تخزينها في الواقع كقوائم بايتات، هكذا:

[
  10100101000000000000000000000000  # ترميز النهاية الصغيرة لـ `number1`
  10110111000000000000000000000000  # ترميز النهاية الصغيرة لـ `number2`.
  10010000000000000000000000000000  # "الإزاحة" التي تشير إلى مكان بدء قيمة `vector` (النهاية الصغيرة 16).
  10010110000000000000000000000000  # ترميز النهاية الصغيرة لـ `number3`.
  10000001100000101000001110000100   # القيمة الفعلية لحقل `bytes`.
]

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

هناك أيضًا بعض الحالات الخاصة التي تتطلب معالجة محددة، مثل نوع BitList الذي يتطلب إضافة حد أقصى للطول أثناء التسلسل وإزالته أثناء إلغاء التسلسل. التفاصيل الكاملة متاحة في مواصفات SSZ (opens in a new tab).

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

التحويل إلى شجرة ميركل

يمكن بعد ذلك تحويل كائن SSZ المتسلسل هذا إلى شجرة ميركل - أي تحويله إلى تمثيل شجرة ميركل لنفس البيانات. أولاً، يتم تحديد عدد القطع المكونة من 32-byte في الكائن المتسلسل. هذه هي "أوراق" الشجرة. يجب أن يكون العدد الإجمالي للأوراق من مضاعفات العدد 2 بحيث تؤدي عملية التجزئة للأوراق معًا في النهاية إلى جذر شجرة تجزئة واحد. إذا لم يكن هذا هو الحال بشكل طبيعي، تتم إضافة أوراق إضافية تحتوي على 32 bytes من الأصفار. تخطيطيًا:

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

بدلاً من الإشارة إلى عناصر الشجرة هذه باسم الورقة X، العقدة X وما إلى ذلك، يمكننا إعطاؤها مؤشرات معممة، بدءًا من الجذر = 1 والعد من اليسار إلى اليمين على طول كل مستوى. هذا هو المؤشر المعمم الموضح أعلاه. كل عنصر في القائمة المتسلسلة له مؤشر معمم يساوي 2**depth + idx حيث idx هو موضعه المفهرس بالصفر في الكائن المتسلسل والعمق هو عدد المستويات في شجرة ميركل، والذي يمكن تحديده على أنه اللوغاريتم ذو الأساس 2 لعدد العناصر (الأوراق).

المؤشرات المعممة

المؤشر المعمم هو عدد صحيح يمثل عقدة في شجرة ميركل ثنائية حيث يكون لكل عقدة مؤشر معمم 2 ** depth + index in row.

1           --العمق = 0  2**0 + 0 = 1
    2       3       --العمق = 1  2**1 + 0 = 2, 2**1+1 = 3
  4   5   6   7     --العمق = 2  2**2 + 0 = 4, 2**2 + 1 = 5...

ينتج عن هذا التمثيل مؤشر عقدة لكل جزء من البيانات في شجرة ميركل.

الإثباتات المتعددة (Multiproofs)

يتيح لنا توفير قائمة المؤشرات المعممة التي تمثل عنصرًا معينًا التحقق منه مقابل جذر شجرة التجزئة. هذا الجذر هو نسختنا المقبولة من الواقع. يمكن التحقق من أي بيانات يتم تزويدنا بها مقابل هذا الواقع عن طريق إدراجها في المكان الصحيح في شجرة ميركل (يتم تحديده بواسطة مؤشرها المعمم) وملاحظة أن الجذر يظل ثابتًا. توجد دوال في المواصفات هنا (opens in a new tab) توضح كيفية حساب الحد الأدنى من مجموعة العقد المطلوبة للتحقق من محتويات مجموعة معينة من المؤشرات المعممة.

على سبيل المثال، للتحقق من البيانات في المؤشر 9 في الشجرة أدناه، نحتاج إلى تجزئة البيانات في المؤشرات 8 و 9 و 5 و 3 و 1. يجب أن تساوي تجزئة (8،9) تجزئة (4)، والتي يتم تجزئتها مع 5 لإنتاج 2، والتي يتم تجزئتها مع 3 لإنتاج جذر الشجرة 1. إذا تم توفير بيانات غير صحيحة لـ 9، فسيتغير الجذر - وسنكتشف ذلك ونفشل في التحقق من الفرع.

* = البيانات المطلوبة لإنشاء الإثبات

                    1*
          2                      3*
    4          5*          6          7
8*     9*   10    11   12    13    14    15