diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 97c4b26c200c29d8543fea9d1c7b88f87166928b..6297781f73c5a9d2f79394109ee770ded4ce9e54 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" diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.ml b/src/proto_alpha/lib_protocol/delegate_cycles.ml index 943467e4155dfb370a4caa5243341e12f1b81f99..67c54829c6373c93beeaed403db8089bd6d44ab2 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 *) @@ -263,8 +262,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 diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.ml b/src/proto_alpha/lib_protocol/delegate_sampler.ml index 19e92d876cb8416f89c974a8714f51d497656e05..03594e25a63b967c32e74ccfb0bcf4909074a5a1 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.ml +++ b/src/proto_alpha/lib_protocol/delegate_sampler.ml @@ -152,13 +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 @@ -172,15 +176,10 @@ 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 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 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 diff --git a/src/proto_alpha/lib_protocol/stake_storage.ml b/src/proto_alpha/lib_protocol/stake_storage.ml index 08549fa26a2c5bc84bd10820600bcbbe8fc2b714..6d85c97e73fd93686fed35a719059df95500e287 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 -> @@ -76,16 +82,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 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 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 = @@ -94,17 +106,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 = @@ -181,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