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

تسلسل البادئة ذات الطول المتكرر (RLP)

آخر تحديث للصفحة: 23 فبراير 2026

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

مزيد من المعلومات في الورقة الصفراء لإيثريوم (الملحق ب) (opens in a new tab).

لاستخدام RLP لترميز القاموس، هناك نموذجان أساسيان مقترحان هما:

  • استخدم [[k1,v1],[k2,v2]...] مع المفاتيح بالترتيب المعجمي
  • استخدم ترميز شجرة باتريشيا عالي المستوى كما يفعل الإيثريوم

التعريف

تستقبل وظيفة ترميز RLP عنصرًا. يتم تعريف العنصر على النحو التالي:

  • السلسلة (أي مصفوفة بايت) هي عنصر
  • قائمة العناصر هي عنصر
  • عدد صحيح موجب هو عنصر

على سبيل المثال، كل ما يلي عبارة عن عناصر:

  • سلسلة فارغة؛
  • السلسلة التي تحتوي على كلمة "قطة"؛
  • قائمة تحتوي على أي عدد من السلاسل؛
  • وهياكل البيانات الأكثر تعقيدًا مثل ["cat", ["puppy", "cow"], "horse", [[]], "pig", [""], "sheep"].
  • الرقم 100

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

يتم تعريف ترميز RLP على النحو التالي:

  • بالنسبة لعدد صحيح موجب، يتم تحويله إلى أقصر مجموعة بايتات يكون تفسيرها الكبير هو العدد الصحيح، ثم يتم ترميزها كسلسلة وفقًا للقواعد أدناه.
  • بالنسبة لبايت واحد تكون قيمته في النطاق [0x00, 0x7f] (عشري [0, 127])، فإن هذا البايت هو ترميز RLP الخاص به.
  • بخلاف ذلك، إذا كان طول السلسلة من 0-55 بايت، فإن ترميز RLP يتكون من بايت واحد بقيمة 0x80 (عشري 128) بالإضافة إلى طول السلسلة متبوعًا بالسلسلة. وبالتالي فإن نطاق البايت الأول هو [0x80, 0xb7] (عشري [128, 183]).
  • إذا كان طول السلسلة أكثر من 55 بايت، فإن ترميز RLP يتكون من بايت واحد بقيمة 0xb7 (عشري 183) بالإضافة إلى الطول بالبايت لطول السلسلة في شكل ثنائي، متبوعًا بطول السلسلة، متبوعًا بالسلسلة. على سبيل المثال، سيتم ترميز سلسلة طولها 1024 بايت على هيئة \xb9\x04\x00 (عشري 185, 4, 0) متبوعة بالسلسلة. هنا، 0xb9 (183 + 2 = 185) هو البايت الأول، متبوعًا بالبايتين 0x0400 (عشري 1024) اللذين يشيران إلى طول السلسلة الفعلية. وبالتالي فإن نطاق البايت الأول هو [0xb8, 0xbf] (عشري [184, 191]).
  • إذا كان طول السلسلة 2^64 بايت أو أكثر، فقد لا يتم ترميزها.
  • إذا كان إجمالي حمولة القائمة (أي، الطول المجمع لجميع عناصرها المشفرة بـ RLP) يتراوح من 0 إلى 55 بايت، فإن ترميز RLP يتكون من بايت واحد بقيمة 0xc0 بالإضافة إلى طول الحمولة متبوعًا بسلسلة ترميزات RLP للعناصر. وبالتالي فإن نطاق البايت الأول هو [0xc0, 0xf7] (عشري [192, 247]).
  • إذا كان إجمالي حمولة القائمة أكثر من 55 بايت، فإن ترميز RLP يتكون من بايت واحد بقيمة 0xf7 بالإضافة إلى الطول بالبايت لطول الحمولة في شكل ثنائي، متبوعًا بطول الحمولة، متبوعًا بسلسلة ترميزات RLP للعناصر. وبالتالي فإن نطاق البايت الأول هو [0xf8, 0xff] (عشري [248, 255]).

في الكود، هذا هو:

1def rlp_encode(input):
2 if isinstance(input,str):
3 if len(input) == 1 and ord(input) < 0x80:
4 return input
5 return encode_length(len(input), 0x80) + input
6 elif isinstance(input, list):
7 output = ''
8 for item in input:
9 output += rlp_encode(item)
10 return encode_length(len(output), 0xc0) + output
11
12def encode_length(L, offset):
13 if L < 56:
14 return chr(L + offset)
15 elif L < 256**8:
16 BL = to_binary(L)
17 return chr(len(BL) + offset + 55) + BL
18 raise Exception("input too long")
19
20def to_binary(x):
21 if x == 0:
22 return ''
23 return to_binary(int(x / 256)) + chr(x % 256)
إظهار الكل

