早在一些数字资产发布之前,计算机科学家兼数学家尼克·沙博首先创造了“智能合同”一词,他将其定义为“一套以数字形式指定的承诺,包括各方履行其他承诺的协议”。此类合约可以在不使用人工智能的情况下创建和执行。他于1995年提出这个想法,他关于智能合约的文章于1996年在一本名为《Extropy》的杂志上发表。Szabo基本上首先定义了“什么是智能合约?”并提出了使用它们的各种场景。
基于区块链技术的智能合约不仅可以发挥智能合约在成本效率方面的优势,而且可以避免恶意行为对合约正常执行的干扰。将智能合约以数字化的形式写入区块链中,由区块链技术的特性保障存储、读取、执行整个过程透明可跟踪、不可攥改。同时,由区块链自带的共识算法构建出一套状态机系统,使得智能合约能够高效地运行。
智能合约由三个主要部分组成:各方之间的合同安排、履行合同义务中设定条件的管理、合同的执行。
可以使用智能合约运行的潜在活动包括支付转账、车辆登记、发送警报、开票等。一旦选定的交易完成,区块链数据就会更新。这样的框架确保它不能被第三方操纵,并且只能被参与交易的各方查看。由于必须确保交易方的安全和隐私,基于区块链的数字分类账系统至关重要。单个交易的数据按顺序捆绑并存储在区块链的块中。消除中心化监督有助于提高此类交易的安全性和防篡改性质。
与以识别问题开始并以解决问题结束的区块链生命周期不同,区块链上的智能合约经历不同的阶段:
创建阶段
合同谈判和重申是第一阶段的重要组成部分。相关各方必须就合同中列出的条款达成共识。这与我们习惯于以物理方式进行的传统合同谈判非常相似,只是以数字方式进行维护。合约参与者还必须在区块链上拥有一个用于起草智能合约的钱包。合同内容一旦确定,就必须编纂成文。由于每个智能合约的个性化性质,编码有时变得困难。因此,大多数区块链开发人员提供了在创建智能合约时测试其行为的方法,以模仿其实际行为。
冻结阶段
区块链上的交易由网络上称为节点的一组计算机进行验证。这些节点只不过是区块链矿工,他们利用自己的计算能力来确保智能合约的公平治理。作为对他们服务的回报,这些矿工也会获得少量费用。这个框架确保区块链只有合法的合约,不会被虚假条目堵塞。在“冻结”阶段,合约及其参与者在公共分类账上向公众开放。在此期间,任何形式的资金转移都会被阻止,因为节点充当管理机构,验证是否满足合同执行的先决条件。
执行阶段
智能合约的完整性由认证节点验证,合约的干扰引擎(或编译器)执行代码。当以硬币的形式收到来自一方的输入(作为要交换的商品的承诺)时,干扰引擎创建由满足标准触发的交易。然后将新的交易数据添加到区块链中,并再次由管理节点验证,以确保根据合同中商定的条款履行。此验证过程由“共识机制”管理,即工作量证明或权益证明。
合约完成
一旦交易数据被写入区块链的分布式账本,共识机制会验证第一方转移的资产是否已经收到,并为接收方解冻。这标志着智能合约的完成,然后关闭并记录。
智能合约的安全性通常可以从代码编写、合约虚拟机和区块链特性这三个维度展开,以下分别对这三个方面的安全性漏洞进行了分析。
一、合约隐私泄露
即使在联盟链中,由于区块链交易信息公开,合约代码完全开源,合约从创建、部署到执行的整个过程都会被广播到参与联盟链的全部节点,导致合约参与者的真实身份有很大可能会被有意的攻击方识破。一些机密合约的隐私内容,有时不便公开,如果依然采用原先的部署、执行方式,将导致合约参与者的重要信息受到威胁。
二、合约主体漏洞
智能合約的代码编写不同于以往的项目开发,智能合约在部署后一旦出现问题,所付出的代价是巨大的,对于多种区块链来说都难以简单的解决,因此我们在编写合约代码时要提升安全思维,做好安全准备。
1、函数可重入性
智能合约执行过程中当一个合约调用另一个合约时,当前的执行过程会暂停等待另一个合约的返回值。这会导致一个很严重的问题,如果程序可以在执行过程中被中断,则可以在其先前的调用完成执行之前安全地再次调用,这被称为可重入计算机程序。在调用其他外部函数的操作完成前,这个被调用的函数很有可能会被多次执行,这种多次调用可能会造成难以想象的问题。
2、 函数可见性
以Solidity为例,在使用Solidity编写合约代码时,共提供了4种函数可见性修饰符,在开发者没有指明的情况下,默认为public。当开发者没有明确指明函数可见性时,可能导致部分关键函数的可见性为公开的,这使得任何外部用户都可以调用这一函数,可能会造成巨大损失。
3、误操作异常
在以太坊中,允许一个合约通过send指令或者直接调用的方式去调用另一个合约内的函数。然而在调用过程中可能会出现错误,例如gas不足、超出调用栈限制,调用就会终止,合约就会回退到之前的状态。调用者很可能并未获知调用过程中出现的异常,这主要取决于调用的方式。使用这条指令调用合约后,必须检查返回值驗证合约是否正确执行。根据数据统计,现有合约中约28%的合约在调用后不会检查异常返回值,这在一定程度上会造成许多问题。
三、虚拟机安全漏洞
合约虚拟机运行在区块链的各个节点之上,虚拟机为合约代码提供了一个沙箱式的执行环境,如果合约虚拟机存在漏洞或不完善的地方,则很由可能会受到攻击者的攻击,虚拟机系统相比较于传统的计算机运行环境具有更多的攻击安全隐患,以下列出常见的几种:
(1)逃逸漏洞:虚拟机在运行中,一般进程只能在沙盒的限制中执行相应的代码,逃逸漏洞指的是进程越过虚拟机范围,进入到宿主机的操作系统中,这种漏洞会使攻击者退出沙盒环境,执行其他本不能执行的代码。
(2)逻辑漏洞:虚拟机在发现数据或代码不符合规范时,可能会对数据做一些“容错处理”,这就导致可能会出现一些逻辑问题,最典型的是“以太坊短地址攻击”。
(3)堆栈溢出漏洞:虚拟机的调用栈有确定的最大深度,在一些攻击者的恶意调用下,有可能导致栈的深度超过虚拟机允许的最大深度,或不断占用系统内存导致内存溢出。
(4)资源滥用漏洞:指的是攻击者在虚拟机中执行恶意代码,估计消耗系统的网络资源、存储资源、计算资源、内存资源。所以在虚拟机系统中必须要有一些限制机制来防止系统的资源被滥用。
四、区块链特性导致的漏洞
1、交易顺序依赖
在区块链中一个区块包含多条交易,而一笔交易从被广播出去到被确认并包含在一个区块内需要一定的时间。我们假设有一个区块链目前处于状态σ,新区块中包括两条调用相同合约的交易(deg:Ti,Tj),在这种情况下,用户无法确定合约在执行调用时是什么状态。当合约处于σ[Ti]时执行Tj的调用和处于σ[Tj]时执行Ti的调用可能会造成截然不同的结果,这取决于Ti和Tj之间的顺序,而只有挖掘这一区块的节点才能决定这些交易的顺序,从而决定合约被调用的顺序。如果有攻击者在监听到网络中对应合约的交易后,发出他自己的交易来改变当前的合约状态,则有一定几率使这两笔交易包含在同一个区块下面,并且有可能排在另一个交易之前,完成攻击。合约的最终状态实际上取决节点在确认时的交易顺序, 我们将此类合约称为交易依赖合约或TOD合约。
2、 时间戳依赖
另一个很重要的安全问题是,合约有时会用区块时间戳作为执行一系列关键操作的触发条件。我们把这样的合约称为时间戳依赖合约,在许多合约游戏中都会使用随机数来决定谁赢得头奖,这些合约使用了之前的区块哈希作为随机种子来挑选冠军,区块的选择则取决于当前区块的时间戳。通常来说,当节点确认一个区块时,它会为这个区块设置一个时间戳,这个时间一般是节点的本地系统时间。但是,节点可以在900s的范围之内随意改变这个时间戳,与此同时其他节点仍然会接受并确认它。节点处理一个新的区块时,如果新的区块的时间戳大于上一个区块,并且时间戳之差小于900秒,那么这个新区块的时间戳就是合法的,因此有一些攻击者就可以通过改变时间戳来控制合约的输出结果
基于区块链技术的智能合约不仅可以发挥智能合约在成本效率方面的优势,而且可以避免恶意行为对合约正常执行的干扰。将智能合约以数字化的形式写入区块链中,由区块链技术的特性保障存储、读取、执行整个过程透明可跟踪、不可攥改。同时,由区块链自带的共识算法构建出一套状态机系统,使得智能合约能够高效地运行。
智能合约由三个主要部分组成:各方之间的合同安排、履行合同义务中设定条件的管理、合同的执行。
可以使用智能合约运行的潜在活动包括支付转账、车辆登记、发送警报、开票等。一旦选定的交易完成,区块链数据就会更新。这样的框架确保它不能被第三方操纵,并且只能被参与交易的各方查看。由于必须确保交易方的安全和隐私,基于区块链的数字分类账系统至关重要。单个交易的数据按顺序捆绑并存储在区块链的块中。消除中心化监督有助于提高此类交易的安全性和防篡改性质。
与以识别问题开始并以解决问题结束的区块链生命周期不同,区块链上的智能合约经历不同的阶段:
创建阶段
合同谈判和重申是第一阶段的重要组成部分。相关各方必须就合同中列出的条款达成共识。这与我们习惯于以物理方式进行的传统合同谈判非常相似,只是以数字方式进行维护。合约参与者还必须在区块链上拥有一个用于起草智能合约的钱包。合同内容一旦确定,就必须编纂成文。由于每个智能合约的个性化性质,编码有时变得困难。因此,大多数区块链开发人员提供了在创建智能合约时测试其行为的方法,以模仿其实际行为。
冻结阶段
区块链上的交易由网络上称为节点的一组计算机进行验证。这些节点只不过是区块链矿工,他们利用自己的计算能力来确保智能合约的公平治理。作为对他们服务的回报,这些矿工也会获得少量费用。这个框架确保区块链只有合法的合约,不会被虚假条目堵塞。在“冻结”阶段,合约及其参与者在公共分类账上向公众开放。在此期间,任何形式的资金转移都会被阻止,因为节点充当管理机构,验证是否满足合同执行的先决条件。
执行阶段
智能合约的完整性由认证节点验证,合约的干扰引擎(或编译器)执行代码。当以硬币的形式收到来自一方的输入(作为要交换的商品的承诺)时,干扰引擎创建由满足标准触发的交易。然后将新的交易数据添加到区块链中,并再次由管理节点验证,以确保根据合同中商定的条款履行。此验证过程由“共识机制”管理,即工作量证明或权益证明。
合约完成
一旦交易数据被写入区块链的分布式账本,共识机制会验证第一方转移的资产是否已经收到,并为接收方解冻。这标志着智能合约的完成,然后关闭并记录。
智能合约的安全性通常可以从代码编写、合约虚拟机和区块链特性这三个维度展开,以下分别对这三个方面的安全性漏洞进行了分析。
一、合约隐私泄露
即使在联盟链中,由于区块链交易信息公开,合约代码完全开源,合约从创建、部署到执行的整个过程都会被广播到参与联盟链的全部节点,导致合约参与者的真实身份有很大可能会被有意的攻击方识破。一些机密合约的隐私内容,有时不便公开,如果依然采用原先的部署、执行方式,将导致合约参与者的重要信息受到威胁。
二、合约主体漏洞
智能合約的代码编写不同于以往的项目开发,智能合约在部署后一旦出现问题,所付出的代价是巨大的,对于多种区块链来说都难以简单的解决,因此我们在编写合约代码时要提升安全思维,做好安全准备。
1、函数可重入性
智能合约执行过程中当一个合约调用另一个合约时,当前的执行过程会暂停等待另一个合约的返回值。这会导致一个很严重的问题,如果程序可以在执行过程中被中断,则可以在其先前的调用完成执行之前安全地再次调用,这被称为可重入计算机程序。在调用其他外部函数的操作完成前,这个被调用的函数很有可能会被多次执行,这种多次调用可能会造成难以想象的问题。
2、 函数可见性
以Solidity为例,在使用Solidity编写合约代码时,共提供了4种函数可见性修饰符,在开发者没有指明的情况下,默认为public。当开发者没有明确指明函数可见性时,可能导致部分关键函数的可见性为公开的,这使得任何外部用户都可以调用这一函数,可能会造成巨大损失。
3、误操作异常
在以太坊中,允许一个合约通过send指令或者直接调用的方式去调用另一个合约内的函数。然而在调用过程中可能会出现错误,例如gas不足、超出调用栈限制,调用就会终止,合约就会回退到之前的状态。调用者很可能并未获知调用过程中出现的异常,这主要取决于调用的方式。使用这条指令调用合约后,必须检查返回值驗证合约是否正确执行。根据数据统计,现有合约中约28%的合约在调用后不会检查异常返回值,这在一定程度上会造成许多问题。
三、虚拟机安全漏洞
合约虚拟机运行在区块链的各个节点之上,虚拟机为合约代码提供了一个沙箱式的执行环境,如果合约虚拟机存在漏洞或不完善的地方,则很由可能会受到攻击者的攻击,虚拟机系统相比较于传统的计算机运行环境具有更多的攻击安全隐患,以下列出常见的几种:
(1)逃逸漏洞:虚拟机在运行中,一般进程只能在沙盒的限制中执行相应的代码,逃逸漏洞指的是进程越过虚拟机范围,进入到宿主机的操作系统中,这种漏洞会使攻击者退出沙盒环境,执行其他本不能执行的代码。
(2)逻辑漏洞:虚拟机在发现数据或代码不符合规范时,可能会对数据做一些“容错处理”,这就导致可能会出现一些逻辑问题,最典型的是“以太坊短地址攻击”。
(3)堆栈溢出漏洞:虚拟机的调用栈有确定的最大深度,在一些攻击者的恶意调用下,有可能导致栈的深度超过虚拟机允许的最大深度,或不断占用系统内存导致内存溢出。
(4)资源滥用漏洞:指的是攻击者在虚拟机中执行恶意代码,估计消耗系统的网络资源、存储资源、计算资源、内存资源。所以在虚拟机系统中必须要有一些限制机制来防止系统的资源被滥用。
四、区块链特性导致的漏洞
1、交易顺序依赖
在区块链中一个区块包含多条交易,而一笔交易从被广播出去到被确认并包含在一个区块内需要一定的时间。我们假设有一个区块链目前处于状态σ,新区块中包括两条调用相同合约的交易(deg:Ti,Tj),在这种情况下,用户无法确定合约在执行调用时是什么状态。当合约处于σ[Ti]时执行Tj的调用和处于σ[Tj]时执行Ti的调用可能会造成截然不同的结果,这取决于Ti和Tj之间的顺序,而只有挖掘这一区块的节点才能决定这些交易的顺序,从而决定合约被调用的顺序。如果有攻击者在监听到网络中对应合约的交易后,发出他自己的交易来改变当前的合约状态,则有一定几率使这两笔交易包含在同一个区块下面,并且有可能排在另一个交易之前,完成攻击。合约的最终状态实际上取决节点在确认时的交易顺序, 我们将此类合约称为交易依赖合约或TOD合约。
2、 时间戳依赖
另一个很重要的安全问题是,合约有时会用区块时间戳作为执行一系列关键操作的触发条件。我们把这样的合约称为时间戳依赖合约,在许多合约游戏中都会使用随机数来决定谁赢得头奖,这些合约使用了之前的区块哈希作为随机种子来挑选冠军,区块的选择则取决于当前区块的时间戳。通常来说,当节点确认一个区块时,它会为这个区块设置一个时间戳,这个时间一般是节点的本地系统时间。但是,节点可以在900s的范围之内随意改变这个时间戳,与此同时其他节点仍然会接受并确认它。节点处理一个新的区块时,如果新的区块的时间戳大于上一个区块,并且时间戳之差小于900秒,那么这个新区块的时间戳就是合法的,因此有一些攻击者就可以通过改变时间戳来控制合约的输出结果