diff --git a/etherlink/bin_node/config/configuration.ml b/etherlink/bin_node/config/configuration.ml index 4f022f6d5754a28f33dfb5cd7843ffee5b7425c8..2e13bb43f59deff8a506eb719ea6672786ccc343 100644 --- a/etherlink/bin_node/config/configuration.ml +++ b/etherlink/bin_node/config/configuration.ml @@ -116,8 +116,8 @@ type rpc = { type l2_chain = { id : L2_chain_id.t; - public_rpc : rpc; - private_rpc : rpc option; + l2_public_rpc : rpc; + l2_private_rpc : rpc option; tx_pool_timeout_limit : int64; tx_pool_addr_limit : int64; tx_pool_tx_per_addr_limit : int64; @@ -126,6 +126,8 @@ type l2_chain = { type t = { l2_chains : l2_chain list; + public_rpc : rpc; + private_rpc : rpc option; log_filter : log_filter_config; kernel_execution : kernel_execution_config; sequencer : sequencer option; @@ -178,6 +180,11 @@ let default_data_dir = Filename.concat (Sys.getenv "HOME") ".octez-evm-node" let config_filename ~data_dir = Filename.concat data_dir "config.json" +let config_l2_filename ~data_dir id = + Filename.concat + data_dir + (Format.asprintf "config_l2_%a.json" L2_chain_id.pp id) + let default_rpc_addr = "127.0.0.1" let default_rpc_port = 8545 @@ -1137,8 +1144,8 @@ let l2_chain_encoding : l2_chain Data_encoding.t = conv (fun { id; - public_rpc; - private_rpc; + l2_public_rpc; + l2_private_rpc; tx_pool_timeout_limit; tx_pool_addr_limit; tx_pool_tx_per_addr_limit; @@ -1149,19 +1156,19 @@ let l2_chain_encoding : l2_chain Data_encoding.t = tx_pool_addr_limit, tx_pool_tx_per_addr_limit, fee_history, - public_rpc, - private_rpc )) + l2_public_rpc, + l2_private_rpc )) (fun ( id, tx_pool_timeout_limit, tx_pool_addr_limit, tx_pool_tx_per_addr_limit, fee_history, - public_rpc, - private_rpc ) -> + l2_public_rpc, + l2_private_rpc ) -> { id; - public_rpc; - private_rpc; + l2_public_rpc; + l2_private_rpc; tx_pool_timeout_limit; tx_pool_addr_limit; tx_pool_tx_per_addr_limit; @@ -1187,8 +1194,8 @@ let l2_chain_encoding : l2_chain Data_encoding.t = int64 default_tx_pool_tx_per_addr_limit) (dft "fee_history" fee_history_encoding default_fee_history) - (dft "public_rpc" rpc_encoding (default_rpc ())) - (opt "private_rpc" rpc_encoding)) + (dft "l2_public_rpc" rpc_encoding (default_rpc ())) + (opt "l2_private_rpc" rpc_encoding)) let encoding ?network data_dir : t Data_encoding.t = let open Data_encoding in @@ -1208,6 +1215,8 @@ let encoding ?network data_dir : t Data_encoding.t = conv (fun { l2_chains; + public_rpc; + private_rpc; log_filter; sequencer; threshold_encryption_sequencer; @@ -1221,29 +1230,31 @@ let encoding ?network data_dir : t Data_encoding.t = finalized_view; } -> ( ( l2_chains, + public_rpc, + private_rpc, log_filter, sequencer, threshold_encryption_sequencer, observer, keep_alive, rollup_node_endpoint, - verbose, - experimental_features, - proxy ), - (kernel_execution, finalized_view) )) + verbose ), + (experimental_features, proxy, kernel_execution, finalized_view) )) (fun ( ( l2_chains, + public_rpc, + private_rpc, log_filter, sequencer, threshold_encryption_sequencer, observer, keep_alive, rollup_node_endpoint, - verbose, - experimental_features, - proxy ), - (kernel_execution, finalized_view) ) -> + verbose ), + (experimental_features, proxy, kernel_execution, finalized_view) ) -> { l2_chains; + public_rpc; + private_rpc; log_filter; sequencer; threshold_encryption_sequencer; @@ -1259,6 +1270,8 @@ let encoding ?network data_dir : t Data_encoding.t = (merge_objs (obj10 (req "l2_chains" (list l2_chain_encoding)) + (dft "public_rpc" rpc_encoding (default_rpc ())) + (opt "private_rpc" rpc_encoding) (dft "log_filter" log_filter_config_encoding @@ -1285,13 +1298,13 @@ let encoding ?network data_dir : t Data_encoding.t = blocks." Tezos_rpc.Encoding.uri_encoding default_rollup_node_endpoint) - (dft "verbose" Internal_event.Level.encoding Internal_event.Notice) + (dft "verbose" Internal_event.Level.encoding Internal_event.Notice)) + (obj4 (dft "experimental_features" experimental_features_encoding default_experimental_features) - (dft "proxy" proxy_encoding (default_proxy ()))) - (obj2 + (dft "proxy" proxy_encoding (default_proxy ())) (dft "kernel_execution" (kernel_execution_encoding ?network data_dir) @@ -1331,6 +1344,19 @@ let save ~force ~data_dir config = let*! () = Lwt_utils_unix.create_dir data_dir in Lwt_utils_unix.Json.write_file config_file json +let save_l2 ~force ~data_dir config = + let open Lwt_result_syntax in + let json = Data_encoding.Json.construct l2_chain_encoding config in + let config_file = config_l2_filename ~data_dir config.id in + let*! exists = Lwt_unix.file_exists config_file in + if exists && not force then + failwith + "Configuration file %S already exists. Use --force to overwrite." + config_file + else + let*! () = Lwt_utils_unix.create_dir data_dir in + Lwt_utils_unix.Json.write_file config_file json + module Json_syntax = struct let ( |-?> ) json field = match json with @@ -1404,6 +1430,15 @@ let load_file ?network ~data_dir path = let load ?network ~data_dir () = load_file ?network ~data_dir (config_filename ~data_dir) +let load_l2_file path = + let open Lwt_result_syntax in + let* json = Lwt_utils_unix.Json.read_file path in + let* () = precheck json in + let l2_config = Data_encoding.Json.destruct l2_chain_encoding json in + return l2_config + +let load_l2 ~data_dir id = load_l2_file (config_l2_filename ~data_dir id) + let error_missing_config ~name = [error_of_fmt "missing %s config" name] let sequencer_config_exn {sequencer; _} = @@ -1431,9 +1466,41 @@ let preimages_endpoint_resolved network preimages_endpoint = (Option.map default_preimages_endpoint network) module Cli = struct - let create ~data_dir ~l2_chain_id ?rpc_addr ?rpc_port ?rpc_batch_limit - ?cors_origins ?cors_headers ?tx_pool_timeout_limit ?tx_pool_addr_limit - ?tx_pool_tx_per_addr_limit ~keep_alive ?rollup_node_endpoint + let create_l2 ~l2_chain_id ?rpc_addr ?rpc_port ?tx_pool_timeout_limit + ?restricted_rpcs ?rpc_batch_limit ?cors_origins ?cors_headers + ?tx_pool_addr_limit ?tx_pool_tx_per_addr_limit ?private_rpc_port () = + let l2_public_rpc = + default_rpc + ?rpc_port + ?rpc_addr + ?batch_limit:rpc_batch_limit + ?cors_origins + ?cors_headers + ?restricted_rpcs + () + in + let l2_private_rpc = + Option.map (fun port -> default_rpc ~rpc_port:port ()) private_rpc_port + in + { + id = l2_chain_id; + l2_public_rpc; + l2_private_rpc; + tx_pool_timeout_limit = + Option.value + ~default:default_tx_pool_timeout_limit + tx_pool_timeout_limit; + tx_pool_addr_limit = + Option.value ~default:default_tx_pool_addr_limit tx_pool_addr_limit; + tx_pool_tx_per_addr_limit = + Option.value + ~default:default_tx_pool_tx_per_addr_limit + tx_pool_tx_per_addr_limit; + fee_history = default_fee_history; + } + + let create ~data_dir ?rpc_addr ?rpc_port ?rpc_batch_limit ?cors_origins + ?cors_headers ~l2_chains ~keep_alive ?rollup_node_endpoint ?dont_track_rollup_node ~verbose ?preimages ?preimages_endpoint ?native_execution_policy ?time_between_blocks ?max_number_of_chunks ?private_rpc_port ?sequencer_key ?evm_node_endpoint @@ -1522,28 +1589,10 @@ module Cli = struct ?native_execution_policy () in - let l2_chains = - [ - { - id = l2_chain_id; - public_rpc; - private_rpc; - tx_pool_timeout_limit = - Option.value - ~default:default_tx_pool_timeout_limit - tx_pool_timeout_limit; - tx_pool_addr_limit = - Option.value ~default:default_tx_pool_addr_limit tx_pool_addr_limit; - tx_pool_tx_per_addr_limit = - Option.value - ~default:default_tx_pool_tx_per_addr_limit - tx_pool_tx_per_addr_limit; - fee_history = default_fee_history; - }; - ] - in { l2_chains; + public_rpc; + private_rpc; log_filter; kernel_execution; sequencer; @@ -1589,8 +1638,8 @@ module Cli = struct let patch_l2_chain_configuration_from_args ?id ?rpc_addr ?rpc_port ?rpc_batch_limit ?cors_origins ?cors_headers ?tx_pool_timeout_limit ?tx_pool_addr_limit ?tx_pool_tx_per_addr_limit ?private_rpc_port - ?restricted_rpcs configuration = - let public_rpc = + ?restricted_rpcs (configuration : l2_chain) = + let l2_public_rpc = patch_rpc ?rpc_addr ?rpc_port @@ -1598,17 +1647,17 @@ module Cli = struct ?cors_origins ?batch_limit:rpc_batch_limit ?restricted_rpcs - configuration.public_rpc + configuration.l2_public_rpc in - let private_rpc = + let l2_private_rpc = Option.map (patch_rpc ?rpc_port:private_rpc_port) - configuration.private_rpc + configuration.l2_private_rpc in { id = Option.value ~default:configuration.id id; - public_rpc; - private_rpc; + l2_public_rpc; + l2_private_rpc; tx_pool_timeout_limit = Option.value ~default:configuration.tx_pool_timeout_limit @@ -1624,9 +1673,8 @@ module Cli = struct fee_history = configuration.fee_history; } - let patch_configuration_from_args ?l2_chain_id ?rpc_addr ?rpc_port - ?rpc_batch_limit ?cors_origins ?cors_headers ?tx_pool_timeout_limit - ?tx_pool_addr_limit ?tx_pool_tx_per_addr_limit ?native_execution_policy + let patch_configuration_from_args ?(l2_chains = []) ?rpc_addr ?rpc_port + ?rpc_batch_limit ?cors_origins ?cors_headers ?native_execution_policy ~keep_alive ?rollup_node_endpoint ?dont_track_rollup_node ~verbose ?preimages ?preimages_endpoint ?time_between_blocks ?max_number_of_chunks ?private_rpc_port ?sequencer_key ?evm_node_endpoint @@ -1635,21 +1683,18 @@ module Cli = struct ?max_blueprints_ahead ?max_blueprints_catchup ?catchup_cooldown ?sequencer_sidecar_endpoint ?restricted_rpcs ~finalized_view ?proxy_ignore_block_param ~dal_slots configuration = - let l2_chains = - List.map - (patch_l2_chain_configuration_from_args - ?id:l2_chain_id - ?rpc_addr - ?rpc_port - ?rpc_batch_limit - ?cors_origins - ?cors_headers - ?tx_pool_timeout_limit - ?tx_pool_addr_limit - ?tx_pool_tx_per_addr_limit - ?private_rpc_port - ?restricted_rpcs) - configuration.l2_chains + let public_rpc = + default_rpc + ?rpc_port + ?rpc_addr + ?batch_limit:rpc_batch_limit + ?cors_origins + ?cors_headers + ?restricted_rpcs + () + in + let private_rpc = + Option.map (fun port -> default_rpc ~rpc_port:port ()) private_rpc_port in let sequencer = let sequencer_config = configuration.sequencer in @@ -1854,9 +1899,10 @@ module Cli = struct ~default:configuration.rollup_node_endpoint rollup_node_endpoint in - { l2_chains; + public_rpc; + private_rpc; log_filter; kernel_execution; sequencer; @@ -1870,19 +1916,13 @@ module Cli = struct finalized_view = finalized_view || configuration.finalized_view; } - let create_or_read_config ~data_dir ~l2_chain_id ?rpc_addr ?rpc_port - ?rpc_batch_limit ?cors_origins ?cors_headers ?tx_pool_timeout_limit - ?tx_pool_addr_limit ?tx_pool_tx_per_addr_limit ~keep_alive - ?rollup_node_endpoint ?dont_track_rollup_node ~verbose ?preimages - ?preimages_endpoint ?native_execution_policy ?time_between_blocks - ?max_number_of_chunks ?private_rpc_port ?sequencer_key ?evm_node_endpoint - ?threshold_encryption_bundler_endpoint ?max_blueprints_lag - ?max_blueprints_ahead ?max_blueprints_catchup ?catchup_cooldown - ?log_filter_max_nb_blocks ?log_filter_max_nb_logs ?log_filter_chunk_size - ?sequencer_sidecar_endpoint ?restricted_rpcs ~finalized_view - ?proxy_ignore_block_param ?dal_slots ?network () = + let create_or_read_l2_config ~data_dir ~l2_chain_id ?rpc_addr ?rpc_port + ?restricted_rpcs ?rpc_batch_limit ?cors_headers ?cors_origins + ?tx_pool_addr_limit ?tx_pool_tx_per_addr_limit ?tx_pool_timeout_limit + ?private_rpc_port () = let open Lwt_result_syntax in let open Filename.Infix in + let l2_chain_id = L2_chain_id.from_int l2_chain_id in (* Check if the data directory of the evm node is not the one of Octez node *) let* () = @@ -1895,21 +1935,91 @@ module Cli = struct please choose a different directory for the EVM node data." else return_unit in + let config_file = config_l2_filename ~data_dir l2_chain_id in + let*! exists_config = Lwt_unix.file_exists config_file in + if exists_config then + (* Read configuration from file and patch if user wanted to override + some fields with values provided by arguments. *) + let* configuration = load_l2 ~data_dir l2_chain_id in + let configuration = + patch_l2_chain_configuration_from_args + ~id:l2_chain_id + ?rpc_addr + ?rpc_port + ?tx_pool_timeout_limit + ?tx_pool_addr_limit + ?tx_pool_tx_per_addr_limit + ?private_rpc_port + ?rpc_batch_limit + ?cors_origins + ?cors_headers + ?restricted_rpcs + configuration + in + return configuration + else + let config = + create_l2 + ~l2_chain_id + ?rpc_addr + ?rpc_port + ?tx_pool_timeout_limit + ?tx_pool_addr_limit + ?tx_pool_tx_per_addr_limit + ?private_rpc_port + ?rpc_batch_limit + ?cors_origins + ?cors_headers + ?restricted_rpcs + () + in + return config + + let create_or_read_config ~data_dir ~l2_chain_ids ?rpc_addr ?rpc_port + ?rpc_batch_limit ?cors_origins ?cors_headers ~keep_alive + ?rollup_node_endpoint ?dont_track_rollup_node ?private_rpc_port ~verbose + ?preimages ?preimages_endpoint ?native_execution_policy + ?time_between_blocks ?max_number_of_chunks ?sequencer_key + ?evm_node_endpoint ?threshold_encryption_bundler_endpoint + ?max_blueprints_lag ?max_blueprints_ahead ?max_blueprints_catchup + ?catchup_cooldown ?log_filter_max_nb_blocks ?log_filter_max_nb_logs + ?log_filter_chunk_size ?sequencer_sidecar_endpoint ?restricted_rpcs + ~finalized_view ?proxy_ignore_block_param ?dal_slots ?network () = + let open Lwt_result_syntax in + let open Filename.Infix in + (* Check if the data directory of the evm node is not the one of Octez + node *) + let* () = + let*! identity_file_in_data_dir_exists = + Lwt_unix.file_exists (data_dir // "identity.json") + in + if identity_file_in_data_dir_exists then + failwith + "Invalid data directory. This is a data directory for an Octez node, \ + please choose a different directory for the EVM node data." + else return_unit + in + let*! l2_chains = + all @@ List.map (fun chain -> load_l2 ~data_dir chain) l2_chain_ids + in + let l2_chains = match l2_chains with Error _ -> [] | Ok l -> l in let config_file = config_filename ~data_dir in let*! exists_config = Lwt_unix.file_exists config_file in if exists_config then (* Read configuration from file and patch if user wanted to override some fields with values provided by arguments. *) let* configuration = load ?network ~data_dir () in + let l2_chains = match l2_chains with [] -> None | l -> Some l in let configuration = patch_configuration_from_args - ~l2_chain_id + ?l2_chains + ~keep_alive ?rpc_addr ?rpc_port ?rpc_batch_limit ?cors_origins ?cors_headers - ~keep_alive + ?private_rpc_port ?sequencer_key ?evm_node_endpoint ?threshold_encryption_bundler_endpoint @@ -1918,14 +2028,10 @@ module Cli = struct ?native_execution_policy ?time_between_blocks ?max_number_of_chunks - ?private_rpc_port ?max_blueprints_lag ?max_blueprints_ahead ?max_blueprints_catchup ?catchup_cooldown - ?tx_pool_timeout_limit - ?tx_pool_addr_limit - ?tx_pool_tx_per_addr_limit ?rollup_node_endpoint ?dont_track_rollup_node ~verbose @@ -1944,13 +2050,14 @@ module Cli = struct let config = create ~data_dir - ~l2_chain_id + ~l2_chains + ~keep_alive ?rpc_addr ?rpc_port ?rpc_batch_limit ?cors_origins ?cors_headers - ~keep_alive + ?private_rpc_port ?sequencer_key ?evm_node_endpoint ?threshold_encryption_bundler_endpoint @@ -1959,14 +2066,10 @@ module Cli = struct ?native_execution_policy ?time_between_blocks ?max_number_of_chunks - ?private_rpc_port ?max_blueprints_lag ?max_blueprints_ahead ?max_blueprints_catchup ?catchup_cooldown - ?tx_pool_timeout_limit - ?tx_pool_addr_limit - ?tx_pool_tx_per_addr_limit ?rollup_node_endpoint ?dont_track_rollup_node ~verbose diff --git a/etherlink/bin_node/config/configuration.mli b/etherlink/bin_node/config/configuration.mli index abda3c1ac8f6d2c98bde4c5b5ec2fc4cd00d57e4..fb7ad55e82dc37dad59f241ae092d5e069e3e2ab 100644 --- a/etherlink/bin_node/config/configuration.mli +++ b/etherlink/bin_node/config/configuration.mli @@ -156,8 +156,8 @@ type rpc = { type l2_chain = { id : L2_chain_id.t; - public_rpc : rpc; - private_rpc : rpc option; + l2_public_rpc : rpc; + l2_private_rpc : rpc option; tx_pool_timeout_limit : int64; tx_pool_addr_limit : int64; tx_pool_tx_per_addr_limit : int64; @@ -166,6 +166,8 @@ type l2_chain = { type t = { l2_chains : l2_chain list; + public_rpc : rpc; + private_rpc : rpc option; log_filter : log_filter_config; kernel_execution : kernel_execution_config; sequencer : sequencer option; @@ -204,6 +206,11 @@ val config_filename : data_dir:string -> string are overwritten. *) val save : force:bool -> data_dir:string -> t -> unit tzresult Lwt.t +(** [save ~force ~data_dir configuration] writes the [configuration] + file in [data_dir]. If [force] is [true], existing configurations + are overwritten. *) +val save_l2 : force:bool -> data_dir:string -> l2_chain -> unit tzresult Lwt.t + val load_file : ?network:supported_network -> data_dir:string -> string -> t tzresult Lwt.t @@ -265,17 +272,29 @@ val observer_config_dft : val make_pattern_restricted_rpcs : string -> restricted_rpcs module Cli : sig + (* val create_l2 : + l2_chain_id:L2_chain_id.t -> + ?rpc_addr:string -> + ?rpc_port:int -> + ?tx_pool_timeout_limit:int64 -> + ?restricted_rpcs:restricted_rpcs -> + ?rpc_batch_limit:limit -> + ?cors_origins:string trace -> + ?cors_headers:string trace -> + ?tx_pool_addr_limit:int64 -> + ?tx_pool_tx_per_addr_limit:int64 -> + ?private_rpc_port:int -> + unit -> + l2_chain *) + val create : data_dir:string -> - l2_chain_id:L2_chain_id.t -> ?rpc_addr:string -> ?rpc_port:int -> ?rpc_batch_limit:limit -> ?cors_origins:string list -> ?cors_headers:string list -> - ?tx_pool_timeout_limit:int64 -> - ?tx_pool_addr_limit:int64 -> - ?tx_pool_tx_per_addr_limit:int64 -> + l2_chains:l2_chain list -> keep_alive:bool -> ?rollup_node_endpoint:Uri.t -> ?dont_track_rollup_node:bool -> @@ -306,15 +325,12 @@ module Cli : sig t val patch_configuration_from_args : - ?l2_chain_id:L2_chain_id.t -> + ?l2_chains:l2_chain trace -> ?rpc_addr:string -> ?rpc_port:int -> ?rpc_batch_limit:limit -> ?cors_origins:string trace -> ?cors_headers:string trace -> - ?tx_pool_timeout_limit:int64 -> - ?tx_pool_addr_limit:int64 -> - ?tx_pool_tx_per_addr_limit:int64 -> ?native_execution_policy:native_execution_policy -> keep_alive:bool -> ?rollup_node_endpoint:Uri.t -> @@ -343,27 +359,40 @@ module Cli : sig t -> t - val create_or_read_config : + val create_or_read_l2_config : data_dir:string -> - l2_chain_id:L2_chain_id.t -> + l2_chain_id:int -> ?rpc_addr:string -> ?rpc_port:int -> + ?restricted_rpcs:restricted_rpcs -> ?rpc_batch_limit:limit -> - ?cors_origins:string list -> ?cors_headers:string list -> - ?tx_pool_timeout_limit:int64 -> + ?cors_origins:string list -> ?tx_pool_addr_limit:int64 -> ?tx_pool_tx_per_addr_limit:int64 -> + ?tx_pool_timeout_limit:int64 -> + ?private_rpc_port:int -> + unit -> + (l2_chain, tztrace) result Lwt.t + + val create_or_read_config : + data_dir:string -> + l2_chain_ids:L2_chain_id.t trace -> + ?rpc_addr:string -> + ?rpc_port:int -> + ?rpc_batch_limit:limit -> + ?cors_origins:string trace -> + ?cors_headers:string trace -> keep_alive:bool -> ?rollup_node_endpoint:Uri.t -> ?dont_track_rollup_node:bool -> + ?private_rpc_port:int -> verbose:bool -> ?preimages:string -> ?preimages_endpoint:Uri.t -> ?native_execution_policy:native_execution_policy -> ?time_between_blocks:time_between_blocks -> ?max_number_of_chunks:int -> - ?private_rpc_port:int -> ?sequencer_key:Client_keys.sk_uri -> ?evm_node_endpoint:Uri.t -> ?threshold_encryption_bundler_endpoint:Uri.t -> @@ -378,10 +407,10 @@ module Cli : sig ?restricted_rpcs:restricted_rpcs -> finalized_view:bool -> ?proxy_ignore_block_param:bool -> - ?dal_slots:int list -> + ?dal_slots:int trace -> ?network:supported_network -> unit -> - t tzresult Lwt.t + (t, tztrace) result Lwt.t end val time_between_blocks_encoding : time_between_blocks Data_encoding.t diff --git a/etherlink/bin_node/lib_dev/block_producer.ml b/etherlink/bin_node/lib_dev/block_producer.ml index 10f200430c044ffaa8afca86b3dbf6dc5eb527f1..5d698118b649fdfa93c24d7cacf64264a69340be 100644 --- a/etherlink/bin_node/lib_dev/block_producer.ml +++ b/etherlink/bin_node/lib_dev/block_producer.ml @@ -361,6 +361,7 @@ module Handlers = struct let state = Worker.state w in match request with | Request.Produce_block (with_delayed_transactions, timestamp, force) -> + Format.eprintf "SALUT@. JE SUIS PRODUCE_BLOCK@." ; protect @@ fun () -> let { l2_chains; @@ -439,6 +440,7 @@ let shutdown () = let produce_block ~with_delayed_transactions ~force ~timestamp = let open Lwt_result_syntax in + Format.eprintf "SALUT@. JE SUIS PRODUCE_BLOCK@." ; let*? worker = Lazy.force worker in Worker.Queue.push_request_and_wait worker diff --git a/etherlink/bin_node/lib_dev/encodings/l2_chain_id.ml b/etherlink/bin_node/lib_dev/encodings/l2_chain_id.ml index 5c91d550ab7366c3bb77d101c9a4534d9af5b0f0..8cf3753ec8375de1c26eadd81370bc3ff2bb1586 100644 --- a/etherlink/bin_node/lib_dev/encodings/l2_chain_id.ml +++ b/etherlink/bin_node/lib_dev/encodings/l2_chain_id.ml @@ -40,6 +40,8 @@ let hash = Hashtbl.hash let from_int x = Z.of_int x +let compare = Z.compare + let to_z x = x let from_z x = x diff --git a/etherlink/bin_node/lib_dev/encodings/l2_chain_id.mli b/etherlink/bin_node/lib_dev/encodings/l2_chain_id.mli index 2d4e4518b9d3e317b15a38e5911e1da8fc3e1216..262f966f13e48441dd0292e9e217ecd6540bee64 100644 --- a/etherlink/bin_node/lib_dev/encodings/l2_chain_id.mli +++ b/etherlink/bin_node/lib_dev/encodings/l2_chain_id.mli @@ -16,6 +16,8 @@ val pp : Format.formatter -> t -> unit val equal : t -> t -> bool +val compare : t -> t -> int + val hash : t -> int val from_int : int -> t diff --git a/etherlink/bin_node/lib_dev/kernel_config.ml b/etherlink/bin_node/lib_dev/kernel_config.ml index 049e5407d9a96c1cc5dc5faccfa01d59e86ad838..73e6f2cc2ce93fbfd314e82cfcfaaf2a38e954c1 100644 --- a/etherlink/bin_node/lib_dev/kernel_config.ml +++ b/etherlink/bin_node/lib_dev/kernel_config.ml @@ -5,6 +5,19 @@ (* *) (*****************************************************************************) +let make_l2_instr ?(path_prefix = []) ?(convert = Fun.id) ~l2_chain_id arg_opt = + let prefix = + let prefix = Format.sprintf "/evm/world_state/%s/" l2_chain_id in + List.fold_left + (fun acc path -> Format.sprintf "%s%s/" acc path) + prefix + path_prefix + in + arg_opt + |> Option.map (fun (key, value) -> + Installer_config.make ~key:(prefix ^ key) ~value:(convert value)) + |> Option.to_list + let make_instr ?(path_prefix = "/evm/") ?(convert = Fun.id) arg_opt = arg_opt |> Option.map (fun (key, value) -> @@ -22,15 +35,16 @@ let parse_z_to_padded_32_le_int_bytes s = let z = Z.of_string s in padded_32_le_int_bytes z -let make ~mainnet_compat ~boostrap_balance ?bootstrap_accounts ?kernel_root_hash - ?chain_id ?sequencer ?delayed_bridge ?ticketer ?admin ?sequencer_governance - ?kernel_governance ?kernel_security_governance ?minimum_base_fee_per_gas - ?da_fee_per_byte ?delayed_inbox_timeout ?delayed_inbox_min_levels - ?sequencer_pool_address ?maximum_allowed_ticks ?maximum_gas_per_transaction - ?max_blueprint_lookahead_in_seconds ?remove_whitelist ?enable_fa_bridge - ?enable_dal ?dal_slots ?set_account_code ?max_delayed_inbox_blueprint_length - ~output () = - let chain_id = Option.value ~default:("chain_id", "1") chain_id in +let le_int64_bytes i = + let b = Bytes.make 8 '\000' in + Bytes.set_int64_le b 0 (Int64.of_string i) ; + String.of_bytes b + +let make_l2 ~mainnet_compat ~boostrap_balance ?bootstrap_accounts ?ticketer + ?minimum_base_fee_per_gas ?da_fee_per_byte ?delayed_inbox_timeout + ?delayed_inbox_min_levels ?sequencer_pool_address + ?maximum_gas_per_transaction ?set_account_code + ?max_delayed_inbox_blueprint_length ~l2_chain_id ~output () = let bootstrap_accounts = match bootstrap_accounts with | None -> [] @@ -38,12 +52,10 @@ let make ~mainnet_compat ~boostrap_balance ?bootstrap_accounts ?kernel_root_hash let balance = padded_32_le_int_bytes boostrap_balance in List.map (fun address -> - make_instr - ~path_prefix: - (Format.asprintf - "/evm/world_state/%s/eth_accounts/" - (snd chain_id)) - (Some (address ^ "/balance", balance))) + make_l2_instr + ~path_prefix:["eth_accounts"; address] + ~l2_chain_id + (Some ("balance", balance))) bootstrap_accounts |> List.flatten in @@ -53,78 +65,91 @@ let make ~mainnet_compat ~boostrap_balance ?bootstrap_accounts ?kernel_root_hash | Some set_account_codes -> List.map (fun (address, code) -> - make_instr + make_l2_instr ~convert:encode_hexa - ~path_prefix: - (Format.asprintf - "/evm/world_state/%s/eth_accounts/" - (snd chain_id)) - (Some (address ^ "/code", code))) + ~path_prefix:["eth_accounts"; address] + ~l2_chain_id + (Some ("code", code))) set_account_codes |> List.flatten in - let le_int64_bytes i = - let b = Bytes.make 8 '\000' in - Bytes.set_int64_le b 0 (Int64.of_string i) ; - String.of_bytes b + let instrs = + (if mainnet_compat then make_instr ~path_prefix:"/evm/" ticketer + else + (* For compatibility reason for Mainnet and Ghostnet *) + make_l2_instr ~l2_chain_id ticketer) + (* TODO: chain_id is the only parameter that I can't make L2 without the integration test crashing *) + @ make_instr + ~convert:parse_z_to_padded_32_le_int_bytes + (Some ("chain_id", l2_chain_id)) + @ make_l2_instr + ~l2_chain_id + ~convert:parse_z_to_padded_32_le_int_bytes + minimum_base_fee_per_gas + @ make_l2_instr + ~l2_chain_id + ~path_prefix:["fees"] + ~convert:parse_z_to_padded_32_le_int_bytes + da_fee_per_byte + @ make_l2_instr ~l2_chain_id ~convert:le_int64_bytes delayed_inbox_timeout + @ make_l2_instr + ~l2_chain_id + ~convert:le_int64_bytes + delayed_inbox_min_levels + @ make_l2_instr + ~l2_chain_id + ~convert:(fun addr -> + let addr = Misc.normalize_addr addr in + Hex.to_bytes_exn (`Hex addr) |> String.of_bytes) + sequencer_pool_address + @ make_l2_instr + ~l2_chain_id + ~convert:le_int64_bytes + maximum_gas_per_transaction + @ bootstrap_accounts @ set_account_code + @ make_l2_instr + ~l2_chain_id + ~convert:(fun s -> Ethereum_types.u16_to_bytes (int_of_string s)) + max_delayed_inbox_blueprint_length in - (* Convert a comma-separated list of decimal values in the [0; 255] - range into a sequence of bytes (of type string). *) + Installer_config.to_file instrs ~output + +let make ~mainnet_compat:_ ?kernel_root_hash ?(l2_chain_ids = []) ?sequencer + ?delayed_bridge ?admin ?sequencer_governance ?kernel_governance + ?kernel_security_governance ?maximum_allowed_ticks + ?max_blueprint_lookahead_in_seconds ?remove_whitelist ?enable_fa_bridge + ?enable_dal ?dal_slots ~output () : unit tzresult Lwt.t = let decimal_list_to_bytes l = l |> String.split ',' |> List.to_seq |> Seq.map (fun s -> Char.chr (int_of_string s)) |> String.of_seq in let chain_configs = - Some - ( "chain_configurations", - let open Rlp in - List [List [Value (snd chain_id |> Z.of_string |> encode_z)]] - |> encode |> String.of_bytes ) + let open Rlp in + let tuples = + List.map + (fun l2_chain_id -> Value (l2_chain_id |> Z.of_string |> encode_z)) + l2_chain_ids + in + let result = String.of_bytes @@ encode (List tuples) in + Some ("chain_configurations", result) in let instrs = - (if mainnet_compat then make_instr ~path_prefix:"/evm/" ticketer - else - (* For compatibility reason for Mainnet and Ghostnet *) - make_instr - ~path_prefix:(Format.asprintf "/evm/world_state/%s/" (snd chain_id)) - ticketer) + make_instr admin @ make_instr ~convert:(fun s -> Hex.to_bytes_exn (`Hex s) |> Bytes.to_string) kernel_root_hash - @ make_instr ~convert:parse_z_to_padded_32_le_int_bytes (Some chain_id) @ make_instr sequencer @ make_instr delayed_bridge - @ make_instr chain_configs @ make_instr admin @ make_instr sequencer_governance @ make_instr kernel_governance @ make_instr kernel_security_governance - @ make_instr - ~path_prefix: - (Format.asprintf "/evm/world_state/%s/fees/" (snd chain_id)) - ~convert:parse_z_to_padded_32_le_int_bytes - minimum_base_fee_per_gas - @ make_instr - ~path_prefix: - (Format.asprintf "/evm/world_state/%s/fees/" (snd chain_id)) - ~convert:parse_z_to_padded_32_le_int_bytes - da_fee_per_byte - @ make_instr ~convert:le_int64_bytes delayed_inbox_timeout - @ make_instr ~convert:le_int64_bytes delayed_inbox_min_levels - @ make_instr - ~convert:(fun addr -> - let addr = Misc.normalize_addr addr in - Hex.to_bytes_exn (`Hex addr) |> String.of_bytes) - sequencer_pool_address - @ make_instr ~convert:le_int64_bytes maximum_allowed_ticks - @ make_instr ~convert:le_int64_bytes maximum_gas_per_transaction - @ make_instr ~convert:le_int64_bytes max_blueprint_lookahead_in_seconds - @ bootstrap_accounts @ set_account_code - @ make_instr remove_whitelist @ make_instr ~path_prefix:"/evm/feature_flags/" enable_fa_bridge @ make_instr ~path_prefix:"/evm/feature_flags/" enable_dal + @ make_instr ~convert:le_int64_bytes maximum_allowed_ticks + @ make_instr ~convert:le_int64_bytes max_blueprint_lookahead_in_seconds @ make_instr ~convert:decimal_list_to_bytes dal_slots - @ make_instr - ~convert:(fun s -> Ethereum_types.u16_to_bytes (int_of_string s)) - max_delayed_inbox_blueprint_length + @ make_instr ~convert:decimal_list_to_bytes dal_slots + @ make_instr remove_whitelist + @ make_instr chain_configs in Installer_config.to_file instrs ~output diff --git a/etherlink/bin_node/lib_dev/kernel_config.mli b/etherlink/bin_node/lib_dev/kernel_config.mli index d3875a08f1b84740066bd09279a24967266f9b2f..3e6adad8289cb775415986c43a5348e0c739dbd7 100644 --- a/etherlink/bin_node/lib_dev/kernel_config.mli +++ b/etherlink/bin_node/lib_dev/kernel_config.mli @@ -11,31 +11,41 @@ [bootstrap_accounts] are provisioned with [bootstrap_balance]. *) val make : mainnet_compat:bool -> - boostrap_balance:Ethereum_types.NonceMap.key -> - ?bootstrap_accounts:string list -> ?kernel_root_hash:string * string -> - ?chain_id:string * string -> + ?l2_chain_ids:string list -> ?sequencer:string * string -> ?delayed_bridge:string * string -> - ?ticketer:string * string -> ?admin:string * string -> ?sequencer_governance:string * string -> ?kernel_governance:string * string -> ?kernel_security_governance:string * string -> - ?minimum_base_fee_per_gas:string * string -> - ?da_fee_per_byte:string * string -> - ?delayed_inbox_timeout:string * string -> - ?delayed_inbox_min_levels:string * string -> - ?sequencer_pool_address:string * string -> ?maximum_allowed_ticks:string * string -> - ?maximum_gas_per_transaction:string * string -> ?max_blueprint_lookahead_in_seconds:string * string -> ?remove_whitelist:string * string -> ?enable_fa_bridge:string * string -> ?enable_dal:string * string -> ?dal_slots:string * string -> + output:string -> + unit -> + unit tzresult Lwt.t + +(** [make ~boostrap_balance ?bootstrap_accounts ... ~output ()] + generates a configuration file located at [output], where + [bootstrap_accounts] are provisioned with [bootstrap_balance]. *) +val make_l2 : + mainnet_compat:bool -> + boostrap_balance:Ethereum_types.NonceMap.key -> + ?bootstrap_accounts:string list -> + ?ticketer:string * string -> + ?minimum_base_fee_per_gas:string * string -> + ?da_fee_per_byte:string * string -> + ?delayed_inbox_timeout:string * string -> + ?delayed_inbox_min_levels:string * string -> + ?sequencer_pool_address:string * string -> + ?maximum_gas_per_transaction:string * string -> ?set_account_code:(string * string) list -> ?max_delayed_inbox_blueprint_length:string * string -> + l2_chain_id:string -> output:string -> unit -> unit tzresult Lwt.t diff --git a/etherlink/bin_node/lib_dev/rpc_server.ml b/etherlink/bin_node/lib_dev/rpc_server.ml index ae429773a39547a1fd1faf1e1381bc01b6f91797..42009f6480001347d036da33cde5983276859b55 100644 --- a/etherlink/bin_node/lib_dev/rpc_server.ml +++ b/etherlink/bin_node/lib_dev/rpc_server.ml @@ -130,18 +130,18 @@ let start_public_server ?delegate_health_check_to ?evm_services let directory = Services.directory ?delegate_health_check_to - l2_chain_config.public_rpc + l2_chain_config.l2_public_rpc config l2_chain_config ctxt |> register_evm_services |> Evm_directory.register_metrics "/metrics" in - let* finalizer = start_server l2_chain_config.public_rpc directory in + let* finalizer = start_server l2_chain_config.l2_public_rpc directory in let*! () = Events.is_ready - ~rpc_addr:l2_chain_config.public_rpc.addr - ~rpc_port:l2_chain_config.public_rpc.port + ~rpc_addr:l2_chain_config.l2_public_rpc.addr + ~rpc_port:l2_chain_config.l2_public_rpc.port ~backend:config.experimental_features.rpc_server ~websockets:config.experimental_features.enable_websocket in @@ -150,7 +150,7 @@ let start_public_server ?delegate_health_check_to ?evm_services let start_private_server ?(block_production = `Disabled) config l2_chain_config ctxt = let open Lwt_result_syntax in - match l2_chain_config.Configuration.private_rpc with + match l2_chain_config.Configuration.l2_private_rpc with | Some private_rpc -> let directory = Services.private_directory diff --git a/etherlink/bin_node/lib_dev/services.ml b/etherlink/bin_node/lib_dev/services.ml index 8a1d771bf68f8dca5802c0715ba0ca6d4e7d259d..4a4c24cd5e2442afa024bebceb43c4ee122d9251 100644 --- a/etherlink/bin_node/lib_dev/services.ml +++ b/etherlink/bin_node/lib_dev/services.ml @@ -100,7 +100,7 @@ let configuration_handler config = in let l2_chains = List.map - (fun l2_chain -> {l2_chain with private_rpc = None}) + (fun l2_chain -> {l2_chain with l2_private_rpc = None}) config.l2_chains in @@ -907,6 +907,7 @@ let dispatch_private_request (rpc : Configuration.rpc) | Method (Produce_block.Method, _) when block_production <> `Single_node -> unsupported () | Method (Produce_block.Method, module_) -> + Format.eprintf "SALUT@. JE SUIS PRODUCE_BLOCK@." ; let f input = let open Lwt_result_syntax in let timestamp, with_delayed_transactions = diff --git a/etherlink/bin_node/main.ml b/etherlink/bin_node/main.ml index 92841d2f15996a41cc85e3fc6e8662b0667adef9..5f8552e51bc266dee0f5808aff500f70cb0f2810 100644 --- a/etherlink/bin_node/main.ml +++ b/etherlink/bin_node/main.ml @@ -175,6 +175,20 @@ let wallet_dir_arg = Client_config.default_base_dir) Params.string +let chain_id_arg = + Tezos_clic.arg + ~long:"l2-chain-id" + ~placeholder:"ID" + ~doc:"The chain id of the L2 chain" + Params.int + +let multiple_chains_arg = + Tezos_clic.multiple_arg + ~long:"l2-chain-id" + ~placeholder:"ID" + ~doc:"The chain id of the L2 chain" + Params.string + let rpc_addr_arg = Tezos_clic.arg ~long:"rpc-addr" @@ -707,21 +721,19 @@ let num_download_retries = Params.int let common_config_args = - Tezos_clic.args19 + Tezos_clic.args17 data_dir_arg rpc_addr_arg rpc_port_arg rpc_batch_limit_arg cors_allowed_origins_arg cors_allowed_headers_arg + multiple_chains_arg log_filter_max_nb_blocks_arg log_filter_max_nb_logs_arg log_filter_chunk_size_arg keep_alive_arg rollup_node_endpoint_arg - tx_pool_timeout_limit_arg - tx_pool_addr_limit_arg - tx_pool_tx_per_addr_limit_arg verbose_arg restricted_rpcs_arg blacklisted_rpcs_arg @@ -764,17 +776,16 @@ let websocket_checks config = Internal_event.Simple.emit Event.buggy_dream_websocket () |> Lwt_result.ok | _ -> Lwt_result_syntax.return_unit -let start_proxy ~data_dir ~keep_alive ~l2_chain_id ?rpc_addr ?rpc_port +let start_proxy ~data_dir ~l2_chain_ids ~keep_alive ?rpc_addr ?rpc_port ?rpc_batch_limit ?cors_origins ?cors_headers ?log_filter_max_nb_blocks ?log_filter_max_nb_logs ?log_filter_chunk_size ?rollup_node_endpoint - ?evm_node_endpoint ?tx_pool_timeout_limit ?tx_pool_addr_limit - ?tx_pool_tx_per_addr_limit ?restricted_rpcs ~verbose ~read_only - ~finalized_view ~ignore_block_param () = + ?evm_node_endpoint ?restricted_rpcs ~verbose ~read_only ~finalized_view + ~ignore_block_param () = let open Lwt_result_syntax in let* config = Cli.create_or_read_config ~data_dir - ~l2_chain_id + ~l2_chain_ids ~keep_alive ?rpc_addr ?rpc_port @@ -786,9 +797,6 @@ let start_proxy ~data_dir ~keep_alive ~l2_chain_id ?rpc_addr ?rpc_port ?log_filter_chunk_size ?rollup_node_endpoint ?evm_node_endpoint - ?tx_pool_timeout_limit - ?tx_pool_addr_limit - ?tx_pool_tx_per_addr_limit ?restricted_rpcs ~finalized_view ~proxy_ignore_block_param:ignore_block_param @@ -819,6 +827,16 @@ let start_proxy ~data_dir ~keep_alive ~l2_chain_id ?rpc_addr ?rpc_port let* () = wait in return_unit +let string_to_l2_chain_ids l2_chain_ids = + let open Evm_node_lib_dev_encoding in + match l2_chain_ids with + | None -> failwith "missing --l2-chain-ids argument" + | Some l2_chain_ids -> + let l2_chain_ids = + List.map (fun z -> L2_chain_id.from_z @@ Z.of_string z) l2_chain_ids + in + Lwt_result_syntax.return l2_chain_ids + let register_wallet ?password_filename ~wallet_dir () = let wallet_ctxt = new Client_context_unix.unix_io_wallet @@ -863,12 +881,11 @@ let make_event_config ~verbosity ~daily_logs_path in add_uri_to_config uri config -let start_sequencer ?password_filename ~wallet_dir ~data_dir ~l2_chain_id - ?rpc_addr ?rpc_port ?rpc_batch_limit ?cors_origins ?cors_headers - ?tx_pool_timeout_limit ?tx_pool_addr_limit ?tx_pool_tx_per_addr_limit - ~keep_alive ?rollup_node_endpoint ~verbose ?preimages ?preimages_endpoint +let start_sequencer ?password_filename ~wallet_dir ~data_dir ~l2_chain_ids + ?rpc_addr ?rpc_port ?rpc_batch_limit ?cors_origins ?cors_headers ~keep_alive + ?rollup_node_endpoint ~verbose ?preimages ?preimages_endpoint ?native_execution_policy ?time_between_blocks ?max_number_of_chunks - ?private_rpc_port ?sequencer_str ?max_blueprints_lag ?max_blueprints_ahead + ?sequencer_str ?max_blueprints_lag ?max_blueprints_ahead ?max_blueprints_catchup ?catchup_cooldown ?log_filter_max_nb_blocks ?log_filter_max_nb_logs ?log_filter_chunk_size ?genesis_timestamp ?restricted_rpcs ?kernel ?dal_slots ?sandbox_key ~finalized_view () = @@ -887,15 +904,12 @@ let start_sequencer ?password_filename ~wallet_dir ~data_dir ~l2_chain_id let* configuration = Cli.create_or_read_config ~data_dir - ~l2_chain_id + ~l2_chain_ids ?rpc_addr ?rpc_port ?rpc_batch_limit ?cors_origins ?cors_headers - ?tx_pool_timeout_limit - ?tx_pool_addr_limit - ?tx_pool_tx_per_addr_limit ~keep_alive ?rollup_node_endpoint ~verbose @@ -904,7 +918,6 @@ let start_sequencer ?password_filename ~wallet_dir ~data_dir ~l2_chain_id ?native_execution_policy ?time_between_blocks ?max_number_of_chunks - ?private_rpc_port ?sequencer_key ?max_blueprints_lag ?max_blueprints_ahead @@ -913,8 +926,8 @@ let start_sequencer ?password_filename ~wallet_dir ~data_dir ~l2_chain_id ?log_filter_max_nb_blocks ?log_filter_max_nb_logs ?log_filter_chunk_size - ?restricted_rpcs ?dal_slots + ?restricted_rpcs ~finalized_view () in @@ -968,7 +981,6 @@ let rpc_run_args = let rpc_command = let open Lwt_result_syntax in let open Tezos_clic in - let open Evm_node_lib_dev_encoding in command ~desc:"Start the EVM node in sequencer mode" (merge_options common_config_args rpc_run_args) @@ -979,36 +991,27 @@ let rpc_command = rpc_batch_limit, cors_origins, cors_headers, + l2_chain_ids, log_filter_max_nb_blocks, log_filter_max_nb_logs, log_filter_chunk_size, keep_alive, rollup_node_endpoint, - tx_pool_timeout_limit, - tx_pool_addr_limit, - tx_pool_tx_per_addr_limit, verbose, restricted_rpcs, - blacklisted_rpcs, whitelisted_rpcs, + blacklisted_rpcs, finalized_view ), ( evm_node_endpoint, preimages, preimages_endpoint, native_execution_policy ) ) () -> - let* restricted_rpcs = - pick_restricted_rpcs restricted_rpcs whitelisted_rpcs blacklisted_rpcs - in - let* rpc_port = - match rpc_port with - | Some rpc_port -> return rpc_port - | None -> failwith "--rpc-port argument required" - in let* () = when_ Option.(is_some rollup_node_endpoint) @@ fun () -> failwith "unexpected --rollup-node-endpoint argument" in + let* l2_chain_ids = string_to_l2_chain_ids l2_chain_ids in let* read_write_config = (* We read the configuration used for the read-write node, without altering it ([keep_alive] and [verbose] are @@ -1019,7 +1022,7 @@ let rpc_command = connect to the read-write node. *) Cli.create_or_read_config ~data_dir - ~l2_chain_id:(L2_chain_id.from_int 1) + ~l2_chain_ids ~keep_alive ~verbose ~finalized_view @@ -1038,7 +1041,7 @@ let rpc_command = uri | None -> let evm_node_addr = - match l2_chain_config.public_rpc.addr with + match l2_chain_config.l2_public_rpc.addr with | "0.0.0.0" (* IPv4 catch-all bind address *) | "[::]" (* IPv6 catch-all bind address *) -> "localhost" @@ -1047,30 +1050,30 @@ let rpc_command = Uri.make ~scheme:"http" ~host:evm_node_addr - ~port:l2_chain_config.public_rpc.port + ~port:l2_chain_config.l2_public_rpc.port () in + let* restricted_rpcs = + pick_restricted_rpcs restricted_rpcs whitelisted_rpcs blacklisted_rpcs + in let config = Cli.patch_configuration_from_args ~keep_alive - ?cors_origins - ?cors_headers - ?rpc_batch_limit ~verbose ?preimages ?preimages_endpoint + ?rpc_addr + ?rpc_port + ?rpc_batch_limit + ?cors_origins + ?cors_headers ?native_execution_policy - ?tx_pool_timeout_limit - ?tx_pool_addr_limit - ?tx_pool_tx_per_addr_limit ?log_filter_chunk_size ?log_filter_max_nb_logs ?log_filter_max_nb_blocks - ?restricted_rpcs - ~rpc_port - ?rpc_addr ~dal_slots:None read_write_config + ?restricted_rpcs ~finalized_view in let*! () = @@ -1102,26 +1105,25 @@ let rpc_command = ~config ~l2_chain_config) -let start_observer ~data_dir ~l2_chain_id ~keep_alive ?rpc_addr ?rpc_port +let start_observer ~data_dir ~l2_chain_ids ~keep_alive ?rpc_addr ?rpc_port ?rpc_batch_limit ?private_rpc_port ?cors_origins ?cors_headers ~verbose ?preimages ?preimages_endpoint ?native_execution_policy ?rollup_node_endpoint ~dont_track_rollup_node ?evm_node_endpoint - ?threshold_encryption_bundler_endpoint ?tx_pool_timeout_limit - ?tx_pool_addr_limit ?tx_pool_tx_per_addr_limit ?log_filter_chunk_size + ?threshold_encryption_bundler_endpoint ?log_filter_chunk_size ?log_filter_max_nb_logs ?log_filter_max_nb_blocks ?restricted_rpcs ?kernel ~no_sync ~init_from_snapshot ~finalized_view ?network () = let open Lwt_result_syntax in let* config = Cli.create_or_read_config ~data_dir - ~l2_chain_id - ~keep_alive + ~l2_chain_ids ?rpc_addr ?rpc_port ?private_rpc_port ?rpc_batch_limit ?cors_origins ?cors_headers + ~keep_alive ?rollup_node_endpoint ?dont_track_rollup_node: (* If `dont_track_rollup_node` is false, it means the argument was @@ -1134,9 +1136,6 @@ let start_observer ~data_dir ~l2_chain_id ~keep_alive ?rpc_addr ?rpc_port ?native_execution_policy ?evm_node_endpoint ?threshold_encryption_bundler_endpoint - ?tx_pool_timeout_limit - ?tx_pool_addr_limit - ?tx_pool_tx_per_addr_limit ?log_filter_chunk_size ?log_filter_max_nb_logs ?log_filter_max_nb_blocks @@ -1381,7 +1380,6 @@ let make_sequencer_upgrade_command = let init_from_rollup_node_command = let open Tezos_clic in - let open Evm_node_lib_dev_encoding in let rollup_node_data_dir_param = Tezos_clic.param ~name:"rollup-node-data-dir" @@ -1391,15 +1389,18 @@ let init_from_rollup_node_command = command ~desc: "initialises the EVM node data-dir using the data-dir of a rollup node." - (args2 data_dir_arg omit_delayed_tx_events_arg) + (args3 data_dir_arg multiple_chains_arg omit_delayed_tx_events_arg) (prefixes ["init"; "from"; "rollup"; "node"] @@ rollup_node_data_dir_param @@ stop) - (fun (data_dir, omit_delayed_tx_events) rollup_node_data_dir () -> + (fun (data_dir, l2_chain_ids, omit_delayed_tx_events) + rollup_node_data_dir + () -> let open Lwt_result_syntax in + let* l2_chain_ids = string_to_l2_chain_ids l2_chain_ids in let* configuration = Cli.create_or_read_config ~data_dir - ~l2_chain_id:(L2_chain_id.from_int 0) + ~l2_chain_ids ~keep_alive:false ~verbose:false ~finalized_view:false @@ -1485,11 +1486,11 @@ let reset_command = let replay_command = let open Tezos_clic in - let open Evm_node_lib_dev_encoding in command ~desc:"Replay a specific block level." - (args7 + (args8 data_dir_arg + multiple_chains_arg preimages_arg preimages_endpoint_arg native_execution_policy_arg @@ -1505,6 +1506,7 @@ let replay_command = @@ Evm_node_lib_dev_encoding.Ethereum_types.Qty (Z.of_string s))) @@ stop) (fun ( data_dir, + l2_chain_ids, preimages, preimages_endpoint, native_execution_policy, @@ -1523,11 +1525,12 @@ let replay_command = in init ?config () in + let* l2_chain_ids = string_to_l2_chain_ids l2_chain_ids in let* configuration = Cli.create_or_read_config ~keep_alive:false ~data_dir - ~l2_chain_id:(L2_chain_id.from_int 1) + ~l2_chain_ids ~verbose:false ?preimages ?preimages_endpoint @@ -1545,15 +1548,15 @@ let replay_command = let patch_kernel_command = let open Tezos_clic in - let open Evm_node_lib_dev_encoding in command ~desc: "Patch the kernel used by the EVM node from its current HEAD. This is an \ unsafe command, which can lead to the EVM node diverging from the \ Etherlink main branch if the new kernel is not compatible with the one \ deployed on the network." - (args3 + (args4 data_dir_arg + multiple_chains_arg (block_number_arg ~doc: "If provided, the state resulting in the application of the \ @@ -1564,7 +1567,7 @@ let patch_kernel_command = (prefixes ["patch"; "kernel"; "with"] @@ Tezos_clic.string ~name:"kernel_path" ~desc:"Path to the kernel" @@ stop) - (fun (data_dir, block_number, force) kernel_path () -> + (fun (data_dir, l2_chain_ids, block_number, force) kernel_path () -> let open Lwt_result_syntax in let open Evm_node_lib_dev in let*! () = @@ -1572,10 +1575,11 @@ let patch_kernel_command = let config = make_with_defaults ~verbosity:Warning () in init ~config () in + let* l2_chain_ids = string_to_l2_chain_ids l2_chain_ids in let* configuration = Cli.create_or_read_config ~data_dir - ~l2_chain_id:(L2_chain_id.from_int 0) + ~l2_chain_ids ~keep_alive:false ~verbose:false ~finalized_view:false @@ -1604,10 +1608,82 @@ let describe_config_command = Configuration.describe () ; return_unit) +let init_chain_config_command = + let open Tezos_clic in + let open Lwt_result_syntax in + command + ~desc: + {|Create an initial config with default value. +If the is set then adds the configuration for the proxy +mode. +If the is set,then adds the configuration for the sequencer and +threshold encryption sequencer modes. +If the is set then adds the configuration for the observer +mode.|} + (args15 + (* sequencer and observer config*) + data_dir_arg + chain_id_arg + rpc_addr_arg + rpc_port_arg + rpc_batch_limit_arg + cors_allowed_headers_arg + cors_allowed_origins_arg + private_rpc_port_arg + tx_pool_addr_limit_arg + tx_pool_timeout_limit_arg + tx_pool_tx_per_addr_limit_arg + restricted_rpcs_arg + blacklisted_rpcs_arg + whitelisted_rpcs_arg + (Tezos_clic.switch + ~long:"force" + ~short:'f' + ~doc:"Overwrites the configuration file when it exists." + ())) + (prefixes ["init"; "chain"; "config"] @@ stop) + (fun ( data_dir, + chain_id, + rpc_addr, + rpc_port, + rpc_batch_limit, + cors_headers, + cors_origins, + private_rpc_port, + tx_pool_addr_limit, + tx_pool_timeout_limit, + tx_pool_tx_per_addr_limit, + restricted_rpcs, + blacklisted_rpcs, + whitelisted_rpcs, + force ) + () -> + let l2_chain_id = Option.value chain_id ~default:1 in + Evm_node_lib_dev.Data_dir.use ~data_dir @@ fun () -> + let* restricted_rpcs = + pick_restricted_rpcs restricted_rpcs whitelisted_rpcs blacklisted_rpcs + in + let* config_l2 = + Cli.create_or_read_l2_config + ~data_dir + ~l2_chain_id + ?rpc_addr + ?rpc_port + ?rpc_batch_limit + ?cors_headers + ?cors_origins + ?private_rpc_port + ?tx_pool_addr_limit + ?tx_pool_timeout_limit + ?restricted_rpcs + ?tx_pool_tx_per_addr_limit + () + in + Configuration.save_l2 ~force ~data_dir config_l2) + let init_config_command = let open Tezos_clic in let open Lwt_result_syntax in - let open Evm_node_lib_dev_encoding in command ~desc: {|Create an initial config with default value. @@ -1656,18 +1732,16 @@ mode.|} rpc_batch_limit, cors_origins, cors_headers, + l2_chain_ids, log_filter_max_nb_blocks, log_filter_max_nb_logs, log_filter_chunk_size, keep_alive, rollup_node_endpoint, - tx_pool_timeout_limit, - tx_pool_addr_limit, - tx_pool_tx_per_addr_limit, verbose, restricted_rpcs, - blacklisted_rpcs, whitelisted_rpcs, + blacklisted_rpcs, finalized_view ), ( preimages, preimages_endpoint, @@ -1690,9 +1764,6 @@ mode.|} network ) ) () -> Evm_node_lib_dev.Data_dir.use ~data_dir @@ fun () -> - let* restricted_rpcs = - pick_restricted_rpcs restricted_rpcs whitelisted_rpcs blacklisted_rpcs - in let* sequencer_key = Option.map_es (fun str -> @@ -1700,12 +1771,25 @@ mode.|} Client_keys.Secret_key.parse_source_string wallet_ctxt str) sequencer_str in + (* (* When initialing maybe we can just not check l2_chain_ids *) + let open Evm_node_lib_dev_encoding in + let l2_chain_ids = + Option.fold + ~some:(List.map (fun z -> L2_chain_id.from_z @@ Z.of_string z)) + ~none:[] + l2_chain_ids + in *) + let* l2_chain_ids = string_to_l2_chain_ids l2_chain_ids in + let* restricted_rpcs = + pick_restricted_rpcs restricted_rpcs whitelisted_rpcs blacklisted_rpcs + in let* config = Cli.create_or_read_config ~data_dir - ~l2_chain_id:(L2_chain_id.from_int 1) + ~l2_chain_ids ?rpc_addr ?rpc_port + ?private_rpc_port ?rpc_batch_limit ?cors_origins ?cors_headers @@ -1719,15 +1803,11 @@ mode.|} omitted from the command-line. As a consequence, we default to the config value by passing [None]. *) (if dont_track_rollup_node then Some true else None) - ?tx_pool_timeout_limit - ?tx_pool_addr_limit - ?tx_pool_tx_per_addr_limit ?preimages ?preimages_endpoint ?native_execution_policy ?time_between_blocks ?max_number_of_chunks - ?private_rpc_port ?sequencer_key ?evm_node_endpoint ?threshold_encryption_bundler_endpoint @@ -1736,9 +1816,9 @@ mode.|} ?max_blueprints_ahead ?max_blueprints_catchup ?catchup_cooldown - ?restricted_rpcs ~verbose ?dal_slots + ?restricted_rpcs ~finalized_view ?network () @@ -1825,124 +1905,139 @@ let set_account_code = Lwt.return_ok (address, code) | _ -> failwith "Parsing error for set-code") -let make_kernel_config_command = +let make_l2_kernel_config_command = let open Tezos_clic in let open Lwt_result_syntax in command ~desc:"Transforms the JSON list of instructions to a RLP list" - (merge_options - (args25 - mainnet_compat_arg - (config_key_arg ~name:"kernel_root_hash" ~placeholder:"root hash") - (config_key_arg ~name:"chain_id" ~placeholder:"chain id") - (config_key_arg ~name:"sequencer" ~placeholder:"edpk...") - (config_key_arg ~name:"delayed_bridge" ~placeholder:"KT1...") - (config_key_arg ~name:"ticketer" ~placeholder:"KT1...") - (config_key_arg ~name:"admin" ~placeholder:"KT1..") - (config_key_arg ~name:"sequencer_governance" ~placeholder:"KT1...") - (config_key_arg ~name:"kernel_governance" ~placeholder:"KT1...") - (config_key_arg - ~name:"kernel_security_governance" - ~placeholder:"KT1...") - (config_key_arg - ~name:"minimum_base_fee_per_gas" - ~placeholder:"111...") - (config_key_arg ~name:"da_fee_per_byte" ~placeholder:"111...") - (config_key_arg ~name:"delayed_inbox_timeout" ~placeholder:"111...") - (config_key_arg - ~name:"delayed_inbox_min_levels" - ~placeholder:"111...") - (config_key_arg ~name:"sequencer_pool_address" ~placeholder:"0x...") - (config_key_arg ~name:"maximum_allowed_ticks" ~placeholder:"11000...") - (config_key_arg - ~name:"maximum_gas_per_transaction" - ~placeholder:"30000...") - (config_key_arg - ~name:"max_blueprint_lookahead_in_seconds" - ~placeholder:"500") - (config_key_flag ~name:"remove_whitelist") - (Tezos_clic.default_arg - ~long:"bootstrap-balance" - ~doc:"balance of the bootstrap accounts" - ~default:"9999000000000000000000" - ~placeholder:"9999000000000000000000" - @@ Tezos_clic.parameter (fun _ s -> return @@ Z.of_string s)) - bootstrap_account_arg - set_account_code - (config_key_flag ~name:"enable_fa_bridge") - (config_key_flag ~name:"enable_dal") - (config_key_arg ~name:"dal_slots" ~placeholder:"0,1,4,6,...")) - (args1 - (config_key_arg - ~name:"max_delayed_inbox_blueprint_length" - ~placeholder:"1000"))) + (args13 + mainnet_compat_arg + (config_key_arg ~name:"ticketer" ~placeholder:"KT1...") + (config_key_arg ~name:"minimum_base_fee_per_gas" ~placeholder:"111...") + (config_key_arg ~name:"da_fee_per_byte" ~placeholder:"111...") + (config_key_arg ~name:"delayed_inbox_timeout" ~placeholder:"111...") + (config_key_arg ~name:"delayed_inbox_min_levels" ~placeholder:"111...") + (config_key_arg ~name:"sequencer_pool_address" ~placeholder:"0x...") + (config_key_arg + ~name:"maximum_gas_per_transaction" + ~placeholder:"30000...") + (Tezos_clic.default_arg + ~long:"bootstrap-balance" + ~doc:"balance of the bootstrap accounts" + ~default:"9999000000000000000000" + ~placeholder:"9999000000000000000000" + @@ Tezos_clic.parameter (fun _ s -> return @@ Z.of_string s)) + bootstrap_account_arg + set_account_code + (config_key_arg + ~name:"max_delayed_inbox_blueprint_length" + ~placeholder:"1000") + chain_id_arg) + (prefixes ["make"; "l2"; "kernel"; "installer"; "config"] + @@ param + ~name:"kernel config file" + ~desc:"file path where the config will be written to" + Params.string + @@ stop) + (fun ( mainnet_compat, + ticketer, + minimum_base_fee_per_gas, + da_fee_per_byte, + delayed_inbox_timeout, + delayed_inbox_min_levels, + sequencer_pool_address, + maximum_gas_per_transaction, + boostrap_balance, + bootstrap_accounts, + set_account_code, + max_delayed_inbox_blueprint_length, + l2_chain_id ) + output + () -> + let l2_chain_id = Option.fold ~none:"1" ~some:string_of_int l2_chain_id in + Evm_node_lib_dev.Kernel_config.make_l2 + ~mainnet_compat + ?ticketer + ?minimum_base_fee_per_gas + ?da_fee_per_byte + ?delayed_inbox_timeout + ?delayed_inbox_min_levels + ?sequencer_pool_address + ?maximum_gas_per_transaction + ~boostrap_balance + ?bootstrap_accounts + ?set_account_code + ?max_delayed_inbox_blueprint_length + ~l2_chain_id + ~output + ()) + +let make_kernel_config_command = + let open Tezos_clic in + command + ~desc:"Transforms the JSON list of instructions to a RLP list" + (args15 + mainnet_compat_arg + (config_key_arg ~name:"kernel_root_hash" ~placeholder:"root hash") + multiple_chains_arg + (config_key_arg ~name:"sequencer" ~placeholder:"edpk...") + (config_key_arg ~name:"delayed_bridge" ~placeholder:"edpk...") + (config_key_arg ~name:"admin" ~placeholder:"KT1..") + (config_key_arg ~name:"sequencer_governance" ~placeholder:"KT1...") + (config_key_arg ~name:"kernel_governance" ~placeholder:"KT1...") + (config_key_arg ~name:"kernel_security_governance" ~placeholder:"KT1...") + (config_key_arg ~name:"maximum_allowed_ticks" ~placeholder:"11000...") + (config_key_arg + ~name:"max_blueprint_lookahead_in_seconds" + ~placeholder:"500") + (config_key_flag ~name:"remove_whitelist") + (config_key_flag ~name:"enable_fa_bridge") + (config_key_flag ~name:"enable_dal") + (config_key_arg ~name:"dal_slots" ~placeholder:"0,1,4,6,...")) (prefixes ["make"; "kernel"; "installer"; "config"] @@ param ~name:"kernel config file" ~desc:"file path where the config will be written to" Params.string @@ stop) - (fun ( ( mainnet_compat, - kernel_root_hash, - chain_id, - sequencer, - delayed_bridge, - ticketer, - admin, - sequencer_governance, - kernel_governance, - kernel_security_governance, - minimum_base_fee_per_gas, - da_fee_per_byte, - delayed_inbox_timeout, - delayed_inbox_min_levels, - sequencer_pool_address, - maximum_allowed_ticks, - maximum_gas_per_transaction, - max_blueprint_lookahead_in_seconds, - remove_whitelist, - boostrap_balance, - bootstrap_accounts, - set_account_code, - enable_fa_bridge, - enable_dal, - dal_slots ), - max_delayed_inbox_blueprint_length ) + (fun ( mainnet_compat, + kernel_root_hash, + l2_chain_ids, + sequencer, + delayed_bridge, + admin, + sequencer_governance, + kernel_governance, + kernel_security_governance, + maximum_allowed_ticks, + max_blueprint_lookahead_in_seconds, + remove_whitelist, + enable_fa_bridge, + enable_dal, + dal_slots ) output () -> Evm_node_lib_dev.Kernel_config.make ~mainnet_compat ?kernel_root_hash - ?chain_id + ?l2_chain_ids ?sequencer ?delayed_bridge - ?ticketer ?admin ?sequencer_governance ?kernel_governance ?kernel_security_governance - ?minimum_base_fee_per_gas - ?da_fee_per_byte - ?delayed_inbox_timeout - ?delayed_inbox_min_levels - ?sequencer_pool_address ?maximum_allowed_ticks - ?maximum_gas_per_transaction ?max_blueprint_lookahead_in_seconds ?remove_whitelist - ~boostrap_balance - ?bootstrap_accounts ?enable_fa_bridge ?enable_dal ?dal_slots - ?set_account_code - ?max_delayed_inbox_blueprint_length ~output ()) let proxy_command = let open Tezos_clic in - let open Evm_node_lib_dev_encoding in command ~desc:"Start the EVM node in proxy mode." (merge_options @@ -1955,56 +2050,51 @@ let proxy_command = rpc_batch_limit, cors_origins, cors_headers, + l2_chain_ids, log_filter_max_nb_blocks, log_filter_max_nb_logs, log_filter_chunk_size, keep_alive, rollup_node_endpoint, - tx_pool_timeout_limit, - tx_pool_addr_limit, - tx_pool_tx_per_addr_limit, verbose, restricted_rpcs, - blacklisted_rpcs, whitelisted_rpcs, + blacklisted_rpcs, finalized_view ), (read_only, ignore_block_param, evm_node_endpoint) ) () -> let open Lwt_result_syntax in + let* l2_chain_ids = string_to_l2_chain_ids l2_chain_ids in let* restricted_rpcs = pick_restricted_rpcs restricted_rpcs whitelisted_rpcs blacklisted_rpcs in start_proxy ~data_dir - ~l2_chain_id:(L2_chain_id.from_int 1) - ~keep_alive + ~l2_chain_ids ?rpc_addr ?rpc_port ?rpc_batch_limit ?cors_origins ?cors_headers + ~keep_alive ?log_filter_max_nb_blocks ?log_filter_max_nb_logs ?log_filter_chunk_size ?rollup_node_endpoint ?evm_node_endpoint - ?tx_pool_timeout_limit - ?tx_pool_addr_limit - ?tx_pool_tx_per_addr_limit - ?restricted_rpcs ~verbose ~read_only + ?restricted_rpcs ~finalized_view ~ignore_block_param ()) let sequencer_config_args = - Tezos_clic.args15 + Tezos_clic.args14 preimages_arg preimages_endpoint_arg time_between_blocks_arg max_number_of_chunks_arg - private_rpc_port_arg sequencer_key_arg maximum_blueprints_lag_arg maximum_blueprints_ahead_arg @@ -2017,13 +2107,12 @@ let sequencer_config_args = dal_slots_arg let sandbox_config_args = - Tezos_clic.args10 + Tezos_clic.args9 preimages_arg preimages_endpoint_arg native_execution_policy_arg time_between_blocks_arg max_number_of_chunks_arg - private_rpc_port_arg genesis_timestamp_arg initial_kernel_arg wallet_dir_arg @@ -2031,7 +2120,6 @@ let sandbox_config_args = let sequencer_command = let open Tezos_clic in - let open Evm_node_lib_dev_encoding in command ~desc:"Start the EVM node in sequencer mode" (merge_options common_config_args sequencer_config_args) @@ -2042,24 +2130,21 @@ let sequencer_command = rpc_batch_limit, cors_origins, cors_headers, + l2_chain_ids, log_filter_max_nb_blocks, log_filter_max_nb_logs, log_filter_chunk_size, keep_alive, rollup_node_endpoint, - tx_pool_timeout_limit, - tx_pool_addr_limit, - tx_pool_tx_per_addr_limit, verbose, restricted_rpcs, - blacklisted_rpcs, whitelisted_rpcs, + blacklisted_rpcs, finalized_view ), ( preimages, preimages_endpoint, time_between_blocks, max_number_of_chunks, - private_rpc_port, sequencer_str, max_blueprints_lag, max_blueprints_ahead, @@ -2072,6 +2157,7 @@ let sequencer_command = dal_slots ) ) () -> let open Lwt_result_syntax in + let* l2_chain_ids = string_to_l2_chain_ids l2_chain_ids in let* restricted_rpcs = pick_restricted_rpcs restricted_rpcs whitelisted_rpcs blacklisted_rpcs in @@ -2079,15 +2165,12 @@ let sequencer_command = ?password_filename ~wallet_dir ~data_dir - ~l2_chain_id:(L2_chain_id.from_int 1) + ~l2_chain_ids ?rpc_addr ?rpc_port ?rpc_batch_limit ?cors_origins ?cors_headers - ?tx_pool_timeout_limit - ?tx_pool_addr_limit - ?tx_pool_tx_per_addr_limit ~keep_alive ?rollup_node_endpoint ~verbose @@ -2095,7 +2178,6 @@ let sequencer_command = ?preimages_endpoint ?time_between_blocks ?max_number_of_chunks - ?private_rpc_port ?sequencer_str ?max_blueprints_lag ?max_blueprints_ahead @@ -2113,7 +2195,6 @@ let sequencer_command = let sandbox_command = let open Tezos_clic in - let open Evm_node_lib_dev_encoding in command ~desc: "Start the EVM node in sandbox mode. The sandbox mode is a \ @@ -2127,53 +2208,48 @@ let sandbox_command = rpc_batch_limit, cors_origins, cors_headers, + l2_chain_ids, log_filter_max_nb_blocks, log_filter_max_nb_logs, log_filter_chunk_size, keep_alive, rollup_node_endpoint, - tx_pool_timeout_limit, - tx_pool_addr_limit, - tx_pool_tx_per_addr_limit, verbose, restricted_rpcs, - blacklisted_rpcs, whitelisted_rpcs, + blacklisted_rpcs, finalized_view ), ( preimages, preimages_endpoint, native_execution_policy, time_between_blocks, max_number_of_chunks, - private_rpc_port, genesis_timestamp, kernel, wallet_dir, password_filename ) ) () -> - let open Lwt_result_syntax in - let* restricted_rpcs = - pick_restricted_rpcs restricted_rpcs whitelisted_rpcs blacklisted_rpcs - in let _pkh, pk, sk = Tezos_crypto.Signature.(generate_key ~algo:Ed25519) () in let rollup_node_endpoint = Option.value ~default:Uri.empty rollup_node_endpoint in + let open Lwt_result_syntax in + let* l2_chain_ids = string_to_l2_chain_ids l2_chain_ids in + let* restricted_rpcs = + pick_restricted_rpcs restricted_rpcs whitelisted_rpcs blacklisted_rpcs + in start_sequencer ?password_filename ~wallet_dir ~data_dir - ~l2_chain_id:(L2_chain_id.from_int 1) + ~l2_chain_ids ?rpc_addr ?rpc_port ?rpc_batch_limit ?cors_origins ?cors_headers - ?tx_pool_timeout_limit - ?tx_pool_addr_limit - ?tx_pool_tx_per_addr_limit ~keep_alive ~rollup_node_endpoint ~verbose @@ -2182,7 +2258,6 @@ let sandbox_command = ?native_execution_policy ?time_between_blocks ?max_number_of_chunks - ?private_rpc_port ~max_blueprints_lag:100_000_000 ~max_blueprints_ahead:100_000_000 ~max_blueprints_catchup:100_000_000 @@ -2191,9 +2266,9 @@ let sandbox_command = ?log_filter_max_nb_logs ?log_filter_chunk_size ?genesis_timestamp - ?restricted_rpcs ?kernel ~sandbox_key:(pk, sk) + ?restricted_rpcs ~finalized_view ()) @@ -2215,7 +2290,6 @@ let observer_run_args = let observer_command = let open Tezos_clic in - let open Evm_node_lib_dev_encoding in command ~desc:"Start the EVM node in observer mode" (merge_options common_config_args observer_run_args) @@ -2226,18 +2300,16 @@ let observer_command = rpc_batch_limit, cors_origins, cors_headers, + l2_chain_ids, log_filter_max_nb_blocks, log_filter_max_nb_logs, log_filter_chunk_size, keep_alive, rollup_node_endpoint, - tx_pool_timeout_limit, - tx_pool_addr_limit, - tx_pool_tx_per_addr_limit, verbose, restricted_rpcs, - blacklisted_rpcs, whitelisted_rpcs, + blacklisted_rpcs, finalized_view ), ( evm_node_endpoint, threshold_encryption_bundler_endpoint, @@ -2250,10 +2322,6 @@ let observer_command = init_from_snapshot, network ) ) () -> - let open Lwt_result_syntax in - let* restricted_rpcs = - pick_restricted_rpcs restricted_rpcs whitelisted_rpcs blacklisted_rpcs - in let kernel = let open Evm_node_lib_dev.Wasm_debugger in Option.either @@ -2263,15 +2331,20 @@ let observer_command = Some (In_memory Evm_node_supported_installers.mainnet) | Testnet -> None)) in + let open Lwt_result_syntax in + let* l2_chain_ids = string_to_l2_chain_ids l2_chain_ids in + let* restricted_rpcs = + pick_restricted_rpcs restricted_rpcs whitelisted_rpcs blacklisted_rpcs + in start_observer ~data_dir - ~l2_chain_id:(L2_chain_id.from_int 1) - ~keep_alive + ~l2_chain_ids ?rpc_addr ?rpc_port ?rpc_batch_limit ?cors_origins ?cors_headers + ~keep_alive ~verbose ?preimages ?preimages_endpoint @@ -2280,16 +2353,13 @@ let observer_command = ~dont_track_rollup_node ?evm_node_endpoint ?threshold_encryption_bundler_endpoint - ?tx_pool_timeout_limit - ?tx_pool_addr_limit - ?tx_pool_tx_per_addr_limit ?log_filter_chunk_size ?log_filter_max_nb_logs ?log_filter_max_nb_blocks - ?restricted_rpcs ?kernel ~no_sync ~init_from_snapshot + ?restricted_rpcs ~finalized_view ?network ()) @@ -2395,14 +2465,14 @@ let snapshot_info_command = let patch_state_command = let open Tezos_clic in let open Lwt_result_syntax in - let open Evm_node_lib_dev_encoding in command ~desc: "Patches the state with an arbitrary value. This is an unsafe command, \ it should be used for debugging only. Patched state is persisted and \ you need to use the command `reset` to revert the changes." - (args3 + (args4 data_dir_arg + multiple_chains_arg (block_number_arg ~doc: "If provided, the state resulting in the application of the \ @@ -2413,17 +2483,18 @@ let patch_state_command = @@ prefixes ["with"] @@ param ~name:"value" ~desc:"Patched value" Params.hex_string @@ stop) - (fun (data_dir, block_number, force) key value () -> + (fun (data_dir, l2_chain_ids, block_number, force) key value () -> let open Evm_node_lib_dev in let*! () = let open Tezos_base_unix.Internal_event_unix in let config = make_with_defaults ~verbosity:Warning () in init ~config () in + let* l2_chain_ids = string_to_l2_chain_ids l2_chain_ids in let* configuration = Cli.create_or_read_config ~data_dir - ~l2_chain_id:(L2_chain_id.from_int 0) + ~l2_chain_ids ~keep_alive:false ~verbose:false ~finalized_view:false @@ -2442,11 +2513,11 @@ let patch_state_command = let preemptive_kernel_download_command = let open Tezos_clic in - let open Evm_node_lib_dev_encoding in command ~desc:"Transforms the JSON list of instructions to a RLP list" - (args4 + (args5 data_dir_arg + multiple_chains_arg preimages_arg preimages_endpoint_arg num_download_retries) @@ -2457,14 +2528,19 @@ let preemptive_kernel_download_command = (Tezos_clic.parameter (fun _ str -> Lwt_result_syntax.return @@ `Hex str)) @@ stop) - (fun (data_dir, preimages, preimages_endpoint, num_download_retries) + (fun ( data_dir, + l2_chain_ids, + preimages, + preimages_endpoint, + num_download_retries ) root_hash () -> let open Lwt_result_syntax in + let* l2_chain_ids = string_to_l2_chain_ids l2_chain_ids in let* configuration = Cli.create_or_read_config ~data_dir - ~l2_chain_id:(L2_chain_id.from_int 1) + ~l2_chain_ids ~keep_alive:false ~verbose:false ?preimages @@ -2541,9 +2617,11 @@ let commands = replay_command; patch_kernel_command; init_config_command; + init_chain_config_command; check_config_command; describe_config_command; make_kernel_config_command; + make_l2_kernel_config_command; patch_state_command; preemptive_kernel_download_command; debug_print_store_schemas_command; diff --git a/etherlink/kernel_evm/evm_evaluation/src/evalhost.rs b/etherlink/kernel_evm/evm_evaluation/src/evalhost.rs index 1874941a2ee44109db853f7477e8a5eb1af84896..05c7cdb25ad099107d70a79326936fe2e761e9ba 100644 --- a/etherlink/kernel_evm/evm_evaluation/src/evalhost.rs +++ b/etherlink/kernel_evm/evm_evaluation/src/evalhost.rs @@ -40,14 +40,12 @@ const WORLD_STATE_PATH: RefPath = RefPath::assert_from(b"/evm/world_state" const TRACE_PATH: RefPath = RefPath::assert_from(b"/evm/trace"); fn world_state_path(p: &impl Path) -> Result, RuntimeError> { - concat(&WORLD_STATE_PATH, p) - .map_err(|_| RuntimeError::PathNotFound(format!("{} + {}", WORLD_STATE_PATH, p))) + concat(&WORLD_STATE_PATH, p).map_err(|_| RuntimeError::PathNotFound) } fn trace_path(p: &TracePath) -> Result, RuntimeError> { let TracePath(p) = p; - concat(&TRACE_PATH, p) - .map_err(|_| RuntimeError::PathNotFound(format!("{} + {}", TRACE_PATH, p))) + concat(&TRACE_PATH, p).map_err(|_| RuntimeError::PathNotFound) } impl<'a> SdkRuntime for EvalHost<'a> { diff --git a/etherlink/kernel_evm/evm_execution/src/account_storage.rs b/etherlink/kernel_evm/evm_execution/src/account_storage.rs index e608be1ad671fd55e931b17cdc95843d70b58d75..ec13d19d44c742818e6201fea098feebfe8b3185 100644 --- a/etherlink/kernel_evm/evm_execution/src/account_storage.rs +++ b/etherlink/kernel_evm/evm_execution/src/account_storage.rs @@ -472,7 +472,7 @@ impl EthereumAccount { // would be dead code. match host.store_read_all(&path) { Ok(bytes) => Ok(bytes), - Err(RuntimeError::PathNotFound(_)) => { + Err(RuntimeError::PathNotFound) => { let code_hash = self.code_hash(host)?; code_storage::CodeStorage::get_code(host, &code_hash).map_err(Into::into) } diff --git a/etherlink/kernel_evm/evm_execution/src/lib.rs b/etherlink/kernel_evm/evm_execution/src/lib.rs index 1ac4bf57cf7eb5dfa3fcede1a47f0f89c928c017..9687881bbe282bf3a66c023522d310950c8468ba 100755 --- a/etherlink/kernel_evm/evm_execution/src/lib.rs +++ b/etherlink/kernel_evm/evm_execution/src/lib.rs @@ -52,7 +52,7 @@ use trace::{ use crate::storage::tracer; -#[derive(Error, Clone, Debug, Eq, PartialEq)] +#[derive(Error, Clone, Copy, Debug, Eq, PartialEq)] pub enum DurableStorageError { /// Some runtime error happened while using durable storage #[error("Runtime error: {0:?}")] diff --git a/etherlink/kernel_evm/indexable_storage/src/lib.rs b/etherlink/kernel_evm/indexable_storage/src/lib.rs index a98a53293f59a9e24820184c5b4701a192b6051d..8a83012e4b9615f01e259701d32bfc48baf64d66 100644 --- a/etherlink/kernel_evm/indexable_storage/src/lib.rs +++ b/etherlink/kernel_evm/indexable_storage/src/lib.rs @@ -107,7 +107,7 @@ impl IndexableStorage { Ok(l) => Ok(l), Err( GenStorageError::Runtime( - RuntimeError::PathNotFound(_) + RuntimeError::PathNotFound | RuntimeError::HostErr(tezos_smart_rollup_host::Error::StoreNotAValue) | RuntimeError::HostErr( tezos_smart_rollup_host::Error::StoreInvalidAccess, diff --git a/etherlink/kernel_evm/kernel/src/block.rs b/etherlink/kernel_evm/kernel/src/block.rs index dfd0a67e72f4224479a227debe5676d03272a69b..fecc48b55adb91fdbef57380f815e8cbd749ee64 100644 --- a/etherlink/kernel_evm/kernel/src/block.rs +++ b/etherlink/kernel_evm/kernel/src/block.rs @@ -466,7 +466,7 @@ fn promote_block>( store_last_block_timestamp(host, ¤t_timestamp)?; Ok(()) } - Err(Error::Storage(StorageError::Runtime(PathNotFound(_)))) => { + Err(Error::Storage(StorageError::Runtime(PathNotFound))) => { // Blueprint has already been dropped, this means that a // block at this level has already been promoted for // another chain id so next blueprint number and last @@ -476,6 +476,7 @@ fn promote_block>( err => err, }?; + log!(host, Info, "Path absolute: {:?}", world_state_path); let mut relative_runtime = RelativeRuntime { root: world_state_path, host, @@ -507,7 +508,8 @@ const AT_MOST_ONE_BLOCK: RefPath = RefPath::assert_from(b"/__at_most_one_b pub fn world_state(chain_id: &U256) -> Result, Error> { let chain_id_path: Vec = (format!("/{}", chain_id)).into(); let chain_id_path: RefPath = RefPath::::assert_from(&chain_id_path); - Ok(concat(&WORLD_STATE_PATH, &chain_id_path)?) + let path = concat(&WORLD_STATE_PATH, &chain_id_path)?; + Ok(path) } pub fn produce>( diff --git a/etherlink/kernel_evm/kernel/src/block_in_progress.rs b/etherlink/kernel_evm/kernel/src/block_in_progress.rs index 25a44aa671a3ecf1065f1b6fde45ab447095435e..3f92fa29e20345680e03a830b43940d26a796d79 100644 --- a/etherlink/kernel_evm/kernel/src/block_in_progress.rs +++ b/etherlink/kernel_evm/kernel/src/block_in_progress.rs @@ -466,6 +466,7 @@ impl BlockInProgress { block_constants, base_fee_per_gas, ); + log!(host, Info, "Stocke current block {:?}", new_block); block_storage::store_current(host, &new_block) .context("Failed to store the current block")?; Ok(new_block) diff --git a/etherlink/kernel_evm/kernel/src/block_storage.rs b/etherlink/kernel_evm/kernel/src/block_storage.rs index 9f4d6e9e5eef8dcbdacb10913a801e0953334fdd..3e0a5347252e470d73d6ff6f60dff07787cbf19a 100644 --- a/etherlink/kernel_evm/kernel/src/block_storage.rs +++ b/etherlink/kernel_evm/kernel/src/block_storage.rs @@ -4,7 +4,7 @@ use crate::Timestamp; use primitive_types::{H256, U256}; -use tezos_ethereum::block::L2Block; +use tezos_ethereum::block::{self, L2Block}; use tezos_ethereum::rlp_helpers::VersionedEncoding; use tezos_evm_logging::{ log, @@ -51,6 +51,13 @@ fn store_current_number( } fn store_current_hash(host: &mut impl Runtime, hash: H256) -> anyhow::Result<()> { + log!( + host, + Info, + "READ CURRENT NUMBER: {:?} {:?}", + path::CURRENT_HASH, + hash + ); write_h256_be(host, &path::CURRENT_HASH, hash) } @@ -66,6 +73,7 @@ fn store_block( index.push_value(host, block.hash.as_bytes())?; } let path = path::path(block.hash)?; + log!(host, Info, "Store at Block path: {:?}", path); let bytes = block.to_bytes(); Ok(host.store_write_all(&path, &bytes)?) } @@ -109,12 +117,21 @@ pub fn read_current_number(host: &impl Runtime) -> anyhow::Result { } pub fn read_current_hash(host: &impl Runtime) -> anyhow::Result { - read_h256_be(host, &path::CURRENT_HASH) + let current_hash = read_h256_be(host, &path::CURRENT_HASH); + log!( + host, + Info, + "READ CURRENT HASH: {:?} {:?}", + path::CURRENT_HASH, + current_hash + ); + current_hash } pub fn read_current(host: &mut impl Runtime) -> anyhow::Result { let hash = read_current_hash(host)?; let block_path = path::path(hash)?; + log!(host, Info, "Read at Block path: {:?}", block_path); let bytes = &host.store_read_all(&block_path)?; let block_from_bytes = L2Block::from_bytes(bytes)?; Ok(block_from_bytes) diff --git a/etherlink/kernel_evm/kernel/src/blueprint_storage.rs b/etherlink/kernel_evm/kernel/src/blueprint_storage.rs index ff3f0ed55682502c54a8b93982c19c649a6c6b2d..2586672b85a0cdf1ec1870211295fd0a4be93407 100644 --- a/etherlink/kernel_evm/kernel/src/blueprint_storage.rs +++ b/etherlink/kernel_evm/kernel/src/blueprint_storage.rs @@ -3,7 +3,7 @@ // // SPDX-License-Identifier: MIT -use crate::block::GENESIS_PARENT_HASH; +use crate::block::{world_state, GENESIS_PARENT_HASH}; use crate::block_storage; use crate::blueprint::Blueprint; use crate::configuration::{Configuration, ConfigurationMode}; @@ -22,6 +22,7 @@ use sha3::{Digest, Keccak256}; use tezos_ethereum::rlp_helpers; use tezos_ethereum::tx_common::EthereumTransactionCommon; use tezos_evm_logging::{log, Level::*, Verbosity}; +use tezos_evm_runtime::relative_runtime::RelativeRuntime; use tezos_evm_runtime::{ runtime::Runtime, safe_storage::{SafeStorage, WORLD_STATE_PATH}, @@ -186,7 +187,7 @@ pub fn read_next_blueprint_number>( host: &Host, ) -> anyhow::Result { match read_u256_le(host, &NEXT_BLUEPRINT_NUMBER) { - Err(GenStorageError::Runtime(RuntimeError::PathNotFound(_))) => Ok(U256::zero()), + Err(GenStorageError::Runtime(RuntimeError::PathNotFound)) => Ok(U256::zero()), res => Ok(res?), } } @@ -316,13 +317,15 @@ fn parse_and_validate_blueprint>( current_blueprint_size: usize, evm_node_flag: bool, max_blueprint_lookahead_in_seconds: i64, + chain_id: &U256, ) -> anyhow::Result<(BlueprintValidity, usize)> { // Decode match rlp::decode::(bytes) { Err(e) => Ok((BlueprintValidity::DecoderError(e), bytes.len())), Ok(blueprint_with_hashes) => { - let mut host = SafeStorage { - root: WORLD_STATE_PATH.into(), + log!(host, Info, "{:?}", blueprint_with_hashes); + let mut host = RelativeRuntime { + root: world_state(chain_id)?, host, }; let head = block_storage::read_current(&mut host); @@ -410,6 +413,7 @@ fn read_all_chunks_and_validate>( blueprint_path: &OwnedPath, nb_chunks: u16, config: &mut Configuration, + chain_id: &U256, ) -> anyhow::Result<(Option, usize)> { let mut chunks = vec![]; let mut size = 0; @@ -450,6 +454,7 @@ fn read_all_chunks_and_validate>( size, *evm_node_flag, *max_blueprint_lookahead_in_seconds, + chain_id, )?; if let (BlueprintValidity::Valid(blueprint), size_with_delayed_transactions) = validity @@ -489,8 +494,13 @@ pub fn read_next_blueprint>( let available_chunks = n_subkeys as u16 - 1; if available_chunks == nb_chunks { // All chunks are available - let (blueprint, size) = - read_all_chunks_and_validate(host, &blueprint_path, nb_chunks, config)?; + let (blueprint, size) = read_all_chunks_and_validate( + host, + &blueprint_path, + nb_chunks, + config, + chain_id, + )?; Ok((blueprint, size)) } else { if available_chunks > nb_chunks { @@ -623,6 +633,7 @@ mod tests { 0, false, 500, + &U256::one(), ) .expect("Should be able to parse blueprint"); assert_eq!( @@ -683,6 +694,7 @@ mod tests { 0, false, 500, + &U256::one(), ) .expect("Should be able to parse blueprint"); assert_eq!(validity.0, BlueprintValidity::InvalidParentHash); diff --git a/etherlink/kernel_evm/kernel/src/migration.rs b/etherlink/kernel_evm/kernel/src/migration.rs index d32d17945de0b8161d894a4257488213fb533496..16e8fdb1ba5c340bc82b268344da2c726563835b 100644 --- a/etherlink/kernel_evm/kernel/src/migration.rs +++ b/etherlink/kernel_evm/kernel/src/migration.rs @@ -52,7 +52,7 @@ fn is_etherlink_network( ) -> Result { match read_chain_id(host) { Ok(chain_id) => Ok(chain_id == expected_chain_id.into()), - Err(Error::Storage(StorageError::Runtime(RuntimeError::PathNotFound(_)))) => { + Err(Error::Storage(StorageError::Runtime(RuntimeError::PathNotFound))) => { Ok(false) } Err(err) => Err(err), @@ -63,7 +63,7 @@ fn is_etherlink_network( pub fn allow_path_not_found(res: Result<(), RuntimeError>) -> Result<(), RuntimeError> { match res { Ok(()) => Ok(()), - Err(RuntimeError::PathNotFound(_)) => Ok(()), + Err(RuntimeError::PathNotFound) => Ok(()), Err(err) => Err(err), } } diff --git a/etherlink/kernel_evm/runtime/src/relative_runtime.rs b/etherlink/kernel_evm/runtime/src/relative_runtime.rs index fbdc7ab465909b883a049c4be569bb406b29b0ab..bfbd6a351c394e55c18de2ce0841201f4a997252 100644 --- a/etherlink/kernel_evm/runtime/src/relative_runtime.rs +++ b/etherlink/kernel_evm/runtime/src/relative_runtime.rs @@ -5,7 +5,8 @@ use crate::extensions::WithGas; use crate::internal_runtime::{ExtendedRuntime, InternalRuntime}; use crate::runtime::{Runtime, TracePath, TraceRuntime}; -use tezos_evm_logging::Verbosity; +use tezos_evm_logging::Level::Info; +use tezos_evm_logging::{log, Verbosity}; use tezos_smart_rollup_core::PREIMAGE_HASH_SIZE; use tezos_smart_rollup_host::dal_parameters::RollupDalParameters; use tezos_smart_rollup_host::{ @@ -14,7 +15,6 @@ use tezos_smart_rollup_host::{ path::{concat, OwnedPath, Path}, runtime::{Runtime as SdkRuntime, RuntimeError, ValueType}, }; - pub struct RelativeRuntime { pub root: OwnedPath, pub host: Host, @@ -25,8 +25,7 @@ impl RelativeRuntime { &self, path: &impl Path, ) -> Result, RuntimeError> { - concat(&self.root, path) - .map_err(|_| RuntimeError::PathNotFound(format!("{}+{}", self.root, path))) + concat(&self.root, path).map_err(|_| RuntimeError::PathNotFound) } } @@ -94,6 +93,12 @@ impl> SdkRuntime for RelativeRuntime<&mut Host> { buffer: &mut [u8], ) -> Result { let path = self.absolute_path(path)?; + log!( + self.host, + Info, + "STORE READ ALL RELATIVE RUNTIME: {:?}", + path + ); self.host.store_read_slice(&path, from_offset, buffer) } diff --git a/etherlink/kernel_evm/runtime/src/runtime.rs b/etherlink/kernel_evm/runtime/src/runtime.rs index 54db8cb2d5a92e815a89afb7c5f678a70678bdb6..1617b1d41ef40f307102ab1a52457672010b3ff8 100644 --- a/etherlink/kernel_evm/runtime/src/runtime.rs +++ b/etherlink/kernel_evm/runtime/src/runtime.rs @@ -375,9 +375,8 @@ impl, Host: BorrowMut + Borrow, Internal: InternalRunt src: &[u8], ) -> Result<(), RuntimeError> { let TracePath(path) = path; - let absolute_path = concat(&TRACE_PATH, path).map_err(|_| { - RuntimeError::PathNotFound(format!("{}+{}", TRACE_PATH, path)) - })?; + let absolute_path = + concat(&TRACE_PATH, path).map_err(|_| RuntimeError::PathNotFound)?; self.store_write_all(&absolute_path, src) } } diff --git a/etherlink/kernel_evm/runtime/src/safe_storage.rs b/etherlink/kernel_evm/runtime/src/safe_storage.rs index 79cd115cdc106c4ca40856dfbbfa7bf6976beb91..2ba69c691938bf99b5f502552355ad3162e2fe1b 100644 --- a/etherlink/kernel_evm/runtime/src/safe_storage.rs +++ b/etherlink/kernel_evm/runtime/src/safe_storage.rs @@ -8,6 +8,7 @@ use crate::extensions::WithGas; use crate::internal_runtime::{ExtendedRuntime, InternalRuntime}; use crate::runtime::{Runtime, TracePath, TraceRuntime}; +use tezos_evm_logging::Level::Info; use tezos_evm_logging::{log, Level::Debug, Verbosity}; use tezos_smart_rollup_core::PREIMAGE_HASH_SIZE; use tezos_smart_rollup_host::dal_parameters::RollupDalParameters; @@ -26,15 +27,12 @@ pub const TRACE_PATH: RefPath = RefPath::assert_from(b"/evm/trace"); pub const TMP_TRACE_PATH: RefPath = RefPath::assert_from(b"/tmp/evm/trace"); pub fn safe_path(path: &impl Path) -> Result, RuntimeError> { - concat(&TMP_WORLD_STATE_PATH, path).map_err(|_| { - RuntimeError::PathNotFound(format!("{} + {}", TMP_WORLD_STATE_PATH, path)) - }) + concat(&TMP_WORLD_STATE_PATH, path).map_err(|_| RuntimeError::PathNotFound) } pub fn safe_trace_path(path: &TracePath) -> Result, RuntimeError> { let TracePath(path) = path; - concat(&TMP_TRACE_PATH, path) - .map_err(|_| RuntimeError::PathNotFound(format!("{} + {}", TMP_TRACE_PATH, path))) + concat(&TMP_TRACE_PATH, path).map_err(|_| RuntimeError::PathNotFound) } pub struct SafeStorage { @@ -106,6 +104,7 @@ impl> SdkRuntime for SafeStorage<&mut Host> { buffer: &mut [u8], ) -> Result { let path = safe_path(path)?; + log!(self.host, Info, "STORE READ ALL SAFE STORAGE: {:?}", path); self.host.store_read_slice(&path, from_offset, buffer) } @@ -258,11 +257,11 @@ impl> Verbosity for SafeStorage<&mut Host> { impl<'a, Host: Runtime> SafeStorage<&'a mut Host> { pub fn start(&mut self) -> Result<(), RuntimeError> { - log!(self, Debug, "Safe Storage: Start"); + log!(self, Info, "Safe Storage: Start"); match self.host.store_copy(&self.root, &TMP_WORLD_STATE_PATH) { // PathNotFound error means that self.root is empty, the // first write under TMP_WORLD_STATE_PATH will create it. - Ok(()) | Err(RuntimeError::PathNotFound(_)) => Ok(()), + Ok(()) | Err(RuntimeError::PathNotFound) => Ok(()), err => err, } } diff --git a/etherlink/kernel_evm/storage/src/lib.rs b/etherlink/kernel_evm/storage/src/lib.rs index aafc594585cdf8071bb09b434f8cb6f587ec4a63..276e3a97efafa2c641f819964cb9c104a138e2de 100644 --- a/etherlink/kernel_evm/storage/src/lib.rs +++ b/etherlink/kernel_evm/storage/src/lib.rs @@ -70,7 +70,7 @@ pub fn read_h256_be_opt( ) -> Result, Error> { match host.store_read_all(path) { Ok(bytes) if bytes.len() == WORD_SIZE => Ok(Some(H256::from_slice(&bytes))), - Ok(_) | Err(RuntimeError::PathNotFound(_)) => Ok(None), + Ok(_) | Err(RuntimeError::PathNotFound) => Ok(None), Err(err) => Err(err.into()), } } @@ -123,7 +123,7 @@ pub fn read_u256_le_default( ) -> Result { match host.store_read_all(path) { Ok(bytes) if bytes.len() == WORD_SIZE => Ok(U256::from_little_endian(&bytes)), - Ok(_) | Err(RuntimeError::PathNotFound(_)) => Ok(default), + Ok(_) | Err(RuntimeError::PathNotFound) => Ok(default), Err(err) => Err(err.into()), } } @@ -169,7 +169,7 @@ pub fn read_u64_le_default( .map_err(|_| Error::Runtime(RuntimeError::DecodingError))?; Ok(u64::from_le_bytes(bytes_array)) } - Ok(_) | Err(RuntimeError::PathNotFound(_)) => Ok(default), + Ok(_) | Err(RuntimeError::PathNotFound) => Ok(default), Err(err) => Err(err.into()), } } @@ -192,7 +192,7 @@ pub fn read_u16_le_default( .map_err(|_| Error::Runtime(RuntimeError::DecodingError))?; Ok(u16::from_le_bytes(bytes_array)) } - Ok(_) | Err(RuntimeError::PathNotFound(_)) => Ok(default), + Ok(_) | Err(RuntimeError::PathNotFound) => Ok(default), Err(err) => Err(err.into()), } } diff --git a/etherlink/tezt/lib/evm_node.ml b/etherlink/tezt/lib/evm_node.ml index 692008fc803df8846565ca75b4874dd7c11831b1..d95b38a9a76addcc264316d01d1258b1ada166bf 100644 --- a/etherlink/tezt/lib/evm_node.ml +++ b/etherlink/tezt/lib/evm_node.ml @@ -28,6 +28,17 @@ type time_between_blocks = Nothing | Time_between_blocks of float +type l2_chain_info = { + id : int; + restricted_rpcs : string option; + rpc_addr : string option; + rpc_port : int; + tx_pool_timeout_limit : int option; + tx_pool_addr_limit : int option; + tx_pool_tx_per_addr_limit : int option; + private_rpc_port : int option; +} + type mode = | Observer of { initial_kernel : string; @@ -54,9 +65,6 @@ type mode = catchup_cooldown : int option; max_number_of_chunks : int option; wallet_dir : string option; - tx_pool_timeout_limit : int option; - tx_pool_addr_limit : int option; - tx_pool_tx_per_addr_limit : int option; dal_slots : int list option; } | Sandbox of { @@ -67,9 +75,6 @@ type mode = genesis_timestamp : Client.timestamp option; max_number_of_chunks : int option; wallet_dir : string option; - tx_pool_timeout_limit : int option; - tx_pool_addr_limit : int option; - tx_pool_tx_per_addr_limit : int option; } | Threshold_encryption_sequencer of { initial_kernel : string; @@ -84,9 +89,6 @@ type mode = catchup_cooldown : int option; max_number_of_chunks : int option; wallet_dir : string option; - tx_pool_timeout_limit : int option; - tx_pool_addr_limit : int option; - tx_pool_tx_per_addr_limit : int option; sequencer_sidecar_endpoint : string; dal_slots : int list option; } @@ -95,6 +97,8 @@ type mode = module Per_level_map = Map.Make (Int) +let find_l2 id chains = List.find_opt (fun info -> info.id = id) chains + module Parameters = struct type persistent_state = { arguments : string list; @@ -107,12 +111,14 @@ module Parameters = struct mutable pending_blueprint_finalized : unit option Lwt.u list Per_level_map.t; mode : mode; + chains : l2_chain_info list; data_dir : string; rpc_addr : string; rpc_port : int; endpoint : string; runner : Runner.t option; restricted_rpcs : string option; + websockets : bool; } type session_state = {mutable ready : bool} @@ -549,7 +555,7 @@ let wait_for_rollup_node_ahead evm_node = let level = json |> as_int in Some level -let wait_for_tx_pool_add_transaction ?timeout evm_node = +let wait_for_tx_pool_add_transaction ?timeout ?l2_chain_id:_ evm_node = wait_for_event ?timeout evm_node ~event:"tx_pool_add_transaction.v0" @@ JSON.as_string_opt @@ -614,6 +620,18 @@ let wait_for_blueprint_injection_failure ?timeout ?level evm_node = if json |-> "level" |> as_int = expected_level then Some () else None | None -> Some () +let chain_with_new_private_rpc l2_chain_info = + match l2_chain_info.private_rpc_port with + | None -> l2_chain_info + | Some _ -> {l2_chain_info with private_rpc_port = Some (Port.fresh ())} + +let _node_with_new_private_rpc (evm_node : t) = + let chains = + List.map chain_with_new_private_rpc evm_node.persistent_state.chains + in + let persistent_state = {evm_node.persistent_state with chains} in + {evm_node with persistent_state} + let mode_with_new_private_rpc (mode : mode) = match mode with | Observer @@ -644,9 +662,6 @@ let mode_with_new_private_rpc (mode : mode) = catchup_cooldown; max_number_of_chunks; wallet_dir; - tx_pool_timeout_limit; - tx_pool_addr_limit; - tx_pool_tx_per_addr_limit; dal_slots; } -> Sequencer @@ -663,9 +678,6 @@ let mode_with_new_private_rpc (mode : mode) = catchup_cooldown; max_number_of_chunks; wallet_dir; - tx_pool_timeout_limit; - tx_pool_addr_limit; - tx_pool_tx_per_addr_limit; dal_slots; } | Sandbox @@ -677,9 +689,6 @@ let mode_with_new_private_rpc (mode : mode) = genesis_timestamp; max_number_of_chunks; wallet_dir; - tx_pool_timeout_limit; - tx_pool_addr_limit; - tx_pool_tx_per_addr_limit; } -> Sandbox { @@ -690,9 +699,6 @@ let mode_with_new_private_rpc (mode : mode) = genesis_timestamp; max_number_of_chunks; wallet_dir; - tx_pool_timeout_limit; - tx_pool_addr_limit; - tx_pool_tx_per_addr_limit; } | Threshold_encryption_sequencer { @@ -708,9 +714,6 @@ let mode_with_new_private_rpc (mode : mode) = catchup_cooldown; max_number_of_chunks; wallet_dir; - tx_pool_timeout_limit; - tx_pool_addr_limit; - tx_pool_tx_per_addr_limit; sequencer_sidecar_endpoint; dal_slots; } -> @@ -728,16 +731,14 @@ let mode_with_new_private_rpc (mode : mode) = catchup_cooldown; max_number_of_chunks; wallet_dir; - tx_pool_timeout_limit; - tx_pool_addr_limit; - tx_pool_tx_per_addr_limit; sequencer_sidecar_endpoint; dal_slots; } | _ -> mode let create ?(path = Uses.path Constant.octez_evm_node) ?name ?runner - ?(mode = Proxy) ?data_dir ?rpc_addr ?rpc_port ?restricted_rpcs endpoint = + ?(mode = Proxy) ?data_dir ?rpc_addr ?rpc_port ?restricted_rpcs + ?(websockets = false) ?(chains = []) endpoint = let arguments, rpc_addr, rpc_port = connection_arguments ?rpc_addr ?rpc_port ?runner () in @@ -756,7 +757,7 @@ let create ?(path = Uses.path Constant.octez_evm_node) ?name ?runner let data_dir = match data_dir with None -> Temp.dir name | Some dir -> dir in - let evm_node = + let evm_node : t = create ~path ~name @@ -774,8 +775,10 @@ let create ?(path = Uses.path Constant.octez_evm_node) ?name ?runner rpc_addr; rpc_port; endpoint; - restricted_rpcs; + chains; runner; + restricted_rpcs; + websockets; } in on_event evm_node (handle_is_ready_event evm_node) ; @@ -786,17 +789,33 @@ let create ?(path = Uses.path Constant.octez_evm_node) ?name ?runner let name evm_node = evm_node.name -let rpc_port evm_node = evm_node.persistent_state.rpc_port +let rpc_port ?chain_id evm_node = + let state = evm_node.persistent_state in + match chain_id with + | None -> state.rpc_port + | Some chain_id -> ( + let chain = find_l2 chain_id state.chains in + match chain with None -> assert false | Some chain -> chain.rpc_port) let data_dir evm_node = evm_node.persistent_state.data_dir let data_dir_arg evm_node = ["--data-dir"; evm_node.persistent_state.data_dir] +let l2_chain_ids_arg evm_node = + let l2_chain_ids = + List.map + (fun l2_chain_info -> + Cli_arg.optional_arg "l2-chain-id" string_of_int (Some l2_chain_info.id)) + evm_node.persistent_state.chains + in + List.flatten l2_chain_ids + (* assume a valid config for the given command and uses new latest run command format. *) let run_args evm_node = let shared_args = - data_dir_arg evm_node @ evm_node.persistent_state.arguments + data_dir_arg evm_node @ l2_chain_ids_arg evm_node + @ evm_node.persistent_state.arguments in let mode_args = match evm_node.persistent_state.mode with @@ -941,13 +960,45 @@ let spawn_init_config_minimal ~data_dir @@ ["init"; "config"; "--data-dir"; data_dir] @ extra_arguments -let spawn_init_config ?(extra_arguments = []) evm_node = - let shared_args = - data_dir_arg evm_node @ evm_node.persistent_state.arguments +let spawn_init_l2_config ?(path = Uses.(path Constant.octez_evm_node)) + ?(extra_arguments = []) ~data_dir l2_chain_info = + let arguments = + Cli_arg.optional_arg + "tx-pool-addr-limit" + Int.to_string + l2_chain_info.tx_pool_addr_limit + @ Cli_arg.optional_arg + "tx-pool-timeout-limit" + Int.to_string + l2_chain_info.tx_pool_timeout_limit + @ Cli_arg.optional_arg + "tx-pool-tx-per-addr-limit" + Int.to_string + l2_chain_info.tx_pool_tx_per_addr_limit @ Cli_arg.optional_arg "restricted-rpcs" Fun.id - evm_node.persistent_state.restricted_rpcs + l2_chain_info.restricted_rpcs + @ Cli_arg.optional_arg "rpc-addr" Fun.id l2_chain_info.rpc_addr + @ Cli_arg.optional_arg + "private-rpc-port" + Int.to_string + l2_chain_info.private_rpc_port + @ [ + "--rpc-port"; + Int.to_string l2_chain_info.rpc_port; + "--l2-chain-id"; + Int.to_string l2_chain_info.id; + ] + in + Process.spawn ~name:"evm_node_init_config" path + @@ ["init"; "chain"; "config"; "--data-dir"; data_dir] + @ arguments @ extra_arguments + +let spawn_init_config ?(extra_arguments = []) evm_node = + let shared_args = + data_dir_arg evm_node @ l2_chain_ids_arg evm_node + @ evm_node.persistent_state.arguments in let time_between_blocks_fmt = function | Nothing -> "none" @@ -971,9 +1022,6 @@ let spawn_init_config ?(extra_arguments = []) evm_node = catchup_cooldown; max_number_of_chunks; wallet_dir; - tx_pool_timeout_limit; - tx_pool_addr_limit; - tx_pool_tx_per_addr_limit; dal_slots; } -> [ @@ -1009,18 +1057,6 @@ let spawn_init_config ?(extra_arguments = []) evm_node = string_of_int max_number_of_chunks @ Cli_arg.optional_arg "wallet-dir" Fun.id wallet_dir - @ Cli_arg.optional_arg - "tx-pool-timeout-limit" - string_of_int - tx_pool_timeout_limit - @ Cli_arg.optional_arg - "tx-pool-addr-limit" - string_of_int - tx_pool_addr_limit - @ Cli_arg.optional_arg - "tx-pool-tx-per-addr-limit" - string_of_int - tx_pool_tx_per_addr_limit @ Cli_arg.optional_arg "dal-slots" (fun l -> String.concat "," (List.map string_of_int l)) @@ -1034,9 +1070,6 @@ let spawn_init_config ?(extra_arguments = []) evm_node = genesis_timestamp = _; max_number_of_chunks; wallet_dir; - tx_pool_timeout_limit; - tx_pool_addr_limit; - tx_pool_tx_per_addr_limit; } -> [ (* These two fields are not necessary for the sandbox mode, however, @@ -1057,18 +1090,6 @@ let spawn_init_config ?(extra_arguments = []) evm_node = string_of_int max_number_of_chunks @ Cli_arg.optional_arg "wallet-dir" Fun.id wallet_dir - @ Cli_arg.optional_arg - "tx-pool-timeout-limit" - string_of_int - tx_pool_timeout_limit - @ Cli_arg.optional_arg - "tx-pool-addr-limit" - string_of_int - tx_pool_addr_limit - @ Cli_arg.optional_arg - "tx-pool-tx-per-addr-limit" - string_of_int - tx_pool_tx_per_addr_limit | Threshold_encryption_sequencer { initial_kernel = _; @@ -1083,9 +1104,6 @@ let spawn_init_config ?(extra_arguments = []) evm_node = catchup_cooldown; max_number_of_chunks; wallet_dir; - tx_pool_timeout_limit; - tx_pool_addr_limit; - tx_pool_tx_per_addr_limit; sequencer_sidecar_endpoint; dal_slots; } -> @@ -1124,18 +1142,6 @@ let spawn_init_config ?(extra_arguments = []) evm_node = string_of_int max_number_of_chunks @ Cli_arg.optional_arg "wallet-dir" Fun.id wallet_dir - @ Cli_arg.optional_arg - "tx-pool-timeout-limit" - string_of_int - tx_pool_timeout_limit - @ Cli_arg.optional_arg - "tx-pool-addr-limit" - string_of_int - tx_pool_addr_limit - @ Cli_arg.optional_arg - "tx-pool-tx-per-addr-limit" - string_of_int - tx_pool_tx_per_addr_limit @ Cli_arg.optional_arg "dal-slots" (fun l -> String.concat "," (List.map string_of_int l)) @@ -1173,37 +1179,57 @@ let spawn_init_config ?(extra_arguments = []) evm_node = preimages_dir; ] in - spawn_command evm_node @@ ["init"; "config"] @ mode_args @ shared_args - @ extra_arguments - -let rpc_endpoint ?(local = false) ?(private_ = false) (evm_node : t) = + let* () = + Lwt_list.iter_p + (fun l2_chain -> + Process.check + @@ spawn_init_l2_config + ~data_dir:evm_node.persistent_state.data_dir + l2_chain) + evm_node.persistent_state.chains + in + Process.check @@ spawn_command evm_node @@ ["init"; "config"] @ mode_args + @ shared_args @ extra_arguments + +let rpc_endpoint ?(local = false) ?(private_ = false) ?l2_chain_id + (evm_node : t) = + let chain = + match l2_chain_id with + | None -> None + | Some l2_chain_id -> find_l2 l2_chain_id evm_node.persistent_state.chains + in let addr, port, path = let host = if local then Constant.default_host else Runner.address evm_node.persistent_state.runner in if private_ then - match evm_node.persistent_state.mode with - | Sequencer {private_rpc_port = Some private_rpc_port; _} - | Observer {private_rpc_port = Some private_rpc_port; _} - | Sandbox {private_rpc_port = Some private_rpc_port; _} -> + match (evm_node.persistent_state.mode, chain) with + | Sequencer _, Some {private_rpc_port = Some private_rpc_port; _} + | Observer _, Some {private_rpc_port = Some private_rpc_port; _} + | Sandbox _, Some {private_rpc_port = Some private_rpc_port; _} + | Sequencer {private_rpc_port = Some private_rpc_port; _}, None + | Observer {private_rpc_port = Some private_rpc_port; _}, None + | Sandbox {private_rpc_port = Some private_rpc_port; _}, None + | ( Threshold_encryption_sequencer + {private_rpc_port = Some private_rpc_port; _}, + None ) -> (host, private_rpc_port, "/private") - | Sequencer {private_rpc_port = None; _} - | Sandbox {private_rpc_port = None; _} -> + | Sequencer _, _ | Sandbox _, _ -> Test.fail "Sequencer doesn't have a private RPC server" - | Threshold_encryption_sequencer - {private_rpc_port = Some private_rpc_port; _} -> - (host, private_rpc_port, "/private") - | Threshold_encryption_sequencer {private_rpc_port = None; _} -> + | Threshold_encryption_sequencer _, _ -> Test.fail "Threshold encryption sequencer doesn't have a private RPC server" - | Proxy -> Test.fail "Proxy doesn't have a private RPC server" - | Observer _ -> Test.fail "Observer doesn't have a private RPC server" - | Rpc _ -> Test.fail "Rpc node doesn't have a private RPC server" - | Threshold_encryption_observer _ -> + | Proxy, _ -> Test.fail "Proxy doesn't have a private RPC server" + | Observer _, _ -> Test.fail "Observer doesn't have a private RPC server" + | Rpc _, _ -> Test.fail "Rpc node doesn't have a private RPC server" + | Threshold_encryption_observer _, _ -> Test.fail "Threshold encryption observer doesn't have a private RPC server" - else (host, evm_node.persistent_state.rpc_port, "") + else + match chain with + | None -> (host, evm_node.persistent_state.rpc_port, "") + | Some chain -> (host, chain.rpc_port, "") in Format.sprintf "http://%s:%d%s" addr port path @@ -1290,10 +1316,39 @@ let patch_config_with_experimental_feature ~name:"monitor_websocket_heartbeat" (`O [("ping_interval", `Float 0.5); ("ping_timeout", `Float 2.)]) -let init ?patch_config ?name ?runner ?mode ?data_dir ?rpc_addr ?rpc_port - ?restricted_rpcs rollup_node = +let create_l2 ?restricted_rpcs ?rpc_addr ?rpc_port ?tx_pool_timeout_limit + ?tx_pool_addr_limit ?tx_pool_tx_per_addr_limit ?private_rpc_port + ~l2_chain_id () = + let rpc_port = Option.value rpc_port ~default:(Port.fresh ()) in + { + id = l2_chain_id; + restricted_rpcs; + rpc_addr; + rpc_port; + tx_pool_timeout_limit; + tx_pool_addr_limit; + tx_pool_tx_per_addr_limit; + private_rpc_port; + } + +let init ?patch_config ?tx_pool_timeout_limit ?tx_pool_addr_limit + ?tx_pool_tx_per_addr_limit ?name ?runner ?mode ?data_dir ?rpc_addr ?rpc_port + ?restricted_rpcs ?websockets ~l2_chain_ids rollup_node = + let l2_chains = + List.map + (fun l2_chain_id -> + create_l2 + ?tx_pool_timeout_limit + ?tx_pool_addr_limit + ?tx_pool_tx_per_addr_limit (* TODO Don't have private rpc for each *) + ~private_rpc_port:(Port.fresh ()) + ~l2_chain_id + ()) + l2_chain_ids + in let evm_node = create + ~chains:l2_chains ?name ?runner ?mode @@ -1301,9 +1356,10 @@ let init ?patch_config ?name ?runner ?mode ?data_dir ?rpc_addr ?rpc_port ?rpc_addr ?rpc_port ?restricted_rpcs + ?websockets rollup_node in - let* () = Process.check @@ spawn_init_config evm_node in + let* () = spawn_init_config evm_node in let* () = match patch_config with | Some patch_config -> Config_file.update evm_node patch_config @@ -1344,20 +1400,27 @@ let batch_requests requests = (* We keep both encoding (with a single object or an array of objects) and both function on purpose, to ensure both encoding are supported by the server. *) -let call_evm_rpc ?(private_ = false) evm_node request = - let endpoint = endpoint ~private_ evm_node in +let call_evm_rpc ?(private_ = false) ?l2_chain_id evm_node request = + let l2_chain_id = + match l2_chain_id with + | None -> + let l2_chain = List.hd evm_node.persistent_state.chains in + l2_chain.id + | Some l2_chain_id -> l2_chain_id + in + let endpoint = endpoint ~private_ ~l2_chain_id evm_node in Curl.post endpoint (build_request request) |> Runnable.run -let batch_evm_rpc ?(private_ = false) evm_node requests = - let endpoint = endpoint ~private_ evm_node in +let batch_evm_rpc ?(private_ = false) ?l2_chain_id evm_node requests = + let endpoint = endpoint ~private_ ?l2_chain_id evm_node in let* json = Curl.post endpoint (batch_requests requests) |> Runnable.run in return (JSON.as_list json) -let open_websocket ?(private_ = false) evm_node = +let open_websocket ?(private_ = false) ?l2_chain_id evm_node = let kind = if private_ then "private" else "public" in Websocket.connect ~name:(String.concat "_" ["ws"; kind; evm_node.name]) - (endpoint ~private_ evm_node ^ "/ws") + (endpoint ~private_ ?l2_chain_id evm_node ^ "/ws") let call_evm_websocket websocket request = Websocket.send_recv websocket (build_request request) @@ -1370,23 +1433,24 @@ let batch_evm_websocket websocket requests = in Lwt_list.map_s (fun () -> Websocket.recv websocket) l -let jsonrpc ?websocket ?private_ evm_node = +let jsonrpc ?websocket ?private_ ?l2_chain_id evm_node = match websocket with - | None -> call_evm_rpc ?private_ evm_node + | None -> call_evm_rpc ?private_ ?l2_chain_id evm_node | Some ws -> call_evm_websocket ws -let batch_jsonrpc ?websocket ?private_ evm_node = +let batch_jsonrpc ?websocket ?private_ ?l2_chain_id evm_node = match websocket with - | None -> batch_evm_rpc ?private_ evm_node + | None -> batch_evm_rpc ?private_ ?l2_chain_id evm_node | Some ws -> batch_evm_websocket ws let extract_result json = JSON.(json |-> "result") let extract_error_message json = JSON.(json |-> "error" |-> "message") -let fetch_contract_code evm_node contract_address = +let fetch_contract_code ?l2_chain_id evm_node contract_address = let* code = call_evm_rpc + ?l2_chain_id evm_node { method_ = "eth_getCode"; @@ -1580,37 +1644,18 @@ let wait_termination (evm_node : t) = let ten_years_in_seconds = 3600 * 24 * 365 * 10 |> Int64.of_int -let make_kernel_installer_config ?max_delayed_inbox_blueprint_length - ?(mainnet_compat = false) ?(remove_whitelist = false) ?kernel_root_hash - ?chain_id ?bootstrap_balance ?bootstrap_accounts ?sequencer ?delayed_bridge - ?ticketer ?administrator ?sequencer_governance ?kernel_governance - ?kernel_security_governance ?minimum_base_fee_per_gas - ?(da_fee_per_byte = Wei.zero) ?delayed_inbox_timeout - ?delayed_inbox_min_levels ?sequencer_pool_address ?maximum_allowed_ticks - ?maximum_gas_per_transaction +let make_kernel_installer_config ?(mainnet_compat = false) + ?(remove_whitelist = false) ?kernel_root_hash ?(l2_chain_ids = []) + ?sequencer ?(delayed_bridges = []) ?administrator ?sequencer_governance + ?kernel_governance ?kernel_security_governance ?maximum_allowed_ticks ?(max_blueprint_lookahead_in_seconds = ten_years_in_seconds) - ?(set_account_code = []) ?(enable_fa_bridge = false) ?(enable_dal = false) - ?dal_slots ~output () = - let set_account_code = - List.flatten - @@ List.map - (fun (address, code) -> - ["--set-code"; Format.sprintf "%s,%s" address code]) - set_account_code - in + ?(enable_fa_bridge = false) ?(enable_dal = false) ?dal_slots ~output () = let cmd = ["make"; "kernel"; "installer"; "config"; output] - @ Cli_arg.optional_arg - "max-delayed-inbox-blueprint-length" - Int.to_string - max_delayed_inbox_blueprint_length @ Cli_arg.optional_switch "mainnet-compat" mainnet_compat @ Cli_arg.optional_switch "remove-whitelist" remove_whitelist @ Cli_arg.optional_arg "kernel-root-hash" Fun.id kernel_root_hash - @ Cli_arg.optional_arg "chain-id" string_of_int chain_id @ Cli_arg.optional_arg "sequencer" Fun.id sequencer - @ Cli_arg.optional_arg "delayed-bridge" Fun.id delayed_bridge - @ Cli_arg.optional_arg "ticketer" Fun.id ticketer @ Cli_arg.optional_arg "admin" Fun.id administrator @ Cli_arg.optional_arg "sequencer-governance" Fun.id sequencer_governance @ Cli_arg.optional_arg "kernel-governance" Fun.id kernel_governance @@ -1618,15 +1663,79 @@ let make_kernel_installer_config ?max_delayed_inbox_blueprint_length "kernel-security-governance" Fun.id kernel_security_governance + @ Cli_arg.optional_arg + "maximum-allowed-ticks" + Int64.to_string + maximum_allowed_ticks + @ [ + "--max-blueprint-lookahead-in-seconds"; + Int64.to_string max_blueprint_lookahead_in_seconds; + ] + @ Cli_arg.optional_switch "enable-fa-bridge" enable_fa_bridge + @ Cli_arg.optional_switch "enable-dal" enable_dal + @ Cli_arg.optional_arg + "dal-slots" + (fun l -> String.concat "," (List.map string_of_int l)) + dal_slots + in + let cmd = + List.fold_left + (fun acc chain_id -> + let arg = + Cli_arg.optional_arg "l2-chain-id" Int.to_string (Some chain_id) + in + acc @ arg) + cmd + l2_chain_ids + in + let cmd = + List.fold_left + (fun acc delayed_bridge -> + let arg = + Cli_arg.optional_arg "delayed-bridge" Fun.id (Some delayed_bridge) + in + acc @ arg) + cmd + delayed_bridges + in + let process = Process.spawn (Uses.path Constant.octez_evm_node) cmd in + Runnable.{value = process; run = Process.check} + +let make_l2_kernel_installer_config ?max_delayed_inbox_blueprint_length + ?(mainnet_compat = false) ~l2_chain_id ?bootstrap_balance + ?bootstrap_accounts ?ticketer ?tx_pool_tx_per_addr_limit + ?minimum_base_fee_per_gas ?(da_fee_per_byte = Wei.zero) + ?delayed_inbox_timeout ?delayed_inbox_min_levels ?sequencer_pool_address + ?maximum_gas_per_transaction ?(set_account_code = []) ~output () = + let set_account_code = + List.flatten + @@ List.map + (fun (address, code) -> + ["--set-code"; Format.sprintf "%s,%s" address code]) + set_account_code + in + let cmd = + ["make"; "l2"; "kernel"; "installer"; "config"; output] + @ Cli_arg.optional_arg + "max-delayed-inbox-blueprint-length" + Int.to_string + max_delayed_inbox_blueprint_length + @ Cli_arg.optional_switch "mainnet-compat" mainnet_compat + @ Cli_arg.optional_arg "l2-chain-id" string_of_int (Some l2_chain_id) @ Cli_arg.optional_arg "minimum-base-fee-per-gas" Wei.to_string minimum_base_fee_per_gas @ ["--da-fee-per-byte"; Wei.to_string da_fee_per_byte] + @ Cli_arg.optional_arg + "tx-pool-tx-per-addr-limit" + string_of_int + tx_pool_tx_per_addr_limit @ Cli_arg.optional_arg "delayed-inbox-timeout" string_of_int delayed_inbox_timeout + @ Cli_arg.optional_arg "ticketer" Fun.id ticketer @ Cli_arg.optional_arg "delayed-inbox-min-levels" string_of_int @@ -1635,25 +1744,11 @@ let make_kernel_installer_config ?max_delayed_inbox_blueprint_length "sequencer-pool-address" Fun.id sequencer_pool_address - @ Cli_arg.optional_arg - "maximum-allowed-ticks" - Int64.to_string - maximum_allowed_ticks @ set_account_code @ Cli_arg.optional_arg "maximum-gas-per-transaction" Int64.to_string maximum_gas_per_transaction - @ [ - "--max-blueprint-lookahead-in-seconds"; - Int64.to_string max_blueprint_lookahead_in_seconds; - ] - @ Cli_arg.optional_switch "enable-fa-bridge" enable_fa_bridge - @ Cli_arg.optional_switch "enable-dal" enable_dal - @ Cli_arg.optional_arg - "dal-slots" - (fun l -> String.concat "," (List.map string_of_int l)) - dal_slots @ Cli_arg.optional_arg "bootstrap-balance" Wei.to_string bootstrap_balance @ match bootstrap_accounts with diff --git a/etherlink/tezt/lib/evm_node.mli b/etherlink/tezt/lib/evm_node.mli index 9191bdf6fbcc4c2aca9e5f74513e3b47e6ff228b..cf20083314d318db438a82b0fe9debeb6f4eb827 100644 --- a/etherlink/tezt/lib/evm_node.mli +++ b/etherlink/tezt/lib/evm_node.mli @@ -35,12 +35,28 @@ type time_between_blocks = (** Interval at which the sequencer creates an empty block by default. *) +type l2_chain_info = { + id : int; + restricted_rpcs : string option; + rpc_addr : string option; + rpc_port : int; + tx_pool_timeout_limit : int option; + (** --tx-pool-timeout-limit: transaction timeout inside the pool. *) + tx_pool_addr_limit : int option; + (** --tx-pool-addr-limit: maximum address allowed simultaneously inside + the pool. *) + tx_pool_tx_per_addr_limit : int option; + (** --tx-pool-tx-per-addr-limit: maximum transaction per address allowed + simultaneously inside the pool. *) + private_rpc_port : int option; +} + (** EVM node mode. *) type mode = | Observer of { initial_kernel : string; preimages_dir : string option; - private_rpc_port : int option; (** Port for private RPC server*) + private_rpc_port : int option; rollup_node_endpoint : string; } | Threshold_encryption_observer of { @@ -54,7 +70,7 @@ type mode = (** Path to the initial kernel used by the sequencer. *) preimage_dir : string option; (** Path to the directory with the associated preimages. *) - private_rpc_port : int option; (** Port for private RPC server*) + private_rpc_port : int option; time_between_blocks : time_between_blocks option; (** See {!time_between_blocks}, if the value is not provided, the sequencer uses it default value. *) @@ -66,14 +82,6 @@ type mode = catchup_cooldown : int option; max_number_of_chunks : int option; wallet_dir : string option; (** --wallet-dir: client directory. *) - tx_pool_timeout_limit : int option; - (** --tx-pool-timeout-limit: transaction timeout inside the pool. *) - tx_pool_addr_limit : int option; - (** --tx-pool-addr-limit: maximum address allowed simultaneously inside - the pool. *) - tx_pool_tx_per_addr_limit : int option; - (** --tx-pool-tx-per-addr-limit: maximum transaction per address allowed - simultaneously inside the pool. *) dal_slots : int list option; } | Sandbox of { @@ -84,16 +92,13 @@ type mode = genesis_timestamp : Client.timestamp option; max_number_of_chunks : int option; wallet_dir : string option; - tx_pool_timeout_limit : int option; - tx_pool_addr_limit : int option; - tx_pool_tx_per_addr_limit : int option; } | Threshold_encryption_sequencer of { initial_kernel : string; (** Path to the initial kernel used by the sequencer. *) preimage_dir : string option; (** Path to the directory with the associated preimages. *) - private_rpc_port : int option; (** Port for private RPC server*) + private_rpc_port : int option; time_between_blocks : time_between_blocks option; (** See {!time_between_blocks}, if the value is not provided, the sequencer uses it default value. *) @@ -104,15 +109,7 @@ type mode = max_blueprints_catchup : int option; catchup_cooldown : int option; max_number_of_chunks : int option; - wallet_dir : string option; (** --wallet-dir: client directory. *) - tx_pool_timeout_limit : int option; - (** --tx-pool-timeout-limit: transaction timeout inside the pool. *) - tx_pool_addr_limit : int option; - (** --tx-pool-addr-limit: maximum address allowed simultaneously inside - the pool. *) - tx_pool_tx_per_addr_limit : int option; - (** --tx-pool-tx-per-addr-limit: maximum transaction per address allowed - simultaneously inside the pool. *) + wallet_dir : string option; sequencer_sidecar_endpoint : string; (** --sequencer-sidecar-endpoint: Uri of the sidecar endpoints to which proposals are forwarded, and from where preblocks are fetched. *) @@ -157,6 +154,8 @@ val create : ?rpc_addr:string -> ?rpc_port:int -> ?restricted_rpcs:string -> + ?websockets:bool -> + ?chains:l2_chain_info list -> string -> t @@ -273,7 +272,7 @@ end (** [spawn_init_config ?extra_arguments evm_node] runs "init config" with arguments found in the state. *) -val spawn_init_config : ?extra_arguments:string list -> t -> Process.t +val spawn_init_config : ?extra_arguments:string list -> t -> unit Lwt.t (** [spawn_init_config_minimal ~data_dir ?path ?extra_arguments ()] creates a minimal config with no cli argument populated as [spawn_init_config]. @@ -320,6 +319,9 @@ val patch_config_with_experimental_feature : with [patch_config], then runs it with {!run}. *) val init : ?patch_config:(JSON.t -> JSON.t) -> + ?tx_pool_timeout_limit:int -> + ?tx_pool_addr_limit:int -> + ?tx_pool_tx_per_addr_limit:int -> ?name:string -> ?runner:Runner.t -> ?mode:mode -> @@ -327,11 +329,13 @@ val init : ?rpc_addr:string -> ?rpc_port:int -> ?restricted_rpcs:string -> + ?websockets:bool -> + l2_chain_ids:int list -> string -> t Lwt.t (** Get the RPC port given as [--rpc-port] to a node. *) -val rpc_port : t -> int +val rpc_port : ?chain_id:int -> t -> int (** [spawn_run ?extra_arguments evm_node] same as {!run} but spawns a process. *) @@ -389,7 +393,8 @@ val wait_for_rollup_node_ahead : t -> int Lwt.t (** [wait_for_tx_pool_add_transaction ?timeout evm_node] waits for the event [tx_pool_add_transaction.v0] using {!wait_for} and returns the transaction hash. *) -val wait_for_tx_pool_add_transaction : ?timeout:float -> t -> string Lwt.t +val wait_for_tx_pool_add_transaction : + ?timeout:float -> ?l2_chain_id:int -> t -> string Lwt.t (** [wait_for_shutdown ?can_terminate evm_node] waits until a node terminates and return its status. If the node is not running, make the test fail. If @@ -419,10 +424,11 @@ val wait_for_start_history_mode : ?history_mode:string -> t -> string Lwt.t then [Constant.default_host] is used (it overrides [rpc-addr] or the [runner] argument). *) -val rpc_endpoint : ?local:bool -> ?private_:bool -> t -> string +val rpc_endpoint : + ?local:bool -> ?private_:bool -> ?l2_chain_id:int -> t -> string (** A deprecated alias for [rpc_endpoint] where [local] optional parameter is not given. *) -val endpoint : ?private_:bool -> t -> string +val endpoint : ?private_:bool -> ?l2_chain_id:int -> t -> string (** JSON-RPC request. *) type request = {method_ : string; parameters : JSON.u} @@ -431,17 +437,20 @@ type request = {method_ : string; parameters : JSON.u} the [evm_node], for the given [request]. If [private_] is true, the request is sent to the private RPC server. *) -val call_evm_rpc : ?private_:bool -> t -> request -> JSON.t Lwt.t +val call_evm_rpc : + ?private_:bool -> ?l2_chain_id:int -> t -> request -> JSON.t Lwt.t (** [batch_evm_rpc ?private_ evm_node requests] sends multiple JSON-RPC requests to the [evm_node], for the given [requests]. If [private_] is true, the requests are sent to the private RPC server. *) -val batch_evm_rpc : ?private_:bool -> t -> request list -> JSON.t list Lwt.t +val batch_evm_rpc : + ?private_:bool -> ?l2_chain_id:int -> t -> request list -> JSON.t list Lwt.t (** Open a websocket connection with the EVM node. If [private_] is true, a connection is created with the private websocket endpoint of the node. *) -val open_websocket : ?private_:bool -> t -> Websocket.t Lwt.t +val open_websocket : + ?private_:bool -> ?l2_chain_id:int -> t -> Websocket.t Lwt.t (** [call_evm_websocket ws request] sends a JSON-RPC request on the websocket connection [ws] and waits for the response. *) @@ -455,13 +464,19 @@ val batch_evm_websocket : Websocket.t -> request list -> JSON.t list Lwt.t (** [jsonrpc] uses the [websocket] to make a JSON-RPC call if provided or falls back to using HTTP RPC request on the EVM node otherwise. *) val jsonrpc : - ?websocket:Websocket.t -> ?private_:bool -> t -> request -> JSON.t Lwt.t + ?websocket:Websocket.t -> + ?private_:bool -> + ?l2_chain_id:int -> + t -> + request -> + JSON.t Lwt.t (** [batch_jsonrpc] uses the [websocket] to make a JSON-RPC calls if provided or falls back to using an HTTP RPC batch request on the EVM node otherwise. *) val batch_jsonrpc : ?websocket:Websocket.t -> ?private_:bool -> + ?l2_chain_id:int -> t -> request list -> JSON.t list Lwt.t @@ -474,7 +489,7 @@ val extract_error_message : JSON.t -> JSON.t (** [fetch_contract_code evm_node contract] returns the code associated to the given contract in the rollup. *) -val fetch_contract_code : t -> string -> string Lwt.t +val fetch_contract_code : ?l2_chain_id:int -> t -> string -> string Lwt.t (** [upgrade_payload ~root_hash ~activation_timestamp] gives the upgrade payload to put in a upgrade message, it will upgrade to @@ -549,32 +564,42 @@ val wait_termination : t -> unit Lwt.t (** [make_kernel_installer_config ~output ()] create the config needed for the evm kernel used by the installer *) val make_kernel_installer_config : - ?max_delayed_inbox_blueprint_length:int -> ?mainnet_compat:bool -> ?remove_whitelist:bool -> ?kernel_root_hash:string -> - ?chain_id:int -> - ?bootstrap_balance:Wei.t -> - ?bootstrap_accounts:string list -> + ?l2_chain_ids:int list -> ?sequencer:string -> - ?delayed_bridge:string -> - ?ticketer:string -> + ?delayed_bridges:string list -> ?administrator:string -> ?sequencer_governance:string -> ?kernel_governance:string -> ?kernel_security_governance:string -> + ?maximum_allowed_ticks:int64 -> + ?max_blueprint_lookahead_in_seconds:int64 -> + ?enable_fa_bridge:bool -> + ?enable_dal:bool -> + ?dal_slots:int list -> + output:string -> + unit -> + (Process.t, unit) Runnable.t + +(** [make_kernel_installer_config ~output ()] create the config needed for the + evm kernel used by the installer *) +val make_l2_kernel_installer_config : + ?max_delayed_inbox_blueprint_length:int -> + ?mainnet_compat:bool -> + l2_chain_id:int -> + ?bootstrap_balance:Wei.t -> + ?bootstrap_accounts:string list -> + ?ticketer:string -> + ?tx_pool_tx_per_addr_limit:int -> ?minimum_base_fee_per_gas:Wei.t -> ?da_fee_per_byte:Wei.t -> ?delayed_inbox_timeout:int -> ?delayed_inbox_min_levels:int -> ?sequencer_pool_address:string -> - ?maximum_allowed_ticks:int64 -> ?maximum_gas_per_transaction:int64 -> - ?max_blueprint_lookahead_in_seconds:int64 -> ?set_account_code:(string * string) list -> - ?enable_fa_bridge:bool -> - ?enable_dal:bool -> - ?dal_slots:int list -> output:string -> unit -> (Process.t, unit) Runnable.t diff --git a/etherlink/tezt/lib/helpers.ml b/etherlink/tezt/lib/helpers.ml index ad0a8d81737e069d93a07a93f847aff06242d9e2..c77f07e18a9281bc43c0aa585d4e615359fe764b 100644 --- a/etherlink/tezt/lib/helpers.ml +++ b/etherlink/tezt/lib/helpers.ml @@ -412,25 +412,38 @@ let find_and_execute_withdrawal ?(outbox_lookup_depth = 10) ~withdrawal_level return withdrawal_level let init_sequencer_sandbox ?maximum_gas_per_transaction ?genesis_timestamp - ?tx_pool_tx_per_addr_limit ?set_account_code ?da_fee_per_byte + ?set_account_code ?da_fee_per_byte ?tx_pool_tx_per_addr_limit ?minimum_base_fee_per_gas ?patch_config ?(kernel = Constant.WASM.evm_kernel) ?(bootstrap_accounts = List.map (fun account -> account.Eth_account.address) - (Array.to_list Eth_account.bootstrap_accounts)) () = + (Array.to_list Eth_account.bootstrap_accounts)) ~l2_chain_ids () = let wallet_dir = Temp.dir "wallet" in let output_config = Temp.file "config.yaml" in let preimages_dir = Temp.dir "wasm_2_0_0" in - + let* () = + Lwt_list.iter_s + (fun l2_chain_id -> + let l2_config = + Temp.file (Format.sprintf "l2-%d-config.yaml" l2_chain_id) + in + let*! () = + Evm_node.make_l2_kernel_installer_config + ?maximum_gas_per_transaction + ?set_account_code + ?da_fee_per_byte + ?tx_pool_tx_per_addr_limit + ?minimum_base_fee_per_gas + ~bootstrap_accounts + ~output:l2_config + ~l2_chain_id + () + in + Lwt.return_unit) + l2_chain_ids + in let*! () = - Evm_node.make_kernel_installer_config - ?maximum_gas_per_transaction - ?set_account_code - ?da_fee_per_byte - ?minimum_base_fee_per_gas - ~output:output_config - ~bootstrap_accounts - () + Evm_node.make_kernel_installer_config ~output:output_config ~l2_chain_ids () in let* {output; _} = Sc_rollup_helpers.prepare_installer_kernel @@ -444,17 +457,18 @@ let init_sequencer_sandbox ?maximum_gas_per_transaction ?genesis_timestamp { initial_kernel = output; preimage_dir = Some preimages_dir; - private_rpc_port = Some (Port.fresh ()); + private_rpc_port = None; time_between_blocks = Some Nothing; genesis_timestamp; max_number_of_chunks = None; wallet_dir = Some wallet_dir; - tx_pool_timeout_limit = None; - tx_pool_addr_limit = None; - tx_pool_tx_per_addr_limit; } in - Evm_node.init ?patch_config ~mode:sequencer_mode Uri.(empty |> to_string) + Evm_node.init + ?patch_config + ~mode:sequencer_mode + ~l2_chain_ids + Uri.(empty |> to_string) (* Send the transaction but doesn't wait to be mined and does not produce a block after sending the transaction. *) diff --git a/etherlink/tezt/lib/helpers.mli b/etherlink/tezt/lib/helpers.mli index 3c9b608c168f26d0125c0d9ba464d1591790de1e..1b3d8e9690457d870720a02cbe9cbe93571afb29 100644 --- a/etherlink/tezt/lib/helpers.mli +++ b/etherlink/tezt/lib/helpers.mli @@ -231,13 +231,14 @@ val find_and_execute_withdrawal : val init_sequencer_sandbox : ?maximum_gas_per_transaction:int64 -> ?genesis_timestamp:Client.timestamp -> - ?tx_pool_tx_per_addr_limit:int -> ?set_account_code:(string * string) list -> ?da_fee_per_byte:Wei.t -> + ?tx_pool_tx_per_addr_limit:int -> ?minimum_base_fee_per_gas:Wei.t -> ?patch_config:(JSON.t -> JSON.t) -> ?kernel:Uses.t -> ?bootstrap_accounts:string list -> + l2_chain_ids:int list -> unit -> Evm_node.t Lwt.t diff --git a/etherlink/tezt/lib/rpc.ml b/etherlink/tezt/lib/rpc.ml index 1b6d2da4ca6f91b7b168b89fba607cbec38fe173..9b9895fcb727d6a9a61acec26498007a1af0d3a8 100644 --- a/etherlink/tezt/lib/rpc.ml +++ b/etherlink/tezt/lib/rpc.ml @@ -365,8 +365,10 @@ let get_logs ?websocket ?from_block ?to_block ?address ?topics evm_node = |> List.map (fun json -> Transaction.logs_of_json json))) json) -let block_number ?websocket evm_node = - let* json = Evm_node.jsonrpc ?websocket evm_node Request.eth_blockNumber in +let block_number ?websocket ?l2_chain_id evm_node = + let* json = + Evm_node.jsonrpc ?websocket ?l2_chain_id evm_node Request.eth_blockNumber + in return (decode_or_error (fun json -> JSON.(json |-> "result" |> as_int32)) json) diff --git a/etherlink/tezt/lib/rpc.mli b/etherlink/tezt/lib/rpc.mli index 17ddf95d32ed3722f5cf4986684516f73799592d..a27d00e9b344618752b42c557ea740e043478055 100644 --- a/etherlink/tezt/lib/rpc.mli +++ b/etherlink/tezt/lib/rpc.mli @@ -121,7 +121,10 @@ val get_logs : (** [block_number evm_node] calls [eth_blockNumber]. *) val block_number : - ?websocket:Websocket.t -> Evm_node.t -> (int32, error) result Lwt.t + ?websocket:Websocket.t -> + ?l2_chain_id:int -> + Evm_node.t -> + (int32, error) result Lwt.t (** [block_number_opt evm_node] calls [eth_blockNumber]. allows None when no block have been produced yet. *) diff --git a/etherlink/tezt/lib/setup.ml b/etherlink/tezt/lib/setup.ml index 479c24e92261db6bddc1d41dadb01adedb7293b3..348af9116a5505d806fbfc4ed5c25cbaf1809ecd 100644 --- a/etherlink/tezt/lib/setup.ml +++ b/etherlink/tezt/lib/setup.ml @@ -31,7 +31,7 @@ type sequencer_setup = { boot_sector : string; kernel : Uses.t; enable_dal : bool; - l2_chain_id : int; + l2_chain_ids : int list; } let uses _protocol = @@ -120,18 +120,18 @@ let setup_l1_contracts ?(dictator = Constant.bootstrap2) ~kernel client = ticket_router_tester; } -let run_new_rpc_endpoint evm_node = +let run_new_rpc_endpoint ~l2_chain_id evm_node = let rpc_node = Evm_node.create ~data_dir:(Evm_node.data_dir evm_node) ~mode:(Rpc Evm_node.(mode evm_node)) - (Evm_node.endpoint evm_node) + (Evm_node.endpoint ~l2_chain_id evm_node) in let* () = Evm_node.run rpc_node in return rpc_node let run_new_observer_node ?(finalized_view = false) ?(patch_config = Fun.id) - ~sc_rollup_node ?rpc_server ?websockets evm_node = + ~sc_rollup_node ?rpc_server ?websockets ~l2_chain_id evm_node = let preimages_dir = Evm_node.preimages_dir evm_node in let initial_kernel = Evm_node.initial_kernel evm_node in let patch_config = @@ -157,7 +157,7 @@ let run_new_observer_node ?(finalized_view = false) ?(patch_config = Fun.id) let* observer_mode = if Evm_node.supports_threshold_encryption evm_node then let bundler = - Dsn_node.bundler ~endpoint:(Evm_node.endpoint evm_node) () + Dsn_node.bundler ~endpoint:(Evm_node.endpoint ~l2_chain_id evm_node) () in let* () = Dsn_node.start bundler in return @@ -174,32 +174,58 @@ let run_new_observer_node ?(finalized_view = false) ?(patch_config = Fun.id) { initial_kernel; preimages_dir = Some preimages_dir; - private_rpc_port = Some (Port.fresh ()); + private_rpc_port = None; rollup_node_endpoint = Sc_rollup_node.endpoint sc_rollup_node; }) in let* observer = - Evm_node.init ~patch_config ~mode:observer_mode (Evm_node.endpoint evm_node) + Evm_node.init + ~patch_config + ~mode:observer_mode + ?websockets + ~l2_chain_ids:[l2_chain_id] + (Evm_node.endpoint ~l2_chain_id evm_node) in return observer +let setup_l2 ?max_delayed_inbox_blueprint_length ?mainnet_compat + ?(bootstrap_accounts = + List.map + (fun account -> account.Eth_account.address) + (Array.to_list Eth_account.bootstrap_accounts)) ~l2_chain_id + ?bootstrap_balance ?minimum_base_fee_per_gas ?(da_fee_per_byte = Wei.zero) + ?delayed_inbox_timeout ?delayed_inbox_min_levels ?sequencer_pool_address + ?maximum_gas_per_transaction ?set_account_code ?ticketer ~output () = + Evm_node.make_l2_kernel_installer_config + ?mainnet_compat + ~bootstrap_accounts + ~l2_chain_id + ?max_delayed_inbox_blueprint_length + ?bootstrap_balance + ?minimum_base_fee_per_gas + ~da_fee_per_byte + ?delayed_inbox_timeout + ?delayed_inbox_min_levels + ?sequencer_pool_address + ?maximum_gas_per_transaction + ?set_account_code + ?ticketer + ~output + () + let setup_sequencer ?max_delayed_inbox_blueprint_length ?next_wasm_runtime ?block_storage_sqlite3 ?sequencer_rpc_port ?sequencer_private_rpc_port ~mainnet_compat ?genesis_timestamp ?time_between_blocks ?max_blueprints_lag ?max_blueprints_ahead ?max_blueprints_catchup ?catchup_cooldown ?delayed_inbox_timeout ?delayed_inbox_min_levels ?max_number_of_chunks - ?commitment_period ?challenge_window - ?(bootstrap_accounts = - List.map - (fun account -> account.Eth_account.address) - (Array.to_list Eth_account.bootstrap_accounts)) + ?commitment_period ?challenge_window ?bootstrap_accounts ?(sequencer = Constant.bootstrap1) ?sequencer_pool_address ?(kernel = Constant.WASM.evm_kernel) ?da_fee ?minimum_base_fee_per_gas ?preimages_dir ?maximum_allowed_ticks ?maximum_gas_per_transaction ?max_blueprint_lookahead_in_seconds ?enable_fa_bridge ?(threshold_encryption = false) ?(drop_duplicate_when_injection = true) ?(blueprints_publisher_order_enabled = true) ?history_mode ~enable_dal - ?dal_slots ?rpc_server ?websockets protocol = + ?dal_slots ?rpc_server ?websockets ?(number_of_chains = 1) protocol = let* node, client = setup_l1 ?commitment_period @@ -233,33 +259,66 @@ let setup_sequencer ?max_delayed_inbox_blueprint_length ?next_wasm_runtime ~default:(Sc_rollup_node.data_dir sc_rollup_node // "wasm_2_0_0") preimages_dir in - let output_config = Temp.file "config.yaml" in + let output_config = Temp.file "rollup_config.yaml" in + let l2_chain_ids = List.init number_of_chains (( + ) 1) in + let l2_info = + List.map + (fun l2_chain_id -> + (l2_chain_id, Temp.file (Format.sprintf "config_l2_%d.yaml" l2_chain_id))) + l2_chain_ids + in + let* () = + Lwt_list.iter_s + (fun (l2_chain_id, l2_config) -> + let*! () = + setup_l2 + ~l2_chain_id + ?max_delayed_inbox_blueprint_length + ?delayed_inbox_timeout + ?delayed_inbox_min_levels + ?bootstrap_accounts + ?sequencer_pool_address + ?da_fee_per_byte:da_fee + ?minimum_base_fee_per_gas + ?maximum_gas_per_transaction + ~output:l2_config + () + in + Lwt.return_unit) + l2_info + in let*! () = Evm_node.make_kernel_installer_config - ?max_delayed_inbox_blueprint_length + (* ?max_delayed_inbox_blueprint_length *) ~mainnet_compat ~sequencer:sequencer.public_key - ~delayed_bridge:l1_contracts.delayed_transaction_bridge - ~ticketer:l1_contracts.exchanger + ~delayed_bridges:[l1_contracts.delayed_transaction_bridge] + (* ~ticketer:l1_contracts.exchanger *) ~administrator:l1_contracts.admin ~sequencer_governance:l1_contracts.sequencer_governance - ?minimum_base_fee_per_gas - ?da_fee_per_byte:da_fee - ?delayed_inbox_timeout - ?delayed_inbox_min_levels - ?sequencer_pool_address - ?maximum_allowed_ticks - ?maximum_gas_per_transaction + (* ?minimum_base_fee_per_gas *) + (* ?da_fee_per_byte:da_fee *) + (* ?delayed_inbox_timeout *) + (* ?delayed_inbox_min_levels *) + (* ?sequencer_pool_address *) + ?maximum_allowed_ticks (* ?maximum_gas_per_transaction *) ~enable_dal ?dal_slots - ?max_blueprint_lookahead_in_seconds - ~bootstrap_accounts + ?max_blueprint_lookahead_in_seconds (* ~bootstrap_accounts *) ~output:output_config + ~l2_chain_ids ?enable_fa_bridge () in + let l2_configs = + List.map (fun (_, l2_config_file) -> `Path l2_config_file) l2_info + in let* {output; _} = - prepare_installer_kernel ~preimages_dir ~config:(`Path output_config) kernel + prepare_installer_kernel + ~preimages_dir + ~config:(`Path output_config) + ~l2_configs + kernel in let* sc_rollup_address = originate_sc_rollup @@ -308,9 +367,6 @@ let setup_sequencer ?max_delayed_inbox_blueprint_length ?next_wasm_runtime catchup_cooldown; max_number_of_chunks; wallet_dir = Some (Client.base_dir client); - tx_pool_timeout_limit = None; - tx_pool_addr_limit = None; - tx_pool_tx_per_addr_limit = None; sequencer_sidecar_endpoint = Dsn_node.endpoint sequencer_sidecar; dal_slots; } @@ -330,17 +386,16 @@ let setup_sequencer ?max_delayed_inbox_blueprint_length ?next_wasm_runtime catchup_cooldown; max_number_of_chunks; wallet_dir = Some (Client.base_dir client); - tx_pool_timeout_limit = None; - tx_pool_addr_limit = None; - tx_pool_tx_per_addr_limit = None; dal_slots; } in let* sequencer = Evm_node.init - ?rpc_port:sequencer_rpc_port ~patch_config + ?rpc_port:sequencer_rpc_port ~mode:sequencer_mode + ?websockets + ~l2_chain_ids (Sc_rollup_node.endpoint sc_rollup_node) in let* observer = @@ -349,12 +404,14 @@ let setup_sequencer ?max_delayed_inbox_blueprint_length ?next_wasm_runtime ~sc_rollup_node ?rpc_server ?websockets + ~l2_chain_id:1 sequencer in let* proxy = Evm_node.init ~patch_config ~mode:Proxy + ~l2_chain_ids (Sc_rollup_node.endpoint sc_rollup_node) in return @@ -370,7 +427,7 @@ let setup_sequencer ?max_delayed_inbox_blueprint_length ?next_wasm_runtime boot_sector = output; kernel; enable_dal; - l2_chain_id = 1; + l2_chain_ids; } (* Register a single variant of a test but for all protocols. *) @@ -386,7 +443,7 @@ let register_test ~__FILE__ ?max_delayed_inbox_blueprint_length ?(threshold_encryption = false) ?(uses = uses) ?(additional_uses = []) ?history_mode ~enable_dal ?(dal_slots = if enable_dal then Some [0; 1; 2; 3] else None) ?rpc_server - ?websockets body ~title ~tags protocols = + ?websockets ?number_of_chains body ~title ~tags protocols = let kernel_tag, kernel_use = Kernel.to_uses_and_tags kernel in let tags = kernel_tag :: tags in let additional_uses = @@ -442,6 +499,7 @@ let register_test ~__FILE__ ?max_delayed_inbox_blueprint_length ~threshold_encryption ?history_mode ?websockets + ?number_of_chains ~enable_dal ?dal_slots ?rpc_server @@ -486,7 +544,8 @@ let register_test_for_kernels ~__FILE__ ?max_delayed_inbox_blueprint_length ?maximum_allowed_ticks ?maximum_gas_per_transaction ?max_blueprint_lookahead_in_seconds ?enable_fa_bridge ?history_mode ?commitment_period ?challenge_window ?additional_uses ~threshold_encryption - ~enable_dal ?dal_slots ?rpc_server ?websockets ~title ~tags body protocols = + ~enable_dal ?dal_slots ?rpc_server ?websockets ?number_of_chains ~title + ~tags body protocols = List.iter (fun kernel -> register_test @@ -520,6 +579,7 @@ let register_test_for_kernels ~__FILE__ ?max_delayed_inbox_blueprint_length ?additional_uses ?rpc_server ?websockets + ?number_of_chains ~threshold_encryption ?history_mode ~enable_dal diff --git a/etherlink/tezt/lib/setup.mli b/etherlink/tezt/lib/setup.mli index 8d05f85ba6e9b8d1715547cf12f4d4c92b9befcf..1c1ed4122edd90f9925dcbfd580265ab9b467a55 100644 --- a/etherlink/tezt/lib/setup.mli +++ b/etherlink/tezt/lib/setup.mli @@ -28,7 +28,7 @@ type sequencer_setup = { boot_sector : string; kernel : Uses.t; enable_dal : bool; - l2_chain_id : int; + l2_chain_ids : int list; } (** [uses protocol] returns the list of dependencies for the tests. *) @@ -40,7 +40,7 @@ val setup_l1_contracts : ?dictator:Account.key -> kernel:Kernel.t -> Client.t -> l1_contracts Lwt.t (** [run_new_rpc_endpoint node] starts a new rpc node following the setup. *) -val run_new_rpc_endpoint : Evm_node.t -> Evm_node.t Lwt.t +val run_new_rpc_endpoint : l2_chain_id:int -> Evm_node.t -> Evm_node.t Lwt.t (**[run_new_rpc_endpoint ~sc_rollup_node node] starts a new observer following the setup. *) @@ -50,6 +50,7 @@ val run_new_observer_node : sc_rollup_node:Sc_rollup_node.t -> ?rpc_server:Evm_node.rpc_server -> ?websockets:bool -> + l2_chain_id:int -> Evm_node.t -> Evm_node.t Lwt.t @@ -92,6 +93,7 @@ val register_test : ?dal_slots:int list option -> ?rpc_server:Evm_node.rpc_server -> ?websockets:bool -> + ?number_of_chains:int -> (sequencer_setup -> Protocol.t -> unit Lwt.t) -> title:string -> tags:string list -> @@ -136,6 +138,7 @@ val register_test_for_kernels : ?dal_slots:int list option -> ?rpc_server:Evm_node.rpc_server -> ?websockets:bool -> + ?number_of_chains:int -> title:string -> tags:string list -> (sequencer_setup -> Protocol.t -> unit Lwt.t) -> @@ -179,5 +182,6 @@ val setup_sequencer : ?dal_slots:int list -> ?rpc_server:Evm_node.rpc_server -> ?websockets:bool -> + ?number_of_chains:int -> Protocol.t -> sequencer_setup Lwt.t diff --git a/etherlink/tezt/tests/evm_rollup.ml b/etherlink/tezt/tests/evm_rollup.ml index f95d6602ef4677d168dbb6bcf6e16971ac38de0b..72e7b82a7419b5d8dc3b07319ff4ca0571f5043d 100644 --- a/etherlink/tezt/tests/evm_rollup.ml +++ b/etherlink/tezt/tests/evm_rollup.ml @@ -300,7 +300,7 @@ type setup_mode = let setup_evm_kernel ?additional_config ?(setup_kernel_root_hash = true) ?(kernel = Kernel.Latest) ?(originator_key = Constant.bootstrap1.public_key_hash) - ?(rollup_operator_key = Constant.bootstrap1.public_key_hash) ?chain_id + ?(rollup_operator_key = Constant.bootstrap1.public_key_hash) ?(bootstrap_accounts = List.map (fun account -> account.Eth_account.address) @@ -363,16 +363,31 @@ let setup_evm_kernel ?additional_config ?(setup_kernel_root_hash = true) | Setup_sequencer {sequencer; _} -> Some sequencer.public_key in let output_config = Temp.file "config.yaml" in + let l2_chain_id = 1 in + let l2_config = + Temp.file (Format.sprintf "l2-%d-config.yaml" l2_chain_id) + in + let*! () = + Evm_node.make_l2_kernel_installer_config + ~bootstrap_accounts + ?ticketer + ?da_fee_per_byte + ?minimum_base_fee_per_gas + (* ?tx_pool_timeout_limit + ?tx_pool_addr_limit + ?tx_pool_tx_per_addr_limit + ?max_number_of_chunks *) + ~l2_chain_id + ~output:l2_config + () + in let*! () = Evm_node.make_kernel_installer_config - ?chain_id ~mainnet_compat:false ~remove_whitelist:Option.(is_some whitelist) ?kernel_root_hash - ~bootstrap_accounts - ?da_fee_per_byte - ?minimum_base_fee_per_gas - ?ticketer + ~l2_chain_ids:[l2_chain_id] + ~delayed_bridges:[""] ?administrator ?kernel_governance ?kernel_security_governance @@ -437,12 +452,18 @@ let setup_evm_kernel ?additional_config ?(setup_kernel_root_hash = true) let* produce_block, evm_node = match setup_mode with | Setup_proxy -> + let l2_chain_ids = [1] in let mode = Evm_node.Proxy in let* evm_node = Evm_node.init ~patch_config ~mode + ?websockets + ?tx_pool_timeout_limit + ?tx_pool_addr_limit + ?tx_pool_tx_per_addr_limit ?restricted_rpcs + ~l2_chain_ids (Sc_rollup_node.endpoint sc_rollup_node) in return @@ -458,19 +479,19 @@ let setup_evm_kernel ?additional_config ?(setup_kernel_root_hash = true) max_blueprints_ahead; block_storage_sqlite3; } -> + let l2_chain_ids = [1] in let patch_config = Evm_node.patch_config_with_experimental_feature ~block_storage_sqlite3 ?enable_websocket:websockets () in - let private_rpc_port = Some (Port.fresh ()) in let sequencer_mode = Evm_node.Sequencer { initial_kernel = output; preimage_dir = Some preimages_dir; - private_rpc_port; + private_rpc_port = Some (Port.fresh ()); time_between_blocks; sequencer = sequencer.alias; genesis_timestamp = None; @@ -480,9 +501,6 @@ let setup_evm_kernel ?additional_config ?(setup_kernel_root_hash = true) catchup_cooldown = None; max_number_of_chunks; wallet_dir = Some (Client.base_dir client); - tx_pool_timeout_limit; - tx_pool_addr_limit; - tx_pool_tx_per_addr_limit; dal_slots; } in @@ -490,7 +508,8 @@ let setup_evm_kernel ?additional_config ?(setup_kernel_root_hash = true) Evm_node.init ~patch_config ~mode:sequencer_mode - ?restricted_rpcs + ?websockets + ~l2_chain_ids (Sc_rollup_node.endpoint sc_rollup_node) in let produce_block () = Rpc.produce_block sequencer in @@ -816,7 +835,7 @@ let test_evm_node_connection = ~default_operator:Constant.bootstrap1.alias in let evm_node = Evm_node.create (Sc_rollup_node.endpoint sc_rollup_node) in - let* () = Process.check @@ Evm_node.spawn_init_config evm_node in + let* () = Evm_node.spawn_init_config evm_node in (* Tries to start the EVM node server without a listening rollup node. *) let* () = Process.check ~expect_failure:true @@ Evm_node.spawn_run evm_node in (* Starts the rollup node. *) @@ -3160,11 +3179,11 @@ type storage_migration_results = { on master. - everytime a new path/rpc/object is stored in the kernel, a new sanity check MUST be generated. *) -let gen_kernel_migration_test ~from ~to_ ?bootstrap_accounts ?chain_id +let gen_kernel_migration_test ~from ~to_ ?bootstrap_accounts ?(admin = Constant.bootstrap5) ~scenario_prior ~scenario_after protocol = + let l2_chain_ids = [1] in let* evm_setup = setup_evm_kernel - ?chain_id ?bootstrap_accounts ~da_fee_per_byte:Wei.zero ~minimum_base_fee_per_gas:(Wei.of_string "21000") @@ -3174,7 +3193,10 @@ let gen_kernel_migration_test ~from ~to_ ?bootstrap_accounts ?chain_id in (* Load the EVM rollup's storage and sanity check results. *) let* evm_node = - Evm_node.init ~mode:Proxy (Sc_rollup_node.endpoint evm_setup.sc_rollup_node) + Evm_node.init + ~mode:Proxy + ~l2_chain_ids + (Sc_rollup_node.endpoint evm_setup.sc_rollup_node) in let endpoint = Evm_node.endpoint evm_node in let* sanity_check = @@ -3193,7 +3215,10 @@ let gen_kernel_migration_test ~from ~to_ ?bootstrap_accounts ?chain_id ~client:evm_setup.client in let* evm_node = - Evm_node.init ~mode:Proxy (Sc_rollup_node.endpoint evm_setup.sc_rollup_node) + Evm_node.init + ~mode:Proxy + ~l2_chain_ids + (Sc_rollup_node.endpoint evm_setup.sc_rollup_node) in let evm_setup = {evm_setup with evm_node} in (* Check the values after the upgrade with [sanity_check] results. *) @@ -4790,7 +4815,8 @@ let test_migrate_proxy_to_sequencer_future = ~activation_timestamp ~pool_address:Eth_account.bootstrap_accounts.(0).address in - let sequencer_node = + let l2_chain_ids = [1] in + let* sequencer_node = let mode = Evm_node.Sequencer { @@ -4807,15 +4833,12 @@ let test_migrate_proxy_to_sequencer_future = catchup_cooldown = None; max_number_of_chunks = None; wallet_dir = Some (Client.base_dir client); - tx_pool_timeout_limit = None; - tx_pool_addr_limit = None; - tx_pool_tx_per_addr_limit = None; dal_slots = None; } in - Evm_node.create ~mode (Sc_rollup_node.endpoint sc_rollup_node) + Evm_node.init ~mode ~l2_chain_ids (Sc_rollup_node.endpoint sc_rollup_node) in - let* () = Process.check @@ Evm_node.spawn_init_config sequencer_node in + (* let* () = Evm_node.spawn_init_config sequencer_node in *) let* () = repeat 10 (fun () -> let* _ = next_rollup_node_level ~sc_rollup_node ~client in @@ -4960,7 +4983,8 @@ let test_migrate_proxy_to_sequencer_past = let* _ = next_rollup_node_level ~sc_rollup_node ~client in unit) in - let sequencer_node = + let l2_chain_ids = [1] in + let* sequencer_node = let mode = Evm_node.Sequencer { @@ -4977,15 +5001,11 @@ let test_migrate_proxy_to_sequencer_past = catchup_cooldown = None; max_number_of_chunks = None; wallet_dir = Some (Client.base_dir client); - tx_pool_timeout_limit = None; - tx_pool_addr_limit = None; - tx_pool_tx_per_addr_limit = None; dal_slots = None; } in - Evm_node.create ~mode (Sc_rollup_node.endpoint sc_rollup_node) + Evm_node.init ~mode ~l2_chain_ids (Sc_rollup_node.endpoint sc_rollup_node) in - let* () = Process.check @@ Evm_node.spawn_init_config sequencer_node in (* Run the sequencer from the rollup node state. *) let* () = Evm_node.init_from_rollup_node_data_dir sequencer_node sc_rollup_node diff --git a/etherlink/tezt/tests/evm_sequencer.ml b/etherlink/tezt/tests/evm_sequencer.ml index 873148ab18e4c212a6fbb4a23f1b9d9d47e2a6d4..9103c4a6fecba2c3b8223f27d71b71dca1460281 100644 --- a/etherlink/tezt/tests/evm_sequencer.ml +++ b/etherlink/tezt/tests/evm_sequencer.ml @@ -235,6 +235,7 @@ let register_sandbox ?tx_pool_tx_per_addr_limit ~title ?set_account_code ?da_fee_per_byte ?minimum_base_fee_per_gas ?patch_config + ~l2_chain_ids:[1] () in body sequencer @@ -249,7 +250,7 @@ let register_all ?max_delayed_inbox_blueprint_length ?block_storage_sqlite3 ?minimum_base_fee_per_gas ?preimages_dir ?maximum_allowed_ticks ?maximum_gas_per_transaction ?max_blueprint_lookahead_in_seconds ?enable_fa_bridge ?history_mode ?commitment_period ?challenge_window - ?additional_uses ?rpc_server ?websockets + ?additional_uses ?rpc_server ?websockets ?number_of_chains ?(use_threshold_encryption = default_threshold_encryption_registration) ?(use_dal = default_dal_registration) ~title ~tags body protocols = let dal_cases = @@ -303,6 +304,7 @@ let register_all ?max_delayed_inbox_blueprint_length ?block_storage_sqlite3 ?additional_uses ?rpc_server ?websockets + ?number_of_chains ~threshold_encryption ?history_mode ~enable_dal @@ -412,9 +414,13 @@ let test_observer_reset = let* () = Sc_rollup_node.run sc_rollup_node sc_rollup_address [Log_kernel_debug] in + let l2_chain_ids = [1] in (* Run a proxy. *) let* proxy = - Evm_node.init ~mode:Proxy (Sc_rollup_node.endpoint sc_rollup_node) + Evm_node.init + ~mode:Proxy + ~l2_chain_ids + (Sc_rollup_node.endpoint sc_rollup_node) in (* Run a valid sequencer. *) let* valid_sequencer = @@ -436,11 +442,12 @@ let test_observer_reset = catchup_cooldown = None; max_number_of_chunks = None; wallet_dir = Some (Client.base_dir client); - tx_pool_timeout_limit = None; - tx_pool_addr_limit = None; - tx_pool_tx_per_addr_limit = None; + (* tx_pool_timeout_limit = None; + tx_pool_addr_limit = None; + tx_pool_tx_per_addr_limit = None; *) dal_slots = None; }) + ~l2_chain_ids (Sc_rollup_node.endpoint sc_rollup_node) in (* We start a sequencer with an invalid key, but from its perspective the @@ -479,11 +486,12 @@ let test_observer_reset = catchup_cooldown = None; max_number_of_chunks = None; wallet_dir = Some (Client.base_dir client); - tx_pool_timeout_limit = None; - tx_pool_addr_limit = None; - tx_pool_tx_per_addr_limit = None; + (* tx_pool_timeout_limit = None; + tx_pool_addr_limit = None; + tx_pool_tx_per_addr_limit = None; *) dal_slots = None; }) + ~l2_chain_ids (Sc_rollup_node.endpoint temp_sc_rollup_node) in (* Preparing two observers, they will be the victim of our tests in 2 different @@ -505,6 +513,7 @@ let test_observer_reset = private_rpc_port = Some (Port.fresh ()); rollup_node_endpoint = Sc_rollup_node.endpoint sc_rollup_node; }) + ~l2_chain_ids (Evm_node.endpoint invalid_sequencer) in let* observer_victim2 = @@ -519,6 +528,7 @@ let test_observer_reset = private_rpc_port = Some (Port.fresh ()); rollup_node_endpoint = Sc_rollup_node.endpoint sc_rollup_node; }) + ~l2_chain_ids (Evm_node.endpoint invalid_sequencer) in (* We want this observer to detect the divergence after seeing the L1 events, @@ -599,6 +609,77 @@ module Protocol = struct [@@warning "-unused-value-declaration"] end +let test_multi_chain = + register_all + ~time_between_blocks:Nothing + ~tags:["evm"; "sequencer"; "multichain"] + ~title:"Multi chain first test" + ~number_of_chains:2 + @@ fun {sequencer; l2_chain_ids; _} _protocol -> + let l2_chain_id = List.hd l2_chain_ids in + let*@ start_block_number = Rpc.block_number ~l2_chain_id sequencer in + let*@ _ = produce_block sequencer in + let*@ new_block_number = Rpc.block_number ~l2_chain_id sequencer in + Check.((Int32.succ start_block_number = new_block_number) int32) + ~error_msg:"Expected new block number to be %L, but got: %R" ; + unit +(* register_all + ~time_between_blocks:Nothing + ~tags:["evm"; "sequencer"; "admin"] + ~title:"Multi chain first test" + @@ fun { + sequencer; + proxy; + sc_rollup_node; + client; + sc_rollup_address; + l1_contracts; + observer; + _; + } + _protocol -> + (* Produce blocks to show that both the sequencer and proxy are not + progressing. *) + let* _ = + repeat 5 (fun () -> + let* _ = next_rollup_node_level ~sc_rollup_node ~client in + unit) + in + (* Both are at genesis *) + let*@ sequencer_head = Rpc.block_number sequencer in + let*@ proxy_head = Rpc.block_number proxy in + Check.((sequencer_head = 0l) int32) + ~error_msg:"Sequencer should be at genesis" ; + Check.((sequencer_head = proxy_head) int32) + ~error_msg:"Sequencer and proxy should have the same block number" ; + (* Remove the sequencer via the sequencer-admin contract. *) + let* () = + Client.transfer + ~amount:Tez.zero + ~giver:Constant.bootstrap2.public_key_hash + ~receiver:l1_contracts.sequencer_governance + ~arg:(sf "Pair %S 0x" sc_rollup_address) + ~burn_cap:Tez.one + client + in + let* exit_code = Evm_node.wait_for_shutdown_event sequencer + and* missing_block_nb = Evm_node.wait_for_rollup_node_ahead observer + and* () = + (* Produce L1 blocks to show that only the proxy is progressing *) + repeat 5 (fun () -> + let* _ = next_rollup_node_level ~sc_rollup_node ~client in + unit) + in + Check.((exit_code = Some 100) (option int)) + ~error_msg:"Expected exit code %R, got %L" ; + (* Sequencer is at genesis, proxy is at [advance]. *) + Check.((missing_block_nb = 1) int) + ~error_msg:"Sequencer should be missing block %L" ; + let*@ proxy_head = Rpc.block_number proxy in + Check.((proxy_head > 0l) int32) ~error_msg:"Proxy should have advanced" ; + + unit *) + let test_remove_sequencer = register_all ~time_between_blocks:Nothing @@ -789,7 +870,7 @@ let test_snapshots_import_empty = let mode = Evm_node.mode sequencer |> Evm_node.mode_with_new_private_rpc in Evm_node.create ~mode (Sc_rollup_node.endpoint sc_rollup_node) in - let* () = Process.check @@ Evm_node.spawn_init_config new_sequencer in + let* () = Evm_node.spawn_init_config new_sequencer in let*! () = Evm_node.import_snapshot new_sequencer ~snapshot_file in Log.info "Start new sequencer." ; let* () = Evm_node.run new_sequencer in @@ -870,7 +951,7 @@ let test_snapshots_reexport = let mode = Evm_node.mode sequencer |> Evm_node.mode_with_new_private_rpc in Evm_node.create ~mode (Sc_rollup_node.endpoint sc_rollup_node) in - let* () = Process.check @@ Evm_node.spawn_init_config new_sequencer in + let* () = Evm_node.spawn_init_config new_sequencer in let*! () = Evm_node.import_snapshot new_sequencer ~snapshot_file in Log.info "Re-export snapshot from new sequencer." ; let*! _file = Evm_node.export_snapshot sequencer in @@ -1171,7 +1252,7 @@ let test_send_transaction_to_delayed_inbox = l1_contracts; sc_rollup_address; sc_rollup_node; - l2_chain_id; + l2_chain_ids; _; } _protocol -> @@ -1205,7 +1286,10 @@ let test_send_transaction_to_delayed_inbox = (* Assert that the expected transaction hash is found in the delayed inbox durable storage path. *) let* () = - Delayed_inbox.assert_mem ~l2_chain_id (Sc_rollup_node sc_rollup_node) hash + Delayed_inbox.assert_mem + ~l2_chain_id:(List.hd l2_chain_ids) + (Sc_rollup_node sc_rollup_node) + hash in (* Test that paying more than 1XTZ is allowed. *) let* _hash = @@ -1223,10 +1307,11 @@ let test_send_deposit_to_delayed_inbox = l1_contracts; sc_rollup_address; sc_rollup_node; - l2_chain_id; + l2_chain_ids; _; } _protocol -> + let l2_chain_id = List.hd l2_chain_ids in let amount = Tez.of_int 16 in let depositor = Constant.bootstrap5 in let receiver = @@ -1289,10 +1374,11 @@ let test_rpc_produceBlock = ~time_between_blocks:Nothing ~tags:["evm"; "sequencer"; "produce_block"] ~title:"RPC method produceBlock" - @@ fun {sequencer; _} _protocol -> - let*@ start_block_number = Rpc.block_number sequencer in + @@ fun {sequencer; l2_chain_ids; _} _protocol -> + let l2_chain_id = List.hd l2_chain_ids in + let*@ start_block_number = Rpc.block_number ~l2_chain_id sequencer in let*@ _ = produce_block sequencer in - let*@ new_block_number = Rpc.block_number sequencer in + let*@ new_block_number = Rpc.block_number ~l2_chain_id sequencer in Check.((Int32.succ start_block_number = new_block_number) int32) ~error_msg:"Expected new block number to be %L, but got: %R" ; unit @@ -1361,10 +1447,11 @@ let test_delayed_transfer_is_included = sequencer; proxy; observer; - l2_chain_id; + l2_chain_ids; _; } _protocol -> + let l2_chain_id = List.hd l2_chain_ids in let endpoint = Evm_node.endpoint sequencer in (* This is a transfer from Eth_account.bootstrap_accounts.(0) to Eth_account.bootstrap_accounts.(1). *) @@ -1426,10 +1513,11 @@ let test_largest_delayed_transfer_is_included = sc_rollup_node; sequencer; proxy; - l2_chain_id; + l2_chain_ids; _; } _protocol -> + let l2_chain_id = List.hd l2_chain_ids in let _endpoint = Evm_node.endpoint sequencer in (* This is the largest ethereum transaction we transfer via the bridge contract. *) let max_data = String.make 64896 '0' in @@ -1509,10 +1597,11 @@ let test_delayed_deposit_is_included = sc_rollup_node; sequencer; proxy; - l2_chain_id; + l2_chain_ids; _; } _protocol -> + let l2_chain_id = List.hd l2_chain_ids in let endpoint = Evm_node.endpoint sequencer in let amount = Tez.of_int 16 in @@ -1631,11 +1720,12 @@ let test_delayed_fa_deposit_is_included = sc_rollup_node; sequencer; proxy; - l2_chain_id; + l2_chain_ids; _; } _protocol -> (* let endpoint = Evm_node.endpoint sequencer in *) + let l2_chain_id = List.hd l2_chain_ids in let amount = 42 in let depositor = Constant.bootstrap5 in let receiver = "0x1074Fd1EC02cbeaa5A90450505cF3B48D834f3EB" in @@ -1707,11 +1797,12 @@ let test_delayed_fa_deposit_is_ignored_if_feature_disabled = sc_rollup_node; sequencer; proxy; - l2_chain_id; + l2_chain_ids; _; } _protocol -> (* let endpoint = Evm_node.endpoint sequencer in *) + let l2_chain_id = List.hd l2_chain_ids in let amount = 42 in let depositor = Constant.bootstrap5 in let receiver = "0x1074Fd1EC02cbeaa5A90450505cF3B48D834f3EB" in @@ -1833,11 +1924,12 @@ let test_invalid_delayed_transaction = sc_rollup_node; sequencer; proxy; - l2_chain_id; + l2_chain_ids; _; } _protocol -> (* Produces an invalid transaction by setting an invalid nonce. *) + let l2_chain_id = List.hd l2_chain_ids in let* invalid_nonce = Cast.craft_tx ~source_private_key:Eth_account.bootstrap_accounts.(0).private_key @@ -1928,11 +2020,12 @@ let test_fa_withdrawal_is_included = sc_rollup_node; sequencer; proxy; - l2_chain_id; + l2_chain_ids; _; } _protocol -> (* 1. Deposit some tickets *) + let l2_chain_id = List.hd l2_chain_ids in let amount = 42 in let depositor = Constant.bootstrap5 in let receiver = Eth_account.bootstrap_accounts.(0).address in @@ -2165,10 +2258,11 @@ let test_delayed_deposit_from_init_rollup_node = sc_rollup_node; sequencer; proxy; - l2_chain_id; + l2_chain_ids; _; } _protocol -> + let l2_chain_id = List.hd l2_chain_ids in let receiver = "0x1074Fd1EC02cbeaa5A90450505cF3B48D834f3EB" in let* receiver_balance_prev = Eth_cli.balance ~account:receiver ~endpoint:(Evm_node.endpoint sequencer) () @@ -2200,7 +2294,7 @@ let test_delayed_deposit_from_init_rollup_node = let mode = Evm_node.mode sequencer |> Evm_node.mode_with_new_private_rpc in Evm_node.create ~mode (Sc_rollup_node.endpoint sc_rollup_node) in - let* () = Process.check @@ Evm_node.spawn_init_config new_sequencer in + let* () = Evm_node.spawn_init_config new_sequencer in let* () = Evm_node.init_from_rollup_node_data_dir new_sequencer sc_rollup_node in @@ -2261,7 +2355,7 @@ let test_init_from_rollup_node_data_dir = ~mode:(Evm_node.mode sequencer) (Sc_rollup_node.endpoint sc_rollup_node) in - let* () = Process.check @@ Evm_node.spawn_init_config evm_node' in + let* () = Evm_node.spawn_init_config evm_node' in let* () = (* bake 2 blocks so rollup context is for the finalized l1 level and can't be reorged. *) @@ -2300,12 +2394,13 @@ let test_init_from_rollup_node_with_delayed_inbox = client; l1_contracts; sc_rollup_address; - l2_chain_id; + l2_chain_ids; _; } _protocol -> (* The sequencer is needed to produce an initial block for the init from rollup node to work. *) + let l2_chain_id = List.hd l2_chain_ids in let* () = bake_until_sync ~sc_rollup_node ~client ~sequencer ~proxy () in let* () = Evm_node.terminate sequencer in let* () = Evm_node.terminate observer in @@ -2330,7 +2425,7 @@ let test_init_from_rollup_node_with_delayed_inbox = ~mode:(Evm_node.mode sequencer) (Sc_rollup_node.endpoint sc_rollup_node) in - let* () = Process.check @@ Evm_node.spawn_init_config sequencer in + let* () = Evm_node.spawn_init_config sequencer in let* () = Evm_node.init_from_rollup_node_data_dir sequencer sc_rollup_node in let* () = Evm_node.run sequencer in (* The sequencer should have items in its delayed inbox. *) @@ -2343,7 +2438,7 @@ let test_init_from_rollup_node_with_delayed_inbox = let observer = Evm_node.create ~mode:(Evm_node.mode observer) (Evm_node.endpoint sequencer) in - let* () = Process.check @@ Evm_node.spawn_init_config observer in + let* () = Evm_node.spawn_init_config observer in let* () = Evm_node.init_from_rollup_node_data_dir ~omit_delayed_tx_events:true @@ -2472,8 +2567,10 @@ let test_observer_applies_blueprint_from_rpc_node = connects to a RPC mode process. *) let levels_to_wait = 3 in - let* rpc_node = run_new_rpc_endpoint sequencer_node in - let* observer_node = run_new_observer_node ~sc_rollup_node rpc_node in + let* rpc_node = run_new_rpc_endpoint ~l2_chain_id:1 sequencer_node in + let* observer_node = + run_new_observer_node ~l2_chain_id:1 ~sc_rollup_node rpc_node + in let* _ = Evm_node.wait_for_blueprint_applied observer_node levels_to_wait and* _ = Evm_node.wait_for_blueprint_applied sequencer_node levels_to_wait @@ -2597,9 +2694,7 @@ let test_get_balance_block_param = ~data_dir:(Temp.dir name) (Evm_node.endpoint sequencer) in - let* () = - Process.check @@ Evm_node.spawn_init_config observer_partial_history - in + let* () = Evm_node.spawn_init_config observer_partial_history in let* () = Evm_node.init_from_rollup_node_data_dir observer_partial_history @@ -2671,9 +2766,7 @@ let test_get_block_by_number_block_param = ~data_dir:(Temp.dir name) (Evm_node.endpoint sequencer) in - let* () = - Process.check @@ Evm_node.spawn_init_config observer_partial_history - in + let* () = Evm_node.spawn_init_config observer_partial_history in let* () = Evm_node.init_from_rollup_node_data_dir observer_partial_history @@ -3249,10 +3342,11 @@ let test_legacy_deposits_dispatched_after_kernel_upgrade = client; sequencer; proxy; - l2_chain_id; + l2_chain_ids; _; } _protocol -> + let l2_chain_id = List.hd l2_chain_ids in let* () = match Kernel.commit_of from with | Some from_commit -> @@ -5105,13 +5199,17 @@ let test_force_kernel_upgrade_too_early = client; sequencer; proxy; + l2_chain_ids; _; } _protocol -> (* Wait for the sequencer to publish its genesis block. *) let* () = bake_until_sync ~sc_rollup_node ~client ~sequencer ~proxy () in let* proxy = - Evm_node.init ~mode:Proxy (Sc_rollup_node.endpoint sc_rollup_node) + Evm_node.init + ~mode:Proxy + ~l2_chain_ids + (Sc_rollup_node.endpoint sc_rollup_node) in (* Assert the kernel version is the same at start up. *) @@ -5166,13 +5264,17 @@ let test_force_kernel_upgrade = client; sequencer; proxy; + l2_chain_ids; _; } _protocol -> (* Wait for the sequencer to publish its genesis block. *) let* () = bake_until_sync ~sc_rollup_node ~client ~sequencer ~proxy () in let* proxy = - Evm_node.init ~mode:Proxy (Sc_rollup_node.endpoint sc_rollup_node) + Evm_node.init + ~mode:Proxy + ~l2_chain_ids + (Sc_rollup_node.endpoint sc_rollup_node) in (* Assert the kernel version is the same at start up. *) @@ -5663,7 +5765,7 @@ let test_sequencer_upgrade = in Evm_node.create ~mode (Sc_rollup_node.endpoint sc_rollup_node) in - let* () = Process.check @@ Evm_node.spawn_init_config new_sequencer in + let* () = Evm_node.spawn_init_config new_sequencer in let* _ = Evm_node.wait_for_shutdown_event sequencer and* () = @@ -5752,7 +5854,7 @@ let test_sequencer_diverge = in return @@ Evm_node.create ~mode (Sc_rollup_node.endpoint sc_rollup_node) in - let* () = Process.check @@ Evm_node.spawn_init_config sequencer_bis in + let* () = Evm_node.spawn_init_config sequencer_bis in let* () = Runnable.run @@ Evm_node.import_snapshot sequencer_bis ~snapshot_file in @@ -5760,7 +5862,9 @@ let test_sequencer_diverge = let* () = Evm_node.run sequencer_bis in (* We start a new observer for the new sequencer and wait for it to catch-up *) - let* observer_bis = run_new_observer_node ~sc_rollup_node sequencer_bis in + let* observer_bis = + run_new_observer_node ~l2_chain_id:1 ~sc_rollup_node sequencer_bis + in let* () = Evm_node.wait_for_blueprint_applied observer_bis 4 in (* When run in the CI the shutdown event are sometimes handled after the @@ -5942,10 +6046,11 @@ let test_outbox_size_limit_resilience ~slow = sc_rollup_node; sequencer; proxy; - l2_chain_id; + l2_chain_ids; _; } _protocol -> + let l2_chain_id = List.hd l2_chain_ids in let endpoint = Evm_node.endpoint sequencer in (* Make a tez deposit *) @@ -6477,7 +6582,7 @@ let test_preimages_endpoint = ~mode:sequencer_mode_without_preimages_dir (Sc_rollup_node.endpoint sc_rollup_node) in - let* () = Process.check @@ Evm_node.spawn_init_config new_sequencer in + let* () = Evm_node.spawn_init_config new_sequencer in (* Prepares the observer without [preimages-dir], to force the use of preimages endpoint. *) let observer_mode_without_preimages_dir () = @@ -6502,8 +6607,8 @@ let test_preimages_endpoint = (Evm_node.endpoint new_observer) in - let* () = Process.check @@ Evm_node.spawn_init_config new_observer in - let* () = Process.check @@ Evm_node.spawn_init_config new_observer2 in + let* () = Evm_node.spawn_init_config new_observer in + let* () = Evm_node.spawn_init_config new_observer2 in let* () = repeat 2 (fun () -> @@ -6673,7 +6778,7 @@ let test_trace_transaction = @@ fun {sequencer; _} _protocol -> (* Start a RPC node, as we also want to test that the sequencer and its RPC node return the same thing. *) - let* rpc_node = run_new_rpc_endpoint sequencer in + let* rpc_node = run_new_rpc_endpoint ~l2_chain_id:1 sequencer in (* Transfer funds to a random address. *) let address = "0xB7A97043983f24991398E5a82f63F4C58a417185" in let* transaction_hash = @@ -6755,6 +6860,7 @@ let test_overwrite_simulation_tick_limit = let* observer = run_new_observer_node ~sc_rollup_node + ~l2_chain_id:1 ~patch_config: JSON.( update @@ -7936,7 +8042,7 @@ let test_trace_call = @@ fun {sc_rollup_node; sequencer; client; proxy = _; _} _protocol -> (* Start a RPC node as well, since we will want to check it returns the same result as the sequencer *) - let* rpc_node = run_new_rpc_endpoint sequencer in + let* rpc_node = run_new_rpc_endpoint ~l2_chain_id:1 sequencer in (* Transfer funds to a random address. *) let endpoint = Evm_node.endpoint sequencer in let sender = Eth_account.bootstrap_accounts.(0) in @@ -8149,7 +8255,8 @@ let test_finalized_view = and the RPC does not fail, which is not the expected result when running this test without DAL activation. *) ~use_dal:Register_without_feature - @@ fun {sc_rollup_node; client; sequencer; proxy; _} _protocol -> + @@ fun {sc_rollup_node; client; sequencer; proxy; l2_chain_ids; _} _protocol + -> (* Start a proxy node with --finalized-view enabled *) let* finalized_proxy = Evm_node.init @@ -8158,10 +8265,15 @@ let test_finalized_view = fun json -> put ("finalized_view", annotate ~origin:"" (`Bool true)) json) ~mode:Proxy + ~l2_chain_ids (Sc_rollup_node.endpoint sc_rollup_node) in let* finalized_observer = - run_new_observer_node ~finalized_view:true ~sc_rollup_node sequencer + run_new_observer_node + ~l2_chain_id:1 + ~finalized_view:true + ~sc_rollup_node + sequencer in (* Produce a few EVM blocks *) let* _ = @@ -8252,7 +8364,11 @@ let test_finalized_view_forward_txn = @@ fun {sc_rollup_node; client; sequencer; _} _protocol -> (* Start a proxy node with --finalized-view enabled *) let* finalized_observer = - run_new_observer_node ~finalized_view:true ~sc_rollup_node sequencer + run_new_observer_node + ~l2_chain_id:1 + ~finalized_view:true + ~sc_rollup_node + sequencer in (* Produce a few EVM blocks *) let* _ = @@ -8311,7 +8427,7 @@ let test_finalized_block_param = "The finalized block parameter is correctly interpreted by the EVM node" ~da_fee:Wei.zero @@ fun {sc_rollup_node; client; sequencer; proxy; _} _protocol -> - let* rpc = run_new_rpc_endpoint sequencer in + let* rpc = run_new_rpc_endpoint ~l2_chain_id:1 sequencer in (* Produce a few EVM blocks *) let* () = repeat 4 @@ fun () -> @@ -8428,7 +8544,7 @@ let test_sequencer_sandbox () = Constant.smart_rollup_installer; ] @@ fun () -> - let* sequencer = init_sequencer_sandbox () in + let* sequencer = init_sequencer_sandbox ~l2_chain_ids:[1] () in let*@ _ = produce_block sequencer in let* tx_hash = send_transaction_to_sequencer @@ -8457,7 +8573,7 @@ let test_rpc_mode_while_block_are_produced = ready at all to accept concurrent read-only access to the SQLite and Irmin stores, the test was failing, demonstrating that it was capturing the expected behavior. *) - let* rpc_node = run_new_rpc_endpoint sequencer in + let* rpc_node = run_new_rpc_endpoint ~l2_chain_id:1 sequencer in let latest_block_number = ref 0l in @@ -9209,6 +9325,7 @@ let test_websocket_newPendingTransactions_event = @@ fun {sequencer; sc_rollup_node; _} _protocol -> let* observer = run_new_observer_node + ~l2_chain_id:1 ~finalized_view:false ~sc_rollup_node ~websockets:true @@ -9712,6 +9829,7 @@ let test_filling_max_slots_cant_lead_to_out_of_memory = let protocols = Protocol.all let () = + test_multi_chain protocols ; test_remove_sequencer protocols ; test_persistent_state protocols ; test_snapshots protocols ; diff --git a/etherlink/tezt/tests/gc.ml b/etherlink/tezt/tests/gc.ml index 48240fdcf1b0044b666b58eeeaa2665436f712bb..ad64daeae89927b62171051dbb6c3c05901974fe 100644 --- a/etherlink/tezt/tests/gc.ml +++ b/etherlink/tezt/tests/gc.ml @@ -46,7 +46,11 @@ let register ?genesis_timestamp () in let* sequencer = - Helpers.init_sequencer_sandbox ?genesis_timestamp ~patch_config () + Helpers.init_sequencer_sandbox + ?genesis_timestamp + ~patch_config + ~l2_chain_ids:[1] + () in f sequencer diff --git a/etherlink/tezt/tests/validate.ml b/etherlink/tezt/tests/validate.ml index 418c0aa696a445148df04bb63e9377b5196f9d23..bd756ca0a3079ee7ee7c874bd870e110d6e0e1fb 100644 --- a/etherlink/tezt/tests/validate.ml +++ b/etherlink/tezt/tests/validate.ml @@ -44,6 +44,7 @@ let register ?maximum_gas_per_transaction ?set_account_code ?da_fee_per_byte ?da_fee_per_byte ?minimum_base_fee_per_gas ~patch_config + ~l2_chain_ids:[1] () in f sequencer tx_type) diff --git a/src/kernel_sdk/host/src/runtime.rs b/src/kernel_sdk/host/src/runtime.rs index 93009036bac5c7b2e644bed71be4458d84b8b687..41df8f38779616dfe5ebd86723a05568b4a848ed 100644 --- a/src/kernel_sdk/host/src/runtime.rs +++ b/src/kernel_sdk/host/src/runtime.rs @@ -30,11 +30,11 @@ use tezos_smart_rollup_core::smart_rollup_core::ReadInputMessageInfo; #[cfg(feature = "alloc")] use alloc::string::String; -#[derive(Eq, PartialEq, Clone, Debug)] +#[derive(Copy, Eq, PartialEq, Clone, Debug)] /// Errors that may be returned when called [Runtime] methods. pub enum RuntimeError { /// Attempted to read from/delete a key that does not exist. - PathNotFound(String), + PathNotFound, /// Attempted to get a subkey at an out-of-bounds index. StoreListIndexOutOfBounds, /// Errors returned by the host functions @@ -55,7 +55,7 @@ impl std::error::Error for RuntimeError { impl core::fmt::Display for RuntimeError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - Self::PathNotFound(s) => write!(f, "RuntimeError::PathNotFound {}", s), + Self::PathNotFound => write!(f, "RuntimeError::PathNotFound"), Self::HostErr(e) => e.fmt(f), Self::DecodingError => write!(f, "RuntimeError::DecodingError"), Self::StoreListIndexOutOfBounds => { @@ -485,7 +485,7 @@ where fn store_delete>(&mut self, path: &T) -> Result<(), RuntimeError> { if let Ok(None) = Runtime::store_has(self, path) { - return Err(RuntimeError::PathNotFound(format!("{}", path))); + return Err(RuntimeError::PathNotFound); } let res = @@ -731,13 +731,13 @@ fn check_path_has_value<'a>( runtime: &'a impl Runtime, path: &'a impl Path, ) -> impl FnOnce(RuntimeError) -> RuntimeError + 'a { - move |err| { + |err| { if let Ok(Some(ValueType::Value | ValueType::ValueWithSubtree)) = runtime.store_has(path) { err } else { - RuntimeError::PathNotFound(format!("{}", path)) + RuntimeError::PathNotFound } } } @@ -746,11 +746,11 @@ fn check_path_exists<'a, T: Path>( runtime: &'a impl Runtime, path: &'a T, ) -> impl FnOnce(RuntimeError) -> RuntimeError + 'a { - move |err| { + |err| { if let Ok(Some(_)) = runtime.store_has(path) { err } else { - RuntimeError::PathNotFound(format!("{}", path)) + RuntimeError::PathNotFound } } } diff --git a/src/kernel_sdk/installer-client/src/commands.rs b/src/kernel_sdk/installer-client/src/commands.rs index a7c5df673aac98d448f8f98dd838493986ead98d..74577b3ece229c4a2c6d278b3a49087e1887d77a 100644 --- a/src/kernel_sdk/installer-client/src/commands.rs +++ b/src/kernel_sdk/installer-client/src/commands.rs @@ -27,6 +27,9 @@ pub enum Commands { #[arg(short = 'S', long, value_name = "INSTALLER_SETUP_CONFIG")] setup_file: Option, + #[arg(short = 'L', long, value_name = "L2_SETUP_CONFIG")] + l2_setup_file: Vec, + #[arg(short, long, value_name = "DISPLAY_ROOT_HASH")] display_root_hash: bool, }, diff --git a/src/kernel_sdk/installer-client/src/config.rs b/src/kernel_sdk/installer-client/src/config.rs index cfc9281ebdedd770113a5e033d4b0fe672e03935..afd199cbcb1c2c98956a7a8f6e1c186b37b8bae0 100644 --- a/src/kernel_sdk/installer-client/src/config.rs +++ b/src/kernel_sdk/installer-client/src/config.rs @@ -24,14 +24,27 @@ pub enum ConfigurationError { } // Path that we write the kernel to, before upgrading. -const PREPARE_KERNEL_PATH: RefPath = RefPath::assert_from(b"/installer/kernel/boot.wasm"); +const PREPARE_KERNEL_PATH: RefPath = + RefPath::assert_from(b"/installer/kernel/boot.wasm"); // Path of currently running kernel. const KERNEL_BOOT_PATH: RefPath = RefPath::assert_from(b"/kernel/boot.wasm"); -pub fn create_installer_config( +fn setup_file_to_config( + setup_file: OsString, + content_to_config: impl Fn(Vec) -> Option, +) -> Result { + let setup_file = + File::open(Path::new(&setup_file)).map_err(ConfigurationError::FileNotFound)?; + let yaml_config: YamlConfig = + YamlConfig::from_reader(setup_file).map_err(ConfigurationError::ParseError)?; + Ok(yaml_config.to_config_program(content_to_config)?) +} + +pub fn create_installer_multi_chain_config( root_hash: PreimageHash, - setup_file: Option, + rollup_setup_file: Option, + l2_setup_file: Vec, preimages_dir: Option<&Path>, ) -> Result { let mut reveal_instructions = vec![ @@ -49,18 +62,17 @@ pub fn create_installer_config( crate::preimages::content_to_preimages(content, preimages_dir.unwrap()).ok() }; - let setup_program: OwnedConfigProgram = match setup_file { + let setup_program: OwnedConfigProgram = match rollup_setup_file { None => OwnedConfigProgram(vec![]), - Some(setup_file) => { - let setup_file = File::open(Path::new(&setup_file)) - .map_err(ConfigurationError::FileNotFound)?; - let yaml_config: YamlConfig = YamlConfig::from_reader(setup_file) - .map_err(ConfigurationError::ParseError)?; - yaml_config.to_config_program(content_to_config)? - } + Some(setup_file) => setup_file_to_config(setup_file, content_to_config)?, }; reveal_instructions.extend(setup_program.0); + for setup_file in l2_setup_file.into_iter() { + let setup_l2_program = setup_file_to_config(setup_file, content_to_config)?; + reveal_instructions.extend(setup_l2_program.0); + } + Ok(OwnedConfigProgram(reveal_instructions)) } diff --git a/src/kernel_sdk/installer-client/src/main.rs b/src/kernel_sdk/installer-client/src/main.rs index 2ef3551ea65cb6612d4ea7ad0cae01a8ecb066d0..b742ba6e05fb02e2fe08f708fba8901d67bb3b7c 100644 --- a/src/kernel_sdk/installer-client/src/main.rs +++ b/src/kernel_sdk/installer-client/src/main.rs @@ -11,7 +11,9 @@ use clap::Parser; use commands::Cli; use commands::Commands; use std::path::Path; -use tezos_smart_rollup_installer::config::{create_installer_config, ConfigurationError}; +use tezos_smart_rollup_installer::config::{ + create_installer_multi_chain_config, ConfigurationError, +}; use thiserror::Error; fn main() -> Result<(), ClientError> { @@ -21,8 +23,10 @@ fn main() -> Result<(), ClientError> { output, preimages_dir, setup_file, + l2_setup_file, display_root_hash, } => { + println!("Taille l2: {}", l2_setup_file.len()); let upgrade_to = Path::new(&upgrade_to); let output = Path::new(&output); let preimages_dir = Path::new(&preimages_dir); @@ -33,8 +37,12 @@ fn main() -> Result<(), ClientError> { let root_hash = preimages::content_to_preimages(kernel, preimages_dir)?; let root_hash_hex = hex::encode(root_hash.as_ref()); - let config = - create_installer_config(root_hash, setup_file, Some(preimages_dir))?; + let config = create_installer_multi_chain_config( + root_hash, + setup_file, + l2_setup_file, + Some(preimages_dir), + )?; let kernel = installer::with_config_program(config); output::save_kernel(output, &kernel).map_err(ClientError::SaveInstaller)?; diff --git a/src/kernel_sdk/storage/src/layer.rs b/src/kernel_sdk/storage/src/layer.rs index f1fffed3a35aa3611d0c91a042c83aa67c0e0c4c..324eae4a2e6eca7822a045fc995f73c2238bbff4 100644 --- a/src/kernel_sdk/storage/src/layer.rs +++ b/src/kernel_sdk/storage/src/layer.rs @@ -65,7 +65,7 @@ impl>> Layer Ok(copy), + Ok(()) | Err(RuntimeError::PathNotFound) => Ok(copy), Err(e) => Err(e.into()), } } diff --git a/src/kernel_sdk/storage/src/lib.rs b/src/kernel_sdk/storage/src/lib.rs index ff3b0a45abd2ca052e0e2404564aef3a0fa9d22a..0993331f1448d2b8367ec88b36a1b63eff663b9a 100644 --- a/src/kernel_sdk/storage/src/lib.rs +++ b/src/kernel_sdk/storage/src/lib.rs @@ -14,7 +14,7 @@ use thiserror::Error; /// All errors that may occur when using the accoun transaction API. When /// the error variant encapsulates some other error type, this is where the /// error originates from the durable storage interface on the host runtime. -#[derive(Error, Eq, PartialEq, Clone, Debug)] +#[derive(Error, Copy, Eq, PartialEq, Clone, Debug)] pub enum StorageError { /// Invalid accounts path. Could not get the string representation of /// the accounts storage path. diff --git a/tezt/lib_tezos/sc_rollup_helpers.ml b/tezt/lib_tezos/sc_rollup_helpers.ml index d1eb940ced54a4b3428153685f8c4197c3730f88..54e9b744f3fc0157fd3fd43b039304dfbf5b57dc 100644 --- a/tezt/lib_tezos/sc_rollup_helpers.ml +++ b/tezt/lib_tezos/sc_rollup_helpers.ml @@ -121,6 +121,26 @@ type installer_result = { root_hash : string; } +let handle_config config = + match config with + | `Config config -> + let setup_file = Temp.file "setup-config.yaml" in + Base.write_file + setup_file + ~contents:(Installer_kernel_config.to_yaml config) ; + setup_file + | `Path path -> path + | `Both (config, path) -> + let setup_file = Temp.file "setup-config.yaml" in + let base_config = Base.read_file path in + let new_contents = + String.concat "" (List.map Installer_kernel_config.instr_to_yaml config) + in + let contents = base_config ^ new_contents in + Log.info "installer config:\n%s" contents ; + Base.write_file setup_file ~contents ; + setup_file + (* Testing the installation of a larger kernel, with e2e messages. When a kernel is too large to be originated directly, we can install @@ -129,7 +149,7 @@ type installer_result = { *) let prepare_installer_kernel_with_arbitrary_file ?output ?smart_rollup_installer_path ?runner ?(boot_sector = `Content) - ~preimages_dir ?config installee = + ~preimages_dir ?config ?l2_configs installee = let open Tezt.Base in let open Lwt.Syntax in let output = @@ -141,32 +161,22 @@ let prepare_installer_kernel_with_arbitrary_file ?output | Some v -> v in let setup_file_args = - match config with - | Some config -> - let setup_file = - match config with - | `Config config -> - let setup_file = Temp.file "setup-config.yaml" in - Base.write_file - setup_file - ~contents:(Installer_kernel_config.to_yaml config) ; - setup_file - | `Path path -> path - | `Both (config, path) -> - let setup_file = Temp.file "setup-config.yaml" in - let base_config = Base.read_file path in - let new_contents = - String.concat - "" - (List.map Installer_kernel_config.instr_to_yaml config) - in - let contents = base_config ^ new_contents in - Log.info "installer config:\n%s" contents ; - Base.write_file setup_file ~contents ; - setup_file - in + match (config, l2_configs) with + | Some config, None -> + let setup_file = handle_config config in ["--setup-file"; setup_file] - | None -> [] + | Some config, Some l2_configs -> + let setup_file = handle_config config in + let l2_setups = + List.map + (fun config -> ["--l2-setup-file"; handle_config config]) + l2_configs + in + List.flatten (["--setup-file"; setup_file] :: l2_setups) + | None, Some _ -> + (* Not possible to provide l2_chains setup file but not the main one*) + assert false + | None, None -> [] in let* process = let smart_rollup_installer_path = @@ -209,12 +219,14 @@ let prepare_installer_kernel_with_arbitrary_file ?output root_hash; } -let prepare_installer_kernel ?output ?runner ~preimages_dir ?config installee = +let prepare_installer_kernel ?output ?runner ~preimages_dir ?config ?l2_configs + installee = prepare_installer_kernel_with_arbitrary_file ?output ?runner ~preimages_dir ?config + ?l2_configs (Uses.path installee) let default_boot_sector_of ~kind = diff --git a/tezt/lib_tezos/sc_rollup_helpers.mli b/tezt/lib_tezos/sc_rollup_helpers.mli index a43bc2223893973f1ddd74eb2633c7e244df7b04..fccab48a86ddaf93bea8c6f44df528ea4fc20f6e 100644 --- a/tezt/lib_tezos/sc_rollup_helpers.mli +++ b/tezt/lib_tezos/sc_rollup_helpers.mli @@ -92,6 +92,10 @@ val prepare_installer_kernel : [< `Config of Installer_kernel_config.t | `Path of string | `Both of Installer_kernel_config.t * string ] -> + ?l2_configs: + [< `Config of Installer_kernel_config.t + | `Path of string + | `Both of Installer_kernel_config.t * string ] list -> Uses.t -> installer_result Lwt.t @@ -107,6 +111,11 @@ val prepare_installer_kernel_with_arbitrary_file : [< `Config of Installer_kernel_config.t | `Path of string | `Both of Installer_kernel_config.t * string ] -> + ?l2_configs: + [< `Config of Installer_kernel_config.t + | `Path of string + | `Both of Installer_kernel_config.t * string ] + list -> string -> installer_result Lwt.t