From 8e4e3c9b4ce9fc23179e9f663052e823d661aa12 Mon Sep 17 00:00:00 2001 From: Victor Allombert Date: Fri, 7 Jul 2023 15:34:01 +0200 Subject: [PATCH] Shell: cleaner handling of validator specific RPCs --- src/lib_shell/block_directory.ml | 126 ++++++++++++++++++++----------- src/lib_shell/chain_directory.ml | 9 +++ 2 files changed, 91 insertions(+), 44 deletions(-) diff --git a/src/lib_shell/block_directory.ml b/src/lib_shell/block_directory.ml index 2480842a9aa6..cce2295cafe2 100644 --- a/src/lib_shell/block_directory.ml +++ b/src/lib_shell/block_directory.ml @@ -858,7 +858,32 @@ let get_protocol hash = | None -> raise Not_found | Some protocol -> protocol -let get_directory chain_store block ~with_validator = +let load_proto chain_store block (module Next_proto : Registered_protocol.T) = + let open Lwt_syntax in + let* o = Store.Block.read_predecessor_opt chain_store block in + match o with + | None -> + (* No predecessors (e.g. pruned caboose), return the + current protocol *) + Lwt.return (module Next_proto : Registered_protocol.T) + | Some pred -> + let* _, savepoint_level = Store.Chain.savepoint chain_store in + let* protocol_hash = + if Compare.Int32.(Store.Block.level pred < savepoint_level) then + let* predecessor_protocol = + Store.Chain.find_protocol + chain_store + ~protocol_level:(Store.Block.proto_level pred) + in + let protocol_hash = + WithExceptions.Option.to_exn ~none:Not_found predecessor_protocol + in + Lwt.return protocol_hash + else Store.Block.protocol_hash_exn chain_store pred + in + Lwt.return (get_protocol protocol_hash) + +let get_directory_with_validator chain_store block = let open Lwt_syntax in let* o = Store.Chain.get_rpc_directory chain_store block in match o with @@ -874,40 +899,62 @@ let get_directory chain_store block ~with_validator = (module Block_services.Fake_protocol) (module Next_proto) in - if with_validator then - let dir_with_validator = - build_raw_rpc_directory_with_validator - (module Block_services.Fake_protocol) - (module Next_proto) - in - Lwt.return (Tezos_rpc.Directory.merge dir dir_with_validator) - else Lwt.return dir + let dir_with_validator = + build_raw_rpc_directory_with_validator + (module Block_services.Fake_protocol) + (module Next_proto) + in + Lwt.return (Tezos_rpc.Directory.merge dir dir_with_validator) else let* (module Proto) = - let* o = Store.Block.read_predecessor_opt chain_store block in - match o with - | None -> - (* No predecessors (e.g. pruned caboose), return the - current protocol *) - Lwt.return (module Next_proto : Registered_protocol.T) - | Some pred -> - let* _, savepoint_level = Store.Chain.savepoint chain_store in - let* protocol_hash = - if Compare.Int32.(Store.Block.level pred < savepoint_level) then - let* predecessor_protocol = - Store.Chain.find_protocol - chain_store - ~protocol_level:(Store.Block.proto_level pred) - in - let protocol_hash = - WithExceptions.Option.to_exn - ~none:Not_found - predecessor_protocol - in - Lwt.return protocol_hash - else Store.Block.protocol_hash_exn chain_store pred + load_proto chain_store block (module Next_proto) + in + let* o = Store.Chain.get_rpc_directory chain_store block in + match o with + | Some dir -> Lwt.return dir + | None -> + let dir = + let dir_without_validator = + build_raw_rpc_directory_without_validator + (module Proto) + (module Next_proto) + in + let dir_with_validator = + build_raw_rpc_directory_with_validator + (module Proto) + (module Next_proto) in - Lwt.return (get_protocol protocol_hash) + Tezos_rpc.Directory.merge dir_without_validator dir_with_validator + in + let* () = + Store.Chain.set_rpc_directory + chain_store + ~protocol_hash:Proto.hash + ~next_protocol_hash:Next_proto.hash + dir + in + Lwt.return dir) + +let get_directory_without_validator chain_store block = + let open Lwt_syntax in + let* o = Store.Chain.get_rpc_directory chain_store block in + match o with + | Some dir -> Lwt.return dir + | None -> ( + let* next_protocol_hash = + Store.Block.protocol_hash_exn chain_store block + in + let (module Next_proto) = get_protocol next_protocol_hash in + if Store.Block.is_genesis chain_store (Store.Block.hash block) then + let dir = + build_raw_rpc_directory_without_validator + (module Block_services.Fake_protocol) + (module Next_proto) + in + Lwt.return dir + else + let* (module Proto) = + load_proto chain_store block (module Next_proto) in let* o = Store.Chain.get_rpc_directory chain_store block in match o with @@ -919,16 +966,7 @@ let get_directory chain_store block ~with_validator = (module Proto) (module Next_proto) in - if with_validator then - let dir_with_validator = - build_raw_rpc_directory_with_validator - (module Proto) - (module Next_proto) - in - Tezos_rpc.Directory.merge - dir_without_validator - dir_with_validator - else dir_without_validator + dir_without_validator in let* () = Store.Chain.set_rpc_directory @@ -945,7 +983,7 @@ let build_rpc_directory_with_validator chain_store block = match o with | None -> Lwt.fail Not_found | Some b -> - let* dir = get_directory ~with_validator:true chain_store b in + let* dir = get_directory_with_validator chain_store b in Lwt.return (Tezos_rpc.Directory.map (fun _ -> Lwt.return (chain_store, b)) dir) @@ -955,6 +993,6 @@ let build_rpc_directory_without_validator chain_store block = match o with | None -> Lwt.fail Not_found | Some b -> - let* dir = get_directory ~with_validator:false chain_store b in + let* dir = get_directory_without_validator chain_store b in Lwt.return (Tezos_rpc.Directory.map (fun _ -> Lwt.return (chain_store, b)) dir) diff --git a/src/lib_shell/chain_directory.ml b/src/lib_shell/chain_directory.ml index 8e173dd6cb7e..7d7e9d50e89a 100644 --- a/src/lib_shell/chain_directory.ml +++ b/src/lib_shell/chain_directory.ml @@ -123,6 +123,10 @@ let register0 dir s f = (Tezos_rpc.Service.subst0 s) (fun chain p q -> f chain p q) +(* This RPC directory must be instantiated by the node itself. Indeed, + only the node has access to some particular resources, such as the + validator or some store internal values computed at runtime, that + are necessary for some RPCs. *) let rpc_directory_with_validator dir validator = let open Lwt_result_syntax in let register1 s f = @@ -159,6 +163,9 @@ let rpc_directory_with_validator dir validator = register1 S.Invalid_blocks.delete (fun chain_store hash () () -> Store.Block.unmark_invalid chain_store hash) +(* This RPC directory is agnostic to the node internal + resources. However, theses RPCs can access a data subset by reading + the store static values. *) let rpc_directory_without_validator dir = let open Lwt_result_syntax in register0 dir S.chain_id (fun chain_store () () -> @@ -204,6 +211,8 @@ let rpc_directory validator = Block_directory.build_rpc_directory_with_validator ; !dir +(* This RPC directory instantiates only a subset of the chain RPCs as + it is agnostic to the node internal resources. *) let rpc_directory_without_validator () = let dir : Store.chain_store Tezos_rpc.Directory.t ref = ref Tezos_rpc.Directory.empty -- GitLab