From e094d010c5e2a796fec9111c5860427c2890bd33 Mon Sep 17 00:00:00 2001 From: Gauthier SEBILLE Date: Mon, 12 Jun 2023 18:02:34 +0200 Subject: [PATCH 1/4] DAC: get rid of Hash_chain_v0 pagination scheme DAC: delete useless fixme comment DAC: fix arith PVM test DAC: remove hash_chain from pages_encoding --- src/lib_dac/RPC_services.ml | 6 +- src/lib_dac/RPC_services.mli | 7 +- src/lib_dac/pagination_scheme.ml | 30 ----- src/lib_dac/pagination_scheme.mli | 31 ----- src/lib_dac_client/dac_node_client.ml | 8 +- src/lib_dac_client/dac_node_client.mli | 11 +- src/lib_dac_node/RPC_handlers.ml | 40 ++---- src/lib_dac_node/RPC_handlers.mli | 2 +- src/lib_dac_node/pages_encoding.ml | 53 -------- src/lib_dac_node/pages_encoding.mli | 14 -- .../test/test_dac_pages_encoding.ml | 123 ------------------ .../test/test_dac_pages_encoding.ml | 123 ------------------ tezt/lib_tezos/dac_helper.ml | 6 +- tezt/lib_tezos/dac_helper.mli | 7 +- tezt/lib_tezos/dac_rpc.ml | 7 +- tezt/lib_tezos/dac_rpc.mli | 13 +- tezt/tests/dac.ml | 28 ++-- 17 files changed, 44 insertions(+), 465 deletions(-) delete mode 100644 src/lib_dac/pagination_scheme.ml delete mode 100644 src/lib_dac/pagination_scheme.mli diff --git a/src/lib_dac/RPC_services.ml b/src/lib_dac/RPC_services.ml index 646fd80ba10f..00d0f6a88ec9 100644 --- a/src/lib_dac/RPC_services.ml +++ b/src/lib_dac/RPC_services.ml @@ -30,11 +30,7 @@ module V0 = struct (* A variant of [Sc_rollup_reveal_hash.encoding] that prefers hex encoding over b58check encoding for JSON. *) let store_preimage_request_encoding = - let pagination_scheme_encoding = Pagination_scheme.encoding in - Data_encoding.( - obj2 - (req "payload" Data_encoding.(bytes' Hex)) - (req "pagination_scheme" pagination_scheme_encoding)) + Data_encoding.(obj1 (req "payload" Data_encoding.(bytes' Hex))) let store_preimage_response_encoding = Data_encoding.( diff --git a/src/lib_dac/RPC_services.mli b/src/lib_dac/RPC_services.mli index 0e9ae4419d84..47cea45c02d7 100644 --- a/src/lib_dac/RPC_services.mli +++ b/src/lib_dac/RPC_services.mli @@ -28,15 +28,14 @@ 1M/tps demo. The plan is to remove it once we get rid of the [Legacy] mode. Use at your own risk! *) module V0 : sig - (** "POST v0/store_preimage" stores a payload using a given - [pagination_scheme]. It returns the base58 encoded root page hash - and the raw bytes. *) + (** "POST v0/store_preimage" stores a payload. It returns the + base58 encoded root page hash and the raw bytes. *) val post_store_preimage : ( [`POST], unit, unit, unit, - Bytes.t * Pagination_scheme.t, + Bytes.t, Dac_plugin.raw_hash * Bytes.t ) Tezos_rpc.Service.service diff --git a/src/lib_dac/pagination_scheme.ml b/src/lib_dac/pagination_scheme.ml deleted file mode 100644 index e11caf882a25..000000000000 --- a/src/lib_dac/pagination_scheme.ml +++ /dev/null @@ -1,30 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 TriliTech *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -type t = Merkle_tree_V0 | Hash_chain_V0 - -let encoding = - Data_encoding.string_enum - [("Merkle_tree_V0", Merkle_tree_V0); ("Hash_chain_V0", Hash_chain_V0)] diff --git a/src/lib_dac/pagination_scheme.mli b/src/lib_dac/pagination_scheme.mli deleted file mode 100644 index 48707bcdb569..000000000000 --- a/src/lib_dac/pagination_scheme.mli +++ /dev/null @@ -1,31 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 TriliTech *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -(** The pagination schemes that are supported by the DAC node for converting - a payload in a set of pages of 4096 bytes each. *) -type t = Merkle_tree_V0 | Hash_chain_V0 - -(** The encoding for pagination schemes. *) -val encoding : t Data_encoding.t diff --git a/src/lib_dac_client/dac_node_client.ml b/src/lib_dac_client/dac_node_client.ml index b678bb3256cf..0d3cc85031a5 100644 --- a/src/lib_dac_client/dac_node_client.ml +++ b/src/lib_dac_client/dac_node_client.ml @@ -54,12 +54,8 @@ module V0 = struct let get_preimage (cctxt : #cctxt) ~page_hash = cctxt#call_service RPC_services.V0.get_preimage ((), page_hash) () () - let post_store_preimage (cctxt : #cctxt) ~payload ~pagination_scheme = - cctxt#call_service - RPC_services.V0.post_store_preimage - () - () - (payload, pagination_scheme) + let post_store_preimage (cctxt : #cctxt) ~payload = + cctxt#call_service RPC_services.V0.post_store_preimage () () payload let get_verify_signature (cctxt : #cctxt) ~external_message = cctxt#call_service diff --git a/src/lib_dac_client/dac_node_client.mli b/src/lib_dac_client/dac_node_client.mli index 1c63d68c46e0..db2ea4646f51 100644 --- a/src/lib_dac_client/dac_node_client.mli +++ b/src/lib_dac_client/dac_node_client.mli @@ -49,14 +49,11 @@ module V0 : sig 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 v0/store_preimage using a given [pagination_scheme]. It returns the hex - encoded root page hash and the raw bytes. *) + (** [post_store_preimage cctxt ~payload] posts a [payload] + to v0/store_preimage. 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 + #cctxt -> payload:bytes -> (Dac_plugin.raw_hash * bytes) tzresult Lwt.t (** [get_verify_signature cctxt ~external_message] requests the DAC node to verify the signature of the external message [external_message] via diff --git a/src/lib_dac_node/RPC_handlers.ml b/src/lib_dac_node/RPC_handlers.ml index 8853ea812261..2105a42793e7 100644 --- a/src/lib_dac_node/RPC_handlers.ml +++ b/src/lib_dac_node/RPC_handlers.ml @@ -83,38 +83,20 @@ end module V0 = struct let handle_post_store_preimage dac_plugin cctxt dac_sk_uris page_store - hash_streamer (data, pagination_scheme) = + hash_streamer data = let open Lwt_result_syntax in let open Pages_encoding in let* root_hash = - match pagination_scheme with - | Pagination_scheme.Merkle_tree_V0 -> - (* FIXME: https://gitlab.com/tezos/tezos/-/issues/4897 - Once new "PUT /preimage" endpoint is implemented, pushing - a new root hash to the data streamer should be moved there. - Tezt for testing streaming of root hashes should also use - the new endpoint. *) - let* root_hash = - Merkle_tree.V0.Filesystem.serialize_payload - dac_plugin - ~page_store - data - in - let () = - Data_streamer.publish - hash_streamer - (Dac_plugin.hash_to_raw root_hash) - in - let*! () = - Event.emit_root_hash_pushed_to_data_streamer dac_plugin root_hash - in - return root_hash - | Pagination_scheme.Hash_chain_V0 -> - Hash_chain.V0.serialize_payload - dac_plugin - ~for_each_page:(fun (hash, content) -> - Page_store.Filesystem.save dac_plugin page_store ~hash ~content) - data + let* root_hash = + Merkle_tree.V0.Filesystem.serialize_payload dac_plugin ~page_store data + in + let () = + Data_streamer.publish hash_streamer (Dac_plugin.hash_to_raw root_hash) + in + let*! () = + Event.emit_root_hash_pushed_to_data_streamer dac_plugin root_hash + in + return root_hash in let* signature, witnesses = Signature_manager.Legacy.sign_root_hash diff --git a/src/lib_dac_node/RPC_handlers.mli b/src/lib_dac_node/RPC_handlers.mli index d0834ffac045..686d348227b8 100644 --- a/src/lib_dac_node/RPC_handlers.mli +++ b/src/lib_dac_node/RPC_handlers.mli @@ -59,7 +59,7 @@ module V0 : sig Client_keys.aggregate_sk_uri option trace -> Page_store.Filesystem.t -> Dac_plugin.raw_hash Data_streamer.t -> - bytes * Pagination_scheme.t -> + bytes -> (Dac_plugin.raw_hash * bytes, tztrace) result Lwt.t (** [handle_get_verify_signature] is a handler for "GET v0/verify_signature". *) diff --git a/src/lib_dac_node/pages_encoding.ml b/src/lib_dac_node/pages_encoding.ml index 7c090bea980b..96b0d19f497e 100644 --- a/src/lib_dac_node/pages_encoding.ml +++ b/src/lib_dac_node/pages_encoding.ml @@ -567,56 +567,3 @@ module Merkle_tree = struct module Make = Make end end - -module Hash_chain = struct - module V0 = struct - type page = {succ_hash : Dac_plugin.hash; content : string} - - let hash ((module Plugin) : Dac_plugin.t) bytes = - Plugin.hash_bytes ~scheme:Blake2B [bytes] - - let content_limit = - (4 * 1024) - 100 (* We reserve 100 bytes for the continuation hash. *) - - let serialize_page ((module Plugin) : Dac_plugin.t) page = - Format.asprintf "%s hash:%s" page.content (Plugin.to_hex page.succ_hash) - - let link_chunks dac_plugin chunks : (Dac_plugin.hash * bytes) list = - let rec link_chunks_rev linked_pages rev_pages = - match rev_pages with - | [] -> linked_pages - | chunk :: rev_chunks -> - let page = - match linked_pages with - | [] -> chunk - | (succ_hash, _) :: _ -> - serialize_page dac_plugin {succ_hash; content = chunk} - in - let page = Bytes.of_string page in - let hash = hash dac_plugin page in - (link_chunks_rev [@tailcall]) - ((hash, page) :: linked_pages) - rev_chunks - in - let rev_chunks = List.rev chunks in - link_chunks_rev [] rev_chunks - - let make_hash_chain dac_plugin data = - let open Result_syntax in - let+ chunks = String.chunk_bytes content_limit data in - link_chunks dac_plugin chunks - - (** Main function for computing a hash chain from a byte sequence. Returns the - chain head hash.[for_each_page] may be supplied to run post processing - tasks on each page, for example, to persisit a serialized page to disk. - *) - let serialize_payload dac_plugin ~for_each_page payload = - let open Lwt_result_syntax in - let* () = - fail_unless (Bytes.length payload > 0) Payload_cannot_be_empty - in - let*? hash_chain = make_hash_chain dac_plugin payload in - let+ () = List.iter_es for_each_page hash_chain in - Stdlib.List.hd hash_chain |> fst - end -end diff --git a/src/lib_dac_node/pages_encoding.mli b/src/lib_dac_node/pages_encoding.mli index 662d27731ff8..02ab4429c154 100644 --- a/src/lib_dac_node/pages_encoding.mli +++ b/src/lib_dac_node/pages_encoding.mli @@ -169,17 +169,3 @@ module Merkle_tree : sig end end -(** Encoding of DAC payload as a Hash Chain/Merkle List. The encoding - implementation is specific to the Arith PVM. *) -module Hash_chain : sig - module V0 : sig - val serialize_payload : - Dac_plugin.t -> - for_each_page:(Dac_plugin.hash * bytes -> unit tzresult Lwt.t) -> - bytes -> - Dac_plugin.hash tzresult Lwt.t - - val make_hash_chain : - Dac_plugin.t -> bytes -> ((Dac_plugin.hash * bytes) list, 'a) result - end -end diff --git a/src/proto_017_PtNairob/lib_dac_plugin/test/test_dac_pages_encoding.ml b/src/proto_017_PtNairob/lib_dac_plugin/test/test_dac_pages_encoding.ml index a9483a551538..814efbb706bb 100644 --- a/src/proto_017_PtNairob/lib_dac_plugin/test/test_dac_pages_encoding.ml +++ b/src/proto_017_PtNairob/lib_dac_plugin/test/test_dac_pages_encoding.ml @@ -543,112 +543,6 @@ module Merkle_tree = struct end end -module Hash_chain = struct - (* Return substring of [str] after the first [n] char. Returns the original string - if n <= 0. Returns an empty string if n > String.length str *) - let take_after str n = - let n = max 0 n in - String.sub str (min (String.length str) n) (max 0 (String.length str - n)) - - module V0 = struct - module Pagination_scheme = Pages_encoding.Hash_chain.V0 - - let deserialize_page page : - [`Node of Dac_plugin.hash * string | `Leaf of string] = - if String.length page > 3996 then - let content = String.sub page 0 3996 in - let (module Plugin) = dac_plugin in - let hash = - Stdlib.Option.get - @@ Plugin.of_hex (take_after page (3996 + String.length " hash:")) - in - `Node (hash, content) - else `Leaf page - - let rec retrieve_content ~get_page ?(result = "") hash = - let open Lwt_result_syntax in - let* page = get_page hash in - let* res = return @@ deserialize_page (Bytes.to_string page) in - match res with - | `Node (succ_hash, content) -> - (retrieve_content [@tailcall]) - ~get_page - ~result:(String.cat result content) - succ_hash - | `Leaf content -> return @@ String.cat result content - - let test_make_chain_hash_one_page () = - let open Lwt_result_syntax in - let payload = Bytes.of_string "simple payload" in - let*? pages = Pagination_scheme.make_hash_chain dac_plugin payload in - let* () = Assert.equal_int ~loc:__LOC__ 1 (List.length pages) in - let actual_hash, content = Stdlib.List.hd pages in - let* () = - assert_equal_bytes ~loc:__LOC__ "Contents not equal" payload content - in - let (module Plugin) = dac_plugin in - let expected_hash = - Plugin.to_hex @@ Plugin.hash_bytes ~scheme:Blake2B [content] - in - Assert.equal_string ~loc:__LOC__ expected_hash (Plugin.to_hex actual_hash) - - let test_make_chain_hash_long () = - let open Lwt_result_syntax in - let payload = Bytes.of_string long_payload in - let*? pages = Pagination_scheme.make_hash_chain dac_plugin payload in - let* () = Assert.equal_int ~loc:__LOC__ 2 (List.length pages) in - let head_succ = - Stdlib.List.hd pages |> snd |> fun byt -> - take_after (String.of_bytes byt) (3996 + String.length " hash:") - in - let (module Plugin) = dac_plugin in - let next_hash, content = Stdlib.List.nth pages 1 in - let* () = - Assert.equal_string ~loc:__LOC__ (Plugin.to_hex next_hash) head_succ - in - Assert.equal_string - ~loc:__LOC__ - (Plugin.to_hex next_hash) - (Plugin.to_hex @@ Plugin.hash_bytes ~scheme:Blake2B [content]) - - let test_serialize () = - let open Lwt_result_syntax in - let payload = Bytes.of_string long_payload in - let page_store = Hashes_map_backend.init () in - let* root_hash = - Pagination_scheme.serialize_payload - dac_plugin - ~for_each_page:(fun (hash, content) -> - Hashes_map_backend.save dac_plugin page_store ~hash ~content) - payload - in - let* () = - Assert.equal_int - ~loc:__LOC__ - (Hashes_map_backend.number_of_pages page_store) - 2 - in - let get_page hash = Hashes_map_backend.load dac_plugin page_store hash in - let* content = retrieve_content ~get_page root_hash in - Assert.equal_string ~loc:__LOC__ long_payload content - - let test_serialize_empty_payload_fails () = - let page_store = Hashes_map_backend.init () in - let payload = Bytes.of_string "" in - let result = - Pagination_scheme.serialize_payload - ~for_each_page:(fun (hash, content) -> - Hashes_map_backend.save dac_plugin page_store ~hash ~content) - dac_plugin - payload - in - assert_fails_with - ~loc:__LOC__ - result - Pages_encoding.Payload_cannot_be_empty - end -end - let tests = [ Tztest.tztest @@ -683,23 +577,6 @@ let tests = "Hashes pages are not larger than expected" `Quick Merkle_tree.V0.multiple_pages_roundtrip_do_not_exceed_page_size; - Tztest.tztest - "Constructing hash chain (V0) for single page content is correct" - `Quick - Hash_chain.V0.test_make_chain_hash_one_page; - Tztest.tztest - "Constructing hash chain (V0) for multi page content is correct" - `Quick - Hash_chain.V0.test_make_chain_hash_long; - Tztest.tztest - "Serializing an empty payload returns an error (Hash chain)" - `Quick - Hash_chain.V0.test_serialize_empty_payload_fails; - Tztest.tztest - "Contents fitting in more pages can be retrieved after being saved - \ - repeated pages (Hash chain, V0)" - `Quick - Hash_chain.V0.test_serialize; Tztest.tztest "Deserialization with integrity check fails if page contents are corrupt" `Quick diff --git a/src/proto_alpha/lib_dac_plugin/test/test_dac_pages_encoding.ml b/src/proto_alpha/lib_dac_plugin/test/test_dac_pages_encoding.ml index 2a6018905dec..4fc0eab684fd 100644 --- a/src/proto_alpha/lib_dac_plugin/test/test_dac_pages_encoding.ml +++ b/src/proto_alpha/lib_dac_plugin/test/test_dac_pages_encoding.ml @@ -589,112 +589,6 @@ module Merkle_tree = struct end end -module Hash_chain = struct - (* Return substring of [str] after the first [n] char. Returns the original string - if n <= 0. Returns an empty string if n > String.length str *) - let take_after str n = - let n = max 0 n in - String.sub str (min (String.length str) n) (max 0 (String.length str - n)) - - module V0 = struct - module Pagination_scheme = Pages_encoding.Hash_chain.V0 - - let deserialize_page page : - [`Node of Dac_plugin.hash * string | `Leaf of string] = - if String.length page > 3996 then - let content = String.sub page 0 3996 in - let (module Plugin) = dac_plugin in - let hash = - Stdlib.Option.get - @@ Plugin.of_hex (take_after page (3996 + String.length " hash:")) - in - `Node (hash, content) - else `Leaf page - - let rec retrieve_content ~get_page ?(result = "") hash = - let open Lwt_result_syntax in - let* page = get_page hash in - let* res = return @@ deserialize_page (Bytes.to_string page) in - match res with - | `Node (succ_hash, content) -> - (retrieve_content [@tailcall]) - ~get_page - ~result:(String.cat result content) - succ_hash - | `Leaf content -> return @@ String.cat result content - - let test_make_chain_hash_one_page () = - let open Lwt_result_syntax in - let payload = Bytes.of_string "simple payload" in - let*? pages = Pagination_scheme.make_hash_chain dac_plugin payload in - let* () = Assert.equal_int ~loc:__LOC__ 1 (List.length pages) in - let actual_hash, content = Stdlib.List.hd pages in - let* () = - assert_equal_bytes ~loc:__LOC__ "Contents not equal" payload content - in - let (module Plugin) = dac_plugin in - let expected_hash = - Plugin.to_hex @@ Plugin.hash_bytes ~scheme:Blake2B [content] - in - Assert.equal_string ~loc:__LOC__ expected_hash (Plugin.to_hex actual_hash) - - let test_make_chain_hash_long () = - let open Lwt_result_syntax in - let payload = Bytes.of_string long_payload in - let*? pages = Pagination_scheme.make_hash_chain dac_plugin payload in - let* () = Assert.equal_int ~loc:__LOC__ 2 (List.length pages) in - let head_succ = - Stdlib.List.hd pages |> snd |> fun byt -> - take_after (String.of_bytes byt) (3996 + String.length " hash:") - in - let (module Plugin) = dac_plugin in - let next_hash, content = Stdlib.List.nth pages 1 in - let* () = - Assert.equal_string ~loc:__LOC__ (Plugin.to_hex next_hash) head_succ - in - Assert.equal_string - ~loc:__LOC__ - (Plugin.to_hex next_hash) - (Plugin.to_hex @@ Plugin.hash_bytes ~scheme:Blake2B [content]) - - let test_serialize () = - let open Lwt_result_syntax in - let payload = Bytes.of_string long_payload in - let page_store = Hashes_map_backend.init () in - let* root_hash = - Pagination_scheme.serialize_payload - dac_plugin - ~for_each_page:(fun (hash, content) -> - Hashes_map_backend.save dac_plugin page_store ~hash ~content) - payload - in - let* () = - Assert.equal_int - ~loc:__LOC__ - (Hashes_map_backend.number_of_pages page_store) - 2 - in - let get_page hash = Hashes_map_backend.load dac_plugin page_store hash in - let* content = retrieve_content ~get_page root_hash in - Assert.equal_string ~loc:__LOC__ long_payload content - - let test_serialize_empty_payload_fails () = - let page_store = Hashes_map_backend.init () in - let payload = Bytes.of_string "" in - let result = - Pagination_scheme.serialize_payload - ~for_each_page:(fun (hash, content) -> - Hashes_map_backend.save dac_plugin page_store ~hash ~content) - dac_plugin - payload - in - assert_fails_with - ~loc:__LOC__ - result - Pages_encoding.Payload_cannot_be_empty - end -end - let tests = [ Tztest.tztest @@ -729,23 +623,6 @@ let tests = "Hashes pages are not larger than expected" `Quick Merkle_tree.V0.multiple_pages_roundtrip_do_not_exceed_page_size; - Tztest.tztest - "Constructing hash chain (V0) for single page content is correct" - `Quick - Hash_chain.V0.test_make_chain_hash_one_page; - Tztest.tztest - "Constructing hash chain (V0) for multi page content is correct" - `Quick - Hash_chain.V0.test_make_chain_hash_long; - Tztest.tztest - "Serializing an empty payload returns an error (Hash chain)" - `Quick - Hash_chain.V0.test_serialize_empty_payload_fails; - Tztest.tztest - "Contents fitting in more pages can be retrieved after being saved - \ - repeated pages (Hash chain, V0)" - `Quick - Hash_chain.V0.test_serialize; Tztest.tztest "Deserialization with integrity check fails if page contents are corrupt" `Quick diff --git a/tezt/lib_tezos/dac_helper.ml b/tezt/lib_tezos/dac_helper.ml index 7471da0333b0..b957cc2eb747 100644 --- a/tezt/lib_tezos/dac_helper.ml +++ b/tezt/lib_tezos/dac_helper.ml @@ -460,10 +460,8 @@ module Call_endpoint = struct let get_preimage dac_node page_hash = RPC.call dac_node (Dac_rpc.V0.get_preimage page_hash) - let post_store_preimage dac_node ~payload ~pagination_scheme = - RPC.call - dac_node - (Dac_rpc.V0.post_store_preimage ~payload ~pagination_scheme) + let post_store_preimage dac_node ~payload = + RPC.call dac_node (Dac_rpc.V0.post_store_preimage ~payload) let get_verify_signature dac_node external_message = RPC.call dac_node (Dac_rpc.V0.get_verify_signature external_message) diff --git a/tezt/lib_tezos/dac_helper.mli b/tezt/lib_tezos/dac_helper.mli index e87f18edb485..9a30ac39a4e7 100644 --- a/tezt/lib_tezos/dac_helper.mli +++ b/tezt/lib_tezos/dac_helper.mli @@ -200,12 +200,9 @@ module Call_endpoint : sig (** Call GET v0/preimage/page_hash for the provided [page_hash]. *) val get_preimage : Dac_node.t -> string -> string Lwt.t - (** Call POST v0/store_preimage with provided payload and pagination_scheme. *) + (** Call POST v0/store_preimage with provided payload. *) val post_store_preimage : - Dac_node.t -> - payload:string -> - pagination_scheme:string -> - (string * string) Lwt.t + Dac_node.t -> payload:string -> (string * string) Lwt.t (** Call GET v0/verify_signature for the provided payload. *) val get_verify_signature : Dac_node.t -> string -> bool Lwt.t diff --git a/tezt/lib_tezos/dac_rpc.ml b/tezt/lib_tezos/dac_rpc.ml index 5e203719ebc7..ca5dccdf668c 100644 --- a/tezt/lib_tezos/dac_rpc.ml +++ b/tezt/lib_tezos/dac_rpc.ml @@ -46,14 +46,11 @@ module V0 = struct let get_preimage page_hash = make GET [api_prefix; "preimage"; page_hash] JSON.as_string - let post_store_preimage ~payload ~pagination_scheme = + let post_store_preimage ~payload = let preimage = JSON.parse ~origin:"dal_node_dac_store_preimage_rpc" - (Format.sprintf - {|{"payload":%s,"pagination_scheme":"%s"}|} - (encode_bytes_to_hex_string payload) - pagination_scheme) + (Format.sprintf {|{"payload":%s}|} (encode_bytes_to_hex_string payload)) in let data : RPC_core.data = Data (JSON.unannotate preimage) in make ~data POST [api_prefix; "store_preimage"] @@ fun json -> diff --git a/tezt/lib_tezos/dac_rpc.mli b/tezt/lib_tezos/dac_rpc.mli index 05fca80686ae..14b6f46daa8c 100644 --- a/tezt/lib_tezos/dac_rpc.mli +++ b/tezt/lib_tezos/dac_rpc.mli @@ -33,15 +33,12 @@ module V0 : sig returned as a sequence of bytes. *) val get_preimage : string -> (Dac_node.t, string) RPC_core.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 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] posts a + [payload] to "v0/store_preimage". 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 -> - (Dac_node.t, string * string) RPC_core.t + payload:string -> (Dac_node.t, string * string) RPC_core.t (** [get_verify_signature cctxt external_message] requests the DAC node to verify the signature of the external message [external_message] via diff --git a/tezt/tests/dac.ml b/tezt/tests/dac.ml index b7d92a15097b..b52148e19645 100644 --- a/tezt/tests/dac.ml +++ b/tezt/tests/dac.ml @@ -47,10 +47,7 @@ let assert_lwt_failure ?__LOC__ msg lwt_under_inspection = let init_hex_root_hash ?payload coordinator_node = let payload = Option.value payload ~default:"hello test message" in let* root_hash, _l1_op = - Dac_helper.Call_endpoint.V0.post_store_preimage - coordinator_node - ~payload - ~pagination_scheme:"Merkle_tree_V0" + Dac_helper.Call_endpoint.V0.post_store_preimage coordinator_node ~payload in let hex_root_hash = `Hex root_hash in return hex_root_hash @@ -314,6 +311,15 @@ let sample_payload example_filename = let decode_hex_string_to_bytes s = Hex.to_string (`Hex s) +let assert_state_changed ?block sc_rollup_client prev_state_hash = + let*! state_hash = + Sc_rollup_client.state_hash ?block ~hooks sc_rollup_client + in + Check.(state_hash <> prev_state_hash) + Check.string + ~error_msg:"State hash has not changed (%L <> %R)" ; + Lwt.return_unit + (** This modules encapsulate tests for DAC nodes when running in legacy node. It includes tests where we have two dac nodes running in the legacy mode interacting with each other. As such one node normally tries @@ -342,10 +348,7 @@ module Legacy = struct let coordinator_serializes_payload coordinator ~payload ~expected_rh = let* actual_rh, _l1_operation = - Dac_helper.Call_endpoint.V0.post_store_preimage - coordinator - ~payload - ~pagination_scheme:"Merkle_tree_V0" + Dac_helper.Call_endpoint.V0.post_store_preimage coordinator ~payload in return @@ check_valid_root_hash expected_rh actual_rh @@ -1773,15 +1776,6 @@ module Tx_kernel_e2e = struct @@ [multiaccount_tx_of accounts_ops] end - let assert_state_changed ?block sc_rollup_client prev_state_hash = - let*! state_hash = - Sc_rollup_client.state_hash ?block ~hooks sc_rollup_client - in - Check.(state_hash <> prev_state_hash) - Check.string - ~error_msg:"State hash has not changed (%L <> %R)" ; - Lwt.return_unit - let assert_ticks_advanced ?block sc_rollup_client prev_ticks = let*! ticks = Sc_rollup_client.total_ticks ?block ~hooks sc_rollup_client in Check.(ticks > prev_ticks) -- GitLab From a668a7706aa91dd3049152e0c8cb1b6e2ffa2ba6 Mon Sep 17 00:00:00 2001 From: Gauthier SEBILLE Date: Thu, 22 Jun 2023 20:56:42 +0200 Subject: [PATCH 2/4] DAC: migrate test to sc_rollup --- src/lib_dac_node/pages_encoding.mli | 1 - tezt/tests/dac.ml | 9 -------- tezt/tests/sc_rollup.ml | 34 +++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/lib_dac_node/pages_encoding.mli b/src/lib_dac_node/pages_encoding.mli index 02ab4429c154..02242a167366 100644 --- a/src/lib_dac_node/pages_encoding.mli +++ b/src/lib_dac_node/pages_encoding.mli @@ -168,4 +168,3 @@ module Merkle_tree : sig Dac_codec with type page_store := B.page_store end end - diff --git a/tezt/tests/dac.ml b/tezt/tests/dac.ml index b52148e19645..eb576f0265d1 100644 --- a/tezt/tests/dac.ml +++ b/tezt/tests/dac.ml @@ -173,15 +173,6 @@ let pp fmt = function let status_typ = Check.equalable pp ( = ) -let send_messages ?(src = Constant.bootstrap2.alias) ?(alter_final_msg = Fun.id) - client msgs = - let msg = - alter_final_msg - @@ Ezjsonm.(to_string ~minify:true @@ list Ezjsonm.string msgs) - in - let* () = Client.Sc_rollup.send_message ~hooks ~src ~msg client in - Client.bake_for_and_wait client - let bake_levels n client = repeat n (fun () -> Client.bake_for_and_wait client) let check_valid_root_hash expected_rh actual_rh = diff --git a/tezt/tests/sc_rollup.ml b/tezt/tests/sc_rollup.ml index 379da6d2e6bb..3da13307cc6c 100644 --- a/tezt/tests/sc_rollup.ml +++ b/tezt/tests/sc_rollup.ml @@ -2719,6 +2719,39 @@ let test_reveals_fails_on_wrong_hash = in Lwt.choose [error_promise; should_not_sync] +let test_reveals_fails_on_unknown_hash = + let kind = "arith" in + test_full_scenario + ~timeout:120 + ~kind + { + tags = ["reveals"; "unknown"]; + variant = None; + description = "reveal data fails with unknown hash"; + } + @@ fun _protocol sc_rollup_node _sc_rollup_client sc_rollup node client -> + let unknown_hash = + "0027782d2a7020be332cc42c4e66592ec50305f559a4011981f1d5af81428ecafe" + in + let* () = Sc_rollup_node.run sc_rollup_node sc_rollup [] in + let error_promise = + Sc_rollup_node.wait_for sc_rollup_node "sc_rollup_daemon_error.v0" (fun e -> + let id = JSON.(e |=> 0 |-> "id" |> as_string) in + if id =~ rex "could_not_open_reveal_preimage_file" then Some () + else None) + in + let* () = send_text_messages client ["hash:" ^ unknown_hash] in + let should_not_sync = + let* _level = + Sc_rollup_node.wait_for_level + ~timeout:10. + sc_rollup_node + (Node.get_level node) + in + Test.fail "The rollup node processed the unknown reveal without failing" + in + Lwt.choose [error_promise; should_not_sync] + let test_reveals_4k = let kind = "arith" in test_full_scenario @@ -5613,6 +5646,7 @@ let register ~protocols = ~kind:"arith" protocols ; test_reveals_fails_on_wrong_hash protocols ; + test_reveals_fails_on_unknown_hash protocols ; test_reveals_4k protocols ; test_reveals_above_4k protocols ; (* Specific Wasm PVM tezts *) -- GitLab From 7905956d6ec5c1d8f6db194095c5b95ba18db937 Mon Sep 17 00:00:00 2001 From: Gauthier SEBILLE Date: Fri, 30 Jun 2023 18:11:22 +0200 Subject: [PATCH 3/4] DAC: remove useless test of hash_chain for oxford DAC: only run test for Nairobi and after --- .../test/test_dac_pages_encoding.ml | 123 ------------------ tezt/tests/sc_rollup.ml | 1 + 2 files changed, 1 insertion(+), 123 deletions(-) diff --git a/src/proto_018_Proxford/lib_dac_plugin/test/test_dac_pages_encoding.ml b/src/proto_018_Proxford/lib_dac_plugin/test/test_dac_pages_encoding.ml index 7af792bdb072..505db3183705 100644 --- a/src/proto_018_Proxford/lib_dac_plugin/test/test_dac_pages_encoding.ml +++ b/src/proto_018_Proxford/lib_dac_plugin/test/test_dac_pages_encoding.ml @@ -589,112 +589,6 @@ module Merkle_tree = struct end end -module Hash_chain = struct - (* Return substring of [str] after the first [n] char. Returns the original string - if n <= 0. Returns an empty string if n > String.length str *) - let take_after str n = - let n = max 0 n in - String.sub str (min (String.length str) n) (max 0 (String.length str - n)) - - module V0 = struct - module Pagination_scheme = Pages_encoding.Hash_chain.V0 - - let deserialize_page page : - [`Node of Dac_plugin.hash * string | `Leaf of string] = - if String.length page > 3996 then - let content = String.sub page 0 3996 in - let (module Plugin) = dac_plugin in - let hash = - Stdlib.Option.get - @@ Plugin.of_hex (take_after page (3996 + String.length " hash:")) - in - `Node (hash, content) - else `Leaf page - - let rec retrieve_content ~get_page ?(result = "") hash = - let open Lwt_result_syntax in - let* page = get_page hash in - let* res = return @@ deserialize_page (Bytes.to_string page) in - match res with - | `Node (succ_hash, content) -> - (retrieve_content [@tailcall]) - ~get_page - ~result:(String.cat result content) - succ_hash - | `Leaf content -> return @@ String.cat result content - - let test_make_chain_hash_one_page () = - let open Lwt_result_syntax in - let payload = Bytes.of_string "simple payload" in - let*? pages = Pagination_scheme.make_hash_chain dac_plugin payload in - let* () = Assert.equal_int ~loc:__LOC__ 1 (List.length pages) in - let actual_hash, content = Stdlib.List.hd pages in - let* () = - assert_equal_bytes ~loc:__LOC__ "Contents not equal" payload content - in - let (module Plugin) = dac_plugin in - let expected_hash = - Plugin.to_hex @@ Plugin.hash_bytes ~scheme:Blake2B [content] - in - Assert.equal_string ~loc:__LOC__ expected_hash (Plugin.to_hex actual_hash) - - let test_make_chain_hash_long () = - let open Lwt_result_syntax in - let payload = Bytes.of_string long_payload in - let*? pages = Pagination_scheme.make_hash_chain dac_plugin payload in - let* () = Assert.equal_int ~loc:__LOC__ 2 (List.length pages) in - let head_succ = - Stdlib.List.hd pages |> snd |> fun byt -> - take_after (String.of_bytes byt) (3996 + String.length " hash:") - in - let (module Plugin) = dac_plugin in - let next_hash, content = Stdlib.List.nth pages 1 in - let* () = - Assert.equal_string ~loc:__LOC__ (Plugin.to_hex next_hash) head_succ - in - Assert.equal_string - ~loc:__LOC__ - (Plugin.to_hex next_hash) - (Plugin.to_hex @@ Plugin.hash_bytes ~scheme:Blake2B [content]) - - let test_serialize () = - let open Lwt_result_syntax in - let payload = Bytes.of_string long_payload in - let page_store = Hashes_map_backend.init () in - let* root_hash = - Pagination_scheme.serialize_payload - dac_plugin - ~for_each_page:(fun (hash, content) -> - Hashes_map_backend.save dac_plugin page_store ~hash ~content) - payload - in - let* () = - Assert.equal_int - ~loc:__LOC__ - (Hashes_map_backend.number_of_pages page_store) - 2 - in - let get_page hash = Hashes_map_backend.load dac_plugin page_store hash in - let* content = retrieve_content ~get_page root_hash in - Assert.equal_string ~loc:__LOC__ long_payload content - - let test_serialize_empty_payload_fails () = - let page_store = Hashes_map_backend.init () in - let payload = Bytes.of_string "" in - let result = - Pagination_scheme.serialize_payload - ~for_each_page:(fun (hash, content) -> - Hashes_map_backend.save dac_plugin page_store ~hash ~content) - dac_plugin - payload - in - assert_fails_with - ~loc:__LOC__ - result - Pages_encoding.Payload_cannot_be_empty - end -end - let tests = [ Tztest.tztest @@ -729,23 +623,6 @@ let tests = "Hashes pages are not larger than expected" `Quick Merkle_tree.V0.multiple_pages_roundtrip_do_not_exceed_page_size; - Tztest.tztest - "Constructing hash chain (V0) for single page content is correct" - `Quick - Hash_chain.V0.test_make_chain_hash_one_page; - Tztest.tztest - "Constructing hash chain (V0) for multi page content is correct" - `Quick - Hash_chain.V0.test_make_chain_hash_long; - Tztest.tztest - "Serializing an empty payload returns an error (Hash chain)" - `Quick - Hash_chain.V0.test_serialize_empty_payload_fails; - Tztest.tztest - "Contents fitting in more pages can be retrieved after being saved - \ - repeated pages (Hash chain, V0)" - `Quick - Hash_chain.V0.test_serialize; Tztest.tztest "Deserialization with integrity check fails if page contents are corrupt" `Quick diff --git a/tezt/tests/sc_rollup.ml b/tezt/tests/sc_rollup.ml index 3da13307cc6c..32bda48be0f0 100644 --- a/tezt/tests/sc_rollup.ml +++ b/tezt/tests/sc_rollup.ml @@ -2722,6 +2722,7 @@ let test_reveals_fails_on_wrong_hash = let test_reveals_fails_on_unknown_hash = let kind = "arith" in test_full_scenario + ~supports:(Protocol.From_protocol 17) ~timeout:120 ~kind { -- GitLab From 559c00e5a59c046a2cb2a37a2592b1845fc5265a Mon Sep 17 00:00:00 2001 From: Gauthier SEBILLE Date: Thu, 6 Jul 2023 14:22:37 +0200 Subject: [PATCH 4/4] DAC: fix rollup test on unknown hash --- tezt/tests/sc_rollup.ml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tezt/tests/sc_rollup.ml b/tezt/tests/sc_rollup.ml index 32bda48be0f0..e6ef16693380 100644 --- a/tezt/tests/sc_rollup.ml +++ b/tezt/tests/sc_rollup.ml @@ -2741,6 +2741,14 @@ let test_reveals_fails_on_unknown_hash = if id =~ rex "could_not_open_reveal_preimage_file" then Some () else None) in + (* We need to check that the rollup has entered the degraded mode, + so we wait for 60 blocks (commitment period) + 2. *) + let* {commitment_period_in_blocks; _} = get_sc_rollup_constants client in + let* () = + repeat (commitment_period_in_blocks + 2) (fun () -> + Client.bake_for_and_wait client) + in + (* Then, we finally send the message with the unknown hash. *) let* () = send_text_messages client ["hash:" ^ unknown_hash] in let should_not_sync = let* _level = -- GitLab