أمثلة

  • السلسلة "dog" = [0x83، 'd'، 'o'، 'g']
  • القائمة [ "cat", "dog" ] = [ 0xc8, 0x83, 'c', 'a', 't', 0x83, 'd', 'o', 'g' ]
  • السلسلة الفارغة ('null') = [ 0x80 ]
  • القائمة الفارغة = [ 0xc0 ]
  • العدد الصحيح 0 = [ 0x80 ]
  • البايت '\x00' = [ 0x00 ]
  • البايت '\x0f' = [ 0x0f ]
  • البايتات '\x04\x00' = [ 0x82, 0x04, 0x00 ]
  • التمثيل بنظرية المجموعات للرقم ثلاثة (opens in a new tab)، [ [], [[]], [ [], [[]] ] ] = [ 0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0 ]
  • السلسلة "Lorem ipsum dolor sit amet, consectetur adipisicing elit" = [ 0xb8, 0x38, 'L', 'o', 'r', 'e', 'm', ' ', ... , 'e', 'l', 'i', 't' ]

فك ترميز RLP

وفقًا لقواعد وعملية ترميز RLP، يُعتبر إدخال فك تشفير RLP بمثابة مجموعة من البيانات الثنائية. تتم عملية فك تشفير RLP على النحو التالي:

  1. وفقًا للبايت الأول (أي البادئة) لبيانات الإدخال، وفك ترميز نوع البيانات، وطول البيانات الفعلية، والإزاحة؛

  2. وفقًا لنوع البيانات وإزاحتها، قم بفك تشفير البيانات وفقًا لذلك، مع مراعاة قاعدة الترميز الأدنى للأعداد الصحيحة الموجبة؛

  3. استمر في فك تشفير بقية المدخلات؛

ومن بينها قواعد فك تشفير أنواع البيانات والإزاحة على النحو التالي:

  1. البيانات عبارة عن سلسلة إذا كان نطاق البايت الأول (أي البادئة) هو [0x00, 0x7f]، والسلسلة هي البايت الأول نفسه بالضبط؛

  2. البيانات عبارة عن سلسلة إذا كان نطاق البايت الأول هو [0x80، 0xb7]، والسلسلة التي يساوي طولها البايت الأول ناقص 0x80 تتبع البايت الأول؛

  3. تكون البيانات عبارة عن سلسلة إذا كان نطاق البايت الأول هو [0xb8، 0xbf]، وطول السلسلة التي يكون طولها بالبايتات مساويًا للبايت الأول ناقص 0xb7 يتبع البايت الأول، وتتبع السلسلة طول السلسلة؛

  4. البيانات عبارة عن قائمة إذا كان نطاق البايت الأول هو [0xc0، 0xf7]، وتسلسل ترميزات RLP لجميع عناصر القائمة التي يكون إجمالي الحمولة فيها مساويًا للبايت الأول ناقص 0xc0 يتبع البايت الأول؛

  5. البيانات عبارة عن قائمة إذا كان نطاق البايت الأول هو [0xf8، 0xff]، والحمولة الإجمالية للقائمة التي يساوي طولها البايت الأول ناقص 0xf7 تتبع البايت الأول، وتسلسل ترميزات RLP لجميع عناصر القائمة يتبع الحمولة الإجمالية للقائمة؛

في الكود، هذا هو:

1def rlp_decode(input):
2 if len(input) == 0:
3 return
4 output = ''
5 (offset, dataLen, type) = decode_length(input)
6 if type is str:
7 output = instantiate_str(substr(input, offset, dataLen))
8 elif type is list:
9 output = instantiate_list(substr(input, offset, dataLen))
10 output += rlp_decode(substr(input, offset + dataLen))
11 return output
12
13def decode_length(input):
14 length = len(input)
15 if length == 0:
16 raise Exception("input is null")
17 prefix = ord(input[0])
18 if prefix <= 0x7f:
19 return (0, 1, str)
20 elif prefix <= 0xb7 and length > prefix - 0x80:
21 strLen = prefix - 0x80
22 return (1, strLen, str)
23 elif prefix <= 0xbf and length > prefix - 0xb7 and length > prefix - 0xb7 + to_integer(substr(input, 1, prefix - 0xb7)):
24 lenOfStrLen = prefix - 0xb7
25 strLen = to_integer(substr(input, 1, lenOfStrLen))
26 return (1 + lenOfStrLen, strLen, str)
27 elif prefix <= 0xf7 and length > prefix - 0xc0:
28 listLen = prefix - 0xc0;
29 return (1, listLen, list)
30 elif prefix <= 0xff and length > prefix - 0xf7 and length > prefix - 0xf7 + to_integer(substr(input, 1, prefix - 0xf7)):
31 lenOfListLen = prefix - 0xf7
32 listLen = to_integer(substr(input, 1, lenOfListLen))
33 return (1 + lenOfListLen, listLen, list)
34 raise Exception("input does not conform to RLP encoding form")
35
36def to_integer(b):
37 length = len(b)
38 if length == 0:
39 raise Exception("input is null")
40 elif length == 1:
41 return ord(b[0])
42 return ord(substr(b, -1)) + to_integer(substr(b, 0, -1)) * 256
إظهار الكل

قراءة إضافية

هل كانت هذه المقالة مفيدة؟