From 8613bab257d392139febb022cba2f8c8e53562f4 Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Thu, 29 Aug 2019 10:34:15 -0300 Subject: [PATCH 01/39] issue - 154: Don't allow to vote when vesting balance is 0 --- libraries/wallet/wallet.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 812740e6..46acf25e 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -1995,6 +1995,13 @@ public: bool approve, bool broadcast /* = false */) { try { + std::vector vbo_info = get_vesting_balances(voting_account); + std::vector::iterator vbo_iter; + + vbo_iter = std::find_if(vbo_info.begin(), vbo_info.end(), [](vesting_balance_object_with_info const& obj){return obj.balance_type == vesting_balance_type::gpos;}); + if( vbo_info.size() == 0 || vbo_iter == vbo_info.end()) + FC_THROW("Account *** ${account} *** have insufficient or 0 vested balance(GPOS) to vote", ("account", voting_account)); + account_object voting_account_object = get_account(voting_account); account_id_type committee_member_owner_account_id = get_account_id(committee_member); fc::optional committee_member_obj = _remote_db->get_committee_member_by_account(committee_member_owner_account_id); @@ -2029,6 +2036,13 @@ public: bool approve, bool broadcast /* = false */) { try { + std::vector vbo_info = get_vesting_balances(voting_account); + std::vector::iterator vbo_iter; + + vbo_iter = std::find_if(vbo_info.begin(), vbo_info.end(), [](vesting_balance_object_with_info const& obj){return obj.balance_type == vesting_balance_type::gpos;}); + if( vbo_info.size() == 0 || vbo_iter == vbo_info.end()) + FC_THROW("Account *** ${account} *** have insufficient or 0 vested balance(GPOS) to vote", ("account", voting_account)); + account_object voting_account_object = get_account(voting_account); account_id_type witness_owner_account_id = get_account_id(witness); fc::optional witness_obj = _remote_db->get_witness_by_account(witness_owner_account_id); From 2a3d8a4c66456c18a7d7bd0790477a2f59295799 Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Fri, 20 Sep 2019 11:32:07 -0300 Subject: [PATCH 02/39] changes to withdraw_vesting feature(for both cdd and GPOS) --- libraries/chain/db_maint.cpp | 4 +- .../chain/include/graphene/chain/config.hpp | 1 + .../chain/protocol/chain_parameters.hpp | 5 ++ .../graphene/chain/protocol/vesting.hpp | 4 +- .../graphene/chain/vesting_balance_object.hpp | 2 +- libraries/chain/proposal_evaluator.cpp | 2 +- libraries/chain/vesting_balance_evaluator.cpp | 4 +- .../wallet/include/graphene/wallet/wallet.hpp | 4 +- libraries/wallet/wallet.cpp | 74 +++++++++++++++---- 9 files changed, 75 insertions(+), 25 deletions(-) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 06e15a19..81fce8f9 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -873,7 +873,7 @@ void schedule_pending_dividend_balances(database& db, std::map vesting_amounts; - auto balance_type = vesting_balance_type::unspecified; + auto balance_type = vesting_balance_type::normal; if(db.head_block_time() >= HARDFORK_GPOS_TIME) balance_type = vesting_balance_type::gpos; @@ -1403,7 +1403,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g d._committee_count_histogram_buffer.resize(props.parameters.maximum_committee_count / 2 + 1); d._total_voting_stake = 0; - auto balance_type = vesting_balance_type::unspecified; + auto balance_type = vesting_balance_type::normal; if(d.head_block_time() >= HARDFORK_GPOS_TIME) balance_type = vesting_balance_type::gpos; diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index 7b3e8743..fd080b09 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -228,3 +228,4 @@ #define TOURNAMENT_MAX_START_DELAY (60*60*24*7) // 1 week #define GPOS_PERIOD (60*60*24*30*6) // 6 months #define GPOS_SUBPERIOD (60*60*24*30) // 1 month +#define GPOS_VESTING_LOCKIN_PERIOD (60*60*24*30) // 1 month diff --git a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp index 87c2e3fe..a66e4ba8 100644 --- a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp +++ b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp @@ -43,6 +43,7 @@ namespace graphene { namespace chain { optional < uint32_t > gpos_period; optional < uint32_t > gpos_subperiod; optional < uint32_t > gpos_period_start; + optional < uint32_t > gpos_vesting_lockin_period; }; struct chain_parameters @@ -121,6 +122,9 @@ namespace graphene { namespace chain { inline uint32_t gpos_period_start()const { return extensions.value.gpos_period_start.valid() ? *extensions.value.gpos_period_start : HARDFORK_GPOS_TIME.sec_since_epoch(); /// current period start date } + inline uint32_t gpos_vesting_lockin_period()const { + return extensions.value.gpos_vesting_lockin_period.valid() ? *extensions.value.gpos_vesting_lockin_period : GPOS_VESTING_LOCKIN_PERIOD; /// GPOS vesting lockin period + } }; } } // graphene::chain @@ -134,6 +138,7 @@ FC_REFLECT( graphene::chain::parameter_extension, (gpos_period) (gpos_subperiod) (gpos_period_start) + (gpos_vesting_lockin_period) ) FC_REFLECT( graphene::chain::chain_parameters, diff --git a/libraries/chain/include/graphene/chain/protocol/vesting.hpp b/libraries/chain/include/graphene/chain/protocol/vesting.hpp index 5a78fd65..ac995aaf 100644 --- a/libraries/chain/include/graphene/chain/protocol/vesting.hpp +++ b/libraries/chain/include/graphene/chain/protocol/vesting.hpp @@ -26,7 +26,7 @@ namespace graphene { namespace chain { - enum class vesting_balance_type { unspecified, gpos }; + enum class vesting_balance_type { normal, gpos }; struct linear_vesting_policy_initializer { @@ -122,4 +122,4 @@ FC_REFLECT(graphene::chain::linear_vesting_policy_initializer, (begin_timestamp) FC_REFLECT(graphene::chain::cdd_vesting_policy_initializer, (start_claim)(vesting_seconds) ) FC_REFLECT_TYPENAME( graphene::chain::vesting_policy_initializer ) -FC_REFLECT_ENUM( graphene::chain::vesting_balance_type, (unspecified)(gpos) ) +FC_REFLECT_ENUM( graphene::chain::vesting_balance_type, (normal)(gpos) ) diff --git a/libraries/chain/include/graphene/chain/vesting_balance_object.hpp b/libraries/chain/include/graphene/chain/vesting_balance_object.hpp index 6e0bd689..a94e7015 100644 --- a/libraries/chain/include/graphene/chain/vesting_balance_object.hpp +++ b/libraries/chain/include/graphene/chain/vesting_balance_object.hpp @@ -146,7 +146,7 @@ namespace graphene { namespace chain { vesting_policy policy; /// We can have 2 types of vesting, gpos and all the rest - vesting_balance_type balance_type = vesting_balance_type::unspecified; + vesting_balance_type balance_type = vesting_balance_type::normal; vesting_balance_object() {} diff --git a/libraries/chain/proposal_evaluator.cpp b/libraries/chain/proposal_evaluator.cpp index 8306128d..a690ab33 100644 --- a/libraries/chain/proposal_evaluator.cpp +++ b/libraries/chain/proposal_evaluator.cpp @@ -137,7 +137,7 @@ struct proposal_operation_hardfork_visitor void operator()(const vesting_balance_create_operation &vbco) const { if(block_time < HARDFORK_GPOS_TIME) - FC_ASSERT( vbco.balance_type == vesting_balance_type::unspecified, "balance_type in vesting create not allowed yet!" ); + FC_ASSERT( vbco.balance_type == vesting_balance_type::normal, "balance_type in vesting create not allowed yet!" ); } // loop and self visit in proposals diff --git a/libraries/chain/vesting_balance_evaluator.cpp b/libraries/chain/vesting_balance_evaluator.cpp index 0b6e192e..bd44b934 100644 --- a/libraries/chain/vesting_balance_evaluator.cpp +++ b/libraries/chain/vesting_balance_evaluator.cpp @@ -43,7 +43,7 @@ void_result vesting_balance_create_evaluator::do_evaluate( const vesting_balance FC_ASSERT( !op.amount.asset_id(d).is_transfer_restricted() ); if(d.head_block_time() < HARDFORK_GPOS_TIME) // Todo: can be removed after gpos hf time pass - FC_ASSERT( op.balance_type == vesting_balance_type::unspecified); + FC_ASSERT( op.balance_type == vesting_balance_type::normal); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -101,7 +101,7 @@ object_id_type vesting_balance_create_evaluator::do_apply( const vesting_balance // forcing gpos policy linear_vesting_policy p; p.begin_timestamp = now; - p.vesting_cliff_seconds = gpo.parameters.gpos_subperiod(); + p.vesting_cliff_seconds = gpo.parameters.gpos_vesting_lockin_period(); p.vesting_duration_seconds = gpo.parameters.gpos_subperiod(); obj.policy = p; } diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index a7189138..2b8012b4 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1349,12 +1349,14 @@ class wallet_api * @param amount The amount to withdraw. * @param asset_symbol The symbol of the asset to withdraw. * @param broadcast true if you wish to broadcast the transaction + * @param vb_type vestig balance type to withdraw 0-OLD, 1-GPOS, 2-SONS(if required) */ signed_transaction withdraw_vesting( string witness_name, string amount, string asset_symbol, - bool broadcast = false); + bool broadcast = false, + uint8_t vb_type = 0); /** Vote for a given committee_member. * diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 46acf25e..75a90f82 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -1963,26 +1963,64 @@ public: string witness_name, string amount, string asset_symbol, - bool broadcast = false ) + bool broadcast = false, + uint8_t vb_type = 0 ) { try { asset_object asset_obj = get_asset( asset_symbol ); + vector< vesting_balance_object > vbos; fc::optional vbid = maybe_id(witness_name); if( !vbid ) { - witness_object wit = get_witness( witness_name ); - FC_ASSERT( wit.pay_vb ); - vbid = wit.pay_vb; + //Changes done to retrive user accounts along with witnesses accounts based on account name + fc::optional acct_id = maybe_id( witness_name ); + if( !acct_id ) + acct_id = get_account( witness_name ).id; + + vbos = _remote_db->get_vesting_balances( *acct_id ); + if( vbos.size() == 0 ) + { + witness_object wit = get_witness( witness_name ); + FC_ASSERT( wit.pay_vb ); + vbid = wit.pay_vb; + } } - vesting_balance_object vbo = get_object< vesting_balance_object >( *vbid ); - vesting_balance_withdraw_operation vesting_balance_withdraw_op; - - vesting_balance_withdraw_op.vesting_balance = *vbid; - vesting_balance_withdraw_op.owner = vbo.owner; - vesting_balance_withdraw_op.amount = asset_obj.amount_from_string(amount); - + //whether it is a witness or user, keep in container and iterate over it process all vesting balances and types + if(!vbos.size()) + vbos.emplace_back( get_object(*vbid) ); + signed_transaction tx; - tx.operations.push_back( vesting_balance_withdraw_op ); + asset withdraw_amount = asset_obj.amount_from_string(amount); + + for(const vesting_balance_object& vbo: vbos ) + { + if((vb_type == (uint8_t)vbo.balance_type) && vbo.balance.amount > 0) + { + fc::optional vest_id = vbo.id; + vesting_balance_withdraw_operation vesting_balance_withdraw_op; + + vesting_balance_withdraw_op.vesting_balance = *vest_id; + vesting_balance_withdraw_op.owner = vbo.owner; + if(withdraw_amount.amount >= vbo.balance.amount) + { + vesting_balance_withdraw_op.amount = vbo.balance.amount; + withdraw_amount.amount -= vbo.balance.amount; + } + else + { + vesting_balance_withdraw_op.amount = withdraw_amount.amount; + tx.operations.push_back( vesting_balance_withdraw_op ); + withdraw_amount.amount -= vbo.balance.amount; + break; + } + + tx.operations.push_back( vesting_balance_withdraw_op ); + } + } + + if( withdraw_amount.amount > 0) + FC_THROW("Account has insufficient balance to withdraw"); + set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees ); tx.validate(); @@ -4045,9 +4083,10 @@ signed_transaction wallet_api::withdraw_vesting( string witness_name, string amount, string asset_symbol, - bool broadcast /* = false */) + bool broadcast, + uint8_t vb_type) { - return my->withdraw_vesting( witness_name, amount, asset_symbol, broadcast ); + return my->withdraw_vesting( witness_name, amount, asset_symbol, broadcast, vb_type ); } signed_transaction wallet_api::vote_for_committee_member(string voting_account, @@ -5783,7 +5822,7 @@ signed_transaction wallet_api::create_vesting_balance(string owner, fc::optional asset_obj = get_asset(asset_symbol); - auto type = vesting_balance_type::unspecified; + auto type = vesting_balance_type::normal; if(is_gpos) type = vesting_balance_type::gpos; @@ -5856,7 +5895,10 @@ vesting_balance_object_with_info::vesting_balance_object_with_info( const vestin : vesting_balance_object( vbo ) { allowed_withdraw = get_allowed_withdraw( now ); - allowed_withdraw_time = now; + if(vbo.balance_type == vesting_balance_type::gpos) + allowed_withdraw_time = vbo.policy.get().begin_timestamp + vbo.policy.get().vesting_cliff_seconds; + else + allowed_withdraw_time = now; } } } // graphene::wallet From b358241e43fbaca0669c9ab34d4116e96822bb9d Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Fri, 20 Sep 2019 14:03:59 -0300 Subject: [PATCH 03/39] Comments update --- libraries/wallet/wallet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 75a90f82..185fc7d1 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -1971,7 +1971,7 @@ public: fc::optional vbid = maybe_id(witness_name); if( !vbid ) { - //Changes done to retrive user accounts along with witnesses accounts based on account name + //Changes done to retrive user account/witness account based on account name fc::optional acct_id = maybe_id( witness_name ); if( !acct_id ) acct_id = get_account( witness_name ).id; @@ -1985,7 +1985,7 @@ public: } } - //whether it is a witness or user, keep in container and iterate over it process all vesting balances and types + //whether it is a witness or user, keep it in a container and iterate over to process all vesting balances and types if(!vbos.size()) vbos.emplace_back( get_object(*vbid) ); From 8e1c0385589e68ce879f07bc8b131690ba9b6090 Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Fri, 20 Sep 2019 16:58:06 -0300 Subject: [PATCH 04/39] update to GPOS hardfork ref --- .../chain/include/graphene/chain/protocol/chain_parameters.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp index a66e4ba8..b020c4b4 100644 --- a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp +++ b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp @@ -27,7 +27,7 @@ #include #include -#include +#include <../hardfork.d/GPOS.hf> namespace graphene { namespace chain { struct fee_schedule; } } From 4a72f943e8347fd1125d258015632c9fc9361de0 Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Sat, 21 Sep 2019 13:04:43 -0300 Subject: [PATCH 05/39] fix for get_vesting_balance API call --- libraries/chain/vesting_balance_object.cpp | 35 ++++++++++++++-------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/libraries/chain/vesting_balance_object.cpp b/libraries/chain/vesting_balance_object.cpp index 73448e04..794413d1 100644 --- a/libraries/chain/vesting_balance_object.cpp +++ b/libraries/chain/vesting_balance_object.cpp @@ -35,6 +35,7 @@ inline bool sum_below_max_shares(const asset& a, const asset& b) } asset linear_vesting_policy::get_allowed_withdraw( const vesting_policy_context& ctx )const +{ { share_type allowed_withdraw = 0; @@ -45,23 +46,33 @@ asset linear_vesting_policy::get_allowed_withdraw( const vesting_policy_context& if( elapsed_seconds >= vesting_cliff_seconds ) { - share_type total_vested = 0; - if( elapsed_seconds < vesting_duration_seconds ) + // BLOCKBACK-154 fix, Begin balance for linear vesting applies only to initial account balance from genesis + // So, for any GPOS vesting, the begin balance would be 0 and should be able to withdraw balance amount based on lockin period + if(begin_balance == 0) { - total_vested = (fc::uint128_t( begin_balance.value ) * elapsed_seconds / vesting_duration_seconds).to_uint64(); + allowed_withdraw = ctx.balance.amount; + return asset( allowed_withdraw, ctx.balance.asset_id ); } else { - total_vested = begin_balance; + share_type total_vested = 0; + if( elapsed_seconds < vesting_duration_seconds ) + { + total_vested = (fc::uint128_t( begin_balance.value ) * elapsed_seconds / vesting_duration_seconds).to_uint64(); + } + else + { + total_vested = begin_balance; + } + assert( total_vested >= 0 ); + + const share_type withdrawn_already = begin_balance - ctx.balance.amount; + assert( withdrawn_already >= 0 ); + + allowed_withdraw = total_vested - withdrawn_already; + assert( allowed_withdraw >= 0 ); } - assert( total_vested >= 0 ); - - const share_type withdrawn_already = begin_balance - ctx.balance.amount; - assert( withdrawn_already >= 0 ); - - allowed_withdraw = total_vested - withdrawn_already; - assert( allowed_withdraw >= 0 ); - } + } } return asset( allowed_withdraw, ctx.balance.asset_id ); From a7df686ebe92e6ac25c310a714bd34d26dc6c612 Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Sat, 21 Sep 2019 13:08:33 -0300 Subject: [PATCH 06/39] braces update --- libraries/chain/vesting_balance_object.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/chain/vesting_balance_object.cpp b/libraries/chain/vesting_balance_object.cpp index 794413d1..afba2557 100644 --- a/libraries/chain/vesting_balance_object.cpp +++ b/libraries/chain/vesting_balance_object.cpp @@ -35,7 +35,6 @@ inline bool sum_below_max_shares(const asset& a, const asset& b) } asset linear_vesting_policy::get_allowed_withdraw( const vesting_policy_context& ctx )const -{ { share_type allowed_withdraw = 0; From db01f313e5d0b80f1dd75d50e8e7173bc9e50c02 Mon Sep 17 00:00:00 2001 From: Roshan Syed Date: Wed, 25 Sep 2019 10:30:15 -0300 Subject: [PATCH 07/39] Create .gitlab-ci.yml --- .gitlab-ci.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..620c6673 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,29 @@ +stages: + - build + - test + +build: + stage: build + script: + - git submodule update --init --recursive + - cmake . + - make -j$(nproc) + artifacts: + untracked: true + paths: + - libraries/ + - programs/ + - tests/ + tags: + - builder + +test: + stage: test + dependencies: + - build + script: + - ./tests/betting_test + - ./tests/chain_test + - ./tests/cli_test + tags: + - builder From 7fae375e0f03f61901c43b66276f3f5d46b78c86 Mon Sep 17 00:00:00 2001 From: Bobinson K B Date: Thu, 26 Sep 2019 11:41:28 -0400 Subject: [PATCH 08/39] fixing build errors (#150) * fixing build errors vest type correction * fixing build errors vest type correction * fixes new Dockerfile * vesting_balance_type correction vesting_balance_type changed to normal * gcc5 support to Dockerfile gcc5 support to Dockerfile --- Dockerfile | 70 +++++++++++++++++++++----------- tests/tests/operation_tests.cpp | 6 +-- tests/tests/operation_tests2.cpp | 4 +- 3 files changed, 51 insertions(+), 29 deletions(-) diff --git a/Dockerfile b/Dockerfile index a3cc326a..fa7cb87a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,44 +1,66 @@ -FROM phusion/baseimage:0.9.19 +FROM ubuntu:18.04 MAINTAINER PeerPlays Blockchain Standards Association -ENV LANG=en_US.UTF-8 +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US.UTF-8 +ENV LC_ALL en_US.UTF-8 + RUN \ apt-get update -y && \ - apt-get install -y \ - g++ \ + DEBIAN_FRONTEND=noninteractive apt-get install -y \ autoconf \ - cmake \ - git \ - libbz2-dev \ - libreadline-dev \ - libboost-all-dev \ - libcurl4-openssl-dev \ - libssl-dev \ - libncurses-dev \ - doxygen \ + gcc-5 \ + g++-5 \ + bash \ + build-essential \ ca-certificates \ + cmake \ + doxygen \ + git \ + graphviz \ + libbz2-dev \ + libcurl4-openssl-dev \ + libncurses-dev \ + libreadline-dev \ + libssl-dev \ + libtool \ + locales \ + ntp \ + pkg-config \ + wget \ && \ - apt-get update -y && \ - apt-get install -y fish && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* +RUN \ + sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \ + locale-gen + +# Compile Boost +RUN \ + BOOST_ROOT=$HOME/boost_1_67_0 && \ + wget -c 'http://sourceforge.net/projects/boost/files/boost/1.67.0/boost_1_67_0.tar.gz/download' -O boost_1_67_0.tar.gz &&\ + tar -zxvf boost_1_67_0.tar.gz && \ + cd boost_1_67_0/ && \ + ./bootstrap.sh "--prefix=$BOOST_ROOT" && \ + ./b2 install && \ + cd .. + ADD . /peerplays-core WORKDIR /peerplays-core -# Compile +# Compile Peerplays RUN \ - ( git submodule sync --recursive || \ - find `pwd` -type f -name .git | \ - while read f; do \ - rel="$(echo "${f#$PWD/}" | sed 's=[^/]*/=../=g')"; \ - sed -i "s=: .*/.git/=: $rel/=" "$f"; \ - done && \ - git submodule sync --recursive ) && \ + BOOST_ROOT=$HOME/boost_1_67_0 && \ + export CC=gcc-5 ; export CXX=g++-5\ git submodule update --init --recursive && \ + mkdir build && \ + mkdir build/release && \ + cd build/release && \ cmake \ + -DBOOST_ROOT="$BOOST_ROOT" \ -DCMAKE_BUILD_TYPE=Release \ - . && \ + ../.. && \ make witness_node cli_wallet && \ install -s programs/witness_node/witness_node programs/cli_wallet/cli_wallet /usr/local/bin && \ # diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index c1278021..e04db96c 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -1560,7 +1560,7 @@ BOOST_AUTO_TEST_CASE( vesting_balance_create_test ) op.amount = test_asset.amount( 100 ); //op.vesting_seconds = 60*60*24; op.policy = cdd_vesting_policy_initializer{ 60*60*24 }; - op.balance_type == vesting_balance_type::unspecified; + op.balance_type == vesting_balance_type::normal; // Fee must be non-negative REQUIRE_OP_VALIDATION_SUCCESS( op, fee, core.amount(1) ); @@ -1580,7 +1580,7 @@ BOOST_AUTO_TEST_CASE( vesting_balance_create_test ) op.creator = alice_account.get_id(); op.owner = alice_account.get_id(); - op.balance_type = vesting_balance_type::unspecified; + op.balance_type = vesting_balance_type::normal; account_id_type nobody = account_id_type(1234); @@ -1651,7 +1651,7 @@ BOOST_AUTO_TEST_CASE( vesting_balance_withdraw_test ) create_op.owner = owner; create_op.amount = amount; create_op.policy = cdd_vesting_policy_initializer(vesting_seconds); - create_op.balance_type = vesting_balance_type::unspecified; + create_op.balance_type = vesting_balance_type::normal; tx.operations.push_back( create_op ); set_expiration( db, tx ); diff --git a/tests/tests/operation_tests2.cpp b/tests/tests/operation_tests2.cpp index 9b6bb5ee..834d2d42 100644 --- a/tests/tests/operation_tests2.cpp +++ b/tests/tests/operation_tests2.cpp @@ -1312,7 +1312,7 @@ BOOST_AUTO_TEST_CASE(zero_second_vbo) create_op.owner = alice_id; create_op.amount = asset(500); create_op.policy = pinit; - create_op.balance_type = vesting_balance_type::unspecified; + create_op.balance_type = vesting_balance_type::normal; signed_transaction create_tx; create_tx.operations.push_back( create_op ); @@ -1396,7 +1396,7 @@ BOOST_AUTO_TEST_CASE( vbo_withdraw_different ) create_op.owner = alice_id; create_op.amount = asset(100, stuff_id); create_op.policy = pinit; - create_op.balance_type = vesting_balance_type::unspecified; + create_op.balance_type = vesting_balance_type::normal; signed_transaction create_tx; create_tx.operations.push_back( create_op ); From f1eb625df8a23d6fa5498e093cf4fe25a0c41699 Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Mon, 30 Sep 2019 00:27:21 -0300 Subject: [PATCH 09/39] Changes to compiple with GCC 7(Ubuntu 18.04) --- CMakeLists.txt | 4 ++++ .../chain/include/graphene/chain/vesting_balance_object.hpp | 4 ++-- libraries/net/CMakeLists.txt | 2 +- libraries/wallet/CMakeLists.txt | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 20d96a9a..e939f113 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -120,6 +120,10 @@ else( WIN32 ) # Apple AND Linux set( CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++11 -Wall" ) set( rt_library rt ) set( pthread_library pthread) + set(CMAKE_LINKER_FLAGS "-pthread" CACHE STRING "Linker Flags" FORCE) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_LINKER_FLAGS}" CACHE STRING "" FORCE) + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS}" CACHE STRING "" FORCE) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS}" CACHE STRING "" FORCE) if ( NOT DEFINED crypto_library ) # I'm not sure why this is here, I guess someone has openssl and can't detect it with find_package()? # if you have a normal install, you can define crypto_library to the empty string to avoid a build error diff --git a/libraries/chain/include/graphene/chain/vesting_balance_object.hpp b/libraries/chain/include/graphene/chain/vesting_balance_object.hpp index a94e7015..ec789f30 100644 --- a/libraries/chain/include/graphene/chain/vesting_balance_object.hpp +++ b/libraries/chain/include/graphene/chain/vesting_balance_object.hpp @@ -189,9 +189,9 @@ namespace graphene { namespace chain { ordered_non_unique< tag, composite_key< vesting_balance_object, - member_offset, + member_offset, member, - member_offset + member_offset //member //member_offset >, diff --git a/libraries/net/CMakeLists.txt b/libraries/net/CMakeLists.txt index 39f9cd05..7aa617d7 100644 --- a/libraries/net/CMakeLists.txt +++ b/libraries/net/CMakeLists.txt @@ -13,7 +13,7 @@ target_link_libraries( graphene_net PUBLIC fc graphene_db ) target_include_directories( graphene_net PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" - PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../chain/include" + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../chain/include" "${CMAKE_CURRENT_BINARY_DIR}/../chain/include" ) if(MSVC) diff --git a/libraries/wallet/CMakeLists.txt b/libraries/wallet/CMakeLists.txt index 74b9f7c5..8c9f8790 100644 --- a/libraries/wallet/CMakeLists.txt +++ b/libraries/wallet/CMakeLists.txt @@ -10,7 +10,7 @@ if( PERL_FOUND AND DOXYGEN_FOUND AND NOT "${CMAKE_GENERATOR}" STREQUAL "Ninja" ) COMMAND ${DOXYGEN_EXECUTABLE} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile include/graphene/wallet/wallet.hpp ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/api_documentation.cpp - COMMAND PERLLIB=${CMAKE_CURRENT_SOURCE_DIR} ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/generate_api_documentation.pl ${CMAKE_CURRENT_BINARY_DIR}/api_documentation.cpp.new + COMMAND PERLLIB=${CMAKE_CURRENT_BINARY_DIR} ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/generate_api_documentation.pl ${CMAKE_CURRENT_BINARY_DIR}/api_documentation.cpp.new COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/api_documentation.cpp.new ${CMAKE_CURRENT_BINARY_DIR}/api_documentation.cpp COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_CURRENT_BINARY_DIR}/api_documentation.cpp.new From d65f20a89fc941d6b06643c8a78846a1aa1d104f Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Thu, 3 Oct 2019 16:38:40 -0300 Subject: [PATCH 10/39] changes to have separate methods and single withdrawl fee for multiple vest objects --- .../chain/vesting_balance_evaluator.hpp | 1 + libraries/chain/vesting_balance_evaluator.cpp | 26 ++++++- .../wallet/include/graphene/wallet/wallet.hpp | 21 ++++- libraries/wallet/wallet.cpp | 78 +++++++++++++++---- 4 files changed, 107 insertions(+), 19 deletions(-) diff --git a/libraries/chain/include/graphene/chain/vesting_balance_evaluator.hpp b/libraries/chain/include/graphene/chain/vesting_balance_evaluator.hpp index fccfbb75..9bb7520e 100644 --- a/libraries/chain/include/graphene/chain/vesting_balance_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/vesting_balance_evaluator.hpp @@ -46,6 +46,7 @@ class vesting_balance_withdraw_evaluator : public evaluator(); + + const time_point_sec now = d.head_block_time(); + + if(now >= (fc::time_point_sec(1570114100)) ) + { + if(oper.fee.amount == 0) + { + trx_state->skip_fee_schedule_check = true; + trx_state->skip_fee = true; + } + } + //check_required_authorities(op); + auto result = evaluate( oper ); + + if( apply ) result = this->apply( oper ); + return result; +} FC_CAPTURE_AND_RETHROW() } + void_result vesting_balance_withdraw_evaluator::do_evaluate( const vesting_balance_withdraw_operation& op ) { try { const database& d = db(); @@ -125,7 +148,7 @@ void_result vesting_balance_withdraw_evaluator::do_evaluate( const vesting_balan FC_ASSERT( vbo.is_withdraw_allowed( now, op.amount ), "", ("now", now)("op", op)("vbo", vbo) ); assert( op.amount <= vbo.balance ); // is_withdraw_allowed should fail before this check is reached - /* const account_object& owner_account = */ op.owner( d ); + /* const account_object& owner_account = op.owner( d ); */ // TODO: Check asset authorizations and withdrawals return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -133,6 +156,7 @@ void_result vesting_balance_withdraw_evaluator::do_evaluate( const vesting_balan void_result vesting_balance_withdraw_evaluator::do_apply( const vesting_balance_withdraw_operation& op ) { try { database& d = db(); + const time_point_sec now = d.head_block_time(); const vesting_balance_object& vbo = op.vesting_balance( d ); diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 2b8012b4..8a15fec0 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1343,20 +1343,32 @@ class wallet_api vector< vesting_balance_object_with_info > get_vesting_balances( string account_name ); /** - * Withdraw a vesting balance. + * Withdraw a normal(old) vesting balance. * * @param witness_name The account name of the witness, also accepts account ID or vesting balance ID type. * @param amount The amount to withdraw. * @param asset_symbol The symbol of the asset to withdraw. * @param broadcast true if you wish to broadcast the transaction - * @param vb_type vestig balance type to withdraw 0-OLD, 1-GPOS, 2-SONS(if required) */ signed_transaction withdraw_vesting( string witness_name, string amount, string asset_symbol, - bool broadcast = false, - uint8_t vb_type = 0); + bool broadcast = false); + + /** + * Withdraw a GPOS vesting balance. + * + * @param account_name The account name of the witness/user, also accepts account ID or vesting balance ID type. + * @param amount The amount to withdraw. + * @param asset_symbol The symbol of the asset to withdraw. + * @param broadcast true if you wish to broadcast the transaction + */ + signed_transaction withdraw_GPOS_vesting_balance( + string account_name, + string amount, + string asset_symbol, + bool broadcast = false); /** Vote for a given committee_member. * @@ -1966,6 +1978,7 @@ FC_API( graphene::wallet::wallet_api, (update_worker_votes) (get_vesting_balances) (withdraw_vesting) + (withdraw_GPOS_vesting_balance) (vote_for_committee_member) (vote_for_witness) (update_witness_votes) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 185fc7d1..b6aa2cbf 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -1963,23 +1963,57 @@ public: string witness_name, string amount, string asset_symbol, - bool broadcast = false, - uint8_t vb_type = 0 ) + bool broadcast = false ) { try { asset_object asset_obj = get_asset( asset_symbol ); - vector< vesting_balance_object > vbos; fc::optional vbid = maybe_id(witness_name); if( !vbid ) + { + witness_object wit = get_witness( witness_name ); + FC_ASSERT( wit.pay_vb ); + vbid = wit.pay_vb; + } + + vesting_balance_object vbo = get_object< vesting_balance_object >( *vbid ); + + if(vbo.balance_type != vesting_balance_type::normal) + FC_THROW("Allowed to withdraw only Normal type vest balances with this method"); + + vesting_balance_withdraw_operation vesting_balance_withdraw_op; + + vesting_balance_withdraw_op.vesting_balance = *vbid; + vesting_balance_withdraw_op.owner = vbo.owner; + vesting_balance_withdraw_op.amount = asset_obj.amount_from_string(amount); + + signed_transaction tx; + tx.operations.push_back( vesting_balance_withdraw_op ); + set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees ); + tx.validate(); + + return sign_transaction( tx, broadcast ); + } FC_CAPTURE_AND_RETHROW( (witness_name)(amount) ) + } + + signed_transaction withdraw_GPOS_vesting_balance( + string account_name, + string amount, + string asset_symbol, + bool broadcast = false) + { try { + asset_object asset_obj = get_asset( asset_symbol ); + vector< vesting_balance_object > vbos; + fc::optional vbid = maybe_id(account_name); + if( !vbid ) { //Changes done to retrive user account/witness account based on account name - fc::optional acct_id = maybe_id( witness_name ); + fc::optional acct_id = maybe_id( account_name ); if( !acct_id ) - acct_id = get_account( witness_name ).id; + acct_id = get_account( account_name ).id; vbos = _remote_db->get_vesting_balances( *acct_id ); if( vbos.size() == 0 ) { - witness_object wit = get_witness( witness_name ); + witness_object wit = get_witness( account_name ); FC_ASSERT( wit.pay_vb ); vbid = wit.pay_vb; } @@ -1991,14 +2025,22 @@ public: signed_transaction tx; asset withdraw_amount = asset_obj.amount_from_string(amount); - + bool onetime_fee_paid = false; + for(const vesting_balance_object& vbo: vbos ) { - if((vb_type == (uint8_t)vbo.balance_type) && vbo.balance.amount > 0) + if((vbo.balance_type == vesting_balance_type::gpos) && vbo.balance.amount > 0) { fc::optional vest_id = vbo.id; vesting_balance_withdraw_operation vesting_balance_withdraw_op; + // Since there are multiple vesting objects, below logic with vesting_balance_evaluator.cpp changes will + // deduct fee from single object and set withdrawl fee to 0 for rest of objects based on requested amount. + if(onetime_fee_paid) + vesting_balance_withdraw_op.fee = asset( 0, asset_id_type() ); + else + vesting_balance_withdraw_op.fee = _remote_db->get_global_properties().parameters.current_fees->calculate_fee(vesting_balance_withdraw_op); + vesting_balance_withdraw_op.vesting_balance = *vest_id; vesting_balance_withdraw_op.owner = vbo.owner; if(withdraw_amount.amount >= vbo.balance.amount) @@ -2015,17 +2057,17 @@ public: } tx.operations.push_back( vesting_balance_withdraw_op ); + onetime_fee_paid = true; } } if( withdraw_amount.amount > 0) - FC_THROW("Account has insufficient balance to withdraw"); + FC_THROW("Account has NO or Insufficient balance to withdraw"); - set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees ); tx.validate(); return sign_transaction( tx, broadcast ); - } FC_CAPTURE_AND_RETHROW( (witness_name)(amount) ) + } FC_CAPTURE_AND_RETHROW( (account_name)(amount) ) } signed_transaction vote_for_committee_member(string voting_account, @@ -4083,10 +4125,18 @@ signed_transaction wallet_api::withdraw_vesting( string witness_name, string amount, string asset_symbol, - bool broadcast, - uint8_t vb_type) + bool broadcast) { - return my->withdraw_vesting( witness_name, amount, asset_symbol, broadcast, vb_type ); + return my->withdraw_vesting( witness_name, amount, asset_symbol, broadcast ); +} + +signed_transaction wallet_api::withdraw_GPOS_vesting_balance( + string account_name, + string amount, + string asset_symbol, + bool broadcast) +{ + return my->withdraw_GPOS_vesting_balance( account_name, amount, asset_symbol, broadcast ); } signed_transaction wallet_api::vote_for_committee_member(string voting_account, From c73d0a338a1ded621a28064e30131ff4de650c68 Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Thu, 3 Oct 2019 22:22:21 -0300 Subject: [PATCH 11/39] 163-fix, Return only non-zero vesting balances --- libraries/app/database_api.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index 3f95a8c1..e3e82790 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -935,7 +935,8 @@ vector database_api_impl::get_vesting_balances( account_ auto vesting_range = _db.get_index_type().indices().get().equal_range(account_id); std::for_each(vesting_range.first, vesting_range.second, [&result](const vesting_balance_object& balance) { - result.emplace_back(balance); + if(balance.balance.amount > 0) + result.emplace_back(balance); }); return result; } From c025f639d7e9f3479438dde8be217f762ec6ac67 Mon Sep 17 00:00:00 2001 From: Sandip Patel Date: Sat, 19 Oct 2019 10:58:56 +0530 Subject: [PATCH 12/39] Fixed few error messages --- libraries/chain/vesting_balance_evaluator.cpp | 2 +- .../wallet/include/graphene/wallet/wallet.hpp | 7 +++ libraries/wallet/wallet.cpp | 60 ++++++++++++++++--- 3 files changed, 61 insertions(+), 8 deletions(-) diff --git a/libraries/chain/vesting_balance_evaluator.cpp b/libraries/chain/vesting_balance_evaluator.cpp index 22cf544f..9630d011 100644 --- a/libraries/chain/vesting_balance_evaluator.cpp +++ b/libraries/chain/vesting_balance_evaluator.cpp @@ -145,7 +145,7 @@ void_result vesting_balance_withdraw_evaluator::do_evaluate( const vesting_balan const vesting_balance_object& vbo = op.vesting_balance( d ); FC_ASSERT( op.owner == vbo.owner, "", ("op.owner", op.owner)("vbo.owner", vbo.owner) ); - FC_ASSERT( vbo.is_withdraw_allowed( now, op.amount ), "", ("now", now)("op", op)("vbo", vbo) ); + FC_ASSERT( vbo.is_withdraw_allowed( now, op.amount ), "GPOS Vested Balance cannont be withdrwan during the locking period", ("now", now)("op", op)("vbo", vbo) ); assert( op.amount <= vbo.balance ); // is_withdraw_allowed should fail before this check is reached /* const account_object& owner_account = op.owner( d ); */ diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 8a15fec0..fed7d55d 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1265,6 +1265,12 @@ class wallet_api */ witness_object get_witness(string owner_account); + /** Returns true if the account is witness, false otherwise + * @param owner_account the name or id of the witness account owner, or the id of the witness + * @returns true if account is witness, false otherwise + */ + bool is_witness(string owner_account); + /** Returns information about the given committee_member. * @param owner_account the name or id of the committee_member account owner, or the id of the committee_member * @returns the information about the committee_member stored in the block chain @@ -1969,6 +1975,7 @@ FC_API( graphene::wallet::wallet_api, (whitelist_account) (create_committee_member) (get_witness) + (is_witness) (get_committee_member) (list_witnesses) (list_committee_members) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index b6aa2cbf..75c47d8a 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -1720,6 +1720,42 @@ public: FC_CAPTURE_AND_RETHROW( (owner_account) ) } + bool is_witness(string owner_account) + { + try + { + fc::optional witness_id = maybe_id(owner_account); + if (witness_id) + { + std::vector ids_to_get; + ids_to_get.push_back(*witness_id); + std::vector> witness_objects = _remote_db->get_witnesses(ids_to_get); + if (witness_objects.front()) + return true; + else + return false; + } + else + { + // then maybe it's the owner account + try + { + account_id_type owner_account_id = get_account_id(owner_account); + fc::optional witness = _remote_db->get_witness_by_account(owner_account_id); + if (witness) + return true; + else + return false; + } + catch (const fc::exception&) + { + return false; + } + } + } + FC_CAPTURE_AND_RETHROW( (owner_account) ) + } + committee_member_object get_committee_member(string owner_account) { try @@ -2013,9 +2049,14 @@ public: vbos = _remote_db->get_vesting_balances( *acct_id ); if( vbos.size() == 0 ) { - witness_object wit = get_witness( account_name ); - FC_ASSERT( wit.pay_vb ); - vbid = wit.pay_vb; + if (is_witness(account_name)) + { + witness_object wit = get_witness( account_name ); + FC_ASSERT( wit.pay_vb ); + vbid = wit.pay_vb; + } + else + FC_THROW("Account ${account} has no core TOKEN vested and thus its not allowed to withdraw.", ("account", account_name)); } } @@ -2080,7 +2121,7 @@ public: vbo_iter = std::find_if(vbo_info.begin(), vbo_info.end(), [](vesting_balance_object_with_info const& obj){return obj.balance_type == vesting_balance_type::gpos;}); if( vbo_info.size() == 0 || vbo_iter == vbo_info.end()) - FC_THROW("Account *** ${account} *** have insufficient or 0 vested balance(GPOS) to vote", ("account", voting_account)); + FC_THROW("Account ${account} has no core Token vested and thus she will not be allowed to vote for the committee member", ("account", voting_account)); account_object voting_account_object = get_account(voting_account); account_id_type committee_member_owner_account_id = get_account_id(committee_member); @@ -2121,7 +2162,7 @@ public: vbo_iter = std::find_if(vbo_info.begin(), vbo_info.end(), [](vesting_balance_object_with_info const& obj){return obj.balance_type == vesting_balance_type::gpos;}); if( vbo_info.size() == 0 || vbo_iter == vbo_info.end()) - FC_THROW("Account *** ${account} *** have insufficient or 0 vested balance(GPOS) to vote", ("account", voting_account)); + FC_THROW("Account ${account} has no core Token vested and thus she will not be allowed to vote for the witness", ("account", voting_account)); account_object voting_account_object = get_account(voting_account); account_id_type witness_owner_account_id = get_account_id(witness); @@ -2132,13 +2173,13 @@ public: { auto insert_result = voting_account_object.options.votes.insert(witness_obj->vote_id); if (!insert_result.second) - FC_THROW("Account ${account} was already voting for witness ${witness}", ("account", voting_account)("witness", witness)); + FC_THROW("Account ${account} has already voted for witness ${witness}", ("account", voting_account)("witness", witness)); } else { unsigned votes_removed = voting_account_object.options.votes.erase(witness_obj->vote_id); if (!votes_removed) - FC_THROW("Account ${account} is already not voting for witness ${witness}", ("account", voting_account)("witness", witness)); + FC_THROW("Account ${account} has not voted for witness ${witness}", ("account", voting_account)("witness", witness)); } account_update_operation account_update_op; account_update_op.account = voting_account_object.id; @@ -4073,6 +4114,11 @@ witness_object wallet_api::get_witness(string owner_account) return my->get_witness(owner_account); } +bool wallet_api::is_witness(string owner_account) +{ + return my->is_witness(owner_account); +} + committee_member_object wallet_api::get_committee_member(string owner_account) { return my->get_committee_member(owner_account); From 0800e2bc6710cd67394943812fbddf29e88cee91 Mon Sep 17 00:00:00 2001 From: Sandip Patel Date: Sat, 19 Oct 2019 16:38:12 +0530 Subject: [PATCH 13/39] error message corrections at other places --- .../include/graphene/chain/protocol/vesting.hpp | 10 ++++++++++ libraries/chain/vesting_balance_evaluator.cpp | 3 ++- libraries/wallet/wallet.cpp | 13 +++++++++---- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/libraries/chain/include/graphene/chain/protocol/vesting.hpp b/libraries/chain/include/graphene/chain/protocol/vesting.hpp index ac995aaf..2a861b2a 100644 --- a/libraries/chain/include/graphene/chain/protocol/vesting.hpp +++ b/libraries/chain/include/graphene/chain/protocol/vesting.hpp @@ -28,6 +28,16 @@ namespace graphene { namespace chain { enum class vesting_balance_type { normal, gpos }; + inline std::string get_vesting_balance_type(vesting_balance_type type) { + switch (type) { + case vesting_balance_type::normal: + return "NORMAL"; + case vesting_balance_type::gpos: + default: + return "GPOS"; + } + } + struct linear_vesting_policy_initializer { /** while vesting begins on begin_timestamp, none may be claimed before vesting_cliff_seconds have passed */ diff --git a/libraries/chain/vesting_balance_evaluator.cpp b/libraries/chain/vesting_balance_evaluator.cpp index 9630d011..9f42d4ff 100644 --- a/libraries/chain/vesting_balance_evaluator.cpp +++ b/libraries/chain/vesting_balance_evaluator.cpp @@ -145,7 +145,8 @@ void_result vesting_balance_withdraw_evaluator::do_evaluate( const vesting_balan const vesting_balance_object& vbo = op.vesting_balance( d ); FC_ASSERT( op.owner == vbo.owner, "", ("op.owner", op.owner)("vbo.owner", vbo.owner) ); - FC_ASSERT( vbo.is_withdraw_allowed( now, op.amount ), "GPOS Vested Balance cannont be withdrwan during the locking period", ("now", now)("op", op)("vbo", vbo) ); + FC_ASSERT( vbo.is_withdraw_allowed( now, op.amount ), "${balance_type} Vested Balance cannont be withdrwan during the locking period", + ("balance_type", get_vesting_balance_type(vbo.balance_type))("now", now)("op", op)("vbo", vbo) ); assert( op.amount <= vbo.balance ); // is_withdraw_allowed should fail before this check is reached /* const account_object& owner_account = op.owner( d ); */ diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 75c47d8a..c7e605cc 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2005,9 +2005,14 @@ public: fc::optional vbid = maybe_id(witness_name); if( !vbid ) { - witness_object wit = get_witness( witness_name ); - FC_ASSERT( wit.pay_vb ); - vbid = wit.pay_vb; + if (is_witness(witness_name)) + { + witness_object wit = get_witness( witness_name ); + FC_ASSERT( wit.pay_vb, "Account ${account} has no core TOKEN vested and thus its not allowed to withdraw.", ("account", witness_name)); + vbid = wit.pay_vb; + } + else + FC_THROW("Account ${account} has no core TOKEN vested and thus its not allowed to withdraw.", ("account", witness_name)); } vesting_balance_object vbo = get_object< vesting_balance_object >( *vbid ); @@ -2052,7 +2057,7 @@ public: if (is_witness(account_name)) { witness_object wit = get_witness( account_name ); - FC_ASSERT( wit.pay_vb ); + FC_ASSERT( wit.pay_vb, "Account ${account} has no core TOKEN vested and thus its not allowed to withdraw.", ("account", account_name)); vbid = wit.pay_vb; } else From 0d1c41557d54029ef2d49862d9a6a441cdd4ddec Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Tue, 22 Oct 2019 10:39:45 -0300 Subject: [PATCH 14/39] changes to allow user to vote in each sub-period --- libraries/app/database_api.cpp | 2 + .../app/include/graphene/app/database_api.hpp | 5 ++- libraries/chain/account_evaluator.cpp | 4 +- libraries/chain/db_maint.cpp | 38 +++++++++++++++---- .../chain/include/graphene/chain/database.hpp | 1 + libraries/wallet/wallet.cpp | 9 ++++- 6 files changed, 47 insertions(+), 12 deletions(-) diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index e3e82790..e27da19b 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -2039,6 +2039,8 @@ graphene::app::gpos_info database_api_impl::get_gpos_info(const account_id_type { gpos_info result; result.vesting_factor = _db.calculate_vesting_factor(account(_db)); + result.current_subperiod = _db.get_gpos_current_subperiod(); + result.last_voted_time = account(_db).statistics(_db).last_vote_time; const auto& dividend_data = asset_id_type()(_db).dividend_data(_db); const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(_db); diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index 3fac4b5f..7d9ffde8 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -118,6 +118,9 @@ struct gpos_info { double vesting_factor; asset award; share_type total_amount; + uint32_t current_subperiod; + fc::time_point_sec last_voted_time; + }; /** @@ -672,7 +675,7 @@ FC_REFLECT( graphene::app::order_book, (base)(quote)(bids)(asks) ); FC_REFLECT( graphene::app::market_ticker, (base)(quote)(latest)(lowest_ask)(highest_bid)(percent_change)(base_volume)(quote_volume) ); FC_REFLECT( graphene::app::market_volume, (base)(quote)(base_volume)(quote_volume) ); FC_REFLECT( graphene::app::market_trade, (date)(price)(amount)(value) ); -FC_REFLECT( graphene::app::gpos_info, (vesting_factor)(award)(total_amount) ); +FC_REFLECT( graphene::app::gpos_info, (vesting_factor)(award)(total_amount)(current_subperiod)(last_voted_time) ); FC_API(graphene::app::database_api, diff --git a/libraries/chain/account_evaluator.cpp b/libraries/chain/account_evaluator.cpp index 2d117f52..b29c169c 100644 --- a/libraries/chain/account_evaluator.cpp +++ b/libraries/chain/account_evaluator.cpp @@ -284,8 +284,8 @@ void_result account_update_evaluator::do_apply( const account_update_operation& { d.modify( acnt->statistics( d ), [&]( account_statistics_object& aso ) { - if((o.new_options->votes != acnt->options.votes || - o.new_options->voting_account != acnt->options.voting_account)) + //if((o.new_options->votes != acnt->options.votes || + // o.new_options->voting_account != acnt->options.voting_account)) aso.last_vote_time = d.head_block_time(); } ); } diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 81fce8f9..ade8c160 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -725,13 +725,8 @@ void deprecate_annual_members( database& db ) return; } -double database::calculate_vesting_factor(const account_object& stake_account) +uint32_t database::get_gpos_current_subperiod() { - // get last time voted form stats - const auto &stats = stake_account.statistics(*this); - fc::time_point_sec last_date_voted = stats.last_vote_time; - - // get global data related to gpos const auto &gpo = this->get_global_properties(); const auto vesting_period = gpo.parameters.gpos_period(); const auto vesting_subperiod = gpo.parameters.gpos_subperiod(); @@ -741,7 +736,6 @@ double database::calculate_vesting_factor(const account_object& stake_account) const fc::time_point_sec period_end = period_start + vesting_period; const auto number_of_subperiods = vesting_period / vesting_subperiod; const auto now = this->head_block_time(); - double vesting_factor; auto seconds_since_period_start = now.sec_since_epoch() - period_start.sec_since_epoch(); FC_ASSERT(period_start <= now && now <= period_end); @@ -757,6 +751,28 @@ double database::calculate_vesting_factor(const account_object& stake_account) current_subperiod = period; }); + return current_subperiod; +} + +double database::calculate_vesting_factor(const account_object& stake_account) +{ + // get last time voted form stats + const auto &stats = stake_account.statistics(*this); + fc::time_point_sec last_date_voted = stats.last_vote_time; + + // get global data related to gpos + const auto &gpo = this->get_global_properties(); + const auto vesting_period = gpo.parameters.gpos_period(); + const auto vesting_subperiod = gpo.parameters.gpos_subperiod(); + const auto period_start = fc::time_point_sec(gpo.parameters.gpos_period_start()); + + // variables needed + const auto number_of_subperiods = vesting_period / vesting_subperiod; + double vesting_factor; + + // get in what sub period we are + uint32_t current_subperiod = get_gpos_current_subperiod(); + if(current_subperiod == 0 || current_subperiod > number_of_subperiods) return 0; if(last_date_voted < period_start) return 0; @@ -1389,7 +1405,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g rolling_period_start(*this); process_dividend_assets(*this); - + struct vote_tally_helper { database& d; const global_property_object& props; @@ -1558,6 +1574,12 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g p.pending_parameters->extensions.value.permitted_betting_odds_increments = p.parameters.extensions.value.permitted_betting_odds_increments; if( !p.pending_parameters->extensions.value.live_betting_delay_time.valid() ) p.pending_parameters->extensions.value.live_betting_delay_time = p.parameters.extensions.value.live_betting_delay_time; + if( !p.pending_parameters->extensions.value.gpos_period.valid() ) + p.pending_parameters->extensions.value.gpos_period = p.parameters.extensions.value.gpos_period; + if( !p.pending_parameters->extensions.value.gpos_subperiod.valid() ) + p.pending_parameters->extensions.value.gpos_subperiod = p.parameters.extensions.value.gpos_subperiod; + if( !p.pending_parameters->extensions.value.gpos_vesting_lockin_period.valid() ) + p.pending_parameters->extensions.value.gpos_vesting_lockin_period = p.parameters.extensions.value.gpos_vesting_lockin_period; p.parameters = std::move(*p.pending_parameters); p.pending_parameters.reset(); } diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index 179fb2df..a181fe58 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -500,6 +500,7 @@ namespace graphene { namespace chain { void update_worker_votes(); public: double calculate_vesting_factor(const account_object& stake_account); + uint32_t get_gpos_current_subperiod(); template diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index b6aa2cbf..5b867c47 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2125,13 +2125,20 @@ public: account_object voting_account_object = get_account(voting_account); account_id_type witness_owner_account_id = get_account_id(witness); + fc::optional witness_obj = _remote_db->get_witness_by_account(witness_owner_account_id); if (!witness_obj) FC_THROW("Account ${witness} is not registered as a witness", ("witness", witness)); if (approve) { + account_id_type stake_account = get_account_id(voting_account); + const auto gpos_info = _remote_db->get_gpos_info(stake_account); + const auto vesting_subperiod = _remote_db->get_global_properties().parameters.gpos_subperiod(); + const auto gpos_start_time = fc::time_point_sec(_remote_db->get_global_properties().parameters.gpos_period_start()); + const auto subperiod_start_time = gpos_start_time.sec_since_epoch() + (gpos_info.current_subperiod - 1) * vesting_subperiod; + auto insert_result = voting_account_object.options.votes.insert(witness_obj->vote_id); - if (!insert_result.second) + if (!insert_result.second && (gpos_info.last_voted_time.sec_since_epoch() >= subperiod_start_time)) FC_THROW("Account ${account} was already voting for witness ${witness}", ("account", voting_account)("witness", witness)); } else From 73829bd97f070f8264ab9a98a8a68a3a21be1ec4 Mon Sep 17 00:00:00 2001 From: Sandip Patel Date: Wed, 23 Oct 2019 11:56:38 +0530 Subject: [PATCH 15/39] Fixed GPOS vesting factor issue when proxy is set --- libraries/chain/db_maint.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 81fce8f9..182c04fc 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -727,9 +727,13 @@ void deprecate_annual_members( database& db ) double database::calculate_vesting_factor(const account_object& stake_account) { - // get last time voted form stats - const auto &stats = stake_account.statistics(*this); - fc::time_point_sec last_date_voted = stats.last_vote_time; + fc::time_point_sec last_date_voted; + // get last time voted form account stats + // check last_vote_time of proxy voting account if proxy is set + if (stake_account.options.voting_account == GRAPHENE_PROXY_TO_SELF_ACCOUNT) + last_date_voted = stake_account.statistics(*this).last_vote_time; + else + last_date_voted = stake_account.options.voting_account(*this).statistics(*this).last_vote_time; // get global data related to gpos const auto &gpo = this->get_global_properties(); From ccdea033f398b7de760e08d9b220a54fb50f9456 Mon Sep 17 00:00:00 2001 From: Sandip Patel Date: Wed, 23 Oct 2019 17:41:16 +0530 Subject: [PATCH 16/39] Added unit test for proxy voting --- tests/tests/gpos_tests.cpp | 87 +++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/tests/tests/gpos_tests.cpp b/tests/tests/gpos_tests.cpp index 11104409..81f56500 100644 --- a/tests/tests/gpos_tests.cpp +++ b/tests/tests/gpos_tests.cpp @@ -832,8 +832,94 @@ BOOST_AUTO_TEST_CASE( competing_proposals ) */ BOOST_AUTO_TEST_CASE( proxy_voting ) { + ACTORS((alice)(bob)); try { + // move to hardfork + generate_blocks( HARDFORK_GPOS_TIME ); + generate_block(); + + // database api + graphene::app::database_api db_api(db); + + const auto& core = asset_id_type()(db); + + // send some asset to alice and bob + transfer( committee_account, alice_id, core.amount( 1000 ) ); + transfer( committee_account, bob_id, core.amount( 1000 ) ); + generate_block(); + + // add some vesting to alice and bob + create_vesting(alice_id, core.amount(100), vesting_balance_type::gpos); + generate_block(); + + // total balance is 100 rest of data at 0 + auto gpos_info = db_api.get_gpos_info(alice_id); + BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 0); + BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 0); + BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 100); + + create_vesting(bob_id, core.amount(100), vesting_balance_type::gpos); + generate_block(); + + gpos_info = db_api.get_gpos_info(bob_id); + BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 0); + BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 0); + BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 200); + + auto now = db.head_block_time(); + update_gpos_global(518400, 86400, now); + + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period(), 518400); + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_subperiod(), 86400); + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), now.sec_since_epoch()); + + // alice assign bob as voting account + graphene::chain::account_update_operation op; + op.account = alice_id; + op.new_options = alice_id(db).options; + op.new_options->voting_account = bob_id; + trx.operations.push_back(op); + set_expiration(db, trx); + trx.validate(); + sign(trx, alice_private_key); + PUSH_TX( db, trx, ~0 ); + trx.clear(); + + generate_block(); + + // vote for witness1 + auto witness1 = witness_id_type(1)(db); + vote_for(bob_id, witness1.vote_id, bob_private_key); + + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + + // check vesting factor of current subperiod + BOOST_CHECK_EQUAL(db_api.get_gpos_info(alice_id).vesting_factor, 1); + BOOST_CHECK_EQUAL(db_api.get_gpos_info(bob_id).vesting_factor, 1); + + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + generate_block(); + + // GPOS 2nd subperiod started. + // vesting factor decay + BOOST_CHECK_EQUAL(db_api.get_gpos_info(alice_id).vesting_factor, 0.83333333333333337); + BOOST_CHECK_EQUAL(db_api.get_gpos_info(bob_id).vesting_factor, 0.83333333333333337); + + // vote for witness2 + auto witness2 = witness_id_type(2)(db); + vote_for(bob_id, witness2.vote_id, bob_private_key); + + // vesting factor should be 1 for both alice and bob for the current subperiod + BOOST_CHECK_EQUAL(db_api.get_gpos_info(alice_id).vesting_factor, 1); + BOOST_CHECK_EQUAL(db_api.get_gpos_info(bob_id).vesting_factor, 1); + + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + generate_block(); + + // vesting factor decay + BOOST_CHECK_EQUAL(db_api.get_gpos_info(alice_id).vesting_factor, 0.83333333333333337); + BOOST_CHECK_EQUAL(db_api.get_gpos_info(bob_id).vesting_factor, 0.83333333333333337); } catch (fc::exception &e) { edump((e.to_detail_string())); @@ -949,5 +1035,4 @@ BOOST_AUTO_TEST_CASE( database_api ) throw; } } - BOOST_AUTO_TEST_SUITE_END() From 8bbab4c113aa77164a8382bd025eb4b0de748acd Mon Sep 17 00:00:00 2001 From: Sandip Patel Date: Wed, 23 Oct 2019 18:25:33 +0530 Subject: [PATCH 17/39] Review changes --- tests/tests/gpos_tests.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/tests/gpos_tests.cpp b/tests/tests/gpos_tests.cpp index 81f56500..5b089685 100644 --- a/tests/tests/gpos_tests.cpp +++ b/tests/tests/gpos_tests.cpp @@ -906,6 +906,14 @@ BOOST_AUTO_TEST_CASE( proxy_voting ) BOOST_CHECK_EQUAL(db_api.get_gpos_info(alice_id).vesting_factor, 0.83333333333333337); BOOST_CHECK_EQUAL(db_api.get_gpos_info(bob_id).vesting_factor, 0.83333333333333337); + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + generate_block(); + + // GPOS 3rd subperiod started + // vesting factor decay + BOOST_CHECK_EQUAL(db_api.get_gpos_info(alice_id).vesting_factor, 0.66666666666666663); + BOOST_CHECK_EQUAL(db_api.get_gpos_info(bob_id).vesting_factor, 0.66666666666666663); + // vote for witness2 auto witness2 = witness_id_type(2)(db); vote_for(bob_id, witness2.vote_id, bob_private_key); From 48d0d88ff048e203a82bb9e2f6e736fe785e4ca0 Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Wed, 23 Oct 2019 18:33:17 -0300 Subject: [PATCH 18/39] changes to update last voting time --- .../app/include/graphene/app/database_api.hpp | 3 +-- libraries/chain/account_evaluator.cpp | 6 +++-- .../graphene/chain/protocol/account.hpp | 1 + libraries/wallet/wallet.cpp | 24 ++++++++++++++++--- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index 7d9ffde8..843d6af5 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -119,8 +119,7 @@ struct gpos_info { asset award; share_type total_amount; uint32_t current_subperiod; - fc::time_point_sec last_voted_time; - + fc::time_point_sec last_voted_time; }; /** diff --git a/libraries/chain/account_evaluator.cpp b/libraries/chain/account_evaluator.cpp index b29c169c..3185c456 100644 --- a/libraries/chain/account_evaluator.cpp +++ b/libraries/chain/account_evaluator.cpp @@ -284,8 +284,10 @@ void_result account_update_evaluator::do_apply( const account_update_operation& { d.modify( acnt->statistics( d ), [&]( account_statistics_object& aso ) { - //if((o.new_options->votes != acnt->options.votes || - // o.new_options->voting_account != acnt->options.voting_account)) + fc::optional< bool > flag = o.extensions.value.update_last_voting_time; + if((o.new_options->votes != acnt->options.votes || + o.new_options->voting_account != acnt->options.voting_account) || + flag) aso.last_vote_time = d.head_block_time(); } ); } diff --git a/libraries/chain/include/graphene/chain/protocol/account.hpp b/libraries/chain/include/graphene/chain/protocol/account.hpp index 6d13a4d3..a0e43ad0 100644 --- a/libraries/chain/include/graphene/chain/protocol/account.hpp +++ b/libraries/chain/include/graphene/chain/protocol/account.hpp @@ -140,6 +140,7 @@ namespace graphene { namespace chain { optional< void_t > null_ext; optional< special_authority > owner_special_authority; optional< special_authority > active_special_authority; + optional< bool > update_last_voting_time = false; }; struct fee_parameters_type diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 5b867c47..5bc53bdc 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2087,11 +2087,22 @@ public: fc::optional committee_member_obj = _remote_db->get_committee_member_by_account(committee_member_owner_account_id); if (!committee_member_obj) FC_THROW("Account ${committee_member} is not registered as a committee_member", ("committee_member", committee_member)); + + bool update_vote_time = false; + if (approve) { + account_id_type stake_account = get_account_id(voting_account); + const auto gpos_info = _remote_db->get_gpos_info(stake_account); + const auto vesting_subperiod = _remote_db->get_global_properties().parameters.gpos_subperiod(); + const auto gpos_start_time = fc::time_point_sec(_remote_db->get_global_properties().parameters.gpos_period_start()); + const auto subperiod_start_time = gpos_start_time.sec_since_epoch() + (gpos_info.current_subperiod - 1) * vesting_subperiod; + auto insert_result = voting_account_object.options.votes.insert(committee_member_obj->vote_id); - if (!insert_result.second) - FC_THROW("Account ${account} was already voting for committee_member ${committee_member}", ("account", voting_account)("committee_member", committee_member)); + if (!insert_result.second && (gpos_info.last_voted_time.sec_since_epoch() >= subperiod_start_time)) + FC_THROW("Account ${account} was already voting for committee_member ${committee_member} in the current GPOS sub-period", ("account", voting_account)("committee_member", committee_member)); + else + update_vote_time = true; //Allow user to vote in each sub-period(Update voting time, which is reference in calculating VF) } else { @@ -2102,6 +2113,7 @@ public: account_update_operation account_update_op; account_update_op.account = voting_account_object.id; account_update_op.new_options = voting_account_object.options; + account_update_op.extensions.value.update_last_voting_time = update_vote_time; signed_transaction tx; tx.operations.push_back( account_update_op ); @@ -2129,6 +2141,8 @@ public: fc::optional witness_obj = _remote_db->get_witness_by_account(witness_owner_account_id); if (!witness_obj) FC_THROW("Account ${witness} is not registered as a witness", ("witness", witness)); + + bool update_vote_time = false; if (approve) { account_id_type stake_account = get_account_id(voting_account); @@ -2139,7 +2153,9 @@ public: auto insert_result = voting_account_object.options.votes.insert(witness_obj->vote_id); if (!insert_result.second && (gpos_info.last_voted_time.sec_since_epoch() >= subperiod_start_time)) - FC_THROW("Account ${account} was already voting for witness ${witness}", ("account", voting_account)("witness", witness)); + FC_THROW("Account ${account} was already voting for witness ${witness} in the current GPOS sub-period", ("account", voting_account)("witness", witness)); + else + update_vote_time = true; //Allow user to vote in each sub-period(Update voting time, which is reference in calculating VF) } else { @@ -2147,9 +2163,11 @@ public: if (!votes_removed) FC_THROW("Account ${account} is already not voting for witness ${witness}", ("account", voting_account)("witness", witness)); } + account_update_operation account_update_op; account_update_op.account = voting_account_object.id; account_update_op.new_options = voting_account_object.options; + account_update_op.extensions.value.update_last_voting_time = update_vote_time; signed_transaction tx; tx.operations.push_back( account_update_op ); From d6da2963dcb2267ce7a924a6a876f56180b1b71f Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Wed, 23 Oct 2019 22:15:26 -0300 Subject: [PATCH 19/39] resolve merge conflict --- libraries/chain/db_maint.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 7eab5cf8..aee9d451 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -728,12 +728,6 @@ void deprecate_annual_members( database& db ) uint32_t database::get_gpos_current_subperiod() { fc::time_point_sec last_date_voted; - // get last time voted form account stats - // check last_vote_time of proxy voting account if proxy is set - if (stake_account.options.voting_account == GRAPHENE_PROXY_TO_SELF_ACCOUNT) - last_date_voted = stake_account.statistics(*this).last_vote_time; - else - last_date_voted = stake_account.options.voting_account(*this).statistics(*this).last_vote_time; const auto &gpo = this->get_global_properties(); const auto vesting_period = gpo.parameters.gpos_period(); @@ -764,9 +758,13 @@ uint32_t database::get_gpos_current_subperiod() double database::calculate_vesting_factor(const account_object& stake_account) { - // get last time voted form stats - const auto &stats = stake_account.statistics(*this); - fc::time_point_sec last_date_voted = stats.last_vote_time; + fc::time_point_sec last_date_voted; + // get last time voted form account stats + // check last_vote_time of proxy voting account if proxy is set + if (stake_account.options.voting_account == GRAPHENE_PROXY_TO_SELF_ACCOUNT) + last_date_voted = stake_account.statistics(*this).last_vote_time; + else + last_date_voted = stake_account.options.voting_account(*this).statistics(*this).last_vote_time; // get global data related to gpos const auto &gpo = this->get_global_properties(); From cf3b54ece47773c4daa407b9ed51128fb2800a3a Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Wed, 23 Oct 2019 23:13:23 -0300 Subject: [PATCH 20/39] unit test changes and also separated GPOS test suite --- tests/CMakeLists.txt | 4 + tests/gpos/gpos_tests.cpp | 1093 +++++++++++++++++++++++++++++++++++++ 2 files changed, 1097 insertions(+) create mode 100644 tests/gpos/gpos_tests.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 57a451aa..55f369f4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -13,6 +13,10 @@ if(MSVC) set_source_files_properties( tests/serialization_tests.cpp PROPERTIES COMPILE_FLAGS "/bigobj" ) endif(MSVC) +file(GLOB GPOS_TESTS "gpos/*.cpp") +add_executable( gpos_test ${GPOS_TESTS} ${COMMON_SOURCES} ) +target_link_libraries( gpos_test graphene_chain graphene_app graphene_account_history graphene_bookie graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} ) + file(GLOB PERFORMANCE_TESTS "performance/*.cpp") add_executable( performance_test ${PERFORMANCE_TESTS} ${COMMON_SOURCES} ) target_link_libraries( performance_test graphene_chain graphene_app graphene_account_history graphene_bookie graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} ) diff --git a/tests/gpos/gpos_tests.cpp b/tests/gpos/gpos_tests.cpp new file mode 100644 index 00000000..335230d7 --- /dev/null +++ b/tests/gpos/gpos_tests.cpp @@ -0,0 +1,1093 @@ +/* + * Copyright (c) 2018 oxarbitrage and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include +#include +#include + +#include +#include +#include +#include + +#include "../common/database_fixture.hpp" + +#include + +using namespace graphene::chain; +using namespace graphene::chain::test; + +struct gpos_fixture: database_fixture +{ + const worker_object& create_worker( const account_id_type owner, const share_type daily_pay, + const fc::microseconds& duration ) { + worker_create_operation op; + op.owner = owner; + op.daily_pay = daily_pay; + op.initializer = vesting_balance_worker_initializer(1); + op.work_begin_date = db.head_block_time(); + op.work_end_date = op.work_begin_date + duration; + trx.operations.push_back(op); + set_expiration(db, trx); + trx.validate(); + processed_transaction ptx = db.push_transaction(trx, ~0); + trx.clear(); + return db.get(ptx.operation_results[0].get()); + } + const vesting_balance_object& create_vesting(const account_id_type owner, const asset amount, + const vesting_balance_type type) + { + vesting_balance_create_operation op; + op.creator = owner; + op.owner = owner; + op.amount = amount; + op.balance_type = type; + + trx.operations.push_back(op); + set_expiration(db, trx); + processed_transaction ptx = PUSH_TX(db, trx, ~0); + trx.clear(); + return db.get(ptx.operation_results[0].get()); + } + + void update_payout_interval(std::string asset_name, fc::time_point start, uint32_t interval) + { + auto dividend_holder_asset_object = get_asset(asset_name); + asset_update_dividend_operation op; + op.issuer = dividend_holder_asset_object.issuer; + op.asset_to_update = dividend_holder_asset_object.id; + op.new_options.next_payout_time = start; + op.new_options.payout_interval = interval; + trx.operations.push_back(op); + set_expiration(db, trx); + PUSH_TX(db, trx, ~0); + trx.operations.clear(); + } + + void update_gpos_global(uint32_t vesting_period, uint32_t vesting_subperiod, fc::time_point_sec period_start) + { + db.modify(db.get_global_properties(), [vesting_period, vesting_subperiod, period_start](global_property_object& p) { + p.parameters.extensions.value.gpos_period = vesting_period; + p.parameters.extensions.value.gpos_subperiod = vesting_subperiod; + p.parameters.extensions.value.gpos_period_start = period_start.sec_since_epoch(); + }); + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period(), vesting_period); + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_subperiod(), vesting_subperiod); + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), period_start.sec_since_epoch()); + } + void vote_for(const account_id_type account_id, const vote_id_type vote_for, const fc::ecc::private_key& key) + { + account_update_operation op; + op.account = account_id; + op.new_options = account_id(db).options; + op.new_options->votes.insert(vote_for); + trx.operations.push_back(op); + set_expiration(db, trx); + trx.validate(); + sign(trx, key); + PUSH_TX(db, trx); + trx.clear(); + } + void fill_reserve_pool(const account_id_type account_id, asset amount) + { + asset_reserve_operation op; + op.payer = account_id; + op.amount_to_reserve = amount; + trx.operations.push_back(op); + trx.validate(); + set_expiration(db, trx); + PUSH_TX( db, trx, ~0 ); + trx.clear(); + } + + void advance_x_maint(int periods) + { + for(int i=0; i(ptx.operation_results[0].get()); + + // check created vesting amount and policy + BOOST_CHECK_EQUAL(alice_vesting.balance.amount.value, 100); + BOOST_CHECK_EQUAL(alice_vesting.policy.get().vesting_duration_seconds, + db.get_global_properties().parameters.gpos_subperiod()); + BOOST_CHECK_EQUAL(alice_vesting.policy.get().vesting_cliff_seconds, + db.get_global_properties().parameters.gpos_subperiod()); + + // bob creates a gpos vesting with his custom policy + { + vesting_balance_create_operation op; + op.creator = bob_id; + op.owner = bob_id; + op.amount = core.amount(200); + op.balance_type = vesting_balance_type::gpos; + op.policy = cdd_vesting_policy_initializer{ 60*60*24 }; + + trx.operations.push_back(op); + set_expiration(db, trx); + ptx = PUSH_TX(db, trx, ~0); + trx.clear(); + } + auto bob_vesting = db.get(ptx.operation_results[0].get()); + + generate_block(); + + // policy is not the one defined by the user but default + BOOST_CHECK_EQUAL(bob_vesting.balance.amount.value, 200); + BOOST_CHECK_EQUAL(bob_vesting.policy.get().vesting_duration_seconds, + db.get_global_properties().parameters.gpos_subperiod()); + BOOST_CHECK_EQUAL(bob_vesting.policy.get().vesting_cliff_seconds, + db.get_global_properties().parameters.gpos_subperiod()); + + } + catch (fc::exception& e) + { + edump((e.to_detail_string())); + throw; + } +} + +BOOST_AUTO_TEST_CASE( dividends ) +{ + ACTORS((alice)(bob)); + try + { + // move to 1 week before hardfork + generate_blocks( HARDFORK_GPOS_TIME - fc::days(7) ); + generate_block(); + + const auto& core = asset_id_type()(db); + + // all core coins are in the committee_account + BOOST_CHECK_EQUAL(get_balance(committee_account(db), core), 1000000000000000); + + // transfer half of the total stake to alice so not all the dividends will go to the committee_account + transfer( committee_account, alice_id, core.amount( 500000000000000 ) ); + generate_block(); + + // send some to bob + transfer( committee_account, bob_id, core.amount( 1000 ) ); + generate_block(); + + // committee balance + BOOST_CHECK_EQUAL(get_balance(committee_account(db), core), 499999999999000); + + // alice balance + BOOST_CHECK_EQUAL(get_balance(alice_id(db), core), 500000000000000); + + // bob balance + BOOST_CHECK_EQUAL(get_balance(bob_id(db), core), 1000); + + // get core asset object + const auto& dividend_holder_asset_object = get_asset(GRAPHENE_SYMBOL); + + // by default core token pays dividends once per month + const auto& dividend_data = dividend_holder_asset_object.dividend_data(db); + BOOST_CHECK_EQUAL(*dividend_data.options.payout_interval, 2592000); // 30 days + + // update the payout interval for speed purposes of the test + update_payout_interval(core.symbol, HARDFORK_GPOS_TIME - fc::days(7) + fc::minutes(1), 60 * 60 * 24); // 1 day + + generate_block(); + + BOOST_CHECK_EQUAL(*dividend_data.options.payout_interval, 86400); // 1 day now + + // get the dividend distribution account + const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db); + + // transfering some coins to distribution account. + // simulating the blockchain haves some dividends to pay. + transfer( committee_account, dividend_distribution_account.id, core.amount( 100 ) ); + generate_block(); + + // committee balance + BOOST_CHECK_EQUAL(get_balance(committee_account(db), core), 499999999998900 ); + + // distribution account balance + BOOST_CHECK_EQUAL(get_balance(dividend_distribution_account, core), 100); + + // get when is the next payout time as we need to advance there + auto next_payout_time = dividend_data.options.next_payout_time; + + // advance to next payout + generate_blocks(*next_payout_time); + + // advance to next maint after payout time arrives + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + + // check balances now, dividends are paid "normally" + BOOST_CHECK_EQUAL(get_balance(committee_account(db), core), 499999999998949 ); + BOOST_CHECK_EQUAL(get_balance(alice_id(db), core), 500000000000050 ); + BOOST_CHECK_EQUAL(get_balance(bob_id(db), core), 1000 ); + BOOST_CHECK_EQUAL(get_balance(dividend_distribution_account, core), 1); + + // advance to hardfork + generate_blocks( HARDFORK_GPOS_TIME ); + + // advance to next maint + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + + // send 99 to the distribution account so it will have 100 PPY again to share + transfer( committee_account, dividend_distribution_account.id, core.amount( 99 ) ); + generate_block(); + + // get when is the next payout time as we need to advance there + next_payout_time = dividend_data.options.next_payout_time; + + // advance to next payout + generate_blocks(*next_payout_time); + + // advance to next maint + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + + // make sure no dividends were paid "normally" + BOOST_CHECK_EQUAL(get_balance(committee_account(db), core), 499999999998850 ); + BOOST_CHECK_EQUAL(get_balance(alice_id(db), core), 500000000000050 ); + BOOST_CHECK_EQUAL(get_balance(bob_id(db), core), 1000 ); + BOOST_CHECK_EQUAL(get_balance(dividend_distribution_account, core), 100); + + // create vesting balance + create_vesting(bob_id, core.amount(100), vesting_balance_type::gpos); + + // need to vote to get paid + auto witness1 = witness_id_type(1)(db); + vote_for(bob_id, witness1.vote_id, bob_private_key); + + generate_block(); + + // check balances + BOOST_CHECK_EQUAL(get_balance(bob_id(db), core), 900 ); + BOOST_CHECK_EQUAL(get_balance(dividend_distribution_account, core), 100); + + // advance to next payout + generate_blocks(*next_payout_time); + + // advance to next maint + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + + // check balances, dividends paid to bob + BOOST_CHECK_EQUAL(get_balance(bob_id(db), core), 1000 ); + BOOST_CHECK_EQUAL(get_balance(dividend_distribution_account, core), 0); + } + catch (fc::exception& e) + { + edump((e.to_detail_string())); + throw; + } +} + +BOOST_AUTO_TEST_CASE( voting ) +{ + ACTORS((alice)(bob)); + try { + + // move to hardfork + generate_blocks( HARDFORK_GPOS_TIME ); + generate_block(); + + const auto& core = asset_id_type()(db); + + // send some asset to alice and bob + transfer( committee_account, alice_id, core.amount( 1000 ) ); + transfer( committee_account, bob_id, core.amount( 1000 ) ); + generate_block(); + + // default maintenance_interval is 1 day + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.maintenance_interval, 86400); + + // add some vesting to alice and bob + create_vesting(alice_id, core.amount(100), vesting_balance_type::gpos); + create_vesting(bob_id, core.amount(100), vesting_balance_type::gpos); + generate_block(); + + // default gpos values + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period(), 15552000); + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_subperiod(), 2592000); + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), HARDFORK_GPOS_TIME.sec_since_epoch()); + + // update default gpos for test speed + auto now = db.head_block_time(); + // 5184000 = 60x60x24x60 = 60 days + // 864000 = 60x60x24x10 = 10 days + update_gpos_global(5184000, 864000, now); + + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period(), 5184000); + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_subperiod(), 864000); + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), now.sec_since_epoch()); + // end global changes + + generate_block(); + + // no votes for witness 1 + auto witness1 = witness_id_type(1)(db); + BOOST_CHECK_EQUAL(witness1.total_votes, 0); + + // no votes for witness 2 + auto witness2 = witness_id_type(2)(db); + BOOST_CHECK_EQUAL(witness2.total_votes, 0); + + // vote for witness1 + vote_for(alice_id, witness1.vote_id, alice_private_key); + vote_for(bob_id, witness2.vote_id, bob_private_key); + + // go to maint + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + + // vote is the same as amount in the first subperiod since voting + witness1 = witness_id_type(1)(db); + witness2 = witness_id_type(2)(db); + BOOST_CHECK_EQUAL(witness1.total_votes, 100); + BOOST_CHECK_EQUAL(witness2.total_votes, 100); + + advance_x_maint(10); + + auto now1 = db.head_block_time(); + //vote bob tot witness2 in each subperiod and verify votes + vote_for(bob_id, witness2.vote_id, bob_private_key); + // go to maint + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + // vote decay as time pass + witness1 = witness_id_type(1)(db); + witness2 = witness_id_type(2)(db); + + BOOST_CHECK_EQUAL(witness1.total_votes, 83); + BOOST_CHECK_EQUAL(witness2.total_votes, 100); + + advance_x_maint(10); + now1 = db.head_block_time(); + vote_for(bob_id, witness2.vote_id, bob_private_key); + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + // decay more + witness1 = witness_id_type(1)(db); + witness2 = witness_id_type(2)(db); + BOOST_CHECK_EQUAL(witness1.total_votes, 66); + BOOST_CHECK_EQUAL(witness2.total_votes, 100); + + advance_x_maint(10); + now1 = db.head_block_time(); + // more + vote_for(bob_id, witness2.vote_id, bob_private_key); + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + // decay more + witness1 = witness_id_type(1)(db); + witness2 = witness_id_type(2)(db); + BOOST_CHECK_EQUAL(witness1.total_votes, 50); + BOOST_CHECK_EQUAL(witness2.total_votes, 100); + + advance_x_maint(10); + now1 = db.head_block_time(); + // more + vote_for(bob_id, witness2.vote_id, bob_private_key); + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + // decay more + witness1 = witness_id_type(1)(db); + witness2 = witness_id_type(2)(db); + + BOOST_CHECK_EQUAL(witness1.total_votes, 33); + BOOST_CHECK_EQUAL(witness2.total_votes, 100); + + advance_x_maint(10); + now1 = db.head_block_time(); + + // more + vote_for(bob_id, witness2.vote_id, bob_private_key); + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + // decay more + witness1 = witness_id_type(1)(db); + witness2 = witness_id_type(2)(db); + BOOST_CHECK_EQUAL(witness1.total_votes, 16); + BOOST_CHECK_EQUAL(witness2.total_votes, 100); + + // we are still in gpos period 1 + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), now.sec_since_epoch()); + + advance_x_maint(5); + // a new GPOS period is in but vote from user is before the start so his voting power is 0 + now = db.head_block_time(); + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), now.sec_since_epoch()); + + generate_block(); + + witness1 = witness_id_type(1)(db); + witness2 = witness_id_type(2)(db); + BOOST_CHECK_EQUAL(witness1.total_votes, 0); + BOOST_CHECK_EQUAL(witness2.total_votes, 0); + + // we are in the second GPOS period, at subperiod 2, lets vote here + vote_for(bob_id, witness2.vote_id, bob_private_key); + generate_block(); + + // go to maint + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + + witness1 = witness_id_type(1)(db); + witness2 = witness_id_type(2)(db); + + BOOST_CHECK_EQUAL(witness1.total_votes, 0); + BOOST_CHECK_EQUAL(witness2.total_votes, 100); + + advance_x_maint(10); + + witness1 = witness_id_type(1)(db); + witness2 = witness_id_type(2)(db); + + BOOST_CHECK_EQUAL(witness1.total_votes, 0); + BOOST_CHECK_EQUAL(witness2.total_votes, 83); + + vote_for(bob_id, witness2.vote_id, bob_private_key); + generate_block(); + + advance_x_maint(10); + + witness1 = witness_id_type(1)(db); + witness2 = witness_id_type(2)(db); + + BOOST_CHECK_EQUAL(witness1.total_votes, 0); + BOOST_CHECK_EQUAL(witness2.total_votes, 83); + + // alice votes again, now for witness 2, her vote worth 100 now + vote_for(alice_id, witness2.vote_id, alice_private_key); + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + + witness1 = witness_id_type(1)(db); + witness2 = witness_id_type(2)(db); + + BOOST_CHECK_EQUAL(witness1.total_votes, 100); + BOOST_CHECK_EQUAL(witness2.total_votes, 183); + + } + catch (fc::exception &e) { + edump((e.to_detail_string())); + throw; + } +} + +BOOST_AUTO_TEST_CASE( rolling_period_start ) +{ + // period start rolls automatically after HF + try { + // advance to HF + generate_blocks(HARDFORK_GPOS_TIME); + generate_block(); + + // update default gpos global parameters to make this thing faster + auto now = db.head_block_time(); + update_gpos_global(518400, 86400, now); + + // moving outside period: + while( db.head_block_time() <= now + fc::days(6) ) + { + generate_block(); + } + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + + // rolling is here so getting the new now + now = db.head_block_time(); + generate_block(); + + // period start rolled + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), now.sec_since_epoch()); + } + catch (fc::exception &e) { + edump((e.to_detail_string())); + throw; + } +} +BOOST_AUTO_TEST_CASE( worker_dividends_voting ) +{ + try { + // advance to HF + generate_blocks(HARDFORK_GPOS_TIME); + generate_block(); + + // update default gpos global parameters to 4 days + auto now = db.head_block_time(); + update_gpos_global(345600, 86400, now); + + generate_block(); + set_expiration(db, trx); + const auto& core = asset_id_type()(db); + + // get core asset object + const auto& dividend_holder_asset_object = get_asset(GRAPHENE_SYMBOL); + + // by default core token pays dividends once per month + const auto& dividend_data = dividend_holder_asset_object.dividend_data(db); + BOOST_CHECK_EQUAL(*dividend_data.options.payout_interval, 2592000); // 30 days + + // update the payout interval to 1 day for speed purposes of the test + update_payout_interval(core.symbol, HARDFORK_GPOS_TIME + fc::minutes(1), 60 * 60 * 24); // 1 day + + generate_block(); + + // get the dividend distribution account + const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db); + + // transfering some coins to distribution account. + transfer( committee_account, dividend_distribution_account.id, core.amount( 100 ) ); + generate_block(); + + ACTORS((nathan)(voter1)(voter2)(voter3)); + + transfer( committee_account, nathan_id, core.amount( 1000 ) ); + transfer( committee_account, voter1_id, core.amount( 1000 ) ); + transfer( committee_account, voter2_id, core.amount( 1000 ) ); + + generate_block(); + + upgrade_to_lifetime_member(nathan_id); + + auto worker = create_worker(nathan_id, 10, fc::days(6)); + + // add some vesting to voter1 + create_vesting(voter1_id, core.amount(100), vesting_balance_type::gpos); + + // add some vesting to voter2 + create_vesting(voter2_id, core.amount(100), vesting_balance_type::gpos); + + generate_block(); + + // vote for worker + vote_for(voter1_id, worker.vote_for, voter1_private_key); + + // first maint pass, coefficient will be 1 + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + worker = worker_id_type()(db); + BOOST_CHECK_EQUAL(worker.total_votes_for, 100); + + // here dividends are paid to voter1 and voter2 + // voter1 get paid full dividend share as coefficent is at 1 here + BOOST_CHECK_EQUAL(get_balance(voter1_id(db), core), 950); + + // voter2 didnt voted so he dont get paid + BOOST_CHECK_EQUAL(get_balance(voter2_id(db), core), 900); + + // send some asset to the reserve pool so the worker can get paid + fill_reserve_pool(account_id_type(), asset(GRAPHENE_MAX_SHARE_SUPPLY/2)); + + BOOST_CHECK_EQUAL(worker_id_type()(db).worker.get().balance(db).balance.amount.value, 0); + BOOST_CHECK_EQUAL(worker.worker.get().balance(db).balance.amount.value, 0); + + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + + // worker is getting paid + BOOST_CHECK_EQUAL(worker_id_type()(db).worker.get().balance(db).balance.amount.value, 10); + BOOST_CHECK_EQUAL(worker.worker.get().balance(db).balance.amount.value, 10); + + // second maint pass, coefficient will be 0.75 + worker = worker_id_type()(db); + BOOST_CHECK_EQUAL(worker.total_votes_for, 75); + + // more decay + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + + worker = worker_id_type()(db); + BOOST_CHECK_EQUAL(worker.total_votes_for, 50); + + transfer( committee_account, dividend_distribution_account.id, core.amount( 100 ) ); + generate_block(); + + BOOST_CHECK_EQUAL(get_balance(committee_account(db), core), 499999999996850); + + // more decay + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + + worker = worker_id_type()(db); + BOOST_CHECK_EQUAL(worker.total_votes_for, 25); + + // here voter1 get paid again but less money by vesting coefficient + BOOST_CHECK_EQUAL(get_balance(voter1_id(db), core), 962); + BOOST_CHECK_EQUAL(get_balance(voter2_id(db), core), 900); + + // remaining dividends not paid by coeffcient are sent to committee account + BOOST_CHECK_EQUAL(get_balance(committee_account(db), core), 499999999996938); + } + catch (fc::exception &e) { + edump((e.to_detail_string())); + throw; + } +} + +BOOST_AUTO_TEST_CASE( account_multiple_vesting ) +{ + try { + // advance to HF + generate_blocks(HARDFORK_GPOS_TIME); + generate_block(); + set_expiration(db, trx); + + // update default gpos global parameters to 4 days + auto now = db.head_block_time(); + update_gpos_global(345600, 86400, now); + + ACTORS((sam)(patty)); + + const auto& core = asset_id_type()(db); + + transfer( committee_account, sam_id, core.amount( 300 ) ); + transfer( committee_account, patty_id, core.amount( 100 ) ); + + // add some vesting to sam + create_vesting(sam_id, core.amount(100), vesting_balance_type::gpos); + + // have another balance with 200 more + create_vesting(sam_id, core.amount(200), vesting_balance_type::gpos); + + // patty also have vesting balance + create_vesting(patty_id, core.amount(100), vesting_balance_type::gpos); + + // get core asset object + const auto& dividend_holder_asset_object = get_asset(GRAPHENE_SYMBOL); + const auto& dividend_data = dividend_holder_asset_object.dividend_data(db); + + // update the payout interval + update_payout_interval(core.symbol, HARDFORK_GPOS_TIME + fc::minutes(1), 60 * 60 * 24); // 1 day + + // get the dividend distribution account + const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db); + + // transfering some coins to distribution account. + transfer( committee_account, dividend_distribution_account.id, core.amount( 100 ) ); + generate_block(); + + // vote for a votable object + auto witness1 = witness_id_type(1)(db); + vote_for(sam_id, witness1.vote_id, sam_private_key); + vote_for(patty_id, witness1.vote_id, patty_private_key); + + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + + // amount in vested balanced will sum up as voting power + witness1 = witness_id_type(1)(db); + BOOST_CHECK_EQUAL(witness1.total_votes, 400); + + // sam get paid dividends + BOOST_CHECK_EQUAL(get_balance(sam_id(db), core), 75); + + // patty also + BOOST_CHECK_EQUAL(get_balance(patty_id(db), core), 25); + + // total vote not decaying + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + generate_block(); + + witness1 = witness_id_type(1)(db); + + BOOST_CHECK_EQUAL(witness1.total_votes, 300); + } + catch (fc::exception &e) { + edump((e.to_detail_string())); + throw; + } +} +/* +BOOST_AUTO_TEST_CASE( competing_proposals ) +{ + try { + // advance to HF + generate_blocks(HARDFORK_GPOS_TIME); + generate_block(); + set_expiration(db, trx); + + ACTORS((voter1)(voter2)(worker1)(worker2)); + + const auto& core = asset_id_type()(db); + + transfer( committee_account, worker1_id, core.amount( 1000 ) ); + transfer( committee_account, worker2_id, core.amount( 1000 ) ); + transfer( committee_account, voter1_id, core.amount( 1000 ) ); + transfer( committee_account, voter2_id, core.amount( 1000 ) ); + + create_vesting(voter1_id, core.amount(200), vesting_balance_type::gpos); + create_vesting(voter2_id, core.amount(300), vesting_balance_type::gpos); + + generate_block(); + + auto now = db.head_block_time(); + update_gpos_global(518400, 86400, now); + + update_payout_interval(core.symbol, fc::time_point::now() + fc::minutes(1), 60 * 60 * 24); // 1 day + + upgrade_to_lifetime_member(worker1_id); + upgrade_to_lifetime_member(worker2_id); + + // create 2 competing proposals asking a lot of token + // todo: maybe a refund worker here so we can test with smaller numbers + auto w1 = create_worker(worker1_id, 100000000000, fc::days(10)); + auto w1_id_instance = w1.id.instance(); + auto w2 = create_worker(worker2_id, 100000000000, fc::days(10)); + auto w2_id_instance = w2.id.instance(); + + fill_reserve_pool(account_id_type(), asset(GRAPHENE_MAX_SHARE_SUPPLY/2)); + + // vote for the 2 workers + vote_for(voter1_id, w1.vote_for, voter1_private_key); + vote_for(voter2_id, w2.vote_for, voter2_private_key); + + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + generate_block(); + + w1 = worker_id_type(w1_id_instance)(db); + w2 = worker_id_type(w2_id_instance)(db); + + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + generate_block(); + + // only w2 is getting paid as it haves more votes and money is only enough for 1 + BOOST_CHECK_EQUAL(w1.worker.get().balance(db).balance.amount.value, 0); + BOOST_CHECK_EQUAL(w2.worker.get().balance(db).balance.amount.value, 100000000000); + + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + generate_block(); + + BOOST_CHECK_EQUAL(w1.worker.get().balance(db).balance.amount.value, 0); + BOOST_CHECK_EQUAL(w2.worker.get().balance(db).balance.amount.value, 150000000000); + + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + generate_block(); + + w1 = worker_id_type(w1_id_instance)(db); + w2 = worker_id_type(w2_id_instance)(db); + + // as votes decay w1 is still getting paid as it always have more votes than w1 + BOOST_CHECK_EQUAL(w1.total_votes_for, 100); + BOOST_CHECK_EQUAL(w2.total_votes_for, 150); + + BOOST_CHECK_EQUAL(w1.worker.get().balance(db).balance.amount.value, 0); + BOOST_CHECK_EQUAL(w2.worker.get().balance(db).balance.amount.value, 200000000000); + + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + generate_block(); + + w1 = worker_id_type(w1_id_instance)(db); + w2 = worker_id_type(w2_id_instance)(db); + + BOOST_CHECK_EQUAL(w1.total_votes_for, 66); + BOOST_CHECK_EQUAL(w2.total_votes_for, 100); + + // worker is sil getting paid as days pass + BOOST_CHECK_EQUAL(w1.worker.get().balance(db).balance.amount.value, 0); + BOOST_CHECK_EQUAL(w2.worker.get().balance(db).balance.amount.value, 250000000000); + + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + generate_block(); + + w1 = worker_id_type(w1_id_instance)(db); + w2 = worker_id_type(w2_id_instance)(db); + + BOOST_CHECK_EQUAL(w1.total_votes_for, 33); + BOOST_CHECK_EQUAL(w2.total_votes_for, 50); + + BOOST_CHECK_EQUAL(w1.worker.get().balance(db).balance.amount.value, 0); + BOOST_CHECK_EQUAL(w2.worker.get().balance(db).balance.amount.value, 300000000000); + + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + generate_block(); + + w1 = worker_id_type(w1_id_instance)(db); + w2 = worker_id_type(w2_id_instance)(db); + + // worker2 will not get paid anymore as it haves 0 votes + BOOST_CHECK_EQUAL(w1.total_votes_for, 0); + BOOST_CHECK_EQUAL(w2.total_votes_for, 0); + + BOOST_CHECK_EQUAL(w1.worker.get().balance(db).balance.amount.value, 0); + BOOST_CHECK_EQUAL(w2.worker.get().balance(db).balance.amount.value, 300000000000); + } + catch (fc::exception &e) { + edump((e.to_detail_string())); + throw; + } +} +*/ +BOOST_AUTO_TEST_CASE( proxy_voting ) +{ + ACTORS((alice)(bob)); + try { + + // move to hardfork + generate_blocks( HARDFORK_GPOS_TIME ); + generate_block(); + + // database api + graphene::app::database_api db_api(db); + + const auto& core = asset_id_type()(db); + + // send some asset to alice and bob + transfer( committee_account, alice_id, core.amount( 1000 ) ); + transfer( committee_account, bob_id, core.amount( 1000 ) ); + generate_block(); + + // add some vesting to alice and bob + create_vesting(alice_id, core.amount(100), vesting_balance_type::gpos); + generate_block(); + + // total balance is 100 rest of data at 0 + auto gpos_info = db_api.get_gpos_info(alice_id); + BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 0); + BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 0); + BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 100); + + create_vesting(bob_id, core.amount(100), vesting_balance_type::gpos); + generate_block(); + + gpos_info = db_api.get_gpos_info(bob_id); + BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 0); + BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 0); + BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 200); + + auto now = db.head_block_time(); + update_gpos_global(518400, 86400, now); + + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period(), 518400); + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_subperiod(), 86400); + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), now.sec_since_epoch()); + + // alice assign bob as voting account + graphene::chain::account_update_operation op; + op.account = alice_id; + op.new_options = alice_id(db).options; + op.new_options->voting_account = bob_id; + trx.operations.push_back(op); + set_expiration(db, trx); + trx.validate(); + sign(trx, alice_private_key); + PUSH_TX( db, trx, ~0 ); + trx.clear(); + + generate_block(); + + // vote for witness1 + auto witness1 = witness_id_type(1)(db); + vote_for(bob_id, witness1.vote_id, bob_private_key); + + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + + // check vesting factor of current subperiod + BOOST_CHECK_EQUAL(db_api.get_gpos_info(alice_id).vesting_factor, 1); + BOOST_CHECK_EQUAL(db_api.get_gpos_info(bob_id).vesting_factor, 1); + + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + generate_block(); + + // GPOS 2nd subperiod started. + // vesting factor decay + BOOST_CHECK_EQUAL(db_api.get_gpos_info(alice_id).vesting_factor, 0.83333333333333337); + BOOST_CHECK_EQUAL(db_api.get_gpos_info(bob_id).vesting_factor, 0.83333333333333337); + + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + generate_block(); + + // GPOS 3rd subperiod started + // vesting factor decay + BOOST_CHECK_EQUAL(db_api.get_gpos_info(alice_id).vesting_factor, 0.66666666666666663); + BOOST_CHECK_EQUAL(db_api.get_gpos_info(bob_id).vesting_factor, 0.66666666666666663); + + // vote for witness2 + auto witness2 = witness_id_type(2)(db); + vote_for(bob_id, witness2.vote_id, bob_private_key); + + // vesting factor should be 1 for both alice and bob for the current subperiod + BOOST_CHECK_EQUAL(db_api.get_gpos_info(alice_id).vesting_factor, 1); + BOOST_CHECK_EQUAL(db_api.get_gpos_info(bob_id).vesting_factor, 1); + + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + generate_block(); + + // vesting factor decay + BOOST_CHECK_EQUAL(db_api.get_gpos_info(alice_id).vesting_factor, 0.83333333333333337); + BOOST_CHECK_EQUAL(db_api.get_gpos_info(bob_id).vesting_factor, 0.83333333333333337); + } + catch (fc::exception &e) { + edump((e.to_detail_string())); + throw; + } +} + +BOOST_AUTO_TEST_CASE( no_proposal ) +{ + try { + + } + catch (fc::exception &e) { + edump((e.to_detail_string())); + throw; + } +} +BOOST_AUTO_TEST_CASE( database_api ) +{ + ACTORS((alice)(bob)); + try { + + // move to hardfork + generate_blocks( HARDFORK_GPOS_TIME ); + generate_block(); + + // database api + graphene::app::database_api db_api(db); + + const auto& core = asset_id_type()(db); + + // send some asset to alice and bob + transfer( committee_account, alice_id, core.amount( 1000 ) ); + transfer( committee_account, bob_id, core.amount( 1000 ) ); + generate_block(); + + // add some vesting to alice and bob + create_vesting(alice_id, core.amount(100), vesting_balance_type::gpos); + generate_block(); + + // total balance is 100 rest of data at 0 + auto gpos_info = db_api.get_gpos_info(alice_id); + BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 0); + BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 0); + BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 100); + + create_vesting(bob_id, core.amount(100), vesting_balance_type::gpos); + generate_block(); + + // total gpos balance is now 200 + gpos_info = db_api.get_gpos_info(alice_id); + BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 200); + + // update default gpos and dividend interval to 10 days + auto now = db.head_block_time(); + update_gpos_global(5184000, 864000, now); // 10 days subperiods + update_payout_interval(core.symbol, HARDFORK_GPOS_TIME + fc::minutes(1), 60 * 60 * 24 * 10); // 10 days + + generate_block(); + + // no votes for witness 1 + auto witness1 = witness_id_type(1)(db); + BOOST_CHECK_EQUAL(witness1.total_votes, 0); + + // no votes for witness 2 + auto witness2 = witness_id_type(2)(db); + BOOST_CHECK_EQUAL(witness2.total_votes, 0); + + // transfering some coins to distribution account. + const auto& dividend_holder_asset_object = get_asset(GRAPHENE_SYMBOL); + const auto& dividend_data = dividend_holder_asset_object.dividend_data(db); + const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db); + transfer( committee_account, dividend_distribution_account.id, core.amount( 100 ) ); + generate_block(); + + // award balance is now 100 + gpos_info = db_api.get_gpos_info(alice_id); + BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 0); + BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 100); + BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 200); + + // vote for witness1 + vote_for(alice_id, witness1.vote_id, alice_private_key); + vote_for(bob_id, witness1.vote_id, bob_private_key); + + // go to maint + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + + // payment for alice and bob is done, distribution account is back in 0 + gpos_info = db_api.get_gpos_info(alice_id); + BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 1); + BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 0); + BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 200); + + advance_x_maint(10); + + // alice vesting coeffcient decay + gpos_info = db_api.get_gpos_info(alice_id); + BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 0.83333333333333337); + BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 0); + BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 200); + + advance_x_maint(10); + + // vesting factor for alice decaying more + gpos_info = db_api.get_gpos_info(alice_id); + BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 0.66666666666666663); + BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 0); + BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 200); + } + catch (fc::exception &e) { + edump((e.to_detail_string())); + throw; + } +} +BOOST_AUTO_TEST_SUITE_END() + +//#define BOOST_TEST_MODULE "C++ Unit Tests for Graphene Blockchain Database" +#include +#include +#include + +boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) { + std::srand(time(NULL)); + std::cout << "Random number generator seeded to " << time(NULL) << std::endl; + + // betting operations don't take effect until HARDFORK 1000 + GRAPHENE_TESTING_GENESIS_TIMESTAMP = HARDFORK_1000_TIME.sec_since_epoch() + 2; + + return nullptr; +} From f7d7f043cefbc6adfa9fb2ff485323a9c47d9281 Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Wed, 23 Oct 2019 23:18:44 -0300 Subject: [PATCH 21/39] delete unused variables --- tests/gpos/gpos_tests.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/gpos/gpos_tests.cpp b/tests/gpos/gpos_tests.cpp index 335230d7..bfb0e5d3 100644 --- a/tests/gpos/gpos_tests.cpp +++ b/tests/gpos/gpos_tests.cpp @@ -403,7 +403,6 @@ BOOST_AUTO_TEST_CASE( voting ) advance_x_maint(10); - auto now1 = db.head_block_time(); //vote bob tot witness2 in each subperiod and verify votes vote_for(bob_id, witness2.vote_id, bob_private_key); // go to maint @@ -416,7 +415,6 @@ BOOST_AUTO_TEST_CASE( voting ) BOOST_CHECK_EQUAL(witness2.total_votes, 100); advance_x_maint(10); - now1 = db.head_block_time(); vote_for(bob_id, witness2.vote_id, bob_private_key); generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); // decay more @@ -426,7 +424,7 @@ BOOST_AUTO_TEST_CASE( voting ) BOOST_CHECK_EQUAL(witness2.total_votes, 100); advance_x_maint(10); - now1 = db.head_block_time(); + // more vote_for(bob_id, witness2.vote_id, bob_private_key); generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); @@ -437,7 +435,7 @@ BOOST_AUTO_TEST_CASE( voting ) BOOST_CHECK_EQUAL(witness2.total_votes, 100); advance_x_maint(10); - now1 = db.head_block_time(); + // more vote_for(bob_id, witness2.vote_id, bob_private_key); generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); @@ -449,8 +447,7 @@ BOOST_AUTO_TEST_CASE( voting ) BOOST_CHECK_EQUAL(witness2.total_votes, 100); advance_x_maint(10); - now1 = db.head_block_time(); - + // more vote_for(bob_id, witness2.vote_id, bob_private_key); generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); From 69630183f961c3489128478acb066d7a9c5a022f Mon Sep 17 00:00:00 2001 From: Sandip Patel Date: Thu, 24 Oct 2019 19:24:09 +0530 Subject: [PATCH 22/39] removed witness check --- libraries/wallet/wallet.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index c7e605cc..0e4f3198 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2052,17 +2052,8 @@ public: acct_id = get_account( account_name ).id; vbos = _remote_db->get_vesting_balances( *acct_id ); - if( vbos.size() == 0 ) - { - if (is_witness(account_name)) - { - witness_object wit = get_witness( account_name ); - FC_ASSERT( wit.pay_vb, "Account ${account} has no core TOKEN vested and thus its not allowed to withdraw.", ("account", account_name)); - vbid = wit.pay_vb; - } - else - FC_THROW("Account ${account} has no core TOKEN vested and thus its not allowed to withdraw.", ("account", account_name)); - } + if( vbos.size() == 0 ) + FC_THROW("Account ${account} has no core TOKEN vested and thus its not allowed to withdraw.", ("account", account_name)); } //whether it is a witness or user, keep it in a container and iterate over to process all vesting balances and types From 78787c2a14a18ba06efb9ebbcbf611c1b5e7f271 Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Thu, 24 Oct 2019 14:39:01 -0300 Subject: [PATCH 23/39] eliminate time gap between two consecutive vesting periods --- libraries/chain/db_maint.cpp | 6 +++--- tests/tests/gpos_tests.cpp | 31 ++++++++++++++++++++----------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 182c04fc..c983efe8 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -833,7 +833,7 @@ void rolling_period_start(database& db) auto vesting_period = db.get_global_properties().parameters.gpos_period(); auto now = db.head_block_time(); - if(now.sec_since_epoch() > (period_start + vesting_period)) + if(now.sec_since_epoch() >= (period_start + vesting_period)) { // roll db.modify(db.get_global_properties(), [now](global_property_object& p) { @@ -1390,10 +1390,10 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g distribute_fba_balances(*this); create_buyback_orders(*this); - rolling_period_start(*this); - process_dividend_assets(*this); + rolling_period_start(*this); + struct vote_tally_helper { database& d; const global_property_object& props; diff --git a/tests/tests/gpos_tests.cpp b/tests/tests/gpos_tests.cpp index 5b089685..615e76c4 100644 --- a/tests/tests/gpos_tests.cpp +++ b/tests/tests/gpos_tests.cpp @@ -95,6 +95,15 @@ struct gpos_fixture: database_fixture BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_subperiod(), vesting_subperiod); BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), period_start.sec_since_epoch()); } + + void update_maintenance_interval(uint32_t new_interval) + { + db.modify(db.get_global_properties(), [new_interval](global_property_object& p) { + p.parameters.maintenance_interval = new_interval; + }); + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.maintenance_interval, new_interval); + } + void vote_for(const account_id_type account_id, const vote_id_type vote_for, const fc::ecc::private_key& key) { account_update_operation op; @@ -497,26 +506,26 @@ BOOST_AUTO_TEST_CASE( rolling_period_start ) // period start rolls automatically after HF try { // advance to HF - generate_blocks(HARDFORK_GPOS_TIME); - generate_block(); // update default gpos global parameters to make this thing faster - auto now = db.head_block_time(); - update_gpos_global(518400, 86400, now); + update_gpos_global(518400, 86400, HARDFORK_GPOS_TIME); + generate_blocks(HARDFORK_GPOS_TIME); + update_maintenance_interval(3600); //update maintenance interval to 1hr to evaluate sub-periods + BOOST_CHECK_EQUAL(db.get_global_properties().parameters.maintenance_interval, 3600); + auto vesting_period_1 = db.get_global_properties().parameters.gpos_period_start(); + + auto now = db.head_block_time(); // moving outside period: while( db.head_block_time() <= now + fc::days(6) ) { generate_block(); } - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - - // rolling is here so getting the new now - now = db.head_block_time(); generate_block(); - - // period start rolled - BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), now.sec_since_epoch()); + auto vesting_period_2 = db.get_global_properties().parameters.gpos_period_start(); + + //difference between start of two consecutive vesting periods should be 6 days + BOOST_CHECK_EQUAL(vesting_period_1 + 518400, vesting_period_2); } catch (fc::exception &e) { edump((e.to_detail_string())); From 22e5dfa502da136290fb480d774437b49b0ab44f Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Thu, 24 Oct 2019 15:31:49 -0300 Subject: [PATCH 24/39] deleted GPOS specific test suite and updated gpos tests --- tests/CMakeLists.txt | 4 - tests/gpos/gpos_tests.cpp | 1090 ------------------------------------ tests/tests/gpos_tests.cpp | 55 +- 3 files changed, 42 insertions(+), 1107 deletions(-) delete mode 100644 tests/gpos/gpos_tests.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 55f369f4..57a451aa 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -13,10 +13,6 @@ if(MSVC) set_source_files_properties( tests/serialization_tests.cpp PROPERTIES COMPILE_FLAGS "/bigobj" ) endif(MSVC) -file(GLOB GPOS_TESTS "gpos/*.cpp") -add_executable( gpos_test ${GPOS_TESTS} ${COMMON_SOURCES} ) -target_link_libraries( gpos_test graphene_chain graphene_app graphene_account_history graphene_bookie graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} ) - file(GLOB PERFORMANCE_TESTS "performance/*.cpp") add_executable( performance_test ${PERFORMANCE_TESTS} ${COMMON_SOURCES} ) target_link_libraries( performance_test graphene_chain graphene_app graphene_account_history graphene_bookie graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} ) diff --git a/tests/gpos/gpos_tests.cpp b/tests/gpos/gpos_tests.cpp deleted file mode 100644 index bfb0e5d3..00000000 --- a/tests/gpos/gpos_tests.cpp +++ /dev/null @@ -1,1090 +0,0 @@ -/* - * Copyright (c) 2018 oxarbitrage and contributors. - * - * The MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include -#include - -#include -#include -#include -#include - -#include "../common/database_fixture.hpp" - -#include - -using namespace graphene::chain; -using namespace graphene::chain::test; - -struct gpos_fixture: database_fixture -{ - const worker_object& create_worker( const account_id_type owner, const share_type daily_pay, - const fc::microseconds& duration ) { - worker_create_operation op; - op.owner = owner; - op.daily_pay = daily_pay; - op.initializer = vesting_balance_worker_initializer(1); - op.work_begin_date = db.head_block_time(); - op.work_end_date = op.work_begin_date + duration; - trx.operations.push_back(op); - set_expiration(db, trx); - trx.validate(); - processed_transaction ptx = db.push_transaction(trx, ~0); - trx.clear(); - return db.get(ptx.operation_results[0].get()); - } - const vesting_balance_object& create_vesting(const account_id_type owner, const asset amount, - const vesting_balance_type type) - { - vesting_balance_create_operation op; - op.creator = owner; - op.owner = owner; - op.amount = amount; - op.balance_type = type; - - trx.operations.push_back(op); - set_expiration(db, trx); - processed_transaction ptx = PUSH_TX(db, trx, ~0); - trx.clear(); - return db.get(ptx.operation_results[0].get()); - } - - void update_payout_interval(std::string asset_name, fc::time_point start, uint32_t interval) - { - auto dividend_holder_asset_object = get_asset(asset_name); - asset_update_dividend_operation op; - op.issuer = dividend_holder_asset_object.issuer; - op.asset_to_update = dividend_holder_asset_object.id; - op.new_options.next_payout_time = start; - op.new_options.payout_interval = interval; - trx.operations.push_back(op); - set_expiration(db, trx); - PUSH_TX(db, trx, ~0); - trx.operations.clear(); - } - - void update_gpos_global(uint32_t vesting_period, uint32_t vesting_subperiod, fc::time_point_sec period_start) - { - db.modify(db.get_global_properties(), [vesting_period, vesting_subperiod, period_start](global_property_object& p) { - p.parameters.extensions.value.gpos_period = vesting_period; - p.parameters.extensions.value.gpos_subperiod = vesting_subperiod; - p.parameters.extensions.value.gpos_period_start = period_start.sec_since_epoch(); - }); - BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period(), vesting_period); - BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_subperiod(), vesting_subperiod); - BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), period_start.sec_since_epoch()); - } - void vote_for(const account_id_type account_id, const vote_id_type vote_for, const fc::ecc::private_key& key) - { - account_update_operation op; - op.account = account_id; - op.new_options = account_id(db).options; - op.new_options->votes.insert(vote_for); - trx.operations.push_back(op); - set_expiration(db, trx); - trx.validate(); - sign(trx, key); - PUSH_TX(db, trx); - trx.clear(); - } - void fill_reserve_pool(const account_id_type account_id, asset amount) - { - asset_reserve_operation op; - op.payer = account_id; - op.amount_to_reserve = amount; - trx.operations.push_back(op); - trx.validate(); - set_expiration(db, trx); - PUSH_TX( db, trx, ~0 ); - trx.clear(); - } - - void advance_x_maint(int periods) - { - for(int i=0; i(ptx.operation_results[0].get()); - - // check created vesting amount and policy - BOOST_CHECK_EQUAL(alice_vesting.balance.amount.value, 100); - BOOST_CHECK_EQUAL(alice_vesting.policy.get().vesting_duration_seconds, - db.get_global_properties().parameters.gpos_subperiod()); - BOOST_CHECK_EQUAL(alice_vesting.policy.get().vesting_cliff_seconds, - db.get_global_properties().parameters.gpos_subperiod()); - - // bob creates a gpos vesting with his custom policy - { - vesting_balance_create_operation op; - op.creator = bob_id; - op.owner = bob_id; - op.amount = core.amount(200); - op.balance_type = vesting_balance_type::gpos; - op.policy = cdd_vesting_policy_initializer{ 60*60*24 }; - - trx.operations.push_back(op); - set_expiration(db, trx); - ptx = PUSH_TX(db, trx, ~0); - trx.clear(); - } - auto bob_vesting = db.get(ptx.operation_results[0].get()); - - generate_block(); - - // policy is not the one defined by the user but default - BOOST_CHECK_EQUAL(bob_vesting.balance.amount.value, 200); - BOOST_CHECK_EQUAL(bob_vesting.policy.get().vesting_duration_seconds, - db.get_global_properties().parameters.gpos_subperiod()); - BOOST_CHECK_EQUAL(bob_vesting.policy.get().vesting_cliff_seconds, - db.get_global_properties().parameters.gpos_subperiod()); - - } - catch (fc::exception& e) - { - edump((e.to_detail_string())); - throw; - } -} - -BOOST_AUTO_TEST_CASE( dividends ) -{ - ACTORS((alice)(bob)); - try - { - // move to 1 week before hardfork - generate_blocks( HARDFORK_GPOS_TIME - fc::days(7) ); - generate_block(); - - const auto& core = asset_id_type()(db); - - // all core coins are in the committee_account - BOOST_CHECK_EQUAL(get_balance(committee_account(db), core), 1000000000000000); - - // transfer half of the total stake to alice so not all the dividends will go to the committee_account - transfer( committee_account, alice_id, core.amount( 500000000000000 ) ); - generate_block(); - - // send some to bob - transfer( committee_account, bob_id, core.amount( 1000 ) ); - generate_block(); - - // committee balance - BOOST_CHECK_EQUAL(get_balance(committee_account(db), core), 499999999999000); - - // alice balance - BOOST_CHECK_EQUAL(get_balance(alice_id(db), core), 500000000000000); - - // bob balance - BOOST_CHECK_EQUAL(get_balance(bob_id(db), core), 1000); - - // get core asset object - const auto& dividend_holder_asset_object = get_asset(GRAPHENE_SYMBOL); - - // by default core token pays dividends once per month - const auto& dividend_data = dividend_holder_asset_object.dividend_data(db); - BOOST_CHECK_EQUAL(*dividend_data.options.payout_interval, 2592000); // 30 days - - // update the payout interval for speed purposes of the test - update_payout_interval(core.symbol, HARDFORK_GPOS_TIME - fc::days(7) + fc::minutes(1), 60 * 60 * 24); // 1 day - - generate_block(); - - BOOST_CHECK_EQUAL(*dividend_data.options.payout_interval, 86400); // 1 day now - - // get the dividend distribution account - const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db); - - // transfering some coins to distribution account. - // simulating the blockchain haves some dividends to pay. - transfer( committee_account, dividend_distribution_account.id, core.amount( 100 ) ); - generate_block(); - - // committee balance - BOOST_CHECK_EQUAL(get_balance(committee_account(db), core), 499999999998900 ); - - // distribution account balance - BOOST_CHECK_EQUAL(get_balance(dividend_distribution_account, core), 100); - - // get when is the next payout time as we need to advance there - auto next_payout_time = dividend_data.options.next_payout_time; - - // advance to next payout - generate_blocks(*next_payout_time); - - // advance to next maint after payout time arrives - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - - // check balances now, dividends are paid "normally" - BOOST_CHECK_EQUAL(get_balance(committee_account(db), core), 499999999998949 ); - BOOST_CHECK_EQUAL(get_balance(alice_id(db), core), 500000000000050 ); - BOOST_CHECK_EQUAL(get_balance(bob_id(db), core), 1000 ); - BOOST_CHECK_EQUAL(get_balance(dividend_distribution_account, core), 1); - - // advance to hardfork - generate_blocks( HARDFORK_GPOS_TIME ); - - // advance to next maint - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - - // send 99 to the distribution account so it will have 100 PPY again to share - transfer( committee_account, dividend_distribution_account.id, core.amount( 99 ) ); - generate_block(); - - // get when is the next payout time as we need to advance there - next_payout_time = dividend_data.options.next_payout_time; - - // advance to next payout - generate_blocks(*next_payout_time); - - // advance to next maint - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - - // make sure no dividends were paid "normally" - BOOST_CHECK_EQUAL(get_balance(committee_account(db), core), 499999999998850 ); - BOOST_CHECK_EQUAL(get_balance(alice_id(db), core), 500000000000050 ); - BOOST_CHECK_EQUAL(get_balance(bob_id(db), core), 1000 ); - BOOST_CHECK_EQUAL(get_balance(dividend_distribution_account, core), 100); - - // create vesting balance - create_vesting(bob_id, core.amount(100), vesting_balance_type::gpos); - - // need to vote to get paid - auto witness1 = witness_id_type(1)(db); - vote_for(bob_id, witness1.vote_id, bob_private_key); - - generate_block(); - - // check balances - BOOST_CHECK_EQUAL(get_balance(bob_id(db), core), 900 ); - BOOST_CHECK_EQUAL(get_balance(dividend_distribution_account, core), 100); - - // advance to next payout - generate_blocks(*next_payout_time); - - // advance to next maint - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - - // check balances, dividends paid to bob - BOOST_CHECK_EQUAL(get_balance(bob_id(db), core), 1000 ); - BOOST_CHECK_EQUAL(get_balance(dividend_distribution_account, core), 0); - } - catch (fc::exception& e) - { - edump((e.to_detail_string())); - throw; - } -} - -BOOST_AUTO_TEST_CASE( voting ) -{ - ACTORS((alice)(bob)); - try { - - // move to hardfork - generate_blocks( HARDFORK_GPOS_TIME ); - generate_block(); - - const auto& core = asset_id_type()(db); - - // send some asset to alice and bob - transfer( committee_account, alice_id, core.amount( 1000 ) ); - transfer( committee_account, bob_id, core.amount( 1000 ) ); - generate_block(); - - // default maintenance_interval is 1 day - BOOST_CHECK_EQUAL(db.get_global_properties().parameters.maintenance_interval, 86400); - - // add some vesting to alice and bob - create_vesting(alice_id, core.amount(100), vesting_balance_type::gpos); - create_vesting(bob_id, core.amount(100), vesting_balance_type::gpos); - generate_block(); - - // default gpos values - BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period(), 15552000); - BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_subperiod(), 2592000); - BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), HARDFORK_GPOS_TIME.sec_since_epoch()); - - // update default gpos for test speed - auto now = db.head_block_time(); - // 5184000 = 60x60x24x60 = 60 days - // 864000 = 60x60x24x10 = 10 days - update_gpos_global(5184000, 864000, now); - - BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period(), 5184000); - BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_subperiod(), 864000); - BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), now.sec_since_epoch()); - // end global changes - - generate_block(); - - // no votes for witness 1 - auto witness1 = witness_id_type(1)(db); - BOOST_CHECK_EQUAL(witness1.total_votes, 0); - - // no votes for witness 2 - auto witness2 = witness_id_type(2)(db); - BOOST_CHECK_EQUAL(witness2.total_votes, 0); - - // vote for witness1 - vote_for(alice_id, witness1.vote_id, alice_private_key); - vote_for(bob_id, witness2.vote_id, bob_private_key); - - // go to maint - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - - // vote is the same as amount in the first subperiod since voting - witness1 = witness_id_type(1)(db); - witness2 = witness_id_type(2)(db); - BOOST_CHECK_EQUAL(witness1.total_votes, 100); - BOOST_CHECK_EQUAL(witness2.total_votes, 100); - - advance_x_maint(10); - - //vote bob tot witness2 in each subperiod and verify votes - vote_for(bob_id, witness2.vote_id, bob_private_key); - // go to maint - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - // vote decay as time pass - witness1 = witness_id_type(1)(db); - witness2 = witness_id_type(2)(db); - - BOOST_CHECK_EQUAL(witness1.total_votes, 83); - BOOST_CHECK_EQUAL(witness2.total_votes, 100); - - advance_x_maint(10); - vote_for(bob_id, witness2.vote_id, bob_private_key); - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - // decay more - witness1 = witness_id_type(1)(db); - witness2 = witness_id_type(2)(db); - BOOST_CHECK_EQUAL(witness1.total_votes, 66); - BOOST_CHECK_EQUAL(witness2.total_votes, 100); - - advance_x_maint(10); - - // more - vote_for(bob_id, witness2.vote_id, bob_private_key); - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - // decay more - witness1 = witness_id_type(1)(db); - witness2 = witness_id_type(2)(db); - BOOST_CHECK_EQUAL(witness1.total_votes, 50); - BOOST_CHECK_EQUAL(witness2.total_votes, 100); - - advance_x_maint(10); - - // more - vote_for(bob_id, witness2.vote_id, bob_private_key); - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - // decay more - witness1 = witness_id_type(1)(db); - witness2 = witness_id_type(2)(db); - - BOOST_CHECK_EQUAL(witness1.total_votes, 33); - BOOST_CHECK_EQUAL(witness2.total_votes, 100); - - advance_x_maint(10); - - // more - vote_for(bob_id, witness2.vote_id, bob_private_key); - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - // decay more - witness1 = witness_id_type(1)(db); - witness2 = witness_id_type(2)(db); - BOOST_CHECK_EQUAL(witness1.total_votes, 16); - BOOST_CHECK_EQUAL(witness2.total_votes, 100); - - // we are still in gpos period 1 - BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), now.sec_since_epoch()); - - advance_x_maint(5); - // a new GPOS period is in but vote from user is before the start so his voting power is 0 - now = db.head_block_time(); - BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), now.sec_since_epoch()); - - generate_block(); - - witness1 = witness_id_type(1)(db); - witness2 = witness_id_type(2)(db); - BOOST_CHECK_EQUAL(witness1.total_votes, 0); - BOOST_CHECK_EQUAL(witness2.total_votes, 0); - - // we are in the second GPOS period, at subperiod 2, lets vote here - vote_for(bob_id, witness2.vote_id, bob_private_key); - generate_block(); - - // go to maint - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - - witness1 = witness_id_type(1)(db); - witness2 = witness_id_type(2)(db); - - BOOST_CHECK_EQUAL(witness1.total_votes, 0); - BOOST_CHECK_EQUAL(witness2.total_votes, 100); - - advance_x_maint(10); - - witness1 = witness_id_type(1)(db); - witness2 = witness_id_type(2)(db); - - BOOST_CHECK_EQUAL(witness1.total_votes, 0); - BOOST_CHECK_EQUAL(witness2.total_votes, 83); - - vote_for(bob_id, witness2.vote_id, bob_private_key); - generate_block(); - - advance_x_maint(10); - - witness1 = witness_id_type(1)(db); - witness2 = witness_id_type(2)(db); - - BOOST_CHECK_EQUAL(witness1.total_votes, 0); - BOOST_CHECK_EQUAL(witness2.total_votes, 83); - - // alice votes again, now for witness 2, her vote worth 100 now - vote_for(alice_id, witness2.vote_id, alice_private_key); - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - - witness1 = witness_id_type(1)(db); - witness2 = witness_id_type(2)(db); - - BOOST_CHECK_EQUAL(witness1.total_votes, 100); - BOOST_CHECK_EQUAL(witness2.total_votes, 183); - - } - catch (fc::exception &e) { - edump((e.to_detail_string())); - throw; - } -} - -BOOST_AUTO_TEST_CASE( rolling_period_start ) -{ - // period start rolls automatically after HF - try { - // advance to HF - generate_blocks(HARDFORK_GPOS_TIME); - generate_block(); - - // update default gpos global parameters to make this thing faster - auto now = db.head_block_time(); - update_gpos_global(518400, 86400, now); - - // moving outside period: - while( db.head_block_time() <= now + fc::days(6) ) - { - generate_block(); - } - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - - // rolling is here so getting the new now - now = db.head_block_time(); - generate_block(); - - // period start rolled - BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), now.sec_since_epoch()); - } - catch (fc::exception &e) { - edump((e.to_detail_string())); - throw; - } -} -BOOST_AUTO_TEST_CASE( worker_dividends_voting ) -{ - try { - // advance to HF - generate_blocks(HARDFORK_GPOS_TIME); - generate_block(); - - // update default gpos global parameters to 4 days - auto now = db.head_block_time(); - update_gpos_global(345600, 86400, now); - - generate_block(); - set_expiration(db, trx); - const auto& core = asset_id_type()(db); - - // get core asset object - const auto& dividend_holder_asset_object = get_asset(GRAPHENE_SYMBOL); - - // by default core token pays dividends once per month - const auto& dividend_data = dividend_holder_asset_object.dividend_data(db); - BOOST_CHECK_EQUAL(*dividend_data.options.payout_interval, 2592000); // 30 days - - // update the payout interval to 1 day for speed purposes of the test - update_payout_interval(core.symbol, HARDFORK_GPOS_TIME + fc::minutes(1), 60 * 60 * 24); // 1 day - - generate_block(); - - // get the dividend distribution account - const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db); - - // transfering some coins to distribution account. - transfer( committee_account, dividend_distribution_account.id, core.amount( 100 ) ); - generate_block(); - - ACTORS((nathan)(voter1)(voter2)(voter3)); - - transfer( committee_account, nathan_id, core.amount( 1000 ) ); - transfer( committee_account, voter1_id, core.amount( 1000 ) ); - transfer( committee_account, voter2_id, core.amount( 1000 ) ); - - generate_block(); - - upgrade_to_lifetime_member(nathan_id); - - auto worker = create_worker(nathan_id, 10, fc::days(6)); - - // add some vesting to voter1 - create_vesting(voter1_id, core.amount(100), vesting_balance_type::gpos); - - // add some vesting to voter2 - create_vesting(voter2_id, core.amount(100), vesting_balance_type::gpos); - - generate_block(); - - // vote for worker - vote_for(voter1_id, worker.vote_for, voter1_private_key); - - // first maint pass, coefficient will be 1 - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - worker = worker_id_type()(db); - BOOST_CHECK_EQUAL(worker.total_votes_for, 100); - - // here dividends are paid to voter1 and voter2 - // voter1 get paid full dividend share as coefficent is at 1 here - BOOST_CHECK_EQUAL(get_balance(voter1_id(db), core), 950); - - // voter2 didnt voted so he dont get paid - BOOST_CHECK_EQUAL(get_balance(voter2_id(db), core), 900); - - // send some asset to the reserve pool so the worker can get paid - fill_reserve_pool(account_id_type(), asset(GRAPHENE_MAX_SHARE_SUPPLY/2)); - - BOOST_CHECK_EQUAL(worker_id_type()(db).worker.get().balance(db).balance.amount.value, 0); - BOOST_CHECK_EQUAL(worker.worker.get().balance(db).balance.amount.value, 0); - - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - - // worker is getting paid - BOOST_CHECK_EQUAL(worker_id_type()(db).worker.get().balance(db).balance.amount.value, 10); - BOOST_CHECK_EQUAL(worker.worker.get().balance(db).balance.amount.value, 10); - - // second maint pass, coefficient will be 0.75 - worker = worker_id_type()(db); - BOOST_CHECK_EQUAL(worker.total_votes_for, 75); - - // more decay - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - - worker = worker_id_type()(db); - BOOST_CHECK_EQUAL(worker.total_votes_for, 50); - - transfer( committee_account, dividend_distribution_account.id, core.amount( 100 ) ); - generate_block(); - - BOOST_CHECK_EQUAL(get_balance(committee_account(db), core), 499999999996850); - - // more decay - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - - worker = worker_id_type()(db); - BOOST_CHECK_EQUAL(worker.total_votes_for, 25); - - // here voter1 get paid again but less money by vesting coefficient - BOOST_CHECK_EQUAL(get_balance(voter1_id(db), core), 962); - BOOST_CHECK_EQUAL(get_balance(voter2_id(db), core), 900); - - // remaining dividends not paid by coeffcient are sent to committee account - BOOST_CHECK_EQUAL(get_balance(committee_account(db), core), 499999999996938); - } - catch (fc::exception &e) { - edump((e.to_detail_string())); - throw; - } -} - -BOOST_AUTO_TEST_CASE( account_multiple_vesting ) -{ - try { - // advance to HF - generate_blocks(HARDFORK_GPOS_TIME); - generate_block(); - set_expiration(db, trx); - - // update default gpos global parameters to 4 days - auto now = db.head_block_time(); - update_gpos_global(345600, 86400, now); - - ACTORS((sam)(patty)); - - const auto& core = asset_id_type()(db); - - transfer( committee_account, sam_id, core.amount( 300 ) ); - transfer( committee_account, patty_id, core.amount( 100 ) ); - - // add some vesting to sam - create_vesting(sam_id, core.amount(100), vesting_balance_type::gpos); - - // have another balance with 200 more - create_vesting(sam_id, core.amount(200), vesting_balance_type::gpos); - - // patty also have vesting balance - create_vesting(patty_id, core.amount(100), vesting_balance_type::gpos); - - // get core asset object - const auto& dividend_holder_asset_object = get_asset(GRAPHENE_SYMBOL); - const auto& dividend_data = dividend_holder_asset_object.dividend_data(db); - - // update the payout interval - update_payout_interval(core.symbol, HARDFORK_GPOS_TIME + fc::minutes(1), 60 * 60 * 24); // 1 day - - // get the dividend distribution account - const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db); - - // transfering some coins to distribution account. - transfer( committee_account, dividend_distribution_account.id, core.amount( 100 ) ); - generate_block(); - - // vote for a votable object - auto witness1 = witness_id_type(1)(db); - vote_for(sam_id, witness1.vote_id, sam_private_key); - vote_for(patty_id, witness1.vote_id, patty_private_key); - - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - - // amount in vested balanced will sum up as voting power - witness1 = witness_id_type(1)(db); - BOOST_CHECK_EQUAL(witness1.total_votes, 400); - - // sam get paid dividends - BOOST_CHECK_EQUAL(get_balance(sam_id(db), core), 75); - - // patty also - BOOST_CHECK_EQUAL(get_balance(patty_id(db), core), 25); - - // total vote not decaying - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - generate_block(); - - witness1 = witness_id_type(1)(db); - - BOOST_CHECK_EQUAL(witness1.total_votes, 300); - } - catch (fc::exception &e) { - edump((e.to_detail_string())); - throw; - } -} -/* -BOOST_AUTO_TEST_CASE( competing_proposals ) -{ - try { - // advance to HF - generate_blocks(HARDFORK_GPOS_TIME); - generate_block(); - set_expiration(db, trx); - - ACTORS((voter1)(voter2)(worker1)(worker2)); - - const auto& core = asset_id_type()(db); - - transfer( committee_account, worker1_id, core.amount( 1000 ) ); - transfer( committee_account, worker2_id, core.amount( 1000 ) ); - transfer( committee_account, voter1_id, core.amount( 1000 ) ); - transfer( committee_account, voter2_id, core.amount( 1000 ) ); - - create_vesting(voter1_id, core.amount(200), vesting_balance_type::gpos); - create_vesting(voter2_id, core.amount(300), vesting_balance_type::gpos); - - generate_block(); - - auto now = db.head_block_time(); - update_gpos_global(518400, 86400, now); - - update_payout_interval(core.symbol, fc::time_point::now() + fc::minutes(1), 60 * 60 * 24); // 1 day - - upgrade_to_lifetime_member(worker1_id); - upgrade_to_lifetime_member(worker2_id); - - // create 2 competing proposals asking a lot of token - // todo: maybe a refund worker here so we can test with smaller numbers - auto w1 = create_worker(worker1_id, 100000000000, fc::days(10)); - auto w1_id_instance = w1.id.instance(); - auto w2 = create_worker(worker2_id, 100000000000, fc::days(10)); - auto w2_id_instance = w2.id.instance(); - - fill_reserve_pool(account_id_type(), asset(GRAPHENE_MAX_SHARE_SUPPLY/2)); - - // vote for the 2 workers - vote_for(voter1_id, w1.vote_for, voter1_private_key); - vote_for(voter2_id, w2.vote_for, voter2_private_key); - - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - generate_block(); - - w1 = worker_id_type(w1_id_instance)(db); - w2 = worker_id_type(w2_id_instance)(db); - - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - generate_block(); - - // only w2 is getting paid as it haves more votes and money is only enough for 1 - BOOST_CHECK_EQUAL(w1.worker.get().balance(db).balance.amount.value, 0); - BOOST_CHECK_EQUAL(w2.worker.get().balance(db).balance.amount.value, 100000000000); - - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - generate_block(); - - BOOST_CHECK_EQUAL(w1.worker.get().balance(db).balance.amount.value, 0); - BOOST_CHECK_EQUAL(w2.worker.get().balance(db).balance.amount.value, 150000000000); - - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - generate_block(); - - w1 = worker_id_type(w1_id_instance)(db); - w2 = worker_id_type(w2_id_instance)(db); - - // as votes decay w1 is still getting paid as it always have more votes than w1 - BOOST_CHECK_EQUAL(w1.total_votes_for, 100); - BOOST_CHECK_EQUAL(w2.total_votes_for, 150); - - BOOST_CHECK_EQUAL(w1.worker.get().balance(db).balance.amount.value, 0); - BOOST_CHECK_EQUAL(w2.worker.get().balance(db).balance.amount.value, 200000000000); - - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - generate_block(); - - w1 = worker_id_type(w1_id_instance)(db); - w2 = worker_id_type(w2_id_instance)(db); - - BOOST_CHECK_EQUAL(w1.total_votes_for, 66); - BOOST_CHECK_EQUAL(w2.total_votes_for, 100); - - // worker is sil getting paid as days pass - BOOST_CHECK_EQUAL(w1.worker.get().balance(db).balance.amount.value, 0); - BOOST_CHECK_EQUAL(w2.worker.get().balance(db).balance.amount.value, 250000000000); - - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - generate_block(); - - w1 = worker_id_type(w1_id_instance)(db); - w2 = worker_id_type(w2_id_instance)(db); - - BOOST_CHECK_EQUAL(w1.total_votes_for, 33); - BOOST_CHECK_EQUAL(w2.total_votes_for, 50); - - BOOST_CHECK_EQUAL(w1.worker.get().balance(db).balance.amount.value, 0); - BOOST_CHECK_EQUAL(w2.worker.get().balance(db).balance.amount.value, 300000000000); - - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - generate_block(); - - w1 = worker_id_type(w1_id_instance)(db); - w2 = worker_id_type(w2_id_instance)(db); - - // worker2 will not get paid anymore as it haves 0 votes - BOOST_CHECK_EQUAL(w1.total_votes_for, 0); - BOOST_CHECK_EQUAL(w2.total_votes_for, 0); - - BOOST_CHECK_EQUAL(w1.worker.get().balance(db).balance.amount.value, 0); - BOOST_CHECK_EQUAL(w2.worker.get().balance(db).balance.amount.value, 300000000000); - } - catch (fc::exception &e) { - edump((e.to_detail_string())); - throw; - } -} -*/ -BOOST_AUTO_TEST_CASE( proxy_voting ) -{ - ACTORS((alice)(bob)); - try { - - // move to hardfork - generate_blocks( HARDFORK_GPOS_TIME ); - generate_block(); - - // database api - graphene::app::database_api db_api(db); - - const auto& core = asset_id_type()(db); - - // send some asset to alice and bob - transfer( committee_account, alice_id, core.amount( 1000 ) ); - transfer( committee_account, bob_id, core.amount( 1000 ) ); - generate_block(); - - // add some vesting to alice and bob - create_vesting(alice_id, core.amount(100), vesting_balance_type::gpos); - generate_block(); - - // total balance is 100 rest of data at 0 - auto gpos_info = db_api.get_gpos_info(alice_id); - BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 0); - BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 0); - BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 100); - - create_vesting(bob_id, core.amount(100), vesting_balance_type::gpos); - generate_block(); - - gpos_info = db_api.get_gpos_info(bob_id); - BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 0); - BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 0); - BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 200); - - auto now = db.head_block_time(); - update_gpos_global(518400, 86400, now); - - BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period(), 518400); - BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_subperiod(), 86400); - BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), now.sec_since_epoch()); - - // alice assign bob as voting account - graphene::chain::account_update_operation op; - op.account = alice_id; - op.new_options = alice_id(db).options; - op.new_options->voting_account = bob_id; - trx.operations.push_back(op); - set_expiration(db, trx); - trx.validate(); - sign(trx, alice_private_key); - PUSH_TX( db, trx, ~0 ); - trx.clear(); - - generate_block(); - - // vote for witness1 - auto witness1 = witness_id_type(1)(db); - vote_for(bob_id, witness1.vote_id, bob_private_key); - - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - - // check vesting factor of current subperiod - BOOST_CHECK_EQUAL(db_api.get_gpos_info(alice_id).vesting_factor, 1); - BOOST_CHECK_EQUAL(db_api.get_gpos_info(bob_id).vesting_factor, 1); - - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - generate_block(); - - // GPOS 2nd subperiod started. - // vesting factor decay - BOOST_CHECK_EQUAL(db_api.get_gpos_info(alice_id).vesting_factor, 0.83333333333333337); - BOOST_CHECK_EQUAL(db_api.get_gpos_info(bob_id).vesting_factor, 0.83333333333333337); - - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - generate_block(); - - // GPOS 3rd subperiod started - // vesting factor decay - BOOST_CHECK_EQUAL(db_api.get_gpos_info(alice_id).vesting_factor, 0.66666666666666663); - BOOST_CHECK_EQUAL(db_api.get_gpos_info(bob_id).vesting_factor, 0.66666666666666663); - - // vote for witness2 - auto witness2 = witness_id_type(2)(db); - vote_for(bob_id, witness2.vote_id, bob_private_key); - - // vesting factor should be 1 for both alice and bob for the current subperiod - BOOST_CHECK_EQUAL(db_api.get_gpos_info(alice_id).vesting_factor, 1); - BOOST_CHECK_EQUAL(db_api.get_gpos_info(bob_id).vesting_factor, 1); - - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - generate_block(); - - // vesting factor decay - BOOST_CHECK_EQUAL(db_api.get_gpos_info(alice_id).vesting_factor, 0.83333333333333337); - BOOST_CHECK_EQUAL(db_api.get_gpos_info(bob_id).vesting_factor, 0.83333333333333337); - } - catch (fc::exception &e) { - edump((e.to_detail_string())); - throw; - } -} - -BOOST_AUTO_TEST_CASE( no_proposal ) -{ - try { - - } - catch (fc::exception &e) { - edump((e.to_detail_string())); - throw; - } -} -BOOST_AUTO_TEST_CASE( database_api ) -{ - ACTORS((alice)(bob)); - try { - - // move to hardfork - generate_blocks( HARDFORK_GPOS_TIME ); - generate_block(); - - // database api - graphene::app::database_api db_api(db); - - const auto& core = asset_id_type()(db); - - // send some asset to alice and bob - transfer( committee_account, alice_id, core.amount( 1000 ) ); - transfer( committee_account, bob_id, core.amount( 1000 ) ); - generate_block(); - - // add some vesting to alice and bob - create_vesting(alice_id, core.amount(100), vesting_balance_type::gpos); - generate_block(); - - // total balance is 100 rest of data at 0 - auto gpos_info = db_api.get_gpos_info(alice_id); - BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 0); - BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 0); - BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 100); - - create_vesting(bob_id, core.amount(100), vesting_balance_type::gpos); - generate_block(); - - // total gpos balance is now 200 - gpos_info = db_api.get_gpos_info(alice_id); - BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 200); - - // update default gpos and dividend interval to 10 days - auto now = db.head_block_time(); - update_gpos_global(5184000, 864000, now); // 10 days subperiods - update_payout_interval(core.symbol, HARDFORK_GPOS_TIME + fc::minutes(1), 60 * 60 * 24 * 10); // 10 days - - generate_block(); - - // no votes for witness 1 - auto witness1 = witness_id_type(1)(db); - BOOST_CHECK_EQUAL(witness1.total_votes, 0); - - // no votes for witness 2 - auto witness2 = witness_id_type(2)(db); - BOOST_CHECK_EQUAL(witness2.total_votes, 0); - - // transfering some coins to distribution account. - const auto& dividend_holder_asset_object = get_asset(GRAPHENE_SYMBOL); - const auto& dividend_data = dividend_holder_asset_object.dividend_data(db); - const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db); - transfer( committee_account, dividend_distribution_account.id, core.amount( 100 ) ); - generate_block(); - - // award balance is now 100 - gpos_info = db_api.get_gpos_info(alice_id); - BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 0); - BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 100); - BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 200); - - // vote for witness1 - vote_for(alice_id, witness1.vote_id, alice_private_key); - vote_for(bob_id, witness1.vote_id, bob_private_key); - - // go to maint - generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); - - // payment for alice and bob is done, distribution account is back in 0 - gpos_info = db_api.get_gpos_info(alice_id); - BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 1); - BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 0); - BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 200); - - advance_x_maint(10); - - // alice vesting coeffcient decay - gpos_info = db_api.get_gpos_info(alice_id); - BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 0.83333333333333337); - BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 0); - BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 200); - - advance_x_maint(10); - - // vesting factor for alice decaying more - gpos_info = db_api.get_gpos_info(alice_id); - BOOST_CHECK_EQUAL(gpos_info.vesting_factor, 0.66666666666666663); - BOOST_CHECK_EQUAL(gpos_info.award.amount.value, 0); - BOOST_CHECK_EQUAL(gpos_info.total_amount.value, 200); - } - catch (fc::exception &e) { - edump((e.to_detail_string())); - throw; - } -} -BOOST_AUTO_TEST_SUITE_END() - -//#define BOOST_TEST_MODULE "C++ Unit Tests for Graphene Blockchain Database" -#include -#include -#include - -boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) { - std::srand(time(NULL)); - std::cout << "Random number generator seeded to " << time(NULL) << std::endl; - - // betting operations don't take effect until HARDFORK 1000 - GRAPHENE_TESTING_GENESIS_TIMESTAMP = HARDFORK_1000_TIME.sec_since_epoch() + 2; - - return nullptr; -} diff --git a/tests/tests/gpos_tests.cpp b/tests/tests/gpos_tests.cpp index 5b089685..3366a84b 100644 --- a/tests/tests/gpos_tests.cpp +++ b/tests/tests/gpos_tests.cpp @@ -390,53 +390,77 @@ BOOST_AUTO_TEST_CASE( voting ) // vote for witness1 vote_for(alice_id, witness1.vote_id, alice_private_key); + vote_for(bob_id, witness2.vote_id, bob_private_key); // go to maint generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); // vote is the same as amount in the first subperiod since voting witness1 = witness_id_type(1)(db); + witness2 = witness_id_type(2)(db); BOOST_CHECK_EQUAL(witness1.total_votes, 100); + BOOST_CHECK_EQUAL(witness2.total_votes, 100); advance_x_maint(10); + //vote bob tot witness2 in each subperiod and verify votes + vote_for(bob_id, witness2.vote_id, bob_private_key); + // go to maint + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); // vote decay as time pass witness1 = witness_id_type(1)(db); + witness2 = witness_id_type(2)(db); + BOOST_CHECK_EQUAL(witness1.total_votes, 83); - + BOOST_CHECK_EQUAL(witness2.total_votes, 100); + advance_x_maint(10); - + vote_for(bob_id, witness2.vote_id, bob_private_key); + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); // decay more witness1 = witness_id_type(1)(db); + witness2 = witness_id_type(2)(db); BOOST_CHECK_EQUAL(witness1.total_votes, 66); + BOOST_CHECK_EQUAL(witness2.total_votes, 100); advance_x_maint(10); - + // more + vote_for(bob_id, witness2.vote_id, bob_private_key); + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + // decay more witness1 = witness_id_type(1)(db); + witness2 = witness_id_type(2)(db); BOOST_CHECK_EQUAL(witness1.total_votes, 50); + BOOST_CHECK_EQUAL(witness2.total_votes, 100); advance_x_maint(10); - + // more + vote_for(bob_id, witness2.vote_id, bob_private_key); + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + // decay more witness1 = witness_id_type(1)(db); + witness2 = witness_id_type(2)(db); + BOOST_CHECK_EQUAL(witness1.total_votes, 33); + BOOST_CHECK_EQUAL(witness2.total_votes, 100); advance_x_maint(10); - + // more + vote_for(bob_id, witness2.vote_id, bob_private_key); + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + // decay more witness1 = witness_id_type(1)(db); + witness2 = witness_id_type(2)(db); BOOST_CHECK_EQUAL(witness1.total_votes, 16); + BOOST_CHECK_EQUAL(witness2.total_votes, 100); // we are still in gpos period 1 BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), now.sec_since_epoch()); - advance_x_maint(10); - - // until 0 - witness1 = witness_id_type(1)(db); - BOOST_CHECK_EQUAL(witness1.total_votes, 0); - + advance_x_maint(5); // a new GPOS period is in but vote from user is before the start so his voting power is 0 now = db.head_block_time(); BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), now.sec_since_epoch()); @@ -444,7 +468,9 @@ BOOST_AUTO_TEST_CASE( voting ) generate_block(); witness1 = witness_id_type(1)(db); + witness2 = witness_id_type(2)(db); BOOST_CHECK_EQUAL(witness1.total_votes, 0); + BOOST_CHECK_EQUAL(witness2.total_votes, 0); // we are in the second GPOS period, at subperiod 2, lets vote here vote_for(bob_id, witness2.vote_id, bob_private_key); @@ -467,13 +493,16 @@ BOOST_AUTO_TEST_CASE( voting ) BOOST_CHECK_EQUAL(witness1.total_votes, 0); BOOST_CHECK_EQUAL(witness2.total_votes, 83); + vote_for(bob_id, witness2.vote_id, bob_private_key); + generate_block(); + advance_x_maint(10); witness1 = witness_id_type(1)(db); witness2 = witness_id_type(2)(db); BOOST_CHECK_EQUAL(witness1.total_votes, 0); - BOOST_CHECK_EQUAL(witness2.total_votes, 66); + BOOST_CHECK_EQUAL(witness2.total_votes, 83); // alice votes again, now for witness 2, her vote worth 100 now vote_for(alice_id, witness2.vote_id, alice_private_key); @@ -483,7 +512,7 @@ BOOST_AUTO_TEST_CASE( voting ) witness2 = witness_id_type(2)(db); BOOST_CHECK_EQUAL(witness1.total_votes, 100); - BOOST_CHECK_EQUAL(witness2.total_votes, 166); + BOOST_CHECK_EQUAL(witness2.total_votes, 183); } catch (fc::exception &e) { From bdd1863cf2a4e3f58b67c01c792e53e2c089f0bc Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Thu, 24 Oct 2019 23:53:47 -0300 Subject: [PATCH 25/39] updated GPOS hf --- libraries/chain/hardfork.d/GPOS.hf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/chain/hardfork.d/GPOS.hf b/libraries/chain/hardfork.d/GPOS.hf index f175ef2c..f86dbc22 100644 --- a/libraries/chain/hardfork.d/GPOS.hf +++ b/libraries/chain/hardfork.d/GPOS.hf @@ -1,4 +1,4 @@ -// GPOS HARDFORK Friday, March 15, 2019 11:57:28 PM +// GPOS HARDFORK Tuesday, October 22, 2019 05:00:00 AM GMT #ifndef HARDFORK_GPOS_TIME -#define HARDFORK_GPOS_TIME (fc::time_point_sec( 1552694248 )) -#endif \ No newline at end of file +#define HARDFORK_GPOS_TIME (fc::time_point_sec( 1571720400 )) +#endif From a8423f167d934167c7c48e72ef400b101ca2418f Mon Sep 17 00:00:00 2001 From: Sandip Patel Date: Fri, 25 Oct 2019 16:41:34 +0530 Subject: [PATCH 26/39] Fixed dividend distribution issue and added test case --- libraries/chain/db_maint.cpp | 4 +- tests/tests/gpos_tests.cpp | 170 +++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+), 2 deletions(-) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 182c04fc..42c13705 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -1090,8 +1090,8 @@ void schedule_pending_dividend_balances(database& db, dlog("Crediting committee_account with ${amount}", ("amount", asset(full_shares_to_credit - shares_to_credit, payout_asset_type))); db.adjust_balance(dividend_data.dividend_distribution_account, - -(full_shares_to_credit - shares_to_credit)); - db.adjust_balance(account_id_type(0), full_shares_to_credit - shares_to_credit); + -asset(full_shares_to_credit - shares_to_credit, payout_asset_type)); + db.adjust_balance(account_id_type(0), asset(full_shares_to_credit - shares_to_credit, payout_asset_type)); } remaining_amount_to_distribute = credit_account(db, diff --git a/tests/tests/gpos_tests.cpp b/tests/tests/gpos_tests.cpp index 5b089685..76d27e46 100644 --- a/tests/tests/gpos_tests.cpp +++ b/tests/tests/gpos_tests.cpp @@ -338,6 +338,176 @@ BOOST_AUTO_TEST_CASE( dividends ) } } +BOOST_AUTO_TEST_CASE( gpos_basic_dividend_distribution_to_core_asset ) +{ + + using namespace graphene; + ACTORS((alice)(bob)(carol)(dave)); + try { + + const auto& core = asset_id_type()(db); + BOOST_TEST_MESSAGE("Creating test asset"); + { + asset_create_operation creator; + creator.issuer = account_id_type(); + creator.fee = asset(); + creator.symbol = "TESTB"; + creator.common_options.max_supply = 100000000; + creator.precision = 2; + creator.common_options.market_fee_percent = GRAPHENE_MAX_MARKET_FEE_PERCENT/100; /*1%*/ + creator.common_options.issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK; + creator.common_options.flags = charge_market_fee; + creator.common_options.core_exchange_rate = price({asset(2),asset(1,asset_id_type(1))}); + trx.operations.push_back(std::move(creator)); + set_expiration(db, trx); + PUSH_TX( db, trx, ~0 ); + trx.operations.clear(); + } + + // pass hardfork + generate_blocks( HARDFORK_GPOS_TIME ); + generate_block(); + + const auto& dividend_holder_asset_object = asset_id_type(0)(db); + const auto& dividend_data = dividend_holder_asset_object.dividend_data(db); + const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db); + const account_object& alice = get_account("alice"); + const account_object& bob = get_account("bob"); + const account_object& carol = get_account("carol"); + const account_object& dave = get_account("dave"); + const auto& test_asset_object = get_asset("TESTB"); + + auto issue_asset_to_account = [&](const asset_object& asset_to_issue, const account_object& destination_account, int64_t amount_to_issue) + { + asset_issue_operation op; + op.issuer = asset_to_issue.issuer; + op.asset_to_issue = asset(amount_to_issue, asset_to_issue.id); + op.issue_to_account = destination_account.id; + trx.operations.push_back( op ); + set_expiration(db, trx); + PUSH_TX( db, trx, ~0 ); + trx.operations.clear(); + }; + + auto verify_pending_balance = [&](const account_object& holder_account_obj, const asset_object& payout_asset_obj, int64_t expected_balance) { + int64_t pending_balance = get_dividend_pending_payout_balance(dividend_holder_asset_object.id, + holder_account_obj.id, + payout_asset_obj.id); + BOOST_CHECK_EQUAL(pending_balance, expected_balance); + }; + + auto advance_to_next_payout_time = [&]() { + // Advance to the next upcoming payout time + BOOST_REQUIRE(dividend_data.options.next_payout_time); + fc::time_point_sec next_payout_scheduled_time = *dividend_data.options.next_payout_time; + idump((next_payout_scheduled_time)); + // generate blocks up to the next scheduled time + generate_blocks(next_payout_scheduled_time); + // if the scheduled time fell on a maintenance interval, then we should have paid out. + // if not, we need to advance to the next maintenance interval to trigger the payout + if (dividend_data.options.next_payout_time) + { + // we know there was a next_payout_time set when we entered this, so if + // it has been cleared, we must have already processed payouts, no need to + // further advance time. + BOOST_REQUIRE(dividend_data.options.next_payout_time); + if (*dividend_data.options.next_payout_time == next_payout_scheduled_time) + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + generate_block(); // get the maintenance skip slots out of the way + } + idump((db.head_block_time())); + }; + + // the first test will be testing pending balances, so we need to hit a + // maintenance interval that isn't the payout interval. Payout is + // every 3 days, maintenance interval is every 1 day. + advance_to_next_payout_time(); + + // Set up the first test, issue alice, bob, and carol, and dave each 1/4 of the total + // supply of the core asset. + // Then deposit 400 TEST in the distribution account, and see that they + // each are credited 100 TEST. + transfer( committee_account(db), alice, asset( 250000000000000 ) ); + transfer( committee_account(db), bob, asset( 250000000000000 ) ); + transfer( committee_account(db), carol, asset( 250000000000000 ) ); + transfer( committee_account(db), dave, asset( 250000000000000 ) ); + + // create vesting balance + // bob has not vested anything + create_vesting(alice_id, core.amount(25000000), vesting_balance_type::gpos); + create_vesting(carol_id, core.amount(25000000), vesting_balance_type::gpos); + create_vesting(dave_id, core.amount(25000000), vesting_balance_type::gpos); + + // need to vote to get paid + // carol doesn't participate in voting + auto witness1 = witness_id_type(1)(db); + vote_for(alice_id, witness1.vote_id, alice_private_key); + vote_for(bob_id, witness1.vote_id, bob_private_key); + vote_for(dave_id, witness1.vote_id, dave_private_key); + + // issuing 30000 TESTB to the dividend account + // alice and dave should receive 10000 TESTB as they have gpos vesting and + // participated in voting + // bob should not receive any TESTB as he doesn't have gpos vested + // carol should not receive any TESTB as she doesn't participated in voting + // remaining 10000 TESTB should be deposited in commitee_accoount. + BOOST_TEST_MESSAGE("Issuing 30000 TESTB to the dividend account"); + issue_asset_to_account(test_asset_object, dividend_distribution_account, 30000); + + generate_block(); + + BOOST_TEST_MESSAGE( "Generating blocks until next maintenance interval" ); + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + generate_block(); // get the maintenance skip slots out of the way + + verify_pending_balance(alice, test_asset_object, 10000); + verify_pending_balance(bob, test_asset_object, 0); + verify_pending_balance(carol, test_asset_object, 0); + verify_pending_balance(dave, test_asset_object, 10000); + + + advance_to_next_payout_time(); + + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + generate_block(); // get the maintenance skip slots out of the way + + + auto verify_dividend_payout_operations = [&](const account_object& destination_account, const asset& expected_payout) + { + BOOST_TEST_MESSAGE("Verifying the virtual op was created"); + const account_transaction_history_index& hist_idx = db.get_index_type(); + auto account_history_range = hist_idx.indices().get().equal_range(boost::make_tuple(destination_account.id)); + BOOST_REQUIRE(account_history_range.first != account_history_range.second); + const operation_history_object& history_object = std::prev(account_history_range.second)->operation_id(db); + const asset_dividend_distribution_operation& distribution_operation = history_object.op.get(); + BOOST_CHECK(distribution_operation.account_id == destination_account.id); + BOOST_CHECK(std::find(distribution_operation.amounts.begin(), distribution_operation.amounts.end(), expected_payout) + != distribution_operation.amounts.end()); + }; + + BOOST_TEST_MESSAGE("Verifying the payouts"); + BOOST_CHECK_EQUAL(get_balance(alice, test_asset_object), 10000); + verify_dividend_payout_operations(alice, asset(10000, test_asset_object.id)); + verify_pending_balance(alice, test_asset_object, 0); + + BOOST_CHECK_EQUAL(get_balance(bob, test_asset_object), 0); + verify_pending_balance(bob, test_asset_object, 0); + + BOOST_CHECK_EQUAL(get_balance(carol, test_asset_object), 0); + verify_pending_balance(carol, test_asset_object, 0); + + BOOST_CHECK_EQUAL(get_balance(dave, test_asset_object), 10000); + verify_dividend_payout_operations(dave, asset(10000, test_asset_object.id)); + verify_pending_balance(dave, test_asset_object, 0); + + BOOST_CHECK_EQUAL(get_balance(account_id_type(0)(db), test_asset_object), 10000); + } catch(fc::exception& e) { + edump((e.to_detail_string())); + throw; + } +} + + BOOST_AUTO_TEST_CASE( voting ) { ACTORS((alice)(bob)); From a80d25f9df1e720c1135cc9108325fb7ce8c8b94 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Sun, 27 Oct 2019 08:54:18 -0300 Subject: [PATCH 27/39] fix flag --- libraries/chain/account_evaluator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/account_evaluator.cpp b/libraries/chain/account_evaluator.cpp index 3185c456..96429304 100644 --- a/libraries/chain/account_evaluator.cpp +++ b/libraries/chain/account_evaluator.cpp @@ -287,7 +287,7 @@ void_result account_update_evaluator::do_apply( const account_update_operation& fc::optional< bool > flag = o.extensions.value.update_last_voting_time; if((o.new_options->votes != acnt->options.votes || o.new_options->voting_account != acnt->options.voting_account) || - flag) + (flag.valid() && *flag)) aso.last_vote_time = d.head_block_time(); } ); } From 84f30926bc4f6338347cca07faa3ddc6e032bec1 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Sun, 27 Oct 2019 08:54:37 -0300 Subject: [PATCH 28/39] clean newlines gpos_tests --- tests/tests/gpos_tests.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/tests/tests/gpos_tests.cpp b/tests/tests/gpos_tests.cpp index 37c9475d..5ee36a9e 100644 --- a/tests/tests/gpos_tests.cpp +++ b/tests/tests/gpos_tests.cpp @@ -348,12 +348,10 @@ BOOST_AUTO_TEST_CASE( dividends ) } BOOST_AUTO_TEST_CASE( gpos_basic_dividend_distribution_to_core_asset ) -{ - +{ using namespace graphene; ACTORS((alice)(bob)(carol)(dave)); try { - const auto& core = asset_id_type()(db); BOOST_TEST_MESSAGE("Creating test asset"); { @@ -474,13 +472,11 @@ BOOST_AUTO_TEST_CASE( gpos_basic_dividend_distribution_to_core_asset ) verify_pending_balance(carol, test_asset_object, 0); verify_pending_balance(dave, test_asset_object, 10000); - advance_to_next_payout_time(); generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); generate_block(); // get the maintenance skip slots out of the way - auto verify_dividend_payout_operations = [&](const account_object& destination_account, const asset& expected_payout) { BOOST_TEST_MESSAGE("Verifying the virtual op was created"); @@ -516,12 +512,10 @@ BOOST_AUTO_TEST_CASE( gpos_basic_dividend_distribution_to_core_asset ) } } - BOOST_AUTO_TEST_CASE( voting ) { ACTORS((alice)(bob)); try { - // move to hardfork generate_blocks( HARDFORK_GPOS_TIME ); generate_block(); @@ -704,8 +698,6 @@ BOOST_AUTO_TEST_CASE( rolling_period_start ) { // period start rolls automatically after HF try { - // advance to HF - // update default gpos global parameters to make this thing faster update_gpos_global(518400, 86400, HARDFORK_GPOS_TIME); generate_blocks(HARDFORK_GPOS_TIME); @@ -731,6 +723,7 @@ BOOST_AUTO_TEST_CASE( rolling_period_start ) throw; } } + BOOST_AUTO_TEST_CASE( worker_dividends_voting ) { try { @@ -1042,7 +1035,6 @@ BOOST_AUTO_TEST_CASE( proxy_voting ) { ACTORS((alice)(bob)); try { - // move to hardfork generate_blocks( HARDFORK_GPOS_TIME ); generate_block(); @@ -1153,11 +1145,11 @@ BOOST_AUTO_TEST_CASE( no_proposal ) throw; } } + BOOST_AUTO_TEST_CASE( database_api ) { ACTORS((alice)(bob)); try { - // move to hardfork generate_blocks( HARDFORK_GPOS_TIME ); generate_block(); @@ -1251,4 +1243,5 @@ BOOST_AUTO_TEST_CASE( database_api ) throw; } } + BOOST_AUTO_TEST_SUITE_END() From 7c1966247b4fc29f130a12063e4c2d61d4e04b10 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Sun, 27 Oct 2019 09:10:53 -0300 Subject: [PATCH 29/39] adapt gpos_tests to changed flag --- tests/tests/gpos_tests.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/tests/gpos_tests.cpp b/tests/tests/gpos_tests.cpp index 5ee36a9e..fb3f6987 100644 --- a/tests/tests/gpos_tests.cpp +++ b/tests/tests/gpos_tests.cpp @@ -110,6 +110,7 @@ struct gpos_fixture: database_fixture op.account = account_id; op.new_options = account_id(db).options; op.new_options->votes.insert(vote_for); + op.extensions.value.update_last_voting_time = true; trx.operations.push_back(op); set_expiration(db, trx); trx.validate(); From 5f1436b8be1f26c093f2ff41c8ff6905ec6b85ad Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Sun, 27 Oct 2019 12:54:54 -0300 Subject: [PATCH 30/39] Fix to roll in GPOS rules, carry votes from 6th sub-period --- libraries/chain/db_maint.cpp | 10 ++++++++++ tests/tests/gpos_tests.cpp | 18 ++++++++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index f330e746..9aa684f6 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -780,6 +780,16 @@ double database::calculate_vesting_factor(const account_object& stake_account) uint32_t current_subperiod = get_gpos_current_subperiod(); if(current_subperiod == 0 || current_subperiod > number_of_subperiods) return 0; + + // On starting new vesting period, all votes become zero until some one votes, To avoid a situation of zero votes, + // changes done to roll in GPOS rules, the vesting factor will be 1 for who ever votes in 6th sub-period of last vesting period + // BLOCKBACK-174 fix + if(current_subperiod == 1 && this->head_block_time() >= HARDFORK_GPOS_TIME + vesting_period) //Applicable only from 2nd vesting period + { + if(last_date_voted > period_start - vesting_subperiod) + return 1; //return vesting factor as 1 + } + if(last_date_voted < period_start) return 0; double numerator = number_of_subperiods; diff --git a/tests/tests/gpos_tests.cpp b/tests/tests/gpos_tests.cpp index 37c9475d..3d038ca7 100644 --- a/tests/tests/gpos_tests.cpp +++ b/tests/tests/gpos_tests.cpp @@ -110,6 +110,7 @@ struct gpos_fixture: database_fixture op.account = account_id; op.new_options = account_id(db).options; op.new_options->votes.insert(vote_for); + op.extensions.value.update_last_voting_time = true; trx.operations.push_back(op); set_expiration(db, trx); trx.validate(); @@ -640,18 +641,23 @@ BOOST_AUTO_TEST_CASE( voting ) BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), now.sec_since_epoch()); advance_x_maint(5); - // a new GPOS period is in but vote from user is before the start so his voting power is 0 + // a new GPOS period is in but vote from user is before the start. WHo ever votes in 6th sub-period, votes will carry now = db.head_block_time(); BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), now.sec_since_epoch()); generate_block(); + // we are in the second GPOS period, at subperiod 1, witness1 = witness_id_type(1)(db); witness2 = witness_id_type(2)(db); BOOST_CHECK_EQUAL(witness1.total_votes, 0); - BOOST_CHECK_EQUAL(witness2.total_votes, 0); + //It's critical here, since bob votes in 6th sub-period of last vesting period, witness2 should retain his votes + BOOST_CHECK_EQUAL(witness2.total_votes, 100); - // we are in the second GPOS period, at subperiod 2, lets vote here + + // lets vote here from alice to generate votes for witness 1 + //vote from bob to reatin VF 1 + vote_for(alice_id, witness1.vote_id, alice_private_key); vote_for(bob_id, witness2.vote_id, bob_private_key); generate_block(); @@ -661,7 +667,7 @@ BOOST_AUTO_TEST_CASE( voting ) witness1 = witness_id_type(1)(db); witness2 = witness_id_type(2)(db); - BOOST_CHECK_EQUAL(witness1.total_votes, 0); + BOOST_CHECK_EQUAL(witness1.total_votes, 100); BOOST_CHECK_EQUAL(witness2.total_votes, 100); advance_x_maint(10); @@ -669,7 +675,7 @@ BOOST_AUTO_TEST_CASE( voting ) witness1 = witness_id_type(1)(db); witness2 = witness_id_type(2)(db); - BOOST_CHECK_EQUAL(witness1.total_votes, 0); + BOOST_CHECK_EQUAL(witness1.total_votes, 83); BOOST_CHECK_EQUAL(witness2.total_votes, 83); vote_for(bob_id, witness2.vote_id, bob_private_key); @@ -680,7 +686,7 @@ BOOST_AUTO_TEST_CASE( voting ) witness1 = witness_id_type(1)(db); witness2 = witness_id_type(2)(db); - BOOST_CHECK_EQUAL(witness1.total_votes, 0); + BOOST_CHECK_EQUAL(witness1.total_votes, 66); BOOST_CHECK_EQUAL(witness2.total_votes, 83); // alice votes again, now for witness 2, her vote worth 100 now From ac3554ea2e4de8c117bac0747798a0d20db1e54d Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Sun, 27 Oct 2019 13:11:58 -0300 Subject: [PATCH 31/39] check was already modified --- libraries/wallet/wallet.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 8d2ae75f..449000bc 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2193,9 +2193,6 @@ public: FC_THROW("Account ${account} was already voting for witness ${witness} in the current GPOS sub-period", ("account", voting_account)("witness", witness)); else update_vote_time = true; //Allow user to vote in each sub-period(Update voting time, which is reference in calculating VF) - - if (!insert_result.second) - FC_THROW("Account ${account} has already voted for witness ${witness}", ("account", voting_account)("witness", witness)); } else { From 9f0b23122f3acb0e0d717cd6204a5f395e1a2a1b Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Mon, 28 Oct 2019 10:46:10 -0300 Subject: [PATCH 32/39] comments updated --- libraries/chain/db_maint.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 9aa684f6..5c7e7f5c 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -781,8 +781,8 @@ double database::calculate_vesting_factor(const account_object& stake_account) if(current_subperiod == 0 || current_subperiod > number_of_subperiods) return 0; - // On starting new vesting period, all votes become zero until some one votes, To avoid a situation of zero votes, - // changes done to roll in GPOS rules, the vesting factor will be 1 for who ever votes in 6th sub-period of last vesting period + // On starting new vesting period, all votes become zero until someone votes, To avoid a situation of zero votes, + // changes were done to roll in GPOS rules, the vesting factor will be 1 for whoever votes in 6th sub-period of last vesting period // BLOCKBACK-174 fix if(current_subperiod == 1 && this->head_block_time() >= HARDFORK_GPOS_TIME + vesting_period) //Applicable only from 2nd vesting period { From 3f8ac21b1e31827d0d4889d9f573d11ccf928041 Mon Sep 17 00:00:00 2001 From: pbattu123 Date: Mon, 28 Oct 2019 12:14:53 -0300 Subject: [PATCH 33/39] updated comments to the benefit of reviewer --- libraries/chain/db_maint.cpp | 2 +- tests/tests/gpos_tests.cpp | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 5c7e7f5c..b8044259 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -787,7 +787,7 @@ double database::calculate_vesting_factor(const account_object& stake_account) if(current_subperiod == 1 && this->head_block_time() >= HARDFORK_GPOS_TIME + vesting_period) //Applicable only from 2nd vesting period { if(last_date_voted > period_start - vesting_subperiod) - return 1; //return vesting factor as 1 + return 1; } if(last_date_voted < period_start) return 0; diff --git a/tests/tests/gpos_tests.cpp b/tests/tests/gpos_tests.cpp index 3d038ca7..c2a65673 100644 --- a/tests/tests/gpos_tests.cpp +++ b/tests/tests/gpos_tests.cpp @@ -568,7 +568,7 @@ BOOST_AUTO_TEST_CASE( voting ) auto witness2 = witness_id_type(2)(db); BOOST_CHECK_EQUAL(witness2.total_votes, 0); - // vote for witness1 + // vote for witness1 and witness2 - sub-period 1 vote_for(alice_id, witness1.vote_id, alice_private_key); vote_for(bob_id, witness2.vote_id, bob_private_key); @@ -583,7 +583,7 @@ BOOST_AUTO_TEST_CASE( voting ) advance_x_maint(10); - //vote bob tot witness2 in each subperiod and verify votes + //Bob votes for witness2 - sub-period 2 vote_for(bob_id, witness2.vote_id, bob_private_key); // go to maint generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); @@ -595,6 +595,7 @@ BOOST_AUTO_TEST_CASE( voting ) BOOST_CHECK_EQUAL(witness2.total_votes, 100); advance_x_maint(10); + //Bob votes for witness2 - sub-period 3 vote_for(bob_id, witness2.vote_id, bob_private_key); generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); // decay more @@ -605,7 +606,7 @@ BOOST_AUTO_TEST_CASE( voting ) advance_x_maint(10); - // more + // Bob votes for witness2 - sub-period 4 vote_for(bob_id, witness2.vote_id, bob_private_key); generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); // decay more @@ -616,7 +617,7 @@ BOOST_AUTO_TEST_CASE( voting ) advance_x_maint(10); - // more + // Bob votes for witness2 - sub-period 5 vote_for(bob_id, witness2.vote_id, bob_private_key); generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); // decay more @@ -628,7 +629,7 @@ BOOST_AUTO_TEST_CASE( voting ) advance_x_maint(10); - // more + // Bob votes for witness2 - sub-period 6 vote_for(bob_id, witness2.vote_id, bob_private_key); generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); // decay more @@ -641,7 +642,7 @@ BOOST_AUTO_TEST_CASE( voting ) BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), now.sec_since_epoch()); advance_x_maint(5); - // a new GPOS period is in but vote from user is before the start. WHo ever votes in 6th sub-period, votes will carry + // a new GPOS period is in but vote from user is before the start. Whoever votes in 6th sub-period, votes will carry now = db.head_block_time(); BOOST_CHECK_EQUAL(db.get_global_properties().parameters.gpos_period_start(), now.sec_since_epoch()); From d5d4fdd6d3c5099d6a0e94bb6cffa163b120ec4a Mon Sep 17 00:00:00 2001 From: Sandip Patel Date: Wed, 30 Oct 2019 17:51:02 +0530 Subject: [PATCH 34/39] Added token symbol name in error messages --- libraries/wallet/wallet.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 0e4f3198..9b900d6e 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2008,11 +2008,11 @@ public: if (is_witness(witness_name)) { witness_object wit = get_witness( witness_name ); - FC_ASSERT( wit.pay_vb, "Account ${account} has no core TOKEN vested and thus its not allowed to withdraw.", ("account", witness_name)); + FC_ASSERT( wit.pay_vb, "Account ${account} has no core Token ${TOKEN} vested and thus its not allowed to withdraw.", ("account", witness_name)("TOKEN", GRAPHENE_SYMBOL)); vbid = wit.pay_vb; } else - FC_THROW("Account ${account} has no core TOKEN vested and thus its not allowed to withdraw.", ("account", witness_name)); + FC_THROW("Account ${account} has no core Token ${TOKEN} vested and thus its not allowed to withdraw.", ("account", witness_name)("TOKEN", GRAPHENE_SYMBOL)); } vesting_balance_object vbo = get_object< vesting_balance_object >( *vbid ); @@ -2117,7 +2117,7 @@ public: vbo_iter = std::find_if(vbo_info.begin(), vbo_info.end(), [](vesting_balance_object_with_info const& obj){return obj.balance_type == vesting_balance_type::gpos;}); if( vbo_info.size() == 0 || vbo_iter == vbo_info.end()) - FC_THROW("Account ${account} has no core Token vested and thus she will not be allowed to vote for the committee member", ("account", voting_account)); + FC_THROW("Account ${account} has no core Token ${TOKEN} vested and thus she will not be allowed to vote for the committee member", ("account", voting_account)("TOKEN", GRAPHENE_SYMBOL)); account_object voting_account_object = get_account(voting_account); account_id_type committee_member_owner_account_id = get_account_id(committee_member); @@ -2158,7 +2158,7 @@ public: vbo_iter = std::find_if(vbo_info.begin(), vbo_info.end(), [](vesting_balance_object_with_info const& obj){return obj.balance_type == vesting_balance_type::gpos;}); if( vbo_info.size() == 0 || vbo_iter == vbo_info.end()) - FC_THROW("Account ${account} has no core Token vested and thus she will not be allowed to vote for the witness", ("account", voting_account)); + FC_THROW("Account ${account} has no core Token ${TOKEN} vested and thus she will not be allowed to vote for the witness", ("account", voting_account)("TOKEN", GRAPHENE_SYMBOL)); account_object voting_account_object = get_account(voting_account); account_id_type witness_owner_account_id = get_account_id(witness); From c8db22d481bd5ab04e23ffcc8d28183b749b52b5 Mon Sep 17 00:00:00 2001 From: Sandip Patel Date: Wed, 30 Oct 2019 18:29:30 +0530 Subject: [PATCH 35/39] Added token symbol name in error messages (#204) --- libraries/wallet/wallet.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 449000bc..14f73db4 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2008,11 +2008,11 @@ public: if (is_witness(witness_name)) { witness_object wit = get_witness( witness_name ); - FC_ASSERT( wit.pay_vb, "Account ${account} has no core TOKEN vested and thus its not allowed to withdraw.", ("account", witness_name)); + FC_ASSERT( wit.pay_vb, "Account ${account} has no core Token ${TOKEN} vested and thus its not allowed to withdraw.", ("account", witness_name)("TOKEN", GRAPHENE_SYMBOL)); vbid = wit.pay_vb; } else - FC_THROW("Account ${account} has no core TOKEN vested and thus its not allowed to withdraw.", ("account", witness_name)); + FC_THROW("Account ${account} has no core Token ${TOKEN} vested and thus its not allowed to withdraw.", ("account", witness_name)("TOKEN", GRAPHENE_SYMBOL)); } vesting_balance_object vbo = get_object< vesting_balance_object >( *vbid ); @@ -2117,7 +2117,7 @@ public: vbo_iter = std::find_if(vbo_info.begin(), vbo_info.end(), [](vesting_balance_object_with_info const& obj){return obj.balance_type == vesting_balance_type::gpos;}); if( vbo_info.size() == 0 || vbo_iter == vbo_info.end()) - FC_THROW("Account ${account} has no core Token vested and thus she will not be allowed to vote for the committee member", ("account", voting_account)); + FC_THROW("Account ${account} has no core Token ${TOKEN} vested and thus she will not be allowed to vote for the committee member", ("account", voting_account)("TOKEN", GRAPHENE_SYMBOL)); account_object voting_account_object = get_account(voting_account); account_id_type committee_member_owner_account_id = get_account_id(committee_member); @@ -2170,7 +2170,7 @@ public: vbo_iter = std::find_if(vbo_info.begin(), vbo_info.end(), [](vesting_balance_object_with_info const& obj){return obj.balance_type == vesting_balance_type::gpos;}); if( vbo_info.size() == 0 || vbo_iter == vbo_info.end()) - FC_THROW("Account ${account} has no core Token vested and thus she will not be allowed to vote for the witness", ("account", voting_account)); + FC_THROW("Account ${account} has no core Token ${TOKEN} vested and thus she will not be allowed to vote for the witness", ("account", voting_account)("TOKEN", GRAPHENE_SYMBOL)); account_object voting_account_object = get_account(voting_account); account_id_type witness_owner_account_id = get_account_id(witness); From 5d36258f0c818276a11d17e07eee848e1b2843a5 Mon Sep 17 00:00:00 2001 From: Sandip Patel Date: Thu, 31 Oct 2019 15:02:05 +0530 Subject: [PATCH 36/39] case 1: Fixed last voting time issue --- libraries/chain/include/graphene/chain/protocol/account.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/include/graphene/chain/protocol/account.hpp b/libraries/chain/include/graphene/chain/protocol/account.hpp index a0e43ad0..6a8aa20c 100644 --- a/libraries/chain/include/graphene/chain/protocol/account.hpp +++ b/libraries/chain/include/graphene/chain/protocol/account.hpp @@ -296,7 +296,7 @@ FC_REFLECT( graphene::chain::account_create_operation, (name)(owner)(active)(options)(extensions) ) -FC_REFLECT(graphene::chain::account_update_operation::ext, (null_ext)(owner_special_authority)(active_special_authority) ) +FC_REFLECT(graphene::chain::account_update_operation::ext, (null_ext)(owner_special_authority)(active_special_authority)(update_last_voting_time) ) FC_REFLECT( graphene::chain::account_update_operation, (fee)(account)(owner)(active)(new_options)(extensions) ) From e7f65c676047ac58fea8297ed68f9f644342e896 Mon Sep 17 00:00:00 2001 From: Sandip Patel Date: Mon, 2 Sep 2019 16:51:45 +0530 Subject: [PATCH 37/39] get_account bug fixed --- libraries/wallet/wallet.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 8d2ae75f..66034d6e 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -717,8 +717,6 @@ public: } account_object get_account(account_id_type id) const { - if( _wallet.my_accounts.get().count(id) ) - return *_wallet.my_accounts.get().find(id); auto rec = _remote_db->get_accounts({id}).front(); FC_ASSERT(rec); return *rec; @@ -732,19 +730,6 @@ public: // It's an ID return get_account(*id); } else { - // It's a name - if( _wallet.my_accounts.get().count(account_name_or_id) ) - { - auto local_account = *_wallet.my_accounts.get().find(account_name_or_id); - auto blockchain_account = _remote_db->lookup_account_names({account_name_or_id}).front(); - FC_ASSERT( blockchain_account ); - if (local_account.id != blockchain_account->id) - elog("my account id ${id} different from blockchain id ${id2}", ("id", local_account.id)("id2", blockchain_account->id)); - if (local_account.name != blockchain_account->name) - elog("my account name ${id} different from blockchain name ${id2}", ("id", local_account.name)("id2", blockchain_account->name)); - - return *_wallet.my_accounts.get().find(account_name_or_id); - } auto rec = _remote_db->lookup_account_names({account_name_or_id}).front(); FC_ASSERT( rec && rec->name == account_name_or_id ); return *rec; From fd8659caafaa26a444c9a20a22dd51be6a0b07ea Mon Sep 17 00:00:00 2001 From: Sandip Patel Date: Thu, 31 Oct 2019 19:01:50 +0530 Subject: [PATCH 38/39] Fixed flag issue --- libraries/chain/account_evaluator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/account_evaluator.cpp b/libraries/chain/account_evaluator.cpp index 3185c456..96429304 100644 --- a/libraries/chain/account_evaluator.cpp +++ b/libraries/chain/account_evaluator.cpp @@ -287,7 +287,7 @@ void_result account_update_evaluator::do_apply( const account_update_operation& fc::optional< bool > flag = o.extensions.value.update_last_voting_time; if((o.new_options->votes != acnt->options.votes || o.new_options->voting_account != acnt->options.voting_account) || - flag) + (flag.valid() && *flag)) aso.last_vote_time = d.head_block_time(); } ); } From 61fa3918ef6cd08b17890c413d787dd04eb905ac Mon Sep 17 00:00:00 2001 From: Sandip Patel Date: Tue, 5 Nov 2019 15:02:38 +0530 Subject: [PATCH 39/39] Fixed spelling issue --- libraries/chain/vesting_balance_evaluator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/vesting_balance_evaluator.cpp b/libraries/chain/vesting_balance_evaluator.cpp index 9f42d4ff..28282b87 100644 --- a/libraries/chain/vesting_balance_evaluator.cpp +++ b/libraries/chain/vesting_balance_evaluator.cpp @@ -145,7 +145,7 @@ void_result vesting_balance_withdraw_evaluator::do_evaluate( const vesting_balan const vesting_balance_object& vbo = op.vesting_balance( d ); FC_ASSERT( op.owner == vbo.owner, "", ("op.owner", op.owner)("vbo.owner", vbo.owner) ); - FC_ASSERT( vbo.is_withdraw_allowed( now, op.amount ), "${balance_type} Vested Balance cannont be withdrwan during the locking period", + FC_ASSERT( vbo.is_withdraw_allowed( now, op.amount ), "${balance_type} Vested Balance cannot be withdrawn during the locking period", ("balance_type", get_vesting_balance_type(vbo.balance_type))("now", now)("op", op)("vbo", vbo) ); assert( op.amount <= vbo.balance ); // is_withdraw_allowed should fail before this check is reached