diff --git a/Dockerfile b/Dockerfile index 942a1726ae..772c84b02b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -82,6 +82,7 @@ RUN \ fi && \ cd tests && \ ctest -j$(nproc) --output-on-failure && \ + ./chain_test -t basic_tests/curation_weight_test && \ cd .. && \ ./programs/util/test_fixed_string && \ cd /usr/local/src/steem && \ diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index d4bd09d73e..6f586fae28 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -1829,7 +1829,7 @@ share_type database::pay_curators( const comment_object& c, share_type& max_rewa } for( auto& item : proxy_set ) - { + { try { uint128_t weight( item->weight ); auto claim = ( ( max_rewards.value * weight ) / total_weight ).to_uint64(); if( claim > 0 ) // min_amt is non-zero satoshis @@ -1852,12 +1852,12 @@ share_type database::pay_curators( const comment_object& c, share_type& max_rewa #endif post_push_virtual_operation( vop ); } - } + } FC_CAPTURE_AND_RETHROW( (*item) ) } } max_rewards -= unclaimed_rewards; return unclaimed_rewards; - } FC_CAPTURE_AND_RETHROW() + } FC_CAPTURE_AND_RETHROW( (max_rewards) ) } void fill_comment_reward_context_local_state( util::comment_reward_context& ctx, const comment_object& comment ) @@ -2029,7 +2029,7 @@ share_type database::cashout_comment_helper( util::comment_reward_context& ctx, } return claimed_reward; - } FC_CAPTURE_AND_RETHROW( (comment) ) + } FC_CAPTURE_AND_RETHROW( (comment)(ctx) ) } void database::process_comment_cashout() diff --git a/libraries/chain/steem_evaluator.cpp b/libraries/chain/steem_evaluator.cpp index f02dd74748..61bc432185 100644 --- a/libraries/chain/steem_evaluator.cpp +++ b/libraries/chain/steem_evaluator.cpp @@ -2077,17 +2077,25 @@ void hf20_vote_evaluator( const vote_operation& o, database& _db ) auto curve = reward_fund.curation_reward_curve; uint64_t old_weight = util::evaluate_reward_curve( old_vote_rshares.value, curve, reward_fund.content_constant ).to_uint64(); uint64_t new_weight = util::evaluate_reward_curve( comment.vote_rshares.value, curve, reward_fund.content_constant ).to_uint64(); - cv.weight = new_weight - old_weight; - max_vote_weight = cv.weight; + if( old_weight >= new_weight ) // old_weight > new_weight should never happen + { + cv.weight = 0; + } + else + { + cv.weight = new_weight - old_weight; + + max_vote_weight = cv.weight; - /// discount weight by time - uint128_t w(max_vote_weight); - uint64_t delta_t = std::min( uint64_t((cv.last_update - comment.created).to_seconds()), uint64_t( dgpo.reverse_auction_seconds ) ); + /// discount weight by time + uint128_t w(max_vote_weight); + uint64_t delta_t = std::min( uint64_t((cv.last_update - comment.created).to_seconds()), uint64_t( dgpo.reverse_auction_seconds ) ); - w *= delta_t; - w /= dgpo.reverse_auction_seconds; - cv.weight = w.to_uint64(); + w *= delta_t; + w /= dgpo.reverse_auction_seconds; + cv.weight = w.to_uint64(); + } } else { diff --git a/libraries/protocol/include/steem/protocol/config.hpp b/libraries/protocol/include/steem/protocol/config.hpp index 0d69f3e272..5ad76e3e65 100644 --- a/libraries/protocol/include/steem/protocol/config.hpp +++ b/libraries/protocol/include/steem/protocol/config.hpp @@ -44,7 +44,7 @@ #else // IS LIVE STEEM NETWORK -#define STEEM_BLOCKCHAIN_VERSION ( version(0, 22, 0) ) +#define STEEM_BLOCKCHAIN_VERSION ( version(0, 22, 1) ) #define STEEM_INIT_PUBLIC_KEY_STR "STM8GC13uCZbP44HzMLV6zPZGwVQ8Nt4Kji8PapsPiNq1BK153XTX" #define STEEM_CHAIN_ID fc::sha256() diff --git a/tests/tests/basic_tests.cpp b/tests/tests/basic_tests.cpp index 46afe247dd..ce6c5910f6 100644 --- a/tests/tests/basic_tests.cpp +++ b/tests/tests/basic_tests.cpp @@ -32,6 +32,8 @@ #include #include +#include + #include #include #include "../db_fixture/database_fixture.hpp" @@ -357,4 +359,75 @@ BOOST_AUTO_TEST_CASE( adjust_balance_test ) BOOST_REQUIRE( db->get_balance( "alice", SBD_SYMBOL ) == asset( 0, SBD_SYMBOL ) ); } +uint8_t find_msb( const uint128_t& u ) +{ + uint64_t x; + uint8_t places; + x = (u.lo ? u.lo : 1); + places = (u.hi ? 64 : 0); + x = (u.hi ? u.hi : x); + return uint8_t( boost::multiprecision::detail::find_msb(x) + places ); +} + +uint64_t approx_sqrt( const uint128_t& x ) +{ + if( (x.lo == 0) && (x.hi == 0) ) + return 0; + + uint8_t msb_x = find_msb(x); + uint8_t msb_z = msb_x >> 1; + + uint128_t msb_x_bit = uint128_t(1) << msb_x; + uint64_t msb_z_bit = uint64_t (1) << msb_z; + + uint128_t mantissa_mask = msb_x_bit - 1; + uint128_t mantissa_x = x & mantissa_mask; + uint64_t mantissa_z_hi = (msb_x & 1) ? msb_z_bit : 0; + uint64_t mantissa_z_lo = (mantissa_x >> (msb_x - msb_z)).lo; + uint64_t mantissa_z = (mantissa_z_hi | mantissa_z_lo) >> 1; + uint64_t result = msb_z_bit | mantissa_z; + + return result; +} + +BOOST_AUTO_TEST_CASE( curation_weight_test ) +{ + fc::uint128_t rshares = 856158; + fc::uint128_t s = uint128_t( 0, 2000000000000ull ); + fc::uint128_t sqrt = approx_sqrt( rshares + 2 * s ); + uint64_t result = ( rshares / sqrt ).to_uint64(); + + BOOST_REQUIRE( sqrt.to_uint64() == 2002250 ); + BOOST_REQUIRE( result == 0 ); + + rshares = 0; + sqrt = approx_sqrt( rshares + 2 * s ); + result = ( rshares / sqrt ).to_uint64(); + + BOOST_REQUIRE( sqrt.to_uint64() == 2002250 ); + BOOST_REQUIRE( result == 0 ); + + result = ( uint128_t( 0 ) - uint128_t( 0 ) ).to_uint64(); + + BOOST_REQUIRE( result == 0 ); + rshares = uint128_t( 0, 3351842535167ull ); + + for( int64_t i = 856158; i >= 0; --i ) + { + uint64_t old_weight = util::evaluate_reward_curve( rshares - i, protocol::convergent_square_root, s ).to_uint64(); + uint64_t new_weight = util::evaluate_reward_curve( rshares, protocol::convergent_square_root, s ).to_uint64(); + + BOOST_REQUIRE( old_weight <= new_weight ); + + uint128_t w( new_weight - old_weight ); + + w *= 300; + w /= 300; + BOOST_REQUIRE( w.to_uint64() == new_weight - old_weight ); + } + + //idump( (delta)(old_weight)(new_weight) ); + +} + BOOST_AUTO_TEST_SUITE_END()