From d773e4dd1ad58ee9735e22f21b0f025b9c2b078d Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Fri, 7 Nov 2025 15:20:29 +0100 Subject: [PATCH 1/7] Tezt/Etherlink: allow pre-funded addresses in sandbox --- etherlink/tezt/lib/evm_node.ml | 19 ++++++++++++++----- etherlink/tezt/lib/evm_node.mli | 1 + etherlink/tezt/lib/test_helpers.ml | 1 + 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/etherlink/tezt/lib/evm_node.ml b/etherlink/tezt/lib/evm_node.ml index 7b881475f612..5b1111626d70 100644 --- a/etherlink/tezt/lib/evm_node.ml +++ b/etherlink/tezt/lib/evm_node.ml @@ -97,6 +97,7 @@ type mode = } | Sandbox of { initial_kernel : string; + funded_addresses : string list; preimage_dir : string option; private_rpc_port : int option; time_between_blocks : time_between_blocks option; @@ -792,6 +793,7 @@ let mode_with_new_private_rpc (mode : mode) = genesis_timestamp; max_number_of_chunks; wallet_dir; + funded_addresses; tx_queue_max_lifespan; tx_queue_max_size; tx_queue_tx_per_addr_limit; @@ -806,6 +808,7 @@ let mode_with_new_private_rpc (mode : mode) = genesis_timestamp; max_number_of_chunks; wallet_dir; + funded_addresses; tx_queue_max_lifespan; tx_queue_max_size; tx_queue_tx_per_addr_limit; @@ -878,6 +881,12 @@ let config_file_arg evm_node = Fun.id evm_node.persistent_state.config_file +let fund_args funded_addresses = + List.fold_left + (fun acc pk -> Cli_arg.optional_arg "fund" Fun.id (Some pk) @ acc) + [] + funded_addresses + (* assume a valid config for the given command and uses new latest run command format. *) let run_args evm_node = @@ -896,7 +905,8 @@ let run_args evm_node = Client.time_of_timestamp timestamp |> Client.Time.to_notation) genesis_timestamp @ Cli_arg.optional_arg "wallet-dir" Fun.id wallet_dir - | Sandbox {initial_kernel; genesis_timestamp; wallet_dir; sequencer_keys; _} + | Sandbox + {initial_kernel; funded_addresses; genesis_timestamp; wallet_dir; sequencer_keys; _} -> let sequencer_keys = List.map (fun s -> ["--sequencer-key"; s]) sequencer_keys @@ -910,6 +920,7 @@ let run_args evm_node = Client.time_of_timestamp timestamp |> Client.Time.to_notation) genesis_timestamp @ Cli_arg.optional_arg "wallet-dir" Fun.id wallet_dir + @ fund_args funded_addresses | Tezlink_sandbox { initial_kernel; @@ -926,10 +937,7 @@ let run_args evm_node = Client.time_of_timestamp timestamp |> Client.Time.to_notation) genesis_timestamp @ Cli_arg.optional_arg "wallet-dir" Fun.id wallet_dir - @ List.fold_left - (fun acc pk -> Cli_arg.optional_arg "fund" Fun.id (Some pk) @ acc) - [] - funded_addresses + @ fund_args funded_addresses @ Cli_arg.optional_switch "verbose" verbose | Observer {initial_kernel; _} -> ["run"; "observer"; "--initial-kernel"; initial_kernel] @@ -1159,6 +1167,7 @@ let spawn_init_config ?(extra_arguments = []) evm_node = genesis_timestamp = _; max_number_of_chunks; wallet_dir; + funded_addresses = _; tx_queue_max_lifespan; tx_queue_max_size; tx_queue_tx_per_addr_limit; diff --git a/etherlink/tezt/lib/evm_node.mli b/etherlink/tezt/lib/evm_node.mli index 4a3a7f91e348..a6193bb2f4e7 100644 --- a/etherlink/tezt/lib/evm_node.mli +++ b/etherlink/tezt/lib/evm_node.mli @@ -100,6 +100,7 @@ type mode = } | Sandbox of { initial_kernel : string; + funded_addresses : string list; preimage_dir : string option; private_rpc_port : int option; time_between_blocks : time_between_blocks option; diff --git a/etherlink/tezt/lib/test_helpers.ml b/etherlink/tezt/lib/test_helpers.ml index 97abe86510e9..fddf4fc1c929 100644 --- a/etherlink/tezt/lib/test_helpers.ml +++ b/etherlink/tezt/lib/test_helpers.ml @@ -551,6 +551,7 @@ let init_sequencer_sandbox ?maximum_gas_per_transaction ?genesis_timestamp genesis_timestamp; max_number_of_chunks = None; wallet_dir = Some wallet_dir; + funded_addresses = []; tx_queue_max_lifespan; tx_queue_max_size; tx_queue_tx_per_addr_limit; -- GitLab From 026e0e58c6d9890dc9dab99fe2a37f8b99302bc3 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Fri, 7 Nov 2025 16:21:29 +0100 Subject: [PATCH 2/7] Tezt/Etherlink: allow to not specify initial kernel file path --- etherlink/tezt/lib/evm_node.ml | 35 ++++++++++++++++++--------- etherlink/tezt/lib/evm_node.mli | 7 +++--- etherlink/tezt/lib/test_helpers.ml | 3 ++- etherlink/tezt/tests/evm_sequencer.ml | 10 ++++---- tezt/tests/cloud/etherlink_helpers.ml | 2 +- 5 files changed, 36 insertions(+), 21 deletions(-) diff --git a/etherlink/tezt/lib/evm_node.ml b/etherlink/tezt/lib/evm_node.ml index 5b1111626d70..017423fa0130 100644 --- a/etherlink/tezt/lib/evm_node.ml +++ b/etherlink/tezt/lib/evm_node.ml @@ -68,7 +68,7 @@ let default_l2_setup ~l2_chain_id = type mode = | Observer of { - initial_kernel : string; + initial_kernel : string option; preimages_dir : string option; private_rpc_port : int option; rollup_node_endpoint : string option; @@ -96,7 +96,8 @@ type mode = sequencer_sunset_sec : int option; } | Sandbox of { - initial_kernel : string; + initial_kernel : string option; + network : string option; funded_addresses : string list; preimage_dir : string option; private_rpc_port : int option; @@ -179,11 +180,10 @@ let is_observer t = let initial_kernel t = let rec from_mode = function - | Sandbox {initial_kernel; _} - | Tezlink_sandbox {initial_kernel; _} - | Sequencer {initial_kernel; _} - | Observer {initial_kernel; _} -> + | Sandbox {initial_kernel; _} | Observer {initial_kernel; _} -> initial_kernel + | Tezlink_sandbox {initial_kernel; _} | Sequencer {initial_kernel; _} -> + Some initial_kernel | Rpc mode -> from_mode mode | Proxy -> Test.fail "cannot start a RPC node from a proxy node" in @@ -787,6 +787,7 @@ let mode_with_new_private_rpc (mode : mode) = | Sandbox { initial_kernel; + network; preimage_dir; private_rpc_port = Some _; time_between_blocks; @@ -802,6 +803,7 @@ let mode_with_new_private_rpc (mode : mode) = Sandbox { initial_kernel; + network; preimage_dir; private_rpc_port = Some (Port.fresh ()); time_between_blocks; @@ -906,13 +908,22 @@ let run_args evm_node = genesis_timestamp @ Cli_arg.optional_arg "wallet-dir" Fun.id wallet_dir | Sandbox - {initial_kernel; funded_addresses; genesis_timestamp; wallet_dir; sequencer_keys; _} - -> + { + initial_kernel; + network; + funded_addresses; + genesis_timestamp; + wallet_dir; + sequencer_keys; + _; + } -> let sequencer_keys = List.map (fun s -> ["--sequencer-key"; s]) sequencer_keys |> List.flatten in - ["run"; "sandbox"; "--kernel"; initial_kernel] + ["run"; "sandbox"] + @ Cli_arg.optional_arg "kernel" Fun.id initial_kernel + @ Cli_arg.optional_arg "network" Fun.id network @ sequencer_keys @ Cli_arg.optional_arg "genesis-timestamp" @@ -940,7 +951,8 @@ let run_args evm_node = @ fund_args funded_addresses @ Cli_arg.optional_switch "verbose" verbose | Observer {initial_kernel; _} -> - ["run"; "observer"; "--initial-kernel"; initial_kernel] + ["run"; "observer"] + @ Cli_arg.optional_arg "initial-kernel" Fun.id initial_kernel | Rpc _ -> ["experimental"; "run"; "rpc"] in mode_args @ shared_args @@ -1161,6 +1173,7 @@ let spawn_init_config ?(extra_arguments = []) evm_node = | Sandbox { initial_kernel = _; + network = _; preimage_dir; private_rpc_port; time_between_blocks; @@ -2025,7 +2038,7 @@ let switch_sequencer_to_observer ~(old_sequencer : t) ~(new_sequencer : t) = mode = Observer { - initial_kernel; + initial_kernel = Some initial_kernel; preimages_dir; private_rpc_port; rollup_node_endpoint = diff --git a/etherlink/tezt/lib/evm_node.mli b/etherlink/tezt/lib/evm_node.mli index a6193bb2f4e7..c39cd3c8fb34 100644 --- a/etherlink/tezt/lib/evm_node.mli +++ b/etherlink/tezt/lib/evm_node.mli @@ -62,7 +62,7 @@ type time_between_blocks = (** EVM node mode. *) type mode = | Observer of { - initial_kernel : string; + initial_kernel : string option; preimages_dir : string option; private_rpc_port : int option; (** Port for private RPC server*) rollup_node_endpoint : string option; @@ -99,7 +99,8 @@ type mode = sequencer_sunset_sec : int option; } | Sandbox of { - initial_kernel : string; + initial_kernel : string option; + network : string option; funded_addresses : string list; preimage_dir : string option; private_rpc_port : int option; @@ -185,7 +186,7 @@ val create : (** [initial_kernel node] returns the path to the kernel used to initialize the EVM state. Fails if [node] is a proxy node. *) -val initial_kernel : t -> string +val initial_kernel : t -> string option (** [run ?wait ?extra_arguments evm_node] launches the EVM node server with the arguments given during {!create}, additional arguments can be diff --git a/etherlink/tezt/lib/test_helpers.ml b/etherlink/tezt/lib/test_helpers.ml index fddf4fc1c929..806e9e6d0bba 100644 --- a/etherlink/tezt/lib/test_helpers.ml +++ b/etherlink/tezt/lib/test_helpers.ml @@ -544,7 +544,8 @@ let init_sequencer_sandbox ?maximum_gas_per_transaction ?genesis_timestamp let sequencer_mode = Evm_node.Sandbox { - initial_kernel = output; + initial_kernel = Some output; + network = None; preimage_dir = Some preimages_dir; private_rpc_port = Some (Port.fresh ()); time_between_blocks = Some Nothing; diff --git a/etherlink/tezt/tests/evm_sequencer.ml b/etherlink/tezt/tests/evm_sequencer.ml index 77a6b712207d..c04605bf000d 100644 --- a/etherlink/tezt/tests/evm_sequencer.ml +++ b/etherlink/tezt/tests/evm_sequencer.ml @@ -491,7 +491,7 @@ let test_observer_reset = ~mode: (Evm_node.Observer { - initial_kernel = invalid_kernel; + initial_kernel = Some invalid_kernel; preimages_dir = Some preimages_dir; private_rpc_port = Some (Port.fresh ()); rollup_node_endpoint = @@ -509,7 +509,7 @@ let test_observer_reset = ~mode: (Evm_node.Observer { - initial_kernel = invalid_kernel; + initial_kernel = Some invalid_kernel; preimages_dir = Some preimages_dir; private_rpc_port = Some (Port.fresh ()); rollup_node_endpoint = @@ -2785,7 +2785,7 @@ let test_get_balance_block_param = ~mode: (Observer { - initial_kernel = "evm_kernel.wasm"; + initial_kernel = Some "evm_kernel.wasm"; preimages_dir = Some "/tmp"; private_rpc_port = None; rollup_node_endpoint = @@ -2884,7 +2884,7 @@ let test_get_block_by_number_block_param = ~mode: (Observer { - initial_kernel = "evm_kernel.wasm"; + initial_kernel = Evm_node.initial_kernel observer; preimages_dir = Some "/tmp"; private_rpc_port = None; rollup_node_endpoint = @@ -12664,7 +12664,7 @@ let test_observer_init_from_snapshot = ~mode: (Observer { - initial_kernel = "evm_kernel.wasm"; + initial_kernel = Evm_node.initial_kernel sequencer; preimages_dir = Some "/tmp"; private_rpc_port = None; rollup_node_endpoint = diff --git a/tezt/tests/cloud/etherlink_helpers.ml b/tezt/tests/cloud/etherlink_helpers.ml index dd3efc3e4377..4582e56439c3 100644 --- a/tezt/tests/cloud/etherlink_helpers.ml +++ b/tezt/tests/cloud/etherlink_helpers.ml @@ -505,7 +505,7 @@ let init_etherlink_producer_setup operator name ~node_p2p_endpoint ~rpc_external Evm_node.Observer { private_rpc_port = None; - initial_kernel = output; + initial_kernel = Some output; preimages_dir = Some preimages_dir; rollup_node_endpoint = Some (Sc_rollup_node.endpoint sc_rollup_node); tx_queue_max_lifespan = None; -- GitLab From 31f15a19b70a9570631778a9627c6ae73e0a6399 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 20 Nov 2025 15:28:33 +0100 Subject: [PATCH 3/7] Tezt/Etherlink: extract library for tezt benchmarks --- etherlink/tezt/benchmarks/dune | 9 +- .../tezt/benchmarks/evm_node_capacity.ml | 1 + .../benchmarks/{ => lib}/benchmark_utils.ml | 0 .../tezt/benchmarks/{ => lib}/contracts.ml | 0 .../contracts/UniSwapV2/GLDToken.sol | 0 .../UniSwapV2/compiled/GLDToken.json | 0 .../UniSwapV2/compiled/Multicall.json | 0 .../UniSwapV2/compiled/UniswapV2Factory.json | 0 .../UniSwapV2/compiled/UniswapV2Router02.json | 0 .../compiled/UniswapV2Router02_unopt.json | 0 .../UniSwapV2/core/UniswapV2ERC20.sol | 0 .../UniSwapV2/core/UniswapV2Factory.sol | 0 .../UniSwapV2/core/UniswapV2Pair.sol | 0 .../UniSwapV2/core/interfaces/IERC20.sol | 0 .../core/interfaces/IUniswapV2Callee.sol | 0 .../core/interfaces/IUniswapV2ERC20.sol | 0 .../core/interfaces/IUniswapV2Factory.sol | 0 .../core/interfaces/IUniswapV2Pair.sol | 0 .../UniSwapV2/core/libraries/Math.sol | 0 .../UniSwapV2/core/libraries/SafeMath.sol | 0 .../UniSwapV2/core/libraries/UQ112x112.sol | 0 .../UniSwapV2/periphery/UniswapV2Migrator.sol | 0 .../UniSwapV2/periphery/UniswapV2Router01.sol | 0 .../UniSwapV2/periphery/UniswapV2Router02.sol | 0 .../UniSwapV2/periphery/interfaces/IERC20.sol | 0 .../interfaces/IUniswapV2Migrator.sol | 0 .../interfaces/IUniswapV2Router01.sol | 0 .../interfaces/IUniswapV2Router02.sol | 0 .../UniSwapV2/periphery/interfaces/IWETH.sol | 0 .../interfaces/V1/IUniswapV1Exchange.sol | 0 .../interfaces/V1/IUniswapV1Factory.sol | 0 .../periphery/libraries/SafeMath.sol | 0 .../periphery/libraries/UniswapV2Library.sol | 0 .../UniswapV2LiquidityMathLibrary.sol | 0 .../libraries/UniswapV2OracleLibrary.sol | 0 .../contracts/snailtracer/snailtracer.abi | 0 .../contracts/snailtracer/snailtracer.bin | 0 .../contracts/snailtracer/snailtracer.sol | 0 etherlink/tezt/benchmarks/lib/dune | 27 ++ etherlink/tezt/benchmarks/lib/uniswap.ml | 459 ++++++++++++++++++ etherlink/tezt/benchmarks/snailtracer.ml | 1 + etherlink/tezt/benchmarks/uniswap.ml | 448 +---------------- manifest/product_etherlink.ml | 39 +- opam/etherlink-benchmark.opam | 1 - opam/tezt-etherlink.opam | 4 +- tobi/config | 2 +- 46 files changed, 527 insertions(+), 464 deletions(-) rename etherlink/tezt/benchmarks/{ => lib}/benchmark_utils.ml (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts.ml (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/GLDToken.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/compiled/GLDToken.json (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/compiled/Multicall.json (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/compiled/UniswapV2Factory.json (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/compiled/UniswapV2Router02.json (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/compiled/UniswapV2Router02_unopt.json (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/core/UniswapV2ERC20.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/core/UniswapV2Factory.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/core/UniswapV2Pair.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/core/interfaces/IERC20.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/core/interfaces/IUniswapV2Callee.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/core/interfaces/IUniswapV2ERC20.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/core/interfaces/IUniswapV2Factory.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/core/interfaces/IUniswapV2Pair.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/core/libraries/Math.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/core/libraries/SafeMath.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/core/libraries/UQ112x112.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/periphery/UniswapV2Migrator.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/periphery/UniswapV2Router01.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/periphery/UniswapV2Router02.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/periphery/interfaces/IERC20.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/periphery/interfaces/IUniswapV2Migrator.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/periphery/interfaces/IUniswapV2Router01.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/periphery/interfaces/IUniswapV2Router02.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/periphery/interfaces/IWETH.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/periphery/interfaces/V1/IUniswapV1Exchange.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/periphery/interfaces/V1/IUniswapV1Factory.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/periphery/libraries/SafeMath.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/periphery/libraries/UniswapV2Library.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/periphery/libraries/UniswapV2LiquidityMathLibrary.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/UniSwapV2/periphery/libraries/UniswapV2OracleLibrary.sol (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/snailtracer/snailtracer.abi (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/snailtracer/snailtracer.bin (100%) rename etherlink/tezt/benchmarks/{ => lib}/contracts/snailtracer/snailtracer.sol (100%) create mode 100644 etherlink/tezt/benchmarks/lib/dune create mode 100644 etherlink/tezt/benchmarks/lib/uniswap.ml diff --git a/etherlink/tezt/benchmarks/dune b/etherlink/tezt/benchmarks/dune index f175628e6ba1..648c0b971cdc 100644 --- a/etherlink/tezt/benchmarks/dune +++ b/etherlink/tezt/benchmarks/dune @@ -12,7 +12,8 @@ octez-libs.tezt-wrapper tezt-tezos tezt_etherlink - floodgate_lib) + floodgate_lib + etherlink_benchmark_lib) (link_flags (:standard) (:include %{workspace_root}/macos-link-flags.sexp)) @@ -24,9 +25,3 @@ -open Tezt_tezos -open Tezt_tezos.Runnable.Syntax -open Tezt_etherlink)) - -(rule - (target static_contracts.ml) - (deps (glob_files_rec contracts/**.{abi,bin,json})) - (action - (run ocaml-crunch -e bin -e abi -e json -m plain -o %{target} -s contracts))) diff --git a/etherlink/tezt/benchmarks/evm_node_capacity.ml b/etherlink/tezt/benchmarks/evm_node_capacity.ml index c40fe68f4bd3..23cea9a9c6b1 100644 --- a/etherlink/tezt/benchmarks/evm_node_capacity.ml +++ b/etherlink/tezt/benchmarks/evm_node_capacity.ml @@ -7,6 +7,7 @@ (*****************************************************************************) open Setup +open Etherlink_benchmark_lib open Benchmark_utils open Floodgate_lib open Evm_node_lib_dev_encoding diff --git a/etherlink/tezt/benchmarks/benchmark_utils.ml b/etherlink/tezt/benchmarks/lib/benchmark_utils.ml similarity index 100% rename from etherlink/tezt/benchmarks/benchmark_utils.ml rename to etherlink/tezt/benchmarks/lib/benchmark_utils.ml diff --git a/etherlink/tezt/benchmarks/contracts.ml b/etherlink/tezt/benchmarks/lib/contracts.ml similarity index 100% rename from etherlink/tezt/benchmarks/contracts.ml rename to etherlink/tezt/benchmarks/lib/contracts.ml diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/GLDToken.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/GLDToken.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/GLDToken.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/GLDToken.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/compiled/GLDToken.json b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/compiled/GLDToken.json similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/compiled/GLDToken.json rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/compiled/GLDToken.json diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/compiled/Multicall.json b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/compiled/Multicall.json similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/compiled/Multicall.json rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/compiled/Multicall.json diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/compiled/UniswapV2Factory.json b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/compiled/UniswapV2Factory.json similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/compiled/UniswapV2Factory.json rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/compiled/UniswapV2Factory.json diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/compiled/UniswapV2Router02.json b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/compiled/UniswapV2Router02.json similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/compiled/UniswapV2Router02.json rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/compiled/UniswapV2Router02.json diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/compiled/UniswapV2Router02_unopt.json b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/compiled/UniswapV2Router02_unopt.json similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/compiled/UniswapV2Router02_unopt.json rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/compiled/UniswapV2Router02_unopt.json diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/core/UniswapV2ERC20.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/UniswapV2ERC20.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/core/UniswapV2ERC20.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/UniswapV2ERC20.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/core/UniswapV2Factory.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/UniswapV2Factory.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/core/UniswapV2Factory.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/UniswapV2Factory.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/core/UniswapV2Pair.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/UniswapV2Pair.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/core/UniswapV2Pair.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/UniswapV2Pair.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/core/interfaces/IERC20.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/interfaces/IERC20.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/core/interfaces/IERC20.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/interfaces/IERC20.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/core/interfaces/IUniswapV2Callee.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/interfaces/IUniswapV2Callee.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/core/interfaces/IUniswapV2Callee.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/interfaces/IUniswapV2Callee.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/core/interfaces/IUniswapV2ERC20.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/interfaces/IUniswapV2ERC20.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/core/interfaces/IUniswapV2ERC20.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/interfaces/IUniswapV2ERC20.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/core/interfaces/IUniswapV2Factory.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/interfaces/IUniswapV2Factory.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/core/interfaces/IUniswapV2Factory.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/interfaces/IUniswapV2Factory.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/core/interfaces/IUniswapV2Pair.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/interfaces/IUniswapV2Pair.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/core/interfaces/IUniswapV2Pair.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/interfaces/IUniswapV2Pair.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/core/libraries/Math.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/libraries/Math.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/core/libraries/Math.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/libraries/Math.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/core/libraries/SafeMath.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/libraries/SafeMath.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/core/libraries/SafeMath.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/libraries/SafeMath.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/core/libraries/UQ112x112.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/libraries/UQ112x112.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/core/libraries/UQ112x112.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/core/libraries/UQ112x112.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/UniswapV2Migrator.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/UniswapV2Migrator.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/UniswapV2Migrator.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/UniswapV2Migrator.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/UniswapV2Router01.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/UniswapV2Router01.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/UniswapV2Router01.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/UniswapV2Router01.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/UniswapV2Router02.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/UniswapV2Router02.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/UniswapV2Router02.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/UniswapV2Router02.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/interfaces/IERC20.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/interfaces/IERC20.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/interfaces/IERC20.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/interfaces/IERC20.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/interfaces/IUniswapV2Migrator.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/interfaces/IUniswapV2Migrator.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/interfaces/IUniswapV2Migrator.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/interfaces/IUniswapV2Migrator.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/interfaces/IUniswapV2Router01.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/interfaces/IUniswapV2Router01.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/interfaces/IUniswapV2Router01.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/interfaces/IUniswapV2Router01.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/interfaces/IUniswapV2Router02.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/interfaces/IUniswapV2Router02.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/interfaces/IUniswapV2Router02.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/interfaces/IUniswapV2Router02.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/interfaces/IWETH.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/interfaces/IWETH.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/interfaces/IWETH.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/interfaces/IWETH.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/interfaces/V1/IUniswapV1Exchange.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/interfaces/V1/IUniswapV1Exchange.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/interfaces/V1/IUniswapV1Exchange.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/interfaces/V1/IUniswapV1Exchange.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/interfaces/V1/IUniswapV1Factory.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/interfaces/V1/IUniswapV1Factory.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/interfaces/V1/IUniswapV1Factory.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/interfaces/V1/IUniswapV1Factory.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/libraries/SafeMath.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/libraries/SafeMath.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/libraries/SafeMath.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/libraries/SafeMath.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/libraries/UniswapV2Library.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/libraries/UniswapV2Library.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/libraries/UniswapV2Library.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/libraries/UniswapV2Library.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/libraries/UniswapV2LiquidityMathLibrary.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/libraries/UniswapV2LiquidityMathLibrary.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/libraries/UniswapV2LiquidityMathLibrary.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/libraries/UniswapV2LiquidityMathLibrary.sol diff --git a/etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/libraries/UniswapV2OracleLibrary.sol b/etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/libraries/UniswapV2OracleLibrary.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/UniSwapV2/periphery/libraries/UniswapV2OracleLibrary.sol rename to etherlink/tezt/benchmarks/lib/contracts/UniSwapV2/periphery/libraries/UniswapV2OracleLibrary.sol diff --git a/etherlink/tezt/benchmarks/contracts/snailtracer/snailtracer.abi b/etherlink/tezt/benchmarks/lib/contracts/snailtracer/snailtracer.abi similarity index 100% rename from etherlink/tezt/benchmarks/contracts/snailtracer/snailtracer.abi rename to etherlink/tezt/benchmarks/lib/contracts/snailtracer/snailtracer.abi diff --git a/etherlink/tezt/benchmarks/contracts/snailtracer/snailtracer.bin b/etherlink/tezt/benchmarks/lib/contracts/snailtracer/snailtracer.bin similarity index 100% rename from etherlink/tezt/benchmarks/contracts/snailtracer/snailtracer.bin rename to etherlink/tezt/benchmarks/lib/contracts/snailtracer/snailtracer.bin diff --git a/etherlink/tezt/benchmarks/contracts/snailtracer/snailtracer.sol b/etherlink/tezt/benchmarks/lib/contracts/snailtracer/snailtracer.sol similarity index 100% rename from etherlink/tezt/benchmarks/contracts/snailtracer/snailtracer.sol rename to etherlink/tezt/benchmarks/lib/contracts/snailtracer/snailtracer.sol diff --git a/etherlink/tezt/benchmarks/lib/dune b/etherlink/tezt/benchmarks/lib/dune new file mode 100644 index 000000000000..99c5a1847062 --- /dev/null +++ b/etherlink/tezt/benchmarks/lib/dune @@ -0,0 +1,27 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name etherlink_benchmark_lib) + (package tezt-etherlink) + (libraries + bls12-381.archive + octez-libs.test-helpers + octez-libs.tezt-wrapper + tezt-tezos + tezt_etherlink + floodgate_lib) + (flags + (:standard) + -open Tezos_test_helpers + -open Tezt_wrapper + -open Tezt_wrapper.Base + -open Tezt_tezos + -open Tezt_tezos.Runnable.Syntax + -open Tezt_etherlink)) + +(rule + (target static_contracts.ml) + (deps (glob_files_rec contracts/**.{abi,bin,json})) + (action + (run ocaml-crunch -e bin -e abi -e json -m plain -o %{target} -s contracts))) diff --git a/etherlink/tezt/benchmarks/lib/uniswap.ml b/etherlink/tezt/benchmarks/lib/uniswap.ml new file mode 100644 index 000000000000..e78345276b51 --- /dev/null +++ b/etherlink/tezt/benchmarks/lib/uniswap.ml @@ -0,0 +1,459 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2025 Nomadic Labs *) +(* Copyright (c) 2025 Functori *) +(* *) +(*****************************************************************************) + +open Evm_node_lib_dev_encoding +open Benchmark_utils +open Floodgate_lib + +type env = { + sequencer : Evm_node.t; + rpc_node : Evm_node.t; + infos : Network_info.t; + gas_limit : Z.t; + accounts : Floodgate_lib.Account.t Array.t; + wxtz_addr : string; + gld_tokens : string list; + factory_addr : string; + router_addr : string; + nb_hops : int; +} + +let max_uint256 = + let open Z in + (one lsl 256) - one + +let z1e18 = Z.of_float 1e18 + +let to_wei x = Z.(of_int x * z1e18) + +let of_wei z = Z.to_float z /. 1e18 + +let encode_value v t = + Efunc_core.Evm.encode_value v t |> Rope.to_string |> Hex.of_string |> Hex.show + +let address a = + Tezos_stdlib.TzString.remove_prefix ~prefix:"0x" a + |> Option.value ~default:a |> Efunc_core.Private.a + +let encode_address a = encode_value `address (`address (address a)) + +let bin_of_json_contract json = + JSON.(json |-> "data" |-> "bytecode" |-> "object" |> as_string) + +let deposit_wxtz_gas_limit {accounts; infos; rpc_node; wxtz_addr; _} = + let sender = accounts.(0) in + let rpc_endpoint = Evm_node.endpoint rpc_node |> Uri.of_string in + let*? gas_limit = + Network_info.get_gas_limit + ~rpc_endpoint + ~base_fee_per_gas:infos.base_fee_per_gas + ~from:(Account.address_et sender) + ~to_:(Address (Hex wxtz_addr)) + ~value:(to_wei 1000) + () + in + Log.debug "Deposit gas limit: %a@." Z.pp_print gas_limit ; + return gas_limit + +let deposit_wxtz ~gas_limit {infos; rpc_node; wxtz_addr; _} ?nonce value account + = + let* _ = + call + infos + rpc_node + wxtz_addr + ~gas_limit + account + ?nonce + ~value:(to_wei value) + [] + [] + in + unit + +let deposits_wxtz env = + Log.info "Depositing tokens to WXTZ contract" ; + let* gas_limit = deposit_wxtz_gas_limit env in + let f () = + Lwt_list.iter_p + (deposit_wxtz env ~gas_limit 1000) + (Array.to_list env.accounts) + in + wait_for_application env.sequencer f + +let get_total_supply {infos; rpc_node; accounts; _} contract = + let* res = + let open Evm_node_lib_dev in + Batch.call + (module Rpc_encodings.Eth_call) + ~evm_node_endpoint:(Evm_node.endpoint rpc_node |> Uri.of_string) + ~keep_alive:true + ~timeout:10. + ( { + from = Some (Account.address_et accounts.(0)); + to_ = Some (Ethereum_types.Address.of_string contract); + gas = None; + gasPrice = Some (Qty infos.base_fee_per_gas); + value = Some (Qty Z.zero); + data = + Some + ((Efunc_core.Evm.encode ~name:"totalSupply" [] [] :> string) + |> Ethereum_types.hash_of_string); + }, + Block_parameter Latest, + Ethereum_types.AddressMap.empty ) + in + match res with + | Error e -> + Test.fail "supply error: %a" Tezos_base.TzPervasives.pp_print_trace e + | Ok (Ethereum_types.Hash (Ethereum_types.Hex s)) -> + Helpers.decode_z_be (`Hex s |> Hex.to_bytes) |> return + +let get_balance {infos; rpc_node; _} contract sender = + let* res = + let open Evm_node_lib_dev in + Batch.call + (module Rpc_encodings.Eth_call) + ~evm_node_endpoint:(Evm_node.endpoint rpc_node |> Uri.of_string) + ~keep_alive:true + ~timeout:10. + ( { + from = Some (Account.address_et sender); + to_ = Some (Ethereum_types.Address.of_string contract); + gas = None; + gasPrice = Some (Qty infos.base_fee_per_gas); + value = Some (Qty Z.zero); + data = + Some + ((Efunc_core.Evm.encode + ~name:"balanceOf" + [`address] + [`address (Account.address sender)] + :> string) + |> Ethereum_types.hash_of_string); + }, + Block_parameter Latest, + Ethereum_types.AddressMap.empty ) + in + match res with + | Error e -> + Test.fail "supply error: %a" Tezos_base.TzPervasives.pp_print_trace e + | Ok (Ethereum_types.Hash (Ethereum_types.Hex s)) -> + Helpers.decode_z_be (`Hex s |> Hex.to_bytes) |> return + +let z = Check.comparable Z.pp_print Z.compare + +let check_wxtz_deposits env = + let* supply = get_total_supply env env.wxtz_addr in + Check.((supply = Z.(of_int (Array.length env.accounts) * to_wei 1000)) z) + ~error_msg:(sf "Total supply for %s is %%L instead of %%R" env.wxtz_addr) ; + Log.report "Deposited tokens to WXTZ contract" ; + unit + +let add_xtz_liquidity {sequencer; rpc_node; infos; router_addr; _} ~sender + ~token_addr ~xtz ~token = + let name = "addLiquidityETH" in + let params_ty = + [`address; `uint 256; `uint 256; `uint 256; `address; `uint 256] + in + let deadline = int_of_float (Unix.time ()) + 1000 in + let to_ = Account.address sender in + let params = + [ + `address (address token_addr); + `int (to_wei token); + `int Z.one; + `int Z.one; + `address to_; + `int (Z.of_int deadline); + ] + in + wait_for_application sequencer @@ fun () -> + let* _ = + call + infos + rpc_node + router_addr + sender + ~name + params_ty + params + ~value:(to_wei xtz) + ~check_success:true + in + unit + +let add_xtz_liquidities env ~sender = + Lwt_list.iteri_s + (fun i token_addr -> + Log.info "Adding XTZ/GLD%i Liquidity" (i + 1) ; + let token = 1000 * 10 * (i + 1) in + add_xtz_liquidity env ~sender ~token_addr ~xtz:1000 ~token) + env.gld_tokens + +let add_liquidity {sequencer; rpc_node; infos; router_addr; _} ~sender ~gld + ~gld2 = + let name = "addLiquidity" in + let params_ty = + [ + `address; + `address; + `uint 256; + `uint 256; + `uint 256; + `uint 256; + `address; + `uint 256; + ] + in + let deadline = int_of_float (Unix.time ()) + 1000 in + let to_ = Account.address sender in + let params = + [ + `address (address (fst gld)); + `address (address (fst gld2)); + `int (to_wei (snd gld)); + `int (to_wei (snd gld2)); + `int Z.one; + `int Z.one; + `address to_; + `int (Z.of_int deadline); + ] + in + wait_for_application sequencer @@ fun () -> + let* _ = + call + infos + rpc_node + router_addr + sender + ~name + params_ty + params + ~check_success:true + in + unit + +let pairs {gld_tokens; _} = + let tokens = List.mapi (fun i t -> (sf "GLD%d" (i + 1), t)) gld_tokens in + match tokens with + | [] -> assert false + | [_] -> [] + | [gld1; gld2] -> [(gld1, gld2)] + | t :: rest -> List.combine tokens (rest @ [t]) + +let add_token_liquidities env ~sender = + match env.gld_tokens with + | [] | [_] -> unit + | _ -> + Log.info "Adding token liquidities" ; + Lwt_list.iter_s + (fun ((n1, p1), (n2, p2)) -> + Log.info " - Adding liquidity in %s/%s" n1 n2 ; + add_liquidity env ~sender ~gld:(p1, 100_000) ~gld2:(p2, 200_000)) + (pairs env) + +let approve_router {sequencer; rpc_node; infos; router_addr; _} ~sender + ~token_addr = + let name = "approve" in + let params_ty = [`address; `uint 256] in + let params = [`address (address router_addr); `int max_uint256] in + wait_for_application sequencer @@ fun () -> + let* _ = + call + infos + rpc_node + token_addr + sender + ~name + params_ty + params + ~check_success:true + in + unit + +let approve_router_to_tokens env ~sender = + Lwt_list.iteri_s + (fun i token_addr -> + Log.info "Approving router to GLD%d" (i + 1) ; + approve_router env ~sender ~token_addr) + env.gld_tokens + +let mk_path env ~nb_hops = + let tokens = Seq.cycle (List.to_seq env.gld_tokens) in + let hops = Seq.take nb_hops tokens in + let rpath = Seq.map (fun a -> `address (address a)) hops in + `address (address env.wxtz_addr) :: List.of_seq rpath + +let swap_xtz ~nb_hops env iteration sender_index = + let sender = env.accounts.(sender_index) in + let dest = + env.accounts.((sender_index + iteration) mod Array.length env.accounts) + in + let amount_out_min = Z.one in + let deadline = int_of_float (Unix.time ()) + 600 in + let params_ty = [`uint 256; `array `address; `address; `uint 256] in + let params = + [ + `int amount_out_min; + `array (mk_path env ~nb_hops); + `address (Account.address dest); + `int (Z.of_int deadline); + ] + in + let* _ = + call + env.infos + env.rpc_node + env.router_addr + sender + ~gas_limit:(Z.of_int (260_000 * nb_hops)) (* Rough approximation *) + ~value:(Z.of_int (10000 + (iteration * 100))) + ~name:"swapExactETHForTokens" (* "swapETHForExactTokens" *) + params_ty + params + ~check_success:true + in + unit + +let step ({sequencer; accounts; nb_hops; _} as env) iteration = + Log.report "Iteration %d" iteration ; + let sender_indexes = List.init (Array.length accounts) Fun.id in + let step_f () = + Lwt_list.iter_p (swap_xtz ~nb_hops env iteration) sender_indexes + in + wait_for_application sequencer step_f + +let create_pair ?nonce {sequencer; rpc_node; infos; factory_addr; _} ~sender + ((n, gld_addr), (n2, gld2_addr)) = + Log.info " - Create pair %s/%s" n n2 ; + let name = "createPair" in + let params_ty = [`address; `address] in + let params = [`address (address gld_addr); `address (address gld2_addr)] in + wait_for_application sequencer @@ fun () -> + let* _ = + call infos rpc_node factory_addr sender ?nonce ~name params_ty params + in + unit + +let create_pairs env ~sender = + match env.gld_tokens with + | [] | [_] -> unit + | _ -> + Log.info "Creating pairs" ; + Lwt_list.iter_s (create_pair env ~sender) (pairs env) + +let deploy_gld_token infos ~sequencer ~rpc_node ~sender i = + Log.report "Deploying GLD%d" i ; + let gldbin = Contracts.UniswapV2.GLDToken.json () |> bin_of_json_contract in + let bin = + gldbin + ^ encode_value + (`tuple [`string; `string]) + (`array [`string (sf "Gold%d" i); `string (sf "GLD%d" i)]) + in + wait_for_application sequencer @@ fun () -> + deploy_contract ~rpc_node infos ~sequencer sender (`Custom bin) + +let deploy_gld_tokens infos ~sequencer ~rpc_node ~sender nb = + Lwt_list.map_s + (fun i -> deploy_gld_token infos ~sequencer ~rpc_node ~sender (i + 1)) + (List.init nb Fun.id) + +let setup ~accounts ~nb_tokens ~nb_hops ~sequencer ~rpc_node = + let* accounts = floodgate_accounts sequencer accounts in + let sender = accounts.(0) in + (* Compile contracts *) + Log.info "Deploying UniswapV2 contracts" ; + let endpoint = Evm_node.endpoint rpc_node |> Uri.of_string in + let*? infos = + Network_info.fetch ~rpc_endpoint:endpoint ~base_fee_factor:1000. + in + let*? () = + Tx_queue.start + ~relay_endpoint:endpoint + ~max_transaction_batch_length:(Some 300) + ~inclusion_timeout:parameters.timeout + () + in + let follower = + Floodgate.start_blueprint_follower + ~relay_endpoint:endpoint + ~rpc_endpoint:endpoint + in + let tx_queue = Tx_queue.beacon ~tick_interval:0.5 in + Log.report "Deploying WXTZ" ; + let* wxtz_addr = deploy_contract ~rpc_node infos ~sequencer sender `ERC20 in + Log.info " WXTZ: %s" wxtz_addr ; + + let* gld_tokens = + deploy_gld_tokens infos ~sequencer ~rpc_node ~sender nb_tokens + in + + Log.report "Deploying UniswapV2 contracts" ; + let fee_recv = sender in + Log.report + "- Deploying UniswapV2Factory (feeToSetter %s)" + (Account.address fee_recv :> string) ; + let bin = Contracts.UniswapV2.Factory.json () |> bin_of_json_contract in + let bin = bin ^ encode_address (Account.address fee_recv :> string) in + let* factory_addr = + deploy_contract ~rpc_node infos ~sequencer sender (`Custom bin) + in + Log.info " UniswapV2Factory address: %s" factory_addr ; + Log.report "- Deploying UniswapV2Router02" ; + let bin = Contracts.UniswapV2.Router02.json () |> bin_of_json_contract in + let bin = + String.concat + "" + [bin; encode_address factory_addr; encode_address wxtz_addr] + in + let* router_addr = + deploy_contract ~rpc_node infos ~sequencer sender (`Custom bin) + in + Log.info " UniswapV2Router02 address: %s" router_addr ; + + let env = + { + sequencer; + rpc_node; + infos; + gas_limit = Z.zero; + accounts; + factory_addr; + router_addr; + wxtz_addr; + gld_tokens; + nb_hops; + } + in + + let* () = create_pairs env ~sender in + + let* () = approve_router_to_tokens env ~sender in + + Log.info "Adding XTZ/GLD1 Liquidity" ; + let* () = + add_xtz_liquidity + env + ~sender + ~token_addr:(List.hd env.gld_tokens) + ~xtz:1000 + ~token:10_000 + in + let* () = add_token_liquidities env ~sender in + + let shutdown () = + Lwt.cancel follower ; + Lwt.cancel tx_queue ; + let* () = Tx_queue.shutdown () in + let* () = Evm_node.terminate sequencer in + unit + in + + return (env, shutdown) diff --git a/etherlink/tezt/benchmarks/snailtracer.ml b/etherlink/tezt/benchmarks/snailtracer.ml index 3f3fcd3d7765..89f06453f421 100644 --- a/etherlink/tezt/benchmarks/snailtracer.ml +++ b/etherlink/tezt/benchmarks/snailtracer.ml @@ -9,6 +9,7 @@ open Evm_node_lib_dev_encoding open Evm_node_lib_dev open Setup +open Etherlink_benchmark_lib open Benchmark_utils open Floodgate_lib diff --git a/etherlink/tezt/benchmarks/uniswap.ml b/etherlink/tezt/benchmarks/uniswap.ml index 0c8b10fd2adc..75ca5fbf0da2 100644 --- a/etherlink/tezt/benchmarks/uniswap.ml +++ b/etherlink/tezt/benchmarks/uniswap.ml @@ -6,365 +6,10 @@ (* *) (*****************************************************************************) -open Evm_node_lib_dev_encoding open Setup +open Etherlink_benchmark_lib open Benchmark_utils -open Floodgate_lib - -type env = { - sequencer : Evm_node.t; - rpc_node : Evm_node.t; - infos : Network_info.t; - gas_limit : Z.t; - accounts : Floodgate_lib.Account.t Array.t; - wxtz_addr : string; - gld_tokens : string list; - factory_addr : string; - router_addr : string; - nb_hops : int; -} - -let max_uint256 = - let open Z in - (one lsl 256) - one - -let z1e18 = Z.of_float 1e18 - -let to_wei x = Z.(of_int x * z1e18) - -let of_wei z = Z.to_float z /. 1e18 - -let encode_value v t = - Efunc_core.Evm.encode_value v t |> Rope.to_string |> Hex.of_string |> Hex.show - -let address a = - Tezos_stdlib.TzString.remove_prefix ~prefix:"0x" a - |> Option.value ~default:a |> Efunc_core.Private.a - -let encode_address a = encode_value `address (`address (address a)) - -let bin_of_json_contract json = - JSON.(json |-> "data" |-> "bytecode" |-> "object" |> as_string) - -let deposit_wxtz_gas_limit {accounts; infos; rpc_node; wxtz_addr; _} = - let sender = accounts.(0) in - let rpc_endpoint = Evm_node.endpoint rpc_node |> Uri.of_string in - let*? gas_limit = - Network_info.get_gas_limit - ~rpc_endpoint - ~base_fee_per_gas:infos.base_fee_per_gas - ~from:(Account.address_et sender) - ~to_:(Address (Hex wxtz_addr)) - ~value:(to_wei 1000) - () - in - Log.debug "Deposit gas limit: %a@." Z.pp_print gas_limit ; - return gas_limit - -let deposit_wxtz ~gas_limit {infos; rpc_node; wxtz_addr; _} ?nonce value account - = - let* _ = - call - infos - rpc_node - wxtz_addr - ~gas_limit - account - ?nonce - ~value:(to_wei value) - [] - [] - in - unit - -let deposits_wxtz env = - Log.info "Depositing tokens to WXTZ contract" ; - let* gas_limit = deposit_wxtz_gas_limit env in - let f () = - Lwt_list.iter_p - (deposit_wxtz env ~gas_limit 1000) - (Array.to_list env.accounts) - in - wait_for_application env.sequencer f - -let get_total_supply {infos; rpc_node; accounts; _} contract = - let* res = - let open Evm_node_lib_dev in - Batch.call - (module Rpc_encodings.Eth_call) - ~evm_node_endpoint:(Evm_node.endpoint rpc_node |> Uri.of_string) - ~keep_alive:true - ~timeout:10. - ( { - from = Some (Account.address_et accounts.(0)); - to_ = Some (Ethereum_types.Address.of_string contract); - gas = None; - gasPrice = Some (Qty infos.base_fee_per_gas); - value = Some (Qty Z.zero); - data = - Some - ((Efunc_core.Evm.encode ~name:"totalSupply" [] [] :> string) - |> Ethereum_types.hash_of_string); - }, - Block_parameter Latest, - Ethereum_types.AddressMap.empty ) - in - match res with - | Error e -> - Test.fail "supply error: %a" Tezos_base.TzPervasives.pp_print_trace e - | Ok (Ethereum_types.Hash (Ethereum_types.Hex s)) -> - Helpers.decode_z_be (`Hex s |> Hex.to_bytes) |> return - -let get_balance {infos; rpc_node; _} contract sender = - let* res = - let open Evm_node_lib_dev in - Batch.call - (module Rpc_encodings.Eth_call) - ~evm_node_endpoint:(Evm_node.endpoint rpc_node |> Uri.of_string) - ~keep_alive:true - ~timeout:10. - ( { - from = Some (Account.address_et sender); - to_ = Some (Ethereum_types.Address.of_string contract); - gas = None; - gasPrice = Some (Qty infos.base_fee_per_gas); - value = Some (Qty Z.zero); - data = - Some - ((Efunc_core.Evm.encode - ~name:"balanceOf" - [`address] - [`address (Account.address sender)] - :> string) - |> Ethereum_types.hash_of_string); - }, - Block_parameter Latest, - Ethereum_types.AddressMap.empty ) - in - match res with - | Error e -> - Test.fail "supply error: %a" Tezos_base.TzPervasives.pp_print_trace e - | Ok (Ethereum_types.Hash (Ethereum_types.Hex s)) -> - Helpers.decode_z_be (`Hex s |> Hex.to_bytes) |> return - -let z = Check.comparable Z.pp_print Z.compare - -let check_wxtz_deposits env = - let* supply = get_total_supply env env.wxtz_addr in - Check.((supply = Z.(of_int (Array.length env.accounts) * to_wei 1000)) z) - ~error_msg:(sf "Total supply for %s is %%L instead of %%R" env.wxtz_addr) ; - Log.report "Deposited tokens to WXTZ contract" ; - unit - -let add_xtz_liquidity {sequencer; rpc_node; infos; router_addr; _} ~sender - ~token_addr ~xtz ~token = - let name = "addLiquidityETH" in - let params_ty = - [`address; `uint 256; `uint 256; `uint 256; `address; `uint 256] - in - let deadline = int_of_float (Unix.time ()) + 1000 in - let to_ = Account.address sender in - let params = - [ - `address (address token_addr); - `int (to_wei token); - `int Z.one; - `int Z.one; - `address to_; - `int (Z.of_int deadline); - ] - in - wait_for_application sequencer @@ fun () -> - let* _ = - call - infos - rpc_node - router_addr - sender - ~name - params_ty - params - ~value:(to_wei xtz) - ~check_success:true - in - unit - -let add_xtz_liquidities env ~sender = - Lwt_list.iteri_s - (fun i token_addr -> - Log.info "Adding XTZ/GLD%i Liquidity" (i + 1) ; - let token = 1000 * 10 * (i + 1) in - add_xtz_liquidity env ~sender ~token_addr ~xtz:1000 ~token) - env.gld_tokens - -let add_liquidity {sequencer; rpc_node; infos; router_addr; _} ~sender ~gld - ~gld2 = - let name = "addLiquidity" in - let params_ty = - [ - `address; - `address; - `uint 256; - `uint 256; - `uint 256; - `uint 256; - `address; - `uint 256; - ] - in - let deadline = int_of_float (Unix.time ()) + 1000 in - let to_ = Account.address sender in - let params = - [ - `address (address (fst gld)); - `address (address (fst gld2)); - `int (to_wei (snd gld)); - `int (to_wei (snd gld2)); - `int Z.one; - `int Z.one; - `address to_; - `int (Z.of_int deadline); - ] - in - wait_for_application sequencer @@ fun () -> - let* _ = - call - infos - rpc_node - router_addr - sender - ~name - params_ty - params - ~check_success:true - in - unit - -let pairs {gld_tokens; _} = - let tokens = List.mapi (fun i t -> (sf "GLD%d" (i + 1), t)) gld_tokens in - match tokens with - | [] -> assert false - | [_] -> [] - | [gld1; gld2] -> [(gld1, gld2)] - | t :: rest -> List.combine tokens (rest @ [t]) - -let add_token_liquidities env ~sender = - match env.gld_tokens with - | [] | [_] -> unit - | _ -> - Log.info "Adding token liquidities" ; - Lwt_list.iter_s - (fun ((n1, p1), (n2, p2)) -> - Log.info " - Adding liquidity in %s/%s" n1 n2 ; - add_liquidity env ~sender ~gld:(p1, 100_000) ~gld2:(p2, 200_000)) - (pairs env) - -let approve_router {sequencer; rpc_node; infos; router_addr; _} ~sender - ~token_addr = - let name = "approve" in - let params_ty = [`address; `uint 256] in - let params = [`address (address router_addr); `int max_uint256] in - wait_for_application sequencer @@ fun () -> - let* _ = - call - infos - rpc_node - token_addr - sender - ~name - params_ty - params - ~check_success:true - in - unit - -let approve_router_to_tokens env ~sender = - Lwt_list.iteri_s - (fun i token_addr -> - Log.info "Approving router to GLD%d" (i + 1) ; - approve_router env ~sender ~token_addr) - env.gld_tokens - -let mk_path env ~nb_hops = - let tokens = Seq.cycle (List.to_seq env.gld_tokens) in - let hops = Seq.take nb_hops tokens in - let rpath = Seq.map (fun a -> `address (address a)) hops in - `address (address env.wxtz_addr) :: List.of_seq rpath - -let swap_xtz ~nb_hops env iteration sender_index = - let sender = env.accounts.(sender_index) in - let dest = - env.accounts.((sender_index + iteration) mod Array.length env.accounts) - in - let amount_out_min = Z.one in - let deadline = int_of_float (Unix.time ()) + 600 in - let params_ty = [`uint 256; `array `address; `address; `uint 256] in - let params = - [ - `int amount_out_min; - `array (mk_path env ~nb_hops); - `address (Account.address dest); - `int (Z.of_int deadline); - ] - in - let* _ = - call - env.infos - env.rpc_node - env.router_addr - sender - ~gas_limit:(Z.of_int (260_000 * nb_hops)) (* Rough approximation *) - ~value:(Z.of_int (10000 + (iteration * 100))) - ~name:"swapExactETHForTokens" (* "swapETHForExactTokens" *) - params_ty - params - ~check_success:true - in - unit - -let step ({sequencer; accounts; nb_hops; _} as env) iteration = - Log.report "Iteration %d" iteration ; - let sender_indexes = List.init (Array.length accounts) Fun.id in - let step_f () = - Lwt_list.iter_p (swap_xtz ~nb_hops env iteration) sender_indexes - in - wait_for_application sequencer step_f - -let create_pair ?nonce {sequencer; rpc_node; infos; factory_addr; _} ~sender - ((n, gld_addr), (n2, gld2_addr)) = - Log.info " - Create pair %s/%s" n n2 ; - let name = "createPair" in - let params_ty = [`address; `address] in - let params = [`address (address gld_addr); `address (address gld2_addr)] in - wait_for_application sequencer @@ fun () -> - let* _ = - call infos rpc_node factory_addr sender ?nonce ~name params_ty params - in - unit - -let create_pairs env ~sender = - match env.gld_tokens with - | [] | [_] -> unit - | _ -> - Log.info "Creating pairs" ; - Lwt_list.iter_s (create_pair env ~sender) (pairs env) - -let deploy_gld_token infos ~sequencer ~rpc_node ~sender i = - Log.report "Deploying GLD%d" i ; - let gldbin = Contracts.UniswapV2.GLDToken.json () |> bin_of_json_contract in - let bin = - gldbin - ^ encode_value - (`tuple [`string; `string]) - (`array [`string (sf "Gold%d" i); `string (sf "GLD%d" i)]) - in - wait_for_application sequencer @@ fun () -> - deploy_contract ~rpc_node infos ~sequencer sender (`Custom bin) - -let deploy_gld_tokens infos ~sequencer ~rpc_node ~sender nb = - Lwt_list.map_s - (fun i -> deploy_gld_token infos ~sequencer ~rpc_node ~sender (i + 1)) - (List.init nb Fun.id) +open Uniswap let test_swaps = let nb_accounts = Option.value parameters.accounts ~default:100 in @@ -388,98 +33,15 @@ let test_swaps = ~maximum_gas_per_transaction:(1 lsl 50 |> Int64.of_int) ~tx_queue:{max_lifespan = 4; max_size = 4_000; tx_per_addr_limit = 1024} @@ fun {sequencer; _} _protocol -> - let* accounts = floodgate_accounts sequencer accounts in - let sender = accounts.(0) in - (* Compile contracts *) - Log.info "Deploying UniswapV2 contracts" ; - let rpc_node = sequencer in - let endpoint = Evm_node.endpoint rpc_node |> Uri.of_string in - let*? infos = - Network_info.fetch ~rpc_endpoint:endpoint ~base_fee_factor:1000. + let* env, shutdown = + setup ~accounts ~nb_tokens ~nb_hops ~sequencer ~rpc_node:sequencer in - let*? () = - Tx_queue.start - ~relay_endpoint:endpoint - ~max_transaction_batch_length:(Some 300) - ~inclusion_timeout:parameters.timeout - () - in - let follower = - Floodgate.start_blueprint_follower - ~relay_endpoint:endpoint - ~rpc_endpoint:endpoint - in - let tx_queue = Tx_queue.beacon ~tick_interval:0.5 in - Log.report "Deploying WXTZ" ; - let* wxtz_addr = deploy_contract ~rpc_node infos ~sequencer sender `ERC20 in - Log.info " WXTZ: %s" wxtz_addr ; - - let* gld_tokens = - deploy_gld_tokens infos ~sequencer ~rpc_node ~sender nb_tokens - in - - Log.report "Deploying UniswapV2 contracts" ; - let fee_recv = sender in - Log.report - "- Deploying UniswapV2Factory (feeToSetter %s)" - (Account.address fee_recv :> string) ; - let bin = Contracts.UniswapV2.Factory.json () |> bin_of_json_contract in - let bin = bin ^ encode_address (Account.address fee_recv :> string) in - let* factory_addr = - deploy_contract ~rpc_node infos ~sequencer sender (`Custom bin) - in - Log.info " UniswapV2Factory address: %s" factory_addr ; - Log.report "- Deploying UniswapV2Router02" ; - let bin = Contracts.UniswapV2.Router02.json () |> bin_of_json_contract in - let bin = - String.concat - "" - [bin; encode_address factory_addr; encode_address wxtz_addr] - in - let* router_addr = - deploy_contract ~rpc_node infos ~sequencer sender (`Custom bin) - in - Log.info " UniswapV2Router02 address: %s" router_addr ; - - let env = - { - sequencer; - rpc_node; - infos; - gas_limit = Z.zero; - accounts; - factory_addr; - router_addr; - wxtz_addr; - gld_tokens; - nb_hops; - } - in - - let* () = create_pairs env ~sender in - - let* () = approve_router_to_tokens env ~sender in - - Log.info "Adding XTZ/GLD1 Liquidity" ; - let* () = - add_xtz_liquidity - env - ~sender - ~token_addr:(List.hd env.gld_tokens) - ~xtz:1000 - ~token:10_000 - in - let* () = add_token_liquidities env ~sender in - monitor_gasometer sequencer @@ fun () -> let* stop_profile = if parameters.profiling then profile sequencer else return (fun () -> unit) in let* () = Lwt_list.iter_s (step env) (List.init parameters.iterations succ) in - Lwt.cancel follower ; - Lwt.cancel tx_queue ; - let* () = Tx_queue.shutdown () in - let* () = Evm_node.terminate sequencer in + let* () = shutdown () in stop_profile () let register () = test_swaps [Protocol.Alpha] diff --git a/manifest/product_etherlink.ml b/manifest/product_etherlink.ml index 65dd1905c4fb..f49f0faa25bf 100644 --- a/manifest/product_etherlink.ml +++ b/manifest/product_etherlink.ml @@ -524,14 +524,12 @@ let _tezt_testnet_scenarios = tezt_etherlink |> open_; ] -let _tezt_node_benchmark = - public_exe - "etherlink-benchmark" - ~internal_name:"main" - ~path:"etherlink/tezt/benchmarks" - ~synopsis:"Run EVM node benchmark" +let tezt_benchmark_lib = + private_lib + "etherlink_benchmark_lib" + ~path:"etherlink/tezt/benchmarks/lib" + ~opam:"tezt-etherlink" ~bisect_ppx:No - ~static:false ~deps: [ bls12_381_archive; @@ -542,10 +540,6 @@ let _tezt_node_benchmark = tezt_etherlink |> open_; floodgate_lib; ] - ~with_macos_security_framework:true - ~dep_globs: - ["evm_kernel_inputs/*"; "../../tezos_contracts/*"; "../../config/*"] - ~dep_globs_rec:["../../kernel_latest/*"] ~dune: Dune. [ @@ -575,6 +569,29 @@ let _tezt_node_benchmark = ]; ] +let _tezt_node_benchmark = + public_exe + "etherlink-benchmark" + ~internal_name:"main" + ~path:"etherlink/tezt/benchmarks" + ~synopsis:"Run EVM node benchmark" + ~bisect_ppx:No + ~static:false + ~deps: + [ + bls12_381_archive; + octez_test_helpers |> open_; + tezt_wrapper |> open_ |> open_ ~m:"Base"; + tezt_tezos |> open_ |> open_ ~m:"Runnable.Syntax"; + tezt_etherlink |> open_; + floodgate_lib; + tezt_benchmark_lib; + ] + ~with_macos_security_framework:true + ~dep_globs: + ["evm_kernel_inputs/*"; "../../tezos_contracts/*"; "../../config/*"] + ~dep_globs_rec:["../../kernel_latest/*"] + let _tezt_etherlink_benchmark_producer = public_exe "etherlink-benchmark-producer" diff --git a/opam/etherlink-benchmark.opam b/opam/etherlink-benchmark.opam index c6c6acf2f07a..ced454a0f1c7 100644 --- a/opam/etherlink-benchmark.opam +++ b/opam/etherlink-benchmark.opam @@ -12,7 +12,6 @@ depends: [ "ocaml" { >= "4.14" } "octez-evm-node-libs" { = version } "bls12-381" - "crunch" { >= "3.3.0" } "octez-libs" "tezt-tezos" "tezt-etherlink" { = version } diff --git a/opam/tezt-etherlink.opam b/opam/tezt-etherlink.opam index c3b7e00cf817..f8c78cad82ec 100644 --- a/opam/tezt-etherlink.opam +++ b/opam/tezt-etherlink.opam @@ -14,11 +14,13 @@ depends: [ "octez-libs" "tezt-tezos" "tezt-cloud" + "bls12-381" + "crunch" { >= "3.3.0" } + "floodgate" { = version } "octez-rust-deps" {with-test} "ppx_import" {with-test} "ppx_deriving" {with-test} "tezt" { with-test & >= "4.1.0" & < "5.0.0" } - "bls12-381" {with-test} "qcheck-alcotest" { with-test & >= "0.20" } "octez-alcotezt" {with-test} "octez-l2-libs" {with-test} diff --git a/tobi/config b/tobi/config index 34aa79d5f734..676c78b10871 100644 --- a/tobi/config +++ b/tobi/config @@ -212,7 +212,7 @@ tezos_internal_brassaia_eio_tests: brassaia-eio/test, brassaia-eio/test/brassaia tezos_internal_brassaia_tests: brassaia/test, brassaia/test/brassaia, brassaia/test/brassaia-mem, brassaia/test/brassaia-pack, brassaia/test/brassaia-tezos, brassaia/test/brassaia/data, brassaia/test/brassaia/generic-key tezos_internal_irmin_tests: irmin/test, irmin/test/irmin, irmin/test/irmin-mem, irmin/test/irmin-pack, irmin/test/irmin-tezos, irmin/test/irmin/data, irmin/test/irmin/generic-key tezt-cloud: tezt/lib_cloud -tezt-etherlink: etherlink/tezt/lib, etherlink/tezt/tests +tezt-etherlink: etherlink/tezt/benchmarks/lib, etherlink/tezt/lib, etherlink/tezt/tests tezt-tests-cloud: tezt/tests/cloud tezt-tezos: tezt/lib_performance_regression, tezt/lib_tezos, tezt/self_tests tezt-tx-kernel: tezt/lib_tx_kernel -- GitLab From 2ec51d47f3dc920159fd41f3e35b48ebdb1869e1 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Mon, 10 Nov 2025 15:44:20 +0100 Subject: [PATCH 4/7] Tezt-cloud: depdend on etherlink benchmarks library --- manifest/product_etherlink.mli | 2 ++ manifest/product_tezt_cloud_tests.ml | 1 + opam/tezt-tests-cloud.opam | 1 + tezt/tests/cloud/dune | 2 ++ 4 files changed, 6 insertions(+) diff --git a/manifest/product_etherlink.mli b/manifest/product_etherlink.mli index c012d2e0ca91..980734c77c02 100644 --- a/manifest/product_etherlink.mli +++ b/manifest/product_etherlink.mli @@ -9,4 +9,6 @@ val tezt_etherlink : Manifest.target +val tezt_benchmark_lib : Manifest.target + val registered_octez_evm_node_libs : Manifest.Sub_lib.container diff --git a/manifest/product_tezt_cloud_tests.ml b/manifest/product_tezt_cloud_tests.ml index dd525d6dd219..e3d499413f9d 100644 --- a/manifest/product_tezt_cloud_tests.ml +++ b/manifest/product_tezt_cloud_tests.ml @@ -24,6 +24,7 @@ let _main = tezt_tezos |> open_ |> open_ ~m:"Runnable.Syntax"; tezt_cloud |> open_; tezt_etherlink; + tezt_benchmark_lib; octez_stdlib_unix; ] ~release_status:Unreleased diff --git a/opam/tezt-tests-cloud.opam b/opam/tezt-tests-cloud.opam index 29917be770d8..64ad00c1cfad 100644 --- a/opam/tezt-tests-cloud.opam +++ b/opam/tezt-tests-cloud.opam @@ -10,6 +10,7 @@ license: "MIT" depends: [ "dune" { >= "3.11.1" } "ocaml" { >= "4.14" } + "octez-evm-node-libs" "bls12-381" "octez-libs" "tezt-tezos" diff --git a/tezt/tests/cloud/dune b/tezt/tests/cloud/dune index b3e7187547c1..04915f7c5037 100644 --- a/tezt/tests/cloud/dune +++ b/tezt/tests/cloud/dune @@ -4,12 +4,14 @@ (executable (name main) (libraries + octez-evm-node-libs.evm_node_rust_deps bls12-381.archive octez-libs.test-helpers octez-libs.tezt-wrapper tezt-tezos tezt-cloud tezt_etherlink + etherlink_benchmark_lib octez-libs.stdlib-unix) (link_flags (:standard) -- GitLab From 1aea5fed1dd407987b840ff3e9accc6a8f86ccb0 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Mon, 10 Nov 2025 16:16:08 +0100 Subject: [PATCH 5/7] Tezt/Etherlink: adapt benchmark lib for use in tezt cloud --- .../tezt/benchmarks/evm_node_capacity.ml | 4 +- .../tezt/benchmarks/lib/benchmark_utils.ml | 119 ++++++++++++------ etherlink/tezt/benchmarks/main.ml | 1 + etherlink/tezt/benchmarks/snailtracer.ml | 8 +- etherlink/tezt/benchmarks/uniswap.ml | 4 +- 5 files changed, 89 insertions(+), 47 deletions(-) diff --git a/etherlink/tezt/benchmarks/evm_node_capacity.ml b/etherlink/tezt/benchmarks/evm_node_capacity.ml index 23cea9a9c6b1..b6baff63b5ab 100644 --- a/etherlink/tezt/benchmarks/evm_node_capacity.ml +++ b/etherlink/tezt/benchmarks/evm_node_capacity.ml @@ -178,7 +178,7 @@ let step ({sequencer; accounts; _} as env) erc20s iteration = in wait_for_application sequencer step_f -let test_erc20_capacity = +let test_erc20_capacity () = let nb_accounts = Option.value parameters.accounts ~default:100 in let nb_contracts = Option.value parameters.contracts ~default:10 in let accounts = Eth_account.accounts nb_accounts in @@ -257,4 +257,4 @@ let test_erc20_capacity = let* () = Evm_node.terminate sequencer in stop_profile () -let register () = test_erc20_capacity [Protocol.Alpha] +let register () = test_erc20_capacity () [Protocol.Alpha] diff --git a/etherlink/tezt/benchmarks/lib/benchmark_utils.ml b/etherlink/tezt/benchmarks/lib/benchmark_utils.ml index 8355513e3ec0..e784f7aeaf60 100644 --- a/etherlink/tezt/benchmarks/lib/benchmark_utils.ml +++ b/etherlink/tezt/benchmarks/lib/benchmark_utils.ml @@ -10,24 +10,61 @@ open Test_helpers open Floodgate_lib type parameters = { - profiling : bool; - time_between_blocks : float; - iterations : int; - accounts : int option; - contracts : int option; - timeout : float; - spp : int; - width : int; - height : int; - swap_hops : int; + mutable profiling : bool; + mutable time_between_blocks : float; + mutable iterations : int; + mutable accounts : int option; + mutable contracts : int option; + mutable timeout : float; + mutable spp : int; + mutable width : int; + mutable height : int; + mutable swap_hops : int; } let parameters = + (* default values *) + { + profiling = false; + time_between_blocks = 0.5; + iterations = 5; + accounts = None; + contracts = None; + timeout = 2.0; + spp = 2; + width = 64; + height = 48; + swap_hops = 1; + } + +module type PARAMETERS = sig + val profiling : bool + + val time_between_blocks : float + + val iterations : int + + val accounts : int option + + val contracts : int option + + val timeout : float + + val spp : int + + val width : int + + val height : int + + val swap_hops : int +end + +module Parameters () : PARAMETERS = struct let section = Clap.section "EVM NODE BENCHMARK" ~description:"Parameters for running benchmarks on the EVM node" - in + let profiling = Clap.flag ~section @@ -36,7 +73,7 @@ let parameters = ~description: "Report profiling information (needs perf on linux and xctrace on \ macos)" - in + let time_between_blocks = Clap.default_float ~section @@ -44,8 +81,8 @@ let parameters = ~short:'T' ~placeholder:"seconds" ~description:"Number of seconds between blocks" - 0.5 - in + parameters.time_between_blocks + let iterations = Clap.default_int ~section @@ -53,8 +90,8 @@ let parameters = ~short:'I' ~placeholder:"nb" ~description:"Number of iterations for the benchmark" - 5 - in + parameters.iterations + let accounts = Clap.optional_int ~section @@ -63,7 +100,7 @@ let parameters = ~placeholder:"nb" ~description:"Number of accounts that sign transactions for the benchmark" () - in + let contracts = Clap.optional_int ~section @@ -72,7 +109,7 @@ let parameters = ~placeholder:"nb" ~description:"Number of ERC20 contracts for the benchmark" () - in + let timeout = Clap.default_float ~section @@ -81,8 +118,8 @@ let parameters = ~description: "Number of seconds to wait for inclusion before considering operation \ dropped" - 2.0 - in + parameters.timeout + let spp = Clap.default_int ~section @@ -91,8 +128,8 @@ let parameters = ~description: "Samples Per Pixel for SnailTracer benchmark. Higher values will use \ more gas." - 2 - in + parameters.spp + let width = Clap.default_int ~section @@ -100,8 +137,8 @@ let parameters = ~placeholder:"pixels" ~description: "Width of image for SnailTracer. Higher values will use more gas." - 64 - in + parameters.width + let height = Clap.default_int ~section @@ -110,27 +147,31 @@ let parameters = ~description: "Height of image for SnailTracer. Higher values will use more gas." 48 - in + let swap_hops = Clap.default_int ~section ~long:"swap-hops" ~placeholder:"nb" ~description:"Number of hops to do in swap path." - 1 - in - { - profiling; - time_between_blocks; - iterations; - accounts; - contracts; - timeout; - spp; - width; - height; - swap_hops; - } + parameters.swap_hops + + let () = + parameters.profiling <- profiling ; + parameters.time_between_blocks <- time_between_blocks ; + parameters.iterations <- iterations ; + parameters.accounts <- accounts ; + parameters.contracts <- contracts ; + parameters.timeout <- timeout ; + parameters.spp <- spp ; + parameters.width <- width ; + parameters.height <- height ; + parameters.swap_hops <- swap_hops +end + +let parse_cli () = + let module P = Parameters () in + () let ( let+? ) x f = match x with diff --git a/etherlink/tezt/benchmarks/main.ml b/etherlink/tezt/benchmarks/main.ml index bd81e29c2adc..09c267deff4f 100644 --- a/etherlink/tezt/benchmarks/main.ml +++ b/etherlink/tezt/benchmarks/main.ml @@ -7,6 +7,7 @@ (*****************************************************************************) let () = + Etherlink_benchmark_lib.Benchmark_utils.parse_cli () ; Evm_node_capacity.register () ; Snailtracer.register () ; Uniswap.register () diff --git a/etherlink/tezt/benchmarks/snailtracer.ml b/etherlink/tezt/benchmarks/snailtracer.ml index 89f06453f421..92b2f27fc8e8 100644 --- a/etherlink/tezt/benchmarks/snailtracer.ml +++ b/etherlink/tezt/benchmarks/snailtracer.ml @@ -207,7 +207,7 @@ let encode_parameters width height = in enc_int width ^ enc_int height -let test_snailtracer = +let test_snailtracer () = let nb_accounts = Option.value parameters.accounts ~default:1 in let width = parameters.width in let height = parameters.height in @@ -286,7 +286,7 @@ let test_snailtracer = let* () = Evm_node.terminate sequencer in stop_profile () -let test_full_image_raytracing = +let test_full_image_raytracing () = let width = parameters.width in let height = parameters.height in let accounts = Eth_account.accounts 1 in @@ -368,6 +368,6 @@ let test_full_image_raytracing = stop_profile () let register () = - test_snailtracer [Protocol.Alpha] ; - test_full_image_raytracing [Protocol.Alpha] ; + test_snailtracer () [Protocol.Alpha] ; + test_full_image_raytracing () [Protocol.Alpha] ; () diff --git a/etherlink/tezt/benchmarks/uniswap.ml b/etherlink/tezt/benchmarks/uniswap.ml index 75ca5fbf0da2..84796b052060 100644 --- a/etherlink/tezt/benchmarks/uniswap.ml +++ b/etherlink/tezt/benchmarks/uniswap.ml @@ -11,7 +11,7 @@ open Etherlink_benchmark_lib open Benchmark_utils open Uniswap -let test_swaps = +let test_swaps () = let nb_accounts = Option.value parameters.accounts ~default:100 in let nb_tokens = Option.value parameters.contracts ~default:1 in let nb_hops = parameters.swap_hops in @@ -44,4 +44,4 @@ let test_swaps = let* () = shutdown () in stop_profile () -let register () = test_swaps [Protocol.Alpha] +let register () = test_swaps () [Protocol.Alpha] -- GitLab From 7efead00b37d57cdaef63a2c355435653e247c63 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Wed, 12 Nov 2025 10:39:39 +0100 Subject: [PATCH 6/7] Tezt/Etherlink: add Dockerfile for tezt cloud --- .gitignore | 2 + .../dockerfiles/etherlink.Dockerfile | 40 +++++++++++++++++++ .../etherlink.Dockerfile.dockerignore | 0 3 files changed, 42 insertions(+) create mode 100644 tezt/lib_cloud/dockerfiles/etherlink.Dockerfile create mode 100644 tezt/lib_cloud/dockerfiles/etherlink.Dockerfile.dockerignore diff --git a/.gitignore b/.gitignore index 9d0cf4e26ee0..ce742fc57282 100644 --- a/.gitignore +++ b/.gitignore @@ -93,6 +93,8 @@ tezt/lib_cloud/dockerfiles/*.Dockerfile.dockerignore !tezt/lib_cloud/dockerfiles/dal_with_snapshot.Dockerfile.dockerignore !tezt/lib_cloud/dockerfiles/octez.Dockerfile !tezt/lib_cloud/dockerfiles/octez.Dockerfile.dockerignore +!tezt/lib_cloud/dockerfiles/etherlink.Dockerfile +!tezt/lib_cloud/dockerfiles/etherlink.Dockerfile.dockerignore .merlin *~ diff --git a/tezt/lib_cloud/dockerfiles/etherlink.Dockerfile b/tezt/lib_cloud/dockerfiles/etherlink.Dockerfile new file mode 100644 index 000000000000..75e1ee7bf115 --- /dev/null +++ b/tezt/lib_cloud/dockerfiles/etherlink.Dockerfile @@ -0,0 +1,40 @@ +# This dockerfile can be run on any system and provides an image with +# the latest EVM node released and everything necessary for tezt-cloud. + +ARG EVM_NODE_VERSION=latest +FROM tezos/tezos:octez-evm-node-${EVM_NODE_VERSION} + +# hadolint ignore=DL3002 +USER root + +# hadolint ignore=DL3018 +RUN apk add --no-cache \ + openssh openssh-server \ + docker-cli screen file \ + curl wget jq \ + prometheus prometheus-node-exporter + +# hadolint ignore=DL3022 +COPY --from=ncabatoff/process-exporter:latest \ + /bin/process-exporter /usr/local/bin/prometheus-process-exporter + +# SSH key that will be used for the SSH server +ARG SSH_PUBLIC_KEY + +# This is extracted from the link below +# https://dev.to/yakovlev_alexey/running-ssh-in-an-alpine-docker-container-3lop +RUN mkdir -p /root/.ssh \ + && chmod 0700 /root/.ssh \ + && echo "$SSH_PUBLIC_KEY" > /root/.ssh/authorized_keys \ + && ssh-keygen -A \ + && echo "PasswordAuthentication no" >> /etc/ssh/sshd_config \ + && mkdir -p /run/openrc \ + && touch /run/openrc/softlevel + +# Path where binaries should be stored on the docker container +ARG BINARIES_DESTINATION_PATH +RUN mkdir -p $BINARIES_DESTINATION_PATH/ && \ + cp /usr/local/bin/octez-evm-node $BINARIES_DESTINATION_PATH/ + +CMD ["-D", "-p", "30000", "-e"] +ENTRYPOINT ["/usr/sbin/sshd"] diff --git a/tezt/lib_cloud/dockerfiles/etherlink.Dockerfile.dockerignore b/tezt/lib_cloud/dockerfiles/etherlink.Dockerfile.dockerignore new file mode 100644 index 000000000000..e69de29bb2d1 -- GitLab From cfa92699fb53ed00da959c54211d3eb1b342ebeb Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 20 Nov 2025 15:28:44 +0100 Subject: [PATCH 7/7] Tezt/Etherlink: Tezt cloud scenario for running UniswapV2 benchmark --- .../tezt/benchmarks/lib/benchmark_utils.ml | 52 +++-- etherlink/tezt/benchmarks/lib/uniswap.ml | 8 +- tezt/lib_cloud/tezt_cloud.ml | 2 + tezt/lib_cloud/tezt_cloud.mli | 2 + tezt/tests/cloud/etherlink.ml | 215 ++++++++++++++++++ tezt/tests/cloud/main.ml | 4 + tezt/tests/cloud/scenarios_cli.ml | 63 +++++ tezt/tests/cloud/tezos.ml | 15 +- 8 files changed, 340 insertions(+), 21 deletions(-) create mode 100644 tezt/tests/cloud/etherlink.ml diff --git a/etherlink/tezt/benchmarks/lib/benchmark_utils.ml b/etherlink/tezt/benchmarks/lib/benchmark_utils.ml index e784f7aeaf60..3bedcfb751c4 100644 --- a/etherlink/tezt/benchmarks/lib/benchmark_utils.ml +++ b/etherlink/tezt/benchmarks/lib/benchmark_utils.ml @@ -11,7 +11,13 @@ open Floodgate_lib type parameters = { mutable profiling : bool; - mutable time_between_blocks : float; + mutable time_between_blocks : + [ `Manual of float + (** [`Manual t] the sandbox node will not produce any block by itself but + the tezt benchmark will call [produce_block] every [t] seconds *) + | `Auto of float + (** [`Auto t] the sandbox node will produce a block every [t] seconds *) + ]; mutable iterations : int; mutable accounts : int option; mutable contracts : int option; @@ -26,7 +32,7 @@ let parameters = (* default values *) { profiling = false; - time_between_blocks = 0.5; + time_between_blocks = `Manual 0.5; iterations = 5; accounts = None; contracts = None; @@ -40,7 +46,7 @@ let parameters = module type PARAMETERS = sig val profiling : bool - val time_between_blocks : float + val time_between_blocks : [`Manual of float | `Auto of float] val iterations : int @@ -74,13 +80,31 @@ module Parameters () : PARAMETERS = struct "Report profiling information (needs perf on linux and xctrace on \ macos)" + let tbb = + Clap.typ + ~name:"time_between_blocks" + ~dummy:parameters.time_between_blocks + ~parse:(fun s -> + match String.split_on_char ':' s with + | ["auto"; v] -> Some (`Auto (float_of_string v)) + | ["manual"; v] -> Some (`Manual (float_of_string v)) + | _ -> None) + ~show:(function + | `Auto v -> "auto:" ^ string_of_float v + | `Manual v -> "manual:" ^ string_of_float v) + let time_between_blocks = - Clap.default_float + Clap.default + tbb ~section ~long:"time_between_blocks" ~short:'T' - ~placeholder:"seconds" - ~description:"Number of seconds between blocks" + ~placeholder:"[auto|manual]:seconds" + ~description: + "Number of seconds between blocks. With auto:t the sequencer will \ + produce a block every t seconds, while with manual:t the sequencer \ + will not produce any block by itself but the tezt benchmark will call \ + produce_block every t seconds." parameters.time_between_blocks let iterations = @@ -196,14 +220,16 @@ let nb_confirmed = ref 0 let wait_for_application ?(time_between_blocks = parameters.time_between_blocks) ?(max_blocks = - max 1 (int_of_float ((parameters.timeout /. time_between_blocks) +. 1.))) - sequencer f = + let (`Auto tbb | `Manual tbb) = time_between_blocks in + max 1 (int_of_float ((parameters.timeout /. tbb) +. 1.))) sequencer f = + let (`Auto tbb | `Manual tbb) = time_between_blocks in + let produce_block = + match time_between_blocks with + | `Auto _ -> fun () -> Lwt.return_ok 0 + | `Manual _ -> fun () -> produce_block sequencer + in let* res = - wait_for_application - f - ~time_between_blocks - ~max_blocks - ~produce_block:(fun _ -> produce_block sequencer) + wait_for_application f ~time_between_blocks:tbb ~max_blocks ~produce_block in if !nb_dropped <> 0 then Log.info ~color:Log.Color.FG.red "%d operations DROPPED" !nb_dropped ; diff --git a/etherlink/tezt/benchmarks/lib/uniswap.ml b/etherlink/tezt/benchmarks/lib/uniswap.ml index e78345276b51..e891725636e5 100644 --- a/etherlink/tezt/benchmarks/lib/uniswap.ml +++ b/etherlink/tezt/benchmarks/lib/uniswap.ml @@ -312,12 +312,14 @@ let swap_xtz ~nb_hops env iteration sender_index = env.rpc_node env.router_addr sender - ~gas_limit:(Z.of_int (260_000 * nb_hops)) (* Rough approximation *) + ~gas_limit:(Z.of_int (2_600_000 * nb_hops)) (* Rough approximation *) ~value:(Z.of_int (10000 + (iteration * 100))) ~name:"swapExactETHForTokens" (* "swapETHForExactTokens" *) params_ty params - ~check_success:true + ~check_success:false + (* Don't check success as this is an additional RPC and will slow the + benchmark down. It can be set to true for debugging. *) in unit @@ -386,7 +388,7 @@ let setup ~accounts ~nb_tokens ~nb_hops ~sequencer ~rpc_node = ~relay_endpoint:endpoint ~rpc_endpoint:endpoint in - let tx_queue = Tx_queue.beacon ~tick_interval:0.5 in + let tx_queue = Tx_queue.beacon ~tick_interval:0.25 in Log.report "Deploying WXTZ" ; let* wxtz_addr = deploy_contract ~rpc_node infos ~sequencer sender `ERC20 in Log.info " WXTZ: %s" wxtz_addr ; diff --git a/tezt/lib_cloud/tezt_cloud.ml b/tezt/lib_cloud/tezt_cloud.ml index b2cda72b037c..85dccd0c7c59 100644 --- a/tezt/lib_cloud/tezt_cloud.ml +++ b/tezt/lib_cloud/tezt_cloud.ml @@ -313,6 +313,8 @@ module Tezt_cloud_cli = struct let artifacts_dir = Cli.artifacts_dir + let binaries_path = Cli.binaries_path + let teztale_artifacts = Cli.teztale_artifacts let faketime = Cli.faketime diff --git a/tezt/lib_cloud/tezt_cloud.mli b/tezt/lib_cloud/tezt_cloud.mli index 6a4e2a1d81f4..cff19c9634d3 100644 --- a/tezt/lib_cloud/tezt_cloud.mli +++ b/tezt/lib_cloud/tezt_cloud.mli @@ -277,6 +277,8 @@ module Tezt_cloud_cli : sig val artifacts_dir : string option + val binaries_path : string + val teztale_artifacts : bool val faketime : string option diff --git a/tezt/tests/cloud/etherlink.ml b/tezt/tests/cloud/etherlink.ml new file mode 100644 index 000000000000..a1448dd7c90d --- /dev/null +++ b/tezt/tests/cloud/etherlink.ml @@ -0,0 +1,215 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* SPDX-FileCopyrightText: 2025 Nomadic Labs *) +(* SPDX-FileCopyrightText: 2025 Functori *) +(* *) +(*****************************************************************************) + +(** + This scenario runs an Etherlink sandbox and benchmarks the node capacity + using the UniswapV2 contracts. + + To run this tezt-cloud scenario, first setup your gcloud environmenmt + {v + gcloud auth application-default login + gcloud config set project tezlink + v} + + If you run Docker on mac os, enable + {{!https://docs.docker.com/engine/network/drivers/host/#docker-desktop}host + networking} and add the flag [--macosx] to the command below. + + The scenario can then be started with + {v + dune exec tezt/tests/cloud/main.exe -- ETHERLINK \ + --tezt-cloud etherlink --destroy \ + --machine-type c2d-standard-8 \ + --docker-host-network \ + --network braeburn -i + v} + + You can benchmark different combinations of network context and kernel using + the [--network] and [--kernel] options. See the [--help] for more benchmark + options to control the number of iterations, swap hops, accounts, etc. +*) + +module Cli = Scenarios_cli +open Scenarios_helpers +open Tezt_etherlink +open Etherlink_benchmark_lib +open Benchmark_utils + +let setup_sequencer_sandbox (cloud : Cloud.t) ~name network kernel + (time_between_blocks : Evm_node.time_between_blocks) accounts agent = + let rpc_port = Agent.next_available_port agent in + let private_rpc_port = Agent.next_available_port agent |> Option.some in + let custom_dest = "/kernel/evm_kernel.wasm" in + let init_from_snapshot = Option.is_some network in + let initial_kernel_source = + match (network, kernel) with + | Some _, `Mainnet -> None + | _, `Mainnet -> + Some + "etherlink/kernel_latest/kernel/tests/resources/mainnet_kernel.wasm" + | _, `Custom k -> Some k + in + let* initial_kernel = + match initial_kernel_source with + | None -> return None + | Some source -> + let* p = Agent.copy ~source ~destination:custom_dest agent in + return (Some p) + in + let wallet_dir = Temp.dir "wallet" in + let preimages_dir = Temp.dir "wasm_2_0_0" in + let funded_addresses = + Array.to_list accounts |> List.map (fun a -> a.Eth_account.address) + in + let mode = + Evm_node.Sandbox + { + initial_kernel; + network; + funded_addresses; + sequencer_keys = []; + preimage_dir = Some preimages_dir; + private_rpc_port; + time_between_blocks = Some time_between_blocks; + genesis_timestamp = None; + max_number_of_chunks = None; + wallet_dir = Some wallet_dir; + tx_queue_max_lifespan = None; + tx_queue_max_size = None; + tx_queue_tx_per_addr_limit = None; + } + in + let () = toplog "Launching the sandbox L2 node" in + let add_cors rpc = + JSON.update rpc (fun json -> + JSON.update + "cors_headers" + (fun _ -> + JSON.annotate ~origin:"patch-config:cors_headers" + @@ `A [`String "*"]) + json + |> JSON.update "cors_origins" (fun _ -> + JSON.annotate ~origin:"patch-config:cors_origins" + @@ `A [`String "*"])) + in + let add_telemetry config = + match Cloud.open_telemetry_endpoint cloud with + | None -> config + | Some base -> + let j = JSON.annotate ~origin:"patch-config:opentelemetry" in + config + |> JSON.update "opentelemetry" @@ fun otel_config -> + otel_config + |> JSON.update "enable" (fun _ -> j (`Bool true)) + |> JSON.update "url_traces" (fun _ -> + j (`String (base ^ "/v1/traces"))) + |> JSON.update "url_logs" (fun _ -> j (`String (base ^ "/v1/logs"))) + in + let extra_arguments = + Cli_arg.optional_switch "init-from-snapshot" init_from_snapshot + in + let* evm_node = + Tezos.Evm_node.Agent.init + ~wait:false + ~copy_binary:false + (* We use the binary from the EVM release docker image *) + ~patch_config:(fun json -> + json |> add_cors "public_rpc" |> add_cors "private_rpc" |> add_telemetry + |> Evm_node.patch_config_with_experimental_feature + ~drop_duplicate_when_injection:true + ~blueprints_publisher_order_enabled:true + ~rpc_server:Resto + ()) + ~name:"sandboxed-sequencer" + ~mode + ~rpc_port + ~extra_arguments + "http://dummy_rollup_endpoint" + cloud + agent + in + let* () = Evm_node.wait_for_ready ~timeout:1200. evm_node in + let () = toplog "Launching the sandbox L2 node: done" in + let* () = add_prometheus_source ~evm_node cloud agent name in + let () = toplog "Added prometheus source" in + return evm_node + +(* Set default values for CLI arguments. *) +let () = + parameters.time_between_blocks <- `Auto 0.5 ; + parameters.iterations <- 1000 ; + parameters.accounts <- Some 150 ; + parameters.contracts <- Some 2 ; + parameters.timeout <- 15. ; + parameters.swap_hops <- 2 ; + () + +let register (module Cli : Scenarios_cli.Etherlink) = + let () = toplog "Parsing CLI done" in + let name = "etherlink" in + let docker_tag = + match Cli.evm_node_version with `Latest -> "latest" | `V s -> "v" ^ s + in + let dockerbuild_args = [("EVM_NODE_VERSION", docker_tag)] in + let vms () = return [Agent.Configuration.make ~name ~dockerbuild_args ()] in + Cloud.register + ~vms + ~proxy_files:[] + ~proxy_args:[] + ~__FILE__ + ~title:"Etherlink benchmark" + ~tags:[] + ~dockerbuild_args + @@ fun cloud -> + Clap.close () ; + let () = toplog "Creating the agents" in + let agents = Cloud.agents cloud in + let sequencer_agent = List.hd agents in + let nb_accounts = Option.value parameters.accounts ~default:150 in + let accounts = Eth_account.accounts nb_accounts in + let nb_tokens = Option.value parameters.contracts ~default:2 in + let () = toplog "Starting sequencer" in + let time_between_empty_blocks = 6.0 in + let time_between_blocks = + match Cli.time_between_blocks with + | `Auto _ -> Evm_node.Time_between_blocks time_between_empty_blocks + | `Manual _ -> Nothing + in + let* sequencer = + setup_sequencer_sandbox + cloud + ~name + Cli.network + Cli.kernel + time_between_blocks + accounts + sequencer_agent + in + let* () = + (* The durable storage is patched on startup to pre-fund addresses. If there + is already a context, we need to wait for the next block for the patch to + be effective. *) + match Cli.kernel with + | `Custom _ -> unit + | `Mainnet -> Lwt_unix.sleep (time_between_empty_blocks *. 4.) + in + let () = toplog "Setup UniswapV2 benchmark" in + let* env, shutdown = + Uniswap.setup + ~accounts + ~nb_tokens + ~nb_hops:parameters.swap_hops + ~sequencer + ~rpc_node:sequencer + in + let () = toplog "Setup UniswapV2 benchmark complete" in + monitor_gasometer sequencer @@ fun () -> + let* () = + Lwt_list.iter_s (Uniswap.step env) (List.init parameters.iterations succ) + in + shutdown () diff --git a/tezt/tests/cloud/main.ml b/tezt/tests/cloud/main.ml index 8f5d46e75eb1..1abc0a603cc1 100644 --- a/tezt/tests/cloud/main.ml +++ b/tezt/tests/cloud/main.ml @@ -20,6 +20,9 @@ let () = let module M = Scenarios_cli.Tezlink () in `tezlink (module M : Scenarios_cli.Tezlink) ); (Clap.case "BASIC" @@ fun () -> `basic); + ( Clap.case "ETHERLINK" @@ fun () -> + let module M = Scenarios_cli.Etherlink () in + `etherlink (module M : Scenarios_cli.Etherlink) ); ( Clap.case ~description: "Perform tasks unrelated to any particular scenario such as \ @@ -33,5 +36,6 @@ let () = | `dal m -> Dal.register m | `layer1 m -> Layer1.register m | `tezlink m -> Tezlink.register m + | `etherlink m -> Etherlink.register m | `cloud -> Tezt_cloud.register ~tags:[]) ; Test.run () diff --git a/tezt/tests/cloud/scenarios_cli.ml b/tezt/tests/cloud/scenarios_cli.ml index b53fc4e02245..4a48ab738aa3 100644 --- a/tezt/tests/cloud/scenarios_cli.ml +++ b/tezt/tests/cloud/scenarios_cli.ml @@ -1277,3 +1277,66 @@ module Tezlink () : Tezlink = struct domains need to be registered with the dns-domain option." () end + +module type Etherlink = sig + val kernel : [`Mainnet | `Custom of string] + + val network : string option + + val evm_node_version : [`Latest | `V of string] + + include Etherlink_benchmark_lib.Benchmark_utils.PARAMETERS +end + +module Etherlink () : Etherlink = struct + let section = + Clap.section + ~description: + "All the options related to running Etherlink scenarios onto the cloud" + "Etherlink" + + let kernel = + let s = + Clap.default_string + ~section + ~long:"kernel" + ~description: + "Path to wasm kernel for Etherlink node. (default: mainnet)" + ~placeholder:"" + "mainnet" + in + if s = "mainnet" then `Mainnet else `Custom s + + let network = + let typ = + Clap.enum + "network" + (List.map (fun x -> (x, x)) ["mainnet"; "testnet"; "braeburn"]) + in + Clap.optional + typ + ~section + ~long:"network" + ~description:"Start a sandbox with a context from this network" + ~placeholder:"" + () + + let evm_node_version = + Clap.default + (Clap.typ + ~name:"EVM node version" + ~dummy:`Latest + ~parse:(function + | "latest" -> Some `Latest + | s when String.length s >= 1 && s.[0] = 'v' -> + Some (`V (String.sub s 1 (String.length s - 1))) + | s -> Some (`V s)) + ~show:(function `Latest -> "latest" | `V s -> "v" ^ s)) + ~section + ~long:"evm-node-version" + ~description:"Choose the EVM node version to use for the benchmark" + ~placeholder:"" + `Latest + + include Etherlink_benchmark_lib.Benchmark_utils.Parameters () +end diff --git a/tezt/tests/cloud/tezos.ml b/tezt/tests/cloud/tezos.ml index a52859ca7805..88c2309c69b2 100644 --- a/tezt/tests/cloud/tezos.ml +++ b/tezt/tests/cloud/tezos.ml @@ -862,10 +862,14 @@ module Evm_node = struct module Agent = struct (* Use for compatibility with `tezt-cloud`. *) - let create ?(group = "Etherlink") + let create ?(group = "Etherlink") ?(copy_binary = true) ?(path = Uses.path Constant.octez_evm_node) ?name ?data_dir ?mode ?rpc_port ?websockets endpoint cloud agent = - let* path = Agent.copy agent ~source:path in + let* path = + if copy_binary then Agent.copy agent ~source:path + else + return Filename.(concat Tezt_cloud_cli.binaries_path (basename path)) + in let* () = Cloud.register_binary cloud @@ -883,11 +887,12 @@ module Evm_node = struct create ?name ~path ?runner ?data_dir ~rpc_port ?mode ?websockets endpoint |> Lwt.return - let init ?patch_config ?name ?mode ?websockets ?data_dir ?rpc_port - rollup_node cloud agent = + let init ?patch_config ?name ?mode ?websockets ?data_dir ?rpc_port ?wait + ?extra_arguments ?copy_binary rollup_node cloud agent = let* evm_node = create ?name + ?copy_binary ?mode ?rpc_port ?websockets @@ -902,7 +907,7 @@ module Evm_node = struct | Some patch_config -> Config_file.update evm_node patch_config | None -> unit in - let* () = run evm_node in + let* () = run ?wait ?extra_arguments evm_node in return evm_node end end -- GitLab