以太坊:底層序列化編碼方式RLP


轉載請注明出處:https://www.cnblogs.com/zhizaixingzou/p/10122380.html

 

目錄

 

1. RLP以太坊底層序列化編碼方式

1.1. 簡介

https://segmentfault.com/a/1190000011763339

https://github.com/ethereum/wiki/wiki/RLP

RLPRecursive Length Prefix,遞歸長度前綴。它是以太坊底層序列化采用的編碼方式。RLP主要用於以太坊中數據的網絡傳輸和持久化存儲。它的設計目的就是編碼任意嵌套的二進制數組或列表。

 

序列化對象的編碼方式有很多種,為什么還要重復發明輪子呢?常見的JSON編碼,有個明顯的缺點,就是引入了太多冗余信息編碼結果比較大。而其他的編碼方式,要么不為以太坊設計者所知,要么看起來都不如自己設計的編碼來的合適。

1.2. 原理

RLP編碼只對3種數據類型編碼:

類型1值在[0127]之間的單個字節。使用下面的規則1

類型2字節數組(元素數可為0)。使用下面的規則2和規則3

類型3列表(列表是以數組或列表為元素的數組,元素數不可為0)。使用下面的規則4和規則5

 

RLP編碼的編碼規則:

規則1對於值在[0127]之間的單個字節,其編碼是字節自身。

9->9

 規則2對於長度len<=55的字節數組,其編碼是128+len,緊接着字節數組自身。

[9]->[129,9]

len=1
129=128+len

規則3對於長度len>55的字節數組,其編碼是183+len編碼的長度,緊接着len的編碼,緊接着字節數組自身。len的大小不能超過8字節能表示的值。

[97,97,...,97]->[185,4,0,97,97,...,97]

len=1024
[4,0]=len的編碼(編碼涉及多字節的數值表示時,使用大端模式)
185=183+[4,0]的長度

 規則4如果列表長度len<=55其編碼是192+len緊接着各子列表的編碼。列表長度是指子列表編碼后的長度之和。這是遞歸定義。

[[97,98,99],[100,101,102]]->[200,131,97,98,99,131,100,101,102]

131=128+3
200=192+4+4

規則5如果列表長度len>55,其編碼是247+len的編碼的長度,緊接着len的編碼,緊接着各子列表的編碼。len的大小不能超過8字節能表示的值。這是遞歸定義。

["The length of this sentence is more than 55 bytes, ", "I know it because I pre-designed it"]->[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 101 110 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 73 32 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 103 110 101 100 32 105 116]

179 = 128 + 51
163 = 128 + 35
88 = 51+35 + 2
248 = 247 +1

 

從編碼規則可以看出:編碼的結果是一個字節數組。編碼結果的長度不能超過8字節能表示的值,也就是264次方,2ZB的數據,這是很大的數據了。

 

各種程序設計語言在實現RLP編碼時,需要首先將對象轉換為3種數據類型中的一種具體怎么轉換則自己定義。

 

RLP編碼的解碼規則是編碼規則的逆運算。首先根據編碼結果的第一個字節f,執行以下的規則判斷:

判斷1如果f[0127],那么反序列化后是一個字節,就是f

判斷2如果f[128183],那么反序列化后是一個長度len<=55的字節數組,字節數組的長度為len=f-128

判斷3如果f[184192],那么反序列化后是一個長度len>55的字節數組,字節數組長度的編碼的長度lenOfLen=f-183,然后從第二個字節開始讀取lenOfLen個字節,按照大端模式轉換成整數lenlen即為字節數組的長度。

判斷4如果f[193247],那么反序列化后是一個編碼后長度len<=55的列表,列表長度為len=f-192。遞歸使用判斷1~4進行解碼。

判斷5如果f[247255],那么反序列化后是編碼后長度len>55的列表,列表長度的編碼的長度lenOfLen=f-247,然后從第二個字節開始讀取lenOfLen個字節,按照大端模式轉換成整數lenlen即為子列表總長度。然后遞歸使用判斷1~5進行解碼。

 

可以看到,接收到編碼的數據1)就能根據第一個字節推斷出數據的類型2)並且最多再讀幾個字節就能知道數據的大小,這就解釋了“長度前綴”的意義。加之解碼時使用了遞歸算法,因而此編碼方式就叫遞歸長度前綴編碼。

1.3. 源碼實現

源代碼見:org.ethereum.util.RLP

 

源碼實現與原理描述有兩點稍有不同:

1)實際上不只提供了3種數據類型,但其他類型都轉換成這3種后才編碼,且每種類型都對應了編碼和解密方法。也就是說,收方知道收到的數據是用什么方法編碼的,它會調用對應的方法解密。

2)實際使用的規則可能稍有出入,也更瑣碎些。

 


免責聲明!

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



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