diff --git a/etherlink/bin_node/lib_dev/block_producer.ml b/etherlink/bin_node/lib_dev/block_producer.ml index 201d8b79a273432d529ddbf5901b41f4e1e1e189..bbacf13bb3c2e74cbb2fa6978cbfabf70f8bcac4 100644 --- a/etherlink/bin_node/lib_dev/block_producer.ml +++ b/etherlink/bin_node/lib_dev/block_producer.ml @@ -78,7 +78,9 @@ end module Request = struct type ('a, 'b) t = - | Produce_block : (bool * Time.Protocol.t * bool) -> (int, tztrace) t + | Produce_block : + (bool * Time.Protocol.t * bool) + -> ([`Block_produced of int | `No_block], tztrace) t type view = View : _ t -> view @@ -228,8 +230,8 @@ let produce_block_if_needed ~cctxt ~smart_rollup_address ~sequencer_key ~force ~confirmed_txs else Tx_pool.clear_popped_transactions () in - return n - else return 0 + return (`Block_produced n) + else return `No_block let head_info_and_delayed_transactions ~with_delayed_transactions maximum_number_of_chunks = @@ -257,7 +259,7 @@ let produce_block ~uses_tx_queue ~cctxt ~smart_rollup_address ~sequencer_key in if is_locked then let*! () = Block_producer_events.production_locked () in - return 0 + return `No_block else let* head_info, delayed_hashes, remaining_cumulative_size = head_info_and_delayed_transactions @@ -271,7 +273,7 @@ let produce_block ~uses_tx_queue ~cctxt ~smart_rollup_address ~sequencer_key | None -> false in if is_going_to_upgrade then - let* _hashes (* empty because no txs given *) = + let* hashes = produce_block_with_transactions ~sequencer_key ~cctxt @@ -281,7 +283,8 @@ let produce_block ~uses_tx_queue ~cctxt ~smart_rollup_address ~sequencer_key ~delayed_hashes:[] head_info in - return 0 + (* Is always be zero, only to be "future" proof *) + return (`Block_produced (Seq.length hashes)) else produce_block_if_needed ~cctxt diff --git a/etherlink/bin_node/lib_dev/block_producer.mli b/etherlink/bin_node/lib_dev/block_producer.mli index bca2b791d170e6fe9c142dc25e108d9f62935f2c..39ad2455b48a884fdee3ec9fffe207424c7b5434 100644 --- a/etherlink/bin_node/lib_dev/block_producer.mli +++ b/etherlink/bin_node/lib_dev/block_producer.mli @@ -24,12 +24,14 @@ val shutdown : unit -> unit Lwt.t transaction in the block. The block is not produced if the list of transactions is empty and [force] is set to [false].*) val produce_block : - force:bool -> timestamp:Time.Protocol.t -> int tzresult Lwt.t + force:bool -> + timestamp:Time.Protocol.t -> + [`Block_produced of int | `No_block] tzresult Lwt.t module Internal_for_tests : sig val produce_block : with_delayed_transactions:bool -> force:bool -> timestamp:Time.Protocol.t -> - int tzresult Lwt.t + [`Block_produced of int | `No_block] tzresult Lwt.t end diff --git a/etherlink/bin_node/lib_dev/sequencer.ml b/etherlink/bin_node/lib_dev/sequencer.ml index 363ea5beeec74824613c9bbe4e588756f3513d03..0410f23dc73353d6c25146d51f8ea5e872e33470 100644 --- a/etherlink/bin_node/lib_dev/sequencer.ml +++ b/etherlink/bin_node/lib_dev/sequencer.ml @@ -33,28 +33,29 @@ let install_finalizer_seq server_public_finalizer server_private_finalizer let loop_sequencer (sequencer_config : Configuration.sequencer) = let open Lwt_result_syntax in let time_between_blocks = sequencer_config.time_between_blocks in - let rec loop last_produced_block = - match time_between_blocks with - | Nothing -> - (* Bind on a never-resolved promise ensures this call never returns, - meaning no block will ever be produced. *) - let task, _resolver = Lwt.task () in - let*! () = task in - return_unit - | Time_between_blocks time_between_blocks -> + match time_between_blocks with + | Nothing -> + (* Bind on a never-resolved promise ensures this call never returns, + meaning no block will ever be produced. *) + let task, _resolver = Lwt.task () in + let*! () = task in + return_unit + | Time_between_blocks time_between_blocks -> + let rec loop last_produced_block = let now = Misc.now () in (* We force if the last produced block is older than [time_between_blocks]. *) let force = let diff = Time.Protocol.(diff now last_produced_block) in diff >= Int64.of_float time_between_blocks in - let* nb_transactions = + let* has_produced_block = Block_producer.produce_block ~force ~timestamp:now and* () = Lwt.map Result.ok @@ Lwt_unix.sleep 0.5 in - if nb_transactions > 0 || force then loop now - else loop last_produced_block - in - loop Misc.(now ()) + match has_produced_block with + | `Block_produced _nb_transactions -> loop now + | `No_block -> loop last_produced_block + in + loop Misc.(now ()) let main ~data_dir ?(genesis_timestamp = Misc.now ()) ~cctxt ~(configuration : Configuration.t) ?kernel ?sandbox_config () = diff --git a/etherlink/bin_node/lib_dev/services.ml b/etherlink/bin_node/lib_dev/services.ml index 9923fb2774f5c1c49b7c811b86df131500f7e9fb..fa51cd09d61b7be0e441e4a84810e5cf192a8045 100644 --- a/etherlink/bin_node/lib_dev/services.ml +++ b/etherlink/bin_node/lib_dev/services.ml @@ -948,13 +948,19 @@ let dispatch_private_request (rpc_server_family : Rpc_types.rpc_server_family) | None -> (None, true) in let timestamp = Option.value timestamp ~default:(Misc.now ()) in - let* nb_transactions = + let* has_produced_block = Block_producer.Internal_for_tests.produce_block ~with_delayed_transactions ~force:true ~timestamp in - rpc_ok (Ethereum_types.quantity_of_z @@ Z.of_int nb_transactions) + match has_produced_block with + | `Block_produced nb_transactions -> + rpc_ok (Ethereum_types.quantity_of_z @@ Z.of_int nb_transactions) + | `No_block -> + rpc_error + (Rpc_errors.internal_error + (Format.sprintf "Block production failed")) in build ~f module_ parameters | Method (Inject_transaction.Method, module_) -> diff --git a/etherlink/tezt/tests/evm_sequencer.ml b/etherlink/tezt/tests/evm_sequencer.ml index 92cfe2aad3e093fe5ca8ca3c671ec69866d63f7a..f98e5af4db2cfdcc94b0427cd1878df098d32966 100644 --- a/etherlink/tezt/tests/evm_sequencer.ml +++ b/etherlink/tezt/tests/evm_sequencer.ml @@ -1229,12 +1229,14 @@ let test_sequencer_too_ahead = unit) in let* () = - let*@ _ = produce_block ~wait_on_blueprint_applied:false sequencer in + (* Failing as the block_producer is locked. *) + let*@? _ = produce_block ~wait_on_blueprint_applied:false sequencer in unit and* () = Evm_node.wait_for_block_producer_locked sequencer in let* () = + (* Repeating won't make the production magically successful. *) repeat max_blueprints_ahead (fun () -> - let*@ _ = produce_block ~wait_on_blueprint_applied:false sequencer in + let*@? _ = produce_block ~wait_on_blueprint_applied:false sequencer in unit) in let*@ block_number = Rpc.block_number sequencer in