這是一步步的用EOSIO開發區塊鏈DApp的第二部分,這部分將主要是爲EOSIO平臺開發智能合約。php
示例智能合約的目的是模擬選舉。我建立了一個EOSIO用戶來託管智能合約。建立了兩個公民用戶來投票給候選人。投票記錄保存在EOSIO區塊鏈中。在此示例中,全部操做都在命令模式下運行。讓咱們開始吧。java
EOSIO執行以WebAssembly標準開發的智能合約。因此我用C++開發了選舉智能合約。如下是election.cpp
的完整源代碼:node
#include <eosiolib/eosio.hpp> using namespace eosio; class election : public contract { private: // create the multi index tables to store the data /// @abi table struct candidate { uint64_t _key; // primary key std::string _name; // candidate name uint32_t _count = 0; // voted count uint64_t primary_key() const { return _key; } }; typedef eosio::multi_index<N(candidate), candidate> candidates; /// @abi table struct voter { uint64_t _key; uint64_t _candidate_key; // name of poll account_name _account; // this account has voted, avoid duplicate voter uint64_t primary_key() const { return _key; } uint64_t candidate_key() const { return _candidate_key; } }; typedef eosio::multi_index<N(voter), voter, indexed_by<N(_candidate_key), const_mem_fun<voter, uint64_t, &voter::candidate_key>>> voters; // local instances of the multi indexes candidates _candidates; voters _voters; uint64_t _candidates_count; public: election(account_name s) : contract(s), _candidates(s, s), _voters(s, s), _candidates_count(0) {} // public methods exposed via the ABI // on candidates /// @abi action void version() { print("Election Smart Contract version 0.0.1\n"); }; /// @abi action void addc(std::string name) { print("Adding candidate ", name, "\n"); uint64_t key = _candidates.available_primary_key(); // update the table to include a new candidate _candidates.emplace(get_self(), [&](auto &p) { p._key = key; p._name = name; p._count = 0; }); print("Candidate added successfully. candidate_key = ", key, "\n"); }; /// @abi action void reset() { // Get all keys of _candidates std::vector<uint64_t> keysForDeletion; for (auto &itr : _candidates) { keysForDeletion.push_back(itr.primary_key()); } // now delete each item for that poll for (uint64_t key : keysForDeletion) { auto itr = _candidates.find(key); if (itr != _candidates.end()) { _candidates.erase(itr); } } // Get all keys of _voters keysForDeletion.empty(); for (auto &itr : _voters) { keysForDeletion.push_back(itr.primary_key()); } // now delete each item for that poll for (uint64_t key : keysForDeletion) { auto itr = _voters.find(key); if (itr != _voters.end()) { _voters.erase(itr); } } print("candidates and voters reset successfully.\n"); }; /// @abi action void results() { print("Start listing voted results\n"); for (auto& item : _candidates) { print("Candidate ", item._name, " has voted count: ", item._count, "\n"); } }; /// @abi action void vote(account_name s, uint64_t candidate_key) { require_auth(s); bool found = false; // Did the voter vote before? for (auto& item : _voters) { if (item._account == s) { found = true; break; } } eosio_assert(!found, "You're voted already!"); // Findout the candidate by id std::vector<uint64_t> keysForModify; for (auto& item : _candidates) { if (item.primary_key() == candidate_key) { keysForModify.push_back(item.primary_key()); break; } } if (keysForModify.size() == 0) { eosio_assert(found, "Invalid candidate id!"); return; } // Update the voted count inside the candidate for (uint64_t key : keysForModify) { auto itr = _candidates.find(key); auto candidate = _candidates.get(key); if (itr != _candidates.end()) { _candidates.modify(itr, get_self(), [&](auto& p) { p._count++; }); print("Voted candidate: ", candidate._name, " successfully\n"); } } // Add this user to voters array _voters.emplace(get_self(), [&](auto& p) { p._key = _voters.available_primary_key(); p._candidate_key = candidate_key; p._account = s; }); }; }; EOSIO_ABI(election, (version)(reset)(addc)(results)(vote))
注意最後一行EOSIO_ABI()
是一個宏語句,用於自動生成ABI文件而不是手動編寫。ABI文件用於定義提交動做處理程序。這告訴了EOSIO智能合約中處理程序的定義。python
EOSIO爲咱們提供了多索引數據庫API,能夠將數據保存到區塊鏈中。在上面的選舉智能合約中,我定義了兩個multi_index
(相似於SQL表):候選人和選民。其實是兩個數組存儲兩個結構:候選者和選民。我使用C++ STL來操做multi_index
,例如add
,update
,delete
。android
請注意,兩個結構在開頭標有/// @abi table
。這是告訴EOSIO abi生成器在election.abi
文件中生成ABI表。這很方便。c++
編譯選舉智能合約:git
$ eosiocpp -o election.wast election.cpp
分別生成WAST和WASM文件。但這對EOSIO來講還不夠。咱們還須要生成ABI文件:程序員
$ eosiocpp -g election.abi election.cpp
爲了加強開發體驗,我爲Visual Studio Code(VSCode)建立了一個屬性文件c_cpp_properties.json
,告訴它如何查找頭文件。該文件須要存儲在.vscode
目錄中,以下所示:github
.vscode/c_cpp_properties
文件內容以下:web
{ "configurations": [ { "name": "Linux", "includePath": [ "${workspaceFolder}/**", "~/eos/contracts", "~/opt/boost/include" ], "defines": [], "compilerPath": "/usr/bin/clang++-4.0", "cStandard": "c11", "cppStandard": "c++17", "intelliSenseMode": "clang-x64" } ], "version": 4 }
一直在使用配置良好的虛擬機(在第1部分中提到)。要啓動單節點Testnet服務器:
$ nodeos -e -p eosio --plugin eosio::wallet_api_plugin --plugin eosio::chain_api_plugin --plugin eosio::history_api_plugin --access-control-allow-origin=* --contracts-console
單擊此處獲取nodeos參數的更多信息。
下一個任務是解鎖默認錢包。EOSIO將密鑰對存儲在錢包中。每次服務器重啓或每15分鐘須要解鎖一次。解鎖錢包:
$ cleos wallet unlock --password ${wallet_password}
咱們須要分別建立一個全部者密鑰對和活動密鑰對。而後將該私鑰導入錢包。鍵入如下命令:
$ cleos create key # Create an owner key $ cleos create key # Create an active key $ cleos wallet import ${private_owner_key} $ cleos wallet import ${private_active_key}
不要忘記在某個地方記錄這些密鑰對。
接下來的任務是建立一個新的賬戶來保存選舉智能合約。 鍵入如下命令:
$ cleos create account eosio election ${public_owner_key} ${public_active_key}
此外,爲投票模擬建立兩個公民:
$ cleos create account eosio voter1 ${public_owner_key} ${public_active_key} $ cleos create account eosio voter2 ${public_owner_key} ${public_active_key}
輸入如下命令上傳選舉智能合約:
$ cleos set contract election ../election -p election
結果相似下圖:
咱們能夠嘗試運行合約。
1.運行version
操做
$ cleos push action election version '' -p election
咱們能夠從nodeos檢查控制檯輸出:
2.增長選舉候選人
$ cleos push action election addc '["Hillary Clinton"]' -p election $ cleos push action election addc '["Donald J. Trump"]' -p election
3.顯示存儲在區塊鏈中的候選數據庫
$ cleos get table election election candidate
結果如圖所示:
4.模擬投票(兩位選民都被投票給唐納德·J·特朗普)
$ cleos push action election vote '["voter1", 1]' -p voter1 $ cleos push action election vote '["voter2", 1]' -p voter2
若是voter1再次投票:
$ cleos push action election vote '["voter1", 0]' -p voter1
EOSIO 將返回一個例外:
5.查看投票結果
$ cleos get table election election candidate
如你所見,候選人「Donald J. Trump」的投票數爲2.這意味着選舉智能合約正在工做!
這就是EOS開發dapp的第二部分。
在下一部分中,我將建立一個Web應用程序,用於演示Web訪問者和區塊鏈之間的交互。
源代碼在這裏github repo
分享一個交互式的在線編程實戰,EOS智能合約與DApp開發入門:
本課程幫助你快速入門EOS區塊鏈去中心化應用的開發,內容涵蓋EOS工具鏈、帳戶與錢包、發行代幣、智能合約開發與部署、使用代碼與智能合約交互等核心知識點,最後綜合運用各知識點完成一個便籤DApp的開發。
- web3j教程,主要是針對java和android程序員進行區塊鏈以太坊開發的web3j詳解。
- 以太坊教程,主要介紹智能合約與dapp應用開發,適合入門。
- 以太坊開發,主要是介紹使用node.js、mongodb、區塊鏈、ipfs實現去中心化電商DApp實戰,適合進階。
- python以太坊,主要是針對python工程師使用web3.py進行區塊鏈以太坊開發的詳解。
- php以太坊,主要是介紹使用php進行智能合約開發交互,進行帳號建立、交易、轉帳、代幣開發以及過濾器和事件等內容。
- C#以太坊,主要講解如何使用C#開發基於.Net的以太坊應用,包括帳戶管理、狀態與交易、智能合約開發與交互、過濾器和事件等。
匯智網原創翻譯,轉載請標明出處。這裏是原文