From d8f1ffff060ec5a2c9d82e1b690775d3c9d00318 Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Tue, 3 Dec 2024 11:15:22 +0100 Subject: [PATCH 1/3] Alpha/DAL: add storage for already denounced entrapments --- src/proto_alpha/lib_protocol/TEZOS_PROTOCOL | 1 + src/proto_alpha/lib_protocol/alpha_context.ml | 1 + .../lib_protocol/alpha_context.mli | 8 +++ .../dal_already_denounced_storage.ml | 34 +++++++++++ .../dal_already_denounced_storage.mli | 58 +++++++++++++++++++ .../lib_protocol/dal_slot_index_repr.ml | 28 ++++++++- .../lib_protocol/dal_slot_index_repr.mli | 2 + src/proto_alpha/lib_protocol/dune | 4 ++ src/proto_alpha/lib_protocol/storage.ml | 19 ++++++ src/proto_alpha/lib_protocol/storage.mli | 10 +++- 10 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 src/proto_alpha/lib_protocol/dal_already_denounced_storage.ml create mode 100644 src/proto_alpha/lib_protocol/dal_already_denounced_storage.mli diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index 33bc68f01d84..b304bdd315b7 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -181,6 +181,7 @@ "Delegate_rewards", "Delegate_missed_attestations_storage", "Already_denounced_storage", + "Dal_already_denounced_storage", "Forbidden_delegates_storage", "Slash_percentage", "Delegate_slashed_deposits_storage", diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index eeca09443756..84ba964b8c80 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -168,6 +168,7 @@ module Dal = struct module Slots_history = Dal_slot_repr.History module Slots_storage = Dal_slot_storage + module Delegate = Dal_already_denounced_storage end module Dal_errors = Dal_errors_repr diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 29b0403d65c8..2735811e1f37 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -3021,6 +3021,14 @@ module Dal : sig (Slots_history.Pointer_hash.t * Slots_history.t) list option tzresult Lwt.t end + + (* This would normally be a part of {!Delegate}, but it is not because + {!Dal.Slot_index} is defined after {!Delegate}. *) + module Delegate : 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 + end end (** This module re-exports definitions from {!Dal_errors_repr}. *) diff --git a/src/proto_alpha/lib_protocol/dal_already_denounced_storage.ml b/src/proto_alpha/lib_protocol/dal_already_denounced_storage.ml new file mode 100644 index 000000000000..bbfac05f8644 --- /dev/null +++ b/src/proto_alpha/lib_protocol/dal_already_denounced_storage.ml @@ -0,0 +1,34 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021-2024 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(*****************************************************************************) + +let is_already_denounced ctxt delegate (level : Level_repr.t) slot_index = + Storage.Dal_already_denounced.mem + (ctxt, level.cycle) + ((level.level, slot_index), delegate) + +let add_denunciation ctxt delegate (level : Level_repr.t) slot_index = + let open Lwt_syntax in + let* already_denounced = + is_already_denounced ctxt delegate level slot_index + in + let* ctxt = + if already_denounced then Lwt.return ctxt + else + Storage.Dal_already_denounced.add + (ctxt, level.cycle) + ((level.level, slot_index), delegate) + () + in + return (ctxt, already_denounced) + +let clear_outdated_cycle ctxt ~new_cycle = + match Cycle_repr.(sub new_cycle Constants_repr.max_slashing_period) with + | None -> Lwt.return ctxt + | Some outdated_cycle -> + Storage.Dal_already_denounced.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 new file mode 100644 index 000000000000..ee66e8e57285 --- /dev/null +++ b/src/proto_alpha/lib_protocol/dal_already_denounced_storage.mli @@ -0,0 +1,58 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021-2024 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(*****************************************************************************) + +(** This module is responsible for ensuring that a delegate doesn't get slashed + twice for the same DAL offense. To do so, it maintains the + {!Storage.Dal_already_denounced} table, which tracks which DAL (entrapment) + denunciations have already been seen in blocks. + + A denunciation is uniquely characterized by the delegate (the culprit), the + level and the slot index of the entrapment evidence. + + Invariant: {!Storage.Dal_already_denounced} is empty for cycles equal + to [current_cycle - max_slashing_period] or older. Indeed, such + denunciations are no longer allowed (see + [Anonymous.check_denunciation_age] in {!Validate}) so there is no + need to track them anymore. *) + +(** Returns true if the given delegate has already been denounced at the given + level and slot index. *) +val is_already_denounced : + Raw_context.t -> + Signature.Public_key_hash.t -> + Level_repr.t -> + Dal_slot_index_repr.t -> + bool Lwt.t + +(** Records a denunciation in {!Storage.Dal_already_denounced}. + + Returns a pair [(ctxt, already_denounced)], where + [already_denounced] is a boolean indicating whether the + denunciation was already recorded in the storage previously. + + When [already_denounced] is [true], the returned [ctxt] is + actually the unchanged context argument. + + Precondition: the given level should be more recent than + [current_cycle - max_slashing_period] in order to maintain the + invariant on the age of tracked denunciations. Fortunately, this + is already enforced in {!Validate} by + [Anonymous.check_denunciation_age]. *) +val add_denunciation : + Raw_context.t -> + Signature.public_key_hash -> + Level_repr.t -> + Dal_slot_index_repr.t -> + (Raw_context.t * bool) Lwt.t + +(** Clear {!Storage.Dal_already_denounced} for the cycle [new_cycle - + max_slashing_period]. Indeed, denunciations on events which + happened during this cycle are no longer allowed anyway. *) +val clear_outdated_cycle : + Raw_context.t -> new_cycle:Cycle_repr.t -> Raw_context.t Lwt.t diff --git a/src/proto_alpha/lib_protocol/dal_slot_index_repr.ml b/src/proto_alpha/lib_protocol/dal_slot_index_repr.ml index ce2abb9d0910..a036abd3f053 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_index_repr.ml +++ b/src/proto_alpha/lib_protocol/dal_slot_index_repr.ml @@ -1,7 +1,7 @@ (*****************************************************************************) (* *) (* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022-2024 Nomadic Labs *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -88,3 +88,29 @@ let slots_range_opt ~number_of_slots ~lower ~upper = Option.of_result @@ slots_range ~number_of_slots ~lower ~upper let is_succ t ~succ = Compare.Int.(t + 1 = succ) + +module Index = struct + type t = int + + let path_length = 1 + + let to_path slot_index l = string_of_int slot_index :: l + + let of_path = function [s] -> int_of_string_opt s | _ -> None + + let rpc_arg = + let construct slot_index = string_of_int slot_index in + let destruct str = + int_of_string_opt str |> Option.to_result ~none:"Cannot parse slot index" + in + RPC_arg.make + ~descr:"A slot index" + ~name:"dal_slot_index" + ~construct + ~destruct + () + + let encoding = encoding + + let compare = compare +end diff --git a/src/proto_alpha/lib_protocol/dal_slot_index_repr.mli b/src/proto_alpha/lib_protocol/dal_slot_index_repr.mli index 380825600d5a..cf0dab47b591 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_index_repr.mli +++ b/src/proto_alpha/lib_protocol/dal_slot_index_repr.mli @@ -71,3 +71,5 @@ val slots_range_opt : val is_succ : t -> succ:t -> bool include Compare.S with type t := t + +module Index : Storage_description.INDEX with type t = t diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index b04b6c00fb47..e1c9e1ae8d76 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -197,6 +197,7 @@ Delegate_rewards Delegate_missed_attestations_storage Already_denounced_storage + Dal_already_denounced_storage Forbidden_delegates_storage Slash_percentage Delegate_slashed_deposits_storage @@ -494,6 +495,7 @@ 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 forbidden_delegates_storage.ml forbidden_delegates_storage.mli slash_percentage.ml slash_percentage.mli delegate_slashed_deposits_storage.ml delegate_slashed_deposits_storage.mli @@ -792,6 +794,7 @@ 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 forbidden_delegates_storage.ml forbidden_delegates_storage.mli slash_percentage.ml slash_percentage.mli delegate_slashed_deposits_storage.ml delegate_slashed_deposits_storage.mli @@ -1074,6 +1077,7 @@ 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 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 6a759c5c41fe..d355cdc9a87c 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -1177,6 +1177,24 @@ module Cycle = struct (req "for_double_baking" bool)) end) + module Dal_already_denounced = + Make_indexed_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["dal_already_denounced"] + end)) + (Pair + (Pair + (Make_index + (Raw_level_repr.Index)) + (Make_index (Dal_slot_index_repr.Index))) + (Public_key_hash_index)) + (struct + type t = unit + + let encoding = Data_encoding.unit + end) + module Selected_stake_distribution = Indexed_context.Make_map (Registered) @@ -1318,6 +1336,7 @@ module Cycle = struct end module Already_denounced = Cycle.Already_denounced +module Dal_already_denounced = Cycle.Dal_already_denounced 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 948cb6112c57..ec6e76148d75 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -503,7 +503,7 @@ type denounced = { (** {!denounced} with all fields set to [false]. *) val default_denounced : denounced -(** Set used to avoid slashing multiple times the same event *) +(** Set used to avoid slashing multiple times for the same double-signing event *) module Already_denounced : Indexed_data_storage with type t := Raw_context.t * Cycle_repr.t @@ -511,6 +511,14 @@ module Already_denounced : (Raw_level_repr.t * Round_repr.t) * Signature.Public_key_hash.t and type value = denounced +(** Set used to avoid slashing multiple times for the same DAL entrapment event *) +module Dal_already_denounced : + Indexed_data_storage + with type t := Raw_context.t * Cycle_repr.t + and type key = + (Raw_level_repr.t * Dal_slot_index_repr.t) * 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 -- GitLab From 3d444ad697b94534d8c50a3ddc561b5f72dd0637 Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Tue, 29 Oct 2024 14:27:00 +0100 Subject: [PATCH 2/3] Alpha/DAL: validate dal_entrapment_evidence --- src/proto_alpha/lib_protocol/validate.ml | 173 +++++++++++++++++- .../lib_protocol/validate_errors.ml | 98 +++++++++- .../lib_protocol/validate_errors.mli | 7 + 3 files changed, 265 insertions(+), 13 deletions(-) diff --git a/src/proto_alpha/lib_protocol/validate.ml b/src/proto_alpha/lib_protocol/validate.ml index 81090a6a935e..a29c0bf44a58 100644 --- a/src/proto_alpha/lib_protocol/validate.ml +++ b/src/proto_alpha/lib_protocol/validate.ml @@ -1310,13 +1310,23 @@ module Anonymous = struct let* () = error_unless Cycle.(given_cycle <= current_cycle) - (Too_early_denunciation - {kind; level = given_level; current = vi.current_level.level}) + (match kind with + | `Consensus_denounciation kind -> + Too_early_denunciation + {kind; level = given_level; current = vi.current_level.level} + | `Dal_denounciation -> + Too_early_dal_denunciation + {level = given_level; current = vi.current_level.level}) in error_unless Cycle.(last_slashable_cycle >= current_cycle) - (Outdated_denunciation - {kind; level = given_level; last_cycle = last_slashable_cycle}) + (match kind with + | `Consensus_denounciation kind -> + Outdated_denunciation + {kind; level = given_level; last_cycle = last_slashable_cycle} + | `Dal_denounciation -> + Outdated_dal_denunciation + {level = given_level; last_cycle = last_slashable_cycle}) let check_double_attesting_evidence (type kind) vi (op1 : kind Kind.consensus Operation.t) @@ -1365,7 +1375,9 @@ module Anonymous = struct in (* Disambiguate: levels are equal *) let level = Level.from_raw vi.ctxt e1.level in - let*? () = check_denunciation_age vi kind level.level in + let*? () = + check_denunciation_age vi (`Consensus_denounciation kind) level.level + in let* ctxt, consensus_key1 = Stake_distribution.slot_owner vi.ctxt level e1.slot in @@ -1524,7 +1536,12 @@ module Anonymous = struct (Invalid_double_baking_evidence {hash1; level1; round1; hash2; level2; round2}) in - let*? () = check_denunciation_age vi Double_baking level1 in + let*? () = + check_denunciation_age + vi + (`Consensus_denounciation Misbehaviour.Double_baking) + level1 + in let level = Level.from_raw vi.ctxt level1 in let committee_size = Constants.consensus_committee_size vi.ctxt in let*? slot1 = Round.to_slot round1 ~committee_size in @@ -1627,9 +1644,149 @@ module Anonymous = struct in {vs with anonymous_state} + let check_shard_index_is_in_range ~number_of_shards shard_index = + error_unless + Compare.Int.(shard_index >= 0 && shard_index < number_of_shards) + (Invalid_shard_index + {given = shard_index; min = 0; max = number_of_shards - 1}) + + (* This function validates an entrapment evidence by doing the following checks: + - the included slot index and shard index are within bounds + - the included attestation contains a DAL attestation + - the slot was attested by the attester + - the level of the faulty attestation is within the slashing period + - the included shard is a trap + - the delegate has not already been denounced for the same level and slot index + - the delegate that signed the included attestation is assigned to the included shard + - the signature verification of the included attestation succeeds + *) + let check_dal_entrapment_evidence vi + (operation : Kind.dal_entrapment_evidence operation) = + let open Lwt_result_syntax in + let (Single + (Dal_entrapment_evidence {attestation; slot_index; shard_with_proof})) + = + operation.protocol_data.contents + in + let consensus_content, dal_content = + match attestation.protocol_data.contents with + | Single (Attestation {consensus_content; dal_content}) -> + (consensus_content, dal_content) + in + match dal_content with + | None -> + (* TODO: return error *) + failwith "Wrong evidence: the attester did not DAL attest" + | Some dal_content -> ( + let number_of_slots = Constants.dal_number_of_slots vi.ctxt in + let*? () = + Dal.Slot_index.check_is_in_range ~number_of_slots slot_index + in + let number_of_shards = Constants.dal_number_of_shards vi.ctxt in + let shard_index = shard_with_proof.shard.index in + let*? () = + check_shard_index_is_in_range ~number_of_shards shard_index + in + assert ( + (* TODO: check and return error *) + Dal.Attestation.is_attested + dal_content.attestation + slot_index) ; + let level = Level.from_raw vi.ctxt consensus_content.level in + let*? () = check_denunciation_age vi `Dal_denounciation level.level in + let* ctxt, consensus_key = + Stake_distribution.slot_owner vi.ctxt level consensus_content.slot + in + let delegate = consensus_key.delegate in + let*! already_denounced = + Dal.Delegate.is_already_denounced ctxt delegate level slot_index + in + let*? () = + error_unless + (not already_denounced) + (Dal_already_denounced {delegate; level}) + in + let traps_fraction = (Constants.parametric ctxt).dal.traps_fraction in + let*? is_trap = + Dal.Shard_with_proof.share_is_trap + delegate + shard_with_proof.shard.share + ~traps_fraction + in + assert (* TODO: check and return error *) + is_trap ; + let* _ctxt, shard_owner = + let*? tb_slot = Slot.of_int shard_index in + Stake_distribution.slot_owner vi.ctxt level tb_slot + in + assert ( + (* TODO: check and return error *) + Signature.Public_key_hash.equal + delegate + shard_owner.delegate) ; + let attestation_lag = + (Constants.parametric vi.ctxt).dal.attestation_lag + in + let published_level = + match Raw_level.(sub (succ level.level) attestation_lag) with + | None -> + failwith + "SHOULD NOT HAPPEN ON MAINNET. It can in theory happen on test \ + networks (but it is very unlikely)" + | Some level -> level + in + let* slot_headers_opt = + Dal.Slot.find_slot_headers ctxt published_level + in + match slot_headers_opt with + | None -> + (* TODO: https://gitlab.com/tezos/tezos/-/issues/7126 + Can also fail if `attestation_lag` changes. *) + failwith (* TODO: return error *) + "SHOULD NOT HAPPEN IF 1) the denunciation age is correct, and 2) \ + the storage is updated correctly" + | Some headers -> ( + let slot_header_opt = + List.find + (fun (Dal.Slot.Header.{id; _}, _publisher) -> + Dal.Slot_index.equal id.index slot_index) + headers + in + match slot_header_opt with + | Some (header, _publisher) + when Raw_level.equal header.id.published_level published_level -> + let*? _ctxt, cryptobox = Dal.make ctxt in + let*? () = + Dal.Shard_with_proof.verify + cryptobox + header.commitment + shard_with_proof + in + let*? () = + Operation.check_signature + consensus_key.consensus_pk + vi.chain_id + attestation + in + return_unit + | Some _ -> + (* TODO: https://gitlab.com/tezos/tezos/-/issues/7126 + Can also fail if `attestation_lag` changes. *) + (* TODO: return error *) + failwith + "SHOULD NOT HAPPEN: mismatch between published levels in \ + storage versus in evidence" + | None -> + (* TODO: return error *) + failwith + "Wrong evidence: no slot was published at the mentioned \ + level and index")) + let check_dal_entrapment_evidence vi - (_operation : Kind.dal_entrapment_evidence operation) = - Dal.assert_incentives_enabled vi.ctxt |> Lwt.return + (operation : Kind.dal_entrapment_evidence operation) = + if (Constants.parametric vi.ctxt).dal.incentives_enable then + check_dal_entrapment_evidence vi operation + else tzfail Dal_errors.Dal_incentives_disabled let dal_entrapment_evidence_info (operation : Kind.dal_entrapment_evidence operation) = diff --git a/src/proto_alpha/lib_protocol/validate_errors.ml b/src/proto_alpha/lib_protocol/validate_errors.ml index 87299d7dadd7..419644be0e64 100644 --- a/src/proto_alpha/lib_protocol/validate_errors.ml +++ b/src/proto_alpha/lib_protocol/validate_errors.ml @@ -842,12 +842,12 @@ module Anonymous = struct `Temporary ~id:"validate.operation.block.too_early_denunciation" ~title:"Too early denunciation" - ~description:"A denunciation is too far in the future" + ~description:"A denunciation is for a future level" ~pp:(fun ppf (kind, level, current) -> Format.fprintf ppf - "A double-%a denunciation is too far in the future (current level: \ - %a, given level: %a)" + "A double-%a denunciation is for a future level (current level: %a, \ + given level: %a)" pp_denunciation_kind kind Raw_level.pp @@ -893,9 +893,97 @@ module Anonymous = struct (fun (kind, level, last_cycle) -> Outdated_denunciation {kind; level; last_cycle}) - type error += Conflicting_dal_entrapment of operation_conflict + type error += + | Too_early_dal_denunciation of {level : Raw_level.t; current : Raw_level.t} + | Outdated_dal_denunciation of {level : Raw_level.t; last_cycle : Cycle.t} + | Invalid_shard_index of {given : int; min : int; max : int} + | Dal_already_denounced of { + delegate : Signature.Public_key_hash.t; + level : Level.t; + } + | Conflicting_dal_entrapment of operation_conflict let () = + let open Data_encoding in + register_error_kind + `Temporary + ~id:"validate.operation.block.too_early_dal_denunciation" + ~title:"Too early DAL denunciation" + ~description:"A DAL denunciation is for a future level" + ~pp:(fun ppf (level, current) -> + Format.fprintf + ppf + "A DAL entrapment denunciation is for a future level (current level: \ + %a, given level: %a)" + Raw_level.pp + current + Raw_level.pp + level) + (obj2 (req "level" Raw_level.encoding) (req "current" Raw_level.encoding)) + (function + | Too_early_dal_denunciation {level; current} -> Some (level, current) + | _ -> None) + (fun (level, current) -> Too_early_dal_denunciation {level; current}) ; + register_error_kind + `Permanent + ~id:"validate.operation.block.outdated_dal_denunciation" + ~title:"Outdated DAL denunciation" + ~description:"A DAL denunciation is outdated." + ~pp:(fun ppf (level, last_cycle) -> + Format.fprintf + ppf + "A DAL entrapment denunciation is outdated (last acceptable cycle: \ + %a, given level: %a)." + Cycle.pp + last_cycle + Raw_level.pp + level) + (obj2 (req "level" Raw_level.encoding) (req "last" Cycle.encoding)) + (function + | Outdated_dal_denunciation {level; last_cycle} -> + Some (level, last_cycle) + | _ -> None) + (fun (level, last_cycle) -> Outdated_dal_denunciation {level; last_cycle}) ; + register_error_kind + `Permanent + ~id:"validate.operation.block.invalid_dal_shard_index" + ~title:"Invalid DAL shard index" + ~description: + "The given shard index is out of range of representable shard indices" + ~pp:(fun ppf (given, min, max) -> + Format.fprintf + ppf + "The given shard index %d is out of range of representable shard \ + indices [%d, %d]" + given + min + max) + (obj3 (req "given" int31) (req "min" int31) (req "max" int31)) + (function + | Invalid_shard_index {given; min; max} -> Some (given, min, max) + | _ -> None) + (fun (given, min, max) -> Invalid_shard_index {given; min; max}) ; + register_error_kind + `Branch + ~id:"validate.operation.already_dal_denounced" + ~title:"Already denounced for DAL entrapement" + ~description:"The same DAL denunciation has already been validated." + ~pp:(fun ppf (delegate, level) -> + Format.fprintf + ppf + "Delegate %a at level %a has already been denounced for a DAL \ + entrapment." + Signature.Public_key_hash.pp + delegate + Level.pp + level) + (obj2 + (req "delegate" Signature.Public_key_hash.encoding) + (req "level" Level.encoding)) + (function + | Dal_already_denounced {delegate; level} -> Some (delegate, level) + | _ -> None) + (fun (delegate, level) -> Dal_already_denounced {delegate; level}) ; register_error_kind `Branch ~id:"validate.operation.conflicting_dal_entrapment" @@ -911,7 +999,7 @@ module Anonymous = struct entrapment evidence %a" Operation_hash.pp existing) - Data_encoding.(obj1 (req "conflict" operation_conflict_encoding)) + (obj1 (req "conflict" operation_conflict_encoding)) (function | Conflicting_dal_entrapment conflict -> Some conflict | _ -> None) (fun conflict -> Conflicting_dal_entrapment conflict) diff --git a/src/proto_alpha/lib_protocol/validate_errors.mli b/src/proto_alpha/lib_protocol/validate_errors.mli index ac2d36e01ab3..bded453f4dd3 100644 --- a/src/proto_alpha/lib_protocol/validate_errors.mli +++ b/src/proto_alpha/lib_protocol/validate_errors.mli @@ -155,6 +155,13 @@ module Anonymous : sig level : Raw_level.t; last_cycle : Cycle.t; } + | Too_early_dal_denunciation of {level : Raw_level.t; current : Raw_level.t} + | Outdated_dal_denunciation of {level : Raw_level.t; last_cycle : Cycle.t} + | Invalid_shard_index of {given : int; min : int; max : int} + | Dal_already_denounced of { + delegate : Signature.Public_key_hash.t; + level : Level.t; + } | Conflicting_dal_entrapment of operation_conflict | Conflicting_nonce_revelation of operation_conflict | Conflicting_vdf_revelation of operation_conflict -- GitLab From 26faa39b8aa95cbff665a2fba315c8f1f85f608a Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Wed, 4 Dec 2024 20:14:48 +0100 Subject: [PATCH 3/3] CHANGE: update entry --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index d2981971abd6..3054c09dbc82 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -208,6 +208,9 @@ Protocol - A new antonymous operation "DAL entrapment evidence" was added. This operation is not valid when the feature flag for DAL incentives is turned off. (MR :gl:`!15677`) +- A new anonymous operation "DAL entrapment evidence" was added. This operation + is not valid when the feature flag for DAL incentives is turned off. (MRs + :gl:`!15677`, :gl:`!15832`, :gl:`!15836`) - Set the message validation function at node startup, fixing https://gitlab.com/tezos/tezos/-/issues/7629. (MR :gl:`!15830`) - A warning has been introduced in case it is observed that the DAL node lags -- GitLab