深入以太坊智能合约开发
上QQ阅读APP看书,第一时间看更新

第1章 快速了解以太坊

从2013年年底Vitalik Buterin发布《以太坊白皮书》(Ethereum White Paper)以来,以太坊逐渐被世人认同为区块链2.0的代表。以太坊与区块链1.0时代的代表比特币(bitcoin)最大的不同在于应用的目的和范围。比特币区块链由于非图灵完备的脚本以及单个区块存储空间的限制,主要用于追踪比特币的所有权。然而以太坊是具有图灵完备的编程语言、更高效的共识机制、支持更多应用场景的智能合约开发平台,可以为各种去中心化应用(Decentralized App,DApp)提供运行环境。

一般来说,实际生活中的任何商品、服务、管理或经济活动都可以在以太坊平台上使用代码表示,实现去中心化(decentralized)以及通证化(tokenized),从而进行交易。而且相比于传统的方式(如使用借记卡支付等),以太坊在提供交易的安全性、抗审查性的同时,花费的成本更低。

本章内容主要参考《以太坊白皮书》以及Wiki,主要目的是带领读者快速了解以太坊的相关概念、发展历史以及相关的开源项目。阅读本章之前最好先对比特币区块链的概念以及运行原理有大致的了解,从而与以太坊进行对比理解。

1.1 以太坊是什么

