1. 程式人生 > >以太坊可更新智慧合約研究與開發綜述

以太坊可更新智慧合約研究與開發綜述

這篇文章是對以太坊可更新智慧合約領域裡的研究和開發的綜述。它意圖成為一篇便利的資源帖,集中迄今為止的研究,並推進技術討論。此外,我已經建立了一個關於不同策略的優缺點比較的簡要表格,下面會放出來。如果你正在研究或者開發領域工作或者觀摩,請對本文作出評論,給出你對這份表格和我對不同策略的描述的支援、反對或是其它意見。

除了幾個月前我自己為 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 運營成本。

結論

沒有一種策略是完美的,選擇正確的策略依賴於要實現的智慧合約系統。所有策略都是複雜的,而智慧合約設計者們應該非常熟悉他們選擇的可更新策略,以避免安全上的脆弱性。

我的觀點

  • 要建立一個可更新的智慧合約,代理機制在這些策略中看起來是最好的,因為他允許程式設計師將可更新機制從它們的合約設計中分離,這會到這事情變得更容易思考和使用,也會讓錯誤更少(這可是一個最初我們需要可更新合約的根本原因)。
  • 使用一個綜合的部分可更新策略,讓最簡單的核心邏輯變成不可更改的同樣是一個好主意,可以強有力地維護使用者對合約的信任。
  • 首先設計你的不可更新的智慧合約,然後形成一個可更新的策略;這似乎是一個有實踐意義的方式,也是理想的方式。