diff --git a/etherlink/bin_node/config/configuration.ml b/etherlink/bin_node/config/configuration.ml index 4811ce1cf9598883221ad8c49a88e2ff6cab6576..ae254ffdc68b4fcb17096fd1394fa993bc076c7d 100644 --- a/etherlink/bin_node/config/configuration.ml +++ b/etherlink/bin_node/config/configuration.ml @@ -73,6 +73,7 @@ type experimental_features = { enable_websocket : bool; max_websocket_message_length : int; monitor_websocket_heartbeat : monitor_websocket_heartbeat option; + spawn_rpc : int option; l2_chains : l2_chain list option; enable_tx_queue : bool; } @@ -215,6 +216,7 @@ let default_experimental_features = enable_websocket = false; max_websocket_message_length = default_max_socket_message_length; monitor_websocket_heartbeat = default_monitor_websocket_heartbeat; + spawn_rpc = None; l2_chains = default_l2_chains; enable_tx_queue = false; } @@ -845,6 +847,7 @@ let experimental_features_encoding = enable_websocket; max_websocket_message_length; monitor_websocket_heartbeat; + spawn_rpc; l2_chains : l2_chain list option; enable_tx_queue; } -> @@ -858,6 +861,7 @@ let experimental_features_encoding = enable_websocket, max_websocket_message_length, monitor_websocket_heartbeat, + spawn_rpc, l2_chains, enable_tx_queue ) )) (fun ( ( drop_duplicate_on_injection, @@ -870,6 +874,7 @@ let experimental_features_encoding = enable_websocket, max_websocket_message_length, monitor_websocket_heartbeat, + spawn_rpc, l2_chains, enable_tx_queue ) ) -> { @@ -881,6 +886,7 @@ let experimental_features_encoding = enable_websocket; max_websocket_message_length; monitor_websocket_heartbeat; + spawn_rpc; l2_chains; enable_tx_queue; }) @@ -933,7 +939,7 @@ let experimental_features_encoding = DEPRECATED: You should remove this option from your \ configuration file." bool)) - (obj6 + (obj7 (dft "rpc_server" ~description: @@ -958,6 +964,11 @@ let experimental_features_encoding = ~description:"Parameters to monitor websocket connections" opt_monitor_websocket_heartbeat_encoding default_monitor_websocket_heartbeat) + (dft + "spawn_rpc" + ~description:"Spawn a RPC node listening on the given port" + (option @@ obj1 (req "protected_port" (ranged_int 1 65535))) + None) (dft "l2_chains" ~description: diff --git a/etherlink/bin_node/config/configuration.mli b/etherlink/bin_node/config/configuration.mli index e0be742d8f8951ce961d1cccfc76d2947559d28e..f1cbd6ed4a2bafaeef5b294ceae2db1ddcc1ae01 100644 --- a/etherlink/bin_node/config/configuration.mli +++ b/etherlink/bin_node/config/configuration.mli @@ -98,6 +98,7 @@ type experimental_features = { enable_websocket : bool; max_websocket_message_length : int; monitor_websocket_heartbeat : monitor_websocket_heartbeat option; + spawn_rpc : int option; l2_chains : l2_chain list option; enable_tx_queue : bool; } diff --git a/etherlink/bin_node/lib_dev/events.ml b/etherlink/bin_node/lib_dev/events.ml index 3b95764338e5640da81560b2ab9bba8679cc4d6a..f5385b9c20516a41e63f5de8008f9bb6156499a6 100644 --- a/etherlink/bin_node/lib_dev/events.ml +++ b/etherlink/bin_node/lib_dev/events.ml @@ -99,6 +99,14 @@ let legacy_mode = snapshot to start using the new block storage" () +let spawn_rpc_is_ready = + Internal_event.Simple.declare_0 + ~section + ~name:"spawn_rpc_is_ready" + ~level:Notice + ~msg:"the rpc process is ready" + () + let event_private_server_is_ready = declare_4 ~section @@ -423,6 +431,8 @@ let is_ready ~rpc_addr ~rpc_port ~websockets ~backend = let legacy_mode () = emit legacy_mode () +let spawn_rpc_is_ready () = emit spawn_rpc_is_ready () + let private_server_is_ready ~rpc_addr ~rpc_port ~websockets ~backend = emit event_private_server_is_ready (rpc_addr, rpc_port, backend, websockets) diff --git a/etherlink/bin_node/lib_dev/events.mli b/etherlink/bin_node/lib_dev/events.mli index b0b85686b2d0035ad589be077ce37a88ab395430..ec7f249e4f0cf25bf21c1c5ee706b4cd1e0688f2 100644 --- a/etherlink/bin_node/lib_dev/events.mli +++ b/etherlink/bin_node/lib_dev/events.mli @@ -56,6 +56,10 @@ val is_ready : (** [legacy_mode ()] advertises the EVM node is using the legacy block storage. *) val legacy_mode : unit -> unit Lwt.t +(** [spawn_rpc_is_ready ()] advertises that the RPC spawned with experimental + feature [spawn_rpc] has made its public endpoint available. *) +val spawn_rpc_is_ready : unit -> unit Lwt.t + (** [private_server_is_ready ~rpc_addr ~rpc_port ~websockets ~backend] advertises that the private rpc server is ready and listens to [rpc_addr]:[rpc_port]. *) diff --git a/etherlink/bin_node/lib_dev/observer.ml b/etherlink/bin_node/lib_dev/observer.ml index 97a87275ca1223aab67eff7a97b83a0b171b09d1..b09cc73ef9facb039c3efd0fa0e20e82dc73a4cc 100644 --- a/etherlink/bin_node/lib_dev/observer.ml +++ b/etherlink/bin_node/lib_dev/observer.ml @@ -70,12 +70,13 @@ let on_new_blueprint evm_node_endpoint next_blueprint_number else return `Continue let install_finalizer_observer ~rollup_node_tracking finalizer_public_server - finalizer_private_server = + finalizer_private_server finalizer_rpc_process = let open Lwt_syntax in Lwt_exit.register_clean_up_callback ~loc:__LOC__ @@ fun exit_status -> let* () = Events.shutdown_node ~exit_status in let* () = finalizer_public_server () in let* () = finalizer_private_server () in + let* () = Option.iter_s (fun f -> f ()) finalizer_rpc_process in Misc.unwrap_error_monad @@ fun () -> let open Lwt_result_syntax in let* () = Tx_pool.shutdown () in @@ -126,6 +127,7 @@ let interpolate_snapshot_provider rollup_address network provider = let main ?network ?kernel_path ~data_dir ~(config : Configuration.t) ~no_sync ~init_from_snapshot () = let open Lwt_result_syntax in + let open Configuration in let*? { evm_node_endpoint; threshold_encryption_bundler_endpoint; @@ -262,11 +264,31 @@ let main ?network ?kernel_path ~data_dir ~(config : Configuration.t) ~no_sync return_unit in + let finalizer_rpc_process = + Option.map + (fun port -> + let protected_endpoint = + Uri.make ~scheme:"http" ~host:config.public_rpc.addr ~port () + in + let private_endpoint = + Option.map + (fun {addr; port; _} -> Uri.make ~scheme:"http" ~host:addr ~port ()) + config.private_rpc + in + Rpc.spawn_main + ~exposed_port:config.public_rpc.port + ~protected_endpoint + ?private_endpoint + ~data_dir + ()) + config.experimental_features.spawn_rpc + in let (_ : Lwt_exit.clean_up_callback_id) = install_finalizer_observer ~rollup_node_tracking finalizer_public_server finalizer_private_server + finalizer_rpc_process in let*! next_blueprint_number = Evm_context.next_blueprint_number () in diff --git a/etherlink/bin_node/lib_dev/rpc.ml b/etherlink/bin_node/lib_dev/rpc.ml index fe117c52edfe817164c088423c89fef517990351..36b9c8ef95c0c66ae0987a8bbdb0bb808e5dec3f 100644 --- a/etherlink/bin_node/lib_dev/rpc.ml +++ b/etherlink/bin_node/lib_dev/rpc.ml @@ -5,6 +5,35 @@ (* *) (*****************************************************************************) +let spawn_main ~exposed_port ~protected_endpoint ?private_endpoint ~data_dir () + = + let p_name = Sys.executable_name in + let base_cmd = + [| + Filename.basename p_name; + "experimental"; + "run"; + "rpc"; + "--rpc-port"; + string_of_int exposed_port; + "--evm-node-endpoint"; + Uri.to_string protected_endpoint; + "--data-dir"; + data_dir; + |] + in + let private_cmd = + Option.fold + ~none:[||] + ~some:(fun uri -> [|"--evm-node-private-endpoint"; Uri.to_string uri|]) + private_endpoint + in + let process = + Lwt_process.open_process_none (p_name, Array.concat [base_cmd; private_cmd]) + in + let finalizer () = Lwt.return process#terminate in + finalizer + let install_finalizer_rpc server_public_finalizer = let open Lwt_syntax in Lwt_exit.register_clean_up_callback ~loc:__LOC__ @@ fun exit_status -> @@ -84,6 +113,15 @@ let main ~data_dir ~evm_node_endpoint ?evm_node_private_endpoint ~tx_pool_size_info:Tx_pool.size_info ~smart_rollup_address:ctxt.smart_rollup_address ; + (* Never spawn from an RPC node *) + let rpc_config = + { + config with + experimental_features = + {config.experimental_features with spawn_rpc = None}; + } + in + let* server_public_finalizer = Rpc_server.start_public_server ~delegate_health_check_to:evm_node_endpoint @@ -91,7 +129,7 @@ let main ~data_dir ~evm_node_endpoint ?evm_node_private_endpoint Evm_ro_context.(evm_services_methods ctxt time_between_blocks) ~data_dir Stateless - config + rpc_config (rpc_backend, ctxt.smart_rollup_address) in @@ -99,6 +137,11 @@ let main ~data_dir ~evm_node_endpoint ?evm_node_private_endpoint install_finalizer_rpc server_public_finalizer in + let* () = + when_ (Option.is_some config.experimental_features.spawn_rpc) @@ fun () -> + Lwt_result.ok (Events.spawn_rpc_is_ready ()) + in + let* next_blueprint_number = Evm_ro_context.next_blueprint_number ctxt in Blueprints_follower.start diff --git a/etherlink/bin_node/lib_dev/rpc.mli b/etherlink/bin_node/lib_dev/rpc.mli index 02014460a7528965c59c5203594f0a9e91dc68a6..9110427f6f429215281fb5602f53842b12e627e8 100644 --- a/etherlink/bin_node/lib_dev/rpc.mli +++ b/etherlink/bin_node/lib_dev/rpc.mli @@ -16,3 +16,14 @@ val main : config:Configuration.t -> unit -> unit tzresult Lwt.t + +(** [spawn_main ~exposed_port ~redirection_endpoint ~data_dir] spawn an RPC process that listens + to [exposed_port], connects to [protected_endpoint] and [private_endpoint] when specified, + and reads the config in [data_dir]. *) +val spawn_main : + exposed_port:int -> + protected_endpoint:Uri.t -> + ?private_endpoint:Uri.t -> + data_dir:string -> + unit -> + Rpc_server.finalizer diff --git a/etherlink/bin_node/lib_dev/rpc_server.ml b/etherlink/bin_node/lib_dev/rpc_server.ml index 7cd4e4b1b4f64fdee8bd1aa49089a5b17422581b..f76c806dffd63994de29c573a262156af4dcecfe 100644 --- a/etherlink/bin_node/lib_dev/rpc_server.ml +++ b/etherlink/bin_node/lib_dev/rpc_server.ml @@ -143,21 +143,24 @@ let start_public_server ?delegate_health_check_to ?evm_services ?data_dir impl.smart_rollup_address impl.time_between_blocks in + + (* If spawn_rpc is defined, use it as intermediate *) + let rpc = + match config.experimental_features.spawn_rpc with + | Some port -> {config.public_rpc with port} + | _ -> config.public_rpc + in + let directory = - Services.directory - ?delegate_health_check_to - config.public_rpc - validation - config - ctxt + Services.directory ?delegate_health_check_to rpc validation config ctxt |> register_evm_services |> Evm_directory.register_metrics "/metrics" in - let* finalizer = start_server config.public_rpc directory in + let* finalizer = start_server rpc directory in let*! () = Events.is_ready - ~rpc_addr:config.public_rpc.addr - ~rpc_port:config.public_rpc.port + ~rpc_addr:rpc.addr + ~rpc_port:rpc.port ~backend:config.experimental_features.rpc_server ~websockets:config.experimental_features.enable_websocket in diff --git a/etherlink/bin_node/lib_dev/sequencer.ml b/etherlink/bin_node/lib_dev/sequencer.ml index 8331b59501a8e0732ec528e59e33e25f6975de73..62da7d22ea27ba7554bea009d9cdcffab62f7b59 100644 --- a/etherlink/bin_node/lib_dev/sequencer.ml +++ b/etherlink/bin_node/lib_dev/sequencer.ml @@ -6,12 +6,14 @@ (* *) (*****************************************************************************) -let install_finalizer_seq server_public_finalizer server_private_finalizer = +let install_finalizer_seq server_public_finalizer server_private_finalizer + finalizer_rpc_process = let open Lwt_syntax in Lwt_exit.register_clean_up_callback ~loc:__LOC__ @@ fun exit_status -> let* () = Events.shutdown_node ~exit_status in let* () = server_public_finalizer () in let* () = server_private_finalizer () in + let* () = Option.iter_s (fun f -> f ()) finalizer_rpc_process in Misc.unwrap_error_monad @@ fun () -> let open Lwt_result_syntax in let* () = Tx_pool.shutdown () in @@ -203,8 +205,30 @@ let main ~data_dir ?(genesis_timestamp = Misc.now ()) ~cctxt configuration (backend, smart_rollup_address_typed) in + let finalizer_rpc_process = + Option.map + (fun port -> + let protected_endpoint = + Uri.make ~scheme:"http" ~host:configuration.public_rpc.addr ~port () + in + let private_endpoint = + Option.map + (fun {addr; port; _} -> Uri.make ~scheme:"http" ~host:addr ~port ()) + configuration.private_rpc + in + Rpc.spawn_main + ~exposed_port:configuration.public_rpc.port + ~protected_endpoint + ?private_endpoint + ~data_dir + ()) + configuration.experimental_features.spawn_rpc + in let (_ : Lwt_exit.clean_up_callback_id) = - install_finalizer_seq finalizer_public_server finalizer_private_server + install_finalizer_seq + finalizer_public_server + finalizer_private_server + finalizer_rpc_process in let* () = loop_sequencer sequencer_config in return_unit diff --git a/etherlink/tezt/lib/evm_node.ml b/etherlink/tezt/lib/evm_node.ml index 96fc7ac712beef87e45d593aea06ae53f85f1f32..80ce7706a4c1a59dae734c6167871bbd38143fce 100644 --- a/etherlink/tezt/lib/evm_node.ml +++ b/etherlink/tezt/lib/evm_node.ml @@ -423,6 +423,10 @@ let wait_for_successful_upgrade ?timeout evm_node = let level = json |-> "level" |> as_int in Some (root_hash, level)) +let wait_for_spawn_rpc_ready ?timeout evm_node = + wait_for_event ?timeout evm_node ~event:"spawn_rpc_is_ready.v0" + @@ Fun.const (Some ()) + let wait_for_block_producer_locked ?timeout evm_node = wait_for_event ?timeout evm_node ~event:"block_producer_locked.v0" @@ Fun.const (Some ()) @@ -1265,7 +1269,7 @@ let patch_config_with_experimental_feature ?(drop_duplicate_when_injection = false) ?(blueprints_publisher_order_enabled = false) ?(next_wasm_runtime = true) ?rpc_server ?(enable_websocket = false) ?max_websocket_message_length - ?(enable_tx_queue = false) () = + ?(enable_tx_queue = false) ?spawn_rpc () = JSON.update "experimental_features" @@ fun json -> conditional_json_put drop_duplicate_when_injection @@ -1295,6 +1299,8 @@ let patch_config_with_experimental_feature enable_websocket ~name:"monitor_websocket_heartbeat" (`O [("ping_interval", `Float 0.5); ("ping_timeout", `Float 2.)]) + |> optional_json_put spawn_rpc ~name:"spawn_rpc" (fun port -> + `O [("protected_port", `Float (float_of_int port))]) let patch_config_gc ?history_mode json = json diff --git a/etherlink/tezt/lib/evm_node.mli b/etherlink/tezt/lib/evm_node.mli index db0ac37eab451aed54ea83f5d8d9a6ed28d54ae9..3087942eebcaa0c6ee16c3f014dcd724da702d14 100644 --- a/etherlink/tezt/lib/evm_node.mli +++ b/etherlink/tezt/lib/evm_node.mli @@ -233,6 +233,8 @@ val wait_for_pending_upgrade : ?timeout:float -> t -> (string * string) Lwt.t val wait_for_successful_upgrade : ?timeout:float -> t -> (string * int) Lwt.t +val wait_for_spawn_rpc_ready : ?timeout:float -> t -> unit Lwt.t + val wait_for_block_producer_locked : ?timeout:float -> t -> unit Lwt.t val wait_for_block_producer_tx_injected : ?timeout:float -> t -> string Lwt.t @@ -310,6 +312,7 @@ val patch_config_with_experimental_feature : ?enable_websocket:bool -> ?max_websocket_message_length:int -> ?enable_tx_queue:bool -> + ?spawn_rpc:int -> unit -> JSON.t -> JSON.t diff --git a/etherlink/tezt/lib/setup.ml b/etherlink/tezt/lib/setup.ml index 8a4561ef8254aa6c257746955068a0c14fa21bd5..0c0c23a6ef0b69d8dee4b9a5ef76b744cf0745ec 100644 --- a/etherlink/tezt/lib/setup.ml +++ b/etherlink/tezt/lib/setup.ml @@ -205,7 +205,7 @@ let setup_sequencer ?max_delayed_inbox_blueprint_length ?next_wasm_runtime ?(drop_duplicate_when_injection = true) ?(blueprints_publisher_order_enabled = true) ?rollup_history_mode ~enable_dal ?dal_slots ~enable_multichain ?rpc_server ?websockets - ?history_mode ?enable_tx_queue protocol = + ?history_mode ?enable_tx_queue ?spawn_rpc protocol = let* node, client = setup_l1 ?commitment_period @@ -285,18 +285,28 @@ let setup_sequencer ?max_delayed_inbox_blueprint_length ?next_wasm_runtime | Some p -> Some p | None -> Some (Port.fresh ()) in - let patch_config ?enable_tx_queue = + let seq_patch_config = Evm_node.patch_config_with_experimental_feature ~drop_duplicate_when_injection ~blueprints_publisher_order_enabled ?next_wasm_runtime ?rpc_server ?enable_websocket:websockets - ?enable_tx_queue + ?spawn_rpc (* When adding new experimental feature please make sure it's a good idea to activate it for all test or not. *) () in + let obs_patch_config = + Evm_node.patch_config_with_experimental_feature + ~drop_duplicate_when_injection + ~blueprints_publisher_order_enabled + ?next_wasm_runtime + ?rpc_server + ?enable_websocket:websockets + ?enable_tx_queue + () + in let* sequencer_mode = if threshold_encryption then let sequencer_sidecar = Dsn_node.sequencer () in @@ -347,14 +357,19 @@ let setup_sequencer ?max_delayed_inbox_blueprint_length ?next_wasm_runtime let* sequencer = Evm_node.init ?rpc_port:sequencer_rpc_port - ~patch_config:(patch_config ~enable_tx_queue:false) + ~patch_config:seq_patch_config ~mode:sequencer_mode ?history_mode (Sc_rollup_node.endpoint sc_rollup_node) in + let* _ = + match spawn_rpc with + | Some _ -> Evm_node.wait_for_spawn_rpc_ready sequencer + | None -> unit + in let* observer = run_new_observer_node - ~patch_config:(patch_config ?enable_tx_queue) + ~patch_config:obs_patch_config ~sc_rollup_node ?rpc_server ?websockets @@ -363,7 +378,7 @@ let setup_sequencer ?max_delayed_inbox_blueprint_length ?next_wasm_runtime in let* proxy = Evm_node.init - ~patch_config + ~patch_config:obs_patch_config ~mode:Proxy (Sc_rollup_node.endpoint sc_rollup_node) in @@ -397,7 +412,7 @@ let register_test ~__FILE__ ?max_delayed_inbox_blueprint_length ?rollup_history_mode ~enable_dal ?(dal_slots = if enable_dal then Some [0; 1; 2; 3] else None) ~enable_multichain ?rpc_server ?websockets ?history_mode ?enable_tx_queue - body ~title ~tags protocols = + ?spawn_rpc body ~title ~tags protocols = let kernel_tag, kernel_use = Kernel.to_uses_and_tags kernel in let tags = kernel_tag :: tags in let additional_uses = @@ -451,6 +466,7 @@ let register_test ~__FILE__ ?max_delayed_inbox_blueprint_length ~enable_multichain ?rpc_server ?enable_tx_queue + ?spawn_rpc protocol in body sequencer_setup protocol @@ -495,7 +511,7 @@ let register_test_for_kernels ~__FILE__ ?max_delayed_inbox_blueprint_length ?enable_fa_bridge ?rollup_history_mode ?commitment_period ?challenge_window ?additional_uses ~threshold_encryption ~enable_dal ?dal_slots ~enable_multichain ?rpc_server ?websockets ?enable_fast_withdrawal - ?history_mode ?enable_tx_queue ~title ~tags body protocols = + ?history_mode ?enable_tx_queue ?spawn_rpc ~title ~tags body protocols = List.iter (fun kernel -> register_test @@ -536,6 +552,7 @@ let register_test_for_kernels ~__FILE__ ?max_delayed_inbox_blueprint_length ?dal_slots ~enable_multichain ?enable_tx_queue + ?spawn_rpc ~title ~tags body diff --git a/etherlink/tezt/lib/setup.mli b/etherlink/tezt/lib/setup.mli index ad781ef2d086ca1bc76015d1c87c6567cb1c14ee..06fd1a10cd77f3bfd177b967d54b325fc2eb2830 100644 --- a/etherlink/tezt/lib/setup.mli +++ b/etherlink/tezt/lib/setup.mli @@ -96,6 +96,7 @@ val register_test : ?websockets:bool -> ?history_mode:Evm_node.history_mode -> ?enable_tx_queue:bool -> + ?spawn_rpc:int -> (sequencer_setup -> Protocol.t -> unit Lwt.t) -> title:string -> tags:string list -> @@ -143,6 +144,7 @@ val register_test_for_kernels : ?enable_fast_withdrawal:bool -> ?history_mode:Evm_node.history_mode -> ?enable_tx_queue:bool -> + ?spawn_rpc:int -> title:string -> tags:string list -> (sequencer_setup -> Protocol.t -> unit Lwt.t) -> @@ -189,5 +191,6 @@ val setup_sequencer : ?websockets:bool -> ?history_mode:Evm_node.history_mode -> ?enable_tx_queue:bool -> + ?spawn_rpc:int -> Protocol.t -> sequencer_setup Lwt.t diff --git a/etherlink/tezt/tests/evm_sequencer.ml b/etherlink/tezt/tests/evm_sequencer.ml index 6ba43aa16fbc7554ffc8ebdd973519399b12a89d..5ee24db372c74bf1c18917253a24feffd2fdc27b 100644 --- a/etherlink/tezt/tests/evm_sequencer.ml +++ b/etherlink/tezt/tests/evm_sequencer.ml @@ -252,8 +252,8 @@ let register_all ?max_delayed_inbox_blueprint_length ?sequencer_rpc_port ?websockets ?enable_fast_withdrawal ?history_mode ?(use_threshold_encryption = default_threshold_encryption_registration) ?(use_dal = default_dal_registration) - ?(use_multichain = default_multichain_registration) ?enable_tx_queue ~title - ~tags body protocols = + ?(use_multichain = default_multichain_registration) ?enable_tx_queue + ?spawn_rpc ~title ~tags body protocols = let dal_cases = match use_dal with | Register_both {extra_tags_with; extra_tags_without} -> @@ -320,6 +320,7 @@ let register_all ?max_delayed_inbox_blueprint_length ?sequencer_rpc_port ~enable_dal ~enable_multichain ?enable_tx_queue + ?spawn_rpc ~title ~tags:(te_tags @ dal_tags @ multichain_tags @ tags) body @@ -10295,6 +10296,38 @@ let test_tx_queue = ~error_msg:"Expected %r transaction injected found %l.") ; unit +let test_spawn_rpc = + let fresh_port = Port.fresh () in + register_all + ~spawn_rpc:fresh_port + ~tags:["sequencer"; "spawn"; "rpc"] + ~title: + "The spawned RPC successfully functions as an intermediate node for \ + public requests" + @@ fun {sequencer; observer; _} _protocol -> + Log.info "experimental_features.spawn_rpc = %d" fresh_port ; + let* raw_tx = + Cast.craft_tx + ~source_private_key:Eth_account.bootstrap_accounts.(0).private_key + ~chain_id:1337 + ~nonce:0 + ~gas_price:1_000_000_000 + ~gas:300_000 + ~value:Wei.zero + ~address:Eth_account.bootstrap_accounts.(1).address + () + in + let*@ transaction_hash = Rpc.send_raw_transaction ~raw_tx sequencer in + let*@ size = Rpc.produce_block sequencer in + Check.((size = 1) int) ~error_msg:"block size sould be 1" ; + let* () = Evm_node.wait_for_blueprint_applied sequencer 1 in + let* () = Evm_node.wait_for_blueprint_applied observer 1 in + let*@ _seq_block = Rpc.get_block_by_number ~block:"1" sequencer in + let*@ _obs_block = Rpc.get_block_by_number ~block:"1" observer in + let*@ tx_obj = Rpc.get_transaction_by_hash ~transaction_hash sequencer in + Check.is_true (Option.is_some tx_obj) ~error_msg:"tx is missing" ; + unit + let protocols = Protocol.all let () = @@ -10439,4 +10472,5 @@ let () = test_eip2930_transaction_object [Alpha] ; test_eip1559_transaction_object [Alpha] ; test_apply_from_full_history_mode protocols ; - test_tx_queue [Alpha] + test_tx_queue [Alpha] ; + test_spawn_rpc protocols diff --git a/etherlink/tezt/tests/expected/evm_rollup.ml/EVM node- list events regression.out b/etherlink/tezt/tests/expected/evm_rollup.ml/EVM node- list events regression.out index b18c8859d9373085b5d6831bf502a46d6ae70353..21bf038be9918a63323d6d7089faafa23fc3fec8 100644 --- a/etherlink/tezt/tests/expected/evm_rollup.ml/EVM node- list events regression.out +++ b/etherlink/tezt/tests/expected/evm_rollup.ml/EVM node- list events regression.out @@ -1819,6 +1819,14 @@ private_server_is_ready: contain invalid byte sequences. */ string || { "invalid_utf8_string": [ integer ∈ [0, 255] ... ] } +spawn_rpc_is_ready: + description: the rpc process is ready + level: notice + section: evm_node.dev + json format: + { /* spawn_rpc_is_ready version 0 */ + "spawn_rpc_is_ready.v0": any } + legacy_mode: description: node is using the (deprecated) legacy block storage, import a recent snapshot to start using the new block storage level: warning diff --git a/etherlink/tezt/tests/expected/evm_sequencer.ml/Alpha- Configuration RPC.out b/etherlink/tezt/tests/expected/evm_sequencer.ml/Alpha- Configuration RPC.out index 9886e1b094cbd5749999f694de76b281c90f1570..efd8cdd8f8432033afbe3e51e6220b96e282f4b1 100644 --- a/etherlink/tezt/tests/expected/evm_sequencer.ml/Alpha- Configuration RPC.out +++ b/etherlink/tezt/tests/expected/evm_sequencer.ml/Alpha- Configuration RPC.out @@ -22,6 +22,7 @@ "ping_interval": 5, "ping_timeout": 30 }, + "spawn_rpc": null, "l2_chains": null, "enable_tx_queue": false }, @@ -81,6 +82,7 @@ "ping_interval": 5, "ping_timeout": 30 }, + "spawn_rpc": null, "l2_chains": null, "enable_tx_queue": false }, @@ -133,6 +135,7 @@ "ping_interval": 5, "ping_timeout": 30 }, + "spawn_rpc": null, "l2_chains": null, "enable_tx_queue": false }, diff --git a/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- describe config.out b/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- describe config.out index 8f81bba32ff748c2d9e5cbe2c16e086ad827d503..8ba82f7218c880039a4d2e679256ea359585d747 100644 --- a/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- describe config.out +++ b/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- describe config.out @@ -162,6 +162,12 @@ number /* Timeout in seconds after which the connection will be considered dead and closed. */ }, + "spawn_rpc"?: + /* Spawn a RPC node listening on the given port */ + { /* Some */ + "protected_port": integer ∈ [1, 2^16-1] } + || null + /* None */, "l2_chains"?: /* Configuration of l2_chains for multisequencing. If not set, the node will adopt a single chain