教程 | 以太坊开发演练, Part-3:安全性、限制性以及一些顾虑

ETHButterfly2018-04-04 20:36:48  阅读 -评论 1  阅读原文

时间轴拨转到2023年,管理员 Dave 马上就要失业了,因为 SaaS 去中心化应用程序正在完成着他的工作,在人力被程序所替代的洪流中,无人幸免。然而作为一名诚实的工作者,他依然会站好最后一班岗。Dave 收到一封邮件,要求他向一份智能合约函数发送一些以太币和一个地址。

接着,Dave 打开了他的以太坊钱包,换言之,一个word文档。他进入了myWallets.docx 中并找到了四条记录:我的密钥,公司的密钥,我的密码,公司的密码。

他打开了 Mist 钱包,找到了那个他需要发送以太坊的智能合约,从公司账户里发送了1000个以太币到那个智能合约的函数中,接着从邮件里粘贴了那个他必须要给函数发送的以太坊地址。但不幸的是,Dave 没有把整个地址复制全。在意识到这个错误之后,他手动地补全了整个地址,但是输错了最后一个字母。现在,这个地址是一个完全不同的新地址了。

Dave 按下了发送键,粘贴下了公司的密码,确认了这笔交易以及函数的执行。在函数执行过程中,该函数将一部分以太币发送到了某些预先定义好的账户地址中,并通过合约的自毁调用把余下的以太币都发送到了 Dave 输入的地址中,因为编写这个智能合约的开发者认为在函数执行之后把这个已经没用的智能合约从区块链中清理干净(事实上这做不到)是一个相当不错的做法。

无巧不成书,那一个被误输入的地址正好是这篇教程中第一部分里"角力合约(Wrestling contract)"的地址,它其实也是由另一个人按照这篇教程中第二部分的第二种方法不小心在主网上布署的。

在同一时刻,有人发现了这个主网上的"角力合约",他通过注册,成为了二号选手,然后向智能合约发送了一些以太币来调用 Wrestle() 函数,但是因为一号选手从来没有开始自己的回合,就导致了二号选手的以太币被永久地锁定在了"角力智能合约"中。所以在这个几乎不可能(吗?)的场景中,以太币的丢失是由于人为失误和不完整的智能合约而造成的。

『 关于"角力合约" 』

虽然我们实现了游戏的基本功能,但是我们我没有考虑到智能合约的生命周期。它何时被生成,何时被使用,何时不复存在。

如果一个选手在数个回合之后就不再继续玩游戏了,这之后怎么办?我们应该赋予玩家当某一个选手不再玩游戏后,在特定的一段时间后能取回自己资产的权限。

我们也要考虑到到当一个智能合约不再被使用之后的情形(在上文的案例中就是比赛结束的情形)。我曾经提及,为了让智能合约能收到以太币,我们应该在函数修饰符中加上"payable"关键字。但是一个合约仍然能通过如下两种途径来获得以太币(并且你无法禁止这些途径),当一个合约自毁并调用另一个智能合约的地址时(一种在Solidity中特殊的提前定义好的函数,能使智能合约失效,并把其拥有的以太币发送到预先设计好的地址中去),或是当智能合约接收挖矿所得的以太币时。所以在设计智能合约时,你应当确保其中具备提取以太币的方法,以备不时之需。

在这个角力的案例中,既然获胜者已经能够从合约中拿走所有的以太币,我们应当给他设计另一种如下这样的提款函数:

function withdraw() public { require(gameFinished && theWinner == msg.sender); msg.sender.transfer(this.balance); }

这个函数能让他在合约中任其需求且不限次数地提走以太币。通常在转账时,一定要留意由于某些原因转账可能会失败,并且你也应当在设计时考虑让智能合约的用户来调用提款的功能,而不是由智能合约自动发起转账。

此外,你可能会认为让智能合约执行自毁是一个好的做法,这样貌似能够清理区块链,但是一个自毁之后的智能合约依然是保留在区块链上的,它仍可以通过上述的两种方法收到以太币。

你也应当考虑设计一个B计划,以防出于某些未知的原因,你的智能合约无法按照设计那般正常地执行。由于在部署之后,就无法再更改智能合约,你可能想要在智能合约中增加一些你能够触发的锁定状态,这些锁定状态或是能暂停智能合约上交易的执行,或是能向上文的案例那样允许用户通过令此合约向另外的合约发送以太币的方式来达到提款的目的。这样的触发器通过把权力交给第三方的方式使得智能合约去中心化的特性受损,所以是否采用这样的做法还是要看你的智能合约是用在具体哪一个场景之中。

『 安全性 』

