以太坊学习笔记
Ⅰ 以太坊共有三种类型的网络,是以下哪三个
往常跟我们的饮食特定的方式,我认为可以学习他的性格
Ⅱ 以太坊智能合约开发语言solidity是什么
Solidity 语言是一种专门用于编写和执行智能合约的语言,是在以太坊虚拟机基础上运行的、面向合约的高级语言,最初是在 2014 年 8 月由以太坊的前任 CTO和联合创始人 Gavin Wood 提出来的,后来由以太坊开发人员组建了一支专门的团队,对 Solidity 语言进行不断改进,目前仍在开发和优化之中,在 GitHub 上的开发存储区域是 htps:/github.com/thereum/solidity,在这里我们可以了解到最全面的关于 Solidity 语言开发和迭代的过程详情、相关文档。 在语言的风格上,Solidity 语言受到 C++、Python 和 JavaScript 3 种语言的深刻影响,它是一种静态类型的编程语言,以字节码(Bytecode)的模式进行编译,因此可以在以太坊虚拟机上运行。Gavin Wood 在开发 Solidity 语言时借鉴了 JavaScript 的 ECMAScript 脚本语言的语法规则,使它与现有的网页开发语言有些类似,但其实有较大不同,如 Solidity 语言拥有静态类型、可变返回函数等。最重要的一点是,Solidity 语言可以编写具有自执行的业务逻辑、嵌入智能合约中的合约,因此它不但是以太坊的基础编程语言之一,而且是其他绝大部分基于以太坊的、具有智能合约的各种区块链产品(Blockchain 2.0)的基础编程语言,被广泛应用于目前绝大多数区块链产品,如超级账本(Hyperledger)项目就是用 Soliditv 语言开发而成的。
链乔教育在线旗下学硕创新区块链技术工作站是中国教育部学校规划建设发展中心开展的“智慧学习工场2020-学硕创新工作站 ”唯一获准的“区块链技术专业”试点工作站。专业站立足为学生提供多样化成长路径,推进专业学位研究生产学研结合培养模式改革,构建应用型、复合型人才培养体系。
Ⅲ 以太坊是什么丨以太坊开发入门指南
以太坊是什么丨以太坊开发入门指南
很多同学已经跃跃欲试投入到区块链开发队伍当中来,可是又感觉无从下手,本文将基于以太坊平台,以通俗的方式介绍以太坊开发中涉及的各晦涩的概念,轻松带大家入门。
以太坊是什么
以太坊(Ethereum)是一个建立在区块链技术之上, 去中心化应用平台。它允许任何人在平台中建立和使用通过区块链技术运行的去中心化应用。
对这句话不理解的同学,姑且可以理解为以太坊是区块链里的Android,它是一个开发平台,让我们就可以像基于Android Framework一样基于区块链技术写应用。
在没有以太坊之前,写区块链应用是这样的:拷贝一份比特币代码,然后去改底层代码如加密算法,共识机制,网络协议等等(很多山寨币就是这样,改改就出来一个新币)。
以太坊平台对底层区块链技术进行了封装,让区块链应用开发者可以直接基于以太坊平台进行开发,开发者只要专注于应用本身的开发,从而大大降低了难度。
目前围绕以太坊已经形成了一个较为完善的开发生态圈:有社区的支持,有很多开发框架、工具可以选择。
智能合约
什么是智能合约
以太坊上的程序称之为智能合约, 它是代码和数据(状态)的集合。
智能合约可以理解为在区块链上可以自动执行的(由事件驱动的)、以代码形式编写的合同(特殊的交易)。
在比特币脚本中,我们讲到过比特币的交易是可以编程的,但是比特币脚本有很多的限制,能够编写的程序也有限,而以太坊则更加完备(在计算机科学术语中,称它为是“图灵完备的”),让我们就像使用任何高级语言一样来编写几乎可以做任何事情的程序(智能合约)。
智能合约非常适合对信任、安全和持久性要求较高的应用场景,比如:数字货币、数字资产、投票、保险、金融应用、预测市场、产权所有权管理、物联网、点对点交易等等。
目前除数字货币之外,真正落地的应用还不多(就像移动平台刚开始出来一样),相信1到3年内,各种杀手级会慢慢出现。
编程语言:Solidity
智能合约的默认的编程语言是Solidity,文件扩展名以.sol结尾。
Solidity是和JavaScript相似的语言,用它来开发合约并编译成以太坊虚拟机字节代码。
还有长像Python的智能合约开发语言:Serpent,不过建议大家还是使用Solidity。
Browser-Solidity是一个浏览器的Solidity IDE, 大家可以点进去看看,以后我们更多文章介绍Solidity这个语言。
运行环境:EVM
EVM(Ethereum Virtual Machine)以太坊虚拟机是以太坊中智能合约的运行环境。
Solidity之于EVM,就像之于跟JVM的关系一样,这样大家就容易理解了。
以太坊虚拟机是一个隔离的环境,在EVM内部运行的代码不能跟外部有联系。
而EVM运行在以太坊节点上,当我们把合约部署到以太坊网络上之后,合约就可以在以太坊网络中运行了。
合约的编译
以太坊虚拟机上运行的是合约的字节码形式,需要我们在部署之前先对合约进行编译,可以选择Browser-Solidity Web IDE或solc编译器。
合约的部署
在以太坊上开发应用时,常常要使用到以太坊客户端(钱包)。平时我们在开发中,一般不接触到客户端或钱包的概念,它是什么呢?
以太坊客户端(钱包)
以太坊客户端,其实我们可以把它理解为一个开发者工具,它提供账户管理、挖矿、转账、智能合约的部署和执行等等功能。
EVM是由以太坊客户端提供的。
Geth是典型的开发以太坊时使用的客户端,基于Go语言开发。 Geth提供了一个交互式命令控制台,通过命令控制台中包含了以太坊的各种功能(API)。Geth的使用我们之后会有文章介绍,这里大家先有个概念。
Geth控制台和Chrome浏览器开发者工具里的面的控制台是类似,不过是跑在终端里。
相对于Geth,Mist则是图形化操作界面的以太坊客户端。
如何部署
智能合约的部署是指把合约字节码发布到区块链上,并使用一个特定的地址来标示这个合约,这个地址称为合约账户。
以太坊中有两类账户:
· 外部账户
该类账户被私钥控制(由人控制),没有关联任何代码。
· 合约账户
该类账户被它们的合约代码控制且有代码与之关联。
和比特币使用UTXO的设计不一样,以太坊使用更为简单的账户概念。
两类账户对于EVM来说是一样的。
外部账户与合约账户的区别和关系是这样的:一个外部账户可以通过创建和用自己的私钥来对交易进行签名,来发送消息给另一个外部账户或合约账户。
在两个外部账户之间传送消息是价值转移的过程。但从外部账户到合约账户的消息会激活合约账户的代码,允许它执行各种动作(比如转移代币,写入内部存储,挖出一个新代币,执行一些运算,创建一个新的合约等等)。
只有当外部账户发出指令时,合同账户才会执行相应的操作。
合约部署就是将编译好的合约字节码通过外部账号发送交易的形式部署到以太坊区块链上(由实际矿工出块之后,才真正部署成功)。
运行
合约部署之后,当需要调用这个智能合约的方法时只需要向这个合约账户发送消息(交易)即可,通过消息触发后智能合约的代码就会在EVM中执行了。
Gas
和云计算相似,占用区块链的资源(不管是简单的转账交易,还是合约的部署和执行)同样需要付出相应的费用(天下没有免费的午餐对不对!)。
以太坊上用Gas机制来计费,Gas也可以认为是一个工作量单位,智能合约越复杂(计算步骤的数量和类型,占用的内存等),用来完成运行就需要越多Gas。
任何特定的合约所需的运行合约的Gas数量是固定的,由合约的复杂度决定。
而Gas价格由运行合约的人在提交运行合约请求的时候规定,以确定他愿意为这次交易愿意付出的费用:Gas价格(用以太币计价) * Gas数量。
Gas的目的是限制执行交易所需的工作量,同时为执行支付费用。当EVM执行交易时,Gas将按照特定规则被逐渐消耗,无论执行到什么位置,一旦Gas被耗尽,将会触发异常。当前调用帧所做的所有状态修改都将被回滚, 如果执行结束还有Gas剩余,这些Gas将被返还给发送账户。
如果没有这个限制,就会有人写出无法停止(如:死循环)的合约来阻塞网络。
因此实际上(把前面的内容串起来),我们需要一个有以太币余额的外部账户,来发起一个交易(普通交易或部署、运行一个合约),运行时,矿工收取相应的工作量费用。
以太坊网络
有些着急的同学要问了,没有以太币,要怎么进行智能合约的开发?可以选择以下方式:
选择以太坊官网测试网络Testnet
测试网络中,我们可以很容易获得免费的以太币,缺点是需要发很长时间初始化节点。
使用私有链
创建自己的以太币私有测试网络,通常也称为私有链,我们可以用它来作为一个测试环境来开发、调试和测试智能合约。
通过上面提到的Geth很容易就可以创建一个属于自己的测试网络,以太币想挖多少挖多少,也免去了同步正式网络的整个区块链数据。
使用开发者网络(模式)
相比私有链,开发者网络(模式)下,会自动分配一个有大量余额的开发者账户给我们使用。
使用模拟环境
另一个创建测试网络的方法是使用testrpc,testrpc是在本地使用内存模拟的一个以太坊环境,对于开发调试来说,更方便快捷。而且testrpc可以在启动时帮我们创建10个存有资金的测试账户。
进行合约开发时,可以在testrpc中测试通过后,再部署到Geth节点中去。
更新:testrpc 现在已经并入到Truffle 开发框架中,现在名字是Ganache CLI。
Dapp:去中心化的应用程序
以太坊社区把基于智能合约的应用称为去中心化的应用程序(DecentralizedApp)。如果我们把区块链理解为一个不可篡改的数据库,智能合约理解为和数据库打交道的程序,那就很容易理解Dapp了,一个Dapp不单单有智能合约,比如还需要有一个友好的用户界面和其他的东西。
Truffle
Truffle是Dapp开发框架,他可以帮我们处理掉大量无关紧要的小事情,让我们可以迅速开始写代码-编译-部署-测试-打包DApp这个流程。
总结
我们现在来总结一下,以太坊是平台,它让我们方便的使用区块链技术开发去中心化的应用,在这个应用中,使用Solidity来编写和区块链交互的智能合约,合约编写好后之后,我们需要用以太坊客户端用一个有余额的账户去部署及运行合约(使用Truffle框架可以更好的帮助我们做这些事情了)。为了开发方便,我们可以用Geth或testrpc来搭建一个测试网络。
注:本文中为了方便大家理解,对一些概念做了类比,有些严格来不是准确,不过我也认为对于初学者,也没有必要把每一个概念掌握的很细致和准确,学习是一个逐步深入的过程,很多时候我们会发现,过一段后,我们会对同一个东西有不一样的理解。
Ⅳ 以太坊目前处于做空的状态,你对以太坊有何看法
社会经济发展越来越快,有越来越多的人选择将自己的钱财放入到投资市场之中进行盈利,不得不说的是,虚拟货币在我国是不被认可的,以太坊尽管说目前处于多空的状态,我们也应该尽量的敬而远之才行,只有远离虚拟货币才可以更好的保障我们的财产安全,希望每个人都能够认识到这一点。
我们在日常生活中还是应该努力工作,好好学习为主,只有通过自己双手赚来的钱财,才是会让我们感觉到花着放心,希望每个人都能够守好自己的钱袋子,只有这样才可以让我们在经济上减少损失,我们也相信会有越来越多的人会远离虚拟货币的。
Ⅳ 以太坊架构是怎么样的
以太坊最上层的是DApp。它通过Web3.js和智能合约层进行交换。所有的智能合约都运行在EVM(以太坊虚拟机)上,并会用到RPC的调用。在EVM和RPC下面是以太坊的四大核心内容,包括:blockChain, 共识算法,挖矿以及网络层。除了DApp外,其他的所有部分都在以太坊的客户端里,目前最流行的以太坊客户端就是Geth(Go-Ethereum)
Ⅵ 以太坊虚拟机(EVM)是什么
以太坊是一个可编程的区块链。与比特币不同,以太坊并没有给用户提供一组预定义的操作(比如比特币交易),而是允许用户创建他们自己的操作,这些操作可以任意复杂。这样,以太坊成为了多种不同类型去中心化区块链的平台,包括但是不限于密码学货币。
EVM为以太坊虚拟机。以太坊底层通过EVM模块支持智能合约的执行和调用,调用时根据合约的地址获取到代码,生成具体的执行环境,然后将代码载入到EVM虚拟机中运行。通常目前开发智能合约的高级语言为Solidity,在利用solidity实现智能合约逻辑后,通过编译器编译成元数据(字节码)最后发布到以坊上。
EVM架构概述
EVM本质上是一个堆栈机器,它最直接的的功能是执行智能合约,根据官方给出的设计原理,EVM的主要的设计目标为如下几点:
简单性
确定性
空间节省
为区块链服务
安全性保证
便于优化
针对以上几点通过对EVM源代码的阅读来了解其具体的设计思想和工程实用性。
EVM存储系统机器位宽
EVM机器位宽为256位,即32个字节,256位机器字宽不同于我们经常见到主流的64位的机器字宽,这就标明EVM设计上将考虑一套自己的关于操作,数据,逻辑控制的指令编码。目前主流的处理器原生的支持的计算数据类型有:8bits整数,16bits整数,32bits整数,64bits整数。一般情况下宽字节的计算将更加的快一些,因为它可能包含更多的指令被一次性加载到pc寄存器中,同时伴有内存访问次数的减少。目前在X86的架构中8bits的计算并不是完全的支持(除法和乘法),但基本的数学运算大概在几个时钟周期内就能完成,也就是说主流的字节宽度基本上处理器能够原生的支持,那为什么EVM要采用256位的字宽。主要从以下两个方面考虑:
时间,智能合约是否能执行得更快
空间,这样是否整体字节码的大小会有所减少
gas成本
时间上主要体现在执行的效率上,我们以两个整型数相加来对比具体的操作时间消耗。32bits相加的X86
的汇编代码
mov eax, dword [9876ABCD] //将地址9876ABCD中的32位数据放入eax数据寄存器
add eax, dword [1234DCBA] //将1234DCBA地址指向32位数和eax相加,结果保存在eax中
64bits相加的X86汇编代码
mov rax, qword [123456789ABCDEF1] //将地址指向的64位数据放入64位寄存器
add rax, qword [1020304050607080] //计算相加的结果并将结果放入到64位寄存器中
链乔教育在线旗下学硕创新区块链技术工作站是中国教育部学校规划建设发展中心开展的“智慧学习工场2020-学硕创新工作站 ”唯一获准的“区块链技术专业”试点工作站。专业站立足为学生提供多样化成长路径,推进专业学位研究生产学研结合培养模式改革,构建应用型、复合型人才培养体系。
Ⅶ 011:Ethash算法|《ETH原理与智能合约开发》笔记
待字闺中开发了一门区块链方面的课程:《深入浅出ETH原理与智能合约开发》,马良老师讲授。此文集记录我的学习笔记。
课程共8节课。其中,前四课讲ETH原理,后四课讲智能合约。
第四课分为三部分:
这篇文章是第四课第一部分的学习笔记:Ethash算法。
这节课介绍的是以太坊非常核心的挖矿算法。
在介绍Ethash算法之前,先讲一些背景知识。其实区块链技术主要是解决一个共识的问题,而共识是一个层次很丰富的概念,这里把范畴缩小,只讨论区块链中的共识。
什么是共识?
在区块链中,共识是指哪个节点有记账权。网络中有多个节点,理论上都有记账权,首先面临的问题就是,到底谁来记帐。另一个问题,交易一定是有顺序的,即谁在前,前在后。这样可以解决双花问题。区块链中的共识机制就是解决这两个问题,谁记帐和交易的顺序。
什么是工作量证明算法
为了决定众多节点中谁来记帐,可以有多种方案。其中,工作量证明就让节点去算一个哈希值,满足难度目标值的胜出。这个过程只能通过枚举计算,谁算的快,谁获胜的概率大。收益跟节点的工作量有关,这就是工作量证明算法。
为什么要引入工作量证明算法?
Hash Cash 由Adam Back 在1997年发表,中本聪首次在比特币中应用来解决共识问题。
它最初用来解决垃圾邮件问题。
其主要设计思想是通过暴力搜索,找到一种Block头部组合(通过调整nonce)使得嵌套的SHA256单向散列值输出小于一个特定的值(Target)。
这个算法是计算密集型算法,一开始从CPU挖矿,转而为GPU,转而为FPGA,转而为ASIC,从而使得算力变得非常集中。
算力集中就会带来一个问题,若有一个矿池的算力达到51%,则它就会有作恶的风险。这是比特币等使用工作量证明算法的系统的弊端。而以太坊则吸取了这个教训,进行了一些改进,诞生了Ethash算法。
Ethash算法吸取了比特币的教训,专门设计了非常不利用计算的模型,它采用了I/O密集的模型,I/O慢,计算再快也没用。这样,对专用集成电路则不是那么有效。
该算法对GPU友好。一是考虑如果只支持CPU,担心易被木马攻击;二是现在的显存都很大。
轻型客户端的算法不适于挖矿,易于验证;快速启动
算法中,主要依赖于Keccake256 。
数据源除了传统的Block头部,还引入了随机数阵列DAG(有向非循环图)(Vitalik提出)
种子值很小。根据种子值生成缓存值,缓存层的初始值为16M,每个世代增加128K。
在缓存层之下是矿工使用的数据值,数据层的初始值是1G,每个世代增加8M。整个数据层的大小是128Bytes的素数倍。
框架主要分为两个部分,一是DAG的生成,二是用Hashimoto来计算最终的结果。
DAG分为三个层次,种子层,缓存层,数据层。三个层次是逐渐增大的。
种子层很小,依赖上个世代的种子层。
缓存层的第一个数据是根据种子层生成的,后面的根据前面的一个来生成,它是一个串行化的过程。其初始大小是16M,每个世代增加128K。每个元素64字节。
数据层就是要用到的数据,其初始大小1G,现在约2个G,每个元素128字节。数据层的元素依赖缓存层的256个元素。
整个流程是内存密集型。
首先是头部信息和随机数结合在一起,做一个Keccak运算,获得初始的单向散列值Mix[0],128字节。然后,通过另外一个函数,映射到DAG上,获取一个值,再与Mix[0]混合得到Mix[1],如此循环64次,得到Mix[64],128字节。
接下来经过后处理过程,得到 mix final 值,32字节。(这个值在前面两个小节《 009:GHOST协议 》、《 010:搭建测试网络 》都出现过)
再经过计算,得出结果。把它和目标值相比较,小于则挖矿成功。
难度值大,目标值小,就越难(前面需要的 0 越多)。
这个过程也是挖矿难,验证容易。
为防止矿机,mix function函数也有更新过。
难度公式见课件截图。
根据上一个区块的难度,来推算下一个。
从公式看出,难度由三部分组成,首先是上一区块的难度,然后是线性部分,最后是非线性部分。
非线性部分也叫难度炸弹,在过了一个特定的时间节点后,难度是指数上升。如此设计,其背后的目的是,在以太坊的项目周期中,在大都会版本后的下一个版本中,要转换共识,由POW变为POW、POS混合型的协议。基金会的意思可能是使得挖矿变得没意思。
难度曲线图显示,2017年10月,难度有一个大的下降,奖励也由5个变为3个。
本节主要介绍了Ethash算法,不足之处,请批评指正。
Ⅷ 以太坊转账流程
发起:用户在本地的以太坊钱包软件中选择要发送的交易地址(From)、输入目标地址(To)、金额(Value)、是否部署或调用合(Data)、手续费单价(Gasprice)等,确认发送至以太坊节点节点和钱包可以是同一台
广播:节点收到(或自己发起)交易后,会对交易进行验证。验证:交易的签名、发起账号的余额是否能支付转账余额与手续费、Nonce是否为账号已发出的交易数。验证为合法后,将交易加入节点的交易池中交易池中存储着待打包的交
安装以太坊浏览器钱包插件,创建钱包,获取虚拟以太币,进行转账交易。 实验内容 学习 初识以太坊,发送交易 1.学习《初始以太坊,发送交易》,虚拟以太币交易。
Ⅸ 什么是以太坊系统
以太坊项目借鉴了比特币区块链的技术,对它的应用范围进行了扩展。如果说比特币是利用区块链技术的专用计算器,那么以太坊就是利用区块链技术的通用计算机。简单地讲,以太坊 = 区块链 + 智能合约。
与比特币相比,以太坊最大的不同点是:它可以支持更加强大的脚本语言(用技术语言讲就是图灵完备的脚本语言),允许开发者在上面开发任意应用,实现任意智能合约,这也是以太坊的最强大之处。作为平台,以太坊可以类比于苹果的应用商店,任何开发者都可以在上面开发应用,并出售给用户。每一类金融合约都可以程序代码的形式写成智能合约。
链乔教育在线旗下学硕创新区块链技术工作站是中国教育部学校规划建设发展中心开展的“智慧学习工场2020-学硕创新工作站 ”唯一获准的“区块链技术专业”试点工作站。专业站立足为学生提供多样化成长路径,推进专业学位研究生产学研结合培养模式改革,构建应用型、复合型人才培养体系。
Ⅹ 【深度知识】以太坊数据序列化RLP编码/解码原理
RLP(Recursive Length Prefix),中文翻译过来叫递归长度前缀编码,它是以太坊序列化所采用的编码方式。RLP主要用于以太坊中数据的网络传输和持久化存储。
对象序列化方法有很多种,常见的像JSON编码,但是JSON有个明显的缺点:编码结果比较大。例如有如下的结构:
变量s序列化的结果是{"name":"icattlecoder","sex":"male"},字符串长度35,实际有效数据是icattlecoder 和male,共计16个字节,我们可以看到JSON的序列化时引入了太多的冗余信息。假设以太坊采用JSON来序列化,那么本来50GB的区块链可能现在就要100GB,当然实际没这么简单。
所以,以太坊需要设计一种结果更小的编码方法。
RLP编码的定义只处理两类数据:一类是字符串(例如字节数组),一类是列表。字符串指的是一串二进制数据,列表是一个嵌套递归的结构,里面可以包含字符串和列表,例如["cat",["puppy","cow"],"horse",[[]],"pig",[""],"sheep"]就是一个复杂的列表。其他类型的数据需要转成以上的两类,转换的规则不是RLP编码定义的,可以根据自己的规则转换,例如struct可以转成列表,int可以转成二进制(属于字符串一类),以太坊中整数都以大端形式存储。
从RLP编码的名字可以看出它的特点:一个是递归,被编码的数据是递归的结构,编码算法也是递归进行处理的;二是长度前缀,也就是RLP编码都带有一个前缀,这个前缀是跟被编码数据的长度相关的,从下面的编码规则中可以看出这一点。
对于值在[0, 127]之间的单个字节,其编码是其本身。
例1:a的编码是97。
如果byte数组长度l <= 55,编码的结果是数组本身,再加上128+l作为前缀。
例2:空字符串编码是128,即128 = 128 + 0。
例3:abc编码结果是131 97 98 99,其中131=128+len("abc"),97 98 99依次是a b c。
如果数组长度大于55, 编码结果第一个是183加数组长度的编码的长度,然后是数组长度的本身的编码,最后是byte数组的编码。
请把上面的规则多读几篇,特别是数组长度的编码的长度。
例4:编码下面这段字符串:
The length of this sentence is more than 55 bytes, I know it because I pre-designed it
这段字符串共86个字节,而86的编码只需要一个字节,那就是它自己,因此,编码的结果如下:
184 86 84 104 101 32 108 101 110 103 116 104 32 111 102 32 116 104 105 115 32 115 101 110 116 101 110 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 73 32 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 103 110 101 100 32 105 116
其中前三个字节的计算方式如下:
184 = 183 + 1,因为数组长度86编码后仅占用一个字节。
86即数组长度86
84是T的编码
例5:编码一个重复1024次"a"的字符串,其结果为:185 4 0 97 97 97 97 97 97 ...。
1024按 big endian编码为004 0,省略掉前面的零,长度为2,因此185 = 183 + 2。
规则1~3定义了byte数组的编码方案,下面介绍列表的编码规则。在此之前,我们先定义列表长度是指子列表编码后的长度之和。
如果列表长度小于55,编码结果第一位是192加列表长度的编码的长度,然后依次连接各子列表的编码。
注意规则4本身是递归定义的。
例6:["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加列表长度的编码长度,然后是列表长度本身的编码,最后依次连接各子列表的编码。
规则5本身也是递归定义的,和规则3相似。
例7:
["The length of this sentence is more than 55 bytes, ", "I know it because I pre-designed it"]
的编码结果是:
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 101 110 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 73 32 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 103 110 101 100 32 105 116
其中前两个字节的计算方式如下:
248 = 247 +1
88 = 86 + 2,在规则3的示例中,长度为86,而在此例中,由于有两个子字符串,每个子字符串本身的长度的编码各占1字节,因此总共占2字节。
第3个字节179依据规则2得出179 = 128 + 51
第55个字节163同样依据规则2得出163 = 128 + 35
例8:最后我们再来看个稍复杂点的例子以加深理解递归长度前缀,
["abc",["The length of this sentence is more than 55 bytes, ", "I know it because I pre-designed it"]]
编码结果是:
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 101 110 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 73 32 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 103 110 101 100 32 105 116
列表第一项字符串abc根据规则2,编码结果为131 97 98 99,长度为4。
列表第二项也是一个列表项:
["The length of this sentence is more than 55 bytes, ", "I know it because I pre-designed it"]
根据规则5,结果为
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 101 110 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 73 32 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 103 110 101 100 32 105 116
长度为90,因此,整个列表的编码结果第二位是90 + 4 = 94, 占用1个字节,第一位247 + 1 = 248
以上5条就是RPL的全部编码规则。
各语言在具体实现RLP编码时,首先需要将对像映射成byte数组或列表两种形式。以go语言编码struct为例,会将其映射为列表,例如Student这个对象处理成列表["icattlecoder","male"]
如果编码map类型,可以采用以下列表形式:
[["",""],["",""],["",""]]
解码时,首先根据编码结果第一个字节f的大小,执行以下的规则判断:
1.如果f∈ [0,128),那么它是一个字节本身。
2.如果f∈[128,184),那么它是一个长度不超过55的byte数组,数组的长度为 l=f-128
3.如果f∈[184,192),那么它是一个长度超过55的数组,长度本身的编码长度ll=f-183,然后从第二个字节开始读取长度为ll的bytes,按照BigEndian编码成整数l,l即为数组的长度。
4.如果f∈(192,247],那么它是一个编码后总长度不超过55的列表,列表长度为l=f-192。递归使用规则1~4进行解码。
5.如果f∈(247,256],那么它是编码后长度大于55的列表,其长度本身的编码长度ll=f-247,然后从第二个字节读取长度为ll的bytes,按BigEndian编码成整数l,l即为子列表长度。然后递归根据解码规则进行解码。
以上解释了什么叫递归长度前缀编码,这个名字本身很好的解释了编码规则。
(1) 以太坊源码学习—RLP编码( https://segmentfault.com/a/1190000011763339 )
(2)简单分析RLP编码原理
( https://blog.csdn.net/itchosen/article/details/78183991 )