这篇文章是对以太坊可更新智能合约领域里的研究和开发的综述。它意图成为一篇便利的资源帖,集中迄今为止的研究,并推进技术讨论。此外,我已经创建了一个关于不同策略的优缺点比较的简要表格,下面会放出来。如果你正在研究或者开发领域工作或者观摩,请对本文作出评论,给出你对这份表格和我对不同策略的描述的支持、反对或是其它意见。
除了几个月前我自己为 AvanceHub 项目贡献的部分以外,这篇文章没有加入新的技术开发和研究。本文中对不同策略进行了排序,但这不应被解读成它们的接受度以及我或者是开发者社区的偏爱。作为 indorse.io 项目的一部分,本文将从对我们的可更新策略的介绍开始,我们认为这是有必要的。
在文章底部可以看到一份比较综合的列表,里面包含了我认为迄今为止重要的研究和发展。
策略 | 优点 | 缺点 |
---|---|---|
代理合约(Proxy Contract) | 1. 使用这种策略,不需要重新设计就可以更新合约 | 1. 代理的合约代码将不会反映出它存储的状态;2. 无法改变目标合约的字段,但可以添加新字段;3. 合约的交互界面必须保持原样; |
将逻辑与数据分离 | 1. 数据可以从数据合约中正常读取;2. 用在数据合约中的数据结构可以更新和添加 | 1. 合约必须被分成数据合约和逻辑合约;2. 合约交互界面必须保持原样;3. 变更复杂的数据类型(例如,结构体)的方式比较复杂; |
将逻辑与数据分离,并使用"key-value"对 | 1. Key-value更加普遍也更加点;2. 用在数据合约中的数据结构可以更新和添加 | 1. 合约必须被分成数据合约和逻辑合约;2.合约交互界面必须保持原样;3. 因为数据储存在 Key-value 对中,读取数据的过程非常抽象; |
部分可更新智能合约系统 | 1. 让合约系统的简单部分变成不可更改的,以维系信任 | 1. (显然)不可更新的合约代码永远也不能更新 |
100% 可更新机制
使用更多的智能合约基础设施,创建一套完全可以更新逻辑的智能合约是有可能的。这种策略有两个分支:代理、逻辑与数据分离为不同合约。而分离合约中的数据和逻辑有两种方式。
所有这些方法解决的基本问题都是如何更新智能合约的逻辑、同时维持通往合约状态的通道。
我没有看过这些策略中的任何一个用于生产或是通过合理的安全审计。在下文中我哦哦给出了这些策略如何生效的简短描述,但我推荐大家到文末阅读最新的资源,以充分地熟悉它们的工作原理(尤其是,如果你正要开始跑进可更新合约的兔子洞的话)。
代理合约
一个代理合约使用 delegatecall 操作码,将函数调用请求发送给一个可以被更新的哦目标合约。因为 delegatecall 会保持函数调用的状态,目标函数的逻辑是可以被更新的,并且状态会保留在代理合约中以供可更新目标合约的逻辑使用。也因为 delegatecall, msg.sender 将保持代理合约调用者的身份。
因为最近的拜占庭硬分叉让一个函数调用返回值的大小变得可知,这种方法现在变成普遍的了(比起 Nick Johnson 初次提议的时候)。你可以在 Daonomic 的资源中看到普遍代理合约的一个例子,当然,该文同时也是一篇值得阅读的好文章,讲到了这种机制的更多细节。
逻辑与数据分离
这种方法包括将智能合约分成一个带有合适 getter 和 setter 的数据合约,包含了数据(变量、结构体、映射,等等);以及一个逻辑合约,包含了如何更新数据的所有业务逻辑。逻辑合约通过 setter 更新数据,数据合约只允许逻辑合约调用 setter。这让在保持数据储存在同一个地方的同时让逻辑可以被替换,允许一个完全可更新的系统。
这样的话合约就可以更新,通过指定用户使用新的逻辑合约(通过一个 resolver 比如 ENS实现)、更新数据合约的许可以使新的逻辑合约可以运行 setter。
观看 @Thomas Wiesner 的视频以获得对这种机制更好的理解。
逻辑与数据分离并使用 Key-value 形式的数据
这种策略与上一个方法有相似的工作原理,但是不使用在一般情况下你的合约使用的最终需要的数据结构(结构体、映射,等等),所有的数据都被抽象并且以基本的 Key-value 的形式存储。使用一个围绕 sha256 哈希算法的标准命名系统来发现数据的值。
观看 David Rugendyke 的文章以获得对这种机制的更深入的理解。
部分可更新的策略
创建一个完全可更新的合约听起来很棒,但它要在信任问题上要求一个大妥协:合约的不可更改性。使用部分可更新的合约系统在很多情况下也许是有意义的。
在这种策略中,智能合约的核心功能可以变成不可更新的。其他的也许更不基础或者更加复杂(因此更有可能要求更新)的组件则使用一个可更新的策略来实现。
我已经看到了这种策略的一些好例子,当然如果你知道别的也请告诉我:
- 以太坊域名系统(ENS):核心的 ENS 合约是一个非常简单的合约,也是不可变更的。而域名登记者(例如,对“.eth”域名来说)可以由管理员更新。“.eth”域名的登记者是所有权(Deed)合约的一个合约参数;每一个所有权都会创立一个所有权合约,所以如果使用一个新的域名管理器,它也可以被重新连接到所有之前的所有权以及它们的状态,没有什么麻烦。
- 0x 项目:603 行核心 DEX(去中心化交易)智能合约完全可以更新,同时代理合约(每一个用户都有)保持原样。0x “代理”合约(与上述的代理策略并不等同)保留了用户的资金和设置。因为这一点,它要求更多信任,它也是 0x 合约系统中一个不可更新的部分。
其它挑战
- 所有情况都要求治理上的权衡:妥协掉智能合约的不可更改性。一个有力的治理策略也是一个可更新策略的一部分。
- 创建一个选择性可更新智能合约系统是可能的,对用户来说也是有意义的,但会增加复杂性。
- Solidity 编译器的变化也许会打破新旧合约之间的协作性。
- 在形成一个可更新的策略时要考虑 gas 运营成本。
结论
没有一种策略是完美的,选择正确的策略依赖于要实现的智能合约系统。所有策略都是复杂的,而智能合约设计者们应该非常熟悉他们选择的可更新策略,以避免安全上的脆弱性。
我的观点
- 要创建一个可更新的智能合约,代理机制在这些策略中看起来是最好的,因为他允许程序员将可更新机制从它们的合约设计中分离,这会到这事情变得更容易思考和使用,也会让错误更少(这可是一个最初我们需要可更新合约的根本原因)。
- 使用一个综合的部分可更新策略,让最简单的核心逻辑变成不可更改的同样是一个好主意,可以强有力地维护用户对合约的信任。
- 首先设计你的不可更新的智能合约,然后形成一个可更新的策略;这似乎是一个有实践意义的方式,也是理想的方式。
我的推特:@theblockstalk
研究文献
一般文献
- 2018–02–01 Zeppelin Solutions: Zeppelin and the Evolution of Smart Contract Development (Epicenter Youtube Video)
- 2016–2017 : Upgradable Smart Contracts Stackexchange thread
- ConsenSys: Ethereum Smart Contract Best Practices (编者注:中译本见文末《智能合约最佳实践》)
- Evoluchain: Evoluchain
代理合约
- 2018–02–22 Jorge Izquierdo: ERC DelegateProxy #897
- 2018–02–15 Daonomic: Upgradeable Ethereum Smart Contracts, Github Project
- 2018–01–11 Team B9lab: Upgradeable Github Project
- 2018–01–10 Manuel Araoz : Solidity-proxy Github Project
- 2017–06–02 @Ownage : Ether-routher Github Project
- 2017–05–24 Nick Johnson: Mad blockchain science: A 100% upgradeable contract, Gist File
- 2017–03–15 Jorge Izquierdo: Advanced Solidity code deployment techniques
- 2017–03–07 Manuel Araoz: Proxy Libraries in Solidity
- 2017–02–13 Jorge Izquierdo: Library Driven Development in Solidity
- 2017–01–21 Tjaden Hess: Upgradeable smart contracts
- 2016–06–16 @Martin Swende: Implicit method proxy
逻辑与数据分离
- 2017–12–09 @Thomas Wiesner: Upgrade Smart Contracts on Chain
- 2017–11–13 Jack Tanner: Upgradeable, Github Project
- 2017–08–21 Lukas K: Upgradable smart contracts. What we’ve learned building Insurance on a Blockchain
- 2016–08–16 @nikolai: Dapp-a-day 6: Upgradeable Tokens
- @monax: Solidity 1: The Five Types Model
- @monax: Solidity 7: Updating Solidity Contracts
- @Z.com Cloud Blockchain: Solution — Version Upgrade Issue
逻辑与数据分离并使用 Key-value 形式的数据
- 2018–01–20 Hassan Abdel-Rahman: Upgradable Contracts in Solidity
- 2017–11–22 David Rugendyke: Upgradable Solidity Contract Design, Github Project
- 2017–06–29 Chandan Gupta: Interfaces make your Solidity contracts upgradeable, Github Project
- 2016–06–08 Elena Dimitrova: Writing upgradable contracts in Solidity