RLP源码解析
一:概念:RLP(Recursive Length Prefix--递归长度前缀):是一个编码算法
二:功能:主要用于编码任意嵌套结构的二进制数据。是以太坊中序列和反序列化的主要方法,所有的区块、交易等数据结构都会经过RLP编码之后再存储到区块数据库中
三:数据处理特性:RLP处理两类数据
四:RLP编码规则
五:编码实例
六:解码规则
1. 根据输入首字节数据,解码数据类型、实际数据长度和位置;
2. 根据类型和实际数据,解码不同类型的数据;
3. 继续解码剩余的数据;
1. 如果首字节(prefix)的值在[0x00, 0x7f]范围之间,那么该数据是字符串,且字符串就是首字节本身;
2. 如果首字节的值在[0x80, 0xb7]范围之间,那么该数据是字符串,且字符串的长度等于首字节减去0x80,且字符串位于首字节之后;(比如首字节占0x87,那么长度就是0x87-0x80=7)
3. 如果首字节的值在[0xb8, 0xbf]范围之间,那么该数据是字符串,该字符串长度大于55,且字符串的长度的**字节长度**等于首字节减去0xb7,数据的长度位于首字节之后,且字符串位于数据的长度之后;
4. 如果首字节的值在[0xc0, 0xf7]范围之间,那么该数据是列表,在这种情况下,需要对列表各项的数据进行递归解码。列表的总长度(列表各项编码后的长度之和)等于首字节减去0xc0,且列表各项位于首字节之后;
5. 如果首字节的值在[0xf8, 0xff]范围之间,那么该数据为列表,总长度大于55,列表的总长度的字节长度等于首字节减去0xf7,列表的总长度位于首字节之后,且列表各项位于列表的总长度之后;
七:总结
1. RLP编码主要和字符串或者列表的长度有关,在解码的过程中,采用相对应编码规则逆推的方式进行
2. 与其他的序列化方式相比,RLP编码优点在于灵活使用长度前缀来表示数据的实际长度,并且使用递归的方式可以编码相当的数据
3. 在接收到经过RLP编码的数据之后,根据第1个字节就可以推断出数据类型,长度,数据本身等信息。而其它的序列化方式,不能要搞第一个字节获得这么多信息
八:目录结构
decode.go 解码器,把RLP数据解码成go的数据结构
decode_tail_test.go/decode_test.go 解码器测试代码
encode.go 编码器,把GO的数据结构转换成RLP的编码
encode_test.go/encode_example_test.go 编码器的测试
raw.go 原始的RLP数据
raw_test.go 测试文件
typecache.go 类型缓存,记录了类型->内容(编码器/解码器)
```
九:typecache.go:根据给定的类型找到对应的编码器和解码器
string encode(int)
string encode(log)
string encode(struct test*)
```
1. 该文件定义了类型->编码器/解码器函数的核心数据结构
2. 定义了编码器和解码器的函数
3. 通过对应类型查找对应的编码器和解码器
4. 通过给定的类型生成对应的编码器和解码器
十:encoder.go:编码器函数,把数据结构转换为RLP编码
1. 定义编码器接口
2. RLP编码函数
3. RLP数据组装
十一:decoder.go:解码器函数,把RLP编码转换为对应的golang数据结构
1. 定义解码器接口
2. RLP解析函数