【问链财经-区块链基础知识系列】 第三十七课 区块链智能合约重新认识:不再智能
> 编者按:不得不说在区块链世界里“智能合约”这个词被用滥了,就好像有了智能合约以后,社会一下进入智能时代,改变了整个社会的运行轨迹,但事实上它真有宣传的那么神吗,那么无所不能吗,接下来我们就来重新认识一下。
一、什么是智能合约
1995年Nick.Szabo首次提出智能合约概念,定义为:一个智能合约是一套以数字形式定义的承诺,包括合约参与方可以在上面执行这些承诺的协议。2015年Vitalik Buterin将智能合约引入区块链,创建了智能合约运行平台以太坊,智能合约因此得到了极大的发展。很多人开始坚信“代码及法律”,期望智能合约带来去中心化的完美世界。然而智能合约并不智能。我希望重新给他起个名字:合约代码,而不是叫智能合约。但也应该做好对自然语言合约和程序代码的区分,强调合理和实质性。智能合约的代码编写越简单越好而不是把整个自然语言的合同都放在上面。只有能简单到‘如果…,就…’ 的逻辑才能用代码来表达。
合约,又称合同,是以双方当事人互相对立合致的意思表示所构成的一种法律行为。一个正常的合约是两个或多个当事人之间的协议,它将他们与未来的某件事绑定在一起。Alice可以用Bob的房子(也就是租金)支付Bob一些钱。查理可能会同意在未来对Denise的汽车进行任何损坏,以换取每月的付款(也就是汽车保险)。
合约代码的不同之处在于,条件都是由计算机代码评估和执行的,这使得它变得不需要信任。因此,如果Alice同意支付给Bob500美元,让他在3个月后买一个沙发,一些代码就可以确定条件是否正确(Alice付钱给Bob了吗? 已经3个月了吗?)然后执行(将沙发从托管中交付)而不给任何一方退出的能力。
合约代码的关键特征是它的执行不可靠。也就是说,您不需要依赖第三方来执行各种条件。一份合约代码不是依靠对方来兑现诺言,甚至更糟,不是依靠律师和法律体系在出现问题时进行补救,而是及时、客观地执行应该发生的事情。
“智能”一词的使用意味着这些契约具有某种天生的智慧,他们没有。合约的巧妙之处在于不需要对方的合作来执行协议。一份智能合约可能将把那些不付房租的租房者锁在公寓门外,而不是把他们赶出去。达成协议的后果是使智能合约变得强大,而不是在合约本身的智力。
一个真正明智的合约会考虑到所有可减轻的情况,审视合约的精神,做出即使在最黑暗的情况下也是公平的裁决。换句话说,一个真正智能的合约就像一个真正优秀的法官。相反,在这种情况下,“智能合约”根本就不智能。它实际上是基于规则的,遵循规则,不能考虑任何次要的考虑或法律的“精神”。
二、智能合约典型代表
1.比特币的智能合约
从2009年开始,比特币就有了一种相当广泛的智能合约语言——脚本。脚本是一种简单的计算机语言,比如JavaScript就是一种脚本。比特币的脚本可以表述的内容非常灵活,远远超出了一对一转账的范畴。例如:A可以约定必须由收款人B和担保人C同时签名才能支配某笔比特币(担保交易),也可以约定B、C、D中任意两人签名就能支配(联名账户);A可以约定B必须在一年后才能动用某笔比特币(延时支付),也可以约定任何人都能支配(撒钱)或者都不能支配(烧钱)。通过这套内置的脚本编程语言,你可以灵活地编写出各种各样的约定——而这其实就是简单的智能合约。用比特币脚本编写的合约系统,使得比特币成为了人类历史上第一种可编程的货币。
现在请把你的大脑当做一台基于堆栈的解释器和虚拟机,看看比特币的脚本到底是怎么运作的。一个典型的比特币标准交易(Pay-to-Public-Key-Hash)的验证流程,需要执行这样的脚本:
scriptPubKey: OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG
(scriptPubKey就是前文比喻的1 BTC上的脚本“锁”)
scriptSig: <sig> <pubKey>
(scriptSig就是前文比喻的发送方A提供的脚本“钥匙”)
脚本执行完毕后,如果结果为true,那么说明验证通过,A有权支配这笔比特币。比特币网络就会根据A的指示为这笔比特币加上一把“新锁”,转账完成。
为了保持比特币的向前兼容和简单稳定,比特币的开发者们对其脚本做了诸多限制。比如脚本中没有循环语句,比如bitcoin core客户端目前只支持5种固定模式的脚本。这一方面是由于历史包袱,一方面是比特币的开发团队倾向于保守和稳健。因此说它不是图灵完备的。图灵完备是指一个能计算出每个图灵可计算函数(Turing-computable function)的计算系统。或者说,图灵完备使我们的脚本系统有能力解决所有的可计算问题。一方面,它带来了强大的处理能力;另一方面,它也使对脚本的静态分析变为不可能:我们永远也无法知道脚本何时会停止,除非我们真正去执行它。
比特币网络中的每一个节点都要执行每一笔交易中的脚本,这就使得比特币脚本系统的设计需要足够精简。而作为一个点对点的电子现金系统,比特币也确实无需更为复杂的脚本系统。
2.以太坊的智能合约
以太坊中的智能合约是图灵完备的。在图灵完整的上下文中执行是非常棘手的,而且很难分析。确保一个完整的智能合约就相当于证明一个计算机程序没有错误。我们知道这很困难,因为几乎所有存在的计算机程序都有bug。
考虑到写正常的合约需要数年的学习和一个很难的律师考试才能胜任写作。智能合约至少需要这样的能力水平,但目前,许多合约都是新手写的,他们不知道它需要多安全。从各种被证明存在缺陷的合约中可以看出这一点。
比特币解决这一问题的办法就是不具备图灵的完整性。这使契约更容易分析,因为程序的可能状态更容易枚举和检查。
以太坊的解决方案是给那些智能的合约开发者们增加负担。合约作者要确保合约履行他们的意愿。
智能合约并不是真正的合约(至少在ETH上),在理论上,把确保合约安全的责任交给开发者听起来不错,但在实践中,这产生了一些严重的集中后果。
Ethereum提出的理念是“代码就是法律”。也就是说,以太公司的合约是最终的权威,没有人可以否决这个合约。这个想法是为了向智能合约开发人员表明他们是独立的。如果你把自己的智能合约搞砸了,那么从某种意义上说,你是自己承担后果的。当DAO事件发生时,这一切都戛然而止了。
DAO代表“分散的自治组织”,并在Ethereum (Ethereum)设立了一个基金,用以展示平台的功能。用户可以将钱存入DAO并根据DAO所做的投资获得回报。这些决定本身将是由群众决定的,分散的。在ETH币在20美元左右时,这个组织在以太坊上筹集了1.5亿美元。这一切在理论上听起来都不错,但有一个问题。代码没有得到很好的保护,导致有人想出了一个办法来耗尽DAO的钱。
“黑客”攻击DAO。从某种意义上说,“黑客”找到了一种从合约中获取金钱的方式,这种方式不是创作者的本意,这是真的。但从更广泛的意义上来说,这根本不是黑客,只是一个利用智能合约中的漏洞对他们有利的人。这和一个有创意的注册会计师想出一个税收漏洞来为他们的客户省钱是没什么区别的。
接下来发生的事情是,Ethereum认为代码不再是法律,而是把所有进入DAO的钱都锁定了。换句话说,合约开发者和投资者做了一些愚蠢的事情,Ethereum的开发者决定对他们进行纾困。
这一事件的后果已得到充分的记录。以太经典诞生了,“code is no longer law”。此外,开发人员开始回避使用Ethereum的图-完全性,因为它被证明很难保证。ERC20和ERC721标准是Ethereum中最常用的智能合约模板,需要指出的是,这两种类型的合约都可以在没有任何图灵完整性的情况下编写。
以太坊中的智能合约是运行在区块链上的一段代码,代码的逻辑定义了合约的内容。合约的账户保存了合约当前的运行状态,主要包含了4部分内容。
balance:当前余额
nonce: 交易次数
code: 合约代码
storge: 存储,是一棵MPT
智能合约一般使用Solidity语言进行编写,语法上与JavaScript相似。如下是一段Solidity编写的智能合约的代码,这段代码是一个商品拍卖的智能合约。所有参与拍卖的人员对商品进行竞价,每次竞价时都会将相应的价格发送到智能合约中,合约会自动记录竞价人的报价,拍卖结束时,出价最高者获得拍卖品,同时出价最高者的钱会发送给受益人。其他人可以使用withDraw函数拿回自己的钱。代码详细内容见注释。
pragma solididity ^0.4.21 // 声明使用的solidity版本contract SimpleAuction{ // 声明一个SimplaAuction的合约类address public beneficiary; // 拍卖受益人uint public auctionEnd; // 拍卖截止日期address public highestBidder; // 当前的最高出价人mapping(address => uint) bids; // 所有竞拍者的出价,map结构address[] bidders; // 所有竞拍者数组// 需要记录的事件,event主要用来记录日志event HighestBidIncreased(address bidder, uint amount); // 出价最高的人发生变动event Pay2Beneficiary(address winner, uint amount); // 竞拍成功者的钱发送给受益人/// constructor是构造函数/// _biddingTime 表示拍卖时长/// _beneficiary 表示拍卖受益人constructor(uint _biddingTime, address _beneficiary) public{beneficiary = _beneficiary;auctionEnd = now + _biddingTime;}/// 对拍卖进行竞价,如果之前出过价,就会把之前的价格与当前价格求和作为竞价function bid() public payable{...}/// 参与投标的人在拍卖结束后取回自己的钱function withdraw() public returns(bool){}/// 结束拍卖,将最高出价的钱发送给受益人function pay2Beneficiary() public returns(bools){}}
智能合约的构造函数名,最新版本使用constructor关键字,不推荐使用类名命名构造函数。构造函数只能有1个。构造函数仅仅在合约创建的时候调用一次。
bid()函数中,可以看到有一个 payable 关键字。如果一个函数添加了关键字payable,表明该函数接受转账,如果一个函数不写payable关键字,表明该函数不接受转账。
bid()函数, withdraw()函数,pay2Beneficiary()函数是成员函数,他们有public修饰,表示可供外部调用。
solidity中的map,其结构不支持遍历,这就意味着需要手动记录map中的元素。一般使用数组进行记录。上述代码中使用bidders记录参与竞拍的人。solidity中的数组元素既可以是定长数组,也可以是可变数组。
编写好智能合约之后,如何将该智能合约发布到区块链上呢?在以太坊中,发布一个智能合约,只需要将该合约的内容写入到一笔交易即可。具体过程如下:
利用一个外部帐户发起一个转账交易,这笔交易的收款地址为0x0,转账金额设置为0。
将智能合约代码编译为二进制字节码,并将这些二进制字节码写入交易的data域。
填写交易其他部分内容。
发布交易,交易执行完毕后会返回智能合约的地址。
通过上述步骤就可以创建一个智能合约,以后调用智能合约时就将交易的收款地址写为智能合约的地址即可。
3.fabric的智能合约
在fabric中chaincode代码通常处理由网络成员同意的业务逻辑,因此它相当于“智能合约”。可以调用chaincode代码来更新或查询提案交易中的分类帐。考虑到适当的许可,chaincode代码可以调用另一个chaincode代码,无论是在同一频道还是在不同的频道中,以访问其状态。请注意,如果被调用的chaincode代码与调用chaincode代码位于不同的通道上,则只允许读取查询。也就是说,不同渠道上的被调用的chaincode代码只是一个查询,它在随后的提交阶段不参与状态验证检查。
Fabric的Chaincode运行在容器中,可以使用Go,Java,Node.js语言开发,Golang是目前为主比较成熟稳定的。
Chaincode主要由下面几个组成:
- 必须在main包下
- 引用必要的依赖
- 定义一个结构体,并为结构体绑定Init和Invoke方法
- shim.ChaincodeStubInterface和pb.Response
main方法
下面以一个例子进行说明
// 1.在main包下
package main
// 2.引入必要的依赖
import("fmt""github.com/hyperledger/fabric/core/chaincode/shim"pb "github.com/hyperledger/fabric/protos/peer"
)
// 3.定义一个结构体
type mychaincode struct {
}
// 4.为结构体绑定init和invoke方法
func (t *mychaincode) Init(stub shim.ChaincodeStubInterface) pb.Response{fmt.Println(" << ====[Init] success init it is view in docker ======")return shim.Success([]byte("success init"))
}func (t *mychaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response{fmt.Println(" << ====[Invoke] success init it is view in docker ======")return shim.Success([]byte("success init"))
}
// 5.主方法
func main(){err := shim.Start(new(mychaincode))if err != nil{fmt.Println("Error starting Simple chaincode : %s",err)}
}
三、总结
图灵完备的智能合约,已经被证实是很难维护的。因此,以太坊开发人员不再刻意去追求智能合约的图灵完备性。
目前,以太坊中使用最多的智能合约模板是图灵不完备的ERC20和ERC721。
即使放弃图灵完备性,智能合约听起来也还不错。毕竟,没有人喜欢必须通过法律才能获得本属于他的东西或权利,相比于普通纸质合约,智能合约使用起来真的更容易吗?
比如,智能合约真的能用于房地产吗?通过智能合约,可以证明Alice拥有房子的所有权,Bob通过付钱给Alice获得房子的使用权,合约保证交易能快速执行,且不需要律师等任何第三方的介入,听起来真的很不错!
但是,仍然存在两个问题。
通过中心化组织执行的智能合约并没有做到去信任,你仍然需要信任这个中心化组织。去信任是智能合约的关键特征,因此中心化执行并不合理,实际上你需要的是一个去中心化平台。
在去中心化的情况下,只有当数字合约内容与现实真实情景间确实存在一些确定联系时,智能合约才有效。也就是说,在智能合约中房屋所有权发生变更时,现实中的房屋所有权也必须发生了改变。
数字世界需要保证与现实世界的完美契合。
当Alice将房子转让给Bob时,智能合约需要匹配真实情况。
现实中,可以做到数字世界与现实世界的真实匹配,但面临着一个问题,现实世界中,必须有可信任的第三方来进行验证。
比如,将房屋作为以太坊上不可替代的Token,Alice可以通过原子交换,将房子转给Bob,获得一定数量的以太币。
这就存在一个很关键的问题,Bob需要相信这种Token可以代表Alice的房屋,相信获得代表房屋的Token就可以获得房屋的所有权。
此外,即使政府机构证明Token可以代表房屋,但试想,如果Token被偷,房子就属于偷窃者吗?如果Token丢失,房屋就不能再出售了吗?房屋Token可以重新发行吗?如果可以,由谁发行呢?
在去中心化环境下,无论是水果,汽车还是房屋,将数字资产与实物资产联系起来,是一个很难解决的问题,
对于实体资产交易,除了信任特定的智能合约之外,你还需要信任自身所处环境的司法管辖。
也就是说,拥有智能合约并不意味着拥有实体资产,你会遇到普通合约相同的信任问题。
依赖第三方信任的智能合约丢失了其去信任化的关键特性。
即使是电子书,医疗记录或电影等数字资产也面临着同样的问题。
只有数字化无记名票据才能真正“舍弃”第三方信任。代币的所有权在智能签约平台之外,不具有依赖关系,这才能真正实现去信任化。
因此,智能合约并不像我们想象的那么有用。
我们希望智能的合约比实际更有用。不幸的是,我们人类所认为的契约带来了大量的假设和建立的判例法,这些都不需要明确说明。
此外,利用图灵完整性是一种容易搞砸并导致各种意外行为的方法。我们应该给智能合约平台贴上图灵或者不是图灵的标签。DAO事件也证明了合约的“精神”是隐含的信任,有助于解决纠纷,而不是我们意识到的。
智能的合约太容易搞砸,太难以确保,太难以让人信任,并且有太多的外部依赖关系来处理大多数事情。只有在像比特币这样分散的平台上,智能合约才会增加信任感。
【问链财经-区块链基础知识系列】 第三十七课 区块链智能合约重新认识:不再智能相关推荐
- 【问链财经-区块链基础知识系列】 第二十七课 区块链与分布式账本的异同
编者按:在加密货币和区块链领域,有一个业内人士常挂在嘴边的新术语:分布式账本技术(简称DLT).但具有讽刺意味的是,恰恰是比特币和各种区块链试图颠覆的实体们,例如银行,政府和大公司,对分布式账本技术情 ...
- 【问链财经-区块链基础知识系列】 第十七课 区块链应用于汽车保险行业所带来的变革
编者按:在一般汽车保险诈骗案,汽车驾驶会故意安排假车祸,然后向保险公司提出各种不实和非法的索赔.据德勤(Deloitte)统计,这些假车祸每年让保险业损失约7亿新元.汽车驾驶若对不同保险公司索赔,除非 ...
- 【问链财经-区块链基础知识系列】 第二十一课 区块链应用于大宗商品供应链金融
编者按:融资难.融资贵一直是中小企业难以摆脱的"心结".日前,国内首例基于区块链技术的大宗商品证券化融资在上海煤炭交易所(以下简称"上海煤交所")完成全业务流程 ...
- 【区块链基础知识系列】 第6课 区块链之分片技术(sharding)-区块链扩容问题的良方
进行区块链扩容的一个答案就是分片技术(Sharding).分片技术承诺通过改变网络验证的方式来增加吞吐量.分片技术独特于其他解决扩容的链上技术的关键特性,就是它可以进行水平扩容,也就是说,网络的吞吐量 ...
- 【区块链基础知识系列】 第8课 区块链之零知识证明
所谓零知识证明,指的是示证者在证明自己身份时不泄露任何信息,验证者得不到示证者的任何私有信息,但又能有效证明对方身份的一种方法. 从本质上讲,零知识证明是一种协议.所谓协议(Protocol),就是两 ...
- 【问链-区块链基础知识系列】 第十课 首席架构师谈区块链技术演进
一.区块链和比特币,都有"币-链-网"三层含义 1.第一层含义是"币".这个"币"并不是刚才王行长所说的真正意义上的"货币&quo ...
- 【区块链基础知识系列】 第9课 一文诠释什么是DAG
一.什么是DAG? 有向无环图(Direct Acyclic Graph或DAG)是可以说是近几年区块链项目的技术热点之一.不少业内人士都认为这项技术有可能在根本上解决区块链的扩容问题,因此相关的项目 ...
- 区块链基础知识系列 第三课 区块链中的默克尔树
"区块链是实现无中心分布式总账的一种技术.除了采用块.链结构的典型区块链以外,还有其他的方式实现分布式总账这个需求.总账技术的基本单元是'交易',整个账本是由一条条的交易构成.'块'类似于账 ...
- 链方法[C# 基础知识系列]专题三:如何用委托包装多个方法——委托链
最近研究链方法,稍微总结一下,以后继续补充: 弁言: 上一专题分析了下编译器是如何来翻译委托的,从中间语言的角度去看委托,希望可以帮助大家进一步的理解委托,然而之前的分析都是委托只是封装一个方法,那委 ...
最新文章
- Java项目:嘟嘟校园一卡通系统(java+JSP+Servlet+html+css+JavaScript+JQuery+Ajax+mysql)
- Delphi动态事件
- mezzanine安装配置
- java综合项目推荐,推荐20个5月最热门的Java开源项目
- 终于要跟大家见面了,Flink 面试指南
- bash ./php-memcache.sh,PHP+shell脚本操作Memcached和Apache Status的实例分享
- python ndimage_Python ndimage.zoom方法代码示例
- 元素周期表Mac动态桌面壁纸
- TCN机器之心的转载,后面需要实现
- 步进驱动系统:步进电机与步进驱动器控制原理简述
- 2018 Google IO大会来了
- 计算机网络初探教案,计算机网络基础知识教案.doc
- 先有鸡还是先有蛋的定论
- 我们为什么要使用室内定位技术?
- expect 自动输入密码
- 图形化WiFi密码的破解
- 图片打开太暗看不清并且手机传给电脑的视频打开卡
- Sign In With Apple
- 面试题 08.08. 有重复字符串的排列组合
- 大家尽管鄙视这种人吧!