摘要:若返回值為表示合約調(diào)用成功,返回值為其它表示合約調(diào)用失敗。舉個例子,我們可以將編譯為二進(jìn)制文件,來啟用基于的合約開發(fā)。共識規(guī)則強(qiáng)制規(guī)定交易中所有的容量總和不能超過所有的容量總和。
Nervos 底層公鏈 CKB 的虛擬機(jī)(CKB-VM)是基于 RISC-V 打造的區(qū)塊鏈虛擬機(jī)。在前三節(jié)課中,我們介紹了 CKB 虛擬機(jī)的設(shè)計理念及優(yōu)勢。那么,怎樣才能利用 CKB-VM 更好的開發(fā)呢?本文是實現(xiàn) CKB 背后腳手架-技術(shù)系列的最后一篇文章,CKB-VM 設(shè)計者肖雪潔會以三種不同的方式展示 CKB-VM 的合約示例,它會幫助你更好的在 CKB-VM 上玩?!?/pre>秘猿科技區(qū)塊鏈小課堂第 24 期
最簡化智能合約示例以下代碼示例為可以在 CKB-VM 上運行的最簡化智能合約:
int main() { return 0; }以下代碼可以通過 GCC 編譯:
riscv64-unknown-elf-gcc main.c -o mainCKB 的智能合約是一個遵循傳統(tǒng) Unix 調(diào)用方式的二進(jìn)制文件??梢酝ㄟ^ argc/argv 輸入?yún)?shù),以 main 函數(shù)的返回值來表示輸出結(jié)果。
若返回值為 0 表示合約調(diào)用成功,返回值為其它表示合約調(diào)用失敗。
為了簡化說明,我們以 C 語言為例來實現(xiàn)示例中的合約。但實際上任何可以編譯成 RISC-V 指令集的語言均可以直接用來開發(fā) CKB 的智能合約:
最新版的 Rust Stable 已經(jīng)有 RISC-V
Go 語言的 RISC-V 支持也在開發(fā)中:
對于更高級的語言,我們可以直接將其 C 語言的實現(xiàn)編譯為 RISC-V 二進(jìn)制文件,并通過 「VM 中的 VM」 技術(shù),在 CKB 上啟用以這些語言編寫的智能合約。舉個例子,我們可以將 mruby 編譯為 RISC-V 二進(jìn)制文件,來啟用基于 Ruby 的合約開發(fā)?;?MicroPython 的 Python 語言或基于 Duktape 的 JavaScript 語言也可以使用同樣的方式,在 CKB 上開發(fā)智能合約。
即使是編譯為 EVM 字節(jié)碼或 Bitcoin 腳本的智能合約也可以編譯為 CKB-VM 字節(jié)碼。當(dāng)然我們可以清晰地看到這些傳統(tǒng)合約遷移到更有效字節(jié)碼上的優(yōu)勢,并且,與使用較低級編程語言實現(xiàn)的智能合約相比,在 CKB 上的這些合約可能具有更大的運行開銷(CPU cycles),但是對于一些不同的應(yīng)用場景來說,這里節(jié)省下來的開發(fā)時間以及安全性優(yōu)勢,可能比在運行開銷更有價值。
CKB 還滿足了哪些需求?除了最簡化的合約之外,CKB 也會提供一個系統(tǒng)庫來滿足如下需求:
支持 libc 核心庫;
支持動態(tài)鏈接,以減少當(dāng)前合約占用的空間,比如可以通過動態(tài)鏈接在 VM 中加載 system Cell 的方式來調(diào)用庫;
讀取交易數(shù)據(jù)后,CKB-VM 中會有類似比特幣的 SIGHASH 功能,以最大限度地提高合約的靈活性。
下圖顯示了基于前面系統(tǒng)庫的 CKB 智能合約驗證模型:
如上圖所示,CKB 的交易由 Input 和 Output 構(gòu)成。雖然交易也可能包含 Deps(包含運行合約時所需的數(shù)據(jù)或代碼的依賴項),但它們僅會影響智能合約的實現(xiàn),并且會從交易模型中刪除。
交易的每個 Input 都會引用一個現(xiàn)有 Cell,一筆交易可以覆蓋、銷毀或生成一個 Cell。共識規(guī)則強(qiáng)制規(guī)定交易中所有 Output Cell 的容量總和不能超過所有 Input Cell 的容量總和。
驗證智能合約的標(biāo)準(zhǔn)CKB-VM 使用以下標(biāo)準(zhǔn)來驗證智能合約:
每個 Input 中都會包含一個解鎖腳本(Unlock Script),用于驗證交易發(fā)起者是否可以使用當(dāng)前 Input 所引用到的 Cell。Unlock Script 中包含由交易發(fā)起者生成的簽名,且 Unlock Script 通常會有指定的簽名算法(如 SIGHASH-ALL-SHA3-SECP256K1)。CKB 會通過 VM 運行 Unlock Script 進(jìn)行驗證:智能合約會通過一個 API 來讀取交易數(shù)據(jù)以實現(xiàn) SIGHASH 相關(guān)的計算,從而提供最大的靈活性。
每個 Cell 中包含一個驗證腳本,用于驗證當(dāng)前 Cell Data 是否滿足先前指定的條件,例如我們可以創(chuàng)建一個 Cell 來保存用戶自定義代幣(User Defined Token,簡稱 UDT)。在 Cell 創(chuàng)建完畢后,我們需要驗證 Input Cell 中所有 Token 總和是否大于或等于 Output Cell 中所有 Token 的總和,以確保交易中不會生成新的 Token。為增強(qiáng)安全性,CKB 的合約開發(fā)人員還可以利用特殊合約來確保創(chuàng)建 Cell 后,Cell 的驗證腳本不會被修改。
Input Cell 驗證示例基于上述對 CKB-VM 安全模型的描述,我們可以首先實現(xiàn)一個完整的 SIGHASH-ALL-SHA3-SECP256K1 合約,來驗證所提供的簽名以及驗證提供簽名的交易發(fā)起者是否可以使用當(dāng)前的 Cell:
// For simplicity, we are keeping pubkey in the contract, however this // solution has a potential problem: even though many contracts might share // the very same structure, keeping pubkey here will make each contract // quite different, preventing common contract sharing. In CKB we will // provide ways to share common contract while still enabling each user // to embed their own pubkey. char* PUBKEY = "this is a pubkey"; int main(int argc, char* argv[]) { // We need 2 arguments for this contract // * The first argument is contract name, this is for compatibility issue // * The second argument is signature for current contract input if (argc < 2) { return -1; } // This function loads current transaction into VM memory, and returns the // pointer to serialized transaction data. Notice ckb_mmap might preprocess // the transaction a bit, such as removing signatures in all tx inputs to // avoid chicken-egg problem when signing signature. int length = 0; char* tx = ckb_mmap(CKB_TX, &length); if (tx == NULL) { return -2; } // This function dynamically links sha3 library to current VM memory space void *sha3_handle = ckb_dlopen("sha3"); void (*sha3_func)(const char*, int, char*) = ckb_dlsym("sha3_256"); // Here we run sha3 on all the transaction data, simulating a SIGHASH_ALL process, // a different contract might choose to deserialize and only hash certain part // of the transaction char hash[32]; sha3_func(tx, length, hash); // Now we load secp256k1 module. void *secp_handle = ckb_dlopen("secp256k1"); int (*secp_verify_func)(const char*, int, const char*, int, const char*, int) = ckb_dlsym("secp256k1_verify"); int result = secp_verify_func(argv[1], strlen(argv[1]), PUBKEY, strlen(PUBKEY), hash, 32); if (result == 1) { // Verification success, we are returning 0 to indicate contract succeeds return 0; } else { // Verification failure return -3; } }在此示例中,我們首先將所有的交易數(shù)據(jù)讀入 CKB-VM 中以獲取交易數(shù)據(jù)的 SHA3 哈希,并將此交易數(shù)據(jù)的 SHA3 哈希、指定的公鑰和交易發(fā)起者提供的簽名提供給 secp256k1 模塊,以驗證合約中指定的公鑰是否已對提供的交易數(shù)據(jù)進(jìn)行了簽名。
如果此驗證成功,則交易發(fā)起者可以使用當(dāng)前 Input 引用的 Cell,合約成功執(zhí)行。 如果此驗證不成功,則合約執(zhí)行和交易驗證會失敗。
用戶自定義代幣(UDT)示例下面的示例中,演示了一個 Cell 驗證腳本實現(xiàn)類似 ERC-20 用戶自定義代幣的過程。Cell 驗證腳本也可以實現(xiàn)其他 UDT 功能,為簡單起見,以下示例中僅包含 UDT 的轉(zhuǎn)移功能:
int main(int argc, char* argv[]) { size_t input_cell_length; void* input_cell_data = ckb_mmap_cell(CKB_CELL_INPUT, 0, &input_cell_length); size_t output_cell_length; void* output_cell_data = ckb_mmap_cell(CKB_CELL_OUTPUT, 0, &output_cell_length); if (input_cell_data == NULL || output_cell_data == NULL) { return -1; } void* udt_handle = ckb_dlopen("udt"); data_t* (*udt_parse)(const char*, size_t) = ckb_dlsym(udt_handle, "udt_parse"); int (*udt_transfer)(data_t *, const char*, const char*, int64_t) = ckb_dlsym(udt_handle, "udt_transfer"); data_t* input_cell = udt_parse(input_cell_data, input_cell_length); data_t* output_cell = udt_parse(output_cell_data, output_cell_length); if (input_cell == NULL || output_cell == NULL) { return -2; } ret = udt_transfer(input_cell, from, to, tokens); if (ret != 0) { return ret; } int (*udt_compare)(const data_t *, const data_t *); if (udt_compare(input_cell, output_cell) != 0) { return -1; } return 0; }在這段代碼中,首先我們通過調(diào)用系統(tǒng)庫讀取了 Input 與 Output Cell 中的內(nèi)容,然后我們動態(tài)加載了 UDT 的實現(xiàn),并使用轉(zhuǎn)移方式對 Input 進(jìn)行轉(zhuǎn)換。
轉(zhuǎn)換后,Input 與 Output Cell 中的內(nèi)容應(yīng)該完全匹配,否則我們得到的驗證結(jié)果會是:當(dāng)前交易不符合驗證腳本中指定的條件,合約執(zhí)行即為失敗。
注意:以上示例僅用于展示 CKB-VM 的功能,并不代表此實現(xiàn)方式為 CKB 上 UDT 實現(xiàn)的最佳實踐。
在 Ruby 中的 Unlock Script 示例雖然上面的示例都是通過 C 語言來編寫的,但是實際上,CKB-VM 上編寫智能合約并不僅限于用 C 語言。例如我們可以將 mruby 這個針對嵌入式平臺的 Ruby 實現(xiàn)編譯為 RISC-V 二進(jìn)制文件,并以它作為通用系統(tǒng)庫,這樣我們就可以使用 Ruby 在 CKB 上編寫智能合約。Unlock Script 示例如下:
if ARGV.length < 2 raise "Not enough arguments!" end tx = CKB.load_tx sha3 = Sha3.new sha3.update(tx["version"].to_s) tx["deps"].each do |dep| sha3.update(dep["hash"]) sha3.update(dep["index"].to_s) end tx["inputs"].each do |input| sha3.update(input["hash"]) sha3.update(input["index"].to_s) sha3.update(input["unlock"]["version"].to_s) # First argument here is signature input["unlock"]["arguments"].drop(1).each do |argument| sha3.update(argument) end end tx["outputs"].each do |output| sha3.update(output["capacity"].to_s) sha3.update(output["lock"]) end hash = sha3.final pubkey = ARGV[0] signature = ARGV[1] unless Secp256k1.verify(pubkey, signature, hash) raise "Signature verification error!" End社區(qū)驅(qū)動的 CKB-VM以上為 CKB-VM 上三種不同方式的智能合約實現(xiàn)示例,它們也許會幫助你更好的在 CKB-VM 上玩耍。通過 CKB-VM 的設(shè)計,我們的目標(biāo)是建立一個圍繞 CKB 的社區(qū),該社區(qū)可以自由地發(fā)展和適應(yīng)新技術(shù)的進(jìn)步,并且可以最大限度地減少人工干預(yù)(例如硬分叉)。 我們相信 CKB-VM 可以實現(xiàn)這一愿景。
注:CKB-VM 與 CKB 一樣為開源項目,目前 CKB-VM 仍在開發(fā)過程中,盡管 CKB-VM 的大部分設(shè)計已經(jīng)敲定,但某些設(shè)計也可能會在將來由于你的加入而有新的進(jìn)步。這篇文章是為了讓我們的社區(qū)更加了解 CKB-VM,這樣人人都可以在里面更好的玩耍并做出貢獻(xiàn)啦!
CKB-VM:https://github.com/nervosnetw...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/24718.html
摘要:模塊鏈的共識配置,該配置會寫入創(chuàng)世塊。主要指責(zé)是記錄和更新本地累計工作量最高的鏈,并維護(hù)鏈上數(shù)據(jù)的索引。消息使用序列化。協(xié)議是節(jié)點之間用來處理廣播和轉(zhuǎn)發(fā)新的交易。 by Nervos CKB Team 在 2017 年底,我們感到心里的一些想法,包括分層的網(wǎng)絡(luò)以及一個作為共同知識庫(Common Knowledge Base)的區(qū)塊鏈,都已經(jīng)成熟。因此 2018 年元旦一過我們就迫不及...
摘要:年,包括分層的網(wǎng)絡(luò)以及一個作為共同知識庫的區(qū)塊鏈,都已經(jīng)成熟。是一個在設(shè)計上非常不同的公有鏈協(xié)議,也是網(wǎng)絡(luò)中的基礎(chǔ)層,是整個加密經(jīng)濟(jì)網(wǎng)絡(luò)的信任引擎。主要指責(zé)是記錄和更新本地累計工作量最高的鏈,并維護(hù)鏈上數(shù)據(jù)的索引。 說到猿起,這些心里的想法能追溯到 2016 年,甚至更早。2017 年,包括分層的網(wǎng)絡(luò)以及一個作為共同知識庫(Common Knowledge Base)的區(qū)塊鏈,都已經(jīng)成...
摘要:目前,比特幣使用的是來進(jìn)行交易簽名,并且在共識協(xié)議中使用了哈希算法。盡管的實現(xiàn)提供的是最流行的加密算法,但我們鼓勵社區(qū)提供更優(yōu)化的加密算法實現(xiàn)以減少運行時開銷。 Nervos 底層公鏈 CKB 的虛擬機(jī)(CKB-VM)是基于 RISC-V 指令集打造的區(qū)塊鏈虛擬機(jī)。在上一堂分享中,我們簡單介紹了區(qū)塊鏈虛擬機(jī),以及我們理想中的區(qū)塊鏈虛擬機(jī)的樣子。在本篇文章中,CKB-VM 設(shè)計者將詳細(xì)的...
摘要:在區(qū)塊鏈上,虛擬機(jī)就是智能合約的運行環(huán)境,是一個可以完全對外隔離的完整計算機(jī)體系。區(qū)塊鏈通過虛擬機(jī)來調(diào)用和執(zhí)行智能合約,并要求所有節(jié)點都達(dá)成一致。 秘猿科技使命是用技術(shù)創(chuàng)造信任,為價值網(wǎng)絡(luò)提供基礎(chǔ)設(shè)施和服務(wù)。為了實現(xiàn)這個使命,我們?nèi)陙韴猿殖跣模讲綖闋I打造加密經(jīng)濟(jì)網(wǎng)絡(luò)。我們想要讓互聯(lián)網(wǎng)回歸到本源,用區(qū)塊鏈技術(shù),去構(gòu)造更美好的社會,因此我們設(shè)計了 CKB 底層公鏈。我們自己造輪子,開創(chuàng)...
摘要:在區(qū)塊鏈上,虛擬機(jī)就是智能合約的運行環(huán)境,是一個可以完全對外隔離的完整計算機(jī)體系。區(qū)塊鏈通過虛擬機(jī)來調(diào)用和執(zhí)行智能合約,并要求所有節(jié)點都達(dá)成一致。當(dāng)區(qū)塊鏈遇見在很多科技領(lǐng)域都得到了運用,目前,也開始在區(qū)塊鏈領(lǐng)域逐漸的得以發(fā)展。 showImg(https://segmentfault.com/img/bVbsfi2?w=2779&h=1179); 區(qū)塊鏈的出現(xiàn)使得智能合約得到了更好的實...
閱讀 725·2021-11-16 11:44
閱讀 3554·2019-08-26 12:13
閱讀 3248·2019-08-26 10:46
閱讀 2365·2019-08-23 12:37
閱讀 1194·2019-08-22 18:30
閱讀 2539·2019-08-22 17:30
閱讀 1847·2019-08-22 17:26
閱讀 2298·2019-08-22 16:20