From a8702c698b636961fd5bef3ed15f4de78abfc270 Mon Sep 17 00:00:00 2001 From: Thomas Letan Date: Tue, 15 Jul 2025 18:17:20 +0200 Subject: [PATCH] EVM Node: Support signing and applying blueprints concurrently MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * What This patch refactors the blueprint application logic within the EVM node. Since we now longer forward signed blueprint chunks to the kernel, it becomes possible to concurrently sign and apply a given blueprint. That is, the signing and payload creation now happen in parallel to the state transition. * Why The previous implementation required the blueprint to be fully prepared and signed before it could be applied to the EVM state. This created a bottleneck, as state application had to wait for cryptographic operations to complete. By passing the unsigned chunks directly to the application function, the EVM state transition can begin immediately, while the signing process runs concurrently. This change is intended to reduce block production latency, especially in setups where keys are held by a KMS. * How The `Evm_context.apply_blueprint` function has now a new `apply_chunks` companion function. This function takes a list of unsigned_chunk and a signer. Internally, the `Evm_context` ensures the applying and signing of the chunks are done concurrently. The block producer is updated to call this function. The `Apply_blueprint` worker request has been updated to carry the unsigned chunks separately from the payload promise. Consequently, the signature verification logic within `apply_blueprint_store_unsafe` has been moved, as the function now receives trusted, unsigned chunks. The signature check is now done in the `Evm_context.apply_blueprint` top-level function (outside of the worker) Besides, both `apply_blueprint` and `apply_chunks` now preemptively check that the sequencer behind the submitted blueprint is the expected one. The former is checking the signature using its current state, while the latter trusts the sequencer declared by its caller (the block producer). In both cases, the case where a sequencer upgrade is pending is taken into account. For `apply_chunks` to work, the `Patch_state` worker request has been updated to propagate its changes to the `head_info` global reference. Otherwise, the first block created by the sandbox on a non-empty state would be refused due to a mismatch in sequencer identity (as the `head_info` reference would still contain the EVM state initialized at load time, prior to the sequencer overwrite). Finally, the new workflow required some clean-up. The `blueprint_proposal` event has been removed as it no longer corresponds to a distinct step in the production flow. The `smart_rollup_address` field of the `Block_producer` worker is dropped because the `Evm_context` worker is now the component producing the blueprint payloads. Co-authored-by: Raphaël Cauderlier --- etherlink/bin_node/lib_dev/block_producer.ml | 50 ++--- etherlink/bin_node/lib_dev/block_producer.mli | 1 - .../bin_node/lib_dev/blueprint_events.ml | 13 -- .../bin_node/lib_dev/blueprint_events.mli | 5 - etherlink/bin_node/lib_dev/evm_context.ml | 179 +++++++++++++----- etherlink/bin_node/lib_dev/evm_context.mli | 15 ++ .../bin_node/lib_dev/evm_context_types.ml | 15 +- etherlink/bin_node/lib_dev/evm_state.mli | 10 +- etherlink/bin_node/lib_dev/sequencer.ml | 1 - .../bin_node/lib_dev/sequencer_blueprint.ml | 24 ++- .../bin_node/lib_dev/sequencer_blueprint.mli | 2 + .../EVM node- list events regression.out | 29 +-- 12 files changed, 206 insertions(+), 138 deletions(-) diff --git a/etherlink/bin_node/lib_dev/block_producer.ml b/etherlink/bin_node/lib_dev/block_producer.ml index 6139ae81f185..e624e4386de7 100644 --- a/etherlink/bin_node/lib_dev/block_producer.ml +++ b/etherlink/bin_node/lib_dev/block_producer.ml @@ -7,7 +7,6 @@ type parameters = { signer : Signer.t; - smart_rollup_address : string; maximum_number_of_chunks : int; tx_container : Services_backend_sig.ex_tx_container; sequencer_sunset_sec : int64; @@ -63,7 +62,6 @@ module Types = struct type state = { signer : Signer.t; - smart_rollup_address : string; maximum_number_of_chunks : int; tx_container : Services_backend_sig.ex_tx_container; sequencer_sunset_sec : int64; @@ -141,8 +139,8 @@ let take_delayed_transactions maximum_number_of_chunks = in return (delayed_transactions, remaining_cumulative_size) -let produce_block_with_transactions ~signer ~timestamp ~smart_rollup_address - ~transactions_and_objects ~delayed_hashes ~hash_of_tx_object head_info = +let produce_block_with_transactions ~signer ~timestamp ~transactions_and_objects + ~delayed_hashes ~hash_of_tx_object head_info = let open Lwt_result_syntax in let transactions, tx_hashes = List.to_seq transactions_and_objects @@ -154,27 +152,15 @@ let produce_block_with_transactions ~signer ~timestamp ~smart_rollup_address (Blueprint_events.blueprint_production head_info.Evm_context.next_blueprint_number) @@ fun () -> - let* blueprint_chunks = - Misc.with_timing - (Blueprint_events.blueprint_proposal - head_info.Evm_context.next_blueprint_number) - @@ fun () -> - let chunks = - Sequencer_blueprint.make_blueprint_chunks - ~number:head_info.next_blueprint_number - { - parent_hash = head_info.current_block_hash; - delayed_transactions = delayed_hashes; - transactions; - timestamp; - } - in - Sequencer_blueprint.sign ~signer ~chunks - in - let blueprint_payload = - Sequencer_blueprint.create_inbox_payload - ~smart_rollup_address - ~chunks:blueprint_chunks + let chunks = + Sequencer_blueprint.make_blueprint_chunks + ~number:head_info.next_blueprint_number + { + parent_hash = head_info.current_block_hash; + delayed_transactions = delayed_hashes; + transactions; + timestamp; + } in (* Resolve the content of delayed transactions. *) let* delayed_transactions = @@ -183,15 +169,15 @@ let produce_block_with_transactions ~signer ~timestamp ~smart_rollup_address Evm_state.get_delayed_inbox_item head_info.evm_state delayed_hash) delayed_hashes in - let* confirmed_txs = - Evm_context.apply_blueprint timestamp blueprint_payload delayed_transactions + let* blueprint_chunks, payload, confirmed_txs = + Evm_context.apply_chunks ~signer timestamp chunks delayed_transactions in let (Qty number) = head_info.next_blueprint_number in let* () = Blueprints_publisher.publish number (Blueprints_publisher_types.Request.Blueprint - {chunks = blueprint_chunks; inbox_payload = blueprint_payload}) + {chunks = blueprint_chunks; inbox_payload = payload}) in let*! () = List.iter_p @@ -323,8 +309,8 @@ let pop_valid_tx (type f) ~(tx_container : f Services_backend_sig.tx_container) (** Produces a block if we find at least one valid transaction in the transaction pool or if [force] is true. *) -let produce_block_if_needed (type f) ~signer ~smart_rollup_address ~force - ~timestamp ~delayed_hashes ~remaining_cumulative_size +let produce_block_if_needed (type f) ~signer ~force ~timestamp ~delayed_hashes + ~remaining_cumulative_size ~(tx_container : f Services_backend_sig.tx_container) head_info = let open Lwt_result_syntax in let* transactions_and_objects = @@ -344,7 +330,6 @@ let produce_block_if_needed (type f) ~signer ~smart_rollup_address ~force produce_block_with_transactions ~signer ~timestamp - ~smart_rollup_address ~transactions_and_objects:(Some transactions_and_objects) ~delayed_hashes ~tx_container @@ -421,7 +406,6 @@ let produce_block (type f) (state : Types.state) ~force ~timestamp produce_block_with_transactions ~signer:state.signer ~timestamp - ~smart_rollup_address:state.smart_rollup_address ~transactions_and_objects:None ~delayed_hashes:[] ~tx_container @@ -433,7 +417,6 @@ let produce_block (type f) (state : Types.state) ~force ~timestamp produce_block_if_needed ~signer:state.signer ~timestamp - ~smart_rollup_address:state.smart_rollup_address ~force ~delayed_hashes ~remaining_cumulative_size @@ -462,7 +445,6 @@ module Handlers = struct { sunset = false; signer = parameters.signer; - smart_rollup_address = parameters.smart_rollup_address; maximum_number_of_chunks = parameters.maximum_number_of_chunks; tx_container = parameters.tx_container; sequencer_sunset_sec = parameters.sequencer_sunset_sec; diff --git a/etherlink/bin_node/lib_dev/block_producer.mli b/etherlink/bin_node/lib_dev/block_producer.mli index e6a81acc88d5..23847021b778 100644 --- a/etherlink/bin_node/lib_dev/block_producer.mli +++ b/etherlink/bin_node/lib_dev/block_producer.mli @@ -7,7 +7,6 @@ type parameters = { signer : Signer.t; - smart_rollup_address : string; maximum_number_of_chunks : int; tx_container : Services_backend_sig.ex_tx_container; sequencer_sunset_sec : int64; diff --git a/etherlink/bin_node/lib_dev/blueprint_events.ml b/etherlink/bin_node/lib_dev/blueprint_events.ml index 1382e921a2a9..871d00b2a074 100644 --- a/etherlink/bin_node/lib_dev/blueprint_events.ml +++ b/etherlink/bin_node/lib_dev/blueprint_events.ml @@ -109,16 +109,6 @@ let blueprint_catchup = ("min", Data_encoding.n) ("max", Data_encoding.n) -let blueprint_proposal = - declare_2 - ~section - ~name:"blueprint_proposal" - ~msg:"crafted a blueprint proposal for level {level} in {process_time}" - ~level:Debug - ~pp2:Ptime.Span.pp - ("level", Data_encoding.n) - ("process_time", Time.System.Span.encoding) - let blueprint_production = declare_2 ~section @@ -241,9 +231,6 @@ let missing_blueprints count Ethereum_types.(Qty from) Ethereum_types.(Qty to_) = emit missing_blueprints (count, from, to_) -let blueprint_proposal Ethereum_types.(Qty level) time = - emit blueprint_proposal (level, time) - let blueprint_production Ethereum_types.(Qty level) time = emit blueprint_production (level, time) diff --git a/etherlink/bin_node/lib_dev/blueprint_events.mli b/etherlink/bin_node/lib_dev/blueprint_events.mli index 9cfa59984f32..eb3fec220482 100644 --- a/etherlink/bin_node/lib_dev/blueprint_events.mli +++ b/etherlink/bin_node/lib_dev/blueprint_events.mli @@ -69,11 +69,6 @@ val missing_blueprints : blueprints from level [min] to [max] because the rollup node is lagging. *) val catching_up : Z.t -> Z.t -> unit Lwt.t -(** [blueprint_proposal level duration] advertizes the sequencer has crafted a - blueprint for [level] in [duration] time. *) -val blueprint_proposal : - Ethereum_types.quantity -> Time.System.Span.t -> unit Lwt.t - (** [blueprint_production level duration] advertizes the sequencer has fully produced a blueprint for [level] in [duration] time. *) val blueprint_production : diff --git a/etherlink/bin_node/lib_dev/evm_context.ml b/etherlink/bin_node/lib_dev/evm_context.ml index 678b380385dc..2bd17eb9482f 100644 --- a/etherlink/bin_node/lib_dev/evm_context.ml +++ b/etherlink/bin_node/lib_dev/evm_context.ml @@ -792,15 +792,14 @@ module State = struct {l1_level; start_l2_level; end_l2_level} ; return_unit - (** [apply_blueprint_store_unsafe ctxt payload delayed_transactions] applies - the blueprint [payload] on the head of [ctxt], and commit the resulting - state to Irmin and the node’s store. - - However, it does not modifies [ctxt] to make it aware of the new state. - This is because [apply_blueprint_store_unsafe] is expected to be called - within a SQL transaction to make sure the node’s store is not left in an - inconsistent state in case of error. *) - let apply_blueprint_store_unsafe ctxt conn timestamp payload + (** [apply_blueprint_store_unsafe ctxt conn timestamp chunks payload + delayed_transactions] applies the blueprint [chunks] on the head of + [ctxt], and commit the resulting state and the blueprint signed [payload] + (when the promise is fulfilled) to Irmin and the node’s store. + + This function expects its connection to the store [conn] to be wrapped in + a SQL transaction. *) + let apply_blueprint_store_unsafe ctxt conn timestamp chunks payload delayed_transactions = let open Lwt_result_syntax in Evm_store.assert_in_transaction conn ; @@ -868,16 +867,6 @@ module State = struct ctxt.session.next_blueprint_number in - let* sequencer = Durable_storage.sequencer (read_from_state evm_state) in - let*? chunks = - List.map_e - (fun chunk -> - let open Result_syntax in - let* chunk = Sequencer_blueprint.chunk_of_external_message chunk in - Sequencer_blueprint.check_signature sequencer chunk) - payload - in - let* try_apply = Misc.with_timing (fun time -> Lwt.return (time_processed := time)) @@ -963,6 +952,7 @@ module State = struct (* TODO: https://gitlab.com/tezos/tezos/-/issues/7866 *) () in + let* payload in let* () = Evm_store.Blueprints.store conn @@ -1090,6 +1080,14 @@ module State = struct Evm_events.Flushed_blueprint. {transactions; timestamp; level = flushed_level} = let open Lwt_result_syntax in + let sign ~signer chunks = + let+ blueprint_chunks = Sequencer_blueprint.sign ~signer ~chunks in + Sequencer_blueprint.create_inbox_payload + ~smart_rollup_address: + (Tezos_crypto.Hashed.Smart_rollup_address.to_string + ctxt.smart_rollup_address) + ~chunks:blueprint_chunks + in let hashes = List.map (fun tx -> tx.Evm_events.Delayed_transaction.hash) transactions in @@ -1109,15 +1107,8 @@ module State = struct timestamp; } in - let* blueprint_chunks = Sequencer_blueprint.sign ~signer ~chunks in - let payload = - Sequencer_blueprint.create_inbox_payload - ~smart_rollup_address: - (Tezos_crypto.Hashed.Smart_rollup_address.to_string - ctxt.smart_rollup_address) - ~chunks:blueprint_chunks - in - return payload + + return (chunks, sign ~signer chunks) let clear_head_delayed_inbox ctxt = let open Lwt_result_syntax in @@ -1127,7 +1118,7 @@ module State = struct ctxt.session.evm_state <- cleaned_evm_state ; return_unit - let rec apply_blueprint ?(events = []) ctxt conn timestamp payload + let rec apply_blueprint ?(events = []) ctxt conn timestamp chunks payload delayed_transactions : 'a L2_types.block tzresult Lwt.t = let open Lwt_result_syntax in let+ current_block, _execution_gas = @@ -1146,6 +1137,7 @@ module State = struct ctxt conn timestamp + chunks payload delayed_transactions in @@ -1165,6 +1157,8 @@ module State = struct | _ -> None in + let* payload in + let* current_block = match current_block with | Eth block -> @@ -1411,12 +1405,19 @@ module State = struct let* parent_hash = Evm_state.current_block_hash ~chain_family ctxt.session.evm_state in - let* payload = + let* chunks, payload = prepare_local_flushed_blueprint ctxt parent_hash flushed_blueprint in (* Apply the blueprint. *) let* _block = - apply_blueprint ~events ctxt conn timestamp payload delayed_transactions + apply_blueprint + ~events + ctxt + conn + timestamp + chunks + payload + delayed_transactions in return ctxt.session.evm_state @@ -1839,14 +1840,13 @@ module State = struct let perform_commit = commit - let patch_state (ctxt : t) ?block_number ~commit ~key patch () = + let patch_state (ctxt : t) conn ?block_number ~commit ~key patch () = let open Lwt_result_syntax in let block_number = canonical_block_number ctxt block_number in let* evm_state = match block_number with | None -> return ctxt.session.evm_state | Some block_number -> ( - Evm_store.use ctxt.store @@ fun conn -> let* hash = Evm_store.Context_hashes.find conn block_number in match hash with | Some hash -> @@ -1872,7 +1872,6 @@ module State = struct match block_number with | None -> if commit then ( - Evm_store.use ctxt.store @@ fun conn -> let* commit = replace_current_commit ctxt conn evm_state in on_modified_head ctxt evm_state commit ; return (current_blueprint_number ctxt)) @@ -1881,7 +1880,6 @@ module State = struct return (current_blueprint_number ctxt)) | Some block_number -> if commit then ( - Evm_store.use ctxt.store @@ fun conn -> let* context = perform_commit conn ctxt.session.context evm_state block_number in @@ -1910,13 +1908,27 @@ module State = struct let events = Blueprint_types.events_of_blueprint_with_events blueprint_with_events in + let* sequencer = + Durable_storage.sequencer (read_from_state ctxt.session.evm_state) + in + let*? chunks = + List.map_e + (fun chunk -> + let open Result_syntax in + let* chunk = + Sequencer_blueprint.chunk_of_external_message chunk + in + Sequencer_blueprint.check_signature sequencer chunk) + blueprint_with_events.blueprint.payload + in let* _block = apply_blueprint ~events ctxt conn blueprint_with_events.blueprint.timestamp - blueprint_with_events.blueprint.payload + chunks + (return blueprint_with_events.blueprint.payload) blueprint_with_events.delayed_transactions in @@ -2097,7 +2109,8 @@ module Handlers = struct let ctxt = Worker.state self in State.Transaction.run ctxt @@ fun ctxt conn -> State.apply_evm_events ?finalized_level conn ctxt events - | Apply_blueprint {events; timestamp; payload; delayed_transactions} -> + | Apply_blueprint {events; timestamp; chunks; payload; delayed_transactions} + -> protect @@ fun () -> let ctxt = Worker.state self in State.Transaction.run ctxt @@ fun ctxt conn -> @@ -2107,6 +2120,7 @@ module Handlers = struct ctxt conn timestamp + chunks payload delayed_transactions in @@ -2134,7 +2148,8 @@ module Handlers = struct | Patch_state {commit; key; patch; block_number} -> protect @@ fun () -> let ctxt = Worker.state self in - State.patch_state ?block_number ctxt ~commit ~key patch () + State.Transaction.run ctxt @@ fun ctxt conn -> + State.patch_state ?block_number ctxt conn ~commit ~key patch () | Wasm_pvm_version -> protect @@ fun () -> let ctxt = Worker.state self in @@ -2252,6 +2267,11 @@ let return_ : (_, _ Worker.message_error) result -> _ = | Error (Request_error err) -> Lwt.return (Error err) | Error (Any exn) -> fail_with_exn exn +let smart_rollup_address () = + let open Lwt_result_syntax in + let*? w = Lazy.force worker in + return (Worker.state w).smart_rollup_address + let worker_wait_for_request req = let open Lwt_result_syntax in let*? w = Lazy.force worker in @@ -2477,19 +2497,90 @@ let init_from_rollup_node ~configuration ~omit_delayed_tx_events ~data_dir (Apply_evm_events {finalized_level = Some finalized_level; events = evm_events}) +let head_info () = + let open Lwt_syntax in + let+ head_info in + !head_info + let apply_blueprint ?events timestamp payload delayed_transactions = + let open Lwt_result_syntax in + let*! head = head_info () in + let* sequencer = + (* To guess the identity of the sequencer public key to use, we need to + cover the edge case were a bleuprint contains the sequencer upgrade that + needs to be triggered to get the correct sequencer. *) + let incoming_sequencer_upgrade = + List.find_map + (function + | Evm_events.Sequencer_upgrade_event upgrade -> Some upgrade + | _ -> None) + (Option.value ~default:[] events) + in + match + Option.either incoming_sequencer_upgrade head.pending_sequencer_upgrade + with + | Some {sequencer; timestamp = upgrade_timestamp; _} + when Time.Protocol.(timestamp >= upgrade_timestamp) -> + return sequencer + | _ -> Durable_storage.sequencer (State.read_from_state head.evm_state) + in + let*? chunks = + List.map_e + (fun chunk -> + let open Result_syntax in + let* chunk = Sequencer_blueprint.chunk_of_external_message chunk in + Sequencer_blueprint.check_signature sequencer chunk) + payload + in worker_wait_for_request - (Apply_blueprint {events; timestamp; payload; delayed_transactions}) + (Apply_blueprint + { + events; + timestamp; + chunks; + payload = return payload; + delayed_transactions; + }) + +let apply_chunks ~signer timestamp chunks delayed_transactions = + let open Lwt_result_syntax in + let blueprint_chunks = Sequencer_blueprint.sign ~signer ~chunks in + let payload = + let* blueprint_chunks in + let+ smart_rollup_address = smart_rollup_address () in + Sequencer_blueprint.create_inbox_payload + ~smart_rollup_address: + (Tezos_crypto.Hashed.Smart_rollup_address.to_string + smart_rollup_address) + ~chunks:blueprint_chunks + in + let* sequencer = Signer.public_key signer in + let*! head = head_info () in + let* expected_sequencer = + match head.pending_sequencer_upgrade with + | Some {sequencer; timestamp = upgrade_timestamp; _} + when Time.Protocol.(timestamp >= upgrade_timestamp) -> + return sequencer + | _ -> Durable_storage.sequencer (State.read_from_state head.evm_state) + in + if Signature.Public_key.(sequencer = expected_sequencer) then + let* confirmed_txs = + worker_wait_for_request + (Apply_blueprint + {events = None; timestamp; chunks; payload; delayed_transactions}) + and* blueprint_chunks + and* payload in + return (blueprint_chunks, payload, confirmed_txs) + else + failwith + "Cannot apply a blueprint produced by sequencer %a" + Signature.Public_key.pp + sequencer let apply_finalized_levels ~l1_level ~start_l2_level ~end_l2_level = worker_wait_for_request (Finalized_levels {l1_level; start_l2_level; end_l2_level}) -let head_info () = - let open Lwt_syntax in - let+ head_info in - !head_info - let next_blueprint_number () = let open Lwt_syntax in let+ head_info = head_info () in diff --git a/etherlink/bin_node/lib_dev/evm_context.mli b/etherlink/bin_node/lib_dev/evm_context.mli index 1bd6b758b37e..769971b0783c 100644 --- a/etherlink/bin_node/lib_dev/evm_context.mli +++ b/etherlink/bin_node/lib_dev/evm_context.mli @@ -95,6 +95,21 @@ val apply_blueprint : Evm_events.Delayed_transaction.t list -> Ethereum_types.hash Seq.t tzresult Lwt.t +(** [apply_chunks ~signer chunks delayed_transactions] works similarly to + {!apply_blueprint}, with the notable difference that it allows to start + applying the [chunks] of a blueprint {e before} their signatures (computed + by [signer]) are ready. *) +val apply_chunks : + signer:Signer.t -> + Time.Protocol.t -> + Sequencer_blueprint.unsigned_chunk list -> + Evm_events.Delayed_transaction.t list -> + (Sequencer_blueprint.t list + * Blueprint_types.payload + * Ethereum_types.hash Seq.t) + tzresult + Lwt.t + (** [apply_finalized_levels ~l1_level ~start_l2_level ~end_l2_level] stores the finalization relationship between L1 level [l1_level] and the L2 level range from [start_l2_level] to [end_l2_level]. It diff --git a/etherlink/bin_node/lib_dev/evm_context_types.ml b/etherlink/bin_node/lib_dev/evm_context_types.ml index 8dd5fadb3ae1..5ff6ec83627c 100644 --- a/etherlink/bin_node/lib_dev/evm_context_types.ml +++ b/etherlink/bin_node/lib_dev/evm_context_types.ml @@ -17,7 +17,8 @@ module Request = struct | Apply_blueprint : { events : Evm_events.t list option; timestamp : Time.Protocol.t; - payload : Blueprint_types.payload; + chunks : Sequencer_blueprint.unsigned_chunk list; + payload : Blueprint_types.payload tzresult Lwt.t; delayed_transactions : Evm_events.Delayed_transaction.t list; } -> (Ethereum_types.hash Seq.t, tztrace) t @@ -82,20 +83,18 @@ module Request = struct (req "request" (constant "apply_blueprint")) (opt "events" (list Evm_events.encoding)) (req "timestamp" Time.Protocol.encoding) - (req "payload" Blueprint_types.payload_encoding) + (req "chunks" (list Sequencer_blueprint.unsigned_chunk_encoding)) (req "delayed_transactions" (list Evm_events.Delayed_transaction.encoding))) (function | View (Apply_blueprint - {events; timestamp; payload; delayed_transactions}) -> - Some ((), events, timestamp, payload, delayed_transactions) + {events; timestamp; chunks; payload = _; delayed_transactions}) + -> + Some ((), events, timestamp, chunks, delayed_transactions) | _ -> None) - (fun ((), events, timestamp, payload, delayed_transactions) -> - View - (Apply_blueprint - {events; timestamp; payload; delayed_transactions})); + (fun _ -> assert false); case (Tag 2) ~title:"Last_known_L1_level" diff --git a/etherlink/bin_node/lib_dev/evm_state.mli b/etherlink/bin_node/lib_dev/evm_state.mli index 3bdea3d4ffb7..e8cc8a58064c 100644 --- a/etherlink/bin_node/lib_dev/evm_state.mli +++ b/etherlink/bin_node/lib_dev/evm_state.mli @@ -96,13 +96,13 @@ type apply_result = | Apply_failure (** [apply_unsigned_chunks ~data-dir ~config state chunks] applies the - blueprint [chunks] on top of [evm_state]. If the payload produces - a block, the new updated EVM state is returned along with the new - block’s height. + blueprint [chunks] on top of [evm_state]. If the operation results in the + production of a block, the new updated EVM state is returned along with the + new block’s height. {e It is the responsibility of the caller to ensure + the correctness of the chunks.} The [data-dir] is used to store the kernel logs in the - {!kernel_logs_directory}. -*) + {!kernel_logs_directory}. *) val apply_unsigned_chunks : ?wasm_pvm_fallback:bool -> ?log_file:string -> diff --git a/etherlink/bin_node/lib_dev/sequencer.ml b/etherlink/bin_node/lib_dev/sequencer.ml index c26d920c634a..77356d8e9c02 100644 --- a/etherlink/bin_node/lib_dev/sequencer.ml +++ b/etherlink/bin_node/lib_dev/sequencer.ml @@ -457,7 +457,6 @@ let main ~data_dir ~cctxt ?signer ?(genesis_timestamp = Misc.now ()) Block_producer.start { signer; - smart_rollup_address = smart_rollup_address_b58; maximum_number_of_chunks = sequencer_config.max_number_of_chunks; tx_container = Ex_tx_container tx_container; sequencer_sunset_sec = sequencer_config.sunset_sec; diff --git a/etherlink/bin_node/lib_dev/sequencer_blueprint.ml b/etherlink/bin_node/lib_dev/sequencer_blueprint.ml index dde1fd767baf..5e970274d9a2 100644 --- a/etherlink/bin_node/lib_dev/sequencer_blueprint.ml +++ b/etherlink/bin_node/lib_dev/sequencer_blueprint.ml @@ -96,20 +96,28 @@ type unsigned_chunk = { type t = {unsigned_chunk : unsigned_chunk; signature : Signature.t} -let chunk_encoding = +let unsigned_chunk_encoding = Data_encoding.( let bytes_hex = bytes' Hex in conv - (fun {unsigned_chunk = {value; number; nb_chunks; chunk_index}; signature} -> - (value, number, nb_chunks, chunk_index, signature)) - (fun (value, number, nb_chunks, chunk_index, signature) -> - {unsigned_chunk = {value; number; nb_chunks; chunk_index}; signature}) - (obj5 + (fun {value; number; nb_chunks; chunk_index} -> + (value, number, nb_chunks, chunk_index)) + (fun (value, number, nb_chunks, chunk_index) -> + {value; number; nb_chunks; chunk_index}) + (obj4 (req "value" bytes_hex) (req "number" quantity_encoding) (req "nb_chunks" int31) - (req "chunk_index" int31) - (req "signature" Signature.encoding))) + (req "chunk_index" int31))) + +let chunk_encoding = + Data_encoding.( + conv + (fun {unsigned_chunk; signature} -> (unsigned_chunk, signature)) + (fun (unsigned_chunk, signature) -> {unsigned_chunk; signature}) + (merge_objs + unsigned_chunk_encoding + (obj1 (req "signature" Signature.encoding)))) let unsigned_chunk_to_rlp {value; number; nb_chunks; chunk_index} = Rlp.( diff --git a/etherlink/bin_node/lib_dev/sequencer_blueprint.mli b/etherlink/bin_node/lib_dev/sequencer_blueprint.mli index 10f6400addb9..4fb4570d923d 100644 --- a/etherlink/bin_node/lib_dev/sequencer_blueprint.mli +++ b/etherlink/bin_node/lib_dev/sequencer_blueprint.mli @@ -26,6 +26,8 @@ val unsafe_drop_signature : t -> unsigned_chunk verification and just get the unsigned content. *) val check_signature : Signature.public_key -> t -> unsigned_chunk tzresult +val unsigned_chunk_encoding : unsigned_chunk Data_encoding.t + val chunk_encoding : t Data_encoding.t (** [chunk_to_rlp chunk] encodes a chunk into its RLP format. *) 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 296b3b268772..5c823144ee74 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 @@ -231,23 +231,6 @@ blueprint_production: /* A span of time, as seen by the local computer. */ number -blueprint_proposal: - description: crafted a blueprint proposal for level {level} in {process_time} - level: debug - section: evm_node.dev - json format: - { /* blueprint_proposal version 0 */ - "blueprint_proposal.v0": - { "level": $positive_bignum, - "process_time": $timespan.system } } - $positive_bignum: - /* Positive big number - Decimal representation of a positive big number */ - string - $timespan.system: - /* A span of time, as seen by the local computer. */ - number - blueprint_publisher_is_ready: description: blueprint publisher is ready level: info @@ -690,7 +673,11 @@ evm_context_request_failed: $timestamp.protocol, $positive_bignum ] } ... ], "timestamp": $timestamp.protocol, - "payload": [ /^([a-zA-Z0-9][a-zA-Z0-9])*$/ ... ], + "chunks": + [ { "value": /^([a-zA-Z0-9][a-zA-Z0-9])*$/, + "number": $unistring, + "nb_chunks": integer ∈ [-2^30, 2^30], + "chunk_index": integer ∈ [-2^30, 2^30] } ... ], "delayed_transactions": [ [ "transaction" || "deposit" || "fa_deposit", $unistring, @@ -2500,7 +2487,11 @@ evm_context_request_failed: $timestamp.protocol, $positive_bignum ] } ... ], "timestamp": $timestamp.protocol, - "payload": [ /^([a-zA-Z0-9][a-zA-Z0-9])*$/ ... ], + "chunks": + [ { "value": /^([a-zA-Z0-9][a-zA-Z0-9])*$/, + "number": $unistring, + "nb_chunks": integer ∈ [-2^30, 2^30], + "chunk_index": integer ∈ [-2^30, 2^30] } ... ], "delayed_transactions": [ [ "transaction" || "deposit" || "fa_deposit", $unistring, -- GitLab