From 05f563ff0b5a4bb351f6645634d1c5c990754470 Mon Sep 17 00:00:00 2001 From: Gabriel Moise Date: Mon, 29 Sep 2025 13:38:23 +0100 Subject: [PATCH 1/5] Dal_node: Fix proto parameters for get_attestable_slots --- src/lib_dal_node/RPC_server.ml | 45 +++++++++++++--------------------- 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/src/lib_dal_node/RPC_server.ml b/src/lib_dal_node/RPC_server.ml index 193bc1589fbf..1dbedbdf1636 100644 --- a/src/lib_dal_node/RPC_server.ml +++ b/src/lib_dal_node/RPC_server.ml @@ -453,7 +453,7 @@ module Profile_handlers = struct assigned_shard_indexes let get_attestable_slots ctxt pkh attested_level () () = - let get_attestable_slots ~shard_indices store proto_parameters + let get_attestable_slots ~shard_indices store last_known_parameters ~attested_level = let open Lwt_result_syntax in let number_of_assigned_shards = List.length shard_indices in @@ -464,28 +464,17 @@ module Profile_handlers = struct Correctly compute [published_level] in case of protocol changes, in particular a change of the value of [attestation_lag]. *) Int32.( - sub attested_level (of_int proto_parameters.Types.attestation_lag)) + sub + attested_level + (of_int last_known_parameters.Types.attestation_lag)) in if published_level < 1l then let slots = - Stdlib.List.init proto_parameters.number_of_slots (fun _ -> false) + Stdlib.List.init last_known_parameters.number_of_slots (fun _ -> + false) in return (Types.Attestable_slots {slots; published_level}) else - (* FIXME: https://gitlab.com/tezos/tezos/-/issues/7291 - - Normally, for checking whether the incentives are enabled we would - use the (parameters at) [attested_level]. However, the attestation - level may be in the future and we may not have the plugin for - it. *) - let* proto_parameters = - Node_context.get_proto_parameters - ctxt - ~level:(`Level published_level) - |> Lwt.return - |> lwt_map_error (fun e -> `Other e) - in - let shards_store = Store.shards store in let number_of_shards_stored slot_index = let slot_id : Types.slot_id = @@ -500,12 +489,6 @@ module Profile_handlers = struct in (slot_id, number_stored_shards) in - let all_slot_indexes = - Utils.Infix.(0 -- (proto_parameters.number_of_slots - 1)) - in - let* number_of_stored_shards_per_slot = - List.map_es number_of_shards_stored all_slot_indexes - in let* published_level_parameters = Node_context.get_proto_parameters ctxt @@ -513,17 +496,23 @@ module Profile_handlers = struct |> Lwt.return |> lwt_map_error (fun e -> `Other e) in + let all_slot_indexes = + Utils.Infix.(0 -- (published_level_parameters.number_of_slots - 1)) + in + let* number_of_stored_shards_per_slot = + List.map_es number_of_shards_stored all_slot_indexes + in let* flags = List.map_es (fun (slot_id, num_stored) -> let all_stored = num_stored = number_of_assigned_shards in - if not published_level_parameters.incentives_enable then + if not last_known_parameters.incentives_enable then return all_stored else if not all_stored then return false else is_slot_attestable_with_traps shards_store - published_level_parameters.traps_fraction + last_known_parameters.traps_fraction pkh shard_indices slot_id) @@ -555,8 +544,8 @@ module Profile_handlers = struct ~level:attestation_level |> Errors.other_lwt_result in - let* proto_parameters = - Node_context.get_proto_parameters ctxt ~level:`Last_proto + let* attested_level_parameters = + Node_context.get_proto_parameters ctxt ~level:(`Level attested_level) |> Lwt.return |> lwt_map_error (fun e -> `Other e) in @@ -564,7 +553,7 @@ module Profile_handlers = struct get_attestable_slots ~shard_indices store - proto_parameters + attested_level_parameters ~attested_level) end -- GitLab From 73fccf752ab160dec9c5b62aa62143b93bb91492 Mon Sep 17 00:00:00 2001 From: Gabriel Moise Date: Fri, 3 Oct 2025 17:27:09 +0100 Subject: [PATCH 2/5] Dal_node: Proto_plugins: Add current_proto_level method --- src/lib_dal_node/proto_plugins.ml | 4 ++++ src/lib_dal_node/proto_plugins.mli | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/lib_dal_node/proto_plugins.ml b/src/lib_dal_node/proto_plugins.ml index 312003e2bab1..5881e3368f09 100644 --- a/src/lib_dal_node/proto_plugins.ml +++ b/src/lib_dal_node/proto_plugins.ml @@ -31,6 +31,10 @@ module Plugins = struct |> List.map (fun (_block_level, {proto_level = _; plugin; proto_parameters = _}) -> plugin) + + let current_proto_level t = + LevelMap.min_binding_opt t + |> Option.map (fun (_, proto_plugin) -> proto_plugin.proto_level) end let singleton = Plugins.add Plugins.empty diff --git a/src/lib_dal_node/proto_plugins.mli b/src/lib_dal_node/proto_plugins.mli index 6b86e8725b9e..e2a54adf0660 100644 --- a/src/lib_dal_node/proto_plugins.mli +++ b/src/lib_dal_node/proto_plugins.mli @@ -24,6 +24,10 @@ val singleton : val to_list : t -> (module Dal_plugin.T) list +(** [current_proto_level plugins] returns the [proto_level] of the most recently + added protocol plugin. *) +val current_proto_level : t -> int option + type error += | No_plugin_for_level of {level : int32} | No_plugin_for_proto of {proto_hash : Protocol_hash.t} -- GitLab From bdc539d1c31fa0bb16dc3aad0c0605237e80079c Mon Sep 17 00:00:00 2001 From: Gabriel Moise Date: Fri, 3 Oct 2025 10:42:30 +0100 Subject: [PATCH 3/5] Dal_node: Node_context: Add last_migration_level field --- src/lib_dal_node/node_context.ml | 18 +++++++++++++++--- src/lib_dal_node/node_context.mli | 5 +++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/lib_dal_node/node_context.ml b/src/lib_dal_node/node_context.ml index a85b5619b63d..6ee9e4cfe6ac 100644 --- a/src/lib_dal_node/node_context.ml +++ b/src/lib_dal_node/node_context.ml @@ -46,6 +46,7 @@ type t = { l1_crawler_status_input : L1_crawler_status.t Lwt_watcher.input; disable_shard_validation : bool; ignore_pkhs : Signature.Public_key_hash.Set.t; + mutable last_migration_level : int32; } let init config ~network_name profile_ctxt cryptobox @@ -72,6 +73,7 @@ let init config ~network_name profile_ctxt cryptobox l1_crawler_status_input = Lwt_watcher.create_input (); disable_shard_validation; ignore_pkhs; + last_migration_level = 0l; } let get_tezos_node_cctxt ctxt = ctxt.tezos_node_cctxt @@ -105,14 +107,22 @@ let may_reconstruct ~reconstruct slot_id t = let may_add_plugin ctxt cctxt ~block_level ~proto_level = let open Lwt_result_syntax in - let* proto_plugins = + let old_proto_plugins = ctxt.proto_plugins in + let* new_proto_plugins = Proto_plugins.may_add cctxt - ctxt.proto_plugins + old_proto_plugins ~first_level:block_level ~proto_level in - ctxt.proto_plugins <- proto_plugins ; + if + not + @@ Option.equal + Int.equal + (Proto_plugins.current_proto_level old_proto_plugins) + (Proto_plugins.current_proto_level new_proto_plugins) + then ctxt.last_migration_level <- block_level ; + ctxt.proto_plugins <- new_proto_plugins ; return_unit let get_plugin_and_parameters_for_level ctxt ~level = @@ -254,6 +264,8 @@ let warn_if_attesters_not_delegates ctxt controller_profiles = let get_disable_shard_validation ctxt = ctxt.disable_shard_validation +let get_last_migration_level ctxt = ctxt.last_migration_level + module P2P = struct let connect {transport_layer; _} ?timeout point = Gossipsub.Transport_layer.connect transport_layer ?timeout point diff --git a/src/lib_dal_node/node_context.mli b/src/lib_dal_node/node_context.mli index 46656196ee47..4baead1e6e8a 100644 --- a/src/lib_dal_node/node_context.mli +++ b/src/lib_dal_node/node_context.mli @@ -222,6 +222,11 @@ val warn_if_attesters_not_delegates : validation in the DAL node. *) val get_disable_shard_validation : t -> bool +(** [get_last_migration_level ctxt] returns the first block with a new [proto_level], + which is the last block of the old protocol. See + [Proto_plugins.get_plugin_and_parameters_for_level] for more clarifications. *) +val get_last_migration_level : t -> int32 + (** Module for P2P-related accessors. *) module P2P : sig (** [connect t ?timeout point] initiates a connection to the point -- GitLab From 83b3dfac6a70dae861c158a65c54dd2c4b660cb6 Mon Sep 17 00:00:00 2001 From: Gabriel Moise Date: Fri, 3 Oct 2025 16:53:32 +0100 Subject: [PATCH 4/5] Dal_node: RPC_server: Fix migration level case for get_attestable_slots --- src/lib_dal_node/RPC_server.ml | 58 +++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/src/lib_dal_node/RPC_server.ml b/src/lib_dal_node/RPC_server.ml index 1dbedbdf1636..062e8b67506b 100644 --- a/src/lib_dal_node/RPC_server.ml +++ b/src/lib_dal_node/RPC_server.ml @@ -460,9 +460,6 @@ module Profile_handlers = struct if number_of_assigned_shards = 0 then return Types.Not_in_committee else let published_level = - (* FIXME: https://gitlab.com/tezos/tezos/-/issues/4612 - Correctly compute [published_level] in case of protocol changes, in - particular a change of the value of [attestation_lag]. *) Int32.( sub attested_level @@ -529,6 +526,57 @@ module Profile_handlers = struct (fun _exn -> ()) ; return (Types.Attestable_slots {slots = flags; published_level}) in + + (* Decide whether to short-circuit attestation computation at attested level [L] + because of a protocol migration that decreased [attestation_lag]. + + - M = migration level (first level of the new protocol); + - new_lag = attestation_lag at attested level L (new protocol); + - published_level = L - new_lag + + If published_level is still in the old protocol and the old lag > new lag, + then for L in [M .. M + new_lag - 1] the corresponding published data belongs + to the old protocol and should be ignored for attestation purposes. *) + let should_drop_due_to_migration last_known_parameters = + let open Lwt_result_syntax in + let migration_level = Node_context.get_last_migration_level ctxt in + let new_lag = Int32.of_int last_known_parameters.Types.attestation_lag in + let published_level = Int32.(sub attested_level new_lag) in + let* published_level_parameters = + Node_context.get_proto_parameters ctxt ~level:(`Level published_level) + |> Lwt.return + |> lwt_map_error (fun e -> `Other e) + in + let old_lag = + Int32.of_int published_level_parameters.Types.attestation_lag + in + return + (old_lag > new_lag + && migration_level <= attested_level + && attested_level < Int32.add migration_level new_lag) + in + + (* TODO: https://gitlab.com/tezos/tezos/-/issues/8064 *) + let get_attestable_slots ~shard_indices store last_known_parameters + ~attested_level = + let open Lwt_result_syntax in + let* should_drop_due_to_migration = + should_drop_due_to_migration last_known_parameters + in + if should_drop_due_to_migration then + let slots = + Stdlib.List.init last_known_parameters.number_of_slots (fun _ -> + false) + in + return (Types.Attestable_slots {slots; published_level = 0l}) + else + get_attestable_slots + ~shard_indices + store + last_known_parameters + ~attested_level + in + call_handler1 (fun () -> let open Lwt_result_syntax in let last_finalized_level = Node_context.get_last_finalized_level ctxt in @@ -544,7 +592,7 @@ module Profile_handlers = struct ~level:attestation_level |> Errors.other_lwt_result in - let* attested_level_parameters = + let* last_known_parameters = Node_context.get_proto_parameters ctxt ~level:(`Level attested_level) |> Lwt.return |> lwt_map_error (fun e -> `Other e) @@ -553,7 +601,7 @@ module Profile_handlers = struct get_attestable_slots ~shard_indices store - attested_level_parameters + last_known_parameters ~attested_level) end -- GitLab From 2fa55227a82165f74f14fa957538ebfc751f34da Mon Sep 17 00:00:00 2001 From: Gabriel Moise Date: Fri, 3 Oct 2025 10:51:31 +0100 Subject: [PATCH 5/5] Dal_node: Event: Add skip attesting shards event --- src/lib_dal_node/RPC_server.ml | 2 ++ src/lib_dal_node/event.ml | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/lib_dal_node/RPC_server.ml b/src/lib_dal_node/RPC_server.ml index 062e8b67506b..bb0c1ac4b112 100644 --- a/src/lib_dal_node/RPC_server.ml +++ b/src/lib_dal_node/RPC_server.ml @@ -564,6 +564,8 @@ module Profile_handlers = struct should_drop_due_to_migration last_known_parameters in if should_drop_due_to_migration then + let*! () = Event.emit_skip_attesting_shards ~level:attested_level in + let slots = Stdlib.List.init last_known_parameters.number_of_slots (fun _ -> false) diff --git a/src/lib_dal_node/event.ml b/src/lib_dal_node/event.ml index 4f9e41a96543..77fb3a096b30 100644 --- a/src/lib_dal_node/event.ml +++ b/src/lib_dal_node/event.ml @@ -1221,6 +1221,17 @@ open struct ("shard_index", Data_encoding.int31) ("sender", Types.Peer.encoding) ~pp4:Types.Peer.pp + + (* TODO: https://gitlab.com/tezos/tezos/-/issues/8064 *) + let skip_attesting_shards = + declare_1 + ~section:["dal_shards"; "skip"] + ~name:"skip_attesting_shards" + ~msg: + "Skip attested level {level} due to change in attestation lag at \ + migration level." + ~level:Warning + ("level", Data_encoding.int32) end (* DAL node event emission functions *) @@ -1569,3 +1580,5 @@ let emit_validation_of_shard_update ~level ~slot_index ~slot_metrics = let emit_reception_of_shard_detailed ~level ~slot_index ~shard_index ~sender = emit reception_of_shard_detailed (level, slot_index, shard_index, sender) + +let emit_skip_attesting_shards ~level = emit skip_attesting_shards level -- GitLab