关于以太坊:以太坊RLP序列化

62次阅读

共计 1732 个字符,预计需要花费 5 分钟才能阅读完成。

RLP 序列化

RLP 是 Recursive Length Prefix 的简写。是以太坊中的序列化办法,以太坊的所有对象都会应用 RLP 办法序列化为字节数组。

字节数组中数据局部的每个元素均为 ascii 编码,即小于 127

元素汇合:T


T为序列化后的对象的汇合,元素分为两种:

  • B:代表了所有可能的字节数组(一些字节的序列,这些字节形成了某个特定的元素,比方一个字符,一个字符串,或一个数字)
  • L:递归列表构造,其中所有元素为 T 类型,即 B 类型或 L 类型

咱们应用两个子函数来定义 RLP 函数,这两个子函数别离解决下面说到的两种构造 (L 或者B)

类型 B 的处理函数


伪代码如下:

func Rb(bytes []byte) []byte {if len(bytes) == 1 && bytes[0] < 127 {return bytes}
    if len(bytes) < 56 {
        // 数据局部字节数组长度小于 56 时,前缀为 128+ 数组长度
        bytes = append([]byte{uint8(128 + len(bytes))}, bytes...)
    } else {
        // 前缀 1:存储字节数组长度的数值需占用的字节数
        var lbe int
        lbe = len(BE(len(bytes)))
        // 前缀 2:示字符数组长的十六进制数
        var be []byte
        be = BE(len(bytes))
        // 附上前缀 2
        bytes = append(be, bytes...)
        // 附上前缀 1
        bytes = append([]byte{uint8(183 + lbe)}, bytes...)
    }
    return bytes
}
  • (a).(b,c).(d,e) = (a,b,c,d,e) 代表了 concat 的操作,也就是字符串的相加操作。“hello “+”world” = “hello world”
  • BE(x)函数其实是去掉了前导 0 的大端模式。比方 4 个字节的整形 0x1234 用大端模式来示意是 00 00 12 34 那么用 BE 函数解决之后返回的其实是 12 34. 结尾的多余的 00 被去掉了。

序列化后数值的语义

当数据 x 被序列化后,即成为字节序列。

  • 若数值在区间[0,128),表明该处为一个 ascii 字符
  • 若数值在区间[128,192),表明其后有一个字节数组
  • 若数值(n)在区间[128,183),表明该处的数据由两局部形成,第一个字节数值 n 及其后一个长度为 n-128 的字符序列
  • 若数值(n)在区间[183,192),表明该处的数据由三局部形成

    • 第一局部,同时也为第一个字节:lbe = len(BE(len(x))),即存储字节数组长度的数值需占用的字节数
    • 第二个局部,占用 lbe 个字节:存储示意字符数组长的十六进制数
    • 第三个局部:数据自身

类型 L 的处理函数

伪代码如下:

func Rl(x []T) []byte {var bytes []byte
    // 先序列化并拼接所有元素成一个字节数组
    for _, member := range x {bytes = append(bytes, RLB(member)...)
    }
    // 加上前缀
    if len(bytes) < 56 {
        // 拼接后数据局部字节数组长度小于 56 时,前缀为 192+ 数组长度
        bytes = append([]byte{uint8(192 + len(bytes))}, bytes...)
    } else {
        // 前缀 1:存储字节数组长度的数值需占用的字节数
        var lbe int
        lbe = len(BE(len(bytes)))
        // 前缀 2:示字符数组长的十六进制数
        var be []byte
        be = BE(len(bytes))
        // 附上前缀 2
        bytes = append(be, bytes...)
        // 附上前缀 1
        bytes = append([]byte{uint8(247 + lbe)}, bytes...)
    }
    return bytes
}

文档数值的语义

  • 若数值(n)在区间[192,256),表明其后有一个对象列表
  • 若数值(n)在区间[192,247),表明该处的数据由两局部形成,第一个字节数值 n 及其后一个长度为 n-192 的字符序列
  • 若数值(n)在区间[247,256),表明该处的数据由三局部形成

    • 第一局部,同时也为第一个字节:lbe = len(BE(len(x))),即存储字节数组长度的数值需占用的字节数
    • 第二个局部,占用 lbe 个字节:存储示意字符数组长的十六进制数
    • 第三个局部:数据自身

正文完
 0