diff --git a/contrib/kaitai-struct-files/files/alpha__constants.ksy b/contrib/kaitai-struct-files/files/alpha__constants.ksy index 75cfeb9ea02b025a2283cfa06dc7987f8115a128..934d4bb5dc8f9cad65ba60e1285c8fdb0d25698d 100644 --- a/contrib/kaitai-struct-files/files/alpha__constants.ksy +++ b/contrib/kaitai-struct-files/files/alpha__constants.ksy @@ -5,10 +5,18 @@ doc: ! 'Encoding id: alpha.constants' types: adaptive_rewards_params: seq: - - id: issuance_ratio_min - type: issuance_ratio_min - - id: issuance_ratio_max - type: issuance_ratio_max + - id: issuance_ratio_final_min + type: issuance_ratio_final_min + - id: issuance_ratio_final_max + type: issuance_ratio_final_max + - id: issuance_ratio_initial_min + type: issuance_ratio_initial_min + - id: issuance_ratio_initial_max + type: issuance_ratio_initial_max + - id: initial_period + type: u1 + - id: transition_period + type: u1 - id: max_bonus type: s8 - id: growth_rate @@ -64,13 +72,25 @@ types: valid: min: -1073741824 max: 1073741823 - issuance_ratio_max: + issuance_ratio_final_max: + seq: + - id: numerator + type: z + - id: denominator + type: z + issuance_ratio_final_min: + seq: + - id: numerator + type: z + - id: denominator + type: z + issuance_ratio_initial_max: seq: - id: numerator type: z - id: denominator type: z - issuance_ratio_min: + issuance_ratio_initial_min: seq: - id: numerator type: z diff --git a/contrib/kaitai-struct-files/files/alpha__constants__parametric.ksy b/contrib/kaitai-struct-files/files/alpha__constants__parametric.ksy index 7a9cdc7f284f4ab6f0b7bf04bb49ad8343985bc1..752688d917472a07dfaaf0d9221c5907cb06a29a 100644 --- a/contrib/kaitai-struct-files/files/alpha__constants__parametric.ksy +++ b/contrib/kaitai-struct-files/files/alpha__constants__parametric.ksy @@ -5,10 +5,18 @@ doc: ! 'Encoding id: alpha.constants.parametric' types: adaptive_rewards_params: seq: - - id: issuance_ratio_min - type: issuance_ratio_min - - id: issuance_ratio_max - type: issuance_ratio_max + - id: issuance_ratio_final_min + type: issuance_ratio_final_min + - id: issuance_ratio_final_max + type: issuance_ratio_final_max + - id: issuance_ratio_initial_min + type: issuance_ratio_initial_min + - id: issuance_ratio_initial_max + type: issuance_ratio_initial_max + - id: initial_period + type: u1 + - id: transition_period + type: u1 - id: max_bonus type: s8 - id: growth_rate @@ -64,13 +72,25 @@ types: valid: min: -1073741824 max: 1073741823 - issuance_ratio_max: + issuance_ratio_final_max: + seq: + - id: numerator + type: z + - id: denominator + type: z + issuance_ratio_final_min: + seq: + - id: numerator + type: z + - id: denominator + type: z + issuance_ratio_initial_max: seq: - id: numerator type: z - id: denominator type: z - issuance_ratio_min: + issuance_ratio_initial_min: seq: - id: numerator type: z diff --git a/contrib/kaitai-struct-files/files/alpha__parameters.ksy b/contrib/kaitai-struct-files/files/alpha__parameters.ksy index 0bc137163152aca0596babdf62fc8b784bfcf684..9904127c7c66c26fdd55333b792018eda4aff5e2 100644 --- a/contrib/kaitai-struct-files/files/alpha__parameters.ksy +++ b/contrib/kaitai-struct-files/files/alpha__parameters.ksy @@ -5,10 +5,18 @@ doc: ! 'Encoding id: alpha.parameters' types: adaptive_rewards_params: seq: - - id: issuance_ratio_min - type: issuance_ratio_min - - id: issuance_ratio_max - type: issuance_ratio_max + - id: issuance_ratio_final_min + type: issuance_ratio_final_min + - id: issuance_ratio_final_max + type: issuance_ratio_final_max + - id: issuance_ratio_initial_min + type: issuance_ratio_initial_min + - id: issuance_ratio_initial_max + type: issuance_ratio_initial_max + - id: initial_period + type: u1 + - id: transition_period + type: u1 - id: max_bonus type: s8 - id: growth_rate @@ -198,13 +206,25 @@ types: valid: min: -1073741824 max: 1073741823 - issuance_ratio_max: + issuance_ratio_final_max: + seq: + - id: numerator + type: z + - id: denominator + type: z + issuance_ratio_final_min: + seq: + - id: numerator + type: z + - id: denominator + type: z + issuance_ratio_initial_max: seq: - id: numerator type: z - id: denominator type: z - issuance_ratio_min: + issuance_ratio_initial_min: seq: - id: numerator type: z diff --git a/src/proto_alpha/lib_parameters/default_parameters.ml b/src/proto_alpha/lib_parameters/default_parameters.ml index 9c9ef545f9cba42561a612e11fc34f76bbb33791..03f75600a51250e8f4806bacecf14ba73b597a66 100644 --- a/src/proto_alpha/lib_parameters/default_parameters.ml +++ b/src/proto_alpha/lib_parameters/default_parameters.ml @@ -279,8 +279,12 @@ let constants_mainnet = launch_ema_threshold = 1_600_000_000l; adaptive_rewards_params = { - issuance_ratio_min = Q.(5 // 10000); - issuance_ratio_max = Q.(1 // 20); + issuance_ratio_final_min = Q.(0_25 // 100_00); + issuance_ratio_final_max = Q.(10 // 100); + issuance_ratio_initial_min = Q.(45 // 1000); + issuance_ratio_initial_max = Q.(55 // 1000); + initial_period = 10; + transition_period = 50; max_bonus = Protocol.Issuance_bonus_repr.max_bonus_parameter_of_Q_exn Q.(5 // 100); diff --git a/src/proto_alpha/lib_protocol/adaptive_issuance_storage.ml b/src/proto_alpha/lib_protocol/adaptive_issuance_storage.ml index 23fb8d1ef4e177e85bc6447d7a9a695544ed3148..18adf520661755c6dd15f1e1aeeabbb368125c1e 100644 --- a/src/proto_alpha/lib_protocol/adaptive_issuance_storage.ml +++ b/src/proto_alpha/lib_protocol/adaptive_issuance_storage.ml @@ -60,6 +60,8 @@ let () = | Undetermined_issuance_coeff_for_cycle cycle -> Some cycle | _ -> None) (fun cycle -> Undetermined_issuance_coeff_for_cycle cycle) +let launch_cycle ctxt = Storage.Adaptive_issuance.Activation.get ctxt + let check_determined_cycle ctxt cycle = let ai_enable = Constants_storage.adaptive_issuance_enable ctxt in if ai_enable then @@ -106,6 +108,59 @@ let truncate_reward_coeff ~issuance_ratio_min ~issuance_ratio_max f = let f = Q.max f issuance_ratio_min in f +let compute_extremum ~launch_cycle ~new_cycle ~initial_period ~transition_period + ~initial ~final = + match launch_cycle with + | None -> + (* This case shouldn't happen, but if it does this value is the most sensible *) + initial + | Some launch_cycle -> + let transition_period = transition_period + 1 in + assert (Compare.Int.(transition_period > 0)) ; + let t1 = Cycle_repr.add launch_cycle initial_period in + let t2 = Cycle_repr.add t1 transition_period in + if Cycle_repr.(new_cycle <= t1) then initial + else if Cycle_repr.(new_cycle >= t2) then final + else + let t = Cycle_repr.diff new_cycle t1 |> Q.of_int32 in + Q.(((final - initial) * t / of_int transition_period) + initial) + +let compute_min + ~(reward_params : Constants_parametric_repr.adaptive_rewards_params) = + let Constants_parametric_repr. + { + initial_period; + transition_period; + issuance_ratio_initial_min; + issuance_ratio_final_min; + _; + } = + reward_params + in + compute_extremum + ~initial_period + ~transition_period + ~initial:issuance_ratio_initial_min + ~final:issuance_ratio_final_min + +let compute_max + ~(reward_params : Constants_parametric_repr.adaptive_rewards_params) = + let Constants_parametric_repr. + { + initial_period; + transition_period; + issuance_ratio_initial_max; + issuance_ratio_final_max; + _; + } = + reward_params + in + compute_extremum + ~initial_period + ~transition_period + ~initial:issuance_ratio_initial_max + ~final:issuance_ratio_final_max + let compute_reward_coeff_ratio_without_bonus = let q_1600 = Q.of_int 1600 in fun ~stake_ratio ~issuance_ratio_max ~issuance_ratio_min -> @@ -114,12 +169,17 @@ let compute_reward_coeff_ratio_without_bonus = (* f is truncated so that 0.05% <= f <= 5% *) truncate_reward_coeff ~issuance_ratio_min ~issuance_ratio_max f -let compute_bonus ~seconds_per_cycle ~stake_ratio ~base_reward_coeff_ratio - ~(previous_bonus : Issuance_bonus_repr.t) ~reward_params = +let compute_bonus ~issuance_ratio_max ~seconds_per_cycle ~stake_ratio + ~base_reward_coeff_ratio ~(previous_bonus : Issuance_bonus_repr.t) + ~reward_params = let Constants_parametric_repr. { - issuance_ratio_min = _; - issuance_ratio_max; + issuance_ratio_final_min = _; + issuance_ratio_final_max = _; + issuance_ratio_initial_min = _; + issuance_ratio_initial_max = _; + initial_period = _; + transition_period = _; max_bonus; growth_rate; center_dz; @@ -156,17 +216,14 @@ let compute_bonus ~seconds_per_cycle ~stake_ratio ~base_reward_coeff_ratio let compute_coeff = let q_min_per_year = Q.of_int 525600 in - fun ~base_total_issued_per_minute + fun ~issuance_ratio_max + ~issuance_ratio_min + ~base_total_issued_per_minute ~base_reward_coeff_ratio ~q_total_supply - ~(bonus : Issuance_bonus_repr.t) - ~reward_params -> + ~(bonus : Issuance_bonus_repr.t) -> if Tez_repr.(base_total_issued_per_minute = zero) then Q.one else - let Constants_parametric_repr.{issuance_ratio_min; issuance_ratio_max; _} - = - reward_params - in let q_base_total_issued_per_minute = Tez_repr.to_mutez base_total_issued_per_minute |> Q.of_int64 in @@ -181,6 +238,7 @@ let compute_and_store_reward_coeff_at_cycle_end ctxt ~new_cycle = let ai_enable = Constants_storage.adaptive_issuance_enable ctxt in if not ai_enable then return ctxt else + let* launch_cycle = launch_cycle ctxt in let reward_params = Constants_storage.adaptive_issuance_rewards_params ctxt in @@ -208,14 +266,21 @@ let compute_and_store_reward_coeff_at_cycle_end ctxt ~new_cycle = let stake_ratio = Q.div q_total_frozen_stake q_total_supply (* = portion of frozen stake *) in + let issuance_ratio_min = + compute_min ~launch_cycle ~new_cycle ~reward_params + in + let issuance_ratio_max = + compute_max ~launch_cycle ~new_cycle ~reward_params + in let base_reward_coeff_ratio = compute_reward_coeff_ratio_without_bonus ~stake_ratio - ~issuance_ratio_max:reward_params.issuance_ratio_max - ~issuance_ratio_min:reward_params.issuance_ratio_min + ~issuance_ratio_max + ~issuance_ratio_min in let*? bonus = compute_bonus + ~issuance_ratio_max ~seconds_per_cycle ~stake_ratio ~base_reward_coeff_ratio @@ -224,11 +289,12 @@ let compute_and_store_reward_coeff_at_cycle_end ctxt ~new_cycle = in let coeff = compute_coeff + ~issuance_ratio_max + ~issuance_ratio_min ~base_total_issued_per_minute ~base_reward_coeff_ratio ~q_total_supply ~bonus - ~reward_params in let*! ctxt = Storage.Issuance_bonus.add ctxt for_cycle bonus in let*! ctxt = Storage.Issuance_coeff.add ctxt for_cycle coeff in @@ -259,8 +325,6 @@ let init ctxt = let activate ctxt ~cycle = Storage.Adaptive_issuance.Activation.update ctxt (Some cycle) -let launch_cycle ctxt = Storage.Adaptive_issuance.Activation.get ctxt - let set_adaptive_issuance_enable ctxt = let open Lwt_result_syntax in let+ enable = @@ -327,4 +391,8 @@ module Internal_for_tests = struct let compute_bonus = compute_bonus let compute_coeff = compute_coeff + + let compute_min = compute_min + + let compute_max = compute_max end diff --git a/src/proto_alpha/lib_protocol/adaptive_issuance_storage.mli b/src/proto_alpha/lib_protocol/adaptive_issuance_storage.mli index 5305a216b73f16f36557eea8b1b6d2f339beae55..4f007628d215fe67b2b4267a1ee2fc87cbefcaf3 100644 --- a/src/proto_alpha/lib_protocol/adaptive_issuance_storage.mli +++ b/src/proto_alpha/lib_protocol/adaptive_issuance_storage.mli @@ -101,6 +101,7 @@ module Internal_for_tests : sig stake_ratio:Q.t -> issuance_ratio_max:Q.t -> issuance_ratio_min:Q.t -> Q.t val compute_bonus : + issuance_ratio_max:Q.t -> seconds_per_cycle:int64 -> stake_ratio:Q.t -> base_reward_coeff_ratio:Q.t -> @@ -109,10 +110,23 @@ module Internal_for_tests : sig Issuance_bonus_repr.t tzresult val compute_coeff : + issuance_ratio_max:Q.t -> + issuance_ratio_min:Q.t -> base_total_issued_per_minute:Tez_repr.t -> base_reward_coeff_ratio:Q.t -> q_total_supply:Q.t -> bonus:Issuance_bonus_repr.t -> + Q.t + + val compute_min : + reward_params:Constants_parametric_repr.adaptive_rewards_params -> + launch_cycle:Cycle_repr.t option -> + new_cycle:Cycle_repr.t -> + Q.t + + val compute_max : reward_params:Constants_parametric_repr.adaptive_rewards_params -> + launch_cycle:Cycle_repr.t option -> + new_cycle:Cycle_repr.t -> Q.t end diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index d3b015125674327e211eb3067c6be409fe6fcf06..9db99c9a6e0eebcc22a3861734ff3a2573c2fd4b 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -855,8 +855,12 @@ module Constants : sig } type adaptive_rewards_params = { - issuance_ratio_min : Q.t; - issuance_ratio_max : Q.t; + issuance_ratio_final_min : Q.t; + issuance_ratio_final_max : Q.t; + issuance_ratio_initial_min : Q.t; + issuance_ratio_initial_max : Q.t; + initial_period : int; + transition_period : int; max_bonus : Issuance_bonus_repr.max_bonus; growth_rate : Q.t; center_dz : Q.t; @@ -2363,6 +2367,7 @@ module Delegate : sig Q.t val compute_bonus : + issuance_ratio_max:Q.t -> seconds_per_cycle:int64 -> stake_ratio:Q.t -> base_reward_coeff_ratio:Q.t -> @@ -2371,11 +2376,24 @@ module Delegate : sig Issuance_bonus_repr.t tzresult val compute_coeff : + issuance_ratio_max:Q.t -> + issuance_ratio_min:Q.t -> base_total_issued_per_minute:Tez_repr.t -> base_reward_coeff_ratio:Q.t -> q_total_supply:Q.t -> bonus:Issuance_bonus_repr.t -> + Q.t + + val compute_min : + reward_params:Constants.Parametric.adaptive_rewards_params -> + launch_cycle:Cycle_repr.t option -> + new_cycle:Cycle_repr.t -> + Q.t + + val compute_max : reward_params:Constants.Parametric.adaptive_rewards_params -> + launch_cycle:Cycle_repr.t option -> + new_cycle:Cycle_repr.t -> Q.t end end diff --git a/src/proto_alpha/lib_protocol/constants_parametric_repr.ml b/src/proto_alpha/lib_protocol/constants_parametric_repr.ml index c6e5a5ab93454f0cc5bdf6f17abb1bd2e042de74..b66fc7a8e6b9e59601f01eb7acb09036d9144fa8 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_repr.ml +++ b/src/proto_alpha/lib_protocol/constants_parametric_repr.ml @@ -144,8 +144,12 @@ type zk_rollup = { } type adaptive_rewards_params = { - issuance_ratio_min : Q.t; - issuance_ratio_max : Q.t; + issuance_ratio_final_min : Q.t; + issuance_ratio_final_max : Q.t; + issuance_ratio_initial_min : Q.t; + issuance_ratio_initial_max : Q.t; + initial_period : int; + transition_period : int; max_bonus : Issuance_bonus_repr.max_bonus; growth_rate : Q.t; center_dz : Q.t; @@ -368,36 +372,56 @@ let adaptive_rewards_params_encoding = let open Data_encoding in conv (fun { - issuance_ratio_min; - issuance_ratio_max; + issuance_ratio_final_min; + issuance_ratio_final_max; + issuance_ratio_initial_min; + issuance_ratio_initial_max; + initial_period; + transition_period; max_bonus; growth_rate; center_dz; radius_dz; } -> - ( issuance_ratio_min, - issuance_ratio_max, + ( issuance_ratio_final_min, + issuance_ratio_final_max, + issuance_ratio_initial_min, + issuance_ratio_initial_max, + initial_period, + transition_period, max_bonus, growth_rate, center_dz, radius_dz )) - (fun ( issuance_ratio_min, - issuance_ratio_max, + (fun ( issuance_ratio_final_min, + issuance_ratio_final_max, + issuance_ratio_initial_min, + issuance_ratio_initial_max, + initial_period, + transition_period, max_bonus, growth_rate, center_dz, radius_dz ) -> { - issuance_ratio_min; - issuance_ratio_max; + issuance_ratio_final_min; + issuance_ratio_final_max; + issuance_ratio_initial_min; + issuance_ratio_initial_max; + initial_period; + transition_period; max_bonus; growth_rate; center_dz; radius_dz; }) - (obj6 - (req "issuance_ratio_min" extremum_encoding) - (req "issuance_ratio_max" extremum_encoding) + (obj10 + (req "issuance_ratio_final_min" extremum_encoding) + (req "issuance_ratio_final_max" extremum_encoding) + (req "issuance_ratio_initial_min" extremum_encoding) + (req "issuance_ratio_initial_max" extremum_encoding) + (req "initial_period" uint8) + (req "transition_period" uint8) (req "max_bonus" Issuance_bonus_repr.max_bonus_encoding) (req "growth_rate" growth_rate_encoding) (req "center_dz" center_encoding) diff --git a/src/proto_alpha/lib_protocol/constants_parametric_repr.mli b/src/proto_alpha/lib_protocol/constants_parametric_repr.mli index 4533c37e2fe3c74b1372e61d6196ec76ad40c390..66a7d0d0272800b0da299262f6d93c5e75fe18fa 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_repr.mli +++ b/src/proto_alpha/lib_protocol/constants_parametric_repr.mli @@ -108,8 +108,20 @@ type zk_rollup = { } type adaptive_rewards_params = { - issuance_ratio_min : (* Maximum yearly issuance rate *) Q.t; - issuance_ratio_max : (* Minimum yearly issuance rate *) Q.t; + issuance_ratio_final_min : (* Minimum yearly issuance rate *) Q.t; + issuance_ratio_final_max : (* Maximum yearly issuance rate *) Q.t; + issuance_ratio_initial_min : + (* Minimum yearly issuance rate at adaptive issuance activation *) Q.t; + issuance_ratio_initial_max : + (* Maximum yearly issuance rate at adaptive issuance activation *) Q.t; + initial_period : + (* Period in cycles during which the minimum and maximum yearly + issuance rate values stay at their initial values *) + int; + transition_period : + (* Period in cycles during which the minimum and maximum yearly + issuance rate values decrease/increase until they reach their global values *) + int; max_bonus : (* Maximum issuance bonus value *) Issuance_bonus_repr.max_bonus; growth_rate : (* Bonus value's growth rate *) Q.t; center_dz : (* Center for bonus *) Q.t; diff --git a/src/proto_alpha/lib_protocol/raw_context.ml b/src/proto_alpha/lib_protocol/raw_context.ml index b81fd58726eceee948e9e328939fd77fe33eb1e0..424600b31c3cd6745ddace0c242565a70765b91b 100644 --- a/src/proto_alpha/lib_protocol/raw_context.ml +++ b/src/proto_alpha/lib_protocol/raw_context.ml @@ -1135,10 +1135,17 @@ let prepare_first_block ~level ~timestamp _chain_id ctxt = let adaptive_rewards_params = Constants_parametric_repr. { - issuance_ratio_min = - c.adaptive_issuance.adaptive_rewards_params.issuance_ratio_min; - issuance_ratio_max = - c.adaptive_issuance.adaptive_rewards_params.issuance_ratio_max; + issuance_ratio_final_min = Q.(0_25 // 100_00); + (* 0.25% *) + issuance_ratio_final_max = Q.(10 // 100) (* 10% *); + issuance_ratio_initial_min = Q.(45 // 1000); + (* 4.5% *) + issuance_ratio_initial_max = Q.(55 // 1000); + (* 5.5% *) + initial_period = 10; + (* 1 month *) + transition_period = 50; + (* 5 months *) max_bonus = c.adaptive_issuance.adaptive_rewards_params.max_bonus; growth_rate = c.adaptive_issuance.adaptive_rewards_params.growth_rate; diff --git a/src/proto_alpha/lib_protocol/test/unit/test_adaptive_issuance.ml b/src/proto_alpha/lib_protocol/test/unit/test_adaptive_issuance.ml index 8026f9665ce74b3fa416498debd299a9f6860877..23a82c1a994d3e217104d90e2708bd8440186886 100644 --- a/src/proto_alpha/lib_protocol/test/unit/test_adaptive_issuance.ml +++ b/src/proto_alpha/lib_protocol/test/unit/test_adaptive_issuance.ml @@ -121,14 +121,17 @@ let test_compute_bonus () = let*?@ previous_bonus = Issuance_bonus_repr.of_Q ~max_bonus:reward_params.max_bonus previous_bonus in + let issuance_ratio_max = reward_params.issuance_ratio_final_max in + let issuance_ratio_min = reward_params.issuance_ratio_final_min in let base_reward_coeff_ratio = compute_reward_coeff_ratio_without_bonus ~stake_ratio - ~issuance_ratio_max:reward_params.issuance_ratio_max - ~issuance_ratio_min:reward_params.issuance_ratio_min + ~issuance_ratio_max + ~issuance_ratio_min in let*?@ bonus = compute_bonus + ~issuance_ratio_max ~seconds_per_cycle ~stake_ratio ~base_reward_coeff_ratio @@ -142,14 +145,14 @@ let test_compute_bonus () = ~loc:__LOC__ ~f:Q.geq (return full_reward_coeff) - reward_params.issuance_ratio_min + issuance_ratio_min in let* () = assert_fun ~loc:__LOC__ ~f:Q.leq (return full_reward_coeff) - reward_params.issuance_ratio_max + issuance_ratio_max in return (bonus :> Q.t) in @@ -244,7 +247,6 @@ let test_compute_coeff () = let* b in Assert.equal ~loc Q.equal "" Q.pp_print a b in - let reward_params = Default_parameters.constants_test.adaptive_issuance.adaptive_rewards_params in @@ -255,7 +257,11 @@ let test_compute_coeff () = let compute_coeff ?(base_total_issued_per_minute = base_total_issued_per_minute) ?(q_total_supply = Q.of_int64 1_000_000_000L) () = - compute_coeff ~base_total_issued_per_minute ~q_total_supply ~reward_params + compute_coeff + ~issuance_ratio_max:reward_params.issuance_ratio_final_max + ~issuance_ratio_min:reward_params.issuance_ratio_final_min + ~base_total_issued_per_minute + ~q_total_supply in (* Test inverse linearity wrt base issuance Base issuance * Issuance coeff = constant (= issuance per unit of time) @@ -360,24 +366,224 @@ let test_compute_coeff () = assert_eq_lwt ~loc:__LOC__ (compute_coeff Q.zero Q.zero) - (compute_coeff reward_params.issuance_ratio_min Q.zero) + (compute_coeff reward_params.issuance_ratio_final_min Q.zero) in (* Test max *) let* () = assert_eq_lwt ~loc:__LOC__ - (compute_coeff (Q.add reward_params.issuance_ratio_max Q.one) Q.zero) - (compute_coeff reward_params.issuance_ratio_max Q.zero) + (compute_coeff + (Q.add reward_params.issuance_ratio_final_max Q.one) + Q.zero) + (compute_coeff reward_params.issuance_ratio_final_max Q.zero) in let* () = assert_eq_lwt ~loc:__LOC__ - (compute_coeff reward_params.issuance_ratio_max Q.(1 // 100)) - (compute_coeff reward_params.issuance_ratio_max Q.zero) + (compute_coeff reward_params.issuance_ratio_final_max Q.(1 // 100)) + (compute_coeff reward_params.issuance_ratio_final_max Q.zero) in return_unit in + return_unit +let test_compute_min_max () = + let open Delegate.Rewards.Internal_for_tests in + let open Lwt_result_wrap_syntax in + (* let assert_eq ~loc a b = Assert.equal ~loc Q.equal "" Q.pp_print a b in *) + let assert_eq_list ~loc a b = + Assert.assert_equal_list ~loc Q.equal "" Q.pp_print a b + in + let reward_params = + Default_parameters.constants_test.adaptive_issuance.adaptive_rewards_params + in + let update_reward_params ?issuance_ratio_final_min ?issuance_ratio_final_max + ?issuance_ratio_initial_min ?issuance_ratio_initial_max ?initial_period + ?transition_period + (reward_params : Constants.Parametric.adaptive_rewards_params) = + let issuance_ratio_final_min = + Option.value + ~default:reward_params.issuance_ratio_final_min + issuance_ratio_final_min + in + let issuance_ratio_final_max = + Option.value + ~default:reward_params.issuance_ratio_final_max + issuance_ratio_final_max + in + let issuance_ratio_initial_min = + Option.value + ~default:reward_params.issuance_ratio_initial_min + issuance_ratio_initial_min + in + let issuance_ratio_initial_max = + Option.value + ~default:reward_params.issuance_ratio_initial_max + issuance_ratio_initial_max + in + let initial_period = + Option.value ~default:reward_params.initial_period initial_period + in + let transition_period = + Option.value ~default:reward_params.transition_period transition_period + in + { + reward_params with + issuance_ratio_final_min; + issuance_ratio_final_max; + issuance_ratio_initial_min; + issuance_ratio_initial_max; + initial_period; + transition_period; + } + in + let compute_aux ~f ?issuance_ratio_final_min ?issuance_ratio_final_max + ?issuance_ratio_initial_min ?issuance_ratio_initial_max ?initial_period + ?transition_period ?(launch_cycle = Some 0l) cycle = + let launch_cycle = Option.map Cycle_repr.of_int32_exn launch_cycle in + let new_cycle = Cycle_repr.of_int32_exn (Int32.of_int cycle) in + let reward_params = + update_reward_params + ?issuance_ratio_final_min + ?issuance_ratio_final_max + ?issuance_ratio_initial_min + ?issuance_ratio_initial_max + ?initial_period + ?transition_period + reward_params + in + f ~reward_params ~launch_cycle ~new_cycle + in + let compute_min = compute_aux ~f:compute_min in + let compute_max = compute_aux ~f:compute_max in + let assert_eq_on_interval ~loc ~f ~from ~to_ expected = + assert (List.length expected = to_ - from + 1) ; + let actual = Stdlib.List.init (to_ - from + 1) (fun i -> f (i + from)) in + assert_eq_list ~loc expected actual + in + (* Python-style list generation *) + let ( *+ ) a b = Stdlib.List.init b (fun _ -> a) in + (* Test before launch cycle *) + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:(compute_min ~launch_cycle:(Some 10l)) + ~from:0 + ~to_:10 + (reward_params.issuance_ratio_initial_min *+ 11) + in + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:(compute_max ~launch_cycle:(Some 10l)) + ~from:0 + ~to_:10 + (reward_params.issuance_ratio_initial_max *+ 11) + in + (* Test no launch cycle *) + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:(compute_min ~launch_cycle:None) + ~from:0 + ~to_:10 + (reward_params.issuance_ratio_initial_min *+ 11) + in + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:(compute_max ~launch_cycle:None) + ~from:0 + ~to_:10 + (reward_params.issuance_ratio_initial_max *+ 11) + in + (* From now on, launch_cycle = 0 *) + (* Test initial period *) + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:compute_min + ~from:0 + ~to_:reward_params.initial_period + (reward_params.issuance_ratio_initial_min + *+ (reward_params.initial_period + 1)) + in + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:compute_max + ~from:0 + ~to_:reward_params.initial_period + (reward_params.issuance_ratio_initial_max + *+ (reward_params.initial_period + 1)) + in + (* Test final period *) + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:compute_min + ~from:(reward_params.initial_period + reward_params.transition_period + 1) + ~to_:(reward_params.initial_period + reward_params.transition_period + 10) + (reward_params.issuance_ratio_final_min *+ 10) + in + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:compute_max + ~from:(reward_params.initial_period + reward_params.transition_period + 1) + ~to_:(reward_params.initial_period + reward_params.transition_period + 10) + (reward_params.issuance_ratio_final_max *+ 10) + in + (* Test transition period *) + let* () = + let initial_period = 5 in + let transition_period = 5 in + let issuance_ratio_initial_min = Q.(7 // 100) in + let issuance_ratio_final_min = Q.(1 // 100) in + (* Min increases by 1/100th per cycle *) + let issuance_ratio_initial_max = Q.(1 // 10) in + let issuance_ratio_final_max = Q.(7 // 10) in + (* Max increases by 1/10th per cycle *) + let compute_min = + compute_min + ~initial_period + ~transition_period + ~issuance_ratio_initial_max + ~issuance_ratio_initial_min + ~issuance_ratio_final_max + ~issuance_ratio_final_min + in + let compute_max = + compute_max + ~initial_period + ~transition_period + ~issuance_ratio_initial_max + ~issuance_ratio_initial_min + ~issuance_ratio_final_max + ~issuance_ratio_final_min + in + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:compute_min + ~from:0 + ~to_:15 + ((issuance_ratio_initial_min *+ 6) + @ Q.[6 // 100; 5 // 100; 4 // 100; 3 // 100; 2 // 100] + @ (issuance_ratio_final_min *+ 5)) + in + let* () = + assert_eq_on_interval + ~loc:__LOC__ + ~f:compute_max + ~from:0 + ~to_:15 + ((issuance_ratio_initial_max *+ 6) + @ Q.[2 // 10; 3 // 10; 4 // 10; 5 // 10; 6 // 10] + @ (issuance_ratio_final_max *+ 5)) + in + return_unit + in return_unit let tests = @@ -399,6 +605,10 @@ let tests = "adaptive issuance - reward coeff computation" `Quick test_compute_coeff; + tztest + "adaptive issuance - min/max coeff computation" + `Quick + test_compute_min_max; ] let () = diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- misc_protocol.out index d55ecea3bf29777959fa22297a1611741c5ae919..7c82c383618adee01e60b251c5f8c6c5c5286fe1 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- misc_protocol.out @@ -63,9 +63,13 @@ "edge_of_staking_over_delegation": 2, "adaptive_issuance_launch_ema_threshold": 1600000000, "adaptive_rewards_params": - { "issuance_ratio_min": { "numerator": "1", "denominator": "2000" }, - "issuance_ratio_max": { "numerator": "1", "denominator": "20" }, - "max_bonus": "50000000000000", + { "issuance_ratio_final_min": { "numerator": "1", "denominator": "400" }, + "issuance_ratio_final_max": { "numerator": "1", "denominator": "10" }, + "issuance_ratio_initial_min": + { "numerator": "9", "denominator": "200" }, + "issuance_ratio_initial_max": + { "numerator": "11", "denominator": "200" }, "initial_period": 10, + "transition_period": 50, "max_bonus": "50000000000000", "growth_rate": { "numerator": "1", "denominator": "100" }, "center_dz": { "numerator": "1", "denominator": "2" }, "radius_dz": { "numerator": "1", "denominator": "50" } }, diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- misc_protocol.out index 08e4088fc65097d633f47731516b3eb8e557a479..456ddf0b760ba54c8c190e05708c6c791e83fa3e 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- misc_protocol.out @@ -63,9 +63,13 @@ "edge_of_staking_over_delegation": 2, "adaptive_issuance_launch_ema_threshold": 1600000000, "adaptive_rewards_params": - { "issuance_ratio_min": { "numerator": "1", "denominator": "2000" }, - "issuance_ratio_max": { "numerator": "1", "denominator": "20" }, - "max_bonus": "50000000000000", + { "issuance_ratio_final_min": { "numerator": "1", "denominator": "400" }, + "issuance_ratio_final_max": { "numerator": "1", "denominator": "10" }, + "issuance_ratio_initial_min": + { "numerator": "9", "denominator": "200" }, + "issuance_ratio_initial_max": + { "numerator": "11", "denominator": "200" }, "initial_period": 10, + "transition_period": 50, "max_bonus": "50000000000000", "growth_rate": { "numerator": "1", "denominator": "100" }, "center_dz": { "numerator": "1", "denominator": "2" }, "radius_dz": { "numerator": "1", "denominator": "50" } }, diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- misc_protocol.out index 2d256be68aa0ca86f81ccd6ba89dd2385f7f5ca1..75146fa3223a7ead5b0877d23aaebf2df130e630 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- misc_protocol.out @@ -63,9 +63,13 @@ "edge_of_staking_over_delegation": 2, "adaptive_issuance_launch_ema_threshold": 1600000000, "adaptive_rewards_params": - { "issuance_ratio_min": { "numerator": "1", "denominator": "2000" }, - "issuance_ratio_max": { "numerator": "1", "denominator": "20" }, - "max_bonus": "50000000000000", + { "issuance_ratio_final_min": { "numerator": "1", "denominator": "400" }, + "issuance_ratio_final_max": { "numerator": "1", "denominator": "10" }, + "issuance_ratio_initial_min": + { "numerator": "9", "denominator": "200" }, + "issuance_ratio_initial_max": + { "numerator": "11", "denominator": "200" }, "initial_period": 10, + "transition_period": 50, "max_bonus": "50000000000000", "growth_rate": { "numerator": "1", "denominator": "100" }, "center_dz": { "numerator": "1", "denominator": "2" }, "radius_dz": { "numerator": "1", "denominator": "50" } }, diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out index da9e47d1ee684cc4f019c542a50981eb52435ec5..3ee7bcdc91448df36d03dbdec2286498d08125e0 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out @@ -63,9 +63,13 @@ "edge_of_staking_over_delegation": 2, "adaptive_issuance_launch_ema_threshold": 1600000000, "adaptive_rewards_params": - { "issuance_ratio_min": { "numerator": "1", "denominator": "2000" }, - "issuance_ratio_max": { "numerator": "1", "denominator": "20" }, - "max_bonus": "50000000000000", + { "issuance_ratio_final_min": { "numerator": "1", "denominator": "400" }, + "issuance_ratio_final_max": { "numerator": "1", "denominator": "10" }, + "issuance_ratio_initial_min": + { "numerator": "9", "denominator": "200" }, + "issuance_ratio_initial_max": + { "numerator": "11", "denominator": "200" }, "initial_period": 10, + "transition_period": 50, "max_bonus": "50000000000000", "growth_rate": { "numerator": "1", "denominator": "100" }, "center_dz": { "numerator": "1", "denominator": "2" }, "radius_dz": { "numerator": "1", "denominator": "50" } }, diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out index da9e47d1ee684cc4f019c542a50981eb52435ec5..3ee7bcdc91448df36d03dbdec2286498d08125e0 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out @@ -63,9 +63,13 @@ "edge_of_staking_over_delegation": 2, "adaptive_issuance_launch_ema_threshold": 1600000000, "adaptive_rewards_params": - { "issuance_ratio_min": { "numerator": "1", "denominator": "2000" }, - "issuance_ratio_max": { "numerator": "1", "denominator": "20" }, - "max_bonus": "50000000000000", + { "issuance_ratio_final_min": { "numerator": "1", "denominator": "400" }, + "issuance_ratio_final_max": { "numerator": "1", "denominator": "10" }, + "issuance_ratio_initial_min": + { "numerator": "9", "denominator": "200" }, + "issuance_ratio_initial_max": + { "numerator": "11", "denominator": "200" }, "initial_period": 10, + "transition_period": 50, "max_bonus": "50000000000000", "growth_rate": { "numerator": "1", "denominator": "100" }, "center_dz": { "numerator": "1", "denominator": "2" }, "radius_dz": { "numerator": "1", "denominator": "50" } }, diff --git a/tezt/tests/mockup.ml b/tezt/tests/mockup.ml index 1f2012ecd6b5c2fa5150061fdb9ed50810cb00db..bf55728d07bc15207a8b791c38a0fa07a0a38e64 100644 --- a/tezt/tests/mockup.ml +++ b/tezt/tests/mockup.ml @@ -1217,13 +1217,58 @@ let test_create_mockup_config_show_init_roundtrip protocols = ("chain_id", `String "NetXaFDF7xZQCpR"); ] in + (* Since adaptive rewards use [Q.t], the numerators and denominators should be co-primes. *) + let co_primed_adaptive_rewards : JSON.t = + let adaptive_rewards_succ = + JSON.(parametric_constants_succ |-> "adaptive_rewards_params") + in + if JSON.is_null adaptive_rewards_succ then + JSON.annotate ~origin:"no_adaptive_rewards" `Null + else + let simplify_field obj = + match JSON.as_object_opt obj with + | Some [("numerator", numerator); ("denominator", denominator)] -> + let numerator = JSON.as_int numerator in + let denominator = JSON.as_int denominator in + let Q.{num; den} = Q.(numerator // denominator) in + JSON.annotate ~origin:"simplify_field" + @@ `O + [ + ("numerator", `String (Z.to_int num |> string_of_int)); + ("denominator", `String (Z.to_int den |> string_of_int)); + ] + | _ -> obj + in + let all_fields = JSON.as_object adaptive_rewards_succ in + let co_primed_adaptive_rewards_params = + JSON.annotate ~origin:"new_adaptive_rewards_params" + @@ `O + (List.map + (fun (field_name, obj) -> + (field_name, JSON.unannotate (simplify_field obj))) + all_fields) + in + let new_adaptive_rewards_params = + JSON.merge_objects + adaptive_rewards_succ + co_primed_adaptive_rewards_params + in + JSON.annotate ~origin:"co_primed_adaptive_rewards" + @@ `O + [ + ( "adaptive_rewards_params", + JSON.unannotate new_adaptive_rewards_params ); + ] + in return JSON.( merge_objects (merge_objects - (merge_objects parametric_constants_succ updated_dal_parametric) - constant_parametric_constants) - mockup_constants) + (merge_objects + (merge_objects parametric_constants_succ updated_dal_parametric) + constant_parametric_constants) + mockup_constants) + co_primed_adaptive_rewards) in let get_state_using_config_show_mockup ~protocol mockup_client =