区块链读书笔记04 - 以太坊

以太坊(Ethereum)

以太坊是一个去中心化平台,可以在其上运行使用智能合约编写的DApp(DApp可以由一个或多个智能合约构建。以太坊智能合约是在以太坊上运行的程序,可以使用Solidity语言编写。智能合约完全按照程序运行,杜绝了停机、中心化操控、欺诈和第三方干涉的可能性。)

使用以太坊运行智能合约的主要优点是方便智能合约彼此交互,而且不需要担心整合共识协议等事情,只需编写应用所需逻辑即可。

以太坊内置了一种加密货币——以太币(ether)。部署智能合约或者执行智能合约函数需要用到以太币。

和任何其他DApp一样,智能合约可以有多个实例,且每个实例都有自己专门的地址。用户账户和智能合约都可以持有以太币。

以太坊使用区块链数据结构和工作量证明共识协议。智能合约可以通过发送交易调用或者其他合约调用。

以太坊关键概念

账户(Account)

  • 外部账户(Externally Owned Accounts,EOA)
    一般意义上的用户账户,用户在创建账户时自动生成公私钥对,编码存放在Keyfile中,私钥使用用户口令加密,公钥哈希值截取后20位作为账户地址
  • 合约账户(Contract Accounts)
    保存在以太坊区块链上,是合约代码(功能)和数据(状态)的集合。合约账户通过外部账户或既存合约账户进行部署和操作控制。在部署合约二进制代码时由以太坊虚拟机(EVM)基于创建者账户地址、创建者交易nonce生成账户地址。账户地址生成过程如下图所示。
    以太坊账户

交易(Transaction)

以太坊的交易是外部账户发往其他账户(外部账户或合约账户)报文结构体,只要包括接收者地址(0地址代表新建合约实例)、发送者签名、发送金额、数据域(若接收方为合约账户)、Gas上限和Gas价格。

消息(Messsage)

以太坊的消息是合约账户发往其他账户(外部账户或合约账户)报文结构体,主要包括消息发送者、消息接受者地址、发送金额、数据域(若接收方为合约账户)和Gas上限。

Gas

由于以太坊为公有链设计,为了避免恶意程序无代价发动Dos攻击或滥用以太坊网络,参考比特币引入了经济概念,所有在以太坊EVM上的操作和存储消耗都需要Gas。

交易发送者设定Gas上限和Gas价格作为矿工打包费用。如果费用过低,矿工可以选择不打包交易到区块。

合约在执行过程中,如果当前代码执行以及子消息产生的代码执行发生的所有Gas消耗超过Gas上限,矿工依然可以获得打包费用,但是当前交易的所有状态都会被回滚。如果未出现Gas耗尽(gas overrun),交易成功执行,所有未消耗的Ether(以太币)依然会返回发送者账户。

矿工挖矿获得Ether,合约执行消耗Ether,形成天然的供求关系。Gas只与程序逻辑处理复杂度有关,将其与市场波动相关的Ether价格隔离开,通过发送者设定Gas Price的方式,可以对抗通货紧缩/膨胀。

合约(contract)

以太坊的合约即为合约账户,是以EVM字节码形式存储的代码(功能)和数据(状态)的集合体。它们以Patricia树组织,存储在区块链的账户地址上,账户可以相互发送交易或消息事件,在Gas上限内进行一次交易的图灵完备运算。交易发送者支付实际消耗Gas * 指定GasPrice的Ether给矿工作为费用,将此交易和结果打包到下一个区块上。智能合约的交互如下图所示。
智能合约间的交互

以太坊虚拟机(EVM)

以太坊虚拟机是智能合约的运行环境,是比JVM或Docker VM“沙箱”模式还严格的一种完全隔离的虚拟运行环境。运行在EVM中的合约代码无法访问网络、文件系统和其他进程,合约之间的访问也受到严格限制。EVM是基于栈操作的虚拟机,栈最大深度1024,每个元素32个字节,其指令集由最基本的算术、位、逻辑、比较、条件跳转、无条件跳转这些满足图灵完备的最小指令集组成,EVM可以发送消息调用其他合约,还可以加载目标地址的合约代码在当前合约上下文执行(callocode)

DApp(去中心化应用)

