RLP(轉發注明出處)


@

RLP序列化

RLP:這是一種對任意結構的二進制數據(字節數組)進行編碼的序列化方法

什么是序列化?

序列化將對象的狀態信息轉換為可以存儲或傳輸的形式的過程。在序列化期間,對象將其當前狀態寫入到臨時或持久性存儲區。以后,可以通過從存儲區中讀取或反序列化對象的狀態,重新創建該對象。
序列化機制的核心作用就是對象狀態的保存與重建

為什么要序列化?

1、以某種存儲形式使自定義對象持久化。->便於對象持久化,通過序列化可以把數據永久地保存到硬盤上(通常存放在文件里)
2、將對象從一個地方傳遞到另一個地方。->便於網絡傳輸,利用序列化實現遠程通信,即在網絡上傳送對象的字節序列
3、使程序更具維護性。->便於維護,程序員依照相同的序列化規則,進行序列化及反序列化。

序列化的方法:Json序列化、FastJson序列化、xml序列化..等等,RLP正是序列化方法的一種,以太坊中使用了大量的RLP序列化

RLP序列化處理的兩項數據

區塊、交易等數據結構在持久化時會先經過RLP編碼后再存儲到數據庫中,RLP編碼的定義只處理兩類數據:

  1. 一類是byte數組。
  2. 一類byte數組的數組,稱之為列表。(遞歸定義)
    這里的遞歸定義就比較相似與JSON,可以很容易的表示出一個樹的結構。

RLP序列化采取的5項規則:

  1. 對於值在[0, 127]之間的單個字節,其編碼是其本身。
    例1:a的編碼是97。
  2. 如果byte數組長度l <= 55,編碼的結果是數組本身,再加上128+l作為前綴。
    例2:abc編碼結果是131 97 98 99.其中131=128+len("abc"),97 98 99依次是a b c。
  3. 如果數組長度大於55,編碼結果第一個是183加數組長度的編碼的長度,然后是數組長度的本身的編碼,最后是byte數組的編碼。
    例3:“The length of this sentence is more than 55 bytes, I know it because I pre-designed it” = [183 + 1,86, ‘T’, ‘h’, ‘e’, ‘ ’, ’l’, ‘e’, … , ‘d’, ‘ ’, ‘i’, ’t’]
    這里一定要注意的是:加上的數組長度的編碼,86是數組的長度,86編碼之后占用1個字節(在1到128之間),所以才加上1
  4. 如果列表長度小於55,編碼結果第一位是192加列表長度的編碼的長度,然后依次連接各子列表的編碼。
    例4: ["abc", "def"]的編碼結果是200 131 97 98 99 131 100 101 102。其中abc的編碼為131 97 98 99,def的編碼為131 100 101 102。兩個子字符串的編碼后總長度是8,因此編碼結果第一位計算得出:192 + 8 = 200。
  5. 如果列表長度超過55,編碼結果第一位是247加列表長度的編碼長度,然后是列表長度本身的編碼,最后依次連接各子列表的編碼。
    這里一定要注意的是:加上的是列表長度的編碼長度!類似於規則3

ps:

  • 列表長度是指子列表編碼后的長度之和。
  • 規則1~3定義了byte數組的編碼方案(也就是第一種數據結構)下面介紹列表(第二種數據結構)的編碼規則

現在我們看一個較復雜的例子:

例5:["abc",["The length of this sentence is more than 55 bytes, ", "I know it because I pre-designed it"]]
列表第一項字符串abc根據規則2,編碼結果為131 97 98 99,長度為4。
列表第二項也是一個列表項,根據規則5,編碼結果為
247+1 88 179 84 104 101 32 108 101 110 103 116 104 32 111 102 32 116 104 105 115 32 115 101 110 116 101110 99 101 32 105 115 32 109 111 114 101 32 116 104 97 110 32 53 53 32 98 121 116 101 115 44 32 163 7332 107 110 111 119 32 105 116 32 98 101 99 97 117 115 101 32 73 32 112 114 101 45 100 101 115 105 103110 101 100 32 105 116,長度為90。
因此,整個列表的編碼結果第二位是90 + 4 = 94, 占用1個字節,第一位247 + 1 = 248
最后的結果為:248,94+第一個列表編碼+第二個列表編碼

