مرکزی مواد پر جائیں
Change page

سمپل سیریلائز

صفحہ کی آخری اپ ڈیٹ: 1 فروری، 2026

سمپل سیریلائز (SSZ) بیکن چین پر استعمال ہونے والا سیریلائزیشن کا طریقہ ہے۔ یہ پیئر ڈسکوری پروٹوکول کے علاوہ کنسینسس لیئر میں ہر جگہ ایگزیکیوشن لیئر پر استعمال ہونے والی RLP سیریلائزیشن کی جگہ لیتا ہے۔ RLP سیریلائزیشن کے بارے میں مزید جاننے کے لیے، ریکرسیو-لینتھ پریفکس (RLP) دیکھیں۔ SSZ کو اس طرح ڈیزائن کیا گیا ہے کہ یہ ڈیٹرمنسٹک ہو اور موثر طریقے سے مرکلائز (Merkleize) بھی کر سکے۔ SSZ کو دو اجزاء پر مشتمل سمجھا جا سکتا ہے: ایک سیریلائزیشن اسکیم اور ایک مرکلائزیشن اسکیم جسے سیریلائزڈ ڈیٹا اسٹرکچر کے ساتھ موثر طریقے سے کام کرنے کے لیے ڈیزائن کیا گیا ہے۔

SSZ کیسے کام کرتا ہے؟

سیریلائزیشن

SSZ ایک سیریلائزیشن اسکیم ہے جو خود وضاحتی نہیں ہے - بلکہ یہ ایک ایسی اسکیمہ (schema) پر انحصار کرتی ہے جس کا پہلے سے معلوم ہونا ضروری ہے۔ SSZ سیریلائزیشن کا مقصد صوابدیدی پیچیدگی کے آبجیکٹس کو بائٹس کی اسٹرنگز کے طور پر پیش کرنا ہے۔ "بنیادی اقسام" کے لیے یہ ایک بہت ہی آسان عمل ہے۔ ایلیمنٹ کو آسانی سے ہیکساڈیسیمل بائٹس میں تبدیل کر دیا جاتا ہے۔ بنیادی اقسام میں شامل ہیں:

  • ان سائنڈ انٹیجرز (unsigned integers)
  • بولینز (Booleans)

پیچیدہ "کمپوزٹ" اقسام کے لیے، سیریلائزیشن زیادہ پیچیدہ ہوتی ہے کیونکہ کمپوزٹ قسم میں متعدد ایلیمنٹس ہوتے ہیں جن کی اقسام یا سائز مختلف ہو سکتے ہیں، یا دونوں۔ جہاں ان تمام آبجیکٹس کی لمبائی مقرر ہوتی ہے (یعنی، ایلیمنٹس کا سائز ان کی اصل قدروں سے قطع نظر ہمیشہ مستقل رہے گا) وہاں سیریلائزیشن محض کمپوزٹ قسم کے ہر ایلیمنٹ کو لٹل-اینڈین (little-endian) بائٹ اسٹرنگز میں ترتیب دے کر تبدیل کرنا ہے۔ ان بائٹ اسٹرنگز کو آپس میں جوڑ دیا جاتا ہے۔ سیریلائزڈ آبجیکٹ میں مقررہ لمبائی والے ایلیمنٹس کی بائٹ لسٹ کی نمائندگی اسی ترتیب میں ہوتی ہے جس ترتیب میں وہ ڈی سیریلائزڈ آبجیکٹ میں ظاہر ہوتے ہیں۔

متغیر لمبائی (variable lengths) والی اقسام کے لیے، اصل ڈیٹا کو سیریلائزڈ آبجیکٹ میں اس ایلیمنٹ کی پوزیشن پر ایک "آف سیٹ" (offset) ویلیو سے بدل دیا جاتا ہے۔ اصل ڈیٹا کو سیریلائزڈ آبجیکٹ کے آخر میں ایک ہیپ (heap) میں شامل کر دیا جاتا ہے۔ آف سیٹ ویلیو ہیپ میں اصل ڈیٹا کے آغاز کا انڈیکس ہوتی ہے، جو متعلقہ بائٹس کے لیے ایک پوائنٹر کے طور پر کام کرتی ہے۔

ذیل کی مثال واضح کرتی ہے کہ ایک ایسے کنٹینر کے لیے آف سیٹنگ کیسے کام کرتی ہے جس میں مقررہ اور متغیر لمبائی والے دونوں ایلیمنٹس ہوں:

1
2 struct Dummy {
3
4 number1: u64,
5 number2: u64,
6 vector: Vec<u8>,
7 number3: u64
8 }
9
10 dummy = Dummy{
11
12 number1: 37,
13 number2: 55,
14 vector: vec![1,2,3,4],
15 number3: 22,
16 }
17
18 serialized = ssz.serialize(dummy)
19
سب دکھائیں

