以太坊RLP机制分析
目錄
1 RLP 定義
2 RLP 編碼規(guī)則
3 RLP 編碼實例
4 RLP 分析
?
1 RLP 定義
RLP,即 Recursive Length Prefix, 遞歸長度前綴編碼,是以太坊數(shù)據(jù)序列化的主要方法, 具有較好的數(shù)據(jù)處理效率,尤其是將長度和類型統(tǒng)一作為前綴,實際上 RLP 是基于 ASCII 編碼的一種結(jié)構(gòu)化擴充,既能表示長度還能表示類型,是一種非常緊湊的結(jié)構(gòu)化編碼方案。 該編碼方案用于編碼任意的嵌套結(jié)構(gòu)的二進制數(shù)據(jù),區(qū)塊、交易等數(shù)據(jù)結(jié)構(gòu)在持久化時會先 經(jīng)過 RLP 編碼后再存儲到數(shù)據(jù)庫中。RLP 的唯一目標就是解決結(jié)構(gòu)體的編碼問題;對原子 數(shù)據(jù)類型(比如,字符串,整數(shù)型,浮點型)的編碼則交給更高層的協(xié)議;以太坊中要求數(shù) 字必須是一個大端字節(jié)序的、沒有零占位的存儲的格式(也就是說,一個整數(shù) 0 和一個空數(shù) 組是等同的)。如果要編碼一個字典,推薦使用兩種規(guī)范的編碼格式——一是通過 key 的字 典序來組織字典[[k1,v1],[k2,v2]……],另一種是以太坊中使用的高層的 Patricia Tree。
RLP 編碼的定義只處理兩類數(shù)據(jù):
一類是字符串(例如字節(jié)數(shù)組),即一串二進制數(shù)據(jù)(strings);
一類是列表。即一個嵌套遞歸的結(jié)構(gòu),里面可以包含字符串和列表。
例如:[“cat”,[“puppy”,“cow”],“horse”,[[]],“pig”,[“”],“sheep”]
其他類型的數(shù)據(jù)需要轉(zhuǎn)成以上的兩類,轉(zhuǎn)換的規(guī)則不是 RLP 編碼定義的,可以根據(jù)自己的 規(guī)則轉(zhuǎn)換,例如 struct 可以轉(zhuǎn)成列表,int 可以轉(zhuǎn)成二進制(屬于字符串一類),以太坊中整 數(shù)都以大端形式存儲。
從 RLP 編碼的名字可以看出它的特點:
一是遞歸,被編碼的數(shù)據(jù)是遞歸的結(jié)構(gòu),編碼算法也是遞歸進行處理的;
二是長度前綴,即 RLP 編碼都帶有一個前綴,這個前綴是跟被編碼數(shù)據(jù)的長度相關(guān)的。
?
2 RLP 編碼規(guī)則
規(guī)則一:單字節(jié)值在[0x00,0x7f]之間的,編碼就是自身。需要注意的是 0x7f 這個邊界,因為 ASCII 編碼最大值就是 0x7f(即二進制 1111,1111),也就是說在 0x7f 以內(nèi)完全當(dāng)做 ASCII 編碼使用。
規(guī)則二:如果一個 string 長度在 0-55 之間,編碼結(jié)果的為在 string 開頭加一個字節(jié),這個字 節(jié)的值是 0x80 加上 string 的長度。由于被編碼的字符串最大長度是 55=0x37,因此單字節(jié)前 綴的最大值是 0x80+0x37=0xb7,即編碼的第一個字節(jié)的取值范圍是[0x80, 0xb7]。 (128—183)
(0x80+[string 的長度]) || string
規(guī)則三:如果一個 string 長度超過了 55 個字節(jié),編碼結(jié)果的第 1 個字節(jié)為 0xb7+string 的長度 值(字節(jié)表示)的長度,后跟著string的長度,后跟著string。所以第一個字節(jié)的范圍為[0xb8,0xbf]。
(0xb7+string 長度值的長度) || (string 的長度) || string
比如某個 string 長度為 1024(0x0400),0x0400 的長度為 2,因此第 1 個字節(jié)為前綴應(yīng)該是 0xb7+2=0xb9,后面跟著0x0400,再后面跟著string,即整個RLP編碼應(yīng)該是\xb9\x0400\string。 編碼的第一個字節(jié)即前綴的取值范圍是[0xb8, 0xbf],因為字符串長度二進制形式最少是 1個字節(jié),因此最小值是 0xb7+1=0xb8,字符串長度二進制最大是 8 個字節(jié),因此最大值是 0xb7+8=0xbf。(184—191)
規(guī)則四:如果一個數(shù)組中所有元素的長度之和在 0-55 之間,編碼結(jié)果的第 1 個字節(jié)為 0xc0+ 所有元素的長度,后面跟著列表中各元素的編碼串,因此第 1 個字節(jié)的范圍在[0xc0,0xf7]。 [192—247]
(0xc0+列表元素總長度) || 列表各元素的編碼串
規(guī)則五:如果數(shù)組中所有元素的長度超過 55 個字節(jié),編碼結(jié)果的第 1 個字節(jié)為 0xf7 加上所 有元素長度值(字節(jié)表示)的長度,后跟所有元素長度,后面跟著數(shù)組。第 1 個字節(jié)的范圍是 [0xf8,0xff]。 [248—255]
(0xf7+所有元素長度值的長度) || 列表元素總長度 || 列表各元素的編碼串
?
3 RLP 編碼實例
字符串 “dog” = [0x83, ’d’, ‘o’, ‘g’ ] (規(guī)則二)
列表 [“cat”,“dog”] = [0xc8, 0x83, ‘c’, ‘a(chǎn)’, ’t’, 0x83, ’d’, ‘o’, ‘g’ ] (規(guī)則四)
空字符串 “” = 0x80 (規(guī)則二)
空列表 [] = [0xc0] (規(guī)則四)
整數(shù) 15(‘\x0f’) = 0x0f (規(guī)則一)
整數(shù) 1024(‘\x04\00’) = [0x82, 0x04, 0x00] (規(guī)則二)
列表 [ [], [[]], [ [], [[]] ] ] = [0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0] (規(guī)則四)
字符串 “Lorem ipsum dolor sit amet, consectetur adipisicing elit” = [0xb8, 0x38, ‘L’, ‘o’, ‘r’, ‘e’, ’m’, ‘ ’, … , ‘e’, ‘l’, ‘i’, ’t’](規(guī)則三)
?
4 RLP 分析
RLP 編碼的設(shè)計思想,就是通過首字節(jié)快速判斷一串編碼的類型,充分利用了一個字 節(jié)的存儲空間,將 0x7f 以后的值賦予了新的含義。相比于 Unicode 的對指定長度字節(jié)進行 編碼,處理這些編碼時一般按照指定長度進行拆分解碼,最大的弊端是傳統(tǒng)編碼無法表現(xiàn)一 個結(jié)構(gòu),即列表。RLP 最大的優(yōu)點是在充分利用字節(jié)的情況下,同時支持列表結(jié)構(gòu),也就 是說可以很輕易的利用 RLP 存儲一個樹狀結(jié)構(gòu)。
程序處理 RLP 編碼時也非常容易,根據(jù)首字節(jié)就可以判斷出這段編碼的類型,同時調(diào)用不 同的方法進行解碼,類似于 json 結(jié)構(gòu), RLP 支持嵌套的結(jié)構(gòu),通過遞歸調(diào)用可以將整個 RLP 快速還原成一顆樹,或者轉(zhuǎn)譯成一個 json 結(jié)構(gòu),便于其他程序使用。
RLP 使用首字節(jié)存儲長度的位數(shù),再用后續(xù)的字節(jié)表明整體字符串的長度,根據(jù)規(guī)則二計 算,RLP 可以支持的單個最大字符串長度為 2 的 64 次方,再加上嵌套規(guī)則,理論上 RLP 可 以編碼任何數(shù)據(jù)。
?
原文鏈接:http://wangxiaoming.com/blog/2017/12/28/HPB-39-ETH-RLP/
?
轉(zhuǎn)載于:https://www.cnblogs.com/blockchain/p/9397103.html
總結(jié)
以上是生活随笔為你收集整理的以太坊RLP机制分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我爱都是为你准备的是什么歌啊
- 下一篇: 查看某个存储过程