From 28f298dbe4b99685986848bf9d465d9e377033b0 Mon Sep 17 00:00:00 2001 From: Matthieu Vachon Date: Tue, 21 Aug 2018 11:04:12 -0400 Subject: [PATCH 1/2] Updated contract to v1.1.x of EOS --- contract/.env.example | 3 --- contract/.envrc.example | 3 +++ contract/.gitignore | 12 ++++++++---- contract/CMakeLists.txt | 13 +++++++++++++ contract/Makefile | 26 -------------------------- contract/asset.hpp | 9 ++++----- contract/shine.abi | 3 +++ contract/shine.cpp | 6 +++--- contract/shine.hpp | 2 +- contract/shine.wasm | Bin 31440 -> 32193 bytes contract/shine_bot.rb | 5 ++++- 11 files changed, 39 insertions(+), 43 deletions(-) delete mode 100644 contract/.env.example create mode 100644 contract/.envrc.example create mode 100644 contract/CMakeLists.txt delete mode 100644 contract/Makefile mode change 100644 => 100755 contract/shine.wasm diff --git a/contract/.env.example b/contract/.env.example deleted file mode 100644 index db27492..0000000 --- a/contract/.env.example +++ /dev/null @@ -1,3 +0,0 @@ -SHINE_BOT_CONTRACT=shine.v1 -SHINE_BOT_WALLET_HOST=localhost -SHINE_BOT_WALLET_PORT=6666 diff --git a/contract/.envrc.example b/contract/.envrc.example new file mode 100644 index 0000000..43849b6 --- /dev/null +++ b/contract/.envrc.example @@ -0,0 +1,3 @@ +export SHINE_BOT_CONTRACT=shine +export SHINE_BOT_WALLET_HOST=localhost +export SHINE_BOT_WALLET_PORT=6666 diff --git a/contract/.gitignore b/contract/.gitignore index 736b045..8b9a998 100644 --- a/contract/.gitignore +++ b/contract/.gitignore @@ -1,5 +1,9 @@ -*.wast +CMakeCache.txt +cmake_install.cmake +compile_commands.json +eosc-vault.json +Makefile +.envrc -/.env - -.idea +CMakeFiles/ +.vscode/ diff --git a/contract/CMakeLists.txt b/contract/CMakeLists.txt new file mode 100644 index 0000000..262e696 --- /dev/null +++ b/contract/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.5) +project(FORUM VERSION 1.0.0) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +if(WASM_ROOT STREQUAL "" OR NOT WASM_ROOT) + set(WASM_ROOT ${CMAKE_INSTALL_PREFIX}) +endif() +list(APPEND CMAKE_MODULE_PATH ${WASM_ROOT}/lib/cmake) + +include(EosioWasmToolchain) + +add_executable( shine.wasm asset.hpp table.hpp shine.hpp shine.cpp ) diff --git a/contract/Makefile b/contract/Makefile deleted file mode 100644 index 8a8a744..0000000 --- a/contract/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -BLOCKCHAIN_HOST := "localhost" -BLOCKCHAIN_PORT := "8888" -CONTRACT_ACCOUNT := "shine.v1" -WALLET_HOST := "localhost" -WALLET_PORT := "6666" - -HEADERS = asset.hpp shine.hpp table.hpp - -default: build - -build: shine.wast - -shine.wast: shine.cpp $(HEADERS) - eosiocpp -o shine.wast shine.cpp shine.abi - -install: build - cleos \ - --host ${BLOCKCHAIN_HOST} \ - --port ${BLOCKCHAIN_PORT} \ - --wallet-host ${WALLET_HOST} \ - --wallet-port ${WALLET_PORT} \ - set contract ${CONTRACT_ACCOUNT} `pwd` \ - shine.wast shine.abi - -clean: - -@rm -f shine.wast 2>/dev/null || true \ No newline at end of file diff --git a/contract/asset.hpp b/contract/asset.hpp index 477e3bf..39ce4ed 100644 --- a/contract/asset.hpp +++ b/contract/asset.hpp @@ -7,13 +7,12 @@ namespace eoscanada { -static const uint64_t EOS_PRECISION = 4; -static const asset_symbol EOS_SYMBOL = S(EOS_PRECISION, EOS); +static const eosio::symbol_type EOS_SYMBOL = S(4, EOS); -inline static eosio::asset double_to_asset(double amount) { - return eosio::asset((uint64_t)(pow(10, EOS_PRECISION) * amount), EOS_SYMBOL); +inline static eosio::asset double_to_asset(double amount, eosio::symbol_type symbol) { + return eosio::asset((uint64_t)(pow(10, symbol.precision()) * amount), symbol); } -inline static double asset_to_double(const eosio::asset& asset) { return asset.amount / pow(10, EOS_PRECISION); } +inline static double asset_to_double(const eosio::asset& asset) { return asset.amount / pow(10, asset.symbol.precision()); } } // namespace eoscanada diff --git a/contract/shine.abi b/contract/shine.abi index a6f122b..9263842 100644 --- a/contract/shine.abi +++ b/contract/shine.abi @@ -1,5 +1,8 @@ { "types": [{ + "new_type_name": "account_name", + "type": "name" + },{ "new_type_name": "post_id", "type": "uint64" }], diff --git a/contract/shine.cpp b/contract/shine.cpp index 152400d..86dd2cc 100644 --- a/contract/shine.cpp +++ b/contract/shine.cpp @@ -173,9 +173,9 @@ void shine::distribute_rewards(const asset& pot, distribution_stat& distribution auto post_count_weight = post_vote_received / (double)distribution.vote_explicit; auto vote_given_weight = vote_given_weighted / distribution.vote_given_weighted_total; - auto vote_received_amount = double_to_asset(vote_received_weight * pot_amount * REWARD_VOTE_RECEIVED_WEIGHT); - auto post_count_amount = double_to_asset(post_count_weight * pot_amount * REWARD_post_count_WEIGHT); - auto vote_given_amount = double_to_asset(vote_given_weight * pot_amount * REWARD_VOTE_GIVEN_WEIGHT); + auto vote_received_amount = double_to_asset(vote_received_weight * pot_amount * REWARD_VOTE_RECEIVED_WEIGHT, EOS_SYMBOL); + auto post_count_amount = double_to_asset(post_count_weight * pot_amount * REWARD_POST_COUNT_WEIGHT, EOS_SYMBOL); + auto vote_given_amount = double_to_asset(vote_given_weight * pot_amount * REWARD_VOTE_GIVEN_WEIGHT, EOS_SYMBOL); auto amount_total = vote_received_amount + post_count_amount + vote_given_amount; balance -= amount_total; diff --git a/contract/shine.hpp b/contract/shine.hpp index a8c6194..7ae8c96 100644 --- a/contract/shine.hpp +++ b/contract/shine.hpp @@ -11,7 +11,7 @@ #include "table.hpp" // Configurable values -#define REWARD_post_count_WEIGHT 0.07 +#define REWARD_POST_COUNT_WEIGHT 0.07 #define REWARD_VOTE_RECEIVED_WEIGHT 0.9 #define REWARD_VOTE_GIVEN_WEIGHT 0.03 diff --git a/contract/shine.wasm b/contract/shine.wasm old mode 100644 new mode 100755 index d45860f023e55a2d6abbc4fe53d2fd1debd4458e..664071fa847c0566250078b90094370bc6744167 GIT binary patch literal 32193 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 Date: Tue, 21 Aug 2018 15:17:01 -0400 Subject: [PATCH 2/2] Moved stuff around to fit more with eosio.contracts structure --- contract/.gitignore | 1 + contract/CMakeLists.txt | 21 ++++- contract/README.md | 151 +++++++++++++++---------------- contract/{ => abi}/shine.abi | 0 contract/build.sh | 16 ++++ contract/{ => include}/asset.hpp | 0 contract/{ => include}/shine.hpp | 0 contract/{ => include}/table.hpp | 0 contract/shine.wasm | Bin 32193 -> 0 bytes contract/{ => src}/shine.cpp | 0 10 files changed, 108 insertions(+), 81 deletions(-) rename contract/{ => abi}/shine.abi (100%) create mode 100755 contract/build.sh rename contract/{ => include}/asset.hpp (100%) rename contract/{ => include}/shine.hpp (100%) rename contract/{ => include}/table.hpp (100%) delete mode 100755 contract/shine.wasm rename contract/{ => src}/shine.cpp (100%) diff --git a/contract/.gitignore b/contract/.gitignore index 8b9a998..4701377 100644 --- a/contract/.gitignore +++ b/contract/.gitignore @@ -5,5 +5,6 @@ eosc-vault.json Makefile .envrc +build*/ CMakeFiles/ .vscode/ diff --git a/contract/CMakeLists.txt b/contract/CMakeLists.txt index 262e696..fa3258b 100644 --- a/contract/CMakeLists.txt +++ b/contract/CMakeLists.txt @@ -1,13 +1,24 @@ cmake_minimum_required(VERSION 3.5) -project(FORUM VERSION 1.0.0) +project(shine VERSION 1.0.0) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(EOSIO_WASMSDK_DEPENDENCY "1.1") -if(WASM_ROOT STREQUAL "" OR NOT WASM_ROOT) - set(WASM_ROOT ${CMAKE_INSTALL_PREFIX}) +if(EOSIO_WASMSDK_ROOT STREQUAL "" OR NOT EOSIO_WASMSDK_ROOT) + set(EOSIO_WASMSDK_ROOT "/usr/local/eosio.wasmsdk") endif() -list(APPEND CMAKE_MODULE_PATH ${WASM_ROOT}/lib/cmake) + +list(APPEND CMAKE_MODULE_PATH ${EOSIO_WASMSDK_ROOT}/lib/cmake) include(EosioWasmToolchain) -add_executable( shine.wasm asset.hpp table.hpp shine.hpp shine.cpp ) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/abi/shine.abi" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY) + +add_executable(shine.wasm ${CMAKE_CURRENT_SOURCE_DIR}/src/shine.cpp) +target_include_directories(shine.wasm + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include) + +set_target_properties(shine.wasm + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") diff --git a/contract/README.md b/contract/README.md index c62f7fd..c583cd8 100644 --- a/contract/README.md +++ b/contract/README.md @@ -1,109 +1,108 @@ -## EOS Shine SmartContract +## EOS Shine Smart Contract -This document describes various aspects of the EOS Shine SmartContract +This document describes various aspects of the EOS Shine smart contract implementation ranging from architecture, building, troubleshooting, etc. Moreover, this document also contains various information about EOS -SmartContract in general, mainly aimed at the developer audience. - -### Architecture & Features - -The Shine contract goal is to enable the implementation of a recognition -system based on praise and votes. Person (i.e. account) broadcast a praise -to all other members. Each member (i.e. account) can then vote for this -particular praise. - -TBC +smart contract in general, mainly aimed at the developer audience. #### Actions -* `praise` (`addpraise`) - Create a praise in the blockchain. -* `vote` (`addvote`) - Vote for a given praise in the blockchain. -* `rewards` (`calcrewards`) - Update the rewards table in the blockchain. +* `post` - Create a post in the blockchain. +* `vote` - Vote for a given praise in the blockchain. +* `reset` - Reset all collected stats to initial state. ### Development -#### Prerequisites +#### Compilation -For development, ideally you would have a testnet running on your machine -executing the EOS blockchain by configuring a local environment. Follow the instructions at https://github.com/EOSIO/eos/wiki/Local-Environment and when you have a `nodeos` -running with a producer emitting blocks, come back here. +##### Docker -There is a `shine_bot.rb` script that enables to interact with the contract -in a more rapid way. For this you will need Ruby 2.4+ installed along with the -following dependency installed globally: +The easiest way to compile is by using EOS Canada `gcr.io/eoscanada-public/eosio-wasmsdk` +Docker image. + +While at the root of this project: ``` -gem install 'tty-prompt' +cd contract +docker run --rm -it -v `pwd`:/shine -w /shine gcr.io/eoscanada-public/eosio-wasmsdk:v1.1.1 bash build.sh ``` -Note that this is not needed if you don't plan on using the - -#### Preparation +You will find the compiled `shine.abi` and `shine.wasm` in the `build` directory. -Let's prepare for the development of EOS Shine SmartContract. We will -need an account on a running blockchain. It's quite possible to run -you own test blockchain on your machine for development purposes. +##### Locally -Let's create the account by creating two EOS key sets (first one for owner -permission second one for active permission). Note the private keys outputted -somewhere as we will need them in later section: +Ensure that you have `https://github.com/EOSIO/eosio.wasmsdk` compiled locally. -**Note** You will need to have `eosios@active` private key imported into a -wallet for the account creation to work. Import it using `cleos wallet import `. +While at the root of this project: ``` -# Owner -cleos create key -Private key: 5H123 -Public key: EOSXYZ - -# Active -cleos create key -Private key: 5B456 -Public key: EOSABC - -cleos create account eosio shine EOSXYZ EOSABC +./build.sh ``` -Once the account is created, let's import the owner and active private keys -into the default wallet (you are free to use another wallet also): +You will find the compiled `shine.abi` and `shine.wasm` in the `build` directory. + +#### Installation -**Note** Ensures that the wallet is unlocked prior doing this operation. You -can unlock it by using `cleos wallet unlock` and entering the wallet password -that was outputted at wallet creation time. +While at the root of this project: ``` -# Of course, change 5H123 and 5B456 by real owner & active private keys respectively -cleos wallet import 5H123 -cleos wallet import 5B456 +cd contract +cleos set contract shine build build/shine.wasm build/shine.abi ``` -We are then good to go. Note that if the blockchain node is stopped, -wallet will need to be unlocked again prior doing any operations -in the upcoming sections. - -#### Building & Testing +#### Testing -Building the SmartContract ABI and code to WAST is performed through -the `eosiocpp` command line utility. Navigate to the root folder -of this project and then issue: - -``` -eosiocpp -o shine.wast shine.cpp -``` +First, install [eos-bios](https://github.com/eoscanada/eos-bios) then follow +the [local-development-environment](https://github.com/eoscanada/eos-bios#local-development-environment) +instructions to start a local `nodeos` for development. -Once the WAST has been generated correctly, next step is to set the contract -on the account `shine` that was created in the preparation step: +Ensure that your `boot_sequence.yaml` contains the following content: (the content must comes +before the `Replacing eosio account from eosio.bios contract to eosio.system` block): ``` -cleos set contract shine `pwd` +- op: system.newaccount + label: Create account eosioforum + data: + creator: eosio + new_account: shine + pubkey: EOS5MHPYyhjBjnQZejzZHqHewPWhGTfQWSVTWYEhDmJu4SXkzgweP + +- op: system.newaccount + label: Create user account for shine + data: + creator: eosio + new_account: matt + pubkey: EOS5MHPYyhjBjnQZejzZHqHewPWhGTfQWSVTWYEhDmJu4SXkzgweP + +- op: system.newaccount + label: Create user account for shine + data: + creator: eosio + new_account: eve + pubkey: EOS5MHPYyhjBjnQZejzZHqHewPWhGTfQWSVTWYEhDmJu4SXkzgweP + +- op: system.newaccount + label: Create user account for shine + data: + creator: eosio + new_account: evan + pubkey: EOS5MHPYyhjBjnQZejzZHqHewPWhGTfQWSVTWYEhDmJu4SXkzgweP + +- op: system.newaccount + label: Create user account for shine + data: + creator: eosio + new_account: mike + pubkey: EOS5MHPYyhjBjnQZejzZHqHewPWhGTfQWSVTWYEhDmJu4SXkzgweP ``` -##### Testing +Import the following private key in your wallet: `5JpjqdhVCQTegTjrLtCSXHce7c9M8w7EXYZS7xC13jVFF4Phcrx` +(this is the private key for the public one `EOS5MHPYyhjBjnQZejzZHqHewPWhGTfQWSVTWYEhDmJu4SXkzgweP`, of +course, you can use your own pair if you change the public key part in the boot sequence). To make it easier to develop, the `shine_bot.rb` is a small command line -utility to interact more easily with the SmartContract. +utility to interact more easily with the smart contract. First, it's possible to run all command in a quick way by passing the flag `-q` to the CLI tool. This will not ask for question for which a default value @@ -133,20 +132,20 @@ the `member_id` being pass to the contract. Possible usage: -* `./shine_bot.rb --praise` - Perform a praise (author, praisee, memo) +* `./shine_bot.rb --post` - Perform a post (from, to, memo) * `./shine_bot.rb --vote` - Perform a vote (praise_id, voter) -* `./shine_bot.rb --rewards` - Compute the rewards (pot) -* `./shine_bot.rb --scenario` - Perform a scenario adding 6 praises and 10 votes. +* `./shine_bot.rb --reset` - Reset the all state to initial values +* `./shine_bot.rb --scenario` - Perform a scenario adding 6 posts and 10 votes. By using the scenario, you will automatically add a bunch of praises and -votes so it's easier to test your SmartContract code and changes afterward. +votes so it's easier to test your smart contract code and changes afterward. -### EOS SmartContract +### EOS smart contract #### References This section aims at providing links to documentation related to some concept -of building SmartContract for the EOS blockchain. +of building smart contract for the EOS blockchain. * `eosio::multi_index` diff --git a/contract/shine.abi b/contract/abi/shine.abi similarity index 100% rename from contract/shine.abi rename to contract/abi/shine.abi diff --git a/contract/build.sh b/contract/build.sh new file mode 100755 index 0000000..247ee1e --- /dev/null +++ b/contract/build.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +GREEN='\033[0;33m' +RED='\033[0;31m' +NC='\033[0m' + +printf "${GREEN}=========== Building shine ===========${NC}\n\n" + +BUILD_SUFFIX=${1} +CORES=`getconf _NPROCESSORS_ONLN` + +mkdir -p build${BUILD_SUFFIX} +pushd build${BUILD_SUFFIX} &> /dev/null +cmake ../ +make -j${CORES} +popd &> /dev/null \ No newline at end of file diff --git a/contract/asset.hpp b/contract/include/asset.hpp similarity index 100% rename from contract/asset.hpp rename to contract/include/asset.hpp diff --git a/contract/shine.hpp b/contract/include/shine.hpp similarity index 100% rename from contract/shine.hpp rename to contract/include/shine.hpp diff --git a/contract/table.hpp b/contract/include/table.hpp similarity index 100% rename from contract/table.hpp rename to contract/include/table.hpp diff --git a/contract/shine.wasm b/contract/shine.wasm deleted file mode 100755 index 664071fa847c0566250078b90094370bc6744167..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32193 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