From 19489269f787ab70952a4e0514225c1e95e3e7f1 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 25 Jul 2023 17:53:17 +0200 Subject: [PATCH 01/12] SCORU/Node: move RPC helpers outside of proto directories --- .../rpc_directory_helpers.ml} | 4 +- .../rpc_directory_helpers.mli} | 4 +- .../RPC_directory_helpers.mli | 64 ------------------ .../lib_sc_rollup_node/RPC_directory.ml | 2 +- .../RPC_directory_helpers.ml | 66 ------------------- .../RPC_directory_helpers.mli | 64 ------------------ .../lib_sc_rollup_node/RPC_directory.ml | 2 +- .../RPC_directory_helpers.ml | 66 ------------------- .../lib_sc_rollup_node/RPC_directory.ml | 2 +- 9 files changed, 9 insertions(+), 265 deletions(-) rename src/{proto_016_PtMumbai/lib_sc_rollup_layer2/RPC_directory_helpers.ml => lib_smart_rollup_node/rpc_directory_helpers.ml} (97%) rename src/{proto_alpha/lib_sc_rollup_layer2/RPC_directory_helpers.mli => lib_smart_rollup_node/rpc_directory_helpers.mli} (98%) delete mode 100644 src/proto_016_PtMumbai/lib_sc_rollup_layer2/RPC_directory_helpers.mli delete mode 100644 src/proto_017_PtNairob/lib_sc_rollup_layer2/RPC_directory_helpers.ml delete mode 100644 src/proto_017_PtNairob/lib_sc_rollup_layer2/RPC_directory_helpers.mli delete mode 100644 src/proto_alpha/lib_sc_rollup_layer2/RPC_directory_helpers.ml diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_layer2/RPC_directory_helpers.ml b/src/lib_smart_rollup_node/rpc_directory_helpers.ml similarity index 97% rename from src/proto_016_PtMumbai/lib_sc_rollup_layer2/RPC_directory_helpers.ml rename to src/lib_smart_rollup_node/rpc_directory_helpers.ml index 6b0c8ec4337c..69704a714a5a 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_layer2/RPC_directory_helpers.ml +++ b/src/lib_smart_rollup_node/rpc_directory_helpers.ml @@ -27,7 +27,9 @@ against a subcontext of the Node_context *) module type PARAM = sig - include Sc_rollup_services.PREFIX + type prefix + + val prefix : (unit, prefix) Tezos_rpc.Path.t type context diff --git a/src/proto_alpha/lib_sc_rollup_layer2/RPC_directory_helpers.mli b/src/lib_smart_rollup_node/rpc_directory_helpers.mli similarity index 98% rename from src/proto_alpha/lib_sc_rollup_layer2/RPC_directory_helpers.mli rename to src/lib_smart_rollup_node/rpc_directory_helpers.mli index c98568773bf7..1d511c6cb068 100644 --- a/src/proto_alpha/lib_sc_rollup_layer2/RPC_directory_helpers.mli +++ b/src/lib_smart_rollup_node/rpc_directory_helpers.mli @@ -29,7 +29,9 @@ open Tezos_rpc (** This module defines subcontext type of the subdirectory and the way to project it from Node_context and a path prefix. *) module type PARAM = sig - include Sc_rollup_services.PREFIX + type prefix + + val prefix : (unit, prefix) Tezos_rpc.Path.t type context diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_layer2/RPC_directory_helpers.mli b/src/proto_016_PtMumbai/lib_sc_rollup_layer2/RPC_directory_helpers.mli deleted file mode 100644 index c98568773bf7..000000000000 --- a/src/proto_016_PtMumbai/lib_sc_rollup_layer2/RPC_directory_helpers.mli +++ /dev/null @@ -1,64 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 Nomadic Labs, *) -(* Copyright (c) 2022-2023 TriliTech *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -open Tezos_rpc - -(** This module defines subcontext type of the subdirectory and - the way to project it from Node_context and a path prefix. *) -module type PARAM = sig - include Sc_rollup_services.PREFIX - - type context - - type subcontext - - val context_of_prefix : context -> prefix -> subcontext tzresult Lwt.t -end - -(** This module is a helper to register your endpoints and - build a resulting subdirectory eventually. *) -module Make_directory (S : PARAM) : sig - (** Register an endpoint with no parameters in the path. *) - val register0 : - ([< Resto.meth], 'prefix, 'prefix, 'query, 'input, 'output) Service.t -> - (S.subcontext -> 'query -> 'input -> 'output tzresult Lwt.t) -> - unit - - (** Register an endpoint with a single parameter in the path. *) - val register1 : - ( [< Resto.meth], - 'prefix, - 'prefix * 'param1, - 'query, - 'input, - 'output ) - Service.t -> - (S.subcontext -> 'param1 -> 'query -> 'input -> 'output tzresult Lwt.t) -> - unit - - (** Build directory with registered endpoints with respect to Node_context. *) - val build_directory : S.context -> unit Tezos_rpc.Directory.t -end diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_directory.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_directory.ml index 67b128d608a7..757611ac0d02 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_directory.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_directory.ml @@ -25,7 +25,7 @@ (* *) (*****************************************************************************) -open RPC_directory_helpers +open Rpc_directory_helpers open Protocol let get_head_hash_opt node_ctxt = diff --git a/src/proto_017_PtNairob/lib_sc_rollup_layer2/RPC_directory_helpers.ml b/src/proto_017_PtNairob/lib_sc_rollup_layer2/RPC_directory_helpers.ml deleted file mode 100644 index 6b0c8ec4337c..000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_layer2/RPC_directory_helpers.ml +++ /dev/null @@ -1,66 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -(* Conveniences to construct RPC directory - against a subcontext of the Node_context *) - -module type PARAM = sig - include Sc_rollup_services.PREFIX - - type context - - type subcontext - - val context_of_prefix : context -> prefix -> subcontext tzresult Lwt.t -end - -module Make_directory (S : PARAM) = struct - open S - - let directory : subcontext tzresult Tezos_rpc.Directory.t ref = - ref Tezos_rpc.Directory.empty - - let register service f = - directory := Tezos_rpc.Directory.register !directory service f - - let register0 service f = - let open Lwt_result_syntax in - register (Tezos_rpc.Service.subst0 service) @@ fun ctxt query input -> - let*? ctxt in - f ctxt query input - - let register1 service f = - let open Lwt_result_syntax in - register (Tezos_rpc.Service.subst1 service) - @@ fun (ctxt, arg) query input -> - let*? ctxt in - f ctxt arg query input - - let build_directory node_ctxt = - !directory - |> Tezos_rpc.Directory.map (fun prefix -> - context_of_prefix node_ctxt prefix) - |> Tezos_rpc.Directory.prefix prefix -end diff --git a/src/proto_017_PtNairob/lib_sc_rollup_layer2/RPC_directory_helpers.mli b/src/proto_017_PtNairob/lib_sc_rollup_layer2/RPC_directory_helpers.mli deleted file mode 100644 index c98568773bf7..000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_layer2/RPC_directory_helpers.mli +++ /dev/null @@ -1,64 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 Nomadic Labs, *) -(* Copyright (c) 2022-2023 TriliTech *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -open Tezos_rpc - -(** This module defines subcontext type of the subdirectory and - the way to project it from Node_context and a path prefix. *) -module type PARAM = sig - include Sc_rollup_services.PREFIX - - type context - - type subcontext - - val context_of_prefix : context -> prefix -> subcontext tzresult Lwt.t -end - -(** This module is a helper to register your endpoints and - build a resulting subdirectory eventually. *) -module Make_directory (S : PARAM) : sig - (** Register an endpoint with no parameters in the path. *) - val register0 : - ([< Resto.meth], 'prefix, 'prefix, 'query, 'input, 'output) Service.t -> - (S.subcontext -> 'query -> 'input -> 'output tzresult Lwt.t) -> - unit - - (** Register an endpoint with a single parameter in the path. *) - val register1 : - ( [< Resto.meth], - 'prefix, - 'prefix * 'param1, - 'query, - 'input, - 'output ) - Service.t -> - (S.subcontext -> 'param1 -> 'query -> 'input -> 'output tzresult Lwt.t) -> - unit - - (** Build directory with registered endpoints with respect to Node_context. *) - val build_directory : S.context -> unit Tezos_rpc.Directory.t -end diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_directory.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_directory.ml index 67b128d608a7..757611ac0d02 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_directory.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_directory.ml @@ -25,7 +25,7 @@ (* *) (*****************************************************************************) -open RPC_directory_helpers +open Rpc_directory_helpers open Protocol let get_head_hash_opt node_ctxt = diff --git a/src/proto_alpha/lib_sc_rollup_layer2/RPC_directory_helpers.ml b/src/proto_alpha/lib_sc_rollup_layer2/RPC_directory_helpers.ml deleted file mode 100644 index 6b0c8ec4337c..000000000000 --- a/src/proto_alpha/lib_sc_rollup_layer2/RPC_directory_helpers.ml +++ /dev/null @@ -1,66 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -(* Conveniences to construct RPC directory - against a subcontext of the Node_context *) - -module type PARAM = sig - include Sc_rollup_services.PREFIX - - type context - - type subcontext - - val context_of_prefix : context -> prefix -> subcontext tzresult Lwt.t -end - -module Make_directory (S : PARAM) = struct - open S - - let directory : subcontext tzresult Tezos_rpc.Directory.t ref = - ref Tezos_rpc.Directory.empty - - let register service f = - directory := Tezos_rpc.Directory.register !directory service f - - let register0 service f = - let open Lwt_result_syntax in - register (Tezos_rpc.Service.subst0 service) @@ fun ctxt query input -> - let*? ctxt in - f ctxt query input - - let register1 service f = - let open Lwt_result_syntax in - register (Tezos_rpc.Service.subst1 service) - @@ fun (ctxt, arg) query input -> - let*? ctxt in - f ctxt arg query input - - let build_directory node_ctxt = - !directory - |> Tezos_rpc.Directory.map (fun prefix -> - context_of_prefix node_ctxt prefix) - |> Tezos_rpc.Directory.prefix prefix -end diff --git a/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml b/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml index ed7c2dc254c0..09bd8037594c 100644 --- a/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml +++ b/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml @@ -25,7 +25,7 @@ (* *) (*****************************************************************************) -open RPC_directory_helpers +open Rpc_directory_helpers open Protocol let get_head_hash_opt node_ctxt = -- GitLab From 07463d32e8efd00023ae6311032d2bb5c73637bc Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 20 Jun 2023 10:36:44 +0200 Subject: [PATCH 02/12] SCORU/Node/RPC: allow to build sub-directories without set prefix --- .../rpc_directory_helpers.ml | 22 ++++++++++---- .../rpc_directory_helpers.mli | 30 ++++++++++++++++--- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/lib_smart_rollup_node/rpc_directory_helpers.ml b/src/lib_smart_rollup_node/rpc_directory_helpers.ml index 69704a714a5a..8c0298d2a564 100644 --- a/src/lib_smart_rollup_node/rpc_directory_helpers.ml +++ b/src/lib_smart_rollup_node/rpc_directory_helpers.ml @@ -29,8 +29,6 @@ module type PARAM = sig type prefix - val prefix : (unit, prefix) Tezos_rpc.Path.t - type context type subcontext @@ -38,7 +36,13 @@ module type PARAM = sig val context_of_prefix : context -> prefix -> subcontext tzresult Lwt.t end -module Make_directory (S : PARAM) = struct +module type PARAM_PREFIX = sig + include PARAM + + val prefix : (unit, prefix) Tezos_rpc.Path.t +end + +module Make_sub_directory (S : PARAM) = struct open S let directory : subcontext tzresult Tezos_rpc.Directory.t ref = @@ -60,9 +64,17 @@ module Make_directory (S : PARAM) = struct let*? ctxt in f ctxt arg query input - let build_directory node_ctxt = + let build_sub_directory node_ctxt = !directory |> Tezos_rpc.Directory.map (fun prefix -> context_of_prefix node_ctxt prefix) - |> Tezos_rpc.Directory.prefix prefix +end + +module Make_directory (S : PARAM_PREFIX) = struct + include Make_sub_directory (S) + + let of_subdirectory = Tezos_rpc.Directory.prefix S.prefix + + let build_directory node_ctxt = + build_sub_directory node_ctxt |> Tezos_rpc.Directory.prefix S.prefix end diff --git a/src/lib_smart_rollup_node/rpc_directory_helpers.mli b/src/lib_smart_rollup_node/rpc_directory_helpers.mli index 1d511c6cb068..473eff22ffaf 100644 --- a/src/lib_smart_rollup_node/rpc_directory_helpers.mli +++ b/src/lib_smart_rollup_node/rpc_directory_helpers.mli @@ -31,8 +31,6 @@ open Tezos_rpc module type PARAM = sig type prefix - val prefix : (unit, prefix) Tezos_rpc.Path.t - type context type subcontext @@ -40,9 +38,17 @@ module type PARAM = sig val context_of_prefix : context -> prefix -> subcontext tzresult Lwt.t end +(** Parameter signature to use with {!Make_directory}, where the prefix is + given. *) +module type PARAM_PREFIX = sig + include PARAM + + val prefix : (unit, prefix) Tezos_rpc.Path.t +end + (** This module is a helper to register your endpoints and build a resulting subdirectory eventually. *) -module Make_directory (S : PARAM) : sig +module Make_sub_directory (S : PARAM) : sig (** Register an endpoint with no parameters in the path. *) val register0 : ([< Resto.meth], 'prefix, 'prefix, 'query, 'input, 'output) Service.t -> @@ -61,6 +67,22 @@ module Make_directory (S : PARAM) : sig (S.subcontext -> 'param1 -> 'query -> 'input -> 'output tzresult Lwt.t) -> unit - (** Build directory with registered endpoints with respect to Node_context. *) + (** Build sub-directory with registered endpoints with respect to + Node_context. *) + val build_sub_directory : S.context -> S.prefix Tezos_rpc.Directory.t +end + +(** This module is a helper to register your endpoints and + build a resulting top level directory eventually. *) +module Make_directory (S : PARAM_PREFIX) : sig + include module type of Make_sub_directory (S) + + (** Build a top-level directory from a sub-directory by prefixing it with + {!val:prefix}. *) + val of_subdirectory : + S.prefix Tezos_rpc.Directory.t -> unit Tezos_rpc.Directory.t + + (** Build top-level directory with registered endpoints with respect to + Node_context. *) val build_directory : S.context -> unit Tezos_rpc.Directory.t end -- GitLab From 5d7d2ace21ad1daa20aa13e4c47b88ea398e2bc5 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 20 Jun 2023 10:57:06 +0200 Subject: [PATCH 03/12] SCORU/Node/RPC: move proof helper RPC under /global/block/{b}/helpers --- src/proto_alpha/lib_sc_rollup_client/RPC.ml | 4 +- .../sc_rollup_services.ml | 39 +++++++------- .../lib_sc_rollup_node/RPC_directory.ml | 54 +++++++++++-------- .../lib_sc_rollup_node/RPC_directory.mli | 10 +++- 4 files changed, 64 insertions(+), 43 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_client/RPC.ml b/src/proto_alpha/lib_sc_rollup_client/RPC.ml index 98ad7f965b46..8184ab94335c 100644 --- a/src/proto_alpha/lib_sc_rollup_client/RPC.ml +++ b/src/proto_alpha/lib_sc_rollup_client/RPC.ml @@ -30,8 +30,8 @@ let get_state_value_command cctxt block key = Sc_rollup_services.Global.Block.(make_call1 state_value) cctxt block {key} () let get_outbox_proof cctxt serialized_output = - Sc_rollup_services.Global.Helpers.(make_call outbox_proof) + Sc_rollup_services.Global.Block.Helpers.(make_call outbox_proof) cctxt - () + ((), `Head) serialized_output () diff --git a/src/proto_alpha/lib_sc_rollup_layer2/sc_rollup_services.ml b/src/proto_alpha/lib_sc_rollup_layer2/sc_rollup_services.ml index b6539529a288..9603f6737fac 100644 --- a/src/proto_alpha/lib_sc_rollup_layer2/sc_rollup_services.ml +++ b/src/proto_alpha/lib_sc_rollup_layer2/sc_rollup_services.ml @@ -553,25 +553,6 @@ module Global = struct ~output:(Data_encoding.option Encodings.commitment_with_hash) (path / "last_stored_commitment") - module Helpers = struct - include Make_services (struct - type prefix = unit - - let prefix = open_root / "helpers" - end) - - let outbox_proof = - Tezos_rpc.Service.get_service - ~description:"Generate serialized output proof for some outbox message" - ~query:Query.outbox_proof_query - ~output: - Data_encoding.( - obj2 - (req "commitment" Sc_rollup.Commitment.Hash.encoding) - (req "proof" Encodings.hex_string)) - (path / "proofs" / "outbox") - end - module Block = struct include Make_services (struct type prefix = unit * Arg.block_id @@ -750,6 +731,26 @@ module Global = struct ~output:Data_encoding.(list Sc_rollup.output_encoding) (path / "messages") end + + module Helpers = struct + include Make_services (struct + type nonrec prefix = prefix + + let prefix = prefix / "helpers" + end) + + let outbox_proof = + Tezos_rpc.Service.get_service + ~description: + "Generate serialized output proof for some outbox message" + ~query:Query.outbox_proof_query + ~output: + Data_encoding.( + obj2 + (req "commitment" Sc_rollup.Commitment.Hash.encoding) + (req "proof" Encodings.hex_string)) + (path / "proofs" / "outbox") + end end end diff --git a/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml b/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml index 09bd8037594c..4efd44b0fdfc 100644 --- a/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml +++ b/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml @@ -59,20 +59,6 @@ module Global_directory = Make_directory (struct let context_of_prefix node_ctxt () = return (Node_context.readonly node_ctxt) end) -module Proof_helpers_directory = Make_directory (struct - include Sc_rollup_services.Global.Helpers - - (* The context needs to be accessed with write permissions because we need to - commit on disk to generate the proofs. *) - type context = Node_context.rw - - (* The context needs to be accessed with write permissions because we need to - commit on disk to generate the proofs. *) - type subcontext = Node_context.rw - - let context_of_prefix node_ctxt () = return node_ctxt -end) - module Local_directory = Make_directory (struct include Sc_rollup_services.Local @@ -109,6 +95,23 @@ module Outbox_directory = Make_directory (struct (Node_context.readonly node_ctxt, block, level) end) +module Block_helpers_directory = Make_directory (struct + include Sc_rollup_services.Global.Block.Helpers + + (* The context needs to be accessed with write permissions because we need to + commit on disk to generate the proofs. *) + type context = Node_context.rw + + (* The context needs to be accessed with write permissions because we need to + commit on disk to generate the proofs. *) + type subcontext = Node_context.rw * Block_hash.t + + let context_of_prefix node_ctxt (((), block) : prefix) = + let open Lwt_result_syntax in + let+ block = Block_directory_helpers.block_of_prefix node_ctxt block in + (node_ctxt, block) +end) + module Common = struct let () = Block_directory.register0 Sc_rollup_services.Global.Block.block @@ -348,9 +351,9 @@ let () = return outbox let () = - Proof_helpers_directory.register0 - Sc_rollup_services.Global.Helpers.outbox_proof - @@ fun node_ctxt output () -> + Block_helpers_directory.register0 + Sc_rollup_services.Global.Block.Helpers.outbox_proof + @@ fun (node_ctxt, _block_hash) output () -> let open Lwt_result_syntax in let+ commitment, proof = Outbox.proof_of_output node_ctxt output in (Sc_rollup_proto_types.Commitment_hash.of_octez commitment, proof) @@ -521,16 +524,25 @@ let () = return status -let directory (node_ctxt : _ Node_context.t) = +let block_directory (node_ctxt : _ Node_context.t) = let module PVM = (val Pvm_rpc.of_kind node_ctxt.kind) in List.fold_left (fun dir f -> Tezos_rpc.Directory.merge dir (f node_ctxt)) Tezos_rpc.Directory.empty [ - Global_directory.build_directory; - Local_directory.build_directory; Block_directory.build_directory; - Proof_helpers_directory.build_directory; + Block_helpers_directory.build_directory; Outbox_directory.build_directory; PVM.build_directory; ] + +let top_directory (node_ctxt : _ Node_context.t) = + List.fold_left + (fun dir f -> Tezos_rpc.Directory.merge dir (f node_ctxt)) + Tezos_rpc.Directory.empty + [Global_directory.build_directory; Local_directory.build_directory] + +let directory (node_ctxt : _ Node_context.t) = + Tezos_rpc.Directory.merge + (top_directory node_ctxt) + (block_directory node_ctxt) diff --git a/src/proto_alpha/lib_sc_rollup_node/RPC_directory.mli b/src/proto_alpha/lib_sc_rollup_node/RPC_directory.mli index 206e38547b0c..ee6d9b0eb44d 100644 --- a/src/proto_alpha/lib_sc_rollup_node/RPC_directory.mli +++ b/src/proto_alpha/lib_sc_rollup_node/RPC_directory.mli @@ -23,5 +23,13 @@ (* *) (*****************************************************************************) -(** The RPC directory for this rollup node. *) +(** The RPC directory, specific to blocks, for this rollup node. *) +val block_directory : Node_context.rw -> unit Tezos_rpc.Directory.t + +(** The RPC top level directory (without the block directory) for this rollup + node. *) +val top_directory : Node_context.rw -> unit Tezos_rpc.Directory.t + +(** The full RPC directory for this rollup node, merging the top level directory + and the block directory. *) val directory : Node_context.rw -> unit Tezos_rpc.Directory.t -- GitLab From f8044d67ba8c789ac0f558a37a6195d6706f7cfc Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 20 Jun 2023 11:49:03 +0200 Subject: [PATCH 04/12] SCORU/Node: move L2 messages outside of proto directories --- .../l2_message.ml | 0 .../l2_message.mli | 0 .../lib_sc_rollup_layer2/l2_message.ml | 72 ------------------- .../lib_sc_rollup_layer2/l2_message.mli | 48 ------------- .../lib_sc_rollup_layer2/l2_message.ml | 72 ------------------- .../lib_sc_rollup_layer2/l2_message.mli | 48 ------------- 6 files changed, 240 deletions(-) rename src/{proto_016_PtMumbai/lib_sc_rollup_layer2 => lib_smart_rollup}/l2_message.ml (100%) rename src/{proto_016_PtMumbai/lib_sc_rollup_layer2 => lib_smart_rollup}/l2_message.mli (100%) delete mode 100644 src/proto_017_PtNairob/lib_sc_rollup_layer2/l2_message.ml delete mode 100644 src/proto_017_PtNairob/lib_sc_rollup_layer2/l2_message.mli delete mode 100644 src/proto_alpha/lib_sc_rollup_layer2/l2_message.ml delete mode 100644 src/proto_alpha/lib_sc_rollup_layer2/l2_message.mli diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_layer2/l2_message.ml b/src/lib_smart_rollup/l2_message.ml similarity index 100% rename from src/proto_016_PtMumbai/lib_sc_rollup_layer2/l2_message.ml rename to src/lib_smart_rollup/l2_message.ml diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_layer2/l2_message.mli b/src/lib_smart_rollup/l2_message.mli similarity index 100% rename from src/proto_016_PtMumbai/lib_sc_rollup_layer2/l2_message.mli rename to src/lib_smart_rollup/l2_message.mli diff --git a/src/proto_017_PtNairob/lib_sc_rollup_layer2/l2_message.ml b/src/proto_017_PtNairob/lib_sc_rollup_layer2/l2_message.ml deleted file mode 100644 index cdf5f672edad..000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_layer2/l2_message.ml +++ /dev/null @@ -1,72 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -type t = { - counter : Z.t; - (** Each message is given a unique counter to allow for the batcher to - receive multiple identical messages. *) - content : string; (** The actual content of the message. *) -} - -let content_encoding = - let open Data_encoding in - def "sc_l2_message" ~description:"A hex encoded smart rollup message" - @@ string' Hex - -let encoding = - let open Data_encoding in - conv - (fun {counter; content} -> (counter, content)) - (fun (counter, content) -> {counter; content}) - @@ obj2 (req "counter" z) (req "content" content_encoding) - -let make = - let counter = ref Z.zero in - fun content -> - let m = {content; counter = !counter} in - counter := Z.succ !counter ; - m - -let content m = m.content - -module Hash = - Tezos_crypto.Blake2B.Make - (Tezos_crypto.Base58) - (struct - let name = "sc_rollup_l2_message" - - let title = "A smart rollup layer 2 message" - - let b58check_prefix = "\003\250\179\247\196" (* scmsg(55) *) - - let size = None - end) - -let () = - Tezos_crypto.Base58.check_encoded_prefix Hash.b58check_encoding "scmsg" 55 - -type hash = Hash.t - -let hash t = Hash.hash_bytes [Data_encoding.Binary.to_bytes_exn encoding t] diff --git a/src/proto_017_PtNairob/lib_sc_rollup_layer2/l2_message.mli b/src/proto_017_PtNairob/lib_sc_rollup_layer2/l2_message.mli deleted file mode 100644 index 5f8f8ee52a90..000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_layer2/l2_message.mli +++ /dev/null @@ -1,48 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -(** Type of L2 messages. *) -type t - -(** [make message] constructs a message with content [message]. *) -val make : string -> t - -(** [content message] returns the string content of [message], i.e. - [content (make s) = s]. *) -val content : t -> string - -(** Hash with b58check encoding scmsg(55), for hashes of L2 messages. *) -module Hash : Tezos_crypto.Intfs.HASH - -(** Alias for message hash *) -type hash = Hash.t - -(** {2 Serialization} *) - -val content_encoding : string Data_encoding.t - -val encoding : t Data_encoding.t - -val hash : t -> Hash.t diff --git a/src/proto_alpha/lib_sc_rollup_layer2/l2_message.ml b/src/proto_alpha/lib_sc_rollup_layer2/l2_message.ml deleted file mode 100644 index cdf5f672edad..000000000000 --- a/src/proto_alpha/lib_sc_rollup_layer2/l2_message.ml +++ /dev/null @@ -1,72 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -type t = { - counter : Z.t; - (** Each message is given a unique counter to allow for the batcher to - receive multiple identical messages. *) - content : string; (** The actual content of the message. *) -} - -let content_encoding = - let open Data_encoding in - def "sc_l2_message" ~description:"A hex encoded smart rollup message" - @@ string' Hex - -let encoding = - let open Data_encoding in - conv - (fun {counter; content} -> (counter, content)) - (fun (counter, content) -> {counter; content}) - @@ obj2 (req "counter" z) (req "content" content_encoding) - -let make = - let counter = ref Z.zero in - fun content -> - let m = {content; counter = !counter} in - counter := Z.succ !counter ; - m - -let content m = m.content - -module Hash = - Tezos_crypto.Blake2B.Make - (Tezos_crypto.Base58) - (struct - let name = "sc_rollup_l2_message" - - let title = "A smart rollup layer 2 message" - - let b58check_prefix = "\003\250\179\247\196" (* scmsg(55) *) - - let size = None - end) - -let () = - Tezos_crypto.Base58.check_encoded_prefix Hash.b58check_encoding "scmsg" 55 - -type hash = Hash.t - -let hash t = Hash.hash_bytes [Data_encoding.Binary.to_bytes_exn encoding t] diff --git a/src/proto_alpha/lib_sc_rollup_layer2/l2_message.mli b/src/proto_alpha/lib_sc_rollup_layer2/l2_message.mli deleted file mode 100644 index 5f8f8ee52a90..000000000000 --- a/src/proto_alpha/lib_sc_rollup_layer2/l2_message.mli +++ /dev/null @@ -1,48 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -(** Type of L2 messages. *) -type t - -(** [make message] constructs a message with content [message]. *) -val make : string -> t - -(** [content message] returns the string content of [message], i.e. - [content (make s) = s]. *) -val content : t -> string - -(** Hash with b58check encoding scmsg(55), for hashes of L2 messages. *) -module Hash : Tezos_crypto.Intfs.HASH - -(** Alias for message hash *) -type hash = Hash.t - -(** {2 Serialization} *) - -val content_encoding : string Data_encoding.t - -val encoding : t Data_encoding.t - -val hash : t -> Hash.t -- GitLab From 7e652c54106df641e81b3527667ad151a1b1755b Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 20 Jun 2023 11:59:56 +0200 Subject: [PATCH 05/12] SCORU/Node: split RPC services in proto and non proto specific parts --- src/lib_scoru_sequencer/rpc_server.ml | 7 +- src/lib_scoru_sequencer/sequencer_services.ml | 5 +- src/lib_smart_rollup/rollup_node_services.ml | 418 +++++++++++ src/proto_alpha/lib_sc_rollup_client/RPC.ml | 13 +- .../lib_sc_rollup_client/commands.ml | 2 +- .../sc_rollup_services.ml | 699 ++++-------------- .../lib_sc_rollup_node/RPC_directory.ml | 104 ++- .../lib_sc_rollup_node/RPC_directory.mli | 4 +- src/proto_alpha/lib_sc_rollup_node/pvm_rpc.ml | 6 +- .../lib_sc_rollup_node/wasm_2_0_0_rpc.ml | 16 +- 10 files changed, 653 insertions(+), 621 deletions(-) create mode 100644 src/lib_smart_rollup/rollup_node_services.ml diff --git a/src/lib_scoru_sequencer/rpc_server.ml b/src/lib_scoru_sequencer/rpc_server.ml index 95236ebbed62..1cc524bea8db 100644 --- a/src/lib_scoru_sequencer/rpc_server.ml +++ b/src/lib_scoru_sequencer/rpc_server.ml @@ -25,11 +25,12 @@ (*****************************************************************************) open Tezos_rpc_http_server -open RPC_directory_helpers +open Rpc_directory_helpers +open Octez_smart_rollup open Octez_smart_rollup_node module Local_directory = Make_directory (struct - include Sc_rollup_services.Local + include Rollup_node_services.Local type context = Node_context.rw @@ -49,7 +50,7 @@ let () = (Sequencer_services.Local.durable_state_subkeys Kind.Wasm_2_0_0) @@ fun () {key} () -> Seq_batcher.get_simulated_state_subkeys key ) ; - Local_directory.register0 Sc_rollup_services.Local.injection + Local_directory.register0 Rollup_node_services.Local.injection @@ fun _node_ctxt () messages -> Seq_batcher.register_messages messages let register (node_ctxt : _ Node_context.t) = diff --git a/src/lib_scoru_sequencer/sequencer_services.ml b/src/lib_scoru_sequencer/sequencer_services.ml index 765817c15237..c453223d313e 100644 --- a/src/lib_scoru_sequencer/sequencer_services.ml +++ b/src/lib_scoru_sequencer/sequencer_services.ml @@ -25,12 +25,13 @@ (*****************************************************************************) open Protocol.Alpha_context +open Octez_smart_rollup module Sc_services = Sc_rollup_services module Local = struct open Tezos_rpc.Path - include Sc_services.Make_services (struct + include Rollup_node_services.Make_services (struct type prefix = unit let prefix = open_root / "local" @@ -55,5 +56,5 @@ module Local = struct ~output:Data_encoding.(list string) (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "subkeys") - let injection = Sc_services.Local.injection + let injection = Rollup_node_services.Local.injection end diff --git a/src/lib_smart_rollup/rollup_node_services.ml b/src/lib_smart_rollup/rollup_node_services.ml new file mode 100644 index 000000000000..c0f154321ce3 --- /dev/null +++ b/src/lib_smart_rollup/rollup_node_services.ml @@ -0,0 +1,418 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** This file defines the services of the rollup node that do not depend on the + protocol. A top-level directory is built for them in the rollup node + library. + + Protocol specific services are for RPCs under [/global/block/] and are + defined in the protocol specific libraries in + [src/proto_*/lib_sc_rollup_layer2/sc_rollup_services.ml]. +*) + +(** We distinguish RPC endpoints served by the rollup node into [global] and + [local]. The difference between the two lies in whether the responses given + by different rollup nodes in the same state (see below for an exact + definition) must be the same (in the case of global endpoints) or can differ + (in the case of local endpoints). + + More formally, two rollup nodes are in the same quiescent state if they are + subscribed to the same rollup address, and have processed the same set of + heads from the layer1. We only consider quiescent states, that is those + where rollup nodes are not actively processing a head received from layer1. + + Examples of global endpoints are [current_tezos_head] and + [last_stored_commitment], as the responses returned by these endpoints is + expected to be consistent across rollup nodes in the same state. + + An example of local endpoint is [last_published_commitment], as two rollup + nodes in the same state may either publish or not publish a commitment, + according to whether its inbox level is below the inbox level of the last + cemented commitment at the time they tried to publish the commitment. See + below for a more detailed explanation. +*) + +type message_status = + | Unknown + | Pending_batch + | Pending_injection of L1_operation.t + | Injected of {op : L1_operation.t; oph : Operation_hash.t; op_index : int} + | Included of { + op : L1_operation.t; + oph : Operation_hash.t; + op_index : int; + l1_block : Block_hash.t; + l1_level : int32; + finalized : bool; + cemented : bool; + } + | Committed of { + op : L1_operation.t; + oph : Operation_hash.t; + op_index : int; + l1_block : Block_hash.t; + l1_level : int32; + finalized : bool; + cemented : bool; + commitment : Commitment.t; + commitment_hash : Commitment.Hash.t; + first_published_at_level : int32; + published_at_level : int32; + } + +module Encodings = struct + open Data_encoding + + let commitment_with_hash = + obj2 + (req "commitment" Commitment.encoding) + (req "hash" Commitment.Hash.encoding) + + let commitment_with_hash_and_level_infos = + obj4 + (req "commitment" Commitment.encoding) + (req "hash" Commitment.Hash.encoding) + (opt "first_published_at_level" int32) + (opt "published_at_level" int32) + + let queued_message = + obj2 + (req "hash" L2_message.Hash.encoding) + (req "message" L2_message.encoding) + + let batcher_queue = list queued_message + + let message_status = + union + [ + case + (Tag 0) + ~title:"unknown" + ~description:"The message is not known by the batcher." + (obj1 (req "status" (constant "unknown"))) + (function Unknown -> Some () | _ -> None) + (fun () -> Unknown); + case + (Tag 1) + ~title:"pending_batch" + ~description:"The message is in the batcher queue." + (obj1 (req "status" (constant "pending_batch"))) + (function Pending_batch -> Some () | _ -> None) + (fun () -> Pending_batch); + case + (Tag 2) + ~title:"pending_injection" + ~description:"The message is batched but not injected yet." + (obj2 + (req "status" (constant "pending_injection")) + (req "operation" L1_operation.encoding)) + (function Pending_injection op -> Some ((), op) | _ -> None) + (fun ((), op) -> Pending_injection op); + case + (Tag 3) + ~title:"injected" + ~description: + "The message is injected as part of an L1 operation but it is not \ + included in a block." + (obj3 + (req "status" (constant "injected")) + (req "operation" L1_operation.encoding) + (req + "layer1" + (obj2 + (req "operation_hash" Operation_hash.encoding) + (req "operation_index" int31)))) + (function + | Injected {op; oph; op_index} -> Some ((), op, (oph, op_index)) + | _ -> None) + (fun ((), op, (oph, op_index)) -> Injected {op; oph; op_index}); + case + (Tag 4) + ~title:"included" + ~description:"The message is included in an inbox in an L1 block." + (obj5 + (req "status" (constant "included")) + (req "operation" L1_operation.encoding) + (req + "layer1" + (obj4 + (req "operation_hash" Operation_hash.encoding) + (req "operation_index" int31) + (req "block_hash" Block_hash.encoding) + (req "level" int32))) + (req "finalized" bool) + (req "cemented" bool)) + (function + | Included + {op; oph; op_index; l1_block; l1_level; finalized; cemented} -> + Some + ( (), + op, + (oph, op_index, l1_block, l1_level), + finalized, + cemented ) + | _ -> None) + (fun ((), op, (oph, op_index, l1_block, l1_level), finalized, cemented) + -> + Included + {op; oph; op_index; l1_block; l1_level; finalized; cemented}); + case + (Tag 5) + ~title:"committed" + ~description:"The message is included in a committed inbox on L1." + (obj9 + (req "status" (constant "committed")) + (req "operation" L1_operation.encoding) + (req + "layer1" + (obj4 + (req "operation_hash" Operation_hash.encoding) + (req "operation_index" int31) + (req "block_hash" Block_hash.encoding) + (req "level" int32))) + (req "finalized" bool) + (req "cemented" bool) + (req "commitment" Commitment.encoding) + (req "hash" Commitment.Hash.encoding) + (req "first_published_at_level" int32) + (req "published_at_level" int32)) + (function + | Committed + { + op; + oph; + op_index; + l1_block; + l1_level; + finalized; + cemented; + commitment; + commitment_hash; + first_published_at_level; + published_at_level; + } -> + Some + ( (), + op, + (oph, op_index, l1_block, l1_level), + finalized, + cemented, + commitment, + commitment_hash, + first_published_at_level, + published_at_level ) + | _ -> None) + (fun ( (), + op, + (oph, op_index, l1_block, l1_level), + finalized, + cemented, + commitment, + commitment_hash, + first_published_at_level, + published_at_level ) -> + Committed + { + op; + oph; + op_index; + l1_block; + l1_level; + finalized; + cemented; + commitment; + commitment_hash; + first_published_at_level; + published_at_level; + }); + ] + + let message_status_output = + merge_objs (obj1 (opt "content" (string' Hex))) message_status +end + +module Arg = struct + type block_id = + [`Head | `Hash of Block_hash.t | `Level of Int32.t | `Finalized | `Cemented] + + let construct_block_id = function + | `Head -> "head" + | `Hash h -> Block_hash.to_b58check h + | `Level l -> Int32.to_string l + | `Finalized -> "finalized" + | `Cemented -> "cemented" + + let destruct_block_id h = + match h with + | "head" -> Ok `Head + | "finalized" -> Ok `Finalized + | "cemented" -> Ok `Cemented + | _ -> ( + match Int32.of_string_opt h with + | Some l -> Ok (`Level l) + | None -> ( + match Block_hash.of_b58check_opt h with + | Some b -> Ok (`Hash b) + | None -> Error "Cannot parse block id")) + + let block_id : block_id Tezos_rpc.Arg.t = + Tezos_rpc.Arg.make + ~descr:"An L1 block identifier." + ~name:"block_id" + ~construct:construct_block_id + ~destruct:destruct_block_id + () + + let l2_message_hash : L2_message.hash Tezos_rpc.Arg.t = + Tezos_rpc.Arg.make + ~descr:"A L2 message hash." + ~name:"l2_message_hash" + ~construct:L2_message.Hash.to_b58check + ~destruct:(fun s -> + L2_message.Hash.of_b58check_opt s + |> Option.to_result ~none:"Invalid L2 message hash") + () +end + +module type PREFIX = sig + type prefix + + val prefix : (unit, prefix) Tezos_rpc.Path.t +end + +module Make_services (P : PREFIX) = struct + include P + + let path : prefix Tezos_rpc.Path.context = Tezos_rpc.Path.open_root + + let make_call s = + Tezos_rpc.Context.make_call (Tezos_rpc.Service.prefix prefix s) + + let make_call1 s = + Tezos_rpc.Context.make_call1 (Tezos_rpc.Service.prefix prefix s) + + let make_call2 s = + Tezos_rpc.Context.make_call2 (Tezos_rpc.Service.prefix prefix s) +end + +module Global = struct + open Tezos_rpc.Path + + include Make_services (struct + type prefix = unit + + let prefix = open_root / "global" + end) + + let sc_rollup_address = + Tezos_rpc.Service.get_service + ~description:"Smart rollup address" + ~query:Tezos_rpc.Query.empty + ~output:Address.encoding + (path / "smart_rollup_address") + + let current_tezos_head = + Tezos_rpc.Service.get_service + ~description:"Tezos head known to the smart rollup node" + ~query:Tezos_rpc.Query.empty + ~output:(Data_encoding.option Block_hash.encoding) + (path / "tezos_head") + + let current_tezos_level = + Tezos_rpc.Service.get_service + ~description:"Tezos level known to the smart rollup node" + ~query:Tezos_rpc.Query.empty + ~output:(Data_encoding.option Data_encoding.int32) + (path / "tezos_level") + + let last_stored_commitment = + Tezos_rpc.Service.get_service + ~description:"Last commitment computed by the node" + ~query:Tezos_rpc.Query.empty + ~output:(Data_encoding.option Encodings.commitment_with_hash) + (path / "last_stored_commitment") +end + +module Local = struct + open Tezos_rpc.Path + + include Make_services (struct + type prefix = unit + + let prefix = open_root / "local" + end) + + (* commitments are published only if their inbox level is above the last + cemented commitment level inbox level. Because this information is + fetched from the head of the tezos node to which the rollup node is + connected, it is possible that two rollup nodes that have processed + the same set of heads, but whose corresponding layer1 node has + different information about the last cemented commitment, will + decide to publish and not to publish a commitment, respectively. + As a consequence, the results returned by the endpoint below + in the rollup node will be different. + *) + let last_published_commitment = + Tezos_rpc.Service.get_service + ~description:"Last commitment published by the node" + ~query:Tezos_rpc.Query.empty + ~output: + (Data_encoding.option Encodings.commitment_with_hash_and_level_infos) + (path / "last_published_commitment") + + let injection = + Tezos_rpc.Service.post_service + ~description:"Inject messages in the batcher's queue" + ~query:Tezos_rpc.Query.empty + ~input: + Data_encoding.( + def + "messages" + ~description:"Messages to inject" + (list L2_message.content_encoding)) + ~output: + Data_encoding.( + def + "message_hashes" + ~description:"Hashes of injected L2 messages" + (list L2_message.Hash.encoding)) + (path / "batcher" / "injection") + + let batcher_queue = + Tezos_rpc.Service.get_service + ~description:"List messages present in the batcher's queue" + ~query:Tezos_rpc.Query.empty + ~output:Encodings.batcher_queue + (path / "batcher" / "queue") + + let batcher_message = + Tezos_rpc.Service.get_service + ~description:"Retrieve an L2 message and its status" + ~query:Tezos_rpc.Query.empty + ~output:Encodings.message_status_output + (path / "batcher" / "queue" /: Arg.l2_message_hash) +end diff --git a/src/proto_alpha/lib_sc_rollup_client/RPC.ml b/src/proto_alpha/lib_sc_rollup_client/RPC.ml index 8184ab94335c..2f491d40e44a 100644 --- a/src/proto_alpha/lib_sc_rollup_client/RPC.ml +++ b/src/proto_alpha/lib_sc_rollup_client/RPC.ml @@ -23,14 +23,21 @@ (* *) (*****************************************************************************) +module Block_services = + Rollup_node_services.Make_services (Sc_rollup_services.Block) + let get_sc_rollup_addresses_command cctxt = - Sc_rollup_services.Global.(make_call sc_rollup_address) cctxt () () () + Rollup_node_services.Global.(make_call sc_rollup_address) cctxt () () () let get_state_value_command cctxt block key = - Sc_rollup_services.Global.Block.(make_call1 state_value) cctxt block {key} () + Block_services.(make_call1 Sc_rollup_services.Block.state_value) + cctxt + block + {key} + () let get_outbox_proof cctxt serialized_output = - Sc_rollup_services.Global.Block.Helpers.(make_call outbox_proof) + Block_services.(make_call Sc_rollup_services.Block.Helpers.outbox_proof) cctxt ((), `Head) serialized_output diff --git a/src/proto_alpha/lib_sc_rollup_client/commands.ml b/src/proto_alpha/lib_sc_rollup_client/commands.ml index f9e21f7467af..6419b4d952eb 100644 --- a/src/proto_alpha/lib_sc_rollup_client/commands.ml +++ b/src/proto_alpha/lib_sc_rollup_client/commands.ml @@ -40,7 +40,7 @@ let block_arg = (String.concat ", " possible_block_ids)) (Tezos_clic.parameter (fun _ s -> - match Sc_rollup_services.Arg.destruct_block_id s with + match Rollup_node_services.Arg.destruct_block_id s with | Ok b -> return b | Error reason -> failwith "Invalid block id: %s" reason) ~autocomplete:(fun _ -> return possible_block_ids)) diff --git a/src/proto_alpha/lib_sc_rollup_layer2/sc_rollup_services.ml b/src/proto_alpha/lib_sc_rollup_layer2/sc_rollup_services.ml index 9603f6737fac..04cb4c46665a 100644 --- a/src/proto_alpha/lib_sc_rollup_layer2/sc_rollup_services.ml +++ b/src/proto_alpha/lib_sc_rollup_layer2/sc_rollup_services.ml @@ -3,6 +3,7 @@ (* Open Source License *) (* Copyright (c) 2021 Nomadic Labs, *) (* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -26,28 +27,6 @@ open Protocol.Alpha_context -(* We distinguish RPC endpoints served by the rollup node into `global` and - `local`. The difference between the two lies in whether the responses - given by different rollup nodes in the same state (see below for an - exact definition) must be the same (in the case of global endpoints) - or can differ (in the case of local endpoints). - - More formally, two rollup nodes are in the same quiescent state if they are - subscribed to the same rollup address, and have processed the same set of - heads from the layer1. We only consider quiescent states, that is those - where rollup nodes are not actively processing a head received from layer1. - - Examples of global endpoints are `current_inbox` and - `last_stored_commitment`, as the responses returned by these endpoints - is expected to be consistent across rollup nodes in the same state. - - An example of local endpoint is `last_published_commitments`, as two rollup - nodes in the same state may either publish or not publish a commitment, - according to whether its inbox level is below the inbox level of the - last cemented commitment at the time they tried to publish the commitment. - See below for a more detailed explanation. -*) - type eval_result = { state_hash : Sc_rollup.State_hash.t; status : string; @@ -76,50 +55,10 @@ type commitment_info = { published_at_level : Raw_level.t; } -type message_status = - | Unknown - | Pending_batch - | Pending_injection of L1_operation.t - | Injected of {op : L1_operation.t; oph : Operation_hash.t; op_index : int} - | Included of { - op : L1_operation.t; - oph : Operation_hash.t; - op_index : int; - l1_block : Block_hash.t; - l1_level : int32; - finalized : bool; - cemented : bool; - } - | Committed of { - op : L1_operation.t; - oph : Operation_hash.t; - op_index : int; - l1_block : Block_hash.t; - l1_level : int32; - finalized : bool; - cemented : bool; - commitment : Octez_smart_rollup.Commitment.t; - commitment_hash : Octez_smart_rollup.Commitment.Hash.t; - first_published_at_level : int32; - published_at_level : int32; - } - module Encodings = struct open Data_encoding - let commitment_with_hash = - obj2 - (req "commitment" Octez_smart_rollup.Commitment.encoding) - (req "hash" Octez_smart_rollup.Commitment.Hash.encoding) - - let commitment_with_hash_and_level_infos = - obj4 - (req "commitment" Octez_smart_rollup.Commitment.encoding) - (req "hash" Octez_smart_rollup.Commitment.Hash.encoding) - (opt "first_published_at_level" int32) - (opt "published_at_level" int32) - - let hex_string = conv Bytes.of_string Bytes.to_string bytes + let hex_string = string' Hex let eval_result = conv @@ -195,13 +134,6 @@ module Encodings = struct [] ~description:"Paths in the PVM to inspect after the simulation") - let queued_message = - obj2 - (req "hash" L2_message.Hash.encoding) - (req "message" L2_message.encoding) - - let batcher_queue = list queued_message - let commitment_info = conv (fun { @@ -229,197 +161,6 @@ module Encodings = struct (req "hash" Sc_rollup.Commitment.Hash.encoding) (req "first_published_at_level" Raw_level.encoding) (req "published_at_level" Raw_level.encoding) - - let message_status = - union - [ - case - (Tag 0) - ~title:"unknown" - ~description:"The message is not known by the batcher." - (obj1 (req "status" (constant "unknown"))) - (function Unknown -> Some () | _ -> None) - (fun () -> Unknown); - case - (Tag 1) - ~title:"pending_batch" - ~description:"The message is in the batcher queue." - (obj1 (req "status" (constant "pending_batch"))) - (function Pending_batch -> Some () | _ -> None) - (fun () -> Pending_batch); - case - (Tag 2) - ~title:"pending_injection" - ~description:"The message is batched but not injected yet." - (obj2 - (req "status" (constant "pending_injection")) - (req "operation" L1_operation.encoding)) - (function Pending_injection op -> Some ((), op) | _ -> None) - (fun ((), op) -> Pending_injection op); - case - (Tag 3) - ~title:"injected" - ~description: - "The message is injected as part of an L1 operation but it is not \ - included in a block." - (obj3 - (req "status" (constant "injected")) - (req "operation" L1_operation.encoding) - (req - "layer1" - (obj2 - (req "operation_hash" Operation_hash.encoding) - (req "operation_index" int31)))) - (function - | Injected {op; oph; op_index} -> Some ((), op, (oph, op_index)) - | _ -> None) - (fun ((), op, (oph, op_index)) -> Injected {op; oph; op_index}); - case - (Tag 4) - ~title:"included" - ~description:"The message is included in an inbox in an L1 block." - (obj5 - (req "status" (constant "included")) - (req "operation" L1_operation.encoding) - (req - "layer1" - (obj4 - (req "operation_hash" Operation_hash.encoding) - (req "operation_index" int31) - (req "block_hash" Block_hash.encoding) - (req "level" int32))) - (req "finalized" bool) - (req "cemented" bool)) - (function - | Included - {op; oph; op_index; l1_block; l1_level; finalized; cemented} -> - Some - ( (), - op, - (oph, op_index, l1_block, l1_level), - finalized, - cemented ) - | _ -> None) - (fun ((), op, (oph, op_index, l1_block, l1_level), finalized, cemented) - -> - Included - {op; oph; op_index; l1_block; l1_level; finalized; cemented}); - case - (Tag 5) - ~title:"committed" - ~description:"The message is included in a committed inbox on L1." - (obj9 - (req "status" (constant "committed")) - (req "operation" L1_operation.encoding) - (req - "layer1" - (obj4 - (req "operation_hash" Operation_hash.encoding) - (req "operation_index" int31) - (req "block_hash" Block_hash.encoding) - (req "level" int32))) - (req "finalized" bool) - (req "cemented" bool) - (req "commitment" Octez_smart_rollup.Commitment.encoding) - (req "hash" Octez_smart_rollup.Commitment.Hash.encoding) - (req "first_published_at_level" int32) - (req "published_at_level" int32)) - (function - | Committed - { - op; - oph; - op_index; - l1_block; - l1_level; - finalized; - cemented; - commitment; - commitment_hash; - first_published_at_level; - published_at_level; - } -> - Some - ( (), - op, - (oph, op_index, l1_block, l1_level), - finalized, - cemented, - commitment, - commitment_hash, - first_published_at_level, - published_at_level ) - | _ -> None) - (fun ( (), - op, - (oph, op_index, l1_block, l1_level), - finalized, - cemented, - commitment, - commitment_hash, - first_published_at_level, - published_at_level ) -> - Committed - { - op; - oph; - op_index; - l1_block; - l1_level; - finalized; - cemented; - commitment; - commitment_hash; - first_published_at_level; - published_at_level; - }); - ] - - let message_status_output = - merge_objs (obj1 (opt "content" hex_string)) message_status -end - -module Arg = struct - type block_id = - [`Head | `Hash of Block_hash.t | `Level of Int32.t | `Finalized | `Cemented] - - let construct_block_id = function - | `Head -> "head" - | `Hash h -> Block_hash.to_b58check h - | `Level l -> Int32.to_string l - | `Finalized -> "finalized" - | `Cemented -> "cemented" - - let destruct_block_id h = - match h with - | "head" -> Ok `Head - | "finalized" -> Ok `Finalized - | "cemented" -> Ok `Cemented - | _ -> ( - match Int32.of_string_opt h with - | Some l -> Ok (`Level l) - | None -> ( - match Block_hash.of_b58check_opt h with - | Some b -> Ok (`Hash b) - | None -> Error "Cannot parse block id")) - - let block_id : block_id Tezos_rpc.Arg.t = - Tezos_rpc.Arg.make - ~descr:"An L1 block identifier." - ~name:"block_id" - ~construct:construct_block_id - ~destruct:destruct_block_id - () - - let l2_message_hash : L2_message.hash Tezos_rpc.Arg.t = - Tezos_rpc.Arg.make - ~descr:"A L2 message hash." - ~name:"l2_message_hash" - ~construct:L2_message.Hash.to_b58check - ~destruct:(fun s -> - L2_message.Hash.of_b58check_opt s - |> Option.to_result ~none:"Invalid L2 message hash") - () end module Query = struct @@ -487,27 +228,6 @@ module Query = struct |> seal end -module type PREFIX = sig - type prefix - - val prefix : (unit, prefix) Tezos_rpc.Path.t -end - -module Make_services (P : PREFIX) = struct - include P - - let path : prefix Tezos_rpc.Path.context = Tezos_rpc.Path.open_root - - let make_call s = - Tezos_rpc.Context.make_call (Tezos_rpc.Service.prefix prefix s) - - let make_call1 s = - Tezos_rpc.Context.make_call1 (Tezos_rpc.Service.prefix prefix s) - - let make_call2 s = - Tezos_rpc.Context.make_call2 (Tezos_rpc.Service.prefix prefix s) -end - type simulate_query = {fuel : int64 option} let simulate_query : simulate_query Tezos_rpc.Query.t = @@ -516,300 +236,193 @@ let simulate_query : simulate_query Tezos_rpc.Query.t = |+ opt_field "fuel" Tezos_rpc.Arg.int64 (fun t -> t.fuel) |> seal -module Global = struct +module Block = struct open Tezos_rpc.Path - include Make_services (struct - type prefix = unit + type prefix = unit * Rollup_node_services.Arg.block_id + + let path : prefix Tezos_rpc.Path.context = open_root - let prefix = open_root / "global" - end) + let prefix = root / "global" / "block" /: Rollup_node_services.Arg.block_id - let sc_rollup_address = + let block = Tezos_rpc.Service.get_service - ~description:"Smart rollup address" + ~description: + "Layer-2 block of the layer-2 chain with respect to a Layer 1 block \ + identifier" ~query:Tezos_rpc.Query.empty - ~output:Sc_rollup.Address.encoding - (path / "smart_rollup_address") + ~output:Sc_rollup_block.full_encoding + path - let current_tezos_head = + let hash = Tezos_rpc.Service.get_service - ~description:"Tezos head known to the smart rollup node" + ~description:"Tezos block hash of block known to the smart rollup node" ~query:Tezos_rpc.Query.empty - ~output:(Data_encoding.option Block_hash.encoding) - (path / "tezos_head") + ~output:Block_hash.encoding + (path / "hash") - let current_tezos_level = + let level = Tezos_rpc.Service.get_service - ~description:"Tezos level known to the smart rollup node" + ~description:"Level of Tezos block known to the smart rollup node" ~query:Tezos_rpc.Query.empty - ~output:(Data_encoding.option Data_encoding.int32) - (path / "tezos_level") + ~output:Data_encoding.int32 + (path / "level") - let last_stored_commitment = + let inbox = Tezos_rpc.Service.get_service - ~description:"Last commitment computed by the node" + ~description:"Rollup inbox for block" ~query:Tezos_rpc.Query.empty - ~output:(Data_encoding.option Encodings.commitment_with_hash) - (path / "last_stored_commitment") + ~output:Octez_smart_rollup.Inbox.encoding + (path / "inbox") - module Block = struct - include Make_services (struct - type prefix = unit * Arg.block_id - - let prefix = prefix / "block" /: Arg.block_id - end) - - let block = - Tezos_rpc.Service.get_service - ~description: - "Layer-2 block of the layer-2 chain with respect to a Layer 1 block \ - identifier" - ~query:Tezos_rpc.Query.empty - ~output:Sc_rollup_block.full_encoding - path - - let hash = - Tezos_rpc.Service.get_service - ~description:"Tezos block hash of block known to the smart rollup node" - ~query:Tezos_rpc.Query.empty - ~output:Block_hash.encoding - (path / "hash") - - let level = - Tezos_rpc.Service.get_service - ~description:"Level of Tezos block known to the smart rollup node" - ~query:Tezos_rpc.Query.empty - ~output:Data_encoding.int32 - (path / "level") - - let inbox = - Tezos_rpc.Service.get_service - ~description:"Rollup inbox for block" - ~query:Tezos_rpc.Query.empty - ~output:Octez_smart_rollup.Inbox.encoding - (path / "inbox") - - let ticks = - Tezos_rpc.Service.get_service - ~description:"Number of ticks for specified level" - ~query:Tezos_rpc.Query.empty - ~output:Data_encoding.z - (path / "ticks") - - let total_ticks = - Tezos_rpc.Service.get_service - ~description:"Total number of ticks at specified block" - ~query:Tezos_rpc.Query.empty - ~output:Sc_rollup.Tick.encoding - (path / "total_ticks") - - let num_messages = - Tezos_rpc.Service.get_service - ~description:"Number of messages for specified block" - ~query:Tezos_rpc.Query.empty - ~output:Data_encoding.z - (path / "num_messages") + let ticks = + Tezos_rpc.Service.get_service + ~description:"Number of ticks for specified level" + ~query:Tezos_rpc.Query.empty + ~output:Data_encoding.z + (path / "ticks") - let state_hash = - Tezos_rpc.Service.get_service - ~description:"State hash for this block" - ~query:Tezos_rpc.Query.empty - ~output:Sc_rollup.State_hash.encoding - (path / "state_hash") + let total_ticks = + Tezos_rpc.Service.get_service + ~description:"Total number of ticks at specified block" + ~query:Tezos_rpc.Query.empty + ~output:Sc_rollup.Tick.encoding + (path / "total_ticks") - let state_current_level = - Tezos_rpc.Service.get_service - ~description:"Retrieve the current level of a PVM" - ~query:Tezos_rpc.Query.empty - ~output:(Data_encoding.option Raw_level.encoding) - (path / "state_current_level") + let num_messages = + Tezos_rpc.Service.get_service + ~description:"Number of messages for specified block" + ~query:Tezos_rpc.Query.empty + ~output:Data_encoding.z + (path / "num_messages") - let state_value = - Tezos_rpc.Service.get_service - ~description:"Retrieve value from key is PVM state of specified block" - ~query:Query.key_query - ~output:Data_encoding.bytes - (path / "state") + let state_hash = + Tezos_rpc.Service.get_service + ~description:"State hash for this block" + ~query:Tezos_rpc.Query.empty + ~output:Sc_rollup.State_hash.encoding + (path / "state_hash") - let durable_state_value (pvm_kind : Sc_rollup.Kind.t) = - Tezos_rpc.Service.get_service - ~description: - "Retrieve value by key from PVM durable storage. PVM state is taken \ - with respect to the specified block level. Value returned in hex \ - format." - ~query:Query.key_query - ~output:Data_encoding.(option bytes) - (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "value") - - let durable_state_length - (pvm_kind : Protocol.Alpha_context.Sc_rollup.Kind.t) = - Tezos_rpc.Service.get_service - ~description: - "Retrieve number of bytes in raw representation of value by key from \ - PVM durable storage. PVM state is taken with respect to the \ - specified block level." - ~query:Query.key_query - ~output:Data_encoding.(option int64) - (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "length") - - let durable_state_subkeys (pvm_kind : Sc_rollup.Kind.t) = - Tezos_rpc.Service.get_service - ~description: - "Retrieve subkeys of the specified key from PVM durable storage. PVM \ - state is taken with respect to the specified block level." - ~query:Query.key_query - ~output:Data_encoding.(list string) - (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "subkeys") - - let status = - Tezos_rpc.Service.get_service - ~description:"PVM status at block" - ~query:Tezos_rpc.Query.empty - ~output:Data_encoding.string - (path / "status") + let state_current_level = + Tezos_rpc.Service.get_service + ~description:"Retrieve the current level of a PVM" + ~query:Tezos_rpc.Query.empty + ~output:(Data_encoding.option Raw_level.encoding) + (path / "state_current_level") - let outbox = - Tezos_rpc.Service.get_service - ~description:"Outbox at block for a given outbox level" - ~query:Query.outbox_level_query - ~output:Data_encoding.(list Sc_rollup.output_encoding) - (path / "outbox") - - let simulate = - Tezos_rpc.Service.post_service - ~description:"Simulate messages evaluation by the PVM" - ~query:Tezos_rpc.Query.empty - ~input:Encodings.simulate_input - ~output:Encodings.eval_result - (path / "simulate") - - let dal_slots = - Tezos_rpc.Service.get_service - ~description:"Availability slots for a given block" - ~query:Tezos_rpc.Query.empty - ~output:(Data_encoding.list Dal.Slot.Header.encoding) - (path / "dal" / "slot_headers") + let state_value = + Tezos_rpc.Service.get_service + ~description:"Retrieve value from key is PVM state of specified block" + ~query:Query.key_query + ~output:Data_encoding.bytes + (path / "state") - let dal_slot_status_encoding : [`Confirmed | `Unconfirmed] Data_encoding.t = - Data_encoding.string_enum - [("confirmed", `Confirmed); ("unconfirmed", `Unconfirmed)] + let durable_state_value (pvm_kind : Sc_rollup.Kind.t) = + Tezos_rpc.Service.get_service + ~description: + "Retrieve value by key from PVM durable storage. PVM state is taken \ + with respect to the specified block level. Value returned in hex \ + format." + ~query:Query.key_query + ~output:Data_encoding.(option bytes) + (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "value") + + let durable_state_length (pvm_kind : Protocol.Alpha_context.Sc_rollup.Kind.t) + = + Tezos_rpc.Service.get_service + ~description: + "Retrieve number of bytes in raw representation of value by key from \ + PVM durable storage. PVM state is taken with respect to the specified \ + block level." + ~query:Query.key_query + ~output:Data_encoding.(option int64) + (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "length") + + let durable_state_subkeys (pvm_kind : Sc_rollup.Kind.t) = + Tezos_rpc.Service.get_service + ~description: + "Retrieve subkeys of the specified key from PVM durable storage. PVM \ + state is taken with respect to the specified block level." + ~query:Query.key_query + ~output:Data_encoding.(list string) + (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "subkeys") + + let status = + Tezos_rpc.Service.get_service + ~description:"PVM status at block" + ~query:Tezos_rpc.Query.empty + ~output:Data_encoding.string + (path / "status") - let dal_processed_slots = - Tezos_rpc.Service.get_service - ~description:"Data availability processed slots and their statuses" - ~query:Tezos_rpc.Query.empty - ~output: - Data_encoding.( - list - @@ obj2 (req "index" int31) (req "status" dal_slot_status_encoding)) - (path / "dal" / "processed_slots") - - module Outbox = struct - let level_param = - let destruct s = - match Int32.of_string_opt s with - | None -> Error "Invalid level" - | Some l -> ( - match Raw_level.of_int32 l with - | Error _ -> Error "Invalid level" - | Ok l -> Ok l) - in - let construct = Format.asprintf "%a" Raw_level.pp in - Tezos_rpc.Arg.make ~name:"level" ~construct ~destruct () - - include Make_services (struct - type nonrec prefix = prefix * Raw_level.t - - let prefix = prefix / "outbox" /: level_param - end) - - let messages = - Tezos_rpc.Service.get_service - ~description:"Outbox at block for a given outbox level" - ~query:Tezos_rpc.Query.empty - ~output:Data_encoding.(list Sc_rollup.output_encoding) - (path / "messages") - end - - module Helpers = struct - include Make_services (struct - type nonrec prefix = prefix - - let prefix = prefix / "helpers" - end) - - let outbox_proof = - Tezos_rpc.Service.get_service - ~description: - "Generate serialized output proof for some outbox message" - ~query:Query.outbox_proof_query - ~output: - Data_encoding.( - obj2 - (req "commitment" Sc_rollup.Commitment.Hash.encoding) - (req "proof" Encodings.hex_string)) - (path / "proofs" / "outbox") - end - end -end + let outbox = + Tezos_rpc.Service.get_service + ~description:"Outbox at block for a given outbox level" + ~query:Query.outbox_level_query + ~output:Data_encoding.(list Sc_rollup.output_encoding) + (path / "outbox") -module Local = struct - open Tezos_rpc.Path + let simulate = + Tezos_rpc.Service.post_service + ~description:"Simulate messages evaluation by the PVM" + ~query:Tezos_rpc.Query.empty + ~input:Encodings.simulate_input + ~output:Encodings.eval_result + (path / "simulate") - include Make_services (struct - type prefix = unit - - let prefix = open_root / "local" - end) - - (* commitments are published only if their inbox level is above the last - cemented commitment level inbox level. Because this information is - fetched from the head of the tezos node to which the rollup node is - connected, it is possible that two rollup nodes that have processed - the same set of heads, but whose corresponding layer1 node has - different information about the last cemented commitment, will - decide to publish and not to publish a commitment, respectively. - As a consequence, the results returned by the endpoint below - in the rollup node will be different. - *) - let last_published_commitment = + let dal_slots = Tezos_rpc.Service.get_service - ~description:"Last commitment published by the node" + ~description:"Availability slots for a given block" ~query:Tezos_rpc.Query.empty - ~output: - (Data_encoding.option Encodings.commitment_with_hash_and_level_infos) - (path / "last_published_commitment") + ~output:(Data_encoding.list Dal.Slot.Header.encoding) + (path / "dal" / "slot_headers") - let injection = - Tezos_rpc.Service.post_service - ~description:"Inject messages in the batcher's queue" + let dal_slot_status_encoding : [`Confirmed | `Unconfirmed] Data_encoding.t = + Data_encoding.string_enum + [("confirmed", `Confirmed); ("unconfirmed", `Unconfirmed)] + + let dal_processed_slots = + Tezos_rpc.Service.get_service + ~description:"Data availability processed slots and their statuses" ~query:Tezos_rpc.Query.empty - ~input: - Data_encoding.( - def - "messages" - ~description:"Messages to inject" - (list L2_message.content_encoding)) ~output: Data_encoding.( - def - "message_hashes" - ~description:"Hashes of injected L2 messages" - (list L2_message.Hash.encoding)) - (path / "batcher" / "injection") + list + @@ obj2 (req "index" int31) (req "status" dal_slot_status_encoding)) + (path / "dal" / "processed_slots") + + let level_param = + let destruct s = + match Int32.of_string_opt s with + | None -> Error "Invalid level" + | Some l -> ( + match Raw_level.of_int32 l with + | Error _ -> Error "Invalid level" + | Ok l -> Ok l) + in + let construct = Format.asprintf "%a" Raw_level.pp in + Tezos_rpc.Arg.make ~name:"level" ~construct ~destruct () - let batcher_queue = + let outbox_messages = Tezos_rpc.Service.get_service - ~description:"List messages present in the batcher's queue" + ~description:"Outbox at block for a given outbox level" ~query:Tezos_rpc.Query.empty - ~output:Encodings.batcher_queue - (path / "batcher" / "queue") + ~output:Data_encoding.(list Sc_rollup.output_encoding) + (path / "outbox" /: level_param / "messages") - let batcher_message = - Tezos_rpc.Service.get_service - ~description:"Retrieve an L2 message and its status" - ~query:Tezos_rpc.Query.empty - ~output:Encodings.message_status_output - (path / "batcher" / "queue" /: Arg.l2_message_hash) + module Helpers = struct + type nonrec prefix = prefix + + let path = path / "helpers" + + let outbox_proof = + Tezos_rpc.Service.get_service + ~description:"Generate serialized output proof for some outbox message" + ~query:Query.outbox_proof_query + ~output: + Data_encoding.( + obj2 + (req "commitment" Sc_rollup.Commitment.Hash.encoding) + (req "proof" Encodings.hex_string)) + (path / "proofs" / "outbox") + end end diff --git a/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml b/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml index 4efd44b0fdfc..05cc7b273a49 100644 --- a/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml +++ b/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml @@ -50,7 +50,7 @@ let get_dal_processed_slots node_ctxt block = Node_context.list_slots_statuses node_ctxt ~confirmed_in_block_hash:block module Global_directory = Make_directory (struct - include Sc_rollup_services.Global + include Rollup_node_services.Global type context = Node_context.rw @@ -60,7 +60,7 @@ module Global_directory = Make_directory (struct end) module Local_directory = Make_directory (struct - include Sc_rollup_services.Local + include Rollup_node_services.Local type context = Node_context.rw @@ -69,8 +69,8 @@ module Local_directory = Make_directory (struct let context_of_prefix node_ctxt () = return (Node_context.readonly node_ctxt) end) -module Block_directory = Make_directory (struct - include Sc_rollup_services.Global.Block +module Block_directory = Make_sub_directory (struct + include Sc_rollup_services.Block type context = Node_context.rw @@ -82,21 +82,8 @@ module Block_directory = Make_directory (struct (Node_context.readonly node_ctxt, block) end) -module Outbox_directory = Make_directory (struct - include Sc_rollup_services.Global.Block.Outbox - - type context = Node_context.rw - - type subcontext = Node_context.ro * Block_hash.t * Alpha_context.Raw_level.t - - let context_of_prefix node_ctxt (((), block), level) = - let open Lwt_result_syntax in - let+ block = Block_directory_helpers.block_of_prefix node_ctxt block in - (Node_context.readonly node_ctxt, block, level) -end) - -module Block_helpers_directory = Make_directory (struct - include Sc_rollup_services.Global.Block.Helpers +module Block_helpers_directory = Make_sub_directory (struct + include Sc_rollup_services.Block.Helpers (* The context needs to be accessed with write permissions because we need to commit on disk to generate the proofs. *) @@ -114,12 +101,12 @@ end) module Common = struct let () = - Block_directory.register0 Sc_rollup_services.Global.Block.block + Block_directory.register0 Sc_rollup_services.Block.block @@ fun (node_ctxt, block) () () -> Node_context.get_full_l2_block node_ctxt block let () = - Block_directory.register0 Sc_rollup_services.Global.Block.num_messages + Block_directory.register0 Sc_rollup_services.Block.num_messages @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let* l2_block = Node_context.get_l2_block node_ctxt block in @@ -129,34 +116,34 @@ module Common = struct Z.of_int num_messages let () = - Global_directory.register0 Sc_rollup_services.Global.sc_rollup_address + Global_directory.register0 Rollup_node_services.Global.sc_rollup_address @@ fun node_ctxt () () -> return @@ Sc_rollup_proto_types.Address.of_octez node_ctxt.rollup_address let () = - Global_directory.register0 Sc_rollup_services.Global.current_tezos_head + Global_directory.register0 Rollup_node_services.Global.current_tezos_head @@ fun node_ctxt () () -> get_head_hash_opt node_ctxt let () = - Global_directory.register0 Sc_rollup_services.Global.current_tezos_level + Global_directory.register0 Rollup_node_services.Global.current_tezos_level @@ fun node_ctxt () () -> get_head_level_opt node_ctxt let () = - Block_directory.register0 Sc_rollup_services.Global.Block.hash + Block_directory.register0 Sc_rollup_services.Block.hash @@ fun (_node_ctxt, block) () () -> return block let () = - Block_directory.register0 Sc_rollup_services.Global.Block.level + Block_directory.register0 Sc_rollup_services.Block.level @@ fun (node_ctxt, block) () () -> Node_context.level_of_hash node_ctxt block let () = - Block_directory.register0 Sc_rollup_services.Global.Block.inbox + Block_directory.register0 Sc_rollup_services.Block.inbox @@ fun (node_ctxt, block) () () -> Node_context.get_inbox_by_block_hash node_ctxt block let () = - Block_directory.register0 Sc_rollup_services.Global.Block.ticks + Block_directory.register0 Sc_rollup_services.Block.ticks @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let+ l2_block = Node_context.get_l2_block node_ctxt block in @@ -230,7 +217,7 @@ let simulate_messages (node_ctxt : Node_context.ro) block ~reveal_pages {state_hash; status; output; inbox_level; num_ticks; insights} let () = - Block_directory.register0 Sc_rollup_services.Global.Block.total_ticks + Block_directory.register0 Sc_rollup_services.Block.total_ticks @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -239,7 +226,7 @@ let () = return tick let () = - Block_directory.register0 Sc_rollup_services.Global.Block.state_hash + Block_directory.register0 Sc_rollup_services.Block.state_hash @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -248,7 +235,7 @@ let () = return hash let () = - Block_directory.register0 Sc_rollup_services.Global.Block.state_current_level + Block_directory.register0 Sc_rollup_services.Block.state_current_level @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -257,7 +244,7 @@ let () = return current_level let () = - Block_directory.register0 Sc_rollup_services.Global.Block.state_value + Block_directory.register0 Sc_rollup_services.Block.state_value @@ fun (node_ctxt, block) {key} () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -270,7 +257,7 @@ let () = return value let () = - Global_directory.register0 Sc_rollup_services.Global.last_stored_commitment + Global_directory.register0 Rollup_node_services.Global.last_stored_commitment @@ fun node_ctxt () () -> let open Lwt_result_syntax in let* head = Node_context.last_processed_head_opt node_ctxt in @@ -286,7 +273,7 @@ let () = Option.map (fun c -> (c, commitment_hash)) commitment let () = - Local_directory.register0 Sc_rollup_services.Local.last_published_commitment + Local_directory.register0 Rollup_node_services.Local.last_published_commitment @@ fun node_ctxt () () -> let open Lwt_result_syntax in match Reference.get node_ctxt.lpc with @@ -308,7 +295,7 @@ let () = return_some (commitment, hash, first_published, published) let () = - Block_directory.register0 Sc_rollup_services.Global.Block.status + Block_directory.register0 Sc_rollup_services.Block.status @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -325,7 +312,7 @@ let () = return (PVM.string_of_status status) let () = - Block_directory.register0 Sc_rollup_services.Global.Block.dal_slots + Block_directory.register0 Sc_rollup_services.Block.dal_slots @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let+ slots = @@ -338,12 +325,12 @@ let () = |> List.rev let () = - Block_directory.register0 Sc_rollup_services.Global.Block.dal_processed_slots + Block_directory.register0 Sc_rollup_services.Block.dal_processed_slots @@ fun (node_ctxt, block) () () -> get_dal_processed_slots node_ctxt block let () = - Outbox_directory.register0 Sc_rollup_services.Global.Block.Outbox.messages - @@ fun (node_ctxt, block, outbox_level) () () -> + Block_directory.register1 Sc_rollup_services.Block.outbox_messages + @@ fun (node_ctxt, block) outbox_level () () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in let module PVM = (val Pvm.of_kind node_ctxt.kind) in @@ -352,23 +339,23 @@ let () = let () = Block_helpers_directory.register0 - Sc_rollup_services.Global.Block.Helpers.outbox_proof + Sc_rollup_services.Block.Helpers.outbox_proof @@ fun (node_ctxt, _block_hash) output () -> let open Lwt_result_syntax in let+ commitment, proof = Outbox.proof_of_output node_ctxt output in (Sc_rollup_proto_types.Commitment_hash.of_octez commitment, proof) let () = - Block_directory.register0 Sc_rollup_services.Global.Block.simulate + Block_directory.register0 Sc_rollup_services.Block.simulate @@ fun (node_ctxt, block) () {messages; reveal_pages; insight_requests} -> simulate_messages node_ctxt block ~reveal_pages ~insight_requests messages let () = - Local_directory.register0 Sc_rollup_services.Local.injection + Local_directory.register0 Rollup_node_services.Local.injection @@ fun _node_ctxt () messages -> Batcher.register_messages messages let () = - Local_directory.register0 Sc_rollup_services.Local.batcher_queue + Local_directory.register0 Rollup_node_services.Local.batcher_queue @@ fun _node_ctxt () () -> let open Lwt_result_syntax in let*? queue = Batcher.get_queue () in @@ -408,25 +395,25 @@ let inbox_info_of_level (node_ctxt : _ Node_context.t) inbox_level = (finalized, cemented) let () = - Local_directory.register1 Sc_rollup_services.Local.batcher_message + Local_directory.register1 Rollup_node_services.Local.batcher_message @@ fun node_ctxt hash () () -> let open Lwt_result_syntax in let*? batch_status = Batcher.message_status hash in let* status = match batch_status with - | None -> return (None, Sc_rollup_services.Unknown) + | None -> return (None, Rollup_node_services.Unknown) | Some (batch_status, msg) -> ( let return status = return (Some msg, status) in match batch_status with - | Pending_batch -> return Sc_rollup_services.Pending_batch + | Pending_batch -> return Rollup_node_services.Pending_batch | Batched l1_hash -> ( match Injector.operation_status l1_hash with - | None -> return Sc_rollup_services.Unknown + | None -> return Rollup_node_services.Unknown | Some (Pending op) -> - return (Sc_rollup_services.Pending_injection op) + return (Rollup_node_services.Pending_injection op) | Some (Injected {op; oph; op_index}) -> return - (Sc_rollup_services.Injected + (Rollup_node_services.Injected {op = op.operation; oph; op_index}) | Some (Included {op; oph; op_index; l1_block; l1_level}) -> ( let* finalized, cemented = @@ -438,7 +425,7 @@ let () = match commitment_level with | None -> return - (Sc_rollup_services.Included + (Rollup_node_services.Included { op = op.operation; oph; @@ -458,7 +445,7 @@ let () = | None -> (* Commitment not computed yet for inbox *) return - (Sc_rollup_services.Included + (Rollup_node_services.Included { op = op.operation; oph; @@ -484,7 +471,7 @@ let () = | None | Some {published_at_level = None; _} -> (* Commitment not published yet *) return - (Sc_rollup_services.Included + (Rollup_node_services.Included { op = op.operation; oph; @@ -506,7 +493,7 @@ let () = commitment_hash in return - (Sc_rollup_services.Committed + (Rollup_node_services.Committed { op = op.operation; oph; @@ -530,10 +517,9 @@ let block_directory (node_ctxt : _ Node_context.t) = (fun dir f -> Tezos_rpc.Directory.merge dir (f node_ctxt)) Tezos_rpc.Directory.empty [ - Block_directory.build_directory; - Block_helpers_directory.build_directory; - Outbox_directory.build_directory; - PVM.build_directory; + Block_directory.build_sub_directory; + Block_helpers_directory.build_sub_directory; + PVM.build_sub_directory; ] let top_directory (node_ctxt : _ Node_context.t) = @@ -545,4 +531,6 @@ let top_directory (node_ctxt : _ Node_context.t) = let directory (node_ctxt : _ Node_context.t) = Tezos_rpc.Directory.merge (top_directory node_ctxt) - (block_directory node_ctxt) + (Tezos_rpc.Directory.prefix + Sc_rollup_services.Block.prefix + (block_directory node_ctxt)) diff --git a/src/proto_alpha/lib_sc_rollup_node/RPC_directory.mli b/src/proto_alpha/lib_sc_rollup_node/RPC_directory.mli index ee6d9b0eb44d..44dffc1d7ddf 100644 --- a/src/proto_alpha/lib_sc_rollup_node/RPC_directory.mli +++ b/src/proto_alpha/lib_sc_rollup_node/RPC_directory.mli @@ -24,7 +24,9 @@ (*****************************************************************************) (** The RPC directory, specific to blocks, for this rollup node. *) -val block_directory : Node_context.rw -> unit Tezos_rpc.Directory.t +val block_directory : + Node_context.rw -> + (unit * Rollup_node_services.Arg.block_id) Tezos_rpc.Directory.t (** The RPC top level directory (without the block directory) for this rollup node. *) diff --git a/src/proto_alpha/lib_sc_rollup_node/pvm_rpc.ml b/src/proto_alpha/lib_sc_rollup_node/pvm_rpc.ml index a8d946e87b6a..8069495af039 100644 --- a/src/proto_alpha/lib_sc_rollup_node/pvm_rpc.ml +++ b/src/proto_alpha/lib_sc_rollup_node/pvm_rpc.ml @@ -25,11 +25,13 @@ module type S = sig (** Build RPC directory of the PVM *) - val build_directory : Node_context.rw -> unit Environment.RPC_directory.t + val build_sub_directory : + Node_context.rw -> + (unit * Rollup_node_services.Arg.block_id) Tezos_rpc.Directory.t end module No_rpc = struct - let build_directory _node_ctxt = Tezos_rpc.Directory.empty + let build_sub_directory _node_ctxt = Tezos_rpc.Directory.empty end let no_rpc = (module No_rpc : S) diff --git a/src/proto_alpha/lib_sc_rollup_node/wasm_2_0_0_rpc.ml b/src/proto_alpha/lib_sc_rollup_node/wasm_2_0_0_rpc.ml index dd4c703fa4c5..55ba6f282a06 100644 --- a/src/proto_alpha/lib_sc_rollup_node/wasm_2_0_0_rpc.ml +++ b/src/proto_alpha/lib_sc_rollup_node/wasm_2_0_0_rpc.ml @@ -24,13 +24,13 @@ (* *) (*****************************************************************************) -open RPC_directory_helpers +open Rpc_directory_helpers module Make_RPC (Durable_state : Wasm_2_0_0_pvm.Durable_state with type state = Context.tree) = struct - module Block_directory = Make_directory (struct - include Sc_rollup_services.Global.Block + module Block_directory = Make_sub_directory (struct + include Sc_rollup_services.Block type context = Node_context.rw @@ -51,7 +51,7 @@ struct let register () = let open Protocol.Alpha_context.Sc_rollup in ( Block_directory.register0 - (Sc_rollup_services.Global.Block.durable_state_value Kind.Wasm_2_0_0) + (Sc_rollup_services.Block.durable_state_value Kind.Wasm_2_0_0) @@ fun (node_ctxt, block) {key} () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -59,7 +59,7 @@ struct return value ) ; ( Block_directory.register0 - (Sc_rollup_services.Global.Block.durable_state_length Kind.Wasm_2_0_0) + (Sc_rollup_services.Block.durable_state_length Kind.Wasm_2_0_0) @@ fun (node_ctxt, block) {key} () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -67,14 +67,14 @@ struct return leng ) ; Block_directory.register0 - (Sc_rollup_services.Global.Block.durable_state_subkeys Kind.Wasm_2_0_0) + (Sc_rollup_services.Block.durable_state_subkeys Kind.Wasm_2_0_0) @@ fun (node_ctxt, block) {key} () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in let*! subkeys = Durable_state.list state key in return subkeys - let build_directory node_ctxt = + let build_sub_directory node_ctxt = register () ; - Block_directory.build_directory node_ctxt + Block_directory.build_sub_directory node_ctxt end -- GitLab From 894bf5b45c4e3f16e4af7ec4518d604e0b62c9db Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Wed, 21 Jun 2023 10:34:46 +0200 Subject: [PATCH 06/12] SCORU/Node: move protocol independent RPC directory --- .../protocol_plugin_sig.ml | 23 ++ src/lib_smart_rollup_node/rpc_directory.ml | 298 ++++++++++++++++++ src/lib_smart_rollup_node/rpc_directory.mli | 28 ++ .../lib_sc_rollup_node/RPC_directory.ml | 252 +-------------- .../lib_sc_rollup_node/RPC_directory.mli | 4 - 5 files changed, 350 insertions(+), 255 deletions(-) create mode 100644 src/lib_smart_rollup_node/rpc_directory.ml create mode 100644 src/lib_smart_rollup_node/rpc_directory.mli diff --git a/src/lib_smart_rollup_node/protocol_plugin_sig.ml b/src/lib_smart_rollup_node/protocol_plugin_sig.ml index 9ae5a2329d60..9785d2ccd3fa 100644 --- a/src/lib_smart_rollup_node/protocol_plugin_sig.ml +++ b/src/lib_smart_rollup_node/protocol_plugin_sig.ml @@ -182,6 +182,13 @@ end (** Protocol specific batcher. NOTE: The batcher has to be stopped and the new one restarted on protocol change. *) module type BATCHER = sig + (** The type for the status of messages in the batcher. *) + type status = + | Pending_batch (** The message is in the queue of the batcher. *) + | Batched of Injector.Inj_operation.hash + (** The message has already been batched and sent to the injector in an + L1 operation whose hash is given. *) + (** [init config ~signer node_ctxt] initializes and starts the batcher for [signer]. If [config.simulation] is [true] (the default), messages added to the batcher are simulated in an incremental simulation context. *) @@ -199,6 +206,22 @@ module type BATCHER = sig (** [shutdown ()] stops the batcher, waiting for the ongoing request to be processed. *) val shutdown : unit -> unit Lwt.t + + (** List all queued messages in the order they appear in the queue, i.e. the + message that were added first to the queue are at the end of list. *) + val get_queue : unit -> (L2_message.hash * L2_message.t) list tzresult + + (** [register_messages messages] registers new L2 [messages] in the queue of + the batcher for future injection on L1. If the batcher was initialized + with [simualte = true], the messages are evaluated the batcher's + incremental simulation context. In this case, when the application fails, + the messages are not queued. *) + val register_messages : string list -> L2_message.hash list tzresult Lwt.t + + (** The status of a message in the batcher. Returns [None] if the message is + not known by the batcher (the batcher only keeps the batched status of the + last 500000 messages). *) + val message_status : L2_message.hash -> (status * string) option tzresult end (** Protocol specific functions to interact with the L1 node. *) diff --git a/src/lib_smart_rollup_node/rpc_directory.ml b/src/lib_smart_rollup_node/rpc_directory.ml new file mode 100644 index 000000000000..7ce3d8c47784 --- /dev/null +++ b/src/lib_smart_rollup_node/rpc_directory.ml @@ -0,0 +1,298 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs, *) +(* Copyright (c) 2022-2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Rpc_directory_helpers + +let get_head_hash_opt node_ctxt = + let open Lwt_result_syntax in + let+ res = Node_context.last_processed_head_opt node_ctxt in + Option.map + (fun Sc_rollup_block.{header = {block_hash; _}; _} -> block_hash) + res + +let get_head_level_opt node_ctxt = + let open Lwt_result_syntax in + let+ res = Node_context.last_processed_head_opt node_ctxt in + Option.map (fun Sc_rollup_block.{header = {level; _}; _} -> level) res + +let get_last_proto node_ctxt = + let open Lwt_result_syntax in + let* head = Node_context.last_processed_head_opt node_ctxt in + match head with + | None -> failwith "No processed head, could not determine last protocol" + | Some head -> + let+ proto = Node_context.protocol_of_level node_ctxt head.header.level in + proto.protocol + +let get_last_proto_plugin node_ctxt = + let open Lwt_result_syntax in + let* protocol = get_last_proto node_ctxt in + let*? plugin = Protocol_plugins.proto_plugin_for_protocol protocol in + return plugin + +module Global_directory = Make_directory (struct + include Rollup_node_services.Global + + type context = Node_context.rw + + type subcontext = Node_context.ro + + let context_of_prefix node_ctxt () = + Lwt_result.return (Node_context.readonly node_ctxt) +end) + +module Local_directory = Make_directory (struct + include Rollup_node_services.Local + + type context = Node_context.rw + + type subcontext = Node_context.ro + + let context_of_prefix node_ctxt () = + Lwt_result.return (Node_context.readonly node_ctxt) +end) + +let () = + Global_directory.register0 Rollup_node_services.Global.sc_rollup_address + @@ fun node_ctxt () () -> Lwt_result.return node_ctxt.rollup_address + +let () = + Global_directory.register0 Rollup_node_services.Global.current_tezos_head + @@ fun node_ctxt () () -> get_head_hash_opt node_ctxt + +let () = + Global_directory.register0 Rollup_node_services.Global.current_tezos_level + @@ fun node_ctxt () () -> get_head_level_opt node_ctxt + +let () = + Global_directory.register0 Rollup_node_services.Global.last_stored_commitment + @@ fun node_ctxt () () -> + let open Lwt_result_syntax in + let* head = Node_context.last_processed_head_opt node_ctxt in + match head with + | None -> return_none + | Some head -> + let commitment_hash = + Sc_rollup_block.most_recent_commitment head.header + in + let+ commitment = + Node_context.find_commitment node_ctxt commitment_hash + in + Option.map (fun c -> (c, commitment_hash)) commitment + +let () = + Local_directory.register0 Rollup_node_services.Local.last_published_commitment + @@ fun node_ctxt () () -> + let open Lwt_result_syntax in + match Reference.get node_ctxt.lpc with + | None -> return_none + | Some commitment -> + let hash = Octez_smart_rollup.Commitment.hash commitment in + (* The corresponding level in Store.Commitments.published_at_level is + available only when the commitment has been published and included + in a block. *) + let* published_at_level_info = + Node_context.commitment_published_at_level node_ctxt hash + in + let first_published, published = + match published_at_level_info with + | None -> (None, None) + | Some {first_published_at_level; published_at_level} -> + (Some first_published_at_level, published_at_level) + in + return_some (commitment, hash, first_published, published) + +let () = + Local_directory.register0 Rollup_node_services.Local.injection + @@ fun node_ctxt () messages -> + let open Lwt_result_syntax in + let* (module Plugin) = get_last_proto_plugin node_ctxt in + Plugin.Batcher.register_messages messages + +let () = + Local_directory.register0 Rollup_node_services.Local.batcher_queue + @@ fun node_ctxt () () -> + let open Lwt_result_syntax in + let* (module Plugin) = get_last_proto_plugin node_ctxt in + let*? queue = Plugin.Batcher.get_queue () in + return queue + +(** [commitment_level_of_inbox_level node_ctxt inbox_level] returns the level + of the commitment which should include the inbox of level + [inbox_level]. + + It is computed with the following formula: + {v + commitment_level(inbox_level) = + last_commitment - + ((last_commitment - inbox_level) / commitment_period + * commitment_period) + v} + *) +let commitment_level_of_inbox_level (node_ctxt : _ Node_context.t) inbox_level = + let open Option_syntax in + let+ last_published_commitment = Reference.get node_ctxt.lpc in + let commitment_period = + Int32.of_int + node_ctxt.current_protocol.constants.sc_rollup.commitment_period_in_blocks + in + let last_published = last_published_commitment.inbox_level in + let open Int32 in + div (sub last_published inbox_level) commitment_period + |> mul commitment_period |> sub last_published + +let inbox_info_of_level (node_ctxt : _ Node_context.t) inbox_level = + let open Lwt_result_syntax in + let+ finalized_level = Node_context.get_finalized_level node_ctxt in + let finalized = Compare.Int32.(inbox_level <= finalized_level) in + let lcc = Reference.get node_ctxt.lcc in + let cemented = Compare.Int32.(inbox_level <= lcc.level) in + (finalized, cemented) + +let () = + Local_directory.register1 Rollup_node_services.Local.batcher_message + @@ fun node_ctxt hash () () -> + let open Lwt_result_syntax in + let* (module Plugin) = get_last_proto_plugin node_ctxt in + let*? batch_status = Plugin.Batcher.message_status hash in + let* status = + match batch_status with + | None -> return (None, Rollup_node_services.Unknown) + | Some (batch_status, msg) -> ( + let return status = return (Some msg, status) in + match batch_status with + | Pending_batch -> return Rollup_node_services.Pending_batch + | Batched l1_hash -> ( + match Injector.operation_status l1_hash with + | None -> return Rollup_node_services.Unknown + | Some (Pending op) -> + return (Rollup_node_services.Pending_injection op) + | Some (Injected {op; oph; op_index}) -> + return + (Rollup_node_services.Injected + {op = op.operation; oph; op_index}) + | Some (Included {op; oph; op_index; l1_block; l1_level}) -> ( + let* finalized, cemented = + inbox_info_of_level node_ctxt l1_level + in + let commitment_level = + commitment_level_of_inbox_level node_ctxt l1_level + in + match commitment_level with + | None -> + return + (Rollup_node_services.Included + { + op = op.operation; + oph; + op_index; + l1_block; + l1_level; + finalized; + cemented; + }) + | Some commitment_level -> ( + let* block = + Node_context.find_l2_block_by_level + node_ctxt + commitment_level + in + match block with + | None -> + (* Commitment not computed yet for inbox *) + return + (Rollup_node_services.Included + { + op = op.operation; + oph; + op_index; + l1_block; + l1_level; + finalized; + cemented; + }) + | Some block -> ( + let commitment_hash = + WithExceptions.Option.get + ~loc:__LOC__ + block.header.commitment_hash + in + (* Commitment computed *) + let* published_at = + Node_context.commitment_published_at_level + node_ctxt + commitment_hash + in + match published_at with + | None | Some {published_at_level = None; _} -> + (* Commitment not published yet *) + return + (Rollup_node_services.Included + { + op = op.operation; + oph; + op_index; + l1_block; + l1_level; + finalized; + cemented; + }) + | Some + { + first_published_at_level; + published_at_level = Some published_at_level; + } -> + (* Commitment published *) + let* commitment = + Node_context.get_commitment + node_ctxt + commitment_hash + in + return + (Rollup_node_services.Committed + { + op = op.operation; + oph; + op_index; + l1_block; + l1_level; + finalized; + cemented; + commitment; + commitment_hash; + first_published_at_level; + published_at_level; + })))))) + in + + return status + +let top_directory (node_ctxt : _ Node_context.t) = + List.fold_left + (fun dir f -> Tezos_rpc.Directory.merge dir (f node_ctxt)) + Tezos_rpc.Directory.empty + [Global_directory.build_directory; Local_directory.build_directory] diff --git a/src/lib_smart_rollup_node/rpc_directory.mli b/src/lib_smart_rollup_node/rpc_directory.mli new file mode 100644 index 000000000000..4283be8ed0f7 --- /dev/null +++ b/src/lib_smart_rollup_node/rpc_directory.mli @@ -0,0 +1,28 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** The RPC top level directory (without the block directory) for this rollup + node. *) +val top_directory : Node_context.rw -> unit Tezos_rpc.Directory.t diff --git a/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml b/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml index 05cc7b273a49..02e1beab7f40 100644 --- a/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml +++ b/src/proto_alpha/lib_sc_rollup_node/RPC_directory.ml @@ -28,18 +28,6 @@ open Rpc_directory_helpers open Protocol -let get_head_hash_opt node_ctxt = - let open Lwt_result_syntax in - let+ res = Node_context.last_processed_head_opt node_ctxt in - Option.map - (fun Sc_rollup_block.{header = {block_hash; _}; _} -> block_hash) - res - -let get_head_level_opt node_ctxt = - let open Lwt_result_syntax in - let+ res = Node_context.last_processed_head_opt node_ctxt in - Option.map (fun Sc_rollup_block.{header = {level; _}; _} -> level) res - module Slot_pages_map = struct open Protocol open Alpha_context @@ -49,26 +37,6 @@ end let get_dal_processed_slots node_ctxt block = Node_context.list_slots_statuses node_ctxt ~confirmed_in_block_hash:block -module Global_directory = Make_directory (struct - include Rollup_node_services.Global - - type context = Node_context.rw - - type subcontext = Node_context.ro - - let context_of_prefix node_ctxt () = return (Node_context.readonly node_ctxt) -end) - -module Local_directory = Make_directory (struct - include Rollup_node_services.Local - - type context = Node_context.rw - - type subcontext = Node_context.ro - - let context_of_prefix node_ctxt () = return (Node_context.readonly node_ctxt) -end) - module Block_directory = Make_sub_directory (struct include Sc_rollup_services.Block @@ -115,19 +83,6 @@ module Common = struct in Z.of_int num_messages - let () = - Global_directory.register0 Rollup_node_services.Global.sc_rollup_address - @@ fun node_ctxt () () -> - return @@ Sc_rollup_proto_types.Address.of_octez node_ctxt.rollup_address - - let () = - Global_directory.register0 Rollup_node_services.Global.current_tezos_head - @@ fun node_ctxt () () -> get_head_hash_opt node_ctxt - - let () = - Global_directory.register0 Rollup_node_services.Global.current_tezos_level - @@ fun node_ctxt () () -> get_head_level_opt node_ctxt - let () = Block_directory.register0 Sc_rollup_services.Block.hash @@ fun (_node_ctxt, block) () () -> return block @@ -256,44 +211,6 @@ let () = Format.eprintf "Encoded %S\n@.%!" (Bytes.to_string value) ; return value -let () = - Global_directory.register0 Rollup_node_services.Global.last_stored_commitment - @@ fun node_ctxt () () -> - let open Lwt_result_syntax in - let* head = Node_context.last_processed_head_opt node_ctxt in - match head with - | None -> return_none - | Some head -> - let commitment_hash = - Sc_rollup_block.most_recent_commitment head.header - in - let+ commitment = - Node_context.find_commitment node_ctxt commitment_hash - in - Option.map (fun c -> (c, commitment_hash)) commitment - -let () = - Local_directory.register0 Rollup_node_services.Local.last_published_commitment - @@ fun node_ctxt () () -> - let open Lwt_result_syntax in - match Reference.get node_ctxt.lpc with - | None -> return_none - | Some commitment -> - let hash = Octez_smart_rollup.Commitment.hash commitment in - (* The corresponding level in Store.Commitments.published_at_level is - available only when the commitment has been published and included - in a block. *) - let* published_at_level_info = - Node_context.commitment_published_at_level node_ctxt hash - in - let first_published, published = - match published_at_level_info with - | None -> (None, None) - | Some {first_published_at_level; published_at_level} -> - (Some first_published_at_level, published_at_level) - in - return_some (commitment, hash, first_published, published) - let () = Block_directory.register0 Sc_rollup_services.Block.status @@ fun (node_ctxt, block) () () -> @@ -350,167 +267,6 @@ let () = @@ fun (node_ctxt, block) () {messages; reveal_pages; insight_requests} -> simulate_messages node_ctxt block ~reveal_pages ~insight_requests messages -let () = - Local_directory.register0 Rollup_node_services.Local.injection - @@ fun _node_ctxt () messages -> Batcher.register_messages messages - -let () = - Local_directory.register0 Rollup_node_services.Local.batcher_queue - @@ fun _node_ctxt () () -> - let open Lwt_result_syntax in - let*? queue = Batcher.get_queue () in - return queue - -(** [commitment_level_of_inbox_level node_ctxt inbox_level] returns the level - of the commitment which should include the inbox of level - [inbox_level]. - - It is computed with the following formula: - {v - commitment_level(inbox_level) = - last_commitment - - ((last_commitment - inbox_level) / commitment_period - * commitment_period) - v} - *) -let commitment_level_of_inbox_level (node_ctxt : _ Node_context.t) inbox_level = - let open Alpha_context in - let open Option_syntax in - let+ last_published_commitment = Reference.get node_ctxt.lpc in - let commitment_period = - Int32.of_int - node_ctxt.current_protocol.constants.sc_rollup.commitment_period_in_blocks - in - let last_published = last_published_commitment.inbox_level in - let open Int32 in - div (sub last_published inbox_level) commitment_period - |> mul commitment_period |> sub last_published |> Raw_level.of_int32_exn - -let inbox_info_of_level (node_ctxt : _ Node_context.t) inbox_level = - let open Lwt_result_syntax in - let+ finalized_level = Node_context.get_finalized_level node_ctxt in - let finalized = Compare.Int32.(inbox_level <= finalized_level) in - let lcc = Reference.get node_ctxt.lcc in - let cemented = Compare.Int32.(inbox_level <= lcc.level) in - (finalized, cemented) - -let () = - Local_directory.register1 Rollup_node_services.Local.batcher_message - @@ fun node_ctxt hash () () -> - let open Lwt_result_syntax in - let*? batch_status = Batcher.message_status hash in - let* status = - match batch_status with - | None -> return (None, Rollup_node_services.Unknown) - | Some (batch_status, msg) -> ( - let return status = return (Some msg, status) in - match batch_status with - | Pending_batch -> return Rollup_node_services.Pending_batch - | Batched l1_hash -> ( - match Injector.operation_status l1_hash with - | None -> return Rollup_node_services.Unknown - | Some (Pending op) -> - return (Rollup_node_services.Pending_injection op) - | Some (Injected {op; oph; op_index}) -> - return - (Rollup_node_services.Injected - {op = op.operation; oph; op_index}) - | Some (Included {op; oph; op_index; l1_block; l1_level}) -> ( - let* finalized, cemented = - inbox_info_of_level node_ctxt l1_level - in - let commitment_level = - commitment_level_of_inbox_level node_ctxt l1_level - in - match commitment_level with - | None -> - return - (Rollup_node_services.Included - { - op = op.operation; - oph; - op_index; - l1_block; - l1_level; - finalized; - cemented; - }) - | Some commitment_level -> ( - let* block = - Node_context.find_l2_block_by_level - node_ctxt - (Alpha_context.Raw_level.to_int32 commitment_level) - in - match block with - | None -> - (* Commitment not computed yet for inbox *) - return - (Rollup_node_services.Included - { - op = op.operation; - oph; - op_index; - l1_block; - l1_level; - finalized; - cemented; - }) - | Some block -> ( - let commitment_hash = - WithExceptions.Option.get - ~loc:__LOC__ - block.header.commitment_hash - in - (* Commitment computed *) - let* published_at = - Node_context.commitment_published_at_level - node_ctxt - commitment_hash - in - match published_at with - | None | Some {published_at_level = None; _} -> - (* Commitment not published yet *) - return - (Rollup_node_services.Included - { - op = op.operation; - oph; - op_index; - l1_block; - l1_level; - finalized; - cemented; - }) - | Some - { - first_published_at_level; - published_at_level = Some published_at_level; - } -> - (* Commitment published *) - let* commitment = - Node_context.get_commitment - node_ctxt - commitment_hash - in - return - (Rollup_node_services.Committed - { - op = op.operation; - oph; - op_index; - l1_block; - l1_level; - finalized; - cemented; - commitment; - commitment_hash; - first_published_at_level; - published_at_level; - })))))) - in - - return status - let block_directory (node_ctxt : _ Node_context.t) = let module PVM = (val Pvm_rpc.of_kind node_ctxt.kind) in List.fold_left @@ -522,15 +278,9 @@ let block_directory (node_ctxt : _ Node_context.t) = PVM.build_sub_directory; ] -let top_directory (node_ctxt : _ Node_context.t) = - List.fold_left - (fun dir f -> Tezos_rpc.Directory.merge dir (f node_ctxt)) - Tezos_rpc.Directory.empty - [Global_directory.build_directory; Local_directory.build_directory] - let directory (node_ctxt : _ Node_context.t) = Tezos_rpc.Directory.merge - (top_directory node_ctxt) + (Octez_smart_rollup_node.Rpc_directory.top_directory node_ctxt) (Tezos_rpc.Directory.prefix Sc_rollup_services.Block.prefix (block_directory node_ctxt)) diff --git a/src/proto_alpha/lib_sc_rollup_node/RPC_directory.mli b/src/proto_alpha/lib_sc_rollup_node/RPC_directory.mli index 44dffc1d7ddf..1cac46c2ded4 100644 --- a/src/proto_alpha/lib_sc_rollup_node/RPC_directory.mli +++ b/src/proto_alpha/lib_sc_rollup_node/RPC_directory.mli @@ -28,10 +28,6 @@ val block_directory : Node_context.rw -> (unit * Rollup_node_services.Arg.block_id) Tezos_rpc.Directory.t -(** The RPC top level directory (without the block directory) for this rollup - node. *) -val top_directory : Node_context.rw -> unit Tezos_rpc.Directory.t - (** The full RPC directory for this rollup node, merging the top level directory and the block directory. *) val directory : Node_context.rw -> unit Tezos_rpc.Directory.t -- GitLab From 0365696d7e51355cfe7721828ca0b8c2f1e6b7eb Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 20 Jun 2023 10:57:06 +0200 Subject: [PATCH 07/12] SCORU/Node/Nairobi: keep only protocol specific block directory Backports the following commits: - SCORU/Node/RPC: move proof helper RPC under /global/block/{b}/helpers - SCORU/Node: split RPC services in proto and non proto specific parts - SCORU/Node: move protocol independent RPC directory --- .../lib_sc_rollup_client/RPC.ml | 15 +- .../lib_sc_rollup_client/commands.ml | 4 +- .../sc_rollup_services.ml | 698 ++++-------------- .../lib_sc_rollup_node/RPC_directory.ml | 332 +-------- .../lib_sc_rollup_node/RPC_directory.mli | 8 +- .../lib_sc_rollup_node/pvm_rpc.ml | 6 +- .../lib_sc_rollup_node/wasm_2_0_0_rpc.ml | 16 +- 7 files changed, 229 insertions(+), 850 deletions(-) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_client/RPC.ml b/src/proto_017_PtNairob/lib_sc_rollup_client/RPC.ml index 98ad7f965b46..2f491d40e44a 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_client/RPC.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_client/RPC.ml @@ -23,15 +23,22 @@ (* *) (*****************************************************************************) +module Block_services = + Rollup_node_services.Make_services (Sc_rollup_services.Block) + let get_sc_rollup_addresses_command cctxt = - Sc_rollup_services.Global.(make_call sc_rollup_address) cctxt () () () + Rollup_node_services.Global.(make_call sc_rollup_address) cctxt () () () let get_state_value_command cctxt block key = - Sc_rollup_services.Global.Block.(make_call1 state_value) cctxt block {key} () + Block_services.(make_call1 Sc_rollup_services.Block.state_value) + cctxt + block + {key} + () let get_outbox_proof cctxt serialized_output = - Sc_rollup_services.Global.Helpers.(make_call outbox_proof) + Block_services.(make_call Sc_rollup_services.Block.Helpers.outbox_proof) cctxt - () + ((), `Head) serialized_output () diff --git a/src/proto_017_PtNairob/lib_sc_rollup_client/commands.ml b/src/proto_017_PtNairob/lib_sc_rollup_client/commands.ml index 3ac7a98ca0df..653ff47dee96 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_client/commands.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_client/commands.ml @@ -40,7 +40,7 @@ let block_arg = (String.concat ", " possible_block_ids)) (Tezos_clic.parameter (fun _ s -> - match Sc_rollup_services.Arg.destruct_block_id s with + match Rollup_node_services.Arg.destruct_block_id s with | Ok b -> return b | Error reason -> failwith "Invalid block id: %s" reason) ~autocomplete:(fun _ -> return possible_block_ids)) @@ -52,7 +52,7 @@ let get_sc_rollup_addresses_command () = (Tezos_clic.fixed ["get"; "smart"; "rollup"; "address"]) (fun () (cctxt : #Configuration.sc_client_context) -> RPC.get_sc_rollup_addresses_command cctxt >>=? fun addr -> - cctxt#message "@[%a@]" Sc_rollup.Address.pp addr >>= fun () -> return_unit) + cctxt#message "@[%a@]" Address.pp addr >>= fun () -> return_unit) let get_state_value_command () = Tezos_clic.command diff --git a/src/proto_017_PtNairob/lib_sc_rollup_layer2/sc_rollup_services.ml b/src/proto_017_PtNairob/lib_sc_rollup_layer2/sc_rollup_services.ml index b6539529a288..04cb4c46665a 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_layer2/sc_rollup_services.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_layer2/sc_rollup_services.ml @@ -3,6 +3,7 @@ (* Open Source License *) (* Copyright (c) 2021 Nomadic Labs, *) (* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -26,28 +27,6 @@ open Protocol.Alpha_context -(* We distinguish RPC endpoints served by the rollup node into `global` and - `local`. The difference between the two lies in whether the responses - given by different rollup nodes in the same state (see below for an - exact definition) must be the same (in the case of global endpoints) - or can differ (in the case of local endpoints). - - More formally, two rollup nodes are in the same quiescent state if they are - subscribed to the same rollup address, and have processed the same set of - heads from the layer1. We only consider quiescent states, that is those - where rollup nodes are not actively processing a head received from layer1. - - Examples of global endpoints are `current_inbox` and - `last_stored_commitment`, as the responses returned by these endpoints - is expected to be consistent across rollup nodes in the same state. - - An example of local endpoint is `last_published_commitments`, as two rollup - nodes in the same state may either publish or not publish a commitment, - according to whether its inbox level is below the inbox level of the - last cemented commitment at the time they tried to publish the commitment. - See below for a more detailed explanation. -*) - type eval_result = { state_hash : Sc_rollup.State_hash.t; status : string; @@ -76,50 +55,10 @@ type commitment_info = { published_at_level : Raw_level.t; } -type message_status = - | Unknown - | Pending_batch - | Pending_injection of L1_operation.t - | Injected of {op : L1_operation.t; oph : Operation_hash.t; op_index : int} - | Included of { - op : L1_operation.t; - oph : Operation_hash.t; - op_index : int; - l1_block : Block_hash.t; - l1_level : int32; - finalized : bool; - cemented : bool; - } - | Committed of { - op : L1_operation.t; - oph : Operation_hash.t; - op_index : int; - l1_block : Block_hash.t; - l1_level : int32; - finalized : bool; - cemented : bool; - commitment : Octez_smart_rollup.Commitment.t; - commitment_hash : Octez_smart_rollup.Commitment.Hash.t; - first_published_at_level : int32; - published_at_level : int32; - } - module Encodings = struct open Data_encoding - let commitment_with_hash = - obj2 - (req "commitment" Octez_smart_rollup.Commitment.encoding) - (req "hash" Octez_smart_rollup.Commitment.Hash.encoding) - - let commitment_with_hash_and_level_infos = - obj4 - (req "commitment" Octez_smart_rollup.Commitment.encoding) - (req "hash" Octez_smart_rollup.Commitment.Hash.encoding) - (opt "first_published_at_level" int32) - (opt "published_at_level" int32) - - let hex_string = conv Bytes.of_string Bytes.to_string bytes + let hex_string = string' Hex let eval_result = conv @@ -195,13 +134,6 @@ module Encodings = struct [] ~description:"Paths in the PVM to inspect after the simulation") - let queued_message = - obj2 - (req "hash" L2_message.Hash.encoding) - (req "message" L2_message.encoding) - - let batcher_queue = list queued_message - let commitment_info = conv (fun { @@ -229,197 +161,6 @@ module Encodings = struct (req "hash" Sc_rollup.Commitment.Hash.encoding) (req "first_published_at_level" Raw_level.encoding) (req "published_at_level" Raw_level.encoding) - - let message_status = - union - [ - case - (Tag 0) - ~title:"unknown" - ~description:"The message is not known by the batcher." - (obj1 (req "status" (constant "unknown"))) - (function Unknown -> Some () | _ -> None) - (fun () -> Unknown); - case - (Tag 1) - ~title:"pending_batch" - ~description:"The message is in the batcher queue." - (obj1 (req "status" (constant "pending_batch"))) - (function Pending_batch -> Some () | _ -> None) - (fun () -> Pending_batch); - case - (Tag 2) - ~title:"pending_injection" - ~description:"The message is batched but not injected yet." - (obj2 - (req "status" (constant "pending_injection")) - (req "operation" L1_operation.encoding)) - (function Pending_injection op -> Some ((), op) | _ -> None) - (fun ((), op) -> Pending_injection op); - case - (Tag 3) - ~title:"injected" - ~description: - "The message is injected as part of an L1 operation but it is not \ - included in a block." - (obj3 - (req "status" (constant "injected")) - (req "operation" L1_operation.encoding) - (req - "layer1" - (obj2 - (req "operation_hash" Operation_hash.encoding) - (req "operation_index" int31)))) - (function - | Injected {op; oph; op_index} -> Some ((), op, (oph, op_index)) - | _ -> None) - (fun ((), op, (oph, op_index)) -> Injected {op; oph; op_index}); - case - (Tag 4) - ~title:"included" - ~description:"The message is included in an inbox in an L1 block." - (obj5 - (req "status" (constant "included")) - (req "operation" L1_operation.encoding) - (req - "layer1" - (obj4 - (req "operation_hash" Operation_hash.encoding) - (req "operation_index" int31) - (req "block_hash" Block_hash.encoding) - (req "level" int32))) - (req "finalized" bool) - (req "cemented" bool)) - (function - | Included - {op; oph; op_index; l1_block; l1_level; finalized; cemented} -> - Some - ( (), - op, - (oph, op_index, l1_block, l1_level), - finalized, - cemented ) - | _ -> None) - (fun ((), op, (oph, op_index, l1_block, l1_level), finalized, cemented) - -> - Included - {op; oph; op_index; l1_block; l1_level; finalized; cemented}); - case - (Tag 5) - ~title:"committed" - ~description:"The message is included in a committed inbox on L1." - (obj9 - (req "status" (constant "committed")) - (req "operation" L1_operation.encoding) - (req - "layer1" - (obj4 - (req "operation_hash" Operation_hash.encoding) - (req "operation_index" int31) - (req "block_hash" Block_hash.encoding) - (req "level" int32))) - (req "finalized" bool) - (req "cemented" bool) - (req "commitment" Octez_smart_rollup.Commitment.encoding) - (req "hash" Octez_smart_rollup.Commitment.Hash.encoding) - (req "first_published_at_level" int32) - (req "published_at_level" int32)) - (function - | Committed - { - op; - oph; - op_index; - l1_block; - l1_level; - finalized; - cemented; - commitment; - commitment_hash; - first_published_at_level; - published_at_level; - } -> - Some - ( (), - op, - (oph, op_index, l1_block, l1_level), - finalized, - cemented, - commitment, - commitment_hash, - first_published_at_level, - published_at_level ) - | _ -> None) - (fun ( (), - op, - (oph, op_index, l1_block, l1_level), - finalized, - cemented, - commitment, - commitment_hash, - first_published_at_level, - published_at_level ) -> - Committed - { - op; - oph; - op_index; - l1_block; - l1_level; - finalized; - cemented; - commitment; - commitment_hash; - first_published_at_level; - published_at_level; - }); - ] - - let message_status_output = - merge_objs (obj1 (opt "content" hex_string)) message_status -end - -module Arg = struct - type block_id = - [`Head | `Hash of Block_hash.t | `Level of Int32.t | `Finalized | `Cemented] - - let construct_block_id = function - | `Head -> "head" - | `Hash h -> Block_hash.to_b58check h - | `Level l -> Int32.to_string l - | `Finalized -> "finalized" - | `Cemented -> "cemented" - - let destruct_block_id h = - match h with - | "head" -> Ok `Head - | "finalized" -> Ok `Finalized - | "cemented" -> Ok `Cemented - | _ -> ( - match Int32.of_string_opt h with - | Some l -> Ok (`Level l) - | None -> ( - match Block_hash.of_b58check_opt h with - | Some b -> Ok (`Hash b) - | None -> Error "Cannot parse block id")) - - let block_id : block_id Tezos_rpc.Arg.t = - Tezos_rpc.Arg.make - ~descr:"An L1 block identifier." - ~name:"block_id" - ~construct:construct_block_id - ~destruct:destruct_block_id - () - - let l2_message_hash : L2_message.hash Tezos_rpc.Arg.t = - Tezos_rpc.Arg.make - ~descr:"A L2 message hash." - ~name:"l2_message_hash" - ~construct:L2_message.Hash.to_b58check - ~destruct:(fun s -> - L2_message.Hash.of_b58check_opt s - |> Option.to_result ~none:"Invalid L2 message hash") - () end module Query = struct @@ -487,27 +228,6 @@ module Query = struct |> seal end -module type PREFIX = sig - type prefix - - val prefix : (unit, prefix) Tezos_rpc.Path.t -end - -module Make_services (P : PREFIX) = struct - include P - - let path : prefix Tezos_rpc.Path.context = Tezos_rpc.Path.open_root - - let make_call s = - Tezos_rpc.Context.make_call (Tezos_rpc.Service.prefix prefix s) - - let make_call1 s = - Tezos_rpc.Context.make_call1 (Tezos_rpc.Service.prefix prefix s) - - let make_call2 s = - Tezos_rpc.Context.make_call2 (Tezos_rpc.Service.prefix prefix s) -end - type simulate_query = {fuel : int64 option} let simulate_query : simulate_query Tezos_rpc.Query.t = @@ -516,299 +236,193 @@ let simulate_query : simulate_query Tezos_rpc.Query.t = |+ opt_field "fuel" Tezos_rpc.Arg.int64 (fun t -> t.fuel) |> seal -module Global = struct +module Block = struct open Tezos_rpc.Path - include Make_services (struct - type prefix = unit + type prefix = unit * Rollup_node_services.Arg.block_id + + let path : prefix Tezos_rpc.Path.context = open_root - let prefix = open_root / "global" - end) + let prefix = root / "global" / "block" /: Rollup_node_services.Arg.block_id - let sc_rollup_address = + let block = Tezos_rpc.Service.get_service - ~description:"Smart rollup address" + ~description: + "Layer-2 block of the layer-2 chain with respect to a Layer 1 block \ + identifier" ~query:Tezos_rpc.Query.empty - ~output:Sc_rollup.Address.encoding - (path / "smart_rollup_address") + ~output:Sc_rollup_block.full_encoding + path - let current_tezos_head = + let hash = Tezos_rpc.Service.get_service - ~description:"Tezos head known to the smart rollup node" + ~description:"Tezos block hash of block known to the smart rollup node" ~query:Tezos_rpc.Query.empty - ~output:(Data_encoding.option Block_hash.encoding) - (path / "tezos_head") + ~output:Block_hash.encoding + (path / "hash") - let current_tezos_level = + let level = Tezos_rpc.Service.get_service - ~description:"Tezos level known to the smart rollup node" + ~description:"Level of Tezos block known to the smart rollup node" ~query:Tezos_rpc.Query.empty - ~output:(Data_encoding.option Data_encoding.int32) - (path / "tezos_level") + ~output:Data_encoding.int32 + (path / "level") - let last_stored_commitment = + let inbox = Tezos_rpc.Service.get_service - ~description:"Last commitment computed by the node" + ~description:"Rollup inbox for block" ~query:Tezos_rpc.Query.empty - ~output:(Data_encoding.option Encodings.commitment_with_hash) - (path / "last_stored_commitment") - - module Helpers = struct - include Make_services (struct - type prefix = unit - - let prefix = open_root / "helpers" - end) - - let outbox_proof = - Tezos_rpc.Service.get_service - ~description:"Generate serialized output proof for some outbox message" - ~query:Query.outbox_proof_query - ~output: - Data_encoding.( - obj2 - (req "commitment" Sc_rollup.Commitment.Hash.encoding) - (req "proof" Encodings.hex_string)) - (path / "proofs" / "outbox") - end - - module Block = struct - include Make_services (struct - type prefix = unit * Arg.block_id - - let prefix = prefix / "block" /: Arg.block_id - end) - - let block = - Tezos_rpc.Service.get_service - ~description: - "Layer-2 block of the layer-2 chain with respect to a Layer 1 block \ - identifier" - ~query:Tezos_rpc.Query.empty - ~output:Sc_rollup_block.full_encoding - path - - let hash = - Tezos_rpc.Service.get_service - ~description:"Tezos block hash of block known to the smart rollup node" - ~query:Tezos_rpc.Query.empty - ~output:Block_hash.encoding - (path / "hash") - - let level = - Tezos_rpc.Service.get_service - ~description:"Level of Tezos block known to the smart rollup node" - ~query:Tezos_rpc.Query.empty - ~output:Data_encoding.int32 - (path / "level") - - let inbox = - Tezos_rpc.Service.get_service - ~description:"Rollup inbox for block" - ~query:Tezos_rpc.Query.empty - ~output:Octez_smart_rollup.Inbox.encoding - (path / "inbox") - - let ticks = - Tezos_rpc.Service.get_service - ~description:"Number of ticks for specified level" - ~query:Tezos_rpc.Query.empty - ~output:Data_encoding.z - (path / "ticks") + ~output:Octez_smart_rollup.Inbox.encoding + (path / "inbox") - let total_ticks = - Tezos_rpc.Service.get_service - ~description:"Total number of ticks at specified block" - ~query:Tezos_rpc.Query.empty - ~output:Sc_rollup.Tick.encoding - (path / "total_ticks") - - let num_messages = - Tezos_rpc.Service.get_service - ~description:"Number of messages for specified block" - ~query:Tezos_rpc.Query.empty - ~output:Data_encoding.z - (path / "num_messages") + let ticks = + Tezos_rpc.Service.get_service + ~description:"Number of ticks for specified level" + ~query:Tezos_rpc.Query.empty + ~output:Data_encoding.z + (path / "ticks") - let state_hash = - Tezos_rpc.Service.get_service - ~description:"State hash for this block" - ~query:Tezos_rpc.Query.empty - ~output:Sc_rollup.State_hash.encoding - (path / "state_hash") + let total_ticks = + Tezos_rpc.Service.get_service + ~description:"Total number of ticks at specified block" + ~query:Tezos_rpc.Query.empty + ~output:Sc_rollup.Tick.encoding + (path / "total_ticks") - let state_current_level = - Tezos_rpc.Service.get_service - ~description:"Retrieve the current level of a PVM" - ~query:Tezos_rpc.Query.empty - ~output:(Data_encoding.option Raw_level.encoding) - (path / "state_current_level") + let num_messages = + Tezos_rpc.Service.get_service + ~description:"Number of messages for specified block" + ~query:Tezos_rpc.Query.empty + ~output:Data_encoding.z + (path / "num_messages") - let state_value = - Tezos_rpc.Service.get_service - ~description:"Retrieve value from key is PVM state of specified block" - ~query:Query.key_query - ~output:Data_encoding.bytes - (path / "state") + let state_hash = + Tezos_rpc.Service.get_service + ~description:"State hash for this block" + ~query:Tezos_rpc.Query.empty + ~output:Sc_rollup.State_hash.encoding + (path / "state_hash") - let durable_state_value (pvm_kind : Sc_rollup.Kind.t) = - Tezos_rpc.Service.get_service - ~description: - "Retrieve value by key from PVM durable storage. PVM state is taken \ - with respect to the specified block level. Value returned in hex \ - format." - ~query:Query.key_query - ~output:Data_encoding.(option bytes) - (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "value") - - let durable_state_length - (pvm_kind : Protocol.Alpha_context.Sc_rollup.Kind.t) = - Tezos_rpc.Service.get_service - ~description: - "Retrieve number of bytes in raw representation of value by key from \ - PVM durable storage. PVM state is taken with respect to the \ - specified block level." - ~query:Query.key_query - ~output:Data_encoding.(option int64) - (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "length") - - let durable_state_subkeys (pvm_kind : Sc_rollup.Kind.t) = - Tezos_rpc.Service.get_service - ~description: - "Retrieve subkeys of the specified key from PVM durable storage. PVM \ - state is taken with respect to the specified block level." - ~query:Query.key_query - ~output:Data_encoding.(list string) - (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "subkeys") - - let status = - Tezos_rpc.Service.get_service - ~description:"PVM status at block" - ~query:Tezos_rpc.Query.empty - ~output:Data_encoding.string - (path / "status") + let state_current_level = + Tezos_rpc.Service.get_service + ~description:"Retrieve the current level of a PVM" + ~query:Tezos_rpc.Query.empty + ~output:(Data_encoding.option Raw_level.encoding) + (path / "state_current_level") - let outbox = - Tezos_rpc.Service.get_service - ~description:"Outbox at block for a given outbox level" - ~query:Query.outbox_level_query - ~output:Data_encoding.(list Sc_rollup.output_encoding) - (path / "outbox") - - let simulate = - Tezos_rpc.Service.post_service - ~description:"Simulate messages evaluation by the PVM" - ~query:Tezos_rpc.Query.empty - ~input:Encodings.simulate_input - ~output:Encodings.eval_result - (path / "simulate") - - let dal_slots = - Tezos_rpc.Service.get_service - ~description:"Availability slots for a given block" - ~query:Tezos_rpc.Query.empty - ~output:(Data_encoding.list Dal.Slot.Header.encoding) - (path / "dal" / "slot_headers") + let state_value = + Tezos_rpc.Service.get_service + ~description:"Retrieve value from key is PVM state of specified block" + ~query:Query.key_query + ~output:Data_encoding.bytes + (path / "state") - let dal_slot_status_encoding : [`Confirmed | `Unconfirmed] Data_encoding.t = - Data_encoding.string_enum - [("confirmed", `Confirmed); ("unconfirmed", `Unconfirmed)] + let durable_state_value (pvm_kind : Sc_rollup.Kind.t) = + Tezos_rpc.Service.get_service + ~description: + "Retrieve value by key from PVM durable storage. PVM state is taken \ + with respect to the specified block level. Value returned in hex \ + format." + ~query:Query.key_query + ~output:Data_encoding.(option bytes) + (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "value") + + let durable_state_length (pvm_kind : Protocol.Alpha_context.Sc_rollup.Kind.t) + = + Tezos_rpc.Service.get_service + ~description: + "Retrieve number of bytes in raw representation of value by key from \ + PVM durable storage. PVM state is taken with respect to the specified \ + block level." + ~query:Query.key_query + ~output:Data_encoding.(option int64) + (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "length") + + let durable_state_subkeys (pvm_kind : Sc_rollup.Kind.t) = + Tezos_rpc.Service.get_service + ~description: + "Retrieve subkeys of the specified key from PVM durable storage. PVM \ + state is taken with respect to the specified block level." + ~query:Query.key_query + ~output:Data_encoding.(list string) + (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "subkeys") + + let status = + Tezos_rpc.Service.get_service + ~description:"PVM status at block" + ~query:Tezos_rpc.Query.empty + ~output:Data_encoding.string + (path / "status") - let dal_processed_slots = - Tezos_rpc.Service.get_service - ~description:"Data availability processed slots and their statuses" - ~query:Tezos_rpc.Query.empty - ~output: - Data_encoding.( - list - @@ obj2 (req "index" int31) (req "status" dal_slot_status_encoding)) - (path / "dal" / "processed_slots") - - module Outbox = struct - let level_param = - let destruct s = - match Int32.of_string_opt s with - | None -> Error "Invalid level" - | Some l -> ( - match Raw_level.of_int32 l with - | Error _ -> Error "Invalid level" - | Ok l -> Ok l) - in - let construct = Format.asprintf "%a" Raw_level.pp in - Tezos_rpc.Arg.make ~name:"level" ~construct ~destruct () - - include Make_services (struct - type nonrec prefix = prefix * Raw_level.t - - let prefix = prefix / "outbox" /: level_param - end) - - let messages = - Tezos_rpc.Service.get_service - ~description:"Outbox at block for a given outbox level" - ~query:Tezos_rpc.Query.empty - ~output:Data_encoding.(list Sc_rollup.output_encoding) - (path / "messages") - end - end -end + let outbox = + Tezos_rpc.Service.get_service + ~description:"Outbox at block for a given outbox level" + ~query:Query.outbox_level_query + ~output:Data_encoding.(list Sc_rollup.output_encoding) + (path / "outbox") -module Local = struct - open Tezos_rpc.Path + let simulate = + Tezos_rpc.Service.post_service + ~description:"Simulate messages evaluation by the PVM" + ~query:Tezos_rpc.Query.empty + ~input:Encodings.simulate_input + ~output:Encodings.eval_result + (path / "simulate") - include Make_services (struct - type prefix = unit - - let prefix = open_root / "local" - end) - - (* commitments are published only if their inbox level is above the last - cemented commitment level inbox level. Because this information is - fetched from the head of the tezos node to which the rollup node is - connected, it is possible that two rollup nodes that have processed - the same set of heads, but whose corresponding layer1 node has - different information about the last cemented commitment, will - decide to publish and not to publish a commitment, respectively. - As a consequence, the results returned by the endpoint below - in the rollup node will be different. - *) - let last_published_commitment = + let dal_slots = Tezos_rpc.Service.get_service - ~description:"Last commitment published by the node" + ~description:"Availability slots for a given block" ~query:Tezos_rpc.Query.empty - ~output: - (Data_encoding.option Encodings.commitment_with_hash_and_level_infos) - (path / "last_published_commitment") + ~output:(Data_encoding.list Dal.Slot.Header.encoding) + (path / "dal" / "slot_headers") - let injection = - Tezos_rpc.Service.post_service - ~description:"Inject messages in the batcher's queue" + let dal_slot_status_encoding : [`Confirmed | `Unconfirmed] Data_encoding.t = + Data_encoding.string_enum + [("confirmed", `Confirmed); ("unconfirmed", `Unconfirmed)] + + let dal_processed_slots = + Tezos_rpc.Service.get_service + ~description:"Data availability processed slots and their statuses" ~query:Tezos_rpc.Query.empty - ~input: - Data_encoding.( - def - "messages" - ~description:"Messages to inject" - (list L2_message.content_encoding)) ~output: Data_encoding.( - def - "message_hashes" - ~description:"Hashes of injected L2 messages" - (list L2_message.Hash.encoding)) - (path / "batcher" / "injection") + list + @@ obj2 (req "index" int31) (req "status" dal_slot_status_encoding)) + (path / "dal" / "processed_slots") + + let level_param = + let destruct s = + match Int32.of_string_opt s with + | None -> Error "Invalid level" + | Some l -> ( + match Raw_level.of_int32 l with + | Error _ -> Error "Invalid level" + | Ok l -> Ok l) + in + let construct = Format.asprintf "%a" Raw_level.pp in + Tezos_rpc.Arg.make ~name:"level" ~construct ~destruct () - let batcher_queue = + let outbox_messages = Tezos_rpc.Service.get_service - ~description:"List messages present in the batcher's queue" + ~description:"Outbox at block for a given outbox level" ~query:Tezos_rpc.Query.empty - ~output:Encodings.batcher_queue - (path / "batcher" / "queue") + ~output:Data_encoding.(list Sc_rollup.output_encoding) + (path / "outbox" /: level_param / "messages") - let batcher_message = - Tezos_rpc.Service.get_service - ~description:"Retrieve an L2 message and its status" - ~query:Tezos_rpc.Query.empty - ~output:Encodings.message_status_output - (path / "batcher" / "queue" /: Arg.l2_message_hash) + module Helpers = struct + type nonrec prefix = prefix + + let path = path / "helpers" + + let outbox_proof = + Tezos_rpc.Service.get_service + ~description:"Generate serialized output proof for some outbox message" + ~query:Query.outbox_proof_query + ~output: + Data_encoding.( + obj2 + (req "commitment" Sc_rollup.Commitment.Hash.encoding) + (req "proof" Encodings.hex_string)) + (path / "proofs" / "outbox") + end end diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_directory.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_directory.ml index 757611ac0d02..3f57f74af55a 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_directory.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_directory.ml @@ -28,18 +28,6 @@ open Rpc_directory_helpers open Protocol -let get_head_hash_opt node_ctxt = - let open Lwt_result_syntax in - let+ res = Node_context.last_processed_head_opt node_ctxt in - Option.map - (fun Sc_rollup_block.{header = {block_hash; _}; _} -> block_hash) - res - -let get_head_level_opt node_ctxt = - let open Lwt_result_syntax in - let+ res = Node_context.last_processed_head_opt node_ctxt in - Option.map (fun Sc_rollup_block.{header = {level; _}; _} -> level) res - module Slot_pages_map = struct open Protocol open Alpha_context @@ -49,42 +37,8 @@ end let get_dal_processed_slots node_ctxt block = Node_context.list_slots_statuses node_ctxt ~confirmed_in_block_hash:block -module Global_directory = Make_directory (struct - include Sc_rollup_services.Global - - type context = Node_context.rw - - type subcontext = Node_context.ro - - let context_of_prefix node_ctxt () = return (Node_context.readonly node_ctxt) -end) - -module Proof_helpers_directory = Make_directory (struct - include Sc_rollup_services.Global.Helpers - - (* The context needs to be accessed with write permissions because we need to - commit on disk to generate the proofs. *) - type context = Node_context.rw - - (* The context needs to be accessed with write permissions because we need to - commit on disk to generate the proofs. *) - type subcontext = Node_context.rw - - let context_of_prefix node_ctxt () = return node_ctxt -end) - -module Local_directory = Make_directory (struct - include Sc_rollup_services.Local - - type context = Node_context.rw - - type subcontext = Node_context.ro - - let context_of_prefix node_ctxt () = return (Node_context.readonly node_ctxt) -end) - -module Block_directory = Make_directory (struct - include Sc_rollup_services.Global.Block +module Block_directory = Make_sub_directory (struct + include Sc_rollup_services.Block type context = Node_context.rw @@ -96,27 +50,31 @@ module Block_directory = Make_directory (struct (Node_context.readonly node_ctxt, block) end) -module Outbox_directory = Make_directory (struct - include Sc_rollup_services.Global.Block.Outbox +module Block_helpers_directory = Make_sub_directory (struct + include Sc_rollup_services.Block.Helpers + (* The context needs to be accessed with write permissions because we need to + commit on disk to generate the proofs. *) type context = Node_context.rw - type subcontext = Node_context.ro * Block_hash.t * Alpha_context.Raw_level.t + (* The context needs to be accessed with write permissions because we need to + commit on disk to generate the proofs. *) + type subcontext = Node_context.rw * Block_hash.t - let context_of_prefix node_ctxt (((), block), level) = + let context_of_prefix node_ctxt (((), block) : prefix) = let open Lwt_result_syntax in let+ block = Block_directory_helpers.block_of_prefix node_ctxt block in - (Node_context.readonly node_ctxt, block, level) + (node_ctxt, block) end) module Common = struct let () = - Block_directory.register0 Sc_rollup_services.Global.Block.block + Block_directory.register0 Sc_rollup_services.Block.block @@ fun (node_ctxt, block) () () -> Node_context.get_full_l2_block node_ctxt block let () = - Block_directory.register0 Sc_rollup_services.Global.Block.num_messages + Block_directory.register0 Sc_rollup_services.Block.num_messages @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let* l2_block = Node_context.get_l2_block node_ctxt block in @@ -126,34 +84,21 @@ module Common = struct Z.of_int num_messages let () = - Global_directory.register0 Sc_rollup_services.Global.sc_rollup_address - @@ fun node_ctxt () () -> - return @@ Sc_rollup_proto_types.Address.of_octez node_ctxt.rollup_address - - let () = - Global_directory.register0 Sc_rollup_services.Global.current_tezos_head - @@ fun node_ctxt () () -> get_head_hash_opt node_ctxt - - let () = - Global_directory.register0 Sc_rollup_services.Global.current_tezos_level - @@ fun node_ctxt () () -> get_head_level_opt node_ctxt - - let () = - Block_directory.register0 Sc_rollup_services.Global.Block.hash + Block_directory.register0 Sc_rollup_services.Block.hash @@ fun (_node_ctxt, block) () () -> return block let () = - Block_directory.register0 Sc_rollup_services.Global.Block.level + Block_directory.register0 Sc_rollup_services.Block.level @@ fun (node_ctxt, block) () () -> Node_context.level_of_hash node_ctxt block let () = - Block_directory.register0 Sc_rollup_services.Global.Block.inbox + Block_directory.register0 Sc_rollup_services.Block.inbox @@ fun (node_ctxt, block) () () -> Node_context.get_inbox_by_block_hash node_ctxt block let () = - Block_directory.register0 Sc_rollup_services.Global.Block.ticks + Block_directory.register0 Sc_rollup_services.Block.ticks @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let+ l2_block = Node_context.get_l2_block node_ctxt block in @@ -219,7 +164,7 @@ let simulate_messages (node_ctxt : Node_context.ro) block ~reveal_pages {state_hash; status; output; inbox_level; num_ticks; insights} let () = - Block_directory.register0 Sc_rollup_services.Global.Block.total_ticks + Block_directory.register0 Sc_rollup_services.Block.total_ticks @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -228,7 +173,7 @@ let () = return tick let () = - Block_directory.register0 Sc_rollup_services.Global.Block.state_hash + Block_directory.register0 Sc_rollup_services.Block.state_hash @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -237,7 +182,7 @@ let () = return hash let () = - Block_directory.register0 Sc_rollup_services.Global.Block.state_current_level + Block_directory.register0 Sc_rollup_services.Block.state_current_level @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -246,7 +191,7 @@ let () = return current_level let () = - Block_directory.register0 Sc_rollup_services.Global.Block.state_value + Block_directory.register0 Sc_rollup_services.Block.state_value @@ fun (node_ctxt, block) {key} () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -259,45 +204,7 @@ let () = return value let () = - Global_directory.register0 Sc_rollup_services.Global.last_stored_commitment - @@ fun node_ctxt () () -> - let open Lwt_result_syntax in - let* head = Node_context.last_processed_head_opt node_ctxt in - match head with - | None -> return_none - | Some head -> - let commitment_hash = - Sc_rollup_block.most_recent_commitment head.header - in - let+ commitment = - Node_context.find_commitment node_ctxt commitment_hash - in - Option.map (fun c -> (c, commitment_hash)) commitment - -let () = - Local_directory.register0 Sc_rollup_services.Local.last_published_commitment - @@ fun node_ctxt () () -> - let open Lwt_result_syntax in - match Reference.get node_ctxt.lpc with - | None -> return_none - | Some commitment -> - let hash = Octez_smart_rollup.Commitment.hash commitment in - (* The corresponding level in Store.Commitments.published_at_level is - available only when the commitment has been published and included - in a block. *) - let* published_at_level_info = - Node_context.commitment_published_at_level node_ctxt hash - in - let first_published, published = - match published_at_level_info with - | None -> (None, None) - | Some {first_published_at_level; published_at_level} -> - (Some first_published_at_level, published_at_level) - in - return_some (commitment, hash, first_published, published) - -let () = - Block_directory.register0 Sc_rollup_services.Global.Block.status + Block_directory.register0 Sc_rollup_services.Block.status @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -306,7 +213,7 @@ let () = return (PVM.string_of_status status) let () = - Block_directory.register0 Sc_rollup_services.Global.Block.dal_slots + Block_directory.register0 Sc_rollup_services.Block.dal_slots @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let+ slots = @@ -315,12 +222,12 @@ let () = List.rev_map Sc_rollup_proto_types.Dal.Slot_header.of_octez slots |> List.rev let () = - Block_directory.register0 Sc_rollup_services.Global.Block.dal_processed_slots + Block_directory.register0 Sc_rollup_services.Block.dal_processed_slots @@ fun (node_ctxt, block) () () -> get_dal_processed_slots node_ctxt block let () = - Outbox_directory.register0 Sc_rollup_services.Global.Block.Outbox.messages - @@ fun (node_ctxt, block, outbox_level) () () -> + Block_directory.register1 Sc_rollup_services.Block.outbox_messages + @@ fun (node_ctxt, block) outbox_level () () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in let module PVM = (val Pvm.of_kind node_ctxt.kind) in @@ -328,189 +235,32 @@ let () = return outbox let () = - Proof_helpers_directory.register0 - Sc_rollup_services.Global.Helpers.outbox_proof - @@ fun node_ctxt output () -> + Block_helpers_directory.register0 + Sc_rollup_services.Block.Helpers.outbox_proof + @@ fun (node_ctxt, _block_hash) output () -> let open Lwt_result_syntax in let+ commitment, proof = Outbox.proof_of_output node_ctxt output in (Sc_rollup_proto_types.Commitment_hash.of_octez commitment, proof) let () = - Block_directory.register0 Sc_rollup_services.Global.Block.simulate + Block_directory.register0 Sc_rollup_services.Block.simulate @@ fun (node_ctxt, block) () {messages; reveal_pages; insight_requests} -> simulate_messages node_ctxt block ~reveal_pages ~insight_requests messages -let () = - Local_directory.register0 Sc_rollup_services.Local.injection - @@ fun _node_ctxt () messages -> Batcher.register_messages messages - -let () = - Local_directory.register0 Sc_rollup_services.Local.batcher_queue - @@ fun _node_ctxt () () -> - let open Lwt_result_syntax in - let*? queue = Batcher.get_queue () in - return queue - -(** [commitment_level_of_inbox_level node_ctxt inbox_level] returns the level - of the commitment which should include the inbox of level - [inbox_level]. - - It is computed with the following formula: - {v - commitment_level(inbox_level) = - last_commitment - - ((last_commitment - inbox_level) / commitment_period - * commitment_period) - v} - *) -let commitment_level_of_inbox_level (node_ctxt : _ Node_context.t) inbox_level = - let open Alpha_context in - let open Option_syntax in - let+ last_published_commitment = Reference.get node_ctxt.lpc in - let commitment_period = - Int32.of_int - node_ctxt.current_protocol.constants.sc_rollup.commitment_period_in_blocks - in - let last_published = last_published_commitment.inbox_level in - let open Int32 in - div (sub last_published inbox_level) commitment_period - |> mul commitment_period |> sub last_published |> Raw_level.of_int32_exn - -let inbox_info_of_level (node_ctxt : _ Node_context.t) inbox_level = - let open Lwt_result_syntax in - let+ finalized_level = Node_context.get_finalized_level node_ctxt in - let finalized = Compare.Int32.(inbox_level <= finalized_level) in - let lcc = Reference.get node_ctxt.lcc in - let cemented = Compare.Int32.(inbox_level <= lcc.level) in - (finalized, cemented) - -let () = - Local_directory.register1 Sc_rollup_services.Local.batcher_message - @@ fun node_ctxt hash () () -> - let open Lwt_result_syntax in - let*? batch_status = Batcher.message_status hash in - let* status = - match batch_status with - | None -> return (None, Sc_rollup_services.Unknown) - | Some (batch_status, msg) -> ( - let return status = return (Some msg, status) in - match batch_status with - | Pending_batch -> return Sc_rollup_services.Pending_batch - | Batched l1_hash -> ( - match Injector.operation_status l1_hash with - | None -> return Sc_rollup_services.Unknown - | Some (Pending op) -> - return (Sc_rollup_services.Pending_injection op) - | Some (Injected {op; oph; op_index}) -> - return - (Sc_rollup_services.Injected - {op = op.operation; oph; op_index}) - | Some (Included {op; oph; op_index; l1_block; l1_level}) -> ( - let* finalized, cemented = - inbox_info_of_level node_ctxt l1_level - in - let commitment_level = - commitment_level_of_inbox_level node_ctxt l1_level - in - match commitment_level with - | None -> - return - (Sc_rollup_services.Included - { - op = op.operation; - oph; - op_index; - l1_block; - l1_level; - finalized; - cemented; - }) - | Some commitment_level -> ( - let* block = - Node_context.find_l2_block_by_level - node_ctxt - (Alpha_context.Raw_level.to_int32 commitment_level) - in - match block with - | None -> - (* Commitment not computed yet for inbox *) - return - (Sc_rollup_services.Included - { - op = op.operation; - oph; - op_index; - l1_block; - l1_level; - finalized; - cemented; - }) - | Some block -> ( - let commitment_hash = - WithExceptions.Option.get - ~loc:__LOC__ - block.header.commitment_hash - in - (* Commitment computed *) - let* published_at = - Node_context.commitment_published_at_level - node_ctxt - commitment_hash - in - match published_at with - | None | Some {published_at_level = None; _} -> - (* Commitment not published yet *) - return - (Sc_rollup_services.Included - { - op = op.operation; - oph; - op_index; - l1_block; - l1_level; - finalized; - cemented; - }) - | Some - { - first_published_at_level; - published_at_level = Some published_at_level; - } -> - (* Commitment published *) - let* commitment = - Node_context.get_commitment - node_ctxt - commitment_hash - in - return - (Sc_rollup_services.Committed - { - op = op.operation; - oph; - op_index; - l1_block; - l1_level; - finalized; - cemented; - commitment; - commitment_hash; - first_published_at_level; - published_at_level; - })))))) - in - - return status - -let directory (node_ctxt : _ Node_context.t) = +let block_directory (node_ctxt : _ Node_context.t) = let module PVM = (val Pvm_rpc.of_kind node_ctxt.kind) in List.fold_left (fun dir f -> Tezos_rpc.Directory.merge dir (f node_ctxt)) Tezos_rpc.Directory.empty [ - Global_directory.build_directory; - Local_directory.build_directory; - Block_directory.build_directory; - Proof_helpers_directory.build_directory; - Outbox_directory.build_directory; - PVM.build_directory; + Block_directory.build_sub_directory; + Block_helpers_directory.build_sub_directory; + PVM.build_sub_directory; ] + +let directory (node_ctxt : _ Node_context.t) = + Tezos_rpc.Directory.merge + (Octez_smart_rollup_node.Rpc_directory.top_directory node_ctxt) + (Tezos_rpc.Directory.prefix + Sc_rollup_services.Block.prefix + (block_directory node_ctxt)) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_directory.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_directory.mli index 206e38547b0c..1cac46c2ded4 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_directory.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_directory.mli @@ -23,5 +23,11 @@ (* *) (*****************************************************************************) -(** The RPC directory for this rollup node. *) +(** The RPC directory, specific to blocks, for this rollup node. *) +val block_directory : + Node_context.rw -> + (unit * Rollup_node_services.Arg.block_id) Tezos_rpc.Directory.t + +(** The full RPC directory for this rollup node, merging the top level directory + and the block directory. *) val directory : Node_context.rw -> unit Tezos_rpc.Directory.t diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/pvm_rpc.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/pvm_rpc.ml index a8d946e87b6a..8069495af039 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/pvm_rpc.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/pvm_rpc.ml @@ -25,11 +25,13 @@ module type S = sig (** Build RPC directory of the PVM *) - val build_directory : Node_context.rw -> unit Environment.RPC_directory.t + val build_sub_directory : + Node_context.rw -> + (unit * Rollup_node_services.Arg.block_id) Tezos_rpc.Directory.t end module No_rpc = struct - let build_directory _node_ctxt = Tezos_rpc.Directory.empty + let build_sub_directory _node_ctxt = Tezos_rpc.Directory.empty end let no_rpc = (module No_rpc : S) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/wasm_2_0_0_rpc.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/wasm_2_0_0_rpc.ml index dd4c703fa4c5..55ba6f282a06 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/wasm_2_0_0_rpc.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/wasm_2_0_0_rpc.ml @@ -24,13 +24,13 @@ (* *) (*****************************************************************************) -open RPC_directory_helpers +open Rpc_directory_helpers module Make_RPC (Durable_state : Wasm_2_0_0_pvm.Durable_state with type state = Context.tree) = struct - module Block_directory = Make_directory (struct - include Sc_rollup_services.Global.Block + module Block_directory = Make_sub_directory (struct + include Sc_rollup_services.Block type context = Node_context.rw @@ -51,7 +51,7 @@ struct let register () = let open Protocol.Alpha_context.Sc_rollup in ( Block_directory.register0 - (Sc_rollup_services.Global.Block.durable_state_value Kind.Wasm_2_0_0) + (Sc_rollup_services.Block.durable_state_value Kind.Wasm_2_0_0) @@ fun (node_ctxt, block) {key} () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -59,7 +59,7 @@ struct return value ) ; ( Block_directory.register0 - (Sc_rollup_services.Global.Block.durable_state_length Kind.Wasm_2_0_0) + (Sc_rollup_services.Block.durable_state_length Kind.Wasm_2_0_0) @@ fun (node_ctxt, block) {key} () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -67,14 +67,14 @@ struct return leng ) ; Block_directory.register0 - (Sc_rollup_services.Global.Block.durable_state_subkeys Kind.Wasm_2_0_0) + (Sc_rollup_services.Block.durable_state_subkeys Kind.Wasm_2_0_0) @@ fun (node_ctxt, block) {key} () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in let*! subkeys = Durable_state.list state key in return subkeys - let build_directory node_ctxt = + let build_sub_directory node_ctxt = register () ; - Block_directory.build_directory node_ctxt + Block_directory.build_sub_directory node_ctxt end -- GitLab From 6ea3f52463892722aab39a5e78db8c6f55cbbf21 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 20 Jun 2023 10:57:06 +0200 Subject: [PATCH 08/12] SCORU/Node/Mumbai: keep only protocol specific block directory Backports the following commits: - SCORU/Node/RPC: move proof helper RPC under /global/block/{b}/helpers - SCORU/Node: split RPC services in proto and non proto specific parts - SCORU/Node: move protocol independent RPC directory --- .../lib_sc_rollup_client/RPC.ml | 15 +- .../lib_sc_rollup_client/commands.ml | 4 +- .../sc_rollup_services.ml | 698 ++++-------------- .../lib_sc_rollup_node/RPC_directory.ml | 332 +-------- .../lib_sc_rollup_node/RPC_directory.mli | 8 +- .../lib_sc_rollup_node/pvm_rpc.ml | 6 +- .../lib_sc_rollup_node/wasm_2_0_0_rpc.ml | 16 +- 7 files changed, 229 insertions(+), 850 deletions(-) diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_client/RPC.ml b/src/proto_016_PtMumbai/lib_sc_rollup_client/RPC.ml index 98ad7f965b46..2f491d40e44a 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_client/RPC.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_client/RPC.ml @@ -23,15 +23,22 @@ (* *) (*****************************************************************************) +module Block_services = + Rollup_node_services.Make_services (Sc_rollup_services.Block) + let get_sc_rollup_addresses_command cctxt = - Sc_rollup_services.Global.(make_call sc_rollup_address) cctxt () () () + Rollup_node_services.Global.(make_call sc_rollup_address) cctxt () () () let get_state_value_command cctxt block key = - Sc_rollup_services.Global.Block.(make_call1 state_value) cctxt block {key} () + Block_services.(make_call1 Sc_rollup_services.Block.state_value) + cctxt + block + {key} + () let get_outbox_proof cctxt serialized_output = - Sc_rollup_services.Global.Helpers.(make_call outbox_proof) + Block_services.(make_call Sc_rollup_services.Block.Helpers.outbox_proof) cctxt - () + ((), `Head) serialized_output () diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_client/commands.ml b/src/proto_016_PtMumbai/lib_sc_rollup_client/commands.ml index 86e62aaa814f..c30ee77a4cbf 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_client/commands.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_client/commands.ml @@ -40,7 +40,7 @@ let block_arg = (String.concat ", " possible_block_ids)) (Tezos_clic.parameter (fun _ s -> - match Sc_rollup_services.Arg.destruct_block_id s with + match Rollup_node_services.Arg.destruct_block_id s with | Ok b -> return b | Error reason -> failwith "Invalid block id: %s" reason) ~autocomplete:(fun _ -> return possible_block_ids)) @@ -52,7 +52,7 @@ let get_sc_rollup_addresses_command () = (Tezos_clic.fixed ["get"; "smart"; "rollup"; "address"]) (fun () (cctxt : #Configuration.sc_client_context) -> RPC.get_sc_rollup_addresses_command cctxt >>=? fun addr -> - cctxt#message "@[%a@]" Sc_rollup.Address.pp addr >>= fun () -> return_unit) + cctxt#message "@[%a@]" Address.pp addr >>= fun () -> return_unit) let get_state_value_command () = Tezos_clic.command diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_layer2/sc_rollup_services.ml b/src/proto_016_PtMumbai/lib_sc_rollup_layer2/sc_rollup_services.ml index b6539529a288..04cb4c46665a 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_layer2/sc_rollup_services.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_layer2/sc_rollup_services.ml @@ -3,6 +3,7 @@ (* Open Source License *) (* Copyright (c) 2021 Nomadic Labs, *) (* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -26,28 +27,6 @@ open Protocol.Alpha_context -(* We distinguish RPC endpoints served by the rollup node into `global` and - `local`. The difference between the two lies in whether the responses - given by different rollup nodes in the same state (see below for an - exact definition) must be the same (in the case of global endpoints) - or can differ (in the case of local endpoints). - - More formally, two rollup nodes are in the same quiescent state if they are - subscribed to the same rollup address, and have processed the same set of - heads from the layer1. We only consider quiescent states, that is those - where rollup nodes are not actively processing a head received from layer1. - - Examples of global endpoints are `current_inbox` and - `last_stored_commitment`, as the responses returned by these endpoints - is expected to be consistent across rollup nodes in the same state. - - An example of local endpoint is `last_published_commitments`, as two rollup - nodes in the same state may either publish or not publish a commitment, - according to whether its inbox level is below the inbox level of the - last cemented commitment at the time they tried to publish the commitment. - See below for a more detailed explanation. -*) - type eval_result = { state_hash : Sc_rollup.State_hash.t; status : string; @@ -76,50 +55,10 @@ type commitment_info = { published_at_level : Raw_level.t; } -type message_status = - | Unknown - | Pending_batch - | Pending_injection of L1_operation.t - | Injected of {op : L1_operation.t; oph : Operation_hash.t; op_index : int} - | Included of { - op : L1_operation.t; - oph : Operation_hash.t; - op_index : int; - l1_block : Block_hash.t; - l1_level : int32; - finalized : bool; - cemented : bool; - } - | Committed of { - op : L1_operation.t; - oph : Operation_hash.t; - op_index : int; - l1_block : Block_hash.t; - l1_level : int32; - finalized : bool; - cemented : bool; - commitment : Octez_smart_rollup.Commitment.t; - commitment_hash : Octez_smart_rollup.Commitment.Hash.t; - first_published_at_level : int32; - published_at_level : int32; - } - module Encodings = struct open Data_encoding - let commitment_with_hash = - obj2 - (req "commitment" Octez_smart_rollup.Commitment.encoding) - (req "hash" Octez_smart_rollup.Commitment.Hash.encoding) - - let commitment_with_hash_and_level_infos = - obj4 - (req "commitment" Octez_smart_rollup.Commitment.encoding) - (req "hash" Octez_smart_rollup.Commitment.Hash.encoding) - (opt "first_published_at_level" int32) - (opt "published_at_level" int32) - - let hex_string = conv Bytes.of_string Bytes.to_string bytes + let hex_string = string' Hex let eval_result = conv @@ -195,13 +134,6 @@ module Encodings = struct [] ~description:"Paths in the PVM to inspect after the simulation") - let queued_message = - obj2 - (req "hash" L2_message.Hash.encoding) - (req "message" L2_message.encoding) - - let batcher_queue = list queued_message - let commitment_info = conv (fun { @@ -229,197 +161,6 @@ module Encodings = struct (req "hash" Sc_rollup.Commitment.Hash.encoding) (req "first_published_at_level" Raw_level.encoding) (req "published_at_level" Raw_level.encoding) - - let message_status = - union - [ - case - (Tag 0) - ~title:"unknown" - ~description:"The message is not known by the batcher." - (obj1 (req "status" (constant "unknown"))) - (function Unknown -> Some () | _ -> None) - (fun () -> Unknown); - case - (Tag 1) - ~title:"pending_batch" - ~description:"The message is in the batcher queue." - (obj1 (req "status" (constant "pending_batch"))) - (function Pending_batch -> Some () | _ -> None) - (fun () -> Pending_batch); - case - (Tag 2) - ~title:"pending_injection" - ~description:"The message is batched but not injected yet." - (obj2 - (req "status" (constant "pending_injection")) - (req "operation" L1_operation.encoding)) - (function Pending_injection op -> Some ((), op) | _ -> None) - (fun ((), op) -> Pending_injection op); - case - (Tag 3) - ~title:"injected" - ~description: - "The message is injected as part of an L1 operation but it is not \ - included in a block." - (obj3 - (req "status" (constant "injected")) - (req "operation" L1_operation.encoding) - (req - "layer1" - (obj2 - (req "operation_hash" Operation_hash.encoding) - (req "operation_index" int31)))) - (function - | Injected {op; oph; op_index} -> Some ((), op, (oph, op_index)) - | _ -> None) - (fun ((), op, (oph, op_index)) -> Injected {op; oph; op_index}); - case - (Tag 4) - ~title:"included" - ~description:"The message is included in an inbox in an L1 block." - (obj5 - (req "status" (constant "included")) - (req "operation" L1_operation.encoding) - (req - "layer1" - (obj4 - (req "operation_hash" Operation_hash.encoding) - (req "operation_index" int31) - (req "block_hash" Block_hash.encoding) - (req "level" int32))) - (req "finalized" bool) - (req "cemented" bool)) - (function - | Included - {op; oph; op_index; l1_block; l1_level; finalized; cemented} -> - Some - ( (), - op, - (oph, op_index, l1_block, l1_level), - finalized, - cemented ) - | _ -> None) - (fun ((), op, (oph, op_index, l1_block, l1_level), finalized, cemented) - -> - Included - {op; oph; op_index; l1_block; l1_level; finalized; cemented}); - case - (Tag 5) - ~title:"committed" - ~description:"The message is included in a committed inbox on L1." - (obj9 - (req "status" (constant "committed")) - (req "operation" L1_operation.encoding) - (req - "layer1" - (obj4 - (req "operation_hash" Operation_hash.encoding) - (req "operation_index" int31) - (req "block_hash" Block_hash.encoding) - (req "level" int32))) - (req "finalized" bool) - (req "cemented" bool) - (req "commitment" Octez_smart_rollup.Commitment.encoding) - (req "hash" Octez_smart_rollup.Commitment.Hash.encoding) - (req "first_published_at_level" int32) - (req "published_at_level" int32)) - (function - | Committed - { - op; - oph; - op_index; - l1_block; - l1_level; - finalized; - cemented; - commitment; - commitment_hash; - first_published_at_level; - published_at_level; - } -> - Some - ( (), - op, - (oph, op_index, l1_block, l1_level), - finalized, - cemented, - commitment, - commitment_hash, - first_published_at_level, - published_at_level ) - | _ -> None) - (fun ( (), - op, - (oph, op_index, l1_block, l1_level), - finalized, - cemented, - commitment, - commitment_hash, - first_published_at_level, - published_at_level ) -> - Committed - { - op; - oph; - op_index; - l1_block; - l1_level; - finalized; - cemented; - commitment; - commitment_hash; - first_published_at_level; - published_at_level; - }); - ] - - let message_status_output = - merge_objs (obj1 (opt "content" hex_string)) message_status -end - -module Arg = struct - type block_id = - [`Head | `Hash of Block_hash.t | `Level of Int32.t | `Finalized | `Cemented] - - let construct_block_id = function - | `Head -> "head" - | `Hash h -> Block_hash.to_b58check h - | `Level l -> Int32.to_string l - | `Finalized -> "finalized" - | `Cemented -> "cemented" - - let destruct_block_id h = - match h with - | "head" -> Ok `Head - | "finalized" -> Ok `Finalized - | "cemented" -> Ok `Cemented - | _ -> ( - match Int32.of_string_opt h with - | Some l -> Ok (`Level l) - | None -> ( - match Block_hash.of_b58check_opt h with - | Some b -> Ok (`Hash b) - | None -> Error "Cannot parse block id")) - - let block_id : block_id Tezos_rpc.Arg.t = - Tezos_rpc.Arg.make - ~descr:"An L1 block identifier." - ~name:"block_id" - ~construct:construct_block_id - ~destruct:destruct_block_id - () - - let l2_message_hash : L2_message.hash Tezos_rpc.Arg.t = - Tezos_rpc.Arg.make - ~descr:"A L2 message hash." - ~name:"l2_message_hash" - ~construct:L2_message.Hash.to_b58check - ~destruct:(fun s -> - L2_message.Hash.of_b58check_opt s - |> Option.to_result ~none:"Invalid L2 message hash") - () end module Query = struct @@ -487,27 +228,6 @@ module Query = struct |> seal end -module type PREFIX = sig - type prefix - - val prefix : (unit, prefix) Tezos_rpc.Path.t -end - -module Make_services (P : PREFIX) = struct - include P - - let path : prefix Tezos_rpc.Path.context = Tezos_rpc.Path.open_root - - let make_call s = - Tezos_rpc.Context.make_call (Tezos_rpc.Service.prefix prefix s) - - let make_call1 s = - Tezos_rpc.Context.make_call1 (Tezos_rpc.Service.prefix prefix s) - - let make_call2 s = - Tezos_rpc.Context.make_call2 (Tezos_rpc.Service.prefix prefix s) -end - type simulate_query = {fuel : int64 option} let simulate_query : simulate_query Tezos_rpc.Query.t = @@ -516,299 +236,193 @@ let simulate_query : simulate_query Tezos_rpc.Query.t = |+ opt_field "fuel" Tezos_rpc.Arg.int64 (fun t -> t.fuel) |> seal -module Global = struct +module Block = struct open Tezos_rpc.Path - include Make_services (struct - type prefix = unit + type prefix = unit * Rollup_node_services.Arg.block_id + + let path : prefix Tezos_rpc.Path.context = open_root - let prefix = open_root / "global" - end) + let prefix = root / "global" / "block" /: Rollup_node_services.Arg.block_id - let sc_rollup_address = + let block = Tezos_rpc.Service.get_service - ~description:"Smart rollup address" + ~description: + "Layer-2 block of the layer-2 chain with respect to a Layer 1 block \ + identifier" ~query:Tezos_rpc.Query.empty - ~output:Sc_rollup.Address.encoding - (path / "smart_rollup_address") + ~output:Sc_rollup_block.full_encoding + path - let current_tezos_head = + let hash = Tezos_rpc.Service.get_service - ~description:"Tezos head known to the smart rollup node" + ~description:"Tezos block hash of block known to the smart rollup node" ~query:Tezos_rpc.Query.empty - ~output:(Data_encoding.option Block_hash.encoding) - (path / "tezos_head") + ~output:Block_hash.encoding + (path / "hash") - let current_tezos_level = + let level = Tezos_rpc.Service.get_service - ~description:"Tezos level known to the smart rollup node" + ~description:"Level of Tezos block known to the smart rollup node" ~query:Tezos_rpc.Query.empty - ~output:(Data_encoding.option Data_encoding.int32) - (path / "tezos_level") + ~output:Data_encoding.int32 + (path / "level") - let last_stored_commitment = + let inbox = Tezos_rpc.Service.get_service - ~description:"Last commitment computed by the node" + ~description:"Rollup inbox for block" ~query:Tezos_rpc.Query.empty - ~output:(Data_encoding.option Encodings.commitment_with_hash) - (path / "last_stored_commitment") - - module Helpers = struct - include Make_services (struct - type prefix = unit - - let prefix = open_root / "helpers" - end) - - let outbox_proof = - Tezos_rpc.Service.get_service - ~description:"Generate serialized output proof for some outbox message" - ~query:Query.outbox_proof_query - ~output: - Data_encoding.( - obj2 - (req "commitment" Sc_rollup.Commitment.Hash.encoding) - (req "proof" Encodings.hex_string)) - (path / "proofs" / "outbox") - end - - module Block = struct - include Make_services (struct - type prefix = unit * Arg.block_id - - let prefix = prefix / "block" /: Arg.block_id - end) - - let block = - Tezos_rpc.Service.get_service - ~description: - "Layer-2 block of the layer-2 chain with respect to a Layer 1 block \ - identifier" - ~query:Tezos_rpc.Query.empty - ~output:Sc_rollup_block.full_encoding - path - - let hash = - Tezos_rpc.Service.get_service - ~description:"Tezos block hash of block known to the smart rollup node" - ~query:Tezos_rpc.Query.empty - ~output:Block_hash.encoding - (path / "hash") - - let level = - Tezos_rpc.Service.get_service - ~description:"Level of Tezos block known to the smart rollup node" - ~query:Tezos_rpc.Query.empty - ~output:Data_encoding.int32 - (path / "level") - - let inbox = - Tezos_rpc.Service.get_service - ~description:"Rollup inbox for block" - ~query:Tezos_rpc.Query.empty - ~output:Octez_smart_rollup.Inbox.encoding - (path / "inbox") - - let ticks = - Tezos_rpc.Service.get_service - ~description:"Number of ticks for specified level" - ~query:Tezos_rpc.Query.empty - ~output:Data_encoding.z - (path / "ticks") + ~output:Octez_smart_rollup.Inbox.encoding + (path / "inbox") - let total_ticks = - Tezos_rpc.Service.get_service - ~description:"Total number of ticks at specified block" - ~query:Tezos_rpc.Query.empty - ~output:Sc_rollup.Tick.encoding - (path / "total_ticks") - - let num_messages = - Tezos_rpc.Service.get_service - ~description:"Number of messages for specified block" - ~query:Tezos_rpc.Query.empty - ~output:Data_encoding.z - (path / "num_messages") + let ticks = + Tezos_rpc.Service.get_service + ~description:"Number of ticks for specified level" + ~query:Tezos_rpc.Query.empty + ~output:Data_encoding.z + (path / "ticks") - let state_hash = - Tezos_rpc.Service.get_service - ~description:"State hash for this block" - ~query:Tezos_rpc.Query.empty - ~output:Sc_rollup.State_hash.encoding - (path / "state_hash") + let total_ticks = + Tezos_rpc.Service.get_service + ~description:"Total number of ticks at specified block" + ~query:Tezos_rpc.Query.empty + ~output:Sc_rollup.Tick.encoding + (path / "total_ticks") - let state_current_level = - Tezos_rpc.Service.get_service - ~description:"Retrieve the current level of a PVM" - ~query:Tezos_rpc.Query.empty - ~output:(Data_encoding.option Raw_level.encoding) - (path / "state_current_level") + let num_messages = + Tezos_rpc.Service.get_service + ~description:"Number of messages for specified block" + ~query:Tezos_rpc.Query.empty + ~output:Data_encoding.z + (path / "num_messages") - let state_value = - Tezos_rpc.Service.get_service - ~description:"Retrieve value from key is PVM state of specified block" - ~query:Query.key_query - ~output:Data_encoding.bytes - (path / "state") + let state_hash = + Tezos_rpc.Service.get_service + ~description:"State hash for this block" + ~query:Tezos_rpc.Query.empty + ~output:Sc_rollup.State_hash.encoding + (path / "state_hash") - let durable_state_value (pvm_kind : Sc_rollup.Kind.t) = - Tezos_rpc.Service.get_service - ~description: - "Retrieve value by key from PVM durable storage. PVM state is taken \ - with respect to the specified block level. Value returned in hex \ - format." - ~query:Query.key_query - ~output:Data_encoding.(option bytes) - (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "value") - - let durable_state_length - (pvm_kind : Protocol.Alpha_context.Sc_rollup.Kind.t) = - Tezos_rpc.Service.get_service - ~description: - "Retrieve number of bytes in raw representation of value by key from \ - PVM durable storage. PVM state is taken with respect to the \ - specified block level." - ~query:Query.key_query - ~output:Data_encoding.(option int64) - (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "length") - - let durable_state_subkeys (pvm_kind : Sc_rollup.Kind.t) = - Tezos_rpc.Service.get_service - ~description: - "Retrieve subkeys of the specified key from PVM durable storage. PVM \ - state is taken with respect to the specified block level." - ~query:Query.key_query - ~output:Data_encoding.(list string) - (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "subkeys") - - let status = - Tezos_rpc.Service.get_service - ~description:"PVM status at block" - ~query:Tezos_rpc.Query.empty - ~output:Data_encoding.string - (path / "status") + let state_current_level = + Tezos_rpc.Service.get_service + ~description:"Retrieve the current level of a PVM" + ~query:Tezos_rpc.Query.empty + ~output:(Data_encoding.option Raw_level.encoding) + (path / "state_current_level") - let outbox = - Tezos_rpc.Service.get_service - ~description:"Outbox at block for a given outbox level" - ~query:Query.outbox_level_query - ~output:Data_encoding.(list Sc_rollup.output_encoding) - (path / "outbox") - - let simulate = - Tezos_rpc.Service.post_service - ~description:"Simulate messages evaluation by the PVM" - ~query:Tezos_rpc.Query.empty - ~input:Encodings.simulate_input - ~output:Encodings.eval_result - (path / "simulate") - - let dal_slots = - Tezos_rpc.Service.get_service - ~description:"Availability slots for a given block" - ~query:Tezos_rpc.Query.empty - ~output:(Data_encoding.list Dal.Slot.Header.encoding) - (path / "dal" / "slot_headers") + let state_value = + Tezos_rpc.Service.get_service + ~description:"Retrieve value from key is PVM state of specified block" + ~query:Query.key_query + ~output:Data_encoding.bytes + (path / "state") - let dal_slot_status_encoding : [`Confirmed | `Unconfirmed] Data_encoding.t = - Data_encoding.string_enum - [("confirmed", `Confirmed); ("unconfirmed", `Unconfirmed)] + let durable_state_value (pvm_kind : Sc_rollup.Kind.t) = + Tezos_rpc.Service.get_service + ~description: + "Retrieve value by key from PVM durable storage. PVM state is taken \ + with respect to the specified block level. Value returned in hex \ + format." + ~query:Query.key_query + ~output:Data_encoding.(option bytes) + (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "value") + + let durable_state_length (pvm_kind : Protocol.Alpha_context.Sc_rollup.Kind.t) + = + Tezos_rpc.Service.get_service + ~description: + "Retrieve number of bytes in raw representation of value by key from \ + PVM durable storage. PVM state is taken with respect to the specified \ + block level." + ~query:Query.key_query + ~output:Data_encoding.(option int64) + (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "length") + + let durable_state_subkeys (pvm_kind : Sc_rollup.Kind.t) = + Tezos_rpc.Service.get_service + ~description: + "Retrieve subkeys of the specified key from PVM durable storage. PVM \ + state is taken with respect to the specified block level." + ~query:Query.key_query + ~output:Data_encoding.(list string) + (path / "durable" / Sc_rollup.Kind.to_string pvm_kind / "subkeys") + + let status = + Tezos_rpc.Service.get_service + ~description:"PVM status at block" + ~query:Tezos_rpc.Query.empty + ~output:Data_encoding.string + (path / "status") - let dal_processed_slots = - Tezos_rpc.Service.get_service - ~description:"Data availability processed slots and their statuses" - ~query:Tezos_rpc.Query.empty - ~output: - Data_encoding.( - list - @@ obj2 (req "index" int31) (req "status" dal_slot_status_encoding)) - (path / "dal" / "processed_slots") - - module Outbox = struct - let level_param = - let destruct s = - match Int32.of_string_opt s with - | None -> Error "Invalid level" - | Some l -> ( - match Raw_level.of_int32 l with - | Error _ -> Error "Invalid level" - | Ok l -> Ok l) - in - let construct = Format.asprintf "%a" Raw_level.pp in - Tezos_rpc.Arg.make ~name:"level" ~construct ~destruct () - - include Make_services (struct - type nonrec prefix = prefix * Raw_level.t - - let prefix = prefix / "outbox" /: level_param - end) - - let messages = - Tezos_rpc.Service.get_service - ~description:"Outbox at block for a given outbox level" - ~query:Tezos_rpc.Query.empty - ~output:Data_encoding.(list Sc_rollup.output_encoding) - (path / "messages") - end - end -end + let outbox = + Tezos_rpc.Service.get_service + ~description:"Outbox at block for a given outbox level" + ~query:Query.outbox_level_query + ~output:Data_encoding.(list Sc_rollup.output_encoding) + (path / "outbox") -module Local = struct - open Tezos_rpc.Path + let simulate = + Tezos_rpc.Service.post_service + ~description:"Simulate messages evaluation by the PVM" + ~query:Tezos_rpc.Query.empty + ~input:Encodings.simulate_input + ~output:Encodings.eval_result + (path / "simulate") - include Make_services (struct - type prefix = unit - - let prefix = open_root / "local" - end) - - (* commitments are published only if their inbox level is above the last - cemented commitment level inbox level. Because this information is - fetched from the head of the tezos node to which the rollup node is - connected, it is possible that two rollup nodes that have processed - the same set of heads, but whose corresponding layer1 node has - different information about the last cemented commitment, will - decide to publish and not to publish a commitment, respectively. - As a consequence, the results returned by the endpoint below - in the rollup node will be different. - *) - let last_published_commitment = + let dal_slots = Tezos_rpc.Service.get_service - ~description:"Last commitment published by the node" + ~description:"Availability slots for a given block" ~query:Tezos_rpc.Query.empty - ~output: - (Data_encoding.option Encodings.commitment_with_hash_and_level_infos) - (path / "last_published_commitment") + ~output:(Data_encoding.list Dal.Slot.Header.encoding) + (path / "dal" / "slot_headers") - let injection = - Tezos_rpc.Service.post_service - ~description:"Inject messages in the batcher's queue" + let dal_slot_status_encoding : [`Confirmed | `Unconfirmed] Data_encoding.t = + Data_encoding.string_enum + [("confirmed", `Confirmed); ("unconfirmed", `Unconfirmed)] + + let dal_processed_slots = + Tezos_rpc.Service.get_service + ~description:"Data availability processed slots and their statuses" ~query:Tezos_rpc.Query.empty - ~input: - Data_encoding.( - def - "messages" - ~description:"Messages to inject" - (list L2_message.content_encoding)) ~output: Data_encoding.( - def - "message_hashes" - ~description:"Hashes of injected L2 messages" - (list L2_message.Hash.encoding)) - (path / "batcher" / "injection") + list + @@ obj2 (req "index" int31) (req "status" dal_slot_status_encoding)) + (path / "dal" / "processed_slots") + + let level_param = + let destruct s = + match Int32.of_string_opt s with + | None -> Error "Invalid level" + | Some l -> ( + match Raw_level.of_int32 l with + | Error _ -> Error "Invalid level" + | Ok l -> Ok l) + in + let construct = Format.asprintf "%a" Raw_level.pp in + Tezos_rpc.Arg.make ~name:"level" ~construct ~destruct () - let batcher_queue = + let outbox_messages = Tezos_rpc.Service.get_service - ~description:"List messages present in the batcher's queue" + ~description:"Outbox at block for a given outbox level" ~query:Tezos_rpc.Query.empty - ~output:Encodings.batcher_queue - (path / "batcher" / "queue") + ~output:Data_encoding.(list Sc_rollup.output_encoding) + (path / "outbox" /: level_param / "messages") - let batcher_message = - Tezos_rpc.Service.get_service - ~description:"Retrieve an L2 message and its status" - ~query:Tezos_rpc.Query.empty - ~output:Encodings.message_status_output - (path / "batcher" / "queue" /: Arg.l2_message_hash) + module Helpers = struct + type nonrec prefix = prefix + + let path = path / "helpers" + + let outbox_proof = + Tezos_rpc.Service.get_service + ~description:"Generate serialized output proof for some outbox message" + ~query:Query.outbox_proof_query + ~output: + Data_encoding.( + obj2 + (req "commitment" Sc_rollup.Commitment.Hash.encoding) + (req "proof" Encodings.hex_string)) + (path / "proofs" / "outbox") + end end diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_directory.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_directory.ml index 757611ac0d02..3f57f74af55a 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_directory.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_directory.ml @@ -28,18 +28,6 @@ open Rpc_directory_helpers open Protocol -let get_head_hash_opt node_ctxt = - let open Lwt_result_syntax in - let+ res = Node_context.last_processed_head_opt node_ctxt in - Option.map - (fun Sc_rollup_block.{header = {block_hash; _}; _} -> block_hash) - res - -let get_head_level_opt node_ctxt = - let open Lwt_result_syntax in - let+ res = Node_context.last_processed_head_opt node_ctxt in - Option.map (fun Sc_rollup_block.{header = {level; _}; _} -> level) res - module Slot_pages_map = struct open Protocol open Alpha_context @@ -49,42 +37,8 @@ end let get_dal_processed_slots node_ctxt block = Node_context.list_slots_statuses node_ctxt ~confirmed_in_block_hash:block -module Global_directory = Make_directory (struct - include Sc_rollup_services.Global - - type context = Node_context.rw - - type subcontext = Node_context.ro - - let context_of_prefix node_ctxt () = return (Node_context.readonly node_ctxt) -end) - -module Proof_helpers_directory = Make_directory (struct - include Sc_rollup_services.Global.Helpers - - (* The context needs to be accessed with write permissions because we need to - commit on disk to generate the proofs. *) - type context = Node_context.rw - - (* The context needs to be accessed with write permissions because we need to - commit on disk to generate the proofs. *) - type subcontext = Node_context.rw - - let context_of_prefix node_ctxt () = return node_ctxt -end) - -module Local_directory = Make_directory (struct - include Sc_rollup_services.Local - - type context = Node_context.rw - - type subcontext = Node_context.ro - - let context_of_prefix node_ctxt () = return (Node_context.readonly node_ctxt) -end) - -module Block_directory = Make_directory (struct - include Sc_rollup_services.Global.Block +module Block_directory = Make_sub_directory (struct + include Sc_rollup_services.Block type context = Node_context.rw @@ -96,27 +50,31 @@ module Block_directory = Make_directory (struct (Node_context.readonly node_ctxt, block) end) -module Outbox_directory = Make_directory (struct - include Sc_rollup_services.Global.Block.Outbox +module Block_helpers_directory = Make_sub_directory (struct + include Sc_rollup_services.Block.Helpers + (* The context needs to be accessed with write permissions because we need to + commit on disk to generate the proofs. *) type context = Node_context.rw - type subcontext = Node_context.ro * Block_hash.t * Alpha_context.Raw_level.t + (* The context needs to be accessed with write permissions because we need to + commit on disk to generate the proofs. *) + type subcontext = Node_context.rw * Block_hash.t - let context_of_prefix node_ctxt (((), block), level) = + let context_of_prefix node_ctxt (((), block) : prefix) = let open Lwt_result_syntax in let+ block = Block_directory_helpers.block_of_prefix node_ctxt block in - (Node_context.readonly node_ctxt, block, level) + (node_ctxt, block) end) module Common = struct let () = - Block_directory.register0 Sc_rollup_services.Global.Block.block + Block_directory.register0 Sc_rollup_services.Block.block @@ fun (node_ctxt, block) () () -> Node_context.get_full_l2_block node_ctxt block let () = - Block_directory.register0 Sc_rollup_services.Global.Block.num_messages + Block_directory.register0 Sc_rollup_services.Block.num_messages @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let* l2_block = Node_context.get_l2_block node_ctxt block in @@ -126,34 +84,21 @@ module Common = struct Z.of_int num_messages let () = - Global_directory.register0 Sc_rollup_services.Global.sc_rollup_address - @@ fun node_ctxt () () -> - return @@ Sc_rollup_proto_types.Address.of_octez node_ctxt.rollup_address - - let () = - Global_directory.register0 Sc_rollup_services.Global.current_tezos_head - @@ fun node_ctxt () () -> get_head_hash_opt node_ctxt - - let () = - Global_directory.register0 Sc_rollup_services.Global.current_tezos_level - @@ fun node_ctxt () () -> get_head_level_opt node_ctxt - - let () = - Block_directory.register0 Sc_rollup_services.Global.Block.hash + Block_directory.register0 Sc_rollup_services.Block.hash @@ fun (_node_ctxt, block) () () -> return block let () = - Block_directory.register0 Sc_rollup_services.Global.Block.level + Block_directory.register0 Sc_rollup_services.Block.level @@ fun (node_ctxt, block) () () -> Node_context.level_of_hash node_ctxt block let () = - Block_directory.register0 Sc_rollup_services.Global.Block.inbox + Block_directory.register0 Sc_rollup_services.Block.inbox @@ fun (node_ctxt, block) () () -> Node_context.get_inbox_by_block_hash node_ctxt block let () = - Block_directory.register0 Sc_rollup_services.Global.Block.ticks + Block_directory.register0 Sc_rollup_services.Block.ticks @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let+ l2_block = Node_context.get_l2_block node_ctxt block in @@ -219,7 +164,7 @@ let simulate_messages (node_ctxt : Node_context.ro) block ~reveal_pages {state_hash; status; output; inbox_level; num_ticks; insights} let () = - Block_directory.register0 Sc_rollup_services.Global.Block.total_ticks + Block_directory.register0 Sc_rollup_services.Block.total_ticks @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -228,7 +173,7 @@ let () = return tick let () = - Block_directory.register0 Sc_rollup_services.Global.Block.state_hash + Block_directory.register0 Sc_rollup_services.Block.state_hash @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -237,7 +182,7 @@ let () = return hash let () = - Block_directory.register0 Sc_rollup_services.Global.Block.state_current_level + Block_directory.register0 Sc_rollup_services.Block.state_current_level @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -246,7 +191,7 @@ let () = return current_level let () = - Block_directory.register0 Sc_rollup_services.Global.Block.state_value + Block_directory.register0 Sc_rollup_services.Block.state_value @@ fun (node_ctxt, block) {key} () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -259,45 +204,7 @@ let () = return value let () = - Global_directory.register0 Sc_rollup_services.Global.last_stored_commitment - @@ fun node_ctxt () () -> - let open Lwt_result_syntax in - let* head = Node_context.last_processed_head_opt node_ctxt in - match head with - | None -> return_none - | Some head -> - let commitment_hash = - Sc_rollup_block.most_recent_commitment head.header - in - let+ commitment = - Node_context.find_commitment node_ctxt commitment_hash - in - Option.map (fun c -> (c, commitment_hash)) commitment - -let () = - Local_directory.register0 Sc_rollup_services.Local.last_published_commitment - @@ fun node_ctxt () () -> - let open Lwt_result_syntax in - match Reference.get node_ctxt.lpc with - | None -> return_none - | Some commitment -> - let hash = Octez_smart_rollup.Commitment.hash commitment in - (* The corresponding level in Store.Commitments.published_at_level is - available only when the commitment has been published and included - in a block. *) - let* published_at_level_info = - Node_context.commitment_published_at_level node_ctxt hash - in - let first_published, published = - match published_at_level_info with - | None -> (None, None) - | Some {first_published_at_level; published_at_level} -> - (Some first_published_at_level, published_at_level) - in - return_some (commitment, hash, first_published, published) - -let () = - Block_directory.register0 Sc_rollup_services.Global.Block.status + Block_directory.register0 Sc_rollup_services.Block.status @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -306,7 +213,7 @@ let () = return (PVM.string_of_status status) let () = - Block_directory.register0 Sc_rollup_services.Global.Block.dal_slots + Block_directory.register0 Sc_rollup_services.Block.dal_slots @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let+ slots = @@ -315,12 +222,12 @@ let () = List.rev_map Sc_rollup_proto_types.Dal.Slot_header.of_octez slots |> List.rev let () = - Block_directory.register0 Sc_rollup_services.Global.Block.dal_processed_slots + Block_directory.register0 Sc_rollup_services.Block.dal_processed_slots @@ fun (node_ctxt, block) () () -> get_dal_processed_slots node_ctxt block let () = - Outbox_directory.register0 Sc_rollup_services.Global.Block.Outbox.messages - @@ fun (node_ctxt, block, outbox_level) () () -> + Block_directory.register1 Sc_rollup_services.Block.outbox_messages + @@ fun (node_ctxt, block) outbox_level () () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in let module PVM = (val Pvm.of_kind node_ctxt.kind) in @@ -328,189 +235,32 @@ let () = return outbox let () = - Proof_helpers_directory.register0 - Sc_rollup_services.Global.Helpers.outbox_proof - @@ fun node_ctxt output () -> + Block_helpers_directory.register0 + Sc_rollup_services.Block.Helpers.outbox_proof + @@ fun (node_ctxt, _block_hash) output () -> let open Lwt_result_syntax in let+ commitment, proof = Outbox.proof_of_output node_ctxt output in (Sc_rollup_proto_types.Commitment_hash.of_octez commitment, proof) let () = - Block_directory.register0 Sc_rollup_services.Global.Block.simulate + Block_directory.register0 Sc_rollup_services.Block.simulate @@ fun (node_ctxt, block) () {messages; reveal_pages; insight_requests} -> simulate_messages node_ctxt block ~reveal_pages ~insight_requests messages -let () = - Local_directory.register0 Sc_rollup_services.Local.injection - @@ fun _node_ctxt () messages -> Batcher.register_messages messages - -let () = - Local_directory.register0 Sc_rollup_services.Local.batcher_queue - @@ fun _node_ctxt () () -> - let open Lwt_result_syntax in - let*? queue = Batcher.get_queue () in - return queue - -(** [commitment_level_of_inbox_level node_ctxt inbox_level] returns the level - of the commitment which should include the inbox of level - [inbox_level]. - - It is computed with the following formula: - {v - commitment_level(inbox_level) = - last_commitment - - ((last_commitment - inbox_level) / commitment_period - * commitment_period) - v} - *) -let commitment_level_of_inbox_level (node_ctxt : _ Node_context.t) inbox_level = - let open Alpha_context in - let open Option_syntax in - let+ last_published_commitment = Reference.get node_ctxt.lpc in - let commitment_period = - Int32.of_int - node_ctxt.current_protocol.constants.sc_rollup.commitment_period_in_blocks - in - let last_published = last_published_commitment.inbox_level in - let open Int32 in - div (sub last_published inbox_level) commitment_period - |> mul commitment_period |> sub last_published |> Raw_level.of_int32_exn - -let inbox_info_of_level (node_ctxt : _ Node_context.t) inbox_level = - let open Lwt_result_syntax in - let+ finalized_level = Node_context.get_finalized_level node_ctxt in - let finalized = Compare.Int32.(inbox_level <= finalized_level) in - let lcc = Reference.get node_ctxt.lcc in - let cemented = Compare.Int32.(inbox_level <= lcc.level) in - (finalized, cemented) - -let () = - Local_directory.register1 Sc_rollup_services.Local.batcher_message - @@ fun node_ctxt hash () () -> - let open Lwt_result_syntax in - let*? batch_status = Batcher.message_status hash in - let* status = - match batch_status with - | None -> return (None, Sc_rollup_services.Unknown) - | Some (batch_status, msg) -> ( - let return status = return (Some msg, status) in - match batch_status with - | Pending_batch -> return Sc_rollup_services.Pending_batch - | Batched l1_hash -> ( - match Injector.operation_status l1_hash with - | None -> return Sc_rollup_services.Unknown - | Some (Pending op) -> - return (Sc_rollup_services.Pending_injection op) - | Some (Injected {op; oph; op_index}) -> - return - (Sc_rollup_services.Injected - {op = op.operation; oph; op_index}) - | Some (Included {op; oph; op_index; l1_block; l1_level}) -> ( - let* finalized, cemented = - inbox_info_of_level node_ctxt l1_level - in - let commitment_level = - commitment_level_of_inbox_level node_ctxt l1_level - in - match commitment_level with - | None -> - return - (Sc_rollup_services.Included - { - op = op.operation; - oph; - op_index; - l1_block; - l1_level; - finalized; - cemented; - }) - | Some commitment_level -> ( - let* block = - Node_context.find_l2_block_by_level - node_ctxt - (Alpha_context.Raw_level.to_int32 commitment_level) - in - match block with - | None -> - (* Commitment not computed yet for inbox *) - return - (Sc_rollup_services.Included - { - op = op.operation; - oph; - op_index; - l1_block; - l1_level; - finalized; - cemented; - }) - | Some block -> ( - let commitment_hash = - WithExceptions.Option.get - ~loc:__LOC__ - block.header.commitment_hash - in - (* Commitment computed *) - let* published_at = - Node_context.commitment_published_at_level - node_ctxt - commitment_hash - in - match published_at with - | None | Some {published_at_level = None; _} -> - (* Commitment not published yet *) - return - (Sc_rollup_services.Included - { - op = op.operation; - oph; - op_index; - l1_block; - l1_level; - finalized; - cemented; - }) - | Some - { - first_published_at_level; - published_at_level = Some published_at_level; - } -> - (* Commitment published *) - let* commitment = - Node_context.get_commitment - node_ctxt - commitment_hash - in - return - (Sc_rollup_services.Committed - { - op = op.operation; - oph; - op_index; - l1_block; - l1_level; - finalized; - cemented; - commitment; - commitment_hash; - first_published_at_level; - published_at_level; - })))))) - in - - return status - -let directory (node_ctxt : _ Node_context.t) = +let block_directory (node_ctxt : _ Node_context.t) = let module PVM = (val Pvm_rpc.of_kind node_ctxt.kind) in List.fold_left (fun dir f -> Tezos_rpc.Directory.merge dir (f node_ctxt)) Tezos_rpc.Directory.empty [ - Global_directory.build_directory; - Local_directory.build_directory; - Block_directory.build_directory; - Proof_helpers_directory.build_directory; - Outbox_directory.build_directory; - PVM.build_directory; + Block_directory.build_sub_directory; + Block_helpers_directory.build_sub_directory; + PVM.build_sub_directory; ] + +let directory (node_ctxt : _ Node_context.t) = + Tezos_rpc.Directory.merge + (Octez_smart_rollup_node.Rpc_directory.top_directory node_ctxt) + (Tezos_rpc.Directory.prefix + Sc_rollup_services.Block.prefix + (block_directory node_ctxt)) diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_directory.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_directory.mli index 206e38547b0c..1cac46c2ded4 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_directory.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_directory.mli @@ -23,5 +23,11 @@ (* *) (*****************************************************************************) -(** The RPC directory for this rollup node. *) +(** The RPC directory, specific to blocks, for this rollup node. *) +val block_directory : + Node_context.rw -> + (unit * Rollup_node_services.Arg.block_id) Tezos_rpc.Directory.t + +(** The full RPC directory for this rollup node, merging the top level directory + and the block directory. *) val directory : Node_context.rw -> unit Tezos_rpc.Directory.t diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/pvm_rpc.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/pvm_rpc.ml index a8d946e87b6a..8069495af039 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/pvm_rpc.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/pvm_rpc.ml @@ -25,11 +25,13 @@ module type S = sig (** Build RPC directory of the PVM *) - val build_directory : Node_context.rw -> unit Environment.RPC_directory.t + val build_sub_directory : + Node_context.rw -> + (unit * Rollup_node_services.Arg.block_id) Tezos_rpc.Directory.t end module No_rpc = struct - let build_directory _node_ctxt = Tezos_rpc.Directory.empty + let build_sub_directory _node_ctxt = Tezos_rpc.Directory.empty end let no_rpc = (module No_rpc : S) diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/wasm_2_0_0_rpc.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/wasm_2_0_0_rpc.ml index dd4c703fa4c5..55ba6f282a06 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/wasm_2_0_0_rpc.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/wasm_2_0_0_rpc.ml @@ -24,13 +24,13 @@ (* *) (*****************************************************************************) -open RPC_directory_helpers +open Rpc_directory_helpers module Make_RPC (Durable_state : Wasm_2_0_0_pvm.Durable_state with type state = Context.tree) = struct - module Block_directory = Make_directory (struct - include Sc_rollup_services.Global.Block + module Block_directory = Make_sub_directory (struct + include Sc_rollup_services.Block type context = Node_context.rw @@ -51,7 +51,7 @@ struct let register () = let open Protocol.Alpha_context.Sc_rollup in ( Block_directory.register0 - (Sc_rollup_services.Global.Block.durable_state_value Kind.Wasm_2_0_0) + (Sc_rollup_services.Block.durable_state_value Kind.Wasm_2_0_0) @@ fun (node_ctxt, block) {key} () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -59,7 +59,7 @@ struct return value ) ; ( Block_directory.register0 - (Sc_rollup_services.Global.Block.durable_state_length Kind.Wasm_2_0_0) + (Sc_rollup_services.Block.durable_state_length Kind.Wasm_2_0_0) @@ fun (node_ctxt, block) {key} () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in @@ -67,14 +67,14 @@ struct return leng ) ; Block_directory.register0 - (Sc_rollup_services.Global.Block.durable_state_subkeys Kind.Wasm_2_0_0) + (Sc_rollup_services.Block.durable_state_subkeys Kind.Wasm_2_0_0) @@ fun (node_ctxt, block) {key} () -> let open Lwt_result_syntax in let* state = get_state node_ctxt block in let*! subkeys = Durable_state.list state key in return subkeys - let build_directory node_ctxt = + let build_sub_directory node_ctxt = register () ; - Block_directory.build_directory node_ctxt + Block_directory.build_sub_directory node_ctxt end -- GitLab From fe23f2c92f4c5bb24ca63422d1b9b49ab4bce420 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Wed, 21 Jun 2023 11:08:05 +0200 Subject: [PATCH 09/12] SCORU/Node: block level from RPC block id --- .../lib_sc_rollup_node/block_directory_helpers.ml | 15 +++++++++++++++ .../block_directory_helpers.mli | 11 ++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/block_directory_helpers.ml b/src/proto_alpha/lib_sc_rollup_node/block_directory_helpers.ml index e7cba968fb78..61b02cdb0574 100644 --- a/src/proto_alpha/lib_sc_rollup_node/block_directory_helpers.ml +++ b/src/proto_alpha/lib_sc_rollup_node/block_directory_helpers.ml @@ -33,6 +33,13 @@ let get_head store = | None -> failwith "No head" | Some {header = {block_hash; _}; _} -> return block_hash +let get_head_level store = + let open Lwt_result_syntax in + let* head = Node_context.last_processed_head_opt store in + match head with + | None -> failwith "No head" + | Some {header = {level; _}; _} -> return level + let get_finalized node_ctxt = let open Lwt_result_syntax in let* level = Node_context.get_finalized_level node_ctxt in @@ -50,3 +57,11 @@ let block_of_prefix node_ctxt block = | `Level l -> Node_context.hash_of_level node_ctxt l | `Finalized -> get_finalized node_ctxt | `Cemented -> get_last_cemented node_ctxt + +let block_level_of_id node_ctxt block = + match block with + | `Head -> get_head_level node_ctxt + | `Hash b -> Node_context.level_of_hash node_ctxt b + | `Level l -> return l + | `Finalized -> Node_context.get_finalized_level node_ctxt + | `Cemented -> return (Reference.get node_ctxt.lcc).level diff --git a/src/proto_alpha/lib_sc_rollup_node/block_directory_helpers.mli b/src/proto_alpha/lib_sc_rollup_node/block_directory_helpers.mli index 3994a59f6f84..1f6b4138f5ea 100644 --- a/src/proto_alpha/lib_sc_rollup_node/block_directory_helpers.mli +++ b/src/proto_alpha/lib_sc_rollup_node/block_directory_helpers.mli @@ -24,9 +24,14 @@ (* *) (*****************************************************************************) -(** This module is a helper to extract a block hash - from block reference and Node_context *) +(** This module is a helper to convert block ids used in RPCs to useful values. *) + +(** Returns the block hash corresponding to a block id. *) val block_of_prefix : _ Node_context.t -> - [< `Cemented | `Finalized | `Hash of Block_hash.t | `Head | `Level of int32] -> + Rollup_node_services.Arg.block_id -> Block_hash.t tzresult Lwt.t + +(** Returns the level corresponding to a block id. *) +val block_level_of_id : + _ Node_context.t -> Rollup_node_services.Arg.block_id -> int32 tzresult Lwt.t -- GitLab From 1a6c5d37908d575f8c4b61dfd5504fcf5dff1330 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Wed, 21 Jun 2023 11:04:51 +0200 Subject: [PATCH 10/12] SCORU/Node: move Block_directory_helpers --- .../block_directory_helpers.ml | 6 +-- .../block_directory_helpers.mli | 0 .../block_directory_helpers.ml | 52 ------------------- .../block_directory_helpers.mli | 32 ------------ .../block_directory_helpers.ml | 52 ------------------- .../block_directory_helpers.mli | 32 ------------ 6 files changed, 3 insertions(+), 171 deletions(-) rename src/{proto_alpha/lib_sc_rollup_node => lib_smart_rollup_node}/block_directory_helpers.ml (95%) rename src/{proto_alpha/lib_sc_rollup_node => lib_smart_rollup_node}/block_directory_helpers.mli (100%) delete mode 100644 src/proto_016_PtMumbai/lib_sc_rollup_node/block_directory_helpers.ml delete mode 100644 src/proto_016_PtMumbai/lib_sc_rollup_node/block_directory_helpers.mli delete mode 100644 src/proto_017_PtNairob/lib_sc_rollup_node/block_directory_helpers.ml delete mode 100644 src/proto_017_PtNairob/lib_sc_rollup_node/block_directory_helpers.mli diff --git a/src/proto_alpha/lib_sc_rollup_node/block_directory_helpers.ml b/src/lib_smart_rollup_node/block_directory_helpers.ml similarity index 95% rename from src/proto_alpha/lib_sc_rollup_node/block_directory_helpers.ml rename to src/lib_smart_rollup_node/block_directory_helpers.ml index 61b02cdb0574..16b5c349b82c 100644 --- a/src/proto_alpha/lib_sc_rollup_node/block_directory_helpers.ml +++ b/src/lib_smart_rollup_node/block_directory_helpers.ml @@ -53,7 +53,7 @@ let get_last_cemented (node_ctxt : _ Node_context.t) = let block_of_prefix node_ctxt block = match block with | `Head -> get_head node_ctxt - | `Hash b -> return b + | `Hash b -> Lwt_result.return b | `Level l -> Node_context.hash_of_level node_ctxt l | `Finalized -> get_finalized node_ctxt | `Cemented -> get_last_cemented node_ctxt @@ -62,6 +62,6 @@ let block_level_of_id node_ctxt block = match block with | `Head -> get_head_level node_ctxt | `Hash b -> Node_context.level_of_hash node_ctxt b - | `Level l -> return l + | `Level l -> Lwt_result.return l | `Finalized -> Node_context.get_finalized_level node_ctxt - | `Cemented -> return (Reference.get node_ctxt.lcc).level + | `Cemented -> Lwt_result.return (Reference.get node_ctxt.lcc).level diff --git a/src/proto_alpha/lib_sc_rollup_node/block_directory_helpers.mli b/src/lib_smart_rollup_node/block_directory_helpers.mli similarity index 100% rename from src/proto_alpha/lib_sc_rollup_node/block_directory_helpers.mli rename to src/lib_smart_rollup_node/block_directory_helpers.mli diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/block_directory_helpers.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/block_directory_helpers.ml deleted file mode 100644 index e7cba968fb78..000000000000 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/block_directory_helpers.ml +++ /dev/null @@ -1,52 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -(* Conveniences to construct RPC directory - against a subcontext of the Node_context *) - -let get_head store = - let open Lwt_result_syntax in - let* head = Node_context.last_processed_head_opt store in - match head with - | None -> failwith "No head" - | Some {header = {block_hash; _}; _} -> return block_hash - -let get_finalized node_ctxt = - let open Lwt_result_syntax in - let* level = Node_context.get_finalized_level node_ctxt in - Node_context.hash_of_level node_ctxt level - -let get_last_cemented (node_ctxt : _ Node_context.t) = - protect @@ fun () -> - let lcc = Reference.get node_ctxt.lcc in - Node_context.hash_of_level node_ctxt lcc.level - -let block_of_prefix node_ctxt block = - match block with - | `Head -> get_head node_ctxt - | `Hash b -> return b - | `Level l -> Node_context.hash_of_level node_ctxt l - | `Finalized -> get_finalized node_ctxt - | `Cemented -> get_last_cemented node_ctxt diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/block_directory_helpers.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/block_directory_helpers.mli deleted file mode 100644 index 3994a59f6f84..000000000000 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/block_directory_helpers.mli +++ /dev/null @@ -1,32 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 Nomadic Labs, *) -(* Copyright (c) 2022-2023 TriliTech *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -(** This module is a helper to extract a block hash - from block reference and Node_context *) -val block_of_prefix : - _ Node_context.t -> - [< `Cemented | `Finalized | `Hash of Block_hash.t | `Head | `Level of int32] -> - Block_hash.t tzresult Lwt.t diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/block_directory_helpers.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/block_directory_helpers.ml deleted file mode 100644 index e7cba968fb78..000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/block_directory_helpers.ml +++ /dev/null @@ -1,52 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -(* Conveniences to construct RPC directory - against a subcontext of the Node_context *) - -let get_head store = - let open Lwt_result_syntax in - let* head = Node_context.last_processed_head_opt store in - match head with - | None -> failwith "No head" - | Some {header = {block_hash; _}; _} -> return block_hash - -let get_finalized node_ctxt = - let open Lwt_result_syntax in - let* level = Node_context.get_finalized_level node_ctxt in - Node_context.hash_of_level node_ctxt level - -let get_last_cemented (node_ctxt : _ Node_context.t) = - protect @@ fun () -> - let lcc = Reference.get node_ctxt.lcc in - Node_context.hash_of_level node_ctxt lcc.level - -let block_of_prefix node_ctxt block = - match block with - | `Head -> get_head node_ctxt - | `Hash b -> return b - | `Level l -> Node_context.hash_of_level node_ctxt l - | `Finalized -> get_finalized node_ctxt - | `Cemented -> get_last_cemented node_ctxt diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/block_directory_helpers.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/block_directory_helpers.mli deleted file mode 100644 index 3994a59f6f84..000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/block_directory_helpers.mli +++ /dev/null @@ -1,32 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 Nomadic Labs, *) -(* Copyright (c) 2022-2023 TriliTech *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -(** This module is a helper to extract a block hash - from block reference and Node_context *) -val block_of_prefix : - _ Node_context.t -> - [< `Cemented | `Finalized | `Hash of Block_hash.t | `Head | `Level of int32] -> - Block_hash.t tzresult Lwt.t -- GitLab From 52f23353eaea70dedef8fbbe8b03ba54d763cbe8 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Wed, 21 Jun 2023 11:29:19 +0200 Subject: [PATCH 11/12] SCORU/Node: use dynamic RPC directories for protocol specific RPCs --- .../protocol_plugin_sig.ml | 10 ++-- .../rollup_node_daemon.ml | 14 ++---- src/lib_smart_rollup_node/rpc_directory.ml | 47 +++++++++++++++---- src/lib_smart_rollup_node/rpc_directory.mli | 3 ++ src/lib_smart_rollup_node/rpc_server.ml | 16 ------- src/lib_smart_rollup_node/rpc_server.mli | 4 -- 6 files changed, 51 insertions(+), 43 deletions(-) diff --git a/src/lib_smart_rollup_node/protocol_plugin_sig.ml b/src/lib_smart_rollup_node/protocol_plugin_sig.ml index 9785d2ccd3fa..892090be5908 100644 --- a/src/lib_smart_rollup_node/protocol_plugin_sig.ml +++ b/src/lib_smart_rollup_node/protocol_plugin_sig.ml @@ -23,10 +23,14 @@ (* *) (*****************************************************************************) -(** Protocol specific RPC directory. *) +(** Protocol specific RPC directory, used as a dynamic directory in the protocol + agnostic rollup node. *) module type RPC_DIRECTORY = sig - (** The RPC directory for the rollup node of this protocol *) - val directory : Node_context.rw -> unit Tezos_rpc.Directory.t + (** The RPC directory, specific to blocks of the protocol, for this rollup + node. *) + val block_directory : + Node_context.rw -> + (unit * Rollup_node_services.Arg.block_id) Tezos_rpc.Directory.t end (** Protocol specific functions to track endorsed DAL slots of L1 blocks. *) diff --git a/src/lib_smart_rollup_node/rollup_node_daemon.ml b/src/lib_smart_rollup_node/rollup_node_daemon.ml index fe5e4e2b5ea9..c2605f6bdb4c 100644 --- a/src/lib_smart_rollup_node/rollup_node_daemon.ml +++ b/src/lib_smart_rollup_node/rollup_node_daemon.ml @@ -27,7 +27,7 @@ type state = { mutable plugin : (module Protocol_plugin_sig.S); - mutable rpc_server : Rpc_server.t; + rpc_server : Rpc_server.t; configuration : Configuration.t; node_ctxt : Node_context.rw; } @@ -89,13 +89,8 @@ let handle_protocol_migration ?degraded ~catching_up state let*? constants, new_plugin = protocol_info state.node_ctxt.cctxt new_protocol head.hash in - let module New_plugin = (val new_plugin) in - let* rpc_server = - Rpc_server.change_directory - state.rpc_server - (New_plugin.RPC_directory.directory state.node_ctxt) - and* constants in - let* () = + let* constants + and* () = start_workers ?degraded state.configuration new_plugin state.node_ctxt in let new_protocol = @@ -106,7 +101,6 @@ let handle_protocol_migration ?degraded ~catching_up state } in state.plugin <- new_plugin ; - state.rpc_server <- rpc_server ; state.node_ctxt.current_protocol <- new_protocol ; return_unit @@ -578,7 +572,7 @@ let run ~data_dir ?log_kernel_debug_file (configuration : Configuration.t) in let* () = Plugin.L1_processing.check_pvm_initial_state_hash node_ctxt in let* rpc_server = - Rpc_server.start configuration (Plugin.RPC_directory.directory node_ctxt) + Rpc_server.start configuration (Rpc_directory.directory node_ctxt) in let state = {node_ctxt; rpc_server; configuration; plugin} in let (_ : Lwt_exit.clean_up_callback_id) = install_finalizer state in diff --git a/src/lib_smart_rollup_node/rpc_directory.ml b/src/lib_smart_rollup_node/rpc_directory.ml index 7ce3d8c47784..296c3a4ab7db 100644 --- a/src/lib_smart_rollup_node/rpc_directory.ml +++ b/src/lib_smart_rollup_node/rpc_directory.ml @@ -39,20 +39,18 @@ let get_head_level_opt node_ctxt = let+ res = Node_context.last_processed_head_opt node_ctxt in Option.map (fun Sc_rollup_block.{header = {level; _}; _} -> level) res -let get_last_proto node_ctxt = +let get_proto_plugin_of_level node_ctxt level = let open Lwt_result_syntax in - let* head = Node_context.last_processed_head_opt node_ctxt in - match head with - | None -> failwith "No processed head, could not determine last protocol" - | Some head -> - let+ proto = Node_context.protocol_of_level node_ctxt head.header.level in - proto.protocol + let* proto = Node_context.protocol_of_level node_ctxt level in + let*? plugin = Protocol_plugins.proto_plugin_for_protocol proto.protocol in + return plugin let get_last_proto_plugin node_ctxt = let open Lwt_result_syntax in - let* protocol = get_last_proto node_ctxt in - let*? plugin = Protocol_plugins.proto_plugin_for_protocol protocol in - return plugin + let* head = Node_context.last_processed_head_opt node_ctxt in + match head with + | None -> failwith "No processed head, could not determine last protocol" + | Some head -> get_proto_plugin_of_level node_ctxt head.header.level module Global_directory = Make_directory (struct include Rollup_node_services.Global @@ -296,3 +294,32 @@ let top_directory (node_ctxt : _ Node_context.t) = (fun dir f -> Tezos_rpc.Directory.merge dir (f node_ctxt)) Tezos_rpc.Directory.empty [Global_directory.build_directory; Local_directory.build_directory] + +let directory node_ctxt = + let path = + Tezos_rpc.Path.( + open_root / "global" / "block" /: Rollup_node_services.Arg.block_id) + in + Tezos_rpc.Directory.register_dynamic_directory + ~descr:"Dynamic protocol specific RPC directory for the rollup node" + (top_directory node_ctxt) + path + (fun ((), block_id) -> + let open Lwt_syntax in + let+ dir = + let open Lwt_result_syntax in + let* level = + Block_directory_helpers.block_level_of_id node_ctxt block_id + in + let+ (module Plugin) = get_proto_plugin_of_level node_ctxt level in + Plugin.RPC_directory.block_directory node_ctxt + in + match dir with + | Ok dir -> dir + | Error e -> + Format.kasprintf + Stdlib.failwith + "Could not load block directory for block %s: %a" + (Rollup_node_services.Arg.construct_block_id block_id) + pp_print_trace + e) diff --git a/src/lib_smart_rollup_node/rpc_directory.mli b/src/lib_smart_rollup_node/rpc_directory.mli index 4283be8ed0f7..78993096c60e 100644 --- a/src/lib_smart_rollup_node/rpc_directory.mli +++ b/src/lib_smart_rollup_node/rpc_directory.mli @@ -26,3 +26,6 @@ (** The RPC top level directory (without the block directory) for this rollup node. *) val top_directory : Node_context.rw -> unit Tezos_rpc.Directory.t + +(** The full RPC directory for the protocol agnostic rollup node. *) +val directory : Node_context.rw -> unit Tezos_rpc.Directory.t diff --git a/src/lib_smart_rollup_node/rpc_server.ml b/src/lib_smart_rollup_node/rpc_server.ml index 2d90478b2feb..24c4430e37b1 100644 --- a/src/lib_smart_rollup_node/rpc_server.ml +++ b/src/lib_smart_rollup_node/rpc_server.ml @@ -58,19 +58,3 @@ let start configuration dir = return {server; host; node; acl} let shutdown {server; _} = RPC_server.shutdown server - -let change_directory {server; host; node; acl} dir = - let open Lwt_result_syntax in - let*! () = RPC_server.shutdown server in - let server = - RPC_server.init_server dir ~acl ~media_types:Media_type.all_media_types - in - protect @@ fun () -> - let*! () = - RPC_server.launch - ~host - server - ~callback:(RPC_server.resto_callback server) - node - in - return {server; host; node; acl} diff --git a/src/lib_smart_rollup_node/rpc_server.mli b/src/lib_smart_rollup_node/rpc_server.mli index 047182b620d6..60f652930d3e 100644 --- a/src/lib_smart_rollup_node/rpc_server.mli +++ b/src/lib_smart_rollup_node/rpc_server.mli @@ -34,7 +34,3 @@ val start : Configuration.t -> unit Tezos_rpc.Directory.t -> t tzresult Lwt.t (** Shutdown a running RPC server. When this function is called, the rollup node will stop listening to incoming requests. *) val shutdown : t -> unit Lwt.t - -(** Changes the directory for the RPC server. WARNING: this function stops and - restarts the RPC server. *) -val change_directory : t -> unit Tezos_rpc.Directory.t -> t tzresult Lwt.t -- GitLab From 5cfb5cb03e54acb9596e711ca8618a743720ee30 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Wed, 12 Jul 2023 12:55:43 +0200 Subject: [PATCH 12/12] Doc: changelog for RPC change --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index e5971bcc95c4..4106f6a2e024 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -310,6 +310,9 @@ Smart Rollup node now contains *serialized* messages (external messages start with ``01`` and internal start with ``00``). (MR :gl:`!8876`) +- **Breaking change** RPC ``/global/helpers/proof/outbox`` is moved to + ``/global/block/head/helpers/proof/outbox``. (MR :gl:`!9233`) + Smart Rollup client ------------------- -- GitLab