From e3dc1f34cbf9472f2c2ba8218a9e9a9ab7d71ded Mon Sep 17 00:00:00 2001 From: Pierrick Couderc Date: Tue, 13 Aug 2024 13:55:58 +0200 Subject: [PATCH 1/3] EVM/Node: simple check of the downloaded preimage --- etherlink/bin_node/lib_dev/kernel_download.ml | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/etherlink/bin_node/lib_dev/kernel_download.ml b/etherlink/bin_node/lib_dev/kernel_download.ml index d5bf6806283d..a1c687cabefe 100644 --- a/etherlink/bin_node/lib_dev/kernel_download.ml +++ b/etherlink/bin_node/lib_dev/kernel_download.ml @@ -5,6 +5,28 @@ (* *) (*****************************************************************************) +module Reveal_hash = Tezos_raw_protocol_alpha.Sc_rollup_reveal_hash + +type error += Invalid_preimage_for_hash of Hex.t * string + +let () = + register_error_kind + `Permanent + ~id:"evm_node_dev_invalid_preimage" + ~title:"Preimage has not the expected hash" + ~description: + "The EVM node could not apply a blueprint on top of its local EVM state." + ~pp:(fun ppf (hash, _preimage) -> + Format.fprintf + ppf + "The preimage received for %s doesn't return the same hash" + hash) + Data_encoding.(obj2 (req "expected_hash" string) (req "preimage" string)) + (function + | Invalid_preimage_for_hash (`Hex hash, preimage) -> Some (hash, preimage) + | _ -> None) + (fun (hash, preimage) -> Invalid_preimage_for_hash (`Hex hash, preimage)) + type preimages = Contents of bytes | Hashes of string list let preimages_encoding = @@ -21,15 +43,18 @@ let preimages_encoding = case ~title:"hashes" (Tag 1) - (list Tezos_raw_protocol_alpha.Sc_rollup_reveal_hash.encoding) + (list Reveal_hash.encoding) (function Hashes _hashes -> assert false | _ -> None) - (fun hashes -> - Hashes - (List.map - Tezos_raw_protocol_alpha.Sc_rollup_reveal_hash.to_hex - hashes)); + (fun hashes -> Hashes (List.map Reveal_hash.to_hex hashes)); ]) +let check_preimage (`Hex hash) preimage = + let computed_hash = + Reveal_hash.hash_string ~scheme:Reveal_hash.Blake2B [preimage] + |> Reveal_hash.to_hex + in + hash = computed_hash + let download ~preimages_endpoint ~preimages ~(root_hash : Hex.t) = let open Lwt_result_syntax in (* value found in `commands.ml`, should we make it configurable? *) @@ -46,6 +71,11 @@ let download ~preimages_endpoint ~preimages ~(root_hash : Hex.t) = num_retries hash in + let* () = + if not (check_preimage hash preimage) then + tzfail (Invalid_preimage_for_hash (hash, preimage)) + else return_unit + in match Data_encoding.Binary.of_string_exn preimages_encoding preimage with -- GitLab From 84b788dc8f6a24047e68f78f2c04b6a7dc8ef4d8 Mon Sep 17 00:00:00 2001 From: Pierrick Couderc Date: Tue, 13 Aug 2024 14:01:09 +0200 Subject: [PATCH 2/3] EVM/Node: download again if preimage is wrong This can prevent corrupted data. --- etherlink/bin_node/lib_dev/kernel_download.ml | 41 ++++++++++++++----- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/etherlink/bin_node/lib_dev/kernel_download.ml b/etherlink/bin_node/lib_dev/kernel_download.ml index a1c687cabefe..22547b5b53aa 100644 --- a/etherlink/bin_node/lib_dev/kernel_download.ml +++ b/etherlink/bin_node/lib_dev/kernel_download.ml @@ -55,27 +55,48 @@ let check_preimage (`Hex hash) preimage = in hash = computed_hash +let delete_preimage preimages (`Hex hash) = + Lwt_unix.unlink (Filename.concat preimages hash) + +let rec reveal_and_check ~preimages_endpoint ~preimages ~num_download_retries + hash = + let open Lwt_result_syntax in + let*! preimage = + Commands.reveal_preimage + ~preimages_endpoint + ~preimages + 0 + (* Retrying makes sense only when the preimage is fed through stdin, this + wouldn't make sense in our case. *) + hash + in + if not (check_preimage hash preimage) then + if num_download_retries <= 0 then + tzfail (Invalid_preimage_for_hash (hash, preimage)) + else + let*! () = delete_preimage preimages hash in + reveal_and_check + ~preimages_endpoint + ~preimages + ~num_download_retries:(pred num_download_retries) + hash + else return preimage + let download ~preimages_endpoint ~preimages ~(root_hash : Hex.t) = let open Lwt_result_syntax in - (* value found in `commands.ml`, should we make it configurable? *) - let num_retries = 3 in + let num_download_retries = 1 in let rec go retrieved_hashes = let open Lwt_result_syntax in match retrieved_hashes with | [] -> return_unit | hash :: hashes -> ( - let*! preimage = - Commands.reveal_preimage + let* preimage = + reveal_and_check ~preimages_endpoint ~preimages - num_retries + ~num_download_retries hash in - let* () = - if not (check_preimage hash preimage) then - tzfail (Invalid_preimage_for_hash (hash, preimage)) - else return_unit - in match Data_encoding.Binary.of_string_exn preimages_encoding preimage with -- GitLab From 0c91de0c13eaddad3414fc322ea96be4e469c312 Mon Sep 17 00:00:00 2001 From: Pierrick Couderc Date: Tue, 13 Aug 2024 14:21:27 +0200 Subject: [PATCH 3/3] EVM/Node: download: configure the number of retry --- etherlink/bin_node/lib_dev/kernel_download.ml | 4 ++-- .../bin_node/lib_dev/kernel_download.mli | 2 ++ etherlink/bin_node/main.ml | 24 ++++++++++++++++--- .../evm_sequencer.ml/EVM Node- man.out | 3 ++- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/etherlink/bin_node/lib_dev/kernel_download.ml b/etherlink/bin_node/lib_dev/kernel_download.ml index 22547b5b53aa..09ef181bce21 100644 --- a/etherlink/bin_node/lib_dev/kernel_download.ml +++ b/etherlink/bin_node/lib_dev/kernel_download.ml @@ -82,9 +82,9 @@ let rec reveal_and_check ~preimages_endpoint ~preimages ~num_download_retries hash else return preimage -let download ~preimages_endpoint ~preimages ~(root_hash : Hex.t) = +let download ~preimages_endpoint ~preimages ~(root_hash : Hex.t) + ?(num_download_retries = 1) () = let open Lwt_result_syntax in - let num_download_retries = 1 in let rec go retrieved_hashes = let open Lwt_result_syntax in match retrieved_hashes with diff --git a/etherlink/bin_node/lib_dev/kernel_download.mli b/etherlink/bin_node/lib_dev/kernel_download.mli index edd213d7e8c7..c18741c41b3e 100644 --- a/etherlink/bin_node/lib_dev/kernel_download.mli +++ b/etherlink/bin_node/lib_dev/kernel_download.mli @@ -9,4 +9,6 @@ val download : preimages_endpoint:Uri.t -> preimages:string -> root_hash:Hex.t -> + ?num_download_retries:int -> + unit -> unit tzresult Lwt.t diff --git a/etherlink/bin_node/main.ml b/etherlink/bin_node/main.ml index 13639653e689..a74feb99ec1b 100644 --- a/etherlink/bin_node/main.ml +++ b/etherlink/bin_node/main.ml @@ -579,6 +579,16 @@ let dal_slots_arg = s |> String.split ',' |> List.map int_of_string |> Lwt_result_syntax.return)) +let num_download_retries = + Tezos_clic.arg + ~doc: + "Number of times a revealed preimage can be redownloaded in case the it \ + doesn't pass the sanity check. It can be useful if the download is \ + corrupted for some reason." + ~long:"retry" + ~placeholder:"1" + Params.int + let common_config_args = Tezos_clic.args18 data_dir_arg @@ -2168,7 +2178,11 @@ let preemptive_kernel_download_command = let open Tezos_clic in command ~desc:"Transforms the JSON list of instructions to a RLP list" - (args3 data_dir_arg preimages_arg preimages_endpoint_arg) + (args4 + data_dir_arg + preimages_arg + preimages_endpoint_arg + num_download_retries) (prefixes ["download"; "kernel"; "with"; "root"; "hash"] @@ param ~name:"root hash" @@ -2176,7 +2190,9 @@ let preemptive_kernel_download_command = (Tezos_clic.parameter (fun _ str -> Lwt_result_syntax.return @@ `Hex str)) @@ stop) - (fun (data_dir, preimages, preimages_endpoint) root_hash () -> + (fun (data_dir, preimages, preimages_endpoint, num_download_retries) + root_hash + () -> let open Lwt_result_syntax in let* configuration = Cli.create_or_read_config @@ -2199,9 +2215,11 @@ let preemptive_kernel_download_command = in let*! () = Lwt_utils_unix.create_dir preimages in Evm_node_lib_dev.Kernel_download.download + ~root_hash ~preimages ~preimages_endpoint - ~root_hash) + ?num_download_retries + ()) let debug_print_store_schemas_command = let open Tezos_clic in diff --git a/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- man.out b/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- man.out index 3418aaaefb55..bea7e759a2e8 100644 --- a/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- man.out +++ b/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- man.out @@ -477,12 +477,13 @@ Miscellaneous commands: download kernel with root hash [--data-dir ] [--preimages-dir <_evm_installer_preimages>] - [--preimages-endpoint ] + [--preimages-endpoint ] [--retry <1>] Transforms the JSON list of instructions to a RLP list : root hash of the kernel to download --data-dir : The path to the EVM node data directory --preimages-dir <_evm_installer_preimages>: Path to the preimages directory --preimages-endpoint : The address of a service which provides pre-images for the rollup. Missing pre-images will be downloaded remotely if they are not already present on disk. + --retry <1>: Number of times a revealed preimage can be redownloaded in case the it doesn't pass the sanity check. It can be useful if the download is corrupted for some reason. debug print store schemas Print SQL statements describing the tables created in the store -- GitLab