From bea468c8a51d29b6ec2c3e7ec5ba8d9f397d9611 Mon Sep 17 00:00:00 2001 From: Luciano Freitas Date: Wed, 26 Feb 2025 16:56:53 +0100 Subject: [PATCH 1/7] EVM Node: add feature_flag paths to durable storage --- etherlink/bin_node/lib_dev/durable_storage_path.ml | 6 ++++++ etherlink/bin_node/lib_dev/durable_storage_path.mli | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/etherlink/bin_node/lib_dev/durable_storage_path.ml b/etherlink/bin_node/lib_dev/durable_storage_path.ml index f3cbe1d47375..0e20eb38124b 100644 --- a/etherlink/bin_node/lib_dev/durable_storage_path.ml +++ b/etherlink/bin_node/lib_dev/durable_storage_path.ml @@ -242,3 +242,9 @@ module Chain_configuration = struct let world_state chain_id = root chain_id ^ "/world_state" end + +module Feature_flags = struct + let root = EVM.make "/feature_flags" + + let multichain = root ^ "/enable_multichain" +end diff --git a/etherlink/bin_node/lib_dev/durable_storage_path.mli b/etherlink/bin_node/lib_dev/durable_storage_path.mli index 70efeb8735cf..43d17fabefae 100644 --- a/etherlink/bin_node/lib_dev/durable_storage_path.mli +++ b/etherlink/bin_node/lib_dev/durable_storage_path.mli @@ -172,3 +172,7 @@ module Chain_configuration : sig val world_state : Ethereum_types.chain_id -> path end + +module Feature_flags : sig + val multichain : path +end -- GitLab From fe1c6cd72bd598436e93029dc901ec09a2d1715b Mon Sep 17 00:00:00 2001 From: Luciano Freitas Date: Wed, 26 Feb 2025 17:26:33 +0100 Subject: [PATCH 2/7] EVM Node: add reader to enable_multichain in durable storage Co-authored-by: Pierre-Emmanuel CORNILLEAU --- etherlink/bin_node/lib_dev/durable_storage.ml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/etherlink/bin_node/lib_dev/durable_storage.ml b/etherlink/bin_node/lib_dev/durable_storage.ml index 0409574ae0be..122cfeaa2e38 100644 --- a/etherlink/bin_node/lib_dev/durable_storage.ml +++ b/etherlink/bin_node/lib_dev/durable_storage.ml @@ -334,6 +334,11 @@ let kernel_root_hash read = Durable_storage_path.kernel_root_hash Bytes.to_string +let is_multichain_enabled read = + let open Lwt_result_syntax in + let* bytes_opt = read Durable_storage_path.Feature_flags.multichain in + return (Option.is_some bytes_opt) + let storage_at read address (Qty pos) = let open Lwt_result_syntax in let pad32left0 s = @@ -420,6 +425,11 @@ module Make (Reader : READER) = struct let* read = read_with_state () in chain_id read + let is_multichain_enabled () = + let open Lwt_result_syntax in + let* read = read_with_state () in + is_multichain_enabled read + let l2_minimum_base_fee_per_gas chain_id = let open Lwt_result_syntax in let* read = read_with_state () in -- GitLab From 500928a952ef12356d49990ba5321425aef0ebc2 Mon Sep 17 00:00:00 2001 From: Luciano Freitas Date: Wed, 26 Feb 2025 17:29:43 +0100 Subject: [PATCH 3/7] EVM Node: add enable_multichain reader to evm_ro_context Co-authored-by: Pierre-Emmanuel CORNILLEAU --- etherlink/bin_node/lib_dev/evm_ro_context.ml | 6 ++++++ etherlink/bin_node/lib_dev/evm_ro_context.mli | 2 ++ 2 files changed, 8 insertions(+) diff --git a/etherlink/bin_node/lib_dev/evm_ro_context.ml b/etherlink/bin_node/lib_dev/evm_ro_context.ml index 87f32e856215..c6aac2496651 100644 --- a/etherlink/bin_node/lib_dev/evm_ro_context.ml +++ b/etherlink/bin_node/lib_dev/evm_ro_context.ml @@ -36,6 +36,12 @@ let read_chain_family ctxt chain_id = let* chain_family = Durable_storage.chain_family (read evm_state) chain_id in return chain_family +let read_enable_multichain_flag ctxt = + let open Lwt_result_syntax in + let* _, hash = Evm_store.(use ctxt.store Context_hashes.get_latest) in + let* evm_state = get_evm_state ctxt hash in + Durable_storage.is_multichain_enabled (read evm_state) + let network_sanity_check ~network ctxt = let open Lwt_result_syntax in let expected_smart_rollup_address = Constants.rollup_address network in diff --git a/etherlink/bin_node/lib_dev/evm_ro_context.mli b/etherlink/bin_node/lib_dev/evm_ro_context.mli index 3a3da1965603..d41a9d3df8c4 100644 --- a/etherlink/bin_node/lib_dev/evm_ro_context.mli +++ b/etherlink/bin_node/lib_dev/evm_ro_context.mli @@ -36,6 +36,8 @@ val load : val read_chain_family : t -> Ethereum_types.chain_id -> Ethereum_types.chain_family tzresult Lwt.t +val read_enable_multichain_flag : t -> bool tzresult Lwt.t + (** [preload_known_kernels ctxt] uses [ctxt] to preload every kernel known to the node in the Fast Execution kernel cache. *) val preload_known_kernels : t -> unit tzresult Lwt.t -- GitLab From 1ee0c1809d4e881b1239599f3e9891363a32b438 Mon Sep 17 00:00:00 2001 From: Luciano Freitas Date: Thu, 27 Feb 2025 14:48:07 +0100 Subject: [PATCH 4/7] EVM Node: add backend service to read enable_multichain --- etherlink/bin_node/lib_dev/services_backend_sig.ml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/etherlink/bin_node/lib_dev/services_backend_sig.ml b/etherlink/bin_node/lib_dev/services_backend_sig.ml index a69faca1e48b..b14e0fe20d47 100644 --- a/etherlink/bin_node/lib_dev/services_backend_sig.ml +++ b/etherlink/bin_node/lib_dev/services_backend_sig.ml @@ -99,6 +99,11 @@ module type S = sig or the zero address. *) val coinbase : unit -> Ethereum_types.address tzresult Lwt.t + (** [is_multichain_enabled ()] returns the value of the multichain feature flag + this method targets proxy nodes that do not have direct access + to the durable storage. *) + val is_multichain_enabled : unit -> bool tzresult Lwt.t + include Tracer_sig.S end -- GitLab From 326e5cfc8e94b35079b96d772c17d3e3fe645d91 Mon Sep 17 00:00:00 2001 From: Luciano Freitas Date: Tue, 11 Mar 2025 13:53:16 +0100 Subject: [PATCH 5/7] EVM Node: define errors for mismatched multichain and finalized-proxy multichain --- etherlink/bin_node/lib_dev/node_error.ml | 55 +++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/etherlink/bin_node/lib_dev/node_error.ml b/etherlink/bin_node/lib_dev/node_error.ml index f98116ef32fd..eeb7f90af07b 100644 --- a/etherlink/bin_node/lib_dev/node_error.ml +++ b/etherlink/bin_node/lib_dev/node_error.ml @@ -11,6 +11,16 @@ let exit_code_when_out_of_sync = 101 let exit_code_when_flushed_blueprint = 102 +type error_source = [`Node | `Kernel] + +let error_source_encoding = + let open Data_encoding in + string_enum [("node", `Node); ("kernel", `Kernel)] + +let pp_proxy_finalize_multichain_source fmt = function + | `Node -> Format.fprintf fmt "Node" + | `Kernel -> Format.fprintf fmt "Kernel" + type error += | Diverged of { level : Z.t; @@ -21,6 +31,8 @@ type error += | Out_of_sync of {level_expected : int32; level_received : int32} | Cannot_handle_flushed_blueprint of Ethereum_types.quantity | Unexpected_multichain + | Proxy_finalize_with_multichain of error_source + | Mismatched_multichain of error_source let () = register_error_kind @@ -95,4 +107,45 @@ let () = configuration attempted to configure multiple chains." Data_encoding.empty (function Unexpected_multichain -> Some () | _ -> None) - (fun () -> Unexpected_multichain) + (fun () -> Unexpected_multichain) ; + register_error_kind + `Permanent + ~id:"proxy_finalize_with_multichain" + ~title:"Proxy node finalized_view with multichain" + ~description: + "The proxy node with the finalized_view option is incompatible with the \ + multichain features (originating from either the Node or the Kernel)." + ~pp:(fun ppf source -> + Format.fprintf + ppf + "The %a was configured in multichain mode, which is incompatible with \ + the proxy node's finalized_view option." + pp_proxy_finalize_multichain_source + source) + Data_encoding.(obj1 (req "source" error_source_encoding)) + (function Proxy_finalize_with_multichain src -> Some src | _ -> None) + (fun src -> Proxy_finalize_with_multichain src) ; + register_error_kind + `Permanent + ~id:"mismatched_multichain" + ~title:"Node and Kernel multichain configuration mismatch" + ~description: + "Node and Kernel configurations are mismatched in their multichain \ + settings." + ~pp:(fun ppf source -> + match source with + | `Node -> + Format.fprintf + ppf + "The node is configured to work in a multichain environment, while \ + the kernel is configured as to work in the single chain \ + environment." + | `Kernel -> + Format.fprintf + ppf + "The kernel is configured to work in a multichain environment, \ + while the node is configured as to work in the single chain \ + environment.") + Data_encoding.(obj1 (req "source" error_source_encoding)) + (function Mismatched_multichain source -> Some source | _ -> None) + (fun source -> Mismatched_multichain source) -- GitLab From 4088736060c9242412a16d85be2828c3142cef3e Mon Sep 17 00:00:00 2001 From: Luciano Freitas Date: Tue, 11 Mar 2025 13:52:58 +0100 Subject: [PATCH 6/7] EVM Node: read enable_multichain feature flag on startup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Raphaƫl Cauderlier --- etherlink/bin_node/lib_dev/observer.ml | 10 +++++++--- etherlink/bin_node/lib_dev/proxy.ml | 26 ++++++++++++++++++++----- etherlink/bin_node/lib_dev/rpc.ml | 11 ++++++++--- etherlink/bin_node/lib_dev/sequencer.ml | 10 ++++++++++ 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/etherlink/bin_node/lib_dev/observer.ml b/etherlink/bin_node/lib_dev/observer.ml index 05b181c9887a..2179d9875cc4 100644 --- a/etherlink/bin_node/lib_dev/observer.ml +++ b/etherlink/bin_node/lib_dev/observer.ml @@ -188,10 +188,14 @@ let main ?network ?kernel_path ~data_dir ~(config : Configuration.t) ~no_sync ~tx_pool_size_info:Tx_pool.size_info ~smart_rollup_address ; + let* enable_multichain = Evm_ro_context.read_enable_multichain_flag ro_ctxt in + let* (_chain_family : Ethereum_types.chain_family) = - match config.experimental_features.l2_chains with - | None -> return EVM - | Some [l2_chain] -> + match (config.experimental_features.l2_chains, enable_multichain) with + | None, false -> return EVM + | None, true -> tzfail (Node_error.Mismatched_multichain `Kernel) + | Some [_], false -> tzfail (Node_error.Mismatched_multichain `Node) + | Some [l2_chain], true -> Evm_ro_context.read_chain_family ro_ctxt l2_chain.chain_id | _ -> tzfail Node_error.Unexpected_multichain in diff --git a/etherlink/bin_node/lib_dev/proxy.ml b/etherlink/bin_node/lib_dev/proxy.ml index 854875325595..9dc644612b5c 100644 --- a/etherlink/bin_node/lib_dev/proxy.ml +++ b/etherlink/bin_node/lib_dev/proxy.ml @@ -97,11 +97,22 @@ let main () in let* (_chain_family : Ethereum_types.chain_family) = - if finalized_view then return Ethereum_types.EVM + if finalized_view then + if + (* When finalized_view is set, it's too early to request the + feature flag from the rollup node. *) + Option.is_some config.experimental_features.l2_chains + then + (* The finalized view of the proxy mode and the multichain feature are not compatible. *) + tzfail (Node_error.Proxy_finalize_with_multichain `Node) + else return Ethereum_types.EVM else - match config.experimental_features.l2_chains with - | None -> return Ethereum_types.EVM - | Some [l2_chain] -> Rollup_node_rpc.chain_family l2_chain.chain_id + let* enable_multichain = Rollup_node_rpc.is_multichain_enabled () in + match (config.experimental_features.l2_chains, enable_multichain) with + | None, false -> return Ethereum_types.EVM + | None, true -> tzfail (Node_error.Mismatched_multichain `Kernel) + | Some [_], false -> tzfail (Node_error.Mismatched_multichain `Node) + | Some [l2_chain], true -> Rollup_node_rpc.chain_family l2_chain.chain_id | _ -> tzfail Node_error.Unexpected_multichain in let* server_finalizer = @@ -115,4 +126,9 @@ let main in let wait, _resolve = Lwt.wait () in let* () = wait in - return_unit + if finalized_view then + let* enable_multichain = Rollup_node_rpc.is_multichain_enabled () in + if enable_multichain then + tzfail (Node_error.Proxy_finalize_with_multichain `Kernel) + else return_unit + else return_unit diff --git a/etherlink/bin_node/lib_dev/rpc.ml b/etherlink/bin_node/lib_dev/rpc.ml index 68a0a087329e..5fc57cd71c24 100644 --- a/etherlink/bin_node/lib_dev/rpc.ml +++ b/etherlink/bin_node/lib_dev/rpc.ml @@ -122,10 +122,15 @@ let main ~data_dir ~evm_node_endpoint ?evm_node_private_endpoint } in + let* enable_multichain = Evm_ro_context.read_enable_multichain_flag ctxt in + let* (_chain_family : Ethereum_types.chain_family) = - match config.experimental_features.l2_chains with - | None -> return Ethereum_types.EVM - | Some [l2_chain] -> Evm_ro_context.read_chain_family ctxt l2_chain.chain_id + match (config.experimental_features.l2_chains, enable_multichain) with + | None, false -> return Ethereum_types.EVM + | None, true -> tzfail (Node_error.Mismatched_multichain `Kernel) + | Some [l2_chain], true -> + Evm_ro_context.read_chain_family ctxt l2_chain.chain_id + | Some [_], false -> tzfail (Node_error.Mismatched_multichain `Node) | _ -> tzfail Node_error.Unexpected_multichain in diff --git a/etherlink/bin_node/lib_dev/sequencer.ml b/etherlink/bin_node/lib_dev/sequencer.ml index 631cdaf8c389..c7b07d9b7e89 100644 --- a/etherlink/bin_node/lib_dev/sequencer.ml +++ b/etherlink/bin_node/lib_dev/sequencer.ml @@ -242,6 +242,16 @@ let main ~data_dir ?(genesis_timestamp = Misc.now ()) ~cctxt in return_unit in + let* enable_multichain = Evm_ro_context.read_enable_multichain_flag ro_ctxt in + let* () = + match + (configuration.experimental_features.l2_chains, enable_multichain) + with + | None, false -> return_unit + | None, true -> tzfail (Node_error.Mismatched_multichain `Kernel) + | Some _, true -> return_unit + | Some _, false -> tzfail (Node_error.Mismatched_multichain `Node) + in let* finalizer_public_server = Rpc_server.start_public_server ~evm_services: -- GitLab From 7a147f529f141b880fa582c077aac6414cbfe7ee Mon Sep 17 00:00:00 2001 From: Luciano Freitas Date: Mon, 10 Mar 2025 15:50:35 +0100 Subject: [PATCH 7/7] EVM Node: add docstrings to read multichain and chain_family --- etherlink/bin_node/lib_dev/evm_ro_context.mli | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/etherlink/bin_node/lib_dev/evm_ro_context.mli b/etherlink/bin_node/lib_dev/evm_ro_context.mli index d41a9d3df8c4..f491b0edd787 100644 --- a/etherlink/bin_node/lib_dev/evm_ro_context.mli +++ b/etherlink/bin_node/lib_dev/evm_ro_context.mli @@ -33,9 +33,13 @@ val load : Configuration.t -> t tzresult Lwt.t +(** [read_chain_family chain_id] returns the chain_family associated to the + chain_id passed on parameter. *) val read_chain_family : t -> Ethereum_types.chain_id -> Ethereum_types.chain_family tzresult Lwt.t +(** [read_enable_multichain_flag] reads the value of the `enable_multichain` + feature_flag that enables multichain and tezos compatibility on the l2_node. *) val read_enable_multichain_flag : t -> bool tzresult Lwt.t (** [preload_known_kernels ctxt] uses [ctxt] to preload every kernel known to -- GitLab