摘要:若返回值為表示合約調(diào)用成功,返回值為其它表示合約調(diào)用失敗。舉個(gè)例子,我們可以將編譯為二進(jìn)制文件,來(lái)啟用基于的合約開(kāi)發(fā)。共識(shí)規(guī)則強(qiáng)制規(guī)定交易中所有的容量總和不能超過(guò)所有的容量總和。
Nervos 底層公鏈 CKB 的虛擬機(jī)(CKB-VM)是基于 RISC-V 打造的區(qū)塊鏈虛擬機(jī)。在前三節(jié)課中,我們介紹了 CKB 虛擬機(jī)的設(shè)計(jì)理念及優(yōu)勢(shì)。那么,怎樣才能利用 CKB-VM 更好的開(kāi)發(fā)呢?本文是實(shí)現(xiàn) CKB 背后腳手架-技術(shù)系列的最后一篇文章,CKB-VM 設(shè)計(jì)者肖雪潔會(huì)以三種不同的方式展示 CKB-VM 的合約示例,它會(huì)幫助你更好的在 CKB-VM 上玩耍~
秘猿科技區(qū)塊鏈小課堂第 24 期
以下代碼示例為可以在 CKB-VM 上運(yùn)行的最簡(jiǎn)化智能合約:
int main() { return 0; }
以下代碼可以通過(guò) GCC 編譯:
riscv64-unknown-elf-gcc main.c -o main
CKB 的智能合約是一個(gè)遵循傳統(tǒng) Unix 調(diào)用方式的二進(jìn)制文件。可以通過(guò) argc/argv 輸入?yún)?shù),以 main 函數(shù)的返回值來(lái)表示輸出結(jié)果。
若返回值為 0 表示合約調(diào)用成功,返回值為其它表示合約調(diào)用失敗。
為了簡(jiǎn)化說(shuō)明,我們以 C 語(yǔ)言為例來(lái)實(shí)現(xiàn)示例中的合約。但實(shí)際上任何可以編譯成 RISC-V 指令集的語(yǔ)言均可以直接用來(lái)開(kāi)發(fā) CKB 的智能合約:
最新版的 Rust Stable 已經(jīng)有 RISC-V
Go 語(yǔ)言的 RISC-V 支持也在開(kāi)發(fā)中:
對(duì)于更高級(jí)的語(yǔ)言,我們可以直接將其 C 語(yǔ)言的實(shí)現(xiàn)編譯為 RISC-V 二進(jìn)制文件,并通過(guò) 「VM 中的 VM」 技術(shù),在 CKB 上啟用以這些語(yǔ)言編寫的智能合約。舉個(gè)例子,我們可以將 mruby 編譯為 RISC-V 二進(jìn)制文件,來(lái)啟用基于 Ruby 的合約開(kāi)發(fā)。基于 MicroPython 的 Python 語(yǔ)言或基于 Duktape 的 JavaScript 語(yǔ)言也可以使用同樣的方式,在 CKB 上開(kāi)發(fā)智能合約。
即使是編譯為 EVM 字節(jié)碼或 Bitcoin 腳本的智能合約也可以編譯為 CKB-VM 字節(jié)碼。當(dāng)然我們可以清晰地看到這些傳統(tǒng)合約遷移到更有效字節(jié)碼上的優(yōu)勢(shì),并且,與使用較低級(jí)編程語(yǔ)言實(shí)現(xiàn)的智能合約相比,在 CKB 上的這些合約可能具有更大的運(yùn)行開(kāi)銷(CPU cycles),但是對(duì)于一些不同的應(yīng)用場(chǎng)景來(lái)說(shuō),這里節(jié)省下來(lái)的開(kāi)發(fā)時(shí)間以及安全性優(yōu)勢(shì),可能比在運(yùn)行開(kāi)銷更有價(jià)值。
CKB 還滿足了哪些需求?除了最簡(jiǎn)化的合約之外,CKB 也會(huì)提供一個(gè)系統(tǒng)庫(kù)來(lái)滿足如下需求:
支持 libc 核心庫(kù);
支持動(dòng)態(tài)鏈接,以減少當(dāng)前合約占用的空間,比如可以通過(guò)動(dòng)態(tài)鏈接在 VM 中加載 system Cell 的方式來(lái)調(diào)用庫(kù);
讀取交易數(shù)據(jù)后,CKB-VM 中會(huì)有類似比特幣的 SIGHASH 功能,以最大限度地提高合約的靈活性。
下圖顯示了基于前面系統(tǒng)庫(kù)的 CKB 智能合約驗(yàn)證模型:
如上圖所示,CKB 的交易由 Input 和 Output 構(gòu)成。雖然交易也可能包含 Deps(包含運(yùn)行合約時(shí)所需的數(shù)據(jù)或代碼的依賴項(xiàng)),但它們僅會(huì)影響智能合約的實(shí)現(xiàn),并且會(huì)從交易模型中刪除。
交易的每個(gè) Input 都會(huì)引用一個(gè)現(xiàn)有 Cell,一筆交易可以覆蓋、銷毀或生成一個(gè) Cell。共識(shí)規(guī)則強(qiáng)制規(guī)定交易中所有 Output Cell 的容量總和不能超過(guò)所有 Input Cell 的容量總和。
驗(yàn)證智能合約的標(biāo)準(zhǔn)CKB-VM 使用以下標(biāo)準(zhǔn)來(lái)驗(yàn)證智能合約:
每個(gè) Input 中都會(huì)包含一個(gè)解鎖腳本(Unlock Script),用于驗(yàn)證交易發(fā)起者是否可以使用當(dāng)前 Input 所引用到的 Cell。Unlock Script 中包含由交易發(fā)起者生成的簽名,且 Unlock Script 通常會(huì)有指定的簽名算法(如 SIGHASH-ALL-SHA3-SECP256K1)。CKB 會(huì)通過(guò) VM 運(yùn)行 Unlock Script 進(jìn)行驗(yàn)證:智能合約會(huì)通過(guò)一個(gè) API 來(lái)讀取交易數(shù)據(jù)以實(shí)現(xiàn) SIGHASH 相關(guān)的計(jì)算,從而提供最大的靈活性。
每個(gè) Cell 中包含一個(gè)驗(yàn)證腳本,用于驗(yàn)證當(dāng)前 Cell Data 是否滿足先前指定的條件,例如我們可以創(chuàng)建一個(gè) Cell 來(lái)保存用戶自定義代幣(User Defined Token,簡(jiǎn)稱 UDT)。在 Cell 創(chuàng)建完畢后,我們需要驗(yàn)證 Input Cell 中所有 Token 總和是否大于或等于 Output Cell 中所有 Token 的總和,以確保交易中不會(huì)生成新的 Token。為增強(qiáng)安全性,CKB 的合約開(kāi)發(fā)人員還可以利用特殊合約來(lái)確保創(chuàng)建 Cell 后,Cell 的驗(yàn)證腳本不會(huì)被修改。
Input Cell 驗(yàn)證示例基于上述對(duì) CKB-VM 安全模型的描述,我們可以首先實(shí)現(xiàn)一個(gè)完整的 SIGHASH-ALL-SHA3-SECP256K1 合約,來(lái)驗(yàn)證所提供的簽名以及驗(yàn)證提供簽名的交易發(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 模塊,以驗(yàn)證合約中指定的公鑰是否已對(duì)提供的交易數(shù)據(jù)進(jìn)行了簽名。
如果此驗(yàn)證成功,則交易發(fā)起者可以使用當(dāng)前 Input 引用的 Cell,合約成功執(zhí)行。 如果此驗(yàn)證不成功,則合約執(zhí)行和交易驗(yàn)證會(huì)失敗。
用戶自定義代幣(UDT)示例下面的示例中,演示了一個(gè) Cell 驗(yàn)證腳本實(shí)現(xiàn)類似 ERC-20 用戶自定義代幣的過(guò)程。Cell 驗(yàn)證腳本也可以實(shí)現(xiàn)其他 UDT 功能,為簡(jiǎn)單起見(jiàn),以下示例中僅包含 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; }
在這段代碼中,首先我們通過(guò)調(diào)用系統(tǒng)庫(kù)讀取了 Input 與 Output Cell 中的內(nèi)容,然后我們動(dòng)態(tài)加載了 UDT 的實(shí)現(xiàn),并使用轉(zhuǎn)移方式對(duì) Input 進(jìn)行轉(zhuǎn)換。
轉(zhuǎn)換后,Input 與 Output Cell 中的內(nèi)容應(yīng)該完全匹配,否則我們得到的驗(yàn)證結(jié)果會(huì)是:當(dāng)前交易不符合驗(yàn)證腳本中指定的條件,合約執(zhí)行即為失敗。
注意:以上示例僅用于展示 CKB-VM 的功能,并不代表此實(shí)現(xiàn)方式為 CKB 上 UDT 實(shí)現(xiàn)的最佳實(shí)踐。
在 Ruby 中的 Unlock Script 示例雖然上面的示例都是通過(guò) C 語(yǔ)言來(lái)編寫的,但是實(shí)際上,CKB-VM 上編寫智能合約并不僅限于用 C 語(yǔ)言。例如我們可以將 mruby 這個(gè)針對(duì)嵌入式平臺(tái)的 Ruby 實(shí)現(xiàn)編譯為 RISC-V 二進(jìn)制文件,并以它作為通用系統(tǒng)庫(kù),這樣我們就可以使用 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ū)動(dòng)的 CKB-VM
以上為 CKB-VM 上三種不同方式的智能合約實(shí)現(xiàn)示例,它們也許會(huì)幫助你更好的在 CKB-VM 上玩耍。通過(guò) CKB-VM 的設(shè)計(jì),我們的目標(biāo)是建立一個(gè)圍繞 CKB 的社區(qū),該社區(qū)可以自由地發(fā)展和適應(yīng)新技術(shù)的進(jìn)步,并且可以最大限度地減少人工干預(yù)(例如硬分叉)。 我們相信 CKB-VM 可以實(shí)現(xiàn)這一愿景。
注:CKB-VM 與 CKB 一樣為開(kāi)源項(xiàng)目,目前 CKB-VM 仍在開(kāi)發(fā)過(guò)程中,盡管 CKB-VM 的大部分設(shè)計(jì)已經(jīng)敲定,但某些設(shè)計(jì)也可能會(huì)在將來(lái)由于你的加入而有新的進(jìn)步。這篇文章是為了讓我們的社區(qū)更加了解 CKB-VM,這樣人人都可以在里面更好的玩耍并做出貢獻(xiàn)啦!
CKB-VM:https://github.com/nervosnetw...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/24718.html
摘要:模塊鏈的共識(shí)配置,該配置會(huì)寫入創(chuàng)世塊。主要指責(zé)是記錄和更新本地累計(jì)工作量最高的鏈,并維護(hù)鏈上數(shù)據(jù)的索引。消息使用序列化。協(xié)議是節(jié)點(diǎn)之間用來(lái)處理廣播和轉(zhuǎn)發(fā)新的交易。 by Nervos CKB Team 在 2017 年底,我們感到心里的一些想法,包括分層的網(wǎng)絡(luò)以及一個(gè)作為共同知識(shí)庫(kù)(Common Knowledge Base)的區(qū)塊鏈,都已經(jīng)成熟。因此 2018 年元旦一過(guò)我們就迫不及...
摘要:年,包括分層的網(wǎng)絡(luò)以及一個(gè)作為共同知識(shí)庫(kù)的區(qū)塊鏈,都已經(jīng)成熟。是一個(gè)在設(shè)計(jì)上非常不同的公有鏈協(xié)議,也是網(wǎng)絡(luò)中的基礎(chǔ)層,是整個(gè)加密經(jīng)濟(jì)網(wǎng)絡(luò)的信任引擎。主要指責(zé)是記錄和更新本地累計(jì)工作量最高的鏈,并維護(hù)鏈上數(shù)據(jù)的索引。 說(shuō)到猿起,這些心里的想法能追溯到 2016 年,甚至更早。2017 年,包括分層的網(wǎng)絡(luò)以及一個(gè)作為共同知識(shí)庫(kù)(Common Knowledge Base)的區(qū)塊鏈,都已經(jīng)成...
摘要:目前,比特幣使用的是來(lái)進(jìn)行交易簽名,并且在共識(shí)協(xié)議中使用了哈希算法。盡管的實(shí)現(xiàn)提供的是最流行的加密算法,但我們鼓勵(lì)社區(qū)提供更優(yōu)化的加密算法實(shí)現(xiàn)以減少運(yùn)行時(shí)開(kāi)銷。 Nervos 底層公鏈 CKB 的虛擬機(jī)(CKB-VM)是基于 RISC-V 指令集打造的區(qū)塊鏈虛擬機(jī)。在上一堂分享中,我們簡(jiǎn)單介紹了區(qū)塊鏈虛擬機(jī),以及我們理想中的區(qū)塊鏈虛擬機(jī)的樣子。在本篇文章中,CKB-VM 設(shè)計(jì)者將詳細(xì)的...
摘要:在區(qū)塊鏈上,虛擬機(jī)就是智能合約的運(yùn)行環(huán)境,是一個(gè)可以完全對(duì)外隔離的完整計(jì)算機(jī)體系。區(qū)塊鏈通過(guò)虛擬機(jī)來(lái)調(diào)用和執(zhí)行智能合約,并要求所有節(jié)點(diǎn)都達(dá)成一致。 秘猿科技使命是用技術(shù)創(chuàng)造信任,為價(jià)值網(wǎng)絡(luò)提供基礎(chǔ)設(shè)施和服務(wù)。為了實(shí)現(xiàn)這個(gè)使命,我們?nèi)陙?lái)堅(jiān)持初心,步步為營(yíng)打造加密經(jīng)濟(jì)網(wǎng)絡(luò)。我們想要讓互聯(lián)網(wǎng)回歸到本源,用區(qū)塊鏈技術(shù),去構(gòu)造更美好的社會(huì),因此我們?cè)O(shè)計(jì)了 CKB 底層公鏈。我們自己造輪子,開(kāi)創(chuàng)...
摘要:在區(qū)塊鏈上,虛擬機(jī)就是智能合約的運(yùn)行環(huán)境,是一個(gè)可以完全對(duì)外隔離的完整計(jì)算機(jī)體系。區(qū)塊鏈通過(guò)虛擬機(jī)來(lái)調(diào)用和執(zhí)行智能合約,并要求所有節(jié)點(diǎn)都達(dá)成一致。當(dāng)區(qū)塊鏈遇見(jiàn)在很多科技領(lǐng)域都得到了運(yùn)用,目前,也開(kāi)始在區(qū)塊鏈領(lǐng)域逐漸的得以發(fā)展。 showImg(https://segmentfault.com/img/bVbsfi2?w=2779&h=1179); 區(qū)塊鏈的出現(xiàn)使得智能合約得到了更好的實(shí)...
閱讀 711·2021-11-16 11:44
閱讀 3540·2019-08-26 12:13
閱讀 3236·2019-08-26 10:46
閱讀 2352·2019-08-23 12:37
閱讀 1180·2019-08-22 18:30
閱讀 2526·2019-08-22 17:30
閱讀 1834·2019-08-22 17:26
閱讀 2284·2019-08-22 16:20