From 0b1e53234f3e7616d15017034118dd42f67957a1 Mon Sep 17 00:00:00 2001 From: Alfredo Date: Mon, 17 Dec 2018 18:50:05 -0300 Subject: [PATCH] add last_vote_time to account statistics --- libraries/chain/account_evaluator.cpp | 12 +- .../include/graphene/chain/account_object.hpp | 6 + .../chain/include/graphene/chain/config.hpp | 2 +- tests/tests/voting_tests.cpp | 166 ++++++++++++++++++ 4 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 tests/tests/voting_tests.cpp diff --git a/libraries/chain/account_evaluator.cpp b/libraries/chain/account_evaluator.cpp index a08e9031..2d117f52 100644 --- a/libraries/chain/account_evaluator.cpp +++ b/libraries/chain/account_evaluator.cpp @@ -279,6 +279,17 @@ void_result account_update_evaluator::do_evaluate( const account_update_operatio void_result account_update_evaluator::do_apply( const account_update_operation& o ) { try { database& d = db(); + + if( o.new_options.valid() ) + { + 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)) + aso.last_vote_time = d.head_block_time(); + } ); + } + bool sa_before, sa_after; d.modify( *acnt, [&](account_object& a){ if( o.owner ) @@ -320,7 +331,6 @@ void_result account_update_evaluator::do_apply( const account_update_operation& sa.account = o.account; } ); } - return void_result(); } FC_CAPTURE_AND_RETHROW( (o) ) } diff --git a/libraries/chain/include/graphene/chain/account_object.hpp b/libraries/chain/include/graphene/chain/account_object.hpp index 51ba6748..914ade33 100644 --- a/libraries/chain/include/graphene/chain/account_object.hpp +++ b/libraries/chain/include/graphene/chain/account_object.hpp @@ -82,6 +82,11 @@ namespace graphene { namespace chain { */ share_type pending_vested_fees; + /** + * Keep the date of the last voting activity for this account. + */ + time_point_sec last_vote_time; + /// @brief Split up and pay out @ref pending_fees and @ref pending_vested_fees void process_fees(const account_object& a, database& d) const; @@ -463,6 +468,7 @@ FC_REFLECT_DERIVED( graphene::chain::account_statistics_object, (total_core_in_orders) (lifetime_fees_paid) (pending_fees)(pending_vested_fees) + (last_vote_time) ) FC_REFLECT_DERIVED( graphene::chain::pending_dividend_payout_balance_for_holder_object, diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index fcd3b7c1..d85cc093 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -151,7 +151,7 @@ #define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT 4 #define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT 3 -#define GRAPHENE_CURRENT_DB_VERSION "PPY2.0" +#define GRAPHENE_CURRENT_DB_VERSION "PPY2.1" #define GRAPHENE_IRREVERSIBLE_THRESHOLD (70 * GRAPHENE_1_PERCENT) diff --git a/tests/tests/voting_tests.cpp b/tests/tests/voting_tests.cpp new file mode 100644 index 00000000..b88f485a --- /dev/null +++ b/tests/tests/voting_tests.cpp @@ -0,0 +1,166 @@ +/* + * 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 "../common/database_fixture.hpp" + +using namespace graphene::chain; +using namespace graphene::chain::test; + + +BOOST_FIXTURE_TEST_SUITE(voting_tests, database_fixture) + +BOOST_AUTO_TEST_CASE(last_voting_date) +{ + try + { + ACTORS((alice)); + + transfer(committee_account, alice_id, asset(100)); + + // we are going to vote for this witness + auto witness1 = witness_id_type(1)(db); + + auto stats_obj = alice_id(db).statistics(db); + BOOST_CHECK_EQUAL(stats_obj.last_vote_time.sec_since_epoch(), 0); + + // alice votes + graphene::chain::account_update_operation op; + op.account = alice_id; + op.new_options = alice.options; + op.new_options->votes.insert(witness1.vote_id); + trx.operations.push_back(op); + sign(trx, alice_private_key); + PUSH_TX( db, trx, ~0 ); + + auto now = db.head_block_time().sec_since_epoch(); + + // last_vote_time is updated for alice + stats_obj = alice_id(db).statistics(db); + BOOST_CHECK_EQUAL(stats_obj.last_vote_time.sec_since_epoch(), now); + + } FC_LOG_AND_RETHROW() +} +BOOST_AUTO_TEST_CASE(last_voting_date_proxy) +{ + try + { + ACTORS((alice)(proxy)(bob)); + + transfer(committee_account, alice_id, asset(100)); + transfer(committee_account, bob_id, asset(200)); + transfer(committee_account, proxy_id, asset(300)); + + generate_block(); + + // witness to vote for + auto witness1 = witness_id_type(1)(db); + + // round1: alice changes proxy, this is voting activity + { + graphene::chain::account_update_operation op; + op.account = alice_id; + op.new_options = alice_id(db).options; + op.new_options->voting_account = proxy_id; + trx.operations.push_back(op); + sign(trx, alice_private_key); + PUSH_TX( db, trx, ~0 ); + } + // alice last_vote_time is updated + auto alice_stats_obj = alice_id(db).statistics(db); + auto round1 = db.head_block_time().sec_since_epoch(); + BOOST_CHECK_EQUAL(alice_stats_obj.last_vote_time.sec_since_epoch(), round1); + + generate_block(); + + // round 2: alice update account but no proxy or voting changes are done + { + graphene::chain::account_update_operation op; + op.account = alice_id; + op.new_options = alice_id(db).options; + trx.operations.push_back(op); + sign(trx, alice_private_key); + set_expiration( db, trx ); + PUSH_TX( db, trx, ~0 ); + } + // last_vote_time is not updated + auto round2 = db.head_block_time().sec_since_epoch(); + alice_stats_obj = alice_id(db).statistics(db); + BOOST_CHECK_EQUAL(alice_stats_obj.last_vote_time.sec_since_epoch(), round1); + + generate_block(); + + // round 3: bob votes + { + graphene::chain::account_update_operation op; + op.account = bob_id; + op.new_options = bob_id(db).options; + op.new_options->votes.insert(witness1.vote_id); + trx.operations.push_back(op); + sign(trx, bob_private_key); + set_expiration( db, trx ); + PUSH_TX(db, trx, ~0); + } + + // last_vote_time for bob is updated as he voted + auto round3 = db.head_block_time().sec_since_epoch(); + auto bob_stats_obj = bob_id(db).statistics(db); + BOOST_CHECK_EQUAL(bob_stats_obj.last_vote_time.sec_since_epoch(), round3); + + generate_block(); + + // round 4: proxy votes + { + graphene::chain::account_update_operation op; + op.account = proxy_id; + op.new_options = proxy_id(db).options; + op.new_options->votes.insert(witness1.vote_id); + trx.operations.push_back(op); + sign(trx, proxy_private_key); + PUSH_TX(db, trx, ~0); + } + + // proxy just voted so the last_vote_time is updated + auto round4 = db.head_block_time().sec_since_epoch(); + auto proxy_stats_obj = proxy_id(db).statistics(db); + BOOST_CHECK_EQUAL(proxy_stats_obj.last_vote_time.sec_since_epoch(), round4); + + // alice haves proxy, proxy votes but last_vote_time is not updated for alice + alice_stats_obj = alice_id(db).statistics(db); + BOOST_CHECK_EQUAL(alice_stats_obj.last_vote_time.sec_since_epoch(), round1); + + // bob haves nothing to do with proxy so last_vote_time is not updated + bob_stats_obj = bob_id(db).statistics(db); + BOOST_CHECK_EQUAL(bob_stats_obj.last_vote_time.sec_since_epoch(), round3); + + } FC_LOG_AND_RETHROW() +} + +BOOST_AUTO_TEST_SUITE_END()