這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
前言
RLP(Recursive Length Prefix,遞迴長度首碼)是一種編碼演算法,用於編碼任意的嵌套結構的位元據,它是以太坊中資料序列化/還原序列化的主要方法,區塊、交易等資料結構在持久化時會先經過RLP編碼後再儲存到資料庫中,RLP編碼的定義只處理兩類資料:一類是字串(例如位元組數組),一類是列表。
RLP與JSON的比較
話不多說,直接上代碼
package mainimport ( "encoding/json" "fmt" "rlp")type Pig struct { Name string Gender uint8 Address string}func main() { pig := &Pig{Name: "piggy", Gender: 2, Address: "England"} json_bytes, _ := json.Marshal(pig) fmt.Println(json_bytes) fmt.Println(string(json_bytes)) fmt.Println("length:", len(json_bytes)) //output //[123 34 78 97 109 101 34 58 34 112 105 103 103 121 34 44 34 71 101 110 100 101 114 34 58 50 44 34 65 100 100 114 101 115 115 34 58 34 69 110 103 108 97 110 100 34 125] //{"Name":"piggy","Gender":2,"Address":"England"} //length: 47 rlp_bytes, _ := rlp.EncodeToBytes(pig) fmt.Println(rlp_bytes) fmt.Println("length:", len(rlp_bytes)) //output //[207 133 112 105 103 103 121 2 135 69 110 103 108 97 110 100] //length: 16}
從上面的輸出我們可以看到,同一個結構體,JSON編碼需要47個位元組,而RLP編碼只需要16個位元組,{"Name":"piggy","Gender":2,"Address":"England"}中的Name,Gender,Address都是不需要的。當然JSON編碼也有自己的優點,這裡不展開說明。
定義
RLP 編碼函數接受一個item。定義如下:
- 將一個字串作為一個item(比如,一個 byte 數組)
- 一組item列表(list)作為一個item
例如,一個Null 字元串可以是一個item,一個字串"cat"也可以是一個item,一個含有多個字串的列表也行,列表裡面嵌套列表也可以,比如這樣的["monkey",["tony","kong"],"horse",[[]],"pig",[""],"fish"]。
RLP 編碼定義如下:
| 類型 |
首位元組範圍 |
編碼內容 |
| [0x00, 0x7f]的單個位元組 |
[0x00, 0x7f] |
位元組內容本身 |
| 0-55 位元組長的字串 |
[0x80, 0xb7] |
0x80加上字串長度,後跟字串二進位內容 |
| 超過55個位元組的字串 |
[0xb8, 0xbf] |
0xb7加上字串長度的長度,後跟字串二進位內容 |
| 0-55個位元組長的列表(所有項的組合長度) |
[0xc0, 0xf7] |
0xc0加上所有的項的RLP編碼串聯起來的長度得到的單個位元組,後跟所有的項的RLP編碼的串聯組成。 |
| 列表的內容超過55位元組 |
[0xf8, 0xff] |
0xC0加上所有的項的RLP編碼串聯起來的長度的長度得到的單個位元組,後跟所有的項的RLP編碼串聯起來的長度的長度,再後跟所有的項的RLP編碼的串聯組成 |
例子
- 字串 "pig" = [ 0x83, 'p', 'i', 'g' ]
- 列表 [ "pig", "dog" ] = [ 0xc8, 0x83, 'p', 'i', 'g', 0x83, 'd', 'o', 'g' ]
- Null 字元串 ('null') = [ 0x80 ]
- 空列表 = [ 0xc0 ]
- 數字12 ('x0c') = [ 0x0c ]
- 數字 1024 ('x04x00') = [ 0x82, 0x04, 0x00 ]
- 嵌套列表 [ [], [[]], [ [], [[]] ] ] = [ 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編碼的設計思想,就是通過首位元組快速判斷一串編碼的類型,充分利用了一個位元組的儲存空間,將0x7f以後的值賦予了新的含義,RLP最大的優點是在充分利用位元組的情況下,同時支援列表結構,也就是說可以很輕易的利用RLP儲存一個樹狀結構。
程式處理RLP編碼時也非常容易,根據首位元組就可以判斷出這段編碼的類型,同時調用不同的方法進行解碼,和JSON編碼類別似,支援嵌套的結構,通過遞迴調用可以將整個RLP快速還原成一顆樹,或者轉譯成一個JSON結構,便於其他程式使用。
RLP使用首位元組儲存長度的位元,再用後續的位元組表明整體字串的長度,根據規則二計算,RLP可以支援的單個最大字串長度為2的64次方,這無疑是個天文數字,再加上嵌套規則,所以理論上RLP可以編碼任何資料。