diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.ml b/src/proto_alpha/lib_protocol/delegate_cycles.ml index 6ec818139def89ceeb4791282a05f8fb88f0cdfd..94510caa4530c691889c544a0b13bb6fbda111c4 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.ml +++ b/src/proto_alpha/lib_protocol/delegate_cycles.ml @@ -126,10 +126,12 @@ let adjust_frozen_stakes ctxt ~deactivated_delegates : ~order:`Undefined ~init:(ctxt, []) ~f:(fun delegate (ctxt, balance_updates) -> - let* ({own_frozen; _} as full_staking_balance : - Full_staking_balance_repr.t) = + let* full_staking_balance = Stake_storage.get_full_staking_balance ctxt delegate in + let own_frozen = + Full_staking_balance_repr.own_frozen full_staking_balance + in let*? optimal_frozen = Stake_context.optimal_frozen_wrt_delegated_without_ai ctxt diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.ml b/src/proto_alpha/lib_protocol/delegate_sampler.ml index 7e1b60768985a15b93fffa41da58139c31571dd0..5f11a87febefade8bc7b6c2fe676336ac223f398 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.ml +++ b/src/proto_alpha/lib_protocol/delegate_sampler.ml @@ -168,24 +168,36 @@ let get_delegate_stake_from_staking_balance ctxt delegate staking_balance = let get_stakes_for_selected_index ctxt ~slashings index = let open Lwt_result_syntax in + let minimal_frozen_stake = Constants_storage.minimal_frozen_stake ctxt in + let minimal_stake = Constants_storage.minimal_stake ctxt in Stake_storage.fold_snapshot ctxt ~index - ~f:(fun (delegate, staking_balance) (acc, total_stake) -> + ~f:(fun (delegate, staking_balance) acc -> let staking_balance = match Signature.Public_key_hash.Map.find delegate slashings with | None -> staking_balance | Some percentage -> Full_staking_balance_repr.apply_slashing ~percentage staking_balance in - let* stake_for_cycle = - get_delegate_stake_from_staking_balance ctxt delegate staking_balance - in - if Stake_storage.has_minimal_stake_and_frozen_stake ctxt staking_balance + if + Full_staking_balance_repr.has_minimal_frozen_stake + ~minimal_frozen_stake + staking_balance then - let*? total_stake = Stake_repr.(total_stake +? stake_for_cycle) in - return ((delegate, stake_for_cycle) :: acc, total_stake) - else return (acc, total_stake)) + let* stake_for_cycle = + get_delegate_stake_from_staking_balance ctxt delegate staking_balance + in + if + Stake_repr.has_minimal_stake_to_participate + ~minimal_stake + stake_for_cycle + then + let stakes, total_stake = acc in + let*? total_stake = Stake_repr.(total_stake +? stake_for_cycle) in + return ((delegate, stake_for_cycle) :: stakes, total_stake) + else return acc + else return acc) ~init:([], Stake_repr.zero) let compute_snapshot_index_for_seed ~max_snapshot_index seed = diff --git a/src/proto_alpha/lib_protocol/delegate_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index 04ee724eba8d941c73970d9882645579780422f4..b588082584542599f221f00ab2b27dfdf4b6ffa6 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -286,11 +286,10 @@ let initial_frozen_deposits_of_previous_cycle ctxt delegate = let current_frozen_deposits ctxt delegate = let open Lwt_result_syntax in - let* {own_frozen; staked_frozen; delegated = _} = + let* full_staking_balance = Stake_storage.get_full_staking_balance ctxt delegate in - let*? total = Tez_repr.(own_frozen +? staked_frozen) in - return total + Lwt.return (Full_staking_balance_repr.total_frozen full_staking_balance) let frozen_deposits_limit ctxt delegate = Storage.Contract.Frozen_deposits_limit.find diff --git a/src/proto_alpha/lib_protocol/full_staking_balance_repr.ml b/src/proto_alpha/lib_protocol/full_staking_balance_repr.ml index 1d0e825c5522470edd890c4860db08c6f903ee56..f697fecbd933ae73ffa49aebc4179d46c59bf1ae 100644 --- a/src/proto_alpha/lib_protocol/full_staking_balance_repr.ml +++ b/src/proto_alpha/lib_protocol/full_staking_balance_repr.ml @@ -11,7 +11,7 @@ type t = { delegated : Tez_repr.t; } -let make ~own_frozen ~staked_frozen ~delegated = +let init ~own_frozen ~staked_frozen ~delegated = {own_frozen; staked_frozen; delegated} let encoding = @@ -41,3 +41,66 @@ let apply_slashing ~percentage {own_frozen; staked_frozen; delegated} = Tez_repr.mul_percentage ~rounding:`Down staked_frozen remaining_percentage in {own_frozen; staked_frozen; delegated} + +let own_frozen {own_frozen; staked_frozen = _; delegated = _} = own_frozen + +let staked_frozen {own_frozen = _; staked_frozen; delegated = _} = staked_frozen + +let total_frozen {own_frozen; staked_frozen; delegated = _} = + Tez_repr.(own_frozen +? staked_frozen) + +let delegated {own_frozen = _; staked_frozen = _; delegated} = delegated + +let total {own_frozen; staked_frozen; delegated} = + let open Result_syntax in + let* total_frozen = Tez_repr.(own_frozen +? staked_frozen) in + Tez_repr.(total_frozen +? delegated) + +let own_ratio {own_frozen; staked_frozen; delegated = _} = + if Tez_repr.(staked_frozen = zero) then (1L, 1L) + else if Tez_repr.(own_frozen = zero) then (0L, 1L) + else + let own_frozen = Tez_repr.to_mutez own_frozen in + let staked_frozen = Tez_repr.to_mutez staked_frozen in + (own_frozen, Int64.add own_frozen staked_frozen) + +let has_minimal_frozen_stake ~minimal_frozen_stake + {own_frozen; staked_frozen = _; delegated = _} = + Tez_repr.(own_frozen >= minimal_frozen_stake) + +let has_minimal_stake_to_be_considered ~minimal_stake full_staking_balance = + match total full_staking_balance with + | Error _total_overflows -> + true + (* If the total overflows, we are definitely over the minimal stake. *) + | Ok staking_balance -> Tez_repr.(staking_balance >= minimal_stake) + +let remove_delegated ~amount {own_frozen; staked_frozen; delegated} = + let open Result_syntax in + let+ delegated = Tez_repr.(delegated -? amount) in + {own_frozen; staked_frozen; delegated} + +let remove_own_frozen ~amount {own_frozen; staked_frozen; delegated} = + let open Result_syntax in + let+ own_frozen = Tez_repr.(own_frozen -? amount) in + {own_frozen; staked_frozen; delegated} + +let remove_staked_frozen ~amount {own_frozen; staked_frozen; delegated} = + let open Result_syntax in + let+ staked_frozen = Tez_repr.(staked_frozen -? amount) in + {own_frozen; staked_frozen; delegated} + +let add_delegated ~amount {own_frozen; staked_frozen; delegated} = + let open Result_syntax in + let+ delegated = Tez_repr.(delegated +? amount) in + {own_frozen; staked_frozen; delegated} + +let add_own_frozen ~amount {own_frozen; staked_frozen; delegated} = + let open Result_syntax in + let+ own_frozen = Tez_repr.(own_frozen +? amount) in + {own_frozen; staked_frozen; delegated} + +let add_staked_frozen ~amount {own_frozen; staked_frozen; delegated} = + let open Result_syntax in + let+ staked_frozen = Tez_repr.(staked_frozen +? amount) in + {own_frozen; staked_frozen; delegated} diff --git a/src/proto_alpha/lib_protocol/full_staking_balance_repr.mli b/src/proto_alpha/lib_protocol/full_staking_balance_repr.mli index 0fde0fbfd3ec279e897f724cc6c32a0ff1eef609..ac49289e14a3a946290796da3b1937b6470239ff 100644 --- a/src/proto_alpha/lib_protocol/full_staking_balance_repr.mli +++ b/src/proto_alpha/lib_protocol/full_staking_balance_repr.mli @@ -5,13 +5,9 @@ (* *) (*****************************************************************************) -type t = private { - own_frozen : Tez_repr.t; - staked_frozen : Tez_repr.t; - delegated : Tez_repr.t; -} +type t -val make : +val init : own_frozen:Tez_repr.t -> staked_frozen:Tez_repr.t -> delegated:Tez_repr.t -> t val encoding : t Data_encoding.t @@ -20,3 +16,36 @@ val encoding : t Data_encoding.t val voting_weight : t -> Int64.t tzresult val apply_slashing : percentage:Int_percentage.t -> t -> t + +val own_frozen : t -> Tez_repr.t + +val staked_frozen : t -> Tez_repr.t + +val delegated : t -> Tez_repr.t + +(** Sum of [own_frozen] and [staked_frozen]. *) +val total_frozen : t -> Tez_repr.t tzresult + +(** Sum of [own_frozen], [staked_frozen], and [delegated]. *) +val total : t -> Tez_repr.t tzresult + +(** [own_ratio full_staking_balance] returns [(num, den)] representing the +ratio of [own_frozen] over [total_frozen] for [full_staking_balance]. +If [total_frozen] is zero, the returned ratio is [(1L, 1L)]. *) +val own_ratio : t -> Int64.t * Int64.t + +val has_minimal_frozen_stake : minimal_frozen_stake:Tez_repr.t -> t -> bool + +val has_minimal_stake_to_be_considered : minimal_stake:Tez_repr.t -> t -> bool + +val remove_delegated : amount:Tez_repr.t -> t -> t tzresult + +val remove_own_frozen : amount:Tez_repr.t -> t -> t tzresult + +val remove_staked_frozen : amount:Tez_repr.t -> t -> t tzresult + +val add_delegated : amount:Tez_repr.t -> t -> t tzresult + +val add_own_frozen : amount:Tez_repr.t -> t -> t tzresult + +val add_staked_frozen : amount:Tez_repr.t -> t -> t tzresult diff --git a/src/proto_alpha/lib_protocol/shared_stake.ml b/src/proto_alpha/lib_protocol/shared_stake.ml index 6a855e8590b6a5b67e618301b92606e49d79133d..5164e4a391df5380f7acda7310ba60b3c149a332 100644 --- a/src/proto_alpha/lib_protocol/shared_stake.ml +++ b/src/proto_alpha/lib_protocol/shared_stake.ml @@ -9,25 +9,15 @@ type shared = {baker_part : Tez_repr.t; stakers_part : Tez_repr.t} let share ~rounding ~full_staking_balance amount = let open Result_syntax in - let Full_staking_balance_repr.{own_frozen; staked_frozen; delegated = _} = - full_staking_balance - in - if Tez_repr.(staked_frozen = zero) then - return {baker_part = amount; stakers_part = Tez_repr.zero} - else - let* total_frozen = Tez_repr.(own_frozen +? staked_frozen) in - let* baker_part = - let rounding = - match rounding with `Towards_stakers -> `Down | `Towards_baker -> `Up - in - Tez_repr.mul_ratio - ~rounding - amount - ~num:(Tez_repr.to_mutez own_frozen) - ~den:(Tez_repr.to_mutez total_frozen) + let num, den = Full_staking_balance_repr.own_ratio full_staking_balance in + let* baker_part = + let rounding = + match rounding with `Towards_stakers -> `Down | `Towards_baker -> `Up in - let* stakers_part = Tez_repr.(amount -? baker_part) in - return {baker_part; stakers_part} + Tez_repr.mul_ratio ~rounding amount ~num ~den + in + let* stakers_part = Tez_repr.(amount -? baker_part) in + return {baker_part; stakers_part} type reward_distrib = { to_baker_from_staking : Tez_repr.t; diff --git a/src/proto_alpha/lib_protocol/stake_context.ml b/src/proto_alpha/lib_protocol/stake_context.ml index 44114a327c01bf541fd0d563ed923872aa901c9a..4cbe0b84c1982de46c56deb343ed7287ebdba11d 100644 --- a/src/proto_alpha/lib_protocol/stake_context.ml +++ b/src/proto_alpha/lib_protocol/stake_context.ml @@ -23,9 +23,11 @@ (* *) (*****************************************************************************) -let apply_limits ctxt staking_parameters - {Full_staking_balance_repr.own_frozen; staked_frozen; delegated} = +let apply_limits ctxt staking_parameters staking_balance = let open Result_syntax in + let own_frozen = Full_staking_balance_repr.own_frozen staking_balance in + let staked_frozen = Full_staking_balance_repr.staked_frozen staking_balance in + let delegated = Full_staking_balance_repr.delegated staking_balance in let limit_of_delegation_over_baking = Int64.of_int (Constants_storage.limit_of_delegation_over_baking ctxt) in @@ -83,8 +85,7 @@ let apply_limits ctxt staking_parameters let+ frozen = Tez_repr.(own_frozen +? allowed_staked_frozen) in Stake_repr.make ~frozen ~weighted_delegated -let optimal_frozen_wrt_delegated_without_ai ctxt - {Full_staking_balance_repr.delegated; own_frozen; _} = +let optimal_frozen_wrt_delegated_without_ai ctxt full_staking_balance = let open Result_syntax in let limit_of_delegation_over_baking = Int64.of_int (Constants_storage.limit_of_delegation_over_baking ctxt) @@ -96,6 +97,8 @@ let optimal_frozen_wrt_delegated_without_ai ctxt With AI the optimum is to freeze as much as possible, this computation would make no sense. *) + let delegated = Full_staking_balance_repr.delegated full_staking_balance in + let own_frozen = Full_staking_balance_repr.own_frozen full_staking_balance in let* power = Tez_repr.(delegated +? own_frozen) in let* opti_frozen = Tez_repr.mul_ratio diff --git a/src/proto_alpha/lib_protocol/stake_repr.ml b/src/proto_alpha/lib_protocol/stake_repr.ml index b5da168279a64abbabba0e47b888c0d9e7fba12a..8dd7364b79fbf3dbc9155fccb01447acc36821bb 100644 --- a/src/proto_alpha/lib_protocol/stake_repr.ml +++ b/src/proto_alpha/lib_protocol/stake_repr.ml @@ -51,3 +51,9 @@ let staking_weight {frozen; weighted_delegated} = Int64.add frozen weighted_delegated let compare s1 s2 = Int64.compare (staking_weight s1) (staking_weight s2) + +let has_minimal_stake_to_participate ~minimal_stake {frozen; weighted_delegated} + = + match Tez_repr.(frozen +? weighted_delegated) with + | Error _total_overflows -> true + | Ok total -> Tez_repr.(total >= minimal_stake) diff --git a/src/proto_alpha/lib_protocol/stake_repr.mli b/src/proto_alpha/lib_protocol/stake_repr.mli index e7f58ea9c875eeb613b87b32e7ec87785388e65b..b136f0e0a0c43565cc7ce47e61d389ba3893662e 100644 --- a/src/proto_alpha/lib_protocol/stake_repr.mli +++ b/src/proto_alpha/lib_protocol/stake_repr.mli @@ -43,3 +43,5 @@ val ( +? ) : t -> t -> t tzresult val staking_weight : t -> int64 val compare : t -> t -> int + +val has_minimal_stake_to_participate : minimal_stake:Tez_repr.t -> t -> bool diff --git a/src/proto_alpha/lib_protocol/stake_storage.ml b/src/proto_alpha/lib_protocol/stake_storage.ml index bd3255e5c265f3d0b6ad131cc17714042da608ea..8ecb2d81188d6abf652fa50b44414259f9dd28f1 100644 --- a/src/proto_alpha/lib_protocol/stake_storage.ml +++ b/src/proto_alpha/lib_protocol/stake_storage.ml @@ -75,30 +75,16 @@ end let get_full_staking_balance = Storage.Stake.Staking_balance.get -let has_minimal_stake ctxt - {Full_staking_balance_repr.own_frozen; staked_frozen; delegated} = - let open Result_syntax in - let open Tez_repr in +let has_minimal_stake ctxt staking_balance = let minimal_stake = Constants_storage.minimal_stake ctxt in - let sum = - let* frozen = own_frozen +? staked_frozen in - frozen +? delegated - in - match sum with - | Error _sum_overflows -> - true (* If the sum overflows, we are definitely over the minimal stake. *) - | Ok staking_balance -> Tez_repr.(staking_balance >= minimal_stake) - -let has_minimal_stake_and_frozen_stake ctxt - ({own_frozen; _} as full_staking_balance : Full_staking_balance_repr.t) = - let minimal_frozen_stake = Constants_storage.minimal_frozen_stake ctxt in - Tez_repr.(own_frozen >= minimal_frozen_stake) - && has_minimal_stake ctxt full_staking_balance + Full_staking_balance_repr.has_minimal_stake_to_be_considered + ~minimal_stake + staking_balance let initialize_delegate ctxt delegate ~delegated = let open Lwt_result_syntax in let balance = - Full_staking_balance_repr.make + Full_staking_balance_repr.init ~own_frozen:Tez_repr.zero ~staked_frozen:Tez_repr.zero ~delegated @@ -153,22 +139,16 @@ let update_stake ~f ctxt delegate = | false, false | true, true -> return ctxt let remove_delegated_stake ctxt delegate amount = - let open Result_syntax in - update_stake ctxt delegate ~f:(fun {own_frozen; staked_frozen; delegated} -> - let+ delegated = Tez_repr.(delegated -? amount) in - Full_staking_balance_repr.make ~own_frozen ~staked_frozen ~delegated) + let f = Full_staking_balance_repr.remove_delegated ~amount in + update_stake ctxt delegate ~f let remove_own_frozen_stake ctxt delegate amount = - let open Result_syntax in - update_stake ctxt delegate ~f:(fun {own_frozen; staked_frozen; delegated} -> - let+ own_frozen = Tez_repr.(own_frozen -? amount) in - Full_staking_balance_repr.make ~own_frozen ~staked_frozen ~delegated) + let f = Full_staking_balance_repr.remove_own_frozen ~amount in + update_stake ctxt delegate ~f let remove_staked_frozen_stake ctxt delegate amount = - let open Result_syntax in - update_stake ctxt delegate ~f:(fun {own_frozen; staked_frozen; delegated} -> - let+ staked_frozen = Tez_repr.(staked_frozen -? amount) in - Full_staking_balance_repr.make ~own_frozen ~staked_frozen ~delegated) + let f = Full_staking_balance_repr.remove_staked_frozen ~amount in + update_stake ctxt delegate ~f let remove_frozen_stake_only_call_from_token ctxt staker amount = match staker with @@ -178,22 +158,16 @@ let remove_frozen_stake_only_call_from_token ctxt staker amount = remove_staked_frozen_stake ctxt delegate amount let add_delegated_stake ctxt delegate amount = - let open Result_syntax in - update_stake ctxt delegate ~f:(fun {own_frozen; staked_frozen; delegated} -> - let+ delegated = Tez_repr.(delegated +? amount) in - Full_staking_balance_repr.make ~own_frozen ~staked_frozen ~delegated) + let f = Full_staking_balance_repr.add_delegated ~amount in + update_stake ctxt delegate ~f let add_own_frozen_stake ctxt delegate amount = - let open Result_syntax in - update_stake ctxt delegate ~f:(fun {own_frozen; staked_frozen; delegated} -> - let+ own_frozen = Tez_repr.(own_frozen +? amount) in - Full_staking_balance_repr.make ~own_frozen ~staked_frozen ~delegated) + let f = Full_staking_balance_repr.add_own_frozen ~amount in + update_stake ctxt delegate ~f let add_staked_frozen_stake ctxt delegate amount = - let open Result_syntax in - update_stake ctxt delegate ~f:(fun {own_frozen; staked_frozen; delegated} -> - let+ staked_frozen = Tez_repr.(staked_frozen +? amount) in - Full_staking_balance_repr.make ~own_frozen ~staked_frozen ~delegated) + let f = Full_staking_balance_repr.add_staked_frozen ~amount in + update_stake ctxt delegate ~f let add_frozen_stake_only_call_from_token ctxt staker amount = match staker with @@ -315,12 +289,8 @@ let add_contract_delegated_stake ctxt contract amount = module For_RPC = struct let get_staking_balance ctxt delegate = let open Lwt_result_syntax in - let* {own_frozen; staked_frozen; delegated} = - Storage.Stake.Staking_balance.get ctxt delegate - in - let*? frozen = Tez_repr.(own_frozen +? staked_frozen) in - let*? staking_balance = Tez_repr.(frozen +? delegated) in - return staking_balance + let* staking_balance = Storage.Stake.Staking_balance.get ctxt delegate in + Lwt.return (Full_staking_balance_repr.total staking_balance) end module Internal_for_tests = struct diff --git a/src/proto_alpha/lib_protocol/stake_storage.mli b/src/proto_alpha/lib_protocol/stake_storage.mli index 440aa77b7761be6533bd4fde831a56182f24971d..7fecdcf9871b6f4a16bf3feffacec66f78035462 100644 --- a/src/proto_alpha/lib_protocol/stake_storage.mli +++ b/src/proto_alpha/lib_protocol/stake_storage.mli @@ -45,9 +45,6 @@ val get_full_staking_balance : Signature.public_key_hash -> Full_staking_balance_repr.t tzresult Lwt.t -val has_minimal_stake_and_frozen_stake : - Raw_context.t -> Full_staking_balance_repr.t -> bool - val remove_delegated_stake : Raw_context.t -> Signature.Public_key_hash.t -> diff --git a/src/proto_alpha/lib_protocol/staking_pseudotokens_storage.ml b/src/proto_alpha/lib_protocol/staking_pseudotokens_storage.ml index 9af3dedf02c035bb3f3d8e7cd2f02acda4438b3b..75a02fbbfdffec330f0d22e5110fbe1123258623 100644 --- a/src/proto_alpha/lib_protocol/staking_pseudotokens_storage.ml +++ b/src/proto_alpha/lib_protocol/staking_pseudotokens_storage.ml @@ -156,17 +156,13 @@ type delegator_balances = { deposits, in tez, of the delegate's stakers. *) let get_frozen_deposits_staked_tez ctxt ~delegate = let open Lwt_result_syntax in - let+ {staked_frozen; delegated = _; own_frozen = _} = - Stake_storage.get_full_staking_balance ctxt delegate - in - staked_frozen + let+ staking_balance = Stake_storage.get_full_staking_balance ctxt delegate in + Full_staking_balance_repr.staked_frozen staking_balance let get_own_frozen_deposits ctxt ~delegate = let open Lwt_result_syntax in - let+ {own_frozen; delegated = _; staked_frozen = _} = - Stake_storage.get_full_staking_balance ctxt delegate - in - own_frozen + let+ staking_balance = Stake_storage.get_full_staking_balance ctxt delegate in + Full_staking_balance_repr.own_frozen staking_balance (** [get_frozen_deposits_pseudotokens ctxt ~delegate] returns the total number of pseudotokens in circulation for the given