From aa71db1f910b74abb0c396bdab4f19fb9c6ff5ec Mon Sep 17 00:00:00 2001 From: Victor Allombert Date: Tue, 5 Nov 2024 11:24:40 +0100 Subject: [PATCH 1/2] Shell/peer_validator: store block_hash for last_advertised_head --- src/lib_shell/peer_validator.ml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/lib_shell/peer_validator.ml b/src/lib_shell/peer_validator.ml index bcaefcd85848..3f4b2949719e 100644 --- a/src/lib_shell/peer_validator.ml +++ b/src/lib_shell/peer_validator.ml @@ -75,7 +75,7 @@ module Types = struct parameters : parameters; mutable pipeline : Bootstrap_pipeline.t option; mutable last_validated_head : Block_header.t; - mutable last_advertised_head : Block_header.t; + mutable last_advertised_head : Block_hash.t * Block_header.t; } let pipeline_length = function @@ -523,7 +523,8 @@ let on_launch _ name parameters : (_, launch_error) result Lwt.t = parameters = {parameters with notify_new_block}; pipeline = None; last_validated_head = Store.Block.header genesis; - last_advertised_head = Store.Block.header genesis; + last_advertised_head = + (Store.Block.hash genesis, Store.Block.header genesis); } and notify_new_block ({block; _} as new_block) = pv.last_validated_head <- Store.Block.header block ; @@ -537,10 +538,10 @@ let table = let pv = Worker.state w in match neu with | Request.New_branch (locator, _) -> - pv.last_advertised_head <- locator.Block_locator.head_header ; + pv.last_advertised_head <- (locator.head_hash, locator.head_header) ; Some (Worker.Any_request neu) - | Request.New_head (_, header) -> ( - pv.last_advertised_head <- header ; + | Request.New_head (hash, header) -> ( + pv.last_advertised_head <- (hash, header) ; (* TODO penalize decreasing fitness *) match old with | Some (Worker.Any_request (Request.New_branch _) as old) -> -- GitLab From db9cc9766c98528993711da74d3e9ad7edab2c89 Mon Sep 17 00:00:00 2001 From: Victor Allombert Date: Tue, 5 Nov 2024 12:05:11 +0100 Subject: [PATCH 2/2] Shell: introduce RPC to query active peers last advertized head --- src/lib_shell/chain_directory.ml | 6 +++++ src/lib_shell/chain_validator.ml | 19 ++++++++++++++++ src/lib_shell/chain_validator.mli | 2 ++ src/lib_shell/peer_validator.ml | 4 ++++ src/lib_shell/peer_validator.mli | 2 ++ src/lib_shell_services/chain_services.ml | 27 +++++++++++++++++++++++ src/lib_shell_services/chain_services.mli | 16 ++++++++++++++ 7 files changed, 76 insertions(+) diff --git a/src/lib_shell/chain_directory.ml b/src/lib_shell/chain_directory.ml index 84c92fb4ea59..5b6590d286f5 100644 --- a/src/lib_shell/chain_directory.ml +++ b/src/lib_shell/chain_directory.ml @@ -143,6 +143,12 @@ let rpc_directory_with_validator dir validator = | Ok chain_validator -> let*! v = Chain_validator.force_bootstrapped chain_validator b in return v) ; + register0 dir S.active_peers_heads (fun chain_store () () -> + match Validator.get validator (Store.Chain.chain_id chain_store) with + | Error _ -> Lwt.fail Not_found + | Ok chain_validator -> + let*! ap = Chain_validator.active_peers_heads chain_validator in + return ap) ; (* invalid_blocks *) register0 dir S.Invalid_blocks.list (fun chain_store () () -> let convert (hash, {Store_types.level; errors}) = {hash; level; errors} in diff --git a/src/lib_shell/chain_validator.ml b/src/lib_shell/chain_validator.ml index 8fd57d553eb1..47c013df5257 100644 --- a/src/lib_shell/chain_validator.ml +++ b/src/lib_shell/chain_validator.ml @@ -1046,6 +1046,25 @@ let force_bootstrapped w b = state.synchronisation_state b +let active_peers_heads w = + let open Lwt_syntax in + let state = Worker.state w in + P2p_peer.Error_table.fold_promises + (fun peer_id pv acc -> + let* acc in + let* pv in + match pv with + | Error _ -> + (* Ignoring peer validators with error status. *) Lwt.return acc + | Ok pv -> + let block_hash, head = Peer_validator.get_last_advertised_head pv in + Lwt.return + (Chain_services. + {peer_id; block_hash; block_level = head.shell.level} + :: acc)) + state.active_peers + Lwt.return_nil + let received_block_watcher w = let {received_block_input; _} = Worker.state w in Lwt_watcher.create_stream received_block_input diff --git a/src/lib_shell/chain_validator.mli b/src/lib_shell/chain_validator.mli index 71735b9ce898..731b7623a381 100644 --- a/src/lib_shell/chain_validator.mli +++ b/src/lib_shell/chain_validator.mli @@ -57,6 +57,8 @@ val is_bootstrapped : t -> bool val force_bootstrapped : t -> bool -> unit Lwt.t +val active_peers_heads : t -> Chain_services.active_peers_info list Lwt.t + val prevalidator : t -> Prevalidator.t option val chain_db : t -> Distributed_db.chain_db diff --git a/src/lib_shell/peer_validator.ml b/src/lib_shell/peer_validator.ml index 3f4b2949719e..a5a1ad3fb711 100644 --- a/src/lib_shell/peer_validator.ml +++ b/src/lib_shell/peer_validator.ml @@ -91,6 +91,10 @@ type t = Worker.dropbox Worker.t let metrics = Shell_metrics.Peer_validator.init Name.base +let get_last_advertised_head w = + let pv = Worker.state w in + pv.last_advertised_head + let bootstrap_new_branch w unknown_prefix = let open Lwt_result_syntax in let pv = Worker.state w in diff --git a/src/lib_shell/peer_validator.mli b/src/lib_shell/peer_validator.mli index 3b4f42f58fdc..f59adb4d3ac1 100644 --- a/src/lib_shell/peer_validator.mli +++ b/src/lib_shell/peer_validator.mli @@ -49,6 +49,8 @@ val status : t -> Worker_types.worker_status val information : t -> Worker_types.worker_information +val get_last_advertised_head : t -> Block_hash.t * Block_header.t + val current_request : t -> (Time.System.t * Time.System.t * Peer_validator_worker_state.Request.view) diff --git a/src/lib_shell_services/chain_services.ml b/src/lib_shell_services/chain_services.ml index 2fa821761339..bd7fa0747793 100644 --- a/src/lib_shell_services/chain_services.ml +++ b/src/lib_shell_services/chain_services.ml @@ -83,6 +83,26 @@ let protocol_info_encoding = "The activation block for a protocol is the migration block, i.e. \ the last level of the previous protocol.") +type active_peers_info = { + peer_id : P2p_peer.Id.t; + block_hash : Block_hash.t; + block_level : Int32.t; +} + +let active_peers_info_encoding = + conv + (fun {peer_id; block_hash; block_level} -> + (peer_id, block_hash, block_level)) + (fun (peer_id, block_hash, block_level) -> + {peer_id; block_hash; block_level}) + @@ obj3 + (req "peer_id" P2p_peer.Id.encoding) + (req "block_hash" Block_hash.encoding) + (req "block_level" int32) + +let active_peers_heads_encoding = + obj1 (req "active_peers_heads" (list active_peers_info_encoding)) + module S = struct let path : prefix Tezos_rpc.Path.context = Tezos_rpc.Path.open_root @@ -112,6 +132,13 @@ module S = struct ~output:unit path + let active_peers_heads = + Tezos_rpc.Service.get_service + ~description:"The heads of all active peers" + ~query:Tezos_rpc.Query.empty + ~output:active_peers_heads_encoding + Tezos_rpc.Path.(path / "active_peers_heads") + module Levels = struct let path = Tezos_rpc.Path.(path / "levels") diff --git a/src/lib_shell_services/chain_services.mli b/src/lib_shell_services/chain_services.mli index 7028a0fa3d58..e369c33be276 100644 --- a/src/lib_shell_services/chain_services.mli +++ b/src/lib_shell_services/chain_services.mli @@ -45,6 +45,13 @@ type protocol_info = { last level of the previous protocol. *) } +(* Information regarding the last advertised head of a given peer. *) +type active_peers_info = { + peer_id : P2p_peer.Id.t; + block_hash : Block_hash.t; + block_level : Int32.t; +} + val path : (unit, prefix) Tezos_rpc.Path.path open Tezos_rpc.Context @@ -123,6 +130,15 @@ module S : sig val force_bootstrapped : ([`PATCH], prefix, prefix, unit, bool, unit) Tezos_rpc.Service.t + val active_peers_heads : + ( [`GET], + prefix, + prefix, + unit, + unit, + active_peers_info list ) + Tezos_rpc.Service.t + module Levels : sig val checkpoint : ( [`GET], -- GitLab