RLP編碼
RLP編碼是以太坊對象序列化和反序列化的主要方法,可編碼任意嵌套的二進制數(shù)據(jù)。以太坊中多個地方都用到了RLP編碼,例如區(qū)塊,交易等。
RLP是 Recursive Length Prefix 三個單詞的縮寫,分別是遞歸,長度,前綴。以下是我的理解:遞歸指可以處理嵌套的數(shù)據(jù)結構,長度指編碼是對數(shù)據(jù)的長度進行處理,前綴指編碼結果是在數(shù)據(jù)前加一個前綴。
0.索引
01.為什么要使用RLP編碼
02.RLP編碼規(guī)則
03.總結
1.為什么要使用RLP編碼
使用RLP編碼的情況下,需要保存的額外數(shù)據(jù)比較少。RLP編碼結果的前綴不會超過9個字節(jié),舉個例子:
type Tests struct{
Name string
}
t := Tests{Name:"abc"}
- 1.采用JSON編碼,
t的編碼結果為{"Name":"abc"},長度為14個字節(jié)。 - 2.采用RLP編碼,
t的編碼結果為0x83616263,直觀的表示為131 a b c,長度為4個字節(jié)。
t的有效的數(shù)據(jù)長度為3個字節(jié),采用JSON編碼的時候,額外的數(shù)據(jù)長度為11個字節(jié),而采用RLP編碼的時候,額外的數(shù)據(jù)長度為1個字節(jié)(即前綴)。由此可見,RLP編碼可以節(jié)省編碼后的數(shù)據(jù)的存儲空間,這對以太坊來說是很必要的,區(qū)塊和交易編碼后的長度跟原來的長度相差不大,節(jié)省了存儲空間的開銷。
2.RLP編碼規(guī)則
在以太坊的黃皮書附錄B中,定義了如下的兩種數(shù)據(jù)結構:

簡單的理解為,L為列表類型的數(shù)據(jù),B為字節(jié)數(shù)組,字符串類型的數(shù)據(jù)。如果是其他的數(shù)據(jù)類型,則需要先轉換為這兩種數(shù)據(jù)類型,比如說,結構體轉換為嵌套的列表,布爾類型轉換為整型。對此兩種數(shù)據(jù)類型的RLP編碼表示為:

RLP編碼的規(guī)則一共有5個,3個對于字節(jié)數(shù)組而言,剩下2個與列表有關。
字節(jié)數(shù)組

Rb(x)涉及了3個規(guī)則:
- 1.單個字節(jié),小于128,結果為該字節(jié)
- 2.字節(jié)數(shù)組,長度小于56,結果為128+字節(jié)數(shù)組長度,各個字節(jié)的編碼兩部分
- 3.字節(jié)數(shù)組,長度大于等于56,結果為183+字節(jié)數(shù)組長度編碼的長度,字節(jié)數(shù)組長度,各個字節(jié)的編碼三部分 (長度不能超過288)
舉個例子:
- 1.單個字節(jié):z => “7A”
(z的十六進制ascii碼為7A) - 2.長度小于56的字節(jié)數(shù)組:xyz => “8378797A”
(83為128+3的十六進制表示,xyz分別為78 79 7A) - 3.長度大于等于56的字節(jié)數(shù)組:“Lorem ipsum dolor sit amet, consectetur adipisicing elit” =>“B8384C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E7365637465747572206164697069736963696E6720656C6974”
(B8為183+1,1為字節(jié)數(shù)組長度56的編碼長度;38為字節(jié)數(shù)組長度56十六進制;其余為各個字節(jié)的編碼)
BE(x),去掉前導零的大端表示 (bn是8個字節(jié)的,所以以8個字節(jié)為例)
例如:1024 -> 0x00 00 00 00 00 00 04 00 -> 0x0400
(a)·(b,c)·(d,e) = (a,b,c,d,e),指的是字節(jié)的拼接,類似于把字符串連接起來。
列表

Rl(x)涉及了2個規(guī)則:
- 1.列表,長度小于56,結果為192+列表長度,各個字節(jié)的編碼兩部分
- 2.列表,長度大于等于56,結果為247+列表長度編碼的長度,列表長度,各個子列表的編碼三部分
舉個例子:
- 1.長度小于56的列表:[ 1, 2, 3] => “C3010203”
(C3為192+3的十六進制表示) - 2.長度大于等于56的列表:["aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk", "lll", "mmm", "nnn", "ooo“] =>“F83C836161618362626283636363836464648365656583666666836767678368686883696969836A6A6A836B6B6B836C6C6C836D6D6D836E6E6E836F6F6F”
(F8為247+1,1為總的列表長度60的編碼長度;3C為60十六進制表示;bbb為一個子列表83626262,80+3,以及b為62)
3.總結
- 1.RLP編碼是以太坊對象序列化和反序列化的主要方法,對數(shù)據(jù)進行編碼,編碼結果為在原本的數(shù)據(jù)前增加一個前綴??晒?jié)省編碼后的數(shù)據(jù)的存儲空間。
- 2.RLP編碼有5個規(guī)則,3個規(guī)則適用于字節(jié)數(shù)組,2個規(guī)則適用于列表。根據(jù)字節(jié)數(shù)組和列表的不同長度使用不同的編碼規(guī)則。