文档章节

RLP编码原理

dophin459
 dophin459
发布于 2017/05/06 21:56
字数 1068
阅读 1260
收藏 2

RLP(Recursive Length Prefix,递归长度前缀)是一种编码算法,用于编码任意的嵌套结构的二进制数据,它是以太坊中数据序列化/反序列化的主要方法,区块、交易等数据结构在持久化时会先经过RLP编码后再存储到数据库中。

定义

RLP编码的定义只处理两类数据:一类是字符串(例如字节数组),一类是列表。字符串指的是一串二进制数据,列表是一个嵌套递归的结构,里面可以包含字符串和列表,例如["cat",["puppy","cow"],"horse",[[]],"pig",[""],"sheep"]就是一个复杂的列表。其他类型的数据需要转成以上的两类,转换的规则不是RLP编码定义的,可以根据自己的规则转换,例如struct可以转成列表,int可以转成二进制(属于字符串一类),以太坊中整数都以大端形式存储。

从RLP编码的名字可以看出它的特点:一个是递归,被编码的数据是递归的结构,编码算法也是递归进行处理的;二是长度前缀,也就是RLP编码都带有一个前缀,这个前缀是跟被编码数据的长度相关的,从下面的编码规则中可以看出这一点。

RLP编码规则

  • 对于单个字节,如果它的值范围是[0x00, 0x7f],它的RLP编码就是它本身。
  • 否则,如果一个字符串的长度是0-55字节,它的RLP编码包含一个单字节的前缀,后面跟着字符串本身,这个前缀的值是**0x80**加上字符串的长度。由于被编码的字符串最大长度是55=0x37,因此单字节前缀的最大值是0x80+0x37=0xb7,即编码的第一个字节的取值范围是[0x80, 0xb7]
  • 如果字符串的长度大于55个字节,它的RLP编码包含一个单字节的前缀,后面跟着字符串的长度,后面再跟着字符串本身。这个前缀的值是**0xb7**加上字符串长度的二进制形式的字节长度,说的有点绕,举个例子就明白了,例如一个字符串的长度是1024,它的二进制形式是10000000000,这个二进制形式的长度是2个字节,所以前缀应该是0xb7+2=0xb9,字符串长度1024=0x400,因此整个RLP编码应该是\xb9\x04\x00再跟上字符串本身。编码的第一个字节即前缀的取值范围是[0xb8, 0xbf],因为字符串长度二进制形式最少是1个字节,因此最小值是0xb7+1=0xb8,字符串长度二进制最大是8个字节,因此最大值是0xb7+8=0xbf
  • 如果一个列表的总长度(列表的总长度指的是它包含的项的数量加它包含的各项的长度之和)是0-55字节,它的RLP编码包含一个单字节的前缀,后面跟着列表中各元素项的RLP编码,这个前缀的值是**0xc0**加上列表的总长度。编码的第一个字节的取值范围是[0xc0, 0xf7]
  • 如果一个列表的总长度大于55字节,它的RLP编码包含一个单字节的前缀,后面跟着列表的长度,后面再跟着列表中各元素项的RLP编码,这个前缀的值是**0xf7**加上列表总长度的二进制形式的字节长度。编码的第一个字节的取值范围是[0xf8, 0xff]

RLP编码例子

  • 字符串 "dog" = [0x83, 'd', 'o', 'g' ] (规则二)
  • 列表 ["cat","dog"] = [0xc8, 0x83, 'c', 'a', 't', 0x83, 'd', 'o', 'g' ] (规则四)
  • 空字符串 "" = 0x80 (规则二)
  • 空列表 [] = [0xc0] (规则四)
  • 整数 15('\x0f') = 0x0f (规则一)
  • 整数 1024('\x04\00') = [0x82, 0x04, 0x00] (规则二)
  • 列表 [ [], [[]], [ [], [[]] ] ] = [0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0] (规则四)
  • 字符串 "Lorem ipsum dolor sit amet, consectetur adipisicing elit" = [0xb8, 0x38, 'L', 'o', 'r', 'e', 'm', ' ', ... , 'e', 'l', 'i', 't'] (规则三)

本文大部分翻译自以太坊github wiki文档,并加入自己的理解。

参考资料:https://github.com/ethereum/wiki/wiki/%5BEnglish%5D-RLP

© 著作权归作者所有

共有 人打赏支持
dophin459
粉丝 10
博文 15
码字总数 15489
作品 0
西城
程序员
私信 提问
深入讲解以太坊的数据存储

前言:本文的目的是打算深入浅出讲讲以太坊的整体结构以及存储相关的内容,会聚焦在存储上,同时会结合源码讲解,整个过程也可以体会到作者的设计思想之精妙。 一,区块 block是最重要的数据...

2018/01/08
0
1
Python从头实现以太坊(一):Ping

以太坊是一种可以在区块链上执行代码的加密货币。这个功能允许人们编写可以自动运行的“智能合约”。大概一年前,一个叫做DAO的智能合约炸锅了,有人找到方法操纵它去获取当时价值4100万美元...

JonHuang
2017/08/18
0
0
Ethereum学习(1)—— 基本介绍

1 开发环境安装 安装Ethereum 协议的Go语言的最新实现。 2 Ethereum组成 Ethereum包含以下几大模块。 模块 介绍 基于命令行的Ethereum客户端。使用JSON RPC格式,基于HTTP、WebSocket或者IPC...

翻书
2018/09/11
0
0
java 以太坊开发利器web3j

为了给希望使用web3j的开发人员提供更大的灵活性,项目由多个模块组成。 根据依赖顺序,列一下: org.web3j.utils :最小实用模块。 org.web3j.rlp :递归长度前缀(RLP)编码器。 org.web3...

智能合约
2018/07/03
0
0
PoW挖矿算法原理及其在比特币、以太坊中的实现

  PoW,全称Proof of Work,即工作量证明,又称挖矿。大部分公有链或虚拟货币,如比特币、以太坊,均基于PoW算法,来实现其共识机制。即根据挖矿贡献的有效工作,来决定货币的分配。 比特币...

莫名2013
2018/06/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Nextjs+React非页面组件SSR渲染

@随风溜达的向日葵 Nextjs Nextjs是React生态中非常受欢迎的SSR(server side render——服务端渲染)框架,只需要几个步骤就可以搭建一个支持SSR的工程(_Nextjs_的快速搭建见Next.js入门)...

随风溜达的向日葵
12分钟前
0
0
如何在 Linux 系统查询机器最近重启时间

在你的 Linux 或类 UNIX 系统中,你是如何查询系统上次重新启动的日期和时间?怎样显示系统关机的日期和时间? last 命令不仅可以按照时间从近到远的顺序列出该会话的特定用户、终端和主机名...

来来来来来
今天
2
0
Redis协议是什么样的

前言 我们用过很多redis的客户端,有没有相过自己撸一个redis客户端? 其实很简单,基于socket,监听6379端口,解析数据就可以了。 redis协议 解析数据的过程主要依赖于redis的协议了。 我们...

春哥大魔王的博客
今天
4
0
乱入Linux界的我是如何学习的

欢迎来到建哥学Linux,咳!咳!咳!开个玩笑哈,我是一个IT男,IT界的入门选手,正在学习Linux。 在之前,一直想进军IT界,学习IT技术,但是苦于没有人指导,也不知道学什么,最开始我自己在...

linuxCool
今天
4
0
携程Apollo统一配置中心的搭建和使用(java)

一.Apollo配置中心介绍 1、What is Apollo 1.1 Apollo简介 Apollo(阿波罗)是携程框架部门研发的开源配置管理中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到...

morpheusWB
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部