在探索以太坊这个复杂的区块链世界时,我们经常会遇到各种底层技术和概念,RLP(Recursive Length Prefix,递归长度前缀)编码是以太坊中一项基础且至关重要的数据序列化方法,它简洁、高效,专门为以太坊的设计理念量身定制,使得网络中的节点能够以一种紧凑且无歧义的方式对数据进行编码和解码,本文将带您深入了解RLP编码的原理、规则及其在以太坊中的核心作用。
为什么需要RLP编码?—— 数据序列化的必要性
在以太坊网络中,节点之间需要频繁地交换数据,例如交易信息、区块数据、账户状态、合约代码等,这些数据结构往往非常复杂,可能包含嵌套的其他数据结构(如列表、字典等),为了让这些数据能够在网络上高效传输,或者被持久化存储,我们需要一种统一的“打包”方式,将其转换为一串连续的字节流,这个过程就是序列化。
反之,当接收到这串字节流时,接收方也需要能够准确地将其“解包”,还原成原始的数据结构,这就是反序列化。
RLP编码正是以太坊开发团队选择用于实现这一序列化方案的方法,它的设计目标并非通用,而是针对以太坊中常见的数据类型(字符串、列表)进行优化,力求简洁、快速且易于实现。
RLP编码的核心思想与规则
RLP编码的核心思想是为数据项(字符串或列表)添加一个“长度前缀”,以标识其长度,从而实现递归解码,其编码规则主要针对两种基本数据类型:字符串(字节数组)和列表。
字符串(String)的编码规则
字符串是指一串字节数据(在以太坊中,地址、交易哈希、合约代码等都以字符串形式存在),字符串的RLP编码根据其长度有不同的处理方式:
-
如果字符串长度为0到55字节(包含55字节):
- 编码结果为一个单字节前缀,其值为
0x80 + 字符串长度,后跟字符串本身。 - 空字符串的编码是
0x80(因为0 + 0x80 = 0x80)。 - 字符串
"dog"(长度为3)的编码是0x83+'d'+'o'+'g',即0x83646f67。
- 编码结果为一个单字节前缀,其值为
-
如果字符串长度大于55字节:
- 编码结果为一个单字节前缀,其值为
0xb7 + 字符串长度的字节长度(即长度本身的字节数),后跟字符串长度的字节表示(大端序),最后跟字符串本身。 - 一个长度为1024字节的字符串,其长度1024用2个字节表示(
0x0400),因为1024 > 55,且1024的字节长度是2,所以前缀是0xb7 + 0x02 = 0xb9,然后是0x0400,最后是1024字节的字符串数据。 - 一个长度为56字节的字符串,其长度56用1个字节表示(
0x38),前缀是0xb7 + 0x01 = 0xb8,然后是0x38,最后是56字节的字符串数据。
- 编码结果为一个单字节前缀,其值为
列表(List)的编码规则
列表是指一个包含其他字符串或列表的数据项(如区块包含交易列表,交易包含输入输出列表等),列表的编码也是递归的,即列表中的每个元素都需要先进行RLP编码。
-
如果所有编码后的元素的总长度为0到55字节(包含55字节):
- 编码结果为一个单字节前缀,其值为
0xc0 + 总长度,后跟所有编码后的元素依次拼接。 - 空列表
[]的编码是0xc0(因为0 + 0xc0 = 0xc0)。 - 列表
["cat", "dog"]:"cat"编码为0x83636174"dog"编码为0x83646f67- 两者拼接后长度为
6 + 6 = 12字节,小于55。 - 所以列表前缀是
0xc0 + 12 = 0xcc。 - 最终编码为
0xcc8363617483646f67。
- 编码结果为一个单字节前缀,其值为
-
如果所有编码后的元素的总长度大于55字节:
- 编码结果为一个单字节前缀,其值为
0xf7 + 总长度的字节长度,后跟总长度的字节表示(大端序),最后跟所有编码后的元素依次拼接。 - 这与长字符串的情况类似,只是“内容”变成了所有子元素RLP编码后的拼接结果。

- 编码结果为一个单字节前缀,其值为