本文是對前幾期祕猿區塊鏈課堂中關於 Cell 模型的總結。底層公鏈 CKB 的 Cell 模型是一個高度抽象的模型,事實上,你不只能夠在 Cell 上實現 First-class Asset,也能夠在 Cell 上模擬 Account。經過本文的介紹咱們能夠看出,Cell 模型是一個不一樣於 UTXO 模型和 Account 模型的新設計。除了狀態模型的不一樣,CKB 還將計算(也就是狀態生成)轉移到了鏈外,在鏈上只須要對狀態進行驗證的邏輯。獨特的狀態模型和計算驗證分離這兩點決定了 CKB 的編程模型上必然會出現新的 DApp 範式和設計模式。
祕猿科技區塊鏈小課堂第 19 期git
喜歡函數式編程的工程師應該很熟悉一個名詞:First-class Function,翻譯成中文應該叫「頭等函數」或者「一等函數」。First-class Function 指的是一類編程語言,在這些語言中函數是一個徹底獨立的概念:函數能夠被看成值賦給一個變量,能夠被看成參數傳遞給其餘函數,也能夠被看成返回值從其它函數傳出來。在這樣的語言中咱們能夠像操縱數據同樣操縱函數,因此在這些語言中函數和數據同樣是「一等公民」(First-class Citizen)。First-class Function 是函數式語言的一個關鍵特性,不少函數式編程的強大能力來源於此。github
Nervos CKB 使用 Cell 模型來構建整個共同知識庫的狀態。Cell 模型是一個很是簡單可是與現有區塊鏈設計很是不一樣的狀態模型,咱們在設計 Cell 模型的時候已經意識到,基於 Cell 模型的 DApp 將擁有一些很是不一樣的性質,就像函數式編程和麪向對象編程會產生風格迥異的設計模式和程序特性同樣。在這篇文章中,我想闡述 Cell 模型能夠支持的一種很是有趣的 DApp 設計模式,咱們把它叫作 First-class Asset,由於經過它咱們能夠將用戶自定義的加密資產變成區塊鏈中的「一等公民」。編程
在 Cell 模型以前,各類區塊鏈使用的狀態模型基本上就是兩種:UTXO 模型和 Account 模型。segmentfault
使用 UTXO 模型的表明是比特幣。UTXO 是未被花費的交易輸出(Unspent Transaction Output)的縮寫,一個 UTXO 能夠簡單的理解爲是一個比特幣,然而和通常的硬幣不一樣,每個 UTXO 的面值都是不同的。每一個 UTXO 中都經過一段鎖腳本(Lock Script)記錄了這枚硬幣的全部者是誰,同時保證只有全部者可以花費這枚硬幣。每個比特幣全節點都會維護當前全部 UTXO 的集合,這個集合咱們就稱爲比特幣帳本的當前狀態(即當前的帳本)。每一次比特幣轉帳都是一個從 UTXO 集合中刪除幾個硬幣(屬於付款方)而後又增長几個新硬幣(屬於收款方和 / 或付款方)的過程。因爲整個帳本狀態是基於 UTXO 這個最小單元構建的,咱們把它叫作 UTXO 模型。設計模式
使用 Account 模型的表明是以太坊。Account 就是帳戶,和銀行帳戶相似,表明了資產的全部者,帳戶裏面最重要的數據是餘額(Balance),記錄這個帳戶持有的以太幣的數量。帳戶是資產全部者的表明,全部者能夠是人(對應外部帳戶)或者智能合約(對應合約帳戶),外部帳戶經過私鑰簽名來驗證資產全部權,合約帳戶的全部權經過合約代碼來肯定,合約代碼和狀態都保存合約帳戶內部。外部帳戶要轉帳的時候,用戶在交易中指明轉帳數量,帳本中的付款方帳戶餘額和收款方帳戶餘額就會作相應的減小和增長。因爲整個帳本狀態是基於帳戶(Account)這個最小單元構建的,咱們把它叫作 Account 模型。ruby
UTXO 模型和 Account 模型表明了構建帳本狀態的兩種思路。帳本是全部者與資產之間關係的集合。UTXO 模型以資產爲基礎建模,先構建出「硬幣」的概念,再給硬幣賦予全部者的屬性;Account 模型以全部者爲基礎建模,先構建出「帳戶」的概念,再給帳戶賦予餘額的屬性。以哪一種方式做爲基礎模型決定了系統中的操做的基本對象是資產仍是帳戶(全部者)。網絡
因此咱們說,硬幣(Coin)是 UTXO 模型中的 First-class Citizen,每個 UTXO 都是一個具備獨立標識符的對象(Transaction ID + Output Index),Coin 是用戶直接操做的對象(用戶在構造的交易中包含 UTXO),帳戶是基於 Coin 創建的上層概念(只存在於錢包中)。所以 UTXO 是 First-class Coin。編程語言
在 Account 模型中,帳戶是 First-class Citizen,聚合在帳戶餘額中的硬幣沒有獨立的標識符。帳戶是用戶直接操做的對象,資產的轉移是由帳戶做爲用戶的代理實現的,這一點在接受方是合約帳戶時體現的最爲明顯。在這樣的模型下,用戶定義加密資產(例如 ERC 20)更像是經過第三方記帳的方式,而非點對點的方式轉移,這個差別會將第三方(這裏的第三方指的是託管加密資產的智能合約)引入資產轉移流程,增長智能合約的設計複雜度(咱們能夠把智能合約看做在資產轉移時會自動執行的邏輯)。爲了下降這種複雜度,Account 模型中的交易須要加入特殊的邏輯(Value 字段),可是這樣的特殊邏輯只有助於原生資產,同時形成對原生資產和用戶自定義資產的不一樣代碼路徑。函數式編程
對於這些問題,Kelvin Fitcher 寫過一篇 Looking at ownership in the EVM 進行了很好的分析,在此再也不贅述。函數
有了這些背景,咱們應該更容易理解 CKB 的這一設計理念了:
有了 Cell 模型,咱們可以簡化設計,並在 Nervos CKB 上實現做爲「一等公民」的用戶定義資產(User Defined Assets),簡稱 First-class Assets.
First-class Assets 與 UTXO 同樣,具備獨立標識符,能夠被用戶及腳本直接引用和操做。
如何實現 First-class Assets 呢?
不管用何種方式,咱們都須要記錄全部者和資產之間的關係。這些關係記錄,本質上是通過共識的狀態。要有 First-class Assets, 必須先有First-class State,而這正是 Cell 模型的出發點。
Nervos CKB 的名字來自於 Common Knowledge Base(共同知識庫)的縮寫。咱們之因此把 Nervos 網絡中的區塊鏈稱爲「共同知識庫」,是由於它的責任是持續不斷的對網絡的共同狀態造成全球共識,換句話說,CKB 是一個由全球共識維護的狀態庫。一個狀態庫的基本模型,很天然的是將整個狀態劃分爲更小的狀態單元組織起來。這些更小的狀態單元,就是 Cell。
因爲 Cell 是一種狀態單元,有獨立的標識符(Transaction ID + Cell Output Index),能夠被直接引用,做爲參數傳遞給腳本,它是 CKB 中的「一等公民」,也就是說狀態是 CKB 中的「一等公民」。Cell 不只僅是一種 First-class State,並且是最簡單的一種 First-class State:一個 Cell 中只有 Capacity,Data,Lock 以及 Contract(可選,Contract 能夠是一段代碼或者指向一個 Code Cell 的 Reference)四個字段。
以下圖所示,Cell 的全部者能夠直接更新 Cell 中保存的狀態,不須要通過任何中間方,而在 Account 模型中用戶只能經過合約代碼(帳戶中的 Code)來操做帳戶內的狀態,狀態其實是託管在合約手中的。
值得指出的是,有了 Cell,CKB 實際上就得到了一種有狀態的編程模型。一種廣泛的觀點是,以太坊編程模型的表達能力來自圖靈完備的虛擬機,實際上經過帳戶使得智能合約可以保存計算狀態是一個大過 EVM的優勢(圖靈不完備的語言也有很強大的表達能力)。
CKB 經過 Cell 和 CKB-VM(Simple Yet Powerful! 這得另外寫一篇文章了)的組合實現了一種新的有狀態的智能合約編程模型。這個編程模型更加適合 Layer 2,由於經過分析 Layer 2 協議的共同模式咱們能夠看到,協議層之間的交互對象應該是狀態對象(State Transaction)而不是事件對象(Event Transaction),Layer 1 應該是一個狀態層而不是計算層。
CKB 編程模型的另外一個特色是,不區分數據(狀態)和代碼。這句話的意思是,與 Account 模型不一樣,合約的狀態和代碼均可以儲存在 Cell 的 Data 字段中,保存代碼的 Cell 能夠被其它 Cell 引用(由於它們是First-class State!),合約的狀態和代碼不須要綁定在一塊兒,存放在一個地方。開發者能夠經過一條簡單的指令把代碼 Cell 或者數據 Cell 的內容載入運行時內存,而後根據須要自行將其解釋爲代碼執行或者數據來讀寫。
有了這些底層支持,咱們就能夠將一個合約的代碼和狀態分開保存在不一樣的地方:Code Cell 的 Code(Data)字段存放代碼,而 State Cell 的 State(Data)的字段則保存狀態;在 State Cell 中經過 Contract ref 引用 Code Cell 來創建對自身保存的 State 的業務邏輯約束,經過 Lock ref 引用另一個 Code Cell 來表達 State Cell 的全部權。每個 State Cell 能夠屬於不一樣的用戶,所以在 Cell 模型下獨立的用戶狀態是很是容易實現的模式(在 Account 模型下,合約狀態每每由多個用戶狀態混合構成,例如在一個 ERC 20 合約中,Alice 和 Bob 的 Token 餘額都記錄在同一個合約的內部狀態裏面)。
若是想對 CKB-VM 上的合約編寫有更多瞭解,請看這兩篇文章「An Introduction to Nervos CKB-VM」「Hello:CKB」:有了這樣一種編程模型,咱們就能構造 First-class Asset 了。
CKB 中的用戶定義資產(User Defined Asset)能夠這樣來構造:
能夠看到,在這樣的設計中,用戶定義的資產是做爲獨立對象存在於系統中的,每一份資產都是一個 Cell,每一份資產都擁有本身的標識符。咱們徹底能夠認爲 Asset Cell 是 UTXO 的通用化版本。這樣的 First-class Asset 有以下優勢:
上面的示意圖只是在 CKB 上實現 First-class Asset 的一種方式。除了上面討論的方面,還有一些有趣的細節,例如,Asset Definition Cell 是否是能夠有屬於本身的狀態?Asset Definition Cell 以及 Asset Cell 的 Capacity 應該由誰來提供?對於這些問題,咱們已經有了一些很是漂亮的想法。這些細節的設計、討論和實現是咱們如今正在進行的工做。
Cell 模型是一個高度抽象的模型,事實上,你不只能夠在 Cell 上實現First-class Asset,也能夠在 Cell 上模擬 Account。經過這篇文章的介紹咱們能夠看出,Cell 模型是一個不一樣於 UTXO 模型和 Account 模型的新設計。除了狀態模型的不一樣,CKB 還將計算(也就是狀態生成)轉移到了鏈外,在鏈上只須要對狀態進行驗證的邏輯。獨特的狀態模型和計算驗證分離這兩點決定了 CKB 的編程模型上必然會出現新的 DApp 範式和設計模式。
從CKB白皮書完成到如今將近一年的時間中,咱們看到愈來愈多的人開始關注和討論First-class State和First-class Asset這兩種新的思路(雖然你們用的名詞各自都不同),這些進展讓咱們很是興奮。若是你有興趣對First-class State和First-class Asset進行更多的探討,或是在CKB的編程模型上有什麼有趣的想法,歡迎聯繫咱們討論~
CKB的代碼已經徹底開源,這篇文章介紹的內容在代碼中都已經實現。歡迎給咱們的代碼提出各類意見:
https://github.com/nervosnetw... 9 (ckb上用ruby腳本編程的示例,理解ckb上編程模型的最佳入口)
https://github.com/nervosnetw... 1
https://github.com/nervosnetw... 2感謝Ian Yang, Xuejie Xiao,Kevin Wang在CKB和Cell模型設計中提供的幫助~