根据《以太坊白皮书》(A Next-Generation Smart Contract and Decentralized Application Platform,原文参见:https://github.com/ethereum/wiki/wiki/White-Paper)的描述,我们可以对以太坊进行如下定义:

以太坊的意图是为去中心化应用程序构建一个可替代的协议,这是一种在大规模使用的去中心化应用程序和为特定目的设计的简单的低频应用间进行了必要权衡的协议,同时考虑了应用间的高效交互能力。以太坊通过一个抽象的基础设施层来实现这个目标:一个内置了图灵完备编程语言的区块链系统。在这个系统中,任何人都基于他们自己的要求编写智能合约和去中心化应用,他们可以自定义权限控制、交易数据格式以及状态转换函数。在这个平台上,我们可以构建基于密码学原理构成的自主对象,也就是所谓的智能合约,它在比特币脚本系统能实现的功能之上增加了图灵完备、价值感知、区块链感知和状态保存等特性。

用最简单的一句话来说:以太坊就是一个基于区块链的智能合约平台。

这里有两个关键的基本概念:区块链和智能合约。

区块链(blockchain)的概念出自比特币协议,本质上是一个基于P2P网络(点对点网络)的分布式账本系统,交易数据被以所谓的“区块(block)”进行打包,在全网节点中被顺序执行并通过工作量证明(proof of work)共识算法进行数据同步和验证,是一种已经被证明安全可靠的分布式底层技术。它具有去中心化、去信任(无须信任)、开放自治、极难篡改、极难伪造以及其他一些技术特性。关于区块链,在很多书籍、资料中都有详细介绍,这里不再过多展开。

而所谓智能合约(smart contract)其实并不是一个非常新的概念。早在1994年,美国计算机科学家尼克·萨博(Nick Szabo)就在他的论文中正式提出了智能合约的概念,并且他自己也尝试做了实验性的软件系统,但并没有得到工程上的验证,或者说当时还没有发现可以真正支撑相关特性的技术方案。直到2013年年底《以太坊白皮书》的出现,才使这个概念重新进入大众的视野,而以太坊这四年来总体稳定地运行,也从工程上证明了智能合约是可以实现的。

那什么是智能合约呢?

尼克·萨博曾举过一个现实世界中的例子来说明智能合约,他用的是ATM或者自动售货机。很容易理解,比如ATM,我们要从自己的账户中取若干现金,那我们需要告诉ATM我们的账号(无论以何种方式),然后输入我们要提取的金额,ATM则会根据我们账户余额的情况判断是否能给出足额的现金。对于自动售货机,也是类似的。售货机内的商品肯定是明码标价的,我们选想要的商品,然后付钱,机器会把商品“吐出”,并找零;商品不足或者支付金额不足时会给出相应的反馈。而与此类似的功能,目前都是可以在以太坊上通过智能合约实现的。比如我可以将合约当作我自己的一个现金钱包,有需要的时候从合约中提取相应的金额,余额不足时合约也会产生错误;又比如,我们可以通过合约来进行虚拟资产的售卖,就像2017年的ICO(Initial Coin Offering)风潮那样,通过智能合约来进行token的发行、售卖等操作,整个过程都可以是公开透明且自动完成的。这就是智能合约。

在以太坊中,就是通过把基于区块链的交易,拿到一个具有自己的指令集、自己的存储机制(临时存储和永久存储)的可编程虚拟机中来执行,来实现智能合约的。这个虚拟机就是以太坊协议的最大创新,就是所谓的“以太坊虚拟机(Ethereum Virtual Machine,EVM)”。所以,以太坊也可以看作是“区块链+EVM”。EVM就是前面以太坊的技术定义中提到的支持图灵完备编程语言的基础设施,我们可以通过特定的高级语言,比如Solidity,来自定义地编写智能合约。在本书的第7章中,我们将完整、详细地讲解以太坊协议(EVM)的原理和实现细节,这里就不再做过多展开介绍了。

最后需要解释的就是上文中以太坊的技术定义里多次提到的去中性化应用程序。DApp可以简单地理解为以智能合约而不是以传统的、由个别组织和公司控制的以中心化的服务器(server)为后端的应用程序,DApp的叫法是为了与那些基于客户端-服务器(client-server)架构或者浏览器-服务器(browser-server)架构的所谓中心化应用程序相区别。目前来看,根据业务需求,仅将部分应该由智能合约来处理的逻辑放到类似于以太坊这样的去中心化智能合约平台中,而其他无须做这种改动的业务仍然基于传统的服务器架构实现的所谓混合架构(hybird mode)的DApp具有更大的现实性,也更具有工程可行性。在本书中也有关于DApp开发的具体实例供读者参考,在此也不再过多展开了。

如今,以太坊已经成为程序员最为青睐的智能合约开发平台,这离不开社区为以太坊贡献的优秀的开源DApp开发工具和框架,例如:目前最受欢迎的以太坊开发框架Truffle,可以在本地提供完整的合约编译、部署、测试功能;以太坊的JavaScript API——Web3.js,能够帮助开发者使用HTTP或者IPC连接轻而易举地与本地或远程的以太坊节点交互;在币市上,排名前100的币中有94%都是按照以太坊的“ERC-20 tokens”标准进行的ICO。

接下来使用一个简单的众筹示例来展示以太坊是如何运行的,以及以太坊在这个示例中解决了什么问题。目前世界上最大的众筹公司Kickstarter,在每次众筹过程中,投资者都会将资金交给Kickstarter管理。如果众筹金额达到了创业团队设置的目标,那么Kickstarter应该将资金转交给团队,否则将投资者的资金按原路返还。然而,在这个过程中,无论是投资者还是创业团队,都完全将信任建立在Kickstarter上。目前在以太坊上已经有很多类似的应用,如图1-1所示,创业团队可以将众筹合约部署在以太坊上,通过EVM由以太坊上的所有节点执行。投资者向合约发送以太币(ether),合约将记录资金的变化,同时也会记录发送者的地址,以便将资金退回。

当众筹期限截止时,如图1-2所示,如果实现了众筹目标,合约将自动把资金发送到创业团队的账户,否则,合约将自动把资金退还到投资者的账户。合约的代码以及运行过程中的每一次状态改变都是公开透明的,没有任何机构或个人能够改变合约的执行结果。

图1-1 以太坊运行示例

图1-2 众筹期限截止时资金的转移

1.2 以太坊的历史和发展路线图

以太坊的联合创始人Vitalik Buterin早在2011年就痴迷于比特币背后的技术,那时他年仅17岁。他活跃于各大比特币社区,不仅作为程序员为比特币的发展做出了重要贡献,而且与他人联合创办了Bitcoin Magazine。然而他逐渐认识到了比特币区块链的局限性,他认为区块链除了可以用于数字货币的交易,还可以解决更多实际的问题,于是他开始考虑如何实现自己对区块链的愿景。

在2013年年底,Buterin发布了《以太坊白皮书》,以太坊正式诞生。他凭借自己在开源社区的影响力,吸引了大批优秀开发者加入以太坊的开发队伍。2014年4月,Gavin Wood博士发布了《以太坊黄皮书》,其被称为以太坊技术“圣经”,详细描述了以太坊技术细节,以及EVM的运行原理,为以太坊之后的快速发展打下了坚实基础。2015年7月,以太坊第一个正式版本“边境(frontier)”发布,从此以太坊进入高速发展期,越来越多的开发者加入其中。

根据Etherscan提供的数据,如图1-3所示,从以太坊上线时算起,截至2018年6月,整个以太坊网络处理的交易数量总计超过了750万次,基本呈指数型上升的趋势。其中,在2018年1月4日,达到了交易的顶峰,网络在24小时内处理了130万次交易。

图1-3 以太坊交易数量图

发展至今,以太坊网络中拥有唯一地址的节点数已经超过3500万,如图1-4所示,从以太坊上线到2018年1月,节点总数一直呈指数级增长,其中,2018年1月5日当天为增长速度的最高峰,增加了35万节点,之后基本以每天增加10万节点的速度线性增长。

从各个国家和地区的分布情况来看,根据Ethernodes提供的数据,共有超过17000个以太坊节点分布在六大洲,这使得以太坊成为去中心化程度最高的区块链。拥有以太坊节点数最多的10个国家如表1-1所示。

表1-1 拥有以太坊节点数排名前10的国家

图1-4 以太坊网络中拥有唯一地址的节点数量图

以太坊的发展规划主要分为4个阶段,每个阶段都会以硬分叉(hard forking)的方式进行。以下是这4个阶段的基本情况。

第一阶段:边境(frontier)

以太坊的第一个正式版本,2015年7月30日发布。这个版本的以太坊还十分简陋,但已经可以执行智能合约,支持矿工挖矿,也支持以太币的交易。在这个版本上,用户首次可以购买以太币,并在以太坊上测试自己的DApp。

第二阶段:家园(homestead)

“家园”于2015年3月14日发布,这个版本作为“边境”的后续版本,核心开发人员对其进行了大量的优化改进和广泛的测试,其安全性和稳定性已经受到开发者和用户的认可。但这个阶段仍处于以太坊的测试和发展阶段,在发布之后依然暴露出许多问题。

第三阶段:大都会(metropolis)

这一阶段的目标是实现更加易用、轻量级、速度更快、更安全的以太坊,给开发者在其上开发DApp提供更大的灵活性。此阶段分为两个版本,分别命名为“拜占庭(byzantium)”和“君士坦丁堡(constantinople)”。其中,“拜占庭”版本的硬分叉发生在2017年10月16日,而“君士坦丁堡”版本的升级时间预计在2018年完成,具体时间待定。

第四阶段:宁静(serenity)

以太坊的最终版本,目前规划在2019年完成升级。届时,以太坊最终将从工作量证明的共识算法完全转变成持有量证明算法(proof of stake),整个网络也将更快、更高效、更稳定、更安全、对用户更加友好,成为真正的主流区块链。

1.3 以太坊的基本概念

1.3.1 账户(accounts)

在比特币中,用户控制的只是地址,不存在实际账户的概念。用户通过带有自己地址的作为输出的UTXO的金额计算出自己的余额。这就类似于现实生活中使用的纸币,每次交易都会消耗整数个的UTXO,并且产生新的UTXO(找零)。然而以太坊的核心就在于拥有账户的概念,每个用户都会拥有两类账户:外部账户(Externally Owned Accounts,EOAs)和合约账户(Contract Accounts,CAs)。在一般情况下,以太坊中的账户指的是外部账户。

以太坊之所以设计外部账户和合约账户,是因为在以太坊中,账户被认为是状态对象:其中外部账户具有余额(balance),合约账户不仅具有余额,而且还有存储。所有账户的状态的集合就是整个以太坊网络的状态,每次产生区块的过程都是以太坊状态的一次更新,需要全网的节点达成共识。因此,账户对于用户之间的交易以及以太坊之上智能合约的执行都具有至关重要的意义。

以太坊的外部账户由用户创建,通过公钥密码学生成一个密钥对,唯一对应一个外部账户。用户在使用外部账户发送交易时,交易信息会被账户对应的私钥签名,从而使得EVM可以安全地认证交易发送者的身份。可以想象,如果以太坊只有外部账户的话,那它的功能也就只局限于外部账户之间发送以太币交易,也就跟比特币区块链差不多了。用户可以任意创建外部账户,而不需支付任何费用,而且外部账户之间的以太币交易也不消耗费用。

合约账户则是由外部账户创建的,由相应的外部账户所有,但只受到合约中的代码控制。一个合约账户对应一个合约代码。合约账户中也可以有以太币,这是为了将以太币暂存,等到合适的条件或时间再将以太币发送给其他合约或外部账户。合约账户中的代码不会自主执行,需要其他账户(外部账户或合约账户)发送交易(transaction)来触发代码执行。合约账户拥有属于自己的链上存储空间,代码以及代码每次执行后的状态都会存储在链上。合约账户的创建需要消耗一定的以太币,这是因为创建合约账户就是要部署新的合约,因此需要消耗一定的存储空间存储合约代码。而且由于每次调用合约账户都会触发代码的执行,激发全网节点进行共识,因此合约账户跟任何其他账户发生交易的时候都需要消耗一定的代价。

从表1-2中可以清楚地看出外部账户跟合约账户之间的共同点和区别。

表1-2 外部账户跟合约账户的异同

1.3.2 合约(contracts)

以太坊中的合约也称“智能合约”,但实际上就是一串非常简单的代码,并不具有智能性。在英文中称其为“smart contracts”更多的是取单词“smart”中“精巧的”之意,准确来说不应该翻译成智能合约,但按照业内形成的习惯,本书依旧会采用“智能合约”或者“合约”统一作为对“smart contracts”的翻译。

在以太坊中,一个合约实际上是一串代码的集合,包括代码中的各种函数以及代码运行过程中产生的各种状态。被部署的合约以EVM字节码(bytecode)的形式存储在区块链上,一个合约唯一对应一个合约地址。

幸运的是,合约开发者并不需要了解EVM的原理就可以编写自己的合约。以太坊支持多种高级编程语言,开发者可以用很少量的代码编写合约,经过专门的编译器将合约编译成字节码之后,部署到区块链上。以下是以太坊支持的几种用来编写合约的高级语言。

·Solidity:目前最受欢迎也是使用最广泛的合约编程语言,语法跟JavaScript十分类似,也是官方最为推荐和支撑力度最大的编程语言。在后文的智能合约实战部分,将全面介绍如何使用Solidity编写智能合约。

·Vyper:以太坊平台上目前最年轻的合约编程语言,目前仍处于试验阶段。Vyper的设计初衷是简化合约编写流程,减少合约执行过程中的gas消耗,增强合约安全性。Vyper的逻辑类似于Solidity,但在句法上更像Python,它的出现意味着以太坊彻底抛弃了原来基于Python的开发语言Serpent,同时为开发者提供了对于Solidity的一个替代选择。

·LLL(Lisp Like Language):类似于汇编的略微低级的合约编程语言,适宜完成一些简单、直接的任务。

1.3.3 交易(transaction)和消息(message)

在以太坊中,同时具有交易和消息两个概念。这两个概念有的时候表示的意思相同,但在一些特殊情况下却要区别对待。在这里我们将简单介绍两者的相同点和不同点。

“交易”和“消息”都在《以太坊黄皮书》中有明确的定义。“交易”在《以太坊黄皮书》中的定义是:“由外部账户签名的一串数据。既可以表示一个消息,也可以表示一个新的自治对象。交易记录在区块链的每个交易中。”这里的自治对象指的就是合约。简单来说,一个交易有可能表示发送一个消息,也有可能表示部署一个新的合约。一个交易会被广播到整个网络中,会被矿工处理后记录在区块链上,在这个过程中会消耗以太币。

“消息”在《以太坊黄皮书》中的定义是:“两个账户之间发送的数据(data)和值(value,即以太币)。消息既可能由自治对象产生一些确定性操作时产生,也可能由交易在数字签名时产生。”这里的意思是一个消息就是账户之间传递的数据和一定数量的以太币。消息有可能是在合约之间交互的时候产生,也有可能由交易产生,是一种内部的参数传输,不会发布在区块链上。

简而言之,交易都会在区块链上记录,而消息是发生在EVM内部的参数传输,不会显示在区块链上。

1.3.4 气(gas)

以太坊作为一个“世界计算机”,在执行每次操作的时候都会消耗一定的资源(计算、存储、内存等),因此以太坊的使用者想要让以太坊为其工作,就要向网络中的矿工支付一定的费用。由于计算机执行每次任务消耗的资源量几乎是恒定的,用户也希望自己支出的费用不会因为以太币价格的波动而有太大的变化。于是,gas作为以太坊中一种特殊的工作量计量单位应运而生。

gas,顾名思义,可以很确切地将其比喻成以太坊世界的“燃料”,是以太坊生态系统的命脉,以太坊中的一切交易都要消耗一定量的gas。比如在现实生活中,我们想要让我们的汽车一直运转,就要时不时地去加油站加油,并需要按照加油的量支付相应的费用。类比到以太坊中,汽车就是我们的合约,汽油的计量单位就是gas,加油站就是矿工。

虽然矿工收取的是gas,但gas并不能在以太坊中交易,更不能在以太坊之外流通,因此矿工需要将收到的gas转换成以太币作为收益。与gas机制相关的几个概念有:gasPrice、gasCost、gasLimit,以及gasFee。以太坊通过一系列机制保证在gas兑换成以太币的过程中,gas的价值不会发生太大的变化。

1.gasPrice

gasPrice表示用户愿意支付的gas的价格,即每单位的gas可以兑换的以太币数量(eth/gas)。为了保证gas价值的稳定,gasPrice会根据市场的波动而一直变化,保持用户愿意支付的价格与矿工能够接受的价格的平衡。换句话说,以太坊的矿工会优先打包gasPrice高的交易,如果gasPrice的值过低,那么这个交易可能要等很久,甚至永远不会被打包。根据Etherscan给出的数据,可以得出gasPrice的平均变化图,如图1-5所示。

图1-5 gasPrice平均变化图

2.gasCost

gasCost一般是恒定的值,表示以太坊的节点在执行某种操作时固定花费的gas数量,也就是表明每种操作所花费的成本是恒定的,几乎不会发生变化,从表1-3中可以查看常用的一些操作所花费的gas数量。

表1-3 常用操作花费的gas数量

3.gasLimit

gasLimit指的是用户愿意为某个交易花费的最高gas数量,当实际消耗的gas达到gasLimit的值的时候,交易就会终止。换句话说,就是给一个交易能够消耗的gas数量设定一个上限。设计gasLimit的目的主要是为合约的执行提供一种安全机制,防止因为合约中的漏洞导致的对gas的无限消耗,可以将其类比成汽车油箱的容量上限。一个标准的发送以太币的交易所设定的gasLimit一般是21000。

4.gasFee

gasFee是指在执行一个交易或者一段合约代码的过程中实际需要支付的gas数量。一个区块的gasFee可以用来推测出一个区块消耗的计算量、所包含交易的数量以及一个区块的大小。gasFee最终都会支付给矿工。

1.4 以太币(ether)

以太币是类似于比特币的一种加密货币,在以太坊的健康可持续运行方面起着至关重要的作用。以太币不仅可以作为一种数字资产在以太坊上交易,更重要的功能是给以太坊中的矿工支付费用(通过兑换成gas的方式间接支付给矿工)。

在1.1节中我们已经了解到,以太坊致力于构建一种分布式互联网,为新型应用程序DApp提供基础运行环境。尽管以太坊不被任何第三方所有,但以太坊的运行也不是免费的,需要通过一种激励机制吸引全世界的矿工加入,为以太坊中发生的所有交易提供打包服务。跟比特币区块链通过比特币奖励矿工的方式类似,以太坊中奖励以太币。

1.4.1 以太币的发行

2014年8月,以太坊在主网上线之前,展开了为期6个月的以太币“预售(presale)”活动,在预售期的前两周,用户可以以“1比特币=2000以太币”的比率兑换以太币,之后兑换比率线性降低到“1比特币=1337以太币”。预售活动结束后,总计募集了大约6000万以太币,其中1200万以太币用作以太坊开发资金,其余大部分都分配给了以太坊的早期贡献者、开发者,以及“以太坊基金会(Ethereum Foundation)”。

以太坊上线后,矿工每挖到一个区块(大约15s)会获得5个以太币的报酬,即挖矿奖励(mining reward)。有些矿工虽然也挖到区块(找到了PoW的解),但他们的区块可能因为网络原因没有被添加到区块链上。此时,他们可能仍然会获得2~3个以太币的报酬,这种奖励称为“旁系奖励(uncle/aunt reward)”。在拜占庭版本更新后,挖矿奖励和旁系奖励分别降低到了3个以太币和0.625~2.625个以太币。

根据2014年预售时各方商定的条款,每年以太币发行的上限是1800万,这个数字大约是最初发行量的25%。

1.4.2 以太币的单位

以太币的基础单位称为wei,其他单位都是从wei衍生出来的,例如Kwei、Mwei等,而且这些衍生出的单位都有独特的名字,一些源自为计算机科学和加密货币的发展做出杰出贡献的人的姓氏。表1-4列出了以太币各个单位的名称以及换算关系。

表1-4 以太币单位换算关系

1.4.3 以太坊挖矿

以太坊中的“挖矿”跟现实世界挖掘金矿类似,只不过矿工获取的是以太币,而不是金矿。矿工在付出算力和电力挖矿的同时,实际上维持了整个以太坊网络的安全运行。为了补贴和奖励这些矿工,以太坊中每有一个区块生成,发布该区块的矿工将获得一定数量的以太币作为奖励。在以太坊中,挖矿是目前发行以太币的唯一方式,也是人们获得以太币的主要方式(还可以通过交易换取以太币)。

以太坊中之所以存在“挖矿”和“矿工”的概念,是因为以太坊与比特币区块链一样,采用工作量证明算法(Proof of Work,PoW)实现全网共识。工作量证明算法的核心是矿工在将交易数据打包进区块的时候,需要计算一个奇异值,使得整个区块的哈希值满足某个条件。由于哈希算法的特性,网络中的节点在计算这个奇异值的过程中,没有比逐一枚举更优的策略,然而验证奇异值是否满足条件只需要一次计算即可完成。找到符合条件的奇异值的时间与条件设置的难度以及节点的算力有关,因此,每个节点都有机会获得发布区块的权利,但算力更高的节点最终胜出的概率更高。除此之外,还可以通过调整条件设置的难度来控制全网产生一个区块的平均时间,在以太坊中,目前区块产出的平均时间是15s。

1.5 以太坊测试网络

和大多数区块链网络一样,以太坊网络也分为主网(mainnet)和测试网(testnet),彼此相互独立,为不同目的服务。

以太坊的主网即以太坊实际的“生产环境”。在主网上,以太币具有实际的价值,每次以太币的交换以及智能合约的执行都意味着实际价值的转移。测试网则是为了给开发人员测试新的网络特性,以及测试为智能合约的运行效果提供服务的“测试环境”。测试网中的以太币不具有实际价值,测试人员可以给自己的账户设置任意数量的以太币进行测试,而不用消耗实际的以太币。任何组织和个人都可以根据自己的需要搭建公开或私有的测试网络。以太坊官方发布的测试网络的发展历程如下。

(1)Olympic Testnet:Olympic Testnet是跟随以太坊的第一阶段“边境”发布的测试网络,在2015年年初发布,不到半年就被Morden Testnet取代了。

(2)Morden Testnet:Morden Testnet取代Olympic Testnet之后被称为以太坊第一个真正的公开测试网络,从2015年7月一直运行到2016年10月。然而由于区块链逐渐臃肿之后导致的同步时间过长,以及Geth客户端和Parity客户端共识不一致等问题,Morden Testnet被重建,之后改名为Ropsten Testnet。

(3)Ropsten Testnet:Ropsten Testnet服务于以太坊的第二阶段“家园”,于2016年年末发布,是一个能够跨客户端运行的测试网,直到2017年2月都在正常运行。在当时发生了一起针对Ropsten Testnet的恶意攻击事件,攻击者将gasLimit的正常值从470万调整到了90亿,导致网络中充斥了大量的巨型交易数据。大约过了一个月的时间,Ropsten Testnet才恢复正常。

(4)Kovan和Rinkeby:Kovan和Rinkeby都采用了权威证明算法(Proof of Authority,PoA)进行共识,只是分别服务于Parity客户端和Geth客户端。在这两个测试网络中,以太币的发行由受信的第三方控制,而不是矿工。这些受信的第三方一般是参与以太坊开发的区块链公司,致力于解决以太坊测试网中存在的问题。

1.6 以太坊客户端

以太坊客户端是一个宽泛的概念,凡是能与其他以太坊客户端通信,而且能够解析和验证以太坊网络中传递的各种交易消息(包括合约代码等)的节点都可以称之为以太坊客户端。主流的客户端应该也会提供创建交易以及参与挖矿的功能。

得益于Gavin Wood博士撰写的《以太坊黄皮书》,开发人员可以使用可行的编程语言在大多数平台上开发以太坊客户端,这也造就了以太坊客户端百花齐放的局面。尽管不同的客户端由不同的团队创建,使用不同的编程语言实现,但它们都遵从一样的协议。

目前,市面上主要有6个使用较广泛的以太坊客户端,分别用不同的编程语言实现。其中,Geth和Parity是目前最流行的两个以太坊客户端,所拥有的节点占有率远超其他语言实现的客户端。Geth使用Go语言实现,被公认为是以太坊客户端的“官方”版本,目前拥有最多的节点占有率。Parity则使用相对小众的Rust语言实现,其作者就是《以太坊黄皮书》的作者GavinWood,目前占有大约30%的节点。

1.7 以太坊生态系统全景扫描

以太坊诞生之后,Gavin Wood首次提出Web3的概念,即利用区块链技术将目前中心化的应用和服务搭建在去中心化的协议之上。然而,想要实现如此宏大的愿景,单凭以太坊的EVM远远不够,还需要搭建许多外围的基础设施,围绕以太坊搭建全新的生态系统。本节将简单介绍目前最受关注的Swarm、Whisper以及ENS(Ethereum Naming System)3个项目,以使读者对以太坊的生态系统建设有大致的了解。

1.7.1 Swarm

Swarm项目由以太坊的核心团队开发,是一个分布式的存储平台,提供内容分发服务,在Web3架构中充当最基础的一层。Swarm的终极目标是为以太坊提供去中心化程度和冗余度足够高的公共数据库,尤其是用来存储和分发区块链上的数据。具体来说,Swarm致力于为DApp提供一系列基础服务,包括但不限于消息传播、数据流、点对点审计、数据库、存储保险、易变资源更新等。

从终端用户的角度来说,Swarm的突出特点不止体现在将数据分散式存储,更重要的是Swarm能够依靠以太坊区块链的优势,给用户提供一种具有抗DDoS攻击、抗审查、永不宕机、容错性高的分布式存储服务。以太坊基金会采用和运行以太坊测试网络类似的方式运行着一个Swarm的测试网络。所有人都可以通过在他们的服务器、台式计算机、笔记本式计算机或者移动设备上运行Swarm节点来加入网络。

1.7.2 ENS

ENS基于以太坊的命名转换服务,主要功能是将形似“0xbfb2e296d9cf3e593e79981235aed29ab9984c0f”的以太坊钱包地址或者智能合约地址转换成易读的“myname.eth”形式。ENS另外还有一个功能,是提供有关命名的元数据,例如智能合约的ABI或者用户的whois信息。

从功能上看,ENS非常类似于我们熟悉的DNS(Domain Name Service),只不过ENS所要转换的并不是网站的IP地址,而是以太坊账户地址、合约地址以及以太坊中其他的身份信息。ENS同样也是使用“.”将域名分级,每一级域名的拥有者对其下的子域名都有控制权。ENS的顶级域名,例如“.eth”和“.test”,由智能合约控制,合约中说明了其下子域名的分配规则。

由于ENS的实现完全依托于以太坊区块链,故ENS跟DNS的架构完全不同。ENS包含两个主要部分:注册器和解析器。注册器由一个单独的中心合约组成,记录了所有的域名以及每个域名对应的所有子域名的信息。解析器则负责从域名到地址的实际解析工作。

1.7.3 Whisper

Whisper同样由以太坊的核心团队开发,代码直接嵌在以太坊客户端中。简单来说,Whisper是用于以太坊上DApp之间相互通信的协议。Whisper的设计并不是为了提供面向连接的系统,也不是为了帮助网络中某一对通信节点简单地传送数据。Whisper专为简单高效的广播通信设计,同时也适用于底层异步通信。典型的应用场景如下:

·需要节点之间互相发布一些信息,且希望这些信息具有一定时效性的DApp。例如,数字货币交易所可能需要这种应用来记录某人以某一汇率出售电子货币的报价信息。

·需要提供节点之间非实时的线索提示或者一般性通信的DApp。例如,小型聊天室应用。

·需要节点之间相互协作才能进行交易的DApp。例如,在数字货币交易所中,可以使用这种DApp在创建交易之前协调多个报价信息。

Whisper的设计很大程度上考虑了对用户隐私的保护,然而这种保护需要消耗节点相当大的性能。在最安全的运行模式下,Whisper在理论上可以提供100%的隐匿度。用户在使用Whisper的同时也可以自定义隐私级别,作为隐私保护与性能消耗之间的权衡。

Whisper是一种底层协议,不同的DApp可以根据特定的需求调整对于Whisper的使用设置,因此它也被称为DApp的发展基石。Whisper目前还在开发当中,处于PoC(Proof of Concept)的第二阶段,已经可以在现有Geth和Parity版本上使用。因此,至于将来的发展,Whisper的很多特性还可能发生变化。

1.7.4 其他相关项目

1.Oraclize

以太坊作为一个DApp的开发平台,其上的许多应用都需要从万维网上读取数据,例如,金融类的应用需要资产的价格数据;保险类的应用需要天气的数据;游戏类的应用需要生成随机数,等等。然而,从某种程度上来说,区块链是一个相对“封闭”的网络,无论是比特币的脚本(script)还是以太坊的智能合约,都无法从区块链外部直接读取数据。Oraclize的诞生解决了这个问题。

Oraclize在区块链的世界里充当“数据搬运工”的角色,它为Web API与DApp之间建立了可靠的连接。当以太坊上的智能合约需要抓取外部数据时,它需要向区块链上Oraclize合约发送一个查询(即合约调用),指定数据源以及相关参数。Oraclize的服务端会不断扫描新传入的查询,每当找到一个新的查询时,服务端会根据查询制定的数据源及参数抓取数据,将其打包后调用合约的_callback方法将结果返回。

在整个数据传输过程中,Oraclize并没有打破区块链自身的安全模型,也没有更改数据源的格式和服务。Oraclize的解决方案是为所有从数据源处获取的数据做真实性证明,证明文件可以跟返回的数据一起获得。关于Oraclize实现真实性证明的细节以及Oraclize服务的使用方法可以从官网www.oraclize.it获取。

2.IPFS

IPFS(InterPlanetary File System,星际文件系统)是一种新型的超媒体分布式存储、传输协议,旨在构建更快、更安全、更自由的互联网。与传统的HTTP不同,IPFS索引数据的方式并不是依赖于服务器的IP地址,而是数据的哈希值。除此之外,IPFS最大的优势体现在数据的存储是分布式的,从而有效地避免了单点失效,也在很大程度上降低了DDoS攻击的风险。

IPFS本身在技术上没有独特的创新,IPFS的主要贡献是将多种市面上成功的P2P技术融合在一起,形成一个单独的分布式系统,从而达到“1+1>2”的效果,这些技术主要包括:哈希表(Distributed Hash Tables,DHTs),文件共享系统——BitTorrent,版本控制系统——Git,自认证文件系统——SFS。IPFS将每个文件的哈希值作为文件的索引,不但可以快速检索文件,而且可以实现在全网剔除冗余数据,减少对存储空间的需求。IPFS使用的数据结构是Merkle DAG(与Git存储文件的数据结构相同),因此可以记录文件的所有变更记录,并且可以轻易回溯到文件的某一历史版本。每个IPFS节点除了存储本地所需的数据之外,还会存储一张记录数据存储位置的哈希表,以便进行文件的查询和下载。

IPFS本身并不是为区块链而设计的,但其与生俱来的去中心化属性以及存储文件的数据结构可以用作区块链的链下存储,很好地解决了区块链本身存储容量受限的问题。目前,在以太坊平台上引入IPFS作为链下存储的一般方案是,将数据本身存入IPFS,获得数据的索引哈希值,之后将该哈希值存入区块链中。

1.8 本章小结

在本章中,我们带领读者初步窥探了以太坊的世界,主要介绍了以太坊相关的概念以及以太坊目前的生态建设情况。一些读者朋友可能在初次阅读本章之后仍然会对一些概念感到有些模糊,不过没有关系,请读者朋友们继续阅读后续的实践以及原理剖析的章节,很多概念都会在后面经常出现,到时回到本章再次阅读,相信读者会有更进一步的理解。