Skip to content

Commit

Permalink
Merge pull request #3489 from steemit/3485-fix-downvote-mana-delegations
Browse files Browse the repository at this point in the history
Fix problems with downvote mana calcs when handling delegations #3485
  • Loading branch information
sgerbino authored Aug 29, 2019
2 parents 51ec865 + 96ee651 commit 51c7bf9
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 19 deletions.
7 changes: 6 additions & 1 deletion libraries/chain/database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4887,10 +4887,13 @@ void database::init_hardforks()
FC_ASSERT( STEEM_HARDFORK_0_21 == 21, "Invalid hardfork configuration" );
_hardfork_versions.times[ STEEM_HARDFORK_0_21 ] = fc::time_point_sec( STEEM_HARDFORK_0_21_TIME );
_hardfork_versions.versions[ STEEM_HARDFORK_0_21 ] = STEEM_HARDFORK_0_21_VERSION;
#ifdef IS_TEST_NET
FC_ASSERT( STEEM_HARDFORK_0_22 == 22, "Invalid hardfork configuration" );
_hardfork_versions.times[ STEEM_HARDFORK_0_22 ] = fc::time_point_sec( STEEM_HARDFORK_0_22_TIME );
_hardfork_versions.versions[ STEEM_HARDFORK_0_22 ] = STEEM_HARDFORK_0_22_VERSION;
#ifdef IS_TEST_NET
FC_ASSERT( STEEM_HARDFORK_0_23 == 23, "Invalid hardfork configuration" );
_hardfork_versions.times[ STEEM_HARDFORK_0_23 ] = fc::time_point_sec( STEEM_HARDFORK_0_23_TIME );
_hardfork_versions.versions[ STEEM_HARDFORK_0_23 ] = STEEM_HARDFORK_0_23_VERSION;
#endif


Expand Down Expand Up @@ -5299,6 +5302,8 @@ void database::apply_hardfork( uint32_t hardfork )
});
}
break;
case STEEM_HARDFORK_0_22:
break;
case STEEM_SMT_HARDFORK:
{
#ifdef STEEM_ENABLE_SMT
Expand Down
53 changes: 46 additions & 7 deletions libraries/chain/steem_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1924,9 +1924,19 @@ void hf20_vote_evaluator( const vote_operation& o, database& _db )
FC_TODO( "This hardfork check should not be needed. Remove after HF21 if that is the case." );
if( _db.has_hardfork( STEEM_HARDFORK_0_21__3336 ) && dgpo.downvote_pool_percent && o.weight < 0 )
{
used_mana = ( std::max( ( uint128_t( voter.downvote_manabar.current_mana * STEEM_100_PERCENT ) / dgpo.downvote_pool_percent ),
if( _db.has_hardfork( STEEM_HARDFORK_0_22__3485 ) )
{
used_mana = ( std::max( ( ( uint128_t( voter.downvote_manabar.current_mana ) * STEEM_100_PERCENT ) / dgpo.downvote_pool_percent ),
uint128_t( voter.voting_manabar.current_mana ) )
* abs_weight * 60 * 60 * 24 ) / STEEM_100_PERCENT;
}
else
{
used_mana = ( std::max( ( uint128_t( voter.downvote_manabar.current_mana * STEEM_100_PERCENT ) / dgpo.downvote_pool_percent ),
uint128_t( voter.voting_manabar.current_mana ) )
* abs_weight * 60 * 60 * 24 ) / STEEM_100_PERCENT;
}

}
else
{
Expand Down Expand Up @@ -3090,9 +3100,18 @@ void delegate_vesting_shares_evaluator::do_apply( const delegate_vesting_shares_
available_shares = asset( delegator.voting_manabar.current_mana, VESTS_SYMBOL );
if( gpo.downvote_pool_percent )
{
available_downvote_shares = asset(
( delegator.downvote_manabar.current_mana * STEEM_100_PERCENT ) / gpo.downvote_pool_percent
+ ( STEEM_100_PERCENT / gpo.downvote_pool_percent ) - 1, VESTS_SYMBOL );
if( _db.has_hardfork( STEEM_HARDFORK_0_22__3485 ) )
{
available_downvote_shares = asset(
( ( uint128_t( delegator.downvote_manabar.current_mana ) * STEEM_100_PERCENT ) / gpo.downvote_pool_percent
+ ( STEEM_100_PERCENT / gpo.downvote_pool_percent ) - 1 ).to_int64(), VESTS_SYMBOL );
}
else
{
available_downvote_shares = asset(
( delegator.downvote_manabar.current_mana * STEEM_100_PERCENT ) / gpo.downvote_pool_percent
+ ( STEEM_100_PERCENT / gpo.downvote_pool_percent ) - 1, VESTS_SYMBOL );
}
}
else
{
Expand Down Expand Up @@ -3169,7 +3188,11 @@ void delegate_vesting_shares_evaluator::do_apply( const delegate_vesting_shares_
{
a.voting_manabar.use_mana( op.vesting_shares.amount.value );

if( _db.has_hardfork( STEEM_HARDFORK_0_21__3336 ) )
if( _db.has_hardfork( STEEM_HARDFORK_0_22__3485 ) )
{
a.downvote_manabar.use_mana( ( ( uint128_t( op.vesting_shares.amount.value ) * gpo.downvote_pool_percent ) / STEEM_100_PERCENT ).to_int64() );
}
else if( _db.has_hardfork( STEEM_HARDFORK_0_21__3336 ) )
{
a.downvote_manabar.use_mana( op.vesting_shares.amount.value );
}
Expand Down Expand Up @@ -3207,7 +3230,11 @@ void delegate_vesting_shares_evaluator::do_apply( const delegate_vesting_shares_
{
a.voting_manabar.use_mana( delta.amount.value );

if( _db.has_hardfork( STEEM_HARDFORK_0_21__3336 ) )
if( _db.has_hardfork( STEEM_HARDFORK_0_22__3485 ) )
{
a.downvote_manabar.use_mana( ( ( uint128_t( delta.amount.value ) * gpo.downvote_pool_percent ) / STEEM_100_PERCENT ).to_int64() );
}
else if( _db.has_hardfork( STEEM_HARDFORK_0_21__3336 ) )
{
a.downvote_manabar.use_mana( delta.amount.value );
}
Expand Down Expand Up @@ -3253,6 +3280,11 @@ void delegate_vesting_shares_evaluator::do_apply( const delegate_vesting_shares_

_db.modify( delegatee, [&]( account_object& a )
{
if( _db.has_hardfork( STEEM_HARDFORK_0_22__3485 ) )
{
util::update_manabar( gpo, a, _db.has_hardfork( STEEM_HARDFORK_0_21__3336 ), _db.head_block_num() > STEEM_HF_21_STALL_BLOCK );
}

a.received_vesting_shares -= delta;

if( _db.has_hardfork( STEEM_HARDFORK_0_20__2539 ) )
Expand All @@ -3266,7 +3298,14 @@ void delegate_vesting_shares_evaluator::do_apply( const delegate_vesting_shares_

if( _db.has_hardfork( STEEM_HARDFORK_0_21__3336 ) )
{
a.downvote_manabar.use_mana( op.vesting_shares.amount.value );
if( _db.has_hardfork( STEEM_HARDFORK_0_22__3485 ) )
{
a.downvote_manabar.use_mana( ( ( uint128_t( delta.amount.value ) * gpo.downvote_pool_percent ) / STEEM_100_PERCENT ).to_int64() );
}
else
{
a.downvote_manabar.use_mana( op.vesting_shares.amount.value );
}

if( a.downvote_manabar.current_mana < 0 )
{
Expand Down
4 changes: 2 additions & 2 deletions libraries/protocol/hardfork.d/0-preamble.hf
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include <set>

#ifdef IS_TEST_NET
#define STEEM_NUM_HARDFORKS 22
#define STEEM_NUM_HARDFORKS 23
#else
#define STEEM_NUM_HARDFORKS 21
#define STEEM_NUM_HARDFORKS 22
#endif
5 changes: 3 additions & 2 deletions libraries/protocol/hardfork.d/0_22.hf
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#ifndef STEEM_HARDFORK_0_22
#define STEEM_HARDFORK_0_22 22
#define STEEM_SMT_HARDFORK STEEM_HARDFORK_0_22

#define STEEM_HARDFORK_0_22_TIME 1597970800 // Future 2020...
#define STEEM_HARDFORK_0_22_TIME 1567090800 // Thu, 29 August 2019 15:00:00 UTC (11:00:00 EDT)

#define STEEM_HARDFORK_0_22__3485 STEEM_HARDFORK_0_22

#define STEEM_HARDFORK_0_22_VERSION hardfork_version( 0, 22 )

Expand Down
9 changes: 9 additions & 0 deletions libraries/protocol/hardfork.d/0_23.hf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef STEEM_HARDFORK_0_23
#define STEEM_HARDFORK_0_23 23
#define STEEM_SMT_HARDFORK STEEM_HARDFORK_0_23

#define STEEM_HARDFORK_0_23_TIME 1597970800 // Future 2020...

#define STEEM_HARDFORK_0_23_VERSION hardfork_version( 0, 23 )

#endif
4 changes: 2 additions & 2 deletions libraries/protocol/include/steem/protocol/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// This is checked by get_config_check.sh called from Dockerfile

#ifdef IS_TEST_NET
#define STEEM_BLOCKCHAIN_VERSION ( version(0, 22, 0) )
#define STEEM_BLOCKCHAIN_VERSION ( version(0, 23, 0) )

#define STEEM_INIT_PRIVATE_KEY (fc::ecc::private_key::regenerate(fc::sha256::hash(std::string("init_key"))))
#define STEEM_INIT_PUBLIC_KEY_STR (std::string( steem::protocol::public_key_type(STEEM_INIT_PRIVATE_KEY.get_public_key()) ))
Expand Down Expand Up @@ -44,7 +44,7 @@

#else // IS LIVE STEEM NETWORK

#define STEEM_BLOCKCHAIN_VERSION ( version(0, 21, 1) )
#define STEEM_BLOCKCHAIN_VERSION ( version(0, 22, 0) )

#define STEEM_INIT_PUBLIC_KEY_STR "STM8GC13uCZbP44HzMLV6zPZGwVQ8Nt4Kji8PapsPiNq1BK153XTX"
#define STEEM_CHAIN_ID fc::sha256()
Expand Down
143 changes: 138 additions & 5 deletions tests/tests/operation_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6556,6 +6556,22 @@ BOOST_AUTO_TEST_CASE( delegate_vesting_shares_apply )
op.delegator = "alice";
op.delegatee = "bob";

util::manabar old_manabar = db->get_account( "alice" ).voting_manabar;
util::manabar_params params( util::get_effective_vesting_shares( db->get_account( "alice" ) ), STEEM_VOTING_MANA_REGENERATION_SECONDS );
old_manabar.regenerate_mana( params, db->head_block_time() );

util::manabar old_downvote_manabar = db->get_account( "alice" ).downvote_manabar;
params.max_mana = util::get_effective_vesting_shares( db->get_account( "alice" ) ) / 4;
old_downvote_manabar.regenerate_mana( params, db->head_block_time() );

util::manabar old_bob_manabar = db->get_account( "bob" ).voting_manabar;
params.max_mana = util::get_effective_vesting_shares( db->get_account( "bob" ) );
old_bob_manabar.regenerate_mana( params, db->head_block_time() );

util::manabar old_bob_downvote_manabar = db->get_account( "bob" ).downvote_manabar;
params.max_mana = util::get_effective_vesting_shares( db->get_account( "bob" ) ) / 4;
old_bob_downvote_manabar.regenerate_mana( params, db->head_block_time() );

tx.set_expiration( db->head_block_time() + STEEM_MAX_TIME_UNTIL_EXPIRATION );
tx.operations.push_back( op );
sign( tx, alice_private_key );
Expand All @@ -6564,30 +6580,59 @@ BOOST_AUTO_TEST_CASE( delegate_vesting_shares_apply )
const account_object& alice_acc = db->get_account( "alice" );
const account_object& bob_acc = db->get_account( "bob" );

BOOST_REQUIRE( alice_acc.delegated_vesting_shares == ASSET( "10000000.000000 VESTS"));
BOOST_REQUIRE( bob_acc.received_vesting_shares == ASSET( "10000000.000000 VESTS"));
BOOST_REQUIRE( alice_acc.delegated_vesting_shares == ASSET( "10000000.000000 VESTS" ) );
BOOST_REQUIRE( alice_acc.voting_manabar.current_mana == old_manabar.current_mana - op.vesting_shares.amount.value );
BOOST_REQUIRE( alice_acc.downvote_manabar.current_mana == old_downvote_manabar.current_mana - op.vesting_shares.amount.value / 4 );
BOOST_REQUIRE( bob_acc.received_vesting_shares == ASSET( "10000000.000000 VESTS" ) );
BOOST_REQUIRE( bob_acc.voting_manabar.current_mana == old_bob_manabar.current_mana + op.vesting_shares.amount.value );
BOOST_REQUIRE( bob_acc.downvote_manabar.current_mana == old_bob_downvote_manabar.current_mana + op.vesting_shares.amount.value / 4 );

BOOST_TEST_MESSAGE( "--- Test that the delegation object is correct. " );
auto delegation = db->find< vesting_delegation_object, by_delegation >( boost::make_tuple( op.delegator, op.delegatee ) );


BOOST_REQUIRE( delegation != nullptr );
BOOST_REQUIRE( delegation->delegator == op.delegator);
BOOST_REQUIRE( delegation->vesting_shares == ASSET( "10000000.000000 VESTS"));

old_manabar = db->get_account( "alice" ).voting_manabar;
params.max_mana = util::get_effective_vesting_shares( db->get_account( "alice" ) );
old_manabar.regenerate_mana( params, db->head_block_time() );

old_downvote_manabar = db->get_account( "alice" ).downvote_manabar;
params.max_mana = util::get_effective_vesting_shares( db->get_account( "alice" ) ) / 4;
old_downvote_manabar.regenerate_mana( params, db->head_block_time() );

old_bob_manabar = db->get_account( "bob" ).voting_manabar;
params.max_mana = util::get_effective_vesting_shares( db->get_account( "bob" ) );
old_bob_manabar.regenerate_mana( params, db->head_block_time() );

old_bob_downvote_manabar = db->get_account( "bob" ).downvote_manabar;
params.max_mana = util::get_effective_vesting_shares( db->get_account( "bob" ) ) / 4;
old_bob_downvote_manabar.regenerate_mana( params, db->head_block_time() );

int64_t delta = 10000000000000;

validate_database();
tx.clear();
op.vesting_shares = ASSET( "20000000.000000 VESTS");
op.vesting_shares.amount += delta;
tx.set_expiration( db->head_block_time() + STEEM_MAX_TIME_UNTIL_EXPIRATION );
tx.operations.push_back( op );
sign( tx, alice_private_key );
db->push_transaction( tx, 0 );
generate_blocks(1);

idump( (alice_acc.voting_manabar)(old_manabar)(delta) );

BOOST_REQUIRE( delegation != nullptr );
BOOST_REQUIRE( delegation->delegator == op.delegator);
BOOST_REQUIRE( delegation->vesting_shares == ASSET( "20000000.000000 VESTS"));
BOOST_REQUIRE( alice_acc.delegated_vesting_shares == ASSET( "20000000.000000 VESTS"));
BOOST_REQUIRE( alice_acc.voting_manabar.current_mana == old_manabar.current_mana - delta );
BOOST_REQUIRE( alice_acc.downvote_manabar.current_mana == old_downvote_manabar.current_mana - delta / 4 );
BOOST_REQUIRE( bob_acc.received_vesting_shares == ASSET( "20000000.000000 VESTS"));
BOOST_REQUIRE( bob_acc.voting_manabar.current_mana == old_bob_manabar.current_mana + delta );
BOOST_REQUIRE( bob_acc.downvote_manabar.current_mana == old_bob_downvote_manabar.current_mana + delta / 4 );

BOOST_TEST_MESSAGE( "--- Test failure delegating delgated VESTS." );

Expand All @@ -6603,8 +6648,8 @@ BOOST_AUTO_TEST_CASE( delegate_vesting_shares_apply )
tx.operations.clear();
tx.signatures.clear();

util::manabar old_manabar = db->get_account( "bob" ).voting_manabar;
util::manabar_params params( util::get_effective_vesting_shares( db->get_account( "bob" ) ), STEEM_VOTING_MANA_REGENERATION_SECONDS );
old_manabar = db->get_account( "bob" ).voting_manabar;
params.max_mana = util::get_effective_vesting_shares( db->get_account( "bob" ) );
old_manabar.regenerate_mana( params, db->head_block_time() );

comment_operation comment_op;
Expand Down Expand Up @@ -6664,8 +6709,54 @@ BOOST_AUTO_TEST_CASE( delegate_vesting_shares_apply )
sign( tx, sam_private_key );
STEEM_REQUIRE_THROW( db->push_transaction( tx ), fc::assert_exception );

BOOST_TEST_MESSAGE( "--- Testing failure delegating when there is not enough mana" );

generate_block();
db_plugin->debug_update( [=]( database& db )
{
db.modify( db.get_account( "sam" ), [&]( account_object& a )
{
a.voting_manabar.current_mana = a.downvote_manabar.current_mana * 3 / 4;
a.voting_manabar.last_update_time = db.head_block_time().sec_since_epoch();
});
});

op.vesting_shares = sam_vest;
tx.clear();
tx.operations.push_back( op );
sign( tx, sam_private_key );
STEEM_REQUIRE_THROW( db->push_transaction( tx ), fc::assert_exception );

BOOST_TEST_MESSAGE( "--- Testing failure delegating when there is not enough downvote mana" );

generate_block();
db_plugin->debug_update( [=]( database& db )
{
db.modify( db.get_account( "sam" ), [&]( account_object& a )
{
a.voting_manabar.current_mana = util::get_effective_vesting_shares( a );
a.voting_manabar.last_update_time = db.head_block_time().sec_since_epoch();
a.downvote_manabar.current_mana = a.downvote_manabar.current_mana * 3 / 4;
a.downvote_manabar.last_update_time = db.head_block_time().sec_since_epoch();
});
});

tx.clear();
tx.operations.push_back( op );
sign( tx, sam_private_key );
STEEM_REQUIRE_THROW( db->push_transaction( tx ), fc::assert_exception );

BOOST_TEST_MESSAGE( "--- Test failure delegating vesting shares that are part of a power down" );
generate_block();
db_plugin->debug_update( [=]( database& db )
{
db.modify( db.get_account( "sam" ), [&]( account_object& a )
{
a.downvote_manabar.current_mana = util::get_effective_vesting_shares( a ) / 4;
a.downvote_manabar.last_update_time = db.head_block_time().sec_since_epoch();
});
});

tx.clear();
sam_vest = asset( sam_vest.amount / 2, VESTS_SYMBOL );
withdraw_vesting_operation withdraw;
Expand Down Expand Up @@ -6704,6 +6795,15 @@ BOOST_AUTO_TEST_CASE( delegate_vesting_shares_apply )


BOOST_TEST_MESSAGE( "--- Remove a delegation and ensure it is returned after 1 week" );

util::manabar old_sam_manabar = db->get_account( "sam" ).voting_manabar;
util::manabar old_sam_downvote_manabar = db->get_account( "sam" ).downvote_manabar;
util::manabar old_dave_manabar = db->get_account( "dave" ).voting_manabar;
util::manabar old_dave_downvote_manabar = db->get_account( "dave" ).downvote_manabar;

util::manabar_params sam_params( util::get_effective_vesting_shares( db->get_account( "sam" ) ), STEEM_VOTING_MANA_REGENERATION_SECONDS );
util::manabar_params dave_params( util::get_effective_vesting_shares( db->get_account( "dave" ) ), STEEM_VOTING_MANA_REGENERATION_SECONDS );

tx.clear();
op.vesting_shares = ASSET( "0.000000 VESTS" );
tx.operations.push_back( op );
Expand All @@ -6725,13 +6825,46 @@ BOOST_AUTO_TEST_CASE( delegate_vesting_shares_apply )
delegation = db->find< vesting_delegation_object, by_delegation >( boost::make_tuple( op.delegator, op.delegatee ) );
BOOST_REQUIRE( delegation == nullptr );

old_sam_manabar.regenerate_mana( sam_params, db->head_block_time() );
sam_params.max_mana /= 4;
old_sam_downvote_manabar.regenerate_mana( sam_params, db->head_block_time() );

old_dave_manabar.regenerate_mana( dave_params, db->head_block_time() );
dave_params.max_mana /= 4;
old_dave_downvote_manabar.regenerate_mana( dave_params, db->head_block_time() );

BOOST_REQUIRE( db->get_account( "sam" ).voting_manabar.current_mana == old_sam_manabar.current_mana );
BOOST_REQUIRE( db->get_account( "sam" ).downvote_manabar.current_mana == old_sam_downvote_manabar.current_mana );
BOOST_REQUIRE( db->get_account( "dave" ).voting_manabar.current_mana == old_dave_manabar.current_mana - sam_vest.amount.value );
BOOST_REQUIRE( db->get_account( "dave" ).downvote_manabar.current_mana == old_dave_downvote_manabar.current_mana - sam_vest.amount.value / 4 );

old_sam_manabar = db->get_account( "sam" ).voting_manabar;
old_sam_downvote_manabar = db->get_account( "sam" ).downvote_manabar;
old_dave_manabar = db->get_account( "dave" ).voting_manabar;
old_dave_downvote_manabar = db->get_account( "dave" ).downvote_manabar;

sam_params.max_mana = util::get_effective_vesting_shares( db->get_account( "sam" ) );
dave_params.max_mana = util::get_effective_vesting_shares( db->get_account( "dave" ) );

generate_blocks( exp_obj->expiration + STEEM_BLOCK_INTERVAL );

old_sam_manabar.regenerate_mana( sam_params, db->head_block_time() );
sam_params.max_mana /= 4;
old_sam_downvote_manabar.regenerate_mana( sam_params, db->head_block_time() );

old_dave_manabar.regenerate_mana( dave_params, db->head_block_time() );
dave_params.max_mana /= 4;
old_dave_downvote_manabar.regenerate_mana( dave_params, db->head_block_time() );

exp_obj = db->get_index< vesting_delegation_expiration_index, by_id >().begin();
end = db->get_index< vesting_delegation_expiration_index, by_id >().end();

BOOST_REQUIRE( exp_obj == end );
BOOST_REQUIRE( db->get_account( "sam" ).delegated_vesting_shares == ASSET( "0.000000 VESTS" ) );
BOOST_REQUIRE( db->get_account( "sam" ).voting_manabar.current_mana == old_sam_manabar.current_mana + sam_vest.amount.value );
BOOST_REQUIRE( db->get_account( "sam" ).downvote_manabar.current_mana == old_sam_downvote_manabar.current_mana + sam_vest.amount.value / 4 );
BOOST_REQUIRE( db->get_account( "dave" ).voting_manabar.current_mana == old_dave_manabar.current_mana );
BOOST_REQUIRE( db->get_account( "dave" ).downvote_manabar.current_mana == old_dave_downvote_manabar.current_mana );
}
FC_LOG_AND_RETHROW()
}
Expand Down

0 comments on commit 51c7bf9

Please sign in to comment.