پرش به محتوای اصلی
Change page

سریال سازی پیشوند با طول بازگشتی (RLP)

آخرین ویرایش: @sipbikardi(opens in a new tab), ۱۹ اردیبهشت ۱۴۰۳

سریال سازی پیشوند طول بازگشتی (RLP) به طور گسترده در کلاینت های اجرایی اتریوم استفاده می شود. RLP انتقال داده ها بین گره ها را در یک فرمت فضا-کارا استاندارد می کند. هدف RLP کدگذاری آرایه های تو در تو دلخواه از داده های دوتایی است و RLP روش رمزگذاری اولیه است که برای سریال سازی اشیاء در لایه اجرای اتریوم استفاده می شود. هدف اصلی RLP کدگذاری ساختار است. به استثنای اعداد صحیح مثبت، RLP کدگذاری انواع داده های خاص (مانند رشته ها، شناورها) را به پروتکل های مرتبه بالاتر واگذار می کند. اعداد صحیح مثبت باید به شکل دوتایی با اندین بزرگ و بدون صفرهای ابتدایی نمایش داده شوند (بنابراین مقدار عدد صحیح صفر معادل آرایه بایت خالی می شود). اعداد صحیح مثبت غیر سریالی شده با صفرهای ابتدایی باید توسط هر پروتکل مرتبه بالاتر با استفاده از RLP نامعتبر تلقی شوند.

اطلاعات بیشتر در مقاله زرد اتریوم (پیوست B)(opens in a new tab).

برای استفاده از RLP برای رمزگذاری یک فرهنگ لغت، دو شکل متعارف پیشنهادی عبارتند از:

  • از [[k1,v1],[k2,v2]...] با کلیدها به ترتیب واژگان استفاده کنید
  • از رمزگذاری درخت پاتریشیا در سطح بالاتر مانند اتریوم استفاده کنید

تعریف

تابع رمزگذاری RLP یک آیتم را می گیرد. یک آیتم به صورت زیر تعریف می شود:

  • یک رشته (یعنی آرایه بایت) یک آیتم است
  • لیست اقلام، یک آیتم است
  • یک عدد صحیح مثبت یک آیتم است

به عنوان مثال، همه موارد زیر عبارتند از:

  • یک رشته خالی؛
  • رشته حاوی کلمه "گربه"؛
  • لیستی حاوی هر تعداد رشته؛
  • و ساختارهای داده پیچیده تری مانند ["گربه"، ["توله سگ"، "گاو"]، "اسب"، [[]]، "خوک"، [""]، "گوسفند"].
  • عدد 100

توجه داشته باشید که در زمینه بقیه این صفحه، "رشته" به معنای "تعداد معینی از بایت داده های دوتایی" است. هیچ کدگذاری خاصی استفاده نمی شود، توجه داشته باشید که در زمینه بقیه این صفحه، "رشته" به معنای "تعداد معینی از بایت داده های دوتایی" است. هیچ کدگذاری خاصی استفاده نمی شود، و هیچ دانشی در مورد محتوای رشته ها وجود ندارد (به جز مواردی که توسط قانون در مورد اعداد صحیح مثبت غیر حداقلی لازم است).

رمزگذاری RLP به صورت زیر تعریف می شود:

  • برای یک عدد صحیح مثبت، به کوتاه‌ترین آرایه بایتی که تفسیر آن عدد صحیح است، تبدیل می‌شود و سپس طبق قوانین زیر به عنوان یک رشته کدگذاری می‌شود.
  • برای یک بایت که مقدار آن در محدوده [0x00, 0x7f] (اعشاری [0, 127]) است، آن بایت رمزگذاری RLP خودش است.
  • در غیر این صورت، اگر یک رشته 0-55 بایت طول داشته باشد، رمزگذاری RLP از یک بایت با مقدار 0x80 (اعشار 128) به اضافه طول رشته و به دنبال آن رشته تشکیل شده است. بنابراین، محدوده اولین بایت [0x80, 0xb7] است (dec. [128, 183]).
  • اگر یک رشته بیش از 55 بایت طول داشته باشد، رمزگذاری RLP شامل یک بایت منفرد با مقدار 0xb7 (اعشار 183) به اضافه طول بر حسب بایت طول رشته به صورت دوتایی است و به دنبال آن طول رشته و به دنبال آن رشته است. به عنوان مثال، یک رشته 1024 بایتی به صورت \xb9\x04\x00 (dec. 185, 4, 0) و به دنبال آن رشته رمزگذاری می‌شود. در اینجا، 0xb9 (183 + 2 = 185) به عنوان اولین بایت، به دنبال آن 2 بایت 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)
نمایش همه
کپی

مثال ها

رمزگشایی 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
نمایش همه
کپی

بیشتر بخوانید

  • درخت مرکل پاتریشیا

آیا این مقاله مفید بود؟