RLP編碼原理

RLP(Recursive Length Prefix,遞歸長度前綴)是一種編碼算法,用於編碼任意的嵌套結構的二進制數據,它是以太坊中數據序列化/反序列化的主要方法,區塊、交易等數據結構在持久化時會先通過RLP編碼後再存儲到數據庫中。git

定義

RLP編碼的定義只處理兩類數據:一類是字符串(例如字節數組),一類是列表。字符串指的是一串二進制數據,列表是一個嵌套遞歸的結構,裏面能夠包含字符串和列表,例如["cat",["puppy","cow"],"horse",[[]],"pig",[""],"sheep"]就是一個複雜的列表。其餘類型的數據須要轉成以上的兩類,轉換的規則不是RLP編碼定義的,能夠根據本身的規則轉換,例如struct能夠轉成列表,int能夠轉成二進制(屬於字符串一類),以太坊中整數都以大端形式存儲。github

從RLP編碼的名字能夠看出它的特色:一個是遞歸,被編碼的數據是遞歸的結構,編碼算法也是遞歸進行處理的;二是長度前綴,也就是RLP編碼都帶有一個前綴,這個前綴是跟被編碼數據的長度相關的,從下面的編碼規則中能夠看出這一點。算法

RLP編碼規則

  • 對於單個字節,若是它的值範圍是[0x00, 0x7f],它的RLP編碼就是它自己。
  • 不然,若是一個字符串的長度是0-55字節,它的RLP編碼包含一個單字節的前綴,後面跟着字符串自己,這個前綴的值是**0x80**加上字符串的長度。因爲被編碼的字符串最大長度是55=0x37,所以單字節前綴的最大值是0x80+0x37=0xb7,即編碼的第一個字節的取值範圍是[0x80, 0xb7]
  • 若是字符串的長度大於55個字節,它的RLP編碼包含一個單字節的前綴,後面跟着字符串的長度,後面再跟着字符串自己。這個前綴的值是**0xb7**加上字符串長度的二進制形式的字節長度,說的有點繞,舉個例子就明白了,例如一個字符串的長度是1024,它的二進制形式是10000000000,這個二進制形式的長度是2個字節,因此前綴應該是0xb7+2=0xb9,字符串長度1024=0x400,所以整個RLP編碼應該是\xb9\x04\x00再跟上字符串自己。編碼的第一個字節即前綴的取值範圍是[0xb8, 0xbf],由於字符串長度二進制形式最少是1個字節,所以最小值是0xb7+1=0xb8,字符串長度二進制最大是8個字節,所以最大值是0xb7+8=0xbf
  • 若是一個列表的總長度(列表的總長度指的是它包含的項的數量加它包含的各項的長度之和)是0-55字節,它的RLP編碼包含一個單字節的前綴,後面跟着列表中各元素項的RLP編碼,這個前綴的值是**0xc0**加上列表的總長度。編碼的第一個字節的取值範圍是[0xc0, 0xf7]
  • 若是一個列表的總長度大於55字節,它的RLP編碼包含一個單字節的前綴,後面跟着列表的長度,後面再跟着列表中各元素項的RLP編碼,這個前綴的值是**0xf7**加上列表總長度的二進制形式的字節長度。編碼的第一個字節的取值範圍是[0xf8, 0xff]

RLP編碼例子

  • 字符串 "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數組

相關文章
相關標籤/搜索