From 2ec20214512c5e65cf6bd1d6d422a099e4ee5493 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Cornilleau Date: Fri, 6 Jun 2025 17:10:18 +0200 Subject: [PATCH 1/3] EVM/Node: split sandbox command args We want to add a sandbox for tezlink, so we isolate the arguments that only make sense for etherlink sandbox, to reuse the rest --- etherlink/bin_node/main.ml | 42 ++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/etherlink/bin_node/main.ml b/etherlink/bin_node/main.ml index 4a9919c97f88..6d02fc893e69 100644 --- a/etherlink/bin_node/main.ml +++ b/etherlink/bin_node/main.ml @@ -2312,7 +2312,7 @@ let fund_arg = Tezos_clic.multiple_arg ~long ~doc ~placeholder:"0x..." Params.eth_address let sandbox_config_args = - Tezos_clic.args16 + Tezos_clic.args12 preimages_arg preimages_endpoint_arg native_execution_policy_arg @@ -2323,12 +2323,15 @@ let sandbox_config_args = (kernel_arg ()) wallet_dir_arg (Client_config.password_filename_arg ()) + disable_da_fees_arg + kernel_verbosity_arg + +let etherlink_sandbox_config_args = + Tezos_clic.args4 (supported_network_arg ()) init_from_snapshot_arg fund_arg replicate_arg - disable_da_fees_arg - kernel_verbosity_arg let sequencer_command = let open Tezos_clic in @@ -2423,7 +2426,9 @@ let sandbox_command = "Start the EVM node in sandbox mode. The sandbox mode is a \ sequencer-like mode that produces blocks with a fake key and no rollup \ node connection." - (merge_options common_config_args sandbox_config_args) + (merge_options + common_config_args + (merge_options sandbox_config_args etherlink_sandbox_config_args)) (prefixes ["run"; "sandbox"] stop) (fun ( ( data_dir, config_file, @@ -2446,22 +2451,19 @@ let sandbox_command = blacklisted_rpcs, whitelisted_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, - network, - init_from_snapshot, - funded_addresses, - main_endpoint, - disable_da_fees, - kernel_verbosity ) ) + ( ( preimages, + preimages_endpoint, + native_execution_policy, + time_between_blocks, + max_number_of_chunks, + private_rpc_port, + genesis_timestamp, + kernel, + wallet_dir, + password_filename, + disable_da_fees, + kernel_verbosity ), + (network, init_from_snapshot, funded_addresses, main_endpoint) ) ) () -> let open Lwt_result_syntax in let* restricted_rpcs = -- GitLab From c46a2f09a6be67e277a3b022fc5e690657e8f7fe Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Cornilleau Date: Fri, 6 Jun 2025 17:12:23 +0200 Subject: [PATCH 2/3] EVM/Node: run tezlink sandbox command For now it just passes along the relevant arguments. The next commit will activate the tezlink mode of teh kernel and the node. --- etherlink/bin_node/main.ml | 105 ++++++++++++++++++ .../evm_sequencer.ml/EVM Node- man.out | 93 +++++++++++++++- 2 files changed, 196 insertions(+), 2 deletions(-) diff --git a/etherlink/bin_node/main.ml b/etherlink/bin_node/main.ml index 6d02fc893e69..5bb539139b06 100644 --- a/etherlink/bin_node/main.ml +++ b/etherlink/bin_node/main.ml @@ -2538,6 +2538,110 @@ let sandbox_command = ~finalized_view config_file) +let tezlink_sandbox_command = + let open Tezos_clic in + command + ~group:Groups.run + ~desc: + "Start the EVM node in tezlink sandbox mode. The sandbox mode is a \ + sequencer-like mode that produces blocks with a fake key and no rollup \ + node connection." + (merge_options common_config_args sandbox_config_args) + (prefixes ["run"; "tezlink"; "sandbox"] stop) + (fun ( ( data_dir, + config_file, + rpc_addr, + rpc_port, + rpc_batch_limit, + cors_origins, + cors_headers, + enable_websocket, + 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, + 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, + disable_da_fees, + kernel_verbosity ) ) + () -> + let open Lwt_result_syntax in + let* restricted_rpcs = + pick_restricted_rpcs restricted_rpcs whitelisted_rpcs blacklisted_rpcs + in + let rollup_node_endpoint = + Option.value ~default:Uri.empty rollup_node_endpoint + in + let _pkh, pk, sk = + Tezos_crypto.Signature.(generate_key ~algo:Ed25519) () + in + let sandbox_config = + Evm_node_lib_dev.Sequencer. + { + public_key = pk; + secret_key = sk; + init_from_snapshot = None; + network = None; + funded_addresses = []; + parent_chain = None; + disable_da_fees; + kernel_verbosity; + } + in + let config_file = config_filename ~data_dir config_file in + start_sequencer + ?password_filename + ~wallet_dir + ~data_dir + ?rpc_addr + ?rpc_port + ?rpc_batch_limit + ?cors_origins + ?cors_headers + ?enable_websocket + ?tx_pool_timeout_limit + ?tx_pool_addr_limit + ?tx_pool_tx_per_addr_limit + ~keep_alive + ~rollup_node_endpoint + ~verbose + ?preimages + ?preimages_endpoint + ?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 + ~catchup_cooldown:100_000_000 + ?log_filter_max_nb_blocks + ?log_filter_max_nb_logs + ?log_filter_chunk_size + ?genesis_timestamp + ?restricted_rpcs + ?kernel + ~sandbox_config + ~finalized_view + config_file) + let observer_run_args = Tezos_clic.args12 private_rpc_port_arg @@ -3022,6 +3126,7 @@ let in_development_commands = [] let commands = [ sandbox_command; + tezlink_sandbox_command; proxy_command; sequencer_command; observer_command; 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 53b989c515ea..b01db3db05bf 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 @@ -45,9 +45,10 @@ Run commands: [--private-rpc-port ] [--genesis-timestamp <[TIMESTAMP]>] [--kernel ] [-d --wallet-dir ] - [-f --password-filename ] [--network ] + [-f --password-filename ] [--disable-da-fees] + [--kernel-verbosity ] [--network ] [--init-from-snapshot [snapshot url]] [--fund <0x...>] - [--replicate [url]] [--disable-da-fees] [--kernel-verbosity ] + [--replicate [url]] Start the EVM node in sandbox mode. The sandbox mode is a sequencer-like mode that produces blocks with a fake key and no rollup node connection. --data-dir : The path to the EVM node data directory. @@ -114,6 +115,9 @@ Run commands: Defaults to the value of the environment variable `$TEZOS_CLIENT_DIR` if it exists, or `$HOME/.tezos-client` otherwise. -f --password-filename : path to the password filename + --disable-da-fees: Disable DA fees for this replay. + --kernel-verbosity : Sets kernel's logging verbosity, either + `fatal`, `error`, `info`, `debug`. --network : The network the EVM node will be connecting to. Can be `mainnet` or `testnet`. If set, defaults to the value of EVM_NODE_NETWORK. @@ -133,6 +137,91 @@ Run commands: --replicate [url]: Replicate a chain in real time from the EVM node whose address is provided. Defaults to `the official relay endpoint if --network is used`. + + run tezlink sandbox [--data-dir ] [--config-file ] + [--rpc-addr ] [--rpc-port ] [--rpc-batch-limit ] + [--cors-origins ] [--cors-headers ] + [--ws [BOOL?]] [--max-number-blocks <100>] [--max-number-logs <1000>] + [--chunk-size <10>] [-K --keep-alive] [--rollup-node-endpoint ] + [--tx-pool-timeout-limit <3_600>] [--tx-pool-addr-limit <4_000>] + [--tx-pool-tx-per-addr-limit <16>] [-v --verbose] + [--restricted-rpcs ] [--blacklisted-rpcs ] + [--whitelisted-rpcs ] [--finalized-view] + [--preimages-dir <_evm_installer_preimages>] + [--preimages-endpoint ] [-n --native-execution-policy ] + [--time-between-blocks <10.>] [--max-number-of-chunks <10.>] + [--private-rpc-port ] + [--genesis-timestamp <[TIMESTAMP]>] + [--kernel ] [-d --wallet-dir ] + [-f --password-filename ] [--disable-da-fees] + [--kernel-verbosity ] + Start the EVM node in tezlink sandbox mode. The sandbox mode is a + sequencer-like mode that produces blocks with a fake key and no rollup + node connection. + --data-dir : The path to the EVM node data directory. + Defaults to the value of the environment variable `$EVM_NODE_DATA_DIR` + if it exists, or `$HOME/.octez-evm-node` otherwise. + --config-file : Path to a configuration file. Defaults to + `config.json` inside the data directory of the node. + If set, defaults to the value of EVM_NODE_CONFIG_FILE. + --rpc-addr : The EVM node server rpc address. + --rpc-port : The EVM node server rpc port. + --rpc-batch-limit : A limit on the number of requests allowed in a + single batch. Can either be `unlimited` or a positive integer. + --cors-origins : List of accepted cors origins. + --cors-headers : List of accepted cors headers. + --ws [BOOL?]: Enable websockets server when present or set to + true. + Defaults to ``true` when the switch is present, and is `false` + otherwise`. + --max-number-blocks <100>: Maximum number of blocks kept in the log. + --max-number-logs <1000>: Maximum number of logs kept. + --chunk-size <10>: Blocks to be filtered are split in chunks, which will + be filtered in sequence. Within each chunk, the block filtering is done + concurrently. + -K --keep-alive: Keep the EVM node process alive even if the connection + is lost with the rollup node. + --rollup-node-endpoint : The address of a rollup node. + --tx-pool-timeout-limit <3_600>: Transaction timeout limit inside the + transaction pool (in seconds). + --tx-pool-addr-limit <4_000>: Maximum allowed addresses inside the + transaction pool. + --tx-pool-tx-per-addr-limit <16>: Maximum allowed transactions per user + address inside the transaction pool. + -v --verbose: Sets logging level to debug. Beware, it is highly verbose. + --restricted-rpcs : Disable methods that matches the given + Perl-like regular expression. Cannot be used with --whitelisted-rpcs or + --blacklisted-rpcs. + --blacklisted-rpcs : Disable the RPC methods which are part of + the provided list. Cannot be used with --restricted-rpcs or + --whitelisted-rpcs. + --whitelisted-rpcs : Disable the RPC methods which are not + part of the provided list. Cannot be used with --restricted-rpcs or + --blacklisted-rpcs. + --finalized-view: If the flag is set, the node will use the latest final + state of the rollup, not its current HEAD, for any read-only operation. + --preimages-dir <_evm_installer_preimages>: Path to the preimages + directory. + --preimages-endpoint : The address of a service which provides + pre-images for the rollup. Missing pre-images will be downloaded + remotely if they are not already present on disk. + -n --native-execution-policy : Policy regarding the use of native + execution for supported kernels. Can be `never`, `rpcs_only` or + `always`. + --time-between-blocks <10.>: Interval (in seconds) at which the sequencer + creates an empty block by default. If set to `none`, blocks are + produced on demand only (see private method produceBlock). + --max-number-of-chunks <10.>: Maximum number of chunks per blueprint. + --private-rpc-port : The EVM node private server rpc port. + --genesis-timestamp <[TIMESTAMP]>: Timestamp used for the + genesis block, uses machine's clock if not provided. + --kernel : Path to the EVM kernel used to launch the + PVM, it will be loaded from storage afterward. + -d --wallet-dir : The directory where the Tezos client stores all + its wallet data. + Defaults to the value of the environment variable `$TEZOS_CLIENT_DIR` + if it exists, or `$HOME/.tezos-client` otherwise. + -f --password-filename : path to the password filename --disable-da-fees: Disable DA fees for this replay. --kernel-verbosity : Sets kernel's logging verbosity, either `fatal`, `error`, `info`, `debug`. -- GitLab From b9a749b5a0cce2ccc22bbc5b028963b99703cbee Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Cornilleau Date: Fri, 6 Jun 2025 17:13:44 +0200 Subject: [PATCH 3/3] EVM/Node: activate tezlink in tezlink sandbox --- etherlink/bin_node/lib_dev/sequencer.ml | 29 ++++++++++++++++++++ etherlink/bin_node/main.ml | 36 +++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/etherlink/bin_node/lib_dev/sequencer.ml b/etherlink/bin_node/lib_dev/sequencer.ml index 45a932ec8bab..830cc32c6d3d 100644 --- a/etherlink/bin_node/lib_dev/sequencer.ml +++ b/etherlink/bin_node/lib_dev/sequencer.ml @@ -15,6 +15,7 @@ type sandbox_config = { parent_chain : Uri.t option; disable_da_fees : bool; kernel_verbosity : Events.kernel_log_level option; + tezlink : int option; } let install_finalizer_seq server_public_finalizer server_private_finalizer @@ -109,6 +110,30 @@ let loop_sequencer chain_family backend in loop Misc.(now ())) +let activate_tezlink chain_id = + let open Lwt_result_syntax in + let* () = + Evm_context.patch_state + ~key:"/evm/feature_flags/enable_multichain" + ~value:"" + () + in + let* () = + Evm_context.patch_state + ~key:"/evm/chain_id" + ~value: + Ethereum_types.( + encode_u256_le (Qty Z.(of_int chain_id)) |> String.of_bytes) + () + in + let* () = + Evm_context.patch_state + ~key:(Format.sprintf "/evm/chain_configurations/%d/chain_family" chain_id) + ~value:"Michelson" + () + in + return_unit + let main ~data_dir ?(genesis_timestamp = Misc.now ()) ~cctxt ~(configuration : Configuration.t) ?kernel ?sandbox_config () = let open Lwt_result_syntax in @@ -169,6 +194,7 @@ let main ~data_dir ?(genesis_timestamp = Misc.now ()) ~cctxt funded_addresses; disable_da_fees; kernel_verbosity; + tezlink; _; } -> let* () = Evm_context.patch_sequencer_key pk in @@ -214,6 +240,9 @@ let main ~data_dir ?(genesis_timestamp = Misc.now ()) ~cctxt Ethereum_types.(encode_u256_le (Qty Z.zero) |> String.of_bytes) () in + let* () = + Option.iter_es (fun chain_id -> activate_tezlink chain_id) tezlink + in return_unit | None -> return_unit in diff --git a/etherlink/bin_node/main.ml b/etherlink/bin_node/main.ml index 5bb539139b06..d9bd66a7ebc9 100644 --- a/etherlink/bin_node/main.ml +++ b/etherlink/bin_node/main.ml @@ -1047,6 +1047,27 @@ let kernel_from_args network kernel = | Mainnet -> Some (In_memory Evm_node_supported_installers.mainnet) | Testnet -> None)) +let add_tezlink_to_node_configuration tezlink_chain_id configuration = + let open Configuration in + let experimental_features = + { + configuration.experimental_features with + l2_chains = + Option.either + configuration.experimental_features.l2_chains + (Some + [ + { + chain_id = Chain_id Z.(of_int tezlink_chain_id); + chain_family = Michelson; + }; + ]); + spawn_rpc = + Option.either configuration.experimental_features.spawn_rpc (Some 12345); + } + in + {configuration with experimental_features} + let start_sequencer ?password_filename ~wallet_dir ~data_dir ?rpc_addr ?rpc_port ?rpc_batch_limit ?cors_origins ?cors_headers ?enable_websocket ?tx_pool_timeout_limit ?tx_pool_addr_limit ?tx_pool_tx_per_addr_limit @@ -1109,6 +1130,17 @@ let start_sequencer ?password_filename ~wallet_dir ~data_dir ?rpc_addr ?rpc_port | None -> (* We are running in sequencer mode (not in sandbox mode), we need to disable native execution *) sequencer_disable_native_execution configuration + | Some Evm_node_lib_dev.Sequencer.{tezlink = Some chain_id; _} -> + (* We are running a tezlink sandbox, we need to activate tezlink node *) + let configuration = + add_tezlink_to_node_configuration chain_id configuration + in + (* We need to save the configuration to the data_dir, as we spawn a rpc + server based on the data_dir *) + let*! _ = + Configuration.save ~force:true ~data_dir configuration config_file + in + Lwt.return configuration | _ -> Lwt.return configuration in let* () = websocket_checks configuration in @@ -2499,6 +2531,7 @@ let sandbox_command = parent_chain; disable_da_fees; kernel_verbosity; + tezlink = None; } in let config_file = config_filename ~data_dir config_file in @@ -2538,6 +2571,8 @@ let sandbox_command = ~finalized_view config_file) +let tezlink_sandbox_chain_id = 12 + let tezlink_sandbox_command = let open Tezos_clic in command @@ -2603,6 +2638,7 @@ let tezlink_sandbox_command = parent_chain = None; disable_da_fees; kernel_verbosity; + tezlink = Some tezlink_sandbox_chain_id; } in let config_file = config_filename ~data_dir config_file in -- GitLab