From 6b7d94df35c84907694c68d5644015ff1da98889 Mon Sep 17 00:00:00 2001 From: Mehdi Bouaziz Date: Tue, 14 Mar 2023 16:13:09 +0100 Subject: [PATCH 1/7] Proto/Delegate_missed_endorsements_storage: use weight instead of Tez to compute expected slots --- .../lib_protocol/delegate_cycles.ml | 6 +++-- .../delegate_missed_endorsements_storage.ml | 22 ++++++++++++------- .../delegate_missed_endorsements_storage.mli | 4 ++-- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.ml b/src/proto_alpha/lib_protocol/delegate_cycles.ml index 8dd309a452d8..f17744ef29fc 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.ml +++ b/src/proto_alpha/lib_protocol/delegate_cycles.ml @@ -204,6 +204,7 @@ let distribute_endorsing_rewards ctxt last_cycle unrevealed_nonces = in Stake_storage.get_total_active_stake ctxt last_cycle >>=? fun total_active_stake -> + let total_active_stake_weight = Tez_repr.to_mutez total_active_stake in Stake_storage.get_selected_distribution ctxt last_cycle >>=? fun delegates -> List.fold_left_es (fun (ctxt, balance_updates) (delegate, active_stake) -> @@ -216,12 +217,13 @@ let distribute_endorsing_rewards ctxt last_cycle unrevealed_nonces = let has_revealed_nonces = delegate_has_revealed_nonces delegate unrevealed_nonces_set in + let active_stake_weight = Tez_repr.to_mutez active_stake in let expected_slots = Delegate_missed_endorsements_storage .expected_slots_for_given_active_stake ctxt - ~total_active_stake - ~active_stake + ~total_active_stake_weight + ~active_stake_weight in let rewards = Tez_repr.mul_exn endorsing_reward_per_slot expected_slots in if sufficient_participation && has_revealed_nonces then 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 48d3be9240d5..459fefe70248 100644 --- a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml @@ -25,8 +25,8 @@ (* *) (*****************************************************************************) -let expected_slots_for_given_active_stake ctxt ~total_active_stake ~active_stake - = +let expected_slots_for_given_active_stake ctxt ~total_active_stake_weight + ~active_stake_weight = let blocks_per_cycle = Int32.to_int (Constants_storage.blocks_per_cycle ctxt) in @@ -39,9 +39,9 @@ let expected_slots_for_given_active_stake ctxt ~total_active_stake ~active_stake Z.to_int (Z.div (Z.mul - (Z.of_int64 (Tez_repr.to_mutez active_stake)) + (Z.of_int64 active_stake_weight) (Z.of_int number_of_endorsements_per_cycle)) - (Z.of_int64 (Tez_repr.to_mutez total_active_stake))) + (Z.of_int64 total_active_stake_weight)) type level_participation = Participated | Didn't_participate @@ -79,10 +79,14 @@ let record_endorsing_participation ctxt ~delegate ~participation Stake_storage.get_total_active_stake ctxt level.cycle >>=? fun total_active_stake -> let expected_slots = + let active_stake_weight = Tez_repr.to_mutez active_stake in + let total_active_stake_weight = + Tez_repr.to_mutez total_active_stake + in expected_slots_for_given_active_stake ctxt - ~total_active_stake - ~active_stake + ~total_active_stake_weight + ~active_stake_weight in let Ratio_repr.{numerator; denominator} = Constants_storage.minimal_participation_ratio ctxt @@ -167,10 +171,12 @@ let participation_info ctxt delegate = Stake_storage.get_total_active_stake ctxt level.cycle >>=? fun total_active_stake -> let expected_cycle_activity = + let active_stake_weight = Tez_repr.to_mutez active_stake in + let total_active_stake_weight = Tez_repr.to_mutez total_active_stake in expected_slots_for_given_active_stake ctxt - ~total_active_stake - ~active_stake + ~total_active_stake_weight + ~active_stake_weight in let Ratio_repr.{numerator; denominator} = Constants_storage.minimal_participation_ratio ctxt diff --git a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli index e3950661ddc1..a5469c79e325 100644 --- a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli @@ -32,8 +32,8 @@ val expected_slots_for_given_active_stake : Raw_context.t -> - total_active_stake:Tez_repr.t -> - active_stake:Tez_repr.t -> + total_active_stake_weight:int64 -> + active_stake_weight:int64 -> int type level_participation = Participated | Didn't_participate -- GitLab From 1c0476e401a52ce0afe8fa1bdda053854a95dca7 Mon Sep 17 00:00:00 2001 From: Mehdi Bouaziz Date: Tue, 14 Mar 2023 14:37:16 +0100 Subject: [PATCH 2/7] Proto: add Stake_repr --- src/proto_alpha/lib_protocol/TEZOS_PROTOCOL | 1 + src/proto_alpha/lib_protocol/dune | 4 ++++ src/proto_alpha/lib_protocol/stake_repr.ml | 24 +++++++++++++++++++++ src/proto_alpha/lib_protocol/stake_repr.mli | 24 +++++++++++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 src/proto_alpha/lib_protocol/stake_repr.ml create mode 100644 src/proto_alpha/lib_protocol/stake_repr.mli diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index c0f468f18c87..f4e52cc12d54 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -119,6 +119,7 @@ "Lazy_storage_kind", "Receipt_repr", "Migration_repr", + "Stake_repr", "Carbonated_map_costs", "Carbonated_map", diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index 1de27598da43..19a717b6c27a 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -142,6 +142,7 @@ Lazy_storage_kind Receipt_repr Migration_repr + Stake_repr Carbonated_map_costs Carbonated_map Raw_context_intf @@ -420,6 +421,7 @@ lazy_storage_kind.ml lazy_storage_kind.mli receipt_repr.ml receipt_repr.mli migration_repr.ml migration_repr.mli + stake_repr.ml stake_repr.mli carbonated_map_costs.ml carbonated_map_costs.mli carbonated_map.ml carbonated_map.mli raw_context_intf.ml @@ -700,6 +702,7 @@ lazy_storage_kind.ml lazy_storage_kind.mli receipt_repr.ml receipt_repr.mli migration_repr.ml migration_repr.mli + stake_repr.ml stake_repr.mli carbonated_map_costs.ml carbonated_map_costs.mli carbonated_map.ml carbonated_map.mli raw_context_intf.ml @@ -964,6 +967,7 @@ lazy_storage_kind.ml lazy_storage_kind.mli receipt_repr.ml receipt_repr.mli migration_repr.ml migration_repr.mli + stake_repr.ml stake_repr.mli carbonated_map_costs.ml carbonated_map_costs.mli carbonated_map.ml carbonated_map.mli raw_context_intf.ml diff --git a/src/proto_alpha/lib_protocol/stake_repr.ml b/src/proto_alpha/lib_protocol/stake_repr.ml new file mode 100644 index 000000000000..48fcc1a4b1b4 --- /dev/null +++ b/src/proto_alpha/lib_protocol/stake_repr.ml @@ -0,0 +1,24 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) diff --git a/src/proto_alpha/lib_protocol/stake_repr.mli b/src/proto_alpha/lib_protocol/stake_repr.mli new file mode 100644 index 000000000000..48fcc1a4b1b4 --- /dev/null +++ b/src/proto_alpha/lib_protocol/stake_repr.mli @@ -0,0 +1,24 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) -- GitLab From a8177d4505191fa2e796068d8589e7408cae189f Mon Sep 17 00:00:00 2001 From: Mehdi Bouaziz Date: Tue, 14 Mar 2023 14:44:42 +0100 Subject: [PATCH 3/7] Proto: use Stake_repr for the selected distribution --- .../lib_protocol/delegate_cycles.ml | 7 +++++-- .../delegate_missed_endorsements_storage.ml | 12 +++++++---- .../lib_protocol/delegate_sampler.ml | 7 ++++--- src/proto_alpha/lib_protocol/raw_context.ml | 2 +- src/proto_alpha/lib_protocol/raw_context.mli | 4 ++-- src/proto_alpha/lib_protocol/stake_repr.ml | 20 +++++++++++++++++++ src/proto_alpha/lib_protocol/stake_repr.mli | 18 +++++++++++++++++ src/proto_alpha/lib_protocol/stake_storage.ml | 4 ++-- .../lib_protocol/stake_storage.mli | 10 +++++----- src/proto_alpha/lib_protocol/storage.ml | 6 +++--- src/proto_alpha/lib_protocol/storage.mli | 4 ++-- 11 files changed, 70 insertions(+), 24 deletions(-) diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.ml b/src/proto_alpha/lib_protocol/delegate_cycles.ml index f17744ef29fc..5b064d064818 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.ml +++ b/src/proto_alpha/lib_protocol/delegate_cycles.ml @@ -71,6 +71,7 @@ let max_frozen_deposits_and_delegates_to_remove ctxt ~from_cycle ~to_cycle = >|=? fun active_stakes -> List.fold_left (fun (maxima, delegates_to_remove) (delegate, stake) -> + let stake = Stake_repr.total stake in let maxima = Signature.Public_key_hash.Map.update delegate @@ -204,7 +205,9 @@ let distribute_endorsing_rewards ctxt last_cycle unrevealed_nonces = in Stake_storage.get_total_active_stake ctxt last_cycle >>=? fun total_active_stake -> - let total_active_stake_weight = Tez_repr.to_mutez total_active_stake in + let total_active_stake_weight = + Stake_repr.staking_weight total_active_stake + in Stake_storage.get_selected_distribution ctxt last_cycle >>=? fun delegates -> List.fold_left_es (fun (ctxt, balance_updates) (delegate, active_stake) -> @@ -217,7 +220,7 @@ let distribute_endorsing_rewards ctxt last_cycle unrevealed_nonces = let has_revealed_nonces = delegate_has_revealed_nonces delegate unrevealed_nonces_set in - let active_stake_weight = Tez_repr.to_mutez active_stake in + let active_stake_weight = Stake_repr.staking_weight active_stake in let expected_slots = Delegate_missed_endorsements_storage .expected_slots_for_given_active_stake 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 459fefe70248..e9cd6c1a9991 100644 --- a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml @@ -79,9 +79,11 @@ let record_endorsing_participation ctxt ~delegate ~participation Stake_storage.get_total_active_stake ctxt level.cycle >>=? fun total_active_stake -> let expected_slots = - let active_stake_weight = Tez_repr.to_mutez active_stake in + let active_stake_weight = + Stake_repr.staking_weight active_stake + in let total_active_stake_weight = - Tez_repr.to_mutez total_active_stake + Stake_repr.staking_weight total_active_stake in expected_slots_for_given_active_stake ctxt @@ -171,8 +173,10 @@ let participation_info ctxt delegate = Stake_storage.get_total_active_stake ctxt level.cycle >>=? fun total_active_stake -> let expected_cycle_activity = - let active_stake_weight = Tez_repr.to_mutez active_stake in - let total_active_stake_weight = Tez_repr.to_mutez total_active_stake in + let active_stake_weight = Stake_repr.staking_weight active_stake in + let total_active_stake_weight = + Stake_repr.staking_weight total_active_stake + in expected_slots_for_given_active_stake ctxt ~total_active_stake_weight diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.ml b/src/proto_alpha/lib_protocol/delegate_sampler.ml index 03594e25a63b..d01382c40a40 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.ml +++ b/src/proto_alpha/lib_protocol/delegate_sampler.ml @@ -192,9 +192,10 @@ let get_stakes_for_selected_index ctxt index = let*? r = max_mutez /? frozen_deposits_percentage in return r in - let*? total_stake = Tez_repr.(total_stake +? stake_for_cycle) in + let stake_for_cycle = Stake_repr.make ~total:stake_for_cycle in + let*? total_stake = Stake_repr.(total_stake +? stake_for_cycle) in return ((delegate, stake_for_cycle) :: acc, total_stake)) - ~init:([], Tez_repr.zero) + ~init:([], Stake_repr.zero) let compute_snapshot_index_for_seed ~max_snapshot_index seed = let rd = Seed_repr.initialize_new seed [Bytes.of_string "stake_snapshot"] in @@ -222,7 +223,7 @@ let select_distribution_for_cycle ctxt cycle = List.fold_left_es (fun acc (pkh, stake) -> Delegate_consensus_key.active_pubkey_for_cycle ctxt pkh cycle - >|=? fun pk -> (pk, Tez_repr.to_mutez stake) :: acc) + >|=? fun pk -> (pk, Stake_repr.staking_weight stake) :: acc) [] stakes >>=? fun stakes_pk -> diff --git a/src/proto_alpha/lib_protocol/raw_context.ml b/src/proto_alpha/lib_protocol/raw_context.ml index 8f20eed7f29a..83d15d27ecc9 100644 --- a/src/proto_alpha/lib_protocol/raw_context.ml +++ b/src/proto_alpha/lib_protocol/raw_context.ml @@ -235,7 +235,7 @@ type back = { dictator_proposal_seen : bool; sampler_state : (Seed_repr.seed * consensus_pk Sampler.t) Cycle_repr.Map.t; stake_distribution_for_current_cycle : - Tez_repr.t Signature.Public_key_hash.Map.t option; + Stake_repr.t Signature.Public_key_hash.Map.t option; tx_rollup_current_messages : Tx_rollup_inbox_repr.Merkle.tree Tx_rollup_repr.Map.t; sc_rollup_current_messages : Sc_rollup_inbox_merkelized_payload_hashes_repr.t; diff --git a/src/proto_alpha/lib_protocol/raw_context.mli b/src/proto_alpha/lib_protocol/raw_context.mli index 01d81c27304e..2da61ffdd78e 100644 --- a/src/proto_alpha/lib_protocol/raw_context.mli +++ b/src/proto_alpha/lib_protocol/raw_context.mli @@ -282,10 +282,10 @@ val sampler_for_cycle : (* The stake distribution is stored both in [t] and in the cache. It may be sufficient to only store it in the cache. *) val stake_distribution_for_current_cycle : - t -> Tez_repr.t Signature.Public_key_hash.Map.t tzresult + t -> Stake_repr.t Signature.Public_key_hash.Map.t tzresult val init_stake_distribution_for_current_cycle : - t -> Tez_repr.t Signature.Public_key_hash.Map.t -> t + t -> Stake_repr.t Signature.Public_key_hash.Map.t -> t module Internal_for_tests : sig val add_level : t -> int -> t diff --git a/src/proto_alpha/lib_protocol/stake_repr.ml b/src/proto_alpha/lib_protocol/stake_repr.ml index 48fcc1a4b1b4..006320bf93cf 100644 --- a/src/proto_alpha/lib_protocol/stake_repr.ml +++ b/src/proto_alpha/lib_protocol/stake_repr.ml @@ -22,3 +22,23 @@ (* DEALINGS IN THE SOFTWARE. *) (* *) (*****************************************************************************) + +type t = {total : Tez_repr.t} + +let make ~total = {total} + +let total {total} = total + +let encoding = + Data_encoding.conv total (fun total -> make ~total) Tez_repr.encoding + +let zero = make ~total:Tez_repr.zero + +let staking_weight stake = Tez_repr.to_mutez (total stake) + +let compare s1 s2 = Int64.compare (staking_weight s1) (staking_weight s2) + +let ( +? ) s1 s2 = + let open Result_syntax in + let+ total = Tez_repr.(total s1 +? total s2) in + make ~total diff --git a/src/proto_alpha/lib_protocol/stake_repr.mli b/src/proto_alpha/lib_protocol/stake_repr.mli index 48fcc1a4b1b4..5e5768410bb5 100644 --- a/src/proto_alpha/lib_protocol/stake_repr.mli +++ b/src/proto_alpha/lib_protocol/stake_repr.mli @@ -22,3 +22,21 @@ (* DEALINGS IN THE SOFTWARE. *) (* *) (*****************************************************************************) + +(** Stake of a delegate. *) +type t + +val zero : t + +val make : total:Tez_repr.t -> t + +val encoding : t Data_encoding.t + +val total : t -> Tez_repr.t + +(** Weight for staking rights. *) +val staking_weight : t -> int64 + +val compare : t -> t -> int + +val ( +? ) : t -> t -> t tzresult diff --git a/src/proto_alpha/lib_protocol/stake_storage.ml b/src/proto_alpha/lib_protocol/stake_storage.ml index 7acfcb76038c..ed8934323c0b 100644 --- a/src/proto_alpha/lib_protocol/stake_storage.ml +++ b/src/proto_alpha/lib_protocol/stake_storage.ml @@ -25,7 +25,7 @@ module Selected_distribution_for_cycle = struct module Cache_client = struct - type cached_value = (Signature.Public_key_hash.t * Tez_repr.t) list + type cached_value = (Signature.Public_key_hash.t * Stake_repr.t) list let namespace = Cache_repr.create_namespace "stake_distribution" @@ -148,7 +148,7 @@ let snapshot ctxt = let max_snapshot_index = Storage.Stake.Last_snapshot.get let set_selected_distribution_for_cycle ctxt cycle stakes total_stake = - let stakes = List.sort (fun (_, x) (_, y) -> Tez_repr.compare y x) stakes in + let stakes = List.sort (fun (_, x) (_, y) -> Stake_repr.compare y x) stakes in Selected_distribution_for_cycle.init ctxt cycle stakes >>=? fun ctxt -> Storage.Stake.Total_active_stake.add ctxt cycle total_stake >>= fun ctxt -> (* cleanup snapshots *) diff --git a/src/proto_alpha/lib_protocol/stake_storage.mli b/src/proto_alpha/lib_protocol/stake_storage.mli index 67968f574697..326e0463c407 100644 --- a/src/proto_alpha/lib_protocol/stake_storage.mli +++ b/src/proto_alpha/lib_protocol/stake_storage.mli @@ -90,8 +90,8 @@ val max_snapshot_index : Raw_context.t -> int tzresult Lwt.t val set_selected_distribution_for_cycle : Raw_context.t -> Cycle_repr.t -> - (Signature.public_key_hash * Tez_repr.t) list -> - Tez_repr.t -> + (Signature.public_key_hash * Stake_repr.t) list -> + Stake_repr.t -> Raw_context.t tzresult Lwt.t val clear_at_cycle_end : @@ -110,12 +110,12 @@ val fold_on_active_delegates_with_minimal_stake : val get_selected_distribution : Raw_context.t -> Cycle_repr.t -> - (Signature.Public_key_hash.t * Tez_repr.t) list tzresult Lwt.t + (Signature.Public_key_hash.t * Stake_repr.t) list tzresult Lwt.t val find_selected_distribution : Raw_context.t -> Cycle_repr.t -> - (Signature.Public_key_hash.t * Tez_repr.t) list option tzresult Lwt.t + (Signature.Public_key_hash.t * Stake_repr.t) list option tzresult Lwt.t (** Copy the stake distribution for the current cycle (from [Storage.Stake.Selected_distribution_for_cycle]) in the raw @@ -125,7 +125,7 @@ val prepare_stake_distribution : Raw_context.t -> Raw_context.t tzresult Lwt.t (** [get_total_active_stake ctxt cycle] retrieves the amount in Tez of the active stake at [cycle] from [ctxt]. *) val get_total_active_stake : - Raw_context.t -> Cycle_repr.t -> Tez_repr.t tzresult Lwt.t + Raw_context.t -> Cycle_repr.t -> Stake_repr.t tzresult Lwt.t (** [add_contract_stake ctxt contract amount] calls [Stake_storage.add_stake ctxt delegate amount] if [contract] has a diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index 2e1b31102f2e..0b16b49c6a15 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -998,14 +998,14 @@ module Cycle = struct let name = ["selected_stake_distribution"] end) (struct - type t = (Signature.Public_key_hash.t * Tez_repr.t) list + type t = (Signature.Public_key_hash.t * Stake_repr.t) list let encoding = Data_encoding.( Variable.list (obj2 (req "baker" Signature.Public_key_hash.encoding) - (req "active_stake" Tez_repr.encoding))) + (req "active_stake" Stake_repr.encoding))) end) module Total_active_stake = @@ -1014,7 +1014,7 @@ module Cycle = struct (struct let name = ["total_active_stake"] end) - (Tez_repr) + (Stake_repr) module Delegate_sampler_state = Indexed_context.Make_map diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index 29bf6cb53352..ba1b81f0144b 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -416,7 +416,7 @@ module Stake : sig module Selected_distribution_for_cycle : Indexed_data_storage with type key = Cycle_repr.t - and type value = (Signature.Public_key_hash.t * Tez_repr.t) list + and type value = (Signature.Public_key_hash.t * Stake_repr.t) list and type t := Raw_context.t (** Sum of the active stakes of all the delegates with @@ -424,7 +424,7 @@ module Stake : sig module Total_active_stake : Indexed_data_storage with type key = Cycle_repr.t - and type value = Tez_repr.t + and type value = Stake_repr.t and type t := Raw_context.t end -- GitLab From 10e82133f7260be2fd2fad7266cc4d6ec3372437 Mon Sep 17 00:00:00 2001 From: Mehdi Bouaziz Date: Wed, 15 Mar 2023 12:48:17 +0100 Subject: [PATCH 4/7] Proto/Delegate_sampler: minor rewrite --- .../lib_protocol/delegate_sampler.ml | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.ml b/src/proto_alpha/lib_protocol/delegate_sampler.ml index d01382c40a40..a32815a4d600 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.ml +++ b/src/proto_alpha/lib_protocol/delegate_sampler.ml @@ -175,24 +175,24 @@ let get_stakes_for_selected_index ctxt index = let*? total_balance = balance_and_frozen_bonds +? frozen_deposits.current_amount in - let* stake_for_cycle = - let frozen_deposits_limit = - match frozen_deposits_limit with Some fdp -> fdp | None -> max_mutez - in - let aux = min total_balance frozen_deposits_limit in - if aux <= overflow_bound then - let*? aux = aux *? 100L in - let*? v = aux /? frozen_deposits_percentage in + let frozen_deposits_limit = + match frozen_deposits_limit with Some fdp -> fdp | None -> max_mutez + in + let frozen = min total_balance frozen_deposits_limit in + let* total_stake_for_cycle = + if frozen <= overflow_bound then + let*? frozen = frozen *? 100L in + let*? v = frozen /? frozen_deposits_percentage in return (min v staking_balance) else let*? sbal = staking_balance /? 100L in - let*? a = aux /? frozen_deposits_percentage in + let*? a = frozen /? frozen_deposits_percentage in if sbal <= a then return staking_balance else let*? r = max_mutez /? frozen_deposits_percentage in return r in - let stake_for_cycle = Stake_repr.make ~total:stake_for_cycle in + let stake_for_cycle = Stake_repr.make ~total:total_stake_for_cycle in let*? total_stake = Stake_repr.(total_stake +? stake_for_cycle) in return ((delegate, stake_for_cycle) :: acc, total_stake)) ~init:([], Stake_repr.zero) -- GitLab From 72844fca7c3755cba513007e20439e35c59794e0 Mon Sep 17 00:00:00 2001 From: Mehdi Bouaziz Date: Wed, 15 Mar 2023 13:10:10 +0100 Subject: [PATCH 5/7] Proto/Stake_storage: minor rewrite --- src/proto_alpha/lib_protocol/stake_storage.ml | 57 ++++++++++--------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/src/proto_alpha/lib_protocol/stake_storage.ml b/src/proto_alpha/lib_protocol/stake_storage.ml index ed8934323c0b..2edbcec8fb52 100644 --- a/src/proto_alpha/lib_protocol/stake_storage.ml +++ b/src/proto_alpha/lib_protocol/stake_storage.ml @@ -75,37 +75,33 @@ let get_initialized_stake ctxt delegate = Storage.Stake.Staking_balance.init ctxt delegate balance >>=? fun ctxt -> return (balance, ctxt) -let remove_stake ctxt delegate amount = +let update_stake ~f ctxt delegate = get_initialized_stake ctxt delegate >>=? fun (staking_balance_before, ctxt) -> - Tez_repr.(staking_balance_before -? amount) >>?= fun staking_balance -> + f staking_balance_before >>?= fun staking_balance -> Storage.Stake.Staking_balance.update ctxt delegate staking_balance >>=? fun ctxt -> let minimal_stake = Constants_storage.minimal_stake ctxt in - if - Tez_repr.(staking_balance_before >= minimal_stake) - && Tez_repr.(staking_balance < minimal_stake) - then - Delegate_activation_storage.is_inactive ctxt delegate >>=? fun inactive -> - if inactive then return ctxt + if Tez_repr.(staking_balance < staking_balance_before) then + if + (* Removing stake. The delegate may become inactive. *) + Tez_repr.(staking_balance_before >= minimal_stake) + && Tez_repr.(staking_balance < minimal_stake) + then + Delegate_activation_storage.is_inactive ctxt delegate >>=? fun inactive -> + if inactive then return ctxt + else + Storage.Stake.Active_delegates_with_minimal_stake.remove ctxt delegate + >>= fun ctxt -> return ctxt else - Storage.Stake.Active_delegates_with_minimal_stake.remove ctxt delegate - >>= fun ctxt -> return ctxt - else - (* The delegate was not in Stake.Active_delegates_with_minimal_stake, either - - because it did not have the minimal required stake, in which case it - still does not have it; - - or because it did have the minimal required stake and still has it, - however it was (and is) inactive. - *) - return ctxt - -let add_stake ctxt delegate amount = - get_initialized_stake ctxt delegate >>=? fun (staking_balance_before, ctxt) -> - Tez_repr.(amount +? staking_balance_before) >>?= fun staking_balance -> - Storage.Stake.Staking_balance.update ctxt delegate staking_balance - >>=? fun ctxt -> - let minimal_stake = Constants_storage.minimal_stake ctxt in - if + (* The delegate was not in Stake.Active_delegates_with_minimal_stake, either + - because it did not have the minimal required stake, in which case it + still does not have it; + - or because it did have the minimal required stake and still has it, + however it was (and is) inactive. + *) + return ctxt + else if + (* Adding stake. The delegate may become active. *) Tez_repr.(staking_balance_before < minimal_stake) && Tez_repr.(staking_balance >= minimal_stake) then @@ -120,8 +116,13 @@ let add_stake ctxt delegate amount = have it; - or because it did have the minimal required stake, in which case it still has it, however it was (and still is) inactive. - *) - return ctxt + *) return ctxt + +let remove_stake ctxt delegate amount = + update_stake ctxt delegate ~f:(fun stake -> Tez_repr.(stake -? amount)) + +let add_stake ctxt delegate amount = + update_stake ctxt delegate ~f:(fun stake -> Tez_repr.(stake +? amount)) let set_inactive ctxt delegate = Delegate_activation_storage.set_inactive ctxt delegate >>= fun ctxt -> -- GitLab From 4a519cab396b0a08a862a8cf3f7b00c65f11e6b0 Mon Sep 17 00:00:00 2001 From: Mehdi Bouaziz Date: Wed, 15 Mar 2023 13:20:30 +0100 Subject: [PATCH 6/7] Proto/Stake: split between frozen and delegated --- .../lib_protocol/delegate_cycles.ml | 37 ++++++++++--------- .../lib_protocol/delegate_sampler.ml | 10 ++++- src/proto_alpha/lib_protocol/stake_repr.ml | 24 +++++++----- src/proto_alpha/lib_protocol/stake_repr.mli | 5 ++- 4 files changed, 46 insertions(+), 30 deletions(-) diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.ml b/src/proto_alpha/lib_protocol/delegate_cycles.ml index 5b064d064818..dc4b26d3622b 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.ml +++ b/src/proto_alpha/lib_protocol/delegate_cycles.ml @@ -68,24 +68,25 @@ let max_frozen_deposits_and_delegates_to_remove ctxt ~from_cycle ~to_cycle = List.fold_left_es (fun (maxima, delegates_to_remove) (cycle : Cycle_repr.t) -> Stake_storage.get_selected_distribution ctxt cycle - >|=? fun active_stakes -> - List.fold_left - (fun (maxima, delegates_to_remove) (delegate, stake) -> - let stake = Stake_repr.total stake in - let maxima = - Signature.Public_key_hash.Map.update - delegate - (function - | None -> Some stake - | Some maximum -> Some (Tez_repr.max maximum stake)) - maxima - in - let delegates_to_remove = - Signature.Public_key_hash.Set.remove delegate delegates_to_remove - in - (maxima, delegates_to_remove)) - (maxima, delegates_to_remove) - active_stakes) + >>=? fun active_stakes -> + Lwt.return + @@ List.fold_left_e + (fun (maxima, delegates_to_remove) (delegate, stake) -> + Stake_repr.total stake >|? fun stake -> + let maxima = + Signature.Public_key_hash.Map.update + delegate + (function + | None -> Some stake + | Some maximum -> Some (Tez_repr.max maximum stake)) + maxima + in + let delegates_to_remove = + Signature.Public_key_hash.Set.remove delegate delegates_to_remove + in + (maxima, delegates_to_remove)) + (maxima, delegates_to_remove) + active_stakes) (Signature.Public_key_hash.Map.empty, cleared_cycle_delegates) cycles diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.ml b/src/proto_alpha/lib_protocol/delegate_sampler.ml index a32815a4d600..a7ddf813b532 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.ml +++ b/src/proto_alpha/lib_protocol/delegate_sampler.ml @@ -192,7 +192,15 @@ let get_stakes_for_selected_index ctxt index = let*? r = max_mutez /? frozen_deposits_percentage in return r in - let stake_for_cycle = Stake_repr.make ~total:total_stake_for_cycle in + let delegated = + (* This subtraction should not result in a negative value because the + staking balance includes the total balance. + But since the staking balance is taken from the snapshot and the + frozen balance is taken at the end of the cycle we have no strong + guarantees. *) + sub_opt total_stake_for_cycle frozen |> Option.value ~default:zero + in + let stake_for_cycle = Stake_repr.make ~frozen ~delegated in let*? total_stake = Stake_repr.(total_stake +? stake_for_cycle) in return ((delegate, stake_for_cycle) :: acc, total_stake)) ~init:([], Stake_repr.zero) diff --git a/src/proto_alpha/lib_protocol/stake_repr.ml b/src/proto_alpha/lib_protocol/stake_repr.ml index 006320bf93cf..655ba7e3b8ea 100644 --- a/src/proto_alpha/lib_protocol/stake_repr.ml +++ b/src/proto_alpha/lib_protocol/stake_repr.ml @@ -23,22 +23,28 @@ (* *) (*****************************************************************************) -type t = {total : Tez_repr.t} +type t = {frozen : Tez_repr.t; delegated : Tez_repr.t} -let make ~total = {total} +let make ~frozen ~delegated = {frozen; delegated} -let total {total} = total +let total {frozen; delegated} = Tez_repr.(frozen +? delegated) let encoding = - Data_encoding.conv total (fun total -> make ~total) Tez_repr.encoding + let open Data_encoding in + conv + (fun {frozen; delegated} -> (frozen, delegated)) + (fun (frozen, delegated) -> {frozen; delegated}) + (obj2 (req "frozen" Tez_repr.encoding) (req "delegated" Tez_repr.encoding)) -let zero = make ~total:Tez_repr.zero +let zero = make ~frozen:Tez_repr.zero ~delegated:Tez_repr.zero -let staking_weight stake = Tez_repr.to_mutez (total stake) +let staking_weight {frozen; delegated} = + Int64.add (Tez_repr.to_mutez frozen) (Tez_repr.to_mutez delegated) let compare s1 s2 = Int64.compare (staking_weight s1) (staking_weight s2) -let ( +? ) s1 s2 = +let ( +? ) {frozen = f1; delegated = d1} {frozen = f2; delegated = d2} = let open Result_syntax in - let+ total = Tez_repr.(total s1 +? total s2) in - make ~total + let* frozen = Tez_repr.(f1 +? f2) in + let+ delegated = Tez_repr.(d1 +? d2) in + {frozen; delegated} diff --git a/src/proto_alpha/lib_protocol/stake_repr.mli b/src/proto_alpha/lib_protocol/stake_repr.mli index 5e5768410bb5..70a0e131584f 100644 --- a/src/proto_alpha/lib_protocol/stake_repr.mli +++ b/src/proto_alpha/lib_protocol/stake_repr.mli @@ -28,11 +28,12 @@ type t val zero : t -val make : total:Tez_repr.t -> t +val make : frozen:Tez_repr.t -> delegated:Tez_repr.t -> t val encoding : t Data_encoding.t -val total : t -> Tez_repr.t +(** Sum of the [frozen] and [delegated] parts of a stake. *) +val total : t -> Tez_repr.t tzresult (** Weight for staking rights. *) val staking_weight : t -> int64 -- GitLab From 08a8b1b815ab560baa95b483c1114e17f70020ed Mon Sep 17 00:00:00 2001 From: Mehdi Bouaziz Date: Thu, 27 Apr 2023 11:55:22 +0200 Subject: [PATCH 7/7] Proto: add stitching for stake distribution --- src/proto_alpha/lib_protocol/init_storage.ml | 45 +++++++++++++++++++- src/proto_alpha/lib_protocol/storage.ml | 31 ++++++++++++++ src/proto_alpha/lib_protocol/storage.mli | 14 ++++++ 3 files changed, 89 insertions(+), 1 deletion(-) diff --git a/src/proto_alpha/lib_protocol/init_storage.ml b/src/proto_alpha/lib_protocol/init_storage.ml index 35b22e66a083..e6e33340adaf 100644 --- a/src/proto_alpha/lib_protocol/init_storage.ml +++ b/src/proto_alpha/lib_protocol/init_storage.ml @@ -103,6 +103,48 @@ let patch_script ctxt (address, hash, patched_code) = address ; return ctxt +(** Converts {Storage.Stake.Total_active_stake} and + {Storage.Stake.Selected_distribution_for_cycle} from {Tez_repr} to + {Stake_repr}. + Remove me in P. *) +let migrate_stake_distribution_for_o ctxt = + let open Lwt_result_syntax in + let convert = + let max_delegated_percentage = + let frozen_deposits_percentage = + Constants_storage.frozen_deposits_percentage ctxt + in + Int64.of_int (100 - frozen_deposits_percentage) + in + fun old_stake -> + let delegated = + match Tez_repr.(old_stake *? max_delegated_percentage) with + | Error _unexpected_overflow -> Tez_repr.zero + | Ok delegated_times_100 -> Tez_repr.div_exn delegated_times_100 100 + in + match Tez_repr.sub_opt old_stake delegated with + | None -> Stake_repr.make ~frozen:old_stake ~delegated:Tez_repr.zero + | Some frozen -> Stake_repr.make ~frozen ~delegated + in + let* ctxt = + Storage.Stake.Total_active_stake_up_to_Nairobi.fold + ctxt + ~order:`Undefined + ~init:(ok ctxt) + ~f:(fun cycle stake ctxt -> + let*? ctxt in + let stake = convert stake in + Storage.Stake.Total_active_stake.update ctxt cycle stake) + in + Storage.Stake.Selected_distribution_for_cycle_up_to_Nairobi.fold + ctxt + ~order:`Undefined + ~init:(ok ctxt) + ~f:(fun cycle distr ctxt -> + let*? ctxt in + let distr = List.map (fun (pkh, stake) -> (pkh, convert stake)) distr in + Storage.Stake.Selected_distribution_for_cycle.update ctxt cycle distr) + let prepare_first_block _chain_id ctxt ~typecheck ~level ~timestamp ~predecessor = Raw_context.prepare_first_block ~level ~timestamp ctxt @@ -169,7 +211,8 @@ let prepare_first_block _chain_id ctxt ~typecheck ~level ~timestamp ~predecessor inbox migration message. see `sc_rollup_inbox_storage`. *) Raw_level_repr.of_int32 level >>?= fun level -> Storage.Tenderbake.First_level_of_protocol.update ctxt level - >>=? fun ctxt -> return (ctxt, [])) + >>=? fun ctxt -> + migrate_stake_distribution_for_o ctxt >>=? fun ctxt -> return (ctxt, [])) >>=? fun (ctxt, balance_updates) -> List.fold_left_es patch_script ctxt Legacy_script_patches.addresses_to_patch >>=? fun ctxt -> diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index 0b16b49c6a15..86e52b2cf407 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -991,6 +991,24 @@ module Cycle = struct (Pair (Make_index (Raw_level_repr.Index)) (Public_key_hash_index)) (Slashed_level) + (* Remove me in P. *) + module Selected_stake_distribution_up_to_Nairobi = + Indexed_context.Make_map + (Ghost) + (struct + let name = ["selected_stake_distribution"] + end) + (struct + type t = (Signature.Public_key_hash.t * Tez_repr.t) list + + let encoding = + Data_encoding.( + Variable.list + (obj2 + (req "baker" Signature.Public_key_hash.encoding) + (req "active_stake" Tez_repr.encoding))) + end) + module Selected_stake_distribution = Indexed_context.Make_map (Registered) @@ -1008,6 +1026,15 @@ module Cycle = struct (req "active_stake" Stake_repr.encoding))) end) + (* Remove me in P. *) + module Total_active_stake_up_to_Nairobi = + Indexed_context.Make_map + (Ghost) + (struct + let name = ["total_active_stake"] + end) + (Tez_repr) + module Total_active_stake = Indexed_context.Make_map (Registered) @@ -1112,7 +1139,11 @@ module Stake = struct let encoding = Data_encoding.unit end) + module Selected_distribution_for_cycle_up_to_Nairobi = + Cycle.Selected_stake_distribution_up_to_Nairobi module Selected_distribution_for_cycle = Cycle.Selected_stake_distribution + module Total_active_stake_up_to_Nairobi = + Cycle.Total_active_stake_up_to_Nairobi module Total_active_stake = Cycle.Total_active_stake (* This is an index that is set to 0 by calls to diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index ba1b81f0144b..a82d10ee85a5 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -412,6 +412,13 @@ module Stake : sig module Last_snapshot : Single_data_storage with type value = int and type t := Raw_context.t + (* Remove me in P. *) + module Selected_distribution_for_cycle_up_to_Nairobi : + Indexed_data_storage + with type key = Cycle_repr.t + and type value = (Signature.Public_key_hash.t * Tez_repr.t) list + and type t := Raw_context.t + (** List of active stake *) module Selected_distribution_for_cycle : Indexed_data_storage @@ -419,6 +426,13 @@ module Stake : sig and type value = (Signature.Public_key_hash.t * Stake_repr.t) list and type t := Raw_context.t + (* Remove me in P. *) + module Total_active_stake_up_to_Nairobi : + Indexed_data_storage + with type key = Cycle_repr.t + and type value = Tez_repr.t + and type t := Raw_context.t + (** Sum of the active stakes of all the delegates with {!Constants_parametric_repr.minimal_stake} *) module Total_active_stake : -- GitLab