DApp直接关联起用户和服务提供方,即买卖双方的应用。以太坊提供多种语言版本的API客户端,并通过以太坊客户端接入网络,DApp基于这些API客户端,把需要共识的业务逻辑和数据以合约的形式部署到以太坊区块链上,并按照需要执行API调用操作。那些不需要共识的逻辑在DApp自身中实现,以降低运行成本。

API库语言项目地址
web3.jsJavaScripthttps://github.com/ethereum/web3.js
web3jJavahttps://github.com/web3j/web3j
NethereumC#.NEThttps://github.com/Nethereum/Nethereum
ethereum-rubyRubyhttps://github.com/DigixGlobal/ethereum-ruby

以太坊架构

作为分布式价值交换网络,以太坊要建模的是一个公有的、可以被世界上任何一个联网的人使用的状态机。这个状态机由交易驱动,在其上可以执行图灵完备的应用,可以自动在分布式不信任的互联网上达成共识。
P.S. 有关图灵完备的理解可参见:什么是图灵完备-知乎图灵完备-百度词条

以太坊遵从如下架构原则:

  • 三明治复杂度模型
    为确保以太坊网络底层尽量简单、以太坊的上层应用接口也尽量简单,将复杂度集中在中间层,如核心共识、高级语言编译器、参数序列化和反序列化脚本、存储数据结构模型、LevelDB存储接口和通信协议等。
  • 对应用自由无偏见
    不对用户发布的合约和发起的交易有任何限制或鼓励,本着“网络中立”的原则,以太坊“交易手续费”让过度使用网络付出相应的代价。
  • 协议和操作码通用性
    所有协议特性和EVM操作码都包含尽量少的语义含义,这样可以充分组合使用,满足未来更高级的语义用途。
  • 没有提供专门的特性
    通用性设计的必然结果就是平台的协议不提供任何特性。用户可以把这些特性通过智能合约的方式实现,如特定的合约代币(token)、侧链。
  • 有风险偏好
    对于存在引起风险的技术改变,如果可以带来很大的收益,如极大地提高出块速度、提高共识效率,都是可以接受的。

以太坊数据模型

RLP编码

全称:Recursive Length Prefix(递归长度前缀)
该算法可用来序列化任意嵌套的二进制数组,是以太坊主要的序列化编码算法。

序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象

编码对象基本元素(item)可以是一个字符串,也可以是由若干item组成的列表。

Merkle Patricia树

改进版Merkle Patricia树是以太坊主要的数据结构,用来存储键值对,可用于账户状态、交易列表、收据列表等类似字典(dictionary)的数据结构,并进行树形结构的数据表示和存储,对于插入、检索、修改、删除可以实现 O ( l o g ( n ) ) O(log(n)) O(log(n))搜索复杂度。

账户模型

区别于比特币的UTXO模型,以太坊对的数据模型更像用传统的数据库方式存储状态,状态包括账户余额和智能合约账户的各种状态,通过层层组装,最终将以太坊所有账户和对应的状态(包括合约存储子状态哈希)用Patricia树的方式组织成账户模型。

以太坊的所有账户(EOA和合约账户)都需要保存余额。另外,对于合约账户,还需要保存合约账户的各种状态值,把合约账户中所有要记录的状态和对应的值以Patricia树方式构建得到合约账户的状态存储根哈希值(storageRoot),对于外部用户账户EOA,这个值就是空字串。

以太坊会将所有账户的余额(balance),账户交易序列号(nonce),账户的状态存储根哈希值(storageRoot),合约代码哈希值(codeHash)组成的元组[nonce, balance, storageRoot, codeHash]进行RLP序列化编码的字符串作为value,以对应账户的20个字符账户地址作为key,再以Patricia树进行组织,计算出世界状态根哈希值,作为当前区块头哈希值的计算要素之一。

区块结构

一个区块由区块体[uncleHeaderList, transactionList]和区块头blockHeader构成。

交易列表(Transaction List)是当前打包进区块的所有交易。一个交易可以是外部账户的转账交易,也可以是合约部署交易,还可以是合约函数的执行交易。

区块头结构和生成过程如下图所示:
区块头结构和生成过程

比特币和以太坊系统比较

图灵完备性

  • 以太坊:引入了编程上图灵完备的智能合约功能,从而用户可以自己定义数字资产和流通的逻辑,通过以太坊虚拟机几乎可以执行任何计算
  • 比特币:不具有图灵完备性,只能支持比特币的转账

