RLP(Recursive Length Prefix,遞歸長度前綴)是一種編碼算法,用於編碼任意的嵌套結構的二進制數據,它是以太坊中數據序列化/反序列化的主要方法,區塊、交易等數據結構在持久化時會先通過RLP編碼後再存儲到數據庫中。git
RLP編碼的定義只處理兩類數據:一類是字符串(例如字節數組),一類是列表。字符串指的是一串二進制數據,列表是一個嵌套遞歸的結構,裏面能夠包含字符串和列表,例如["cat",["puppy","cow"],"horse",[[]],"pig",[""],"sheep"]
就是一個複雜的列表。其餘類型的數據須要轉成以上的兩類,轉換的規則不是RLP編碼定義的,能夠根據本身的規則轉換,例如struct
能夠轉成列表,int
能夠轉成二進制(屬於字符串一類),以太坊中整數都以大端形式存儲。github
從RLP編碼的名字能夠看出它的特色:一個是遞歸,被編碼的數據是遞歸的結構,編碼算法也是遞歸進行處理的;二是長度前綴,也就是RLP編碼都帶有一個前綴,這個前綴是跟被編碼數據的長度相關的,從下面的編碼規則中能夠看出這一點。算法
[0x00, 0x7f]
,它的RLP編碼就是它自己。0x80
**加上字符串的長度。因爲被編碼的字符串最大長度是55=0x37
,所以單字節前綴的最大值是0x80+0x37=0xb7
,即編碼的第一個字節的取值範圍是[0x80, 0xb7]
。0xb7
**加上字符串長度的二進制形式的字節長度,說的有點繞,舉個例子就明白了,例如一個字符串的長度是1024,它的二進制形式是10000000000
,這個二進制形式的長度是2個字節,因此前綴應該是0xb7+2=0xb9
,字符串長度1024=0x400
,所以整個RLP編碼應該是\xb9\x04\x00
再跟上字符串自己。編碼的第一個字節即前綴的取值範圍是[0xb8, 0xbf]
,由於字符串長度二進制形式最少是1個字節,所以最小值是0xb7+1=0xb8
,字符串長度二進制最大是8個字節,所以最大值是0xb7+8=0xbf
。0xc0
**加上列表的總長度。編碼的第一個字節的取值範圍是[0xc0, 0xf7]
。0xf7
**加上列表總長度的二進制形式的字節長度。編碼的第一個字節的取值範圍是[0xf8, 0xff]
。"dog" = [0x83, 'd', 'o', 'g' ]
(規則二)["cat","dog"] = [0xc8, 0x83, 'c', 'a', 't', 0x83, 'd', 'o', 'g' ]
(規則四)"" = 0x80
(規則二)[] = [0xc0]
(規則四)15('\x0f') = 0x0f
(規則一)1024('\x04\00') = [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']
(規則三)本文大部分翻譯自以太坊github wiki文檔,並加入本身的理解。數據庫
參考資料:https://github.com/ethereum/wiki/wiki/%5BEnglish%5D-RLP數組