diff --git a/src/proto_alpha/lib_plugin/RPC.ml b/src/proto_alpha/lib_plugin/RPC.ml index e2973a4dbc7065d57ff7ff915f41f083957d6a46..0995f5a7a7196ccb32839c15ca2522473c2eb0a4 100644 --- a/src/proto_alpha/lib_plugin/RPC.ml +++ b/src/proto_alpha/lib_plugin/RPC.ml @@ -981,8 +981,10 @@ module Scripts = struct mode = application_mode; op_count = 0; migration_balance_updates = []; - liquidity_baking_toggle_ema = Toggle_EMA.zero; - adaptive_inflation_toggle_ema = Toggle_EMA.zero; + liquidity_baking_toggle_ema = + Toggle_votes.Liquidity_baking_toggle_EMA.zero; + adaptive_inflation_toggle_ema = + Toggle_votes.Adaptive_inflation_launch_EMA.zero; implicit_operations_results = []; } in diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 9e7ca8685b32214be33918ef3726e0931d889ddc..60f475e1bb24c0ec7d05915306753588021eb7f4 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -4696,13 +4696,23 @@ end (** This module re-exports definitions from {!Toggle_EMA} *) module Toggle_EMA : sig - type t + module type T = sig + type t - val zero : t + val of_int64 : Int64.t -> t tzresult Lwt.t - val to_int64 : t -> Int64.t + val zero : t - val encoding : t Data_encoding.t + val to_int64 : t -> Int64.t + + val encoding : t Data_encoding.t + + val ( < ) : t -> Int64.t -> bool + + val update_ema_up : t -> t + + val update_ema_down : t -> t + end end (** This module re-exports definitions from {!Toggle_votes_repr}. *) @@ -4723,7 +4733,19 @@ module Toggle_votes : sig val toggle_votes_encoding : toggle_votes Data_encoding.encoding - val compute_new_ema : toggle_vote:toggle_vote -> Toggle_EMA.t -> Toggle_EMA.t + module Liquidity_baking_toggle_EMA : Toggle_EMA.T + + module Adaptive_inflation_launch_EMA : Toggle_EMA.T + + val compute_new_liquidity_baking_ema : + toggle_vote:toggle_vote -> + Liquidity_baking_toggle_EMA.t -> + Liquidity_baking_toggle_EMA.t + + val compute_new_adaptive_inflation_ema : + toggle_vote:toggle_vote -> + Adaptive_inflation_launch_EMA.t -> + Adaptive_inflation_launch_EMA.t end (** This module re-exports definitions from {!Liquidity_baking_storage}. *) @@ -4734,7 +4756,8 @@ module Liquidity_baking : sig context -> toggle_vote:Toggle_votes.toggle_vote -> (context -> Contract_hash.t -> (context * 'a list) tzresult Lwt.t) -> - (context * 'a list * Toggle_EMA.t) tzresult Lwt.t + (context * 'a list * Toggle_votes.Liquidity_baking_toggle_EMA.t) tzresult + Lwt.t end (** This module re-exports definitions from {!Ticket_storage}. *) diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index a623e7956d67cddc1e821786b33d7feffd0991f1..c0390ff3289d4ed396a0702743b87db1b4c69051 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -1791,8 +1791,8 @@ type application_state = { mode : mode; op_count : int; migration_balance_updates : Receipt.balance_updates; - liquidity_baking_toggle_ema : Toggle_EMA.t; - adaptive_inflation_toggle_ema : Toggle_EMA.t; + liquidity_baking_toggle_ema : Toggle_votes.Liquidity_baking_toggle_EMA.t; + adaptive_inflation_toggle_ema : Toggle_votes.Adaptive_inflation_launch_EMA.t; implicit_operations_results : Apply_results.packed_successful_manager_operation_result list; } @@ -2388,7 +2388,8 @@ let begin_application ctxt chain_id ~migration_balance_updates op_count = 0; migration_balance_updates; liquidity_baking_toggle_ema; - adaptive_inflation_toggle_ema = Toggle_EMA.zero; + adaptive_inflation_toggle_ema = + Toggle_votes.Adaptive_inflation_launch_EMA.zero; implicit_operations_results = Apply_results.pack_migration_operation_results migration_operation_results @@ -2447,7 +2448,8 @@ let begin_full_construction ctxt chain_id ~migration_balance_updates op_count = 0; migration_balance_updates; liquidity_baking_toggle_ema; - adaptive_inflation_toggle_ema = Toggle_EMA.zero; + adaptive_inflation_toggle_ema = + Toggle_votes.Adaptive_inflation_launch_EMA.zero; implicit_operations_results = Apply_results.pack_migration_operation_results migration_operation_results @@ -2480,7 +2482,8 @@ let begin_partial_construction ctxt chain_id ~migration_balance_updates op_count = 0; migration_balance_updates; liquidity_baking_toggle_ema; - adaptive_inflation_toggle_ema = Toggle_EMA.zero; + adaptive_inflation_toggle_ema = + Toggle_votes.Adaptive_inflation_launch_EMA.zero; implicit_operations_results = Apply_results.pack_migration_operation_results migration_operation_results diff --git a/src/proto_alpha/lib_protocol/apply.mli b/src/proto_alpha/lib_protocol/apply.mli index 9f1d0de95119c4107f48315153bb15fb375e15a8..87be46e13b56c0816bc5684d9b61f497752df619 100644 --- a/src/proto_alpha/lib_protocol/apply.mli +++ b/src/proto_alpha/lib_protocol/apply.mli @@ -68,8 +68,8 @@ type application_state = { mode : mode; op_count : int; migration_balance_updates : Receipt.balance_updates; - liquidity_baking_toggle_ema : Toggle_EMA.t; - adaptive_inflation_toggle_ema : Toggle_EMA.t; + liquidity_baking_toggle_ema : Toggle_votes.Liquidity_baking_toggle_EMA.t; + adaptive_inflation_toggle_ema : Toggle_votes.Adaptive_inflation_launch_EMA.t; implicit_operations_results : Apply_results.packed_successful_manager_operation_result list; } diff --git a/src/proto_alpha/lib_protocol/apply_results.ml b/src/proto_alpha/lib_protocol/apply_results.ml index fb241a8974d88f923668df4f8418f6795e7b640c..83f991b2144055f261b2ce9b48689f5555175c7a 100644 --- a/src/proto_alpha/lib_protocol/apply_results.ml +++ b/src/proto_alpha/lib_protocol/apply_results.ml @@ -2654,8 +2654,8 @@ type block_metadata = { consumed_gas : Gas.Arith.fp; deactivated : Signature.Public_key_hash.t list; balance_updates : Receipt.balance_updates; - liquidity_baking_toggle_ema : Toggle_EMA.t; - adaptive_inflation_toggle_ema : Toggle_EMA.t; + liquidity_baking_toggle_ema : Toggle_votes.Liquidity_baking_toggle_EMA.t; + adaptive_inflation_toggle_ema : Toggle_votes.Adaptive_inflation_launch_EMA.t; implicit_operations_results : packed_successful_manager_operation_result list; dal_attestation : Dal.Attestation.t option; } @@ -2728,8 +2728,12 @@ let block_metadata_encoding = (req "nonce_hash" (option Nonce_hash.encoding)) (req "deactivated" (list Signature.Public_key_hash.encoding)) (dft "balance_updates" Receipt.balance_updates_encoding []) - (req "liquidity_baking_toggle_ema" Toggle_EMA.encoding) - (req "adaptive_inflation_toggle_ema" Toggle_EMA.encoding) + (req + "liquidity_baking_toggle_ema" + Toggle_votes.Liquidity_baking_toggle_EMA.encoding) + (req + "adaptive_inflation_toggle_ema" + Toggle_votes.Adaptive_inflation_launch_EMA.encoding) (req "implicit_operations_results" (list successful_manager_operation_result_encoding))) diff --git a/src/proto_alpha/lib_protocol/apply_results.mli b/src/proto_alpha/lib_protocol/apply_results.mli index 1bb5f87538664e9d101375a104e6e81658cfbd6b..1af423f19472b3687f42ee9674d8887866994a79 100644 --- a/src/proto_alpha/lib_protocol/apply_results.mli +++ b/src/proto_alpha/lib_protocol/apply_results.mli @@ -342,8 +342,8 @@ type block_metadata = { consumed_gas : Gas.Arith.fp; deactivated : Signature.Public_key_hash.t list; balance_updates : Receipt.balance_updates; - liquidity_baking_toggle_ema : Toggle_EMA.t; - adaptive_inflation_toggle_ema : Toggle_EMA.t; + liquidity_baking_toggle_ema : Toggle_votes.Liquidity_baking_toggle_EMA.t; + adaptive_inflation_toggle_ema : Toggle_votes.Adaptive_inflation_launch_EMA.t; implicit_operations_results : packed_successful_manager_operation_result list; dal_attestation : Dal.Attestation.t option; } diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml b/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml index 2c416fd82f8b4728a988dd9145fc817bbe896f88..c6e87ab09e765df1d2586c107a2700c07ec495a1 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml +++ b/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml @@ -30,7 +30,7 @@ let get_cpmm_address = Storage.Liquidity_baking.Cpmm_address.get let get_toggle_ema ctxt = Storage.Liquidity_baking.Toggle_ema.get ctxt >>=? fun ema -> - Toggle_EMA.of_int64 ema + Liquidity_baking_toggle_EMA.of_int64 ema let on_cpmm_exists ctxt f = get_cpmm_address ctxt >>=? fun cpmm_contract -> @@ -43,12 +43,14 @@ let on_cpmm_exists ctxt f = let update_toggle_ema ctxt ~toggle_vote = get_toggle_ema ctxt >>=? fun old_ema -> - let new_ema = compute_new_ema ~toggle_vote old_ema in - Storage.Liquidity_baking.Toggle_ema.update ctxt (Toggle_EMA.to_int64 new_ema) + let new_ema = compute_new_liquidity_baking_ema ~toggle_vote old_ema in + Storage.Liquidity_baking.Toggle_ema.update + ctxt + (Liquidity_baking_toggle_EMA.to_int64 new_ema) >|=? fun ctxt -> (ctxt, new_ema) let check_ema_below_threshold ctxt ema = - Toggle_EMA.( + Liquidity_baking_toggle_EMA.( ema < Constants_storage.liquidity_baking_toggle_ema_threshold ctxt) let on_subsidy_allowed ctxt ~toggle_vote f = diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli b/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli index 9d83c3cc96893e7b6351fc23043216e8708acfb9..97db7278af4c0ab055f6aeccf4ae93ae6e68630f 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli +++ b/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli @@ -40,4 +40,6 @@ val on_subsidy_allowed : Raw_context.t -> toggle_vote:Toggle_votes_repr.toggle_vote -> (Raw_context.t -> Contract_hash.t -> (Raw_context.t * 'a list) tzresult Lwt.t) -> - (Raw_context.t * 'a list * Toggle_EMA.t) tzresult Lwt.t + (Raw_context.t * 'a list * Toggle_votes_repr.Liquidity_baking_toggle_EMA.t) + tzresult + Lwt.t diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.ml b/src/proto_alpha/lib_protocol/test/helpers/block.ml index 1835f0baa7492f6f1c68b038709f3e911f591006..b023aac8bd406f6a17b50bb46fc104a1576e51b7 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml @@ -996,7 +996,7 @@ let bake_n_with_origination_results ?(baking_mode = Application) ?policy n b = let bake_n_with_liquidity_baking_toggle_ema ?(baking_mode = Application) ?policy ?liquidity_baking_toggle_vote ?adaptive_inflation_vote n b = - let initial_ema = Toggle_EMA.zero in + let initial_ema = Toggle_votes.Liquidity_baking_toggle_EMA.zero in List.fold_left_es (fun (b, _toggle_ema) _ -> bake_with_metadata diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.mli b/src/proto_alpha/lib_protocol/test/helpers/block.mli index 390ef1170f099f683789cc849a059838a3c7b48e..312845c83e81c2364a612451a712ac2b94e396a2 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/block.mli @@ -269,7 +269,8 @@ val bake_n_with_liquidity_baking_toggle_ema : ?adaptive_inflation_vote:Toggle_votes.toggle_vote -> int -> t -> - (block * Alpha_context.Toggle_EMA.t) tzresult Lwt.t + (block * Alpha_context.Toggle_votes.Liquidity_baking_toggle_EMA.t) tzresult + Lwt.t val current_cycle : t -> Cycle.t tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml b/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml index 1c51c7e0c3257d19fb6adb3142226df8adef274b..190d73665fe6ab649ee5ab0113632b83cc05f0da 100644 --- a/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml +++ b/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml @@ -257,7 +257,9 @@ let liquidity_baking_toggle_ema n_vote_on n_vote_off level bake_after >>=? fun (_blk, toggle_ema) -> Assert.leq_int ~loc:__LOC__ - (toggle_ema |> Alpha_context.Toggle_EMA.to_int64 |> Int64.to_int) + (toggle_ema + |> Alpha_context.Toggle_votes.Liquidity_baking_toggle_EMA.to_int64 + |> Int64.to_int) expected_toggle_ema >>=? fun () -> return_unit diff --git a/src/proto_alpha/lib_protocol/test/unit/test_liquidity_baking_repr.ml b/src/proto_alpha/lib_protocol/test/unit/test_liquidity_baking_repr.ml index e3eee00daa1a2bb2fd724c789f72f00920ad9620..388873529b049f52fca8906a6db036e6b7c91cd1 100644 --- a/src/proto_alpha/lib_protocol/test/unit/test_liquidity_baking_repr.ml +++ b/src/proto_alpha/lib_protocol/test/unit/test_liquidity_baking_repr.ml @@ -32,18 +32,21 @@ *) open Protocol +module Toggle_EMA = Toggle_votes_repr.Liquidity_baking_toggle_EMA let ema_of_int64 ema = Toggle_EMA.of_int64 ema >|= Environment.wrap_tzresult let ema_to_int64 = Toggle_EMA.to_int64 let compute_new_ema ~toggle_vote ema = - Toggle_votes_repr.compute_new_ema ~toggle_vote ema |> ema_to_int64 + Toggle_votes_repr.compute_new_liquidity_baking_ema ~toggle_vote ema + |> ema_to_int64 (* Folds compute_new_ema on a list of votes *) let compute_new_ema_n toggle_votes initial_ema = List.fold_left - (fun ema toggle_vote -> Toggle_votes_repr.compute_new_ema ~toggle_vote ema) + (fun ema toggle_vote -> + Toggle_votes_repr.compute_new_liquidity_baking_ema ~toggle_vote ema) initial_ema toggle_votes |> ema_to_int64 diff --git a/src/proto_alpha/lib_protocol/toggle_EMA.ml b/src/proto_alpha/lib_protocol/toggle_EMA.ml index 86ff588368eda6fed6f61fad72418a7b379e85b7..99f0b01b4d02701a34af7af984c8e8b0dcbb9cde 100644 --- a/src/proto_alpha/lib_protocol/toggle_EMA.ml +++ b/src/proto_alpha/lib_protocol/toggle_EMA.ml @@ -24,57 +24,123 @@ (* *) (*****************************************************************************) -(** Exponential moving average of toggle votes. Represented as an int64 between - 0 and 2,000,000,000. It is an exponential moving average of the "off" votes - over a window of the most recent 2000 blocks that did not vote "pass". *) +(** Block headers contain some fields whose values represent the block + producer's opinion on some topics. The votes are averaged to get an + estimation of the will of the stake-weighted majority of bakers on + these topics. The protocol can then perform automatic actions + depending on the values of these averages; typically activating or + deactivating some features. -(* The exponential moving average is represented as an Int64 between 0L and 2_000_000_000L *) -type t = Int64.t (* Invariant 0 <= ema <= 2_000_000_000L *) + This module is about the computation of these averages. -(* This error is not registered because we don't expect it to be - raised. *) -type error += Toggle_ema_out_of_bound of Int64.t + We use exponential moving averages (EMA for short) because they can + easily and efficiently be implemented because a single value needs to + be stored in the context for each average. Each EMA is updated once per + block and stored in the context. It is represented using a 64-bit + signed integer but it can only take non-negative values in a range + of the form 0...ema_max where the constant ema_max, the maximum + value of the EMA, is a parameter of this module. To update an EMA, + we multiply the EMA computed in the previous block by a constant + factor slightly less than 1 called the attenuation factor, and then + we either add or remove (depending on the vote that was casted in + the block header) another constant called the baker's contribution + to the EMA. The baker contribution is also a parameter of this + module. When multiplying by the attenuation factor, we round toward + the middle of the 0...ema_max range. The update formula is thus: -let check_bounds x = Compare.Int64.(0L <= x && x <= 2_000_000_000L) + new_ema = ((old_ema - ema_max/2) * attenuation_factor) +- baker_contribution + ema_max/2 -let of_int64 (x : Int64.t) : t tzresult Lwt.t = - if check_bounds x then return x else tzfail @@ Toggle_ema_out_of_bound x +*) -let zero : t = Int64.zero +module type EMA_PARAMETERS = sig + val baker_contribution : Z.t -(* The conv_with_guard combinator of Data_encoding expects a (_, string) result. *) -let of_int64_for_encoding x = - if check_bounds x then Ok x else Error "out of bounds" + val ema_max : Int64.t -let to_int64 (ema : t) : Int64.t = ema + (* We don't need to parameterize by the attenuation factor because + it can be computed from the two other parameters with the + following formula: -(* We perform the computations in Z to avoid overflows. *) + attenuation_factor = (ema_max - 2 baker_contribution) / ema_max + *) +end -let z_1999 : Z.t = Z.of_int 1999 +module type T = sig + type t -let z_2000 : Z.t = Z.of_int 2000 + val of_int64 : Int64.t -> t tzresult Lwt.t -let attenuate z = Z.(div (mul z_1999 z) z_2000) + val zero : t -let z_1_000_000_000 = Z.of_int 1_000_000_000 + val to_int64 : t -> Int64.t -(* Outside of this module, the EMA is always between 0 and 2,000,000,000. - This [recenter] wrappers, puts it in between -1,000,000,000 and 1,000,000,000. - The goal of this recentering around zero is to make [update_ema_off] and - [update_ema_on] behave symmetrically with respect to rounding. *) -let recenter f ema = Z.(add z_1_000_000_000 (f (sub ema z_1_000_000_000))) + val encoding : t Data_encoding.t -let z_500_000 = Z.of_int 500_000 + val ( < ) : t -> Int64.t -> bool -let update_ema_off (ema : t) : t = - let ema = Z.of_int64 ema in - recenter (fun ema -> Z.add (attenuate ema) z_500_000) ema |> Z.to_int64 + val update_ema_up : t -> t -let update_ema_on (ema : t) : t = - let ema = Z.of_int64 ema in - recenter (fun ema -> Z.sub (attenuate ema) z_500_000) ema |> Z.to_int64 + val update_ema_down : t -> t +end -let ( < ) : t -> Int64.t -> bool = Compare.Int64.( < ) +module Make (EMA_parameters : EMA_PARAMETERS) : T = struct + type t = Int64.t + (* Invariant 0L <= ema <= EMA_Parameters.ema_max *) -let encoding : t Data_encoding.t = - Data_encoding.(conv_with_guard to_int64 of_int64_for_encoding int64) + (* This error is not registered because we don't expect it to be + raised. *) + type error += Toggle_ema_out_of_bound of Int64.t + + let check_bounds x = Compare.Int64.(0L <= x && x <= EMA_parameters.ema_max) + + let of_int64 (x : Int64.t) : t tzresult Lwt.t = + if check_bounds x then return x else tzfail @@ Toggle_ema_out_of_bound x + + let zero : t = Int64.zero + + (* The conv_with_guard combinator of Data_encoding expects a (_, string) result. *) + let of_int64_for_encoding x = + if check_bounds x then Ok x else Error "out of bounds" + + let to_int64 (ema : t) : Int64.t = ema + + (* We perform the computations in Z to avoid overflows. *) + + let ema_max_z = Z.of_int64 EMA_parameters.ema_max + + let attenuation_numerator = + Z.(sub ema_max_z (mul (of_int 2) EMA_parameters.baker_contribution)) + + let attenuation_denominator = ema_max_z + + let attenuate z = + Z.(div (mul attenuation_numerator z) attenuation_denominator) + + let half_ema_max_z = Z.(div ema_max_z (of_int 2)) + + (* Outside of this module, the EMA is always between 0L and ema_max. + This [recenter] wrappers, puts it in between -ema_max/2 and + ema_max/2. The goal of this recentering around zero is to make + [update_ema_off] and [update_ema_on] behave symmetrically with + respect to rounding. *) + let recenter f ema = Z.(add half_ema_max_z (f (sub ema half_ema_max_z))) + + let update_ema_up (ema : t) : t = + let ema = Z.of_int64 ema in + recenter + (fun ema -> Z.add (attenuate ema) EMA_parameters.baker_contribution) + ema + |> Z.to_int64 + + let update_ema_down (ema : t) : t = + let ema = Z.of_int64 ema in + recenter + (fun ema -> Z.sub (attenuate ema) EMA_parameters.baker_contribution) + ema + |> Z.to_int64 + + let ( < ) : t -> Int64.t -> bool = Compare.Int64.( < ) + + let encoding : t Data_encoding.t = + Data_encoding.(conv_with_guard to_int64 of_int64_for_encoding int64) +end diff --git a/src/proto_alpha/lib_protocol/toggle_EMA.mli b/src/proto_alpha/lib_protocol/toggle_EMA.mli index bc1a56679c2c7a81ee6cc495cbf55f76b25b92c8..86c39893ed32fb20437a166cb94fd80cd3a1e744 100644 --- a/src/proto_alpha/lib_protocol/toggle_EMA.mli +++ b/src/proto_alpha/lib_protocol/toggle_EMA.mli @@ -24,22 +24,33 @@ (* *) (*****************************************************************************) -(** Exponential moving average of toggle votes. Represented as an int64 between - 0 and 2,000,000,000. It is an exponential moving average of the "off" votes - over a window of the most recent 2000 blocks that did not vote "pass". *) +module type EMA_PARAMETERS = sig + (* This represents the impact on the EMA of a single block + vote. Between voting On and voting Off, the impact on the EMA is + twice this number. *) + val baker_contribution : Z.t -type t + (* This is the maximum value that the EMA can take. The minimal + value cannot be set, it is 0L. *) + val ema_max : Int64.t +end -val of_int64 : Int64.t -> t tzresult Lwt.t +module type T = sig + type t -val zero : t + val of_int64 : Int64.t -> t tzresult Lwt.t -val to_int64 : t -> Int64.t + val zero : t -val encoding : t Data_encoding.t + val to_int64 : t -> Int64.t -val ( < ) : t -> Int64.t -> bool + val encoding : t Data_encoding.t -val update_ema_off : t -> t + val ( < ) : t -> Int64.t -> bool -val update_ema_on : t -> t + val update_ema_up : t -> t + + val update_ema_down : t -> t +end + +module Make (_ : EMA_PARAMETERS) : T diff --git a/src/proto_alpha/lib_protocol/toggle_votes_repr.ml b/src/proto_alpha/lib_protocol/toggle_votes_repr.ml index 7425ed029b22d7ff159858ad47a6dadffa694242..5a3c9f29ab46d59af59ad769a6c3714b4a27f45e 100644 --- a/src/proto_alpha/lib_protocol/toggle_votes_repr.ml +++ b/src/proto_alpha/lib_protocol/toggle_votes_repr.ml @@ -87,9 +87,26 @@ let toggle_votes_encoding = "toggle_votes" (Compact.make ~tag_size:`Uint8 toggle_votes_compact_encoding) -(* Invariant: 0 <= ema <= 2_000_000 *) -let compute_new_ema ~toggle_vote ema = +module Liquidity_baking_toggle_EMA = Toggle_EMA.Make (struct + let baker_contribution = Z.of_int 500_000 + + let ema_max = 2_000_000_000L +end) + +module Adaptive_inflation_launch_EMA = Toggle_EMA.Make (struct + let baker_contribution = Z.of_int 500_000 + + let ema_max = 2_000_000_000L +end) + +let compute_new_liquidity_baking_ema ~toggle_vote ema = + match toggle_vote with + | Toggle_vote_pass -> ema + | Toggle_vote_off -> Liquidity_baking_toggle_EMA.update_ema_up ema + | Toggle_vote_on -> Liquidity_baking_toggle_EMA.update_ema_down ema + +let compute_new_adaptive_inflation_ema ~toggle_vote ema = match toggle_vote with | Toggle_vote_pass -> ema - | Toggle_vote_off -> Toggle_EMA.update_ema_off ema - | Toggle_vote_on -> Toggle_EMA.update_ema_on ema + | Toggle_vote_off -> Adaptive_inflation_launch_EMA.update_ema_down ema + | Toggle_vote_on -> Adaptive_inflation_launch_EMA.update_ema_up ema diff --git a/src/proto_alpha/lib_protocol/toggle_votes_repr.mli b/src/proto_alpha/lib_protocol/toggle_votes_repr.mli index 25aed7e9b4d0f0c82982c3f2b50f70b794bbcb28..adef7e167b5368887acf35240b1d77a7612f5c7b 100644 --- a/src/proto_alpha/lib_protocol/toggle_votes_repr.mli +++ b/src/proto_alpha/lib_protocol/toggle_votes_repr.mli @@ -39,10 +39,16 @@ val adaptive_inflation_vote_encoding : toggle_vote Data_encoding.encoding val toggle_votes_encoding : toggle_votes Data_encoding.encoding -(** [compute_new_ema ~toggle_vote old_ema] returns the value [new_ema] of the - exponential moving average [old_ema] updated by the vote [toggle_vote]. +module Liquidity_baking_toggle_EMA : Toggle_EMA.T - It is updated as follows: +module Adaptive_inflation_launch_EMA : Toggle_EMA.T + +(** [compute_new_liquidity_baking_ema ~toggle_vote old_ema] returns the value + [new_ema] of the exponential moving average [old_ema] updated by the vote + [toggle_vote] interpreted as a vote to deactivate the liquidity baking + feature (Off increases the EMA). + + The EMA is updated as follows: - if [toggle_vote] is [Toggle_vote_pass] then [new_ema] = [old_ema], - if [toggle_vote] is [Toggle_vote_off], then [new_ema] = (1999 * ema[n] // 2000) + 1,000,000, - if [toggle_vote] is [Toggle_vote_on], then [new_ema] = (1999 * ema[n] // 2000). @@ -50,4 +56,25 @@ val toggle_votes_encoding : toggle_votes Data_encoding.encoding The multiplication is performed in [Z.t] to avoid overflows, division is rounded toward 1,000,000,000 (the middle of the interval). *) -val compute_new_ema : toggle_vote:toggle_vote -> Toggle_EMA.t -> Toggle_EMA.t +val compute_new_liquidity_baking_ema : + toggle_vote:toggle_vote -> + Liquidity_baking_toggle_EMA.t -> + Liquidity_baking_toggle_EMA.t + +(** [compute_new_adaptive_inflation_ema ~toggle_vote old_ema] returns the value + [new_ema] of the exponential moving average [old_ema] updated by the vote + [toggle_vote] interpreted as a vote to activate the adaptive inflation + feature (Off decreases the EMA). + + The EMA is updated as follows: + - if [toggle_vote] is [Toggle_vote_pass] then [new_ema] = [old_ema], + - if [toggle_vote] is [Toggle_vote_off], then [new_ema] = (1999 * ema[n] // 2000), + - if [toggle_vote] is [Toggle_vote_on], then [new_ema] = (1999 * ema[n] // 2000) + 1,000,000. + + The multiplication is performed in [Z.t] to avoid overflows, division is + rounded toward 1,000,000,000 (the middle of the interval). + *) +val compute_new_adaptive_inflation_ema : + toggle_vote:toggle_vote -> + Adaptive_inflation_launch_EMA.t -> + Adaptive_inflation_launch_EMA.t