diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 443669ba345b0d5d00eae5f91d5a1cf8d92243f0..89e46fd4cef219fd4b9676477fc9c48fe3f819c5 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2987,6 +2987,14 @@ module Dal_errors : sig | Dal_feature_disabled | Dal_slot_index_above_hard_limit | Dal_endorsement_unexpected_size of {expected : int; got : int} + | Dal_publish_slot_header_future_level of { + provided : Raw_level.t; + expected : Raw_level.t; + } + | Dal_publish_slot_header_past_level of { + provided : Raw_level.t; + expected : Raw_level.t; + } | Dal_publish_slot_header_invalid_index of { given : Dal.Slot_index.t; maximum : Dal.Slot_index.t; diff --git a/src/proto_alpha/lib_protocol/dal_apply.ml b/src/proto_alpha/lib_protocol/dal_apply.ml index 0bdd88d46e69cb07193ae61e7dd19512fe395764..b904b827b03f6c506016e82d6e7e42e7e958cbfc 100644 --- a/src/proto_alpha/lib_protocol/dal_apply.ml +++ b/src/proto_alpha/lib_protocol/dal_apply.ml @@ -81,18 +81,32 @@ let apply_data_availability ctxt op = | Some shards -> Ok (Dal.Endorsement.record_available_shards ctxt slot_availability shards) -let validate_publish_slot_header ctxt Dal.Slot.Header.{id = {index; _}; _} = +let validate_publish_slot_header ctxt + Dal.Slot.Header.{id = {index; published_level}; _} = assert_dal_feature_enabled ctxt >>? fun () -> let open Tzresult_syntax in let open Constants in let Parametric.{dal = {number_of_slots; _}; _} = parametric ctxt in let* number_of_slots = slot_of_int_e (number_of_slots - 1) in - error_unless - Compare.Int.( - Dal.Slot_index.compare index number_of_slots <= 0 - || Dal.Slot_index.compare index Dal.Slot_index.zero >= 0) - (Dal_publish_slot_header_invalid_index - {given = index; maximum = number_of_slots}) + let* () = + error_unless + Compare.Int.( + Dal.Slot_index.compare index number_of_slots <= 0 + && Dal.Slot_index.compare index Dal.Slot_index.zero >= 0) + (Dal_publish_slot_header_invalid_index + {given = index; maximum = number_of_slots}) + in + let current_level = (Level.current ctxt).level in + let* () = + error_when + Raw_level.(current_level < published_level) + (Dal_publish_slot_header_future_level + {provided = published_level; expected = current_level}) + in + error_when + Raw_level.(current_level > published_level) + (Dal_publish_slot_header_past_level + {provided = published_level; expected = current_level}) let apply_publish_slot_header ctxt slot_header = assert_dal_feature_enabled ctxt >>? fun () -> diff --git a/src/proto_alpha/lib_protocol/dal_errors_repr.ml b/src/proto_alpha/lib_protocol/dal_errors_repr.ml index 639a47a51b8205012a6ea46a30fb9b0c5b1d62e0..5d82b2aea0be6fdb29f2cd42435d78cb9c103640 100644 --- a/src/proto_alpha/lib_protocol/dal_errors_repr.ml +++ b/src/proto_alpha/lib_protocol/dal_errors_repr.ml @@ -27,6 +27,14 @@ type error += | Dal_feature_disabled | Dal_slot_index_above_hard_limit | Dal_endorsement_unexpected_size of {expected : int; got : int} + | Dal_publish_slot_header_future_level of { + provided : Raw_level_repr.t; + expected : Raw_level_repr.t; + } + | Dal_publish_slot_header_past_level of { + provided : Raw_level_repr.t; + expected : Raw_level_repr.t; + } | Dal_publish_slot_header_invalid_index of { given : Dal_slot_repr.Index.t; maximum : Dal_slot_repr.Index.t; @@ -95,6 +103,54 @@ let () = Data_encoding.unit (function Dal_slot_index_above_hard_limit -> Some () | _ -> None) (fun () -> Dal_slot_index_above_hard_limit) ; + let description = "Unexpected level in the future in slot header" in + register_error_kind + `Temporary + ~id:"dal_publish_slot_header_future_level" + ~title:"DAL slot header future level" + ~description + ~pp:(fun ppf (provided, expected) -> + Format.fprintf + ppf + "%s: Provided %a. Expected %a." + description + Raw_level_repr.pp + provided + Raw_level_repr.pp + expected) + (obj2 + (req "provided" Raw_level_repr.encoding) + (req "got" Raw_level_repr.encoding)) + (function + | Dal_publish_slot_header_future_level {provided; expected} -> + Some (provided, expected) + | _ -> None) + (fun (provided, expected) -> + Dal_publish_slot_header_future_level {provided; expected}) ; + let description = "Unexpected level in the past in slot header" in + register_error_kind + `Branch + ~id:"dal_publish_slot_header_past_level" + ~title:"DAL slot header past level" + ~description + ~pp:(fun ppf (provided, expected) -> + Format.fprintf + ppf + "%s: Provided %a. Expected %a." + description + Raw_level_repr.pp + provided + Raw_level_repr.pp + expected) + (obj2 + (req "provided" Raw_level_repr.encoding) + (req "got" Raw_level_repr.encoding)) + (function + | Dal_publish_slot_header_past_level {provided; expected} -> + Some (provided, expected) + | _ -> None) + (fun (provided, expected) -> + Dal_publish_slot_header_past_level {provided; expected}) ; let description = "Bad index for slot header" in register_error_kind `Permanent diff --git a/src/proto_alpha/lib_protocol/test/integration/validate/manager_operation_helpers.ml b/src/proto_alpha/lib_protocol/test/integration/validate/manager_operation_helpers.ml index 4bb617d0b1f5b4624f996d2ade99889e2c5e6595..12e32d4e7cddeb736c06dc63835d0cc4371882bf 100644 --- a/src/proto_alpha/lib_protocol/test/integration/validate/manager_operation_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/integration/validate/manager_operation_helpers.ml @@ -1121,7 +1121,10 @@ let mk_sc_rollup_return_bond (oinfos : operation_req) (infos : infos) = sc_rollup let mk_dal_publish_slot_header (oinfos : operation_req) (infos : infos) = - let published_level = Alpha_context.Raw_level.of_int32_exn Int32.zero in + let published_level = + Alpha_context.Raw_level.succ + @@ Alpha_context.Raw_level.of_int32_exn infos.ctxt.block.header.shell.level + in let index = Alpha_context.Dal.Slot_index.zero in let commitment = Alpha_context.Dal.Slot.Commitment.zero in let slot = diff --git a/tezt/tests/dal.ml b/tezt/tests/dal.ml index 7a73b1d89f6d96489608e80a4ec2020e556e3e45..95577366dbfaa1866b7ac735ca92653b73106494 100644 --- a/tezt/tests/dal.ml +++ b/tezt/tests/dal.ml @@ -280,14 +280,18 @@ let test_feature_flag _protocol _sc_rollup_node _sc_rollup_address node client = Test.fail "Unexpected entry dal in the context when DAL is disabled" ; unit -let publish_slot ~source ?fee ~index ~commitment node client = - let level = Node.get_level node in +let publish_slot ~source ?level ?fee ?error ~index ~commitment node client = + let level = + match level with Some level -> level | None -> 1 + Node.get_level node + in Operation.Manager.( inject + ?error [make ~source ?fee @@ dal_publish_slot_header ~index ~level ~commitment] client) -let publish_dummy_slot ~source ?fee ~index ~message parameters cryptobox = +let publish_dummy_slot ~source ?level ?error ?fee ~index ~message parameters + cryptobox = let commitment = Rollup.Dal.( Commitment.dummy_commitment @@ -295,10 +299,10 @@ let publish_dummy_slot ~source ?fee ~index ~message parameters cryptobox = cryptobox message) in - publish_slot ~source ?fee ~index ~commitment + publish_slot ~source ?level ?fee ?error ~index ~commitment let publish_slot_header ~source ?(fee = 1200) ~index ~commitment node client = - let level = Node.get_level node in + let level = 1 + Node.get_level node in let commitment = Tezos_crypto_dal.Cryptobox.Commitment.of_b58check_opt commitment in @@ -398,6 +402,38 @@ let test_slot_management_logic = @@ fun protocol -> setup ~dal_enable:true ~protocol @@ fun parameters cryptobox node client _bootstrap -> + let* (`OpHash _) = + let error = + rex ~opts:[`Dotall] "Unexpected level in the future in slot header" + in + publish_dummy_slot + ~source:Constant.bootstrap5 + ~fee:3_000 + ~level:3 + ~index:2 + ~message:"a" + ~error + parameters + cryptobox + node + client + in + let* (`OpHash _) = + let error = + rex ~opts:[`Dotall] "Unexpected level in the past in slot header" + in + publish_dummy_slot + ~source:Constant.bootstrap5 + ~fee:3_000 + ~level:1 + ~index:2 + ~message:"a" + ~error + parameters + cryptobox + node + client + in let* (`OpHash oph1) = publish_dummy_slot ~source:Constant.bootstrap1 diff --git a/tezt/tests/expected/dal.ml/Alpha- Testing rollup and Data availability layer node (rollup_node_applies_dal_.out b/tezt/tests/expected/dal.ml/Alpha- Testing rollup and Data availability layer node (rollup_node_applies_dal_.out index 2a92c0d4892eb5981c0c559a76a3e2160e33cb40..860905bc82b59376bcc303fdca90b3c0eca7a2f4 100644 --- a/tezt/tests/expected/dal.ml/Alpha- Testing rollup and Data availability layer node (rollup_node_applies_dal_.out +++ b/tezt/tests/expected/dal.ml/Alpha- Testing rollup and Data availability layer node (rollup_node_applies_dal_.out @@ -38,13 +38,13 @@ This sequence of operations was run: "commitment_hash": "[SC_ROLLUP_COMMITMENT_HASH]" } ./octez-sc-rollup-client-alpha rpc get /global/block/head/dal/slot_headers -[ { "level": 2, "index": 0, +[ { "level": 3, "index": 0, "commitment": "sh23Xtg7DY2qvSKgM1TiQDLH4cGZ2tHQwiQ5usHYdBUMzkirZUEVkSKoBDvjQePseeKFnQDGc9" }, - { "level": 2, "index": 1, + { "level": 3, "index": 1, "commitment": "[DAL_SLOT_HEADER]" }, - { "level": 2, "index": 2, + { "level": 3, "index": 2, "commitment": "sh237VRQLZqf8Uno4hjiiJh8RJxuwhPF4xWnPq2VKuC2ZbwVp3w9nw36iGfLHzpQrbopWx8GFq" } ] diff --git a/tezt/tests/expected/dal.ml/Alpha- Testing rollup and Data availability layer node (rollup_node_downloads_sl.out b/tezt/tests/expected/dal.ml/Alpha- Testing rollup and Data availability layer node (rollup_node_downloads_sl.out index 971b5b72bea57e3575be74970baa024af2c67881..7394b44895e797670ce8deaa7f7bd71c715e01b0 100644 --- a/tezt/tests/expected/dal.ml/Alpha- Testing rollup and Data availability layer node (rollup_node_downloads_sl.out +++ b/tezt/tests/expected/dal.ml/Alpha- Testing rollup and Data availability layer node (rollup_node_downloads_sl.out @@ -38,13 +38,13 @@ This sequence of operations was run: "commitment_hash": "[SC_ROLLUP_COMMITMENT_HASH]" } ./octez-sc-rollup-client-alpha rpc get /global/block/head/dal/slot_headers -[ { "level": 2, "index": 0, +[ { "level": 3, "index": 0, "commitment": "sh23Xtg7DY2qvSKgM1TiQDLH4cGZ2tHQwiQ5usHYdBUMzkirZUEVkSKoBDvjQePseeKFnQDGc9" }, - { "level": 2, "index": 1, + { "level": 3, "index": 1, "commitment": "[DAL_SLOT_HEADER]" }, - { "level": 2, "index": 2, + { "level": 3, "index": 2, "commitment": "sh237VRQLZqf8Uno4hjiiJh8RJxuwhPF4xWnPq2VKuC2ZbwVp3w9nw36iGfLHzpQrbopWx8GFq" } ]