From 3fa15281ad1f133cf522c1594b0cc3ad866cc225 Mon Sep 17 00:00:00 2001 From: Martin Tomazic Date: Tue, 9 May 2023 12:46:39 +0200 Subject: [PATCH 1/5] DAC: Remove register_get_verify_signature from Coordinator mode --- src/lib_dac_node/RPC_server.ml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/lib_dac_node/RPC_server.ml b/src/lib_dac_node/RPC_server.ml index 2135cc2bf98c..d5ae9d733047 100644 --- a/src/lib_dac_node/RPC_server.ml +++ b/src/lib_dac_node/RPC_server.ml @@ -325,14 +325,10 @@ module Coordinator = struct let hash_streamer = coordinator_node_ctxt.Node_context.Coordinator.hash_streamer in - let public_keys_opt = - Node_context.Coordinator.public_keys_opt coordinator_node_ctxt - in let certificate_streamers = coordinator_node_ctxt.certificate_streamers in let committee_members = coordinator_node_ctxt.committee_members in Tezos_rpc.Directory.empty |> register_post_preimage dac_plugin hash_streamer page_store - |> register_get_verify_signature dac_plugin public_keys_opt |> register_get_preimage dac_plugin page_store |> register_monitor_root_hashes hash_streamer |> register_monitor_certificate -- GitLab From d2add33e8322a89723c60272046c9438c19c84f4 Mon Sep 17 00:00:00 2001 From: Martin Tomazic Date: Mon, 24 Apr 2023 12:22:04 +0200 Subject: [PATCH 2/5] DAC: Define `Api` module for versioning DAC API --- src/lib_dac/RPC_services.ml | 18 ++++++++++++++++++ src/lib_dac/RPC_services.mli | 14 ++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/lib_dac/RPC_services.ml b/src/lib_dac/RPC_services.ml index a8d5821dfced..9952a54da791 100644 --- a/src/lib_dac/RPC_services.ml +++ b/src/lib_dac/RPC_services.ml @@ -24,6 +24,24 @@ (* *) (*****************************************************************************) +module Api = struct + type version = V0 + + let version_rpc_arg = + let construct = function V0 -> "v0" in + let destruct version = + match version with + | "v0" -> Ok V0 + | invalid_version -> Error invalid_version + in + Tezos_rpc.Arg.make + ~descr:"API version" + ~name:"api_version" + ~destruct + ~construct + () +end + (* A variant of [Sc_rollup_reveal_hash.encoding] that prefers hex encoding over b58check encoding for JSON. *) let store_preimage_request_encoding = diff --git a/src/lib_dac/RPC_services.mli b/src/lib_dac/RPC_services.mli index 2ee345314dba..fd7f76538745 100644 --- a/src/lib_dac/RPC_services.mli +++ b/src/lib_dac/RPC_services.mli @@ -23,6 +23,20 @@ (* *) (*****************************************************************************) +(** [Api] module is used for versioning DAC API. *) +module Api : sig + (** [version] type is used to version DAC API. *) + type version = + | V0 + (** [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 + [Legacy] mode. Use at your own risk! *) + + (** [version_rpc_arg] is a API version argument for the RPCs.*) + val version_rpc_arg : version Tezos_rpc.Arg.arg +end + (** POST dac/store_preimage to post a payload using a given [pagination_scheme]. It returns the base58 encoded root page hash and the raw bytes. *) -- GitLab From c937bf20a21ad7e7056c399d0109c77825d36d66 Mon Sep 17 00:00:00 2001 From: Martin Tomazic Date: Tue, 9 May 2023 16:46:31 +0200 Subject: [PATCH 3/5] DAC: Introduce experimental (but binding) `V0` API --- src/lib_dac/RPC_services.ml | 20 ++-- src/lib_dac/RPC_services.mli | 69 +++++++----- src/lib_dac/monitor_services.ml | 20 +++- src/lib_dac/monitor_services.mli | 12 +- src/lib_dac_client/dac_node_client.ml | 40 +++++-- src/lib_dac_node/RPC_server.ml | 37 ++++--- src/lib_dac_node/handler.ml | 6 +- tezt/lib_tezos/dac_rpc.ml | 32 +++--- tezt/lib_tezos/dac_rpc.mli | 54 ++++++--- tezt/tests/dac.ml | 154 +++++++++++++++++++------- 10 files changed, 296 insertions(+), 148 deletions(-) diff --git a/src/lib_dac/RPC_services.ml b/src/lib_dac/RPC_services.ml index 9952a54da791..d69b2c5074aa 100644 --- a/src/lib_dac/RPC_services.ml +++ b/src/lib_dac/RPC_services.ml @@ -69,7 +69,7 @@ let post_store_preimage = ~query:Tezos_rpc.Query.empty ~input:store_preimage_request_encoding ~output:store_preimage_response_encoding - Tezos_rpc.Path.(open_root / "store_preimage") + Tezos_rpc.Path.(open_root /: Api.version_rpc_arg / "store_preimage") (* DAC/FIXME: https://gitlab.com/tezos/tezos/-/issues/4263 remove this endpoint once end-to-end tests are in place. *) @@ -78,14 +78,16 @@ let get_verify_signature = ~description:"Verify signature of an external message to inject in L1" ~query:external_message_query ~output:Data_encoding.bool - Tezos_rpc.Path.(open_root / "verify_signature") + Tezos_rpc.Path.(open_root /: Api.version_rpc_arg / "verify_signature") let get_preimage = 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.(open_root / "preimage" /: Dac_plugin.raw_hash_rpc_arg) + Tezos_rpc.Path.( + open_root /: Api.version_rpc_arg / "preimage" + /: Dac_plugin.raw_hash_rpc_arg) let put_dac_member_signature = Tezos_rpc.Service.put_service @@ -94,7 +96,7 @@ let put_dac_member_signature = ~query:Tezos_rpc.Query.empty ~input:Signature_repr.encoding ~output:Data_encoding.empty - Tezos_rpc.Path.(open_root / "dac_member_signature") + Tezos_rpc.Path.(open_root /: Api.version_rpc_arg / "dac_member_signature") let get_certificate = Tezos_rpc.Service.get_service @@ -102,7 +104,9 @@ let get_certificate = "Retrieve the Dac certificate associated with the given root page hash" ~query:Tezos_rpc.Query.empty ~output:(Data_encoding.option Certificate_repr.encoding) - Tezos_rpc.Path.(open_root / "certificates" /: Dac_plugin.raw_hash_rpc_arg) + Tezos_rpc.Path.( + open_root /: Api.version_rpc_arg / "certificates" + /: Dac_plugin.raw_hash_rpc_arg) let get_missing_page = Tezos_rpc.Service.get_service @@ -113,7 +117,9 @@ let get_missing_page = Observer mode." ~query:Tezos_rpc.Query.empty ~output:Data_encoding.bytes - Tezos_rpc.Path.(open_root / "missing_page" /: Dac_plugin.raw_hash_rpc_arg) + Tezos_rpc.Path.( + open_root /: Api.version_rpc_arg / "missing_page" + /: Dac_plugin.raw_hash_rpc_arg) (* TODO: https://gitlab.com/tezos/tezos/-/issues/4935 Coordinator's "POST /preimage" endpoint should in addition to root page hash @@ -133,5 +139,5 @@ module Coordinator = struct ~query:Tezos_rpc.Query.empty ~input:Data_encoding.bytes ~output:Dac_plugin.raw_hash_encoding - Tezos_rpc.Path.(open_root / "preimage") + Tezos_rpc.Path.(open_root /: Api.version_rpc_arg / "preimage") end diff --git a/src/lib_dac/RPC_services.mli b/src/lib_dac/RPC_services.mli index fd7f76538745..234e172c8503 100644 --- a/src/lib_dac/RPC_services.mli +++ b/src/lib_dac/RPC_services.mli @@ -33,79 +33,94 @@ module Api : sig 1M/tps demo. The plan is to remove it once we get rid of the [Legacy] mode. Use at your own risk! *) + (* TODO: https://gitlab.com/tezos/tezos/-/issues/5579 + Add support for first publicly released DAC API [V1]. *) + (** [version_rpc_arg] is a API version argument for the RPCs.*) val version_rpc_arg : version Tezos_rpc.Arg.arg end -(** POST dac/store_preimage to post a payload using a given [pagination_scheme]. - It returns the base58 encoded root page hash - and the raw bytes. *) +(** "POST [api_version]/store_preimage" stores a payload using a given + [pagination_scheme]. It returns the base58 encoded root page hash + and the raw bytes. *) val post_store_preimage : ( [`POST], unit, - unit, + unit * Api.version, unit, Bytes.t * Pagination_scheme.t, Dac_plugin.raw_hash * Bytes.t ) Tezos_rpc.Service.service -(** GET dac/verify_signature endpoint requests the DAL node to verify - the signature of the external message [external_message]. The DAC committee - of the DAL node must be the same that was used to produce the - [external_message]. *) +(** "GET [api_version]/verify_signature" endpoint requests the DAL node to verify + the signature of the external message [external_message]. The DAC committee + of the DAL node must be the same that was used to produce the + [external_message]. *) val get_verify_signature : - ([`GET], unit, unit, string option, unit, bool) Tezos_rpc.Service.service + ( [`GET], + unit, + unit * Api.version, + string option, + unit, + bool ) + Tezos_rpc.Service.service -(** GET dac/preimage requests the preimage of hash, consisting of a +(** "GET [api_version]/preimage" 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_preimage : ( [`GET], unit, - unit * Dac_plugin.raw_hash, + (unit * Api.version) * Dac_plugin.raw_hash, unit, unit, Bytes.t ) Tezos_rpc.Service.service -(** PUT dac/member_signature endpoint stores the [signature] - generated from signing [hex_root_hash] by [dac_member_pkh]. *) +(** "PUT [api_version]/member_signature" endpoint stores the [signature] + generated from signing [hex_root_hash] by [dac_member_pkh]. *) val put_dac_member_signature : - ([`PUT], unit, unit, unit, Signature_repr.t, unit) Tezos_rpc.Service.service + ( [`PUT], + unit, + unit * Api.version, + unit, + Signature_repr.t, + unit ) + Tezos_rpc.Service.service -(** GET dac/certificate endpoint returns the DAC certificate for the - provided [root_page_hash]. *) +(** "GET [api_version]/certificate" endpoint returns the DAC certificate for the + provided [root_page_hash]. *) val get_certificate : ( [`GET], unit, - unit * Dac_plugin.raw_hash, + (unit * Api.version) * Dac_plugin.raw_hash, unit, unit, Certificate_repr.t option ) Tezos_rpc.Service.service -(** GET dac/missing_page/[page_hash] Observer fetches the missing page - from a Coordinator node. The missing page is then saved to a - page store before returning the page as a response. *) +(** "GET [api_version]/missing_page/[page_hash]" Observer fetches the missing page + from a Coordinator node. The missing page is then saved to a + page store before returning the page as a response. *) val get_missing_page : ( [`GET], unit, - unit * Dac_plugin.raw_hash, + (unit * Api.version) * Dac_plugin.raw_hash, unit, unit, Bytes.t ) Tezos_rpc.Service.service module Coordinator : sig - (** POST dac/preimage sends a [payload] to the DAC - [Coordinator]. It returns a hex encoded root page hash, - produced by [Merkle_tree_V0] pagination scheme. - On the backend side it also pushes root page hash of the preimage to all - the subscribed DAC Members and Observers. *) + (** "POST [api_version]/preimage" sends a [payload] to the DAC + [Coordinator]. It returns a hex encoded root page hash, + produced by [Merkle_tree_V0] pagination scheme. + On the backend side it also pushes root page hash of the preimage to all + the subscribed DAC Members and Observers. *) val post_preimage : ( [`POST], unit, - unit, + unit * Api.version, unit, Bytes.t, Dac_plugin.raw_hash ) diff --git a/src/lib_dac/monitor_services.ml b/src/lib_dac/monitor_services.ml index 41a38017d90b..cc0e7d2a6974 100644 --- a/src/lib_dac/monitor_services.ml +++ b/src/lib_dac/monitor_services.ml @@ -31,7 +31,9 @@ module S = struct responsible for the serialization of the dac payload (coordinator). " ~query:Tezos_rpc.Query.empty ~output:Dac_plugin.raw_hash_encoding - Tezos_rpc.Path.(open_root / "monitor" / "root_hashes") + Tezos_rpc.Path.( + open_root /: RPC_services.Api.version_rpc_arg / "monitor" + / "root_hashes") let certificate = Tezos_rpc.Service.get_service @@ -45,16 +47,22 @@ module S = struct ~query:Tezos_rpc.Query.empty ~output:Certificate_repr.encoding Tezos_rpc.Path.( - open_root / "monitor" / "certificate" /: Dac_plugin.raw_hash_rpc_arg) + open_root /: RPC_services.Api.version_rpc_arg / "monitor" + / "certificate" /: Dac_plugin.raw_hash_rpc_arg) end -let root_hashes dac_node_cctxt = - Tezos_rpc.Context.make_streamed_call S.root_hashes dac_node_cctxt () () () +let root_hashes dac_node_cctxt api_version = + Tezos_rpc.Context.make_streamed_call + S.root_hashes + dac_node_cctxt + ((), api_version) + () + () -let certificate dac_node_cctxt root_hash = +let certificate dac_node_cctxt root_hash api_version = Tezos_rpc.Context.make_streamed_call S.certificate dac_node_cctxt - ((), root_hash) + (((), api_version), root_hash) () () diff --git a/src/lib_dac/monitor_services.mli b/src/lib_dac/monitor_services.mli index a5d213d254aa..33a0195e13ad 100644 --- a/src/lib_dac/monitor_services.mli +++ b/src/lib_dac/monitor_services.mli @@ -24,21 +24,21 @@ (*****************************************************************************) module S : sig - (** Define RPC GET /monitor/root_hashes. *) + (** Define RPC "GET [api_version]/monitor/root_hashes". *) val root_hashes : ( [`GET], unit, - unit, + unit * RPC_services.Api.version, unit, unit, Dac_plugin.raw_hash ) Tezos_rpc.Service.service - (** Define RPC GET /monitor/certificate/hex_root_hash. *) + (** Define RPC GET [api_version]/monitor/certificate/hex_root_hash. *) val certificate : ( [`GET], unit, - unit * Dac_plugin.raw_hash, + (unit * RPC_services.Api.version) * Dac_plugin.raw_hash, unit, unit, Certificate_repr.t ) @@ -48,10 +48,11 @@ end (** [root_hashes streamed_cctxt dac_plugin] returns a stream of root hashes and a stopper for it. - Stream is produced by calling RPC GET /monitor/root_hashes. + Stream is produced by calling RPC "GET [api_version]/monitor/root_hashes". *) val root_hashes : #Tezos_rpc.Context.streamed -> + RPC_services.Api.version -> (Dac_plugin.raw_hash Lwt_stream.t * Tezos_rpc.Context.stopper) Error_monad.tzresult Lwt.t @@ -59,6 +60,7 @@ val root_hashes : val certificate : #Tezos_rpc.Context.streamed -> Dac_plugin.raw_hash -> + RPC_services.Api.version -> (Certificate_repr.t Lwt_stream.t * Tezos_rpc.Context.stopper) Error_monad.tzresult Lwt.t diff --git a/src/lib_dac_client/dac_node_client.ml b/src/lib_dac_client/dac_node_client.ml index f185896d61c5..c4e8be257fd1 100644 --- a/src/lib_dac_client/dac_node_client.ml +++ b/src/lib_dac_client/dac_node_client.ml @@ -51,33 +51,57 @@ let make_unix_cctxt ~scheme ~host ~port = was computed. *) let get_preimage (cctxt : #cctxt) ~page_hash = - cctxt#call_service RPC_services.get_preimage ((), page_hash) () () + cctxt#call_service + RPC_services.get_preimage + (((), RPC_services.Api.V0), page_hash) + () + () let post_store_preimage (cctxt : #cctxt) ~payload ~pagination_scheme = cctxt#call_service RPC_services.post_store_preimage - () + ((), RPC_services.Api.V0) () (payload, pagination_scheme) let get_verify_signature (cctxt : #cctxt) ~external_message = - cctxt#call_service RPC_services.get_verify_signature () external_message () + cctxt#call_service + RPC_services.get_verify_signature + ((), RPC_services.Api.V0) + external_message + () let put_dac_member_signature (cctxt : #cctxt) ~signature = - cctxt#call_service RPC_services.put_dac_member_signature () () signature + cctxt#call_service + RPC_services.put_dac_member_signature + ((), RPC_services.Api.V0) + () + signature let get_certificate (cctxt : #cctxt) ~root_page_hash = - cctxt#call_service RPC_services.get_certificate ((), root_page_hash) () () + cctxt#call_service + RPC_services.get_certificate + (((), RPC_services.Api.V0), root_page_hash) + () + () let monitor_certificate (cctxt : #cctxt) ~root_hash = - Monitor_services.certificate cctxt root_hash + Monitor_services.certificate cctxt root_hash RPC_services.Api.V0 module Coordinator = struct let post_preimage (cctxt : #cctxt) ~payload = - cctxt#call_service RPC_services.Coordinator.post_preimage () () payload + cctxt#call_service + RPC_services.Coordinator.post_preimage + ((), RPC_services.Api.V0) + () + payload end module Observer = struct let get_missing_page (cctxt : #cctxt) page_hash = - cctxt#call_service RPC_services.get_missing_page ((), page_hash) () () + cctxt#call_service + RPC_services.get_missing_page + (((), RPC_services.Api.V0), page_hash) + () + () end diff --git a/src/lib_dac_node/RPC_server.ml b/src/lib_dac_node/RPC_server.ml index d5ae9d733047..8d6d7a741172 100644 --- a/src/lib_dac_node/RPC_server.ml +++ b/src/lib_dac_node/RPC_server.ml @@ -165,9 +165,9 @@ let register_post_store_preimage ctx cctxt dac_sk_uris page_store hash_streamer directory = directory |> add_service - Tezos_rpc.Directory.register0 + Tezos_rpc.Directory.register1 RPC_services.post_store_preimage - (fun () input -> + (fun _api_version () input -> handle_post_store_preimage ctx cctxt @@ -179,35 +179,36 @@ let register_post_store_preimage ctx cctxt dac_sk_uris page_store hash_streamer let register_get_verify_signature dac_plugin public_keys_opt directory = directory |> add_service - Tezos_rpc.Directory.register0 + Tezos_rpc.Directory.register1 RPC_services.get_verify_signature - (fun external_message () -> + (fun _api_version external_message () -> handle_get_verify_signature dac_plugin public_keys_opt external_message) let register_get_preimage dac_plugin page_store = add_service - Tezos_rpc.Directory.register1 + Tezos_rpc.Directory.register2 RPC_services.get_preimage - (fun hash () () -> handle_get_preimage dac_plugin page_store hash) + (fun _api_version hash () () -> + handle_get_preimage dac_plugin page_store hash) let register_monitor_root_hashes hash_streamer dir = Tezos_rpc.Directory.gen_register dir Monitor_services.S.root_hashes - (fun () () () -> handle_monitor_root_hashes hash_streamer) + (fun _api_version () () -> handle_monitor_root_hashes hash_streamer) let register_get_certificate node_store dac_plugin = add_service - Tezos_rpc.Directory.register1 + Tezos_rpc.Directory.register2 RPC_services.get_certificate - (fun root_hash () () -> + (fun _api_version root_hash () () -> handle_get_certificate dac_plugin node_store root_hash) let register_get_missing_page dac_plugin page_store cctxt = add_service - Tezos_rpc.Directory.register1 + Tezos_rpc.Directory.register2 RPC_services.get_missing_page - (fun root_hash () () -> + (fun _api_version root_hash () () -> handle_get_missing_page cctxt page_store dac_plugin root_hash) module Coordinator = struct @@ -285,7 +286,7 @@ module Coordinator = struct Tezos_rpc.Directory.gen_register dir Monitor_services.S.certificate - (fun ((), root_hash) () () -> + (fun (((), _api_version), root_hash) () () -> let open Lwt_result_syntax in let*! handler = handle_monitor_certificate @@ -301,17 +302,17 @@ module Coordinator = struct let register_post_preimage dac_plugin hash_streamer page_store = add_service - Tezos_rpc.Directory.register0 + Tezos_rpc.Directory.register1 RPC_services.Coordinator.post_preimage - (fun () payload -> + (fun _api_version () payload -> handle_post_preimage dac_plugin page_store hash_streamer payload) let register_put_dac_member_signature ctx dac_plugin rw_node_store page_store cctxt = add_service - Tezos_rpc.Directory.register0 + Tezos_rpc.Directory.register1 RPC_services.put_dac_member_signature - (fun () dac_member_signature -> + (fun _api_version () dac_member_signature -> Signature_manager.Coordinator.handle_put_dac_member_signature ctx dac_plugin @@ -361,9 +362,9 @@ module Legacy = struct let register_put_dac_member_signature ctx dac_plugin rw_node_store page_store cctxt = add_service - Tezos_rpc.Directory.register0 + Tezos_rpc.Directory.register1 RPC_services.put_dac_member_signature - (fun () dac_member_signature -> + (fun _api_version () dac_member_signature -> Signature_manager.Legacy.handle_put_dac_member_signature ctx dac_plugin diff --git a/src/lib_dac_node/handler.ml b/src/lib_dac_node/handler.ml index 472fea25d6af..24a80c39d073 100644 --- a/src/lib_dac_node/handler.ml +++ b/src/lib_dac_node/handler.ml @@ -202,7 +202,7 @@ module Committee_member = struct let*! () = Event.(emit subscribed_to_root_hashes_stream ()) in make_stream_daemon (handler dac_plugin remote_store) - (Monitor_services.root_hashes coordinator_cctxt) + (Monitor_services.root_hashes coordinator_cctxt RPC_services.Api.V0) end (** Handlers specific to an [Observer]. An [Observer] is responsible for @@ -245,7 +245,7 @@ module Observer = struct let*! () = Event.(emit subscribed_to_root_hashes_stream ()) in make_stream_daemon (handler dac_plugin remote_store) - (Monitor_services.root_hashes coordinator_cctxt) + (Monitor_services.root_hashes coordinator_cctxt RPC_services.Api.V0) end (** Handlers specific to a [Legacy] DAC node. If no @@ -354,7 +354,7 @@ module Legacy = struct let*! () = Event.(emit subscribed_to_root_hashes_stream ()) in make_stream_daemon (handler dac_plugin remote_store) - (Monitor_services.root_hashes coordinator_cctxt) + (Monitor_services.root_hashes coordinator_cctxt RPC_services.Api.V0) end let handlers node_ctxt = diff --git a/tezt/lib_tezos/dac_rpc.ml b/tezt/lib_tezos/dac_rpc.ml index e9cc972abeae..0560dd089016 100644 --- a/tezt/lib_tezos/dac_rpc.ml +++ b/tezt/lib_tezos/dac_rpc.ml @@ -23,6 +23,10 @@ (* *) (*****************************************************************************) +module Api = struct + let v0 = "v0" +end + let make ?data ?query_string = RPC.make ?data @@ -40,9 +44,10 @@ let decode_hex_string_to_bytes s = Hex.to_string (`Hex s) let get_bytes_from_json_string_node json = JSON.as_string json |> decode_hex_string_to_bytes -let get_preimage page_hash = make GET ["preimage"; page_hash] JSON.as_string +let get_preimage page_hash ~api_version = + make GET [api_version; "preimage"; page_hash] JSON.as_string -let post_store_preimage ~payload ~pagination_scheme = +let post_store_preimage ~payload ~pagination_scheme ~api_version = let preimage = JSON.parse ~origin:"dal_node_dac_store_preimage_rpc" @@ -52,18 +57,19 @@ let post_store_preimage ~payload ~pagination_scheme = pagination_scheme) in let data : RPC_core.data = Data (JSON.unannotate preimage) in - make ~data POST ["store_preimage"] @@ fun json -> + make ~data POST [api_version; "store_preimage"] @@ fun json -> JSON. ( json |-> "root_hash" |> as_string, json |-> "external_message" |> get_bytes_from_json_string_node ) -let get_verify_signature external_msg = +let get_verify_signature external_msg ~api_version = let query_string = [("external_message", match Hex.of_string external_msg with `Hex s -> s)] in - make ~query_string GET ["verify_signature"] JSON.as_bool + make ~query_string GET [api_version; "verify_signature"] JSON.as_bool -let put_dac_member_signature ~hex_root_hash ~dac_member_pkh ~signature = +let put_dac_member_signature ~hex_root_hash ~dac_member_pkh ~signature + ~api_version = let (`Hex root_hash) = hex_root_hash in let payload = `O @@ -75,14 +81,14 @@ let put_dac_member_signature ~hex_root_hash ~dac_member_pkh ~signature = ] in let data : RPC_core.data = Data payload in - make ~data PUT ["dac_member_signature"] @@ fun _resp -> () + make ~data PUT [api_version; "dac_member_signature"] @@ fun _resp -> () -let get_missing_page ~hex_root_hash = - make GET ["missing_page"; Hex.show hex_root_hash] JSON.as_string +let get_missing_page ~hex_root_hash ~api_version = + make GET [api_version; "missing_page"; Hex.show hex_root_hash] JSON.as_string -let get_certificate ~hex_root_hash = +let get_certificate ~hex_root_hash ~api_version = let (`Hex page_hash) = hex_root_hash in - make GET ["certificates"; page_hash] @@ fun json -> + make GET [api_version; "certificates"; page_hash] @@ fun json -> JSON. ( json |-> "witnesses" |> as_int, json |-> "aggregate_signature" |> as_string, @@ -90,12 +96,12 @@ let get_certificate ~hex_root_hash = json |-> "version" |> as_int ) module Coordinator = struct - let post_preimage ~payload = + let post_preimage ~payload ~api_version = let preimage = JSON.parse ~origin:"Rollup.DAC.RPC.coordinator_post_preimage" (encode_bytes_to_hex_string payload) in let data : RPC_core.data = Data (JSON.unannotate preimage) in - make ~data POST ["preimage"] JSON.as_string + make ~data POST [api_version; "preimage"] JSON.as_string end diff --git a/tezt/lib_tezos/dac_rpc.mli b/tezt/lib_tezos/dac_rpc.mli index 76f1760f16fd..fa5b2b92e506 100644 --- a/tezt/lib_tezos/dac_rpc.mli +++ b/tezt/lib_tezos/dac_rpc.mli @@ -23,50 +23,68 @@ (* *) (*****************************************************************************) -(** [get_preimage hash] requests the preimage of hash, consisting of a +(** [Api] module is used for versioning DAC API. *) +module Api : sig + (** [v0] is experimental DAC API, which will be deprecated soon. However, for + the time being the API is binding. It will be used by 1M/tps demo. + The plan is to remove it once we get rid of the [Legacy] mode. + Do not use it! *) + val v0 : string +end + +(** [get_preimage hash ~api_version] 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_preimage : string -> (Dac_node.t, string) RPC_core.t +val get_preimage : + string -> api_version:string -> (Dac_node.t, string) RPC_core.t -(** [post_store_preimage cctxt ~payload ~pagination_scheme] posts a [payload] to dac/store_preimage - using a given [pagination_scheme]. It returns the hex encoded root page hash - and the raw bytes that can be used as contents of a rollup message to trigger the request of - the payload in a WASM rollup. *) +(** [post_store_preimage cctxt ~payload ~pagination_scheme ~api_version] posts a + [payload] to [api_version]/store_preimage using a given [pagination_scheme]. + It returns the hex encoded root page hash and the raw bytes that can be used + as contents of a rollup message to trigger the request of the payload in a + WASM rollup. *) val post_store_preimage : payload:string -> pagination_scheme:string -> + api_version:string -> (Dac_node.t, string * string) RPC_core.t -(** [get_verify_signature cctxt external_message] requests the DAL node to verify - the signature of the external message [external_message] via +(** [get_verify_signature cctxt external_message ~api_version] requests the DAL + node to verify the signature of the external message [external_message] via the plugin/dac/verify_signature endpoint. The DAC committee of the DAL node must be the same that was used to produce the [external_message]. *) -val get_verify_signature : string -> (Dac_node.t, bool) RPC_core.t +val get_verify_signature : + string -> api_version:string -> (Dac_node.t, bool) RPC_core.t -(** [put_dac_member_signature hex_root_hash dac_member_pkh signature] +(** [put_dac_member_signature hex_root_hash dac_member_pkh signature ~api_version] stores the [signature] generated from signing [hex_root_hash] by [dac_member_pkh]. *) val put_dac_member_signature : hex_root_hash:Hex.t -> dac_member_pkh:string -> signature:Tezos_crypto.Aggregate_signature.t -> + api_version:string -> (Dac_node.t, unit) RPC_core.t -(** [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 +(** [get_missing_page ~hex_root_hash ~api_version] calls GET + [api_version]/missing_page/[page_hash] endpoint. *) +val get_missing_page : + hex_root_hash:Hex.t -> api_version:string -> (Dac_node.t, string) RPC_core.t -(** [get_certificate ~hex_root_hash] fetches the DAC certificate for the - provided [hex_root_hash]. *) +(** [get_certificate ~hex_root_hash ~api_version] fetches the DAC certificate + for the provided [hex_root_hash]. *) val get_certificate : - hex_root_hash:Hex.t -> (Dac_node.t, int * string * string * int) RPC_core.t + hex_root_hash:Hex.t -> + api_version:string -> + (Dac_node.t, int * string * string * int) RPC_core.t module Coordinator : sig - (** [post_preimage ~payload] sends a [payload] to the DAC + (** [post_preimage ~payload ~api_version] sends a [payload] to the DAC [Coordinator] via a POST RPC call to dac/preimage. It returns a hex encoded root page hash, produced by [Merkle_tree_V0] pagination scheme. On the backend side it also pushes root page hash of the preimage to all the subscribed DAC Members and Observers. *) - val post_preimage : payload:string -> (Dac_node.t, string) RPC_core.t + val post_preimage : + payload:string -> api_version:string -> (Dac_node.t, string) RPC_core.t end diff --git a/tezt/tests/dac.ml b/tezt/tests/dac.ml index 03596489dff3..20a69ccd46bb 100644 --- a/tezt/tests/dac.ml +++ b/tezt/tests/dac.ml @@ -44,12 +44,15 @@ let assert_lwt_failure ?__LOC__ msg lwt_under_inspection = in if passed then unit else Test.fail ?__LOC__ msg -let init_hex_root_hash ?payload coordinator_node = +let init_hex_root_hash ?payload coordinator_node ~api_version = let payload = Option.value payload ~default:"hello test message" in let* root_hash, _l1_op = RPC.call coordinator_node - (Dac_rpc.post_store_preimage ~payload ~pagination_scheme:"Merkle_tree_V0") + (Dac_rpc.post_store_preimage + ~payload + ~pagination_scheme:"Merkle_tree_V0" + ~api_version) in let hex_root_hash = `Hex root_hash in return hex_root_hash @@ -94,12 +97,13 @@ let parse_certificate json = (* Helper process that listens to certificate updates through a RPC request. Upon termination, the list of certificate updates is returned *) -let streamed_certificates_client coordinator_node root_hash = +let streamed_certificates_client coordinator_node root_hash api_version = let endpoint = Format.sprintf - "http://%s:%d/monitor/certificate/%s" + "http://%s:%d/%s/monitor/certificate/%s" (Dac_node.rpc_host coordinator_node) (Dac_node.rpc_port coordinator_node) + api_version root_hash in RPC.Curl.get_raw endpoint @@ -197,14 +201,14 @@ let check_preimage expected_preimage actual_preimage = [coordinator]. It returns the list of the hashes contained in the [page_hash], if the page corresponds to a hash page. Otherwise, it returns the empty list. *) -let check_downloaded_page coordinator observer page_hash = +let check_downloaded_page coordinator observer page_hash ~api_version = let* coordinator_hex_encoded_page = - RPC.call coordinator (Dac_rpc.get_preimage page_hash) + RPC.call coordinator Dac_rpc.(get_preimage page_hash ~api_version) in let coordinator_page = Hex.to_string (`Hex coordinator_hex_encoded_page) in (* Check that the page has been saved by the observer. *) let* observer_hex_encoded_page = - RPC.call observer (Dac_rpc.get_preimage page_hash) + RPC.call observer (Dac_rpc.get_preimage page_hash ~api_version) in let observer_page = Hex.to_string (`Hex observer_hex_encoded_page) in (* Check that the raw page for the root hash stored in the coordinator @@ -240,12 +244,14 @@ let check_downloaded_page coordinator observer page_hash = in return @@ split_hashes concatenated_hashes [] -let check_downloaded_preimage coordinator observer root_hash = +let check_downloaded_preimage coordinator observer root_hash ~api_version = let rec go hashes = match hashes with | [] -> return () | hash :: hashes -> - let* next_hashes = check_downloaded_page coordinator observer hash in + let* next_hashes = + check_downloaded_page coordinator observer hash ~api_version + in go (hashes @ next_hashes) in go [root_hash] @@ -293,6 +299,9 @@ let sample_payload example_filename = no notion of profiles. Once we have a fully working profiles, tests from this module should be refactored. *) module Legacy = struct + (** [Legacy] test suite uses [v0] DAC API. *) + let api_version = Dac_rpc.Api.v0 + let set_coordinator dac_node coordinator = let coordinator = `O @@ -316,7 +325,8 @@ module Legacy = struct coordinator (Dac_rpc.post_store_preimage ~payload - ~pagination_scheme:"Merkle_tree_V0") + ~pagination_scheme:"Merkle_tree_V0" + ~api_version) in return @@ check_valid_root_hash expected_rh actual_rh @@ -436,7 +446,8 @@ module Legacy = struct dac_node (Dac_rpc.post_store_preimage ~payload - ~pagination_scheme:"Merkle_tree_V0") + ~pagination_scheme:"Merkle_tree_V0" + ~api_version) in (* Expected reveal hash equals to the result of [Tezos_dac_alpha.Dac_pages_encoding.Merkle_tree.V0.serialize_payload "test"]. @@ -459,7 +470,7 @@ module Legacy = struct in check_preimage payload recovered_preimage ; let* is_signature_valid = - RPC.call dac_node (Dac_rpc.get_verify_signature l1_operation) + RPC.call dac_node (Dac_rpc.get_verify_signature l1_operation ~api_version) in Check.( (is_signature_valid = true) @@ -476,7 +487,8 @@ module Legacy = struct dac_node (Dac_rpc.post_store_preimage ~payload - ~pagination_scheme:"Hash_chain_V0") + ~pagination_scheme:"Hash_chain_V0" + ~api_version) in (* Expected reveal hash equals to the result of [Tezos_dac_alpha.Dac_pages_encoding.Hash_chain.V0.serialize_payload "test"]. @@ -508,7 +520,8 @@ module Legacy = struct dac_node (Dac_rpc.post_store_preimage ~payload - ~pagination_scheme:"Merkle_tree_V0") + ~pagination_scheme:"Merkle_tree_V0" + ~api_version) in (* Expected reveal hash equals to the result of [Tezos_dac_alpha.Dac_pages_encoding.Merkle_tree.V0.serialize_payload "test"]. @@ -526,7 +539,9 @@ module Legacy = struct let recovered_payload = really_input_string cin (in_channel_length cin) in let () = close_in cin in let recovered_preimage = Hex.of_string recovered_payload in - let* preimage = RPC.call dac_node (Dac_rpc.get_preimage expected_rh) in + let* preimage = + RPC.call dac_node (Dac_rpc.get_preimage expected_rh ~api_version) + in Check.( (preimage = Hex.show recovered_preimage) string @@ -566,7 +581,8 @@ module Legacy = struct dac_node (Dac_rpc.post_store_preimage ~payload - ~pagination_scheme:"Hash_chain_V0") + ~pagination_scheme:"Hash_chain_V0" + ~api_version) in let expected_rh = "0027782d2a7020be332cc42c4e66592ec50305f559a4011981f1d5af81428e7aa3" @@ -608,7 +624,8 @@ module Legacy = struct dac_node (Dac_rpc.post_store_preimage ~payload - ~pagination_scheme:"Hash_chain_V0") + ~pagination_scheme:"Hash_chain_V0" + ~api_version) in let errorneous_hash = "0027782d2a7020be332cc42c4e66592ec50305f559a4011981f1d5af81428ecafe" @@ -866,7 +883,7 @@ module Legacy = struct let* () = push_promise in (* Assert [observer] emitted event of received [expected_rh]. *) let* () = fetch_root_hash_promise in - check_downloaded_preimage coordinator observer expected_rh + check_downloaded_preimage coordinator observer expected_rh ~api_version (* 1. Observer should fetch missing page from Coordinator when GET /missing_page/{hash} is called. @@ -882,7 +899,10 @@ module Legacy = struct 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 + init_hex_root_hash + ~payload:"test payload abc 123" + coordinator + ~api_version in assert (root_hash = Hex.show hex_root_hash) ; let* () = root_hash_stream_promise in @@ -896,17 +916,23 @@ module Legacy = struct assert_lwt_failure ~__LOC__ "Expected retrieve_preimage" - (RPC.call observer (Dac_rpc.get_preimage (Hex.show hex_root_hash))) + (RPC.call + observer + (Dac_rpc.get_preimage (Hex.show hex_root_hash) ~api_version)) in let* missing_page = - RPC.call observer (Dac_rpc.get_missing_page ~hex_root_hash) + RPC.call observer (Dac_rpc.get_missing_page ~hex_root_hash ~api_version) in let* coordinator_page = - RPC.call coordinator (Dac_rpc.get_preimage (Hex.show hex_root_hash)) + RPC.call + coordinator + (Dac_rpc.get_preimage (Hex.show hex_root_hash) ~api_version) in check_preimage coordinator_page missing_page ; let* observer_preimage = - RPC.call observer (Dac_rpc.get_preimage (Hex.show hex_root_hash)) + RPC.call + observer + (Dac_rpc.get_preimage (Hex.show hex_root_hash) ~api_version) in check_preimage coordinator_page observer_preimage ; unit @@ -924,7 +950,8 @@ module Legacy = struct (Dac_rpc.put_dac_member_signature ~hex_root_hash ~dac_member_pkh:invalid_signer_key.aggregate_public_key_hash - ~signature) + ~signature + ~api_version) in assert_lwt_failure ~__LOC__ @@ -949,7 +976,8 @@ module Legacy = struct (Dac_rpc.put_dac_member_signature ~hex_root_hash ~dac_member_pkh:memberj.aggregate_public_key_hash - ~signature) + ~signature + ~api_version) in assert_lwt_failure ~__LOC__ @@ -980,14 +1008,17 @@ module Legacy = struct (Dac_rpc.put_dac_member_signature ~hex_root_hash ~dac_member_pkh:member.aggregate_public_key_hash - ~signature) + ~signature + ~api_version) in return (member :: keys)) (return []) members in let* witnesses, certificate, _root_hash, _version = - RPC.call coordinator_node (Dac_rpc.get_certificate ~hex_root_hash) + RPC.call + coordinator_node + (Dac_rpc.get_certificate ~hex_root_hash ~api_version) in assert_witnesses ~__LOC__ 3 witnesses ; assert_verify_aggregate_signature members_keys hex_root_hash certificate ; @@ -996,7 +1027,10 @@ module Legacy = struct let test_store_same_signature_more_than_once_should_be_noop (coordinator_node, _hex_root_hash, dac_committee) = let* hex_root_hash = - init_hex_root_hash ~payload:"noop test abc 3210" coordinator_node + init_hex_root_hash + ~payload:"noop test abc 3210" + coordinator_node + ~api_version in let member_i = 2 in let member = List.nth dac_committee member_i in @@ -1008,12 +1042,15 @@ module Legacy = struct (Dac_rpc.put_dac_member_signature ~hex_root_hash ~dac_member_pkh - ~signature) + ~signature + ~api_version) in let* () = call () in let* () = call () in let* witnesses, certificate, _root_hash, _version = - RPC.call coordinator_node (Dac_rpc.get_certificate ~hex_root_hash) + RPC.call + coordinator_node + (Dac_rpc.get_certificate ~hex_root_hash ~api_version) in assert_witnesses ~__LOC__ 4 witnesses ; assert_verify_aggregate_signature [member] hex_root_hash certificate ; @@ -1035,7 +1072,8 @@ module Legacy = struct (Dac_rpc.put_dac_member_signature ~hex_root_hash:false_root_hash ~dac_member_pkh - ~signature) + ~signature + ~api_version) in assert_lwt_failure ~__LOC__ @@ -1044,7 +1082,7 @@ module Legacy = struct let test_handle_store_signature _protocol _tezos_node tz_client coordinator _threshold dac_committee = - let* hex_root_hash = init_hex_root_hash coordinator in + let* hex_root_hash = init_hex_root_hash coordinator ~api_version in let dac_env = (coordinator, hex_root_hash, dac_committee) in let* () = test_non_committee_signer_should_fail tz_client dac_env in let* () = test_signature_verification_failure_should_fail dac_env in @@ -1067,6 +1105,7 @@ module Legacy = struct let* hex_root_hash = init_hex_root_hash ~payload:"test get certificate payload 123" + ~api_version coordinator in let signature = bls_sign_hex_hash member hex_root_hash in @@ -1076,10 +1115,13 @@ module Legacy = struct (Dac_rpc.put_dac_member_signature ~hex_root_hash ~dac_member_pkh:member.aggregate_public_key_hash - ~signature) + ~signature + ~api_version) in let* witnesses, certificate, _root_hash, _version = - RPC.call coordinator (Dac_rpc.get_certificate ~hex_root_hash) + RPC.call + coordinator + (Dac_rpc.get_certificate ~hex_root_hash ~api_version) in let expected_witnesses = Z.shift_left Z.one i in assert_witnesses ~__LOC__ (Z.to_int expected_witnesses) witnesses ; @@ -1088,10 +1130,19 @@ module Legacy = struct end end +(** [Full_infrastructure] is a test suite consisting only of tests with the DAC + nodes running in non-[Legacy] modes. *) module Full_infrastructure = struct + (* TODO: https://gitlab.com/tezos/tezos/-/issues/5577 + Once we introduce DAC API ("v1"), [Full_infrastructure] test suite should + be refactored to use [v1] api as well. *) + let api_version = Dac_rpc.Api.v0 + let coordinator_serializes_payload coordinator ~payload ~expected_rh = let* actual_rh = - RPC.call coordinator (Dac_rpc.Coordinator.post_preimage ~payload) + RPC.call + coordinator + (Dac_rpc.Coordinator.post_preimage ~payload ~api_version) in return @@ check_valid_root_hash expected_rh actual_rh @@ -1108,7 +1159,9 @@ module Full_infrastructure = struct wait_for_root_hash_pushed_to_data_streamer coordinator_node expected_rh in let* actual_rh = - RPC.call coordinator_node (Dac_rpc.Coordinator.post_preimage ~payload) + RPC.call + coordinator_node + (Dac_rpc.Coordinator.post_preimage ~payload ~api_version) in let () = check_valid_root_hash expected_rh actual_rh in let* () = root_hash_pushed_to_data_streamer_promise in @@ -1191,7 +1244,11 @@ module Full_infrastructure = struct This might be inefficient *) Lwt_list.iter_s (fun dac_node -> - check_downloaded_preimage coordinator_node dac_node expected_rh) + check_downloaded_preimage + coordinator_node + dac_node + expected_rh + ~api_version) (committee_members_nodes @ observer_nodes) let test_streaming_certificates @@ -1220,7 +1277,8 @@ module Full_infrastructure = struct assert (List.length committee_members > 0) ; let payload, expected_rh = sample_payload "preimage" in let certificate_stream_client = - Runnable.run @@ streamed_certificates_client coordinator_node expected_rh + Runnable.run + @@ streamed_certificates_client coordinator_node expected_rh api_version in let push_promise = wait_for_root_hash_pushed_to_data_streamer coordinator_node expected_rh @@ -1286,18 +1344,19 @@ module Full_infrastructure = struct List.nth certificate_updates (List.length certificate_updates - 1) in (* 5. Check that certificate is consistent with the one returned - from the GET /certificate endpoint. *) + from the GET [api_version]/certificate endpoint. *) let* get_certificate = RPC.call coordinator_node - (Dac_rpc.get_certificate ~hex_root_hash:(`Hex expected_rh)) + (Dac_rpc.get_certificate ~hex_root_hash:(`Hex expected_rh) ~api_version) in check_certificate get_certificate last_certificate_update ; (* 6. Request certificate via streamed endpoints again, check that one item is returned with the same certificate returned by the GET endpoint. *) let* second_certificates_stream = - Runnable.run @@ streamed_certificates_client coordinator_node expected_rh + Runnable.run + @@ streamed_certificates_client coordinator_node expected_rh api_version in Check.( (1 = List.length second_certificates_stream) @@ -1501,6 +1560,11 @@ module Tx_kernel_e2e = struct open Sc_rollup_helpers module Bls = Tezos_crypto.Signature.Bls + (* TODO: https://gitlab.com/tezos/tezos/-/issues/5577 + Once we introduce DAC API ("v1"), [Tx_kernel_e2e] test suite should + be refactored to use [v1] api as well. *) + let api_version = Dac_rpc.Api.v0 + let send_message ?(src = Constant.bootstrap2.alias) client msg = let* () = Client.Sc_rollup.send_message ~hooks ~src ~msg client in Client.bake_for_and_wait client @@ -2014,13 +2078,17 @@ module Tx_kernel_e2e = struct else unit in let* preimage_hash = - RPC.call coordinator_node (Dac_rpc.Coordinator.post_preimage ~payload) + RPC.call + coordinator_node + (Dac_rpc.Coordinator.post_preimage ~payload ~api_version) in let* () = Lwt.join wait_for_member_signature_pushed_to_coordinator in let* witnesses, signature, root_hash, _version = RPC.call coordinator_node - (Dac_rpc.get_certificate ~hex_root_hash:(`Hex preimage_hash)) + (Dac_rpc.get_certificate + ~hex_root_hash:(`Hex preimage_hash) + ~api_version) in let root_hash = `Hex root_hash |> Hex.to_string |> String.to_bytes in let signature = -- GitLab From cec7c44b3c4c86f9f263c0e8f7d39f47c55382b1 Mon Sep 17 00:00:00 2001 From: Martin Tomazic Date: Tue, 9 May 2023 16:53:16 +0200 Subject: [PATCH 4/5] DAC: Introduce `V0` module inside `Dac_node_client` --- src/bin_dac_client/command_handlers.ml | 18 ++- src/lib_dac/monitor_services.mli | 9 +- src/lib_dac_client/dac_node_client.ml | 102 ++++++++--------- src/lib_dac_client/dac_node_client.mli | 106 +++++++++--------- src/lib_dac_node/handler.ml | 14 ++- src/lib_dac_node/page_store.ml | 2 +- .../lib_dac_plugin/dac_observer_client.ml | 6 +- 7 files changed, 146 insertions(+), 111 deletions(-) diff --git a/src/bin_dac_client/command_handlers.ml b/src/bin_dac_client/command_handlers.ml index 08d16144b6b9..09a4f3eeb11f 100644 --- a/src/bin_dac_client/command_handlers.ml +++ b/src/bin_dac_client/command_handlers.ml @@ -68,7 +68,11 @@ let serialize_certificate certificate = rename PUT v1/preimage into v1/payload, and change name of function accordingly. *) let send_preimage cctxt payload = - Dac_node_client.Coordinator.post_preimage cctxt ~payload + (* TODO: https://gitlab.com/tezos/tezos/-/issues/5627 + Currently we have only one major DAC API version ([V0]). For this reason, + client binary can always default to it. This should be revisited once we + add another major version. *) + Dac_node_client.V0.Coordinator.post_preimage cctxt ~payload let number_of_witnesses certificate = let witnesses = Certificate_repr.get_witnesses certificate in @@ -86,7 +90,11 @@ let number_of_witnesses certificate = let wait_for_certificate cctxt root_hash threshold = let open Lwt_result_syntax in let* stream, _stopper = - Dac_node_client.monitor_certificate cctxt ~root_hash + (* TODO: https://gitlab.com/tezos/tezos/-/issues/5627 + Currently we have only one major DAC API version ([V0]). For this reason, + client binary can always default to it. This should be revisited once we + add another major version. *) + Dac_node_client.V0.monitor_certificate cctxt ~root_hash in let rec go best_certificate_opt best_witnesses = let*! certificate_opt = Lwt_stream.get stream in @@ -105,6 +113,10 @@ let wait_for_certificate cctxt root_hash threshold = let get_certificate cctxt root_page_hash = let open Lwt_result_syntax in let* certificate_opt = - Dac_node_client.get_certificate cctxt ~root_page_hash + (* TODO: https://gitlab.com/tezos/tezos/-/issues/5627 + Currently we have only one major DAC API version ([V0]). For this reason, + client binary can always default to it. This should be revisited once we + add another major version. *) + Dac_node_client.V0.get_certificate cctxt ~root_page_hash in Option.map_es serialize_certificate certificate_opt diff --git a/src/lib_dac/monitor_services.mli b/src/lib_dac/monitor_services.mli index 33a0195e13ad..c491ee7e8f92 100644 --- a/src/lib_dac/monitor_services.mli +++ b/src/lib_dac/monitor_services.mli @@ -45,8 +45,8 @@ module S : sig Tezos_rpc.Service.service end -(** [root_hashes streamed_cctxt dac_plugin] returns a stream of root hashes - and a stopper for it. +(** [root_hashes streamed_cctxt raw_hash api_version] returns a stream + of root hashes and a stopper for it. Stream is produced by calling RPC "GET [api_version]/monitor/root_hashes". *) @@ -57,6 +57,11 @@ val root_hashes : Error_monad.tzresult Lwt.t +(** [certificate streamed_cctxt raw_hash api_version] returns a stream and a + stopper for monitoring certificate updates for a given root hash. + + Stream is produced by calling RPC "GET [api_version]/monitor/certificate". +*) val certificate : #Tezos_rpc.Context.streamed -> Dac_plugin.raw_hash -> diff --git a/src/lib_dac_client/dac_node_client.ml b/src/lib_dac_client/dac_node_client.ml index c4e8be257fd1..3c191403fe4f 100644 --- a/src/lib_dac_client/dac_node_client.ml +++ b/src/lib_dac_client/dac_node_client.ml @@ -44,64 +44,66 @@ let make_unix_cctxt ~scheme ~host ~port = in new unix_cctxt ~rpc_config -(* FIXME: https://gitlab.com/tezos/tezos/-/issues/4895 - If the preimage was generated using a different plugin, the computation of - the hash might fail. In practice it would be better to retrieve the - hash of the protocol that the coordinator was using when the page hash - was computed. -*) -let get_preimage (cctxt : #cctxt) ~page_hash = - cctxt#call_service - RPC_services.get_preimage - (((), RPC_services.Api.V0), page_hash) - () - () - -let post_store_preimage (cctxt : #cctxt) ~payload ~pagination_scheme = - cctxt#call_service - RPC_services.post_store_preimage - ((), RPC_services.Api.V0) - () - (payload, pagination_scheme) - -let get_verify_signature (cctxt : #cctxt) ~external_message = - cctxt#call_service - RPC_services.get_verify_signature - ((), RPC_services.Api.V0) - external_message - () - -let put_dac_member_signature (cctxt : #cctxt) ~signature = - cctxt#call_service - RPC_services.put_dac_member_signature - ((), RPC_services.Api.V0) - () - signature +module V0 = struct + (* FIXME: https://gitlab.com/tezos/tezos/-/issues/4895 + If the preimage was generated using a different plugin, the computation of + the hash might fail. In practice it would be better to retrieve the + hash of the protocol that the coordinator was using when the page hash + was computed. + *) + let get_preimage (cctxt : #cctxt) ~page_hash = + cctxt#call_service + RPC_services.get_preimage + (((), RPC_services.Api.V0), page_hash) + () + () -let get_certificate (cctxt : #cctxt) ~root_page_hash = - cctxt#call_service - RPC_services.get_certificate - (((), RPC_services.Api.V0), root_page_hash) - () - () + let post_store_preimage (cctxt : #cctxt) ~payload ~pagination_scheme = + cctxt#call_service + RPC_services.post_store_preimage + ((), RPC_services.Api.V0) + () + (payload, pagination_scheme) -let monitor_certificate (cctxt : #cctxt) ~root_hash = - Monitor_services.certificate cctxt root_hash RPC_services.Api.V0 + let get_verify_signature (cctxt : #cctxt) ~external_message = + cctxt#call_service + RPC_services.get_verify_signature + ((), RPC_services.Api.V0) + external_message + () -module Coordinator = struct - let post_preimage (cctxt : #cctxt) ~payload = + let put_dac_member_signature (cctxt : #cctxt) ~signature = cctxt#call_service - RPC_services.Coordinator.post_preimage + RPC_services.put_dac_member_signature ((), RPC_services.Api.V0) () - payload -end + signature -module Observer = struct - let get_missing_page (cctxt : #cctxt) page_hash = + let get_certificate (cctxt : #cctxt) ~root_page_hash = cctxt#call_service - RPC_services.get_missing_page - (((), RPC_services.Api.V0), page_hash) + RPC_services.get_certificate + (((), RPC_services.Api.V0), root_page_hash) () () + + let monitor_certificate (cctxt : #cctxt) ~root_hash = + Monitor_services.certificate cctxt root_hash RPC_services.Api.V0 + + module Coordinator = struct + let post_preimage (cctxt : #cctxt) ~payload = + cctxt#call_service + RPC_services.Coordinator.post_preimage + ((), RPC_services.Api.V0) + () + payload + end + + module Observer = struct + let get_missing_page (cctxt : #cctxt) page_hash = + cctxt#call_service + RPC_services.get_missing_page + (((), RPC_services.Api.V0), page_hash) + () + () + end end diff --git a/src/lib_dac_client/dac_node_client.mli b/src/lib_dac_client/dac_node_client.mli index a86c83026aba..9cf7a90c58f9 100644 --- a/src/lib_dac_client/dac_node_client.mli +++ b/src/lib_dac_client/dac_node_client.mli @@ -39,62 +39,66 @@ class unix_cctxt : the client configuration parameters. *) val make_unix_cctxt : scheme:string -> host:string -> port:int -> cctxt -(** [get_preimage cctxt ~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. *) -val get_preimage : - #cctxt -> page_hash:Dac_plugin.raw_hash -> bytes tzresult Lwt.t +(** [V0] is a module that provides a client specification for interacting with + experimental [Tezos_lib_dac.Rpc_services.Api.V0] API. Note that even though + [V0] api is binding, it is already deprecated. Use it at your own risk! *) +module V0 : sig + (** [get_preimage cctxt ~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. *) + val get_preimage : + #cctxt -> page_hash:Dac_plugin.raw_hash -> bytes tzresult Lwt.t -(** [post_store_preimage cctxt ~payload ~pagination_scheme] posts a [payload] to dac/store_preimage - using a given [pagination_scheme]. It returns the hex encoded root page hash - and the raw bytes. *) -val post_store_preimage : - #cctxt -> - payload:bytes -> - pagination_scheme:Pagination_scheme.t -> - (Dac_plugin.raw_hash * bytes) tzresult Lwt.t + (** [post_store_preimage cctxt ~payload ~pagination_scheme] posts a [payload] + to v0/store_preimage using a given [pagination_scheme]. It returns the hex + encoded root page hash and the raw bytes. *) + val post_store_preimage : + #cctxt -> + payload:bytes -> + pagination_scheme:Pagination_scheme.t -> + (Dac_plugin.raw_hash * bytes) tzresult Lwt.t -(** [get_verify_signature cctxt ~external_message] requests the DAL node to verify - the signature of the external message [external_message] via - the plugin/dac/verify_signature endpoint. The DAC committee - of the DAL node must be the same that was used to produce the - [external_message]. *) -val get_verify_signature : - #cctxt -> external_message:string option -> bool tzresult Lwt.t + (** [get_verify_signature cctxt ~external_message] requests the DAC node to + verify the signature of the external message [external_message] via + the v0/verify_signature endpoint. The DAC committee of the DAC node must + be the same that was used to produce the [external_message]. *) + val get_verify_signature : + #cctxt -> external_message:string option -> bool tzresult Lwt.t -(** [put_dac_member_signature cctxt ~signature:Signature_repr.t] - stores the [signature] generated from signing [hex_root_hash] by - [dac_member_pkh]. *) -val put_dac_member_signature : - #cctxt -> signature:Signature_repr.t -> unit tzresult Lwt.t + (** [put_dac_member_signature cctxt ~signature:Signature_repr.t] + stores the [signature] generated from signing [hex_root_hash] by + [dac_member_pkh]. *) + val put_dac_member_signature : + #cctxt -> signature:Signature_repr.t -> unit tzresult Lwt.t -(** [get_certificate cctxt ~root_page_hash] fetches the DAC certificate for the - provided [root_page_hash]. *) -val get_certificate : - #cctxt -> - root_page_hash:Dac_plugin.raw_hash -> - Certificate_repr.t option tzresult Lwt.t + (** [get_certificate cctxt ~root_page_hash] fetches the DAC certificate for + the provided [root_page_hash]. *) + val get_certificate : + #cctxt -> + root_page_hash:Dac_plugin.raw_hash -> + Certificate_repr.t option tzresult Lwt.t -(** [monitor_certificate cctxt ~root_hash] returns a stream and a - stopper for monitoring certificate updates for [root_hash]. *) -val monitor_certificate : - #cctxt -> - root_hash:Dac_plugin.raw_hash -> - (Certificate_repr.t Lwt_stream.t * Tezos_rpc.Context.stopper) tzresult Lwt.t + (** [monitor_certificate cctxt ~root_hash] returns a stream and a + stopper for monitoring certificate updates for [root_hash]. *) + val monitor_certificate : + #cctxt -> + root_hash:Dac_plugin.raw_hash -> + (Certificate_repr.t Lwt_stream.t * Tezos_rpc.Context.stopper) tzresult Lwt.t -module Coordinator : sig - (** [post_preimage cctxt ~payload] sends a [payload] to the DAC - [Coordinator] via a POST RPC call to dac/preimage. It returns a hex - encoded root page hash, produced by [Merkle_tree_V0] pagination scheme. - On the backend side it also pushes root page hash of the preimage to all - the subscribed DAC Members and Observers. *) - val post_preimage : - #cctxt -> payload:bytes -> Dac_plugin.raw_hash tzresult Lwt.t -end + module Coordinator : sig + (** [post_preimage cctxt ~payload] sends a [payload] to the DAC + [Coordinator] via a POST RPC call to v0/preimage. It returns a hex + encoded root page hash, produced by [Merkle_tree_V0] pagination scheme. + On the backend side it also pushes root page hash of the preimage to all + the subscribed DAC Members and Observers. *) + val post_preimage : + #cctxt -> payload:bytes -> Dac_plugin.raw_hash tzresult Lwt.t + end -module Observer : sig - (** [get_missing_page plugin cctxt page_hash] notifies an [Observer] that a - page hash must be downloaded. This function returns the preimage of the - requested [page_hash]. *) - val get_missing_page : #cctxt -> Dac_plugin.raw_hash -> bytes tzresult Lwt.t + module Observer : sig + (** [get_missing_page plugin cctxt page_hash] notifies an [Observer] that a + page hash must be downloaded. This function returns the preimage of the + requested [page_hash]. *) + val get_missing_page : #cctxt -> Dac_plugin.raw_hash -> bytes tzresult Lwt.t + end end diff --git a/src/lib_dac_node/handler.ml b/src/lib_dac_node/handler.ml index 24a80c39d073..63042cea6e97 100644 --- a/src/lib_dac_node/handler.ml +++ b/src/lib_dac_node/handler.ml @@ -154,7 +154,11 @@ module Committee_member = struct {root_hash = Dac_plugin.hash_to_raw root_hash; signature; signer_pkh} in let* () = - Dac_node_client.put_dac_member_signature + (* TODO: https://gitlab.com/tezos/tezos/-/issues/5627 + Currently we have only one major DAC API version ([V0]). For this + reason, we can always default to it. This should be revisited once we + add another major version. *) + Dac_node_client.V0.put_dac_member_signature coordinator_cctxt ~signature:signature_repr in @@ -295,7 +299,11 @@ module Legacy = struct } in let* () = - Dac_node_client.put_dac_member_signature + (* TODO: https://gitlab.com/tezos/tezos/-/issues/5627 + Currently we have only one major DAC API version ([V0]). For this + reason, we can always default to it. This should be revisited once + we add another major version. *) + Dac_node_client.V0.put_dac_member_signature coordinator_cctxt ~signature:signature_repr in @@ -307,7 +315,7 @@ module Legacy = struct (** This handler will be invoked only when a [coordinator_cctxt] is specified in the DAC node configuration. The DAC node tries to subscribes to the - stream of root hashes via the streamed GET /monitor/root_hashes RPC call + stream of root hashes via the streamed GET v0/monitor/root_hashes RPC call to the dac node corresponding to [coordinator_cctxt]. *) let new_root_hash ctxt coordinator_cctxt wallet_cctxt dac_plugin page_store = let committee_member_opt = ctxt.Node_context.Legacy.committee_member_opt in diff --git a/src/lib_dac_node/page_store.ml b/src/lib_dac_node/page_store.ml index a7045287d276..679b450a72d5 100644 --- a/src/lib_dac_node/page_store.ml +++ b/src/lib_dac_node/page_store.ml @@ -274,7 +274,7 @@ module Remote : S with type configuration = remote_configuration = struct type remote_context = Dac_node_client.cctxt let fetch _dac_plugin remote_context hash = - Dac_node_client.get_preimage + Dac_node_client.V0.get_preimage remote_context ~page_hash:(Dac_plugin.hash_to_raw hash) end) diff --git a/src/proto_alpha/lib_dac_plugin/dac_observer_client.ml b/src/proto_alpha/lib_dac_plugin/dac_observer_client.ml index 92f6c8d94a4f..3f03091349a6 100644 --- a/src/proto_alpha/lib_dac_plugin/dac_observer_client.ml +++ b/src/proto_alpha/lib_dac_plugin/dac_observer_client.ml @@ -151,7 +151,11 @@ module Client = struct Dac_plugin.hash_to_raw @@ proto_hash_to_dac_hash dac_plugin hash in let+ preimage = - Dac_node_client.Observer.get_missing_page observer_cctxt dac_hash + (* TODO: https://gitlab.com/tezos/tezos/-/issues/5627 + Currently we have only one major DAC API version ([V0]). For this reason, + clients can always default to [Dac_node_client.V0]. This should be + revisited once we add another major version. *) + Dac_node_client.V0.Observer.get_missing_page observer_cctxt dac_hash in String.of_bytes preimage end -- GitLab From 5f4db32e31b85a7045c54946b3ed8442f5ce128e Mon Sep 17 00:00:00 2001 From: Martin Tomazic Date: Tue, 9 May 2023 17:27:02 +0200 Subject: [PATCH 5/5] DAC/tezt: Only valid api version prefix is supported --- tezt/tests/dac.ml | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/tezt/tests/dac.ml b/tezt/tests/dac.ml index 20a69ccd46bb..7c57bacfe59e 100644 --- a/tezt/tests/dac.ml +++ b/tezt/tests/dac.ml @@ -2510,6 +2510,26 @@ module Tx_kernel_e2e = struct (test_tx_kernel_e2e_with_dac_observer_missing_pages commitment_period) end +(** [Api] module consist of tests about valid API calls and API versioning. *) +module Api = struct + (** Test that existing endpoints only support valid API version prefix. *) + let test_only_valid_api_version_prefix_is_supported + Scenarios.{coordinator_node; _} = + (* We want to test that [api_version_rpc_arg] only captures + valid api version. For this we choose a concrete endpoint from V0 API, + and pass it invalid [api_version]. *) + let* response = + RPC.call_raw + coordinator_node + Dac_rpc.( + post_store_preimage + ~payload:"test" + ~pagination_scheme:"Merkle_tree_V0" + ~api_version:"Invalid API version prefix") + in + Lwt.return @@ RPC.check_string_response ~code:400 response +end + let register ~protocols = (* Tests with layer1 and dac nodes *) Legacy.test_dac_node_startup protocols ; @@ -2636,4 +2656,12 @@ let register ~protocols = Full_infrastructure.test_client 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__ + ~committee_size:0 + ~observers:0 + ~tags:["dac"; "dac_node"] + "only valid api version prefix is supported" + Api.test_only_valid_api_version_prefix_is_supported + protocols -- GitLab