在以太坊的复杂世界中,数据的高效、可靠传输与存储至关重要,无论是交易、状态数据还是区块信息,都需要一种统一的方式来编码,以确保不同节点间能够准确无误地理解和交换这些数据,RLP(Recursive Length Prefix,递归长度前缀)编码正是以太坊为实现这一目标而设计的核心数据序列化方案,它以其简洁、高效和递归的特性,成为了以太坊数据结构得以在网络上传输和在区块链上存储的基石。
什么是 RLP 编码
RLP 编码是一种将任意嵌套的数组(或列表)和字节串(字符串)编码为线性字节的序列化方法,它的核心设计理念是“简单”和“递归”,简单意味着其编码规则相对直观,易于实现;递归则意味着它可以处理任意深度的嵌套数据结构,这正是区块链数据(如包含多个交易的区块)所需要的。
RLP 编码的目标不是对数据本身进行压缩(尽管它有时会减少数据大小),而是提供一个确定性的、无歧义的表示方式,使得解码方能够精确地重构出原始数据结构,确定性意味着相同的数据永远会被编码成相同的字节串,这对于区块链的共识至关重要。
RLP 编码的基本规则
RLP 编码主要针对两种数据类型进行编码:字符串(字节串,包括空字符串)和列表(其他 RLP 编码项的集合),其编码规则如下:
字符串(String)的编码
对于长度为 len 的字符串:
len == 0:编码为单字节0x80(二进制10000000)。1 <= len <= 55:编码为单字节0x80 + len(即b11000000 + len,其中前两位为11,后面 6 位表示长度)后紧跟字符串本身。- 字符串
"dog"(长度为 3)的编码为0x83 0x64 0x6f 0x67(83是80 + 3,64、6f、67分别是d、o、g的十六进制)。
- 字符串
len > 55:编码为单字节0xb7(10110111)后跟字符串长度的字节表示(使用最少的字节,大端序),然后是字符串本身。- 一个长度为 60 的字符串,其长度
60的十六进制为0x3c,需要 1 字节表示,编码为0xb7 0x3c后跟字符串本身。 - 一个长度为 1024 的字符串,其长度
1024的十六进制为0x0400,需要 2 字节表示,编码为0xb8 0x02 0x04(b8表示长度占 2 字节)后跟字符串本身。
- 一个长度为 60 的字符串,其长度
列表(List)的编码
列表是 RLP 编码的强大之处,它可以包含其他字符串或列表,形成任意深度的嵌套,列表的编码步骤如下:
- 计算列表中所有项(字符串或列表)的 RLP 编码后的总字节数,记为
total_len。 - 根据
total_len的长度决定前缀:total_len <= 55:编码为单字节0xc0 + total_len(即b11000000 + total_len,前两位为11,后面 6 位表示总长度)后跟所有项的 RLP 编码串联。- 列表
["dog", "cat"]:"dog"编码为0x83 0x64 0x6f 0x67(长度 4)"cat"编码为0x83 0x63 0x61 0x74(长度 4)total_len = 4 + 4 = 8- 列表编码为
0xc8 0x83 0x64 0x6f 0x67 0x83 0x63 0x61 0x74(c8是c0 + 8)
