diff --git a/src/proto_alpha/lib_parameters/default_parameters.ml b/src/proto_alpha/lib_parameters/default_parameters.ml index 6cfa0a4b66f76146fadfdcc810fb125629205e32..370083240de9b0252d1c82b61b8760e5aa9d7aba 100644 --- a/src/proto_alpha/lib_parameters/default_parameters.ml +++ b/src/proto_alpha/lib_parameters/default_parameters.ml @@ -247,9 +247,9 @@ let constants_mainnet = minimal_participation_ratio = {numerator = 2; denominator = 3}; limit_of_delegation_over_baking = 9; percentage_of_frozen_deposits_slashed_per_double_baking = - Protocol.Int_percentage.p5; + Protocol.Percentage.p5; percentage_of_frozen_deposits_slashed_per_double_attestation = - Protocol.Int_percentage.p50; + Protocol.Percentage.p50; (* The `testnet_dictator` should absolutely be None on mainnet *) testnet_dictator = None; initial_seed = None; diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index d185d74b414b3f66c8210fc119628e3e7cc62778..d9fe1c4a64248791d24f418f2a7802c7f67467df 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -19,7 +19,7 @@ "Bounded_history_repr", "Context_binary_proof", "Ratio_repr", - "Int_percentage", + "Percentage", "Michelson_v1_primitives", diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 360c9012084b0b2b2f81e12882fb3589dc03bbe9..f3472cb9007122b7098d00c0fff39dfde3615036 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -921,10 +921,9 @@ module Constants : sig consensus_committee_size : int; consensus_threshold : int; limit_of_delegation_over_baking : int; - percentage_of_frozen_deposits_slashed_per_double_baking : - Int_percentage.t; + percentage_of_frozen_deposits_slashed_per_double_baking : Percentage.t; percentage_of_frozen_deposits_slashed_per_double_attestation : - Int_percentage.t; + Percentage.t; testnet_dictator : public_key_hash option; initial_seed : State_hash.t option; cache_script_size : int; @@ -1021,10 +1020,10 @@ module Constants : sig val limit_of_delegation_over_baking : context -> int val percentage_of_frozen_deposits_slashed_per_double_baking : - context -> Int_percentage.t + context -> Percentage.t val percentage_of_frozen_deposits_slashed_per_double_attestation : - context -> Int_percentage.t + context -> Percentage.t val testnet_dictator : context -> public_key_hash option diff --git a/src/proto_alpha/lib_protocol/constants_parametric_previous_repr.ml b/src/proto_alpha/lib_protocol/constants_parametric_previous_repr.ml index 0536a4c715408ddab1a73826273914b8c20b5f7c..bf32fb497b761b90f0479d142b037285a41740ff 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_previous_repr.ml +++ b/src/proto_alpha/lib_protocol/constants_parametric_previous_repr.ml @@ -193,9 +193,8 @@ type t = { consensus_committee_size : int; consensus_threshold : int; limit_of_delegation_over_baking : int; - percentage_of_frozen_deposits_slashed_per_double_baking : Int_percentage.t; - percentage_of_frozen_deposits_slashed_per_double_attestation : - Int_percentage.t; + percentage_of_frozen_deposits_slashed_per_double_baking : Percentage.t; + percentage_of_frozen_deposits_slashed_per_double_attestation : Percentage.t; testnet_dictator : Signature.Public_key_hash.t option; initial_seed : State_hash.t option; (* If a new cache is added, please also modify the @@ -633,10 +632,10 @@ let encoding = (req "limit_of_delegation_over_baking" uint8) (req "percentage_of_frozen_deposits_slashed_per_double_baking" - Int_percentage.encoding) + Percentage.encoding) (req "percentage_of_frozen_deposits_slashed_per_double_attestation" - Int_percentage.encoding) + Percentage.encoding) (opt "testnet_dictator" Signature.Public_key_hash.encoding) (opt "initial_seed" State_hash.encoding)) (merge_objs diff --git a/src/proto_alpha/lib_protocol/constants_parametric_previous_repr.mli b/src/proto_alpha/lib_protocol/constants_parametric_previous_repr.mli index ac561e744ed280247e0bb3c509e82be37bd18d94..3dc580b002220a83e16a3aeb991aae1575daee0f 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_previous_repr.mli +++ b/src/proto_alpha/lib_protocol/constants_parametric_previous_repr.mli @@ -184,9 +184,8 @@ type t = { (* in slots *) limit_of_delegation_over_baking : int; (* upper bound on the (delegated tz / own frozen tz) ratio *) - percentage_of_frozen_deposits_slashed_per_double_baking : Int_percentage.t; - percentage_of_frozen_deposits_slashed_per_double_attestation : - Int_percentage.t; + percentage_of_frozen_deposits_slashed_per_double_baking : Percentage.t; + percentage_of_frozen_deposits_slashed_per_double_attestation : Percentage.t; testnet_dictator : Signature.Public_key_hash.t option; initial_seed : State_hash.t option; cache_script_size : int; diff --git a/src/proto_alpha/lib_protocol/constants_parametric_repr.ml b/src/proto_alpha/lib_protocol/constants_parametric_repr.ml index cfc9a65b6653a862ef996b458fa2377d9c3a74c9..a85621d4f7a6d53e294a6f8a721e59160f184fb5 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_repr.ml +++ b/src/proto_alpha/lib_protocol/constants_parametric_repr.ml @@ -208,9 +208,8 @@ type t = { consensus_committee_size : int; consensus_threshold : int; limit_of_delegation_over_baking : int; - percentage_of_frozen_deposits_slashed_per_double_baking : Int_percentage.t; - percentage_of_frozen_deposits_slashed_per_double_attestation : - Int_percentage.t; + percentage_of_frozen_deposits_slashed_per_double_baking : Percentage.t; + percentage_of_frozen_deposits_slashed_per_double_attestation : Percentage.t; testnet_dictator : Signature.Public_key_hash.t option; initial_seed : State_hash.t option; (* If a new cache is added, please also modify the @@ -699,10 +698,10 @@ let encoding = (req "limit_of_delegation_over_baking" uint8) (req "percentage_of_frozen_deposits_slashed_per_double_baking" - Int_percentage.encoding) + Percentage.encoding) (req "percentage_of_frozen_deposits_slashed_per_double_attestation" - Int_percentage.encoding) + Percentage.encoding) (opt "testnet_dictator" Signature.Public_key_hash.encoding) (opt "initial_seed" State_hash.encoding)) (merge_objs diff --git a/src/proto_alpha/lib_protocol/constants_parametric_repr.mli b/src/proto_alpha/lib_protocol/constants_parametric_repr.mli index ff4b3a1b26c204cd9321c004692685396e09565e..27d87927420ede1404f97a28702645936055c5e5 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_repr.mli +++ b/src/proto_alpha/lib_protocol/constants_parametric_repr.mli @@ -212,9 +212,8 @@ type t = { (* in slots *) limit_of_delegation_over_baking : int; (* upper bound on the (delegated tz / own frozen tz) ratio *) - percentage_of_frozen_deposits_slashed_per_double_baking : Int_percentage.t; - percentage_of_frozen_deposits_slashed_per_double_attestation : - Int_percentage.t; + percentage_of_frozen_deposits_slashed_per_double_baking : Percentage.t; + percentage_of_frozen_deposits_slashed_per_double_attestation : Percentage.t; testnet_dictator : Signature.Public_key_hash.t option; initial_seed : State_hash.t option; cache_script_size : int; diff --git a/src/proto_alpha/lib_protocol/constants_storage.mli b/src/proto_alpha/lib_protocol/constants_storage.mli index 78d43459778fdb84da3998d32a8d1af21fcebc21..f254c88e80023a789ec4d01e3755d338c4b6ee49 100644 --- a/src/proto_alpha/lib_protocol/constants_storage.mli +++ b/src/proto_alpha/lib_protocol/constants_storage.mli @@ -90,10 +90,10 @@ val minimal_participation_ratio : Raw_context.t -> Ratio_repr.t val limit_of_delegation_over_baking : Raw_context.t -> int val percentage_of_frozen_deposits_slashed_per_double_baking : - Raw_context.t -> Int_percentage.t + Raw_context.t -> Percentage.t val percentage_of_frozen_deposits_slashed_per_double_attestation : - Raw_context.t -> Int_percentage.t + Raw_context.t -> Percentage.t val testnet_dictator : Raw_context.t -> Signature.Public_key_hash.t option diff --git a/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml index 85b2ea98f7326826381ce63b41215610a7526673..645e564c0090fc7a67e4ac386b454dd27248bd8a 100644 --- a/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml @@ -109,7 +109,7 @@ let punish_double_signing ctxt ~operation_hash slash_history in let* ctxt = - if Compare.Int.((previously_slashed_this_cycle :> int) >= 100) then + if Percentage.(Compare.(previously_slashed_this_cycle >= p100)) then (* Do not store denunciations that have no effects .*) return ctxt else let* denunciations_opt = diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index b670cb37c8d55d069b9f0fdaeb2562697ecf8585..f026fdf0eaca0e1edfabde0ec4e10d8a4617e375 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -49,7 +49,7 @@ Bounded_history_repr Context_binary_proof Ratio_repr - Int_percentage + Percentage Michelson_v1_primitives Slot_repr Cycle_repr @@ -342,7 +342,7 @@ bounded_history_repr.ml bounded_history_repr.mli context_binary_proof.ml context_binary_proof.mli ratio_repr.ml ratio_repr.mli - int_percentage.ml int_percentage.mli + percentage.ml percentage.mli michelson_v1_primitives.ml michelson_v1_primitives.mli slot_repr.ml slot_repr.mli cycle_repr.ml cycle_repr.mli @@ -640,7 +640,7 @@ bounded_history_repr.ml bounded_history_repr.mli context_binary_proof.ml context_binary_proof.mli ratio_repr.ml ratio_repr.mli - int_percentage.ml int_percentage.mli + percentage.ml percentage.mli michelson_v1_primitives.ml michelson_v1_primitives.mli slot_repr.ml slot_repr.mli cycle_repr.ml cycle_repr.mli @@ -922,7 +922,7 @@ bounded_history_repr.ml bounded_history_repr.mli context_binary_proof.ml context_binary_proof.mli ratio_repr.ml ratio_repr.mli - int_percentage.ml int_percentage.mli + percentage.ml percentage.mli michelson_v1_primitives.ml michelson_v1_primitives.mli slot_repr.ml slot_repr.mli cycle_repr.ml cycle_repr.mli diff --git a/src/proto_alpha/lib_protocol/forbidden_delegates_storage.ml b/src/proto_alpha/lib_protocol/forbidden_delegates_storage.ml index 4d8bfa9dad982d2b08b80fafdbc1661f94fc48b7..00fd13645be13c737122081ea6ae3198dce37cce 100644 --- a/src/proto_alpha/lib_protocol/forbidden_delegates_storage.ml +++ b/src/proto_alpha/lib_protocol/forbidden_delegates_storage.ml @@ -24,12 +24,12 @@ let should_forbid ~current_cycle slash_history = List.fold_left (fun slashed_since (cycle, slashed) -> if Cycle_repr.(cycle >= since_cycle) then - Int_percentage.add_bounded slashed_since slashed + Percentage.add_bounded slashed_since slashed else slashed_since) - Int_percentage.p0 + Percentage.p0 slash_history in - Compare.Int.((slashed_since :> int) >= 51) + Percentage.(Compare.(slashed_since >= p51)) let may_forbid ctxt delegate ~current_cycle slash_history = let open Lwt_syntax in 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 086550d862dd836b5969028fb044a13f68027eda..767a4d3619e30247d1a1dd7c01d643e0cf180df1 100644 --- a/src/proto_alpha/lib_protocol/full_staking_balance_repr.ml +++ b/src/proto_alpha/lib_protocol/full_staking_balance_repr.ml @@ -84,7 +84,7 @@ let apply_slashing ~percentage min_delegated_in_cycle; cycle_of_min_delegated; } = - let remaining_percentage = Int_percentage.neg percentage in + let remaining_percentage = Percentage.neg percentage in let own_frozen = Tez_repr.mul_percentage ~rounding:`Down own_frozen remaining_percentage in 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 ef2ac998922606bcda5caa8779c67d323f7c1f7b..c55ec8ba76e0d95ae697a8bd0270965e6bf042c6 100644 --- a/src/proto_alpha/lib_protocol/full_staking_balance_repr.mli +++ b/src/proto_alpha/lib_protocol/full_staking_balance_repr.mli @@ -19,7 +19,7 @@ val encoding : t Data_encoding.t (** The weight of a delegate used for voting rights. *) val voting_weight : t -> Int64.t tzresult -val apply_slashing : percentage:Int_percentage.t -> t -> t +val apply_slashing : percentage:Percentage.t -> t -> t val own_frozen : t -> Tez_repr.t diff --git a/src/proto_alpha/lib_protocol/int_percentage.ml b/src/proto_alpha/lib_protocol/percentage.ml similarity index 62% rename from src/proto_alpha/lib_protocol/int_percentage.ml rename to src/proto_alpha/lib_protocol/percentage.ml index 8cc98c4c9de18badaebfd580a7a380c80e75b072..d801e358cd09af6f8c32722e12857b72b74ea13e 100644 --- a/src/proto_alpha/lib_protocol/int_percentage.ml +++ b/src/proto_alpha/lib_protocol/percentage.ml @@ -7,22 +7,26 @@ type t = int +let one_hundred_percent = 100 + let of_int_guarded i = - if Compare.Int.(i >= 0 && i <= 100) then Ok i + if Compare.Int.(i >= 0 && i <= one_hundred_percent) then Ok i else Error "Value must be between 0 and 100" -let of_int_bounded i = Compare.Int.(max 0 (min 100 i)) +let of_int_bounded i = Compare.Int.(max 0 (min one_hundred_percent i)) let encoding = let open Data_encoding in conv_with_guard (fun i -> i) of_int_guarded uint8 let of_ratio_bounded Ratio_repr.{numerator; denominator} = - of_int_bounded (100 * numerator / denominator) + of_int_bounded (one_hundred_percent * numerator / denominator) + +let to_q x = Q.of_ints x one_hundred_percent -let neg p = 100 - p +let neg p = one_hundred_percent - p -let add_bounded p1 p2 = Compare.Int.min 100 (p1 + p2) +let add_bounded p1 p2 = Compare.Int.min one_hundred_percent (p1 + p2) let sub_bounded p1 p2 = Compare.Int.max 0 (p1 - p2) @@ -31,3 +35,11 @@ let p0 = 0 let p5 = 5 let p50 = 50 + +let p51 = 51 + +let p100 = one_hundred_percent + +module Compare = struct + include Compare.Int +end diff --git a/src/proto_alpha/lib_protocol/int_percentage.mli b/src/proto_alpha/lib_protocol/percentage.mli similarity index 66% rename from src/proto_alpha/lib_protocol/int_percentage.mli rename to src/proto_alpha/lib_protocol/percentage.mli index fb7fc90c120169eeeccf1adcca658c30fa969243..29a8097c5bfa5a4f5b743113dfca069425c3cd23 100644 --- a/src/proto_alpha/lib_protocol/int_percentage.mli +++ b/src/proto_alpha/lib_protocol/percentage.mli @@ -5,14 +5,18 @@ (* *) (*****************************************************************************) -(** An integer value between 0 and 100, inclusive. *) -type t = private int +(** A value representing percentages, between 0% and 100%, inclusive. + Precision of the representation is 1% *) +type t val encoding : t Data_encoding.t +(** Rounds down to the nearest percent *) val of_ratio_bounded : Ratio_repr.t -> t -(** [neg p] is [100 - p]. *) +val to_q : t -> Q.t + +(** [neg p] is [100% - p]. *) val neg : t -> t val add_bounded : t -> t -> t @@ -21,11 +25,21 @@ val sub_bounded : t -> t -> t (** Constants *) -(** 0 *) +(** 0% *) val p0 : t -(** 5 *) +(** 5% *) val p5 : t -(** 50 *) +(** 50% *) val p50 : t + +(** 51% *) +val p51 : t + +(** 100% *) +val p100 : t + +module Compare : sig + val ( >= ) : t -> t -> bool +end diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index ccfc2b5d6a6bc6da5f2994a2a2ea41be6bdf1a45..8a4764b4002c9b2ac3e67ef7d2d87115a5a7d3ac 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -154,7 +154,7 @@ module Missed_attestations_info = struct end module Slashed_deposits_history = struct - type slashed_percentage = Int_percentage.t + type slashed_percentage = Percentage.t (* invariant: sorted list *) type t = (Cycle_repr.t * slashed_percentage) list @@ -164,12 +164,12 @@ module Slashed_deposits_history = struct list (obj2 (req "cycle" Cycle_repr.encoding) - (req "slashed_percentage" Int_percentage.encoding)) + (req "slashed_percentage" Percentage.encoding)) let add cycle percentage history = let rec loop rev_prefix = function | (c, p) :: tl when Cycle_repr.(cycle = c) -> - let p = Int_percentage.add_bounded p percentage in + let p = Percentage.add_bounded p percentage in (* cycle found, do not change the order *) List.rev_append rev_prefix ((c, p) :: tl) | ((c, _) as hd) :: tl when Cycle_repr.(cycle > c) -> @@ -184,7 +184,7 @@ module Slashed_deposits_history = struct let rec get cycle = function | (c, p) :: _ when Cycle_repr.(cycle = c) -> p | (c, _) :: tl when Cycle_repr.(cycle > c) -> get cycle tl - | _ -> Int_percentage.p0 + | _ -> Percentage.p0 end module Unstake_request = struct diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index 4ca9d1c1179674a08c9001f25fd15846385266be..4f2565e551488132e45d3af996909c9f749bdfcb 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -52,7 +52,7 @@ module Block_round : Simple_single_data_storage with type value = Round_repr.t type missed_attestations_info = {remaining_slots : int; missed_levels : int} module Slashed_deposits_history : sig - type slashed_percentage = Int_percentage.t + type slashed_percentage = Percentage.t type t = (Cycle_repr.t * slashed_percentage) list diff --git a/src/proto_alpha/lib_protocol/test/helpers/adaptive_issuance_helpers.ml b/src/proto_alpha/lib_protocol/test/helpers/adaptive_issuance_helpers.ml index 58862eb7a96aa72aaacdfd463d938d7232b1346f..e3e9c17c5aca76dee7d704fca927d5f1443ee062 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/adaptive_issuance_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/adaptive_issuance_helpers.ml @@ -250,10 +250,10 @@ module Frozen_tez = struct let a, amount = sub_current amount account a in ({a with initial = Tez.(a.initial -! amount)}, amount) - let slash base_amount (pct : Protocol.Int_percentage.t) a = - let pct_times_100 = (pct :> int) in + let slash base_amount (pct : Protocol.Percentage.t) a = + let pct_q = Protocol.Percentage.to_q pct in let slashed_amount = - Tez.mul_q base_amount Q.(pct_times_100 // 100) |> Tez.of_q ~round_up:false + Tez.mul_q base_amount pct_q |> Tez.of_q ~round_up:false in let total_current = total_current a in let slashed_amount_final = Tez.min slashed_amount total_current in @@ -1084,11 +1084,13 @@ let apply_slashing let frozen_deposits, slashed_frozen = Frozen_tez.slash base_rights slashed_pct frozen_deposits in + let slashed_pct_q = Protocol.Percentage.to_q slashed_pct in + let slashed_pct = Q.(100 // 1 * slashed_pct_q |> to_int) in let unstaked_frozen, slashed_unstaked = Unstaked_frozen.slash ~preserved_cycles:constants.preserved_cycles slashed_cycle - (slashed_pct :> int) + slashed_pct unstaked_frozen in ( {acc with frozen_deposits; unstaked_frozen}, diff --git a/src/proto_alpha/lib_protocol/test/helpers/assert.ml b/src/proto_alpha/lib_protocol/test/helpers/assert.ml index c6df0bd8ae608d399d637747cd65d359df31dccb..9f42a9e2ec7cfcfad6b6d864a3d15e7ad548fec8 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/assert.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/assert.ml @@ -144,6 +144,9 @@ let leq_int64 ~loc (a : int64) (b : int64) = let equal_z ~loc (a : Z.t) (b : Z.t) = equal ~loc Compare.Z.( = ) "Z are not equal" Z.pp_print a b +let equal_q ~loc (a : Q.t) (b : Q.t) = + equal ~loc Compare.Q.( = ) "Q are not equal" Q.pp_print a b + (* bool *) let equal_bool ~loc (a : bool) (b : bool) = equal ~loc Bool.equal "Booleans aren't equal" Format.pp_print_bool a b diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_attestation.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_attestation.ml index 480b70f1b952904d9b1d1520b9e20973988d19e8..49c575efbddf53255b3c7c79cc6c0d29439a64b5 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_attestation.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_attestation.ml @@ -166,11 +166,13 @@ let test_valid_double_attestation_evidence () = Context.Delegate.current_frozen_deposits (B blk_eoc) delegate in let frozen_deposits_after = Test_tez.(frozen_deposits_after -! autostaked) in - let p = - constants.percentage_of_frozen_deposits_slashed_per_double_attestation + let one_minus_p = + Percentage.neg + constants.percentage_of_frozen_deposits_slashed_per_double_attestation in + let {Q.num; den} = Percentage.to_q one_minus_p in let expected_frozen_deposits_after = - Test_tez.(frozen_deposits_before *! Int64.of_int (100 - (p :> int)) /! 100L) + Test_tez.(frozen_deposits_before *! Z.to_int64 num /! Z.to_int64 den) in let* () = Assert.equal_tez @@ -710,7 +712,7 @@ let test_freeze_more_with_low_balance = preserved_cycles = 5; percentage_of_frozen_deposits_slashed_per_double_attestation = (* enforce that percentage is 50% in the test's params. *) - Int_percentage.p50; + Percentage.p50; adaptive_issuance = { Default_parameters.constants_test.adaptive_issuance with @@ -775,14 +777,13 @@ let test_freeze_more_with_low_balance = in (* We also check that compared to deposits at block [b2], [account1] lost 50% of its deposits. *) - let slash_percentage = - constants.percentage_of_frozen_deposits_slashed_per_double_attestation + let one_minus_slash_percentage = + Percentage.neg + constants.percentage_of_frozen_deposits_slashed_per_double_attestation in + let {Q.num; den} = Percentage.to_q one_minus_slash_percentage in let expected_frozen_deposits_after = - Test_tez.( - info2.frozen_deposits - *! Int64.of_int (100 - (slash_percentage :> int)) - /! 100L) + Test_tez.(info2.frozen_deposits *! Z.to_int64 num /! Z.to_int64 den) in let* () = Assert.equal_tez diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_baking.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_baking.ml index f2d09e9bbf0bcf7673a348457ecf87cfb74e66a3..136e1d32cd76e2eff21f16a91596705d99fbc1ea 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_baking.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_baking.ml @@ -124,10 +124,11 @@ let test_valid_double_baking_evidence () = Context.Delegate.current_frozen_deposits (B blk_eoc) baker1 in let autostaked = Block.autostaked baker1 end_cycle_metadata in + let Q.{num; den} = Percentage.to_q p in let expected_frozen_deposits_after = Test_tez.( frozen_deposits_before - -! (initial_frozen_deposits_before *! Int64.of_int (p :> int) /! 100L) + -! (initial_frozen_deposits_before *! Z.to_int64 num /! Z.to_int64 den) +! autostaked) in Assert.equal_tez @@ -204,14 +205,12 @@ let test_valid_double_baking_followed_by_double_attesting () = let p_db = csts.parametric.percentage_of_frozen_deposits_slashed_per_double_baking in - let p = - (p_de :> int) + (p_db :> int) - (* assuming the sum doesn't exceed 100% *) - in + let p = Percentage.add_bounded p_de p_db in + let Q.{num; den} = Percentage.to_q p in let expected_frozen_deposits_after = Test_tez.( frozen_deposits_before - -! (initial_frozen_deposits_before *! Int64.of_int p /! 100L) + -! (initial_frozen_deposits_before *! Z.to_int64 num /! Z.to_int64 den) +! autostaked) in (* Both slashings are computed on the initial amount of frozen deposits so @@ -286,14 +285,12 @@ let test_valid_double_attesting_followed_by_double_baking () = let p_db = csts.parametric.percentage_of_frozen_deposits_slashed_per_double_baking in - let p = - (p_de :> int) + (p_db :> int) - (* assuming the sum doesn't exceed 100% *) - in + let p = Percentage.add_bounded p_de p_db in + let Q.{num; den} = Percentage.to_q p in let expected_frozen_deposits_after = Test_tez.( frozen_deposits_before - -! (initial_frozen_deposits_before *! Int64.of_int p /! 100L) + -! (initial_frozen_deposits_before *! Z.to_int64 num /! Z.to_int64 den) +! autostaked) in (* Both slashings are computed on the initial amount of frozen deposits so @@ -388,10 +385,11 @@ let test_payload_producer_gets_evidence_rewards () = let* frozen_deposits_after = Context.Delegate.current_frozen_deposits (B b') baker1 in + let Q.{num; den} = Percentage.to_q p in let expected_frozen_deposits_after = Test_tez.( frozen_deposits_before - -! (initial_frozen_deposits_before *! Int64.of_int (p :> int) /! 100L) + -! (initial_frozen_deposits_before *! Z.to_int64 num /! Z.to_int64 den) +! autostaked) in (* the frozen deposits of the double-signer [baker1] are slashed *) diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_preattestation.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_preattestation.ml index 4ef33e9f0cbef9defc2b3c8d9e69edc6a4b3f4f6..a75e4c7cd107770972dd3374ae12e3756cb1b01e 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_preattestation.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_preattestation.ml @@ -154,8 +154,9 @@ end = struct (* the diff of the two balances in normal and in denunciation cases *) let diff_end_bal = Test_tez.(bal_good -! bal_bad) in (* amount lost due to denunciation *) + let Q.{num; den} = Percentage.to_q p in let lost_deposit = - Test_tez.(frozen_deposit *! Int64.of_int (p :> int) /! 100L) + Test_tez.(frozen_deposit *! Z.to_int64 num /! Z.to_int64 den) in (* some of the lost deposits (depending on staking constants) will be earned by the baker *) let divider = diff --git a/src/proto_alpha/lib_protocol/test/integration/test_adaptive_issuance_roundtrip.ml b/src/proto_alpha/lib_protocol/test/integration/test_adaptive_issuance_roundtrip.ml index 852e5ad932e2f8cf70069138ddebfa6c573e6553..7c486e8a4c289c8f0cffe03527bbe55f9a162413 100644 --- a/src/proto_alpha/lib_protocol/test/integration/test_adaptive_issuance_roundtrip.ml +++ b/src/proto_alpha/lib_protocol/test/integration/test_adaptive_issuance_roundtrip.ml @@ -1558,12 +1558,16 @@ let cycle_from_level blocks_per_cycle level = let pct_from_kind (block : Block.t) = function | Protocol.Misbehaviour_repr.Double_baking -> - (block.constants.percentage_of_frozen_deposits_slashed_per_double_baking - :> int) + Protocol.Percentage.to_q + block.constants.percentage_of_frozen_deposits_slashed_per_double_baking + |> Q.(mul (100 // 1)) + |> Q.to_int | Double_attesting -> - (block.constants - .percentage_of_frozen_deposits_slashed_per_double_attestation - :> int) + Protocol.Percentage.to_q + block.constants + .percentage_of_frozen_deposits_slashed_per_double_attestation + |> Q.(mul (100 // 1)) + |> Q.to_int let get_pending_slashed_pct_for_delegate (block, state) delegate = let rec aux r = function diff --git a/src/proto_alpha/lib_protocol/test/unit/test_percentage.ml b/src/proto_alpha/lib_protocol/test/unit/test_percentage.ml index 8502e4c445ec42e54ccdab7a7253debe779562f9..fb4b48d049d69987485539add31622682f90e696 100644 --- a/src/proto_alpha/lib_protocol/test/unit/test_percentage.ml +++ b/src/proto_alpha/lib_protocol/test/unit/test_percentage.ml @@ -16,10 +16,11 @@ open Protocol let pct_of_int n = - Int_percentage.of_ratio_bounded Ratio_repr.{numerator = n; denominator = 100} + Percentage.of_ratio_bounded Ratio_repr.{numerator = n; denominator = 100} -let assert_equal ~loc n (pct : Int_percentage.t) = - Assert.equal_int ~loc n (pct :> int) +let assert_equal ~loc n (pct : Percentage.t) = + let pct_q = Percentage.to_q pct in + Assert.equal_q ~loc Q.(n // 100) pct_q let assert_equal_tez ~loc t1 t2 = Assert.equal ~loc Tez_repr.equal "Tez aren't equal" Tez_repr.pp t1 t2 @@ -28,13 +29,16 @@ let f = Tez_repr.mul_percentage let test_constant_values () = let open Lwt_result_syntax in - let* () = assert_equal ~loc:__LOC__ 5 Int_percentage.p5 in - let* () = assert_equal ~loc:__LOC__ 50 Int_percentage.p50 in + let* () = assert_equal ~loc:__LOC__ 0 Percentage.p0 in + let* () = assert_equal ~loc:__LOC__ 5 Percentage.p5 in + let* () = assert_equal ~loc:__LOC__ 50 Percentage.p50 in + let* () = assert_equal ~loc:__LOC__ 51 Percentage.p51 in + let* () = assert_equal ~loc:__LOC__ 100 Percentage.p100 in return_unit let test_neg () = let open Lwt_result_syntax in - let open Int_percentage in + let open Percentage in let* () = assert_equal ~loc:__LOC__ 95 (neg p5) in let* () = assert_equal ~loc:__LOC__ 50 (neg p50) in let* () = assert_equal ~loc:__LOC__ 31 (neg (pct_of_int 69)) in @@ -44,7 +48,7 @@ let test_neg () = let test_bounded () = let open Lwt_result_syntax in - let open Int_percentage in + let open Percentage in let* () = assert_equal ~loc:__LOC__ 100 (pct_of_int 200) in let* () = assert_equal ~loc:__LOC__ 0 (pct_of_int (-100)) in let* () = assert_equal ~loc:__LOC__ 100 (add_bounded p50 p50) in @@ -59,27 +63,27 @@ let test_mul_percentage () = assert_equal_tez ~loc:__LOC__ (of_mutez_exn 50L) - (mul_percentage ~rounding (of_mutez_exn 100L) Int_percentage.p50) + (mul_percentage ~rounding (of_mutez_exn 100L) Percentage.p50) in let* () = assert_equal_tez ~loc:__LOC__ (of_mutez_exn 5L) - (mul_percentage ~rounding (of_mutez_exn 100L) Int_percentage.p5) + (mul_percentage ~rounding (of_mutez_exn 100L) Percentage.p5) in (* round down *) let* () = assert_equal_tez ~loc:__LOC__ (of_mutez_exn 49L) - (mul_percentage ~rounding (of_mutez_exn 99L) Int_percentage.p50) + (mul_percentage ~rounding (of_mutez_exn 99L) Percentage.p50) in (* round up *) let* () = assert_equal_tez ~loc:__LOC__ (of_mutez_exn 50L) - (mul_percentage ~rounding:`Up (of_mutez_exn 99L) Int_percentage.p50) + (mul_percentage ~rounding:`Up (of_mutez_exn 99L) Percentage.p50) in let tz = 123456L in let* () = diff --git a/src/proto_alpha/lib_protocol/tez_repr.ml b/src/proto_alpha/lib_protocol/tez_repr.ml index 4a1ac737ebcb14f7fb8e94551c8d373c0cca3d7e..55e695a9d1256f484d3441aa4b30df0845b9f6da 100644 --- a/src/proto_alpha/lib_protocol/tez_repr.ml +++ b/src/proto_alpha/lib_protocol/tez_repr.ml @@ -182,13 +182,11 @@ let mul_ratio ~rounding tez ~num ~den = let mul_q ~rounding tez {Q.num; den} = mul_ratio_z ~rounding tez ~num ~den -let mul_percentage ~rounding = - let z100 = Z.of_int 100 in - fun (Tez_tag t) (percentage : Int_percentage.t) -> - (* Guaranteed to produce no errors by the invariants on {!Int_percentage.t}. *) - let div' = match rounding with `Down -> Z.div | `Up -> Z.cdiv in - Tez_tag - Z.(to_int64 (div' (mul (of_int64 t) (of_int (percentage :> int))) z100)) +let mul_percentage ~rounding (Tez_tag t) (percentage : Percentage.t) = + let {Q.num; den} = Percentage.to_q percentage in + (* Guaranteed to produce no errors by the invariants on {!Percentage.t}. *) + let div' = match rounding with `Down -> Z.div | `Up -> Z.cdiv in + Tez_tag Z.(to_int64 (div' (mul (of_int64 t) num) den)) let of_mutez t = if t < 0L then None else Some (Tez_tag t) diff --git a/src/proto_alpha/lib_protocol/tez_repr.mli b/src/proto_alpha/lib_protocol/tez_repr.mli index 0d2d974b0c96f736a327174a24dd4e64e9481324..da09235aaae203d0802883210f9bbabe4a7f454b 100644 --- a/src/proto_alpha/lib_protocol/tez_repr.mli +++ b/src/proto_alpha/lib_protocol/tez_repr.mli @@ -85,7 +85,7 @@ val mul_q : rounding:[`Down | `Up] -> t -> Q.t -> t tzresult (** [mul_percentage tez percentage] returns [tez * percentage / 100]. No errors can happen. *) -val mul_percentage : rounding:[`Down | `Up] -> t -> Int_percentage.t -> t +val mul_percentage : rounding:[`Down | `Up] -> t -> Percentage.t -> t val to_mutez : t -> int64 diff --git a/src/proto_alpha/lib_protocol/unstake_requests_storage.ml b/src/proto_alpha/lib_protocol/unstake_requests_storage.ml index afc6ea0456568ed6126e07ae2b90b0d76e1fb779..f4309bf55b388ed01d76dab2a5af24cf51d36c3c 100644 --- a/src/proto_alpha/lib_protocol/unstake_requests_storage.ml +++ b/src/proto_alpha/lib_protocol/unstake_requests_storage.ml @@ -188,7 +188,7 @@ module For_RPC = struct in let denunciations = Option.value denunciations_opt ~default:[] in let not_yet_slashed_pct = - if is_last_of_cycle then Int_percentage.p0 + if is_last_of_cycle then Percentage.p0 else List.fold_left (fun acc Denunciations_repr.{misbehaviour; _} -> @@ -203,25 +203,25 @@ module For_RPC = struct else match misbehaviour.kind with | Double_baking -> - Int_percentage.add_bounded + Percentage.add_bounded acc (Constants_storage .percentage_of_frozen_deposits_slashed_per_double_baking ctxt) | Double_attesting -> - Int_percentage.add_bounded + Percentage.add_bounded acc (Constants_storage .percentage_of_frozen_deposits_slashed_per_double_attestation ctxt)) - Int_percentage.p0 + Percentage.p0 denunciations in return @@ List.map (fun (cycle, pct) -> if Cycle_repr.(succ cycle = current_level.cycle) then - (cycle, Int_percentage.(sub_bounded pct not_yet_slashed_pct)) + (cycle, Percentage.(sub_bounded pct not_yet_slashed_pct)) else (cycle, pct)) slashing_history else if not is_last_of_cycle then