【智能合约】编写复杂业务场景下的智能合约——可升级的智能合约设计模式(附Demo)
智能合約的現(xiàn)狀
以太坊在區(qū)塊鏈上實現(xiàn)了智能合約的概念,用于:同質(zhì)化通證發(fā)行(ERC-20)、眾籌、投票、存證取證等等,共同點是:合約邏輯簡單,只是業(yè)務(wù)流程中的關(guān)鍵節(jié)點,而非整個業(yè)務(wù)流程。而智能合約想解決的信任傳遞,是環(huán)環(huán)相扣的,如果在傳統(tǒng)系統(tǒng)環(huán)節(jié)被惡意侵入和篡改數(shù)據(jù),那么傳入智能合約的數(shù)據(jù)就是不受到信任的。因此,整體業(yè)務(wù)流程上鏈?zhǔn)侵悄芎霞s發(fā)展的趨勢。
智能合約的局限
智能合約在早期被設(shè)計的時候,并不打算支撐復(fù)雜的業(yè)務(wù)體系,這和它設(shè)計的初衷相違背:漏洞往往出現(xiàn)在程序員編寫的代碼和他想實現(xiàn)的邏輯之間存在著差距,越是簡單的代碼越是安全。簡單和受限訪問成了智能合約安全可靠的保障。
因此,智能合約引入了隔離網(wǎng)絡(luò)和文件系統(tǒng)的沙箱環(huán)境、基于棧的編譯器(有限高度的棧深以及僅可訪問棧頂16個元素的限制)、靜態(tài)語言、gasLimit(限定了合約的大小,每個合約能處理的邏輯有限;限定每個函數(shù)邏輯的復(fù)雜度,每一步操作都會消耗gas,以至于連使用循環(huán)都成了奢侈)、嚴(yán)格的內(nèi)存訪問限制(每個合約僅可以訪問自己的存儲單元),這就導(dǎo)致了智能合約不同于傳統(tǒng)編程語言,自身就帶著諸多限制。
目前,智能合約仍然處于發(fā)展的早期階段,配套的工具、成熟的框架、第三方包寥寥可數(shù)。因此編寫復(fù)雜業(yè)務(wù)場景的智能合約,只能從底層的邏輯開始編寫:編寫數(shù)據(jù)庫模型CURD、跨合約數(shù)據(jù)交互、增強基本數(shù)據(jù)類型功能(string類型的slice、array的delete),導(dǎo)致開發(fā)合約速度的緩慢。
另外,由于區(qū)塊鏈的另外一個特性:防篡改。這導(dǎo)致了智能合約部署上鏈后,任何人包括合約所有者都不能再進行修改。意味著智能合約無法像傳統(tǒng)應(yīng)用那樣實現(xiàn)敏捷開發(fā),合約的每一個方法都需要進過大量測試,保證整個合約的正確性嚴(yán)謹(jǐn)性。即使保證合約不出問題,但業(yè)務(wù)的需求并非一成不變,業(yè)務(wù)變動,智能合約無可避免的跟著變動,那么意味著合約的重新部署,但是舊合約的數(shù)據(jù)是無法轉(zhuǎn)移到新合約上的;已部署好的合約如果存在漏洞被惡意攻擊,需要有方法能夠盡快停止合約運行,保證用戶數(shù)據(jù)不被篡改,留出時間讓智能合約的編寫者快速修復(fù)漏洞。因此,合約的升級和管理需要設(shè)計。
智能合約目前的發(fā)展方向
編寫智能合約的程序員目前分為兩派,一派主張合約盡可能的精簡,只有簡單才不容易出現(xiàn)錯誤,只有關(guān)鍵部分上鏈部分;另一派主張信任傳遞的閉環(huán),也就是說整個業(yè)務(wù)邏輯盡可能多的上鏈,例如Polymath,ConsenSys,它們將完整的業(yè)務(wù)流程利用智能合約的方式實現(xiàn)。
輕量級的智能合約并沒有太多的技術(shù)難點可講,真正需要發(fā)展的是智能合約設(shè)計模式。
目前,已有的官方推薦的工具集, Zeppelin,它提供了:
數(shù)學(xué)計算
合約所有權(quán)
編碼解碼
加密解密
方便合約編寫者調(diào)用,但這些只能是以工具、參考的形式存在,并不能算作真正意義上的設(shè)計模式。目前Zeppelin社區(qū)也在積極探索智能合約設(shè)計模式的實現(xiàn)方式。
Zeppelin社區(qū)目前構(gòu)思了智能合約與邏輯分離的設(shè)計模式,用于解決智能合約升級的問題。
原文地址:https://blog.openzeppelin.com/proxy-libraries-in-solidity-79fbe4b970fd/
如何利用智能合約實現(xiàn)復(fù)雜的業(yè)務(wù)場景
目前受限于智能合約的限制,只能實現(xiàn)業(yè)務(wù)場景中的關(guān)鍵步驟,如果將整個業(yè)務(wù)放到鏈上執(zhí)行,傳統(tǒng)智能合約的編寫方式將不再適用,例如無法解決合約文件大小的瓶頸、參數(shù)過多導(dǎo)致棧深錯誤、合約之間互相訪問存儲數(shù)據(jù)的問題等等,這些都會影響智能合約的編寫。目前如何編寫能夠承載負(fù)責(zé)業(yè)務(wù)場景的智能合約,已經(jīng)成為行業(yè)共同面臨的挑戰(zhàn)之一。
在這里,我參照傳統(tǒng)MVC設(shè)計模式、基于關(guān)系型數(shù)據(jù)庫存儲,結(jié)合智能合約自身特性,Zeppelin社區(qū)提供的合約分離理念,初步實現(xiàn)復(fù)雜業(yè)務(wù)場景的智能合約設(shè)計模式。
一、針對業(yè)務(wù)功能處理
每個業(yè)務(wù)場景包括多個角色,角色既有單獨操作,也有與其他角色共同配合的操作。
針對角色,將其合約拆分成為:入口合約、存儲合約、邏輯合約。
1) 設(shè)計存儲合約,用于存儲角色模型的數(shù)據(jù),并提供對外訪問的CURD方法,實現(xiàn)效果等同于MVC中的Model層。
2) 設(shè)計邏輯實現(xiàn)合約,利用存儲合約提供的CURD,實現(xiàn)業(yè)務(wù)邏輯。類比于MVC中的Controller層。
3) 設(shè)計入口合約,用于提供對外訪問的地址,將用戶的請求轉(zhuǎn)發(fā)至邏輯合約進行處理,執(zhí)行的結(jié)果存入存儲合約中。
二、針對業(yè)務(wù)變動及風(fēng)險處理
考慮到業(yè)務(wù)會發(fā)生變動。將傳統(tǒng)智能合約拆分成:入口合約、存儲合約、邏輯合約,三個合約各司其職,共同實現(xiàn)業(yè)務(wù),當(dāng)業(yè)務(wù)發(fā)生變動需要修改,修改并重新部署邏輯合約,并將新版本的邏輯合約注冊到入口合約,即可以解決
1、 合約可實現(xiàn)性:突破合約大小限制、函數(shù)復(fù)雜度限制
2、 合約可升級性:地址不變,只對合約功能進行升級
3、 合約可維護性:發(fā)現(xiàn)bug時,及時對合約進行修復(fù)
另外,智能合約繼承自功能開關(guān)合約,可以實現(xiàn)當(dāng)智能合約發(fā)現(xiàn)漏洞時,緊急關(guān)閉某些功能(例如轉(zhuǎn)賬),減少損失。
三、針對業(yè)務(wù)角色之間的交互處理
智能合約中,數(shù)據(jù)的記錄都是Key-Value形式,類似于Redis這樣的數(shù)據(jù)庫,數(shù)據(jù)之間的關(guān)聯(lián)較弱。通過設(shè)置各個合約都可以訪問的全局存儲合約,記錄各個入口合約的地址、合約數(shù)據(jù)之間的關(guān)聯(lián)關(guān)系,使各個合約之間可以數(shù)據(jù)互通。
四、針對業(yè)務(wù)場景中的執(zhí)行權(quán)限處理
智能合約繼承自所有權(quán)合約,可以限制合約中某些關(guān)鍵方法的操作者,這些操作者可以是個人賬戶、也可以是合約賬戶,使合約受控于系統(tǒng)管理員。另外,也提供了權(quán)限轉(zhuǎn)移功能,可以方便的將權(quán)限轉(zhuǎn)移給其他管理員。
智能合約設(shè)計模式的技術(shù)點
l委托調(diào)用
以上智能合約的拆分,就是依賴智能合約中委托調(diào)用的特性。
委托調(diào)用,會保留調(diào)用者的賬戶與信息,例如User調(diào)用合約A中funcA,funcA委托調(diào)用合約B中的funcB,那么funcB的調(diào)用者就是User,而不是合約A。委托調(diào)用的優(yōu)勢就是可以保留調(diào)用合約的上下文,只是利用合約B的代碼實現(xiàn)想要的功能。這樣可以:
減少合約A中的代碼量。
合約B中的邏輯可以隨時更新。
lFallback機制
當(dāng)調(diào)用智能合約中未定義的方法時,智能合約會將調(diào)用者及參數(shù)都傳給一個錯誤處理函數(shù),類似訪問了網(wǎng)站中不存在的頁面,會跳轉(zhuǎn)到404頁面一樣。正是利用了這個特性,合約A(上文例子)將在這個fallback函數(shù)中統(tǒng)一處理這個未定義方法。
l內(nèi)聯(lián)匯編
智能合約中的委托調(diào)用,只會返回調(diào)用結(jié)果是True和False,但我們要達成智能合約的拆分,就要讓委托調(diào)用返回調(diào)用后的結(jié)果,這就需要修改委托調(diào)用的指令集,將結(jié)果返回。通過內(nèi)聯(lián)匯編,修改智能合約中委托調(diào)用的實現(xiàn)。
l全局存儲合約
全局存儲合約是模擬傳統(tǒng)key-value數(shù)據(jù)庫,通過智能合約的方式實現(xiàn)數(shù)據(jù)庫的CURD,將系統(tǒng)的配置(比如管理員的地址、Token與穩(wěn)定貨幣的兌換比例等)、各個模塊入口合約的地址、合約之間的關(guān)聯(lián)關(guān)系存儲起來,打通各個合約之間的數(shù)據(jù)。
l合約的合理拆分
目前將合約拆分為入口合約、存儲合約、邏輯合約。
入口合約:所有與合約的交互都是通過入口合約。入口合約記錄了存儲合約地址:通過委托調(diào)用轉(zhuǎn)發(fā)給邏輯合約處理,修改存儲合約數(shù)據(jù)。記錄了邏輯合約的地址和版本:知道該轉(zhuǎn)發(fā)給哪個版本的邏輯合約處理。
存儲合約:負(fù)責(zé)存儲數(shù)據(jù),合約的存儲結(jié)構(gòu)不能變,這是底線。類比數(shù)據(jù)庫中的表,一旦設(shè)定就不能輕易修改;訪問及修改數(shù)據(jù)的接口,其他合約不能直接訪問當(dāng)前合約的數(shù)據(jù),需要通過外部函數(shù)來訪問和修改,例如java model中的setter和getter 方法,實現(xiàn)存儲合約的的CURD。
邏輯合約:負(fù)責(zé)處理合約邏輯,通過組合存儲合約的CURD,實現(xiàn)復(fù)雜的邏輯。
智能合約框架
l模塊框架
1、 用戶調(diào)用入口合約函數(shù)。
2、 入口合約委托給邏輯合約處理。
3、 邏輯合約進入到入口合約上下文,獲取到存儲合約地址,修改/查詢存儲合約數(shù)據(jù)。
4、 邏輯合約返回數(shù)據(jù)給入口合約。
5、 入口合約返回數(shù)據(jù)給用戶。
l 整體框架
智能合約設(shè)計模式的優(yōu)缺點
優(yōu)點:
a) 拆分智能合約,可以繞過合約大小的限制,實現(xiàn)復(fù)雜的功能。
b) 可以通過升級邏輯合約來更新智能合約。
c) 可控的智能合約,當(dāng)出現(xiàn)問題時,管理員賬戶可以關(guān)閉關(guān)鍵性操作。
d) 將功能性合約封裝成通用合約,減少重復(fù)部署合約消耗的gas。
e) 通用全局存儲,可以滿足任意格式數(shù)據(jù)的存儲與讀取。
f) 合約注冊表,可以方便合約之間的互相調(diào)用。
缺點:
a) 拆分智能合約,合約總體代碼量增加,增加了部署時gas的消耗。
b) 合約的可讀性大幅下降,用戶無法簡單的讀取合約的邏輯。
c) 鍵值對的存儲合約操作復(fù)雜。【智能合約】編寫復(fù)雜業(yè)務(wù)場景下的智能合約——可升級的智能合約設(shè)計模式
Demo地址:https://github.com/NoharaHiroshi/upgradability-solidity-demo
總結(jié)
以上是生活随笔為你收集整理的【智能合约】编写复杂业务场景下的智能合约——可升级的智能合约设计模式(附Demo)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 信用卡附属卡算新户吗?其实很好理解
- 下一篇: 这个录屏工具在 GitHub 火了,33