diff --git a/CHANGES.rst b/CHANGES.rst index 5dfd60c9ecb31c8b7eaf6b53f1e008351441a1a6..b7b54fa44cb87e501476432851863f4f0177d94b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -256,9 +256,13 @@ Data Availability Layer (DAL) DAL node ~~~~~~~~ +- **Feature** A new RPC ``/p2p/gossipsub/reconnection_delays`` which + provides for each unreachable point, the time remaining until the + next reconnection attempt. (MR :gl:`!16767`) + - **Bugfix** From v21.2, the DAL node tries to recontact peers after the connection attempt failed. However, this MR fixes the timing - when those attempts were made (MR :gl:`!16466`) + when those attempts were made. (MR :gl:`!16466`) - **Feature** The DAL node stores now a peers.json file in its directory when it is shutdown with SIGINT. This file is read if it diff --git a/src/bin_dal_node/RPC_server.ml b/src/bin_dal_node/RPC_server.ml index fc41d7f8f7615e531c2cabb56c6a81306418228a..7f7ad47886508406c430a8070ef1eb16ab2abf1b 100644 --- a/src/bin_dal_node/RPC_server.ml +++ b/src/bin_dal_node/RPC_server.ml @@ -618,6 +618,10 @@ module P2P = struct ?ignore_bootstrap_topics ctxt + let get_reconnection_delays ctxt () () = + let open Lwt_result_syntax in + return @@ Node_context.P2P.Gossipsub.get_reconnection_delays ctxt + let get_scores ctxt () () = let open Lwt_result_syntax in return @@ Node_context.P2P.Gossipsub.get_scores ctxt @@ -735,6 +739,10 @@ let register : Tezos_rpc.Directory.register0 Services.P2P.Gossipsub.get_connections (P2P.Gossipsub.get_connections ~ignore_bootstrap_topics:true ctxt) + |> add_service + Tezos_rpc.Directory.register0 + Services.P2P.Gossipsub.get_reconnection_delays + (P2P.Gossipsub.get_reconnection_delays ctxt) |> add_service Tezos_rpc.Directory.register0 Services.P2P.Gossipsub.get_scores diff --git a/src/bin_dal_node/node_context.ml b/src/bin_dal_node/node_context.ml index 2a62cb212121eb0dbf5f7e26bd4839e62910c2d1..6d0c2f9194c466a817ccb4a8f977b7719fbbb424 100644 --- a/src/bin_dal_node/node_context.ml +++ b/src/bin_dal_node/node_context.ml @@ -383,6 +383,9 @@ module P2P = struct state.connections [] + let get_reconnection_delays {gs_worker; _} = + Gossipsub.Worker.reconnection_delays gs_worker + let get_scores {gs_worker; _} = let state = Gossipsub.Worker.state gs_worker in Gossipsub.Worker.GS.Peer.Map.fold diff --git a/src/bin_dal_node/node_context.mli b/src/bin_dal_node/node_context.mli index 654163e33756d1bd16fdfe01b1bafa9250c71d34..eab5679be421eaae5e274970a332518b56f235d5 100644 --- a/src/bin_dal_node/node_context.mli +++ b/src/bin_dal_node/node_context.mli @@ -311,6 +311,9 @@ module P2P : sig t -> (Types.Peer.t * Types.Gossipsub.connection) list + (** [get_reconnection_delays t] returns the reconnections delays for unreachable points. *) + val get_reconnection_delays : t -> (Types.Point.t * Types.Span.t) list + (** [get_scores t] returns the score of peers with a known score. *) val get_scores : t -> (Types.Peer.t * Types.Score.t) list diff --git a/src/lib_dal_node_services/services.ml b/src/lib_dal_node_services/services.ml index 3dcdbc8762392d9439d169c413f8e5fc7e3a663a..48ffbc88ae2a0ca0d4381aa705e938b261561d42 100644 --- a/src/lib_dal_node_services/services.ml +++ b/src/lib_dal_node_services/services.ml @@ -716,6 +716,27 @@ module P2P = struct (req "connection" Gossipsub.connection_encoding))) (open_root / "connections") + let get_reconnection_delays : + < meth : [`GET] + ; input : unit + ; output : (Point.t * Span.t) list + ; prefix : unit + ; params : unit + ; query : unit > + service = + Tezos_rpc.Service.get_service + ~description: + "For each unreachable point, retrieve the time remaining until the \ + next reconnection attempt." + ~query:Tezos_rpc.Query.empty + ~output: + Data_encoding.( + list + (obj2 + (req "point" Point.encoding) + (req "delay" Span.rpc_encoding))) + (open_root / "reconnection_delays") + let get_scores : < meth : [`GET] ; input : unit diff --git a/src/lib_dal_node_services/services.mli b/src/lib_dal_node_services/services.mli index fbdf428a8f9a567731c16f0fdd273ab5b435b541..13f8b6874ec32755515f4235c6e8ff09c7537406 100644 --- a/src/lib_dal_node_services/services.mli +++ b/src/lib_dal_node_services/services.mli @@ -372,6 +372,15 @@ module P2P : sig ; query : unit > service + val get_reconnection_delays : + < meth : [`GET] + ; input : unit + ; output : (Types.Point.t * Types.Span.t) list + ; prefix : unit + ; params : unit + ; query : unit > + service + val get_scores : < meth : [`GET] ; input : unit diff --git a/src/lib_dal_node_services/types.ml b/src/lib_dal_node_services/types.ml index b1cb15607d8c4eb89033b08ceadab2aca598e05d..5495245c3c058ad9ce632e88766a1fae39f15278 100644 --- a/src/lib_dal_node_services/types.ml +++ b/src/lib_dal_node_services/types.ml @@ -260,6 +260,13 @@ module Span = struct let pp = Ptime.Span.pp + let rpc_encoding : t Data_encoding.t = + let open Data_encoding in + conv + (fun span -> Format.asprintf "%a" Ptime.Span.pp span) + (fun _ -> Stdlib.failwith "This is only used for encoding") + Data_encoding.string + let encoding : t Data_encoding.t = let open Data_encoding in (* We limit the size of a {!Span.t} value to 2 bytes. It is sufficient for the diff --git a/src/lib_dal_node_services/types.mli b/src/lib_dal_node_services/types.mli index ca546154ad032f095edbaac4813a1d5e7e0b5f60..ac33835a90394fecd6676940846c8d9dd40f1ab2 100644 --- a/src/lib_dal_node_services/types.mli +++ b/src/lib_dal_node_services/types.mli @@ -169,6 +169,8 @@ module Span : sig include COMPARABLE with type t := t + val rpc_encoding : t Data_encoding.t + val zero : t val of_int_s : int -> t diff --git a/src/lib_gossipsub/gossipsub_intf.ml b/src/lib_gossipsub/gossipsub_intf.ml index 1318798ec456cc78d174e9bb2f3b0da01e4e11eb..9f35c46cbd46032f5aaa0f7bbf9933b90ab59a14 100644 --- a/src/lib_gossipsub/gossipsub_intf.ml +++ b/src/lib_gossipsub/gossipsub_intf.ml @@ -1222,6 +1222,11 @@ module type WORKER = sig to be processed by the worker. *) val input_events_stream : t -> event Stream.t + (** [reconnection_delays t] returns the points that are currently + unreachable with the span before the next attempt to reconnect + to them. *) + val reconnection_delays : t -> (Point.t * GS.Span.t) list + (** [is_subscribed t topic] checks whether [topic] is in the mesh of [t]. *) val is_subscribed : t -> GS.Topic.t -> bool diff --git a/src/lib_gossipsub/gossipsub_worker.ml b/src/lib_gossipsub/gossipsub_worker.ml index cfb52f29ed93bb080ea5d2c7cfe2043b14ee08ff..3ccb3aa7737bd2d06677799c67a4e7ec3e9a5cf0 100644 --- a/src/lib_gossipsub/gossipsub_worker.ml +++ b/src/lib_gossipsub/gossipsub_worker.ml @@ -954,6 +954,19 @@ module Make (C : Gossipsub_intf.WORKER_CONFIGURATION) : let input_events_stream t = t.state.events_stream + let reconnection_delays {state = {unreachable_points; gossip_state; _}; _} = + let heartbeat_span = View.((view gossip_state).limits.heartbeat_interval) in + let View.{heartbeat_ticks; _} = View.(view gossip_state) in + unreachable_points |> Point.Map.to_seq + |> Seq.map (fun (point, next_heartbeat_reconnection_tick) -> + let how_many_ticks_left = + Int64.(sub next_heartbeat_reconnection_tick heartbeat_ticks) + |> Int64.to_int + in + let span = GS.Span.mul heartbeat_span how_many_ticks_left in + (point, span)) + |> List.of_seq + let is_subscribed t topic = GS.Introspection.(has_joined topic (view t.state.gossip_state)) diff --git a/tezt/tests/expected/dal.ml/Alpha- Testing DAL node (dal node list RPCs).out b/tezt/tests/expected/dal.ml/Alpha- Testing DAL node (dal node list RPCs).out index edf495c0fd38dbce9f65fbb7ad7fb43cae791e94..848e238d2472cddb1b69745e990ab4c31ff4ac1d 100644 --- a/tezt/tests/expected/dal.ml/Alpha- Testing DAL node (dal node list RPCs).out +++ b/tezt/tests/expected/dal.ml/Alpha- Testing DAL node (dal node list RPCs).out @@ -47,6 +47,9 @@ Available services: topic subscribed to by the connected peers and the remote peers subscribed to that topic. If the 'all' flag is not given, then restrict the output to the topics this peer is subscribed to. + - GET /p2p/gossipsub/reconnection_delays + For each unreachable point, retrieve the time remaining until the + next reconnection attempt. - GET /p2p/gossipsub/scores Get the scores of the peers with a known score. - GET /p2p/gossipsub/slot_indexes/peers diff --git a/tezt/tests/expected/dal.ml/Next-- Testing DAL node (dal node list RPCs).out b/tezt/tests/expected/dal.ml/Next-- Testing DAL node (dal node list RPCs).out index edf495c0fd38dbce9f65fbb7ad7fb43cae791e94..848e238d2472cddb1b69745e990ab4c31ff4ac1d 100644 --- a/tezt/tests/expected/dal.ml/Next-- Testing DAL node (dal node list RPCs).out +++ b/tezt/tests/expected/dal.ml/Next-- Testing DAL node (dal node list RPCs).out @@ -47,6 +47,9 @@ Available services: topic subscribed to by the connected peers and the remote peers subscribed to that topic. If the 'all' flag is not given, then restrict the output to the topics this peer is subscribed to. + - GET /p2p/gossipsub/reconnection_delays + For each unreachable point, retrieve the time remaining until the + next reconnection attempt. - GET /p2p/gossipsub/scores Get the scores of the peers with a known score. - GET /p2p/gossipsub/slot_indexes/peers diff --git a/tezt/tests/expected/dal.ml/Quebec- Testing DAL node (dal node list RPCs).out b/tezt/tests/expected/dal.ml/Quebec- Testing DAL node (dal node list RPCs).out index edf495c0fd38dbce9f65fbb7ad7fb43cae791e94..848e238d2472cddb1b69745e990ab4c31ff4ac1d 100644 --- a/tezt/tests/expected/dal.ml/Quebec- Testing DAL node (dal node list RPCs).out +++ b/tezt/tests/expected/dal.ml/Quebec- Testing DAL node (dal node list RPCs).out @@ -47,6 +47,9 @@ Available services: topic subscribed to by the connected peers and the remote peers subscribed to that topic. If the 'all' flag is not given, then restrict the output to the topics this peer is subscribed to. + - GET /p2p/gossipsub/reconnection_delays + For each unreachable point, retrieve the time remaining until the + next reconnection attempt. - GET /p2p/gossipsub/scores Get the scores of the peers with a known score. - GET /p2p/gossipsub/slot_indexes/peers