Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add last_vote_time to account stats object #1449

Merged
merged 6 commits into from
Dec 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions libraries/chain/account_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ void verify_account_votes( const database& db, const account_options& options )
}
}


void_result account_create_evaluator::do_evaluate( const account_create_operation& op )
{ try {
database& d = db();
Expand Down Expand Up @@ -318,11 +317,16 @@ void_result account_update_evaluator::do_apply( const account_update_operation&
bool sa_before = acnt->has_special_authority();

// update account statistics
if( o.new_options.valid() && o.new_options->is_voting() != acnt->options.is_voting() )
if( o.new_options.valid() )
{
d.modify( acnt->statistics( d ), []( account_statistics_object& aso )
d.modify( acnt->statistics( d ), [&]( account_statistics_object& aso )
{
aso.is_voting = !aso.is_voting;
if(o.new_options->is_voting() != acnt->options.is_voting())
aso.is_voting = !aso.is_voting;

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();
} );
}

Expand Down
3 changes: 3 additions & 0 deletions libraries/chain/include/graphene/chain/account_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ namespace graphene { namespace chain {

bool is_voting = false; ///< redundately store whether this account is voting for better maintenance performance

time_point_sec last_vote_time; // add last time voted

/// Whether this account owns some CORE asset and is voting
inline bool has_some_core_voting() const
{
Expand Down Expand Up @@ -445,6 +447,7 @@ FC_REFLECT_DERIVED( graphene::chain::account_statistics_object,
(core_in_balance)
(has_cashback_vb)
(is_voting)
(last_vote_time)
(lifetime_fees_paid)
(pending_fees)(pending_vested_fees)
)
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/include/graphene/chain/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
#define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT 4
#define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT 3

#define GRAPHENE_CURRENT_DB_VERSION "BTS2.181127"
#define GRAPHENE_CURRENT_DB_VERSION "BTS2.181215"

#define GRAPHENE_IRREVERSIBLE_THRESHOLD (70 * GRAPHENE_1_PERCENT)

Expand Down
125 changes: 125 additions & 0 deletions tests/tests/voting_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,5 +414,130 @@ BOOST_AUTO_TEST_CASE(invalid_voting_account)

} FC_LOG_AND_RETHROW()
}
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 = db.get_account_stats_by_owner(alice_id);
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 = db.get_account_stats_by_owner(alice_id);
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 = db.get_account_stats_by_owner(alice_id);
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 = db.get_account_stats_by_owner(alice_id);
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 = db.get_account_stats_by_owner(bob_id);
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 = db.get_account_stats_by_owner(proxy_id);
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 = db.get_account_stats_by_owner(alice_id);
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 = db.get_account_stats_by_owner(bob_id);
BOOST_CHECK_EQUAL(bob_stats_obj.last_vote_time.sec_since_epoch(), round3);

} FC_LOG_AND_RETHROW()
}

BOOST_AUTO_TEST_SUITE_END()