RLP(转发注明出处)
@
RLP序列化
RLP:这是一种对任意结构的二进制数据(字节数组)进行编码的序列化方法
什么是序列化?
序列化将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
序列化机制的核心作用就是对象状态的保存与重建。
为什么要序列化?
1、以某种存储形式使自定义对象持久化。->便于对象持久化,通过序列化可以把数据永久地保存到硬盘上(通常存放在文件里)
2、将对象从一个地方传递到另一个地方。->便于网络传输,利用序列化实现远程通信,即在网络上传送对象的字节序列
3、使程序更具维护性。->便于维护,程序员依照相同的序列化规则,进行序列化及反序列化。
序列化的方法:Json序列化、FastJson序列化、xml序列化..等等,RLP正是序列化方法的一种,以太坊中使用了大量的RLP序列化
RLP序列化处理的两项数据
区块、交易等数据结构在持久化时会先经过RLP编码后再存储到数据库中,RLP编码的定义只处理两类数据:
- 一类是byte数组。
- 一类byte数组的数组,称之为列表。(递归定义)
这里的递归定义就比较相似与JSON,可以很容易的表示出一个树的结构。
RLP序列化采取的5项规则:
- 对于值在[0, 127]之间的单个字节,其编码是其本身。
例1:a的编码是97。 - 如果byte数组长度l <= 55,编码的结果是数组本身,再加上128+l作为前缀。
例2:abc编码结果是131 97 98 99.其中131=128+len("abc"),97 98 99依次是a b c。 - 如果数组长度大于55,编码结果第一个是183加数组长度的编码的长度,然后是数组长度的本身的编码,最后是byte数组的编码。
例3:“The length of this sentence is more than 55 bytes, I know it because I pre-designed it” = [183 + 1,86, ‘T’, ‘h’, ‘e’, ‘ ’, ’l’, ‘e’, … , ‘d’, ‘ ’, ‘i’, ’t’]
这里一定要注意的是:加上的数组长度的编码,86是数组的长度,86编码之后占用1个字节(在1到128之间),所以才加上1 - 如果列表长度小于55,编码结果第一位是192加列表长度的编码的长度,然后依次连接各子列表的编码。
例4: ["abc", "def"]的编码结果是200 131 97 98 99 131 100 101 102。其中abc的编码为131 97 98 99,def的编码为131 100 101 102。两个子字符串的编码后总长度是8,因此编码结果第一位计算得出:192 + 8 = 200。 - 如果列表长度超过55,编码结果第一位是247加列表长度的编码长度,然后是列表长度本身的编码,最后依次连接各子列表的编码。
这里一定要注意的是:加上的是列表长度的编码长度!类似于规则3
ps:
- 列表长度是指子列表编码后的长度之和。
- 规则1~3定义了byte数组的编码方案(也就是第一种数据结构)下面介绍列表(第二种数据结构)的编码规则
现在我们看一个较复杂的例子:
例5:["abc",["The length of this sentence is more than 55 bytes, ", "I know it because I pre-designed it"]]
列表第一项字符串abc根据规则2,编码结果为131 97 98 99,长度为4。
列表第二项也是一个列表项,根据规则5,编码结果为
247+1 88 179 84 104 101 32 108 101 110 103 116 104 32 111 102 32 116 104 105 115 32 115 101 110 116 101110 99 101 32 105 115 32 109 111 114 101 32 116 104 97 110 32 53 53 32 98 121 116 101 115 44 32 163 7332 107 110 111 119 32 105 116 32 98 101 99 97 117 115 101 32 73 32 112 114 101 45 100 101 115 105 103110 101 100 32 105 116,长度为90。
因此,整个列表的编码结果第二位是90 + 4 = 94, 占用1个字节,第一位247 + 1 = 248
最后的结果为:248,94+第一个列表编码+第二个列表编码详细解释:
其中前两个字节的计算方式如下:
248 = 247 +1
为什么加1? 列表长度为90,列表长度的编码为1(字节)
88 = 86 + 2
为什么加2?
列表长度是指子列表编码后的长度之和。
两种看法:
其一可以看为:在规则3的示例中,长度为86,而在此例中,由于有两个子字符串,每个子字符串本身的长度的编码各占1字节,因此总共占2字节。
(列表长度本身的编码)
其二可以看为: 后面的90-2就是88
第3个字节179依据规则2得出179 = 128 + 51
第55个字节163同样依据规则2得出163 = 128 + 35
(递归)因此,整个列表的编码结果第二位是90 + 4 = 94, 占用1个字节,第一位247 + 1 = 248
最后的结果为:248,94,第一个列表编码,第二个列表编码
最后,编码为:
248 94 131 97 98 99 248 88 179 84 104 101 32 108 101 110 103 116 104 32 111 102 32 116 104 105 115 32 115 101 110 116 101110 99 101 32 105 115 32 109 111 114 101 32 116 104 97 110 32 53 53 32 98 121 116 101 115 44 32 163 7332 107 110 111 119 32 105 116 32 98 101 99 97 117 115 101 32 73 32 112 114 101 45 100 101 115 105 103110 101 100 32 105 116
利用python写的RLP
def rlp_encode(input):
if isinstance(input,str):
if len(input) == 1 and chr(input) < 128: return input #规则一
else: return encode_length(len(input),128) + input #规则二和规则三
elif isinstance(input,list):
output = ''
for item in input: output += rlp_encode(item) #递归的去遍历
return encode_length(len(output),192) + output #规则四和规则五
def encode_length(L,offset):
if L < 56:
return chr(L + offset)
elif L < 256**8:
BL = to_binary(L)
return chr(len(BL) + offset + 55) + BL
else:
raise Exception("input too long")
def to_binary(x):
return '' if x == 0 else to_binary(int(x / 256)) + chr(x % 256)
实际中的使用是个怎么样子?
在具体实现RLP编码时,首先需要将对像映射成byte数组或列表两种形式。以go语言编码struct为例,会将其映射为列表,例如Student这个对象处理成列表["icattlecoder","male"]
实际中的,不同,就是讲的没用16进制表示,正常来讲,是16进制表示。
RLP分析
- RLP最大的优点是在充分利用字节的情况下,同时支持列表结构,也就是说可以很轻易的利用RLP存储一个树状结构。
以上我们可以看出RLP编码的设计思想,就是通过首字节快速判断一串编码的类型,充分利用了一个字节,两个字节的存储空间,将0x7f以后的值赋予了新的含义。
- 程序处理RLP编码时也非常容易。
根据首字节就可以判断出这段编码的类型,同时调用不同的方法进行解码,和JSON编码类似,支持嵌套的结构,通过递归调用可以将整个RLP快速还原成一颗树,或者转译成一个JSON结构,便于其他程序使用
- 所以理论上RLP可以编码任何数据。
RLP使用首字节存储长度的位数,再用后续的字节表明整体字符串的长度,根据规则二计算,RLP可以支持的单个最大字符串长度为2的64次方,这无疑是个天文数字,再加上嵌套规则.
参考目录
[1]. RLP编码和解码
[2]. 以太坊RLP用法-以太坊源码学习
[3]. 简单分析RLP编码原理
[4]. 以太坊源码学习—RLP编码
如果我的工作为您带来了少许帮助,帮忙点一波关注或者收藏吧~(#.#)
RLP(转发注明出处)的更多相关文章
- 转载请注明出处: https://github.com/qiu-deqing/FE-interview
转载请注明出处: https://github.com/qiu-deqing/FE-interview Table of Contents generated with DocToc FE-inter ...
- Java程序员面试宝典1 ---Java基础部分(该博文为原创,转载请注明出处)
(该博文为原创,转载请注明出处 http://www.cnblogs.com/luyijoy/ by白手伊凡) 1. 基本概念 1) Java为解释性语言,运行过程:程序源 ...
- 移动端H5页面遇到的问题总结(转载请注明出处)
最近刚做完一个移动端的项目,产品之无敌,过程之艰辛,我就不多说了,记录下在这个项目中遇到的问题,以防万一,虽然这些可能都是已经被N多前辈解决掉了的问题,也放在这里,算是为自己漫漫前端路铺了一颗小石子儿 ...
- KCF:High-Speed Tracking with Kernelized Correlation Filters 的翻译与分析(一)。分享与转发请注明出处-作者:行于此路
High-Speed Tracking with Kernelized Correlation Filters 的翻译与分析 基于核相关滤波器的高速目标跟踪方法,简称KCF 写在前面,之所以对这篇文章 ...
- LAMP环境搭建 (原创帖,转载请注明出处)
=============================说在前面的话==========================第一安装Mysql第二安装Apache-httpd第三安装PHP 第四配置PH ...
- java 代码解压7z(带密码)转载请注明出处,谢谢
<sevenzipjbinding.version>9.20-2.00beta</sevenzipjbinding.version> <dependency> &l ...
- Apache开启状态查看页面(原创贴-转载请注明出处)
=================写在前面的话================== 场景描述:有时候我们需要查看apache的运行状态,只需要开启apache的status功能就可以实现,但是stat ...
- Apache设置页面认证(原创贴-转载请注明出处)
================写在前面的话============== 1.本试验使用的apache版本是2.4.24 场景描述:网站后台管理页面比较重要,不应该任何人都让访问,所以对后台页面做认证 ...
- 后端Apache获取前端Nginx反向代理的真实IP地址 (原创贴-转载请注明出处)
====================说在前面的话==================== 环境:前段Nginx是反向代理服务器:后端是Apache是WEB项目服务器 目的:让后端Apapche获取 ...
随机推荐
- vue---数据更新,视图不更新问题
写点赞功能时,点赞后已经追加到对象里了,但是视图没有更新. 查找了些资料: 数据已经更新了但是视图不更新的问题,有几个原因: 1.根属性不存在,而想要直接给根属性赋值导致的视图不更新.此时初始化属性的 ...
- Netty 内存回收之 noCleaner 策略
前言 对于堆外内存,使用 System.gc() 是不靠谱的,依赖老年代 FGC 也是不靠谱的,而且大部分调优指南都设置了 -DisableExplicitGC 禁用 System.gc().所以主动 ...
- php json_encode在CI框架中的使用细节
这个错误的造成原因是加载类类库,转换成json格式的时候不熟悉CI框架的规定导致的,CI框架中规定在将数据转换成json格式的时候需要将类库小写,当然了,调用的时候必须保证有这个类库,且可以在对应的文 ...
- eclipse .properties插件
资源文件 即 .properties 文件是常用于国际化: eclipse默认的 .properties 文件编辑器有几个问题: 编码问题 多种语言同步问题 下面介绍2种eclipse的 .prope ...
- Maven包查询库
第一个: http://search.maven.org/ 第二个: http://mvnrepository.com/artifact/aspectj/aspectjweaver
- Java基础——GUI编程(一)
一.定义 GUI全称是Graphical User Interface,即图形用户界面.JDK中提供了AWT 和 Swing 两个包,用于GUI程序的设计和开发. 1.java .awt abstr ...
- Retrofit 2.0 使用和原理
使用教程: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/1016/3588.html retrofit2 与okhttp关系 ...
- Flask中request参数
首先要明确一件事,Request这是个对象,不管使用PHP还是python还是什么java语言,虽然request这个对象可能叫的名字不一样,(在其他语言中可能叫什么HttpRequest),但是原理 ...
- Java 并发:Executor ExecutorService ThreadPoolExecutor
Executor Executor仅仅是一个简单的接口,其定义如下 public interface Executor { void execute(Runnable command); } 作为一个 ...
- 微信小程序css画三角形内有文字
<view class="productStatus"> <span> <em>已上架</em> </span> < ...