├── .idea
├── polleos.iml
├── codeStyles
│ ├── codeStyleConfig.xml
│ └── Project.xml
├── vcs.xml
├── misc.xml
└── modules.xml
├── CMakeModules
├── FindWasm.cmake
└── wasm.cmake
├── LICENSE
├── .gitignore
├── tests
├── main.cpp
├── polleos_tests.cpp
└── CMakeLists.txt
├── CMakeLists.txt
├── eosio.token.hpp
├── polleos.hpp
├── polleos.abi
└── polleos.cpp
/.idea/polleos.iml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/CMakeModules/FindWasm.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find WASM
2 |
3 | # TODO: Check if compiler is able to generate wasm32
4 | if ("${WASM_ROOT}" STREQUAL "")
5 | if (APPLE)
6 | set( WASM_ROOT "/usr/local/wasm" )
7 | elseif (UNIX AND NOT APPLE)
8 | set( WASM_ROOT "$ENV{HOME}/opt/wasm" )
9 | else()
10 | message(FATAL_ERROR "WASM not found and don't know where to look, please specify WASM_ROOT")
11 | endif()
12 | endif()
13 | find_program(WASM_CLANG clang PATHS ${WASM_ROOT}/bin NO_DEFAULT_PATH)
14 | find_program(WASM_LLC llc PATHS ${WASM_ROOT}/bin NO_DEFAULT_PATH)
15 | find_program(WASM_LLVM_LINK llvm-link PATHS ${WASM_ROOT}/bin NO_DEFAULT_PATH)
16 |
17 | include(FindPackageHandleStandardArgs)
18 | # handle the QUIETLY and REQUIRED arguments and set EOS_FOUND to TRUE
19 | # if all listed variables are TRUE
20 |
21 | find_package_handle_standard_args(WASM REQUIRED_VARS WASM_CLANG WASM_LLC WASM_LLVM_LINK)
22 |
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 sim31
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
2 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
3 |
4 | # User-specific stuff
5 | .idea/**/workspace.xml
6 | .idea/**/tasks.xml
7 | .idea/**/dictionaries
8 | .idea/**/shelf
9 |
10 | # Sensitive or high-churn files
11 | .idea/**/dataSources/
12 | .idea/**/dataSources.ids
13 | .idea/**/dataSources.local.xml
14 | .idea/**/sqlDataSources.xml
15 | .idea/**/dynamic.xml
16 | .idea/**/uiDesigner.xml
17 |
18 | # Gradle
19 | .idea/**/gradle.xml
20 | .idea/**/libraries
21 |
22 | # CMake
23 | build
24 | build-debug
25 |
26 | # Mongo Explorer plugin
27 | .idea/**/mongoSettings.xml
28 |
29 | # File-based project format
30 | *.iws
31 |
32 | # IntelliJ
33 | out/
34 |
35 | # mpeltonen/sbt-idea plugin
36 | .idea_modules/
37 |
38 | # JIRA plugin
39 | atlassian-ide-plugin.xml
40 |
41 | # Cursive Clojure plugin
42 | .idea/replstate.xml
43 |
44 | # Crashlytics plugin (for Android Studio and IntelliJ)
45 | com_crashlytics_export_strings.xml
46 | crashlytics.properties
47 | crashlytics-build.properties
48 | fabric.properties
49 |
50 | # Editor-based Rest Client
51 | .idea/httpRequests
52 |
53 | # Vim
54 |
55 | # Swap
56 | [._]*.s[a-v][a-z]
57 | [._]*.sw[a-p]
58 | [._]s[a-v][a-z]
59 | [._]sw[a-p]
60 |
61 | # Session
62 | Session.vim
63 |
64 | # Temporary
65 | .netrwhist
66 | *~
67 | # Auto-generated tag files
68 | tags
69 |
70 | # Tests
71 | tests/nodeos/data
72 | tests/node_modules
73 | tests/.idea
74 |
--------------------------------------------------------------------------------
/tests/main.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * @file
3 | * @copyright defined in eos/LICENSE.txt
4 | */
5 | #define BOOST_TEST_MODULE polleos-tests
6 | #define BOOST_TEST_DYN_LINK
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | //extern uint32_t EOS_TESTING_GENESIS_TIMESTAMP;
15 |
16 | void translate_fc_exception(const fc::exception &e) {
17 | std::cerr << "\033[33m" << e.to_detail_string() << "\033[0m" << std::endl;
18 | BOOST_TEST_FAIL("Caught Unexpected Exception");
19 | }
20 |
21 | struct eosio_test_fixture {
22 | eosio_test_fixture() {
23 | // Turn off blockchain logging if no --verbose parameter is not added
24 | // To have verbose enabled, call "tests/chain_test -- --verbose"
25 | bool is_verbose = false;
26 | std::string verbose_arg = "--verbose";
27 | int argc = boost::unit_test::framework::master_test_suite().argc;
28 | char** argv = boost::unit_test::framework::master_test_suite().argv;
29 | for (int i = 0; i < argc; i++) {
30 | if (verbose_arg == argv[i]) {
31 | is_verbose = true;
32 | break;
33 | }
34 | }
35 | if(!is_verbose)
36 | fc::logger::get(DEFAULT_LOGGER).set_log_level(fc::log_level::off);
37 |
38 | // Register fc::exception translator
39 | boost::unit_test::unit_test_monitor.register_exception_translator
40 | (&translate_fc_exception);
41 |
42 | std::srand(time(NULL));
43 | std::cout << "Random number generator seeded to " << time(NULL) << std::endl;
44 | }
45 | };
46 |
47 | BOOST_TEST_GLOBAL_FIXTURE( eosio_test_fixture );
48 |
49 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.9)
2 | project(polleos CXX)
3 |
4 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
5 |
6 | set(BOOST_INCLUDEDIR $ENV{HOME}/opt/boost_1_67_0/include CACHE PATH "Path to boost instalation directory")
7 |
8 | set(EOSIO_INSTALL_DIR /usr/local CACHE PATH "Path to eosio intstall dir")
9 | set(S2WASM_PATH ${EOSIO_INSTALL_DIR}/bin/eosio-s2wasm)
10 | set(WAST2WASM_PATH ${EOSIO_INSTALL_DIR}/bin/eosio-wast2wasm)
11 | set(EOSIOCPP_PATH ${EOSIO_INSTALL_DIR}/bin/eosiocpp)
12 | set(EOSIO_CONTRACTSDK_PATH ${EOSIO_INSTALL_DIR}/usr/share/eosio/contractsdk/lib)
13 |
14 | include("wasm")
15 |
16 | set(DEFAULT_SYSTEM_INCLUDE_FOLDERS ${EOSIO_INSTALL_DIR}/include/libc++/upstream/include
17 | ${EOSIO_INSTALL_DIR}/include/musl/upstream/include ${BOOST_INCLUDEDIR})
18 | set(EOSIO_LIBS ${EOSIO_CONTRACTSDK_PATH}/eosiolib.bc ${EOSIO_CONTRACTSDK_PATH}/libc++.bc
19 | ${EOSIO_CONTRACTSDK_PATH}/libc.bc)
20 |
21 | set(INCLUDE_DIRS "${EOSIO_INSTALL_DIR}/include" "${CMAKE_SOURCE_DIR}/include")
22 |
23 | #include_directories(include)
24 | #include_directories(${EOSIO_INSTALL_DIR}/include)
25 | #include_directories(${EOSIO_INSTALL_DIR}/include/libc++/upstream/include)
26 | #include_directories(${EOSIO_INSTALL_DIR}/include/musl/upstream/include)
27 | #include_directories(${BOOST_INCLUDE_DIR})
28 | #include_directories(${EOSIO_TOKEN_INCLUDE_DIR})
29 |
30 | set(CPP_FILES
31 | ${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_PROJECT_NAME}.cpp)
32 |
33 | set(HPP_FILES
34 | ${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_PROJECT_NAME}.hpp)
35 |
36 | #set(CONTRACT_ASSEMBLY_FILE ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}.s)
37 | #set(CONTRACT_WAST_FILE ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}.wast)
38 |
39 |
40 | add_wast_executable(TARGET ${CMAKE_PROJECT_NAME}
41 | INCLUDE_FOLDERS "${INCLUDE_DIRS}"
42 | LIBRARIES ${EOSIO_LIBS}
43 | DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
44 | SOURCE_FILES ${CPP_FILES})
45 |
46 |
47 | set(CONTRACT_ABI_SRC ${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_PROJECT_NAME}.abi)
48 |
49 | configure_file("${CONTRACT_ABI_SRC}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
50 |
51 | add_subdirectory(tests)
52 |
--------------------------------------------------------------------------------
/eosio.token.hpp:
--------------------------------------------------------------------------------
1 | /**
2 | * @file
3 | * @copyright defined in eos/LICENSE.txt
4 | */
5 | #pragma once
6 |
7 | #include
8 | #include
9 |
10 | #include
11 |
12 | namespace eosiosystem {
13 | class system_contract;
14 | }
15 |
16 | namespace eosio {
17 |
18 | using std::string;
19 |
20 | class token : public contract {
21 | public:
22 | token( account_name self ):contract(self){}
23 |
24 | void create( account_name issuer,
25 | asset maximum_supply);
26 |
27 | void issue( account_name to, asset quantity, string memo );
28 |
29 | void transfer( account_name from,
30 | account_name to,
31 | asset quantity,
32 | string memo );
33 |
34 |
35 | inline bool exists( symbol_name sym)const;
36 |
37 | inline asset get_supply( symbol_name sym )const;
38 |
39 | inline asset get_balance( account_name owner, symbol_name sym )const;
40 |
41 | private:
42 |
43 | friend eosiosystem::system_contract;
44 |
45 | private:
46 | struct account {
47 | asset balance;
48 |
49 | uint64_t primary_key()const { return balance.symbol.name(); }
50 | };
51 |
52 | struct currency_stats {
53 | asset supply;
54 | asset max_supply;
55 | account_name issuer;
56 |
57 | uint64_t primary_key()const { return supply.symbol.name(); }
58 | };
59 |
60 | typedef eosio::multi_index accounts;
61 | typedef eosio::multi_index stats;
62 |
63 | void sub_balance( account_name owner, asset value );
64 | void add_balance( account_name owner, asset value, account_name ram_payer );
65 |
66 | public:
67 | struct transfer_args {
68 | account_name from;
69 | account_name to;
70 | asset quantity;
71 | string memo;
72 | };
73 | };
74 |
75 | asset token::get_supply( symbol_name sym )const {
76 |
77 | stats statstable( _self, sym );
78 | const auto& st = statstable.get( sym, "This token does not exist" );
79 | return st.supply;
80 | }
81 |
82 | asset token::get_balance( account_name owner, symbol_name sym )const {
83 |
84 | accounts accountstable( _self, owner );
85 | const auto& ac = accountstable.get( sym, "This account does not have any balance" );
86 | return ac.balance;
87 | }
88 |
89 | bool token::exists(symbol_name sym)const {
90 |
91 | stats st(_self, sym);
92 | return st.find(sym) != st.end();
93 | }
94 |
95 | } /// namespace eosio
96 |
--------------------------------------------------------------------------------
/tests/polleos_tests.cpp:
--------------------------------------------------------------------------------
1 | #define BOOST_TEST_DYN_LINK
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 | #include
10 |
11 | #include
12 |
13 | #include
14 |
15 | #include
16 |
17 | using namespace eosio;
18 | using namespace eosio::chain;
19 | using namespace eosio::testing;
20 | using namespace fc;
21 | using namespace std;
22 |
23 | using mvo = fc::mutable_variant_object;
24 |
25 | class polleos_tester : public tester {
26 | public:
27 | typedef uint64_t poll_id;
28 | typedef std::vector option_names;
29 | typedef extended_symbol token_info;
30 | typedef vector option_results;
31 |
32 | polleos_tester() {
33 |
34 | produce_blocks(2);
35 |
36 | create_accounts({N(alice), N(bob), N(carol), contract_name});
37 | produce_blocks(2);
38 |
39 | set_code(contract_name, polleos_wast);
40 | set_abi(contract_name, polleos_abi);
41 |
42 | produce_blocks();
43 |
44 | const auto& accnt = control->db().get(N(polleos));
45 | abi_def abi;
46 | BOOST_REQUIRE_EQUAL(abi_serializer::to_abi(accnt.abi, abi), true);
47 | abi_ser.set_abi(abi);
48 | }
49 |
50 | action_result push_action( const account_name& signer, const action_name &name, const variant_object &data ) {
51 | string action_type_name = abi_ser.get_action_type(name);
52 |
53 | action act;
54 | act.account = contract_name;
55 | act.name = name;
56 | act.data = abi_ser.variant_to_binary( action_type_name, data );
57 |
58 | return base_tester::push_action( std::move(act), uint64_t(signer));
59 | }
60 |
61 | action_result newpoll(string question, account_name owner, option_names options) {
62 |
63 | return push_action( owner, N(newpoll), mvo()
64 | ( "question", question)
65 | ( "creator", owner)
66 | ( "options", options )
67 | );
68 | }
69 |
70 | fc::variant get_poll( poll_id id ) {
71 |
72 | auto data = get_row_by_account( contract_name, contract_name, N(poll), id);
73 | return data.empty() ? fc::variant() : abi_ser.binary_to_variant( "poll", data );
74 | }
75 |
76 |
77 | const account_name contract_name = N(polleos);
78 | private:
79 |
80 | abi_serializer abi_ser;
81 | };
82 |
83 | BOOST_AUTO_TEST_SUITE( polleos_tests )
84 |
85 | BOOST_FIXTURE_TEST_CASE( create_poll, polleos_tester ) try {
86 |
87 | string question = "Q1";
88 | option_names options {"opt1", "opt2", "opt3"};
89 | option_results results { mvo("name", "opt1")("votes", 0.0),
90 | mvo("name", "opt2")("votes", 0.0),
91 | mvo("name", "opt3")("votes", 0.0) };
92 |
93 |
94 | newpoll(question, N(alice), options);
95 | produce_blocks(1);
96 |
97 | variant created_poll = get_poll(0);
98 |
99 | variant required_poll = mvo()
100 | ("question", question)
101 | ("results", results)
102 | ("is_token_poll", false);
103 |
104 | cout << "Created poll: " << created_poll << endl;
105 | cout << "Expected poll: " << required_poll << endl;
106 |
107 | REQUIRE_MATCHING_OBJECT(required_poll, created_poll);
108 | } FC_LOG_AND_RETHROW()
109 |
110 | BOOST_AUTO_TEST_SUITE_END()
111 |
112 |
--------------------------------------------------------------------------------
/polleos.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include "eosio.token.hpp"
6 |
7 | class polleos : public eosio::contract {
8 | public:
9 | typedef uint64_t poll_id_t;
10 | typedef std::vector option_names_t;
11 | typedef eosio::extended_symbol token_info_t;
12 | typedef uint8_t option_id_t;
13 |
14 | polleos(account_name contract_name) : eosio::contract(contract_name),
15 | _polls(contract_name, contract_name) {}
16 |
17 | struct option {
18 | std::string name;
19 |
20 | option(std::string name) : name(name) {}
21 |
22 | option() {}
23 |
24 | EOSLIB_SERIALIZE(option, (name))
25 | };
26 |
27 | struct option_result : option {
28 | double votes = 0;
29 |
30 | option_result(const std::string& name, uint64_t votes) : option(name),
31 | votes(votes) {}
32 |
33 | option_result(const std::string& name) : option_result(name, 0) {}
34 |
35 | option_result() {}
36 |
37 | EOSLIB_SERIALIZE(option_result, (name)(votes))
38 | };
39 |
40 | typedef std::vector option_results;
41 |
42 | //@abi table
43 | struct poll {
44 | poll_id_t id;
45 | std::string question;
46 | option_results results;
47 | bool is_token_poll = false;
48 | token_info_t token;
49 |
50 | uint64_t primary_key() const {
51 |
52 | return id;
53 | }
54 |
55 | uint64_t get_reverse_key() const {
56 |
57 | return ~id;
58 | }
59 |
60 | void set(poll_id_t id, const std::string& question,
61 | const option_names_t& options, bool is_token_poll,
62 | token_info_t token);
63 |
64 | EOSLIB_SERIALIZE(poll, (id)(question)(results)(is_token_poll)(token))
65 | };
66 |
67 | //@abi table votes
68 | struct poll_vote {
69 | poll_id_t poll_id;
70 | option_id_t option_id;
71 |
72 | uint64_t primary_key() const {
73 |
74 | return poll_id;
75 | }
76 |
77 | EOSLIB_SERIALIZE(poll_vote, (poll_id)(option_id))
78 | };
79 |
80 | typedef eosio::multi_index
82 | > > poll_table;
83 |
84 | typedef eosio::multi_index vote_table;
85 |
86 | //@abi action
87 | void newpoll(const std::string& question, account_name creator,
88 | const std::vector& options);
89 |
90 | //@abi action
91 | void newtokenpoll(const std::string& question, account_name payer,
92 | const std::vector& options,
93 | token_info_t token);
94 |
95 | //@abi action
96 | void vote(poll_id_t id, account_name voter, option_id_t option_id);
97 |
98 |
99 | private:
100 | void store_poll(const std::string& question, account_name owner,
101 | const option_names_t& options,
102 | bool is_token_poll, token_info_t token);
103 |
104 | void store_vote(const poll& p, vote_table& votes, option_id_t option_id,
105 | double weight);
106 |
107 | void store_token_vote(const poll& p, vote_table& votes, option_id_t option_id);
108 |
109 | double to_weight(const eosio::asset& stake) {
110 |
111 | return stake.amount / std::pow(10, stake.symbol.precision());
112 | }
113 |
114 | poll_table _polls;
115 | };
116 |
--------------------------------------------------------------------------------
/polleos.abi:
--------------------------------------------------------------------------------
1 | {
2 | "types": [{
3 | "new_type_name": "poll_id_t",
4 | "type": "uint64"
5 | },{
6 | "new_type_name": "option_results",
7 | "type": "option_result[]"
8 | },{
9 | "new_type_name": "token_info_t",
10 | "type": "extended_symbol"
11 | },{
12 | "new_type_name": "symbol_name",
13 | "type": "symbol"
14 | }
15 | ],
16 | "structs": [{
17 | "name": "option",
18 | "base": "",
19 | "fields": [{
20 | "name": "name",
21 | "type": "string"
22 | }
23 | ]
24 | },{
25 | "name": "option_result",
26 | "base": "option",
27 | "fields": [{
28 | "name": "votes",
29 | "type": "float64"
30 | }
31 | ]
32 | },{
33 | "name": "symbol_type",
34 | "base": "",
35 | "fields": [{
36 | "name": "value",
37 | "type": "symbol_name"
38 | }
39 | ]
40 | },{
41 | "name": "extended_symbol",
42 | "base": "symbol_type",
43 | "fields": [{
44 | "name": "contract",
45 | "type": "name"
46 | }
47 | ]
48 | },{
49 | "name": "poll",
50 | "base": "",
51 | "fields": [{
52 | "name": "id",
53 | "type": "poll_id_t"
54 | },{
55 | "name": "question",
56 | "type": "string"
57 | },{
58 | "name": "results",
59 | "type": "option_results"
60 | },{
61 | "name": "is_token_poll",
62 | "type": "bool"
63 | },{
64 | "name": "token",
65 | "type": "token_info_t"
66 | }
67 | ]
68 | },{
69 | "name": "poll_vote",
70 | "base": "",
71 | "fields": [{
72 | "name": "pollid",
73 | "type": "poll_id_t"
74 | },{
75 | "name": "optionid",
76 | "type": "uint8"
77 | }
78 | ]
79 | },{
80 | "name": "newpoll",
81 | "base": "",
82 | "fields": [{
83 | "name": "question",
84 | "type": "string"
85 | },{
86 | "name": "creator",
87 | "type": "name"
88 | },{
89 | "name": "options",
90 | "type": "string[]"
91 | }
92 | ]
93 | },{
94 | "name": "newtokenpoll",
95 | "base": "",
96 | "fields": [{
97 | "name": "question",
98 | "type": "string"
99 | },{
100 | "name": "creator",
101 | "type": "name"
102 | },{
103 | "name": "options",
104 | "type": "string[]"
105 | },{
106 | "name": "token",
107 | "type": "token_info_t"
108 | }
109 | ]
110 | },{
111 | "name": "vote",
112 | "base": "",
113 | "fields": [{
114 | "name": "id",
115 | "type": "poll_id_t"
116 | },{
117 | "name": "voter",
118 | "type": "name"
119 | },{
120 | "name": "option_id",
121 | "type": "uint8"
122 | }
123 | ]
124 | }
125 | ],
126 | "actions": [{
127 | "name": "newpoll",
128 | "type": "newpoll",
129 | "ricardian_contract": ""
130 | },{
131 | "name": "newtokenpoll",
132 | "type": "newtokenpoll",
133 | "ricardian_contract": ""
134 | },{
135 | "name": "vote",
136 | "type": "vote",
137 | "ricardian_contract": ""
138 | }
139 | ],
140 | "tables": [{
141 | "name": "poll",
142 | "index_type": "i64",
143 | "key_names": [
144 | "id"
145 | ],
146 | "key_types": [
147 | "poll_id_t"
148 | ],
149 | "type": "poll"
150 | },{
151 | "name": "votes",
152 | "index_type": "i64",
153 | "key_names": [
154 | "id"
155 | ],
156 | "key_types": [
157 | "poll_id_t"
158 | ],
159 | "type": "poll_vote"
160 | }
161 | ],
162 | "ricardian_clauses": []
163 | }
--------------------------------------------------------------------------------
/polleos.cpp:
--------------------------------------------------------------------------------
1 | #include "polleos.hpp"
2 | #include
3 |
4 | void polleos::poll::set(polleos::poll_id_t id, const std::string& question,
5 | const option_names_t& options, bool is_token_poll,
6 | token_info_t token) {
7 |
8 | eosio_assert(!question.empty(), "Question can't be empty");
9 |
10 | this->id = id;
11 | this->question = question;
12 | this->is_token_poll = is_token_poll;
13 | this->token = token;
14 |
15 | results.resize(options.size());
16 | std::transform(options.begin(), options.end(), results.begin(),
17 | [&](std::string str) {
18 | eosio_assert(!str.empty(), "Option names can't be empty");
19 | return option_result(str);
20 | });
21 | }
22 |
23 | void polleos::store_poll(const std::string& question, account_name poll_owner,
24 | const option_names_t& options,
25 | bool is_token_poll, token_info_t token) {
26 |
27 | poll_id_t id;
28 |
29 | eosio_assert(options.size() < std::numeric_limits::max(),
30 | "Too many options");
31 |
32 | _polls.emplace(poll_owner, [&](poll& p) {
33 | id = _polls.available_primary_key();
34 | p.set(id, question, options, is_token_poll, token);
35 | });
36 |
37 | eosio::print("Poll stored with id: ", id);
38 | }
39 |
40 | void polleos::store_vote(const polleos::poll& p, polleos::vote_table& votes,
41 | option_id_t option_id, double weight) {
42 |
43 | eosio_assert(weight > 0, "Vote weight cannot be less than 0. Contract logic issue");
44 |
45 | // Voter (votes.get_scope()) pays
46 | votes.emplace(votes.get_scope(), [&](poll_vote& v) {
47 | v.poll_id = p.id;
48 | v.option_id = option_id;
49 | });
50 |
51 | _polls.modify(p, votes.get_scope(), [&](poll& p) {
52 | p.results[option_id].votes += weight;
53 | });
54 | }
55 |
56 | void polleos::store_token_vote(const polleos::poll& p, polleos::vote_table& votes,
57 | option_id_t option_id) {
58 |
59 | account_name voter = votes.get_scope();
60 |
61 | eosio::token token(p.token.contract);
62 | // Should fail if voter is not a stakeholder
63 | eosio::asset balance = token.get_balance(voter, p.token.name());
64 | // Some additional checks
65 | eosio_assert(balance.is_valid(), "Balance of voter account is invalid. Something"
66 | " wrong with token contract.");
67 | eosio_assert(balance.amount > 0,
68 | "Voter has to have more than 0 of tokens to participate in a poll!");
69 |
70 | store_vote(p, votes, option_id, to_weight(balance));
71 | }
72 |
73 | void polleos::newpoll(const std::string& question, account_name payer,
74 | const option_names_t& options) {
75 |
76 | store_poll(question, payer, options, false, token_info_t());
77 | }
78 |
79 | void polleos::newtokenpoll(const std::string& question, account_name owner,
80 | const option_names_t& options, token_info_t token_inf) {
81 |
82 | eosio::token token(token_inf.contract);
83 | eosio_assert(token.exists(token_inf.name()), "This token does not exist");
84 | store_poll(question, owner, options, true, token_inf);
85 | }
86 |
87 | void polleos::vote(polleos::poll_id_t id, account_name voter, option_id_t option_id) {
88 |
89 | eosio::require_auth(voter);
90 |
91 | const poll & p = _polls.get(id, "Poll with this id does not exist");
92 |
93 | eosio_assert(option_id < p.results.size(),
94 | "Option with this id does not exist");
95 |
96 | vote_table votes(get_self(), voter);
97 | eosio_assert(votes.find(p.id) == votes.end(), "This account has already "
98 | "voted in this poll");
99 |
100 | if (p.is_token_poll)
101 | store_token_vote(p, votes, option_id);
102 | else
103 | store_vote(p, votes, option_id, 1);
104 |
105 | eosio::print("Vote stored!");
106 | }
107 |
108 | EOSIO_ABI(polleos, (newpoll)(newtokenpoll)(vote))
109 |
110 |
--------------------------------------------------------------------------------
/tests/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | #file(GLOB COMMON_SOURCES "common/*.cpp")
2 |
3 | #find_package( Gperftools QUIET )
4 | #if( GPERFTOOLS_FOUND )
5 | # message( STATUS "Found gperftools; compiling tests with TCMalloc")
6 | # list( APPEND PLATFORM_SPECIFIC_LIBS tcmalloc )
7 | #endif()
8 |
9 | set(EOSIO_SRC_DIR "" CACHE PATH "Path to eosio source directory")
10 | set(EOSIO_BUILD_DIR "" CACHE PATH "Path to eosio build directory")
11 | set(BOOST_INCLUDEDIR $ENV{HOME}/opt/boost_1_66_0/include CACHE PATH "Path to boost instalation directory")
12 |
13 | # FIXME: not all might be needed
14 | set(EOSIO_LIB_BUILD_DIR "${EOSIO_BUILD_DIR}/libraries")
15 | set(EOSIO_CHAIN_LIB "${EOSIO_LIB_BUILD_DIR}/chain/libeosio_chain.a")
16 | set(EOSIO_CHAINBASE_LIB "${EOSIO_LIB_BUILD_DIR}/chainbase/libchainbase.a")
17 | set(EOSIO_TESTING_LIB "${EOSIO_LIB_BUILD_DIR}/testing/libeosio_testing.a")
18 | set(EOSIO_UTILITIES_LIB "${EOSIO_LIB_BUILD_DIR}/utilities/libeos_utilities.a")
19 | set(EOSIO_FC_LIB "${EOSIO_LIB_BUILD_DIR}/fc/libfc_debug.a")
20 |
21 | message("Lib: ${EOSIO_CHAIN_LIB} ${EOSIO_CHAINBASE_LIB} ${EOSIO_TESTING_LIB}
22 | ${EOSIO_UTILITIES_LIB} ${EOSIO_FC_LIB}")
23 |
24 | add_library(eosio_chain STATIC IMPORTED)
25 | set_target_properties(eosio_chain PROPERTIES IMPORTED_LOCATION "${EOSIO_CHAIN_LIB}")
26 |
27 | add_library(chainbase STATIC IMPORTED)
28 | set_target_properties(chainbase PROPERTIES IMPORTED_LOCATION "${EOSIO_CHAINBASE_LIB}")
29 |
30 | add_library(testing STATIC IMPORTED)
31 | set_target_properties(testing PROPERTIES IMPORTED_LOCATION "${EOSIO_TESTING_LIB}")
32 |
33 | add_library(utilities STATIC IMPORTED)
34 | set_target_properties(utilities PROPERTIES IMPORTED_LOCATION "${EOSIO_UTILITIES_LIB}")
35 |
36 | add_library(fc STATIC IMPORTED)
37 | set_target_properties(fc PROPERTIES IMPORTED_LOCATION "${EOSIO_FC_LIB}")
38 |
39 | add_library(binaryen STATIC IMPORTED)
40 | set_target_properties(binaryen PROPERTIES IMPORTED_LOCATION
41 | "${EOSIO_BUILD_DIR}/externals/binaryen/lib/libbinaryen.a")
42 |
43 | add_library(binaryen_support STATIC IMPORTED)
44 | set_target_properties(binaryen_support PROPERTIES IMPORTED_LOCATION
45 | "${EOSIO_BUILD_DIR}/externals/binaryen/lib/libsupport.a")
46 |
47 | add_library(binaryen_wasm STATIC IMPORTED)
48 | set_target_properties(binaryen_wasm PROPERTIES IMPORTED_LOCATION
49 | "${EOSIO_BUILD_DIR}/externals/binaryen/lib/libwasm.a")
50 |
51 | add_library(binaryen_cfg STATIC IMPORTED)
52 | set_target_properties(binaryen_cfg PROPERTIES IMPORTED_LOCATION
53 | "${EOSIO_BUILD_DIR}/externals/binaryen/lib/libcfg.a")
54 |
55 | add_library(binaryen_passes STATIC IMPORTED)
56 | set_target_properties(binaryen_passes PROPERTIES IMPORTED_LOCATION
57 | "${EOSIO_BUILD_DIR}/externals/binaryen/lib/libpasses.a")
58 |
59 | add_library(binaryen_asmjs STATIC IMPORTED)
60 | set_target_properties(binaryen_asmjs PROPERTIES IMPORTED_LOCATION
61 | "${EOSIO_BUILD_DIR}/externals/binaryen/lib/libasmjs.a")
62 |
63 | add_library(wasmjit_wasm STATIC IMPORTED)
64 | set_target_properties(wasmjit_wasm PROPERTIES IMPORTED_LOCATION
65 | "${EOSIO_BUILD_DIR}/libraries/wasm-jit/Source/WASM/libWASM.a")
66 |
67 | add_library(wasmjit_wast STATIC IMPORTED)
68 | set_target_properties(wasmjit_wast PROPERTIES IMPORTED_LOCATION
69 | "${EOSIO_BUILD_DIR}/libraries/wasm-jit/Source/WAST/libWAST.a")
70 |
71 | add_library(wasmjit_ir STATIC IMPORTED)
72 | set_target_properties(wasmjit_ir PROPERTIES IMPORTED_LOCATION
73 | "${EOSIO_BUILD_DIR}/libraries/wasm-jit/Source/IR/libIR.a")
74 |
75 | add_library(wasmjit_runtime STATIC IMPORTED)
76 | set_target_properties(wasmjit_runtime PROPERTIES IMPORTED_LOCATION
77 | "${EOSIO_BUILD_DIR}/libraries/wasm-jit/Source/Runtime/libRuntime.a")
78 |
79 | add_library(wasmjit_platform STATIC IMPORTED)
80 | set_target_properties(wasmjit_platform PROPERTIES IMPORTED_LOCATION
81 | "${EOSIO_BUILD_DIR}/libraries/wasm-jit/Source/Platform/libPlatform.a")
82 |
83 | add_library(wasmjit_logging STATIC IMPORTED)
84 | set_target_properties(wasmjit_logging PROPERTIES IMPORTED_LOCATION
85 | "${EOSIO_BUILD_DIR}/libraries/wasm-jit/Source/Logging/libLogging.a")
86 |
87 | add_library(builtins STATIC IMPORTED)
88 | set_target_properties(builtins PROPERTIES IMPORTED_LOCATION
89 | "${EOSIO_BUILD_DIR}/libraries/builtins/libbuiltins.a")
90 |
91 | add_library(softfloat STATIC IMPORTED)
92 | set_target_properties(softfloat PROPERTIES IMPORTED_LOCATION
93 | "${EOSIO_BUILD_DIR}/libraries/softfloat/libsoftfloat.a")
94 |
95 |
96 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${EOSIO_SRC_DIR}/libraries/fc/CMakeModules")
97 | find_package(LLVM 4.0 REQUIRED CONFIG)
98 | find_package(Secp256k1 REQUIRED)
99 | find_package(GMP REQUIRED)
100 | find_package(OpenSSL REQUIRED)
101 |
102 | find_package(Boost 1.67 REQUIRED COMPONENTS
103 | thread
104 | date_time
105 | filesystem
106 | system
107 | program_options
108 | signals
109 | serialization
110 | chrono
111 | unit_test_framework
112 | context
113 | locale
114 | iostreams)
115 |
116 | llvm_map_components_to_libnames(LLVM_LIBS support core passes mcjit native DebugInfoDWARF)
117 | link_directories(${LLVM_LIBRARY_DIR})
118 |
119 | include_directories("${CMAKE_BINARY_DIR}") # For *.wast.hpp and *.abi.hpp
120 | include_directories("${CMAKE_SOURCE_DIR}/")
121 | include_directories("${EOSIO_SRC_DIR}/libraries/testing/include")
122 | include_directories("${EOSIO_SRC_DIR}/libraries/chain/include/")
123 | include_directories("${EOSIO_SRC_DIR}/libraries/fc/include/")
124 | include_directories("${EOSIO_SRC_DIR}/libraries/chainbase/include/")
125 | include_directories("${EOSIO_SRC_DIR}/libraries/utilities/include/")
126 | include_directories("${EOSIO_SRC_DIR}/libraries/wasm-jit/Include/")
127 | include_directories("${EOSIO_SRC_DIR}/libraries/softfloat/source/include")
128 | include_directories("${EOSIO_BUILD_DIR}/libraries/chain/include")
129 | include_directories("${EOSIO_BUILD_DIR}/contracts/") # For eosio.token.wast.hpp and abi
130 | include_directories("${BOOST_INCLUDEDIR}")
131 |
132 | #configure_file(${EOSIO_SRC_DIR}/include/config.hpp.in
133 | # ${CMAKE_CURRENT_BINARY_DIR}/include/config.hpp ESCAPE_QUOTES)
134 |
135 | file(GLOB UNIT_TESTS "*.cpp")
136 |
137 | #add_executable( polleos-tests ${UNIT_TESTS} ${WASM_UNIT_TESTS} )
138 | add_executable( polleos-tests ${UNIT_TESTS})
139 | #target_link_libraries( polleos-tests eosio_chain chainbase eosio_testing eos_utilities
140 | # abi_generator fc ${PLATFORM_SPECIFIC_LIBS} )
141 | target_link_libraries( polleos-tests testing eosio_chain chainbase utilities fc
142 | ${OPENSSL_LIBRARIES} ${Secp256k1_LIBRARY} ${GMP_LIBRARIES} ${Boost_LIBRARIES}
143 | binaryen_wasm binaryen_support binaryen_cfg binaryen binaryen_passes
144 | binaryen_asmjs wasmjit_wasm wasmjit_wast wasmjit_ir wasmjit_runtime
145 | wasmjit_platform wasmjit_logging builtins softfloat ${LLVM_LIBS} -lpthread)
146 |
147 | #target_include_directories( unit_test PUBLIC ${CMAKE_BINARY_DIR}/contracts ${CMAKE_CURRENT_BINARY_DIR}/tests/contracts )
148 | #target_include_directories( unit_test PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/wasm_tests )
149 | #target_include_directories( unit_test PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/include )
150 | #add_dependencies(unit_test asserter test_api test_api_mem test_api_db test_ram_limit test_api_multi_index exchange eosio.token proxy identity identity_test stltest infinite eosio.system eosio.token eosio.bios test.inline multi_index_test noop dice eosio.msig payloadless tic_tac_toe)
151 |
152 | #Manually run unit_test for all supported runtimes
153 | #To run unit_test with all log from blockchain displayed, put --verbose after --, i.e. unit_test -- --verbose
154 | #add_test(NAME unit_test_binaryen COMMAND unit_test
155 | # -t \!wasm_tests/weighted_cpu_limit_tests
156 | # --report_level=detailed --color_output -- --binaryen)
157 | #add_test(NAME unit_test_wavm COMMAND unit_test
158 | # -t \!wasm_tests/weighted_cpu_limit_tests
159 | # --report_level=detailed --color_output --catch_system_errors=no -- --wavm)
160 |
161 | if(ENABLE_COVERAGE_TESTING)
162 |
163 | set(Coverage_NAME ${PROJECT_NAME}_ut_coverage)
164 |
165 | if(NOT LCOV_PATH)
166 | message(FATAL_ERROR "lcov not found! Aborting...")
167 | endif() # NOT LCOV_PATH
168 |
169 | if(NOT LLVMCOV_PATH)
170 | message(FATAL_ERROR "llvm-cov not found! Aborting...")
171 | endif() # NOT LCOV_PATH
172 |
173 | if(NOT GENHTML_PATH)
174 | message(FATAL_ERROR "genhtml not found! Aborting...")
175 | endif() # NOT GENHTML_PATH
176 |
177 | # no spaces allowed within tests list
178 | set(ctest_tests 'unit_test_binaryen|unit_test_wavm')
179 | set(ctest_exclude_tests '')
180 |
181 | # Setup target
182 | add_custom_target(${Coverage_NAME}
183 |
184 | # Cleanup lcov
185 | COMMAND ${LCOV_PATH} --directory . --zerocounters
186 |
187 | # Run tests
188 | COMMAND ./tools/ctestwrapper.sh -R ${ctest_tests} -E ${ctest_exclude_tests}
189 |
190 | COMMAND ${LCOV_PATH} --directory . --capture --gcov-tool ./tools/llvm-gcov.sh --output-file ${Coverage_NAME}.info
191 |
192 | COMMAND ${LCOV_PATH} -remove ${Coverage_NAME}.info '*/boost/*' '/usr/lib/*' '/usr/include/*' '*/externals/*' '*/fc/*' '*/wasm-jit/*' --output-file ${Coverage_NAME}_filtered.info
193 |
194 | COMMAND ${GENHTML_PATH} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}_filtered.info
195 |
196 | COMMAND if [ "$CI" != "true" ]\; then ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.base ${Coverage_NAME}.info ${Coverage_NAME}_filtered.info ${Coverage_NAME}.total ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned ${PROJECT_BINARY_DIR}/${Coverage_NAME}_filtered.info.cleaned\; fi
197 |
198 | WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
199 | COMMENT "Resetting code coverage counters to zero. Processing code coverage counters and generating report. Report published in ./${Coverage_NAME}"
200 | )
201 |
202 | # Show info where to find the report
203 | add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
204 | COMMAND ;
205 | COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
206 | )
207 | endif()
208 |
--------------------------------------------------------------------------------
/CMakeModules/wasm.cmake:
--------------------------------------------------------------------------------
1 | find_package(Wasm)
2 |
3 | if(WASM_FOUND)
4 | message(STATUS "Using WASM clang => " ${WASM_CLANG})
5 | message(STATUS "Using WASM llc => " ${WASM_LLC})
6 | message(STATUS "Using WASM llvm-link => " ${WASM_LLVM_LINK})
7 | else()
8 | message( FATAL_ERROR "No WASM compiler cound be found (make sure WASM_ROOT is set)" )
9 | return()
10 | endif()
11 | macro(compile_wast)
12 | #read arguments include ones that we don't since arguments get forwared "as is" and we don't want to threat unknown argument names as values
13 | cmake_parse_arguments(ARG "NOWARNINGS" "TARGET;DESTINATION_FOLDER" "SOURCE_FILES;INCLUDE_FOLDERS;SYSTEM_INCLUDE_FOLDERS;LIBRARIES" ${ARGN})
14 | set(target ${ARG_TARGET})
15 |
16 | # NOTE: Setting SOURCE_FILE and looping over it to avoid cmake issue with compilation ${target}.bc's rule colliding with
17 | # linking ${target}.bc's rule
18 | if ("${ARG_SOURCE_FILES}" STREQUAL "")
19 | set(SOURCE_FILES ${target}.cpp)
20 | else()
21 | set(SOURCE_FILES ${ARG_SOURCE_FILES})
22 | endif()
23 | set(outfiles "")
24 | foreach(srcfile ${SOURCE_FILES})
25 |
26 | get_filename_component(outfile ${srcfile} NAME)
27 | get_filename_component(extension ${srcfile} EXT)
28 | get_filename_component(infile ${srcfile} ABSOLUTE)
29 |
30 | # -ffreestanding
31 | # Assert that compilation targets a freestanding environment.
32 | # This implies -fno-builtin. A freestanding environment is one in which the standard library may not exist, and program startup may not necessarily be at main.
33 | # The most obvious example is an OS kernel.
34 |
35 | # -nostdlib
36 | # Do not use the standard system startup files or libraries when linking.
37 | # No startup files and only the libraries you specify are passed to the linker, and options specifying linkage of the system libraries, such as -static-libgcc or -shared-libgcc, are ignored.
38 | # The compiler may generate calls to memcmp, memset, memcpy and memmove.
39 | # These entries are usually resolved by entries in libc. These entry points should be supplied through some other mechanism when this option is specified.
40 |
41 | # -fno-threadsafe-statics
42 | # Do not emit the extra code to use the routines specified in the C++ ABI for thread-safe initialization of local statics.
43 | # You can use this option to reduce code size slightly in code that doesn’t need to be thread-safe.
44 |
45 | # -fno-rtti
46 | # Disable generation of information about every class with virtual functions for use by the C++ run-time type identification features (dynamic_cast and typeid).
47 |
48 | # -fno-exceptions
49 | # Disable the generation of extra code needed to propagate exceptions
50 | if ("${extension}" STREQUAL ".c")
51 | set(STDFLAG -D_XOPEN_SOURCE=700)
52 | else()
53 | set(STDFLAG "--std=c++14")
54 | endif()
55 |
56 | set(WASM_COMMAND ${WASM_CLANG} -emit-llvm -O3 ${STDFLAG} --target=wasm32 -ffreestanding
57 | -nostdlib -nostdlibinc -fno-threadsafe-statics -fno-rtti -fno-exceptions
58 | -c ${infile} -o ${outfile}.bc
59 | )
60 | if (${ARG_NOWARNINGS})
61 | list(APPEND WASM_COMMAND -Wno-everything)
62 | else()
63 | list(APPEND WASM_COMMAND -Weverything -Wno-c++98-compat -Wno-old-style-cast -Wno-vla -Wno-vla-extension -Wno-c++98-compat-pedantic
64 | -Wno-missing-prototypes -Wno-missing-variable-declarations -Wno-packed -Wno-padded -Wno-c99-extensions -Wno-documentation-unknown-command)
65 | endif()
66 |
67 | foreach(folder ${ARG_INCLUDE_FOLDERS})
68 | list(APPEND WASM_COMMAND -I ${folder})
69 | endforeach()
70 |
71 | if ("${ARG_SYSTEM_INCLUDE_FOLDERS}" STREQUAL "")
72 | set (ARG_SYSTEM_INCLUDE_FOLDERS ${DEFAULT_SYSTEM_INCLUDE_FOLDERS})
73 | endif()
74 | foreach(folder ${ARG_SYSTEM_INCLUDE_FOLDERS})
75 | list(APPEND WASM_COMMAND -isystem ${folder})
76 | endforeach()
77 |
78 | foreach(folder ${ARG_SYSTEM_INCLUDE_FOLDERS})
79 | list(APPEND WASM_COMMAND -isystem ${folder})
80 | endforeach()
81 |
82 | add_custom_command(OUTPUT ${outfile}.bc
83 | DEPENDS ${infile}
84 | COMMAND ${WASM_COMMAND}
85 | IMPLICIT_DEPENDS CXX ${infile}
86 | COMMENT "Building LLVM bitcode ${outfile}.bc"
87 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
88 | VERBATIM
89 | )
90 | set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${outfile}.bc)
91 | list(APPEND outfiles ${outfile}.bc)
92 |
93 | endforeach(srcfile)
94 |
95 | set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${target}.bc)
96 |
97 | endmacro(compile_wast)
98 |
99 | macro(add_wast_library)
100 | cmake_parse_arguments(ARG "NOWARNINGS" "TARGET;DESTINATION_FOLDER" "SOURCE_FILES;INCLUDE_FOLDERS;SYSTEM_INCLUDE_FOLDERS" ${ARGN})
101 | set(target ${ARG_TARGET})
102 | compile_wast(${ARGV})
103 |
104 | get_filename_component("${ARG_TARGET}_BC_FILENAME" "${ARG_DESTINATION_FOLDER}/${ARG_TARGET}.bc" ABSOLUTE CACHE)
105 | add_custom_target(${target} ALL DEPENDS ${${ARG_TARGET}_BC_FILENAME})
106 |
107 | add_custom_command(OUTPUT ${${ARG_TARGET}_BC_FILENAME}
108 | DEPENDS ${outfiles}
109 | COMMAND ${WASM_LLVM_LINK} -o ${${ARG_TARGET}_BC_FILENAME} ${outfiles}
110 | COMMENT "Linking LLVM bitcode library ${target}.bc"
111 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
112 | VERBATIM
113 | )
114 | #TODO: Fix this path on pending cmake install changes
115 | install(FILES ${${ARG_TARGET}_BC_FILENAME} DESTINATION usr/share/eosio/contractsdk/lib)
116 |
117 | endmacro(add_wast_library)
118 |
119 | macro(add_wast_executable)
120 | cmake_parse_arguments(ARG "NOWARNINGS" "TARGET;DESTINATION_FOLDER;MAX_MEMORY" "SOURCE_FILES;INCLUDE_FOLDERS;SYSTEM_INCLUDE_FOLDERS;LIBRARIES" ${ARGN})
121 | set(target ${ARG_TARGET})
122 | set(DESTINATION_FOLDER ${ARG_DESTINATION_FOLDER})
123 |
124 | compile_wast(${ARGV})
125 |
126 | foreach(lib ${ARG_LIBRARIES})
127 | list(APPEND LIBRARIES ${lib})
128 | endforeach()
129 |
130 | message("${LIBRARIES}")
131 |
132 | add_custom_command(OUTPUT ${target}.bc
133 | DEPENDS ${outfiles} ${ARG_LIBRARIES} ${LIBRARIES}
134 | COMMAND ${WASM_LLVM_LINK} -only-needed -o ${target}.bc ${outfiles} ${LIBRARIES}
135 | COMMENT "Linking LLVM bitcode executable ${target}.bc"
136 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
137 | VERBATIM
138 | )
139 |
140 | set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${target}.bc)
141 |
142 | add_custom_command(OUTPUT ${target}.s
143 | DEPENDS ${target}.bc
144 | COMMAND ${WASM_LLC} -thread-model=single -asm-verbose=false -o ${target}.s ${target}.bc
145 | COMMENT "Generating textual assembly ${target}.s"
146 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
147 | VERBATIM
148 | )
149 | set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${target}.s)
150 |
151 | if(ARG_MAX_MEMORY)
152 | set(MAX_MEMORY_PARAM "-m" ${ARG_MAX_MEMORY})
153 | endif()
154 |
155 | add_custom_command(OUTPUT ${DESTINATION_FOLDER}/${target}.wast
156 | DEPENDS ${target}.s
157 | COMMAND ${S2WASM_PATH} -o ${DESTINATION_FOLDER}/${target}.wast -s 10240
158 | ${MAX_MEMORY_PARAM} ${target}.s
159 | COMMENT "Generating WAST ${target}.wast"
160 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
161 | VERBATIM
162 | )
163 | set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${target}.wast)
164 |
165 | add_custom_command(OUTPUT ${DESTINATION_FOLDER}/${target}.wasm
166 | DEPENDS ${target}.wast
167 | COMMAND ${WAST2WASM_PATH} ${DESTINATION_FOLDER}/${target}.wast
168 | ${DESTINATION_FOLDER}/${target}.wasm -n
169 | COMMENT "Generating WASM ${target}.wasm"
170 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
171 | VERBATIM
172 | )
173 | set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${target}.wasm)
174 |
175 | STRING (REPLACE "." "_" TARGET_VARIABLE "${target}")
176 |
177 | add_custom_command(OUTPUT ${DESTINATION_FOLDER}/${target}.wast.hpp
178 | DEPENDS ${DESTINATION_FOLDER}/${target}.wast
179 | COMMAND echo "const char* const ${TARGET_VARIABLE}_wast = R\"=====(" > ${DESTINATION_FOLDER}/${target}.wast.hpp
180 | COMMAND cat ${DESTINATION_FOLDER}/${target}.wast >> ${DESTINATION_FOLDER}/${target}.wast.hpp
181 | COMMAND echo ")=====\";" >> ${DESTINATION_FOLDER}/${target}.wast.hpp
182 | COMMENT "Generating ${target}.wast.hpp"
183 | VERBATIM
184 | )
185 |
186 | if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${target}.abi )
187 | add_custom_command(OUTPUT ${DESTINATION_FOLDER}/${target}.abi.hpp
188 | DEPENDS ${DESTINATION_FOLDER}/${target}.abi
189 | COMMAND echo "const char* const ${TARGET_VARIABLE}_abi = R\"=====(" > ${DESTINATION_FOLDER}/${target}.abi.hpp
190 | COMMAND cat ${DESTINATION_FOLDER}/${target}.abi >> ${DESTINATION_FOLDER}/${target}.abi.hpp
191 | COMMAND echo ")=====\";" >> ${DESTINATION_FOLDER}/${target}.abi.hpp
192 | COMMENT "Generating ${target}.abi.hpp"
193 | VERBATIM
194 | )
195 | set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${target}.abi.hpp)
196 | set(extra_target_dependency ${DESTINATION_FOLDER}/${target}.abi.hpp)
197 | else()
198 | endif()
199 |
200 | add_custom_target(${target} ALL DEPENDS ${DESTINATION_FOLDER}/${target}.wast.hpp ${extra_target_dependency} ${DESTINATION_FOLDER}/${target}.wasm)
201 |
202 | set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${DESTINATION_FOLDER}/${target}.wast.hpp)
203 |
204 | set_property(TARGET ${target} PROPERTY INCLUDE_DIRECTORIES ${ARG_INCLUDE_FOLDERS})
205 |
206 | set(extra_target_dependency)
207 |
208 | # For CLion code insight
209 | include_directories(..)
210 | if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${target}.hpp)
211 | set(HEADER_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${target}.hpp)
212 | endif()
213 | file(GLOB HEADER_FILES ${ARG_INCLUDE_FOLDERS}/*.hpp ${SYSTEM_INCLUDE_FOLDERS}/*.hpp)
214 | add_executable(${target}.tmp EXCLUDE_FROM_ALL ${SOURCE_FILES} ${HEADER_FILE} ${HEADER_FILES})
215 |
216 | add_test(NAME "validate_${target}_abi"
217 | COMMAND ${CMAKE_BINARY_DIR}/scripts/abi_is_json.py ${ABI_FILES})
218 |
219 | endmacro(add_wast_executable)
220 |
--------------------------------------------------------------------------------