以太坊RLP编码
RLP(Recursive Length Prefix)
递归长度前缀编码,RLP
主要用于以太坊中数据的网络传输和持久化存储。
为什么需要RLP
编码
比较常见的序列化方法有JSON
,ProtoBuf
,但是这些序列化方法在以太坊这样的场景下都有一些问题。
比如像Json
编码,编码后的体积比较大。
从编码后的结果可以看到,其实我们需要的数据是Name
, Tom
, Age
, 22
,其余的括号和引号都是描述这种格式的,也就是冗余数据。
当然,会有人说可以用protoBuf
这样的二进制格式,但是例如JavaScript
这样的弱类型语言,是没有int
类型的,所有数字都是用Number
类型,底层用浮点数来实现,这样就会导致因为语言的不同编码后的数据有一定差异,最后得到的hash值也不同。
针对这些问题,以太坊设计了RLP
编码,同时也大幅简化了编码规则。
RLP
编码定义
RLP
简化了编码的类型,只定义了两种类型编码:
- byte数组
- byte数组的数组,也就是列表
RLP
编码基于上面两种数据类型提出了5条编码规则;
规则一
对于值在[0, 127]之间的单个字节,其编码是其本身;
规则二
如果byte数组的长度l<=55
,编码的结果是数组本身,再加上128+l
作为前缀。
规则三
如果数组长度大于55
,编码结果第一个值是183(128+55)
加数组长度的编码的长度,然后是数组长度本身的编码,最后是byte数组的编码。
1024按照大端编码
是0000 0000 001
转换为十进制是0 0 4 0
,省略前面的0
,长度为2, 因此185 = 183 + 2
规则四
如果列表长度小于55,编码结果第一位是192加列表长度的编码的长度,然后依次连接各个子列表的编码。
其中abc
的编码是131 97 98 99
, 131 = 128 + l
长度是4,def
的编码是131 100 101 102
,长度是4,总长度为8
,编码结果的第一位200 = 192 + 8
规则五
如果列表的长度超过55,编码结果第一位是247(192 + 55)
加列表长度的编码长度,然后是列表本身的编码,最后依次连接子列表的编码
的编码结果是:
|
|
其中前两个字节的计算方式如下:
248 = 247 + 1
88 = 86 + 2
, 在规则3的示例中,长度为86,而在此例中,由于有两个子字符串,每个子字符串本身的长度的编码各占1字节,因此总共占2字节。第3个字节
179
依据规则2得出
第55个字节163
同样依据规则2得出163=128+35
其中
规则三
,规则四
,规则5
是递归定义的,就是可以允许嵌套