diff --git a/src/bin_testnet_scenarios/dal.ml b/src/bin_testnet_scenarios/dal.ml index 29c099ae03e622b5c167c1e1b956d4ed806c649e..c4394889f2122e60db1f0019a86f9843bb279119 100644 --- a/src/bin_testnet_scenarios/dal.ml +++ b/src/bin_testnet_scenarios/dal.ml @@ -162,7 +162,7 @@ let check_attestations node dal_node ~lag ~number_of_slots ~published_level = else x in let num_attested, indexes = - match Map.find_opt Dal_RPC.Attested map with + match Map.find_opt (Dal_RPC.Attested lag) map with | None -> (0, []) | Some (c, l) -> (c, l) in diff --git a/src/lib_dal_node/RPC_server.ml b/src/lib_dal_node/RPC_server.ml index e4e9e0f8300eeb60397951f828d1e7af42a017c3..cb6163d0d13fc4d99851a56aa4c268a3534026c6 100644 --- a/src/lib_dal_node/RPC_server.ml +++ b/src/lib_dal_node/RPC_server.ml @@ -337,7 +337,8 @@ module Profile_handlers = struct match res with | `Waiting_attestation -> Lwt.return_some (`Not_ok (slot_index, num_stored)) - | status -> + | `Unpublished -> Lwt.return_none + | (`Attested _ | `Unattested) as status -> (* Most probably the RPC was called/handled too late. This may mean that that DAL node is lagging. *) let* () = diff --git a/src/lib_dal_node/dal_plugin.ml b/src/lib_dal_node/dal_plugin.ml index d379adfaa9e138c5cd5df8e2641370f97c152806..c124d70f140247fab664e321902bc0bc703d4f48 100644 --- a/src/lib_dal_node/dal_plugin.ml +++ b/src/lib_dal_node/dal_plugin.ml @@ -132,7 +132,7 @@ module type T = sig val slot_header_of_cell : cell -> slot_header option val proto_attestation_status : - cell -> [`Attested | `Unattested | `Unpublished] option + cell -> [`Attested of attestation_lag | `Unattested | `Unpublished] option end module RPC : sig diff --git a/src/lib_dal_node/dal_plugin.mli b/src/lib_dal_node/dal_plugin.mli index d09a92f3b7a9f0f316b2c44ca7a7010796fb972c..8b0dc0d9799ab9c01920234a7a67d6dc745e327f 100644 --- a/src/lib_dal_node/dal_plugin.mli +++ b/src/lib_dal_node/dal_plugin.mli @@ -191,7 +191,7 @@ module type T = sig The function returns [None] for older protocols that do not expose the necessary information to access the status. *) val proto_attestation_status : - cell -> [`Attested | `Unattested | `Unpublished] option + cell -> [`Attested of attestation_lag | `Unattested | `Unpublished] option end module RPC : sig diff --git a/src/lib_dal_node/store.ml b/src/lib_dal_node/store.ml index 9f291013fa61eb66c571e54fbb69c6641ae1c392..4003617a8d1f4ad90136bf2d7b5c77ce93bcb450 100644 --- a/src/lib_dal_node/store.ml +++ b/src/lib_dal_node/store.ml @@ -671,14 +671,14 @@ module Statuses_cache = struct let get_slot_status = Slot_map.find_opt - let update_slot_headers_attestation ~published_level ~number_of_slots t - attested = + let update_slot_headers_attestation ~published_level ~number_of_slots + ~attestation_lag t attested = List.iter (fun slot_index -> let index = Types.Slot_id.{slot_level = published_level; slot_index} in if attested slot_index then ( Dal_metrics.slot_attested ~set:true slot_index ; - add_status t `Attested index) + add_status t (`Attested attestation_lag) index) else let old_data_opt = get_slot_status t index in Dal_metrics.slot_attested ~set:false slot_index ; @@ -693,7 +693,12 @@ module Statuses_cache = struct let update_selected_slot_headers_statuses ~block_level ~attestation_lag ~number_of_slots attested t = let published_level = Int32.(sub block_level (of_int attestation_lag)) in - update_slot_headers_attestation ~published_level ~number_of_slots t attested + update_slot_headers_attestation + ~published_level + ~number_of_slots + ~attestation_lag + t + attested end module Commitment_indexed_cache = diff --git a/src/lib_dal_node_services/types.ml b/src/lib_dal_node_services/types.ml index 7a7b00e5e41dad13695ab24fdfeb766dfb8e52ab..4c545d0a7929c525330b27f4118e10ded1852bd8 100644 --- a/src/lib_dal_node_services/types.ml +++ b/src/lib_dal_node_services/types.ml @@ -348,7 +348,10 @@ type slot_set = {slots : bool list; published_level : int32} type attestable_slots = Attestable_slots of slot_set | Not_in_committee type header_status = - [`Waiting_attestation | `Attested | `Unattested | `Unpublished] + [ `Waiting_attestation + | `Attested of attestation_lag + | `Unattested + | `Unpublished ] type shard_index = int @@ -424,9 +427,8 @@ let attestable_slots_encoding : attestable_slots Data_encoding.t = (function () -> Not_in_committee); ] -(* Note: this encoding is used to store statuses on disk using the - [Key_value_store] module. As such, it's important that this is a - fixed-size encoding. *) +let legacy_attestation_lag = 8 + let header_status_encoding : header_status Data_encoding.t = let open Data_encoding in union @@ -441,8 +443,8 @@ let header_status_encoding : header_status Data_encoding.t = ~title:"attested" (Tag 1) (constant "attested") - (function `Attested -> Some () | _ -> None) - (function () -> `Attested); + (function _ -> None (* Don't encode with this case anymore *)) + (function () -> `Attested legacy_attestation_lag); case ~title:"unattested" (Tag 2) @@ -455,11 +457,18 @@ let header_status_encoding : header_status Data_encoding.t = (constant "unpublished") (function `Unpublished -> Some () | _ -> None) (function () -> `Unpublished); + case + ~title:"attested_with_lag" + (Tag 4) + (obj2 (req "kind" (constant "attested")) (req "attestation_lag" uint8)) + (function + | `Attested attestation_lag -> Some ((), attestation_lag) | _ -> None) + (function (), attestation_lag -> `Attested attestation_lag); ] let pp_header_status fmt = function | `Waiting_attestation -> Format.fprintf fmt "waiting_attestation" - | `Attested -> Format.fprintf fmt "attested" + | `Attested lag -> Format.fprintf fmt "attested(lag:%d)" lag | `Unattested -> Format.fprintf fmt "unattested" | `Unpublished -> Format.fprintf fmt "unpublished" diff --git a/src/lib_dal_node_services/types.mli b/src/lib_dal_node_services/types.mli index cf89aec1294f52f6f5c78b09f6d8f5accd8d1a16..4262575836a3b60edaab0f6edb11b4a877592fbb 100644 --- a/src/lib_dal_node_services/types.mli +++ b/src/lib_dal_node_services/types.mli @@ -239,7 +239,8 @@ type header_status = [ `Waiting_attestation (** The slot header was included and applied in a finalized L1 block but remains to be attested. *) - | `Attested (** The slot header was included in an L1 block and attested. *) + | `Attested of attestation_lag + (** The slot header was included in an L1 block and attested. *) | `Unattested (** The slot header was included in an L1 block but not timely attested. *) | `Unpublished (** The slot header was not included in any L1 block. *) ] diff --git a/src/proto_022_PsRiotum/lib_dal/dal_plugin_registration.ml b/src/proto_022_PsRiotum/lib_dal/dal_plugin_registration.ml index 76fa0002ee46eced87798d12bce1af66b4e60712..d8591e76193eff0cfb6e5e89cc957c4e89d342f5 100644 --- a/src/proto_022_PsRiotum/lib_dal/dal_plugin_registration.ml +++ b/src/proto_022_PsRiotum/lib_dal/dal_plugin_registration.ml @@ -351,13 +351,16 @@ module Plugin = struct commitment; } - let proto_attestation_status cell = - Option.some - @@ - match Dal.Slots_history.(content cell) with - | Dal.Slots_history.Unpublished _ -> `Unpublished - | Published {is_proto_attested; _} -> - if is_proto_attested then `Attested else `Unattested + let proto_attestation_status = + let legacy_attestation_lag = 8 in + fun cell -> + Option.some + @@ + match Dal.Slots_history.(content cell) with + | Dal.Slots_history.Unpublished _ -> `Unpublished + | Published {is_proto_attested; _} -> + if is_proto_attested then `Attested legacy_attestation_lag + else `Unattested end module RPC = struct diff --git a/src/proto_023_PtSeouLo/lib_dal/dal_plugin_registration.ml b/src/proto_023_PtSeouLo/lib_dal/dal_plugin_registration.ml index e8c651481ed79df6540af8e3fb1896b92f975be6..08de5ea63589c5a3568eba2a604b16da7e99205e 100644 --- a/src/proto_023_PtSeouLo/lib_dal/dal_plugin_registration.ml +++ b/src/proto_023_PtSeouLo/lib_dal/dal_plugin_registration.ml @@ -373,13 +373,16 @@ module Plugin = struct commitment; } - let proto_attestation_status cell = - Option.some - @@ - match Dal.Slots_history.(content cell) with - | Dal.Slots_history.Unpublished _ -> `Unpublished - | Published {is_proto_attested; _} -> - if is_proto_attested then `Attested else `Unattested + let proto_attestation_status = + let legacy_attestation_lag = 8 in + fun cell -> + Option.some + @@ + match Dal.Slots_history.(content cell) with + | Dal.Slots_history.Unpublished _ -> `Unpublished + | Published {is_proto_attested; _} -> + if is_proto_attested then `Attested legacy_attestation_lag + else `Unattested end module RPC = struct diff --git a/src/proto_024_PsD5wVTJ/lib_dal/dal_plugin_registration.ml b/src/proto_024_PsD5wVTJ/lib_dal/dal_plugin_registration.ml index 6c18cd0a4fa48d626c7fb6f36b27221dce50cd84..9105382db0131ff0e2e3c2cbd7beba91fdec8c85 100644 --- a/src/proto_024_PsD5wVTJ/lib_dal/dal_plugin_registration.ml +++ b/src/proto_024_PsD5wVTJ/lib_dal/dal_plugin_registration.ml @@ -373,13 +373,16 @@ module Plugin = struct commitment; } - let proto_attestation_status cell = - Option.some - @@ - match Dal.Slots_history.(content cell) with - | Dal.Slots_history.Unpublished _ -> `Unpublished - | Published {is_proto_attested; _} -> - if is_proto_attested then `Attested else `Unattested + let proto_attestation_status = + let legacy_attestation_lag = 8 in + fun cell -> + Option.some + @@ + match Dal.Slots_history.(content cell) with + | Dal.Slots_history.Unpublished _ -> `Unpublished + | Published {is_proto_attested; _} -> + if is_proto_attested then `Attested legacy_attestation_lag + else `Unattested end module RPC = struct diff --git a/src/proto_alpha/lib_dal/dal_plugin_registration.ml b/src/proto_alpha/lib_dal/dal_plugin_registration.ml index daee90d9f3888488cdcdf516d0cceff4a8d632ec..9faa6b7e336d0062314dfc5718d645ff9d49018a 100644 --- a/src/proto_alpha/lib_dal/dal_plugin_registration.ml +++ b/src/proto_alpha/lib_dal/dal_plugin_registration.ml @@ -427,8 +427,9 @@ module Plugin = struct @@ match Dal.Slots_history.(content cell) with | Dal.Slots_history.Unpublished _ -> `Unpublished - | Published {is_proto_attested; _} -> - if is_proto_attested then `Attested else `Unattested + | Published {is_proto_attested; attestation_lag; _} -> + let lag = Dal.Slots_history.attestation_lag_value attestation_lag in + if is_proto_attested then `Attested lag else `Unattested end module RPC = struct diff --git a/tezt/lib_tezos/dal_common.ml b/tezt/lib_tezos/dal_common.ml index 2b4dc41aacba591ea92439b4cc8d3df1353f37e6..766468c2255ff29fe745ad3284884e70bcda102b 100644 --- a/tezt/lib_tezos/dal_common.ml +++ b/tezt/lib_tezos/dal_common.ml @@ -196,7 +196,7 @@ module Dal_RPC = struct type slot_id_status = | Waiting_attestation - | Attested + | Attested of int (* of attestation lag *) | Unattested | Unpublished @@ -209,17 +209,28 @@ module Dal_RPC = struct let pp_slot_id_status fmt = function | Waiting_attestation -> Format.fprintf fmt "Waiting_attestation" - | Attested -> Format.fprintf fmt "Attested" + | Attested lag -> Format.fprintf fmt "Attested(lag:%d)" lag | Unattested -> Format.fprintf fmt "Unattested" | Unpublished -> Format.fprintf fmt "Unpublished" - let slot_id_status_of_json json = - match String.lowercase_ascii @@ JSON.as_string json with - | "waiting_attestation" -> Waiting_attestation - | "attested" -> Attested - | "unattested" -> Unattested - | "unpublished" -> Unattested - | s -> failwith @@ Format.sprintf "Unknown slot_id status %s" s + let slot_id_status_of_json = + let legacy_attestation_lag = 8 in + fun json -> + match String.lowercase_ascii @@ JSON.as_string json with + | "waiting_attestation" -> Waiting_attestation + | "attested" -> Attested legacy_attestation_lag + | "unattested" -> Unattested + | "unpublished" -> Unattested + | exception _exn -> ( + match + JSON. + ( json |-> "kind" |> as_string, + json |-> "attestation_lag" |> as_int ) + with + | "attested", lag -> Attested lag + | (exception _) | _ -> + failwith @@ Format.sprintf "Unknown slot_id status") + | s -> failwith @@ Format.sprintf "Unknown slot_id status %s" s let slot_header_of_json json = let open JSON in diff --git a/tezt/lib_tezos/dal_common.mli b/tezt/lib_tezos/dal_common.mli index e0b0a99ba1fa5a0dd8a3e4542670ccbd03a05281..57d0f5b77c098bd58eeaacd9c5bd4033c813e944 100644 --- a/tezt/lib_tezos/dal_common.mli +++ b/tezt/lib_tezos/dal_common.mli @@ -202,7 +202,7 @@ module RPC : sig (* The status of a slot id (published level + slot index) on L1. *) type slot_id_status = | Waiting_attestation - | Attested + | Attested of int (* of attestation lag *) | Unattested | Unpublished diff --git a/tezt/tests/dal.ml b/tezt/tests/dal.ml index 007e555a52222e21f0168ef0a95003fa814b0c34..60556582bf8a26ee01395f757c71075bc0bcacb7 100644 --- a/tezt/tests/dal.ml +++ b/tezt/tests/dal.ml @@ -2085,7 +2085,7 @@ let test_dal_node_slots_headers_tracking protocol parameters _cryptobox node let* () = check_get_commitment get_commitment_succeeds attested in (* Slots that were waiting for attestation and now attested. *) let* () = - check_slot_status ~__LOC__ ~expected_status:Dal_RPC.Attested attested + check_slot_status ~__LOC__ ~expected_status:(Dal_RPC.Attested lag) attested in (* Slots not published or not included in blocks. *) let* () = check_get_commitment get_commitment_not_found ko in @@ -3045,7 +3045,8 @@ let test_attester_with_daemon protocol parameters cryptobox node client dal_node should be [unattested]. *) let expected_status = let open Dal_RPC in - if level < first_not_attested_published_level then Attested + if level < first_not_attested_published_level then + Attested parameters.attestation_lag else Unattested in Check.( @@ -3160,7 +3161,7 @@ let test_attester_with_bake_for _protocol parameters cryptobox node client in let expected_status = let open Dal_RPC in - if level <= intermediary_level then Attested else Unattested + if level <= intermediary_level then Attested lag else Unattested in Check.( (expected_status = status) @@ -5747,7 +5748,7 @@ let test_attestation_through_p2p ~batching_time_interval _protocol call attester @@ get_level_slot_status ~slot_level:publication_level ~slot_index:index) in - Check.(status = Dal_RPC.Attested) + Check.(status = Dal_RPC.Attested attestation_lag) Dal.Check.slot_id_status_typ ~error_msg:"Expected status %R (got %L)" ; Log.info "Slot sucessfully attested" ; @@ -7310,7 +7311,7 @@ module Garbage_collection = struct call slot_producer @@ get_level_slot_status ~slot_level:published_level ~slot_index) in - Check.(status = Dal_RPC.Attested) + Check.(status = Dal_RPC.Attested dal_parameters.attestation_lag) ~__LOC__ Dal.Check.slot_id_status_typ ~error_msg: @@ -7577,7 +7578,7 @@ module Garbage_collection = struct call slot_producer @@ get_level_slot_status ~slot_level:published_level ~slot_index) in - Check.(status = Dal_RPC.Attested) + Check.(status = Dal_RPC.Attested dal_parameters.attestation_lag) ~__LOC__ Dal.Check.slot_id_status_typ ~error_msg: @@ -10150,7 +10151,7 @@ let test_producer_attester (protocol : Protocol.t) Log.info "Status is %a" Dal_RPC.pp_slot_id_status status ; log_step "Final check." ; Check.( - (status = Dal_RPC.Attested) + (status = Dal_RPC.Attested lag) Dal.Check.slot_id_status_typ ~error_msg:"Published slot was supposed to be attested.") ; unit @@ -10300,7 +10301,7 @@ let test_attester_did_not_attest (protocol : Protocol.t) Log.info "Status is %a" Dal_RPC.pp_slot_id_status status ; log_step "Final checks." ; Check.( - (status = Dal_RPC.Attested) + (status = Dal_RPC.Attested lag) Dal.Check.slot_id_status_typ ~error_msg:"Published slot was supposed to be attested.") ; (* If the [not_attested_by_bootstrap2_promise] is not fulfilled yet, it means that