中移鏈合約常用開發介紹 (一)開發基本流程
本文件從 C++ 及智慧合約基本概念出發再到實戰執行智慧合約,介紹了中移鏈合約開發的基本流程,同時對常見問題做出梳理。本文件將以
hello
合約作為示例介紹智慧合約如何在鏈上工作,適合剛接觸合約開發的開發人員用來了解 EOS 智慧合約如何編寫、編譯、部署、動作呼叫以及管理授權,幫助其快速瞭解以及上手智慧合約。
二、智慧合約介紹
區塊鏈作為一種分散式可信計算平臺,去中心化是其最本質的特徵。每筆交易的記錄不可篡改地儲存在區塊鏈上。智慧合約中定義可以在區塊鏈上執行的動作
action
和交易
transaction
的程式碼。可以在區塊鏈上執行,並將合約執行狀態作為該區塊鏈例項不可變歷史的一部分。
三、術語解釋
EOSIO.CDT(合約開發工具包)
EOSIO.CDT是WebAssembly(WASM)的工具鏈,也是用於促進EOSIO平臺智慧合約開發的一組工具。使用C++程式語言建立EOSIO智慧合約。EOSIO.CDT提供構建智慧合約所需的庫和工具。
WebAssembly(WASM)
用於執行可移植二進位制程式碼格式的虛擬機器,託管在nodeos中。
應用程式二進位制介面(ABI)
定義如何將資料編組進出WebAssembly虛擬機器的介面。
動作(Action)
智慧合約公開的功能,透過批准的交易將正確的引數傳遞給 EOSIO 網路來執行。
李嘉圖合約(Ricardian Contract)
在基於EOSIO的區塊鏈環境中,李嘉圖合約是一個伴隨智慧合約的數字文件,定義了智慧合約與其使用者之間互動的條款和條件,以人類可讀的文字編寫,然後對其進行加密簽署和驗證。對於人和程式來說,它都很容易閱讀,並有助於為智慧合約和其使用者之間的互動中可能出現的任何情況提供清晰的理解。
四、開發流程
(一)知識和環境準備
1、瞭解 C++ 語言
EOSIO 的智慧合約都由 C++ 程式碼編寫,因此,您應當具有一定的 C++ 程式設計能力。不過,智慧合約對 C++ 的使用並不會過於複雜。 C++ 是一種靜態型別的、編譯式的程式語言,支援過程化程式設計、物件導向程式設計和泛型程式設計。因此, C++ 是在編譯時執行型別檢查,而不是在執行時執行型別檢查。您所編寫的
.cpp
檔案只有在透過編譯後,才能嘗試執行。
2、程式碼編輯器或 IDE
任何支援C++的IDE都可以用於編寫智慧合約,本文中智慧合約的編譯和部署都將在終端命令中進行。因此您使用的編輯器甚至可以不具備編譯C++程式碼的功能。若僅用於編寫程式碼,
.txt
文字檔案就可以勝任。但為了方便編寫和檢查,還是建議使用例如VSCode的常規IDE,或智慧合約開發IDE,EOS Stuido。
3、完全配置的本地開發環境
具體可參考
(二)編寫合約
1、建立檔案
建立智慧合約的過程中,通常會建立兩個檔案,分別是包含智慧合約類宣告的標頭檔案.
hpp
,以及包含智慧合約操作實現的檔案
.cpp
。如果程式碼內容十分簡單時,也可以直接在一個
.cpp
檔案中編寫宣告和實現。此處我們僅用一個
.cpp
檔案來展示
hello
樣例。但往後的程式都應採用規範的宣告實現分離寫法。
建立一個名為
hello
的新資料夾來儲存您的智慧合約檔案,並進入目錄:
mkdir hello
cd hello
建立新檔案
hello.cpp
:
touch hello.cpp
使用您的文字編輯器開啟它後,可以開始編寫智慧合約程式碼。
2、編寫程式碼
編寫智慧合約程式碼,主要包括以下四個步驟:
(1)使用
include
匯入 EOSIO 基礎庫
#include <eosio/eosio.hpp>
eosio.hpp
中包含編寫一個智慧合約所需要的基礎類,例如
eosio::contract
。
(2)建立一個類,並使它繼承
eosio::contract
使用
[[eosio::contract]]
屬性通知EOSIO.CDT這是一個智慧合約。
新增一行程式碼:
class [[eosio::contract]] hello : public eosio::contract {};
這表明
hello
作為一個智慧合約,公有的繼承了
eosio::contract
型別。
(3)新增公共訪問說明符和使用宣告
在
C++
的類中,可以宣告公有、私有、保護三種型別的類成員和類成員函式。其中,建構函式是在類被建立時需要執行的類成員函式。我們建立的
hello
類作為
eosio::contract
的派生類(子類),可以繼承基類(父類)的介面和實現。
使用
using
新增一行程式碼表示宣告瞭
eosio::contract
的預設基類建構函式:
public:
using eosio::contract::contract;
(4)新增動作
hi
使用
[[eosio::action]]
通知 EOSIO.CDT 這是一個合約動作。
新增以下程式碼:
[[ eosio::action]] void hi( eosio::name user){
print( "Hello, ", user);
}
在EOSIO中,智慧合約的動作
action
就類似於C++中的類成員函式。此處新增的
hi
動作功能為:接收一個型別為
eosio::name
的引數,列印與該引數打招呼的資訊。其中
eosio::print
是包含在
eosio/eosio.hpp
中的函式,可以直接使用。
(5)儲存檔案
現在,
hello.cpp
檔案應該如下所示:
#include <eosio/eosio.hpp>
class [[ eosio::contract]] hello : public eosio::contract {
public:
using eosio::contract::contract;
[[ eosio::action]] void hi( eosio::name user ) {
print( "Hello, ", user);
}
};
(三)編譯並部署合約
成功建立智慧合約後,要對合約進行編譯和部署。
1、編譯
使用
eosio-cpp
命令編譯
hello.cpp
檔案
要將智慧合約部署到區塊鏈上,首先使用
eosio-cpp
工具編譯智慧合約。編譯構建一個 WebAssembly 檔案
.wasm
和一個相應的應用程式二進位制介面檔案
.abi
。
WebAssenbly 並不是一種程式語言,而是一種編譯器的編譯目標,可以把
.wasm
檔案當成是
.cpp
檔案透過編譯以後生成的檔案。
.wasm
檔案是區塊鏈中的 WebAssembly 引擎執行的二進位制程式碼。WebAssembly 引擎託管在 nodeos 守護程式中並執行智慧合約程式碼。
.abi
檔案定義了資料如何編組進出 WASM 引擎。
在與合約程式相同的資料夾中執行以下命令,或在其他位置使用絕對或相對路徑來引用該檔案:
eosio-cpp -abigen -o hello.wasm hello.cpp
此時資料夾中建立了兩個新檔案:
hello.wasm
和
hello.abi
。
2、部署
將
hello
合約部署到同名賬戶
使用以下命令將編譯好的
hello.wasm
和
hello.abi
檔案部署到區塊鏈上的hello賬戶:
cleos set contract hello ./hello -p hello@active
cleos set contract
命令後必須跟隨部署合約的賬戶名,此處為同名賬戶
hello
。
如果您沒有hello賬戶,請參考
中的
(六)建立開發賬戶
執行此步驟前,請確保您的賬戶中有處於解鎖狀態的錢包。cleos會尋找一個解鎖狀態的錢包以獲取您使用的許可權的私鑰。在本例中,使用的許可權為
-p hello@active
,即hello賬戶的active許可權。
成功部署後,會得到類似下圖的返回資訊:
Reading WASM from ./hello/hello.wasm...
Skipping set abi because the new abi is the same as the existing abi
Publishing contract...
executed transaction: 5f49530dcef3221d51f3160deb3f9ba0911cc6b93b2ce0a6560dff271178f13b 14288 bytes 23172 us
# eosio <= eosio::setcode "00000000001aa36a0000ab8c020061736d0100000001d4012260000060037f7f7f017f60037f7e7f017e60047f7f7f7f006...
(四)呼叫動作
使用
cleos push action
命令,用已有賬戶呼叫
hello
合約中的
hi
動作:
cleos push action hello hi '["bob"]' -p bob@active
應該產生:
executed transaction: 5be02a763ba87db15a22ae2135e7fc6ec5b0ee8fed3a9a012f65f5ebde706b3e 104 bytes 2459 us
# hello <= hello::hi {"user":"bob"}
>> Hello, bob
可以看到,該合約能夠允許任何賬戶向任何使用者打招呼。例如,將賬戶更換為alice後:
cleos push action hello hi '["bob"]' -p alice@active
產生結果如下,依舊可以實現對bob的動作:
executed transaction: bfb8787117257f8e7d3f659509678f24a7bdb040a6b1a846fa090d428bc06540 104 bytes 271 us
# hello <= hello::hi {"user":"bob"}
>> Hello, bob
(五)動作的授權
EOSIO 區塊鏈使用非對稱密碼學來驗證推送交易的賬戶是否已使用匹配的私鑰簽署了交易。使用賬戶許可權表來檢查賬戶是否具有執行操作所需的許可權。使用授權是保護智慧合約的第一步。
本文件提供了四種方式在合約程式碼中進行授權檢查。
1、has_auth(name n) 函式
驗證指定賬戶是否與呼叫動作的賬戶相符,返回
bool
值。
以
hi
動作為例,如果我們希望動作只能向呼叫賬戶進行問好,而不相符的賬戶名進行訊息提示,可以將動作部分的程式碼做如下調整:
[[ eosio::action]] void hi( eosio::name user ) {
if( has_auth( user )){
print( "Hello, ", eosio::name{ user} );
} else{
print( "This is not ", eosio::name{ user} );
}
}
重新編譯並部署合約:
eosio-cpp -abigen -o hello.wasm hello.cpp
cleos set contract hello /home/xxx/biosboot/genesis/hello -p hello@active
使用alice賬戶對bob賬戶和alice賬戶分別呼叫
hi
動作。結果分別如下:
cleos push action hello hi '["bob"]' -p alice@active
executed transaction: 20a297df95fe19840893305a8f18e6380ee3482a3773885224f6381487559105 104 bytes 601 us
# hello <= hello::hi {"user":"bob"}
>> This is not bob
cleos push action hello hi '["alice"]' -p alice@active
executed transaction: 3f12347d3458204be643a2c4cef5ef3542994ed3bb320466aac423e1a983e8d7 104 bytes 204 us
# hello <= hello::hi {"user":"alice"}
>> Hello, alice
2、require_auth(name n) 函式
驗證指定賬戶是否與呼叫動作的賬戶相符,不相符則直接報錯失敗。
與
has_auth
函式不同,此函式會在驗證失敗時直接停止執行。同樣以
hi
動作為例,如果我們希望動作只能向呼叫賬戶進行問好,而對不相符的賬戶直接顯示失敗,可以將動作部分的程式碼做如下調整:
[[ eosio::action]] void hi( eosio::name user ) {
require_auth( user );
print( "Hello, ", eosio::name{ user} );
}
重新編譯並部署合約:
eosio-cpp -abigen -o hello.wasm hello.cpp
cleos set contract hello /home/xxx/biosboot/genesis/hello -p hello@active
使用alice賬戶對bob賬戶和alice賬戶分別呼叫
hi
動作。結果分別如下:
cleos push action hello hi '["bob"]' -p alice@active
Error 3090004: Missing required authority
Ensure that you have the related authority inside your transaction!;
If you are currently using 'cleos push action' command, try to add the relevant authority using -p option.
Error Details:
missing authority of bob
pending console output:
cleos push action hello hi '["alice"]' -p alice@active
executed transaction: 495b0e8d6fa3610f5b91ffd28eb4013d1a53a1e1e13046b6a3069566bfeaf65f 104 bytes 168 us
# hello <= hello::hi {"user":"alice"}
>> Hello, alice
3、require_auth2(capi_name name, capi_name permission) 函式
驗證指定賬戶和許可權是否與呼叫動作的賬戶和許可權相符,不相符則直接報錯失敗。
此函式比之前增加了對賬戶許可權的限制。同樣以
hi
動作為例,如果我們希望動作只能由賬戶的
active
許可權進行呼叫,而對不相符的賬戶直接顯示失敗,可以將動作部分的程式碼做如下調整:
[[ eosio::action]] void hi( eosio::name user ) {
require_auth2( user. value, "active" _n. value);
print( "Hello, ", eosio::name{ user} );
}
重新編譯並部署合約:
eosio-cpp -abigen -o hello.wasm hello.cpp
cleos set contract hello /home/xxx/biosboot/genesis/hello -p hello@active
使用alice賬戶的family和active許可權分別對alice賬戶呼叫
hi
動作。結果分別如下:
cleos push action hello hi '["alice"]' -p alice@family
Error 3090003: Provided keys, permissions, and delays do not satisfy declared authorizations
Ensure that you have the related private keys inside your wallet and your wallet is unlocked.
Error Details:
transaction declares authority '{"actor":"alice","permission":"family"}', but does not have signatures for it.
cleos push action hello hi '["alice"]' -p alice@active
executed transaction: 055228767c6f23c283 910ebc348d8a76d444fa1165454c9886dd58b940023ef5 104 bytes 395 us
# hello <= hello::hi {"user":"alice"}
>> Hello, alice
4、check(bool pred, ...) 函式
斷言,如果
pred
為假,則使用提供的訊息進行反饋。例如:
eosio::check(a == b, "a does not equal b");
因此,之前我們實現的在引數與賬戶不相符時列印錯誤資訊的程式碼可以最佳化為:
[[ eosio::action]] void hi( eosio::name user ) {
eosio::check( has_auth( user), "User is not authorized to perform this action.");
print( "Hello, ", eosio::name{ user} );
}
重新編譯並部署合約:
eosio-cpp -abigen -o hello.wasm hello.cpp
cleos set contract hello /home/xxx/biosboot/genesis/hello -p hello@active
使用alice賬戶對bob賬戶和alice賬戶分別呼叫
hi
動作。結果分別如下:
cleos push action hello hi '["bob"]' -p alice@active
Error 3050003: eosio_assert_message assertion failure
Error Details:
assertion failure with message: User is not authorized to perform this action.
pending console output:
cleos push action hello hi '["alice"]' -p alice@active
executed transaction: 86887c76f45d9c0f9abc017f2cfc49132bd5d0c1d6bbd7f41aeb7bc1675ab42c 104 bytes 172 us
# hello <= hello::hi {"user":"alice"}
>> Hello, alice
關於上鍊
在之後的程式碼實踐中,開發人員可以透過以上這四種授權檢查程式碼的搭配來實現合約中動作的授權管理。
對於觸發Error導致方法執行中斷的情況,交易記錄不會上鍊。只有當交易ID產生,動作正常執行完成,此次記錄才會記錄在鏈上。
對於上文的舉例來說,第一種程式碼的錯誤案例完成了上鍊。因為交易正常結束,並列印出了錯誤資訊。而後面三種分別觸發了
Error 3090003
、
Error 3090004
、
Error 3050003
,導致動作中斷,資料不會上鍊。
五、常見問題
(一)部署合約時遇到錯誤
<3>error 2022 -08-08T08:44:27.913 cleos main.cpp:4371 operator() ] Failed with error: unspecified (0)
Unable to resolve path './hello'
遇到
Unable to resolve path
錯誤,可以將合約地址改為絕對路徑,避免因相對路徑產生的報錯。
(二)require_auth2編譯錯誤
/home/xxx/biosboot/genesis/hello/hello.cpp:6:10: error: use of undeclared identifier 'require_auth2'; did you mean 'eosio::internal_use_do_not_use::require_auth2'?
require_auth2(user.value, "active"_n.value);
^~~~~~~~~~~~~
eosio::internal_use_do_not_use::require_auth2
常規情況中可依據報錯提示資訊將
require_auth2
補充為
eosio::internal_use_do_not_use::require_auth2
解決。但本例中該字首已經表明這是一個不推薦使用的方法。
故推薦的解決方法為引入
action
標頭檔案。
#include <../capi/eosio/action.h>
(三)編譯警告:缺少李嘉圖合約
合約編譯後會遇到警告,不會影響到合約部署後的正常執行。
警告資訊如下:
Warning, empty ricardian clause file
Warning, action <hi> does not have a ricardian contract
此警告說明合約中的動作不具備李嘉圖合約。
從 EOSIO.CDT v1.4.0 開始,ABI 生成器將嘗試自動將合約和條款匯入到生成的 ABI 中。對此有一些警告,包括檔案的嚴格命名策略和用於標記每個李嘉圖合約和每個條款的 HTML 標記。
李嘉圖合約應該存放在一個名為
.contracts.md
的檔案中,條款名為
.clauses.md
,在同一資料夾中。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70012206/viewspace-2928352/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 中移鏈合約常用開發介紹(三)工程化開發智慧合約
- 中移鏈合約常用開發介紹(四)工程樹目錄
- 中移鏈合約常用開發介紹 (二)多索引表的使用索引
- 關於馬蹄鏈智慧合約DAPP系統開發方案流程詳情介紹APP
- 智慧合約系統開發原理介紹丨智慧合約開發原始碼詳情原始碼
- 中移鏈系統合約管控功能介紹
- DAPP鏈上合約互助模式系統開發詳情介紹APP模式
- matic馬蹄鏈智慧合約dapp系統開發搭建介紹APP
- DAPP開發流程 | DAPP智慧合約開發APP
- 區塊鏈智慧合約開發區塊鏈
- 智慧合約鏈遊開發詳情丨智慧合約鏈遊系統開發(開發方案)及原始碼分析原始碼
- polygon鏈(matic)矩陣公排智慧合約系統開發詳細介紹Go矩陣
- 關於DAPP馬蹄鏈合約模式系統開發詳情介紹APP模式
- NFT鏈上鑄造交易智慧合約模式系統開發詳情介紹模式
- CeresDAO智慧合約模式系統開發技術介紹模式
- FDF互助遊戲智慧合約開發(馬蹄鏈開發)遊戲
- 新泰山眾籌sun4.0dapp系統開發合約部署流程介紹APP
- matic馬蹄鏈合約DAPP技術開發/區塊鏈專案系統開發Demo流程APP區塊鏈
- PG盤古OSK挖礦dapp系統開發智慧合約開發介紹APP
- 關於DAPP馬蹄鏈合約系統開發詳情技術介紹APP
- Dapp智慧合約遊戲鏈遊開發丨智慧合約遊戲鏈遊系統開發案例版APP遊戲
- 開發NEO智慧合約的工作流程
- 智慧合約DApp專案開發流程APP
- 區塊鏈DApp開發 | 跨鏈智慧合約技術搭建開發區塊鏈APP
- 合約跟單開發案例,合約量化跟單系統開發技術詳細流程
- 馬蹄鏈合約互助迴圈複利模式開發流程丨智慧合約dapp系統開發程式設計示例模式APP程式設計
- NFT鑄造鏈上智慧合約模式系統開發丨DAPP技術介紹模式APP
- DAPP馬蹄鏈智慧合約專案系統開發詳情技術介紹APP
- NFT鑄造智慧合約交易平臺系統開發丨Opensea系統開發介紹
- 馬蹄鏈智慧合約DAPP開發需求丨馬蹄鏈智慧合約DAPP質押挖礦系統開發(開發案例)APP
- forsage智慧合約開發技術應用流程
- 鏈上DAPP系統開發|智慧合約DAPP開發搭建APP
- 馬蹄鏈Dapp智慧合約(系統開發)案例丨馬蹄鏈MATIC智慧合約技術開發原理APP
- jQuery外掛開發流程簡單介紹jQuery
- iOS開發-WKWebView的介紹與基本使用iOSWebView
- NFT智慧合約開發鏈遊優勢分析
- 區塊鏈BSC智慧合約DAPP開發區塊鏈APP
- FDF迴圈互助遊戲系統開發原理丨FDF智慧合約開發功能詳細介紹遊戲