diff --git a/contrib/kaitai-struct-files/files/alpha__constants.ksy b/contrib/kaitai-struct-files/files/alpha__constants.ksy index dcf100fd8c7e2824f491be05902911c0389e0dd1..83f23985dbd1299080d2d5af50afb3d43f2a53c8 100644 --- a/contrib/kaitai-struct-files/files/alpha__constants.ksy +++ b/contrib/kaitai-struct-files/files/alpha__constants.ksy @@ -269,9 +269,13 @@ seq: - id: limit_of_delegation_over_baking type: u1 - id: percentage_of_frozen_deposits_slashed_per_double_baking - type: u1 + type: u2 - id: percentage_of_frozen_deposits_slashed_per_double_attestation - type: u1 + type: u2 +- id: max_slashing_per_block + type: u2 +- id: max_slashing_threshold + type: int31 - id: testnet_dictator_tag type: u1 enum: bool diff --git a/contrib/kaitai-struct-files/files/alpha__constants__parametric.ksy b/contrib/kaitai-struct-files/files/alpha__constants__parametric.ksy index b187e1770c59a3856cf4843df6b900cf2dc1e113..cddf94099bcbd91d2fb1f0b3a100d6bc0de174ea 100644 --- a/contrib/kaitai-struct-files/files/alpha__constants__parametric.ksy +++ b/contrib/kaitai-struct-files/files/alpha__constants__parametric.ksy @@ -241,9 +241,13 @@ seq: - id: limit_of_delegation_over_baking type: u1 - id: percentage_of_frozen_deposits_slashed_per_double_baking - type: u1 + type: u2 - id: percentage_of_frozen_deposits_slashed_per_double_attestation - type: u1 + type: u2 +- id: max_slashing_per_block + type: u2 +- id: max_slashing_threshold + type: int31 - id: testnet_dictator_tag type: u1 enum: bool diff --git a/contrib/kaitai-struct-files/files/alpha__parameters.ksy b/contrib/kaitai-struct-files/files/alpha__parameters.ksy index 23d37f392b7e3e09e2616c42fcb34973e8279d71..5979bfa3ec3e56958d670d349a6626ad2982b69a 100644 --- a/contrib/kaitai-struct-files/files/alpha__parameters.ksy +++ b/contrib/kaitai-struct-files/files/alpha__parameters.ksy @@ -519,9 +519,13 @@ seq: - id: limit_of_delegation_over_baking type: u1 - id: percentage_of_frozen_deposits_slashed_per_double_baking - type: u1 + type: u2 - id: percentage_of_frozen_deposits_slashed_per_double_attestation - type: u1 + type: u2 +- id: max_slashing_per_block + type: u2 +- id: max_slashing_threshold + type: int31 - id: testnet_dictator_tag type: u1 enum: bool diff --git a/docs/protocols/alpha.rst b/docs/protocols/alpha.rst index e9ebd75b4d5aa041d98eb2447f9a6a3161b20910..48e3a169edf8b95aef276b8e011393c49801af0f 100644 --- a/docs/protocols/alpha.rst +++ b/docs/protocols/alpha.rst @@ -84,6 +84,18 @@ Adaptive Issuance (ongoing) double bake/attest, by giving them some time to fix it. (MR :gl:`!11704`) +- Denunciations are now applied in chronological order of the denounced + double signing events, instead of chronological order of denunciation + inclusion. (MR :gl:`!11854`) + +- Under the new slashing feature flag, the amount slashed for a double + attestation or pre-attestation depends on the number of slots owned + by misbehaving delegates in the exact block this double signing + event occurred. This greatly diminishes potential losses in cases of + legitimate accidents that do not threaten the chain, while keeping + a strong incentive against potential consensus attacks. (MR + :gl:`!11854`) + - Activating adaptive issuance per-block vote (MR !11935) Gas improvements diff --git a/src/proto_alpha/lib_parameters/default_parameters.ml b/src/proto_alpha/lib_parameters/default_parameters.ml index c4c3909547a90a55c4454fea9095af8bfb1599c9..70b30e51b14814e44b4441788e796f714560bf00 100644 --- a/src/proto_alpha/lib_parameters/default_parameters.ml +++ b/src/proto_alpha/lib_parameters/default_parameters.ml @@ -163,6 +163,7 @@ let constants_mainnet : Constants.Parametric.t = seed_nonce_revelation_tip_weight; vdf_revelation_tip_weight; }; + max_slashing_threshold; } = Constants.Generated.generate ~consensus_committee_size in @@ -247,6 +248,8 @@ let constants_mainnet : Constants.Parametric.t = Protocol.Percentage.p5; percentage_of_frozen_deposits_slashed_per_double_attestation = Protocol.Percentage.p50; + max_slashing_per_block = Protocol.Percentage.p100; + max_slashing_threshold; (* The `testnet_dictator` should absolutely be None on mainnet *) testnet_dictator = None; initial_seed = None; @@ -318,7 +321,8 @@ let derive_cryptobox_parameters ~redundancy_factor ~mainnet_constants_divider = let constants_sandbox = let consensus_committee_size = 256 in let block_time = 1 in - let Constants.Generated.{consensus_threshold = _; issuance_weights} = + let Constants.Generated. + {max_slashing_threshold; consensus_threshold = _; issuance_weights} = Constants.Generated.generate ~consensus_committee_size in { @@ -347,13 +351,15 @@ let constants_sandbox = delay_increment_per_round = Period.one_second; consensus_committee_size = 256; consensus_threshold = 0; + max_slashing_threshold; limit_of_delegation_over_baking = 19; max_operations_time_to_live = 8; } let constants_test = let consensus_committee_size = 25 in - let Constants.Generated.{consensus_threshold; issuance_weights} = + let Constants.Generated. + {max_slashing_threshold = _; consensus_threshold; issuance_weights} = Constants.Generated.generate ~consensus_committee_size in { @@ -386,6 +392,9 @@ let constants_test = (* Not 9 so that multiplication by a percentage and divisions by a limit do not easily get intermingled. *); max_operations_time_to_live = 8; + (* This has the same slashing behaviour as before P *) + max_slashing_per_block = Protocol.Percentage.p50; + max_slashing_threshold = 1; } let test_commitments = diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index 219574dce74e5d6063d0864392b12760440b2c10..c18a7b164d8173d14f7b238a93c4b9ca27a5f135 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -182,6 +182,7 @@ "Delegate_rewards", "Delegate_missed_attestations_storage", "Forbidden_delegates_storage", + "Slash_percentage", "Delegate_slashed_deposits_storage", "Staking", "Delegate_cycles", diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 72123322e830469ed1fcbff6c6e9217ce46bdf43..ff2d0d4be1cd6c9e76c1dc7926fc42bad117f971 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -921,6 +921,8 @@ module Constants : sig percentage_of_frozen_deposits_slashed_per_double_baking : Percentage.t; percentage_of_frozen_deposits_slashed_per_double_attestation : Percentage.t; + max_slashing_per_block : Percentage.t; + max_slashing_threshold : int; testnet_dictator : public_key_hash option; initial_seed : State_hash.t option; cache_script_size : int; @@ -946,6 +948,7 @@ module Constants : sig type t = { consensus_threshold : int; issuance_weights : Parametric.issuance_weights; + max_slashing_threshold : int; } val generate : consensus_committee_size:int -> t @@ -2190,7 +2193,7 @@ end (** This module re-exports definitions from {!Misbehaviour_repr}. *) module Misbehaviour : sig - type kind = Double_baking | Double_attesting + type kind = Double_baking | Double_attesting | Double_preattesting type t = {kind : kind; level : Raw_level.t; round : Round.t; slot : Slot.t} end 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 bf32fb497b761b90f0479d142b037285a41740ff..96b257e4cd1d603670fb7484669ba4ff192b0b60 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_previous_repr.ml +++ b/src/proto_alpha/lib_protocol/constants_parametric_previous_repr.ml @@ -632,10 +632,10 @@ let encoding = (req "limit_of_delegation_over_baking" uint8) (req "percentage_of_frozen_deposits_slashed_per_double_baking" - Percentage.encoding) + Percentage.encoding_legacy_in_o) (req "percentage_of_frozen_deposits_slashed_per_double_attestation" - Percentage.encoding) + Percentage.encoding_legacy_in_o) (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.ml b/src/proto_alpha/lib_protocol/constants_parametric_repr.ml index 8bac5ec48cb187186116a92b04b61ef522aca72b..0f7414b51fd4fe56548831ffab6aaf72a83d82e6 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_repr.ml +++ b/src/proto_alpha/lib_protocol/constants_parametric_repr.ml @@ -202,6 +202,8 @@ type t = { limit_of_delegation_over_baking : int; percentage_of_frozen_deposits_slashed_per_double_baking : Percentage.t; percentage_of_frozen_deposits_slashed_per_double_attestation : Percentage.t; + max_slashing_per_block : Percentage.t; + max_slashing_threshold : int; testnet_dictator : Signature.Public_key_hash.t option; initial_seed : State_hash.t option; (* If a new cache is added, please also modify the @@ -548,6 +550,8 @@ let encoding = c.limit_of_delegation_over_baking, c.percentage_of_frozen_deposits_slashed_per_double_baking, c.percentage_of_frozen_deposits_slashed_per_double_attestation, + c.max_slashing_per_block, + c.max_slashing_threshold, c.testnet_dictator, c.initial_seed ), ( ( c.cache_script_size, @@ -587,6 +591,8 @@ let encoding = limit_of_delegation_over_baking, percentage_of_frozen_deposits_slashed_per_double_baking, percentage_of_frozen_deposits_slashed_per_double_attestation, + max_slashing_per_block, + max_slashing_threshold, testnet_dictator, initial_seed ), ( ( cache_script_size, @@ -627,6 +633,8 @@ let encoding = limit_of_delegation_over_baking; percentage_of_frozen_deposits_slashed_per_double_baking; percentage_of_frozen_deposits_slashed_per_double_attestation; + max_slashing_per_block; + max_slashing_threshold; testnet_dictator; initial_seed; cache_script_size; @@ -677,7 +685,7 @@ let encoding = (req "consensus_committee_size" int31) (req "consensus_threshold" int31)) (merge_objs - (obj6 + (obj8 (req "minimal_participation_ratio" Ratio_repr.encoding) (req "limit_of_delegation_over_baking" uint8) (req @@ -686,6 +694,8 @@ let encoding = (req "percentage_of_frozen_deposits_slashed_per_double_attestation" Percentage.encoding) + (req "max_slashing_per_block" Percentage.encoding) + (req "max_slashing_threshold" int31) (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 b3f4d88a41b71ccf69342a664c89253b0e572495..eb61c83f845131c1987892d1e97f76c9bb3e92a0 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_repr.mli +++ b/src/proto_alpha/lib_protocol/constants_parametric_repr.mli @@ -211,6 +211,8 @@ type t = { (* upper bound on the (delegated tz / own frozen tz) ratio *) percentage_of_frozen_deposits_slashed_per_double_baking : Percentage.t; percentage_of_frozen_deposits_slashed_per_double_attestation : Percentage.t; + max_slashing_per_block : Percentage.t; + max_slashing_threshold : int; 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_repr.ml b/src/proto_alpha/lib_protocol/constants_repr.ml index 14d4387913ff88da9f239beba03abf47f1e50711..9baca9476477ccff86df87ee47bb026a5aa0a7f5 100644 --- a/src/proto_alpha/lib_protocol/constants_repr.ml +++ b/src/proto_alpha/lib_protocol/constants_repr.ml @@ -338,11 +338,14 @@ module Generated = struct type t = { consensus_threshold : int; issuance_weights : Constants_parametric_repr.issuance_weights; + max_slashing_threshold : int; } let generate ~consensus_committee_size = (* The weights are expressed in [(256 * 80)]th of the total reward, because it is the smallest proportion used so far*) + (* let f = consensus_committee_size / 3 in *) + let max_slashing_threshold = (consensus_committee_size / 3) + 1 in let consensus_threshold = (consensus_committee_size * 2 / 3) + 1 in let bonus_committee_size = consensus_committee_size - consensus_threshold in let base_total_issued_per_minute = Tez_repr.of_mutez_exn 85_007_812L in @@ -351,6 +354,7 @@ module Generated = struct let reward_parts_quarter = 5120 (* = reward_parts_whole / 4 *) in let reward_parts_16th = 1280 (* = reward_parts_whole / 16 *) in { + max_slashing_threshold; consensus_threshold; issuance_weights = { diff --git a/src/proto_alpha/lib_protocol/constants_repr.mli b/src/proto_alpha/lib_protocol/constants_repr.mli index 97ca8e81c69e5b0d1797374ee3214631383c47c9..29e20a85e38ffa99600a8c0c3991aa41c536a255 100644 --- a/src/proto_alpha/lib_protocol/constants_repr.mli +++ b/src/proto_alpha/lib_protocol/constants_repr.mli @@ -120,6 +120,7 @@ module Generated : sig type t = { consensus_threshold : int; issuance_weights : Constants_parametric_repr.issuance_weights; + max_slashing_threshold : int; } (* This function is meant to be used just in lib_parameters and in the diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.ml b/src/proto_alpha/lib_protocol/delegate_sampler.ml index 7ecece83bf89017c9fcfd11693ba9e884b0506ab..76a140ee5d5051a1a42b7ab05e661d2b4cbd5540 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.ml +++ b/src/proto_alpha/lib_protocol/delegate_sampler.ml @@ -259,6 +259,25 @@ let cleanup_values_for_protocol_p ctxt ~preserved_cycles ~consensus_rights_delay ctxt Cycle_repr.(start_cycle ---> end_cycle) +let attesting_rights_count ctxt level = + let consensus_committee_size = + Constants_storage.consensus_committee_size ctxt + in + let open Lwt_result_syntax in + let*? slots = Slot_repr.Range.create ~min:0 ~count:consensus_committee_size in + Slot_repr.Range.fold_es + (fun (ctxt, map) slot -> + let* ctxt, consensus_pk = slot_owner ctxt level slot in + let map = + Signature.Public_key_hash.Map.update + consensus_pk.delegate + (function None -> Some 1 | Some slots_n -> Some (slots_n + 1)) + map + in + return (ctxt, map)) + (ctxt, Signature.Public_key_hash.Map.empty) + slots + module For_RPC = struct let delegate_current_baking_power ctxt delegate = let open Lwt_result_syntax in diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.mli b/src/proto_alpha/lib_protocol/delegate_sampler.mli index 801d20b58fafe16f7cc4b432aa351e3ce3943fbd..6dd6001bdd96f90d938c2a8ff2a2b3106f43b31b 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.mli +++ b/src/proto_alpha/lib_protocol/delegate_sampler.mli @@ -77,6 +77,14 @@ val cleanup_values_for_protocol_p : new_cycle:Cycle_repr.t -> Raw_context.t tzresult Lwt.t +(** [attesting_rights_count ctxt level] returns a map of the delegates to + their number of attestation slots for the given level. Fails if the + given level is in a cycle for which the seed is not in the storage *) +val attesting_rights_count : + Raw_context.t -> + Level_repr.t -> + (Raw_context.t * int Signature.Public_key_hash.Map.t) tzresult Lwt.t + module For_RPC : sig (** The baking power for a given delegate computed from its current stake. *) 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 fe14425c5c0886922918fcfc17329f086ec115ec..3d44b1ccb504b5b8171161d775f4adc80e11330e 100644 --- a/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml @@ -25,6 +25,25 @@ (* *) (*****************************************************************************) +(* TODO #6918: Remove after P *) +let update_slashing_storage_for_p ctxt = + let open Lwt_result_syntax in + let*! ctxt = + Storage.Contract.Slashed_deposits__Oxford.fold + ctxt + ~order:`Undefined + ~init:ctxt + ~f:(fun contract slashed_history ctxt -> + let slashed_history = + List.map + (fun (cycle, percentage) -> + (cycle, Percentage.convert_from_o_to_p percentage)) + slashed_history + in + Storage.Contract.Slashed_deposits.add ctxt contract slashed_history) + in + Storage.Contract.Slashed_deposits__Oxford.clear ctxt + let already_denounced_for_double_attesting ctxt delegate (level : Level_repr.t) round = let open Lwt_result_syntax in @@ -68,21 +87,17 @@ let punish_double_signing ctxt ~operation_hash let denounced = Option.value denounced_opt ~default:Storage.default_denounced in - let already_denounced, updated_denounced, slashing_percentage = + (* Placeholder value *) + let* ctxt, slashing_percentage = + Slash_percentage.get ctxt ~kind:misbehaviour.kind ~level [delegate] + in + let already_denounced, updated_denounced = let Storage.{for_double_baking; for_double_attesting} = denounced in match misbehaviour.kind with | Double_baking -> - ( for_double_baking, - {denounced with for_double_baking = true}, - Constants_storage - .percentage_of_frozen_deposits_slashed_per_double_baking - ctxt ) - | Double_attesting -> - ( for_double_attesting, - {denounced with for_double_attesting = true}, - Constants_storage - .percentage_of_frozen_deposits_slashed_per_double_attestation - ctxt ) + (for_double_baking, {denounced with for_double_baking = true}) + | Double_attesting | Double_preattesting -> + (for_double_attesting, {denounced with for_double_attesting = true}) in assert (Compare.Bool.(already_denounced = false)) ; let delegate_contract = Contract_repr.Implicit delegate in @@ -129,6 +144,12 @@ let clear_outdated_already_denounced ctxt ~new_cycle = | None -> Lwt.return ctxt | Some outdated_cycle -> Storage.Already_denounced.clear (ctxt, outdated_cycle) +(* Misbehaviour Map: orders denunciations for application. + See {!Misbehaviour_repr.compare} for the order on misbehaviours: + - by increasing level, then increasing round, then kind, ignoring the slot + - for the kind: double baking > double attesting > double preattesting *) +module MisMap = Map.Make (Misbehaviour_repr) + let apply_and_clear_denunciations ctxt = let open Lwt_result_syntax in let current_cycle = (Raw_context.current_level ctxt).cycle in @@ -166,13 +187,14 @@ let apply_and_clear_denunciations ctxt = let+ amount_to_burn = Tez_repr.(punishing_amount -? reward) in {reward; amount_to_burn} in - let* ctxt, balance_updates, remaining_denunciations = + (* Split denunciations into two groups: to be applied, and to be delayed *) + let*! block_denunciations_map, remaining_denunciations = Pending_denunciations_storage.fold ctxt ~order:`Undefined - ~init:(Ok (ctxt, [], [])) + ~init:(MisMap.empty, []) ~f:(fun delegate denunciations acc -> - let*? ctxt, balance_updates, remaining_denunciations = acc in + let block_map, remaining_denunciations = acc in (* Since the [max_slashing_period] is 2, and we want to apply denunciations at the end of this period, we "delay" the current cycle's misbehaviour's denunciations, while we apply the older denunciations. @@ -197,27 +219,65 @@ let apply_and_clear_denunciations ctxt = Cycle_repr.(misb_cycle < current_cycle)) denunciations in + let block_map = + List.fold_left + (fun block_map denunciation -> + MisMap.update + denunciation.Denunciations_repr.misbehaviour + (function + | None -> + Some + (Signature.Public_key_hash.Map.singleton + delegate + denunciation) + | Some map -> + Some + (Signature.Public_key_hash.Map.update + delegate + (function + | None -> Some denunciation + | Some old_d -> Some old_d) + map)) + block_map) + block_map + denunciations_to_apply + in + Lwt.return + ( block_map, + (delegate, denunciations_to_delay) :: remaining_denunciations )) + in + (* Processes the applicable denunciations *) + let* ctxt, balance_updates = + MisMap.fold_es + (fun ({Misbehaviour_repr.level = raw_level; round = _; kind; _} as miskey) + denunciations_map + acc -> + let ctxt, balance_updates = acc in + let level = + Level_repr.level_from_raw + ~cycle_eras:(Raw_context.cycle_eras ctxt) + raw_level + in + let misbehaviour_cycle = level.cycle in + let denunciations = + Signature.Public_key_hash.Map.bindings denunciations_map + in + let denounced = List.map fst denunciations in + let* ctxt, slashing_percentage = + Slash_percentage.get ctxt ~kind ~level denounced + in let+ ctxt, balance_updates = List.fold_left_es (fun (ctxt, balance_updates) - Denunciations_repr.{operation_hash; rewarded; misbehaviour} -> - let slashing_percentage = - match misbehaviour.kind with - | Double_baking -> - Constants_storage - .percentage_of_frozen_deposits_slashed_per_double_baking - ctxt - | Double_attesting -> - Constants_storage - .percentage_of_frozen_deposits_slashed_per_double_attestation - ctxt - in - let misbehaviour_cycle = - (Level_repr.level_from_raw - ~cycle_eras:(Raw_context.cycle_eras ctxt) - misbehaviour.level) - .cycle - in + ( delegate, + Denunciations_repr.{operation_hash; rewarded; misbehaviour} + ) -> + assert ( + Compare.Int.equal + (* This compare ignores the slot *) + (Misbehaviour_repr.compare miskey misbehaviour) + 0) ; + (* Validate ensures that [denunciations] contains [delegate] at most once *) let get_initial_frozen_deposits_of_misbehaviour_cycle = if Cycle_repr.equal current_cycle misbehaviour_cycle then Delegate_storage.initial_frozen_deposits @@ -321,12 +381,13 @@ let apply_and_clear_denunciations ctxt = punish_balance_updates @ reward_balance_updates @ balance_updates )) (ctxt, balance_updates) - denunciations_to_apply + denunciations in - ( ctxt, - balance_updates, - (delegate, denunciations_to_delay) :: remaining_denunciations )) + (ctxt, balance_updates)) + block_denunciations_map + (ctxt, []) in + (* Updates the storage to only contain the remaining denunciations *) let*! ctxt = Pending_denunciations_storage.clear ctxt in let*! ctxt = List.fold_left_s diff --git a/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.mli b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.mli index 9d45a438aaa7bec7ca848965c4325fba73e9562f..ee066bab8623d1132598ac5514595be1fb8f3c39 100644 --- a/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.mli @@ -88,5 +88,23 @@ val punish_double_signing : val clear_outdated_already_denounced : Raw_context.t -> new_cycle:Cycle_repr.t -> Raw_context.t Lwt.t +(** Applies pending denunciations in {!Storage.Pending_denunciations} + at the end of a cycle. The applicable denunciations are those that + point to a misbehavior whose max slashable period is ending. + (because [max_slashable_period = 2], the misbehavior must be + in the previous cycle). + + The denunciations are applied in chronological order of misbehaviour. + This function slashes the misbehaving bakers, by a proportion defined + in {!Slash_percentage}, and updates the respective + {!Storage.Contract.Slashed_deposits}. The applied denunciations are + removed from the storage. + + It returns the updated context, and all the balance updates, + which includes slashes for the bakers, the stakers, and the rewards + for the denouncers. +*) val apply_and_clear_denunciations : Raw_context.t -> (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t + +val update_slashing_storage_for_p : Raw_context.t -> Raw_context.t Lwt.t diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index e12415dba87c4ba51a72f82fe37ecef7ec0757d2..22248cfa95b78624f08ce97ff4b6b1f0e6fe8d4f 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -198,6 +198,7 @@ Delegate_rewards Delegate_missed_attestations_storage Forbidden_delegates_storage + Slash_percentage Delegate_slashed_deposits_storage Staking Delegate_cycles @@ -496,6 +497,7 @@ delegate_missed_attestations_storage.ml delegate_missed_attestations_storage.mli forbidden_delegates_storage.ml forbidden_delegates_storage.mli + slash_percentage.ml slash_percentage.mli delegate_slashed_deposits_storage.ml delegate_slashed_deposits_storage.mli staking.ml staking.mli delegate_cycles.ml delegate_cycles.mli @@ -795,6 +797,7 @@ delegate_missed_attestations_storage.ml delegate_missed_attestations_storage.mli forbidden_delegates_storage.ml forbidden_delegates_storage.mli + slash_percentage.ml slash_percentage.mli delegate_slashed_deposits_storage.ml delegate_slashed_deposits_storage.mli staking.ml staking.mli delegate_cycles.ml delegate_cycles.mli @@ -1078,6 +1081,7 @@ delegate_missed_attestations_storage.ml delegate_missed_attestations_storage.mli forbidden_delegates_storage.ml forbidden_delegates_storage.mli + slash_percentage.ml slash_percentage.mli delegate_slashed_deposits_storage.ml delegate_slashed_deposits_storage.mli staking.ml staking.mli delegate_cycles.ml delegate_cycles.mli diff --git a/src/proto_alpha/lib_protocol/init_storage.ml b/src/proto_alpha/lib_protocol/init_storage.ml index 1418a8e75fa2e6e580193a34eb1701cc21df44f6..f94f34f018e82428be50830482af64f7b1697459 100644 --- a/src/proto_alpha/lib_protocol/init_storage.ml +++ b/src/proto_alpha/lib_protocol/init_storage.ml @@ -321,6 +321,10 @@ let prepare_first_block chain_id ctxt ~typecheck_smart_contract let* ctxt = cleanup_values_for_protocol_p ctxt previous_proto_constants level in + (* Update the percentage representation of the stored slashes *) + let*! ctxt = + Delegate_slashed_deposits_storage.update_slashing_storage_for_p ctxt + in return (ctxt, []) in let* ctxt = diff --git a/src/proto_alpha/lib_protocol/misbehaviour_repr.ml b/src/proto_alpha/lib_protocol/misbehaviour_repr.ml index dcae67d856974a0c41f93a98ecc21b4a41ad5e26..f0f83d474177588b8d7a2094e9c78dd8db169714 100644 --- a/src/proto_alpha/lib_protocol/misbehaviour_repr.ml +++ b/src/proto_alpha/lib_protocol/misbehaviour_repr.ml @@ -5,7 +5,7 @@ (* *) (*****************************************************************************) -type kind = Double_baking | Double_attesting +type kind = Double_baking | Double_attesting | Double_preattesting let kind_encoding = let open Data_encoding in @@ -24,6 +24,12 @@ let kind_encoding = (constant "double attesting") (function Double_attesting -> Some () | _ -> None) (fun () -> Double_attesting); + case + (Tag 2) + ~title:"Double preattesting" + (constant "double preattesting") + (function Double_preattesting -> Some () | _ -> None) + (fun () -> Double_preattesting); ] type t = { @@ -33,6 +39,21 @@ type t = { slot : Slot_repr.t; } +let compare_kind a b = + let to_int = function + | Double_baking -> 0 + | Double_attesting -> 1 + | Double_preattesting -> 2 + in + Compare.Int.compare (to_int a) (to_int b) + +let equal_kind a b = Compare.Int.equal 0 (compare_kind a b) + +let compare a b = + Compare.or_else (Raw_level_repr.compare a.level b.level) @@ fun () -> + Compare.or_else (Round_repr.compare a.round b.round) @@ fun () -> + compare_kind a.kind b.kind + let encoding = let open Data_encoding in conv diff --git a/src/proto_alpha/lib_protocol/misbehaviour_repr.mli b/src/proto_alpha/lib_protocol/misbehaviour_repr.mli index 93e89fe300d560871cae7af8899f9af212d8d8e9..0ced59700c1b50e880d77fcc17a41b28c93f5636 100644 --- a/src/proto_alpha/lib_protocol/misbehaviour_repr.mli +++ b/src/proto_alpha/lib_protocol/misbehaviour_repr.mli @@ -6,10 +6,7 @@ (*****************************************************************************) (** Which double signing event has occurred. *) -type kind = - | Double_baking - | Double_attesting - (** Includes both double preattestion and double attestion. *) +type kind = Double_baking | Double_attesting | Double_preattesting (** Internal representation of a double signing event used in {!Denunciations_repr.item}. @@ -34,3 +31,10 @@ type t = { } val encoding : t Data_encoding.t + +val compare_kind : kind -> kind -> int + +val equal_kind : kind -> kind -> bool + +(** Note: the field [slot] is not taken into account in this comparison *) +val compare : t -> t -> int diff --git a/src/proto_alpha/lib_protocol/percentage.ml b/src/proto_alpha/lib_protocol/percentage.ml index d801e358cd09af6f8c32722e12857b72b74ea13e..7696be983d965701d5796262333e8a5a699a3823 100644 --- a/src/proto_alpha/lib_protocol/percentage.ml +++ b/src/proto_alpha/lib_protocol/percentage.ml @@ -7,21 +7,47 @@ type t = int -let one_hundred_percent = 100 +(* The factor by which to multiply the smallest non-zero representation in + order to obtain 1%. A factor of 100 means that the precision is 0.01%. *) +let precision_factor = 100 + +let one_hundred_percent = 100 * precision_factor + +(* TODO #6918: Remove after P *) +let convert_from_o_to_p x = x * precision_factor + +(* TODO #6918: Remove after P *) +let of_int_guarded_legacy_in_o i = + if Compare.Int.(i >= 0 && i <= 100) then Ok i + else Error "Value must be between 0 and 100" let of_int_guarded i = if Compare.Int.(i >= 0 && i <= one_hundred_percent) then Ok i - else Error "Value must be between 0 and 100" + else + Error (Format.asprintf "Value must be between 0 and %d" one_hundred_percent) let of_int_bounded i = Compare.Int.(max 0 (min one_hundred_percent i)) +(* TODO #6918: Remove after P *) +let encoding_legacy_in_o = + let open Data_encoding in + conv_with_guard (fun i -> i) of_int_guarded_legacy_in_o uint8 + let encoding = let open Data_encoding in - conv_with_guard (fun i -> i) of_int_guarded uint8 + conv_with_guard (fun i -> i) of_int_guarded uint16 let of_ratio_bounded Ratio_repr.{numerator; denominator} = of_int_bounded (one_hundred_percent * numerator / denominator) +let of_q_bounded ~round (Q.{num; den} as q) = + if Compare.Q.(q >= Q.one) then one_hundred_percent + else + (* Ensures that [to_int] doesn't overflow *) + let div = match round with `Down -> Z.div | `Up -> Z.cdiv in + of_int_bounded + (Z.to_int (div (Z.mul (Z.of_int one_hundred_percent) num) den)) + let to_q x = Q.of_ints x one_hundred_percent let neg p = one_hundred_percent - p @@ -30,13 +56,17 @@ let add_bounded p1 p2 = Compare.Int.min one_hundred_percent (p1 + p2) let sub_bounded p1 p2 = Compare.Int.max 0 (p1 - p2) +let mul ~round a b = Q.mul (to_q a) (to_q b) |> of_q_bounded ~round + +let mul_q_bounded ~round a q = Q.mul (to_q a) q |> of_q_bounded ~round + let p0 = 0 -let p5 = 5 +let p5 = 5 * precision_factor -let p50 = 50 +let p50 = 50 * precision_factor -let p51 = 51 +let p51 = 51 * precision_factor let p100 = one_hundred_percent diff --git a/src/proto_alpha/lib_protocol/percentage.mli b/src/proto_alpha/lib_protocol/percentage.mli index 29a8097c5bfa5a4f5b743113dfca069425c3cd23..c86d4cb14899bb88b694fd8bbef068494c925784 100644 --- a/src/proto_alpha/lib_protocol/percentage.mli +++ b/src/proto_alpha/lib_protocol/percentage.mli @@ -6,14 +6,19 @@ (*****************************************************************************) (** A value representing percentages, between 0% and 100%, inclusive. - Precision of the representation is 1% *) + Precision of the representation is 0.01% *) type t +(* TODO #6918: Remove after P *) +val encoding_legacy_in_o : t Data_encoding.t + val encoding : t Data_encoding.t -(** Rounds down to the nearest percent *) +(** Rounds down to the nearest 0.01% *) val of_ratio_bounded : Ratio_repr.t -> t +val of_q_bounded : round:[`Down | `Up] -> Q.t -> t + val to_q : t -> Q.t (** [neg p] is [100% - p]. *) @@ -23,6 +28,10 @@ val add_bounded : t -> t -> t val sub_bounded : t -> t -> t +val mul : round:[`Down | `Up] -> t -> t -> t + +val mul_q_bounded : round:[`Down | `Up] -> t -> Q.t -> t + (** Constants *) (** 0% *) @@ -43,3 +52,5 @@ val p100 : t module Compare : sig val ( >= ) : t -> t -> bool end + +val convert_from_o_to_p : t -> t diff --git a/src/proto_alpha/lib_protocol/raw_context.ml b/src/proto_alpha/lib_protocol/raw_context.ml index b7a6ef968f89c7bc3a4b99a1bc8894c896a0a2ad..c67c6343d8fd39199cb564131fc359de2c8af5b1 100644 --- a/src/proto_alpha/lib_protocol/raw_context.ml +++ b/src/proto_alpha/lib_protocol/raw_context.ml @@ -1193,6 +1193,10 @@ let prepare_first_block ~level ~timestamp _chain_id ctxt = (* We change the consensus_rights_delay value only for mainnet *) if Compare.Int.(c.preserved_cycles = 5) then 2 else c.preserved_cycles in + let Constants_repr.Generated.{max_slashing_threshold; _} = + Constants_repr.Generated.generate + ~consensus_committee_size:c.consensus_committee_size + in let constants = Constants_parametric_repr. { @@ -1228,9 +1232,13 @@ let prepare_first_block ~level ~timestamp _chain_id ctxt = limit_of_delegation_over_baking = c.limit_of_delegation_over_baking; percentage_of_frozen_deposits_slashed_per_double_baking = - c.percentage_of_frozen_deposits_slashed_per_double_baking; + Percentage.convert_from_o_to_p + c.percentage_of_frozen_deposits_slashed_per_double_baking; percentage_of_frozen_deposits_slashed_per_double_attestation = - c.percentage_of_frozen_deposits_slashed_per_double_attestation; + Percentage.convert_from_o_to_p + c.percentage_of_frozen_deposits_slashed_per_double_attestation; + max_slashing_per_block = Percentage.p100; + max_slashing_threshold; (* The `testnet_dictator` should absolutely be None on mainnet *) testnet_dictator = c.testnet_dictator; initial_seed = c.initial_seed; diff --git a/src/proto_alpha/lib_protocol/slash_percentage.ml b/src/proto_alpha/lib_protocol/slash_percentage.ml new file mode 100644 index 0000000000000000000000000000000000000000..68c9f28c94aa4bdc4ec9861f03da68852f31b7d6 --- /dev/null +++ b/src/proto_alpha/lib_protocol/slash_percentage.ml @@ -0,0 +1,46 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +let for_double_baking ctxt = + Constants_storage.percentage_of_frozen_deposits_slashed_per_double_baking ctxt + +let for_double_attestation ctxt rights denounced = + if + not + (Constants_storage.adaptive_issuance_ns_enable ctxt + && Constants_storage.adaptive_issuance_enable ctxt) + then + Constants_storage + .percentage_of_frozen_deposits_slashed_per_double_attestation + ctxt + else + let total_rights_denounced = + List.fold_left + (fun total delegate -> + Option.value + (Signature.Public_key_hash.Map.find delegate rights) + ~default:0 + |> ( + ) total) + 0 + denounced + in + let threshold_max = (Raw_context.constants ctxt).max_slashing_threshold in + let max_slashing = (Raw_context.constants ctxt).max_slashing_per_block in + if Compare.Int.(total_rights_denounced >= threshold_max) then max_slashing + else + let num_z = Z.(pow (of_int total_rights_denounced) 2) in + let den_z = Z.(pow (of_int threshold_max) 2) in + Percentage.mul_q_bounded ~round:`Up max_slashing Q.(num_z /// den_z) + +let get ctxt ~(kind : Misbehaviour_repr.kind) ~(level : Level_repr.t) + (denounced : Signature.public_key_hash list) = + let open Lwt_result_syntax in + match kind with + | Double_baking -> return (ctxt, for_double_baking ctxt) + | Double_attesting | Double_preattesting -> + let* ctxt, rights = Delegate_sampler.attesting_rights_count ctxt level in + return (ctxt, for_double_attestation ctxt rights denounced) diff --git a/src/proto_alpha/lib_protocol/slash_percentage.mli b/src/proto_alpha/lib_protocol/slash_percentage.mli new file mode 100644 index 0000000000000000000000000000000000000000..2f8a71eca8519c6fa8e700ce7cd46561f7559943 --- /dev/null +++ b/src/proto_alpha/lib_protocol/slash_percentage.mli @@ -0,0 +1,22 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Nomadic Labs, *) +(* *) +(*****************************************************************************) + +(** [get ctxt ~kind ~level denounced] returns the percentage that needs to be + applied for the given misbehaviour. + + [denounced] is the list of delegates that have been denounced together for + the given [kind], for the given [level] and for the same round. The amount + slashed increases quadratically as the number of attesting slots of + denounced delegates increases. The maximum slashing value + [max_slashing_per_block] is reached when that number of slots reaches + [max_slashing_threshold] . *) +val get : + Raw_context.t -> + kind:Misbehaviour_repr.kind -> + level:Level_repr.t -> + Signature.public_key_hash list -> + (Raw_context.t * Percentage.t) tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index e0e2fb3d32795ace8ceab539214fa9eaa3687085..f013bd216c5d823679f0b60537ca627c3d844c3f 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -187,6 +187,18 @@ module Slashed_deposits_history = struct | _ -> Percentage.p0 end +(* TODO #6918: Remove after P *) +module Slashed_deposits_history__Oxford = struct + include Slashed_deposits_history + + let encoding = + let open Data_encoding in + list + (obj2 + (req "cycle" Cycle_repr.encoding) + (req "slashed_percentage" Percentage.encoding_legacy_in_o)) +end + module Unstake_request = struct type request = Cycle_repr.t * Tez_repr.t @@ -475,14 +487,24 @@ module Contract = struct end) (Tez_repr) + (* TODO #6918: change name back after P *) module Slashed_deposits = Indexed_context.Make_map (Registered) (struct - let name = ["slashed_deposits"] + let name = ["slashed_deposits_p"] end) (Slashed_deposits_history) + (* TODO #6918: Remove after P *) + module Slashed_deposits__Oxford = + Indexed_context.Make_map + (Ghost) + (struct + let name = ["slashed_deposits"] + end) + (Slashed_deposits_history__Oxford) + module Bond_id_index = Make_indexed_subcontext (Make_subcontext (Registered) (Indexed_context.Raw_context) diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index dbd3fabb56b44fb1edbd75d08045ff1d358c9560..fcfd823b79531fd7024b824ccad1b423064f12f7 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -70,6 +70,10 @@ module Slashed_deposits_history : sig val get : Cycle_repr.t -> t -> slashed_percentage end +(* TODO #6918: Remove after P *) +module Slashed_deposits_history__Oxford : + module type of Slashed_deposits_history + module Unstake_request : sig type request = Cycle_repr.t * Tez_repr.t @@ -283,6 +287,13 @@ module Contract : sig and type value = Slashed_deposits_history.t and type t := Raw_context.t + (* TODO #6918: Remove after P *) + module Slashed_deposits__Oxford : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Slashed_deposits_history.t + and type t := Raw_context.t + (** Associates a contract and a bond_id with a bond, i.e. an amount of tez that is frozen. *) module Frozen_bonds : 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 f529f3d33d50bbfc9a8512bfe1594fd1dd95f98b..504bb7859556cab539a570c16cc6d761eb22aa2b 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 @@ -1044,7 +1044,7 @@ let apply_slashing constants .Protocol.Alpha_context.Constants.Parametric .percentage_of_frozen_deposits_slashed_per_double_baking - | Double_attesting -> + | Double_attesting | Double_preattesting -> constants.percentage_of_frozen_deposits_slashed_per_double_attestation in let get_total_supply acc_map = 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 561088f9eaa2509d277db8ed54bea1efbff49efb..e2a22bf8a44c26f30c1cf0c8ae68cf3678ead7bf 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 @@ -1422,7 +1422,8 @@ let check_pending_slashings (block, state) : unit tzresult Lwt.t = rewarded (match misbehaviour.kind with | Double_baking -> "double baking" - | Double_attesting -> "double attesting") + | Double_attesting -> "double attesting" + | Double_preattesting -> "double preattesting") in let denunciations_pp = Format.pp_print_list denunciations_obj_pp in let* () = @@ -1575,7 +1576,7 @@ let pct_from_kind (block : Block.t) = function block.constants.percentage_of_frozen_deposits_slashed_per_double_baking |> Q.(mul (100 // 1)) |> Q.to_int - | Double_attesting -> + | Double_attesting | Double_preattesting -> Protocol.Percentage.to_q block.constants .percentage_of_frozen_deposits_slashed_per_double_attestation 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 fb4b48d049d69987485539add31622682f90e696..3fd6886a34746924b7314160fcef150c99f0d194 100644 --- a/src/proto_alpha/lib_protocol/test/unit/test_percentage.ml +++ b/src/proto_alpha/lib_protocol/test/unit/test_percentage.ml @@ -25,6 +25,10 @@ let assert_equal ~loc n (pct : Percentage.t) = let assert_equal_tez ~loc t1 t2 = Assert.equal ~loc Tez_repr.equal "Tez aren't equal" Tez_repr.pp t1 t2 +let assert_equal_q ~loc q (pct : Percentage.t) = + let pct_q = Percentage.to_q pct in + Assert.equal_q ~loc q pct_q + let f = Tez_repr.mul_percentage let test_constant_values () = @@ -101,6 +105,58 @@ let test_mul_percentage () = in return_unit +let test_mul () = + let open Lwt_result_syntax in + let mul = Percentage.mul ~round:`Down in + let* () = + assert_equal_q + ~loc:__LOC__ + Q.(25 // 100) + (mul Percentage.p50 Percentage.p50) + in + let* () = + assert_equal_q + ~loc:__LOC__ + Q.(25 // 10000) + (mul Percentage.p5 Percentage.p5) + in + return_unit + +let test_of_q () = + let open Lwt_result_syntax in + let round = `Down in + let of_q = Percentage.of_q_bounded in + let* () = + assert_equal_q ~loc:__LOC__ Q.(11 // 100) (of_q ~round Q.(11 // 100)) + in + let* () = assert_equal_q ~loc:__LOC__ Q.one (of_q ~round Q.(199 // 100)) in + (* round down *) + let* () = + assert_equal_q ~loc:__LOC__ Q.(777 // 10000) (of_q ~round Q.(777 // 9999)) + in + (* round up *) + let* () = + assert_equal_q + ~loc:__LOC__ + Q.(778 // 10000) + (of_q ~round:`Up Q.(777 // 9999)) + in + + (* precision *) + let* () = assert_equal_q ~loc:__LOC__ Q.zero (of_q ~round Q.(1 // 10001)) in + let* () = + assert_equal_q ~loc:__LOC__ Q.(1 // 10000) (of_q ~round Q.(1 // 10000)) + in + let* () = + assert_equal_q ~loc:__LOC__ Q.(1 // 10000) (of_q ~round:`Up Q.(1 // 10001)) + in + (* no overflow *) + let big_z = Z.of_int64 9131138316486228048L in + let* () = + assert_equal_q ~loc:__LOC__ Q.one (of_q ~round Q.(big_z /// Z.one)) + in + return_unit + let tests = Tztest. [ @@ -108,6 +164,8 @@ let tests = tztest "Test neg" `Quick test_neg; tztest "Test bounded" `Quick test_bounded; tztest "Test mul_percentage" `Quick test_mul_percentage; + tztest "Test mul" `Quick test_mul; + tztest "Test of_q" `Quick test_of_q; ] let () = diff --git a/src/proto_alpha/lib_protocol/unstake_requests_storage.ml b/src/proto_alpha/lib_protocol/unstake_requests_storage.ml index 817b5c8d5ea87bffccaebfd5251dc02c87f322c9..579378b7cf2e13c02c230d673137a6fdfa21e38a 100644 --- a/src/proto_alpha/lib_protocol/unstake_requests_storage.ml +++ b/src/proto_alpha/lib_protocol/unstake_requests_storage.ml @@ -214,7 +214,7 @@ module For_RPC = struct (Constants_storage .percentage_of_frozen_deposits_slashed_per_double_baking ctxt) - | Double_attesting -> + | Double_attesting | Double_preattesting -> Percentage.add_bounded acc (Constants_storage diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- misc_protocol.out index 305e5e95a3da7df3e28e34d99f745e561e3125fd..d8135ede97b1aeb58eb82866624091d4e4ba4533 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- misc_protocol.out @@ -31,8 +31,9 @@ "consensus_threshold": 0, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "limit_of_delegation_over_baking": 19, - "percentage_of_frozen_deposits_slashed_per_double_baking": 5, - "percentage_of_frozen_deposits_slashed_per_double_attestation": 50, + "percentage_of_frozen_deposits_slashed_per_double_baking": 500, + "percentage_of_frozen_deposits_slashed_per_double_attestation": 5000, + "max_slashing_per_block": 10000, "max_slashing_threshold": 86, "cache_script_size": 100000000, "cache_stake_distribution_cycles": 8, "cache_sampler_state_cycles": 8, "dal_parametric": diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- misc_protocol.out index 9a22690a671da73c1f58d0f2e045f07e3e54b296..45fa33e0a8ffe5a19e63fd52f90255446244bd88 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- misc_protocol.out @@ -31,8 +31,9 @@ "consensus_threshold": 0, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "limit_of_delegation_over_baking": 19, - "percentage_of_frozen_deposits_slashed_per_double_baking": 5, - "percentage_of_frozen_deposits_slashed_per_double_attestation": 50, + "percentage_of_frozen_deposits_slashed_per_double_baking": 500, + "percentage_of_frozen_deposits_slashed_per_double_attestation": 5000, + "max_slashing_per_block": 10000, "max_slashing_threshold": 86, "cache_script_size": 100000000, "cache_stake_distribution_cycles": 8, "cache_sampler_state_cycles": 8, "dal_parametric": diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- misc_protocol.out index 15a3f8f6b6d4fe27fb8bba4338d85b95534c78be..36e4b18f568a632b0d410195721615a8b07147f8 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- misc_protocol.out @@ -31,8 +31,9 @@ "consensus_threshold": 0, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "limit_of_delegation_over_baking": 19, - "percentage_of_frozen_deposits_slashed_per_double_baking": 5, - "percentage_of_frozen_deposits_slashed_per_double_attestation": 50, + "percentage_of_frozen_deposits_slashed_per_double_baking": 500, + "percentage_of_frozen_deposits_slashed_per_double_attestation": 5000, + "max_slashing_per_block": 10000, "max_slashing_threshold": 86, "cache_script_size": 100000000, "cache_stake_distribution_cycles": 8, "cache_sampler_state_cycles": 8, "dal_parametric": diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out index 5d43abbe295745b7ee13f3113a27869247046263..ee32b3da1c7fda5a179b329a88af73f9deb5678f 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out @@ -31,8 +31,9 @@ "consensus_threshold": 0, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "limit_of_delegation_over_baking": 19, - "percentage_of_frozen_deposits_slashed_per_double_baking": 5, - "percentage_of_frozen_deposits_slashed_per_double_attestation": 50, + "percentage_of_frozen_deposits_slashed_per_double_baking": 500, + "percentage_of_frozen_deposits_slashed_per_double_attestation": 5000, + "max_slashing_per_block": 10000, "max_slashing_threshold": 86, "cache_script_size": 100000000, "cache_stake_distribution_cycles": 8, "cache_sampler_state_cycles": 8, "dal_parametric": diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out index 5d43abbe295745b7ee13f3113a27869247046263..ee32b3da1c7fda5a179b329a88af73f9deb5678f 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out @@ -31,8 +31,9 @@ "consensus_threshold": 0, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "limit_of_delegation_over_baking": 19, - "percentage_of_frozen_deposits_slashed_per_double_baking": 5, - "percentage_of_frozen_deposits_slashed_per_double_attestation": 50, + "percentage_of_frozen_deposits_slashed_per_double_baking": 500, + "percentage_of_frozen_deposits_slashed_per_double_attestation": 5000, + "max_slashing_per_block": 10000, "max_slashing_threshold": 86, "cache_script_size": 100000000, "cache_stake_distribution_cycles": 8, "cache_sampler_state_cycles": 8, "dal_parametric": diff --git a/tezt/tests/mockup.ml b/tezt/tests/mockup.ml index 57b0f3bfb1ca9f6faa4bd742d57021400cc27b33..dec4ff3351b079ce0b891eb7b15f8883ae10313b 100644 --- a/tezt/tests/mockup.ml +++ b/tezt/tests/mockup.ml @@ -1184,10 +1184,15 @@ let test_create_mockup_config_show_init_roundtrip protocols = let constant_parametric_constants : JSON.t = JSON.annotate ~origin:"constant_parametric_constants" @@ `O - [ - (* DO NOT EDIT the value consensus_threshold this is actually a constant, not a parameter *) - ("consensus_threshold", `Float 0.0); - ] + ((* DO NOT EDIT the value consensus_threshold this is actually a constant, not a parameter *) + ("consensus_threshold", `Float 0.0) + :: + (if Protocol.number protocol >= 019 then + [ + (* Constraint: 0 <= max_slashing_per_block <= 10_000 *) + ("max_slashing_per_block", `Float 10_000.0); + ] + else [])) in (* To fulfill the requirement that [blocks_per_epoch], present in protocols up to O, divides [blocks_per_cycle], we set [blocks_per_cycle] to 1, for