From 55213ce0430d371697d1483c168f1f9200b0a962 Mon Sep 17 00:00:00 2001 From: arnaud Date: Thu, 6 Feb 2025 10:27:20 +0100 Subject: [PATCH 1/8] Evm_node/Refactoring: Move le_int64_bytes function outside of make in kernel_config.ml --- etherlink/bin_node/lib_dev/kernel_config.ml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/etherlink/bin_node/lib_dev/kernel_config.ml b/etherlink/bin_node/lib_dev/kernel_config.ml index d5b0b7076546..a9ed7f2ff9ee 100644 --- a/etherlink/bin_node/lib_dev/kernel_config.ml +++ b/etherlink/bin_node/lib_dev/kernel_config.ml @@ -2,6 +2,7 @@ (* *) (* SPDX-License-Identifier: MIT *) (* Copyright (c) 2024 Nomadic Labs *) +(* Copyright (c) 2025 Functori *) (* *) (*****************************************************************************) @@ -22,6 +23,11 @@ let parse_z_to_padded_32_le_int_bytes s = let z = Z.of_string s in padded_32_le_int_bytes z +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 ~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 @@ -56,11 +62,6 @@ let make ~mainnet_compat ~boostrap_balance ?bootstrap_accounts ?kernel_root_hash 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 - in (* Convert a comma-separated list of decimal values in the [0; 255] range into a sequence of bytes (of type string). *) let decimal_list_to_bytes l = -- GitLab From b2f37609120c6180a3991ed764d9ecd263f0451d Mon Sep 17 00:00:00 2001 From: arnaud Date: Wed, 12 Feb 2025 10:25:11 +0100 Subject: [PATCH 2/8] EVM node: Expose a string conversion function for Chain_id type --- etherlink/bin_node/lib_dev/encodings/ethereum_types.ml | 8 ++++++-- etherlink/bin_node/lib_dev/encodings/ethereum_types.mli | 9 ++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/etherlink/bin_node/lib_dev/encodings/ethereum_types.ml b/etherlink/bin_node/lib_dev/encodings/ethereum_types.ml index 58d7e199cee3..e8c40ab05549 100644 --- a/etherlink/bin_node/lib_dev/encodings/ethereum_types.ml +++ b/etherlink/bin_node/lib_dev/encodings/ethereum_types.ml @@ -3,7 +3,7 @@ (* Open Source License *) (* Copyright (c) 2023 Nomadic Labs *) (* Copyright (c) 2023 Marigold *) -(* Copyright (c) 2024 Functori *) +(* Copyright (c) 2024-2025 Functori *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -128,10 +128,14 @@ let decode_z_be bytes = type chain_id = Chain_id of Z.t [@@ocaml.unboxed] module Chain_id = struct + let of_string_exn s = Chain_id (Z.of_string s) + + let to_string (Chain_id s) = Z.to_string s + let encoding = Data_encoding.conv (fun (Chain_id c) -> z_to_hexa c) - (fun c -> Chain_id (Z.of_string c)) + of_string_exn Data_encoding.string let decode_le bytes = Chain_id (decode_z_le bytes) diff --git a/etherlink/bin_node/lib_dev/encodings/ethereum_types.mli b/etherlink/bin_node/lib_dev/encodings/ethereum_types.mli index ed79c265fed2..887610972d2a 100644 --- a/etherlink/bin_node/lib_dev/encodings/ethereum_types.mli +++ b/etherlink/bin_node/lib_dev/encodings/ethereum_types.mli @@ -3,7 +3,7 @@ (* Open Source License *) (* Copyright (c) 2023 Nomadic Labs *) (* Copyright (c) 2023 Marigold *) -(* Copyright (c) 2024 Functori *) +(* Copyright (c) 2024-2025 Functori *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -58,6 +58,13 @@ type chain_id = Chain_id of Z.t [@@unboxed] module Chain_id : sig val encoding : chain_id Data_encoding.t + (** [of_string_exn hex] transforms a string to a chain id. + It raises an exception if the string is not an number + (base 10, hexa, binary, octal ...) *) + val of_string_exn : string -> chain_id + + val to_string : chain_id -> string + val decode_le : bytes -> chain_id val decode_be : bytes -> chain_id -- GitLab From 5204170a0daa68467d0dab46c611dfb3743eda4c Mon Sep 17 00:00:00 2001 From: arnaud Date: Mon, 24 Feb 2025 10:28:43 +0100 Subject: [PATCH 3/8] Etherlink/Node/Refactoring: Subkeys are more explicit in kernel_config.ml --- etherlink/bin_node/lib_dev/kernel_config.ml | 29 ++++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/etherlink/bin_node/lib_dev/kernel_config.ml b/etherlink/bin_node/lib_dev/kernel_config.ml index a9ed7f2ff9ee..4d2f5bf6e427 100644 --- a/etherlink/bin_node/lib_dev/kernel_config.ml +++ b/etherlink/bin_node/lib_dev/kernel_config.ml @@ -6,7 +6,10 @@ (* *) (*****************************************************************************) -let make_instr ?(path_prefix = "/evm/") ?(convert = Fun.id) arg_opt = +let make_path = function [] -> "" | l -> "/" ^ String.concat "/" l ^ "/" + +let make_instr ?(path_prefix = ["evm"]) ?(convert = Fun.id) arg_opt = + let path_prefix = make_path path_prefix in arg_opt |> Option.map (fun (key, value) -> Installer_config.make ~key:(path_prefix ^ key) ~value:(convert value)) @@ -44,8 +47,8 @@ let make ~mainnet_compat ~boostrap_balance ?bootstrap_accounts ?kernel_root_hash List.map (fun address -> make_instr - ~path_prefix:"/evm/world_state/eth_accounts/" - (Some (address ^ "/balance", balance))) + ~path_prefix:["evm"; "world_state"; "eth_accounts"; address] + (Some ("balance", balance))) bootstrap_accounts |> List.flatten in @@ -57,8 +60,8 @@ let make ~mainnet_compat ~boostrap_balance ?bootstrap_accounts ?kernel_root_hash (fun (address, code) -> make_instr ~convert:encode_hexa - ~path_prefix:"/evm/world_state/eth_accounts/" - (Some (address ^ "/code", code))) + ~path_prefix:["evm"; "world_state"; "eth_accounts"; address] + (Some ("code", code))) set_account_codes |> List.flatten in @@ -70,10 +73,10 @@ let make ~mainnet_compat ~boostrap_balance ?bootstrap_accounts ?kernel_root_hash |> String.of_seq in let instrs = - (if mainnet_compat then make_instr ~path_prefix:"/evm/" ticketer + (if mainnet_compat then make_instr ticketer else (* For compatibility reason for Mainnet and Ghostnet *) - make_instr ~path_prefix:"/evm/world_state/" ticketer) + make_instr ~path_prefix:["evm"; "world_state"] ticketer) @ make_instr ~convert:(fun s -> Hex.to_bytes_exn (`Hex s) |> Bytes.to_string) kernel_root_hash @@ -83,11 +86,11 @@ let make ~mainnet_compat ~boostrap_balance ?bootstrap_accounts ?kernel_root_hash @ make_instr kernel_governance @ make_instr kernel_security_governance @ make_instr - ~path_prefix:"/evm/world_state/fees/" + ~path_prefix:["evm"; "world_state"; "fees"] ~convert:parse_z_to_padded_32_le_int_bytes minimum_base_fee_per_gas @ make_instr - ~path_prefix:"/evm/world_state/fees/" + ~path_prefix:["evm"; "world_state"; "fees"] ~convert:parse_z_to_padded_32_le_int_bytes da_fee_per_byte @ make_instr ~convert:le_int64_bytes delayed_inbox_timeout @@ -102,13 +105,13 @@ let make ~mainnet_compat ~boostrap_balance ?bootstrap_accounts ?kernel_root_hash @ 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 ~path_prefix:["evm"; "feature_flags"] enable_fa_bridge + @ make_instr ~path_prefix:["evm"; "feature_flags"] enable_dal @ make_instr - ~path_prefix:"/evm/world_state/feature_flags/" + ~path_prefix:["evm"; "world_state"; "feature_flags"] enable_fast_withdrawal @ make_instr ~convert:decimal_list_to_bytes dal_slots - @ make_instr ~path_prefix:"/evm/feature_flags/" enable_multichain + @ make_instr ~path_prefix:["evm"; "feature_flags"] enable_multichain @ make_instr ~convert:(fun s -> Ethereum_types.u16_to_bytes (int_of_string s)) max_delayed_inbox_blueprint_length -- GitLab From d1b6ed4abc68c6859a543d5616ea7e03f0809687 Mon Sep 17 00:00:00 2001 From: arnaud Date: Tue, 21 Jan 2025 13:30:02 +0100 Subject: [PATCH 4/8] Evm_node: Add a new command make l2 kernel configuration --- etherlink/bin_node/lib_dev/kernel_config.ml | 77 ++++++++++++++++++++ etherlink/bin_node/lib_dev/kernel_config.mli | 19 ++++- etherlink/bin_node/main.ml | 70 ++++++++++++++++++ 3 files changed, 165 insertions(+), 1 deletion(-) diff --git a/etherlink/bin_node/lib_dev/kernel_config.ml b/etherlink/bin_node/lib_dev/kernel_config.ml index 4d2f5bf6e427..c070a0e5902e 100644 --- a/etherlink/bin_node/lib_dev/kernel_config.ml +++ b/etherlink/bin_node/lib_dev/kernel_config.ml @@ -15,6 +15,12 @@ let make_instr ?(path_prefix = ["evm"]) ?(convert = Fun.id) arg_opt = Installer_config.make ~key:(path_prefix ^ key) ~value:(convert value)) |> Option.to_list +let make_l2_config_instr ?(convert = Fun.id) ~l2_chain_id config = + make_instr + ~path_prefix:["evm"; "chain_configurations"; l2_chain_id] + ~convert + config + let padded_32_le_int_bytes z = String.of_bytes @@ Ethereum_types.encode_u256_le (Qty z) @@ -31,6 +37,77 @@ let le_int64_bytes i = Bytes.set_int64_le b 0 (Int64.of_string i) ; String.of_bytes b +(* When splitting the path given in argument, + their should be empty string at the start/end of + the list *) +let clean_path path = + List.fold_left + (fun acc l -> if l = "" then acc else l :: acc) + [] + (List.rev path) + +let make_l2 ~boostrap_balance ?bootstrap_accounts ?minimum_base_fee_per_gas + ?da_fee_per_byte ?sequencer_pool_address ?maximum_gas_per_transaction + ?set_account_code ?world_state_path ~l2_chain_id ~output () = + let world_state_prefix = + match world_state_path with + | None -> ["evm"; "world_state"; l2_chain_id] + | Some (_, value) -> clean_path (String.split_on_char '/' value) + in + let bootstrap_accounts = + match bootstrap_accounts with + | None -> [] + | Some bootstrap_accounts -> + let balance = padded_32_le_int_bytes boostrap_balance in + List.map + (fun address -> + make_instr + ~path_prefix:(world_state_prefix @ ["eth_accounts"; address]) + (Some ("balance", balance))) + bootstrap_accounts + |> List.flatten + in + let set_account_code = + match set_account_code with + | None -> [] + | Some set_account_codes -> + List.map + (fun (address, code) -> + make_instr + ~convert:encode_hexa + ~path_prefix:(world_state_prefix @ ["eth_accounts"; address]) + (Some ("code", code))) + set_account_codes + |> List.flatten + in + let config_instrs = + (* These configuration parameter will not be stored in the world_state of an l2 chain but are parameter for an l2 chain *) + (* To do so we put them into another path /evm/config/ *) + make_l2_config_instr + ~l2_chain_id + ~convert:parse_z_to_padded_32_le_int_bytes + minimum_base_fee_per_gas + @ make_l2_config_instr + ~l2_chain_id + ~convert:parse_z_to_padded_32_le_int_bytes + da_fee_per_byte + @ make_l2_config_instr + ~l2_chain_id + ~convert:le_int64_bytes + maximum_gas_per_transaction + @ make_l2_config_instr ~l2_chain_id world_state_path + in + let world_state_instrs = + make_instr + ~convert:(fun addr -> + let addr = Misc.normalize_addr addr in + Hex.to_bytes_exn (`Hex addr) |> String.of_bytes) + ~path_prefix:world_state_prefix + sequencer_pool_address + @ bootstrap_accounts @ set_account_code + in + Installer_config.to_file (config_instrs @ world_state_instrs) ~output + 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 diff --git a/etherlink/bin_node/lib_dev/kernel_config.mli b/etherlink/bin_node/lib_dev/kernel_config.mli index 506f31c444bf..ae656139d910 100644 --- a/etherlink/bin_node/lib_dev/kernel_config.mli +++ b/etherlink/bin_node/lib_dev/kernel_config.mli @@ -2,7 +2,7 @@ (* *) (* SPDX-License-Identifier: MIT *) (* Copyright (c) 2024 Nomadic Labs *) -(* Copyright (c) 2024 Functori *) +(* Copyright (c) 2024-2025 Functori *) (* *) (*****************************************************************************) @@ -41,3 +41,20 @@ val make : output:string -> unit -> unit tzresult Lwt.t + +(** [make_l2 ~boostrap_balance ?bootstrap_accounts ... ~l2_chain_id ~output ()] + generates a configuration file located at [output] for the chain [l2_chain_id], + where [bootstrap_accounts] are provisioned with [bootstrap_balance]. *) +val make_l2 : + boostrap_balance:Z.t -> + ?bootstrap_accounts:string list -> + ?minimum_base_fee_per_gas:string * string -> + ?da_fee_per_byte:string * string -> + ?sequencer_pool_address:string * string -> + ?maximum_gas_per_transaction:string * string -> + ?set_account_code:(string * string) list -> + ?world_state_path:string * string -> + l2_chain_id:string -> + output:string -> + unit -> + unit tzresult Lwt.t diff --git a/etherlink/bin_node/main.ml b/etherlink/bin_node/main.ml index 6f8e5acc42b0..a20be2d532d7 100644 --- a/etherlink/bin_node/main.ml +++ b/etherlink/bin_node/main.ml @@ -1850,6 +1850,75 @@ let set_account_code = Lwt.return_ok (address, code) | _ -> failwith "Parsing error for set-code") +let make_l2_kernel_config_command = + let open Tezos_clic in + let open Lwt_result_syntax in + let open Evm_node_lib_dev_encoding.Ethereum_types in + command + ~desc: + "Produce a file containing the part of the kernel configuration \ + instructions related to a particular L2 chain." + (args9 + (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:"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:"world_state_path" + ~placeholder:"/evm/world_state/") + (Tezos_clic.arg + ~long:"l2-chain-id" + ~doc:"L2 chain id" + ~placeholder:"1" + (Tezos_clic.parameter (fun _ s -> return @@ Chain_id.of_string_exn s)))) + (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 ( minimum_base_fee_per_gas, + da_fee_per_byte, + sequencer_pool_address, + maximum_gas_per_transaction, + boostrap_balance, + bootstrap_accounts, + set_account_code, + world_state_path, + l2_chain_id ) + output + () -> + let* l2_chain_id = + match l2_chain_id with + | None -> + failwith + "Chain_id is mandatory when trying to setup an l2 chain, use \ + --l2-chain-id to set it." + | Some l2_chain_id -> return (Chain_id.to_string l2_chain_id) + in + Evm_node_lib_dev.Kernel_config.make_l2 + ?minimum_base_fee_per_gas + ?da_fee_per_byte + ?sequencer_pool_address + ?maximum_gas_per_transaction + ~boostrap_balance + ?bootstrap_accounts + ?set_account_code + ?world_state_path + ~l2_chain_id + ~output + ()) + let make_kernel_config_command = let open Tezos_clic in let open Lwt_result_syntax in @@ -2695,6 +2764,7 @@ let commands = 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; -- GitLab From 49cf8972e87862ade12edf0c8cc98c5652869880 Mon Sep 17 00:00:00 2001 From: arnaud Date: Mon, 10 Feb 2025 16:35:59 +0100 Subject: [PATCH 5/8] Etherlink/Tezt: Update the Evm node man regression file --- .../evm_sequencer.ml/EVM Node- man.out | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- man.out b/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- man.out index e7d862c58de5..5b89e52759f3 100644 --- a/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- man.out +++ b/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- man.out @@ -510,6 +510,27 @@ Miscellaneous commands: --max-delayed-inbox-blueprint-length <1000>: value for max_delayed_inbox_blueprint_length in the installer config --enable-fast-withdrawal: enable flag enable_fast_withdrawal in the installer config + octez-evm-node make l2 kernel installer config [--minimum-base-fee-per-gas <111...>] + [--da-fee-per-byte <111...>] + [--sequencer-pool-address <0x...>] + [--maximum-gas-per-transaction <30000...>] + [--bootstrap-balance <9999000000000000000000>] + [--bootstrap-account <0x...>] + [--set-code <0x...,0x....>] + [--world-state-path >] + [--l2-chain-id <1>] + Produce a file containing the part of the kernel configuration instructions related to a particular L2 chain. + : file path where the config will be written to + --minimum-base-fee-per-gas <111...>: value for minimum_base_fee_per_gas in the installer config + --da-fee-per-byte <111...>: value for da_fee_per_byte in the installer config + --sequencer-pool-address <0x...>: value for sequencer_pool_address in the installer config + --maximum-gas-per-transaction <30000...>: value for maximum_gas_per_transaction in the installer config + --bootstrap-balance <9999000000000000000000>: balance of the bootstrap accounts + --bootstrap-account <0x...>: add a bootstrap account in the installer config. + --set-code <0x...,0x....>: add code to an account in the installer config. + --world-state-path >: value for world_state_path in the installer config + --l2-chain-id <1>: L2 chain id + octez-evm-node patch state at with [--data-dir ] [--block-number ] [-f --force] 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. -- GitLab From d79ae0ceb0ba511d4110e14fe6b7a75a2304a5a4 Mon Sep 17 00:00:00 2001 From: arnaud Date: Thu, 6 Feb 2025 14:28:36 +0100 Subject: [PATCH 6/8] Etherlink/Tezt: Add the support of the new evm_node command in the etherlink tezt library --- etherlink/tezt/lib/evm_node.ml | 45 ++++++++++++++++++++++++++++++++- etherlink/tezt/lib/evm_node.mli | 18 ++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/etherlink/tezt/lib/evm_node.ml b/etherlink/tezt/lib/evm_node.ml index 352d391f7b3a..237453ada080 100644 --- a/etherlink/tezt/lib/evm_node.ml +++ b/etherlink/tezt/lib/evm_node.ml @@ -4,7 +4,7 @@ (* Copyright (c) 2023 Nomadic Labs *) (* Copyright (c) 2023 Functori *) (* Copyright (c) 2023 Marigold *) -(* Copyright (c) 2024 Functori *) +(* Copyright (c) 2024-2025 Functori *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -1674,6 +1674,49 @@ let make_kernel_installer_config ?max_delayed_inbox_blueprint_length let process = Process.spawn (Uses.path Constant.octez_evm_node) cmd in Runnable.{value = process; run = Process.check} +let make_l2_kernel_installer_config ?chain_id ?bootstrap_balance + ?bootstrap_accounts ?minimum_base_fee_per_gas ?(da_fee_per_byte = Wei.zero) + ?sequencer_pool_address ?maximum_gas_per_transaction + ?(set_account_code = []) ?world_state_path ~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 "l2-chain-id" string_of_int chain_id + @ Cli_arg.optional_arg + "minimum-base-fee-per-gas" + Wei.to_string + minimum_base_fee_per_gas + @ Cli_arg.optional_arg "world-state-path" Fun.id world_state_path + @ ["--da-fee-per-byte"; Wei.to_string da_fee_per_byte] + @ Cli_arg.optional_arg + "sequencer-pool-address" + Fun.id + sequencer_pool_address + @ set_account_code + @ Cli_arg.optional_arg + "maximum-gas-per-transaction" + Int64.to_string + maximum_gas_per_transaction + @ Cli_arg.optional_arg "bootstrap-balance" Wei.to_string bootstrap_balance + @ + match bootstrap_accounts with + | None -> [] + | Some bootstrap_accounts -> + List.flatten + @@ List.map + (fun bootstrap_account -> + ["--bootstrap-account"; bootstrap_account]) + bootstrap_accounts + in + let process = Process.spawn (Uses.path Constant.octez_evm_node) cmd in + Runnable.{value = process; run = Process.check} + let preimages_dir evm_node = let rec from_node ~data_dir = function | Sandbox {preimage_dir; _} diff --git a/etherlink/tezt/lib/evm_node.mli b/etherlink/tezt/lib/evm_node.mli index 1c9ab477bd79..caaf52884d9e 100644 --- a/etherlink/tezt/lib/evm_node.mli +++ b/etherlink/tezt/lib/evm_node.mli @@ -4,7 +4,7 @@ (* Copyright (c) 2023 Nomadic Labs *) (* Copyright (c) 2023 Functori *) (* Copyright (c) 2023 Marigold *) -(* Copyright (c) 2024 Functori *) +(* Copyright (c) 2024-2025 Functori *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -550,6 +550,22 @@ val snapshot_info : snapshot_file:string -> (Process.t, string) runnable val wait_termination : t -> unit Lwt.t +(** [make_l2_kernel_installer_config ~output ()] create the config needed for + a l2 chain in a multichain kernel *) +val make_l2_kernel_installer_config : + ?chain_id:int -> + ?bootstrap_balance:Wei.t -> + ?bootstrap_accounts:string list -> + ?minimum_base_fee_per_gas:Wei.t -> + ?da_fee_per_byte:Wei.t -> + ?sequencer_pool_address:string -> + ?maximum_gas_per_transaction:int64 -> + ?set_account_code:(string * string) list -> + ?world_state_path:string -> + output:string -> + unit -> + (Process.t, unit) runnable + (** [make_kernel_installer_config ~output ()] create the config needed for the evm kernel used by the installer *) val make_kernel_installer_config : -- GitLab From 4803e0af11e23c02c6618adad3465a5339041928 Mon Sep 17 00:00:00 2001 From: arnaud Date: Fri, 7 Feb 2025 14:15:27 +0100 Subject: [PATCH 7/8] Sc_rollup/Tezt/Lib: Add in tezt interface to use merge_setup file --- tezt/lib_tezos/sc_rollup_helpers.ml | 54 ++++++++++++++++++++++++++++ tezt/lib_tezos/sc_rollup_helpers.mli | 29 ++++++++++++++- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/tezt/lib_tezos/sc_rollup_helpers.ml b/tezt/lib_tezos/sc_rollup_helpers.ml index d2311d73ba65..100d4b6bb84c 100644 --- a/tezt/lib_tezos/sc_rollup_helpers.ml +++ b/tezt/lib_tezos/sc_rollup_helpers.ml @@ -4,6 +4,7 @@ (* Copyright (c) 2023 Nomadic Labs *) (* Copyright (c) 2022-2023 TriliTech *) (* Copyright (c) 2023 Marigold *) +(* Copyright (c) 2025 Functori *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -209,6 +210,59 @@ let prepare_installer_kernel_with_arbitrary_file ?output root_hash; } +(* This function takes a path and retrieve the name of the file without + all the dir and the extension *) +let name_of_file path = Filename.(remove_extension (basename path)) + +let merge_setup_files ?smart_rollup_installer_path ?runner ?output configs = + let open Tezt.Base in + let open Lwt.Syntax in + let output = + match output with + | None -> + Temp.file (String.concat "_" (List.map name_of_file configs) ^ ".yaml") + | Some output -> output + in + let* process = + let smart_rollup_installer_path = + match smart_rollup_installer_path with + | None -> project_root // Uses.path Constant.smart_rollup_installer + | Some path -> path + in + Process.spawn + ?runner + ~name:output + smart_rollup_installer_path + (["merge-setup-files"; "--output"; output; "--setup-files"] @ configs) + |> Lwt.return + in + let+ () = Runnable.run @@ Runnable.{value = process; run = Process.check} in + output + +let prepare_installer_kernel_with_multiple_setup_file ?output + ?smart_rollup_installer_path ?runner ?boot_sector ~preimages_dir ?configs + installee = + let open Tezt.Base in + let open Lwt.Syntax in + let* config = + match configs with + | None -> return None + | Some [config] -> return (Some (`Path config)) + | Some configs -> + let+ output = + merge_setup_files ?smart_rollup_installer_path ?runner configs + in + Some (`Path output) + in + prepare_installer_kernel_with_arbitrary_file + ?output + ?smart_rollup_installer_path + ?runner + ?boot_sector + ~preimages_dir + ?config + installee + let prepare_installer_kernel ?output ?runner ~preimages_dir ?config installee = prepare_installer_kernel_with_arbitrary_file ?output diff --git a/tezt/lib_tezos/sc_rollup_helpers.mli b/tezt/lib_tezos/sc_rollup_helpers.mli index 4b0da3dd8d27..def74bfdf825 100644 --- a/tezt/lib_tezos/sc_rollup_helpers.mli +++ b/tezt/lib_tezos/sc_rollup_helpers.mli @@ -3,7 +3,7 @@ (* Open Source License *) (* Copyright (c) 2021-2023 Nomadic Labs *) (* Copyright (c) 2022-2023 TriliTech *) -(* Copyright (c) 2023 Functori *) +(* Copyright (c) 2023-2025 Functori *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -95,6 +95,21 @@ val prepare_installer_kernel : Uses.t -> installer_result Lwt.t +(** [merge_setup_files ?output configs] + feeds the [smart-rollup-installer] with multiple setup files + ([configs]), and write in [output] the setup file that is the + concatenation of all the configs files. + + The returned setup file may be passed to [prepare_installer_kernel] + as a {!`Path} configuration. +*) +val merge_setup_files : + ?smart_rollup_installer_path:string -> + ?runner:Runner.t -> + ?output:string -> + string list -> + string Lwt.t + (** Same as [prepare_installer_kernel] but not forcing to use pre-generated kernels. Should be used for kernel generated by the test itself. *) val prepare_installer_kernel_with_arbitrary_file : @@ -110,6 +125,18 @@ val prepare_installer_kernel_with_arbitrary_file : string -> installer_result Lwt.t +(** Same as [prepare_installer_kernel_with_arbitrary_file] but can take multiple + configuration files and merge them with [merge_setup_files]. *) +val prepare_installer_kernel_with_multiple_setup_file : + ?output:string -> + ?smart_rollup_installer_path:string -> + ?runner:Runner.t -> + ?boot_sector:[`Content | `Filename] -> + preimages_dir:string -> + ?configs:string list -> + string -> + installer_result Lwt.t + (** [setup_l1 protocol] initializes a protocol with the given parameters, and returns the L1 node and client. *) val setup_l1 : -- GitLab From c4b0f019c2e4d3ba6c3bd0ab671317cf907fa632 Mon Sep 17 00:00:00 2001 From: arnaud Date: Fri, 7 Feb 2025 17:59:34 +0100 Subject: [PATCH 8/8] Etherlink/Tezt: A new tezt to try the new make_l2_kernel_installer --- etherlink/tezt/tests/evm_sequencer.ml | 119 ++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/etherlink/tezt/tests/evm_sequencer.ml b/etherlink/tezt/tests/evm_sequencer.ml index b53a5b14300f..2dfc96fa109c 100644 --- a/etherlink/tezt/tests/evm_sequencer.ml +++ b/etherlink/tezt/tests/evm_sequencer.ml @@ -347,6 +347,124 @@ let register_upgrade_all ~title ~tags ~genesis_timestamp protocols) kernels +let test_make_l2_kernel_installer_config = + Protocol.register_test + ~__FILE__ + ~title: + "Test that the command make_l2_kernel_installer setup bootstrap account \ + at the right path" + ~tags:["evm"; "multichain"; "installer"] + ~uses_admin_client:true + ~uses_client:true + ~uses_node:true + ~uses:(fun _protocol -> + [ + Constant.octez_evm_node; + Constant.octez_smart_rollup_node; + Constant.WASM.evm_kernel; + Constant.smart_rollup_installer; + ]) + @@ fun protocol -> + let* node, client = setup_l1 protocol in + + (* Random chain id, let's not take one that could have been set by default (1, 42, 1337) *) + let chain_id = 2988 in + + (* Configuration files for an l2 chain and for the rollup *) + let l2_config = Temp.file "l2-chain-config.yaml" in + let rollup_config = Temp.file "rollup-chain-config.yaml" in + + (* Argument for the l2 chain, a bootstrap account and a new world_state_path *) + let world_state_path = "/test/chain/" in + let address = Eth_account.bootstrap_accounts.(0).address in + let*! () = + Evm_node.make_l2_kernel_installer_config + ~chain_id + ~world_state_path + ~bootstrap_accounts:[address] + ~output:l2_config + () + in + let*! () = + Evm_node.make_kernel_installer_config + (* No need for a real sequencer governance *) + ~sequencer_governance:"KT1" + ~output:rollup_config + () + in + + (* Setup the rollup (Origination and Start a rollup node) *) + let sc_rollup_node = + Sc_rollup_node.create + ~default_operator:Constant.bootstrap1.public_key_hash + Batcher + node + ~base_dir:(Client.base_dir client) + in + + let preimages_dir = Sc_rollup_node.data_dir sc_rollup_node // "wasm_2_0_0" in + let kernel = Constant.WASM.evm_kernel in + let* {output = kernel; _} = + prepare_installer_kernel_with_multiple_setup_file + ~output:(Temp.file "kernel.hex") + ~preimages_dir + ~configs:[rollup_config; l2_config] + (Uses.path kernel) + in + let* sc_rollup_address = + originate_sc_rollup + ~keys:[] + ~kind:"wasm_2_0_0" + ~boot_sector:("file:" ^ kernel) + ~parameters_ty:Helpers.evm_type + client + in + let* () = + Sc_rollup_node.run sc_rollup_node sc_rollup_address [Log_kernel_debug] + in + + (* Setup a sequencer with a private rpc port to verify the durable storage. *) + let sequencer = + Evm_node.Sequencer + { + initial_kernel = kernel; + preimage_dir = Some preimages_dir; + private_rpc_port = Some (Port.fresh ()); + time_between_blocks = Some Nothing; + sequencer = Constant.bootstrap1.alias; + genesis_timestamp = None; + max_blueprints_lag = None; + max_blueprints_ahead = None; + max_blueprints_catchup = None; + 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 + let* sequencer = + Evm_node.init ~mode:sequencer (Sc_rollup_node.endpoint sc_rollup_node) + in + + (* Verify that the balance of the bootstrap account is set by the command + `make_l2_kernel_installer_config` *) + let address_in_durable = Helpers.remove_0x (String.lowercase_ascii address) in + let address_balance = + world_state_path ^ "eth_accounts/" ^ address_in_durable ^ "/balance" + in + let*@ rpc = Rpc.state_value sequencer address_balance in + match rpc with + | None -> + Test.fail + ~__LOC__ + "There should be a value at %s setup by the \ + make_l2_kernel_installer_config" + address_balance + | Some _bootstrap_value -> return () + (* The test uses a very specific setup, so it doesn't use general helpers. *) let test_observer_reset = Protocol.register_test @@ -10095,6 +10213,7 @@ let () = test_miner protocols ; test_fa_bridge_feature_flag protocols ; test_multichain_feature_flag protocols ; + test_make_l2_kernel_installer_config protocols ; test_fast_withdrawal_feature_flag protocols ; test_trace_call protocols ; test_trace_empty_block protocols ; -- GitLab