From ca8fcd01eb55824accc4494b3c45579ba4d65600 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Thu, 8 Jun 2023 14:13:42 +0200 Subject: [PATCH 1/3] Proto: expose get_reward_coeff --- .../lib_protocol/adaptive_inflation_storage.ml | 4 ++++ .../lib_protocol/adaptive_inflation_storage.mli | 13 +++++++++++++ src/proto_alpha/lib_protocol/alpha_context.ml | 6 +++++- src/proto_alpha/lib_protocol/alpha_context.mli | 13 +++++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/proto_alpha/lib_protocol/adaptive_inflation_storage.ml b/src/proto_alpha/lib_protocol/adaptive_inflation_storage.ml index a72ad9b43ddc..25682b3f9b89 100644 --- a/src/proto_alpha/lib_protocol/adaptive_inflation_storage.ml +++ b/src/proto_alpha/lib_protocol/adaptive_inflation_storage.ml @@ -204,3 +204,7 @@ let load_reward_coeff ctxt = let init_ema ctxt = Storage.Adaptive_inflation.Launch_ema.init ctxt 0L let activate ctxt ~cycle = Storage.Adaptive_inflation.Activation.init ctxt cycle + +module For_RPC = struct + let get_reward_coeff = get_reward_coeff +end diff --git a/src/proto_alpha/lib_protocol/adaptive_inflation_storage.mli b/src/proto_alpha/lib_protocol/adaptive_inflation_storage.mli index 898da8efcd34..f49be6ce69b2 100644 --- a/src/proto_alpha/lib_protocol/adaptive_inflation_storage.mli +++ b/src/proto_alpha/lib_protocol/adaptive_inflation_storage.mli @@ -54,3 +54,16 @@ val init_ema : Raw_context.t -> Raw_context.t tzresult Lwt.t voted to be activated (yet). *) val activate : Raw_context.t -> cycle:Cycle_repr.t -> Raw_context.t tzresult Lwt.t + +module For_RPC : sig + (** [get_reward_coeff ctxt cycle] reads the reward coeff for the given cycle + from the storage. + Returns [Q.one] if the given cycle is not between [current_cycle] and + [current_cycle + preserved_cycles]. + If adaptive inflation has not been activated, or has been activated and the + given cycle is less than [preserved_cycles] after the activation cycle, + then this function returns [Q.one]. + Used only for RPCs. To get the actual rewards, use [Delegate_rewards]. *) + val get_reward_coeff : + Raw_context.t -> cycle:Cycle_repr.t -> Q.t tzresult Lwt.t +end diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index 8559ab1bb052..04b75aef3703 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -499,7 +499,11 @@ module Delegate = struct let deactivated = Delegate_activation_storage.is_inactive module Consensus_key = Delegate_consensus_key - module Rewards = Delegate_rewards + + module Rewards = struct + include Delegate_rewards + module For_RPC = Adaptive_inflation_storage.For_RPC + end end module Stake_distribution = struct diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 60f475e1bb24..b8e035e4db64 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2249,6 +2249,19 @@ module Delegate : sig val reward_from_constants : ?coeff:Q.t -> Constants.Parametric.t -> reward_kind:reward_kind -> Tez.t end + + module For_RPC : sig + (** [get_reward_coeff ctxt cycle] reads the reward coeff for the given cycle + from the storage. + Returns [Q.one] if the given cycle is not between [current_cycle] and + [current_cycle + preserved_cycles]. + If adaptive inflation has not been activated, or has been activated and the + given cycle is less than [preserved_cycles] after the activation cycle, + then this function returns [Q.one]. + Used only for RPCs. To get the actual rewards, use the reward functions + defined above. *) + val get_reward_coeff : t -> cycle:Cycle.t -> Q.t tzresult Lwt.t + end end end -- GitLab From 49327509d0f9a037e2c38e5614e5444f4b05ef44 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Thu, 8 Jun 2023 14:14:40 +0200 Subject: [PATCH 2/3] Proto/AI/RPC: add helper functions --- .../adaptive_inflation_services.ml | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/proto_alpha/lib_protocol/adaptive_inflation_services.ml b/src/proto_alpha/lib_protocol/adaptive_inflation_services.ml index c9733dc503cd..100e589fb8fc 100644 --- a/src/proto_alpha/lib_protocol/adaptive_inflation_services.ml +++ b/src/proto_alpha/lib_protocol/adaptive_inflation_services.ml @@ -45,6 +45,41 @@ module S = struct RPC_path.(context_path / "total_frozen_stake") end +let q_to_float_string q = + let offset = 1000 in + let unit = Z.div q.Q.num q.den in + let q = Q.(sub q (unit /// Z.one)) in + let q = Q.(mul q (offset // 1)) in + let dec = Z.div q.num q.den in + let padded_dec_string = Format.asprintf "%03d" (Z.to_int dec) in + Format.asprintf "%a.%s" Z.pp_print unit padded_dec_string + +let current_rewards_per_minute ctxt = + let open Lwt_result_syntax in + let base_total_rewards_per_minute = + (Constants.reward_weights ctxt).base_total_rewards_per_minute + in + let q_base_total_rewards_per_minute = + Tez.to_mutez base_total_rewards_per_minute |> Q.of_int64 + in + let cycle = (Level.current ctxt).cycle in + let* f = Delegate.Rewards.For_RPC.get_reward_coeff ctxt ~cycle in + let f = Q.mul f q_base_total_rewards_per_minute (* rewards per minute *) in + return f + +(* Does the reverse operations of [compute_coeff] in [adaptive_inflation_storage.ml] *) +let current_yearly_rate_value ~formatter ctxt = + let open Lwt_result_syntax in + let q_min_per_year = Q.of_int 525600 in + let* total_supply = Contract.get_total_supply ctxt in + let q_total_supply = Tez.to_mutez total_supply |> Q.of_int64 in + let* f = current_rewards_per_minute ctxt in + let f = Q.div f q_total_supply (* inflation per minute *) in + let f = Q.mul f q_min_per_year (* inflation per year *) in + (* transform into a string *) + let f = Q.(mul f (100 // 1)) in + return (formatter f) + let register () = let open Services_registration in register0 ~chunked:false S.total_supply (fun ctxt () () -> -- GitLab From af0bb07d75522a5633a36444c107dd728aaa1619 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Thu, 8 Jun 2023 14:15:11 +0200 Subject: [PATCH 3/3] Proto/AI/RPC: add inflation RPCs --- .../adaptive_inflation_services.ml | 54 ++++++++++++++++++- .../adaptive_inflation_services.mli | 9 ++++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/proto_alpha/lib_protocol/adaptive_inflation_services.ml b/src/proto_alpha/lib_protocol/adaptive_inflation_services.ml index 100e589fb8fc..9ea2d75c5261 100644 --- a/src/proto_alpha/lib_protocol/adaptive_inflation_services.ml +++ b/src/proto_alpha/lib_protocol/adaptive_inflation_services.ml @@ -26,9 +26,17 @@ open Alpha_context module S = struct + open Data_encoding + + let q_encoding = + conv + (fun Q.{num; den} -> (num, den)) + (fun (num, den) -> Q.make num den) + (obj2 (req "numerator" n) (req "denominator" n)) + let context_path = RPC_path.(open_root / "context") - let _path = RPC_path.(context_path / "inflation") + let path = RPC_path.(context_path / "inflation") let total_supply = RPC_service.get_service @@ -43,6 +51,31 @@ module S = struct ~query:RPC_query.empty ~output:Tez.encoding RPC_path.(context_path / "total_frozen_stake") + + let current_yearly_rate = + RPC_service.get_service + ~description: + "Returns the current expected maximum yearly inflation rate (in %)" + ~query:RPC_query.empty + ~output:(string Plain) + RPC_path.(path / "current_yearly_rate") + + let current_yearly_rate_exact = + RPC_service.get_service + ~description: + "Returns the current expected maximum yearly inflation rate (exact \ + quotient)" + ~query:RPC_query.empty + ~output:q_encoding + RPC_path.(path / "current_yearly_rate_exact") + + let current_rewards_per_minute = + RPC_service.get_service + ~description: + "Returns the current expected maximum rewards per minute (in mutez)" + ~query:RPC_query.empty + ~output:Tez.encoding + RPC_path.(path / "rewards_per_minute") end let q_to_float_string q = @@ -82,14 +115,31 @@ let current_yearly_rate_value ~formatter ctxt = let register () = let open Services_registration in + let open Lwt_result_syntax in register0 ~chunked:false S.total_supply (fun ctxt () () -> Contract.get_total_supply ctxt) ; register0 ~chunked:false S.total_frozen_stake (fun ctxt () () -> let cycle = (Level.current ctxt).cycle in - Stake_distribution.get_total_frozen_stake ctxt cycle) + Stake_distribution.get_total_frozen_stake ctxt cycle) ; + register0 ~chunked:false S.current_yearly_rate (fun ctxt () () -> + current_yearly_rate_value ~formatter:q_to_float_string ctxt) ; + register0 ~chunked:false S.current_yearly_rate_exact (fun ctxt () () -> + current_yearly_rate_value ~formatter:(fun x -> x) ctxt) ; + register0 ~chunked:false S.current_rewards_per_minute (fun ctxt () () -> + let* f = current_rewards_per_minute ctxt in + return (Tez.of_mutez_exn (Q.to_int64 f))) let total_supply ctxt block = RPC_context.make_call0 S.total_supply ctxt block () () let total_frozen_stake ctxt block = RPC_context.make_call0 S.total_frozen_stake ctxt block () () + +let current_yearly_rate ctxt block = + RPC_context.make_call0 S.current_yearly_rate ctxt block () () + +let current_yearly_rate_exact ctxt block = + RPC_context.make_call0 S.current_yearly_rate_exact ctxt block () () + +let current_rewards_per_minute ctxt block = + RPC_context.make_call0 S.current_rewards_per_minute ctxt block () () diff --git a/src/proto_alpha/lib_protocol/adaptive_inflation_services.mli b/src/proto_alpha/lib_protocol/adaptive_inflation_services.mli index d22b4b717032..651aa92f8c31 100644 --- a/src/proto_alpha/lib_protocol/adaptive_inflation_services.mli +++ b/src/proto_alpha/lib_protocol/adaptive_inflation_services.mli @@ -30,4 +30,13 @@ val total_supply : 'a #RPC_context.simple -> 'a -> Tez.t shell_tzresult Lwt.t val total_frozen_stake : 'a #RPC_context.simple -> 'a -> Tez.t shell_tzresult Lwt.t +val current_yearly_rate : + 'a #RPC_context.simple -> 'a -> string shell_tzresult Lwt.t + +val current_yearly_rate_exact : + 'a #RPC_context.simple -> 'a -> Q.t shell_tzresult Lwt.t + +val current_rewards_per_minute : + 'a #RPC_context.simple -> 'a -> Tez.t shell_tzresult Lwt.t + val register : unit -> unit -- GitLab