王 群,李馥娟,王振力,梁广俊,徐 杰
江苏警官学院计算机信息与网络安全系,南京 210031
数学为密码学的研究奠定了坚实的理论基础,数学领域的研究在推动了密码技术发展的同时,密码技术的应用也使一些基础数学问题的研究取得了突破。与此同时,密码学及相关学科领域一些成熟的技术在随着应用环境和需求变化进行深度融合后,摧生了一系列新的技术应用,区块链便是其中之一。
2008年,中本聪(Satoshi Nakamoto)在其论文“Bitcoin:a peer-to-peer electronic cash system”[1]中首次提出了一种以区块链(blockchain)为底层技术的比特币(Bitcoin)数字货币,并实际运行了“挖矿”过程,以此证明了论文中提出的比特币理论体系。比特币开创了去中心化数字货币的先河,比特币系统基于区块链这一特殊类型的分布式数据库,通过挖矿激励机制与货币发行之间的关联,再利用共识机制实现交易的确认和比特币在数据库上的安全转移,在不借助任何第三方可信机构支持的前提下,实现了相互间不需要信任的人与人之间货币的交换。当区块链技术在比特币中取得了巨大成功后,Buterin于2013年12月在比特币基础上提出了以太坊(Ethereum)概念[2],将其定义为一个除继承了比特币中数字货币(在以太坊中称为以太币(Ether))功能外,还提供了图灵完备(即能够模拟任何图灵机)的编程语言,将智能合约(smart contract)应用到区块链系统。智能合约与区块链的结合,一方面使区块链借助智能合约的可编程性来简化对分布式节点操作的复杂性,另一方面使智能合约借助区块链的去中心化机制在非信任环境中得以有效实现。相比于比特币,以太坊的设计是通过在区块链中引入智能合约并优化相关的协议,为分布式应用程序和去中心化自治组织提供一个开发平台。以太坊的出现,使区块链应用开始从单一的金融走向电子政务、教育、医疗、物联网等更加广泛的领域。
区块链被定义为一种按时间顺序来组织数据区块,不同区块之间按序形成链条状连接的数据结构,借助这种数据结构来构建数字账本[3]。账本中存放的是交易信息,保存和运行账本的节点通过分布式网络连接起来,再通过数据加密、分布式共识、经济激励等机制来保证在一个没有中心化授权的开放网络环境中实现账本数据的安全共享。
在区块链系统中,每个分布式节点都具有“存储”功能,用于保存账本数据和用户交易等信息,每笔交易和结果需要通过“P2P(peer-to-peer)网络”共享给其他节点,节点在接收到数据后并不是直接保存下来,而是通过“共识机制”对数据进行验证,成功后保存到账本中,一旦保存下来就“不可篡改”。账本中的信息之所以不能修改,是因为使用了“加密”机制,通过哈希技术对区块进行串接,利用公钥加密机制对账本数据进行加密处理和记账。在公有链中,任何用户在下载安装了客户端软件后,就可以加入系统,并通过“激励”机制让节点争相维护这个系统。因此,分布式存储、共识机制、不可篡改、数据加密和激励机制构成了区块链的基本属性。
区块链中所涉及到的技术都不是最新的,例如分布式存储在云计算中就已广泛使用,很多年前的BitTorrent软件就是基于P2P通信方式,哈希算法的使用就更加广泛(如电子邮件加密、电子证据固定等),积分激励机制早已被各大电商、移动运营商成功应用等。为此,可以将区块链认为是综合运用各项成熟技术的一种应用创新。
区块链可以按许可权限分为公有链和联盟链(私有链是应用和管理上更为严格的联盟链)两大类。其中,公有链是一个完全去中心化的区块链系统,任何人都可以通过下载安装一个专用客户端软件加入系统,并利用系统生成的一对非对称密钥进行数据读取或发送交易,也可自由离开系统;联盟链是一个部分去中心化或多中心化的区块链系统,一般由多个业务相关机构(如银行、证券公司等)协同创建和管理,参与机构视具体需要确定一定数量的运行节点,并有限度地分配操作权限。公有链是区块链应用的拓荒者,各种复杂技术的解决和新技术、新功能的测试多是在公有链环境中完成,比特币和以太坊是目前最有影响的公有链应用;联盟链是区块链家族中未来应用的主力军,是企业应用的重点和区块链得以落地的关键,典型的联盟链平台有Hyperledger Fabric(超级账本)、Ripple、BigchainDB、TrustSQL等。另外,根据新节点加入时是否需要进行身份认证和访问授权操作的不同,可以将区块链系统分为许可链和非许可链两类,其中公有链通常称为非许可链,而联盟链一般称为许可链。
随着应用领域的不断拓展,区块链技术得到不断发展和完善:源于比特币的区块链技术构建了一个分布式的“全球账本”,创造了区块链1.0时代;以智能合约为标志的区块链2.0实现了应用程序在区块链上的上传/下载和有效执行,将整个区块链系统演进成一台“全球计算机”;区块链3.0的提出,使运行在企业操作系统(enterprise operation system,EOS)上的智能合约开发变得更加便捷。经济学上的“三元悖论”(mundellian trilemma)原则也适合于区块链系统,即在去中心化、安全与高效三者之间最多只能同时满足两个目标。其中,在公有链中实现了去中心化和安全,而无法实现运行的高效,例如比特币系统中每10 min创建一个新区块,其性能远远不能满足一些时效性较强的跨区域甚至是全球性业务的要求;在联盟链中提高了性能和安全性,但需要在去中心化上做出让步,通过引入传统的授权管理实现半中心化模式。
区块链的特点概括为:(1)去中心化(decentralized)[4]。区块链涉及到数据生成、验证、记账、传输、存储和维护等环节,这些过程都没有依赖任何第三方机构,而是通过相应的算法和协议来实现。(2)去信任(trustless)。整个区块链系统中,参与数据交换的每个节点之间无需相互信任,整个系统的运行规则和结果公开透明,所有数据全部公开,在系统约定的规则和时间范围内任何一个节点是不能也无法欺骗其他节点的。(3)集体维护(collectively maintain)。在比特币、以太坊等公有链中,区块链采用了经济激励机制去刺激系统中节点参与新区块的生成(挖矿),并通过共识机制让新区块添加到区块链上。(4)可靠数据库(reliable database)。区块链系统采用分布式数据形式,让每一个参与节点都能够获得一份完整的数据库备份。除非能够同时控制整个系统中51%的节点,否则单个节点对数据库的修改是无效的,也无法影响其他节点上的数据内容。因此,参与系统中的节点越多,算力越强,系统中的数据安全性也就越高。(5)可编程(programmable)。从以太坊开始,区块链技术可提供图灵完备的灵活的可编程功能,为区块链技术与智能合约的结合提供了实现途径,进而实现各类去中心化应用。(6)隐私保护(anonymity)[5]。由于节点之间是无需信任的,也就无需公开个人真实身份信息,因此系统中每个参与节点的隐私都得到了有效保护。
体系结构和实现协议是网络的两大核心要素,分层结构是计算机网络中广泛采用的关系模型,区块链系统也采用了分层架构。如图1所示的是区块链2.0采用的6层结构[6],从下到上依次是数据层、网络层、共识层、激励层、合约层和应用层。
Fig.1 Blockchain infrastructure图1 区块链基础架构
数据层位于整个体系结构的最低层,负责将一段时间内接收到的交易数据存入正在创建的数据区块中,再通过特定的哈希函数和Merkle树数据结构将区块中存入的交易数据进行封装,并在上层协议的协助下,生成一个符合算法约定的带有时间戳的新区块,再通过相应的共识机制链接到主链上。在此过程中,数据层主要涉及到数据结构、数据模型和数据存储等与分布式数据库相关的内容[7],主要包括数据区块、哈希函数、链式结构、Merkle树、时间戳、非对称加密等技术要素[8],确保区块链分布式账本中数据的可靠性和稳定性。
区块链是一种基于互联网的创新应用,不同节点之间的组织形式对区块链系统的整体性能起着关键作用。区块链网络层采用不受任何权威节点控制或层次模型约束的完全去中心化的P2P(对等网)组网方式,以此来实现区块链系统中各个节点之间的互联,为交易数据和新区块创建信息在节点之间的快速传输及正确性验证提供通信保障,并为每个节点参与新区块记账权的竞争提供公平的网络环境。
与互联网中广泛采用的客户机/服务器(client/server,C/S)通信与存储架构不同的是,在区块链系统中,P2P网络在组网结构和通信机制方面具有独特的应用优势:在组网方式上,每个节点既是资源的提供者又是资源的使用者,每个节点在网络中的身份平等,这正是区块链(尤其是公有链)去中心化应用的突出特点;在通信机制上,P2P为区块链中各节点之间基于TCP/UDP协议的对等通信提供了服务保障,确保了节点间链路的可用性和通信的灵活性。
共识层借助于相关的共识机制,在一个由高度分散的节点参与的去中心化系统中就交易和数据的有效性快速达成共识,确保整个系统所有节点记账的一致性和有效性。其中,一致性是指所有节点中保存的区块主链中已确认的区块完全相同,而有效性是指每个节点发送的交易数据都能够被存放在新区块中,同时节点新生成的区块数据也能够被链接到区块链上。
在早期的比特币系统中,设计者采用了高度依赖于节点算力竞争的工作量证明(proof of work,PoW)机制[1],随着区块链应用的发展,研究者又提出了一些符合不同区块链应用要求的共识机制,如应用于点点币(PPCoin)的权益证明(proof of stake,PoS)机制[9],应用于比特股(Bitshares)的股份授权证明(delegated proof of stake,DPoS)机制[10]等。
激励层主要通过提供激励机制刺激网络中的每个节点参与区块链中新区块的生成(挖矿)和验证工作,以保证去中心化区块链系统的安全、有效和稳定运行。激励层和共识层的运行具有相同的机制,以比特币为例,共识过程是趋利的,每个节点参与共识的目的是追求自身利益的最大化,激励是对已达成共识的一种货币发行和分配机制。其中,比特币系统每10 min生成一个新区块,同时给生成该区块的节点(矿工)奖励一定数量的比特币,以此完成比特币系统货币的发行过程。
从第一个区块创世区块(genesis block)产生后的4年中(大约产生了21万个区块),每个区块获得50个比特币的奖励,在之后的4年中每个区块获得25个比特币的奖励,依次类推。整个系统最后会产生2 100万个比特币。另外,新区块的创建者(矿工)还会从每笔交易中获得相应的交易费用(手续费)。新建区块的奖励和每笔交易的手续费都会存入新建区块的第1个交易位置(coinbase)中;根据区块链的共识和激励机制,节点的算力越大则“挖矿”成功的概率越高。为了提高“挖矿”的成功率,多个小算力节点会通过组建一个“矿池”将参与节点的算力汇合起来,在挖到矿后再根据各自贡献的算力大小来分得不同股份(share)的新建区块奖励和交易手续费。
智能合约是部署在区块链上的用计算机程序来实现日常合同条款的内容及执行过程的协议。早在1994年,Szabo就在文献[11]中提出了智能合约的概念,但直到比特币的出现,智能合约才借助区块链技术引起了业界的关注。
由于比特币中采用的是一种非图灵完备、不具备复杂循环和流程控制、功能简单的脚本语言,其实质是嵌入到比特币交易上的一组指令,因此比特币中的脚本只能算是智能合约的雏形。在以太坊中内置了一套图灵完备的编程语言,用户可以根据需要在以太坊平台上编写复杂的智能合约,实现各类去中心化的应用。智能合约的应用,使区块链技术不再局限于比特币应用,而成为一项具有普适性的底层技术框架。
区块链技术在公有链中的应用最为成熟,其中,在比特币中的应用主要是实现去中心化的数字加密货币系统,而在以太坊中除继承了数字加密货币(以太币)的功能外,还针对目前“一切皆Web”的现状,借助智能合约的强大功能,区块链技术开始支持各类去中心化应用(decentralized application,DApp)[12]。DApp最常见的应用情景是一个常规的Web前端应用与一个或多个智能合约进行交互。
联盟链反映了区块链应用价值的多样性和丰富性,提升了区块链应用的广度和深度,可以使区块链技术最大限度地得以落地生根。目前,联盟链主要面向企业级的应用,其中超级账本Hyperledger是Linux基金会于2015年发起的开源项目,包含多个并行的子项目,其中Fabric的成熟度较高。为了实现通过软件开发工具包(software development kit,SDK)访问区块链系统中的账本、交易、事件、权限管理等资源,Fabric提供了gRPC API以及封装应用程序接口(application programming interface,API)的SDK,SDK提供了对Node.Js、Python、Java、Go等语言的支持,可通过对底层gRPC接口的调用与智能合约进行通信,以构建功能更加丰富的应用场景。
Nicklaus Writh曾提出一个著名的公式:算法+数据结构=程序。算法是程序的灵魂,数据结构是程序的核心。在区块链中,针对不同领域、不同场景开发的程序是否能够快速、高效、安全地实现预定任务,在很大程度上取决于是否设计或选用了合适的数据结构。区块链是一种分布式系统,区块结构决定着交易信息的存储形式,Merkle树用于组织和管理交易数据,链式结构发挥着串接区块的功能,区块链交易的数据结构描述了比特币和以太坊的交易形式以及交易地址的生成特点,交易数据的存储方式从宏观角度分析区块链底层数据结构的设计依据和发展趋势。
不同区块链平台的数据结构在部分细节上虽然存在差异,但主体框架基本相同。以比特币为例,每个区块由区块头(Header)和区块体(Body)两部分组成[13],其结构如图2所示。其中,区块头封装了当前版本号(Version)、前一区块哈希(Prev-block Hash)、用于当前区块工作量证明的目标难度值(Bits)、用于工作量证明算法的随机数(Nonce)、用于验证区块体交易哈希的Merkle根(Merkle-root)以及当前区块的生成时间戳(Timestamp)等信息,具体描述如表1所示。
在区块链头部,“时间戳”字段在区块链的形成和维护过程中发挥着极其重要的作用:一是不同区块按照生成时间来确定前后关系;二是用于维护共识算法的最长链规则,即当一个节点通过共识算法产生了一个新区块并将其广播到全网后,其他节点在接收到该新区块数据时必须立即停止当前的共识运算(挖矿),而对新区块数据进行验证。否则,即使通过共识运算得到了新区块,但由于生成时间晚(以时间戳为准),也得不到其他节点的认可。
Fig.2 Data block structure图2 数据区块结构
Table 1 Description of Bitcoin block head structure function表1 比特币区块头结构功能描述
区块体中存放的是已经验证的一段时间内产生的交易数量以及完整的交易记录,这些信息构成了区块链中最为核心的数据结构,即交易的账本。所有的交易记录基于Merkle树的哈希计算,最后生成Merkle根(最后的哈希值),并记入区块头部的“Merkle根”字段。
区块链的链式结构是一个以区块为元素的链表,其中逻辑相邻元素之间以时间作为关联。链式结构的形成描述相邻区块之间关联性的建立,而GHOST协议用于维护链式结构中主链的唯一性。
3.2.1 链式结构的形成
区块链是一个将每一个区块以生成时间为序链接而成的分布式数据库。在区块链结构中,对区块头中的前一区块哈希(Prev-block Hash)、随机数(Nonce)和Merkle根等元数据进行两次SHA256运算即可得到该区块的哈希值。在图2中,前一区块哈希(Prevblock Hash)字段用于存放前一区块的哈希值,所有区块按照生成顺序以Prev-block Hash字段为哈希指针链接在一起,就形成了一条区块链表,即一个完整的账本。链式结构中相邻区块之间的关系如图3所示。
利用区块头中的“Merkle根”(Merkle-root)字段,可以通过哈希运算验证区块头部和区块体中的交易数据是否被篡改;利用区块头中的“前一区块哈希”(Prev-block Hash)字段,可以通过哈希运算验证该区块之前直至创世区块的所有区块是否被篡改;依靠Prev-block Hash字段,所有区块之间依据创建时间环环相扣,如果其中任何一个区块被篡改,都将会引发在其后生成的所有区块的哈希值发生连锁改变。利用链式结构的可验证性特点,当一个节点从不可信节点下载了某些区块或整个区块时,可以通过哈希运算验证每个区块的正确性。
3.2.2 链式结构的维护
在区块链中,由于所有节点在一个没有可信第三方统一协调的环境中几乎同时在同一个区块上进行挖矿,这样有可能出现多个节点同时挖出不同新区块的现象,此现象称为“分叉”,根据区块链的工作机制,最终只允许其中一个区块得到确认。当发生分叉时,花费了最多算力的链被确定为主链,主链是最长链,位于其他分支上的交易都将被引用或忽略。分叉不但影响了区块链系统的稳定性,还容易引起“双花”(双重花费)攻击[14]。当产生了分叉时,位于比特币分支节点上的区块称为孤块,并被丢弃,而以太坊引入了GHOST(greedy heaviest observed subtree)[15]协议来处理分叉。
由于比特币的出块(产生新区块)时间为10 min,因此产生分叉的概率并不高,而以太坊的出块时间为15 s,受区块链共识算法和网络运行机理等因素对网络事件响应机制的制约,在15 s的时间内,当一个新区块还没来得及得到其他节点的验证和接受之前,其他节点可能在相同的区块位置上挖出了新的区块,从而频繁地产生分叉。为了体现以太坊挖矿的公平性,并保持以太坊系统稳定运行,以太坊采用了GHOST协议将产生的分叉尽快进行合并。
Fig.3 Relationship between adjacent blocks图3 相邻区块之间的关系
GHOST协议是一种主链选择算法,其思想是基于“利益均沾”的原则,让挖出新区块的节点都会受益。如图4所示,假设节点A是一个在网络位置、带宽、算力等方面具有绝对优势的矿池,当该节点开始从主链的某一区块位置(假设图4中的3号区块)开始挖矿时,因其具有较高的出块概率,所以理应拥有对新挖出区块的记账权,并从中获得收益。但是,为了鼓励区块链网络中其他节点都积极参与挖矿,协议规定节点A对在同一位置挖出新区块的其他矿工将通过引用方式给予相应的奖励(具体奖励规则如图4所示)。GHOST协议有效维护了主链的唯一性,防止出现永久分叉现象,同时也保持了区块链系统的稳定运行。
分叉会带来交易的不确定性和系统运行的不稳定性。目前,比特币在连续产生6个区块之后,当前的交易确定为不可逆,因此其交易确认时间为60 min;以太坊在连续产生12个区块之后,交易已基本不可逆,因此其交易确认时间为3 min。需要说明的是,当区块间距离达到8时,还未被引用的分叉上的叔块将得不到奖励,而自动废弃。另外,在叔块上挖出来的区块也得不到奖励,以太坊这样规定的目的是为了激励节点在发现了最长区块链时尽快合并,而不是在自己的分支链上继续进行挖矿。
1989年,密码学家Merkle提出了Merkle树的概念[16],它是一种典型的二叉树。Merkle树是区块链中最重要的数据结构,在区块链中使用它来组织交易数据[17]。比特币使用了最简单的二叉Merkle树,每个区块都拥有一个独立的Merkle树,树的一个叶子节点就是一个交易哈希(比特币使用双SHA256哈希)。叶子节点的数量必须是双数,否则就复制最后一个叶子节点的数据。从下而上,同层的节点两两成对进行哈希运算,形成上一层的节点值。重复该过程,直到最后一个节点(树根)。根的哈希值成为区块中所有交易的唯一标识,并将它保存到区块头部的“Merkle根”字段中,用于工作量证明。Merkle树具有以下优点:
(1)极大地提高了区块链的运行效率。Merkle树的形成过程是一个频繁的哈希过程,区块链中使用的SHA256的运行效率较高,对节点性能的要求较低。另外,区块中所有的交易信息都递归到Merkle根,简化了对整个区块链系统的管理。
(2)极大地提高了区块链的可扩展性。Merkle树可以实现交易数据与哈希值的分离,在一些轻量级的应用中只需包含Merkle根的哈希值,而不必封装区块体中的底层数据,这使得区块链技术可以高效地运行在智能手机、物联网等计算和存储能力受限的设备上。
(3)可支持“简化支付验证”(simplified payment verification,SPV)协议[18]。SPV协议的设计思想是将区块链节点变成一个轻量级节点,即在不需要同步下载整个区块链的数据的情况下,仅依靠本区块中某一交易节点到Merkle根的路径信息,就可以对“交易”进行验证。例如,仅需图2中的节点Hash 7、Hash 56和Hash 5678即可验证“交易8”的存在性和正确性。从区块链的运行机制来看,要验证一笔交易,需要遍历所有的区块找到与该笔交易相关的所有交易并进行逐个验证,才能知道交易支付的可靠性。但SPV简化了此过程,极大地降低区块链运行所需的带宽和验证时间,并使得仅保存部分相关区块链数据的轻量级客户端成为可能。
Fig.4 GHOST protocol principle图4 GHOST协议的工作原理
为了提高区块产生的效率和对节点中账户状态数据的查找能力,以太坊在计算Merkle根时使用了Merkle Patricia树[19]。以太坊和比特币的区块中虽然具有相同的交易数据,但在以太坊中状态数据经常发生变化,且产生的数据量较大。为此,为了提高运行效率,以太坊在创建新区块时,仅计算在新区块中账户状态发生了变化的分支,而未发生变化的分支将被直接引用。
交易(transaction)是双方或多方以货币为媒介的价值交换,其实质是将比特币从一个账本转移到另一个或多个账本中。区块链的交易与银行的交易类似,通常就是转账,具体到每一笔交易,同样包括从哪儿来(交易输入地址)、到哪里去(交易输出地址)和发生了哪些变化(交易的数目)。通过交易过程,可实现数字货币资产的创建和转移,也可以对每笔交易进行溯源和找到所有的历史记录,直到挖矿所得的比特币(coinbase)。
3.4.1 比特币交易的数据结构
Fig.5 Data structure of Bitcoin transaction图5 比特币交易的数据结构
比特币使用如图5所示的基于交易模型的数据结构,每笔交易包括交易输入(transaction input)和交易输出(transaction output)两部分,在某笔交易过程中可以将一个或多个账户中的比特币作为输入,转入到另一个或多个账户中。为了完成交易过程,每笔交易还提供了当前交易软件的版本(Version)、用于将交易写入区块的锁定时间(Lock Time)以及交易的输入数量(#vin)和输出数量(#vout)等功能字段。
每笔交易输入主要由上笔交易的哈希(Prev-tx Hash)、上笔交易的输出索引(Index)、输入脚本(Script Sig)、输入脚本长度(Script Sig Len)和交易输入序列号(Sequence)组成;每笔交易的输出主要包括转账金额(Value)、输出脚本(Script-PubKey)和输出脚本的长度(Script-PubKey Len)。解锁脚本(输入脚本)与输入引用到的输出中的锁定脚本(输出脚本)的执行过程同步进行,用于验证本笔交易是否有效,当解锁脚本满足锁定脚本的条件时,则输入有效。比特币系统中的脚本语言是一种基于堆栈的执行语言,主要有P2PKH、P2PK、MS(仅限15个密钥)、P2SH和OP_Return等[20]。交易中每个字段的功能描述如表2所示。
比特币使用交易输入和交易输出进行支付操作。具体到某笔交易输出来说,在该交易中的钱还没有花出去之前,它就是一笔还没有被花费掉的交易输出,即未花费的交易输出(unspent transaction outputs,UTXO)。与现金支付不同的是,现金支付的找零是由收款人负责,而UTXO模型中找零是发起者自己进行设置;现金支付的面值是固定的,而UTXO中的面值不固定,是根据不同的交易而定的。因此,在UTXO模型的交易过程中,支付方不仅要指出接收方的地址,还要指明找零地址,找零地址可以是支付方的地址,也可以由支付方指定一个地址。
当一笔交易的输出没有任何另一笔交易的输入与之对应时,说明该输出中的比特币未被花费。对于某个比特币地址来说,其UTXO的比特币之和即为该账户的比特币余额。另外,对于UTXO中的每笔输出都需要使用锁定脚本将比特币锁定在账户中,当交易过程中需要引用UTXO中的输出时,需要使用该输出账户的公钥来验证签名的正确性,通过解锁脚本来解锁引用账户地址中的比特币。
3.4.2 以太坊交易的数据结构
比特币的数据结构采用基于交易的模型,其特点是可以快速验证每笔交易,但缺点是无法对用户余额进行高效查询。为了提高对交易状态和余额的查询效率,使区块链平台支持更加广泛的应用,以太坊提出了基于账户的模型。
针对某一账户来说,不同时刻可能存在不同的状态,反映了账户中各属性值(如以太币余额、从该账户地址发出去的交易数、合约状态数据的Merkle Patricia树根、合约代码的哈希值等)随时间的变化情况,一旦发生了某笔交易,涉及该交易的账户状态将会发生变化。以太坊的最大特点是在区块链中使用了智能合约,因此以太坊中的账户分为外部账户(externally owned account,EOA)和合约账户(contract account,CA)两种类型,其中EOA一般指分配给自然人并用其私钥进行保护且不存在任何代码与之关联的账户,而CA是分配给智能合约的被合约代码控制的账户。
区块链中的账户是地址的抽象描述,EOA和CA也是地址的两种不同表现形式,两类账户都共用同一个地址空间,即采用相同的数据结构。其中,EOA的地址由其公钥加密后生成,其获取较为容易,在以太坊钱包的客户端可以创建,而CA的地址是在创建合约时由创建者的地址和该地址发生过的交易数量计算得到。两类账户都可以实现对以太币的持有、余额查询、交易发送等管理功能,但由于CA是通过功能丰富的脚本程序控制,因此可以实现更多的个性化管理功能,如查看账户的接收记录、生成多签名的钱包等。区块链中的交易(如转移以太币)由EOA发起,而CA可以触发执行合约代码。以太坊中的EOA和CA的应用特点如图6所示。
Fig.6 Accounts in Ethereum图6 以太坊中的账户
3.4.3 区块链交易地址
现实生活中,当人们需要进行存钱、转账等一系列操作时,首先要前往银行开个账户,领取银行分配的一串数字帐号(银行卡号),帐号的密码由用户设定。而在区块链系统中,账户不需要由中心机构来开设,而是通过密码学原理来产生。本小节以比特币系统中的地址生成为例进行介绍[21],以太坊的实现方法和过程与此基本相同。
地址针对的是具体的账户,主要用于各类交易。比特币系统的地址生成过程如图7所示,具体为:
(1)通过调用操作系统底层的伪随机数生成器(pseudorandom number generator,PRNG)来生成一个256位的随机数作为私钥。
(2)私钥经过椭圆曲线算法生成公钥。比特币和以太坊都使用Secp256k1椭圆曲线算法K=k×G(其中,K为公钥,k为私钥,G为一个生成点),由于生成点G是预定的,因此可以由一个确定的k来单向生成一个确定的K。
(3)通过A=RIPEMD160(SHA256(K))(其中,A为公钥哈希值),对生成的公钥进行SHA256和RIPEMD160双哈希运算,生成一个20 Byte的摘要结果,即Hash160公钥哈希。
(4)在生成的公钥哈希的头部添加一个软件的版本号(比特币主网络版本号为“0×00”),然后进行两次SHA256运算,取运算结果的前4 Byte,将其添加到公钥哈希的后面作为“检验”(Checksum)值,将最后的结果通过Base58Check编码后,就得到最终的比特币的地址。
Fig.7 Bitcoin transaction address formation process图7 比特币交易地址的形成过程
公钥生成过程是不可逆的,即不能通过公钥反推出私钥。比特币的私钥通常保存在比特币钱包文件中,丢失了私钥就意味着丢失了对应地址的全部比特币资产。
底层数据结构的设计直接决定着数据的读写和查询性能。与传统的集中式管理的关系数据库系统相比较,目前比特币和以太坊对数据查询的性能要求并不高,但对数据写入性能的要求较高,尤其区块中交易数据和交易状态数据需要频繁写入。而且,作为一个完全去中心化的分布式系统,比特币和以太坊要求对数据库的部署和应用要尽可能简单和快捷,且不能占用较大的存储空间和CPU资源,以鼓励具有一般算力的节点加入其中。
早期比特币版本中使用的数据库是Berkeley DB[22],从2012年后开始转向使用LevelDB[23]。由于以太坊和超级账本推出时间相对较晚,因此直接使用了LevelDB作为底层数据库。联盟链中的Hyperledge在fabric0.6版本之前使用的底层数据存储系统为levelDB,但从fabric1.0版本开始同时提供了对levelDB和CouchDB[24]的支持。目前,区块链系统的数据存储大多使用levelDB。LevelDB是由Google开发的针对写操作进行了优化的新一代分布式数据存储系统,其底层存储采用了基于日志排序合并树(log structured merge tree,LSM-tree)结构的Key-Value单机数据库。在区块链中,当内存中的数据需要持久写入磁盘时,首先通过递归长度管理前缀(recursive length prefix,RLP)编码将JSON格式数据转化成字符串(Value),然后计算Value的数字签名(Key),最后将<Keyi,Valuei>对存储在levelDB中。LevelDB具有较高的随机写和顺序读/写性能,非常适合于查询操作较少但写操作频繁的区块链应用场景。
共识机制是分布式系统中实现去中心化信任的核心,它通过在互不信任的节点之间建立一套共同遵守的预设规则,实现节点之间的协作与配合,最终达到不同节点数据的一致性。由于区块链的本质是一个去中心化的分布式账本数据库,因此区块链中的共识机制既要体现分布式系统的基本要求,又要考虑区块链中专门针对交易记录、需要解决拜占庭容错以及可能存在的恶意节点篡改数据等安全问题。因此,区块链中的共识机制更具有针对性,可根据不同的区块链应用场景选择符合不同运行需求的共识机制。
自从1982年Lamport等学者在文献[25]中提出“拜占庭将军问题”以来,有关共识算法的大量研究集中在理论探讨方面。但从2008年比特币进入人们的视线以来,各类共识机制开始从理论步入实践,并随着比特币自身的迭代、以太坊平台的发展以及智能合约和超级账本等基于区块链应用的丰富,已有的共识算法在实践中得到完善,同时伴随新应用场景的不断出现,符合相应需求的共识机制相继得到应用。本章主要介绍目前在区块链中具有代表性的共识机制和算法:早期比特币中高度依赖节点算力的工作量证明(PoW)机制[26]、点点币中区块生成与节点所占有股权成反比的权益证明(PoS)机制[27]、比特股中按既定时间段轮流产生区块的授权股份证明机制(DPoS)[28]和在Hyperledger(超级账本)和Antshares(小蚁)中基于实用拜占庭容错(practical Byzantine fault tolerance,PBFT)机制[29]等,表3对各算法的主要特性进行了对比。
1997年,26岁的英国埃克塞特大学博士亚当·巴克(Adam Back)提出哈希现金(Hashcash)的概念[30],其思想类似于密码学的RSA算法:计算两个质数之积是容易的,但分解两个质数之积是困难的。哈希现金的思想体现在一些数学结果很难发现但易于校验。基于这一数学特征,可以设计这样的协议:提供一个有一定计算量的质数之积,只要对方能够将其进行分解,就允许建立连接。这一协议要求对方必须是诚意的,而且为了表示此诚意需要付出一定的算力来解决提出的问题。例如,为了防止接收到垃圾邮件,邮件接收者可以在邮件的消息头中增加一个哈希值,该值在生成时需要包括收件人地址、发送时间及盐值(salt)等信息,可以对该哈希值设置一定的条件(如前10位必须是0),只有满足该条件的邮件才被认为是一个合法的邮件。邮件发送者只有经过不断尝试(改变salt值),直到得到符合要求的哈希值为止,除此之外没有任何捷径。另外,生成该哈希值时的时间戳可以防止一次计算结果的重复使用,避免垃圾邮件制造者利用同一个哈希值来发送多份邮件。
Table 3 Comparison of PoW,PoS,DPoS and PBFT consensus mechanisms表3 PoW、PoS、DPoS和PBFT共识机制对比
哈希现金的本质是一种PoW系统,即愿意并完成了一定计算工作量且提供了证明的节点被认为是可信赖的。在比特币区块链中就采用了高度依赖于节点算力的PoW机制,每个参与共识的矿工基于各自的算力相互竞争来共同解决一个求解复杂但验证容易的SHA256数学难题,最快解决该难题的节点将获得区块记账权和系统给予的比特币奖励。即在已预置区块头中工作量证明难度的前提下,节点通过不断调整随机数Nonce来计算区块头部元数据的双SHA256哈希值以满足以下条件:
其中,H为单向哈希函数,比特币使用SHA256;h为区块头部数据,主要包含前一区块哈希、Merkle根等内容;d为当前工作量证明难度。PoW在区块链网络中的共识流程如下:
(1)当某一节点产生了一笔新交易时,为了尽快完成交易过程并得到别人的认可,交易及相关信息会立即广播给区块链网络中的所有节点。节点在接收到该交易数据时,为了能够完成挖矿操作便将其按序添加到当前区块体中。
(2)根据Merkle根的生成规则,每个节点计算自前一次区块生成以来已接收到的交易构成的Merkle根,并填写区块头中各字段的元数据,其中Nonce的初始值设置为0。
(3)从0开始将Nonce每次按1递增,依次计算区块头的双SHA256值,直到该值小于或等于工作量证明难度的设定值时,该Nonce就是工作量证明的解。
(4)当某个节点找到了符合工作量证明要求的Nonce值后,为了获得对该区块的记账权(获得了记账权就获得了奖励),就需要尽快将该区块以广播形式向全网分发。
(5)其他节点在接收到新区块后,为了尽快挖出下一个区块,就会对接收到的区块进行验证,如果正确,便将该新区块添加到主链上,并在该区块的基础上去竞争下一个区块。
挖矿的实质是所有参与节点集中各自算力去寻找由多个前导0构成的区块头哈希值,工作量证明难度d的设定值越小,区块头哈希值的前导0就越多,寻找到合适随机数的概率越低,挖矿的难度就越大。为了适应硬件技术的快速发展及计算能力的不断提升,比特币每2 016块就会调整一次工作量证明难度,以控制区块的平均生成时间(10 min)始终保持不变。
PoW共识机制的特点是各参与节点紧紧依赖于自己的算力以获得对新区块的记账权,同时获得相应的奖励(该过程也实现了比特币的发行),在此共识过程中引入了经济激励机制,从而使更多的节点为了追求经济利益而愿意加入到挖矿过程中,这种独特的共识机制不但有利于系统的长久稳定运行,而且增强了网络的可靠性与安全性。
PoW共识机制的优势是借助比特币特有的价值属性激励节点参与挖矿,并在共识过程中通过竞争区块的记账权实现了比特币的货币发行和交易支付行为,采用的验证和竞争机制保障了系统的安全性和去中心化。但PoW共识过程完全依赖各节点的算力,从而引起大量资源的浪费,与当前绿色发展的理念格格不入。同时,长达10 min的出块时间,使PoW机制不适合于额度小、交易量大的商业应用,其可扩展性受到了限制。
PoS共识机制是PoW的替代方案,是为解决PoW共识机制中一直被诟病的资源浪费以及为了满足更高要求的安全性而提出来的。PoS设置的记账规则与PoW算法类似,即所有矿工基于算力竞争满足特定条件的哈希值,最先成功求得解的矿工便拥有记账权。两种算法的不同之处在于,PoW共识是基于节点的算力来求解符合条件的哈希值,而PoS则是寻找最高权益的节点,即PoS通过权益证明来替代PoW中的基于节点哈希算力的证明来竞争新区块的记账权。
PoS算法中的权益可以概括为节点拥有的资产,谁拥有资产越多,谁将会更有可能在下一个区块记账权的竞争中胜出。在不同的应用场景中,资产所表示的含义有所不同。PPCoin中的资产为“币龄”,即节点拥有数字货币的数量与持有时间的乘积,其值越大节点获得新区块记账权的概率也就越大。为了避免PoW算法中因算力过于集中带来的问题,在PoS算法中,如果某一节点获得了记账权,则其“币龄”将会自动清零。基于“币龄”的算法设计非常类似于现实生活现象,即某人拥有代币的数量越多、时间越长,就越希望维护币值稳定,也越愿意维护系统的正常运行;基于可验证秘密共享(verifiable secret sharing,VSS)的G.O.D coin tossing算法[31]中的资产为“代币”,持有代币越多的节点将有更高的概率被选中作为新区块记账者;为了防止节点在离线状态下累积“币龄”,黑币(Blackcoin)[32]在其2014年6月发布的PoS2.0白皮书中,用“余额”作为资产来鼓励节点尽可能保持在线,以提高系统的安全性和系统运行的稳定性;为了解决PoW算法在挖矿过程中产生的能源消耗问题,以太坊将从早期的使用PoW的共识机制向着PoW和PoS混合,再到最后实现单一的PoS共识机制过渡。
与PoW算法相比,PoS算法拥有一些明显的优点,如放弃单纯的算力竞争而节约了能源,采用清零机制解决了算力过于集中,限制只有在线用户才能获得收益从而解决“公地悲剧”(tragedy of the commons)的发生等。但PoS更容易出现分叉,安全性和容错性相对较低,某些拥有权益的节点无意全力投入到记账竞争中等。
为了有效解决PoS共识机制存在的不足,2014年4月,Larimer等在PoS的基础上提出了DPoS共识算法[33],以提高持币者参与挖矿的积极性和主动性。DPoS共识机制也称为股份授权证明算法,即每个节点相当于一个股东,所有股东选择一定数量的代表作为共同信任的委托人,由该委托人来帮助大家记账。DPoS共识机制与PoS的最大区别表现为:
(1)委托人的选择。委托人必须是大家信任的股东节点,每个股东节点将其持有股份的数量作为选票多少投给自己信任的某个节点,在规定的时间内获得选票最多且有意愿为大家服务的股东节点将作为委托人(总共101个)。
(2)激励与惩罚。根据系统约定,每个委托人在规定的时间范围内轮流负责新区块的生成、转发和验证,并可以从每笔交易中获得一定数额的交易费(transaction fees)。为了防止委托人不作为,系统规定每个委托人必须事先缴纳金额相当于获得一个新区块记账权奖励100倍的保证金,如果某个委托人没有在规定的时间内完成新区块的创建工作,股东将会收回选票,并将该委托人降为普通股东,同时保证金也会被没收[34]。这样,委托人为了能够获益,必须保持永久在线。
基于DPoS共识机制的区块链系统是一个中心化(针对委托人)和去中心化(针对所有股东)的混合体,每个节点都能够通过投票决定自己的委托人,有限的委托人轮流记账,大幅度减少了参与记账竞争的节点数,提高了共识验证的效率。而且每一个委托人的工作状态都受到投票者的监督,在确保节点真实性的同时,也能够使那些虽然拥有较少资源(算力)但具有较强责任心的节点有机会成为委托人而获益。
与PoW、PoS和DPoS不同的是,拜占庭容错(Byzantine fault tolerance,BFT)[35]机制无需通过竞争来确定记账者,而是让系统中的节点以投票方式来产生新区块,并实现系统中共识结果的一致性,而且不会出现分叉现象。根据分布式系统的CAP理论,任何一个系统在C(consistency,一致性)、A(availability,可用性)和P(partition tolerance,分区容错性)三者中最多能够同时实现两项,这就使得BFT在满足一致性和可用性的前提下,只能弱化分区容错性。由于BFT机制具有强一致性(这是共识机制的前提),因此各种基于BFT的衍生算法广泛应用于区块链网络,如超级账本和Antshares等多个区块链系统都使用了PBFT共识机制。
PBFT通过优化算法将计算复杂度从指数级降到多项式级,解决了BFT运行效率低的不足。PBFT共识机制主要包括共识达成、检查点协议(check point)和视图转换(view-change)3个部分。其中,PBFT共识达成分为以下5个过程(如图8所示):
(1)请求(propose)。当客户端(client)向主节点发起一个请求时,便产生一个新的视图(view)。其中,PBFT中的节点分为主节点(primary)和副本节点(replica)两种类型,1个PBFT区块链网络中的主节点只有1个,其他节点都是副本节点;视图表示当前所有节点身份的状态信息,当视图转换协议更换了一个主节点时,视图也会随之发生变化。
(2)预准备(pre-prepare)。主节点在收到客户端的请求消息后,首先对其进行编号,然后将计算得到的预准备消息发给所有的副本节点。在此过程中,用到了哈希算法、数字签名等方式。
(3)准备(prepare)。副本节点在收到主节点发送的预准备消息后,验证消息的合法性。验证通过后,副本节点分别计算准备消息,然后将结果发送给其他节点。与此同时,各节点对自己收到的准备消息进行验证,当通过验证的合法准备消息数量大于等于2f+1(f为恶意节点数)时,将预准备消息和准备消息写入日志,并向其他节点发送确认消息。
(4)确认(commit)。节点接收到确认消息,并验证其合法性。如果通过验证的合法确认消息的数量大于等于2f+1,将完成消息的证明,并将证明结果发送给客户端。
(5)回复(reply)。客户端对接收到的由各节点回复的证明消息进行验证,当通过验证的消息数量大于等于2f+1时,客户端确认完成请求。否则,客户端需要重新发起一轮全新的请求过程。
Fig.8 PBFT consensus building process图8 PBFT共识达成过程
在采用PBFT共识机制的区块链网络中,主节点代表获得记账权的节点,而客户端请求代表交易信息。
在PBFT共识过程中,还用到了检查点协议和视图转换协议[36-37]。其中,检查点协议的功能是实现节点状态的一致性。当某个节点因网络延时或中断等原因导致从某一编号开始的请求消息没有执行时,检查点协议通过周期性地执行同步操作,将系统中的节点同步到某一个相同的状态,并定期删除指定时间点之前的日志数据,以节约节点存储空间;视图转换协议的功能是在主节点不能正常工作时,重新从现有的副本节点中选出一个新的节点作为主节点,继续PBFT共识过程。
由于PBFT共识中可以生成新区块的节点(primary节点)是唯一的,因此不会存在分叉现象[38]。但由于每个节点都需要频繁地接收从其他节点发送过来的交易数据,同时也要将本节点的交易数据尽快发送出去,因此网络的开销较大,导致基于PBFT共识机制的区块链的系统性能不高,只能满足规模不大的联盟链应用场景。
传统意义上的合约(或合同)是指双方当事人基于意思表示合致而成立的法律行为。1994年,美国计算机科学家Nick Szabo提出了智能合约(smart contract)的概念:一套以程序代码指定的承诺以及执行这些承诺的协议。智能合约的设计初衷是在没有任何第三方可信权威参与和控制的情况下,借助计算机程序,编写能够自动执行合约条款的程序代码,并将代码嵌入到具有价值的信息化物理实体,将其作为合约各方共同信任的执行者代为履行合约规定的条款,并按合约约定创建相应的智能资产。伴随着区块链应用从比特币发展到以太坊和超级账本,智能合约也发生了一次华丽蜕变,尤其是借助区块链的去中心化基础架构,使得智能合约得以在去信任的可执行环境中实现。区块链触发了智能合约的生机和活力,智能合约摧生了区块链技术更加广泛的应用场景。
广义的智能合约是指运行在区块链上的计算机程序。狭义的智能合约可以认为是运行在区块链基础架构上,基于约定规则,由事件驱动,具有状态,能够保存账本上资产,利用程序代码来封装和验证复杂交易行为,实现信息交换、价值转移和资产管理,可自动执行的计算机程序。目前,根据所使用的编程语言和运行环境的不同,将比特币中的智能合约称为脚本型智能合约,将主要运行在以太坊和超级账本中的智能合约称为图灵完备型智能合约,而将正在研发中的kadena项目[39]中的智能合约称为可验证合约型智能合约[40]。
(1)脚本型智能合约。由于比特币中的脚本仅包含指令和数据两部分,其中涉及到的脚本指令(也称为“操作码”,Opcode)只需要完成有限的交易逻辑,如编写比特币中UTXO的锁定脚本和解锁脚本,不需要复杂的循环、条件判断和跳转操作,因此比特币中的脚本型智能合约是一种基于堆栈的功能有限且编写相对容易的简单执行程序,支持的指令不到200条。
(2)图灵完备型智能合约。脚本语言被设计成为仅在有限范围内执行有限功能的简单执行语言,是非图灵完备的语言。使用脚本语言编写的交易指令虽然能够满足比特币应用,但无法适应以太坊平台的开发需求。目前,以太坊主要使用Solidity[41]和Serpent[42]两种智能合约开发语言。其中,Solidity是一种语法上类似于JavaScript的专门针对运行在以太坊虚拟机(environment virtual machine,EVM)上的智能合约开发而设计的高级编程语言,也是以太坊平台主推的智能合约开发语言;Serpent语言的设计类似于Python,具有高效易用的编程风格,是专门针对智能合约的特征而开发的高级语言。在Hyperledger Fabric中采用GO、Java等通用语言编写运行在Docker容器中的智能合约,GO和Java都是通用性较强的图灵完备语言,能够实现基于联盟链智能合约开发中所需要的应用逻辑。
(3)可验证合约型智能合约。可验证语言Pact的语法类似于LISP语言,用于编写运行在区块链Kadena上的智能合约,可实现合约的数据存储和授权验证等功能。Pact语言采用非图灵完备设计,不支持循环和递归,以防止在复杂合约的编程过程中可能存在的安全漏洞以及因此而带来的风险。用Pact语言编写的智能合约代码直接嵌入在区块链上运行,不需要事先编译成为运行在特定环境(如以太坊EVM)的机器代码。
由于区块链应用的多样性,在不同平台上使用的智能合约的运行机制也不尽相同。本节主要选择目前最具代表性的以太坊开发平台,介绍智能合约的运行机制(如图9所示),主要包括以下阶段:
(1)智能合约代码的生成。在合约各方就传统意义上的合同内容达成一致的基础上,通过评估确定该合同是可以通过智能合约实现的(是可编程的),然后由程序员利用合适的开发语言将以自然语言描述的合同内容编码成为可执行的机器语言。
(2)编译。利用开发语言编写的智能合约代码一般不能直接在区块链上运行,而需要在特定的沙箱环境(以太坊为EVM,超级账本为Docker容器)中执行,因此在将合约文件上传到区块链之前需要利用编译器对原代码进行编译,生成符合沙箱环境运行要求的字节码。
(3)提交。智能合约的提交和调用是通过“交易”(transaction,Txn)来完成。当用户以交易形式发起提交合约文件后,通过P2P网络进行全网广播,各节点在进行验证后存储在区块中。
Fig.9 Smart contract operation mechanism图9 智能合约运行机制
(4)确认。被验证后的有效交易被打包进新区块,经过共识机制,新区块添加到区块链的主链。根据交易生成智能合约的账户地址,之后可以利用该账户地址通过发起交易来调用合约,节点对经验证有效的交易进行处理,被调用的合约在沙箱中执行。
另外,主要出于对安全、效率和可扩展性的考虑,一些智能合约在运行时需要区块链以外信息的支撑,这些链外信息的提供,从源头上必须保证是可靠、可信的。
根据运行环境的不同,目前智能合约主要集中在比特币、以太坊和超级账本3类应用场景中。
5.3.1 比特币中智能合约的实现技术
比特币是基于交易的密码货币,它不像基于账户的密码货币(如以太币)那样可以直接查询账户的余额,而需要通过UTXO来计算交易地址的余额。比特币的每笔交易由多个交易输入和多个交易输出组成,交易输入中包含着UTXO和解锁脚本,交易输出中包含着比特币的数量和锁定脚本。当发生一笔交易时,每个UTXO的解锁脚本和锁定脚本同时执行,并根据结果决定是否能够完成本笔交易。脚本直接嵌入在区块链的核心代码中,由比特币钱包(bitcoin core)生成并执行。另外,Kadena的智能合约也采用嵌入到区块链中并与区块链代码一起执行的运行方式。
5.3.2 以太坊中智能合约的实现技术
由于以太坊中的智能合约使用了图灵完备语言,因此合约编写过程中容易产生可能被非法利用的安全漏洞和恶意代码,将直接威胁到区块链运行的安全性,并可能导致无法挽回的后果,如2016年6月发生的著名的The DOA事件[43]。如果以太坊中的智能合约使用比特币中的非图灵完备语言,其功能将会受到极大限制;如果让智能合约不加控制地直接在区块链上运行,则面临巨大的安全隐患。为此,以太坊中的智能合约运行在EVM沙箱中,通过沙箱环境限制合约代码的运行。沙箱(Sandboxie)是一种通过预置的安全策略来限制程序运行行为的执行环境,运行在EVM中的合约与区块链宿主之间以及不同合约之间被沙箱隔离,互不干扰,限制了合约的执行和影响范围。
不同于标准的存储器结构,EVM中的程序代码并没有存放在常规的RAM(random access memory)和外部存储介质中,而是保存在虚拟的ROM(readonly memory)中。为了满足SHA256算法和椭圆曲线加密算法的运行要求,EVM提供了大小为256位的简单栈式结构。EVM部署在以太坊节点上,负责合约的执行。当合约在EVM中初始化时,将创建新的合约账户信息,包括账户地址、存储空间和主体代码等内容。
为了防止因人为或设计缺陷导致的区块链资源消耗,以太坊智能合约引入了gas计费机制。合约创建与调用、账户中存储数据的访问、在EVM上运行操作码等涉及到合约创建和运行的过程,都需要按相应标准支付相应数量的gas。当EVM代码创建过程中所需的gas数量大于账户的gas余量时,不但新的合约无法创建,而且账户中剩余的gas将被清零。gas计费机制为智能合约的运行提供了有效保障。
5.3.3 超级账本中智能合约的实现技术
Docker容器是一个使用广泛的、开源的沙箱环境,Hyperledger Fabric中的智能合约chaincode(链码)就运行在轻量级的Docker容器中,并通过gRPC协议与相应的Peer节点(即存储账本、chaincode等关键数据,并执行背书及chaincode代码等特定程序的物理节点)进行交互。基于Docker容器具有的安全隔离功能,避免了区块链宿主程序遭受容器中恶意合约的攻击,同时防止运行在不同容器中的合约之间的相互干扰。chaincode的运行过程主要包括:
(1)打包(package)。将chaincode安装在Peer节点,包括创建包和对包签名。具体是指将用开发语言(多使用GO语言)编写的源代码按照chaincode部署规范(chaincode deployment spec,CDS)重新定义,并通过签名来检查和确认chaincode的所有者。如果要让chaincode拥有多个所有者,首先需要创建一个被签名的chaincode包(SignedCDS包),然后让这个包依次被每个所有者进行签名。
(2)安装(install)。将CDS规定格式的chaincode安装在一个将要运行该合约的Peer节点上。chaincode只被安装在合约所有者的背书节点上,安装的实质是代码的编译过程。
(3)实例化(instantiate)。调用生命周期系统chaincode(lifecycle system chaincode,LSCC),在channel[44](即基于交易规则将区块链网络划分后形成的逻辑单元)上启动一个Docker容器,实现合约与channel的绑定。实例化过程,会生成对应channel的Docker镜像和Docker容器,可以指定背书策略。在成功进行了实例化后,处于激活状态的chaincode将监听并接收交易请求。
(4)更新(upgrade)。更新是一个类似于实例化的交易,即将新版本的chaincode与channel绑定。更新后其他与旧版本绑定的channel仍旧运行旧版本的chaincode。
(5)删除(delete)。删除chaincode对应的Docker容器以及每个安装合约的背书节点上的SignedCDS包。在正在开发的版本中,将用stop和start交易的指令来停止或重启chaincode,而不需要直接将其删除。
超级账本中的智能合约基于模块化的可扩展架构,将共识服务从背书节点分离开来,形成独立的功能模块,可扩展性强,共识效率高,作为联盟链应用,适合于供应链、银行、证券机构等行业的应用场景。
与传统的数据库系统相比,区块链在去中心化、数据按时序存储及防篡改、交易的可溯源与不可否认、自动执行的智能合约等方面具有绝对的优势,这使得区块链技术不仅在数字加密货币领域彰显了独有的优势,同时在社会管理、金融、经济等众多领域具有广泛的应用场景。而且,区块链在技术迭代过程中其功能得到不断丰富和完善,更显示出迅猛的发展势头。本节以区块链1.0、区块链2.0和区块链3.0发展为脉络,分析区块链技术的应用现状。
6.1.1 基于区块链1.0的数字货币
区块链最初的应用是比特币,但随着比特币在全球的兴起,区块链潜在的价值开始引起大家的普遍关注。区块链1.0对应的是以比特币为代表的数字货币,主要功能集中在货币的发行和转移。比特币的关键技术是使用一种全新的分布式记账方式实现交易过程的去中心化。2009年,比特币作为开源软件发布,之后基于比特币平台,直接在区块链账本内部或利用分叉机制来创建新的代币。
2011年推出的菜特币(Litecoin,LTC)与比特币具有相同的技术原理,但在交易确认、对硬件性能的依赖等方面都较比特币有了更大的改进,性能得到提升;瑞波币(XRP)是Ripple网络中唯一的通用货币,而Ripple是开源P2P网络,基于共享数据库(数据库中记录着账户和余额信息)和一致性账本技术的全球支付网络,可实现任意货币(法币和数字货币)之间的结算,具有较大的应用价值和发展潜力。例如,利用Ripple网络,甲方可以用美元直接实现与乙方欧元之间的结算,结算过程中使用XRP支付手续费。严格地讲,Ripple是一种允许各方使用任意一种货币进行支付的互联网交易协议,XRP虽然也是一种数字货币,但其主要功能是协助Ripple支付网络中货币的流通;达世币(DASH)是在比特币基础上开发的具有良好的匿名性和去中心化特征、以保护用户隐私为目的的数字货币,与比特币相比,达世币的交易速度有了较大提升;未来币(Nextcoin,NXT)采用PoS共识机制,是全新设计和开发的第二代虚拟货币。未来币使用“透明锻造”方式产生新的区块,即通过账户的现有余额去“锻造”新区块,并给予新区块的“锻造者”奖励一定的交易费用。对于恶意锻造者其账户将被清零,以此作为惩罚。
6.1.2 基于区块链2.0的智能合约
基于区块链2.0的智能合约主导的去中心化应用,虽然丰富了区块链的应用场景,但整体上仍然延续了比特币在数字货币上的优势和应用惯性。区块链的本质是由多方共同维护的分布式数据库,如果数据库中记录的是用户的交易数据,则这个数据库就是一个分布式账本;如果记录的内容更加复杂(如学生学籍、公民身份证、护照等信息,或物联网中智能节点产生的感知数据等),则该数据库将会应用于更加广泛的场景,如学生学籍管理、公民身份信息管理、医疗信息管理、物联网应用等;如果能够将记录到区块链中的内容从静态数据扩展为可执行代码,并允许存在“if…then…”和“what…if…”循环判断语句,则可以通过预置合约条款的相应触发场景和判断规则,使区块链能够处理涉及复杂逻辑的交易过程,即实现智能合约。
以以太坊为代表的区块链2.0实现了智能合约功能,智能合约是一类以合约为交易数据的分布式数据库,被代码化的合约记录在区块链中,用户以发起交易的方式来触发合约状态的改变,当合约条款的触发条件满足时,预置的代码逻辑将自动执行,并将执行结果打包后保存在区块中,且经共识机制验证后将不能更改。
以太坊是以交易为对象的状态转移系统。以太坊账本中同时记录着交易数据和全局状态(world state)数据。其中,全局状态是以太坊账本当前的状态,账本中不仅记录了余额,还有合约的数据。以太坊的账户分为外部账户和合约账户两种类型,两者的状态变化都通过具体的交易触发,通常情况下,当一笔交易触发了外部账户时,将会使账户的余额发生变化,当一笔交易触发的是合约账户时,则会产生代码的执行。任何一类账户状态的变化,都需要在经过节点验证后才能够被记录。其中,外部账户状态的变化需要节点对交易进行验证,而合约账户状态的变化需要节点在EVM上进行验证。合约账户的存在,使区块链应用从货币领域向金融、管理、物联网等领域拓展。如果将区块链看作是通信子网,那么智能合约则是接入网络的主机,互联网应用的多样性和内容的丰富性由主机上运行的不同程序决定。同样,基于以太坊平台,可以通过智能合约开发各类去中心化应用,解决不同场景中的应用需求。
超级账本是为了解决以太坊在安全性和性能方面存在的不足,使区块链满足商业应用的需求而建立的开源规范和标准。超级账本中的智能合约通过构建联盟链为参与合作方建立一个透明、公开、半中心化的开发平台。联盟链中的典型代表Hyperledger Fabric由身份认证服务、账本服务和合约链码服务3个核心组件构成[44],其中身份认证服务提供对区块链网络接入节点和用户的认证,账本服务主要为交易数据的存储、账本及全局状态数据的更新等提供服务,合约链码服务作为账本服务的扩展,以Docker容器方式为运行复杂应用业务逻辑提供服务。
6.1.3 基于区块链3.0的EOS
虽然以太坊和超级账本通过增加智能合约层实现了区块链技术在复杂场景中的应用,但以太坊平台只能在并发访问数有限的环境中实现运行功能相对单一的智能合约,超级账本对复杂合约的运行也有限。
企业操作系统(EOS)[45]是专门为区块链应用开发的一款操作系统,具体在合约层下方创建一个功能等同于计算机操作系统的功能层,为企业用户开发更多基于区块链智能合约的应用场景,以实现更加复杂的去中心化应用(DApp)[46]提供操作系统级的支撑和服务。DApp基于区块链技术,将程序代码和运行结果全部保存在区块中,保证了程序运行的可靠性和数据的可信性,因此DApp可以看作是智能合约应用功能的扩展。在EOS中将参与挖矿的节点资源用来部署DApp,采用DPoS共识机制,通过见证人生成新区块。
DApp的出现,可以使开发者在开发区块链应用程序时,不需要像以太坊、超级账本那样还要关注底层的区块链技术,而是专注于构建能够运行在区块链上的DApp应用程序的开发上,DApp与区块链之间的信息交互由EOS负责完成。
区块链技术在持续扬弃中不断发展,实现了以需求为导向的应用创新。例如,针对PoW共识被诟病的能源浪费问题,适时提出了PoS、DPoS、PBFT等一系列共识机制,在能耗、出块速度、一致性、安全性、是否存在代币等方面提供了差异化的服务功能,以满足不同应用场景的需求。再如,在可扩展性方面,区块链技术为了应对全网所有节点使用完全相同的交易数据带来的效率和安全问题,在以太坊中提出了分片(sharding)[47]技术,在Hyperledger Fabric1.0中应用了多通道(multichannel)[48]解决方案。
6.2.1 分片技术
分片技术基于以太坊账户地址,将全网划分成多个地址域,每个相对独立的地址域称为一个分片,每个分片中维护着一条独立的子链。位于分片中的节点(一个节点可同时加入多个分片)在该分片内进行交易,并存储该分片中的交易数据。当需要访问的交易数据不在本分片内时,可以通过轻客户端技术从位于其他分片的节点上读取。
利用分片技术,单一节点不需要存储和处理全网的交易数据,同时整个区块链的处理能力不会受限于某一节点的计算能力[49]。
6.2.2 多通道技术
多通道技术基于交易规则,将整个区块链网络划分成为多个通道(一个节点可以同时加入多个通道,如图10所示),每个通道与关联的配置和数据(包括交易、账本、chaincode及成员身份等)共同构成一条完整的逻辑上的子链,每个节点可同时在多条子链上参与共识,每条子链上的交易具有独立性。
多通道机制将原来的单链结构演化成为多链(multi-chain)模式,不同的应用可根据需要生成不同的子链,不同的交易在各自不同的子链上并行处理,子链所在的通道之间相互隔离,避免了单链结构中处理能力存在的木桶效应。
Fig.10 Multichannel mechanism of Hyperledger Fabric图10 Hyperledger Fabric的多通道机制
区块链给社会发展的贡献不仅仅是技术方面,更在于人们对传统社会管理在理念的转变和方法的创新。仅就技术层面来讲,区块链虽然在近年来得到了迅猛发展,但与整个社会发展的预期之间仍然存在着较大距离。可从不同的视角分析区块链存在的问题和挑战,得出不同的结论。因本文主要基于体系结构和实现协议来分析区块链系统的基础架构,所以选择了与之直接关联的安全、隐私、漏洞和效率进行分析。需要说明的是:漏洞属于安全的范畴,但由于区块链技术发展迅速,应用场景丰富,对社会各领域产生的创新和变革力度大,系统设计和实现中有意预设和无意留下的漏洞成为攻击者寻找的目标和可利用的资源,借助各类安全漏洞的攻击威胁日益突出。为此,本节将漏洞单列出来进行分析。
6.3.1 安全挑战
数据冗余不仅是传统网络的安全手段,也是区块链的安全依赖。作恶节点如果通过伪造和篡改数据对区块链网络实施攻击,虽然在理论上是可行的,但实际上是很难实现的。然而,区块链并非一个物理隔离的系统,而是通过相关协议、规范与机制构建在互联网上的服务系统,攻击者将基于互联网结构和协议实现中存在的漏洞,间接地对区块链实施攻击,或将攻击行为转移到区块链系统,直接破坏区块链的安全性和稳定性。
区块链涉及到身份认证、共识机制、激励机制、智能合约等关键技术,每项技术又存在自身的实现细节,如此复杂的结构在尚未对安全性进行整体评估的前提下,无论是代码级的漏洞,还是系统配置上的不当,都潜在着安全隐患和可能发生的攻击行为。另外,与认证和控制机制相对完善的C/S结构相比,区块链采用的P2P网络传输模式在抵御网络入侵和攻击等方面存在着不足。
区块链应用具有广泛性,已涉及到数字货币、金融资产交易结算、数字政务、数据服务等众多领域,然而受技术和制度(例如,有些国家不承认数字货币的合法性)影响,在对区块链系统攻击行为的追责和取证等方面存在着困难。为此,由于区块链具有的不可篡改性,攻击者借助制度和技术上的漏洞一旦成功实施了攻击,其损失将无法挽回。例如,2016年发生的The DAO事件,攻击者利用智能合约存在的重大缺陷对以太坊成功实施了攻击,最终迫使以太坊分成两条链(硬分叉),一条为原链(即以太坊经典(Ethereum classic,ETC)),另一条为新的分叉链(即ETH,Ethereum的简称)。
SHA256算法和P2P协议是区块链系统中最基本的技术支撑和功能保障。由于SHA256算法在各类安全应用中扮演着重要的角色,因此针对SHA256散列吞吐量的提高成为散列算法一个研究方向[50]。用户为了获得更大利益,出现了针对SHA256算法的专用集成电路(application specific integrated circuit,ASIC)矿机和矿池,严重破坏了比特币等加密数字货币的正常运行机制,并使51%攻击难度变小。针对此类问题,设计并应用不利于并行计算的SHA256成为当务之急。目前,应用于莱特币的scrypt算法和达世币的X11算法通过增加内存消耗来提高ASIC开发的难度,可有效解决这一问题。
由于P2P网络没有提供身份认证、数据验证等安全机制,攻击者可以通过采用广播非法内容、传播恶意代码、实施DDoS攻击等手段,使信息传输延时,进而导致区块链产生分叉[51],或通过控制区块链节点的挖矿来实现自身利益的最大化[52]。处理P2P网络的安全问题是一个系统工程。针对公有链网络,Fadhil等[53]通过创建超级节点来降低网络的波动,以此来保证区块链节点免受外部因素的影响,并利用比特币网络的真实测量数据对提出的基于事件仿真的网络模型的有效性进行了验证;针对联盟链应用,Henry等[54]利用洋葱路由(the onion router,Tor)技术,在实现对接入节点身份的合法性进行有效验证的同时,通过节点之间的层层加密机制来保护数据的安全性及节点身份信息的匿名性。
6.3.2 隐私挑战
隐私即与用户相关但不愿公开的信息。区块链中的隐私信息主要包括用户身份信息和交易信息。其中,用户身份信息涉及到区块链中用户的公钥、所在节点的物理地址(MAC地址)和逻辑地址(IP地址)等内容,这些信息是公开的,即使是通过网络监听、流量分析等手段得到了详细的信息,但由于它们之间不存在相关性,因此无法通过信息之间的关联得知用户的隐私;比特币中的交易金额、交易内容、输入/输出地址等都属于交易信息,这些信息都是通过加密技术受保护的。另外,为了加强区块链的隐私保护,还采用了混币原理(CoinJoin)[55]、环签名[56]、同态加密[57]、零知识证明等安全措施。
然而,区块链(公有链)中节点的加入和离开是不受限制的,也无需身份验证。再加上每个节点都可以获得完整的数据备份,虽然通过隔断交易信息之间的关联来达到匿名目的,但这样的保护效果是有限的,攻击者通过观察和跟踪区块链的信息,通过节点的MAC地址、IP地址和用户的公钥等信息,还是可以追踪到账户和交易之间的关联性,并通过数据分析窥探用户的隐私。同时,在大数据和人工智能技术的辅助下,现有区块链中采取的隐私保护机制存在的脆弱性也逐渐暴露出来。再加上量子计算在信息安全中的应用,传统密码技术的安全性也受到了威胁。因此,加强区块链隐私的保护,需要不断地更新已有技术和完善相关的机制(如共识机制、激励机制等)。
在区块链隐私保护研究方面,祝烈煌等人[58]基于分层思想,从网络层、交易层和应用层分别提出了区块链隐私保护面临的主要威胁和相应的保护方法;张奥和白晓颖[59]对区块链隐私保护进行了综述,将隐私划分为交易内容隐私、账户地址隐私、用户身份隐私、节点隐私和通信隐私5类,给出了相应的隐私保护内容和隐私威胁攻击方式,并结合应用分析了相关的隐私保护技术;针对交易隐私威胁,闪电网络(lightning network)[60]通过在用户之间提供“外链”快速支付通道,将大量交易放在区块链之外结算和存储,以此来隐藏不在线用户之间的交易关系,达到对交易隐私进行保护的目的;针对用户身份隐私威胁,基于大蒜路由的I2P(invisible Internet project)网络[61]通过不断更新本地Net DB发现节点,来取代Tor网络中用目录服务器来管理节点的方法,同时I2P网络中针对同一节点发送信息和返回信息分别使用不同的链路,保持了流量的单向传输,更好地隐藏了节点的真实身份信息,可提升区块链地址的匿名性,增强了用户身份隐私的安全。
6.3.3 漏洞挑战
任何一个系统都存在漏洞,区块链也不例外。漏洞(vulnerability)是信息技术、产品及系统在需求分析、设计开发及配置等过程中有意或无意产生的缺陷(bug),这些缺陷一旦被利用,将会对系统造成严重损害。引起漏洞的因素很多,其中由针对区块链脚本语言的不严谨性和执行机制的不完善性引起的安全漏洞尤为突出。综合分析,具体反映在以下几个方面[62-63]:
(1)交易依赖性(transaction ordering dependence,TOD)。智能合约中账户状态信息的改变由交易触发、交易过程的先后次序决定了状态改变的过程和结果。尤其是引起合约账户状态改变的合约代码的执行,不同的执行次序将会产生截然不同或错误的结果。这种紧紧依赖交易顺序的智能合约容易引起作恶节点通过伪造交易及执行顺序来操控合约的执行。
(2)时间戳依赖(timestamp dependence)。时间戳是一段完整的、可验证的数据,它用于证明某一数据产生于某一特定的时间点。区块链中区块的先后顺序基于时间戳来确定,智能合约中一些合约的执行需要依赖时间戳。但受网络时钟影响,很难使所有节点的时钟都保持高度一致。时间戳在不同节点上存在的偏差为攻击者通过设置区块产生的时间戳来操控合约执行提供了可能的条件。
(3)可重入性弱点(reentrancy vulnerability)。当合约之间存在调用关系时,调用者进程会停下来等待被调用进程结束后再继续执行,攻击者利用调用进程的暂停时间段重复调用合约,实施可重入攻击。
(4)处理异常(mishandled exceptions)。当合约之间存在调用关系时,如果没有对被调用合约的状态和调用结果的正确性进行验证,有意或无意产生的不正确的结果将会影响智能合约的执行。
另外,以太坊在交易过程中会消耗gas,在合约执行前首先要计算账户余额是否能够支付交易所需的gas,如果发起交易用于触发合约执行的账户余额低于执行合约所需的gas,不但合约无法成功执行,而且账户余额将被清零。攻击者在获取了账户信息后,可以发起虚假交易来耗尽账户余额。此外,如果攻击者向合法用户的合约注入虚假的数据,用户也将被迫为这些垃圾数据的处理支付费用。
系统漏洞(尤其是可被利用的安全漏洞)的检测是一个难题,智能合约更不例外。针对智能合约存在的漏洞,可以借鉴对传统系统的漏洞检测方法,发现并修补合约中存在的引起gas消耗的代码。其中,智能合约的形式化验证可基于数学模型,通过相应的分析工具对合约从设计、开发和运行进行全过程验证,以规范合约的生成和执行,提高合约的可靠性[64]。
6.3.4 效率挑战
影响区块链效率的因素很多,主要包括广播机制、数据加解密、交易验证、共识机制等,具体可以分为以下几类:
(1)共识机制。共识机制用于在不存在信任的节点之间达成共识,确保数据的正确性和唯一性。然而,共识结果的达成是需要参与节点付出代价的,就像彩票一样,要想中奖就需要花钱购买彩票。共识过程需要消耗算力和时间,这在很大程度上影响了区块链的出块速度。
(2)交易效率。交易效率由出块速度来决定,目前比特币、以太坊和Hyperledger Fabric的出块速度分别为7 TPS(即每秒处理7笔交易)、25 TPS和2 000 TPS,较低的出块速度与区块链系统采用的共识机制有关,而在现有的共识机制下,较低的出块速度限制了区块链在金融行业等需要快速、小额交易场景中的应用。
(3)确认时间。目前,比特币的区块生成时间为10 min,由于在连续产生6个区块之后交易才不可逆,因此其交易确认时间为60 min;以太坊在连续产生12个区块之后交易不可逆,其交易确认时间为3 min。较长的确认时间限制了区块链在小额交易和时效性较强的场景中的应用。
(4)状态爆炸。从创世区块开始,比特币所有区块的大小从0增长到3 GB用了10年时间,以太坊从0增长到10 GB用了4年时间,区块链历史和状态数据的快速增长,呈现状态爆炸现象。Archive(归档)模式和Default(默认)模式是以太坊节点同步数据时采用的两种模式。其中,在Archive模式下所有历史数据(包括历史交易和历史状态)和当前状态数据都会保存下来,所有数据当前约为2 TB;在Default模式下,历史状态数据会被删除,本地只保留历史交易和当前状态数据,共约170 GB。因为每个节点都要保存一份数据备份,这对于快速增长的存储空间要求带来了挑战。
针对区块链的效率问题,学者们提出了多种有效的解决方案。例如,Eyal等[65]针对比特币在区块大小、出块时间及稳定性等方面存在的不足,提出了一种可扩展的区块链协议,可根据需要将区块分割成微块和宏块;Dickerson等[66]针对现行的区块链系统单位时间内可执行的合约数受限问题,提出了一种允许不同合约在互不冲突的前提下并行执行的框架等。
就像智能手机出现时那样,今天的区块链正在改变着这个世界。随着区块链越来越多地应用到不同的场景,区块链技术的影响力也将从数字加密货币扩展到不同社会领域,在改变甚至颠覆着越来越多的行业。区块链在没有任何第三方权威机构介入的情况下,在不存在信任基础的节点之间达成了彼此之间的共识,实现了去中心化、不可篡改、不可否认、可溯源的价值传输,进而使其应用从数字加密货币迅速扩展到整个社会系统,正在为人类社会处于的大发展大变革大调整的过程注入动力。然而,整个区块链技术和应用尚处于起步阶段,大量涉及到的基础理论和技术研究还需要结合学科及产业发展进一步跟进。