From b5a8e31a8d38aaaf4179aae305bd5bb916c4b9ee Mon Sep 17 00:00:00 2001 From: Julien Tesson Date: Thu, 8 Jun 2023 13:41:59 +0200 Subject: [PATCH 1/7] Proto/delegate_staking_parameters: add compution of rewards distrib amongst spendable and frozen --- .../delegate_staking_parameters.ml | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/src/proto_alpha/lib_protocol/delegate_staking_parameters.ml b/src/proto_alpha/lib_protocol/delegate_staking_parameters.ml index f5db49c5c3b9..972e0b84376b 100644 --- a/src/proto_alpha/lib_protocol/delegate_staking_parameters.ml +++ b/src/proto_alpha/lib_protocol/delegate_staking_parameters.ml @@ -112,3 +112,70 @@ let activate ctxt ~new_cycle = new_cycle in return ctxt) + +type reward_distrib = {to_frozen : Tez_repr.t; to_spendable : Tez_repr.t} + +(** Compute the reward distribution between frozen and spendable according to: + - the [stake] of the delegate composed of the [frozen] deposits and the + [delegated] tokens. + - the [baking_over_staking_edge] parameter set by the baker in 1_000_000_000th + - the [staking_over_delegation_edge] constant. + - the [rewards] to be distributed + +Preconditions: + - [staking_over_delegation_edge] > 0 + - 0 <= [baking_over_staking_edge] <= 1_000_000_000 +*) +let compute_reward_distrib ~stake ~baking_over_staking_edge + ~staking_over_delegation_edge ~(rewards : Tez_repr.t) = + let ({frozen; delegated} : Stake_repr.t) = stake in + (* convert into Q *) + let delegated = (* >= 0 *) Q.of_int64 @@ Tez_repr.to_mutez delegated in + let frozen = (* >= 0 *) Q.of_int64 @@ Tez_repr.to_mutez frozen in + let baking_over_staking_edge (* 0 <= baking_over_staking_edge <= 1 *) = + Q.(of_int32 baking_over_staking_edge / of_int 1_000_000_000) + in + let staking_over_delegation_edge (* > 0 ? *) = + Q.of_int staking_over_delegation_edge + in + let rewards_q = Q.of_int64 @@ Tez_repr.to_mutez rewards in + (* compute in Q *) + let to_frozen = + let open Q in + let weighted_delegated = delegated / staking_over_delegation_edge in + let total_stake = weighted_delegated + frozen in + if total_stake <= zero then zero + else + let non_delegated_ratio = frozen / total_stake in + let non_delegated_rewards = rewards_q * non_delegated_ratio in + non_delegated_rewards * (one - baking_over_staking_edge) + in + (* finish computation into mutez *) + let rewards = Tez_repr.to_mutez rewards in + let to_frozen = Q.to_int64 to_frozen in + (* todo: is there any risk to overflow here ? *) + let to_spendable = Int64.(sub rewards to_frozen) in + (* convert back to tez *) + (* Preconditions prevents to_frozen to be negative or greater than + rewards. Thus we can use to_mutez_exn *) + let to_frozen = Tez_repr.of_mutez_exn to_frozen in + let to_spendable = Tez_repr.of_mutez_exn to_spendable in + ok {to_frozen; to_spendable} + +let _compute_reward_distrib ctxt delegate stake rewards = + let open Lwt_result_syntax in + let* (delegate_parameter : Staking_parameters_repr.t) = + of_delegate ctxt delegate + in + let baking_over_staking_edge = delegate_parameter.baking_over_staking_edge in + let staking_over_delegation_edge = + if Constants_storage.adaptive_inflation_enable ctxt then + Constants_storage.adaptive_inflation_staking_over_delegation_edge ctxt + else 1 + in + Lwt.return + @@ compute_reward_distrib + ~stake + ~baking_over_staking_edge + ~staking_over_delegation_edge + ~rewards -- GitLab From fc296292363a9cb15953e6c1214834a2bc4823d4 Mon Sep 17 00:00:00 2001 From: Julien Tesson Date: Thu, 8 Jun 2023 16:09:27 +0200 Subject: [PATCH 2/7] Proto/delegate_staking_parameters: add function to pay partially frozen rewards --- .../delegate_staking_parameters.ml | 31 ++++++++++++++++++- .../delegate_staking_parameters.mli | 17 ++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/proto_alpha/lib_protocol/delegate_staking_parameters.ml b/src/proto_alpha/lib_protocol/delegate_staking_parameters.ml index 972e0b84376b..32df13a4e127 100644 --- a/src/proto_alpha/lib_protocol/delegate_staking_parameters.ml +++ b/src/proto_alpha/lib_protocol/delegate_staking_parameters.ml @@ -162,7 +162,7 @@ let compute_reward_distrib ~stake ~baking_over_staking_edge let to_spendable = Tez_repr.of_mutez_exn to_spendable in ok {to_frozen; to_spendable} -let _compute_reward_distrib ctxt delegate stake rewards = +let compute_reward_distrib ctxt delegate stake rewards = let open Lwt_result_syntax in let* (delegate_parameter : Staking_parameters_repr.t) = of_delegate ctxt delegate @@ -179,3 +179,32 @@ let _compute_reward_distrib ctxt delegate stake rewards = ~baking_over_staking_edge ~staking_over_delegation_edge ~rewards + +let pay_rewards ctxt ?active_stake ~source ~delegate rewards = + let open Lwt_result_syntax in + let*? active_stake = + let open Result_syntax in + match active_stake with + | Some active_stake -> ok active_stake + | None -> + let+ stake_distrib = + Raw_context.stake_distribution_for_current_cycle ctxt + in + Option.value + (Signature.Public_key_hash.Map.find delegate stake_distrib) + ~default:Stake_repr.zero + in + let* {to_frozen; to_spendable} = + compute_reward_distrib ctxt delegate active_stake rewards + in + let* ctxt, balance_updates_frozen_rewards = + Token.transfer ctxt source (`Frozen_deposits delegate) to_frozen + in + let+ ctxt, balance_updates_spendable_rewards = + Token.transfer + ctxt + source + (`Contract (Contract_repr.Implicit delegate)) + to_spendable + in + (ctxt, balance_updates_frozen_rewards @ balance_updates_spendable_rewards) diff --git a/src/proto_alpha/lib_protocol/delegate_staking_parameters.mli b/src/proto_alpha/lib_protocol/delegate_staking_parameters.mli index f82931051299..f8e0241887ae 100644 --- a/src/proto_alpha/lib_protocol/delegate_staking_parameters.mli +++ b/src/proto_alpha/lib_protocol/delegate_staking_parameters.mli @@ -54,3 +54,20 @@ val register_update : This function iterates on all registered delegates. *) val activate : Raw_context.t -> new_cycle:Cycle_repr.t -> Raw_context.t tzresult Lwt.t + +(** [pay_rewards ctxt ?active_stake source delegate] transfers the rewards to the + [delegate] spendable balance and frozen balance. + + The distribution is based on the baker's staking parameters. + + If adaptive inflation is enabled, it also accounts for the repartition of the + delegate's [active_stake] between delegated token and frozen deposits. + If [active_stake] is not provided, it will be retrived from the context. +*) +val pay_rewards : + Raw_context.t -> + ?active_stake:Stake_repr.t -> + source:[< Token.giver] -> + delegate:Signature.public_key_hash -> + Tez_repr.t -> + (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t -- GitLab From a190aae5539ffb1793e128868e766f09dc686180 Mon Sep 17 00:00:00 2001 From: Julien Tesson Date: Thu, 8 Jun 2023 14:04:22 +0200 Subject: [PATCH 3/7] Proto/delegate_cycles: distribute endorsing rewards according to bakers parameters --- src/proto_alpha/lib_protocol/delegate_cycles.ml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.ml b/src/proto_alpha/lib_protocol/delegate_cycles.ml index 9ce53661b790..dd22d07a5967 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.ml +++ b/src/proto_alpha/lib_protocol/delegate_cycles.ml @@ -180,12 +180,12 @@ let distribute_endorsing_rewards ctxt last_cycle unrevealed_nonces = let rewards = Tez_repr.mul_exn endorsing_reward_per_slot expected_slots in if sufficient_participation && has_revealed_nonces then (* Sufficient participation: we pay the rewards *) - let receiver = - if Constants_storage.freeze_rewards ctxt then - `Frozen_deposits delegate - else `Contract (Contract_repr.Implicit delegate) - in - Token.transfer ctxt `Endorsing_rewards receiver rewards + Delegate_staking_parameters.pay_rewards + ctxt + ~active_stake + ~source:`Endorsing_rewards + ~delegate + rewards >|=? fun (ctxt, payed_rewards_receipts) -> (ctxt, payed_rewards_receipts @ balance_updates) else -- GitLab From 6190012d7b0f654a10e3bed7dbb93872ab184412 Mon Sep 17 00:00:00 2001 From: Julien Tesson Date: Thu, 8 Jun 2023 15:55:46 +0200 Subject: [PATCH 4/7] Proto/baking_rewards: distribute baking rewards according to bakers parameters --- .../delegate_missed_endorsements_storage.ml | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml index 04be96ac4fe7..a757bdf9f6db 100644 --- a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml @@ -108,25 +108,25 @@ let record_baking_activity_and_pay_rewards_and_fees ctxt ~payload_producer Stake_storage.set_active ctxt block_producer else return ctxt) >>=? fun ctxt -> - let freeze_rewards = Constants_storage.freeze_rewards ctxt in let pay_payload_producer ctxt delegate = let contract = Contract_repr.Implicit delegate in Token.balance ctxt `Block_fees >>=? fun (ctxt, block_fees) -> Token.transfer ctxt `Block_fees (`Contract contract) block_fees >>=? fun (ctxt, balance_updates_block_fees) -> - let receiver = - if freeze_rewards then `Frozen_deposits delegate else `Contract contract - in - Token.transfer ctxt `Baking_rewards receiver baking_reward + Delegate_staking_parameters.pay_rewards + ctxt + ~source:`Baking_rewards + ~delegate + baking_reward >|=? fun (ctxt, balance_updates_baking_rewards) -> (ctxt, balance_updates_block_fees @ balance_updates_baking_rewards) in let pay_block_producer ctxt delegate bonus = - let receiver = - if freeze_rewards then `Frozen_deposits delegate - else `Contract (Contract_repr.Implicit delegate) - in - Token.transfer ctxt `Baking_bonuses receiver bonus + Delegate_staking_parameters.pay_rewards + ctxt + ~source:`Baking_bonuses + ~delegate + bonus in pay_payload_producer ctxt payload_producer >>=? fun (ctxt, balance_updates_payload_producer) -> -- GitLab From 6cd40038067ba63c93fb5962ed411a4fbf44e859 Mon Sep 17 00:00:00 2001 From: Julien Tesson Date: Thu, 8 Jun 2023 15:16:03 +0200 Subject: [PATCH 5/7] Proto/alpha_context: expose pay_rewards --- src/proto_alpha/lib_protocol/alpha_context.mli | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 9753a044928e..64fab0c1bfe5 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2274,6 +2274,14 @@ module Delegate : sig context -> Signature.Public_key_hash.t -> Staking_parameters_repr.t tzresult Lwt.t + + val pay_rewards : + context -> + ?active_stake:Stake_repr.t -> + source:[< Token.giver] -> + delegate:public_key_hash -> + Tez.t -> + (context * Receipt.balance_updates) tzresult Lwt.t end end -- GitLab From 4c852c98d14fd37f683f0bf7578e343e6c492bc4 Mon Sep 17 00:00:00 2001 From: Julien Tesson Date: Thu, 8 Jun 2023 15:16:39 +0200 Subject: [PATCH 6/7] Proto/apply: use pay_rewards for revelation_rewards --- src/proto_alpha/lib_protocol/apply.ml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index f17100492235..9d8f19cd7a06 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -2178,11 +2178,11 @@ let apply_contents_list (type kind) ctxt chain_id (mode : mode) Nonce.reveal ctxt level nonce >>=? fun ctxt -> let tip = Delegate.Rewards.seed_nonce_revelation_tip ctxt in let delegate = payload_producer.Consensus_key.delegate in - let receiver = - if Constants.freeze_rewards ctxt then `Frozen_deposits delegate - else `Contract (Contract.Implicit delegate) - in - Token.transfer ctxt `Revelation_rewards receiver tip + Delegate.Staking_parameters.pay_rewards + ctxt + ~source:`Revelation_rewards + ~delegate + tip >|=? fun (ctxt, balance_updates) -> (ctxt, Single_result (Seed_nonce_revelation_result balance_updates)) | Single (Vdf_revelation {solution}) -> -- GitLab From 0460f6b70fd9354ce60e7bf4d3afdaf0f1a372ca Mon Sep 17 00:00:00 2001 From: Mehdi Bouaziz Date: Fri, 9 Jun 2023 22:02:20 +0200 Subject: [PATCH 7/7] Proto/Delegate parameters: baking_over_staking_edge defaults at 100% --- src/proto_alpha/lib_protocol/staking_parameters_repr.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/proto_alpha/lib_protocol/staking_parameters_repr.ml b/src/proto_alpha/lib_protocol/staking_parameters_repr.ml index e2080c48283f..f9398ce6372f 100644 --- a/src/proto_alpha/lib_protocol/staking_parameters_repr.ml +++ b/src/proto_alpha/lib_protocol/staking_parameters_repr.ml @@ -32,7 +32,8 @@ let maximum_baking_over_staking_edge = (* max is 1 expressed in portions of 1_000_000_000 *) 1_000_000_000l -let default = {staking_over_baking_limit = 0l; baking_over_staking_edge = 0l} +let default = + {staking_over_baking_limit = 0l; baking_over_staking_edge = 1_000_000_000l} type error += Invalid_staking_parameters -- GitLab