From 6f25fecdeb2b50c87c46633061bfccbe779de0d9 Mon Sep 17 00:00:00 2001 From: Mehdi Bouaziz Date: Mon, 13 Mar 2023 17:55:53 +0100 Subject: [PATCH 01/10] Proto/Apply: remove dead error Zero_frozen_deposits (moved to Validate_errors) --- src/proto_alpha/lib_protocol/apply.ml | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 97c4b26c200c..6297781f73c5 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -43,7 +43,6 @@ type error += | Internal_operation_replay of Apply_internal_results.packed_internal_operation | Multiple_revelation - | Zero_frozen_deposits of Signature.Public_key_hash.t | Invalid_transfer_to_sc_rollup | Invalid_source of Destination.t @@ -216,21 +215,6 @@ let () = Data_encoding.empty (function Multiple_revelation -> Some () | _ -> None) (fun () -> Multiple_revelation) ; - register_error_kind - `Permanent - ~id:"delegate.zero_frozen_deposits" - ~title:"Zero frozen deposits" - ~description:"The delegate has zero frozen deposits." - ~pp:(fun ppf delegate -> - Format.fprintf - ppf - "Delegate %a has zero frozen deposits; it is not allowed to \ - bake/preendorse/endorse." - Signature.Public_key_hash.pp - delegate) - Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) - (function Zero_frozen_deposits delegate -> Some delegate | _ -> None) - (fun delegate -> Zero_frozen_deposits delegate) ; register_error_kind `Permanent ~id:"operations.invalid_transfer_to_smart_rollup_from_implicit_account" -- GitLab From 23a8b0773cde01410682cface5dcf9f89c9b3c11 Mon Sep 17 00:00:00 2001 From: Mehdi Bouaziz Date: Mon, 13 Mar 2023 11:29:57 +0100 Subject: [PATCH 02/10] Proto/Delegate_cycles: fix typo --- src/proto_alpha/lib_protocol/delegate_cycles.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.ml b/src/proto_alpha/lib_protocol/delegate_cycles.ml index 943467e4155d..cad6e014594b 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.ml +++ b/src/proto_alpha/lib_protocol/delegate_cycles.ml @@ -263,8 +263,8 @@ let cycle_end ctxt last_cycle = >>=? fun (ctxt, balance_updates) -> Stake_storage.clear_at_cycle_end ctxt ~new_cycle >>=? fun ctxt -> Delegate_sampler.clear_outdated_sampling_data ctxt ~new_cycle >>=? fun ctxt -> - update_activity ctxt last_cycle >>=? fun (ctxt, deactivated_delagates) -> - return (ctxt, balance_updates, deactivated_delagates) + update_activity ctxt last_cycle >>=? fun (ctxt, deactivated_delegates) -> + return (ctxt, balance_updates, deactivated_delegates) let init_first_cycles ctxt ~origin = let preserved = Constants_storage.preserved_cycles ctxt in -- GitLab From 4c68bde672b9db403c76249a776f5038272ae118 Mon Sep 17 00:00:00 2001 From: Mehdi Bouaziz Date: Thu, 9 Mar 2023 22:00:23 +0100 Subject: [PATCH 03/10] Proto/Stake_storage: optimize remove_stake --- src/proto_alpha/lib_protocol/stake_storage.ml | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/proto_alpha/lib_protocol/stake_storage.ml b/src/proto_alpha/lib_protocol/stake_storage.ml index 08549fa26a2c..b0d2d00c8815 100644 --- a/src/proto_alpha/lib_protocol/stake_storage.ml +++ b/src/proto_alpha/lib_protocol/stake_storage.ml @@ -76,16 +76,22 @@ let remove_stake ctxt delegate amount = 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) then + 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 (not inactive) && Tez_repr.(staking_balance < minimal_stake) then + if not inactive then Storage.Stake.Active_delegates_with_minimal_stake.remove ctxt delegate >>= fun ctxt -> return ctxt else return ctxt else - (* The delegate was not in Stake.Active_delegates_with_minimal_stake, - either because it was inactive, or because it did not have a - the minimal required stake, in which case it still does not have it. *) + (* 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 = -- GitLab From 487c9e49f9139fedb240ba4d033ed41050c3e62d Mon Sep 17 00:00:00 2001 From: Mehdi Bouaziz Date: Thu, 9 Mar 2023 22:05:35 +0100 Subject: [PATCH 04/10] Proto/Stake_storage: one less negation --- src/proto_alpha/lib_protocol/stake_storage.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/proto_alpha/lib_protocol/stake_storage.ml b/src/proto_alpha/lib_protocol/stake_storage.ml index b0d2d00c8815..9ecbc33ec9f9 100644 --- a/src/proto_alpha/lib_protocol/stake_storage.ml +++ b/src/proto_alpha/lib_protocol/stake_storage.ml @@ -81,10 +81,10 @@ let remove_stake ctxt delegate amount = && Tez_repr.(staking_balance < minimal_stake) then Delegate_activation_storage.is_inactive ctxt delegate >>=? fun inactive -> - if not inactive then + if inactive then return ctxt + else Storage.Stake.Active_delegates_with_minimal_stake.remove ctxt delegate >>= fun ctxt -> return ctxt - else 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 -- GitLab From b8f74afacb76f9436208ff01027aa8f370747412 Mon Sep 17 00:00:00 2001 From: Mehdi Bouaziz Date: Thu, 9 Mar 2023 22:05:59 +0100 Subject: [PATCH 05/10] Proto/Stake_storage: optimize add_stake --- src/proto_alpha/lib_protocol/stake_storage.ml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/proto_alpha/lib_protocol/stake_storage.ml b/src/proto_alpha/lib_protocol/stake_storage.ml index 9ecbc33ec9f9..c964488e0f61 100644 --- a/src/proto_alpha/lib_protocol/stake_storage.ml +++ b/src/proto_alpha/lib_protocol/stake_storage.ml @@ -100,17 +100,22 @@ let add_stake ctxt delegate amount = 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 >= minimal_stake) then + 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 || Tez_repr.(staking_balance_before >= minimal_stake) then - return ctxt + if inactive then return ctxt else Storage.Stake.Active_delegates_with_minimal_stake.add ctxt delegate () >>= fun ctxt -> return ctxt else - (* The delegate was not in Stake.Active_delegates_with_minimal_stake, - because it did not have the minimal required stake (as otherwise it - would also have it now). *) + (* The delegate was not in Stake.Active_delegates_with_minimal_stake, either + - because it did not have the minimal required stake and still does not + 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 let set_inactive ctxt delegate = -- GitLab From bfdcaf31459b8a3ee323b18ddfe80dd3fedf5c02 Mon Sep 17 00:00:00 2001 From: Mehdi Bouaziz Date: Mon, 13 Mar 2023 14:52:08 +0100 Subject: [PATCH 06/10] Proto/Delegate_sampler: max_mutez already exists --- src/proto_alpha/lib_protocol/delegate_sampler.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.ml b/src/proto_alpha/lib_protocol/delegate_sampler.ml index 19e92d876cb8..60fc2f276fb4 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.ml +++ b/src/proto_alpha/lib_protocol/delegate_sampler.ml @@ -175,7 +175,6 @@ let get_stakes_for_selected_index ctxt index = let frozen_deposits_percentage = Int64.of_int @@ Constants_storage.frozen_deposits_percentage ctxt in - let max_mutez = of_mutez_exn Int64.max_int in let frozen_deposits_limit = match frozen_deposits_limit with Some fdp -> fdp | None -> max_mutez in -- GitLab From ee3f2aadfb8ebc76f1f2d8ba16ef06712170fa84 Mon Sep 17 00:00:00 2001 From: Mehdi Bouaziz Date: Mon, 13 Mar 2023 14:52:45 +0100 Subject: [PATCH 07/10] Proto/Delegate_sampler: get frozen_deposits_percentage once --- src/proto_alpha/lib_protocol/delegate_sampler.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.ml b/src/proto_alpha/lib_protocol/delegate_sampler.ml index 60fc2f276fb4..68dc9a82bc83 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.ml +++ b/src/proto_alpha/lib_protocol/delegate_sampler.ml @@ -152,6 +152,9 @@ let load_sampler_for_cycle ctxt cycle = return ctxt let get_stakes_for_selected_index ctxt index = + let frozen_deposits_percentage = + Int64.of_int @@ Constants_storage.frozen_deposits_percentage ctxt + in Stake_storage.fold_snapshot ctxt ~index @@ -172,9 +175,6 @@ let get_stakes_for_selected_index ctxt index = balance_and_frozen_bonds +? frozen_deposits.current_amount in let* stake_for_cycle = - let frozen_deposits_percentage = - Int64.of_int @@ Constants_storage.frozen_deposits_percentage ctxt - in let frozen_deposits_limit = match frozen_deposits_limit with Some fdp -> fdp | None -> max_mutez in -- GitLab From dfb1afec2dff328a2e90d113d612f1500f69d71b Mon Sep 17 00:00:00 2001 From: Mehdi Bouaziz Date: Mon, 13 Mar 2023 14:54:26 +0100 Subject: [PATCH 08/10] Proto/Delegate_sampler: compute overflow_bound once --- src/proto_alpha/lib_protocol/delegate_sampler.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.ml b/src/proto_alpha/lib_protocol/delegate_sampler.ml index 68dc9a82bc83..03594e25a63b 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.ml +++ b/src/proto_alpha/lib_protocol/delegate_sampler.ml @@ -152,16 +152,17 @@ let load_sampler_for_cycle ctxt cycle = return ctxt let get_stakes_for_selected_index ctxt index = + let open Lwt_result_syntax in let frozen_deposits_percentage = Int64.of_int @@ Constants_storage.frozen_deposits_percentage ctxt in + let*? overflow_bound = Tez_repr.(max_mutez /? 100L) in Stake_storage.fold_snapshot ctxt ~index ~f:(fun (delegate, staking_balance) (acc, total_stake) -> let delegate_contract = Contract_repr.Implicit delegate in let open Tez_repr in - let open Lwt_result_syntax in let* frozen_deposits_limit = Delegate_storage.frozen_deposits_limit ctxt delegate in @@ -179,7 +180,6 @@ let get_stakes_for_selected_index ctxt index = match frozen_deposits_limit with Some fdp -> fdp | None -> max_mutez in let aux = min total_balance frozen_deposits_limit in - let*? overflow_bound = max_mutez /? 100L in if aux <= overflow_bound then let*? aux = aux *? 100L in let*? v = aux /? frozen_deposits_percentage in -- GitLab From 284d186b98b61eecea6110b7498a7736d2f25ffe Mon Sep 17 00:00:00 2001 From: Mehdi Bouaziz Date: Mon, 13 Mar 2023 17:51:22 +0100 Subject: [PATCH 09/10] Proto/Delegate_cycles: optimize max_frozen_deposits_and_delegates_to_remove Do `* frozen_deposits_percentage / 100` only once per delegate. --- .../lib_protocol/delegate_cycles.ml | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.ml b/src/proto_alpha/lib_protocol/delegate_cycles.ml index cad6e014594b..67c54829c637 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.ml +++ b/src/proto_alpha/lib_protocol/delegate_cycles.ml @@ -48,13 +48,9 @@ let update_activity ctxt last_cycle = (* Return a map from delegates (with active stake at some cycle in the cycle window [from_cycle, to_cycle]) to the maximum - of the stake to be deposited for each such cycle (which is just the - [frozen_deposits_percentage] of the active stake at that cycle). Also + of the active stake in that window. Also return the delegates that have fallen out of the sliding window. *) let max_frozen_deposits_and_delegates_to_remove ctxt ~from_cycle ~to_cycle = - let frozen_deposits_percentage = - Constants_storage.frozen_deposits_percentage ctxt - in let cycles = Cycle_repr.(from_cycle ---> to_cycle) in (match Cycle_repr.pred from_cycle with | None -> return Signature.Public_key_hash.Set.empty @@ -75,16 +71,12 @@ 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_to_be_deposited = - Tez_repr.(div_exn (mul_exn stake frozen_deposits_percentage) 100) - in let maxima = Signature.Public_key_hash.Map.update delegate (function - | None -> Some stake_to_be_deposited - | Some maximum -> - Some (Tez_repr.max maximum stake_to_be_deposited)) + | None -> Some stake + | Some maximum -> Some (Tez_repr.max maximum stake)) maxima in let delegates_to_remove = @@ -115,8 +107,15 @@ let freeze_deposits ?(origin = Receipt_repr.Block_application) ctxt ~new_cycle let to_cycle = Cycle_repr.(add new_cycle preserved_cycles) in max_frozen_deposits_and_delegates_to_remove ctxt ~from_cycle ~to_cycle >>=? fun (maxima, delegates_to_remove) -> + let frozen_deposits_percentage = + Constants_storage.frozen_deposits_percentage ctxt + in Signature.Public_key_hash.Map.fold_es - (fun delegate maximum_stake_to_be_deposited (ctxt, balance_updates) -> + (fun delegate maximum_stake (ctxt, balance_updates) -> + let maximum_stake_to_be_deposited = + Tez_repr.( + div_exn (mul_exn maximum_stake frozen_deposits_percentage) 100) + in (* Here we make sure to preserve the following invariant : maximum_stake_to_be_deposited <= frozen_deposits + balance See select_distribution_for_cycle *) -- GitLab From df3d1f7f3371db60808fced8ad31eca3e777cc7a Mon Sep 17 00:00:00 2001 From: Mehdi Bouaziz Date: Tue, 14 Mar 2023 14:12:11 +0100 Subject: [PATCH 10/10] Proto/Stake_storage: use cache in find_selected_distribution It is only used in `Delegate_cycles.max_frozen_deposits_and_delegates_to_remove` to get the distribution of the `cleared_cycle = new_cycle - max_slashing_period`. --- src/proto_alpha/lib_protocol/stake_storage.ml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/proto_alpha/lib_protocol/stake_storage.ml b/src/proto_alpha/lib_protocol/stake_storage.ml index c964488e0f61..6d85c97e73fd 100644 --- a/src/proto_alpha/lib_protocol/stake_storage.ml +++ b/src/proto_alpha/lib_protocol/stake_storage.ml @@ -53,6 +53,12 @@ module Selected_distribution_for_cycle = struct | None -> Storage.Stake.Selected_distribution_for_cycle.get ctxt cycle | Some v -> return v + let find ctxt cycle = + let id = identifier_of_cycle cycle in + Cache.find ctxt id >>=? function + | None -> Storage.Stake.Selected_distribution_for_cycle.find ctxt cycle + | Some _ as some_v -> return some_v + let remove_existing ctxt cycle = let id = identifier_of_cycle cycle in Cache.update ctxt id None >>?= fun ctxt -> @@ -192,8 +198,7 @@ let fold_on_active_delegates_with_minimal_stake = let get_selected_distribution = Selected_distribution_for_cycle.get -let find_selected_distribution = - Storage.Stake.Selected_distribution_for_cycle.find +let find_selected_distribution = Selected_distribution_for_cycle.find let prepare_stake_distribution ctxt = let level = Level_storage.current ctxt in -- GitLab