一文了解 CKB 程式設計模型
By 區塊鏈資訊·
昨天,由 Nervos Grants 專案團隊 Obsidian Labs(黑曜石實驗室) 聯合 Nervos 和 Nervos Community 一同推出的 CKB 程式設計體驗課程正式開課啦!這是我們首次為 Nervos 中文社羣的夥伴們精心打造的第一套開發體驗課程。在昨天的課程中,CKB 程式設計體驗課講師 Obsidian Labs 創始人& CKB Studio 核心開發者 Phil Li 和大家初步介紹了 CKB Studio 的安裝以及 IDE 的使用介面,並讓大家瞭解如何在 CKB Studio 上進行轉賬以及部署簡易合約。在接下來的課程中,Phil Li 還將繼續帶大家實操 sUDT 的發幣和轉賬,type 和 lock script 的指令碼程式設計,以及 JavaScript 的智慧合約編譯。這門課程是 CKB 初學者瞭解 CKB 的極佳入口,為了方便同學們更好的掌握課程內容,我們也為大家整理和彙總了 CKB 程式設計模型的基礎圖譜,供大家參閱。Nervos CKB 是一個以狀態為中心的 Layer 1 底層架構,其中交易表示狀態的更改和遷移。CKB 提供了一種獨特的基於 CKB VM 和 Cell 模型的有狀態的圖靈完備程式設計模型。CKB 程式設計模型如果您想要在 CKB 上進行開發,那麼您首先應該要理解它的程式設計模型。CKB 中的狀態是一等公民(First-Class Citizen),狀態包含在交易和區塊中,它們直接同步在節點之間。CKB 的程式設計模型由三部分組成:· 狀態生成(鏈下)· 狀態儲存(Cell 模型)· 狀態驗證(CKB VM)在這個模型中,去中心化的應用邏輯被分為兩個部分(生成和驗證),分別在不同的地方執行。狀態生成發生在客戶端的鏈下,新的狀態被打包成交易並廣播到整個網路;狀態驗證發生在鏈上,它會確保狀態轉換的有效性並建立一個去信任的系統(trustless system)。CKB 交易的 inputs 包括對之前 outputs的引用,以及能夠解鎖它們的證明。客戶端將生成的新狀態作為交易 outputs,在 CKB 中稱為 cell。因此,cell 和交易輸出的表述是可以互換的。Cell 是 CKB 中的主要狀態儲存單元,資產所有權歸使用者所有,並且必須遵循指令碼指定的相關應用程式邏輯。我們在 CKB VM 中執行指令碼(後文將做具體介紹)並驗證交易輸入中包含的證明,以確保使用者可以使用這些引用的 cell,並且在指定的應用程式邏輯下狀態轉換是有效的。透過這種方式,網路中的所有節點都可以驗證新狀態是有效的,並保留這些狀態。1. Cell 模型:通用化的 UTXO 模型Bitcoin 把整個賬本分割儲存在了一個個 UTXO 裡面,UTXO 是未花費交易輸出(Unspent Transaction Output)的簡寫,它被鎖定在特定的所有者手中,記錄在區塊鏈上,並被整個網路識別為貨幣單位。它的資料結構非常簡單,只包含兩個欄位:class TxOut{public:Amount Value;Script scriptPubKey;...}每一個 TxOut 代表了一個硬幣並且有自己的命名,這是由 Value 定義的, scriptPubKey 是一段表示這個硬幣的所有者是誰的指令碼(通常包含了所有者的公鑰),只有能提供正確的引數使這個指令碼執行成功的人,才能把這個硬幣「轉讓」給另外一個人。CellLayer 1 的關注重點在狀態,以 Layer 1 為設計目標的 CKB 設計的關注點很自然就是狀態。CKB 想要驗證和長久儲存的狀態,不僅僅是像在比特幣中那樣簡單的數字(Value),而是任何人們認為有價值的、經過共識的資料,Bitcoin 的交易輸出結構滿足不了這個需求。只需要將 Value 一般化,把它從一個存放整數的空間變成一個可以存放任意資料的空間,我們就得到了一個更加一般化的「Value 」或者叫 Cell:pub struct CellOutput {pub capacity: Capacity,pub data: Vec<u8>,pub lock: Script,pub type_: Option<Script>,}在 Cell 裡面,Value 變成了 capacity 和 data 兩個欄位,這兩個欄位共同表示一塊儲存空間,capacity 不僅僅只是儲存 Token 的數量,也能表示 cell 可以儲存資料數量的限制,這就是名字的由來,它是 cell 能夠儲存的容量限制, data 則是儲存狀態的地方,可以寫入任意的一段位元組。Cell 模型是一個全新的模型,引入了 lock script 和 type script 的概念,我們將在後面提到。總的來說,UTXO 模型讓賬簿的歷史記錄更加清晰,但是它缺乏通用的狀態儲存,這會讓它原本就缺乏表現力(inexpressive)的指令碼更加難以使用。Cell 模型是 UTXO 模型的一個通用版本,它是 CKB 上非常靈活和具有創造力的部分。如果你想要了解更多關於 Cell 模型的內容,歡迎查閱《理解 CKB 的 Cell 模型》:https://talk.nervos.org/t/ckb-cell/15622. 鎖定指令碼 & 型別指令碼:一個全新的驗證模型CKB 是一個全新的驗證模型,與其它一些區塊鏈不同,CKB 為整個社羣提供了開發 CKB 指令碼的自由。1. 鎖定指令碼每個 Cell 都有一個鎖定指令碼。當交易中的 Cell 被以輸入的形式使用時,鎖定指令碼必須執行。交易只有在所有的輸入中鎖定指令碼都正常(執行並)退出時(沒有例外)才有效。因為指令碼在輸入上執行,所以它可以扮演鎖的角色來控制誰可以解鎖或者銷燬 Cell,以及花費儲存在 Cell 中的容量。以下是一個總是可以正常(執行並)退出的鎖指令碼的程式碼示例。如果使用這段程式碼作為鎖指令碼,那麼任何人都可以銷燬這個 Cell。int main(int argc, char *argv[]) {return 0;}最主流的鎖定數字資產的方式是用非對稱加密建立的數字簽名。這個簽名演演算法有兩個要求:· Cell 必須要包含公鑰的資訊,所以只有真正的私鑰可以建立有效的簽名;· 交易必須包含簽名,而且通常以整個交易作為訊息去簽名。2. 型別指令碼型別指令碼和鎖定指令碼很相似,但有兩點不同:· 型別指令碼是可選的;· 在任一交易中,CKB 必須在輸入和輸出端都執行型別指令碼。3. CKB VM:一臺真正的迷你電腦CKB VM 是一個基於 RISC-V 指令集的 VM,用於執行型別指令碼和鎖指令碼。這意味著什麼呢?這意味著我們(在某種程度上)在 CKB 中嵌入了一臺真正的迷你計算機,而不是一臺虛擬機器。真正計算機的好處是,你可以使用任何語言編寫任何你想編寫的邏輯。我們可以用 JavaScript 編寫 CKB 指令碼程式碼。這是怎麼實現的呢?那是因為我們有 C 編譯器可用,我們所做的只是採用了一個 JavaScript 實現的嵌入式系統,透過 duktape 從 C 編譯成 RISC-V 二進位制,並放在區塊鏈中,然後 boom,我們就可以在 CKB 上執行 JavaScript! 因為我們在這裡使用的是一臺真正的迷你計算機,所以我們可以將另一個 VM 作為 CKB 指令碼嵌入到 CKB VM 中,並在 VM 路徑上探索這個 VM。我們還可以用這個方法進行擴充套件,我們可以在 CKB 上透過 duktape 使用 JavaScript,也可以透過 mruby 使用 Ruby,我們甚至可以在 CKB 上使用比特幣指令碼或 EVM 如果我們只是編譯它們的 VM 和把它放在鏈上。這確保了 CKB VM 既能幫助我們儲存自身的優勢,又能建立一個多樣化的生態系統。在 CKB 中,所有的語言都應該被平等對待,自由應該被掌握在區塊鏈智慧合約開發者的手中。4. UDT:First-class asset現有區塊鏈的常見用途是向 Token 發行方發行具有特殊用途/意義的新 Token。在以太坊,我們稱之為 ERC20 代幣。為了區別於 ERC20,我們將 CKB 上發行的 Token 稱為使用者自定義代幣(user defined token,簡稱 UDT)。什麼是 First-Class Asset?First-Class Asset 的概念實際上來自 First-Class Function。First-Class Asset 是使用者直接擁有並可以直接操作的加密資產。為什麼 UDT 是 First-Class Asset?Ethereum 是為每個智慧合約帳戶提供了獨特的儲存空間,而 CKB 是在多個 cell 之間傳播資料。Cell 的鎖定指令碼和型別指令碼決定了該 cell 屬於哪個帳戶,以及如何與 cell 互動。在 CKB 中,我們有一個新的設計來儲存 UDT 使用者的餘額:1. 用一個特殊的型別指令碼來表示該 cell 儲存的是 UDT。2. Cell data 的前 4 個位元組包含了當前 cell 中 UDT 的數量。這個設計有以下幾個含義:· UDT cell 的儲存成本總是恆定的,它與 cell 中儲存的 UDT 數量無關。· 使用者可以將 cell 中的所有 UDT 或部分 UDT 轉移給其他使用者· 實際上,可能有多個 cell 含有相同的 UDT。· 用於保護 UDT 的鎖定指令碼與 UDT 本身解耦。每個 Token 使用者將其 UDT 儲存在自己的 cell 中,Cell 負責為 UDT 提供儲存空間,並確保它們自己的 Token 是安全的。透過這種方式,UDT 可以真正地屬於每個單獨的 UDT 使用者,而不像 ERC20 那樣將所有 Token 使用者的餘額都儲存在 ERC20 合約儲存空間中,而 ERC20 合約存在某些安全漏洞。CKB 的經濟模型關注狀態儲存激勵問題。使用者在區塊鏈上儲存狀態不僅需要支付寫入費用,而且應該承擔與儲存時間成正比的儲存成本。這解決了我們在 Ethereum ERC20 合約中實現「儲存租金」時遇到的問題,例如,如果使用者的資產狀態混合在一個地方儲存,那麼如何讓每個使用者僅支付儲存自己資產的成本將是一個問題。5. Type ID:提供可升級性和確定性之間的平衡在區塊鏈的世界裡,有兩個問題是每個人都必要面對的:可升級性和確定性之間的矛盾。可升級性:在一個智慧合約部署在區塊鏈上之後,我還能升級它嗎?假設一個智慧合約得到了廣泛採用,然後突然有人在這個智慧合約中發現了一個 bug(遺憾的是,這樣的情況在區塊鏈行業總是會發生),我們能否在不影響所有使用者的情況下,將智慧合約升級到一個修復完成的版本呢?確定性:這裡有兩個部分:· 確定性 A:如果我選擇一個智慧合約來保護我的 token,那麼我的 token 在未來也會安全嗎?(可以由我解鎖,且只能由我解鎖)· 確定性 B:如果我現在簽名了一筆交易,然後稍後再傳送它,我的交易還會被區塊連結受嗎?注意,一個安全的區塊鏈要比這裡提到的內容有更多的確定性需求。在這裡我只描述和討論問題相關的屬性。如果我們仔細想一想,就會發現可升級性和確定性之間總是存在衝突:· 如果一個智慧合約可以升級,那它可能具有不同的行為,從而使攻擊者能夠解鎖這個 cell,或者禁止 token 所有者去解鎖這個 cell。· 如果一個智慧合約可以升級,那麼一筆已經簽名的交易可能會(在升級前後)執行不同的行為,從而被區塊鏈拒絕。回看過去,在可升級性和確定性之間,你只能選站一邊。並且大多數現有的區塊鏈專案都選擇了確定性這一邊。「程式碼即法律」的思想在區塊鏈領域非常流行。但是我們都知道軟體的設計是一個權衡的過程。在特定情況下,犧牲一些確定性來換取可升級性帶來的便利是有意義的。因此,我們實現了一個獨特的指令碼:type ID script。 在 CKB 上,這個功能完全是可選的,你可以像在其它區塊鏈中一樣,在 CKB 上完美地踐行「程式碼即法律」的原則,並且可以提供可升級性和確定性之間的平衡。我們只是希望這個獨特的功能,能為那些真正需要它的人提供新的可能性。6. Duktape 高階程式設計:用 JavaScript 編寫 CKB 指令碼得益於強大的 CKB VM,我們可以在 CKB 上透過 duktape 使用 JavaScript。我們不僅可以有一些邏輯非常簡單的程式碼片段,還可以解析 CKB 資料結構,在指令碼中放置外部庫等等。我們的 CKB 核心開發人員 Xuejie 寫了一篇關於如何實現的文章:《CKB 指令碼程式設計簡介[7]:Duktape 高階程式設計》:https://docs.ckb.dev/blog/ckbscript-07這篇文章中演示瞭如何建立一個 CKB 指令碼專案:duktape-powered,這個專案有以下需求:· 外部庫依賴· CKB資料結構的序列化/反序列化· 進行雜湊計算對於想要開發 JS 專案的人來說,這是一個非常有用的例子,你可以透過 JavaScript 和 duktape 獲得精簡的 CKB 指令碼開發體驗。7. 除錯:支援基於 GDB 和 REPL 的開發/除錯除錯 CKB 指令碼和你日常除錯程式並沒有太大區別。CKB 指令碼除錯的第一種方案,通常適用於 C、Rust 等程式語言。也許你已經習慣了寫 C 的程式,而 GDB 也是你的好搭檔。你想知道是不是可以用 GDB 來除錯 C 程式,答案當然是:Yes!你肯定可以透過 GDB 來除錯用 C 編寫的 CKB 指令碼。然而,GDB 僅僅是現代軟體開發中的一部分。動態語言在很大程度上佔據了主導地位,很多程式設計師都使用基於 REPL 的開發/除錯工作流。這與編譯語言中的 GDB 完全不同,基本上你需要的是一個執行的環境,你可以輸入任何你想要與環境進行互動的程式碼,然後得到不同的結果。CKB 也會支援這種型別的開發/除錯工作流。如果你想要了解更多關於如何除錯 CKB 指令碼的內容,歡迎檢視《CKB 指令碼程式設計簡介[5]:除錯》:https://docs.ckb.dev/blog/ckbscript-058. 擁抱 WebAssembly 生態系統與 WebAssembly 相比,RISC-V 實際上是一個更低層次的抽象,我們可以移植現有的 WebAssembly 程式,並直接在 CKB VM 上執行它們。透過這種方式,我們可以擁有 RISC-V 提供的靈活性和穩定性,同時也可以擁抱 WebAssembly 生態系統。在 CKB VM 中執行 WebAssembly 程式實際上比直接使用 WebAssembly 虛擬機器有更多的好處:· 在 CKB 環境中,我們可以附加任何我們喜歡的環境功能,從而支援所有針對不同區塊鏈的 WebAssembly 程式。更重要的是,我們可以使用匯入,因為我們想要向現有的 WebAssembly 程式引入新功能,因為匯入功能是與 WebAssembly 程式一起提供的,所以 CKB 本身不需要做任何事情來支援這一點,所有的神奇之處都發生在一個 CKB 指令碼中。而對於支援區塊鏈的 WebAssembly,這些環境功能很可能是固定的,並且是共識規則的一部分,不能隨意引入新的環境功能。同樣的,這個基於 CKB 的轉型工作流能夠讓它更容易地支援新的 WebAssembly 特性,比如垃圾回收或執行緒,它實際上只是將所需的支援功能作為 CKB 指令碼的一部分即可,所以當 WebAssembly 虛擬機器得到更新時(如果已更新),我們無需再等待 6 個月來進行下一次硬分叉。· 易於實現:在 RISC-V 上構建 WebAssembly 會讓人感覺更自然,因為 WebAssembly 在更高的層級上抽象了許多高階特性,例如更高階別的控制流,垃圾回收等。另一方面,RISC-V 模擬了一個真正的 CPU 可以做什麼,這是在計算機內部執行的實際 CPU 之上非常薄的一層。因此,雖然這兩個方向都是有可能的,但是確定(certain)的功能在 RISC-V 方向的 WebAssembly 中更容易實現,而在 WebAssembly 方向的 RISC-V 中可能會遇到障礙。另一個可供選擇的方案是 EVM,多年來 EVM 一直在倡導圖靈完備的解決方案,但可惜的是,在 EVM 上構建任意複雜的演算法幾乎是不可能的:要麼編碼部分太困難,要麼 gas 消耗不合理。為了在 EVM 上引入最新的演算法,人們不得不想出各種各樣的破解方法,當伊斯坦布林硬分叉發生時,我們只能在 EVM 中運用合理的 blake2b 演算法。那麼其他的演算法呢?我們試圖在這一代的 CPU 架構上找到最小的層,而 RISC-V 是我們可以向區塊鏈世界公開的最透明的模型,同時確保安全性和效能。任何不同的模型,例如 WebAssembly、EVM等,都應該是 RISC-V 模型之上的層,並且可以透過 RISC-V 模型自然地實現,但是,另一個方向可能就不那麼順利了。此外,我們有一個新的專案可以用來生成高效能的 WASM 程式,你可以檢視並瞭解詳情:《CKB 指令碼程式設計簡介[8]: 高效能 WASM》:https://docs.ckb.dev/blog/ckbscript-08開發者社羣看到這裡,你們是否已經對 CKB 的程式設計模型有了初步的瞭解,或者有了一些很好的想法?今年年初,我們已經發布了 Nervos Grants 計劃來促進 CKB 上的創新和發展,並支援多樣化和繁榮的生態系統發展。併成立了 3000 萬美元的基金,用於資助開發者在 Nervos 上的開發。Grants 計劃的目標是吸引更多有才華的人圍繞 Nervos 開發解決方案,來研究和建立必要的工具,並激勵那些有意願和有激情致力於這些解決方案的開發人員和專案。我們的長期願景是完全地去中心化和社羣主導。要實現這一點意味著我們需要激發並引導那些希望為構建 Nervos 基礎設施做出重大貢獻的個人、專案和團隊。您可以訪問 Nervos Talk 來了解 Grants 計劃詳情,並獲取我們希望看到的提交型別列表。如果你也對 Nervos 專案感興趣,如果你也有好的 idea、經驗和技能,我們邀請您提交一份資助提案,和我們一起構建 Nervos 生態系統和共同知識庫(Common Knowledge Base,CKB)。和我們做的每一件事一樣,Grants 計劃過程和程式將是完全透明的。從評估申請,到投票篩選,專案的每一步都將向社羣成員開放,讓他們進行審查並提供反饋。更多關於 Grants 的資訊,歡迎檢視:RFC: Nervos Ecosystem Grants Programhttps://talk.nervos.org/t/rfc-nervos-ecosystem-grants-program/4038/Open Grant Program Categories and Scope of Work for Applicationshttps://talk.nervos.org/t/open-grant-program-categories-and-scope-of-work-for-applications/4109#CKB#Nervos
免責聲明:
- 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
- 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
- 鏈報僅提供相關項目信息,不構成任何投資建議。
推荐阅读