Xuejie 是 CKB-VM 的核心開發(fā)者,他在自己的博客「Less is More」中,創(chuàng)作了一系列介紹 CKB 腳本編程的文章,用于補充白皮書中編寫 CKB 腳本所需的所有缺失的細(xì)節(jié)實現(xiàn)。本文是該系列的第一篇,介紹了 CKB 的全新驗證模型,據(jù)說這是 Xuejie 最后一篇沒有實際代碼示例的帖子,快來查收吧:P
截至目前,CKB 中的 Cell 驗證模型或多或少已經(jīng)趨于穩(wěn)定,因此我將開始寫一系列文章來介紹 CKB 腳本編程。我的目標(biāo)是補充白皮書中編寫 CKB 腳本所需的所有缺失的細(xì)節(jié)實現(xiàn),這樣您就可以開始探索 CKB 呈現(xiàn)的這個美麗的仙境。
您可能會注意到我將在 CKB 上運行的代碼稱為腳本,而不是智能合約。這是因為智能合約對我來說是一個令人困惑的術(shù)語,在這里,我想用另一個詞來表示 CKB 獨特的可編程性。CKB 中的腳本不一定只是我們在腳本語言中看到的腳本,例如 Ruby,JS,它實際上是指在 CKB-VM 上運行的 RISC-V 格式的二進制文件。
這個系列的第一篇文章將專門介紹 CKB v0.14.0 中引入的全新驗證模型(https://github.com/nervosnetwork/ckb/pull/913)。雖然這聽起來很無聊,但我保證這是最后一篇沒有實際示例的帖子:P
請注意,盡管我認(rèn)為 CKB 的編程模型現(xiàn)在非常穩(wěn)定,但目前仍然在開發(fā)過程中,因此可能會有變化。我會盡力確保更新這篇文章的內(nèi)容,但如果您有感到困惑的話,那是因為這篇文章現(xiàn)在正在描述的是 CKB 的這次提交:
概 述
這張圖中有很多內(nèi)容,我們將在稍后的文章中再次提到此圖。今天,我們將只關(guān)注 Cell 數(shù)據(jù)結(jié)構(gòu)中的 2 個實體:lock 和 type。
pub struct CellOutput {
pub capacity: Capacity,
pub data: Bytes,
pub lock: Script,
#[serde(rename = “type”)]
pub type_: Option《Script》,
}
從數(shù)據(jù)結(jié)構(gòu)中我們可以看到 lock 和 type 共享相同的結(jié)構(gòu),稍后我們可以證明它們也是在同一個環(huán)境中執(zhí)行的,它們之間的差異只是體現(xiàn)在幾個小細(xì)節(jié)中:
· lock 是必選項,而 type 是可選項
· 通常,他們被用于不同的場景
我們首先從 type 腳本開始。
type 腳本
請注意,這里的名字只是一個幸運的意外,它與受歡迎的程語言無關(guān)(https://www.typescriptlang.org/)。
我們仔細(xì)思考一下,其實 CKB(或大多數(shù)基于 UTXO 的區(qū)塊鏈)上的交易只會將一組 Cell(或 UTXO )轉(zhuǎn)換為另一組 Cell。這其中最有趣的是這里的實際轉(zhuǎn)換過程,這也是我們開始設(shè)計 CKB 驗證模型的著手點:我們?nèi)绾螛?gòu)建模型以更好地驗證 Cell 轉(zhuǎn)換?
type 腳本的用武之地就體現(xiàn)在這里:type 腳本用于驗證 Cell 轉(zhuǎn)換階段的某些規(guī)則。這里的一些例子包括:
· 驗證 UDT(用戶自定義的 Token)余額以確保不會無效地發(fā)出新 Token;
· 確保每一個可能發(fā)生變化的 Cell 都擁有一個獨一無二的名字。注意一下,這是非常有趣的一點,未來的文章很多都將和這一話題息息相關(guān),敬請期待。
· 實現(xiàn)經(jīng)濟模型結(jié)構(gòu)。事實上,NervosDAO 完全是作為一個type腳本實現(xiàn)的,而不需要共識層的支持。
· 比特幣的虛擬機可以編譯成基于 RISC-V 的二進制文件,這意味著可以將 CKB 轉(zhuǎn)換成另一種替代比特幣的實現(xiàn)。
· 請記住,除了數(shù)據(jù)之外,Cell 還可以用于存儲代碼,因此type腳本也可以被用作對 Cell 中代碼的測試,確保代碼正確。
簡而言之,type 腳本可以用于存儲 Cell 轉(zhuǎn)換中所需要的任何驗證邏輯,結(jié)合 CKB 靈活的虛擬機,我相信它將能提供無限的開發(fā)潛能。
lock 腳本
type 腳本用于存儲 Cell 的邏輯轉(zhuǎn)換,但是還缺少一件事情:如何保護自己的 Cell 不受其他人的攻擊呢?換句話說,在這個瞬息萬變的世界里,我如何才能確保我的 token 永遠(yuǎn)屬于我呢?
這就是為什么我們需要設(shè)計 lock 腳本的原因。只有當(dāng) lock 腳本能夠成功執(zhí)行時,才可以使用該 Cell。與 type 腳本不同,type 腳本是可選的,用戶可以完全不填,而 lock 腳本總是需要被用于保護 Cell 的安全性。
通常,您會期望一個 lock 腳本包含一個簽名驗證,就像所有其他區(qū)塊鏈所做的那樣,當(dāng)然除此之外,CKB 還將提供一些全新的解鎖用例:
· 實際的簽名算法完全由 lock 腳本來決定,而您可以自由使用任何 lock 腳本。這意味著您可以自由地選擇任何符合您需求的簽名算法。在官方發(fā)行的 CKB 版本中,我們將 secp256k1 作為默認(rèn)的 lock 腳本(https://github.com/nervosnetwork/ckb-system-scripts/blob/66d7da8ec72dffaa7e9c55904833951eca2422a9/c/secp256k1_blake160_sighash_all.c)。但您也可以不必使用它,如果有人用 schnorr 簽名實現(xiàn)了一個 lock 腳本,那么我們非常歡迎您使用這個腳本。
· 除了簽名驗證之外,lock 腳本還可以包含其他用于解鎖 Cell 的規(guī)則。比如,如果一筆交易包含了一個使用了我的 lock 腳本的 Output Cell,但是它的容量大于我可以使用的 Cell,那么我可以通過配置我的 lock 腳本來進行容量傳遞。這樣的話,當(dāng)有人向我發(fā)送 CKB Token 時,他們可以利用我現(xiàn)有的 Cell 來完成 CKB 轉(zhuǎn)賬,而不需要像比特幣那樣為我再重新創(chuàng)建一個新的 Cell。
在我看來,CKB 最好的一點就是,社區(qū)創(chuàng)建的 lock 腳本與官方默認(rèn)腳本的處理方式完全相同,官方腳本沒有任何特權(quán)。與其他一些區(qū)塊鏈項目不同,CKB 為社區(qū)開發(fā) CKB 腳本提供了完全的自由。
運行模型
現(xiàn)在讓我們看看是什么時候執(zhí)行 lock 和 type 腳本的。
回到之前的例子
這是我們之前看到的交易:
圖中的執(zhí)行流程如下:
Lock Script 1 執(zhí)行一次。
Lock Script 2 執(zhí)行一次。
Type Script 1 執(zhí)行一次。
Type Script 2 執(zhí)行一次。
在后面的文章中,我們可以看到 lock 和 type 腳本都在相同的環(huán)境中執(zhí)行,并且都可以訪問整個交易。如果任何一個腳本失敗,整個交易就會失敗。只有當(dāng)所有腳本都成功時,交易才被認(rèn)為是有效的。
有幾點值得一提:
· 盡管這里有 2 個帶有 Lock Script 1 的 Input Cell,但它只執(zhí)行一次,由實際的 lock 腳本來定位具有相同 lock 腳本的所有 Input Cell,并驗證兩個簽名。
· 在這個交易中只執(zhí)行 Input Cell 中的 lock 腳本,例如:這里不執(zhí)行 Lock Script 3。
· 即使 Input Cell 和 Output Cell 都包含 Type Script 1,也只執(zhí)行一次。
· 在 Input 和 Output Cell 中都會執(zhí)行 type 腳本,其中包括 Type Script 1 和 Type Script 2。
· 有些 Cell 沒有 type 腳本,在本例中我們只是省略了執(zhí)行。
規(guī)則
現(xiàn)在我們總結(jié)一下規(guī)則:
· 在 Input Cell 中的 lock 腳本會被收集和去重,每個單獨的 lock 腳本會被執(zhí)行一次,并且只執(zhí)行一次。
· Input 和 Output Cell 中的 type 腳本(如果存在的話)會被收集在一起并去重,每個單獨的 type 腳本都會被執(zhí)行一次,并且只執(zhí)行一次。
· 任何腳本失敗,則整個交易驗證失敗。