深入浅出,RLP 以太坊数据序列化的基石
在以太坊区块链的复杂世界中,数据的高效、安全传输与存储至关重要,无论是账户状态、交易信息还是区块数据,都需要一种可靠的方式来编码和解码,RLP(Recursive Length Prefix,递归长度前缀)正是以太坊中用于序列化对象(如字符串、字节数组、列表等)的核心编码方法,它以其简洁、高效和可扩展的特性,成为了以太坊数据结构的基石。
什么是RLP?
RLP,全称Recursive Length Prefix,即“递归长度前缀”,它的主要目标是将任意嵌套的数据结构(一个包含多个字段和子列表的交易对象)转换成一个线性的字节数组(byte array),以便在网络中传输或存储在区块链上,同样,它也能将这些字节数组准确地还原成原始的数据结构。
RLP的设计遵循了两个基本原则:

- 唯一性:任意两个不同的数据结构,通过RLP编码后,得到的字节数组必须是不同的,反之亦然,确保了数据序列化和反序列化的无损和准确。
- 简洁性:编码后的字节数组应尽可能短,以减少存储和网络传输的开销。
RLP的核心编码规则
RLP的编码规则并不复杂,主要针对两类数据:字符串(包括字节数组,下同)和列表。
-
字符串(String)的编码: 字符串是指一串字节的集合,RLP对字符串的编码取决于其长度:

- 如果字符串长度为0-127字节(即单字节,最高位为0): 直接将该字节作为编码结果,字符串 "dog" (ASCII: 0x64, 0x6f, 0x67) 的RLP编码就是其本身
0x646f67。 - 如果字符串长度大于127字节(即单字节,最高位为1)或前缀字节本身是0(即字符串以0x00开头): 编码格式为:[前缀字节] [字符串长度] [字符串内容]
- 前缀字节:计算字符串长度的字节长度(L),然后设置前缀字节为
0x80 L。- 如果字符串长度在128-255字节之间,长度L用1字节表示,前缀字节为
0x80 1 = 0x81。 - 如果字符串长度在256-65535字节之间,长度L用2字节表示,前缀字节为
0x80 2 = 0x82。 - 以此类推,最长支持到
0xb8 8(即长度用8字节表示,字符串长度可达2^64-1字节)。
- 如果字符串长度在128-255字节之间,长度L用1字节表示,前缀字节为
- 字符串长度:以大端序表示的字符串长度。
- :原始字符串的字节。 一个长度为128字节的字符串S:
- 前缀字节:
0x81(因为长度128需要1字节表示,0x80 1 = 0x81) - 字符串长度:
0x80(128的大端单字节表示) - S本身
- RLP编码:
0x810x80S
- 前缀字节:计算字符串长度的字节长度(L),然后设置前缀字节为
- 如果字符串长度为0-127字节(即单字节,最高位为0): 直接将该字节作为编码结果,字符串 "dog" (ASCII: 0x64, 0x6f, 0x67) 的RLP编码就是其本身
-
列表(List)的编码: 列表是指一个包含其他字符串或列表的有序集合,RLP对列表的编码规则是:
- 编码格式为:[前缀字节] [总长度] [串联后的RLP编码元素]
- 前缀字节:计算列表所有元素RLP编码后的总长度(T),然后设置前缀字节为
0xc0 T的字节长度。- 如果总长度T在0-55字节之间,前缀字节为
0xc0 T。 - 如果总长度T大于55字节,前缀字节为
0xc0 T的字节长度,然后是大端序的T值。
- 如果总长度T在0-55字节之间,前缀字节为
- 总长度:列表所有元素RLP编码后拼接在一起的总字节数。
- 串联后的RLP编码元素:将列表中每个元素分别进行RLP编码,然后将这些编码结果按顺序拼接起来。
- 前缀字节:计算列表所有元素RLP编码后的总长度(T),然后设置前缀字节为
- 示例:一个包含两个字符串 "cat" (RLP:
0x636174) 和 "dog" (RLP:0x646f67) 的列表:- 元素1 RLP:
0x636174(长度4) - 元素2 RLP:
0x646f67(长度5) - 串联后总长度:4 5 = 9字节
- 因为总长度9 <= 55,所以前缀字节为
0xc0 9 = 0xc9 - RLP编码:
0xc90x6361740x646f67=0xc9636174646f67
- 元素1 RLP:
- 编码格式为:[前缀字节] [总长度] [串联后的RLP编码元素]
RLP在以太坊中的关键应用
RLP几乎贯穿了以太坊的每一个角落,是构建整个区块链数据结构的基础:

- 区块(Block)结构:每个区块头(包含父区块哈希、叔父区块哈希、Coinbase地址、根哈希、时间戳、难度、随机数、区块号、区块体根哈希等)和区块体(包含交易列表和叔块列表)都使用RLP进行编码,区块的哈希值实际上就是对其RLP编码结果进行Keccak-256哈希计算得到的。
- 交易(Transaction)结构:无论是早期的交易格式还是EIP-1559升级后的交易,其各个字段(如nonce、gas price、gas limit、to、value、data、签名等)都被组织成一个数据结构,并通过RLP进行编码,形成网络上传输的交易数据。
- 状态存储:以太坊的状态树(State Trie)中的每个账户(Account)都由一个RLP编码的对象表示,该对象包含nonce、balance、storageRoot和codeHash等字段,合约代码本身也是通过RLP编码后存储在状态中。
- 收据(Receipt):交易执行后产生的收据,包含了交易状态、日志 bloom 过滤器、日志列表等信息,同样使用RLP编码。
- 合约代码部署与调用:合约代码在部署时,其字节码会被RLP编码后存储,合约内部的存储和内存操作,虽然底层是更复杂的数据结构,但其顶层组织和序列化也离不开RLP的思想。
RLP的优势与局限性
优势:
- 简洁高效:编码后的数据冗余度低,节省了宝贵的链上存储空间和网络带宽。
- 简单易懂:编码规则相对简单,易于实现和调试。
- 可扩展性:能够处理任意深度的嵌套结构,满足以太坊复杂数据模型的需求。
- 唯一性:确保了数据序列化和反序列化的准确性和一致性。
局限性:
- 非类型安全:RLP本身不包含类型信息,解码时需要预先知道原始数据结构的结构,否则无法正确解析,这在一定程度上增加了开发和维护的复杂性。
- 对复杂类型支持有限:主要针对字符串和列表,对于更复杂的数据类型(如自定义结构体、枚举等),需要开发者自行将其转换为RLP支持的类型再进行编码。
RLP作为以太坊数据序列化的“通用语言”,以其简洁而强大的能力,为以太坊网络中的数据传输、存储和状态管理提供了坚实的基础,它虽然简单,却承载着构建去中心化应用所需的核心数据结构,理解RLP的工作原理,对于深入学习以太坊底层机制、开发区块链应用或进行协议分析都具有重要意义,正是这样看似朴素的技术,支撑起了以太坊庞大而复杂的生态系统。
本文 原创,转载保留链接!网址:https://licai.bangqike.com/bixun/1281072.html
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。






