From 8b5191b7359cb0c929b2c4f3065503ffa118e970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Thir=C3=A9?= Date: Thu, 23 Mar 2023 14:47:13 +0100 Subject: [PATCH 1/2] Gossipsub: Export an introspection module --- src/lib_gossipsub/gossipsub_intf.ml | 35 +++++++++++++++++++++++++ src/lib_gossipsub/tezos_gossipsub.ml | 39 ++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/src/lib_gossipsub/gossipsub_intf.ml b/src/lib_gossipsub/gossipsub_intf.ml index d6e24e25bacb..53cefa970d96 100644 --- a/src/lib_gossipsub/gossipsub_intf.ml +++ b/src/lib_gossipsub/gossipsub_intf.ml @@ -344,6 +344,41 @@ module type AUTOMATON = sig val pp_unsubscribe : Format.formatter -> unsubscribe -> unit + module Introspection : sig + type connection = { + topics : Topic.Set.t; + direct : bool; + outbound : bool; + backoff : Time.t Topic.Map.t; + score : Score.t; + expire : Time.t option; + } + + type connections := connection Peer.Map.t + + type fanout_peers = {peers : Peer.Set.t; last_published_time : Time.t} + + module Memory_cache : sig + type value = {message : message; access : int Peer.Map.t} + + type t = {messages : value Message_id.Map.t} + end + + type view = { + limits : limits; + parameters : parameters; + connections : connections; + ihave_per_heartbeat : int Peer.Map.t; + iwant_per_heartbeat : int Peer.Map.t; + mesh : Peer.Set.t Topic.Map.t; + fanout : fanout_peers Topic.Map.t; + seen_messages : Message_id.Set.t; + memory_cache : Memory_cache.t; + rng : Random.State.t; + heartbeat_ticks : int64; + } + end + module Internal_for_tests : sig (** [get_peers_in_topic_mesh topic state] returns the peers in the mesh of [topic]. *) val get_peers_in_topic_mesh : Topic.t -> state -> Peer.t list diff --git a/src/lib_gossipsub/tezos_gossipsub.ml b/src/lib_gossipsub/tezos_gossipsub.ml index 2f5b0247a513..b5d79cd82cfe 100644 --- a/src/lib_gossipsub/tezos_gossipsub.ml +++ b/src/lib_gossipsub/tezos_gossipsub.ml @@ -1431,6 +1431,45 @@ module Make (C : AUTOMATON_CONFIG) : let open Format in fprintf fmtr "{ topic=%a; peer=%a }" Topic.pp topic Peer.pp peer + module Introspection = struct + (* This module reexport datatypes so that it can be used for + introspection. While at the moment, this module reexport purely + the datatype, we can decide that for abstraction purpose, we do + not export all those fields in the future. This may have a + small overhead cost, but for introspection it should be + irrelevant. *) + + type nonrec connection = connection = { + topics : Topic.Set.t; + direct : bool; + outbound : bool; + backoff : time Topic.Map.t; + score : Score.t; + expire : time option; + } + + type nonrec fanout_peers = fanout_peers = { + peers : Peer.Set.t; + last_published_time : time; + } + + module Memory_cache = Memory_cache + + type view = state = { + limits : limits; + parameters : parameters; + connections : connections; + ihave_per_heartbeat : int Peer.Map.t; + iwant_per_heartbeat : int Peer.Map.t; + mesh : Peer.Set.t Topic.Map.t; + fanout : fanout_peers Topic.Map.t; + seen_messages : Message_id.Set.t; + memory_cache : Memory_cache.t; + rng : Random.State.t; + heartbeat_ticks : int64; + } + end + module Internal_for_tests = struct let get_peers_in_topic_mesh topic state = match Topic.Map.find topic state.mesh with -- GitLab From 6fa5fda73e2826b14ff598daec779819f9139405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Thir=C3=A9?= Date: Mon, 27 Mar 2023 10:31:20 +0200 Subject: [PATCH 2/2] Gossipsub: Remove internal for tests --- src/lib_gossipsub/gossipsub_intf.ml | 27 +++++++-------------------- src/lib_gossipsub/test/test_pbt.ml | 4 ++-- src/lib_gossipsub/test/test_unit.ml | 16 +++++++++++----- src/lib_gossipsub/tezos_gossipsub.ml | 13 ++----------- 4 files changed, 22 insertions(+), 38 deletions(-) diff --git a/src/lib_gossipsub/gossipsub_intf.ml b/src/lib_gossipsub/gossipsub_intf.ml index 53cefa970d96..4c3998a5b2b4 100644 --- a/src/lib_gossipsub/gossipsub_intf.ml +++ b/src/lib_gossipsub/gossipsub_intf.ml @@ -377,35 +377,22 @@ module type AUTOMATON = sig rng : Random.State.t; heartbeat_ticks : int64; } - end - module Internal_for_tests : sig + val view : state -> view + (** [get_peers_in_topic_mesh topic state] returns the peers in the mesh of [topic]. *) - val get_peers_in_topic_mesh : Topic.t -> state -> Peer.t list + val get_peers_in_topic_mesh : Topic.t -> view -> Peer.t list (** [get_subscribed_topics peer state] returns the set of topics that are subscribed by [peer] *) - val get_subscribed_topics : Peer.t -> state -> Topic.t list + val get_subscribed_topics : Peer.t -> view -> Topic.t list (** [get_fanout_peers topic state] returns the fanout peers of [topic]. *) - val get_fanout_peers : Topic.t -> state -> Peer.t list - - type connection = { - topics : Topic.Set.t; - direct : bool; - (** A direct (aka explicit) connection is a connection to which we forward all the messages. *) - outbound : bool; - (** An outbound connection is a connection we initiated. *) - backoff : Time.t Topic.Map.t; - (** The backoff times associated to this peer for each topic *) - score : Score.t; (** The score associated to this peer. *) - expire : Time.t option; - (** The expiring time after having being disconnected from this peer. *) - } + val get_fanout_peers : Topic.t -> view -> Peer.t list - val connections : state -> connection Peer.Map.t + val connections : view -> connection Peer.Map.t - val limits : state -> limits + val limits : view -> limits end end diff --git a/src/lib_gossipsub/test/test_pbt.ml b/src/lib_gossipsub/test/test_pbt.ml index e3fe38f30aa8..513a1d245869 100644 --- a/src/lib_gossipsub/test/test_pbt.ml +++ b/src/lib_gossipsub/test/test_pbt.ml @@ -69,7 +69,7 @@ module Test_remove_peer = struct (* This predicate checks that [peer_id] does not appear in the [connections] field of the final state. *) (* FIXME https://gitlab.com/tezos/tezos/-/issues/5190 *) - let conns = GS.Internal_for_tests.connections final_state in + let conns = GS.Introspection.(connections (view final_state)) in let fail = List.find_opt (fun peer -> GS.Peer.Map.mem peer conns) all_peers in @@ -164,7 +164,7 @@ module Test_remove_peer = struct @[%a@]@]" peer pp_limits - (GS.Internal_for_tests.limits final_state) + GS.Introspection.(limits (view final_state)) (pp_trace ()) trace) in diff --git a/src/lib_gossipsub/test/test_unit.ml b/src/lib_gossipsub/test/test_unit.ml index 7d25942f0d52..42031184e407 100644 --- a/src/lib_gossipsub/test/test_unit.ml +++ b/src/lib_gossipsub/test/test_unit.ml @@ -37,7 +37,9 @@ let assert_output ~__LOC__ actual expected = else Test.fail ~__LOC__ "Assert for output failed." let assert_subscribed_topics ~__LOC__ ~peer ~expected_topics state = - let actual_topics = GS.Internal_for_tests.get_subscribed_topics peer state in + let actual_topics = + GS.Introspection.(get_subscribed_topics peer (view state)) + in Check.( (actual_topics = expected_topics) (list string) @@ -241,7 +243,7 @@ let test_join_adds_peers_to_mesh rng limits parameters = in (* should have added [degree_optimal] nodes to the mesh *) let peers_in_topic = - GS.Internal_for_tests.get_peers_in_topic_mesh "topic0" state + GS.Introspection.(get_peers_in_topic_mesh "topic0" (view state)) in Check.( (List.length peers_in_topic = limits.degree_optimal) @@ -296,7 +298,9 @@ let test_join_adds_fanout_to_mesh rng limits parameters = state in (* Check that all [init_peers] have been added to the fanout. *) - let fanout_peers = GS.Internal_for_tests.get_fanout_peers "topic0" state in + let fanout_peers = + GS.Introspection.(get_fanout_peers "topic0" (view state)) + in Check.( (List.length fanout_peers = limits.degree_optimal / 2) int @@ -317,7 +321,7 @@ let test_join_adds_fanout_to_mesh rng limits parameters = | _, _ -> Test.fail ~__LOC__ "Expected Join to succeed" in let peers_in_topic = - GS.Internal_for_tests.get_peers_in_topic_mesh "topic0" state + GS.Introspection.(get_peers_in_topic_mesh "topic0" (view state)) in (* All [degree_optimal / 2] fanout peers should have been added to the mesh, along with [degree_optimal / 2] more from the pool. *) @@ -345,7 +349,9 @@ let test_join_adds_fanout_to_mesh rng limits parameters = ~error_msg:"Expected %R, got %L" ~__LOC__) ; (* Check that the fanout map has been cleared. *) - let fanout_peers = GS.Internal_for_tests.get_fanout_peers "topic0" state in + let fanout_peers = + GS.Introspection.(get_fanout_peers "topic0" (view state)) + in Check.( (List.length fanout_peers = 0) int ~error_msg:"Expected %R, got %L" ~__LOC__) ; unit diff --git a/src/lib_gossipsub/tezos_gossipsub.ml b/src/lib_gossipsub/tezos_gossipsub.ml index b5d79cd82cfe..2dba3da8e962 100644 --- a/src/lib_gossipsub/tezos_gossipsub.ml +++ b/src/lib_gossipsub/tezos_gossipsub.ml @@ -1468,9 +1468,9 @@ module Make (C : AUTOMATON_CONFIG) : rng : Random.State.t; heartbeat_ticks : int64; } - end - module Internal_for_tests = struct + let view state = state + let get_peers_in_topic_mesh topic state = match Topic.Map.find topic state.mesh with | None -> [] @@ -1486,15 +1486,6 @@ module Make (C : AUTOMATON_CONFIG) : | None -> [] | Some fanout_peers -> Peer.Set.elements fanout_peers.peers - type nonrec connection = connection = { - topics : Topic.Set.t; - direct : bool; - outbound : bool; - backoff : Time.t Topic.Map.t; - score : Score.t; - expire : Time.t option; - } - let connections state = state.connections let limits state = state.limits -- GitLab