Ethereum 中的 RLP 算法 (Recursive Length Prefix) 解码

Ethereum 学习笔记

Posted by Nicodechal on 2018-12-22

概述

RLP 算法能够将任意嵌套字节数组编码为字节序列,也能够将其还原为字节数组,这个过程相对于编码过程的逆过程,称为 RLP 算法的解码。下面是一个具体示例。

1
< 0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0 > = [ [], [[]], [ [], [[]] ] ]

本文对于 RLP 算法解码过程进行说明。

算法流程

相对于编码过程,解码过程分为以下几个主要的步骤:

  1. 根据第一个字节,解码出数据类型 ( 列表或字符串 ) 和数据长度信息及偏移 ( 即原始数据开头的在字节序列中的位置 )。
  2. 根据数据类型和偏移,解码数据。
  3. 解码剩余的数据。

具体的操作流程如下:

  1. 如果第一个字节的值在 [0x00, 0x7f] 之间,则该字节解码值为其本身。
  2. 如果第一个字节的值在 [0x80, 0xb7] 之间,则数据类型为字符串,其长度 str_len该字节的值 - 0x80,取接下来的 str_len 个字节进行编码。
  3. 如果第一个字节的值在 [0xb8, 0xbf] 之间,则数据类型为字符串,其长度值的字节数 len_of_str_len该字节的值 - 0xb7,接下来的 len_of_str_len 个字节的值为字符串的长度 str_len,同时取接下来的 str_len 个字节进行编码。
  4. 如果第一个字节的值在 [0xc0, 0xf7] 之间,则数据类型为列表,其长度 list_len该字节的值 - 0xc0,取接下来的 list_len 个字节进行编码。
  5. 如果第一个字节的值在 [0xf8, 0xff] 之间,则数据类型为字符串,其长度值的字节数 len_of_list_len该字节的值 - 0xf7,接下来的 len_of_list_len 个字节的值为字符串的长度 list_len,同时取接下来的 list_len 个字节进行编码。

总结

RLP 算法解码过程通过理解 RLP 算法的编码过程可以很容易的得到,RLP 算法解码主要通过数据前缀实现,利用前缀数据的取值范围不同来判断数据类型和数据长度。对于一个字节的数据 ( 取值范围 [0x00, 0xff] ),首先划分为 [0x00, 0xbf][0xc0, 0xff],分别表示列表数据和字符串数据。再分别根据数据长度进行划分,首先,对于 ASCII 范围内的数据直接进行解码,然后,1. 对于较短的数据,可以直接从第一字节的前缀中解析得到数据长度,2. 对于较长的数据,则先解析出数据长度值的字节数,并在第一字节后取该字节数的数据作为数据长度。得到数据长度后,在前缀 ( 此处包括数据长度,如果有 ) 后取相应长度的数据进行编码。整体过程是递归进行的。

总的来说,RLP 算法能够实现结构化的数据和字节序列之间的转换,可以方便的传输和存储结构化的数据,因而在以太坊中得到了广泛应用。

参考资料

RLP · ethereum/wiki Wiki