RLP 编码
RLP(Recursive Length Prefix,递归长度前缀),关于介绍RLP的文章也挺多的,这里说说我对它的理解。RLP 编解码的精髓就在它的名字里,第一是R,对象可以是递归的,本质上是支持list的编码。第二是LP,长度前缀,第一个字节暗藏了很多信息呀,有关于接下来这个对象的长度,从长度可以推断出这个对象的类型。
支持哪些类型嘞:
- byte. 单字节,并且这个字节的value得小于0x80。这个时候,它的前缀就是这个byte的值,紧凑。
- string. string分为两种,长度小于56的和长度不小于56的。小于56的,它的前缀就是 0x80+string长度,否则就是 0xB8+string长度这个数字大端表示的长度。
- list. list也是分两种,长度小于56和长度不小于56的。小于56的,前缀就是0xC0+整个list表示的长度,否则前缀就是 F8+ 整个list表示的长度这个数字大端表示的长度。
从上面的类型表示可以推断出,空string和空list的表示分别为0x80和0xC0.
注意:map类型是不能直接被序列化(一般先转为二纬数组),负数类型不能被序列化。
例子:
type A struct {
X uint
Y uint
}
{X:1,Y:1} ==> 194 1 1 , 194表示长度为2的list,第一个属性是单byte,值为1。第二个属性为单byte,值为1.
{X:0,Y:0} ==> 194 128 128, 194表示长度为2的list,128表示值为0的string。
{X:233,Y:233} ==> [196 129 233 129 233], 196表示长度为4的list,129表示这个长度为1的string,string的值是233。
type A struct {
X uint
Z string
//Y []uint `rlp:"tail"`
Y []uint
}
{X:1,Z:"aaa",Y:[]uint{1,2,3}} ==> [201 1 131 97 97 97 195 1 2 3]
201 表示这个是长度为9的list,1表示属性值是1,131表示长度为3的string, 195表示长度为3的list,list每个元素值是1,2,3/
有几个tag:
-
nil
,nilString
,nilList
, 表示值是nil的时候,应该被encode成空string还是空list,默认情况下string,uint,bool和byteArray会是空string,其他的是空list。 -
tail
,要求是最后一个field,并且是slice类型,可以省略一个前缀。