声明:本文旨在传递更多市场信息,不构成任何投资建议。文章仅代表作者观点,不代表火星财经官方立场。
边肖:记得要集中注意力。
来源:一级仓库
虽然以太坊是第一个拥有图灵完整智能合约的平台,但是已经可以使用一种叫做比特币脚本的语言在比特币上创建基本合约。比特币现金最近一直在完善其智能合约功能。虽然没有以太坊那么先进,但都以自己独特的方式和优势支持着智能合约在链条中的存在。
本文重点介绍这三个平台上的智能合约之间的显著差异。由于重点是智能合约和脚本函数,这里不讨论平台或区块链的基础知识。本文还介绍了链上的智能合约,还有几个第二层的智能合约解决方案,比如RSK。这些解决方案绝对值得讨论,因为篇幅没有做非常深入的研究。
以太坊:自身状态和完全图灵。
以太坊是迄今为止最大的智能合约平台,其智能合约由以太坊虚拟机(EVM)实现,这是一个图灵完全虚拟机。这意味着只要有足够的资源,EVM可以计算任何东西。从概念上讲,这类似于很多其他通用平台(比如Java虚拟机JVM),用来执行Java程序。
解释EVM
但是,那些常见的平台和以太坊的EVM最大的区别在于,以太坊的智能合约代码是由所有以太坊节点执行的,以验证交易的有效性。为了奖励执行这段代码的节点,所有EVM操作码都有相关的gas开销,如下图所示。
图:EVM费用结构
每个事务都会耗费大量的Gas,这取决于所使用的操作码。用邰方本地加密货币ETH支付汽油费。为了限制这些节点的每个块必须执行的计算量,对单个块可以使用的气体量有一个限制,称为“块气体限制”。
在智能合约功能的执行期间,合约可以存储和访问必要的数据。根据其用途,这些数据可以存储在不同的位置,即不同的数据位置。第一个是“堆栈”,它包含计算中使用的值。只有堆栈中的前16项可以轻松访问,因此不适合长期存储。使用堆栈的计算如下所示。
图:基于堆栈的计算
其次,为了补充堆栈,可以使用“契约内存”来存储、检索和传递当前契约执行过程中的数据。可以从内存中检索这些值,用于堆栈上的计算,并将结果存储回内存中。这些值仅在当前执行期间保持不变。合同执行结束时,合同存储器的内存和堆栈将被清除。
最后,数据的位置是“契约存储”,用于在契约执行期间永久保存数据。持久变量(如令牌余额)存储在协定存储中。为了实现数据持久性,每个以太坊节点上都存储了契约内存。因此,它的内存类似于RAM,而存储类似于硬盘驱动器或持久数据库。
关于以太坊虚拟机如何工作的更多细节,请参考MyCrypto的文章。
编写智能合同
虽然所有的智能合约都使用EVM,但是大多数智能合约并不是使用EVM字节码手工编写的,就像大多数JVM字节码不是手工编写的一样。相反,以太坊中有几种高级语言可以用来编写智能合约。最流行的语言是Solidity,除此之外还出现了Vyper,这也是一种面向EVM的编程语言。下图包含一个非常简单的Solidity smart契约的示例。
与智能合同交互
以太坊中的智能合约在以太坊网络上以字节码的形式存在。这意味着将Solidity代码编译成字节码,然后通过发送部署事务将其部署到网络。这是一种特殊的事务,没有任何接收者,但是使用字节码作为事务数据。
这些部署的契约只是以EVM字节码的“碎片”形式存在于网络中,几乎不能单独使用。为了与它们接口,有必要提供一个应用程序二进制接口(ABI ),它包括所有公共函数及其参数的列表。为了让用户更多地了解这些合同,以太扫描等服务帮助可以验证合同源代码,以便用户在使用合同前检查代码。
通过连接以太坊节点,使用其JSON-RPC接口,可以直接访问所有智能合约。然而,许多智能合同是通过连接到节点并管理ABI的前端应用程序来访问的。这可以通过许多不同的以太坊SDK(例如web3.js或ethers.js)中的一个来完成,这些SDK可以在后台调用JSON-RPC。这为合约用户提供了更好的体验,相当于把最难的部分可视化了。
您可以通过两种不同的方式与智能合约进行交互:调用和交易。是调用合同函数的本地调用,它不会向区块链广播任何内容。因此,调用过程是“只读”的,不能对合同状态进行任何更改,也不会产生任何费用。该交易是一个真正的“写操作”,它确实会被广播到网络并被纳入区块链,并将产生矿工费用。以ERC20 token为例,通过调用检索token余额,通过发起交易转移token。
智能合同间互操作性
以太坊的这些属性(具有图灵的完全EVM和持久存储)允许创建任何类型的运行在链上的分散式应用程序。DeFi生态系统就是一个很好的例子,它包括Maker、Uniswap和Compound等应用程序,以及ERC20和ERC721令牌标准。这些应用程序允许具有无限数量的动态参与者的复杂功能。
图:rDai中的DeFi互操作性
最重要的是,智能合约本身可以成为其他智能合约的“参与者”,从而实现这些合约之间的强集成和组合。例如,持有代币余额并将其借给与Uniswap Exchange的Compound或smart合约,或者使用rDai自动投资Dai并将应计利息捐献给慈善机构。
虽然智能合约可以相互交互,但链中的每笔交易都必须来自外部账户。因此,以太坊中智能合约之间的交互仍然必须由用户通过初始交易来触发。在这个初始触发之后,合同之间的交互类似于直接访问。
换句话说,智能合约可以调用其他智能合约的“只读功能”或触发“写操作”(事务)。因为只有外部账户可以触发交易,所以智能合约之间的交易称为内部交易或消息调用,以区别于用户发起的交易。
比特币:无状态且简单
所有比特币交易(包括常规转账)都由一种基于堆栈的编程语言支持,这种语言称为比特币脚本(Bitcoin Script)。上面提到的以太坊的EVM是为图灵的完整的、可互操作的智能契约而设计的,而比特币脚本则有意添加了各种限制,以一种根本不同的方式工作。
解释比特币脚本
就像EVM一样,比特币脚本使用堆栈来保存值并对这些值进行计算。但与EVM不同,堆栈是比特币脚本中唯一可用的数据位置。这意味着很难为以后的契约执行存储多个值。更重要的是,这意味着在合同执行期间不可能存储或修改那些仍然存在的值(但EVM可以)。
这是以太坊的智能合约和比特币最大的区别。以太坊的模型是有状态的,而比特币是无状态的。通俗的理解是,以太坊可以认为类似于普通的命令式变量数据编程范式,而比特币类似于功能不变的数据范式。
比特币的模型允许对交易进行独立且更有效的验证,这使得交易更容易并行化和碎片化。然而,在没有任何可变数据存储的情况下,在比特币上创建类似以太坊的复杂智能合约更加困难。例如,ERC20合约必须跟踪代币余额并做出更改。
除了这些身份差异,还有其他因素限制了比特币智能合约的复杂性。值得注意的是,比特币脚本缺乏对一些算术函数以及任何形式的循环或递归的支持。契约也有520字节的有效大小限制,最多只能包含201个操作码。
比特币上的智能合约大多属于几个简单的合约。例如,可以由多个参与者使用的多重签名合同,或者散列时间锁定合同(HTLC)。
一级仓库知识:关于哈希锁,可以举个简单的例子。比如你从我这里买了一个视频,这个视频是通过密码访问的,那么在交易合同中,我也会把视频的访问密码改成其中一个密钥。如果你想达成交易,你必须知道这把钥匙;一旦你知道了(你拿到了视频),钱就会支付给我,整个交易过程必须在设定的时间内完成。如果时间超过,合同会自动触发。
由于比特币上的这些合同非常简单,大部分价值是通过将不同的合同与其他离线应用逻辑相结合来获取的。通过这种方式,简单的合同可以组合起来创建复杂的解决方案,如闪电网络或跨链拍卖。
解释比特币交易
比特币的每一笔交易都是通过所谓的“交易输出”来实现的。当这些事务输出在帐户中可用时,它们被称为未使用的事务输出(UTXOs)。UTXOs由锁脚本(或scriptPubKey)锁定,并指定使用条件。尝试使用UTXOs时,会提供一个解锁脚本(或ScriptSig),然后这些脚本一起执行计算。只有当脚本执行无误且结果值正确(TRUE)时,事务才生效。
和EVM一样,所有的比特币节点都执行这些脚本来验证交易,但比特币区块链没有气体成本的概念。因此,每个字节的交易数据都会向矿工支付报酬。为了限制节点必须完成的工作负载,对一些更密集的脚本操作添加了一些限制。
与智能合同交互
比特币中的智能合约是用P2SH模式写的(一级仓注:有的翻译为“支付到脚本哈希”)。P2SH模式下的锁脚本包含脚本哈希,需要提供完整的脚本(称为赎回脚本)和赎回脚本的解锁脚本的解锁脚本。下图显示了这种模式。
图:P2SH模式
一级仓库知识:引入P2SH模式,简化复杂脚本的应用(传统机制是P2PKH)。复杂的锁定脚本被编译成一个20字节哈希的简单脚本,就像比特币地址是基于Base58编码的20字节公钥一样。P2SH和传统的P2PKH最大的区别就是把设置转出条件的发送方改成了接收方。通过在赎回脚本中添加各种转出条件,可以实现多签名交易等各种类型的交易。
比特币节点分两个阶段验证这些智能合约交易。首先,对赎回脚本进行哈希处理,并根据锁脚本中的哈希值进行检查。如果它们匹配,则使用锁定脚本来解锁赎回脚本,就像赎回脚本是原始锁定脚本一样。
因为比特币链上只存储字节码的哈希值,所以完整的字节码必须存储在链外,并且包含在任何契约执行的解锁脚本中。因此,比特币智能合约的“部署”是免费的,但后期执行合约的成本会更高。相反,以太坊的初期部署相对昂贵,而后续的合同执行则便宜。
这些部署上的差异鼓励了这两种智能合约的综合使用。一个很好的例子是LocalCryptos,它支持以太坊和比特币的非托管本地交易。对于以太坊,它使用大型智能合约来跟踪所有交易,而对于比特币,它为每笔交易创建单独的合约。
编写智能合同
虽然以太坊有很多可以编译成EVM字节码的高级语言,但比特币对此关注较少。虽然可以用比特币脚本构建的系统很复杂,但合约本身通常很简单。因此,几乎没有必要对底层系统进行抽象。此外,由于比特币合约的大小限制以及每增加一个字节的成本很高,因此保持合约“尽可能小”很重要。
虽然这些高级语言在比特币中并不是很重要,但它们确实存在。Ivy是比特币中“最精致”的高级语言,由Dan Robinson于2017年创立。下图显示了用Ivy编写的智能合同的示例。如果接收方未能及时使用该合同,则可以使用该合同发送汇款,汇款方可以收回该款项。
最近,Blockstream的几位研究人员发布了Miniscript,它专注于智能合约的分析和可组合性,而不是抽象底层系统。考虑到比特币合约往往缺乏抽象的复杂性,这似乎是一条正确的道路。
比特币:可组合的功能
一方面,以太坊可以创建很多强大有用的智能契约,这些契约完全存在于以太坊链中。同时,由于其有状态的性质,它也提出了可扩展性的问题。另一方面,比特币智能合约的无状态模型允许对智能合约交易进行独立和简单的验证,但其脚本系统限制了合约的实用性。
在分叉之前,比特币现金和比特币有着相同的历史,所以它们的底层脚本系统在功能上是相同的,比特币现金也受益于这些相同的方面。自那以后,比特币现金社区的很大一部分已经认识到需要“更有用的智能合约”。比特币实现了新的功能,使其智能合约更加有用,同时保留了允许比特币执行无状态验证的基本属性。
BCH的功能升级
要了解比特币现金智能合约的可能性,我们需要检查其每半年一次的网络升级。自2017年首次硬分叉以来,这些网络升级将在每年的5月和11月进行。特别是,我们讨论了比特币脚本引擎的变化,尽管其他一些改进也已经完成,如Schnorr签名。
在比特币早期,由于一些操作码的不安全使用而被禁用。在比特币现金分叉后的第一年内,比特币-ABC node的开发者解决了这些问题,重新引入了稍加修改的函数操作码,如下图所示。最重要的是,这一升级使比特币脚本中的结构化数据编码和解码成为可能。
图:2018年5月,BCH启用了新的操作码。
时隔半年,2018年11月比特币现金网升级中又发布了新的操作码。包括更新OP_CHECKDATASIG,它使用户能够验证比特币脚本中任何消息的签名。如果结合2018年推出的脚本更新,这些更新可以用来将新颖有用的智能合约功能引入比特币现金。
编写智能合同
与最初的比特币脚本相比,比特币现金的新功能为其智能合约增加了许多额外的复杂性。这使得拥有一个通过高级语言、SDK和工具提供更高抽象级别的生态系统变得更加重要。
目前正在处理这个问题的两个大项目是Spedn(笔名Tendo Pein创建)和CashScript(本文作者Rosco Kalis创建,灵感来自以太坊的Solidity语言)。虽然它们仍在积极开发中,但这些工具使比特币现金中的智能合约变得更容易处理。在下文中,将通过使用CashScript代码片段来解释一些功能。
神谕(甲骨文)
当结合过去的比特币脚本更新时,它们使您能够通过可信的预言机将外部数据带入比特币现金的智能合约中。结构化数据可以编码成字节数组,并由oracle提供者签名。然后,智能合约可以验证签名并解码结构化数据。
您可以在下面的HODLVault样本契约中查看此示例。合同由霍德林执行,直到达到一定的BCH/美元价格。所需的BCH/美元价格份额由oracle提供商发布,并由用户传递给合同。为了增加分散性,可以将智能合约设置为使用多个数据源,而不是信任单个集中式服务。
担保合同(契约)
第二个大的例子是被称为“契约”的技术,其名称来自物权法中用于限制对象使用的术语。就比特币现金而言,它限制了货币在智能合约中的使用。因此,尽管比特币中的智能合约只能授权一般的货币支出,但比特币现金合约可以对可支出的金额或收款人的身份进行限制。
在转移比特币时,发送者必须提供签名以授权交易。为了生成此签名,发送方对事务的哈希表示进行签名。这个哈希称为Sighash,实际的事务数据包含在原始的Sighash映像中。
通过使用_OP_CHECKSIG_和_OP_CHECKDATASIG_拥有相同的签名,我们可以访问Sighash数据。数据格式可在规范中查看,并包含在下图中。一个重要的字段是scriptCode,它包含智能契约本身的字节码。另一个是hashOutputs的输出,它允许用户强制执行事务。
图:比特币现金Sighash数据格式
很高兴知道担保合同在技术层面上是如何工作的,但是CashScript已经抽象了与合同相关的大部分复杂性。使用CashScript编写智能合约时,这些字段很容易获取,不需要手动验证和解码原始Sighash映像。
第一个使用担保契约技术的智能契约是丽池遗嘱,这是一个允许用户将死者的财产转移到自己财产的智能契约。合同定义了三种不同的功能。第一种允许继任者在180天后申请资金。第二种允许主人的ColdKey以任何方式花钱。第三个允许所有者的热键通过强制将全部合同余额发送回合同来刷新180天期限。
以下是《最后的遗嘱》的CashScript版本,但原始版本是由Spedn编写的,可以在这里查看。
这是有用的保证契约的简单例子之一,但是保证契约可以实现甚至更复杂的功能。在《Last Will》合同签署后,其创始人凯罗尔特尔泽什茨科夫斯基继续创建Mecenas,该公司可以强制执行定期付款,如Patreon。
担保契约最初是在标题为《Bitcoin Covenants》的论文中提出的,需要一个新的操作码_OP_CHECKOUTPUTVERIFY_。然后提出其他建议,比如_ OP _ checktemplatefirverify _ or _ OP _ CHECKSIGFROMSTACK _。后者非常类似于比特币现金的圣约实现。你可以在Tendo Pein的文章中了解更多关于保证合同的内容。
模拟状态(模拟状态)
看“遗嘱”合同。当合同生效时,更换继任者可能是有价值的。因为我们可以通过查看当前契约的字节码来强制发送到当前契约,所以我们可以通过稍微改变这个字节码来强制发送到稍微不同的契约。您可以创建一个函数,将整个契约的余额发送给字节码完全相同但后继者不同的契约。
我们只能使用已知大小(例如20字节)的构造函数参数来执行此操作。构造函数参数总是契约字节码的第一个数据,这是我们如何用新数据替换旧数据的方法。inheritor是第一个构造函数的参数,它的大小是20个字节,所以我们可以应用这个技术,如下图所示。
通过使用这种技术,可以在保持合同规则不变的情况下改变合同中的一些变量。我们称之为“模拟状态”是因为它提供了契约状态的一些好处,不存在以太坊这样的有状态系统的可伸缩性问题。这种方法还有其他缺点,因为必须在某处进行权衡。
主要问题是,我们实际上没有改变原始合同中的任何变量,因为由于比特币现金的无状态特性,这是不可能的。相反,创建一个新合同(使用新地址)并将所有余额转移到新合同。由于新的地址,这将导致UX问题,但是这些问题可以通过在这些智能契约上有良好的应用层抽象来缓解。
在字节码中替换这些变量可能会很麻烦,尤其是在试图替换字节码中更深层次的变量时。这个函数应该用高级语言抽象出来,通过提供新的参数来自动生成新的字节码。这种抽象可能如下所示:
许多抽象是以更大的合同为代价的,这会导致更高的成本。但比特币现金的交易成本通常很低,可谓两者兼而有之。但是比特币现金和比特币有相同的大小限制,所以这些抽象确实增加了保持在限制范围内的难度。因此,许多开发人员不得不手动优化编译后的字节码。
结论
每种加密货币都在其智能合约系统中进行称重。以太坊是最通用、最常用的智能合约平台。比特币通过其无状态脚本系统提供了更基础的智能合约版本,验证效率更高,但功能更少。比特币和比特币的基础是一样的,只是增加了新的功能,试图在有效的验证和有用的智能合约之间妥协。最后,大家都在朝着一个相似的目标前进。
展望未来
本文写于2019年第四季度,反映平台现状。加密货币是一个快节奏的领域,因此参与这些平台的人总是试图做出改进,这可能会改变生态系统的前景。
以太坊正在开发以太坊的主版本2.0,其0期计划于2020年第一季度上线。以太坊2.0旨在通过转移到权益证明、实现碎片化等改进,解决以太坊1.x的性能问题。ETH2.0的完整路线图尚未确定,可能需要几年时间才能推出。但是,如果这次重大更新能够达到目的,就可以为以太坊提供强有力的支持。
对比特币智能合约的研究致力于进一步提高智能合约的效率和隐私,包括Taproot和无脚本脚本等解决方案。另一方面,比特币现金继续致力于实现其他智能合约功能,并使这些变化更容易实现。