diff --git a/docs/doc_gen/rpc_doc.ml b/docs/doc_gen/rpc_doc.ml index 947f08021383181a02eae328bfd5970e7c5b01b7..dd6b7a59e1670e71e5f1f365de0f1eb2aa3bdc04 100644 --- a/docs/doc_gen/rpc_doc.ml +++ b/docs/doc_gen/rpc_doc.ml @@ -392,7 +392,9 @@ let make_index ?introduction_path ~required_version ~hash () = | Some proto -> proto in Tezos_rpc.Directory.map (fun () -> assert false) - @@ Block_directory.build_raw_rpc_directory (module Proto) (module Proto) + @@ Block_directory.build_raw_rpc_directory_with_validator + (module Proto) + (module Proto) in Tezos_rpc.Directory.describe_directory ~recurse:true ~arg:() dir in diff --git a/src/lib_shell/block_directory.ml b/src/lib_shell/block_directory.ml index b1ef3858d18f0144d00408d62c2eeefc071fc2ae..f6a675caa7f730b0df0133d7ecd8cfd20475823b 100644 --- a/src/lib_shell/block_directory.ml +++ b/src/lib_shell/block_directory.ml @@ -157,7 +157,75 @@ let with_metadata ~force_metadata ~metadata = | _, Some `Never -> Some `Never | _, None -> None -let build_raw_rpc_directory (module Proto : Block_services.PROTO) +let build_raw_rpc_directory_with_validator (module Proto : Block_services.PROTO) + (module Next_proto : Registered_protocol.T) = + let open Lwt_result_syntax in + let dir : (Store.chain_store * Store.Block.block) Tezos_rpc.Directory.t ref = + ref Tezos_rpc.Directory.empty + in + let register0 s f = + dir := + Tezos_rpc.Directory.register + !dir + (Tezos_rpc.Service.subst0 s) + (fun block p q -> f block p q) + in + let module Block_services = Block_services.Make (Proto) (Next_proto) in + let module S = Block_services.S in + (* helpers *) + register0 S.Helpers.Preapply.block (fun (chain_store, block) q p -> + let timestamp = + match q#timestamp with + | None -> Time.System.to_protocol (Time.System.now ()) + | Some time -> time + in + let protocol_data = + Data_encoding.Binary.to_bytes_exn + Next_proto.block_header_data_encoding + p.protocol_data + in + let operations = + List.map + (fun operations -> + let operations = + List.map + (fun op -> + let proto = + Data_encoding.Binary.to_bytes_exn + Next_proto + .operation_data_encoding_with_legacy_attestation_name + op.Next_proto.protocol_data + in + (op, {Operation.shell = op.shell; proto})) + operations + in + let operations = + if q#sort_operations then + List.sort + (fun (op, ops) (op', ops') -> + let oph, oph' = (Operation.hash ops, Operation.hash ops') in + Next_proto.compare_operations (oph, op) (oph', op')) + operations + else operations + in + List.map snd operations) + p.operations + in + let* bv = + try return (Block_validator.running_worker ()) + with _ -> failwith "Block validator is not running" + in + Block_validator.preapply + bv + chain_store + ~predecessor:block + ~timestamp + ~protocol_data + operations) ; + !dir + +let build_raw_rpc_directory_without_validator + (module Proto : Block_services.PROTO) (module Next_proto : Registered_protocol.T) = let open Lwt_result_syntax in let dir : (Store.chain_store * Store.Block.block) Tezos_rpc.Directory.t ref = @@ -659,55 +727,6 @@ let build_raw_rpc_directory (module Proto : Block_services.PROTO) operations; } )) ; (* helpers *) - register0 S.Helpers.Preapply.block (fun (chain_store, block) q p -> - let timestamp = - match q#timestamp with - | None -> Time.System.to_protocol (Time.System.now ()) - | Some time -> time - in - let protocol_data = - Data_encoding.Binary.to_bytes_exn - Next_proto.block_header_data_encoding - p.protocol_data - in - let operations = - List.map - (fun operations -> - let operations = - List.map - (fun op -> - let proto = - Data_encoding.Binary.to_bytes_exn - Next_proto - .operation_data_encoding_with_legacy_attestation_name - op.Next_proto.protocol_data - in - (op, {Operation.shell = op.shell; proto})) - operations - in - let operations = - if q#sort_operations then - List.sort - (fun (op, ops) (op', ops') -> - let oph, oph' = (Operation.hash ops, Operation.hash ops') in - Next_proto.compare_operations (oph, op) (oph', op')) - operations - else operations - in - List.map snd operations) - p.operations - in - let* bv = - try return (Block_validator.running_worker ()) - with _ -> failwith "Block validator is not running" - in - Block_validator.preapply - bv - chain_store - ~predecessor:block - ~timestamp - ~protocol_data - operations) ; register0 S.Helpers.Preapply.operations (fun (chain_store, block) params ops -> @@ -839,7 +858,7 @@ let get_protocol hash = | None -> raise Not_found | Some protocol -> protocol -let get_directory chain_store block = +let get_directory chain_store block ~with_validator = let open Lwt_syntax in let* o = Store.Chain.get_rpc_directory chain_store block in match o with @@ -849,13 +868,20 @@ let get_directory chain_store block = Store.Block.protocol_hash_exn chain_store block in let (module Next_proto) = get_protocol next_protocol_hash in - let build_fake_rpc_directory () = - build_raw_rpc_directory - (module Block_services.Fake_protocol) - (module Next_proto) - in if Store.Block.is_genesis chain_store (Store.Block.hash block) then - Lwt.return (build_fake_rpc_directory ()) + let dir = + build_raw_rpc_directory_without_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 else let* (module Proto) = let* o = Store.Block.read_predecessor_opt chain_store block in @@ -888,7 +914,21 @@ let get_directory chain_store block = | Some dir -> Lwt.return dir | None -> let dir = - build_raw_rpc_directory (module Proto) (module Next_proto) + let dir_without_validator = + build_raw_rpc_directory_without_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 in let* () = Store.Chain.set_rpc_directory @@ -899,12 +939,22 @@ let get_directory chain_store block = in Lwt.return dir) -let build_rpc_directory chain_store block = +let build_rpc_directory_with_validator chain_store block = + let open Lwt_syntax in + let* o = Store.Chain.block_of_identifier_opt chain_store block in + match o with + | None -> Lwt.fail Not_found + | Some b -> + let* dir = get_directory ~with_validator:true chain_store b in + Lwt.return + (Tezos_rpc.Directory.map (fun _ -> Lwt.return (chain_store, b)) dir) + +let build_rpc_directory_without_validator chain_store block = let open Lwt_syntax in let* o = Store.Chain.block_of_identifier_opt chain_store block in match o with | None -> Lwt.fail Not_found | Some b -> - let* dir = get_directory chain_store b in + let* dir = get_directory ~with_validator:false chain_store b in Lwt.return (Tezos_rpc.Directory.map (fun _ -> Lwt.return (chain_store, b)) dir) diff --git a/src/lib_shell/block_directory.mli b/src/lib_shell/block_directory.mli index e9c3eb1f0553b6ae27cf37e81f99918b5ba9cd1c..e7b4b1ef376712a197315935aa54c251c37554f9 100644 --- a/src/lib_shell/block_directory.mli +++ b/src/lib_shell/block_directory.mli @@ -24,10 +24,22 @@ (* *) (*****************************************************************************) -val build_raw_rpc_directory : +val build_raw_rpc_directory_with_validator : (module Block_services.PROTO) -> (module Registered_protocol.T) -> (Store.chain_store * Store.Block.t) Tezos_rpc.Directory.directory -val build_rpc_directory : +(** [build_rpc_directory_with_validator chain_store block_services] + builds an [RPC_directory.t] that contains all RPCs in + [block_services], especially the one that depends on the + validator. + + @raises Error when validator is not running. *) +val build_rpc_directory_with_validator : + Store.chain_store -> Block_services.block -> 'a Tezos_rpc.Directory.t Lwt.t + +(** Same as [build_rpc_directory_with_validator] except that the + returned [RPC_directory.t] contains only RPCs that do **not** + depend on the validator. *) +val build_rpc_directory_without_validator : Store.chain_store -> Block_services.block -> 'a Tezos_rpc.Directory.t Lwt.t diff --git a/src/lib_shell/chain_directory.ml b/src/lib_shell/chain_directory.ml index 1d1748dbe7197bfba42fa98e923200cf888ad992..1f3e098952de753e39c284a4d1e169e41edb7642 100644 --- a/src/lib_shell/chain_directory.ml +++ b/src/lib_shell/chain_directory.ml @@ -116,18 +116,31 @@ let list_blocks chain_store ?(length = 1) ?min_date blocks = in return (List.rev blocks) -let rpc_directory validator = +let register0 dir s f = + dir := + Tezos_rpc.Directory.register + !dir + (Tezos_rpc.Service.subst0 s) + (fun chain p q -> f chain p q) + +let rpc_directory_with_validator dir validator = + let open Lwt_result_syntax in + register0 dir S.is_bootstrapped (fun chain_store () () -> + match Validator.get validator (Store.Chain.chain_id chain_store) with + | Error _ -> Lwt.fail Not_found + | Ok chain_validator -> + return + Chain_validator. + (is_bootstrapped chain_validator, sync_status chain_validator)) ; + register0 dir S.force_bootstrapped (fun chain_store () b -> + match Validator.get validator (Store.Chain.chain_id chain_store) with + | Error _ -> Lwt.fail Not_found + | Ok chain_validator -> + let*! v = Chain_validator.force_bootstrapped chain_validator b in + return v) + +let rpc_directory_without_validator dir = let open Lwt_result_syntax in - let dir : Store.chain_store Tezos_rpc.Directory.t ref = - ref Tezos_rpc.Directory.empty - in - let register0 s f = - dir := - Tezos_rpc.Directory.register - !dir - (Tezos_rpc.Service.subst0 s) - (fun chain p q -> f chain p q) - in let register1 s f = dir := Tezos_rpc.Directory.register @@ -135,17 +148,9 @@ let rpc_directory validator = (Tezos_rpc.Service.subst1 s) (fun (chain, a) p q -> f chain a p q) in - let register_dynamic_directory2 ?descr s f = - dir := - Tezos_rpc.Directory.register_dynamic_directory - !dir - ?descr - (Tezos_rpc.Path.subst1 s) - (fun (chain, a) -> f chain a) - in - register0 S.chain_id (fun chain_store () () -> + register0 dir S.chain_id (fun chain_store () () -> return (Store.Chain.chain_id chain_store)) ; - register0 S.checkpoint (fun chain_store () () -> + register0 dir S.checkpoint (fun chain_store () () -> let*! checkpoint_hash, _ = Store.Chain.checkpoint chain_store in let* block = Store.Block.read_block chain_store checkpoint_hash in let checkpoint_header = Store.Block.header block in @@ -153,36 +158,20 @@ let rpc_directory validator = let*! _, caboose_level = Store.Chain.caboose chain_store in let history_mode = Store.Chain.history_mode chain_store in return (checkpoint_header, savepoint_level, caboose_level, history_mode)) ; - register0 S.Levels.checkpoint (fun chain_store () () -> + register0 dir S.Levels.checkpoint (fun chain_store () () -> let*! v = Store.Chain.checkpoint chain_store in return v) ; - register0 S.Levels.savepoint (fun chain_store () () -> + register0 dir S.Levels.savepoint (fun chain_store () () -> let*! v = Store.Chain.savepoint chain_store in return v) ; - register0 S.Levels.caboose (fun chain_store () () -> + register0 dir S.Levels.caboose (fun chain_store () () -> let*! v = Store.Chain.caboose chain_store in return v) ; - register0 S.is_bootstrapped (fun chain_store () () -> - match Validator.get validator (Store.Chain.chain_id chain_store) with - | Error _ -> Lwt.fail Not_found - | Ok chain_validator -> - return - Chain_validator. - (is_bootstrapped chain_validator, sync_status chain_validator)) ; - register0 S.force_bootstrapped (fun chain_store () b -> - match Validator.get validator (Store.Chain.chain_id chain_store) with - | Error _ -> Lwt.fail Not_found - | Ok chain_validator -> - let*! v = Chain_validator.force_bootstrapped chain_validator b in - return v) ; (* blocks *) - register0 S.Blocks.list (fun chain q () -> + register0 dir S.Blocks.list (fun chain q () -> list_blocks chain ?length:q#length ?min_date:q#min_date q#heads) ; - register_dynamic_directory2 - Block_services.path - Block_directory.build_rpc_directory ; (* invalid_blocks *) - register0 S.Invalid_blocks.list (fun chain_store () () -> + register0 dir S.Invalid_blocks.list (fun chain_store () () -> let convert (hash, {Store_types.level; errors}) = {hash; level; errors} in let*! invalid_blocks_map = Store.Block.read_invalid_blocks chain_store in let blocks = Block_hash.Map.bindings invalid_blocks_map in @@ -193,7 +182,45 @@ let rpc_directory validator = | None -> Lwt.fail Not_found | Some {level; errors} -> return {hash; level; errors}) ; register1 S.Invalid_blocks.delete (fun chain_store hash () () -> - Store.Block.unmark_invalid chain_store hash) ; + Store.Block.unmark_invalid chain_store hash) + +let rpc_directory validator = + let dir : Store.chain_store Tezos_rpc.Directory.t ref = + ref Tezos_rpc.Directory.empty + in + rpc_directory_without_validator dir ; + rpc_directory_with_validator dir validator ; + let register_dynamic_directory2 ?descr s f = + dir := + Tezos_rpc.Directory.register_dynamic_directory + !dir + ?descr + (Tezos_rpc.Path.subst1 s) + (fun (chain, a) -> f chain a) + in + (* blocks *) + register_dynamic_directory2 + Block_services.path + Block_directory.build_rpc_directory_with_validator ; + !dir + +let rpc_directory_without_validator () = + let dir : Store.chain_store Tezos_rpc.Directory.t ref = + ref Tezos_rpc.Directory.empty + in + rpc_directory_without_validator dir ; + let register_dynamic_directory2 ?descr s f = + dir := + Tezos_rpc.Directory.register_dynamic_directory + !dir + ?descr + (Tezos_rpc.Path.subst1 s) + (fun (chain, a) -> f chain a) + in + (* blocks *) + register_dynamic_directory2 + Block_services.path + Block_directory.build_rpc_directory_without_validator ; !dir let build_rpc_directory validator = diff --git a/src/lib_shell/chain_directory.mli b/src/lib_shell/chain_directory.mli index 4e15fa460529dab7a3ab7feb2705779cd53d2adf..e80b5b51d72193961d53c951391b9133071aae8e 100644 --- a/src/lib_shell/chain_directory.mli +++ b/src/lib_shell/chain_directory.mli @@ -34,6 +34,7 @@ val get_chain_store_exn : val get_checkpoint : Store.t -> Chain_services.chain -> Block_hash.t Lwt.t -val rpc_directory : Validator.t -> Store.chain_store Tezos_rpc.Directory.t +val rpc_directory_without_validator : + unit -> Store.chain_store Tezos_rpc.Directory.t val build_rpc_directory : Validator.t -> unit Tezos_rpc.Directory.t