diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index c0f468f18c87b98b3b87540ad02980bbc7e28c48..f4e52cc12d54c97040fa751438f656e4d7051b6d 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/delegate_cycles.ml b/src/proto_alpha/lib_protocol/delegate_cycles.ml index 8dd309a452d86cb757ed79a3dd80c34ed317e49f..dc4b26d3622b203d0f7b9ec0bb1f7d37072f3c80 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.ml +++ b/src/proto_alpha/lib_protocol/delegate_cycles.ml @@ -68,23 +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 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 @@ -204,6 +206,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 = + 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) -> @@ -216,12 +221,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 = Stake_repr.staking_weight 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 48d3be9240d52a292ec1990e807bd0d9a2a1928f..e9cd6c1a9991041d80c70d993fd625441db2a464 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,16 @@ 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 = + 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 - ~active_stake + ~total_active_stake_weight + ~active_stake_weight in let Ratio_repr.{numerator; denominator} = Constants_storage.minimal_participation_ratio ctxt @@ -167,10 +173,14 @@ 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 = 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 - ~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 e3950661ddc18a3cd0d74dfe5a27a2e84b3fac8c..a5469c79e32531ecc642572c33928c81a0a6215d 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 diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.ml b/src/proto_alpha/lib_protocol/delegate_sampler.ml index 03594e25a63b967c32e74ccfb0bcf4909074a5a1..a7ddf813b532071c615f918f9bf478c95f04f747 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.ml +++ b/src/proto_alpha/lib_protocol/delegate_sampler.ml @@ -175,26 +175,35 @@ 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*? total_stake = Tez_repr.(total_stake +? 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:([], 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 +231,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/dune b/src/proto_alpha/lib_protocol/dune index 1de27598da43f1a552c8d85b6b62b521ff173fc0..19a717b6c27acdb4f8715ed1789304fa2f0c65b9 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/init_storage.ml b/src/proto_alpha/lib_protocol/init_storage.ml index 35b22e66a0836de5589acca125d47c3c99288dee..e6e33340adaf6adb9a5358071ddc767c28ee9029 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/raw_context.ml b/src/proto_alpha/lib_protocol/raw_context.ml index 8f20eed7f29aa6f9a6ccb3bd437294787fbec97e..83d15d27ecc9184d298aefb9a145c5369e353458 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 01d81c27304e15f4014c4dd43146feea3f02f3f1..2da61ffdd78ed9deebfeb9614982bbca22be93a2 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 new file mode 100644 index 0000000000000000000000000000000000000000..655ba7e3b8eaecb5a24fde0245a24950e0ed73a3 --- /dev/null +++ b/src/proto_alpha/lib_protocol/stake_repr.ml @@ -0,0 +1,50 @@ +(*****************************************************************************) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +type t = {frozen : Tez_repr.t; delegated : Tez_repr.t} + +let make ~frozen ~delegated = {frozen; delegated} + +let total {frozen; delegated} = Tez_repr.(frozen +? delegated) + +let 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 ~frozen:Tez_repr.zero ~delegated:Tez_repr.zero + +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 ( +? ) {frozen = f1; delegated = d1} {frozen = f2; delegated = d2} = + let open Result_syntax in + 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 new file mode 100644 index 0000000000000000000000000000000000000000..70a0e131584fbb989ebf6a038fe94937dad6e06f --- /dev/null +++ b/src/proto_alpha/lib_protocol/stake_repr.mli @@ -0,0 +1,43 @@ +(*****************************************************************************) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +(** Stake of a delegate. *) +type t + +val zero : t + +val make : frozen:Tez_repr.t -> delegated:Tez_repr.t -> t + +val encoding : t Data_encoding.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 + +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 7acfcb76038c1ba7cdc925486019f8868edd82c4..2edbcec8fb520c34a40a1cf203f9c20c252d3ea3 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" @@ -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 -> @@ -148,7 +149,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 67968f574697c39c4aadf0d52d499ddd9f78c05d..326e0463c407f1d8f3d7cc73f0aa8c6f2a5f6bed 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 2e1b31102f2ec7abcd7ad0095c5281635bcfe44f..86e52b2cf4076d971e8d47305c9c8c0365f415d4 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -991,9 +991,10 @@ module Cycle = struct (Pair (Make_index (Raw_level_repr.Index)) (Public_key_hash_index)) (Slashed_level) - module Selected_stake_distribution = + (* Remove me in P. *) + module Selected_stake_distribution_up_to_Nairobi = Indexed_context.Make_map - (Registered) + (Ghost) (struct let name = ["selected_stake_distribution"] end) @@ -1008,14 +1009,40 @@ module Cycle = struct (req "active_stake" Tez_repr.encoding))) end) - module Total_active_stake = + module Selected_stake_distribution = Indexed_context.Make_map (Registered) + (struct + let name = ["selected_stake_distribution"] + end) + (struct + 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" 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) + (struct + let name = ["total_active_stake"] + end) + (Stake_repr) + module Delegate_sampler_state = 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 29bf6cb5335285972bfba1970de37c4d51d208da..a82d10ee85a5042ff486251e965114c77bf70b48 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -412,11 +412,25 @@ 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 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 + + (* 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 @@ -424,7 +438,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