diff --git a/src/bin_dac_client/command_handlers.ml b/src/bin_dac_client/command_handlers.ml index 08d16144b6b9c8f42dab7ed59dfdb822d0c56fc9..09a4f3eeb11f0b008ac719554c735ad1a01d927a 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/RPC_services.ml b/src/lib_dac/RPC_services.ml index a8d5821dfcedf5ede1e068fe33f754c1a10093aa..d69b2c5074aacd7ab79a8ec3812075add166f52b 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 = @@ -51,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. *) @@ -60,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 @@ -76,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 @@ -84,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 @@ -95,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 @@ -115,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 2ee345314dba6b304fe90f12feffdd03ad4a3fa0..234e172c85036fc20ee713be7a406da343254297 100644 --- a/src/lib_dac/RPC_services.mli +++ b/src/lib_dac/RPC_services.mli @@ -23,75 +23,104 @@ (* *) (*****************************************************************************) -(** 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. *) +(** [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! *) + + (* 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 [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 41a38017d90ba10f711927d89fcae44bb94fc073..cc0e7d2a6974a28880dc45b140fa0c9cdde34d07 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 a5d213d254aa803b191def148442d20774cc021f..c491ee7e8f9228fad157c1039df33fcc5f39ef15 100644 --- a/src/lib_dac/monitor_services.mli +++ b/src/lib_dac/monitor_services.mli @@ -24,41 +24,48 @@ (*****************************************************************************) 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 ) 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 /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 +(** [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 -> + 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 f185896d61c500474656c2b7dfc321ada216112b..3c191403fe4f0eff91f2bacbbb5497a69dd59b57 100644 --- a/src/lib_dac_client/dac_node_client.ml +++ b/src/lib_dac_client/dac_node_client.ml @@ -44,40 +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 ((), page_hash) () () +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 post_store_preimage (cctxt : #cctxt) ~payload ~pagination_scheme = - cctxt#call_service - RPC_services.post_store_preimage - () - () - (payload, pagination_scheme) + 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 () + 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 () () signature + let put_dac_member_signature (cctxt : #cctxt) ~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) () () + let get_certificate (cctxt : #cctxt) ~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 + 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 () () payload -end + 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 ((), page_hash) () () + 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 a86c83026aba40f9c7a585aa7a09a9c9e12ca923..9cf7a90c58f9b3d575f70e884fc671130d575b27 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/RPC_server.ml b/src/lib_dac_node/RPC_server.ml index 2135cc2bf98c9d6b7bc979bbc2502edd529b24bb..8d6d7a7411728b1e683a0fec5d3371dfac40cf2f 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 @@ -325,14 +326,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 @@ -365,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 472fea25d6afc0d9fde87192f92224ba898a41a9..63042cea6e97c33664d4f0f7d5a130d829b2c5dc 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 @@ -202,7 +206,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 +249,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 @@ -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 @@ -354,7 +362,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/src/lib_dac_node/page_store.ml b/src/lib_dac_node/page_store.ml index a7045287d27687b202244a55dfaaeb8985f660c3..679b450a72d555cf8a6ccd0111a28be6aa8ebbe1 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 92f6c8d94a4f9f9cc7e6e400888a19d9e3038e39..3f03091349a6a8b1dee2d953ca2af29725d16593 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 diff --git a/tezt/lib_tezos/dac_rpc.ml b/tezt/lib_tezos/dac_rpc.ml index e9cc972abeaefac34a83f32183f50b63b0bb9d43..0560dd0890163b694e40630d26315cad0ce0cc02 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 76f1760f16fda0b10b3d8d4ba468c0f022bff47f..fa5b2b92e5067c10533644d5db4368c4468ec46f 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 03596489dff30ac54c17a842a8328e196cc207a9..7c57bacfe59e583f5d487feae01461e462fab4ea 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 = @@ -2442,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 ; @@ -2568,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