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

Commit

Permalink
HIP-28 support - add consensus reward grace period
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulVMo committed Aug 18, 2021
1 parent ebbff31 commit 043335f
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 4 deletions.
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
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),
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.

0 comments on commit 043335f

Please sign in to comment.