From 473616b9db64985a3d3b3cb59d51b44151a70217 Mon Sep 17 00:00:00 2001 From: Thomas Plisson Date: Mon, 15 Dec 2025 15:03:06 +0100 Subject: [PATCH] L2 Node: Produce genesis request --- etherlink/bin_node/lib_dev/block_producer.ml | 62 +++++++++++++++---- etherlink/bin_node/lib_dev/block_producer.mli | 7 +++ etherlink/bin_node/lib_dev/sequencer.ml | 41 ++---------- 3 files changed, 63 insertions(+), 47 deletions(-) diff --git a/etherlink/bin_node/lib_dev/block_producer.ml b/etherlink/bin_node/lib_dev/block_producer.ml index a403852843f4..ba581fd7bbca 100644 --- a/etherlink/bin_node/lib_dev/block_producer.ml +++ b/etherlink/bin_node/lib_dev/block_producer.ml @@ -71,7 +71,7 @@ module Types = struct mutable selected_delayed_txns : Evm_events.Delayed_transaction.t list; mutable validated_txns : (string * Tx_queue_types.transaction_object_t) list; - mutable validation_state : Validation_types.validation_state; + mutable validation_state : Validation_types.validation_state option; mutable next_block_timestamp : Time.System.t option; } end @@ -90,6 +90,9 @@ end module Request = struct type ('a, 'b) t = + | Produce_genesis : + (Time.Protocol.t * Ethereum_types.block_hash) + -> (unit, tztrace) t | Produce_block : (bool * Time.Protocol.t * bool) -> ([`Block_produced of int | `No_block], tztrace) t @@ -98,6 +101,7 @@ module Request = struct -> (Ethereum_types.hash list, tztrace) t let name : type a b. (a, b) t -> string = function + | Produce_genesis _ -> "Produce_genesis" | Produce_block _ -> "Produce_block" | Preconfirm_transactions _ -> "Preconfirm_transactions" @@ -427,10 +431,7 @@ let clear_preconfirmation_data ~(state : Types.state) = let open Lwt_result_syntax in state.validated_txns <- [] ; state.selected_delayed_txns <- [] ; - let* validation_state = - init_validation_state ~tx_container:state.tx_container - in - state.validation_state <- validation_state ; + state.validation_state <- None ; return_unit (* [now] is the timestamp of the previously created block. @@ -448,6 +449,30 @@ let compute_next_block_timestamp ~now = in Time.System.(max now_plus now') +let produce_genesis ~(state : Types.state) ~timestamp ~parent_hash = + let open Lwt_result_syntax in + let delayed_transactions = [] in + let chunks = + Sequencer_blueprint.make_blueprint_chunks + ~number:Ethereum_types.(Qty Z.zero) + {parent_hash; delayed_transactions; transactions = []; timestamp} + in + let* genesis_chunks, genesis_payload, _ = + Evm_context.apply_chunks + ~signer:state.signer + timestamp + chunks + delayed_transactions + in + state.next_block_timestamp <- + Some + (compute_next_block_timestamp + ~now:(Time.System.of_protocol_exn timestamp)) ; + Blueprints_publisher.publish + Z.zero + (Blueprints_publisher_types.Request.Blueprint + {chunks = genesis_chunks; inbox_payload = genesis_payload}) + (* Required while the preconfirmation system and previous block production co-exist *) let choose_block_timestamp preconfirmation_stream_enabled next_block_timestamp external_timestamp = @@ -608,9 +633,14 @@ let preconfirm_transactions ~(state : Types.state) ~transactions ~timestamp = preconfirm_delayed_transactions ~state ~head_info in return (Int.sub maximum_cumulative_size remaining_cumulative_size)) - else return state.validation_state.current_size + else return 0 in - let input_validation_state = {state.validation_state with current_size} in + let* validation_state = + match state.validation_state with + | Some state -> return state + | None -> init_validation_state ~tx_container:state.tx_container + in + let input_validation_state = {validation_state with current_size} in let validate (validation_state, (rev_txns, rev_accepted_hashes)) ((raw, tx_object) as entry) = let* res, wrapped_raw, hash = @@ -652,7 +682,7 @@ let preconfirm_transactions ~(state : Types.state) ~transactions ~timestamp = List.fold_left_es validate (input_validation_state, ([], [])) transactions in state.validated_txns <- state.validated_txns @ List.rev rev_validated_txns ; - state.validation_state <- validation_state ; + state.validation_state <- Some validation_state ; return (List.rev rev_accepted_hashes) module Handlers = struct @@ -664,6 +694,8 @@ module Handlers = struct fun w request -> let state = Worker.state w in match request with + | Request.Produce_genesis (timestamp, parent_hash) -> + produce_genesis ~state ~timestamp ~parent_hash | Request.Produce_block (with_delayed_transactions, timestamp, force) -> protect @@ fun () -> produce_block state ~force ~timestamp ~with_delayed_transactions @@ -687,9 +719,7 @@ module Handlers = struct preconfirmation_stream_enabled; } : Types.parameters) = - let open Lwt_result_syntax in - let* validation_state = init_validation_state ~tx_container in - return + Lwt_result_syntax.return Types. { sunset = false; @@ -698,7 +728,7 @@ module Handlers = struct tx_container; sequencer_sunset_sec; preconfirmation_stream_enabled; - validation_state; + validation_state = None; selected_delayed_txns = []; validated_txns = []; next_block_timestamp = None; @@ -755,6 +785,14 @@ let shutdown () = let* () = Block_producer_events.shutdown () in Worker.shutdown w +let produce_genesis ~timestamp ~parent_hash = + let open Lwt_result_syntax in + let*? worker = Lazy.force worker in + Worker.Queue.push_request_and_wait + worker + (Request.Produce_genesis (timestamp, parent_hash)) + |> handle_request_error + let produce_block ~with_delayed_transactions ~force ~timestamp = let open Lwt_result_syntax in let*? worker = Lazy.force worker in diff --git a/etherlink/bin_node/lib_dev/block_producer.mli b/etherlink/bin_node/lib_dev/block_producer.mli index 9d2d3544cc29..9cadea9f4cd1 100644 --- a/etherlink/bin_node/lib_dev/block_producer.mli +++ b/etherlink/bin_node/lib_dev/block_producer.mli @@ -19,6 +19,13 @@ val start : parameters -> unit tzresult Lwt.t (** [shutdown ()] stops the events follower. *) val shutdown : unit -> unit Lwt.t +(** [produce_genesis ~timestamp ~parent_hash] creates the first empty block with + the provided timestamp and parent hash *) +val produce_genesis : + timestamp:Time.Protocol.t -> + parent_hash:Ethereum_types.block_hash -> + (unit, error trace) result Lwt.t + (** [produce_block ~force ~timestamp] takes the transactions in the tx pool and produces a block from it, returns the number of transaction in the block. The block is not produced if the list of diff --git a/etherlink/bin_node/lib_dev/sequencer.ml b/etherlink/bin_node/lib_dev/sequencer.ml index 884a0c7bc660..475f83f74a19 100644 --- a/etherlink/bin_node/lib_dev/sequencer.ml +++ b/etherlink/bin_node/lib_dev/sequencer.ml @@ -440,41 +440,6 @@ let main ~cctxt ?(genesis_timestamp = Misc.now ()) ~tx_container () in - let* () = - if status = Created then - (* Create the first empty block. *) - let chunks = - Sequencer_blueprint.make_blueprint_chunks - ~number:Ethereum_types.(Qty Z.zero) - { - parent_hash = L2_types.genesis_parent_hash ~chain_family; - delayed_transactions = []; - transactions = []; - timestamp = genesis_timestamp; - } - in - let* sequencer_pk = - Durable_storage.sequencer (fun path -> - let*! res = Evm_state.inspect head.evm_state path in - return res) - in - let*? signer = Signer.get_signer signer sequencer_pk in - let* genesis_chunks = Sequencer_blueprint.sign ~signer ~chunks in - let genesis_payload = - Sequencer_blueprint.create_inbox_payload - ~smart_rollup_address:smart_rollup_address_b58 - ~chunks:genesis_chunks - in - let* _tx_hashes = - Evm_context.apply_blueprint genesis_timestamp genesis_payload [] - in - Blueprints_publisher.publish - Z.zero - (Blueprints_publisher_types.Request.Blueprint - {chunks = genesis_chunks; inbox_payload = genesis_payload}) - else return_unit - in - let* enable_multichain = Evm_ro_context.read_enable_multichain_flag ro_ctxt in let* l2_chain_id, _chain_family = Rpc_backend.single_chain_id_and_family @@ -497,6 +462,12 @@ let main ~cctxt ?(genesis_timestamp = Misc.now ()) configuration.experimental_features.preconfirmation_stream_enabled; } in + let* () = + when_ (status = Created) @@ fun () -> + Block_producer.produce_genesis + ~timestamp:genesis_timestamp + ~parent_hash:(L2_types.genesis_parent_hash ~chain_family) + in let* () = if is_sandbox then let*! () = Events.sandbox_started (Z.pred next_blueprint_number) in -- GitLab