摘要:,中文翻譯過(guò)來(lái)叫遞歸長(zhǎng)度前綴編碼,它是以太坊序列化所采用的編碼方式。所以,以太坊需要設(shè)計(jì)一種結(jié)果更小的編碼方法。例編碼結(jié)果是,其中,依次是。以上解釋了什么叫遞歸長(zhǎng)度前綴編碼,這個(gè)名字本身很好的解釋了編碼規(guī)則。
為什么又要造輪子RLP(Recursive Length Prefix),中文翻譯過(guò)來(lái)叫遞歸長(zhǎng)度前綴編碼,它是以太坊序列化所采用的編碼方式。RLP主要用于以太坊中數(shù)據(jù)的網(wǎng)絡(luò)傳輸和持久化存儲(chǔ)。
對(duì)象序列化方法有很多種,常見(jiàn)的像JSON編碼,但是JSON有個(gè)明顯的缺點(diǎn):編碼結(jié)果比較大。例如有如下的結(jié)構(gòu):
type Student struct{ Name string `json:"name"` Sex string `json:"sex"` } s := Student{Name:"icattlecoder",Sex:"male"} bs,_ := json.Marsal(&s) print(string(bs)) // {"name":"icattlecoder","sex":"male"}
變量s序列化的結(jié)果是{"name":"icattlecoder","sex":"male"},字符串長(zhǎng)度35,實(shí)際有效數(shù)據(jù)是icattlecoder 和male,共計(jì)16個(gè)字節(jié),我們可以看到JSON的序列化時(shí)引入了太多的冗余信息。假設(shè)以太坊采用JSON來(lái)序列化,那么本來(lái)50GB的區(qū)塊鏈可能現(xiàn)在就要100GB,當(dāng)然實(shí)際沒(méi)這么簡(jiǎn)單。
所以,以太坊需要設(shè)計(jì)一種結(jié)果更小的編碼方法。
RLP編碼定義RLP實(shí)際只給以下兩種類型數(shù)據(jù)編碼:
1. byte數(shù)組
2. byte數(shù)組的數(shù)組,稱之為列表
規(guī)則1:對(duì)于值在[0, 127]之間的單個(gè)字節(jié),其編碼是其本身。
例1:a的編碼是97。
規(guī)則2:如果byte數(shù)組長(zhǎng)度l <= 55,編碼的結(jié)果是數(shù)組本身,再加上128+l作為前綴。
例2:空字符串編碼是128,即128 = 128 + 0。
例3:abc編碼結(jié)果是131 97 98 99,其中131=128+len("abc"),97 98 99依次是a b c。
規(guī)則3:如果數(shù)組長(zhǎng)度大于55, 編碼結(jié)果第一個(gè)是183加數(shù)組長(zhǎng)度的編碼的長(zhǎng)度,然后是數(shù)組長(zhǎng)度的本身的編碼,最后是byte數(shù)組的編碼。
請(qǐng)把上面的規(guī)則多讀幾篇,特別是數(shù)組長(zhǎng)度的編碼的長(zhǎng)度。
例4:編碼下面這段字符串:
The length of this sentence is more than 55 bytes, I know it because I pre-designed it
這段字符串共86個(gè)字節(jié),而86的編碼只需要一個(gè)字節(jié),那就是它自己,因此,編碼的結(jié)果如下:
184 86 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 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
其中前三個(gè)字節(jié)的計(jì)算方式如下:
184 = 183 + 1,因?yàn)閿?shù)組長(zhǎng)度86編碼后僅占用一個(gè)字節(jié)。
86即數(shù)組長(zhǎng)度86
84是T的編碼
例5:編碼一個(gè)重復(fù)1024次"a"的字符串,其結(jié)果為:185 4 0 97 97 97 97 97 97 ...。
1024按 big endian編碼為0 0 4 0,省略掉前面的零,長(zhǎng)度為2,因此185 = 183 + 2。
規(guī)則1~3定義了byte數(shù)組的編碼方案,下面介紹列表的編碼規(guī)則。在此之前,我們先定義列表長(zhǎng)度是指子列表編碼后的長(zhǎng)度之和。
規(guī)則4:如果列表長(zhǎng)度小于55,編碼結(jié)果第一位是192加列表長(zhǎng)度的編碼的長(zhǎng)度,然后依次連接各子列表的編碼。
注意規(guī)則4本身是遞歸定義的。
例6:["abc", "def"]的編碼結(jié)果是200 131 97 98 99 131 100 101 102。
其中abc的編碼為131 97 98 99,def的編碼為131 100 101 102。兩個(gè)子字符串的編碼后總長(zhǎng)度是8,因此編碼結(jié)果第一位計(jì)算得出:192 + 8 = 200。
規(guī)則5:如果列表長(zhǎng)度超過(guò)55,編碼結(jié)果第一位是247加列表長(zhǎng)度的編碼長(zhǎng)度,然后是列表長(zhǎng)度本身的編碼,最后依次連接各子列表的編碼。
規(guī)則5本身也是遞歸定義的,和規(guī)則3相似。
例7:
["The length of this sentence is more than 55 bytes, ", "I know it because I pre-designed it"]
的編碼結(jié)果是:
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
其中前兩個(gè)字節(jié)的計(jì)算方式如下:
248 = 247 +1
88 = 86 + 2,在規(guī)則3的示例中,長(zhǎng)度為86,而在此例中,由于有兩個(gè)子字符串,每個(gè)子字符串本身的長(zhǎng)度的編碼各占1字節(jié),因此總共占2字節(jié)。
第3個(gè)字節(jié)179依據(jù)規(guī)則2得出179 = 128 + 51
第55個(gè)字節(jié)163同樣依據(jù)規(guī)則2得出163 = 128 + 35
例8:最后我們?cè)賮?lái)看個(gè)稍復(fù)雜點(diǎn)的例子以加深理解遞歸長(zhǎng)度前綴,
["abc",["The length of this sentence is more than 55 bytes, ", "I know it because I pre-designed it"]]
編碼結(jié)果是:
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 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
列表第一項(xiàng)字符串abc根據(jù)規(guī)則2,編碼結(jié)果為131 97 98 99,長(zhǎng)度為4。
列表第二項(xiàng)也是一個(gè)列表項(xiàng):
["The length of this sentence is more than 55 bytes, ", "I know it because I pre-designed it"]
根據(jù)規(guī)則5,結(jié)果為
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
長(zhǎng)度為90,因此,整個(gè)列表的編碼結(jié)果第二位是90 + 4 = 94, 占用1個(gè)字節(jié),第一位247 + 1 = 248
以上5條就是RPL的全部編碼規(guī)則。
語(yǔ)言實(shí)現(xiàn)各語(yǔ)言在具體實(shí)現(xiàn)RLP編碼時(shí),首先需要將對(duì)像映射成byte數(shù)組或列表兩種形式。以go語(yǔ)言編碼struct為例,會(huì)將其映射為列表,例如Student這個(gè)對(duì)象處理成列表["icattlecoder","male"]
type Student struct{ Name string Sex string } s := Student{Name:"icattlecoder",Sex:"male"} buff := bytes.Buffer{} rpl.Encode(&buff, &s) print(buff.Bytes()) // [210 140 105 99 97 116 116 108 101 99 111 100 101 114 132 109 97 108 101]
如果編碼map類型,可以采用以下列表形式:
[["",""],["",""],["",""]]RLP解碼
解碼時(shí),首先根據(jù)編碼結(jié)果第一個(gè)字節(jié)f的大小,執(zhí)行以下的規(guī)則判斷:
1. 如果f∈ [0,128), 那么它是一個(gè)字節(jié)本身。
2. 如果f∈[128,184),那么它是一個(gè)長(zhǎng)度不超過(guò)55的byte數(shù)組,數(shù)組的長(zhǎng)度為 l=f-128
3. 如果f∈[184,192),那么它是一個(gè)長(zhǎng)度超過(guò)55的數(shù)組,長(zhǎng)度本身的編碼長(zhǎng)度ll=f-183,然后從第二個(gè)字節(jié)開(kāi)始讀取長(zhǎng)度為ll的bytes,按照BigEndian編碼成整數(shù)l,l即為數(shù)組的長(zhǎng)度。
4. 如果f∈(192,247],那么它是一個(gè)編碼后總長(zhǎng)度不超過(guò)55的列表,列表長(zhǎng)度為l=f-192。遞歸使用規(guī)則1~4進(jìn)行解碼。
5. 如果f∈(247,256],那么它是編碼后長(zhǎng)度大于55的列表,其長(zhǎng)度本身的編碼長(zhǎng)度ll=f-247,然后從第二個(gè)字節(jié)讀取長(zhǎng)度為ll的bytes,按BigEndian編碼成整數(shù)l,l即為子列表長(zhǎng)度。然后遞歸根據(jù)解碼規(guī)則進(jìn)行解碼。
以上解釋了什么叫遞歸長(zhǎng)度前綴編碼,這個(gè)名字本身很好的解釋了編碼規(guī)則。
參考
https://github.com/ethereum/w...
http://hidskes.com/blog/2014/...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/23941.html
摘要:,遞歸長(zhǎng)度前綴編碼,它是以太坊序列化所采用的序列化和反序列化的主要方式。其中的編碼為的編碼為。兩個(gè)子字符串的編碼后總長(zhǎng)度是,因此編碼結(jié)果第一位計(jì)算得出。上面就是的編碼定義,下面開(kāi)始我們來(lái)看一下以太坊中的實(shí)現(xiàn)源碼。 RLP(Recursive Length Prefix),遞歸長(zhǎng)度前綴編碼,它是以太坊序列化所采用的序列化和反序列化的主要方式。區(qū)塊、交易等數(shù)據(jù)結(jié)構(gòu)在 網(wǎng)絡(luò)傳輸和持久化時(shí)會(huì)先...
摘要:是以太坊中存儲(chǔ)區(qū)塊數(shù)據(jù)的核心數(shù)據(jù)結(jié)構(gòu),它和融合一個(gè)樹(shù)形結(jié)構(gòu),理解結(jié)構(gòu)對(duì)之后學(xué)習(xí)以太坊區(qū)塊以及智能合約狀態(tài)存儲(chǔ)結(jié)構(gòu)的模塊源碼很有幫助。 MPT(Merkle Patricia Tries)是以太坊中存儲(chǔ)區(qū)塊數(shù)據(jù)的核心數(shù)據(jù)結(jié)構(gòu),它Merkle Tree和Patricia Tree融合一個(gè)樹(shù)形結(jié)構(gòu),理解MPT結(jié)構(gòu)對(duì)之后學(xué)習(xí)以太坊區(qū)塊header以及智能合約狀態(tài)存儲(chǔ)結(jié)構(gòu)的模塊源碼很有幫助。 首...
摘要:是以太坊存儲(chǔ)數(shù)據(jù)的核心數(shù)據(jù)結(jié)構(gòu),它是由和結(jié)合的一種樹(shù)形結(jié)構(gòu),理解有助于我們更好的理解以太坊的數(shù)據(jù)存儲(chǔ)。所以就有了樹(shù)壓縮前綴樹(shù),后面會(huì)介紹到,也被稱為,中文名稱默克爾樹(shù),主要用于數(shù)據(jù)集較大時(shí)的文件校驗(yàn)。 ??MPT(Merkle Patricia Tries)是以太坊存儲(chǔ)數(shù)據(jù)的核心數(shù)據(jù)結(jié)構(gòu),它是由Merkle Tree和Patricia Tree結(jié)合的一種樹(shù)形結(jié)構(gòu),理解MPT有助于我們更...
摘要:改標(biāo)準(zhǔn)試圖拓展以太坊的簽名規(guī)則,為簽名內(nèi)容的可讀化提供的重要的基礎(chǔ)。摘要這個(gè)提議了一個(gè)關(guān)于如何在以太坊合約中處理簽名數(shù)據(jù)的詳細(xì)說(shuō)明。如果對(duì)沒(méi)有句法約束,這就意味著可以用作句法有效的交易。 本文翻譯了官網(wǎng)EIP-191的相關(guān)內(nèi)容。改標(biāo)準(zhǔn)試圖拓展以太坊的簽名規(guī)則,為簽名內(nèi)容的可讀化提供的重要的基礎(chǔ)。 摘要 這個(gè)ERC提議了一個(gè)關(guān)于如何在以太坊合約中處理簽名數(shù)據(jù)的詳細(xì)說(shuō)明。 動(dòng)機(jī) 一些接受p...
摘要:有效的數(shù)字簽名使收件人有理由相信該信息是由已知的發(fā)件人認(rèn)證創(chuàng)建的,發(fā)件人不能否認(rèn)已發(fā)送的信息不可否認(rèn),并且信息在傳輸過(guò)程中未被更改完整性。當(dāng)我們說(shuō)簽署交易時(shí),我們實(shí)際上是指簽署序列化交易數(shù)據(jù)的哈希。 特殊交易:合約注冊(cè) 有一種特殊的帶有data,沒(méi)有value的交易。表示注冊(cè)一個(gè)新的合約。合約登記交易被發(fā)送到一個(gè)特殊的目的地地址,即零地址。簡(jiǎn)而言之,合約注冊(cè)交易中的+to+字段包含地址...
閱讀 1323·2021-11-22 14:44
閱讀 2464·2021-09-30 09:47
閱讀 1236·2021-09-09 11:56
閱讀 2101·2021-09-08 09:45
閱讀 4018·2021-08-31 09:40
閱讀 1268·2019-08-30 15:52
閱讀 2054·2019-08-30 14:09
閱讀 1604·2019-08-26 17:04