From 8728353b3ff5c469dd859a0f4966c4c036e6a0e9 Mon Sep 17 00:00:00 2001 From: martintomazic Date: Tue, 16 May 2023 14:34:35 +0200 Subject: [PATCH 1/5] DAC: Introduce `V1` API --- src/lib_dac/RPC_services.ml | 2 ++ src/lib_dac/RPC_services.mli | 7 ++++--- src/lib_dac/api_version.ml | 8 ++++++-- src/lib_dac/api_version.mli | 9 ++++++++- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/lib_dac/RPC_services.ml b/src/lib_dac/RPC_services.ml index 47a912134410..b41b49b61800 100644 --- a/src/lib_dac/RPC_services.ml +++ b/src/lib_dac/RPC_services.ml @@ -136,3 +136,5 @@ let get_health_ready = ~query:Tezos_rpc.Query.empty ~output:Data_encoding.bool Tezos_rpc.Path.(open_root / "health" / "ready") + +module V1 = struct end diff --git a/src/lib_dac/RPC_services.mli b/src/lib_dac/RPC_services.mli index f11e7be6a766..e115da866800 100644 --- a/src/lib_dac/RPC_services.mli +++ b/src/lib_dac/RPC_services.mli @@ -23,9 +23,6 @@ (* *) (*****************************************************************************) -(* TODO: https://gitlab.com/tezos/tezos/-/issues/5579 - Add support for first publicly released DAC API [V1]. *) - (** [V0] is experimental DAC API. [V0] is deprecated, however for the time being the API will be binding. It will be used by 1M/tps demo. The plan is to remove it once we get rid of the @@ -117,3 +114,7 @@ val get_health_live : and fail with [tzfail Dac_node_not_ready] otherwise. *) val get_health_ready : ([`GET], unit, unit, unit, unit, bool) Tezos_rpc.Service.service + +(** [V1] is a second major DAC API release. + [V1] API is work in progress. Do not use! *) +module V1 : sig end diff --git a/src/lib_dac/api_version.ml b/src/lib_dac/api_version.ml index b8f0d77de4d1..e8a539ed2476 100644 --- a/src/lib_dac/api_version.ml +++ b/src/lib_dac/api_version.ml @@ -24,8 +24,12 @@ (* *) (*****************************************************************************) -type t = V0 +type t = V0 | V1 -let to_rpc_path_prefix = function V0 -> Tezos_rpc.Path.(open_root / "v0") +let to_rpc_path_prefix = function + | V0 -> Tezos_rpc.Path.(open_root / "v0") + | V1 -> Tezos_rpc.Path.(open_root / "v1") let v0_prefix = to_rpc_path_prefix V0 + +let v1_prefix = to_rpc_path_prefix V1 diff --git a/src/lib_dac/api_version.mli b/src/lib_dac/api_version.mli index 597d9f739ef2..f8ec595dd82b 100644 --- a/src/lib_dac/api_version.mli +++ b/src/lib_dac/api_version.mli @@ -27,7 +27,14 @@ (** [Api_version] module is used for versioning DAC API. *) (** [t] type is used to version DAC API. *) -type t = V0 (** [V0] is experimental DAC API. Use at your own risk! *) +type t = + | V0 (** [V0] is experimental DAC API. Use at your own risk! *) + | V1 + (** [V1] is a second major DAC API release. + [V1] API is work in progress. Do not use! *) (** [v0_prefix] is [V0] API RPC prefix. *) val v0_prefix : (unit, unit) Tezos_rpc.Path.t + +(** [v1_prefix] is [V1] API RPC prefix. *) +val v1_prefix : (unit, unit) Tezos_rpc.Path.t -- GitLab From b6dcf7dfc79167dfeb02a815e7bd8e9687c6b53e Mon Sep 17 00:00:00 2001 From: martintomazic Date: Tue, 16 May 2023 14:43:54 +0200 Subject: [PATCH 2/5] DAC: Add "GET v1/pages" to `V1` API rpc services --- src/lib_dac/RPC_services.ml | 11 ++++++++++- src/lib_dac/RPC_services.mli | 14 +++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/lib_dac/RPC_services.ml b/src/lib_dac/RPC_services.ml index b41b49b61800..7fe6eb452b30 100644 --- a/src/lib_dac/RPC_services.ml +++ b/src/lib_dac/RPC_services.ml @@ -137,4 +137,13 @@ let get_health_ready = ~output:Data_encoding.bool Tezos_rpc.Path.(open_root / "health" / "ready") -module V1 = struct end +module V1 = struct + let v1_prefix = Api_version.v1_prefix + + let get_pages = + Tezos_rpc.Service.get_service + ~description:"Retrieves a page by its page hash and returns its contents" + ~query:Tezos_rpc.Query.empty + ~output:Data_encoding.bytes + Tezos_rpc.Path.(v1_prefix / "pages" /: Dac_plugin.raw_hash_rpc_arg) +end diff --git a/src/lib_dac/RPC_services.mli b/src/lib_dac/RPC_services.mli index e115da866800..e10d84d47f16 100644 --- a/src/lib_dac/RPC_services.mli +++ b/src/lib_dac/RPC_services.mli @@ -117,4 +117,16 @@ val get_health_ready : (** [V1] is a second major DAC API release. [V1] API is work in progress. Do not use! *) -module V1 : sig end +module V1 : sig + (** "GET v1/pages" requests the preimage of hash, consisting of a + single page, from cctxt. When the request succeeds, the raw page will be + returned as a sequence of bytes. *) + val get_pages : + ( [`GET], + unit, + unit * Dac_plugin.raw_hash, + unit, + unit, + Bytes.t ) + Tezos_rpc.Service.service +end -- GitLab From c0f8bb8be4df224b7d9823407278a0377b565277 Mon Sep 17 00:00:00 2001 From: martintomazic Date: Tue, 16 May 2023 14:56:56 +0200 Subject: [PATCH 3/5] DAC: Register "GET v1/pages" --- src/lib_dac_node/RPC_server.ml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/lib_dac_node/RPC_server.ml b/src/lib_dac_node/RPC_server.ml index 3626fad3379c..10023c2be93c 100644 --- a/src/lib_dac_node/RPC_server.ml +++ b/src/lib_dac_node/RPC_server.ml @@ -144,6 +144,7 @@ let handle_get_verify_signature dac_plugin public_keys_opt encoded_l1_message = signature witnesses +(** [handle_get_preimage] is shared by both [V0] and [V1] API. *) let handle_get_preimage dac_plugin page_store raw_hash = let open Lwt_result_syntax in let*? hash = Dac_plugin.raw_to_hash dac_plugin raw_hash in @@ -245,6 +246,12 @@ let register_get_missing_page dac_plugin page_store cctxt = (fun root_hash () () -> handle_get_missing_page cctxt page_store dac_plugin root_hash) +let register_get_pages dac_plugin page_store = + add_service + Tezos_rpc.Directory.register1 + RPC_services.V1.get_pages + (fun hash () () -> handle_get_preimage dac_plugin page_store hash) + module Coordinator = struct let handle_post_preimage dac_plugin page_store hash_streamer payload = let open Lwt_result_syntax in @@ -375,11 +382,14 @@ module Coordinator = struct rw_store page_store |> register_get_certificate rw_store dac_plugin + |> register_get_pages dac_plugin page_store end module Committee_member = struct let dynamic_rpc_dir dac_plugin page_store = - Tezos_rpc.Directory.empty |> register_get_preimage dac_plugin page_store + Tezos_rpc.Directory.empty + |> register_get_preimage dac_plugin page_store + |> register_get_pages dac_plugin page_store end module Observer = struct @@ -387,6 +397,7 @@ module Observer = struct Tezos_rpc.Directory.empty |> register_get_preimage dac_plugin page_store |> register_get_missing_page dac_plugin page_store coordinator_cctxt + |> register_get_pages dac_plugin page_store end module Legacy = struct -- GitLab From 86ac4d06d44388e4cecbbe68b8b5cc687d9cef06 Mon Sep 17 00:00:00 2001 From: martintomazic Date: Tue, 16 May 2023 15:48:22 +0200 Subject: [PATCH 4/5] DAC/tezt: Add V1 module to `Dac_rpc` --- tezt/lib_tezos/dac_rpc.ml | 7 +++++++ tezt/lib_tezos/dac_rpc.mli | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/tezt/lib_tezos/dac_rpc.ml b/tezt/lib_tezos/dac_rpc.ml index 37a4e4905db3..cc747722c8ea 100644 --- a/tezt/lib_tezos/dac_rpc.ml +++ b/tezt/lib_tezos/dac_rpc.ml @@ -110,3 +110,10 @@ end let get_health_live = make GET ["health"; "live"] JSON.as_bool let get_health_ready = make GET ["health"; "ready"] JSON.as_bool + +module V1 = struct + let api_prefix = "v1" + + let get_pages page_hash = + make GET [api_prefix; "pages"; page_hash] JSON.as_string +end diff --git a/tezt/lib_tezos/dac_rpc.mli b/tezt/lib_tezos/dac_rpc.mli index b6b1e77f5ce2..003a714e7ac1 100644 --- a/tezt/lib_tezos/dac_rpc.mli +++ b/tezt/lib_tezos/dac_rpc.mli @@ -85,3 +85,12 @@ val get_health_live : (Dac_node.t, bool) RPC_core.t [Node_context.get_status cctxt] is [Ready] and fail with [tzfail Dac_node_not_ready] otherwise. *) val get_health_ready : (Dac_node.t, bool) RPC_core.t + +(** [V1] is a second major DAC API release which is currently work in progress. *) +module V1 : sig + (** [get_pages hash] requests the preimage of hash, consisting of a + single page, from cctxt. When the request succeeds, the raw page will be + returned as a sequence of bytes. This is achieved by calling + "GET v1/pages". *) + val get_pages : string -> (Dac_node.t, string) RPC_core.t +end -- GitLab From 9e701eed231eb9dbc1b18cdbc8660e6743c90a23 Mon Sep 17 00:00:00 2001 From: martintomazic Date: Wed, 17 May 2023 01:33:20 +0200 Subject: [PATCH 5/5] DAC/tezt: Test "GET v1/pages" --- tezt/tests/dac.ml | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/tezt/tests/dac.ml b/tezt/tests/dac.ml index 82de8e1c2529..fbbe642ee566 100644 --- a/tezt/tests/dac.ml +++ b/tezt/tests/dac.ml @@ -306,6 +306,8 @@ let sample_payload example_filename = let root_hash = JSON.(json |-> "root_hash" |> as_string) in (payload, root_hash) +let decode_hex_string_to_bytes s = Hex.to_string (`Hex s) + (** This modules encapsulate tests for DAC nodes when running in legacy node. It includes tests where we have two dac nodes running in the legacy mode interacting with each other. As such one node normally tries @@ -2615,6 +2617,36 @@ let register_with_unsupported_protocol ~protocols = Observer.test_dac_not_ready_without_protocol protocols ; Member.test_dac_not_ready_without_protocol protocols +(** [V1_API] is a test suite for [V1] API. *) +module V1_API = struct + (** Test "v1/page" endpoint. *) + let test_get_pages Scenarios.{coordinator_node; _} = + (* 1. Post [payload] to [Coordinator] and receive [root_hash]. + 2. Asumming that [payload] fits into one [Contents] page + retrieving it via [GET v1/pages/[root_hash]] should result + in initial payload. *) + let payload = "test" in + (* Assert that [expected] payload fits onto one [Contents] page. + Since [init_hex_root_hash] calls "POST v0/preimage" that uses + [Merkle_tree.V0] serialization, [max_page_size] is 4096 bytes, + out of which 5 bytes are for preamble, meaning inital payload + can be at max 4091 bytes in size for the above to hold. *) + let () = assert (Bytes.length (String.to_bytes payload) < 4091) in + let* root_hash = + (* TODO https://gitlab.com/tezos/tezos/-/issues/5671 + Once we have "PUT v1/preimage" we should use a call to [V1] api here + instead. *) + RPC.call coordinator_node (Dac_rpc.V0.Coordinator.post_preimage ~payload) + in + let* raw = RPC.call coordinator_node (Dac_rpc.V1.get_pages @@ root_hash) in + let remove_preamble s = + let preamle_size = 5 in + String.(sub s preamle_size (length s - preamle_size)) + in + let actual = remove_preamble (decode_hex_string_to_bytes raw) in + return @@ check_preimage payload actual +end + let register ~protocols = (* Tests with layer1 and dac nodes *) Legacy.test_dac_node_startup protocols ; @@ -2749,4 +2781,12 @@ let register ~protocols = (Full_infrastructure.test_client ~send_payload_from_file:true) protocols ; Tx_kernel_e2e.test_tx_kernel_e2e_with_dac_observer_synced_with_dac protocols ; - Tx_kernel_e2e.test_tx_kernel_e2e_with_dac_observer_missing_pages protocols + Tx_kernel_e2e.test_tx_kernel_e2e_with_dac_observer_missing_pages protocols ; + scenario_with_full_dac_infrastructure + ~__FILE__ + ~observers:0 + ~committee_size:0 + ~tags:["dac"; "dac_node"] + "test v1/get_pages" + V1_API.test_get_pages + protocols -- GitLab