diff --git a/src/proto_alpha/lib_protocol/validate.ml b/src/proto_alpha/lib_protocol/validate.ml index bc0220e6e78e73419f43314b00d475945718bf72..d36bec58a7213fd39122db82aa282030fc928671 100644 --- a/src/proto_alpha/lib_protocol/validate.ml +++ b/src/proto_alpha/lib_protocol/validate.ml @@ -1675,8 +1675,13 @@ module Anonymous = struct in match dal_content with | None -> - (* TODO: return error *) - failwith "Wrong evidence: the attester did not DAL attest" + tzfail + (Invalid_accusation_no_dal_content + { + tb_slot = consensus_content.slot; + level = consensus_content.level; + slot_index; + }) | Some dal_content -> ( let number_of_slots = Constants.dal_number_of_slots vi.ctxt in let*? () = @@ -1687,12 +1692,13 @@ module Anonymous = struct 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 = consensus_content.level in + let*? () = + error_unless + (Dal.Attestation.is_attested dal_content.attestation slot_index) + (Invalid_accusation_slot_not_attested + {tb_slot = consensus_content.slot; level; slot_index}) + in let* protocol_first_level = First_level_of_protocol.get vi.ctxt in let*? () = (* Due to the DAL node possibly not checking for traps before the R @@ -1721,7 +1727,7 @@ module Anonymous = struct let*? () = error_unless (not already_denounced) - (Dal_already_denounced {delegate; level}) + (Dal_already_denounced {delegate; level = level.level}) in let traps_fraction = (Constants.parametric ctxt).dal.traps_fraction in let*? is_trap = @@ -1730,27 +1736,44 @@ module Anonymous = struct shard_with_proof.shard.share ~traps_fraction in - assert (* TODO: check and return error *) - is_trap ; + let*? () = + error_unless + is_trap + (Invalid_accusation_shard_is_not_trap + { + delegate; + level = level.level; + slot_index; + shard_index = shard_with_proof.shard.index; + }) + in 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*? () = + error_unless + (Signature.Public_key_hash.equal delegate shard_owner.delegate) + (Invalid_accusation_wrong_shard_owner + { + delegate; + level = level.level; + slot_index; + shard_index = shard_with_proof.shard.index; + shard_owner = shard_owner.delegate; + }) + in let attestation_lag = (Constants.parametric vi.ctxt).dal.attestation_lag in - let published_level = + 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 + (* The slot couldn't have been published in this case *) + tzfail + (Invalid_accusation_slot_not_published + {delegate; level = level.level; slot_index}) + | Some level -> return level in let* slot_headers_opt = Dal.Slot.find_slot_headers ctxt published_level @@ -1759,9 +1782,11 @@ module Anonymous = struct | 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" + (* It should not happen if 1) the denunciation age is correct, and 2) \ + the storage is updated correctly *) + tzfail + (Accusation_validity_error_cannot_get_slot_headers + {delegate; level = level.level; slot_index}) | Some headers -> ( let slot_header_opt = List.find @@ -1786,18 +1811,24 @@ module Anonymous = struct attestation in return_unit - | Some _ -> + | Some (header, _publisher) -> (* 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" + (* mismatch between published levels in \ + storage versus in evidence; it should not happen *) + tzfail + (Accusation_validity_error_levels_mismatch + { + delegate; + level = level.level; + slot_index; + accusation_published_level = published_level; + store_published_level = header.id.published_level; + }) | None -> - (* TODO: return error *) - failwith - "Wrong evidence: no slot was published at the mentioned \ - level and index")) + tzfail + (Invalid_accusation_slot_not_published + {delegate; level = level.level; slot_index}))) let check_dal_entrapment_evidence vi (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 dc59f2460e682cc982eb851c81c9926ea9bb954b..7b48f864b66eef1429ccc2f526d6a61e3e127069 100644 --- a/src/proto_alpha/lib_protocol/validate_errors.ml +++ b/src/proto_alpha/lib_protocol/validate_errors.ml @@ -899,12 +899,52 @@ module Anonymous = struct | Invalid_shard_index of {given : int; min : int; max : int} | Dal_already_denounced of { delegate : Signature.Public_key_hash.t; - level : Level.t; + level : Raw_level.t; } | Denunciations_not_allowed_just_after_migration of { level : Raw_level.t; first_allowed_level : Raw_level.t; } + | Invalid_accusation_no_dal_content of { + tb_slot : Slot.t; + level : Raw_level.t; + slot_index : Dal.Slot_index.t; + } + | Invalid_accusation_slot_not_attested of { + tb_slot : Slot.t; + level : Raw_level.t; + slot_index : Dal.Slot_index.t; + } + | Invalid_accusation_shard_is_not_trap of { + delegate : Signature.Public_key_hash.t; + level : Raw_level.t; + slot_index : Dal.Slot_index.t; + shard_index : int; + } + | Invalid_accusation_wrong_shard_owner of { + delegate : Signature.Public_key_hash.t; + level : Raw_level.t; + slot_index : Dal.Slot_index.t; + shard_index : int; + shard_owner : Signature.Public_key_hash.t; + } + | Invalid_accusation_slot_not_published of { + delegate : Signature.Public_key_hash.t; + level : Raw_level.t; + slot_index : Dal.Slot_index.t; + } + | Accusation_validity_error_cannot_get_slot_headers of { + delegate : Signature.Public_key_hash.t; + level : Raw_level.t; + slot_index : Dal.Slot_index.t; + } + | Accusation_validity_error_levels_mismatch of { + delegate : Signature.Public_key_hash.t; + level : Raw_level.t; + slot_index : Dal.Slot_index.t; + accusation_published_level : Raw_level.t; + store_published_level : Raw_level.t; + } | Conflicting_dal_entrapment of operation_conflict let () = @@ -979,11 +1019,11 @@ module Anonymous = struct entrapment." Signature.Public_key_hash.pp delegate - Level.pp + Raw_level.pp level) (obj2 (req "delegate" Signature.Public_key_hash.encoding) - (req "level" Level.encoding)) + (req "level" Raw_level.encoding)) (function | Dal_already_denounced {delegate; level} -> Some (delegate, level) | _ -> None) @@ -1016,6 +1056,247 @@ module Anonymous = struct Denunciations_not_allowed_just_after_migration {level; first_allowed_level}) ; + register_error_kind + `Permanent + ~id:"validate.operation.invalid_accusation_no_dal_content" + ~title:"Invalid accusation: no DAL content" + ~description: + "Invalid accusation: the attestation operation has no DAL content." + ~pp:(fun ppf (tb_slot, level, slot_index) -> + Format.fprintf + ppf + "Invalid accusation for validator slot %a, level %a, and DAL slot \ + index %a: the attestation operation has no DAL content." + Slot.pp + tb_slot + Raw_level.pp + level + Dal.Slot_index.pp + slot_index) + (obj3 + (req "TB_slot" Slot.encoding) + (req "level" Raw_level.encoding) + (req "slot_index" Dal.Slot_index.encoding)) + (function + | Invalid_accusation_no_dal_content {tb_slot; level; slot_index} -> + Some (tb_slot, level, slot_index) + | _ -> None) + (fun (tb_slot, level, slot_index) -> + Invalid_accusation_no_dal_content {tb_slot; level; slot_index}) ; + register_error_kind + `Permanent + ~id:"validate.operation.invalid_accusation_slot_not_attested" + ~title:"Invalid accusation: the delegate did not attest the DAL slot" + ~description: + "Invalid accusation: the delegate did not attest the DAL slot." + ~pp:(fun ppf (tb_slot, level, slot_index) -> + Format.fprintf + ppf + "Invalid accusation for validator slot %a, level %a, and DAL slot \ + index %a: the delegate did not attest the DAL slot." + Slot.pp + tb_slot + Raw_level.pp + level + Dal.Slot_index.pp + slot_index) + (obj3 + (req "TB_slot" Slot.encoding) + (req "level" Raw_level.encoding) + (req "slot_index" Dal.Slot_index.encoding)) + (function + | Invalid_accusation_slot_not_attested {tb_slot; level; slot_index} -> + Some (tb_slot, level, slot_index) + | _ -> None) + (fun (tb_slot, level, slot_index) -> + Invalid_accusation_slot_not_attested {tb_slot; level; slot_index}) ; + register_error_kind + `Permanent + ~id:"validate.operation.invalid_accusation_shard_is_not_trap" + ~title:"Invalid accusation: the provided shard is not a trap" + ~description:"Invalid accusation: the provided shard is not a trap." + ~pp:(fun ppf (delegate, level, slot_index, shard_index) -> + Format.fprintf + ppf + "Invalid accusation for delegate %a, level %a, DAL slot index %a, \ + and shard index %d: the provided shard is not a trap." + Signature.Public_key_hash.pp + delegate + Raw_level.pp + level + Dal.Slot_index.pp + slot_index + shard_index) + (obj4 + (req "delegate" Signature.Public_key_hash.encoding) + (req "level" Raw_level.encoding) + (req "slot_index" Dal.Slot_index.encoding) + (req "shard_index" int31)) + (function + | Invalid_accusation_shard_is_not_trap + {delegate; level; slot_index; shard_index} -> + Some (delegate, level, slot_index, shard_index) + | _ -> None) + (fun (delegate, level, slot_index, shard_index) -> + Invalid_accusation_shard_is_not_trap + {delegate; level; slot_index; shard_index}) ; + register_error_kind + `Permanent + ~id:"validate.operation.invalid_accusation_wrong_shard_owner" + ~title: + "Invalid accusation: the provided shard is not assigned to the attester" + ~description: + "Invalid accusation: the provided shard is not assigned to the \ + attester." + ~pp:(fun ppf (delegate, level, slot_index, shard_index, shard_owner) -> + Format.fprintf + ppf + "Invalid accusation for delegate %a, level %a, DAL slot index %a, \ + and shard index %d: the shard is assigned to %a, not the attester." + Signature.Public_key_hash.pp + delegate + Raw_level.pp + level + Dal.Slot_index.pp + slot_index + shard_index + Signature.Public_key_hash.pp + shard_owner) + (obj5 + (req "delegate" Signature.Public_key_hash.encoding) + (req "level" Raw_level.encoding) + (req "slot_index" Dal.Slot_index.encoding) + (req "shard_index" Data_encoding.int31) + (req "shard_owner" Signature.Public_key_hash.encoding)) + (function + | Invalid_accusation_wrong_shard_owner + {delegate; level; slot_index; shard_index; shard_owner} -> + Some (delegate, level, slot_index, shard_index, shard_owner) + | _ -> None) + (fun (delegate, level, slot_index, shard_index, shard_owner) -> + Invalid_accusation_wrong_shard_owner + {delegate; level; slot_index; shard_index; shard_owner}) ; + register_error_kind + `Permanent + ~id:"validate.operation.invalid_accusation_slot_not_published" + ~title:"Invalid accusation: DAL slot not published" + ~description:"Invalid accusation: the DAL slot was not published." + ~pp:(fun ppf (delegate, level, slot_index) -> + Format.fprintf + ppf + "Invalid accusation for delegate %a, level %a, and DAL slot index \ + %a: the DAL slot was not published." + Signature.Public_key_hash.pp + delegate + Raw_level.pp + level + Dal.Slot_index.pp + slot_index) + (obj3 + (req "delegate" Signature.Public_key_hash.encoding) + (req "level" Raw_level.encoding) + (req "slot_index" Dal.Slot_index.encoding)) + (function + | Invalid_accusation_slot_not_published {delegate; level; slot_index} -> + Some (delegate, level, slot_index) + | _ -> None) + (fun (delegate, level, slot_index) -> + Invalid_accusation_slot_not_published {delegate; level; slot_index}) ; + register_error_kind + `Permanent + ~id:"validate.operation.accusation_validity_error_cannot_get_slot_headers" + ~title:"Accusation validity error: cannot get slot headers" + ~description: + "Accusation validity internal error: unable to retrieve the required \ + DAL slot headers." + ~pp:(fun ppf (delegate, level, slot_index) -> + Format.fprintf + ppf + "Accusation validity internal error for delegate %a, level %a, and \ + DAL slot index %a: unable to retrieve the required slot headers." + Signature.Public_key_hash.pp + delegate + Raw_level.pp + level + Dal.Slot_index.pp + slot_index) + (obj3 + (req "delegate" Signature.Public_key_hash.encoding) + (req "level" Raw_level.encoding) + (req "slot_index" Dal.Slot_index.encoding)) + (function + | Accusation_validity_error_cannot_get_slot_headers + {delegate; level; slot_index} -> + Some (delegate, level, slot_index) + | _ -> None) + (fun (delegate, level, slot_index) -> + Accusation_validity_error_cannot_get_slot_headers + {delegate; level; slot_index}) ; + register_error_kind + `Permanent + ~id:"validate.operation.accusation_validity_error_levels_mismatch" + ~title:"Accusation validity internal error: levels mismatch" + ~description: + "Accusation validity internal error: mismatch between published levels \ + in storage and evidence." + ~pp:(fun + ppf + ( delegate, + level, + slot_index, + accusation_published_level, + store_published_level ) + -> + Format.fprintf + ppf + "Accusation validity error for delegate %a, level %a, and DAL slot \ + index %a: mismatch between published levels in evidence (%a) and \ + storage (%a)." + Signature.Public_key_hash.pp + delegate + Raw_level.pp + level + Dal.Slot_index.pp + slot_index + Raw_level.pp + accusation_published_level + Raw_level.pp + store_published_level) + (obj5 + (req "delegate" Signature.Public_key_hash.encoding) + (req "level" Raw_level.encoding) + (req "slot_index" Dal.Slot_index.encoding) + (req "accusation_published_level" Raw_level.encoding) + (req "store_published_level" Raw_level.encoding)) + (function + | Accusation_validity_error_levels_mismatch + { + delegate; + level; + slot_index; + accusation_published_level; + store_published_level; + } -> + Some + ( delegate, + level, + slot_index, + accusation_published_level, + store_published_level ) + | _ -> None) + (fun ( delegate, + level, + slot_index, + accusation_published_level, + store_published_level ) -> + Accusation_validity_error_levels_mismatch + { + delegate; + level; + slot_index; + accusation_published_level; + store_published_level; + }) ; register_error_kind `Branch ~id:"validate.operation.conflicting_dal_entrapment" diff --git a/src/proto_alpha/lib_protocol/validate_errors.mli b/src/proto_alpha/lib_protocol/validate_errors.mli index 7ec53da75fe9fb3cf3839641ef0bed049e402fa9..1dbeb5fd03e466cadaca9aafcc6c22a7fcd06614 100644 --- a/src/proto_alpha/lib_protocol/validate_errors.mli +++ b/src/proto_alpha/lib_protocol/validate_errors.mli @@ -160,12 +160,52 @@ module Anonymous : sig | Invalid_shard_index of {given : int; min : int; max : int} | Dal_already_denounced of { delegate : Signature.Public_key_hash.t; - level : Level.t; + level : Raw_level.t; } | Denunciations_not_allowed_just_after_migration of { level : Raw_level.t; first_allowed_level : Raw_level.t; } + | Invalid_accusation_no_dal_content of { + tb_slot : Slot.t; + level : Raw_level.t; + slot_index : Dal.Slot_index.t; + } + | Invalid_accusation_slot_not_attested of { + tb_slot : Slot.t; + level : Raw_level.t; + slot_index : Dal.Slot_index.t; + } + | Invalid_accusation_shard_is_not_trap of { + delegate : Signature.Public_key_hash.t; + level : Raw_level.t; + slot_index : Dal.Slot_index.t; + shard_index : int; + } + | Invalid_accusation_wrong_shard_owner of { + delegate : Signature.Public_key_hash.t; + level : Raw_level.t; + slot_index : Dal.Slot_index.t; + shard_index : int; + shard_owner : Signature.Public_key_hash.t; + } + | Invalid_accusation_slot_not_published of { + delegate : Signature.Public_key_hash.t; + level : Raw_level.t; + slot_index : Dal.Slot_index.t; + } + | Accusation_validity_error_cannot_get_slot_headers of { + delegate : Signature.Public_key_hash.t; + level : Raw_level.t; + slot_index : Dal.Slot_index.t; + } + | Accusation_validity_error_levels_mismatch of { + delegate : Signature.Public_key_hash.t; + level : Raw_level.t; + slot_index : Dal.Slot_index.t; + accusation_published_level : Raw_level.t; + store_published_level : Raw_level.t; + } | Conflicting_dal_entrapment of operation_conflict | Conflicting_nonce_revelation of operation_conflict | Conflicting_vdf_revelation of operation_conflict