From a5b5595c53ec4e74e00cad7eea8d297bff44040d Mon Sep 17 00:00:00 2001 From: Andrea Cerone Date: Wed, 9 Nov 2022 13:40:09 +0000 Subject: [PATCH 1/6] Proto: expose sc_rollup_message_size_limit in Alpha_context Co-authored-by: Martin Tomazic --- src/proto_alpha/lib_protocol/alpha_context.mli | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 6304cbea30a2..443669ba345b 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -774,6 +774,8 @@ module Constants : sig val michelson_maximum_type_size : int + val sc_rollup_message_size_limit : int + (** Constants parameterized by context. See {!Constants_parametric_repr}. *) module Parametric : sig type dal = { -- GitLab From 6279becd6c9e8f789e747fa2022677db08c2995d Mon Sep 17 00:00:00 2001 From: Andrea Cerone Date: Wed, 9 Nov 2022 13:42:19 +0000 Subject: [PATCH 2/6] Dac/Dal_node_plugin: improve Dac_pages_encoding Co-authored-by: Martin Tomazic --- src/proto_alpha/lib_dal/dac_pages_encoding.ml | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/src/proto_alpha/lib_dal/dac_pages_encoding.ml b/src/proto_alpha/lib_dal/dac_pages_encoding.ml index 1bad16d12dd9..1549fd792385 100644 --- a/src/proto_alpha/lib_dal/dac_pages_encoding.ml +++ b/src/proto_alpha/lib_dal/dac_pages_encoding.ml @@ -162,6 +162,8 @@ module Merkle_tree = struct val encoding : t Data_encoding.t + val to_b58check : t -> string + val hash_bytes : ?key:bytes -> bytes list -> t val size : int @@ -174,6 +176,8 @@ module Merkle_tree = struct let hashes_encoding = Data_encoding.list hash_encoding + let to_b58check = Hashing_scheme.to_b58check + (* The preamble of a serialized page contains 1 byte denoting the version, and 4 bytes encoding the size of the rest of the page. In total, 5 bytes. *) @@ -216,7 +220,7 @@ module Merkle_tree = struct page with | Ok raw_page -> Ok raw_page - | Error _ -> Error [Cannot_serialize_page_payload] + | Error _ -> error Cannot_serialize_page_payload let split_hashes ~max_page_size hashes = (* 1 byte for the version size, 4 bytes for the length of the list. *) @@ -228,7 +232,7 @@ module Merkle_tree = struct the number of pages at height `n-1` could be potentially equal to the number of pages at height `n`. *) if number_of_hashes < 2 then - Error [Merkle_tree_branching_factor_not_high_enough] + error Merkle_tree_branching_factor_not_high_enough else let rec go aux list = match list with @@ -243,7 +247,7 @@ module Merkle_tree = struct let open Result_syntax in (* 1 byte for the version size, 4 bytes for the size of the payload. *) let actual_page_size = max_page_size - page_preamble_size in - if actual_page_size <= 0 then Error [Non_positive_size_of_payload] + if actual_page_size <= 0 then error Non_positive_size_of_payload else let+ pages = String.chunk_bytes actual_page_size page in List.map String.to_bytes pages @@ -287,18 +291,30 @@ module Merkle_tree = struct preamble of 5 bytes followed by a page payload - a raw sequence of bytes from the original payload for Contents pages, and a a sequence of serialized hashes for hashes pages. The preamble - bytes is part of the sequence of bytes which is hashed. *) + bytes is part of the sequence of bytes which is hashed. + + Hashes are stored in reverse order in memory for performance + reasons. They are reversed again before the recursive tailcall + is performed.*) let hashes_with_serialized_pages = - List.map - (fun serialized_page -> (hash serialized_page, serialized_page)) - serialized_pages + List.rev_map (fun page -> (hash page, page)) serialized_pages + in + + let* () = + List.iter_es + (fun (hash, page) -> for_each_page (hash, page)) + hashes_with_serialized_pages in - let* () = List.iter_es for_each_page hashes_with_serialized_pages in match hashes_with_serialized_pages with | [(hash, _page)] -> return hash | hashes_with_raw_pages -> - let hashes = List.map fst hashes_with_raw_pages in + let hashes = + (* Hashes_with_raw_pages stores the hash of pages in reverse + order. We use `List.rev_map` to recover the original order + of hashes. *) + List.rev_map (fun (hash, _page) -> hash) hashes_with_raw_pages + in (go [@tailcall]) (Hashes hashes) in go (Contents payload) @@ -308,7 +324,7 @@ module Merkle_tree = struct let deserialize_page raw_page = match Data_encoding.Binary.of_bytes page_encoding raw_page with | Ok page -> Ok page - | Error _ -> Error [Cannot_deserialize_page] + | Error _ -> error Cannot_deserialize_page (** Deserialization function for reconstructing the original payload from its Merkle tree root hash. The function [retrieve_page_from_hash] @@ -347,7 +363,6 @@ module Merkle_tree = struct their original order. *) (go [@tailcall]) hashes (contents :: retrieved_contents)) in - go [root_hash] [] end -- GitLab From d8b90a3702651668b18d5f9da72c91f68453b820 Mon Sep 17 00:00:00 2001 From: Andrea Cerone Date: Wed, 9 Nov 2022 13:43:37 +0000 Subject: [PATCH 3/6] Dac/Dal_node_plugin: RPC server for plugin Co-authored-by: Martin Tomazic --- src/lib_dal_node/dal_plugin.ml | 4 ++ src/lib_dal_node/dal_plugin.mli | 4 ++ src/proto_alpha/lib_dal/RPC.ml | 61 +++++++++++++++++++ .../lib_dal/dal_plugin_registration.ml | 2 + 4 files changed, 71 insertions(+) create mode 100644 src/proto_alpha/lib_dal/RPC.ml diff --git a/src/lib_dal_node/dal_plugin.ml b/src/lib_dal_node/dal_plugin.ml index 750cedd3290c..5554e4282c45 100644 --- a/src/lib_dal_node/dal_plugin.ml +++ b/src/lib_dal_node/dal_plugin.ml @@ -36,6 +36,10 @@ module type T = sig Tezos_shell_services.Block_services.block -> Client_context.full -> (int * Tezos_crypto_dal.Cryptobox.Verifier.commitment) list tzresult Lwt.t + + module RPC : sig + val rpc_services : unit RPC_directory.directory + end end let table : (module T) Protocol_hash.Table.t = Protocol_hash.Table.create 5 diff --git a/src/lib_dal_node/dal_plugin.mli b/src/lib_dal_node/dal_plugin.mli index eee5de9b3cf5..9c34817adb06 100644 --- a/src/lib_dal_node/dal_plugin.mli +++ b/src/lib_dal_node/dal_plugin.mli @@ -36,6 +36,10 @@ module type T = sig Tezos_shell_services.Block_services.block -> Client_context.full -> (int * Tezos_crypto_dal.Cryptobox.Verifier.commitment) list tzresult Lwt.t + + module RPC : sig + val rpc_services : unit RPC_directory.directory + end end val register : (module T) -> unit diff --git a/src/proto_alpha/lib_dal/RPC.ml b/src/proto_alpha/lib_dal/RPC.ml new file mode 100644 index 000000000000..b495ff2d4cc1 --- /dev/null +++ b/src/proto_alpha/lib_dal/RPC.ml @@ -0,0 +1,61 @@ +open Environment + +type Error_monad.error += Cannot_serialize_page_payload + +let () = + Error_monad.register_error_kind + `Permanent + ~id:"cannot_serialize_dac_page" + ~title:"DAC page could not be serialized" + ~description:"Error when serializing DAC page" + ~pp:(fun ppf () -> Format.fprintf ppf "Error when serializing DAC page") + Data_encoding.unit + (function Cannot_serialize_page_payload -> Some () | _ -> None) + (fun () -> Cannot_serialize_page_payload) + +let map_proto_error (res : 'a tzresult Lwt.t) (error : Error_monad.error) : + ('a, Error_monad.error Error_monad.trace) result Lwt.t = + let open Lwt_result_syntax in + let*! res = res in + match res with + | Ok res -> Error_monad.return res + | Error _ -> Error_monad.fail error + +module Registration = struct + let register0_noctxt ~chunked s f dir = + RPC_directory.register ~chunked dir s (fun _rpc_ctxt q i -> f q i) +end + +module DAC = struct + module Hashing_scheme = Dac_pages_encoding.Merkle_tree.V0 + + module S = struct + let dac_store_preimage = + RPC_service.put_service + ~description:"Split DAC reveal data" + ~query:RPC_query.empty + ~input:Data_encoding.bytes + ~output:Hashing_scheme.hash_encoding + RPC_path.(open_root / "dac" / "store_preimage") + end + + let handle_serialize_dac_store_preimage data = + let for_each_page _ = return () in + let size = Protocol.Alpha_context.Constants.sc_rollup_message_size_limit in + Hashing_scheme.serialize_payload ~max_page_size:size data ~for_each_page + + let register_serialize_dac_store_preimage = + Registration.register0_noctxt + ~chunked:false + S.dac_store_preimage + (fun () input -> + map_proto_error + (handle_serialize_dac_store_preimage input) + Cannot_serialize_page_payload) + + let register () = + (RPC_directory.empty : unit RPC_directory.t) + |> register_serialize_dac_store_preimage +end + +let rpc_services = DAC.register () diff --git a/src/proto_alpha/lib_dal/dal_plugin_registration.ml b/src/proto_alpha/lib_dal/dal_plugin_registration.ml index cc3589bd2f76..79a5d66ef6d4 100644 --- a/src/proto_alpha/lib_dal/dal_plugin_registration.ml +++ b/src/proto_alpha/lib_dal/dal_plugin_registration.ml @@ -55,6 +55,8 @@ module Plugin = struct return ( Dal.Slot_index.to_int slot.Dal.Slot.Header.id.index, slot.Dal.Slot.Header.commitment )) + + module RPC = RPC end let () = Dal_plugin.register (module Plugin) -- GitLab From fb25b0130e903c9053c2de059961451bcf104db3 Mon Sep 17 00:00:00 2001 From: Andrea Cerone Date: Wed, 9 Nov 2022 13:45:37 +0000 Subject: [PATCH 4/6] Dac/Dal node: merge plugin RPC directory Co-authored-by: Martin Tomazic --- src/bin_dal_node/RPC_server.ml | 2 ++ src/bin_dal_node/daemon.ml | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/bin_dal_node/RPC_server.ml b/src/bin_dal_node/RPC_server.ml index ce6bff0f3e18..7576a8ab88ef 100644 --- a/src/bin_dal_node/RPC_server.ml +++ b/src/bin_dal_node/RPC_server.ml @@ -131,6 +131,8 @@ let register ctxt = |> register_show_slot_pages ctxt |> register_monitor_slot_headers ctxt +let merge dir plugin_dir = RPC_directory.merge dir plugin_dir + let start configuration dir = let open Lwt_syntax in let Configuration.{rpc_addr; rpc_port; _} = configuration in diff --git a/src/bin_dal_node/daemon.ml b/src/bin_dal_node/daemon.ml index 4dbaf55df1e4..18781592309d 100644 --- a/src/bin_dal_node/daemon.ml +++ b/src/bin_dal_node/daemon.ml @@ -112,6 +112,18 @@ module Handler = struct let* dal_constants, dal_parameters = init_cryptobox config.Configuration.use_unsafe_srs cctxt plugin in + let dir = RPC_server.register ctxt in + let plugin_prefix = RPC_path.(open_root / "plugin") in + let plugin_dir = + RPC_directory.prefix plugin_prefix Plugin.RPC.rpc_services + in + let dir_with_plugin = RPC_server.merge dir plugin_dir in + let* rpc_server = RPC_server.(start config dir_with_plugin) in + let _ = RPC_server.install_finalizer rpc_server in + let*! () = + Event.( + emit rpc_server_is_ready (config.rpc_addr, config.rpc_port)) + in Node_context.set_ready ctxt (module Plugin) @@ -209,9 +221,4 @@ let run ~data_dir cctxt = let config = {config with data_dir} in let*! store = Store.init config in let ctxt = Node_context.init config store in - let* rpc_server = RPC_server.(start config (register ctxt)) in - let _ = RPC_server.install_finalizer rpc_server in - let*! () = - Event.(emit rpc_server_is_ready (config.rpc_addr, config.rpc_port)) - in daemonize (Handler.new_head config ctxt cctxt :: Handler.new_slot_header ctxt) -- GitLab From 3d2d9c6dbeaba225c2049b3b20f578f44c278e89 Mon Sep 17 00:00:00 2001 From: Andrea Cerone Date: Wed, 9 Nov 2022 13:46:44 +0000 Subject: [PATCH 5/6] Dac/Tezt: support to send dac preimage to dal node Co-authored-by: Martin Tomazic --- tezt/lib_tezos/rollup.ml | 9 +++++++++ tezt/lib_tezos/rollup.mli | 3 +++ 2 files changed, 12 insertions(+) diff --git a/tezt/lib_tezos/rollup.ml b/tezt/lib_tezos/rollup.ml index bc0ec7b5bbd4..b90470271bd7 100644 --- a/tezt/lib_tezos/rollup.ml +++ b/tezt/lib_tezos/rollup.ml @@ -592,6 +592,15 @@ module Dal = struct let shard ~slot_header ~shard_id = make GET ["shard"; slot_header; string_of_int shard_id] @@ fun json -> json |> JSON.encode + + let dac_store_preimage preimage = + let preimage = + JSON.parse + ~origin:"dal_node_dac_store_preimage_rpc" + (encode_bytes_to_hex_string preimage) + in + let data = JSON.unannotate preimage in + make ~data PUT ["plugin"; "dac"; "store_preimage"] JSON.as_string end module Cryptobox = Tezos_crypto_dal.Cryptobox diff --git a/tezt/lib_tezos/rollup.mli b/tezt/lib_tezos/rollup.mli index 602c9bfc5b9b..80ae89250df1 100644 --- a/tezt/lib_tezos/rollup.mli +++ b/tezt/lib_tezos/rollup.mli @@ -253,6 +253,9 @@ module Dal : sig a given slot header and shard id *) val shard : slot_header:string -> shard_id:int -> (Dal_node.t, string) RPC_core.t + + (** [dac_store_preimage data] posts [data] on dac/store_preimage *) + val dac_store_preimage : string -> (Dal_node.t, string) RPC_core.t end module Cryptobox = Tezos_crypto_dal.Cryptobox -- GitLab From 5e3bb5f11dda90eb111e69d2e426564426d540df Mon Sep 17 00:00:00 2001 From: Andrea Cerone Date: Wed, 9 Nov 2022 13:47:39 +0000 Subject: [PATCH 6/6] Dac/Tezt: test store preimage endpoint Co-authored-by: Martin Tomazic --- tezt/tests/dal.ml | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/tezt/tests/dal.ml b/tezt/tests/dal.ml index 48447651d9fa..7a73b1d89f6d 100644 --- a/tezt/tests/dal.ml +++ b/tezt/tests/dal.ml @@ -1111,6 +1111,29 @@ let rollup_node_interprets_dal_pages client sc_rollup sc_rollup_node = "Invalid value in rollup state (current = %L, expected = %R)") ; return () +(* DAC tests *) +let test_dal_node_handles_dac_store_preimage = + Protocol.register_test + ~__FILE__ + ~title:"dal node handles dac store preimage" + ~tags:["dac"; "dal_node"] + ~supports:Protocol.(From_protocol (Protocol.number Alpha)) + @@ fun protocol -> + let* _node, _client, dal_node = init_dal_node protocol in + let preimage = "test" in + let* actual_rh = + RPC.call dal_node (Rollup.Dal.RPC.dac_store_preimage preimage) + in + (* Expected reveal hash equals to the result of + [Tezos_dal_alpha.Dac_pages_encoding.Merkle_tree.V0.serialize_payload "test"]. + *) + let expected_rh = "scrrh1Y5hijnFNJPb96EFTY9SjZ4epyaYF9xU3Eid9KCj9vda25H8W" in + Check.( + (actual_rh = expected_rh) + string + ~error_msg:"Invalid root hash returned (Current:%L <> Expected: %R)") ; + return () + let register ~protocols = test_dal_scenario "feature_flag_is_disabled" test_feature_flag protocols ; test_slot_management_logic protocols ; @@ -1129,4 +1152,5 @@ let register ~protocols = "rollup_node_applies_dal_pages" (rollup_node_stores_dal_slots ~expand_test:rollup_node_interprets_dal_pages) protocols ; - test_slots_attestation_operation_behavior protocols + test_slots_attestation_operation_behavior protocols ; + test_dal_node_handles_dac_store_preimage protocols -- GitLab