在以太坊乃至更广泛的区块链生态中,数据的高效、安全传输与存储是保障系统稳定运行的核心,当提到以太坊的数据序列化方案,一个无法绕过的关键词便是 RLP(Recursive Length Prefix,递归长度前缀),RLP 并非一种复杂的加密算法,而是一种简洁而高效的编码方法,它是以太坊中序列化任意任意数据结构(如交易、区块状态、账户信息等)的标准格式,理解 RLP,是深入探索以太坊底层原理、节点间通信协议以及智能合约存储机制的重要一步。
RLP 的诞生:为何需要 RLP?
在以太坊的早期设计阶段,开发者面临一个关键问题:如何在节点之间高效、准确地传递复杂的数据结构?一个区块头包含了父区块哈希、叔父区块哈希、coinbase 地址、根哈希、时间戳、难度值、数字签名等众多字段,这些字段类型各异(字符串、数字、哈希值),长度不一,直接传输原始数据不仅效率低下,且难以解析,也无法保证跨节点数据的一致性。

传统的序列化方案如 JSON、XML 虽然可读性强,但它们存在冗余度高、解析相对复杂等问题,对于追求极致效率和简洁性的区块链底层协议而言并非最优选择,以太坊的创始人 Vitalik Buterin 等人设计了 RLP 编码方案,其核心目标是:
- 简洁性:编码后的数据尽可能紧凑,减少不必要的字节开销。
- 通用性:能够编码任意深度的嵌套数据结构,如数组、列表、字典等。
- 确定性:相同的数据结构经过 RLP 编码后,结果必须是唯一的;反之,从 RLP 编码中也能唯一解码出原始数据结构。
- 高效性:编码和解码过程应尽可能快速,减少计算资源消耗。
RLP 的核心规则:如何编码数据?
RLP 的编码规则非常直观,主要围绕两类数据对象展开:字符串(字节数组)和列表。
-
编码字符串(字节数组) 字符串是指一串连续的字节,可以是数字、文本、哈希等,RLP 对字符串的编码取决于其长度:

- 如果字符串长度为 0~127 字节(即单字节,最高位为 0): 直接将该字节作为编码结果,字符串 "dog"(ASCII 码为 0x64, 0x6f, 0x67)长度为 3,小于 128,RLP 编码就是其本身:
0x646f67。 - 如果字符串长度为 128~183 字节: 编码结果由两部分组成:
- 一个前缀字节,其值为
0x80 + 字符串长度,长度为 128 的字符串,前缀为0x80 + 128 = 0xF8。 - 后跟字符串本身的字节。 一个长度为 128 的字符串 "x...x"(128 个 'x'),其 RLP 编码为:
0xF8 0x80后跟 128 个 'x' 的字节。
- 一个前缀字节,其值为
- 如果字符串长度为 184~55 字节(即长度本身可以用单字节表示): 编码结果由三部分组成:
- 一个前缀字节
0xB7。 - 后跟字符串长度的字节(长度本身是一个字节,范围 184~55,即 0xB8~0xBF)。
- 后跟字符串本身的字节。 长度为 200 的字符串,前缀为
0xB7,长度字节为0xC8(即 200),后跟字符串本身。
- 一个前缀字节
- 如果字符串长度大于 55 字节(即长度需要多个字节表示): 编码结果由三部分组成:
- 一个前缀字节
0xB8。 - 后跟长度字节的长度(L),L 本身是一个变长整数编码(通常用最简方式表示)。
- 后跟字符串的实际长度(L 字节表示)。
- 字符串本身的字节。 一个长度为 1024 的字符串,长度 1024 的十六进制为 0x0400,需要 2 字节表示,因此前缀为
0xB8,后跟长度字节的长度0x02,再跟长度0x0400,最后是字符串本身。
- 一个前缀字节
简单总结字符串编码:短字符串(<128B)直接存;中等字符串(128B~55B)用
0x80 + len前缀;长字符串(>55B)用0xB7或0xB8加长度信息前缀。 - 如果字符串长度为 0~127 字节(即单字节,最高位为 0): 直接将该字节作为编码结果,字符串 "dog"(ASCII 码为 0x64, 0x6f, 0x67)长度为 3,小于 128,RLP 编码就是其本身:
-
编码列表 列表是指一个包含其他字符串或列表的数据结构,RLP 对列表的编码规则如下:
- 编码列表本身:
- 首先计算列表中所有元素(字符串或列表)的 RLP 编码后的总长度(total payload length)。
- 然后根据这个总长度选择前缀:
- 如果总长度为 0~55 字节:前缀为
0xC0 + 总长度。 - 如果总长度大于 55 字节:前缀为
0xF7 + 长度字节的长度 + 总长度(类似于长字符串的规则)。
- 如果总长度为 0~55 字节:前缀为
- 将前缀与所有元素的 RLP 编码结果拼接起来,形成最终的列表编码。
"递归"的含义:这里的“递归”体现在编码列表时,列表中的每个元素(无论是字符串还是子列表)都需要先按照 RLP 规则进行编码,然后将这些编码后的结果拼接起来,再计算总长度并添加列表前缀。

示例:编码列表
["cat", "dog"]。- "cat" 的 RLP 编码:
0x636174(长度 3 < 128,直接存)。 - "dog" 的 RLP 编码:
0x646f67(长度 3 < 128,直接存)。 - 两个元素编码后的总长度 = 3 + 3 = 6 字节。
- 总长度 6 < 55,因此列表前缀为
0xC0 + 6 = 0xC6。 - 最终列表 RLP 编码:
0xC6 636164646f67。
- 编码列表本身:
RLP 在以太坊中的应用场景
RLP 以其简洁高效的特点,深入以太坊的各个角落:
- 区块与交易数据:以太坊的区块头、区块体(包含交易列表)、每笔交易的各个字段(如发送方、接收方、金额、nonce、数据、签名等)都使用 RLP 进行编码,节点之间通过 P2P 网络广播新区块或交易时,传输的就是 RLP 编码后的数据。
- 状态存储:以太坊的状态树(State Trie)中,每个账户的存储(Storage Trie)以及账户本身(nonce, balance, root code, storageRoot)的序列化都依赖于 RLP,当需要修改账户状态时,相关的数据会被 RLP 编码后写入 MPT。
- 合约代码与数据:智能合约的字节码在存储时,以及合约的存储数据(Mapping, Array, Struct 等)在 MPT 中表示时,都会用到 RLP。
- RLPx 协议:以太坊节点之间的加密通信协议 RLpx(基于 devp2p)中,某些消息的封装也可能会使用 RLP 进行序列化。
RLP 的优势与局限性
优势:
- 极致简洁:相比 JSON,RLP 去除了所有冗余的标点符号和关键字,编码后的数据非常紧凑,节省了网络带宽和存储空间。
- 解析高效:由于结构简单,RLP 的解码算法可以非常快速地实现,无需复杂的语法分析。
- 通用且灵活:能够处理任意深度的嵌套结构,满足区块链复杂数据模型的需求。
局限性:
- 可读性差:RLP 编码后的数据是二进制格式,人类几乎无法直接阅读和调试,开发者在处理 RLP 数据时通常需要借助专门的工具库进行编解码。
- 功能单一:RLP 仅仅是一个序列化方案,不包含数据类型信息(如区分整数和字符串)、校验和(如 CRC)或加密功能,这些功能通常需要在 RLP 之上构建其他协议来实现,以太坊中整数通常会被先转换为特定长度的字节数组再进行 RLP 编码。

