forked from albert19882016/steem
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement rc curve generation in c++ steemit#2787
- Loading branch information
1 parent
db06461
commit 83593e8
Showing
3 changed files
with
197 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
#include "rc_curve.hpp" | ||
|
||
#include <steem/protocol/config.hpp> | ||
|
||
#include <fc/exception/exception.hpp> | ||
#include <fc/log/logger.hpp> | ||
|
||
#include <math.h> | ||
#include <limits> | ||
|
||
namespace steem { namespace plugins { namespace rc { | ||
|
||
template< typename T > | ||
T check_and_cast( double num ) | ||
{ | ||
FC_ASSERT( num >= std::numeric_limits< T >::min() && num <= std::numeric_limits< T >::max(), | ||
"Unexpected value out of range. value: ${v} type: ${t}", ("v", num)("t", fc::get_typename< T >::name()) ); | ||
|
||
return (T)num; | ||
} | ||
|
||
rc_resource_params generate_rc_curve( const rc_curve_gen_params& params ) | ||
{ | ||
try | ||
{ | ||
const static double log_2 = std::log( 2.0 ); | ||
|
||
rc_resource_params result; | ||
|
||
result.time_unit = params.time_unit; | ||
|
||
uint32_t time_unit_sec = params.time_unit == rc_time_unit_seconds ? 1 : STEEM_BLOCK_INTERVAL; | ||
fc::microseconds budget_time = params.budget_time; | ||
fc::microseconds half_life = params.half_life; | ||
double inelasticity_threshold = double( params.inelasticity_threshold_num ) / params.inelasticity_threshold_denom; | ||
|
||
idump( (half_life.to_seconds()) ); | ||
|
||
double tau = half_life.to_seconds() / log_2; | ||
double decay_per_sec_float = -1 * std::expm1( -1.0 / tau ); | ||
|
||
double budget_per_sec = double( params.budget ) / double( budget_time.to_seconds() ); | ||
|
||
uint32_t resource_unit_exponent = 0; | ||
if( params.resource_unit_exponent ) | ||
{ | ||
resource_unit_exponent = *(params.resource_unit_exponent); | ||
} | ||
else | ||
{ | ||
idump( (budget_per_sec)(decay_per_sec_float)(params.small_stockpile_size) ); | ||
double pool_eq = budget_per_sec / decay_per_sec_float; | ||
double resource_unit_exponent_float = std::log( params.small_stockpile_size / pool_eq ) / std::log( params.resource_unit_base ); | ||
resource_unit_exponent = std::max( 0, check_and_cast< int32_t >( std::ceil( resource_unit_exponent_float ) ) ); | ||
} | ||
|
||
result.resource_unit = check_and_cast< uint64_t >( std::pow( params.resource_unit_base, resource_unit_exponent ) ); | ||
|
||
budget_per_sec *= result.resource_unit; | ||
double budget_per_time_unit = budget_per_sec * time_unit_sec; | ||
result.budget_per_time_unit = check_and_cast< int32_t >( budget_per_time_unit + 0.5 ); | ||
|
||
double pool_eq = budget_per_sec / decay_per_sec_float; | ||
result.pool_eq = check_and_cast< uint64_t >( pool_eq + 1 ); | ||
result.max_pool_size = check_and_cast< uint64_t >( ( pool_eq * 2.0 ) + 0.5 ); | ||
|
||
double a_point = (double)( params.a_point_num ) / (double)( params.a_point_denom ); | ||
double u_point = (double)( params.u_point_num ) / (double)( params.u_point_denom ); | ||
double k = u_point / ( a_point * ( 1.0 - u_point ) ); | ||
|
||
double B = inelasticity_threshold * pool_eq; | ||
double A = tau / k; | ||
|
||
if( A < 1.0 || B < 1.0 ) | ||
{ | ||
wlog( "Bad parameter vlaue (is time too short?)" ); | ||
FC_ASSERT( false, "Bad parameter vlaue (is time too short?)" ); | ||
} | ||
|
||
double curve_shift_float = std::log( (0xFFFFFFFFFFFFFFFFull) / A ) / log_2; | ||
uint64_t curve_shift = check_and_cast< uint64_t >( std::floor( curve_shift_float ) ); | ||
result.curve_params.coeff_a = check_and_cast< uint64_t >( A * ( std::pow( 2, curve_shift ) + 0.5 ) ); | ||
result.curve_params.coeff_b = check_and_cast< uint64_t >( B + 0.5 ); | ||
result.curve_params.shift = check_and_cast< uint8_t >( curve_shift ); | ||
|
||
double decay_per_time_unit_float = -1 * std::expm1( -1 * ( time_unit_sec * log_2 ) / half_life.to_seconds() ); | ||
|
||
double decay_per_time_unit_denom_shift_float = std::log( 0xFFFFFFFF / decay_per_time_unit_float ) / log_2; | ||
uint64_t decay_per_time_unit_denom_shift = check_and_cast< uint64_t >( std::floor( decay_per_time_unit_denom_shift_float ) ); | ||
uint64_t decay_per_time_unit = check_and_cast< uint64_t >( decay_per_time_unit_float * std::pow( 2.0, decay_per_time_unit_denom_shift ) + 0.5 ); | ||
|
||
result.decay_params.decay_per_time_unit = decay_per_time_unit; | ||
result.decay_params.decay_per_time_unit_denom_shift = decay_per_time_unit_denom_shift; | ||
|
||
return result; | ||
} | ||
FC_CAPTURE_LOG_AND_RETHROW( (params) ) | ||
} | ||
|
||
} } } //steed::plugins::rc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
/** | ||
* Note: | ||
* | ||
* This header is contained within a source directory because it is not meant to be used anywhere | ||
* EXCEPT the rc plugin. The implementation uses floating point arithmetic which can be | ||
* non-deterministic. This implementation is NOT suitable for a consensus level protocol. | ||
*/ | ||
|
||
#pragma once | ||
#include <steem/plugins/rc/rc_utility.hpp> | ||
|
||
// This header shouldn't be needed, but fc reflection was not working | ||
// and something in here makes it work. | ||
#include <steem/protocol/types.hpp> | ||
|
||
#include <fc/time.hpp> | ||
|
||
namespace steem { namespace plugins { namespace rc { | ||
|
||
/** | ||
* The design of these classes is to be json compatible with the parameters | ||
* defined for use with rc_generate_resource_parameters.py | ||
* | ||
* Some of the structures are redundant compared to existing C++ types but | ||
* are designed for this purpose. | ||
*/ | ||
|
||
struct rc_time_type | ||
{ | ||
uint32_t seconds = 0; | ||
uint32_t minutes = 0; | ||
uint32_t hours = 0; | ||
uint32_t days = 0; | ||
uint32_t weeks = 0; | ||
uint32_t months = 0; | ||
uint32_t years = 0; | ||
|
||
operator fc::microseconds() const | ||
{ | ||
return fc::seconds( seconds ) | ||
+ fc::minutes( minutes ) | ||
+ fc::hours( hours ) | ||
+ fc::days( days ) | ||
+ fc::days( weeks * 7 ) | ||
+ fc::days( months * 30 ) | ||
+ fc::days( years * 365 ); | ||
} | ||
}; | ||
|
||
struct rc_curve_gen_params | ||
{ | ||
rc_time_unit_type time_unit = rc_time_unit_seconds; | ||
rc_time_type budget_time; | ||
uint64_t budget; | ||
rc_time_type half_life; | ||
uint32_t inelasticity_threshold_num = 1; | ||
uint32_t inelasticity_threshold_denom = 128; | ||
uint64_t small_stockpile_size = 0x0000000100000000ull; // 2^32 | ||
uint32_t resource_unit_base = 10; | ||
fc::optional< int32_t > resource_unit_exponent; | ||
uint32_t a_point_num = 1; | ||
uint32_t a_point_denom = 32; | ||
uint32_t u_point_num = 1; | ||
uint32_t u_point_denom = 2; | ||
}; | ||
|
||
rc_resource_params generate_rc_curve( const rc_curve_gen_params& params ); | ||
|
||
} } } // steem::plugins::rc | ||
|
||
FC_REFLECT( steem::plugins::rc::rc_time_type, | ||
(seconds) | ||
(minutes) | ||
(hours) | ||
(days) | ||
(weeks) | ||
(months) | ||
(years) | ||
) | ||
//* | ||
FC_REFLECT( steem::plugins::rc::rc_curve_gen_params, | ||
(time_unit) | ||
(budget_time) | ||
(budget) | ||
(half_life) | ||
(inelasticity_threshold_num) | ||
(inelasticity_threshold_denom) | ||
(small_stockpile_size) | ||
(resource_unit_base) | ||
(resource_unit_exponent) | ||
(a_point_num) | ||
(a_point_denom) | ||
(u_point_num) | ||
(u_point_denom) | ||
) | ||
//*/ |