共识机制

都使用PoW(工作量证明)

数据模型

  • 比特币采用的是UTXO模型:
    UTXO,全称Unspent Transaction Output。
    每一笔交易都是由输入和输出两部分组成,环环相扣。除了Coinbase交易,普通的转账交易,其输入部分都是来自于上游的输出部分。也就是说,对于某一个账户地址来说,能有多少比特币可以转账,取决于他拥有多少可用的剩余的“输出”中的余额。
  • 以太坊采用的是账户模型
    由于在以太坊虚拟机上运行的程序非常复杂,每一步指令的运行都需要消耗Gas进而消耗交易发起者的加密货币,为了提高网络攻击成本,运行不成功的交易所消费掉的Gas不被返还。采用账户模型可以减小空间和时间复杂度。

货币发行机制

  • 比特币:
    • 总量上限2100万
    • 打包区块的矿工可以自行设定手续费,也可以仅设定为默认的必要费用——0.00001BTC/KB
    • 平均出块时间为10分钟
  • 以太坊:
    • 无区块上限限制,无以太币总数上限限制
    • 引入Gas,每一个交易都需要包含gas上限和为每个gas支付费用的单价,矿工可以选择接纳交易和收取费用
    • 平均出块时间为20秒

区块结构

  • 以太坊
    在以太坊中,无效块(产生分叉后被忽略的合法区块)被称为叔块(uncle block)。对于无效块矿工,也会给予一定奖励回报,但是少于有效块矿工的奖励。
  • 比特币
    无效分叉将被舍弃

个人对区块链系统设计的看法

安全性

区块链系统的一个弱点是:“它建立在大多数人群总是诚实的假设之上”,故而存在一个51%攻击问题。
此外,智能合约的安全漏洞也是一个问题:区块链上的智能合约是一种全新的计算范式。智能合约一经部署就难以修改,其执行也是自动执行,不受人为干预。引入,如果智能合约有漏洞,就很难防范黑客的攻击。在实践中要提高智能合约的安全性,一定程度上与程序员的编程能力相关。

给出以下建议,在实际编程中尽量遵守,你的合约将更具安全因素
1)更完善的编写测试。
2)建议提供容错和自动错误赏金。
3)为最糟糕的情况做准备。智能合同中的漏洞,应该尽可能让它安全地恢复。
4)添加额外的安全机制。合同的管理者可应急性地冻结合约。
5)限制合约资金存放金额,提高攻击者成功的门槛。
6)不要从零开始编写你所有的代码,尽可能参考成功者的合约。
7)注意开发平台的限制。

共识机制

目前比较广泛采用的PoW共识机制显然在一定程度上造成了算力的浪费,受课堂上老师讲课的启示,个人认为也许可以尝试将这些算力用于解决一些NP难问题或者其他实际需要解决的消耗较大算力的问题。

交易效率

在区块链系统中用TPS指标衡量一个系统的交易效率。

TPS可基于测试周期内完成的事务数量计算得出。一个系统吞吐量通常由TPS、并发数2个因素决定。每套系统的这两个值都有一个相对极限值。在应用场景访问压力下,只要某一项达到系统最高值,系统的吞吐量就上不去了,如果压力继续增大,系统的吞吐量反而下降,原因是系统超负荷工作,上下文切换、内存等等其他消耗导致系统性能下降。

根据这个指标,以比特币为例,其TPS约为7,以太坊大概为20,换算到一天24小时的概念,大概相当于比特币30万笔/天,以太坊45万笔/天。
根据Blockchain的数据,投资者大概需要平均78分钟来确认一次比特币交易。个别时段,这一平均时长一度高达1188分钟,也就是将近20小时。这将大大降低用户使用比特币的兴趣。

参考资料

[1] 邹均,于斌,庄鹏,邢春晓.区块链核心技术与应用[M].北京:机械工业出版社,2018
[2] Narayan Prusty.区块链项目开发指南[M].北京:机械工业出版社,2018
[3] 袁勇,王飞跃.区块链技术发展现状与展望[J].自动化学报,2016,42(04):481-494
[4] Wood, Daniel Davis. “ETHEREUM: A SECURE DECENTRALISED GENERALISED TRANSACTION LEDGER.” (2014).

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值