serialized کا درج ذیل اسٹرکچر ہوگا (یہاں صرف 4 بٹس تک پیڈ کیا گیا ہے، حقیقت میں 32 بٹس تک پیڈ ہوتا ہے، اور وضاحت کے لیے int کی نمائندگی کو برقرار رکھا گیا ہے):

1[37, 0, 0, 0, 55, 0, 0, 0, 16, 0, 0, 0, 22, 0, 0, 0, 1, 2, 3, 4]
2------------ ----------- ----------- ----------- ----------
3 | | | | |
4 number1 number2 offset for number 3 value for
5 vector vector
6

وضاحت کے لیے لائنوں میں تقسیم کیا گیا ہے:

1[
2 37, 0, 0, 0, # little-endian encoding of `number1`.
3 55, 0, 0, 0, # little-endian encoding of `number2`.
4 16, 0, 0, 0, # The "offset" that indicates where the value of `vector` starts (little-endian 16).
5 22, 0, 0, 0, # little-endian encoding of `number3`.
6 1, 2, 3, 4, # The actual values in `vector`.
7]

یہ اب بھی ایک سادہ شکل ہے - اوپر دی گئی اسکیمیٹکس میں انٹیجرز اور صفر دراصل بائٹ لسٹس کے طور پر اسٹور کیے جائیں گے، اس طرح:

1[
2 10100101000000000000000000000000 # little-endian encoding of `number1`
3 10110111000000000000000000000000 # little-endian encoding of `number2`.
4 10010000000000000000000000000000 # The "offset" that indicates where the value of `vector` starts (little-endian 16).
5 10010110000000000000000000000000 # little-endian encoding of `number3`.
6 10000001100000101000001110000100 # The actual value of the `bytes` field.
7]

لہذا متغیر لمبائی والی اقسام کی اصل قدریں سیریلائزڈ آبجیکٹ کے آخر میں ایک ہیپ میں اسٹور کی جاتی ہیں اور ان کے آف سیٹس فیلڈز کی ترتیب وار فہرست میں ان کی درست پوزیشنز پر اسٹور کیے جاتے ہیں۔

کچھ خاص صورتیں بھی ہیں جن کے لیے مخصوص سلوک کی ضرورت ہوتی ہے، جیسے کہ BitList قسم جس میں سیریلائزیشن کے دوران لمبائی کی حد (length cap) شامل کرنے اور ڈی سیریلائزیشن کے دوران ہٹانے کی ضرورت ہوتی ہے۔ مکمل تفصیلات SSZ اسپیک (opens in a new tab) میں دستیاب ہیں۔

ڈی سیریلائزیشن

اس آبجیکٹ کو ڈی سیریلائز کرنے کے لیے اسکیمہ (schema) کی ضرورت ہوتی ہے۔ اسکیمہ سیریلائزڈ ڈیٹا کی درست ترتیب کی وضاحت کرتا ہے تاکہ ہر مخصوص ایلیمنٹ کو بائٹس کے ایک بلاب (blob) سے کسی بامعنی آبجیکٹ میں ڈی سیریلائز کیا جا سکے جس میں ایلیمنٹس کی درست قسم، قدر، سائز اور پوزیشن ہو۔ یہ اسکیمہ ہی ہے جو ڈی سیریلائزر کو بتاتا ہے کہ کون سی قدریں اصل قدریں ہیں اور کون سی آف سیٹس ہیں۔ جب کسی آبجیکٹ کو سیریلائز کیا جاتا ہے تو تمام فیلڈ کے نام غائب ہو جاتے ہیں، لیکن اسکیمہ کے مطابق ڈی سیریلائزیشن پر دوبارہ بحال ہو جاتے ہیں۔

اس پر ایک انٹرایکٹو وضاحت کے لیے ssz.dev (opens in a new tab) دیکھیں۔

مرکلائزیشن

اس SSZ سیریلائزڈ آبجیکٹ کو پھر مرکلائز کیا جا سکتا ہے - یعنی اسی ڈیٹا کی مرکل-ٹری (Merkle-tree) نمائندگی میں تبدیل کیا جا سکتا ہے۔ سب سے پہلے، سیریلائزڈ آبجیکٹ میں 32-بائٹ چنکس (chunks) کی تعداد کا تعین کیا جاتا ہے۔ یہ ٹری کے "پتے" (leaves) ہوتے ہیں۔ پتوں کی کل تعداد 2 کی پاور ہونی چاہیے تاکہ پتوں کو ایک ساتھ ہیش کرنے سے بالآخر ایک واحد ہیش-ٹری-روٹ (hash-tree-root) تیار ہو۔ اگر قدرتی طور پر ایسا نہیں ہے، تو صفر کے 32 بائٹس پر مشتمل اضافی پتے شامل کیے جاتے ہیں۔ خاکہ کے لحاظ سے:

