Skip to content
This repository has been archived by the owner on Mar 5, 2024. It is now read-only.

HIP-28 consensus reward calc grace period #922

Merged
merged 1 commit into from
Aug 23, 2021
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
2 changes: 1 addition & 1 deletion src/transactions/v1/blockchain_txn_vars_v1.erl
Original file line number Diff line number Diff line change
Expand Up @@ -987,7 +987,7 @@ validate_var(?poc_reward_decay_rate, Value) ->
validate_float(Value, "poc_reward_decay_rate", 0.0, 1.0);
validate_var(?reward_version, Value) ->
case Value of
N when is_integer(N), N >= 1, N =< 5 ->
N when is_integer(N), N >= 1, N =< 6 ->
ok;
_ ->
throw({error, {invalid_reward_version, Value}})
Expand Down
61 changes: 58 additions & 3 deletions src/transactions/v2/blockchain_txn_rewards_v2.erl
Original file line number Diff line number Diff line change
Expand Up @@ -277,10 +277,18 @@ calculate_rewards_metadata(Start, End, Chain) ->
Results0 = fold_blocks_for_rewards(Start, End, Chain,
Vars, Ledger, AccInit),

%% Forcing calculation of the EpochReward amount for the CG to always
%% Prior to HIP 28 (reward_version <6), force EpochReward amount for the CG to always
%% be around ElectionInterval (30 blocks) so that there is less incentive
%% to stay in the consensus group
ConsensusEpochReward = calculate_epoch_reward(1, Start, End, Ledger),
%% to stay in the consensus group. With HIP 28, relax that to be up to election_interval +
%% election_retry_interval to allow for time for election to complete.
ConsensusEpochReward =
case maps:get(reward_version,Vars) of
evanmcc marked this conversation as resolved.
Show resolved Hide resolved
RewardVersion when RewardVersion >= 6 ->
calculate_consensus_epoch_reward(Start, End, Vars);
_ ->
calculate_epoch_reward(1, Start, End, Ledger)
end,

Vars1 = Vars#{ consensus_epoch_reward => ConsensusEpochReward },

Results = finalize_reward_calculations(Results0, Ledger, Vars1),
Expand Down Expand Up @@ -667,6 +675,16 @@ calculate_epoch_reward(Version, Start, End, Ledger) ->

-spec calculate_epoch_reward(pos_integer(), pos_integer(), pos_integer(),
pos_integer(), pos_integer(), pos_integer()) -> float().
calculate_epoch_reward(Version, Start, End, BlockTime0, _ElectionInterval, MonthlyReward) when Version >= 6 ->
BlockTime1 = (BlockTime0/1000),
% Convert to blocks per min
BlockPerMin = 60/BlockTime1,
% Convert to blocks per hour
BlockPerHour = BlockPerMin*60,
% Calculate election interval in blocks
ElectionInterval = End - Start + 1, % epoch is inclusive of start and end
ElectionPerHour = BlockPerHour/ElectionInterval,
MonthlyReward/30/24/ElectionPerHour;
calculate_epoch_reward(Version, Start, End, BlockTime0, _ElectionInterval, MonthlyReward) when Version >= 2 ->
BlockTime1 = (BlockTime0/1000),
% Convert to blocks per min
Expand All @@ -687,6 +705,24 @@ calculate_epoch_reward(_Version, _Start, _End, BlockTime0, ElectionInterval, Mon
ElectionPerHour = BlockPerHour/ElectionInterval,
MonthlyReward/30/24/ElectionPerHour.



-spec calculate_consensus_epoch_reward(pos_integer(), pos_integer(), reward_vars()) -> float().
calculate_consensus_epoch_reward(Start, End, #{ block_time := BlockTime0,
election_interval := ElectionInterval,
election_restart_interval := ElectionRestartInterval,
monthly_reward := MonthlyReward }) ->

BlockTime1 = (BlockTime0/1000),
% Convert to blocks per min
BlockPerMin = 60/BlockTime1,
% Convert to blocks per month
BlockPerMonth = BlockPerMin*60*24*30,
% Calculate epoch length in blocks, cap at election interval + grace period
EpochLength = erlang:min(End - Start + 1, ElectionInterval + ElectionRestartInterval),
evanmcc marked this conversation as resolved.
Show resolved Hide resolved
MonthlyReward/BlockPerMonth*EpochLength.


-spec consensus_members_rewards(blockchain_ledger_v1:ledger(),
reward_vars(),
non_neg_integer()) -> rewards_map().
Expand Down Expand Up @@ -1819,4 +1855,23 @@ common_poc_vars() ->
?poc_v5_target_prob_randomness_wt => 0.0
}.


hip28_calc_test() ->
% set test vars such that rewards are 1 per block
Vars = #{ block_time => 60000,
election_interval => 30,
election_restart_interval => 5,
monthly_reward => 43200,
reward_version => 6 },
?assertEqual(30.0, calculate_consensus_epoch_reward(1,30,Vars)),
?assertEqual(35.0, calculate_consensus_epoch_reward(1,50,Vars)).

consensus_epoch_reward_test() ->
% using test values such that reward is 1 per block
% should always return the election interval as the answer
?assertEqual(30.0,calculate_epoch_reward(1,1,25,60000,30,43200)),

% more than 30 blocks should return 30
?assertEqual(30.0,calculate_epoch_reward(1,1,50,60000,30,43200)).

-endif.