diff --git a/src/proto_alpha/lib_plugin/delegate_services.ml b/src/proto_alpha/lib_plugin/delegate_services.ml index b107de23dc0da8646ea87445f8155b8957666e29..d9da5b3dfdb6d01099b0ba05cfbced24a8bfede9 100644 --- a/src/proto_alpha/lib_plugin/delegate_services.ml +++ b/src/proto_alpha/lib_plugin/delegate_services.ml @@ -153,30 +153,35 @@ let dal_participation_info_encoding = total_dal_attested_slots; expected_dal_rewards; sufficient_dal_participation; + denounced; } -> ( expected_assigned_shards_per_slot, delegate_attested_dal_slots, total_dal_attested_slots, expected_dal_rewards, - sufficient_dal_participation )) + sufficient_dal_participation, + denounced )) (fun ( expected_assigned_shards_per_slot, delegate_attested_dal_slots, total_dal_attested_slots, expected_dal_rewards, - sufficient_dal_participation ) -> + sufficient_dal_participation, + denounced ) -> { expected_assigned_shards_per_slot; delegate_attested_dal_slots; total_dal_attested_slots; expected_dal_rewards; sufficient_dal_participation; + denounced; }) - (obj5 + (obj6 (req "expected_assigned_shards_per_slot" int31) (req "delegate_attested_dal_slots" int31) (req "total_dal_attested_slots" int31) (req "expected_dal_rewards" Tez.encoding) - (req "sufficient_dal_participation" bool)) + (req "sufficient_dal_participation" bool) + (req "denounced" bool)) type deposit_per_cycle = {cycle : Cycle.t; deposit : Tez.t} @@ -901,7 +906,9 @@ module S = struct declared to be attested by the protocol. Note that this flag may \ evolve during the cycle. Also note, in particular, that if no DAL no \ DAL slots have been globally attested during the cycle (i.e., when \ - 'total_dal_attested_slots' is zero), the flag is true." + 'total_dal_attested_slots' is zero), the flag is true. The \ + 'denounced' field specifies whether the delegate was denounced for \ + not detecting traps during the current cycle." ~query:RPC_query.empty ~output:dal_participation_info_encoding RPC_path.(path / "dal_participation") diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index 59c0291b4d8a16785c78f6eebd7a0143e9274f98..3c7dcfe24f9f480282e5f0976284f423ca0f368c 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -180,9 +180,9 @@ "Delegate_storage", "Delegate_sampler", "Delegate_rewards", - "Delegate_missed_attestations_storage", "Already_denounced_storage", "Dal_already_denounced_storage", + "Delegate_missed_attestations_storage", "Forbidden_delegates_storage", "Slash_percentage", "Delegate_slashed_deposits_storage", diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index f76701a00c7eb652a47ba2abab8c34a72fbde3e6..72515d9b04246c2021adfd5870079e3338eb1f40 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2524,6 +2524,7 @@ module Delegate : sig total_dal_attested_slots : int; expected_dal_rewards : Tez.t; sufficient_dal_participation : bool; + denounced : bool; } val participation_info : @@ -3060,6 +3061,9 @@ module Dal : sig (** See {!Dal_already_denounced_storage.is_already_denounced}. *) val is_already_denounced : context -> public_key_hash -> Level.t -> Slot_index.t -> bool Lwt.t + + (** See {!Dal_already_denounced_storage.is_denounced}. *) + val is_denounced : context -> public_key_hash -> Cycle.t -> bool Lwt.t end end diff --git a/src/proto_alpha/lib_protocol/dal_already_denounced_storage.ml b/src/proto_alpha/lib_protocol/dal_already_denounced_storage.ml index f0bad6f6d7a695fc19f897825f9d0c228fff15a3..2ded5bb400cdf6fba3b3f1621577ec8cc131eb40 100644 --- a/src/proto_alpha/lib_protocol/dal_already_denounced_storage.ml +++ b/src/proto_alpha/lib_protocol/dal_already_denounced_storage.ml @@ -12,6 +12,9 @@ let is_already_denounced ctxt delegate (level : Level_repr.t) slot_index = (ctxt, level.cycle) ((level.level, slot_index), delegate) +let is_denounced ctxt delegate cycle = + Storage.Dal_denounced_delegates.mem (ctxt, cycle) delegate + let add_denunciation ctxt delegate (level : Level_repr.t) slot_index = let open Lwt_syntax in let* already_denounced = @@ -20,10 +23,13 @@ let add_denunciation ctxt delegate (level : Level_repr.t) slot_index = let* ctxt = if already_denounced then Lwt.return ctxt else - Storage.Dal_already_denounced.add - (ctxt, level.cycle) - ((level.level, slot_index), delegate) - () + let* ctxt = + Storage.Dal_already_denounced.add + (ctxt, level.cycle) + ((level.level, slot_index), delegate) + () + in + Storage.Dal_denounced_delegates.add (ctxt, level.cycle) delegate () in return (ctxt, already_denounced) @@ -37,4 +43,6 @@ let clear_outdated_cycle ctxt ~new_cycle = match Cycle_repr.(sub new_cycle (Constants_repr.denunciation_period + 1)) with | None -> Lwt.return ctxt | Some outdated_cycle -> - Storage.Dal_already_denounced.clear (ctxt, outdated_cycle) + let open Lwt_syntax in + let* ctxt = Storage.Dal_already_denounced.clear (ctxt, outdated_cycle) in + Storage.Dal_denounced_delegates.clear (ctxt, outdated_cycle) diff --git a/src/proto_alpha/lib_protocol/dal_already_denounced_storage.mli b/src/proto_alpha/lib_protocol/dal_already_denounced_storage.mli index 27ae5476ae546f1d94d339e2182fc46135947628..c67a5d4b23c2b8dbe49fa5ea2f1e408900fbf3ec 100644 --- a/src/proto_alpha/lib_protocol/dal_already_denounced_storage.mli +++ b/src/proto_alpha/lib_protocol/dal_already_denounced_storage.mli @@ -30,6 +30,10 @@ val is_already_denounced : Dal_slot_index_repr.t -> bool Lwt.t +(** Returns whether the given delegate has been denounced in the given cycle. *) +val is_denounced : + Raw_context.t -> Signature.Public_key_hash.t -> Cycle_repr.t -> bool Lwt.t + (** Records a denunciation in {!Storage.Dal_already_denounced}. Returns a pair [(ctxt, already_denounced)], where diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.ml b/src/proto_alpha/lib_protocol/delegate_cycles.ml index c1b4ac26c0fead99749e5ed9437a04a1d0825230..61ae9e32083bb012a1a83869c40fa93a8435effc 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.ml +++ b/src/proto_alpha/lib_protocol/delegate_cycles.ml @@ -52,10 +52,13 @@ let update_activity ctxt last_cycle = let delegate_has_revealed_nonces delegate unrevelead_nonces_set = not (Signature.Public_key_hash.Set.mem delegate unrevelead_nonces_set) -let distribute_dal_attesting_rewards ctxt delegate +let distribute_dal_attesting_rewards ctxt delegate ~last_cycle ~dal_attesting_reward_per_shard ~total_dal_attested_slots ~total_active_stake_weight ~active_stake_weight active_stake = let open Lwt_result_syntax in + let*! denounced_in_cycle = + Dal_already_denounced_storage.is_denounced ctxt delegate last_cycle + in let* ctxt, dal_attested_slots_by_delegate = Delegate_missed_attestations_storage .get_and_reset_delegate_dal_participation @@ -78,7 +81,7 @@ let distribute_dal_attesting_rewards ctxt delegate let dal_rewards = Tez_repr.mul_exn dal_attesting_reward_per_shard expected_dal_shards in - if sufficient_dal_participation then + if sufficient_dal_participation && not denounced_in_cycle then Shared_stake.pay_rewards ctxt ~active_stake @@ -98,7 +101,7 @@ let distribute_dal_attesting_rewards ctxt delegate (`Lost_dal_attesting_rewards delegate) dal_rewards -let maybe_distribute_dal_attesting_rewards ctxt delegate +let maybe_distribute_dal_attesting_rewards ctxt delegate ~last_cycle ~dal_attesting_reward_per_shard ~total_dal_attested_slots ~total_active_stake_weight ~active_stake_weight active_stake = let open Lwt_result_syntax in @@ -114,6 +117,7 @@ let maybe_distribute_dal_attesting_rewards ctxt delegate distribute_dal_attesting_rewards ctxt delegate + ~last_cycle ~dal_attesting_reward_per_shard ~total_dal_attested_slots ~total_active_stake_weight @@ -194,6 +198,7 @@ let distribute_attesting_rewards ctxt last_cycle unrevealed_nonces = maybe_distribute_dal_attesting_rewards ctxt delegate + ~last_cycle ~dal_attesting_reward_per_shard ~total_dal_attested_slots ~total_active_stake_weight diff --git a/src/proto_alpha/lib_protocol/delegate_missed_attestations_storage.ml b/src/proto_alpha/lib_protocol/delegate_missed_attestations_storage.ml index 944f0593a8c5ef2c46b95e1574eba66c90c1d40a..e5fa4f1ae98a3fdeb8303e8666ba3c3c091120b4 100644 --- a/src/proto_alpha/lib_protocol/delegate_missed_attestations_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_missed_attestations_storage.ml @@ -321,6 +321,7 @@ module For_RPC = struct total_dal_attested_slots : int; expected_dal_rewards : Tez_repr.t; sufficient_dal_participation : bool; + denounced : bool; } (* Inefficient, only for RPC *) @@ -345,6 +346,7 @@ module For_RPC = struct total_dal_attested_slots = 0; expected_dal_rewards = Tez_repr.zero; sufficient_dal_participation = false; + denounced = false; } | Some active_stake -> let* total_active_stake = @@ -373,13 +375,18 @@ module For_RPC = struct ~dal_attested_slots_by_delegate ~total_dal_attested_slots in + let*! denounced = + Dal_already_denounced_storage.is_denounced ctxt delegate level.cycle + in let*? dal_attesting_reward_per_shard = Delegate_rewards.dal_attesting_reward_per_shard ctxt in let expected_dal_rewards = - Tez_repr.mul_exn - dal_attesting_reward_per_shard - expected_assigned_shards_per_slot + if denounced then Tez_repr.zero + else + Tez_repr.mul_exn + dal_attesting_reward_per_shard + expected_assigned_shards_per_slot in return { @@ -389,6 +396,7 @@ module For_RPC = struct total_dal_attested_slots = Int32.to_int total_dal_attested_slots; expected_dal_rewards; sufficient_dal_participation; + denounced; } (* Inefficient, only for RPC *) diff --git a/src/proto_alpha/lib_protocol/delegate_missed_attestations_storage.mli b/src/proto_alpha/lib_protocol/delegate_missed_attestations_storage.mli index 4e175ac056d8955a76343506ddb55b171b1e9bc0..5638be1cbad8421d9c62e81109f6853805a6f600 100644 --- a/src/proto_alpha/lib_protocol/delegate_missed_attestations_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_missed_attestations_storage.mli @@ -168,6 +168,9 @@ module For_RPC : sig particular, this flag is true if no DAL slot is attested globally by the protocol at a given cycle (i.e. [total_dal_attested_slots] = 0). (dynamic) *) + denounced : bool; + (** A boolean flag telling whether the delegate was denounced for + not detecting traps. (dynamic) *) } (** Only use this function for RPC: this is expensive. diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index 15a062600551661ce2076f94d7dfacdfa95bd459..ead9b8296a7c105a324df7c253703881a5d8fe71 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -196,9 +196,9 @@ Delegate_storage Delegate_sampler Delegate_rewards - Delegate_missed_attestations_storage Already_denounced_storage Dal_already_denounced_storage + Delegate_missed_attestations_storage Forbidden_delegates_storage Slash_percentage Delegate_slashed_deposits_storage @@ -494,10 +494,10 @@ delegate_storage.ml delegate_storage.mli delegate_sampler.ml delegate_sampler.mli delegate_rewards.ml delegate_rewards.mli - delegate_missed_attestations_storage.ml - delegate_missed_attestations_storage.mli already_denounced_storage.ml already_denounced_storage.mli dal_already_denounced_storage.ml dal_already_denounced_storage.mli + 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 @@ -794,10 +794,10 @@ delegate_storage.ml delegate_storage.mli delegate_sampler.ml delegate_sampler.mli delegate_rewards.ml delegate_rewards.mli - delegate_missed_attestations_storage.ml - delegate_missed_attestations_storage.mli already_denounced_storage.ml already_denounced_storage.mli dal_already_denounced_storage.ml dal_already_denounced_storage.mli + 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 @@ -1078,10 +1078,10 @@ delegate_storage.ml delegate_storage.mli delegate_sampler.ml delegate_sampler.mli delegate_rewards.ml delegate_rewards.mli - delegate_missed_attestations_storage.ml - delegate_missed_attestations_storage.mli already_denounced_storage.ml already_denounced_storage.mli dal_already_denounced_storage.ml dal_already_denounced_storage.mli + 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 diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index 7b50f52ec17fb96f9efbb9cc34c7770f7c46f51f..202ae05321d0891203f078c3d3f6a8f7b5a0dce3 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -1205,6 +1205,19 @@ module Cycle = struct let encoding = Data_encoding.unit end) + module Dal_denounced_delegates = + Make_indexed_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["dal_denounced_delegates"] + end)) + (Public_key_hash_index) + (struct + type t = unit + + let encoding = Data_encoding.empty + end) + module Selected_stake_distribution = Indexed_context.Make_map (Registered) @@ -1347,6 +1360,7 @@ end module Already_denounced = Cycle.Already_denounced module Dal_already_denounced = Cycle.Dal_already_denounced +module Dal_denounced_delegates = Cycle.Dal_denounced_delegates module Pending_consensus_keys = Cycle.Pending_consensus_keys module Pending_staking_parameters = Cycle.Pending_staking_parameters diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index 5c8a6bf0ca7c6520e23c6a2fdff762a02dc80cb6..3b0e679497c1c2998bd93f7935a2ffa6c61b9360 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -531,6 +531,13 @@ module Dal_already_denounced : (Raw_level_repr.t * Dal_slot_index_repr.t) * Signature.Public_key_hash.t and type value = unit +(** Set of delegates denounced in a cycle. It is used to not distribute rewards for such delegates. *) +module Dal_denounced_delegates : + Indexed_data_storage + with type t := Raw_context.t * Cycle_repr.t + and type key = Signature.Public_key_hash.t + and type value = unit + module Pending_staking_parameters : Indexed_data_storage with type t := Raw_context.t * Cycle_repr.t