在过去的六天当中,来自Slock.it团队的个人,以及其他几位以太坊开发者,合作探讨了一个以太坊硬分叉方案,试图解决the DAO的黑客攻击问题。
下面的硬分叉计划仍需测试,同时它还需要社区进行审查。这是一个开源项目,因此它依赖于多来源的宝贵意见。它也可以更改,当然。这个帖子仅提供硬分叉发展的最新进展情况。我们希望你觉得它是有用的。
提议的硬分叉计划
所有起始交易来自0xbb9bc244d798123fde783fcc1c72d3bb8c189413的账户,它们的附加余额(extraBalance)账户[1],以及 the DAO的主账户(0xbb9bc244d798123fde783fcc1c72d3bb8c189413)和其附加余额账户(0x807640A13483f8AC783c557fcDF27Be11ea4AC7A)都会被列入列表L
当中。这个列表L是在区块X当中确定的(区块号待定)。该列表目前的内容可在这里看到[2]:在区块Y开始时(区块号待定),所有L列表账户中的以太币,将转移到一个退款合约账户当中,代码如下:
/* This file is part of the DAO. The DAO is free software: you can redistribute it and/or modify it under the terms of the GNU lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The DAO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU lesser General Public License for more details. You should have received a copy of the GNU lesser General Public License along with the DAO. If not, see <http://www.gnu.org/licenses/>. */ // TODO: all constants need to be double checked import "github.com/slockit/DAO/DAO.sol"; contract Refund { DAO constant public mother = 0xbb9bc244d798123fde783fcc1c72d3bb8c189413; mapping (address => bool) public whiteList; uint constant public totalSupply = 11712722930974665882186911; uint constant public totalWeiSupply = 12072858342395652843028271; uint constant public fixChildDAOsListTime = 1468057560; // 09.07.2016 - 11:46:00 CEST function Refund(){ // whitelist all childDAO except of attacker DAO (commented out) whiteList[0xd4fe7bc31cedb7bfb8a345f31e668033056b2728] = true; whiteList[0x2c19c7f9ae8b751e37aeb2d93a699722395ae18f] = true; whiteList[0x1975bd06d486162d5dc297798dfc41edd5d160a7] = true; whiteList[0x319f70bab6845585f412ec7724b744fec6095c85] = true; whiteList[0x5c8536898fbb74fc7445814902fd08422eac56d0] = true; whiteList[0x779543a0491a837ca36ce8c635d6154e3c4911a6] = true; whiteList[0x5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5] = true; whiteList[0x200450f06520bdd6c527622a273333384d870efb] = true; whiteList[0x6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb] = true; whiteList[0xd1ac8b1ef1b69ff51d1d401a476e7e612414f091] = true; whiteList[0x51e0ddd9998364a2eb38588679f0d2c42653e4a6] = true; whiteList[0xf0b1aa0eb660754448a7937c022e30aa692fe0c5] = true; whiteList[0x9f27daea7aca0aa0446220b98d028715e3bc803d] = true; whiteList[0xd9aef3a1e38a39c16b31d1ace71bca8ef58d315b] = true; whiteList[0x6f6704e5a10332af6672e50b3d9754dc460dfa4d] = true; whiteList[0x492ea3bb0f3315521c31f273e565b868fc090f17] = true; whiteList[0x9ea779f907f0b315b364b0cfc39a0fde5b02a416] = true; whiteList[0xcc34673c6c40e791051898567a1222daf90be287] = true; whiteList[0xe308bd1ac5fda103967359b2712dd89deffb7973] = true; whiteList[0xac1ecab32727358dba8962a0f3b261731aad9723] = true; whiteList[0x440c59b325d2997a134c2c7c60a8c61611212bad] = true; whiteList[0x9c15b54878ba618f494b38f0ae7443db6af648ba] = true; whiteList[0x21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241] = true; whiteList[0x1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b] = true; whiteList[0x6131c42fa982e56929107413a9d526fd99405560] = true; whiteList[0x542a9515200d14b68e934e9830d91645a980dd7a] = true; whiteList[0x782495b7b3355efb2833d56ecb34dc22ad7dfcc4] = true; whiteList[0x3ba4d81db016dc2890c81f3acec2454bff5aada5] = true; whiteList[0xe4ae1efdfc53b73893af49113d8694a057b9c0d1] = true; whiteList[0x0737a6b837f97f46ebade41b9bc3e1c509c85c53] = true; whiteList[0x52c5317c848ba20c7504cb2c8052abd1fde29d03] = true; whiteList[0x5d2b2e6fcbe3b11d26b525e085ff818dae332479] = true; whiteList[0x057b56736d32b86616a10f619859c6cd6f59092a] = true; // whiteList[0x304a554a310c7e546dfe434669c62820b7d83490] = true; whiteList[0x4deb0033bb26bc534b197e61d19e0733e5679784] = true; whiteList[0x35a051a0010aba705c9008d7a7eff6fb88f6ea7b] = true; whiteList[0x9da397b9e80755301a3b32173283a91c0ef6c87e] = true; whiteList[0x0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9] = true; whiteList[0xbcf899e6c7d9d5a215ab1e3444c86806fa854c76] = true; whiteList[0xa2f1ccba9395d7fcb155bba8bc92db9bafaeade7] = true; whiteList[0xd164b088bd9108b60d0ca3751da4bceb207b0782] = true; whiteList[0x1cba23d343a983e9b5cfd19496b9a9701ada385f] = true; whiteList[0x9fcd2deaff372a39cc679d5c5e4de7bafb0b1339] = true; whiteList[0x0e0da70933f4c7849fc0d203f5d1d43b9ae4532d] = true; whiteList[0xbc07118b9ac290e4622f5e77a0853539789effbe] = true; whiteList[0xacd87e28b0c9d1254e868b81cba4cc20d9a32225] = true; whiteList[0x5524c55fb03cf21f549444ccbecb664d0acad706] = true; // whiteList[0xfe24cdd8648121a43a7c86d289be4dd2951ed49f] = true; whiteList[0x253488078a4edf4d6f42f113d1e62836a942cf1a] = true; // whiteList[0xb136707642a4ea12fb4bae820f03d2562ebff487] = true; whiteList[0xf14c14075d6c4ed84b86798af0956deef67365b5] = true; // whiteList[0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c] = true; whiteList[0x6d87578288b6cb5549d5076a207456a1f6a63dc0] = true; whiteList[0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6] = true; // whiteList[0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a] = true; // whiteList[0x84ef4b2357079cd7a7c69fd7a37cd0609a679106] = true; // whiteList[0xf4c64518ea10f995918a454158c6b61407ea345c] = true; } function withdrawFromChildDAO(DAO _child) { // to be replaced by a time which allows the direct withdraw to be finished before the childDAO withdraw starts if (now < fixChildDAOsListTime + 4 weeks) throw; if (!whiteList[_child] || _child.lastTimeMinQuorumMet() > fixChildDAOsListTime || _child.privateCreation() != mother) throw; withdraw(_child); } function withdraw(){ withdraw(mother); } function withdraw(DAO _dao) internal { uint balance = _dao.balanceOf(msg.sender); if (!_dao.transferFrom(msg.sender, this, balance) || !msg.sender.send(balance * totalWeiSupply / totalSupply)) throw; } }
备注:
在实际的硬分叉发生之前,子DAO当中的以太币,其实际分配是很难确定的,它将在特定的时间点完成(区块 X)。区块链分析结果将成为这次硬分叉的一部分,并在之后的某个时间点生效(区块 Y)。这就意味着,在区块高度达到X之后,代币持有者不应执行删除主DAO或子DAO以太币的分割操作或提议,否则他们将无法利用这个退款合约。如果他们 这样去做了,他们将失去自己的退款。传输和交易DAO代币,并不受此硬分叉计划的影响。
链接:
[1] web3.eth.contract(abi).at(newDAO).extraBalance()
[2] https://gist.github.com/CJentzsch/856b7d4b3010bf9a10ff7cbbea1876a9 (非最终版,需要进行检查)
[3]根据合约是否已准备好,一个简单的零代码哈希(zero codehash)合约(意味着我们以后还需要另一次硬分叉)或一个最终的合约将被使用。最终的合约将有两个功能(‘取款’和‘从子DAO中取款’)。
当前的代码(粗略版,未经测试):
https://gist.github.com/CJentzsch/038b86ae1658c680cee3bfb1499c1297
或https://gist.github.com/CJentzsch/bc01bfe17d850331eadf0c33041071a8
论证
为了减少执行过程中的错误风险,我们设计了一个简单的硬分叉计划。这使得绝大多数的DAO代币持有者能够挽回损失,但它确实存在着不足之处:一些群体无法得到100%的退款。
1.在过去两周内,创建代币的代币持有者。
因为DAO代币是可交易和可替代的,去区分特定时间创建的代币是非常困难的。这就导致了一个非固定的退款模型, 以稍高于1以太币:100 DAO代币的比率,适用于所有的DAO代币持有人。
2.在攻击开始之后,进行分割操作的代币持有者。
在一个子DAO当中创建的代币数量,取决于主DAO在进行首次“分割DAO”命令时的余额情况。出于这个原因,在攻击开始后进行分割操作的代币持有者,其拥有的子DAO代币数量,要少于他们此前拥有的主DAO代币数量。
这一群体无法获得额外的退款,其主要原因是,他们可能会把以太币发送到主DAO当中,然后再进行分割退出操作。这就创造了一种可能,能以1以太币:100子DAO的代币比例,创建子DAO代币。如果这一群体享有额外的退款,攻击者可能会利用它来获得超过预期的退款。
3. 子DAO用于递归分裂攻击的代币持有者。
攻击者的DAO(包括黑客和白帽)并未列入退款合约白名单,否则攻击者可要求一个更大的退款。不幸的是,这意味着拥有“darkDAO”代币的持有人,将无法得到退款。
然而,解决方案的复杂性可能会导致新的错误和损失。我们从过去的失败中吸取教训,并谨记智能合约保持简单的重要性,因此,我们认为这一硬分叉计划是可实现的,并能在短期内完成测试,它是在给定时间内最优的硬分叉策略。
重要日期
首个子DAO的创建期结束时间:中欧夏季时间2016年7月1日16:25:02
首批(2000)以太币离开the dao系统的时间:中欧夏季时间2016年7月16日17:04:37(分割提议#8)
DarkDAO的创建结束时间:中欧夏季时间2016年7月14日 05:34:48
攻击者DAO可进行首次分割操作的时间:中欧夏季时间2016年7月21日 05:34:48
通过提议,攻击者DAO可进行首次取款的时间:中欧夏季时间2016年7月28日 05:34:48
通过分割提议,攻击者DAO可进行首次取款的时间:中欧夏季时间2106年8月31日 05:34:48
这意味着,不为这一干净硬分叉添加任何其他规则,其截止时间是7月16日。这是分割提议 #8 的所有者可合法地从他们的子DAO中取款以太币的时间。如果所有的分割DAO都被忽略了,我们就能简单地应对攻击者DAO的以太币,然后7月21日将是这 次硬分叉的最后的期限。在此以后,这些以太币就可转移到由攻击者产生的多个分割DAO,这将大大增加硬分叉计划的复杂性。
结论
在这篇文章当中,我们介绍了这次硬分叉计划的建议。它已被转发到各版本客户端的开发者手中:包括geth、 parity、 cpp-ethereum以及pyeth。我们还提出了这个简单硬分叉计划背后的论证,以及有关这次预期硬分叉的一些重要时间点。
我们邀请大家来测试并审查这一硬分叉计划,特别是硬编码数字、列表 L中的账户,当然还有智能合约本身。
声明:此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。本网站所提供的信息,只供参考之用。