রিকার্সিভ-লেংথ প্রিফিক্স (RLP) সিরিয়ালাইজেশন
পেজ সর্বশেষ আপডেট: ১৪ মার্চ, ২০২৬
রিকার্সিভ লেংথ প্রিফিক্স (RLP) সিরিয়ালাইজেশন ইথিরিয়ামের এক্সিকিউশন ক্লায়েন্টগুলোতে ব্যাপকভাবে ব্যবহৃত হয়। RLP একটি স্পেস-এফিশিয়েন্ট ফরম্যাটে নোডগুলোর মধ্যে ডাটা ট্রান্সফারকে স্ট্যান্ডার্ডাইজ করে। RLP-এর উদ্দেশ্য হলো বাইনারি ডাটার আরবিট্রারি নেস্টেড অ্যারেগুলোকে এনকোড করা, এবং ইথিরিয়ামের এক্সিকিউশন লেয়ারে অবজেক্টগুলোকে সিরিয়ালাইজ করার জন্য ব্যবহৃত প্রাথমিক এনকোডিং পদ্ধতি হলো RLP। RLP-এর মূল উদ্দেশ্য হলো স্ট্রাকচার এনকোড করা; পজিটিভ ইন্টিজার বা ধনাত্মক পূর্ণসংখ্যা ছাড়া, RLP নির্দিষ্ট ডাটা টাইপ (যেমন, স্ট্রিং, ফ্লোট) এনকোড করার দায়িত্ব হায়ার-অর্ডার প্রটোকলগুলোর ওপর ছেড়ে দেয়। পজিটিভ ইন্টিজারগুলোকে অবশ্যই কোনো লিডিং জিরো ছাড়া বিগ-এন্ডিয়ান বাইনারি ফর্মে উপস্থাপন করতে হবে (যার ফলে শূন্য মানের ইন্টিজারটি এম্পটি বাইট অ্যারের সমতুল্য হয়)। লিডিং জিরোসহ ডিসিরিয়ালাইজ করা পজিটিভ ইন্টিজারগুলোকে RLP ব্যবহারকারী যেকোনো হায়ার-অর্ডার প্রটোকল দ্বারা ইনভ্যালিড হিসেবে বিবেচনা করতে হবে।
আরও তথ্য ইথিরিয়াম ইয়েলো পেপারে (পরিশিষ্ট B) (opens in a new tab) পাওয়া যাবে।
একটি ডিকশনারি এনকোড করতে RLP ব্যবহার করার জন্য, প্রস্তাবিত দুটি ক্যানোনিকাল ফর্ম হলো:
- লেক্সিকোগ্রাফিক অর্ডারে কিসমূহসহ
[[k1,v1],[k2,v2]...]ব্যবহার করুন - Ethereum এর মতো হায়ার-লেভেল প্যাট্রিসিয়া ট্রি এনকোডিং ব্যবহার করুন
সংজ্ঞা
RLP এনকোডিং ফাংশন একটি আইটেম গ্রহণ করে। একটি আইটেমকে নিম্নরূপ সংজ্ঞায়িত করা হয়:
- একটি স্ট্রিং (অর্থাৎ, বাইট অ্যারে) হলো একটি আইটেম
- আইটেমগুলোর একটি তালিকা হলো একটি আইটেম
- একটি পজিটিভ ইন্টিজার হলো একটি আইটেম
উদাহরণস্বরূপ, নিচের সবগুলোই আইটেম:
- একটি এম্পটি স্ট্রিং;
- "cat" শব্দটি ধারণকারী স্ট্রিং;
- যেকোনো সংখ্যক স্ট্রিং ধারণকারী একটি তালিকা;
- এবং আরও জটিল ডাটা স্ট্রাকচার যেমন
["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), যার পরে 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]) হয়।
সংক্ষেপে:
| রেঞ্জ | বাইট 1 | বাইট 2 | ... | বাইট 9 | বাইট 10 | অর্থ |
|---|---|---|---|---|---|---|
0x00-0x7f | 0ppppppp | সিঙ্গেল বাইট স্ট্রিং | ||||
0x80-0xb7 | 10nnnnnn | pppppppp | ... | ছোট স্ট্রিং (0-55 বাইট) | ||
0xb8-0xbf | 10111NNN | nnnnnnnn | ... | nnnnnnnn/pppppppp | pppppppp | বড় স্ট্রিং, দৈর্ঘ্যের জন্য N+1 বাইট, তারপর পেলোড |
0xc0-0xf7 | 11nnnnnn | pppppppp | ... | ছোট তালিকা (0-55 বাইট) | ||
0xf8-0xff | 11111NNN | nnnnnnnn | ... | nnnnnnnn/pppppppp | pppppppp | বড় তালিকা, দৈর্ঘ্যের জন্য N+1 বাইট, তারপর পেলোড |
p= পেলোডn= দৈর্ঘ্য (পেলোড বাইটের সংখ্যা)N= দৈর্ঘ্যের-দৈর্ঘ্য অফসেট (N+1nবাইট অনুসরণ করে)
কোডে, এটি হলো:
1def rlp_encode(input):2 if isinstance(input,str):3 if len(input) == 1 and ord(input) < 0x80:4 return input5 return encode_length(len(input), 0x80) + input6 elif isinstance(input, list):7 output = ''8 for item in input:9 output += rlp_encode(item)10 return encode_length(len(output), 0xc0) + output1112def 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) + BL18 raise Exception("input too long")1920def 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 ডিকোডিং প্রক্রিয়াটি নিম্নরূপ:
-
ইনপুট ডাটার প্রথম বাইট (অর্থাৎ, প্রিফিক্স) এবং ডাটা টাইপ ডিকোডিং অনুযায়ী, আসল ডাটার দৈর্ঘ্য এবং অফসেট;
-
ডাটার ধরন এবং অফসেট অনুযায়ী, পজিটিভ ইন্টিজারের জন্য মিনিমাল এনকোডিং নিয়ম মেনে ডাটাটি ডিকোড করা;
-
ইনপুটের বাকি অংশ ডিকোড করা চালিয়ে যাওয়া;
এর মধ্যে, ডাটা টাইপ এবং অফসেট ডিকোড করার নিয়মগুলো নিম্নরূপ:
-
যদি প্রথম বাইটের (অর্থাৎ, প্রিফিক্স) রেঞ্জ [0x00, 0x7f] হয় তবে ডাটাটি একটি স্ট্রিং, এবং স্ট্রিংটি হুবহু প্রথম বাইট নিজেই;
-
যদি প্রথম বাইটের রেঞ্জ [0x80, 0xb7] হয় তবে ডাটাটি একটি স্ট্রিং, এবং প্রথম বাইট থেকে 0x80 বিয়োগ করলে যে দৈর্ঘ্য পাওয়া যায় সেই দৈর্ঘ্যের স্ট্রিংটি প্রথম বাইটকে অনুসরণ করে;
-
যদি প্রথম বাইটের রেঞ্জ [0xb8, 0xbf] হয় তবে ডাটাটি একটি স্ট্রিং, এবং প্রথম বাইট থেকে 0xb7 বিয়োগ করলে বাইটে যে দৈর্ঘ্য পাওয়া যায় সেই দৈর্ঘ্যের স্ট্রিংয়ের দৈর্ঘ্য প্রথম বাইটকে অনুসরণ করে, এবং স্ট্রিংটি স্ট্রিংয়ের দৈর্ঘ্যকে অনুসরণ করে;
-
যদি প্রথম বাইটের রেঞ্জ [0xc0, 0xf7] হয় তবে ডাটাটি একটি তালিকা, এবং তালিকার সমস্ত আইটেমের RLP এনকোডিংয়ের কনক্যাটেনেশন যার মোট পেলোড প্রথম বাইট থেকে 0xc0 বিয়োগফলের সমান তা প্রথম বাইটকে অনুসরণ করে;
-
যদি প্রথম বাইটের রেঞ্জ [0xf8, 0xff] হয় তবে ডাটাটি একটি তালিকা, এবং তালিকার মোট পেলোড যার দৈর্ঘ্য প্রথম বাইট থেকে 0xf7 বিয়োগফলের সমান তা প্রথম বাইটকে অনুসরণ করে, এবং তালিকার সমস্ত আইটেমের RLP এনকোডিংয়ের কনক্যাটেনেশন তালিকার মোট পেলোডকে অনুসরণ করে;
কোডে, এটি হলো:
1def rlp_decode(input):2 if len(input) == 0:3 return4 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 output1213def 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 - 0x8022 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 - 0xb725 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 - 0xf732 listLen = to_integer(substr(input, 1, lenOfListLen))33 return (1 + lenOfListLen, listLen, list)34 raise Exception("input does not conform to RLP encoding form")3536def 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সব দেখানআরও পড়ুন
- ইথিরিয়ামে RLP (opens in a new tab)
- ইথিরিয়াম আন্ডার দ্য হুড: RLP (opens in a new tab)
- Coglio, A. (2020). Ethereum's Recursive Length Prefix in ACL2. arXiv preprint arXiv:2009.13769. (opens in a new tab)