From 63aafda0e9b2e98cacfda19d1e3eccfbccbaac95 Mon Sep 17 00:00:00 2001 From: Ryan Tan Date: Tue, 14 Mar 2023 15:12:56 +0000 Subject: [PATCH 1/7] Dac: get missing page rpc for observer --- src/lib_dac/RPC_services.ml | 11 ++++++ src/lib_dac_node/RPC_server.ml | 53 ++++++++++++++++++++++++- src/lib_dac_node/event.ml | 8 ++++ src/lib_dac_node/node_context.ml | 2 + src/lib_dac_node/node_context.mli | 4 ++ tezt/lib_tezos/rollup.ml | 3 ++ tezt/lib_tezos/rollup.mli | 5 +++ tezt/tests/dac.ml | 65 ++++++++++++++++++++++++++++++- 8 files changed, 148 insertions(+), 3 deletions(-) diff --git a/src/lib_dac/RPC_services.ml b/src/lib_dac/RPC_services.ml index b01cc8547352..6b6bf7f0fd1b 100644 --- a/src/lib_dac/RPC_services.ml +++ b/src/lib_dac/RPC_services.ml @@ -106,3 +106,14 @@ let coordinator_post_preimage ((module P) : Dac_plugin.t) = ~input:Data_encoding.bytes ~output:P.encoding Tezos_rpc.Path.(open_root / "preimage") + +let get_missing_page ((module P) : Dac_plugin.t) = + Tezos_rpc.Service.get_service + ~description: + "Fetch a given page by forwarding the request to a Coordinator's GET \ + /preimage. The page is then saved to the node's page store before being \ + returned in the response. The endpoint should only be exposed in \ + Observer mode." + ~query:Tezos_rpc.Query.empty + ~output:Data_encoding.bytes + Tezos_rpc.Path.(open_root / "missing_page" /: P.hash_rpc_arg) diff --git a/src/lib_dac_node/RPC_server.ml b/src/lib_dac_node/RPC_server.ml index 7005a2040478..ba6fd81eb87e 100644 --- a/src/lib_dac_node/RPC_server.ml +++ b/src/lib_dac_node/RPC_server.ml @@ -31,6 +31,7 @@ open Tezos_rpc_http_server type error += | Cannot_construct_external_message | Cannot_deserialize_external_message + | Coordinator_client_config_not_defined let () = register_error_kind @@ -52,7 +53,19 @@ let () = Format.fprintf ppf "External rollup message could not be deserialized") Data_encoding.unit (function Cannot_deserialize_external_message -> Some () | _ -> None) - (fun () -> Cannot_deserialize_external_message) + (fun () -> Cannot_deserialize_external_message) ; + register_error_kind + `Permanent + ~id:"dac_coordinator_cleint_config_not_defined" + ~title:"Cordinator client config was not defined." + ~description:"Cordinator client config was expected but not defined." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "Cordinator client config was expected but not defined.") + Data_encoding.unit + (function Coordinator_client_config_not_defined -> Some () | _ -> None) + (fun () -> Coordinator_client_config_not_defined) let add_service registerer service handler directory = registerer directory service handler @@ -154,6 +167,33 @@ let handle_get_certificate ctx root_hash = Certificate_repr.{aggregate_signature; witnesses; root_hash}) value_opt +let handle_get_missing_page ctx dac_plugin root_hash = + let open Lwt_result_syntax in + let cctx_opt = Node_context.get_coordinator_client_opt ctx in + match cctx_opt with + | Some cctx -> + let page_store = Node_context.get_page_store ctx in + let* exists = Page_store.Filesystem.mem dac_plugin page_store root_hash in + (* Check page exists before querying Coordinator in the event the Observer + has retrieved the page by the time control flow reaches here. *) + if exists then Page_store.Filesystem.load dac_plugin page_store root_hash + else + let* preimage = + Dac_node_client.get_preimage dac_plugin cctx root_hash + (* TODO: https://gitlab.com/tezos/tezos/-/issues/5142 + Retrieve missing page from dac committee via "flooding". *) + in + let* () = + Page_store.Filesystem.save + dac_plugin + page_store + ~hash:root_hash + ~content:preimage + in + let*! () = Event.(emit (fetched_missing_page dac_plugin) root_hash) in + return preimage + | None -> tzfail @@ Coordinator_client_config_not_defined + let register_serialize_dac_store_preimage ctx cctxt dac_sk_uris page_store hash_streamer directory = directory @@ -220,6 +260,16 @@ let register_get_certificate ctx dac_plugin = (RPC_services.get_certificate dac_plugin) (fun root_hash () () -> handle_get_certificate ctx root_hash) +let register_get_missing_page ctx dac_plugin = + match (Node_context.get_config ctx).mode with + | Legacy _ | Observer _ -> + add_service + Tezos_rpc.Directory.register1 + (RPC_services.get_missing_page dac_plugin) + (fun root_hash () () -> + handle_get_missing_page ctx dac_plugin root_hash) + | Coordinator _ | Committee_member _ -> Fun.id + let register dac_plugin node_context cctxt dac_public_keys_opt dac_sk_uris hash_streamer = let page_store = Node_context.get_page_store node_context in @@ -239,6 +289,7 @@ let register dac_plugin node_context cctxt dac_public_keys_opt dac_sk_uris "/preimage" endpoint should be moved out of the [start_legacy]. *) |> register_coordinator_preimage_endpoint dac_plugin hash_streamer page_store |> register_get_certificate node_context dac_plugin + |> register_get_missing_page node_context dac_plugin (* TODO: https://gitlab.com/tezos/tezos/-/issues/4750 Move this to RPC_server.Legacy once all operating modes are supported. *) diff --git a/src/lib_dac_node/event.ml b/src/lib_dac_node/event.ml index 109c26c07c62..24ad5b7a3b29 100644 --- a/src/lib_dac_node/event.ml +++ b/src/lib_dac_node/event.ml @@ -239,3 +239,11 @@ let emit_received_root_hash_processed ((module P) : Dac_plugin.t) hash = let emit_processing_root_hash_failed ((module P) : Dac_plugin.t) hash errors = emit processing_root_hash_failed (P.to_hex hash, errors) + +let fetched_missing_page ((module P) : Dac_plugin.t) = + declare_1 + ~section + ~name:"missing_page_fetched" + ~msg:"Successfully fetched missing page for hash: {hash}" + ~level:Notice + ("hash", P.encoding) diff --git a/src/lib_dac_node/node_context.ml b/src/lib_dac_node/node_context.ml index a2d5be51a135..f29d69e44853 100644 --- a/src/lib_dac_node/node_context.ml +++ b/src/lib_dac_node/node_context.ml @@ -162,3 +162,5 @@ let get_committee_members ctxt = tzfail @@ Invalid_operation_for_mode {mode = "dac_member"; operation = "get_committee_members"} + +let get_coordinator_client_opt ctxt = ctxt.coordinator_opt diff --git a/src/lib_dac_node/node_context.mli b/src/lib_dac_node/node_context.mli index c8ae5cb3cff8..eda9a69c7d9f 100644 --- a/src/lib_dac_node/node_context.mli +++ b/src/lib_dac_node/node_context.mli @@ -95,3 +95,7 @@ val get_node_store : t -> 'a Store_sigs.mode -> 'a Store.Irmin_store.t [Configuration.Coordinator.dac_members_addresses] *) val get_committee_members : t -> Tezos_crypto.Aggregate_signature.public_key_hash list tzresult + +(** [get_coordinator_client_opt ctx] returns the Coordinator client if it + is available. *) +val get_coordinator_client_opt : t -> Dac_node_client.cctxt option diff --git a/tezt/lib_tezos/rollup.ml b/tezt/lib_tezos/rollup.ml index 17e41231a874..092bb08cad06 100644 --- a/tezt/lib_tezos/rollup.ml +++ b/tezt/lib_tezos/rollup.ml @@ -956,5 +956,8 @@ module Dac = struct ( json |-> "witnesses" |> as_int, json |-> "aggregate_signature" |> as_string, json |-> "root_hash" |> as_string ) + + let get_missing_page ~hex_root_hash = + make GET ["missing_page"; Hex.show hex_root_hash] JSON.as_string end end diff --git a/tezt/lib_tezos/rollup.mli b/tezt/lib_tezos/rollup.mli index 34119328904e..692446826e62 100644 --- a/tezt/lib_tezos/rollup.mli +++ b/tezt/lib_tezos/rollup.mli @@ -452,5 +452,10 @@ module Dac : sig the subscribed dac members and obervers. *) val coordinator_store_preimage : payload:string -> (Dac_node.t, string) RPC_core.t + + (** [get_missing_page page_hash] calls GET missing_page/[page_hash] + endpoint. *) + val get_missing_page : + hex_root_hash:Hex.t -> (Dac_node.t, string) RPC_core.t end end diff --git a/tezt/tests/dac.ml b/tezt/tests/dac.ml index eab2b993f7d4..bc1a5671a781 100644 --- a/tezt/tests/dac.ml +++ b/tezt/tests/dac.ml @@ -53,10 +53,10 @@ let regression_test ~__FILE__ ?(tags = []) title f = let tags = "dac" :: tags in Protocol.register_regression_test ~__FILE__ ~title ~tags f -let assert_lwt_failure ?__LOC__ msg unit_lwt = +let assert_lwt_failure ?__LOC__ msg lwt_under_inspection = let* passed = Lwt.catch - (fun () -> Lwt.map (fun () -> false) unit_lwt) + (fun () -> Lwt.map (fun _a -> false) lwt_under_inspection) (fun _exn -> return true) in if passed then unit else Test.fail ?__LOC__ msg @@ -1135,6 +1135,60 @@ let test_get_certificate _protocol _tezos_node _tz_client coordinator _threshold assert_verify_aggregate_signature [member] hex_root_hash certificate ; unit +(* 1. Observer should fetch missing page from Coordinator when GET /missing_page/{hash} + is called. + 2. As a side effect, Observer should save fetched page into its page store before + returning it in the response. This can be observer by checking the result of + retrieving preimage before and after the GET /missing_page/{hash} call.*) +let test_observer_get_missing_page _protocol node client coordinator threshold + dac_members = + let* hex_root_hash = + init_hex_root_hash ~payload:"test payload abc 123" coordinator + in + let* () = + wait_for_root_hash_pushed_to_data_streamer + coordinator + (Hex.show hex_root_hash) + in + let observer = + Dac_node.create_legacy + ~threshold + ~committee_members: + (List.map + (fun (dc : Account.aggregate_key) -> dc.aggregate_public_key_hash) + dac_members) + ~node + ~client + () + in + let* _ = Dac_node.init_config observer in + let () = Legacy.set_coordinator observer coordinator in + let* () = Dac_node.run observer in + let* () = + assert_lwt_failure + ~__LOC__ + "Expected retrieve_preimage" + (RPC.call + observer + (Rollup.Dac.RPC.dac_retrieve_preimage (Hex.show hex_root_hash))) + in + let* missing_page = + RPC.call observer (Rollup.Dac.RPC.get_missing_page ~hex_root_hash) + in + let* coordinator_page = + RPC.call + coordinator + (Rollup.Dac.RPC.dac_retrieve_preimage (Hex.show hex_root_hash)) + in + check_preimage coordinator_page missing_page ; + let* observer_preimage = + RPC.call + observer + (Rollup.Dac.RPC.dac_retrieve_preimage (Hex.show hex_root_hash)) + in + check_preimage coordinator_page observer_preimage ; + unit + let register ~protocols = (* Tests with layer1 and dac nodes *) test_dac_node_startup protocols ; @@ -1209,4 +1263,11 @@ let register ~protocols = ~tags:["dac"; "dac_node"] "dac_store_member_signature" Signature_manager.Coordinator.test_handle_store_signature + protocols ; + scenario_with_layer1_and_legacy_dac_nodes + ~threshold:0 + ~committee_members:1 + ~tags:["dac"; "dac_node"] + "dac_observer_get_missing_page" + test_observer_get_missing_page protocols -- GitLab From fbd430832eef5ca6c7fba544fbb55f66b502a104 Mon Sep 17 00:00:00 2001 From: Ryan Tan Date: Mon, 20 Mar 2023 17:11:42 +0000 Subject: [PATCH 2/7] Fixup: sequence oberserver tests after root hash streamed --- tezt/tests/dac.ml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tezt/tests/dac.ml b/tezt/tests/dac.ml index bc1a5671a781..e4733597ccd2 100644 --- a/tezt/tests/dac.ml +++ b/tezt/tests/dac.ml @@ -1142,14 +1142,17 @@ let test_get_certificate _protocol _tezos_node _tz_client coordinator _threshold retrieving preimage before and after the GET /missing_page/{hash} call.*) let test_observer_get_missing_page _protocol node client coordinator threshold dac_members = + let root_hash = + "00649d431e829f4adc68edecb8d8d8071154b57086cc124b465f6f6600a4bc91c7" + in + let root_hash_stream_promise = + wait_for_root_hash_pushed_to_data_streamer coordinator root_hash + in let* hex_root_hash = init_hex_root_hash ~payload:"test payload abc 123" coordinator in - let* () = - wait_for_root_hash_pushed_to_data_streamer - coordinator - (Hex.show hex_root_hash) - in + assert (root_hash = Hex.show hex_root_hash) ; + let* () = root_hash_stream_promise in let observer = Dac_node.create_legacy ~threshold -- GitLab From 3cc914a250d7bb99d988884b90ea101383eecfaa Mon Sep 17 00:00:00 2001 From: Ryan Tan Date: Mon, 20 Mar 2023 17:16:08 +0000 Subject: [PATCH 3/7] Fixup: apply typo suggestions --- src/lib_dac_node/RPC_server.ml | 17 +++++++++-------- tezt/lib_tezos/rollup.mli | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/lib_dac_node/RPC_server.ml b/src/lib_dac_node/RPC_server.ml index ba6fd81eb87e..614a78f7ce28 100644 --- a/src/lib_dac_node/RPC_server.ml +++ b/src/lib_dac_node/RPC_server.ml @@ -31,7 +31,7 @@ open Tezos_rpc_http_server type error += | Cannot_construct_external_message | Cannot_deserialize_external_message - | Coordinator_client_config_not_defined + | Coordinator_client_not_defined_in_config let () = register_error_kind @@ -56,16 +56,17 @@ let () = (fun () -> Cannot_deserialize_external_message) ; register_error_kind `Permanent - ~id:"dac_coordinator_cleint_config_not_defined" - ~title:"Cordinator client config was not defined." - ~description:"Cordinator client config was expected but not defined." + ~id:"dac_coordinator_client_not_defined_in_config" + ~title:"Coordinator client was not defined in config." + ~description: + "Coordinator client configuration was expected but not defined." ~pp:(fun ppf () -> Format.fprintf ppf - "Cordinator client config was expected but not defined.") + "Coordinator client configuration was expected but not defined.") Data_encoding.unit - (function Coordinator_client_config_not_defined -> Some () | _ -> None) - (fun () -> Coordinator_client_config_not_defined) + (function Coordinator_client_not_defined_in_config -> Some () | _ -> None) + (fun () -> Coordinator_client_not_defined_in_config) let add_service registerer service handler directory = registerer directory service handler @@ -192,7 +193,7 @@ let handle_get_missing_page ctx dac_plugin root_hash = in let*! () = Event.(emit (fetched_missing_page dac_plugin) root_hash) in return preimage - | None -> tzfail @@ Coordinator_client_config_not_defined + | None -> tzfail @@ Coordinator_client_not_defined_in_config let register_serialize_dac_store_preimage ctx cctxt dac_sk_uris page_store hash_streamer directory = diff --git a/tezt/lib_tezos/rollup.mli b/tezt/lib_tezos/rollup.mli index 692446826e62..5f376609ae77 100644 --- a/tezt/lib_tezos/rollup.mli +++ b/tezt/lib_tezos/rollup.mli @@ -453,7 +453,7 @@ module Dac : sig val coordinator_store_preimage : payload:string -> (Dac_node.t, string) RPC_core.t - (** [get_missing_page page_hash] calls GET missing_page/[page_hash] + (** [get_missing_page ~hex_root_hash] calls GET missing_page/[page_hash] endpoint. *) val get_missing_page : hex_root_hash:Hex.t -> (Dac_node.t, string) RPC_core.t -- GitLab From 0e08b8764f57efca95e7e14133d37a3d68446f22 Mon Sep 17 00:00:00 2001 From: Ryan Tan Date: Tue, 21 Mar 2023 13:50:02 +0000 Subject: [PATCH 4/7] Fixup: use remote load instead --- src/lib_dac_node/RPC_server.ml | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/src/lib_dac_node/RPC_server.ml b/src/lib_dac_node/RPC_server.ml index 614a78f7ce28..167f560ffa30 100644 --- a/src/lib_dac_node/RPC_server.ml +++ b/src/lib_dac_node/RPC_server.ml @@ -170,29 +170,18 @@ let handle_get_certificate ctx root_hash = let handle_get_missing_page ctx dac_plugin root_hash = let open Lwt_result_syntax in + let page_store = Node_context.get_page_store ctx in let cctx_opt = Node_context.get_coordinator_client_opt ctx in match cctx_opt with - | Some cctx -> - let page_store = Node_context.get_page_store ctx in - let* exists = Page_store.Filesystem.mem dac_plugin page_store root_hash in - (* Check page exists before querying Coordinator in the event the Observer - has retrieved the page by the time control flow reaches here. *) - if exists then Page_store.Filesystem.load dac_plugin page_store root_hash - else - let* preimage = - Dac_node_client.get_preimage dac_plugin cctx root_hash - (* TODO: https://gitlab.com/tezos/tezos/-/issues/5142 - Retrieve missing page from dac committee via "flooding". *) - in - let* () = - Page_store.Filesystem.save - dac_plugin - page_store - ~hash:root_hash - ~content:preimage - in - let*! () = Event.(emit (fetched_missing_page dac_plugin) root_hash) in - return preimage + | Some cctxt -> + let remote_store = Page_store.Remote.(init {cctxt; page_store}) in + let* preimage = + (* TODO: https://gitlab.com/tezos/tezos/-/issues/5142 + Retrieve missing page from dac committee via "flooding". *) + Page_store.Remote.load dac_plugin remote_store root_hash + in + let*! () = Event.(emit (fetched_missing_page dac_plugin) root_hash) in + return preimage | None -> tzfail @@ Coordinator_client_not_defined_in_config let register_serialize_dac_store_preimage ctx cctxt dac_sk_uris page_store -- GitLab From 6a4ab7cd6030098a4166dec7fd7ebce73bca9e1f Mon Sep 17 00:00:00 2001 From: Ryan Tan Date: Wed, 22 Mar 2023 12:18:53 +0000 Subject: [PATCH 5/7] Fixup: move get coordinator client error --- src/lib_dac_node/RPC_server.ml | 37 +++++++++---------------------- src/lib_dac_node/node_context.ml | 21 ++++++++++++++++-- src/lib_dac_node/node_context.mli | 4 ++-- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/lib_dac_node/RPC_server.ml b/src/lib_dac_node/RPC_server.ml index 167f560ffa30..ad0e56a50b9c 100644 --- a/src/lib_dac_node/RPC_server.ml +++ b/src/lib_dac_node/RPC_server.ml @@ -31,7 +31,6 @@ open Tezos_rpc_http_server type error += | Cannot_construct_external_message | Cannot_deserialize_external_message - | Coordinator_client_not_defined_in_config let () = register_error_kind @@ -53,20 +52,7 @@ let () = Format.fprintf ppf "External rollup message could not be deserialized") Data_encoding.unit (function Cannot_deserialize_external_message -> Some () | _ -> None) - (fun () -> Cannot_deserialize_external_message) ; - register_error_kind - `Permanent - ~id:"dac_coordinator_client_not_defined_in_config" - ~title:"Coordinator client was not defined in config." - ~description: - "Coordinator client configuration was expected but not defined." - ~pp:(fun ppf () -> - Format.fprintf - ppf - "Coordinator client configuration was expected but not defined.") - Data_encoding.unit - (function Coordinator_client_not_defined_in_config -> Some () | _ -> None) - (fun () -> Coordinator_client_not_defined_in_config) + (fun () -> Cannot_deserialize_external_message) let add_service registerer service handler directory = registerer directory service handler @@ -171,18 +157,15 @@ let handle_get_certificate ctx root_hash = let handle_get_missing_page ctx dac_plugin root_hash = let open Lwt_result_syntax in let page_store = Node_context.get_page_store ctx in - let cctx_opt = Node_context.get_coordinator_client_opt ctx in - match cctx_opt with - | Some cctxt -> - let remote_store = Page_store.Remote.(init {cctxt; page_store}) in - let* preimage = - (* TODO: https://gitlab.com/tezos/tezos/-/issues/5142 - Retrieve missing page from dac committee via "flooding". *) - Page_store.Remote.load dac_plugin remote_store root_hash - in - let*! () = Event.(emit (fetched_missing_page dac_plugin) root_hash) in - return preimage - | None -> tzfail @@ Coordinator_client_not_defined_in_config + let*? cctxt = Node_context.get_coordinator_client ctx in + let remote_store = Page_store.Remote.(init {cctxt; page_store}) in + let* preimage = + (* TODO: https://gitlab.com/tezos/tezos/-/issues/5142 + Retrieve missing page from dac committee via "flooding". *) + Page_store.Remote.load dac_plugin remote_store root_hash + in + let*! () = Event.(emit (fetched_missing_page dac_plugin) root_hash) in + return preimage let register_serialize_dac_store_preimage ctx cctxt dac_sk_uris page_store hash_streamer directory = diff --git a/src/lib_dac_node/node_context.ml b/src/lib_dac_node/node_context.ml index f29d69e44853..442ac935870a 100644 --- a/src/lib_dac_node/node_context.ml +++ b/src/lib_dac_node/node_context.ml @@ -87,6 +87,7 @@ let set_ready ctxt dac_plugin = type error += | Node_not_ready | Invalid_operation_for_mode of {mode : string; operation : string} + | Coordinator_client_not_defined_in_config let () = register_error_kind @@ -119,7 +120,20 @@ let () = (function | Invalid_operation_for_mode {mode; operation} -> Some (mode, operation) | _ -> None) - (fun (mode, operation) -> Invalid_operation_for_mode {mode; operation}) + (fun (mode, operation) -> Invalid_operation_for_mode {mode; operation}) ; + register_error_kind + `Permanent + ~id:"dac_coordinator_client_not_defined_in_config" + ~title:"Coordinator client was not defined in config." + ~description: + "Coordinator client configuration was expected but not defined." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "Coordinator client configuration was expected but not defined.") + Data_encoding.unit + (function Coordinator_client_not_defined_in_config -> Some () | _ -> None) + (fun () -> Coordinator_client_not_defined_in_config) let get_ready ctxt = let open Result_syntax in @@ -163,4 +177,7 @@ let get_committee_members ctxt = @@ Invalid_operation_for_mode {mode = "dac_member"; operation = "get_committee_members"} -let get_coordinator_client_opt ctxt = ctxt.coordinator_opt +let get_coordinator_client ctxt = + match ctxt.coordinator_opt with + | Some cctxt -> Ok cctxt + | None -> Result_syntax.tzfail Coordinator_client_not_defined_in_config diff --git a/src/lib_dac_node/node_context.mli b/src/lib_dac_node/node_context.mli index eda9a69c7d9f..e0e2076d652e 100644 --- a/src/lib_dac_node/node_context.mli +++ b/src/lib_dac_node/node_context.mli @@ -96,6 +96,6 @@ val get_node_store : t -> 'a Store_sigs.mode -> 'a Store.Irmin_store.t val get_committee_members : t -> Tezos_crypto.Aggregate_signature.public_key_hash list tzresult -(** [get_coordinator_client_opt ctx] returns the Coordinator client if it +(** [get_coordinator_client ctx] returns the Coordinator client if it is available. *) -val get_coordinator_client_opt : t -> Dac_node_client.cctxt option +val get_coordinator_client : t -> Dac_node_client.cctxt tzresult -- GitLab From de2966f229b73bb993433e6c17be199531512754 Mon Sep 17 00:00:00 2001 From: Ryan Tan Date: Tue, 14 Mar 2023 16:20:42 +0000 Subject: [PATCH 6/7] Dac: proto dac client --- manifest/main.ml | 1 + opam/tezos-dac-alpha.opam | 1 + src/lib_dac/RPC_services.ml | 7 + src/lib_dac_client/dac_node_client.ml | 2 + src/lib_dac_client/dac_node_client.mli | 3 + src/lib_dac_node/RPC_server.ml | 4 + .../lib_dac_plugin/dac_observer_client.ml | 138 ++++++++++++++++++ .../lib_dac_plugin/dac_observer_client.mli | 57 ++++++++ src/proto_alpha/lib_dac_plugin/dune | 2 + tezt/tests/dac.ml | 12 +- 10 files changed, 217 insertions(+), 10 deletions(-) create mode 100644 src/proto_alpha/lib_dac_plugin/dac_observer_client.ml create mode 100644 src/proto_alpha/lib_dac_plugin/dac_observer_client.mli diff --git a/manifest/main.ml b/manifest/main.ml index 5c9c038e36cf..54cecd8f9842 100644 --- a/manifest/main.ml +++ b/manifest/main.ml @@ -5497,6 +5497,7 @@ module Protocol = Protocol octez_protocol_compiler_registerer |> open_; octez_stdlib_unix |> open_; octez_dac_lib |> open_; + octez_dac_client_lib |> open_; client |> if_some |> open_; embedded |> open_; main |> open_; diff --git a/opam/tezos-dac-alpha.opam b/opam/tezos-dac-alpha.opam index c620542e0a5c..4d08e27b0519 100644 --- a/opam/tezos-dac-alpha.opam +++ b/opam/tezos-dac-alpha.opam @@ -15,6 +15,7 @@ depends: [ "octez-protocol-compiler" "tezos-stdlib-unix" "tezos-dac-lib" + "tezos-dac-client-lib" "tezos-client-alpha" "tezos-embedded-protocol-alpha" "tezos-protocol-alpha" diff --git a/src/lib_dac/RPC_services.ml b/src/lib_dac/RPC_services.ml index 6b6bf7f0fd1b..218ed47c77f9 100644 --- a/src/lib_dac/RPC_services.ml +++ b/src/lib_dac/RPC_services.ml @@ -117,3 +117,10 @@ let get_missing_page ((module P) : Dac_plugin.t) = ~query:Tezos_rpc.Query.empty ~output:Data_encoding.bytes Tezos_rpc.Path.(open_root / "missing_page" /: P.hash_rpc_arg) + +let ping : ([`GET], unit, unit, unit, unit, string) Tezos_rpc.Service.service = + Tezos_rpc.Service.get_service + ~description:"Returns pong" + ~query:Tezos_rpc.Query.empty + ~output:Data_encoding.string + Tezos_rpc.Path.(open_root / "ping") diff --git a/src/lib_dac_client/dac_node_client.ml b/src/lib_dac_client/dac_node_client.ml index 5813202fbf94..8a35e0cbeb37 100644 --- a/src/lib_dac_client/dac_node_client.ml +++ b/src/lib_dac_client/dac_node_client.ml @@ -56,3 +56,5 @@ let streamed_call (cctxt : #cctxt) = cctxt#call_streamed_service *) let get_preimage (plugin : Dac_plugin.t) (cctxt : #cctxt) page_hash = call cctxt (RPC_services.retrieve_preimage plugin) ((), page_hash) () () + +let ping (cctxt : #cctxt) = call cctxt RPC_services.ping () () () diff --git a/src/lib_dac_client/dac_node_client.mli b/src/lib_dac_client/dac_node_client.mli index e608a4899e65..c2c00d89be93 100644 --- a/src/lib_dac_client/dac_node_client.mli +++ b/src/lib_dac_client/dac_node_client.mli @@ -64,3 +64,6 @@ val streamed_call : returned as a sequence of bytes. *) val get_preimage : Dac_plugin.t -> #cctxt -> Dac_plugin.hash -> bytes tzresult Lwt.t + +(** [ping cctxt] returns pong. *) +val ping : #cctxt -> string tzresult Lwt.t diff --git a/src/lib_dac_node/RPC_server.ml b/src/lib_dac_node/RPC_server.ml index ad0e56a50b9c..bff9a8578ec4 100644 --- a/src/lib_dac_node/RPC_server.ml +++ b/src/lib_dac_node/RPC_server.ml @@ -243,6 +243,10 @@ let register_get_missing_page ctx dac_plugin = handle_get_missing_page ctx dac_plugin root_hash) | Coordinator _ | Committee_member _ -> Fun.id +let register_ping = + add_service Tezos_rpc.Directory.register0 RPC_services.ping (fun () () -> + Lwt_result_syntax.return "pong") + let register dac_plugin node_context cctxt dac_public_keys_opt dac_sk_uris hash_streamer = let page_store = Node_context.get_page_store node_context in diff --git a/src/proto_alpha/lib_dac_plugin/dac_observer_client.ml b/src/proto_alpha/lib_dac_plugin/dac_observer_client.ml new file mode 100644 index 000000000000..fb64cf613798 --- /dev/null +++ b/src/proto_alpha/lib_dac_plugin/dac_observer_client.ml @@ -0,0 +1,138 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 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. *) +(* *) +(*****************************************************************************) + +module Reveal_hash = Protocol.Sc_rollup_reveal_hash +module Dac_client = Dac_node_client + +module Configuration = struct + type t = {observer_endpoint : Uri.t} +end + +type t = { + config : Configuration.t; + observer_cctx : Dac_client.unix_cctxt; + dac_plugin : Dac_plugin.t; +} + +type error += + | Cannot_initlized_dac_plugin + | Timeout of Z.t + | Cannot_request_preimage_from_observer + +let () = + register_error_kind + ~id:"dac_observer_client.cannot_initialize_dac_plugin" + ~title:"Could not initialize DAC plugin" + ~description:"Could not initialize DAC plugin." + ~pp:(fun ppf () -> Format.fprintf ppf "Could not initialize DAC plugin") + `Permanent + Data_encoding.unit + (function Cannot_initlized_dac_plugin -> Some () | _ -> None) + (fun _ -> Cannot_initlized_dac_plugin) ; + register_error_kind + ~id:"dac_observer_client.timeout" + ~title:"Timeout while querying Dac Observer Node" + ~description:"Timeout while querying Dac Observer Node." + ~pp:(fun ppf seconds -> + Format.fprintf + ppf + "Timeout after %as when querying Dac Observer Node" + Z.pp_print + seconds) + `Permanent + Data_encoding.z + (function Timeout seconds -> Some seconds | _ -> None) + (fun seconds -> Timeout seconds) ; + register_error_kind + ~id:"dac_observer_client.cannot_request_preimage_from_observer" + ~title:"Cannot request preimage from observer" + ~description:"Cannot request preimage from observer." + ~pp:(fun ppf () -> + Format.fprintf ppf "Cannot request preimage from observer.") + `Permanent + Data_encoding.unit + (function Cannot_request_preimage_from_observer -> Some () | _ -> None) + (fun () -> Cannot_request_preimage_from_observer) + +let proto_hash_to_dac_hash ((module P) : Dac_plugin.t) proto_hash = + proto_hash + |> Data_encoding.Binary.to_bytes_exn Protocol.Sc_rollup_reveal_hash.encoding + |> Data_encoding.Binary.of_bytes_exn P.encoding + +module Client = struct + let make_unix endpoint = + let rpc_config = + {Tezos_rpc_http_client_unix.RPC_client_unix.default_config with endpoint} + in + new Dac_node_client.unix_cctxt ~rpc_config + + let ping cctx : string tzresult Lwt.t = Dac_client.ping cctx + + let fetch_missing_page_call (plugin : Dac_plugin.t) + (cctxt : #Dac_client.cctxt) page_hash = + Dac_client.call + cctxt + (RPC_services.get_missing_page plugin) + ((), page_hash) + () + () + + let fetch_missing_page dac_client hash = + let open Lwt_result_syntax in + let dac_plugin = dac_client.dac_plugin in + let dac_hash = proto_hash_to_dac_hash dac_plugin hash in + let+ preimage = + fetch_missing_page_call dac_plugin dac_client.observer_cctx dac_hash + in + String.of_bytes preimage +end + +let timeout_default = Z.of_int 60 + +let init ~observer_endpoint () = + let open Lwt_result_syntax in + let* dac_plugin = + match Dac_plugin.get Protocol.hash with + | Some dac_plugin -> return dac_plugin + | None -> + let () = Dac_plugin.register Dac_plugin_registration.make_plugin in + Option.fold_f + ~none:(fun () -> tzfail @@ Cannot_initlized_dac_plugin) + ~some:(fun p -> return p) + (Dac_plugin.get Protocol.hash) + in + let observer_cctx = Client.make_unix observer_endpoint in + let+ _ping = Client.ping observer_cctx in + {config = {observer_endpoint}; observer_cctx; dac_plugin} + +let fetch_preimage ?(timeout_s = timeout_default) dac_client hash = + let open Lwt_result_syntax in + let run () = + Lwt_unix.with_timeout (Z.to_float timeout_s) (fun () -> + Client.fetch_missing_page dac_client hash) + in + Lwt.catch run (function + | Lwt_unix.Timeout -> tzfail @@ Timeout timeout_s + | _ -> tzfail Cannot_request_preimage_from_observer) diff --git a/src/proto_alpha/lib_dac_plugin/dac_observer_client.mli b/src/proto_alpha/lib_dac_plugin/dac_observer_client.mli new file mode 100644 index 000000000000..27be20f1e69c --- /dev/null +++ b/src/proto_alpha/lib_dac_plugin/dac_observer_client.mli @@ -0,0 +1,57 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 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. *) +(* *) +(*****************************************************************************) + +(* Client for interacting with a Dac Node in Observer mode. *) + +module Reveal_hash = Tezos_protocol_alpha.Protocol.Sc_rollup_reveal_hash +module Dac_client = Dac_node_client + +type error += + | Cannot_initlized_dac_plugin + | Timeout of Z.t + | Cannot_request_preimage_from_observer + +module Configuration : sig + type t +end + +type t + +(** [init observer_endpoint] initializes a [Dac_observer_client.t] with + base endpoint point to [observer_endpoint]. +*) +val init : + observer_endpoint:Uri.t -> + unit -> + (t, error trace) result Lwt.t +(** [fetch_preimage ?timeout_s dac_observer_client hash] requests the preimage of [hash] + from a Dac Observer Node. As a side effect, the Observer node saves the preimage to + disk before returning. +*) +val fetch_preimage : + ?timeout_s:Z.t -> + t -> + Tezos_protocol_alpha.Protocol.Sc_rollup_reveal_hash.t -> + string tzresult Lwt.t diff --git a/src/proto_alpha/lib_dac_plugin/dune b/src/proto_alpha/lib_dac_plugin/dune index dee875addab8..ce6fc8440ebb 100644 --- a/src/proto_alpha/lib_dac_plugin/dune +++ b/src/proto_alpha/lib_dac_plugin/dune @@ -10,6 +10,7 @@ octez-protocol-compiler.registerer tezos-stdlib-unix tezos-dac-lib + tezos-dac-client-lib tezos-client-alpha tezos-embedded-protocol-alpha tezos-protocol-alpha) @@ -23,6 +24,7 @@ -open Tezos_protocol_registerer -open Tezos_stdlib_unix -open Tezos_dac_lib + -open Tezos_dac_client_lib -open Tezos_client_alpha -open Tezos_embedded_protocol_alpha -open Tezos_protocol_alpha)) diff --git a/tezt/tests/dac.ml b/tezt/tests/dac.ml index e4733597ccd2..495dfa3ef77f 100644 --- a/tezt/tests/dac.ml +++ b/tezt/tests/dac.ml @@ -1141,7 +1141,7 @@ let test_get_certificate _protocol _tezos_node _tz_client coordinator _threshold returning it in the response. This can be observer by checking the result of retrieving preimage before and after the GET /missing_page/{hash} call.*) let test_observer_get_missing_page _protocol node client coordinator threshold - dac_members = + _committee_members = let root_hash = "00649d431e829f4adc68edecb8d8d8071154b57086cc124b465f6f6600a4bc91c7" in @@ -1154,15 +1154,7 @@ let test_observer_get_missing_page _protocol node client coordinator threshold assert (root_hash = Hex.show hex_root_hash) ; let* () = root_hash_stream_promise in let observer = - Dac_node.create_legacy - ~threshold - ~committee_members: - (List.map - (fun (dc : Account.aggregate_key) -> dc.aggregate_public_key_hash) - dac_members) - ~node - ~client - () + Dac_node.create_legacy ~threshold ~committee_members:[] ~node ~client () in let* _ = Dac_node.init_config observer in let () = Legacy.set_coordinator observer coordinator in -- GitLab From 970d2f0e6bc5598fdbbce3694a0113e108337554 Mon Sep 17 00:00:00 2001 From: Ryan Tan Date: Wed, 22 Mar 2023 15:07:16 +0000 Subject: [PATCH 7/7] Dac: integrate dac observer client into rollup --- manifest/main.ml | 103 +++++++++--------- opam/octez-smart-rollup-node-alpha.opam | 1 + src/proto_alpha/lib_sc_rollup_node/dune | 6 +- .../lib_sc_rollup_node/fueled_pvm.ml | 2 +- .../lib_sc_rollup_node/refutation_game.ml | 2 +- src/proto_alpha/lib_sc_rollup_node/reveals.ml | 14 ++- .../lib_sc_rollup_node/reveals.mli | 3 +- 7 files changed, 71 insertions(+), 60 deletions(-) diff --git a/manifest/main.ml b/manifest/main.ml index 54cecd8f9842..9d8dae9a462a 100644 --- a/manifest/main.ml +++ b/manifest/main.ml @@ -5233,6 +5233,57 @@ module Protocol = Protocol ~inline_tests:ppx_expect ~linkall:true in + let dac = + (* [~link_all:true] is necessary to ensure that the dac plugin + registration happens when running the dal node. Removing this + option would cause DAL related tezts to fail because the DAC + plugin cannot be resolved. *) + only_if (active && N.(number >= 017)) @@ fun () -> + public_lib + (sf "tezos-dac-%s" name_dash) + ~path:(path // "lib_dac_plugin") + ~synopsis: + "Tezos/Protocol: protocol specific library for the Data availability \ + Committee" + ~deps: + [ + octez_base |> open_ ~m:"TzPervasives" + |> open_ ~m:"TzPervasives.Error_monad.Legacy_monad_globals"; + octez_protocol_compiler_registerer |> open_; + octez_stdlib_unix |> open_; + octez_dac_lib |> open_; + octez_dac_client_lib |> open_; + client |> if_some |> open_; + embedded |> open_; + main |> open_; + ] + ~inline_tests:ppx_expect + ~linkall:true + in + let _dac_tests = + only_if (active && N.(number >= 017)) @@ fun () -> + tezt + [ + "test_dac_pages_encoding"; + "test_dac_plugin_registration"; + "test_helpers"; + ] + ~path:(path // "lib_dac_plugin/test") + ~with_macos_security_framework:true + ~opam:(sf "tezos-dac-%s" name_dash) + ~deps: + [ + octez_base |> open_ ~m:"TzPervasives" + |> open_ ~m:"TzPervasives.Error_monad.Legacy_monad_globals"; + dac |> if_some |> open_; + main |> open_; + octez_base_test_helpers |> open_; + test_helpers |> if_some |> open_; + octez_dac_lib |> open_; + octez_dac_node_lib |> open_; + alcotezt; + ] + in let octez_sc_rollup_layer2 = only_if N.(number >= 016) @@ fun () -> public_lib @@ -5293,6 +5344,7 @@ module Protocol = Protocol octez_crypto_dal |> if_ N.(number >= 016) |> open_; prometheus_app |> if_ N.(number >= 016); octez_node_config |> if_ N.(number >= 016); + dac |> if_some |> open_; ] in let octez_sc_rollup_client = @@ -5478,57 +5530,6 @@ module Protocol = Protocol alcotezt; ] in - let dac = - (* [~link_all:true] is necessary to ensure that the dac plugin - registration happens when running the dal node. Removing this - option would cause DAL related tezts to fail because the DAC - plugin cannot be resolved. *) - only_if (active && N.(number >= 017)) @@ fun () -> - public_lib - (sf "tezos-dac-%s" name_dash) - ~path:(path // "lib_dac_plugin") - ~synopsis: - "Tezos/Protocol: protocol specific library for the Data availability \ - Committee" - ~deps: - [ - octez_base |> open_ ~m:"TzPervasives" - |> open_ ~m:"TzPervasives.Error_monad.Legacy_monad_globals"; - octez_protocol_compiler_registerer |> open_; - octez_stdlib_unix |> open_; - octez_dac_lib |> open_; - octez_dac_client_lib |> open_; - client |> if_some |> open_; - embedded |> open_; - main |> open_; - ] - ~inline_tests:ppx_expect - ~linkall:true - in - let _dac_tests = - only_if (active && N.(number >= 017)) @@ fun () -> - tezt - [ - "test_dac_pages_encoding"; - "test_dac_plugin_registration"; - "test_helpers"; - ] - ~path:(path // "lib_dac_plugin/test") - ~with_macos_security_framework:true - ~opam:(sf "tezos-dac-%s" name_dash) - ~deps: - [ - octez_base |> open_ ~m:"TzPervasives" - |> open_ ~m:"TzPervasives.Error_monad.Legacy_monad_globals"; - dac |> if_some |> open_; - main |> open_; - octez_base_test_helpers |> open_; - test_helpers |> if_some |> open_; - octez_dac_lib |> open_; - octez_dac_node_lib |> open_; - alcotezt; - ] - in let benchmark_type_inference = only_if active @@ fun () -> public_lib diff --git a/opam/octez-smart-rollup-node-alpha.opam b/opam/octez-smart-rollup-node-alpha.opam index 3cb31b9221ad..89f60843426f 100644 --- a/opam/octez-smart-rollup-node-alpha.opam +++ b/opam/octez-smart-rollup-node-alpha.opam @@ -42,6 +42,7 @@ depends: [ "tezos-crypto-dal" "prometheus-app" { >= "1.2" } "octez-node-config" + "tezos-dac-alpha" "tezos-clic" "tezos-client-commands" ] diff --git a/src/proto_alpha/lib_sc_rollup_node/dune b/src/proto_alpha/lib_sc_rollup_node/dune index cf52914bd2cd..8487f124c451 100644 --- a/src/proto_alpha/lib_sc_rollup_node/dune +++ b/src/proto_alpha/lib_sc_rollup_node/dune @@ -40,7 +40,8 @@ tezos-scoru-wasm-fast tezos-crypto-dal prometheus-app - octez-node-config) + octez-node-config + tezos-dac-alpha) (flags (:standard) -open Tezos_base @@ -62,4 +63,5 @@ -open Tezos_layer2_store -open Octez_crawler -open Octez_injector - -open Tezos_crypto_dal)) + -open Tezos_crypto_dal + -open Tezos_dac_alpha)) diff --git a/src/proto_alpha/lib_sc_rollup_node/fueled_pvm.ml b/src/proto_alpha/lib_sc_rollup_node/fueled_pvm.ml index eed5cb02fefe..b31457de4831 100644 --- a/src/proto_alpha/lib_sc_rollup_node/fueled_pvm.ml +++ b/src/proto_alpha/lib_sc_rollup_node/fueled_pvm.ml @@ -88,7 +88,7 @@ module Make (PVM : Pvm.S) = struct in match found_in_map with | Some data -> return data - | None -> Reveals.get ~data_dir ~pvm_kind:PVM.kind ~hash + | None -> Reveals.get ~data_dir ~pvm_kind:PVM.kind hash let continue_with_fuel consumption initial_fuel state f = let open Delayed_write_monad.Lwt_result_syntax in diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_game.ml b/src/proto_alpha/lib_sc_rollup_node/refutation_game.ml index fcc0cb9f7953..465b3e5ba928 100644 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_game.ml +++ b/src/proto_alpha/lib_sc_rollup_node/refutation_game.ml @@ -217,7 +217,7 @@ module Make (Interpreter : Interpreter.S) : let reveal hash = let open Lwt_syntax in let* res = - Reveals.get ~data_dir:node_ctxt.data_dir ~pvm_kind:PVM.kind ~hash + Reveals.get ~data_dir:node_ctxt.data_dir ~pvm_kind:PVM.kind hash in match res with Ok data -> return @@ Some data | Error _ -> return None diff --git a/src/proto_alpha/lib_sc_rollup_node/reveals.ml b/src/proto_alpha/lib_sc_rollup_node/reveals.ml index e61edb2d4003..297955f5185e 100644 --- a/src/proto_alpha/lib_sc_rollup_node/reveals.ml +++ b/src/proto_alpha/lib_sc_rollup_node/reveals.ml @@ -87,17 +87,23 @@ let file_contents filename = Lwt.catch (fun () -> let*! contents = Lwt_utils_unix.read_file filename in - return contents) - (fun _ -> tzfail @@ Could_not_open_preimage_file filename) + return @@ Some contents) + (fun _ -> return_none) let path data_dir pvm_name hash = let hash = Protocol.Sc_rollup_reveal_hash.to_hex hash in Filename.(concat (concat data_dir pvm_name) hash) -let get ~data_dir ~pvm_kind ~hash = +let get ?dac_client_opt ~data_dir ~pvm_kind hash = let open Lwt_result_syntax in let filename = path data_dir (Sc_rollup.Kind.to_string pvm_kind) hash in - let* contents = file_contents filename in + let* contents_opt = file_contents filename in + let* contents = + match (contents_opt, dac_client_opt) with + | Some contents, _ -> return contents + | None, Some client -> Dac_observer_client.fetch_preimage client hash + | None, None -> tzfail @@ Could_not_open_preimage_file filename + in let*? () = let contents_hash = Reveal_hash.hash_string ~scheme:Reveal_hash.Blake2B [contents] diff --git a/src/proto_alpha/lib_sc_rollup_node/reveals.mli b/src/proto_alpha/lib_sc_rollup_node/reveals.mli index 56950f44c8b6..3914c56d1831 100644 --- a/src/proto_alpha/lib_sc_rollup_node/reveals.mli +++ b/src/proto_alpha/lib_sc_rollup_node/reveals.mli @@ -67,7 +67,8 @@ type source = 4kB) to be revealed.} } *) val get : + ?dac_client_opt:Dac_observer_client.t -> data_dir:string -> pvm_kind:Protocol.Alpha_context.Sc_rollup.Kind.t -> - hash:Protocol.Sc_rollup_reveal_hash.t -> + Protocol.Sc_rollup_reveal_hash.t -> string tzresult Lwt.t -- GitLab