1 hash tree root
2 / \
3 / \
4 / \
5 / \
6 hash of leaves hash of leaves
7 1 and 2 3 and 4
8 / \ / \
9 / \ / \
10 / \ / \
11 leaf1 leaf2 leaf3 leaf4
سب دکھائیں

ایسے معاملات بھی ہیں جہاں ٹری کے پتے قدرتی طور پر اس طرح یکساں طور پر تقسیم نہیں ہوتے جیسے وہ اوپر دی گئی مثال میں ہوتے ہیں۔ مثال کے طور پر، لیف 4 ایک ایسا کنٹینر ہو سکتا ہے جس میں متعدد ایلیمنٹس ہوں جن کے لیے مرکل ٹری میں اضافی "گہرائی" (depth) شامل کرنے کی ضرورت ہو، جس سے ایک ناہموار ٹری بنتا ہے۔

ان ٹری ایلیمنٹس کو لیف X، نوڈ X وغیرہ کہنے کے بجائے، ہم انہیں جنرلائزڈ انڈیکسز (generalized indices) دے سکتے ہیں، جو روٹ = 1 سے شروع ہوتے ہیں اور ہر سطح کے ساتھ بائیں سے دائیں گنتے ہیں۔ یہ اوپر بیان کردہ جنرلائزڈ انڈیکس ہے۔ سیریلائزڈ فہرست میں ہر ایلیمنٹ کا ایک جنرلائزڈ انڈیکس 2**depth + idx کے برابر ہوتا ہے جہاں idx سیریلائزڈ آبجیکٹ میں اس کی زیرو-انڈیکسڈ پوزیشن ہے اور گہرائی (depth) مرکل ٹری میں سطحوں کی تعداد ہے، جس کا تعین ایلیمنٹس (پتوں) کی تعداد کے بیس-ٹو لاگرتھم (base-two logarithm) کے طور پر کیا جا سکتا ہے۔

جنرلائزڈ انڈیکسز

جنرلائزڈ انڈیکس ایک انٹیجر ہے جو بائنری مرکل ٹری میں ایک نوڈ کی نمائندگی کرتا ہے جہاں ہر نوڈ کا ایک جنرلائزڈ انڈیکس 2 ** depth + index in row ہوتا ہے۔

1 1 --depth = 0 2**0 + 0 = 1
2 2 3 --depth = 1 2**1 + 0 = 2, 2**1+1 = 3
3 4 5 6 7 --depth = 2 2**2 + 0 = 4, 2**2 + 1 = 5...
4

یہ نمائندگی مرکل ٹری میں ڈیٹا کے ہر حصے کے لیے ایک نوڈ انڈیکس فراہم کرتی ہے۔

ملٹی پروفز

کسی مخصوص ایلیمنٹ کی نمائندگی کرنے والے جنرلائزڈ انڈیکسز کی فہرست فراہم کرنے سے ہم اسے ہیش-ٹری-روٹ کے خلاف تصدیق کر سکتے ہیں۔ یہ روٹ حقیقت کا ہمارا تسلیم شدہ ورژن ہے۔ ہمیں فراہم کردہ کسی بھی ڈیٹا کی اس حقیقت کے خلاف تصدیق کی جا سکتی ہے اسے مرکل ٹری میں صحیح جگہ پر داخل کر کے (اس کے جنرلائزڈ انڈیکس کے ذریعے طے کیا جاتا ہے) اور یہ مشاہدہ کر کے کہ روٹ مستقل رہتا ہے۔ اسپیک میں یہاں (opens in a new tab) ایسے فنکشنز موجود ہیں جو دکھاتے ہیں کہ جنرلائزڈ انڈیکسز کے کسی خاص سیٹ کے مندرجات کی تصدیق کے لیے درکار نوڈز کے کم از کم سیٹ کا حساب کیسے لگایا جائے۔

مثال کے طور پر، نیچے دیے گئے ٹری میں انڈیکس 9 میں ڈیٹا کی تصدیق کرنے کے لیے، ہمیں انڈیکسز 8، 9، 5، 3، 1 پر ڈیٹا کے ہیش کی ضرورت ہے۔ (8,9) کا ہیش ہیش (4) کے برابر ہونا چاہیے، جو 5 کے ساتھ ہیش ہو کر 2 بناتا ہے، جو 3 کے ساتھ ہیش ہو کر ٹری روٹ 1 بناتا ہے۔ اگر 9 کے لیے غلط ڈیٹا فراہم کیا گیا تھا، تو روٹ بدل جائے گا - ہم اس کا پتہ لگا لیں گے اور برانچ کی تصدیق کرنے میں ناکام رہیں گے۔

1* = data required to generate proof
2
3 1*
4 2 3*
5 4 5* 6 7
68* 9* 10 11 12 13 14 15
7

مزید مطالعہ

کیا یہ مضمون مددگار تھا؟