詳細解釋:
其中前兩個字節的計算方式如下:
248 = 247 +1
為什么加1? 列表長度為90,列表長度的編碼為1(字節)
88 = 86 + 2
為什么加2?
列表長度是指子列表編碼后的長度之和。
兩種看法:
其一可以看為:在規則3的示例中,長度為86,而在此例中,由於有兩個子字符串,每個子字符串本身的長度的編碼各占1字節,因此總共占2字節。
(列表長度本身的編碼)
其二可以看為: 后面的90-2就是88
第3個字節179依據規則2得出179 = 128 + 51
第55個字節163同樣依據規則2得出163 = 128 + 35
(遞歸)因此,整個列表的編碼結果第二位是90 + 4 = 94, 占用1個字節,第一位247 + 1 = 248
最后的結果為:248,94,第一個列表編碼,第二個列表編碼
最后,編碼為:
248 94 131 97 98 99 248 88 179 84 104 101 32 108 101 110 103 116 104 32 111 102 32 116 104 105 115 32 115 101 110 116 101110 99 101 32 105 115 32 109 111 114 101 32 116 104 97 110 32 53 53 32 98 121 116 101 115 44 32 163 7332 107 110 111 119 32 105 116 32 98 101 99 97 117 115 101 32 73 32 112 114 101 45 100 101 115 105 103110 101 100 32 105 116

利用python寫的RLP

def rlp_encode(input):
    if isinstance(input,str):
        if len(input) == 1 and chr(input) < 128: return input    #規則一
        else: return encode_length(len(input),128) + input    #規則二和規則三
    elif isinstance(input,list):
        output = ''
        for item in input: output += rlp_encode(item)       #遞歸的去遍歷
        return encode_length(len(output),192) + output    #規則四和規則五

def encode_length(L,offset):
    if L < 56:
         return chr(L + offset)
    elif L < 256**8:
         BL = to_binary(L)
         return chr(len(BL) + offset + 55) + BL
    else:
         raise Exception("input too long")

def to_binary(x):
    return '' if x == 0 else to_binary(int(x / 256)) + chr(x % 256)

實際中的使用是個怎么樣子?

在具體實現RLP編碼時,首先需要將對像映射成byte數組或列表兩種形式。以go語言編碼struct為例,會將其映射為列表,例如Student這個對象處理成列表["icattlecoder","male"]

實際中的,不同,就是講的沒用16進制表示,正常來講,是16進制表示。

RLP分析

  1. RLP最大的優點是在充分利用字節的情況下,同時支持列表結構,也就是說可以很輕易的利用RLP存儲一個樹狀結構。

以上我們可以看出RLP編碼的設計思想,就是通過首字節快速判斷一串編碼的類型,充分利用了一個字節,兩個字節的存儲空間,將0x7f以后的值賦予了新的含義。

  1. 程序處理RLP編碼時也非常容易。

根據首字節就可以判斷出這段編碼的類型,同時調用不同的方法進行解碼,和JSON編碼類似,支持嵌套的結構,通過遞歸調用可以將整個RLP快速還原成一顆樹,或者轉譯成一個JSON結構,便於其他程序使用

  1. 所以理論上RLP可以編碼任何數據。

RLP使用首字節存儲長度的位數,再用后續的字節表明整體字符串的長度,根據規則二計算,RLP可以支持的單個最大字符串長度為2的64次方,這無疑是個天文數字,再加上嵌套規則.

參考目錄

[1]. RLP編碼和解碼
[2]. 以太坊RLP用法-以太坊源碼學習
[3]. 簡單分析RLP編碼原理
[4]. 以太坊源碼學習—RLP編碼

如果我的工作為您帶來了少許幫助,幫忙點一波關注或者收藏吧~(#.#)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM