Skip to content

Commit

Permalink
Merge pull request steemit#886 from steemit/774-comment-reward-fund
Browse files Browse the repository at this point in the history
774 comment reward fund
  • Loading branch information
Michael Vandeberg authored Feb 27, 2017
2 parents 0a095bd + db378d8 commit d47b4ab
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 61 deletions.
3 changes: 2 additions & 1 deletion libraries/app/database_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,8 @@ void database_api::set_pending_payout( discussion& d )const
u256 total_r2 = to256( props.total_reward_shares2 );

if( props.total_reward_shares2 > 0 ){
auto vshares = steemit::chain::util::calculate_vshares( d.net_rshares.value > 0 ? d.net_rshares.value : 0 );
auto vshares = std::max( steemit::chain::util::calculate_claims( d.net_rshares.value > 0 ? d.net_rshares.value : 0 ),
steemit::chain::util::calculate_claims( d.net_rshares.value > 0 ? d.net_rshares.value : 0 , my->_db.get_reward_fund( my->_db.get_comment( d.author, d.permlink ) ) ) ); // TODO: Only return new calculate_claims after HF 17

//int64_t abs_net_rshares = llabs(d.net_rshares.value);

Expand Down
31 changes: 16 additions & 15 deletions libraries/chain/database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ using boost::container::flat_set;

struct reward_fund_context
{
uint128_t recent_rshares2 = 0;
uint128_t recent_claims = 0;
asset reward_balance = asset( 0, STEEM_SYMBOL );
share_type steem_awarded = 0;
};
Expand Down Expand Up @@ -1639,7 +1639,7 @@ share_type database::cashout_comment_helper( util::comment_reward_context& ctx,
}

if( !has_hardfork( STEEMIT_HARDFORK_0_17__774 ) )
adjust_rshares2( comment, util::calculate_vshares( comment.net_rshares.value ), 0 );
adjust_rshares2( comment, util::calculate_claims( comment.net_rshares.value ), 0 );
}

modify( cat, [&]( category_object& c )
Expand Down Expand Up @@ -1731,12 +1731,12 @@ void database::process_comment_cashout()
// Add all reward funds to the local cache and decay their recent rshares
modify( *itr, [&]( reward_fund_object& rfo )
{
rfo.recent_rshares2 -= ( rfo.recent_rshares2 * ( head_block_time() - rfo.last_update ).to_seconds() ) / STEEMIT_RECENT_RSHARES_DECAY_RATE.to_seconds();
rfo.recent_claims -= ( rfo.recent_claims * ( head_block_time() - rfo.last_update ).to_seconds() ) / STEEMIT_RECENT_RSHARES_DECAY_RATE.to_seconds();
rfo.last_update = head_block_time();
});

reward_fund_context rf_ctx;
rf_ctx.recent_rshares2 = itr->recent_rshares2;
rf_ctx.recent_claims = itr->recent_claims;
rf_ctx.reward_balance = itr->reward_balance;

funds.push_back( rf_ctx );
Expand All @@ -1754,8 +1754,7 @@ void database::process_comment_cashout()
if( current->net_rshares > 0 )
{
const auto& rf = get_reward_fund( *current );
funds[ rf.id._id ].recent_rshares2 += util::calculate_vshares( current->net_rshares.value, rf );
FC_ASSERT( funds[ rf.id._id ].recent_rshares2 < std::numeric_limits< uint64_t >::max() );
funds[ rf.id._id ].recent_claims += util::calculate_claims( current->net_rshares.value, rf );
++current;
}
}
Expand All @@ -1781,7 +1780,7 @@ void database::process_comment_cashout()
if( has_hardfork( STEEMIT_HARDFORK_0_17__771 ) )
{
auto fund_id = get_reward_fund( *current ).id._id;
ctx.total_reward_shares2 = funds[ fund_id ].recent_rshares2;
ctx.total_reward_shares2 = funds[ fund_id ].recent_claims;
ctx.total_reward_fund_steem = funds[ fund_id ].reward_balance;
funds[ fund_id ].steem_awarded += cashout_comment_helper( ctx, *current );
}
Expand All @@ -1800,7 +1799,7 @@ void database::process_comment_cashout()
if( funds.size() )
{
const auto& rf = get_reward_fund( *current );
funds[ rf.id._id ].recent_rshares2 += util::calculate_vshares( current->net_rshares.value, rf );
funds[ rf.id._id ].recent_claims += util::calculate_claims( current->net_rshares.value, rf );
}

auto reward = cashout_comment_helper( ctx, comment );
Expand All @@ -1825,7 +1824,7 @@ void database::process_comment_cashout()
{
modify( get< reward_fund_object, by_id >( reward_fund_id_type( i ) ), [&]( reward_fund_object& rfo )
{
rfo.recent_rshares2 = funds[ i ].recent_rshares2;
rfo.recent_claims = funds[ i ].recent_claims;
rfo.reward_balance -= funds[ i ].steem_awarded;
});
}
Expand Down Expand Up @@ -2042,8 +2041,8 @@ void database::pay_liquidity_reward()

uint16_t database::get_curation_rewards_percent( const comment_object& c ) const
{
if( has_hardfork( STEEMIT_HARDFORK_0_17__774 ) && c.parent_author != STEEMIT_ROOT_POST_PARENT )
return 0;
if( has_hardfork( STEEMIT_HARDFORK_0_17__774 ) )
return get_reward_fund( c ).percent_curation_rewards;
else if( has_hardfork( STEEMIT_HARDFORK_0_8__116 ) )
return STEEMIT_1_PERCENT * 25;
else
Expand Down Expand Up @@ -3854,16 +3853,18 @@ void database::apply_hardfork( uint32_t hardfork )
{
rfo.name = STEEMIT_POST_REWARD_FUND_NAME;
rfo.last_update = head_block_time();
rfo.content_constant = STEEMIT_CONTENT_CONSTANT_HF17;
rfo.percent_curation_rewards = STEEMIT_1_PERCENT * 25;
rfo.percent_content_rewards = 0;
rfo.content_constant = util::get_content_constant_s().to_uint64();
});

create< reward_fund_object >( [&]( reward_fund_object& rfo )
{
rfo.name = STEEMIT_COMMENT_REWARD_FUND_NAME;
rfo.last_update = head_block_time();
rfo.content_constant = STEEMIT_CONTENT_CONSTANT_HF17;
rfo.percent_curation_rewards = STEEMIT_1_PERCENT * 25;
rfo.percent_content_rewards = 0;
rfo.content_constant = util::get_content_constant_s().to_uint64();
});
break;
case STEEMIT_HARDFORK_0_17:
Expand Down Expand Up @@ -4079,7 +4080,7 @@ void database::validate_invariants()const
{
if( itr->net_rshares.value > 0 )
{
auto delta = util::calculate_vshares( itr->net_rshares.value );
auto delta = util::calculate_claims( itr->net_rshares.value );
total_rshares2 += delta;
}
if( itr->parent_author == STEEMIT_ROOT_POST_PARENT )
Expand Down Expand Up @@ -4153,7 +4154,7 @@ void database::perform_vesting_share_split( uint32_t magnitude )
for( const auto& c : comments )
{
if( c.net_rshares.value > 0 )
adjust_rshares2( c, 0, util::calculate_vshares( c.net_rshares.value ) );
adjust_rshares2( c, 0, util::calculate_claims( c.net_rshares.value ) );
}

// Update category rshares
Expand Down
10 changes: 6 additions & 4 deletions libraries/chain/include/steemit/chain/steem_objects.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,11 @@ namespace steemit { namespace chain {
reward_fund_id_type id;
reward_fund_name_type name;
asset reward_balance = asset( 0, STEEM_SYMBOL );
fc::uint128_t recent_rshares2 = 0;
fc::uint128_t recent_claims = 0;
time_point_sec last_update;
uint16_t percent_content_rewards = 0;
uint64_t content_constant = 0;
uint16_t percent_curation_rewards = 0;
uint16_t percent_content_rewards = 0;
};

struct by_price;
Expand Down Expand Up @@ -518,9 +519,10 @@ FC_REFLECT( steemit::chain::reward_fund_object,
(id)
(name)
(reward_balance)
(recent_rshares2)
(recent_claims)
(last_update)
(percent_content_rewards)
(content_constant)
(percent_curation_rewards)
(percent_content_rewards)
)
CHAINBASE_SET_INDEX_TYPE( steemit::chain::reward_fund_object, steemit::chain::reward_fund_index )
8 changes: 5 additions & 3 deletions libraries/chain/include/steemit/chain/util/reward.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,16 @@ uint64_t get_rshare_reward( const comment_reward_context& ctx );

uint64_t get_rshare_reward( const comment_reward_context& ctx, const reward_fund_object& rf );

uint64_t get_vote_weight( uint64_t vote_rshares, const reward_fund_object& rf );

inline uint128_t get_content_constant_s()
{
return uint128_t( uint64_t(2000000000000ll) ); // looking good for posters
return STEEMIT_CONTENT_CONSTANT_HF0; // looking good for posters
}

uint128_t calculate_vshares( const uint128_t& rshares );
uint128_t calculate_claims( const uint128_t& rshares );

uint128_t calculate_vshares( const uint128_t& rshares, const reward_fund_object& rf );
uint128_t calculate_claims( const uint128_t& rshares, const reward_fund_object& rf );

inline bool is_comment_payout_dust( const price& p, uint64_t steem_payout )
{
Expand Down
17 changes: 12 additions & 5 deletions libraries/chain/steem_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1345,8 +1345,8 @@ void vote_evaluator::do_apply( const vote_operation& o )
fc::uint128_t new_rshares = std::max( comment.net_rshares.value, int64_t(0));

/// calculate rshares2 value
new_rshares = util::calculate_vshares( new_rshares );
old_rshares = util::calculate_vshares( old_rshares );
new_rshares = util::calculate_claims( new_rshares );
old_rshares = util::calculate_claims( old_rshares );

const auto& cat = _db.get_category( comment.category );
_db.modify( cat, [&]( category_object& c ){
Expand Down Expand Up @@ -1404,7 +1404,14 @@ void vote_evaluator::do_apply( const vote_operation& o )
cv.weight = static_cast<uint64_t>( rshares3 / total2 );
} else {// cv.weight = W(R_1) - W(R_0)
const uint128_t two_s = 2 * util::get_content_constant_s();
if( _db.has_hardfork( STEEMIT_HARDFORK_0_1 ) )
if( _db.has_hardfork( STEEMIT_HARDFORK_0_17__774 ) )
{
const auto& reward_fund = _db.get_reward_fund( comment );
uint64_t old_weight = util::get_vote_weight( old_vote_rshares.value, reward_fund );
uint64_t new_weight = util::get_vote_weight( comment.vote_rshares.value, reward_fund );
cv.weight = new_weight - old_weight;
}
else if ( _db.has_hardfork( STEEMIT_HARDFORK_0_1 ) )
{
uint64_t old_weight = ( ( std::numeric_limits< uint64_t >::max() * fc::uint128_t( old_vote_rshares.value ) ) / ( two_s + old_vote_rshares.value ) ).to_uint64();
uint64_t new_weight = ( ( std::numeric_limits< uint64_t >::max() * fc::uint128_t( comment.vote_rshares.value ) ) / ( two_s + comment.vote_rshares.value ) ).to_uint64();
Expand Down Expand Up @@ -1529,8 +1536,8 @@ void vote_evaluator::do_apply( const vote_operation& o )
fc::uint128_t new_rshares = std::max( comment.net_rshares.value, int64_t(0));

/// calculate rshares2 value
new_rshares = util::calculate_vshares( new_rshares );
old_rshares = util::calculate_vshares( old_rshares );
new_rshares = util::calculate_claims( new_rshares );
old_rshares = util::calculate_claims( old_rshares );

_db.modify( comment, [&]( comment_object& c )
{
Expand Down
56 changes: 33 additions & 23 deletions libraries/chain/util/reward.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ uint64_t get_rshare_reward( const comment_reward_context& ctx )

//idump( (ctx) );

u256 rs2 = to256( calculate_vshares( ctx.rshares.value ) );
u256 rs2 = to256( calculate_claims( ctx.rshares.value ) );
rs2 = ( rs2 * ctx.reward_weight ) / STEEMIT_100_PERCENT;

u256 payout_u256 = ( rf * rs2 ) / total_rshares2;
Expand All @@ -42,16 +42,15 @@ uint64_t get_rshare_reward( const comment_reward_context& ctx, const reward_fund
FC_ASSERT( ctx.rshares > 0 );
FC_ASSERT( ctx.total_reward_shares2 > 0 );

u256 rs(ctx.rshares.value);
u256 rf(ctx.total_reward_fund_steem.amount.value);
u256 total_rshares2 = to256( ctx.total_reward_shares2 );
u256 total_claims = to256( ctx.total_reward_shares2 );

//idump( (ctx) );

u256 rs2 = to256( calculate_vshares( ctx.rshares.value, rf_object ) );
rs2 = ( rs2 * ctx.reward_weight ) / STEEMIT_100_PERCENT;
u256 claim = to256( calculate_claims( ctx.rshares.value, rf_object ) );
claim = ( claim * ctx.reward_weight ) / STEEMIT_100_PERCENT;

u256 payout_u256 = ( rf * rs2 ) / total_rshares2;
u256 payout_u256 = ( rf * claim ) / total_claims;
FC_ASSERT( payout_u256 <= u256( uint64_t( std::numeric_limits<int64_t>::max() ) ) );
uint64_t payout = static_cast< uint64_t >( payout_u256 );

Expand All @@ -66,35 +65,46 @@ uint64_t get_rshare_reward( const comment_reward_context& ctx, const reward_fund
} FC_CAPTURE_AND_RETHROW( (ctx) )
}

uint128_t calculate_vshares( const uint128_t& rshares )
uint64_t get_vote_weight( uint64_t vote_rshares, const reward_fund_object& rf )
{
uint64_t result = 0;
if( rf.name == STEEMIT_POST_REWARD_FUND_NAME || rf.name == STEEMIT_COMMENT_REWARD_FUND_NAME )
{
uint128_t two_alpha = rf.content_constant * 2;
result = ( uint128_t( vote_rshares, 0 ) / ( two_alpha + vote_rshares ) ).to_uint64();
}
else
{
wlog( "Unknown reward fund type ${rf}", ("rf",rf.name) );
}

return result;
}

uint128_t calculate_claims( const uint128_t& rshares )
{
uint128_t s = get_content_constant_s();
uint128_t rshares_plus_s = rshares + s;
return rshares_plus_s * rshares_plus_s - s * s;
}

uint128_t calculate_vshares( const uint128_t& rshares, const reward_fund_object& rf )
uint128_t calculate_claims( const uint128_t& rshares, const reward_fund_object& rf )
{
if( rf.name == STEEMIT_POST_REWARD_FUND_NAME )
uint128_t result = 0;
if( rf.name == STEEMIT_POST_REWARD_FUND_NAME || rf.name == STEEMIT_COMMENT_REWARD_FUND_NAME )
{
// r^2 + 2rs
uint128_t s = rf.content_constant;
uint128_t rshares_plus_s = rshares + s;
return rshares_plus_s * rshares_plus_s - s * s;
// ( ( r + a )^2 - a^2 ) / ( r + g )
// In this implementation g = 40a
uint128_t rshares_plus_a = rshares + rf.content_constant;
uint128_t rshares_plus_g = rshares + rf.content_constant * STEEMIT_CONTENT_G_CONST;
result = ( rshares_plus_a * rshares_plus_a - rf.content_constant * rf.content_constant ) / rshares_plus_g;
}
else if( rf.name == STEEMIT_COMMENT_REWARD_FUND_NAME )
else
{
// r^2 / ( s + r )
// Can be optimized to r - r * s / ( r + s ) Needs investigation to determine what the loss of precision is (if any)
// This optimization is worth noting because it could be implemented using only 64-bit math
uint128_t rshares_2 = ( rshares * rshares );
uint128_t rshares_plus_s = rshares + rf.content_constant;
return rshares_2 / rshares_plus_s;
wlog( "Unknown reward fund type ${rf}", ("rf",rf.name) );
}

wlog( "Unknown reward fund ${rf}", ("rf",rf) );

return 0;
return result;
}

} } }
3 changes: 3 additions & 0 deletions libraries/protocol/include/steemit/protocol/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@
#define STEEMIT_POST_REWARD_FUND_NAME ("post")
#define STEEMIT_COMMENT_REWARD_FUND_NAME ("comment")
#define STEEMIT_RECENT_RSHARES_DECAY_RATE (fc::days(30))
#define STEEMIT_CONTENT_CONSTANT_HF0 (uint128_t(uint64_t(2000000000000ll)))
#define STEEMIT_CONTENT_CONSTANT_HF17 (uint64_t(277777777777ll)) // 1E13 / 36
#define STEEMIT_CONTENT_G_CONST (40)

// 5ccc e802 de5f
// int(expm1( log1p( 1 ) / BLOCKS_PER_YEAR ) * 2**STEEMIT_APR_PERCENT_SHIFT_PER_BLOCK / 100000 + 0.5)
Expand Down
8 changes: 4 additions & 4 deletions tests/tests/operation_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -548,22 +548,22 @@ BOOST_AUTO_TEST_CASE( comment_apply )
{
com.net_rshares = 10;
com.abs_rshares = 10;
com.children_rshares2 = steemit::chain::util::calculate_vshares( 10 );
com.children_rshares2 = steemit::chain::util::calculate_claims( 10 );
});

db.modify( mod_bob_comment, [&]( comment_object& com)
{
com.children_rshares2 = steemit::chain::util::calculate_vshares( 10 );
com.children_rshares2 = steemit::chain::util::calculate_claims( 10 );
});

db.modify( mod_alice_comment, [&]( comment_object& com)
{
com.children_rshares2 = steemit::chain::util::calculate_vshares( 10 );
com.children_rshares2 = steemit::chain::util::calculate_claims( 10 );
});

db.modify( db.get_dynamic_global_properties(), [&]( dynamic_global_property_object& o)
{
o.total_reward_shares2 = steemit::chain::util::calculate_vshares( 10 );
o.total_reward_shares2 = steemit::chain::util::calculate_claims( 10 );
});

tx.signatures.clear();
Expand Down
12 changes: 6 additions & 6 deletions tests/tests/operation_time_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ BOOST_AUTO_TEST_CASE( reward_funds )
FC_LOG_AND_RETHROW()
}

BOOST_AUTO_TEST_CASE( recent_rshares2_decay )
BOOST_AUTO_TEST_CASE( recent_claims_decay )
{
try
{
Expand Down Expand Up @@ -316,7 +316,7 @@ BOOST_AUTO_TEST_CASE( recent_rshares2_decay )
tx.sign( alice_private_key, db.get_chain_id() );
db.push_transaction( tx, 0 );

auto alice_vshares = util::calculate_vshares( db.get_comment( "alice", string( "test" ) ).net_rshares.value, db.get< reward_fund_object, by_name >( STEEMIT_POST_REWARD_FUND_NAME ) );
auto alice_vshares = util::calculate_claims( db.get_comment( "alice", string( "test" ) ).net_rshares.value, db.get< reward_fund_object, by_name >( STEEMIT_POST_REWARD_FUND_NAME ) );

generate_blocks( 5 );

Expand All @@ -334,12 +334,12 @@ BOOST_AUTO_TEST_CASE( recent_rshares2_decay )
{
const auto& post_rf = db.get< reward_fund_object, by_name >( STEEMIT_POST_REWARD_FUND_NAME );

BOOST_REQUIRE( post_rf.recent_rshares2 == alice_vshares );
BOOST_REQUIRE( post_rf.recent_claims == alice_vshares );
validate_database();
}

auto bob_cashout_time = db.get_comment( "bob", string( "test" ) ).cashout_time;
auto bob_vshares = util::calculate_vshares( db.get_comment( "bob", string( "test" ) ).net_rshares.value, db.get< reward_fund_object, by_name >( STEEMIT_POST_REWARD_FUND_NAME ) );
auto bob_vshares = util::calculate_claims( db.get_comment( "bob", string( "test" ) ).net_rshares.value, db.get< reward_fund_object, by_name >( STEEMIT_POST_REWARD_FUND_NAME ) );

generate_block();

Expand All @@ -348,7 +348,7 @@ BOOST_AUTO_TEST_CASE( recent_rshares2_decay )
alice_vshares -= ( alice_vshares * STEEMIT_BLOCK_INTERVAL ) / STEEMIT_RECENT_RSHARES_DECAY_RATE.to_seconds();
const auto& post_rf = db.get< reward_fund_object, by_name >( STEEMIT_POST_REWARD_FUND_NAME );

BOOST_REQUIRE( post_rf.recent_rshares2 == alice_vshares );
BOOST_REQUIRE( post_rf.recent_claims == alice_vshares );

generate_block();

Expand All @@ -358,7 +358,7 @@ BOOST_AUTO_TEST_CASE( recent_rshares2_decay )
alice_vshares -= ( alice_vshares * STEEMIT_BLOCK_INTERVAL ) / STEEMIT_RECENT_RSHARES_DECAY_RATE.to_seconds();
const auto& post_rf = db.get< reward_fund_object, by_name >( STEEMIT_POST_REWARD_FUND_NAME );

BOOST_REQUIRE( post_rf.recent_rshares2 == alice_vshares + bob_vshares );
BOOST_REQUIRE( post_rf.recent_claims == alice_vshares + bob_vshares );
validate_database();
}
}
Expand Down

0 comments on commit d47b4ab

Please sign in to comment.