Godwoken —— Cell 模型中缺失的那一塊

對於開發者來講,cell 編程模型無疑是 Nervos CKB 中最有趣的部分。在這裏,咱們先對 cell 模型做一個簡短的描述:git

  • Cell 是通用版的 UTXO
  • 一個 cell 是一個包含任意數據和可定製腳本的 UTXO
  • 當一筆交易嘗試銷燬或建立一個 cell,cell 中的腳本將被加載並執行,在執行腳本中返回任何錯誤,都將致使交易失敗。

Cell 模型不一樣於帳戶模型:github

  • 驗證而非計算
  • 將數據存儲在單獨的 cell 中,而不是將數據存儲在一個帳戶中

當你比較兩個模型時,你會發現還有許多其餘的不一樣之處,若是你對該話題感興趣,能夠在 talk.nervos.org 上找到更多關於 cell 模型 VS 帳戶模型的討論。web

Cell 模型中缺失的那一塊

UTXO 是一個很是棒的模型,cell 模型繼承了它的靈活性。咱們(經過 cell 模型)能夠發行 UDT(用戶自定義代幣,相似於 ERC20),存儲鏈上資產,玩石頭剪刀布遊戲,或者與比特幣實現原子交換等。Cell 模型能夠實現不少人們最初認爲不可能實現的事情。 編程

不幸的是,有一些合約確實很難在 cell 模型上實現:spa

  • 投票
  • 衆籌
  • 去中心化訂價的虛擬機
  • ...

這些難題合約有一個共性,那就是須要共享狀態。設計

在一個 UTXO 類的模型內,狀態是天然分離的。code

在 CKB 中,用戶能夠在獨立的 cell 中進行投票。這樣咱們就須要一個鏈下的角色收集這些投票的 cells 並計算結果。blog

1.jpg

當咱們只想「看到」結果時,它實現的很是好。可是咱們不能在另外一個合約中使用投票結果,好比一個基於投票的 DAO 合約。咱們很難在一個鏈上合約中驗證統計後的結果。因此咱們必須證實每個投票 cell 的存在,交易時就須要引用每個投票的 cell,這可能很是昂貴。繼承

2.jpg

再舉個例子,咱們來看一個衆籌合約:遊戲

一個 cell 中有全部的衆籌代幣,用戶能夠支付 CKB 來得到相應數量的代幣。

問題在於,當咱們分割這個 cell,衆籌 cell 的 outpoint 就被改變了;其餘用戶必須等到下一個區塊才能看到新的 outpoint。因此在一個區塊時間內,只有一個用戶能夠參與衆籌,這是不可接受的。

與投票的例子相似,一個典型的解決方案就是引入一個鏈下角色,用戶在我的的 cells 中發出衆籌請求;而後鏈下角色須要收集這些 cells 並將結果放在一個 cell 中。

咱們能夠看到,因爲在 cell 模型中,狀態是天然分離的,所以咱們必須依賴某個鏈下角色來收集狀態。

這樣的方法是可行的,可是仍然會有一些問題:

  • 如何有效地證實收集的結果
  • 如何保證在引入了鏈下角色後的去中心化
  • 用戶如何與鏈下角色進行交互

固然,解決這些問題並不難;咱們能夠經過支付鏈下角色一些費用來激勵他們;使用某種挑戰機或者零知識證實(zk proof)來驗證收集的結果;定義一些協議來規定和鏈下角色的交互。咱們總能解決這些問題。

等等,我想要的只是一個投票合約。我爲何須要整這麼多(複雜的)東西?

一個合約管理一切

可不是嘛!咱們可不想爲每個合約都整這麼多東西,咱們只須要構建一次:

Godwoken 是一個創建在 CKB 上的基於帳戶模型的編程層,目標就是管理一切狀態共享的合約。

Godwoken 由如下幾個部分組成:

  • 主合約 —— 一個維護全部帳戶、全部區塊的全局狀態的類型腳本(layer 1.5 層)
  • 挑戰合約 —— 一個處理挑戰需求的類型腳本
  • 聚合器 —— 一個收集 layer 1.5 層交易的鏈下程序,並按期向主合約提交 layer 1.5 層的區塊。
  • 驗證器 —— 一個持續監控兩個合約的鏈下程序。驗證器在一個無效區塊被提交時會發送一個挑戰請求,在一個錯誤的挑戰請求被提交時會發送一個無效的挑戰請求。

你可能發現,這聽起來像是最近很是流行的 rollup 的解決方法。是的,沒錯。可是咱們關注的是聚合的問題,而非可擴展性的問題。Godwoken 提供了 CKB 基於帳戶模型的編程能力來解決聚合問題。

一些人將 Rollup 稱之爲 layer 1.5 層;也有一些人認爲它是 layer 2 層;還有人認爲它是 layer 1 層(根據信任級別)。本文將 Godwoken 稱爲 layer 1.5 層,以便將其與 layer 1 層的 CKB 區分開。

Godwoken 使用和原生 CKB 合約相同的技術棧。惟一的區別在於 Godwoken 合約是基於帳戶模型的;它將驗證帳戶的狀態而不是 cells 的狀態。帳戶狀態和 layer 1 層的 cells 之間的映射關係是由 Godwoken 的主合約處理的,對於 layer 1.5 層的合約來講,是透明的。

對於須要建立一個投票合約的開發者來講,只須要使用腳本簡單地建立一個帳戶,這個腳本就會驗證輸入的數據和帳戶狀態。

// pseudo code
fn verify_voting(i, votes) -> bool {
    state[i] += votes;
    merkle_root(state) == output_account_root
}

從上面的僞代碼中,咱們能夠看到驗證模型相似於 layer 1 層。

Godwoken 主合約使用了一個稀疏 merkle tree來存儲全部的帳戶和帳戶狀態。

所以,若是咱們想要在 layer 1.5 層合約之間使用一個狀態,咱們能夠簡單的爲這個狀態生成一個 merkle proof,並在合約中驗證 merkle proof。

若是咱們想在 layer 1 層的合約中使用一個 layer 1.5 層的狀態,咱們能夠在交易的 cell_deps 字段中引用 Godwoken 主合約 cell,並從 cell 中讀取 Godwoken 中的全局狀態來得到 merkle root,這樣就能夠驗證狀態和 merkle proof 了。

經過建立一個抽象的帳戶層,咱們能夠在 CKB 上經過最小的成本建立一個狀態共享的合約。

在後續的文章中,咱們將會討論 Godwoken 中的詳細信息,咱們如何維護 layer 1.5 層的帳戶和合約,以及基於帳戶模型的合約是如何工做的。

相關文章
相關標籤/搜索