要保证 Solidity 开发的安全性首先要遵循通用开发模式,然后要跟进 Solidity 开发平台的发展,通过测试来确保你的智能合约没有漏洞(或是至少向这个目标努力),认识到开发平台自身的局限性,保持你的代码尽量简洁,并且时刻提醒自己以太坊本身(区块链背后的软件,如 Solidity 编译器等)也存在诸多漏洞,并且以太坊每天都处于不断发展之中。

『 测试 』

在任何正式的开发中,测试都是十分重要的一环。如果你以前都是等着漏洞出现,然后再去修复他们,那就有你好受的了。

在第二部分中提及的 Truffle 就给我们提供了一种测试智能合约的简单方法。打开最后一部分中的项目,打开一些命令行接口,然后运行ganache-cli。

ganache-cli -p 7545

创建一个命名为"test"的文件夹,然后在其中创建一个"TestExample.js"文件。粘贴如下内容:

var Wrestling = artifacts.require("Wrestling"); contract('Wrestling', function(accounts) { // "it" is the block to run a single test it("should not be able to withdraw ether", function() { Wrestling.deployed().then(function (inst) { // We retrieve the instance of the deployed Wrestling contract wrestlingInstance = inst; var account0 = accounts[0]; // how much ether the account has before running the following transaction var beforeWithdraw = web3.eth.getBalance(account0); // We try to use the function withdraw from the Wrestling contract // It should revert because the wrestling isn't finished wrestlingInstance.withdraw({from: account0}).then(function (val) { assert(false, "should revert"); }).catch(function (err) { // We expect a "revert" exception from the VM, because the user // should not be able to withdraw ether console.log('Error: ' + err); // how much ether the account has after running the transaction var afterWithdraw = web3.eth.getBalance(account0); var diff = beforeWithdraw - afterWithdraw; // The account paid for gas to execute the transaction console.log('Difference: ' + web3.fromWei(diff, "ether")); }) }) }) });

上述所做的就是检索"角力合约",将其部署到我们的测试网络中,并且尝试调用提款函数。因为在游戏结束之前没有人能调用提款函数,这就会在合约的提款函数处由于使用"require"指令而返回一个错误。

在开发控制台中运行test:

truffle test --network development

你应该能看到类似如下的输出:

因为执行合约函数是一个异步的进程,你应该使用 async/await 来获得一个更纯净的测试代码。但为了保持简单上手,我们在范例中帮你做了这个工作。

留给你一项模拟角力比赛的练习,你需要保证只有获胜者才能在游戏最后提走合约中的以太币。(和我们在上一节中使用 truflle控制台 所做的十分相像)

你能在这个教程中研究另一个案例。同时别犹豫,去看Truffle的文档。

或者,这里有一些由社区所编写的保证安全性的工具以供你自检代码时使用。列表在此。

『 商业逻辑 』

在合约内部测试函数是必不可少的,但是你也应当跳出来,看看智能合约中函数之间的互动是否能形成一个符合你设计初衷的整体,完好地运行(且没有执行其他事务)。

保证你的智能合约有良好的注释是编写清晰、条理代码的第一步(请注意到我们在第一部分提到的 Wrestling.sol 并没有这样做)。第二步是要保证你的智能合约尽可能地简洁,并且只将应用中需要去中心化的部分书写到智能合约当中。如果你的智能合约是作为一个去中心化应用(简而言之,去中心化应用程序是含有有去中心化的结构的web应用(也就是应用中的一个组成部分是智能合约,或者与智能合约发生交互))的一部分存在的,那就要设计好哪些功能是需要在区块链上运行的,而哪些功能是通过UI手段或者web应用的后端来实现的。

注释:去中心化应用程序的定义比上文要更为广泛,它包括所有应用点对点交互的程序。Mist、BitTorrent、Tor 等等都是能被称之为去中心化的应用。参见Vitalik Buterin的这篇文章。

『 了解开发平台 』

为了明确你所做的工作,你应该阅读这些文档,这一工作不可避免,并且你需要额外搜索这些文档之外Solidity开发的方方面面。

举例而言,你应该知道定点数变量(也叫浮点或双精度浮点)是 Solidity 暂时未能完全支持的,并且应该知道在例子二中,当使用 uint 类型来表示 3/7 时会转换到最接近的整数的区别。是故你不应该在一个仍然处于高频开发的平台上把一些东西看作理所当然的。

人都能知道你合约中变量的内容,你也仅仅能够尝试混淆其中信息的内容,而不能彻底把信息隐藏起来。在生成一个随机数或是随机字符串时也是同样的道理,每一个人都能看到你是如何生成这些信息的,这就存在某些不怀好意者精心伪造变量的可能性。事实上正有人在努力探究生成一个随机数的最好方法,如果那正和你意,那么欢迎加入。正如我之前提及的,所有东西都在进行着高频开发,对于很多东西其实并没有工业化的标准。

依赖时间的合约也是一个研究的热门,如果你的合约需要在一个特定的时间运行,你就只能依靠一个外部程序去实现(记住,有时这会导致合约停止或暂停),因为智能合约本身是无法计时的。如果你的智能合约在某些方便面需要时间来做判断,谨记一些不怀好意的矿工可能会通过破坏转账执行的时间来进行攻击。

牢牢记住你的合约是公开的,每个人都能阅读合约内容并与之交互,并且如果你的合约调用了外部别的合约或和他们交互的话,你必须警惕其他恶意的合约可能会破坏你自身合约的执行。

所有的这一切可能有些过于谨慎了,但是如果有一大笔处于不安全状态的资金,人们可能就会想方设法去操作了。如果你的智能合约仅仅是向老年人卖纸尿布的话,你可能不需要考虑那么多。

『 平台的局限性 』

明晰以太坊开发平台并不能用于大量的计算,并且你的转账操作受限于 gas 上限。你必须把逻辑设计的尽可能简单,并且小心无限循环,存储限制,值溢出和其他像这样的微小细节。因为当智能合约部署到区块链之上后就无法再更改了,你应该在部署之前就考虑到这些方方面面。

编译器和以太坊区块链背后的软件正在处于高频的开发之中,并且经历着持续不断的迭代,所以你应该牢记这些特性,并且保持更新。

『 第三方 』

有很多好的开发者希望便利用户和其他开发者,使其能够不需要在本地下载以太坊主链就能登入以太坊网络。比如说 MEW 能让你转账以太币并且部署合约,又如 INFURA 这样优秀的工具能让你搭配 Truffle,通过 API 接入以太坊主链。毋庸置疑这些工具良好的出发点,以及它们背后开发者卓越的技能,但是是否要将追求便利凌驾于安全性就是你自己的选择了。由于大量的转账操作,上述类型的工具通常都比你自己电脑上的节点更容易成为黑客攻击的目标。总的来说,你所采取的技术手段主要取决你操作和转账的金额大小。

『 一些方向,以及从何处开始 』

在结束这篇教程之前,向你提供一些可以开始研究的素材:

  • 由@KonstantHacker提供的这个视频是个很好的入门介绍
  • Solidity常见模式文档
  • Solidity安全性考量文档
  • 其他开发技巧详解

必须牢记,一旦涉及到安全问题,那么没有一份文档是完全能解决的,所以你必须根据自己的具体需求,调查实践,注意考虑到方方面面并用良好的编程技巧来实现。

最重要的是,加入到智能合约的编写中来,有许多开源的项目都需要开发者来检验他们的代码,寻找漏洞,只要用心,你可是能从中获取很多奖励的。

如果你是那个发现漏洞的有心人,或者找到了实现某种策略的更好方法,别吝啬分享你的知识。以太坊和区块链都拥抱着开放的原则,整个社区都会因为这一点一滴的发现而获益。

这一部分的代码能在 Github 上找到。

devzl/ethereum-walkthrough-3

< https://github.com/devzl/ethereum-walkthrough-3 >

『 结论 』

总而言之,你必须有一个作为智能合约开发者的思维模式,并且在发布合约之前完成一系列的调研和测试。正如Moody教授所言:

如果你喜欢这一部分,你可以联系我 @de_zl。

在下一节,我们将介绍代币

原文链接: https://hackernoon.com/ethereum-development-walkthrough-part-3-security-limitations-and-considerations-d482f05278b4
作者: de_zl
翻译&校对: 安仔Clint & Elisa

译者:安仔Clint

技术投机客,关注区块链落地应用

本文由作者授权 EthFans 翻译及再出版。


声明:链世界登载此文仅出于分享区块链知识,并不意味着赞同其观点或证实其描述。文章内容仅供参考,不构成投资建议。投资者据此操作,风险自担。此文如侵犯到您的合法权益,请联系我们kefu@lianshijie.com

参与讨论 (1 人参与讨论)

相关推荐

比特币有什么缺点?

1.交易平台的脆弱性。比特币网络很健壮,但比特币交易平台很脆弱。交易平台通常是一个网站,而网站会遭到黑客攻击,或者遭到主管部门的关闭。2.交易确认时间长。比特币钱包初次安装时,会消耗大量时间下载历史交易数据块。而比特币交易时,为了确认数据准确性,会消耗一些时间,与p2p网络进行交互,得到全网确认后,交易才算完成。3.价格波动极大。由于大量炒家介入,导致比特币兑换现金的价格如过山车一般起伏。使得比

业务中使用区块链的四种方式

业务中使用区块链的四种方式

暴走时评:区块链是一种支持像比特币这样的数字货币的公共分类帐本,并且正改变着我们的业务方式。一旦那些对匿名交易,甚至是秘密交易感兴趣的人接纳了这样一种鲜为人知的工具,加密货币就会日趋成为主流。 区块链是一种支持像比特币这样的数字货币的公共分类帐本,并且正改变着我们的业务方式。一旦那些对匿名交易,甚至是秘密交易感兴趣的人接纳了这样一种鲜为人知的工具,加密货币就会日趋成为主流。越来越多的个人和企

区块链:法定数字货币技术路线的必然选择

区块链:法定数字货币技术路线的必然选择

在人类发展史上,货币的进化从未停止。从物物交换,到金属铸币,再到纸质货币,以及当前正在发展的数字货币正在向着越来越便捷的方向进化。 比特币的出世起初并未带来轰动,但是最近几年其价格惊人的爬高创造出了一个个造富神话,引起各国政府及监管机构的关注。虽然金融专家普遍认为它只是一种资产,而非货币,但是,其背后的区块链(Blockchain)技术引起了包括各大金融机构、政府、企业及学术界的浓厚兴趣,未

用区块链记录证书,证明真伪,墨尔本大学迈出了第一步

用区块链记录证书,证明真伪,墨尔本大学迈出了第一步

墨尔本大学宣布发起区块链认证和审核计划,允许通过一种隐私、安全且持久的方式验证学生的证书。 墨尔本大学正在试验一个区块链记录维护项目,允许接收者(即学生)存储他们的证书,出于核验目的,第三方也能访问这个系统。Learning Machine是这个发布系统的开发者,他们采用的是麻省理工媒体实验室(MIT Media Lab)在2016年提交的Blockcerts开源代码。 墨尔本大学副校长格雷

日本IT巨头富士通联合日本“三大行”开发区块链p2p资金转移系统

日本IT巨头富士通(Fujitsu)与三家大型银行已经宣布计划试点一项基于区块链创建的点对点资金转移系统。 通过与日本三大行——瑞穗金融集团,三井住友金融集团和三菱UFJ金融集团——的合作,富士通将现场试验一种基于云的区块链平台,用于在个体之间发送资金,并开发一款智能手机APP来提高这个系统的可用性。 从理论上讲,这个平台将把三大行的客户法定货币账户与这个区块链系统相连接。客户然后将能够使用这

动画科普:什么是比特币?

动画科普:什么是比特币?

比特币(Bitcoin,简写BTC)概念由中本聪(化名)提出,是一种点对点、去中心化的数字资产;2009年,中本聪打包了第一个区块,并获得50枚比特币的挖矿奖励,挖矿奖励每4年减半一次,按此计算,比特币预计2140年发行完毕,总量为2100万枚。 随着比特币的发展,比特币逐渐受到认可:德国为全球首个接受比特币支付的国家;微软、戴尔等知名企业也纷纷接受比特币支付。 举个栗子,你能直接用比特币买到

3分钟理解什么是公有链、私有链、联盟链、许可链

不同的区块链有着不同的内涵和功能,在区块链领域经常出现的公有链、私有链、联盟链、许可链,这些又都代表什么意思呢? 公有链 公有链是指全世界任何人都可以随时进入系统中读取数据、发送可确认交易、竞争记账的区块链。公有链通常被认为是完全去中心化的,因为没有任何人或机构可以控制或篡改其中数据的读写。公有链一般会通过代币机制鼓励参与者竞争记账,来确保数据的安全性。比特币、以太坊都是典型的公有链。 私

区块链是比特币的底层技术,但似乎两者已走上不同的道路

区块链是比特币的底层技术,但似乎两者已走上不同的道路

比特币的出现带来了一项新的技术——区块链,不过区块链和比特币似乎已走上了两条不一样道路,作为技术的区块链被越来越多的人所看好,而性质偏向于投资的比特币似乎被更多人看衰。 成也萧何败也萧何 比特币火爆的原因是其拥有去中心化、全世界流通、专属所有权、低交易费用、无隐藏成本、跨平台挖掘的特性,这些特性促使比特币成为了很多人关注的焦点。之后众多庄家的入局让比特币一瞬间成为了热门投资产业,但这几大特

麦妖榜
更新日期 2019-09-03
排名用户贡献值
1牛市来了30910
2BitettFan24187
3等待的宿命23810
4区块大康20369
5六叶树20310
6linjm122719429
7天下无双16192
8lizhen00215280
9让时间淡忘14586
10yelanyi050511349
返回顶部 ↑