From 39dd704ce1b8421892a796847bfc54358e61c3e3 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Mon, 17 Apr 2023 12:55:03 +0200 Subject: [PATCH 1/6] Lib_crawler: monadic map for reorg structure --- src/lib_crawler/reorg.ml | 12 ++++++++++++ src/lib_crawler/reorg.mli | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/src/lib_crawler/reorg.ml b/src/lib_crawler/reorg.ml index 0a7e6aad3066..99ff139e2a00 100644 --- a/src/lib_crawler/reorg.ml +++ b/src/lib_crawler/reorg.ml @@ -39,3 +39,15 @@ let encoding block_encoding = let map f {old_chain; new_chain} = {old_chain = List.map f old_chain; new_chain = List.map f new_chain} + +let map_es f {old_chain; new_chain} = + let open Lwt_result_syntax in + let* old_chain = List.map_es f old_chain in + let* new_chain = List.map_es f new_chain in + return {old_chain; new_chain} + +let map_ep f {old_chain; new_chain} = + let open Lwt_result_syntax in + let* old_chain = List.map_ep f old_chain + and* new_chain = List.map_ep f new_chain in + return {old_chain; new_chain} diff --git a/src/lib_crawler/reorg.mli b/src/lib_crawler/reorg.mli index 0cbc0f8e0323..56dd0d1cf059 100644 --- a/src/lib_crawler/reorg.mli +++ b/src/lib_crawler/reorg.mli @@ -38,3 +38,7 @@ val no_reorg : 'a t val encoding : 'a Data_encoding.t -> 'a t Data_encoding.t val map : ('a -> 'b) -> 'a t -> 'b t + +val map_es : ('a -> 'b tzresult Lwt.t) -> 'a t -> 'b t tzresult Lwt.t + +val map_ep : ('a -> 'b tzresult Lwt.t) -> 'a t -> 'b t tzresult Lwt.t -- GitLab From c1445098d0d3547e5b17747f261323dad53f818d Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Mon, 17 Apr 2023 12:55:57 +0200 Subject: [PATCH 2/6] SCORU/Node: use block headers --- .../lib_sc_rollup_node/commitment.ml | 4 +- .../lib_sc_rollup_node/commitment_sig.ml | 2 +- src/proto_alpha/lib_sc_rollup_node/daemon.ml | 106 +++++++++++------- src/proto_alpha/lib_sc_rollup_node/inbox.ml | 53 ++++----- src/proto_alpha/lib_sc_rollup_node/inbox.mli | 7 +- .../lib_sc_rollup_node/interpreter.ml | 15 ++- .../lib_sc_rollup_node/interpreter.mli | 4 +- src/proto_alpha/lib_sc_rollup_node/layer1.ml | 30 ++++- src/proto_alpha/lib_sc_rollup_node/layer1.mli | 12 +- .../lib_sc_rollup_node/node_context.ml | 24 +++- .../lib_sc_rollup_node/node_context.mli | 15 +++ .../test/helpers/helpers.ml | 37 +++--- 12 files changed, 202 insertions(+), 107 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/commitment.ml b/src/proto_alpha/lib_sc_rollup_node/commitment.ml index 237c288a0ba9..e9fcb6c4e348 100644 --- a/src/proto_alpha/lib_sc_rollup_node/commitment.ml +++ b/src/proto_alpha/lib_sc_rollup_node/commitment.ml @@ -175,8 +175,8 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct Some commitment else return_none - let process_head (node_ctxt : _ Node_context.t) ~predecessor Layer1.{level; _} - ctxt = + let process_head (node_ctxt : _ Node_context.t) ~predecessor + Layer1.{level; header = _; _} ctxt = let open Lwt_result_syntax in let current_level = Raw_level.of_int32_exn level in let* commitment = diff --git a/src/proto_alpha/lib_sc_rollup_node/commitment_sig.ml b/src/proto_alpha/lib_sc_rollup_node/commitment_sig.ml index 96f2306dd8f0..fccdc19b1854 100644 --- a/src/proto_alpha/lib_sc_rollup_node/commitment_sig.ml +++ b/src/proto_alpha/lib_sc_rollup_node/commitment_sig.ml @@ -50,7 +50,7 @@ module type S = sig val process_head : Node_context.rw -> predecessor:Block_hash.t -> - Layer1.head -> + Layer1.header -> Context.rw -> Protocol.Alpha_context.Sc_rollup.Commitment.Hash.t option tzresult Lwt.t diff --git a/src/proto_alpha/lib_sc_rollup_node/daemon.ml b/src/proto_alpha/lib_sc_rollup_node/daemon.ml index c57632ef5789..d066e525e344 100644 --- a/src/proto_alpha/lib_sc_rollup_node/daemon.ml +++ b/src/proto_alpha/lib_sc_rollup_node/daemon.ml @@ -84,7 +84,7 @@ module Make (PVM : Pvm.S) = struct for the first time. {b Note}: this function does not process inboxes for the rollup, which is done instead by {!Inbox.process_head}. *) let process_included_l1_operation (type kind) (node_ctxt : Node_context.rw) - head ~source (operation : kind manager_operation) + (head : Layer1.header) ~source (operation : kind manager_operation) (result : kind successful_manager_operation_result) = let open Lwt_result_syntax in match (operation, result) with @@ -227,8 +227,8 @@ module Make (PVM : Pvm.S) = struct (_result : kind successful_manager_operation_result) = return_unit - let process_l1_operation (type kind) ~finalized node_ctxt head ~source - (operation : kind manager_operation) + let process_l1_operation (type kind) ~finalized node_ctxt + (head : Layer1.header) ~source (operation : kind manager_operation) (result : kind Apply_results.manager_operation_result) = let open Lwt_result_syntax in let is_for_my_rollup : type kind. kind manager_operation -> bool = function @@ -263,10 +263,11 @@ module Make (PVM : Pvm.S) = struct (* No action for non successful operations *) return_unit - let process_l1_block_operations ~finalized node_ctxt - (Layer1.{hash; _} as head) = + let process_l1_block_operations ~finalized node_ctxt (head : Layer1.header) = let open Lwt_result_syntax in - let* block = Layer1.fetch_tezos_block node_ctxt.Node_context.cctxt hash in + let* block = + Layer1.fetch_tezos_block node_ctxt.Node_context.cctxt head.hash + in let apply (type kind) accu ~source (operation : kind manager_operation) result = let open Lwt_result_syntax in @@ -286,46 +287,53 @@ module Make (PVM : Pvm.S) = struct in return_unit - let before_origination (node_ctxt : _ Node_context.t) Layer1.{level; _} = + let before_origination (node_ctxt : _ Node_context.t) (header : Layer1.header) + = let origination_level = Raw_level.to_int32 node_ctxt.genesis_info.level in - level < origination_level + header.level < origination_level let rec processed_finalized_block (node_ctxt : _ Node_context.t) - Layer1.({hash; level} as block) = + (block : Layer1.header) = let open Lwt_result_syntax in let* last_finalized = Node_context.get_finalized_head_opt node_ctxt in let already_finalized = match last_finalized with - | Some finalized -> level <= Raw_level.to_int32 finalized.header.level + | Some finalized -> + block.level <= Raw_level.to_int32 finalized.header.level | None -> false in unless (already_finalized || before_origination node_ctxt block) @@ fun () -> - let* predecessor = Node_context.get_predecessor_opt node_ctxt block in + let* predecessor = + Node_context.get_predecessor_header_opt node_ctxt block + in let* () = Option.iter_es (processed_finalized_block node_ctxt) predecessor in - let*! () = Daemon_event.head_processing hash level ~finalized:true in + let*! () = + Daemon_event.head_processing block.hash block.level ~finalized:true + in let* () = process_l1_block_operations ~finalized:true node_ctxt block in - let* () = Node_context.mark_finalized_head node_ctxt hash in + let* () = Node_context.mark_finalized_head node_ctxt block.hash in return_unit - let previous_context (node_ctxt : _ Node_context.t) ~predecessor - Layer1.{hash = _; level} = + let previous_context (node_ctxt : _ Node_context.t) + ~(predecessor : Layer1.header) = let open Lwt_result_syntax in - if level <= Raw_level.to_int32 node_ctxt.genesis_info.level then + if predecessor.level < Raw_level.to_int32 node_ctxt.genesis_info.level then (* This is before we have interpreted the boot sector, so we start with an empty context in genesis *) return (Context.empty node_ctxt.context) else Node_context.checkout_context node_ctxt predecessor.Layer1.hash - let rec process_head (node_ctxt : _ Node_context.t) - Layer1.({hash; level} as head) = + let rec process_head (node_ctxt : _ Node_context.t) (head : Layer1.header) = let open Lwt_result_syntax in - let* already_processed = Node_context.is_processed node_ctxt hash in + let* already_processed = Node_context.is_processed node_ctxt head.hash in unless (already_processed || before_origination node_ctxt head) @@ fun () -> - let*! () = Daemon_event.head_processing hash level ~finalized:false in - let* predecessor = Node_context.get_predecessor_opt node_ctxt head in + let*! () = + Daemon_event.head_processing head.hash head.level ~finalized:false + in + let* predecessor = Node_context.get_predecessor_header_opt node_ctxt head in match predecessor with | None -> (* Predecessor not available on the L1, which means the block does not @@ -333,14 +341,18 @@ module Make (PVM : Pvm.S) = struct return_unit | Some predecessor -> let* () = process_head node_ctxt predecessor in - let* ctxt = previous_context node_ctxt ~predecessor head in - let* () = Node_context.save_level node_ctxt head in + let* ctxt = previous_context node_ctxt ~predecessor in + let* () = + Node_context.save_level + node_ctxt + {Layer1.hash = head.hash; level = head.level} + in let* inbox_hash, inbox, inbox_witness, messages = Inbox.process_head node_ctxt ~predecessor head in let* () = when_ (Node_context.dal_supported node_ctxt) @@ fun () -> - Dal_slots_tracker.process_head node_ctxt head + Dal_slots_tracker.process_head node_ctxt (Layer1.head_of_header head) in let* () = process_l1_block_operations ~finalized:false node_ctxt head in (* Avoid storing and publishing commitments if the head is not final. *) @@ -362,7 +374,7 @@ module Make (PVM : Pvm.S) = struct head ctxt in - let level = Raw_level.of_int32_exn level in + let level = Raw_level.of_int32_exn head.level in let* previous_commitment_hash = if level = node_ctxt.genesis_info.Sc_rollup.Commitment.level then (* Previous commitment for rollup genesis is itself. *) @@ -374,7 +386,7 @@ module Make (PVM : Pvm.S) = struct let header = Sc_rollup_block. { - block_hash = hash; + block_hash = head.hash; level; predecessor = predecessor.hash; commitment_hash; @@ -388,7 +400,7 @@ module Make (PVM : Pvm.S) = struct Sc_rollup_block.{header; content = (); num_ticks; initial_tick} in let* finalized_block, _ = - Node_context.nth_predecessor + Node_context.nth_predecessor_header node_ctxt node_ctxt.block_finality_time head @@ -396,7 +408,7 @@ module Make (PVM : Pvm.S) = struct let* () = processed_finalized_block node_ctxt finalized_block in let* () = Node_context.save_l2_head node_ctxt l2_block in let*! () = - Daemon_event.new_head_processed hash (Raw_level.to_int32 level) + Daemon_event.new_head_processed head.hash (Raw_level.to_int32 level) in return_unit @@ -404,7 +416,7 @@ module Make (PVM : Pvm.S) = struct also processes any missing blocks that were not processed. Every time a head is processed we also process head~2 as finalized (which may recursively imply the processing of head~3, etc). *) - let on_layer_1_head node_ctxt head = + let on_layer_1_head node_ctxt (head : Layer1.header) = let open Lwt_result_syntax in let* old_head = Node_context.last_processed_head_opt node_ctxt in let old_head = @@ -424,8 +436,9 @@ module Make (PVM : Pvm.S) = struct in `Level (Int32.pred origination_level) in + let stripped_head = Layer1.head_of_header head in let*! reorg = - Node_context.get_tezos_reorg_for_new_head node_ctxt old_head head + Node_context.get_tezos_reorg_for_new_head node_ctxt old_head stripped_head in let*? reorg = match reorg with @@ -441,7 +454,7 @@ module Make (PVM : Pvm.S) = struct trace -> (* The reorganization could not be computed entirely because of missing info on the Layer 1. We fallback to a recursive process_head. *) - Ok {Reorg.no_reorg with new_chain = [head]} + Ok {Reorg.no_reorg with new_chain = [stripped_head]} | _ -> reorg in (* TODO: https://gitlab.com/tezos/tezos/-/issues/3348 @@ -457,13 +470,25 @@ module Make (PVM : Pvm.S) = struct }) in let*! () = Daemon_event.processing_heads_iteration reorg.new_chain in - let* () = List.iter_es (process_head node_ctxt) reorg.new_chain in + let get_header Layer1.{hash; level} = + if Block_hash.equal hash head.hash then return head + else + let+ header = Layer1.fetch_tezos_shell_header node_ctxt.cctxt hash in + {Layer1.hash; level; header} + in + let* () = + List.iter_es + (fun block -> + let* header = get_header block in + process_head node_ctxt header) + reorg.new_chain + in let* () = Components.Commitment.Publisher.publish_commitments () in let* () = Components.Commitment.Publisher.cement_commitments () in let*! () = Daemon_event.new_heads_processed reorg.new_chain in - let* () = Components.Refutation_coordinator.process head in + let* () = Components.Refutation_coordinator.process stripped_head in let* () = Components.Batcher.batch () in - let* () = Components.Batcher.new_head head in + let* () = Components.Batcher.new_head stripped_head in let*! () = Injector.inject ~header () in return_unit @@ -479,7 +504,9 @@ module Make (PVM : Pvm.S) = struct let*! () = message "Shutting down Commitment Publisher@." in let*! () = Components.Commitment.Publisher.shutdown () in Layer1.iter_heads node_ctxt.l1_ctxt @@ fun head -> - let* () = Components.Refutation_coordinator.process head in + let* () = + Components.Refutation_coordinator.process (Layer1.head_of_header head) + in let*! () = Injector.inject () in return_unit @@ -606,16 +633,17 @@ module Make (PVM : Pvm.S) = struct corresponding to [messages]. It is used by the unit tests to build an L2 chain. *) let process_messages (node_ctxt : _ Node_context.t) ~is_migration_block - ~predecessor ~predecessor_timestamp head messages = + ~predecessor head messages = let open Lwt_result_syntax in - let* ctxt = previous_context node_ctxt ~predecessor head in - let* () = Node_context.save_level node_ctxt head in + let* ctxt = previous_context node_ctxt ~predecessor in + let* () = + Node_context.save_level node_ctxt (Layer1.head_of_header head) + in let* inbox_hash, inbox, inbox_witness, messages = Inbox.Internal_for_tests.process_messages node_ctxt ~is_migration_block ~predecessor - ~predecessor_timestamp ~level:head.level messages in diff --git a/src/proto_alpha/lib_sc_rollup_node/inbox.ml b/src/proto_alpha/lib_sc_rollup_node/inbox.ml index 5e6572c4e51c..3a15cf6eba8d 100644 --- a/src/proto_alpha/lib_sc_rollup_node/inbox.ml +++ b/src/proto_alpha/lib_sc_rollup_node/inbox.ml @@ -78,22 +78,7 @@ let get_messages Node_context.{cctxt; _} head = block.operations {apply; apply_internal}) in - let ({predecessor; _} : Block_header.shell_header) = block.header.shell in - let* { - timestamp = predecessor_timestamp; - proto_level = predecessor_proto_level; - _; - } = - Layer1.fetch_tezos_shell_header cctxt predecessor - in - let is_migration_block = - block.header.shell.proto_level <> predecessor_proto_level - in - return - ( is_migration_block, - List.rev rev_messages, - predecessor_timestamp, - predecessor ) + return (List.rev rev_messages) let same_inbox_as_layer_1 node_ctxt head_hash inbox = let open Lwt_result_syntax in @@ -134,9 +119,12 @@ let add_messages ~is_migration_block ~predecessor_timestamp ~predecessor inbox messages_with_protocol_internal_messages ) let process_messages (node_ctxt : _ Node_context.t) ~is_migration_block - ~predecessor ~predecessor_timestamp ~level messages = + ~(predecessor : Layer1.header) ~level messages = let open Lwt_result_syntax in - let* inbox = Node_context.inbox_of_head node_ctxt predecessor in + let* inbox = + Node_context.inbox_of_head node_ctxt (Layer1.head_of_header predecessor) + in + let predecessor_timestamp = predecessor.header.timestamp in let inbox_metrics = Metrics.Inbox.metrics in Prometheus.Gauge.set inbox_metrics.head_inbox_level @@ Int32.to_float level ; let* ( _messages_history, @@ -167,25 +155,25 @@ let process_messages (node_ctxt : _ Node_context.t) ~is_migration_block return (inbox_hash, inbox, witness_hash, messages_with_protocol_internal_messages) -let process_head (node_ctxt : _ Node_context.t) ~predecessor - Layer1.{level; hash = head_hash} = +let process_head (node_ctxt : _ Node_context.t) ~(predecessor : Layer1.header) + (head : Layer1.header) = let open Lwt_result_syntax in let first_inbox_level = Raw_level.to_int32 node_ctxt.genesis_info.level |> Int32.succ in - if level >= first_inbox_level then ( + if head.level >= first_inbox_level then (* We compute the inbox of this block using the inbox of its predecessor. That way, the computation of inboxes is robust to chain reorganization. *) - let* ( is_migration_block, - collected_messages, - predecessor_timestamp, - predecessor_hash ) = - get_messages node_ctxt head_hash - in - assert (Block_hash.(predecessor.Layer1.hash = predecessor_hash)) ; + let* collected_messages = get_messages node_ctxt head.hash in let*! () = - Inbox_event.get_messages head_hash level (List.length collected_messages) + Inbox_event.get_messages + head.hash + head.level + (List.length collected_messages) + in + let is_migration_block = + head.header.proto_level <> predecessor.header.proto_level in let* (( _inbox_hash, inbox, @@ -195,12 +183,11 @@ let process_head (node_ctxt : _ Node_context.t) ~predecessor node_ctxt ~is_migration_block ~predecessor - ~predecessor_timestamp - ~level + ~level:head.level collected_messages in - let* () = same_inbox_as_layer_1 node_ctxt head_hash inbox in - return res) + let* () = same_inbox_as_layer_1 node_ctxt head.hash inbox in + return res else let* inbox = Node_context.genesis_inbox node_ctxt in return diff --git a/src/proto_alpha/lib_sc_rollup_node/inbox.mli b/src/proto_alpha/lib_sc_rollup_node/inbox.mli index 33e895f82593..a723ad47e53e 100644 --- a/src/proto_alpha/lib_sc_rollup_node/inbox.mli +++ b/src/proto_alpha/lib_sc_rollup_node/inbox.mli @@ -42,8 +42,8 @@ open Sc_rollup [operations] of the [head] block. *) val process_head : Node_context.rw -> - predecessor:Layer1.head -> - Layer1.head -> + predecessor:Layer1.header -> + Layer1.header -> (Sc_rollup.Inbox.Hash.t * Sc_rollup.Inbox.t * Sc_rollup.Inbox_merkelized_payload_hashes.Hash.t @@ -88,8 +88,7 @@ module Internal_for_tests : sig val process_messages : Node_context.rw -> is_migration_block:bool -> - predecessor:Layer1.head -> - predecessor_timestamp:Timestamp.time -> + predecessor:Layer1.header -> level:int32 -> Sc_rollup.Inbox_message.t list -> (Sc_rollup.Inbox.Hash.t diff --git a/src/proto_alpha/lib_sc_rollup_node/interpreter.ml b/src/proto_alpha/lib_sc_rollup_node/interpreter.ml index cc5fb9ca2338..41ad610367b3 100644 --- a/src/proto_alpha/lib_sc_rollup_node/interpreter.ml +++ b/src/proto_alpha/lib_sc_rollup_node/interpreter.ml @@ -38,8 +38,8 @@ module type S = sig val process_head : Node_context.rw -> 'a Context.t -> - predecessor:Layer1.head -> - Layer1.head -> + predecessor:Layer1.header -> + Layer1.header -> Sc_rollup.Inbox.t * Sc_rollup.Inbox_message.t list -> ('a Context.t * int * int64 * Sc_rollup.Tick.t) tzresult Lwt.t @@ -165,14 +165,19 @@ module Make (PVM : Pvm.S) : S with module PVM = PVM = struct (** [process_head node_ctxt ctxt ~predecessor head] runs the PVM for the given head. *) - let process_head (node_ctxt : _ Node_context.t) ctxt ~predecessor head - inbox_messages = + let process_head (node_ctxt : _ Node_context.t) ctxt + ~(predecessor : Layer1.header) (head : Layer1.header) inbox_messages = let open Lwt_result_syntax in let first_inbox_level = Raw_level.to_int32 node_ctxt.genesis_info.level |> Int32.succ in if head.Layer1.level >= first_inbox_level then - transition_pvm node_ctxt ctxt predecessor head inbox_messages + transition_pvm + node_ctxt + ctxt + (Layer1.head_of_header predecessor) + (Layer1.head_of_header head) + inbox_messages else if head.Layer1.level = Raw_level.to_int32 node_ctxt.genesis_info.level then let* ctxt, state = genesis_state head.hash node_ctxt ctxt in diff --git a/src/proto_alpha/lib_sc_rollup_node/interpreter.mli b/src/proto_alpha/lib_sc_rollup_node/interpreter.mli index 3bc4a0aa7aee..99dd231a3ab9 100644 --- a/src/proto_alpha/lib_sc_rollup_node/interpreter.mli +++ b/src/proto_alpha/lib_sc_rollup_node/interpreter.mli @@ -45,8 +45,8 @@ module type S = sig val process_head : Node_context.rw -> 'a Context.t -> - predecessor:Layer1.head -> - Layer1.head -> + predecessor:Layer1.header -> + Layer1.header -> Sc_rollup.Inbox.t * Sc_rollup.Inbox_message.t list -> ('a Context.t * int * int64 * Sc_rollup.Tick.t) tzresult Lwt.t diff --git a/src/proto_alpha/lib_sc_rollup_node/layer1.ml b/src/proto_alpha/lib_sc_rollup_node/layer1.ml index 70c02794a585..501d6c403e33 100644 --- a/src/proto_alpha/lib_sc_rollup_node/layer1.ml +++ b/src/proto_alpha/lib_sc_rollup_node/layer1.ml @@ -58,14 +58,31 @@ let () = *) +type header = { + hash : Block_hash.t; + level : int32; + header : Block_header.shell_header; +} + +let header_encoding = + let open Data_encoding in + conv + (fun {hash; level = _; header} -> (hash, header)) + (fun (hash, header) -> {hash; level = header.level; header}) + (merge_objs + (obj1 (req "hash" Block_hash.encoding)) + Block_header.shell_header_encoding) + type head = {hash : Block_hash.t; level : int32} let head_encoding = - Data_encoding.( - conv - (fun {hash; level} -> (hash, level)) - (fun (hash, level) -> {hash; level}) - (obj2 (req "hash" Block_hash.encoding) (req "level" Data_encoding.int32))) + let open Data_encoding in + conv + (fun {hash; level} -> (hash, level)) + (fun (hash, level) -> {hash; level}) + (obj2 (req "hash" Block_hash.encoding) (req "level" Data_encoding.int32)) + +let head_of_header {hash; level; header = _} = {hash; level} module Blocks_cache = Aches_lwt.Lache.Make_option @@ -79,7 +96,8 @@ let blocks_cache : blocks_cache = Blocks_cache.create 32 include Octez_crawler.Layer_1 let iter_heads l1_ctxt f = - iter_heads l1_ctxt @@ fun (hash, {shell = {level; _}; _}) -> f {hash; level} + iter_heads l1_ctxt @@ fun (hash, {shell = {level; _} as header; _}) -> + f {hash; level; header} (** diff --git a/src/proto_alpha/lib_sc_rollup_node/layer1.mli b/src/proto_alpha/lib_sc_rollup_node/layer1.mli index c9697e4fe5c0..b6f34af8ddac 100644 --- a/src/proto_alpha/lib_sc_rollup_node/layer1.mli +++ b/src/proto_alpha/lib_sc_rollup_node/layer1.mli @@ -30,10 +30,20 @@ subscribing to the head monitoring RPC offered by the Tezos node. *) +type header = { + hash : Block_hash.t; + level : int32; + header : Block_header.shell_header; +} + type head = {hash : Block_hash.t; level : int32} +val header_encoding : header Data_encoding.t + val head_encoding : head Data_encoding.t +val head_of_header : header -> head + include module type of Octez_crawler.Layer_1 (* TODO: https://gitlab.com/tezos/tezos/-/issues/3311 @@ -43,7 +53,7 @@ include module type of Octez_crawler.Layer_1 chain. In case of a disconnection with the layer 1 node, it reconnects automatically. If [f] returns an error (other than a disconnection) it, [iter_heads] terminates and returns the error. *) -val iter_heads : t -> (head -> unit tzresult Lwt.t) -> unit tzresult Lwt.t +val iter_heads : t -> (header -> unit tzresult Lwt.t) -> unit tzresult Lwt.t (** {2 Helpers } *) diff --git a/src/proto_alpha/lib_sc_rollup_node/node_context.ml b/src/proto_alpha/lib_sc_rollup_node/node_context.ml index 00d8ed1ac165..58315a24a295 100644 --- a/src/proto_alpha/lib_sc_rollup_node/node_context.ml +++ b/src/proto_alpha/lib_sc_rollup_node/node_context.ml @@ -471,12 +471,24 @@ let nth_predecessor node_ctxt n block = in (head_of_block_level res, List.map head_of_block_level preds) +let header_of_head node_ctxt Layer1.{hash; level} = + let open Lwt_result_syntax in + let+ header = Layer1.fetch_tezos_shell_header node_ctxt.cctxt hash in + {Layer1.hash; level; header} + +let nth_predecessor_header node_ctxt n block = + let open Lwt_result_syntax in + let* res, preds = nth_predecessor node_ctxt n (Layer1.head_of_header block) in + let* res = header_of_head node_ctxt res + and* preds = List.map_ep (header_of_head node_ctxt) preds in + return (res, preds) + let get_tezos_reorg_for_new_head node_ctxt old_head new_head = let open Lwt_result_syntax in let old_head = match old_head with | `Level l -> `Level l - | `Head h -> `Head (block_level_of_head h) + | `Head Layer1.{hash; level} -> `Head (hash, level) in let+ reorg = Layer1.get_tezos_reorg_for_new_head @@ -497,6 +509,16 @@ let get_predecessor node_ctxt head = let+ res = get_predecessor node_ctxt (block_level_of_head head) in head_of_block_level res +let get_predecessor_header_opt node_ctxt head = + let open Lwt_result_syntax in + let* res = get_predecessor_opt node_ctxt (Layer1.head_of_header head) in + Option.map_es (header_of_head node_ctxt) res + +let get_predecessor_header node_ctxt head = + let open Lwt_result_syntax in + let* res = get_predecessor node_ctxt (Layer1.head_of_header head) in + header_of_head node_ctxt res + (* TODO: https://gitlab.com/tezos/tezos/-/issues/4128 Unit test the function tick_search. *) diff --git a/src/proto_alpha/lib_sc_rollup_node/node_context.mli b/src/proto_alpha/lib_sc_rollup_node/node_context.mli index 71ff7edd5a28..7323aa7ae4a6 100644 --- a/src/proto_alpha/lib_sc_rollup_node/node_context.mli +++ b/src/proto_alpha/lib_sc_rollup_node/node_context.mli @@ -224,6 +224,21 @@ val get_predecessor : _ t -> Layer1.head -> Layer1.head tzresult Lwt.t val nth_predecessor : _ t -> int -> Layer1.head -> (Layer1.head * Layer1.head list) tzresult Lwt.t +(** Same as {!get_predecessor_opt} with headers. *) +val get_predecessor_header_opt : + _ t -> Layer1.header -> Layer1.header option tzresult Lwt.t + +(** Same as {!get_predecessor} with headers. *) +val get_predecessor_header : + _ t -> Layer1.header -> Layer1.header tzresult Lwt.t + +(** Same as {!nth_predecessor} with headers. *) +val nth_predecessor_header : + _ t -> + int -> + Layer1.header -> + (Layer1.header * Layer1.header list) tzresult Lwt.t + (** [get_tezos_reorg_for_new_head node_ctxt old_head new_head] returns the L1 reorganization between [old_head] and [new_head]. *) val get_tezos_reorg_for_new_head : diff --git a/src/proto_alpha/lib_sc_rollup_node/test/helpers/helpers.ml b/src/proto_alpha/lib_sc_rollup_node/test/helpers/helpers.ml index 202233df253f..1178838d8360 100644 --- a/src/proto_alpha/lib_sc_rollup_node/test/helpers/helpers.ml +++ b/src/proto_alpha/lib_sc_rollup_node/test/helpers/helpers.ml @@ -180,6 +180,24 @@ module Make (PVM : Pvm.S) = struct in return_unit + let head_of_level ~predecessor level = + let hash = block_hash_of_level level in + let timestamp = Time.Protocol.of_seconds (Int64.of_int32 level) in + let header : Block_header.shell_header = + { + level; + predecessor; + timestamp; + (* dummy values below *) + proto_level = 0; + validation_passes = 3; + operations_hash = Tezos_crypto.Hashed.Operation_list_list_hash.zero; + fitness = []; + context = Tezos_crypto.Hashed.Context_hash.zero; + } + in + {Layer1.hash; level; header} + let append_l2_block (node_ctxt : _ Node_context.t) ?(is_migration_block = false) messages = let open Lwt_result_syntax in @@ -192,26 +210,19 @@ module Make (PVM : Pvm.S) = struct | None -> failwith "No genesis block, please add one with add_l2_genesis_block" in - let level = - Raw_level.(to_int32 @@ succ predecessor_l2_block.header.level) - in - let hash = block_hash_of_level level in + let pred_level = Raw_level.to_int32 predecessor_l2_block.header.level in let predecessor = - Layer1. - { - hash = predecessor_l2_block.header.block_hash; - level = Raw_level.to_int32 predecessor_l2_block.header.level; - } + head_of_level + ~predecessor:predecessor_l2_block.header.predecessor + pred_level in - let head = Layer1.{hash; level} in - let predecessor_timestamp = - Time.Protocol.of_seconds (Int64.of_int32 level) + let head = + head_of_level ~predecessor:predecessor.hash (Int32.succ pred_level) in Daemon.Internal_for_tests.process_messages node_ctxt ~is_migration_block ~predecessor - ~predecessor_timestamp head messages end -- GitLab From 04d131dd7051b50aeb7e0469dec9cfa2f81f9bbe Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Mon, 17 Apr 2023 12:55:57 +0200 Subject: [PATCH 3/6] SCORU/Node/016: use block headers --- .../lib_sc_rollup_node/commitment.ml | 4 +- .../lib_sc_rollup_node/commitment_sig.ml | 2 +- .../lib_sc_rollup_node/daemon.ml | 108 +++++++++++------- .../lib_sc_rollup_node/inbox.ml | 38 +++--- .../lib_sc_rollup_node/inbox.mli | 7 +- .../lib_sc_rollup_node/interpreter.ml | 15 ++- .../lib_sc_rollup_node/interpreter.mli | 4 +- .../lib_sc_rollup_node/layer1.ml | 30 ++++- .../lib_sc_rollup_node/layer1.mli | 12 +- .../lib_sc_rollup_node/node_context.ml | 24 +++- .../lib_sc_rollup_node/node_context.mli | 15 +++ .../test/helpers/helpers.ml | 37 +++--- 12 files changed, 201 insertions(+), 95 deletions(-) diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/commitment.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/commitment.ml index 237c288a0ba9..e9fcb6c4e348 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/commitment.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/commitment.ml @@ -175,8 +175,8 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct Some commitment else return_none - let process_head (node_ctxt : _ Node_context.t) ~predecessor Layer1.{level; _} - ctxt = + let process_head (node_ctxt : _ Node_context.t) ~predecessor + Layer1.{level; header = _; _} ctxt = let open Lwt_result_syntax in let current_level = Raw_level.of_int32_exn level in let* commitment = diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/commitment_sig.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/commitment_sig.ml index 96f2306dd8f0..fccdc19b1854 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/commitment_sig.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/commitment_sig.ml @@ -50,7 +50,7 @@ module type S = sig val process_head : Node_context.rw -> predecessor:Block_hash.t -> - Layer1.head -> + Layer1.header -> Context.rw -> Protocol.Alpha_context.Sc_rollup.Commitment.Hash.t option tzresult Lwt.t diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/daemon.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/daemon.ml index 34b844f6a2ec..058db320e91b 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/daemon.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/daemon.ml @@ -84,7 +84,7 @@ module Make (PVM : Pvm.S) = struct for the first time. {b Note}: this function does not process inboxes for the rollup, which is done instead by {!Inbox.process_head}. *) let process_included_l1_operation (type kind) (node_ctxt : Node_context.rw) - head ~source (operation : kind manager_operation) + (head : Layer1.header) ~source (operation : kind manager_operation) (result : kind successful_manager_operation_result) = let open Lwt_result_syntax in match (operation, result) with @@ -227,8 +227,8 @@ module Make (PVM : Pvm.S) = struct (_result : kind successful_manager_operation_result) = return_unit - let process_l1_operation (type kind) ~finalized node_ctxt head ~source - (operation : kind manager_operation) + let process_l1_operation (type kind) ~finalized node_ctxt + (head : Layer1.header) ~source (operation : kind manager_operation) (result : kind Apply_results.manager_operation_result) = let open Lwt_result_syntax in let is_for_my_rollup : type kind. kind manager_operation -> bool = function @@ -266,10 +266,11 @@ module Make (PVM : Pvm.S) = struct (* No action for non successful operations *) return_unit - let process_l1_block_operations ~finalized node_ctxt - (Layer1.{hash; _} as head) = + let process_l1_block_operations ~finalized node_ctxt (head : Layer1.header) = let open Lwt_result_syntax in - let* block = Layer1.fetch_tezos_block node_ctxt.Node_context.cctxt hash in + let* block = + Layer1.fetch_tezos_block node_ctxt.Node_context.cctxt head.hash + in let apply (type kind) accu ~source (operation : kind manager_operation) result = let open Lwt_result_syntax in @@ -289,46 +290,53 @@ module Make (PVM : Pvm.S) = struct in return_unit - let before_origination (node_ctxt : _ Node_context.t) Layer1.{level; _} = + let before_origination (node_ctxt : _ Node_context.t) (header : Layer1.header) + = let origination_level = Raw_level.to_int32 node_ctxt.genesis_info.level in - level < origination_level + header.level < origination_level let rec processed_finalized_block (node_ctxt : _ Node_context.t) - Layer1.({hash; level} as block) = + (block : Layer1.header) = let open Lwt_result_syntax in let* last_finalized = Node_context.get_finalized_head_opt node_ctxt in let already_finalized = match last_finalized with - | Some finalized -> level <= Raw_level.to_int32 finalized.header.level + | Some finalized -> + block.level <= Raw_level.to_int32 finalized.header.level | None -> false in unless (already_finalized || before_origination node_ctxt block) @@ fun () -> - let* predecessor = Node_context.get_predecessor_opt node_ctxt block in + let* predecessor = + Node_context.get_predecessor_header_opt node_ctxt block + in let* () = Option.iter_es (processed_finalized_block node_ctxt) predecessor in - let*! () = Daemon_event.head_processing hash level ~finalized:true in + let*! () = + Daemon_event.head_processing block.hash block.level ~finalized:true + in let* () = process_l1_block_operations ~finalized:true node_ctxt block in - let* () = Node_context.mark_finalized_head node_ctxt hash in + let* () = Node_context.mark_finalized_head node_ctxt block.hash in return_unit - let previous_context (node_ctxt : _ Node_context.t) ~predecessor - Layer1.{hash = _; level} = + let previous_context (node_ctxt : _ Node_context.t) + ~(predecessor : Layer1.header) = let open Lwt_result_syntax in - if level <= Raw_level.to_int32 node_ctxt.genesis_info.level then + if predecessor.level < Raw_level.to_int32 node_ctxt.genesis_info.level then (* This is before we have interpreted the boot sector, so we start with an empty context in genesis *) return (Context.empty node_ctxt.context) else Node_context.checkout_context node_ctxt predecessor.Layer1.hash - let rec process_head (node_ctxt : _ Node_context.t) - Layer1.({hash; level} as head) = + let rec process_head (node_ctxt : _ Node_context.t) (head : Layer1.header) = let open Lwt_result_syntax in - let* already_processed = Node_context.is_processed node_ctxt hash in + let* already_processed = Node_context.is_processed node_ctxt head.hash in unless (already_processed || before_origination node_ctxt head) @@ fun () -> - let*! () = Daemon_event.head_processing hash level ~finalized:false in - let* predecessor = Node_context.get_predecessor_opt node_ctxt head in + let*! () = + Daemon_event.head_processing head.hash head.level ~finalized:false + in + let* predecessor = Node_context.get_predecessor_header_opt node_ctxt head in match predecessor with | None -> (* Predecessor not available on the L1, which means the block does not @@ -336,14 +344,18 @@ module Make (PVM : Pvm.S) = struct return_unit | Some predecessor -> let* () = process_head node_ctxt predecessor in - let* ctxt = previous_context node_ctxt ~predecessor head in - let* () = Node_context.save_level node_ctxt head in + let* ctxt = previous_context node_ctxt ~predecessor in + let* () = + Node_context.save_level + node_ctxt + {Layer1.hash = head.hash; level = head.level} + in let* inbox_hash, inbox, inbox_witness, messages = Inbox.process_head node_ctxt ~predecessor head in let* () = when_ (Node_context.dal_supported node_ctxt) @@ fun () -> - Dal_slots_tracker.process_head node_ctxt head + Dal_slots_tracker.process_head node_ctxt (Layer1.head_of_header head) in let* () = process_l1_block_operations ~finalized:false node_ctxt head in (* Avoid storing and publishing commitments if the head is not final. *) @@ -365,7 +377,7 @@ module Make (PVM : Pvm.S) = struct head ctxt in - let level = Raw_level.of_int32_exn level in + let level = Raw_level.of_int32_exn head.level in let* previous_commitment_hash = if level = node_ctxt.genesis_info.Sc_rollup.Commitment.level then (* Previous commitment for rollup genesis is itself. *) @@ -377,7 +389,7 @@ module Make (PVM : Pvm.S) = struct let header = Sc_rollup_block. { - block_hash = hash; + block_hash = head.hash; level; predecessor = predecessor.hash; commitment_hash; @@ -391,7 +403,7 @@ module Make (PVM : Pvm.S) = struct Sc_rollup_block.{header; content = (); num_ticks; initial_tick} in let* finalized_block, _ = - Node_context.nth_predecessor + Node_context.nth_predecessor_header node_ctxt node_ctxt.block_finality_time head @@ -399,7 +411,7 @@ module Make (PVM : Pvm.S) = struct let* () = processed_finalized_block node_ctxt finalized_block in let* () = Node_context.save_l2_head node_ctxt l2_block in let*! () = - Daemon_event.new_head_processed hash (Raw_level.to_int32 level) + Daemon_event.new_head_processed head.hash (Raw_level.to_int32 level) in return_unit @@ -407,7 +419,7 @@ module Make (PVM : Pvm.S) = struct also processes any missing blocks that were not processed. Every time a head is processed we also process head~2 as finalized (which may recursively imply the processing of head~3, etc). *) - let on_layer_1_head node_ctxt head = + let on_layer_1_head node_ctxt (head : Layer1.header) = let open Lwt_result_syntax in let* old_head = Node_context.last_processed_head_opt node_ctxt in let old_head = @@ -427,8 +439,9 @@ module Make (PVM : Pvm.S) = struct in `Level (Int32.pred origination_level) in + let stripped_head = Layer1.head_of_header head in let*! reorg = - Node_context.get_tezos_reorg_for_new_head node_ctxt old_head head + Node_context.get_tezos_reorg_for_new_head node_ctxt old_head stripped_head in let*? reorg = match reorg with @@ -444,7 +457,7 @@ module Make (PVM : Pvm.S) = struct trace -> (* The reorganization could not be computed entirely because of missing info on the Layer 1. We fallback to a recursive process_head. *) - Ok {Reorg.no_reorg with new_chain = [head]} + Ok {Reorg.no_reorg with new_chain = [stripped_head]} | _ -> reorg in (* TODO: https://gitlab.com/tezos/tezos/-/issues/3348 @@ -460,13 +473,25 @@ module Make (PVM : Pvm.S) = struct }) in let*! () = Daemon_event.processing_heads_iteration reorg.new_chain in - let* () = List.iter_es (process_head node_ctxt) reorg.new_chain in + let get_header Layer1.{hash; level} = + if Block_hash.equal hash head.hash then return head + else + let+ header = Layer1.fetch_tezos_shell_header node_ctxt.cctxt hash in + {Layer1.hash; level; header} + in + let* () = + List.iter_es + (fun block -> + let* header = get_header block in + process_head node_ctxt header) + reorg.new_chain + in let* () = Components.Commitment.Publisher.publish_commitments () in let* () = Components.Commitment.Publisher.cement_commitments () in let*! () = Daemon_event.new_heads_processed reorg.new_chain in - let* () = Components.Refutation_coordinator.process head in + let* () = Components.Refutation_coordinator.process stripped_head in let* () = Components.Batcher.batch () in - let* () = Components.Batcher.new_head head in + let* () = Components.Batcher.new_head stripped_head in let*! () = Injector.inject ~header () in return_unit @@ -482,7 +507,9 @@ module Make (PVM : Pvm.S) = struct let*! () = message "Shutting down Commitment Publisher@." in let*! () = Components.Commitment.Publisher.shutdown () in Layer1.iter_heads node_ctxt.l1_ctxt @@ fun head -> - let* () = Components.Refutation_coordinator.process head in + let* () = + Components.Refutation_coordinator.process (Layer1.head_of_header head) + in let*! () = Injector.inject () in return_unit @@ -613,16 +640,17 @@ module Make (PVM : Pvm.S) = struct (** Same as {!process_head} but only builds and stores the L2 block corresponding to [messages]. It is used by the unit tests to build an L2 chain. *) - let process_messages (node_ctxt : _ Node_context.t) ~predecessor - ~predecessor_timestamp head messages = + let process_messages (node_ctxt : _ Node_context.t) ~predecessor head + messages = let open Lwt_result_syntax in - let* ctxt = previous_context node_ctxt ~predecessor head in - let* () = Node_context.save_level node_ctxt head in + let* ctxt = previous_context node_ctxt ~predecessor in + let* () = + Node_context.save_level node_ctxt (Layer1.head_of_header head) + in let* inbox_hash, inbox, inbox_witness, messages = Inbox.Internal_for_tests.process_messages node_ctxt ~predecessor - ~predecessor_timestamp ~level:head.level messages in diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/inbox.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/inbox.ml index 6043df1b5004..7a3806c0c037 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/inbox.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/inbox.ml @@ -78,11 +78,7 @@ let get_messages Node_context.{cctxt; _} head = block.operations {apply; apply_internal}) in - let ({predecessor; _} : Block_header.shell_header) = block.header.shell in - let* {timestamp = predecessor_timestamp; _} = - Layer1.fetch_tezos_shell_header cctxt predecessor - in - return (List.rev rev_messages, predecessor_timestamp, predecessor) + return (List.rev rev_messages) let same_inbox_as_layer_1 node_ctxt head_hash inbox = let open Lwt_result_syntax in @@ -120,10 +116,13 @@ let add_messages ~predecessor_timestamp ~predecessor inbox messages = inbox, messages_with_protocol_internal_messages ) -let process_messages (node_ctxt : _ Node_context.t) ~predecessor - ~predecessor_timestamp ~level messages = +let process_messages (node_ctxt : _ Node_context.t) + ~(predecessor : Layer1.header) ~level messages = let open Lwt_result_syntax in - let* inbox = Node_context.inbox_of_head node_ctxt predecessor in + let* inbox = + Node_context.inbox_of_head node_ctxt (Layer1.head_of_header predecessor) + in + let predecessor_timestamp = predecessor.header.timestamp in let inbox_metrics = Metrics.Inbox.metrics in Prometheus.Gauge.set inbox_metrics.head_inbox_level @@ Int32.to_float level ; let* ( _messages_history, @@ -148,22 +147,22 @@ let process_messages (node_ctxt : _ Node_context.t) ~predecessor return (inbox_hash, inbox, witness_hash, messages_with_protocol_internal_messages) -let process_head (node_ctxt : _ Node_context.t) ~predecessor - Layer1.{level; hash = head_hash} = +let process_head (node_ctxt : _ Node_context.t) ~(predecessor : Layer1.header) + (head : Layer1.header) = let open Lwt_result_syntax in let first_inbox_level = Raw_level.to_int32 node_ctxt.genesis_info.level |> Int32.succ in - if level >= first_inbox_level then ( + if head.level >= first_inbox_level then (* We compute the inbox of this block using the inbox of its predecessor. That way, the computation of inboxes is robust to chain reorganization. *) - let* collected_messages, predecessor_timestamp, predecessor_hash = - get_messages node_ctxt head_hash - in - assert (Block_hash.(predecessor.Layer1.hash = predecessor_hash)) ; + let* collected_messages = get_messages node_ctxt head.hash in let*! () = - Inbox_event.get_messages head_hash level (List.length collected_messages) + Inbox_event.get_messages + head.hash + head.level + (List.length collected_messages) in let* (( _inbox_hash, inbox, @@ -172,12 +171,11 @@ let process_head (node_ctxt : _ Node_context.t) ~predecessor process_messages node_ctxt ~predecessor - ~predecessor_timestamp - ~level + ~level:head.level collected_messages in - let* () = same_inbox_as_layer_1 node_ctxt head_hash inbox in - return res) + let* () = same_inbox_as_layer_1 node_ctxt head.hash inbox in + return res else let* inbox = Node_context.genesis_inbox node_ctxt in return diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/inbox.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/inbox.mli index 1226a2a19800..9f5fd133ee79 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/inbox.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/inbox.mli @@ -42,8 +42,8 @@ open Sc_rollup [operations] of the [head] block. *) val process_head : Node_context.rw -> - predecessor:Layer1.head -> - Layer1.head -> + predecessor:Layer1.header -> + Layer1.header -> (Sc_rollup.Inbox.Hash.t * Sc_rollup.Inbox.t * Sc_rollup.Inbox_merkelized_payload_hashes.Hash.t @@ -83,8 +83,7 @@ val payloads_history_of_messages : module Internal_for_tests : sig val process_messages : Node_context.rw -> - predecessor:Layer1.head -> - predecessor_timestamp:Timestamp.time -> + predecessor:Layer1.header -> level:int32 -> Sc_rollup.Inbox_message.t list -> (Sc_rollup.Inbox.Hash.t diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/interpreter.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/interpreter.ml index 381cd852ffd7..132b6b921519 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/interpreter.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/interpreter.ml @@ -38,8 +38,8 @@ module type S = sig val process_head : Node_context.rw -> 'a Context.t -> - predecessor:Layer1.head -> - Layer1.head -> + predecessor:Layer1.header -> + Layer1.header -> Sc_rollup.Inbox.t * Sc_rollup.Inbox_message.t list -> ('a Context.t * int * int64 * Sc_rollup.Tick.t) tzresult Lwt.t @@ -165,14 +165,19 @@ module Make (PVM : Pvm.S) : S with module PVM = PVM = struct (** [process_head node_ctxt ctxt ~predecessor head] runs the PVM for the given head. *) - let process_head (node_ctxt : _ Node_context.t) ctxt ~predecessor head - inbox_messages = + let process_head (node_ctxt : _ Node_context.t) ctxt + ~(predecessor : Layer1.header) (head : Layer1.header) inbox_messages = let open Lwt_result_syntax in let first_inbox_level = Raw_level.to_int32 node_ctxt.genesis_info.level |> Int32.succ in if head.Layer1.level >= first_inbox_level then - transition_pvm node_ctxt ctxt predecessor head inbox_messages + transition_pvm + node_ctxt + ctxt + (Layer1.head_of_header predecessor) + (Layer1.head_of_header head) + inbox_messages else if head.Layer1.level = Raw_level.to_int32 node_ctxt.genesis_info.level then let* ctxt, state = genesis_state head.hash node_ctxt ctxt in diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/interpreter.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/interpreter.mli index 3bc4a0aa7aee..99dd231a3ab9 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/interpreter.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/interpreter.mli @@ -45,8 +45,8 @@ module type S = sig val process_head : Node_context.rw -> 'a Context.t -> - predecessor:Layer1.head -> - Layer1.head -> + predecessor:Layer1.header -> + Layer1.header -> Sc_rollup.Inbox.t * Sc_rollup.Inbox_message.t list -> ('a Context.t * int * int64 * Sc_rollup.Tick.t) tzresult Lwt.t diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.ml index fe5776cb19d1..d3ddb6c753c5 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.ml @@ -58,14 +58,31 @@ let () = *) +type header = { + hash : Block_hash.t; + level : int32; + header : Block_header.shell_header; +} + +let header_encoding = + let open Data_encoding in + conv + (fun {hash; level = _; header} -> (hash, header)) + (fun (hash, header) -> {hash; level = header.level; header}) + (merge_objs + (obj1 (req "hash" Block_hash.encoding)) + Block_header.shell_header_encoding) + type head = {hash : Block_hash.t; level : int32} let head_encoding = - Data_encoding.( - conv - (fun {hash; level} -> (hash, level)) - (fun (hash, level) -> {hash; level}) - (obj2 (req "hash" Block_hash.encoding) (req "level" Data_encoding.int32))) + let open Data_encoding in + conv + (fun {hash; level} -> (hash, level)) + (fun (hash, level) -> {hash; level}) + (obj2 (req "hash" Block_hash.encoding) (req "level" Data_encoding.int32)) + +let head_of_header {hash; level; header = _} = {hash; level} module Blocks_cache = Aches_lwt.Lache.Make_option @@ -79,7 +96,8 @@ let blocks_cache : blocks_cache = Blocks_cache.create 32 include Octez_crawler.Layer_1 let iter_heads l1_ctxt f = - iter_heads l1_ctxt @@ fun (hash, {shell = {level; _}; _}) -> f {hash; level} + iter_heads l1_ctxt @@ fun (hash, {shell = {level; _} as header; _}) -> + f {hash; level; header} (** diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.mli index c9697e4fe5c0..b6f34af8ddac 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.mli @@ -30,10 +30,20 @@ subscribing to the head monitoring RPC offered by the Tezos node. *) +type header = { + hash : Block_hash.t; + level : int32; + header : Block_header.shell_header; +} + type head = {hash : Block_hash.t; level : int32} +val header_encoding : header Data_encoding.t + val head_encoding : head Data_encoding.t +val head_of_header : header -> head + include module type of Octez_crawler.Layer_1 (* TODO: https://gitlab.com/tezos/tezos/-/issues/3311 @@ -43,7 +53,7 @@ include module type of Octez_crawler.Layer_1 chain. In case of a disconnection with the layer 1 node, it reconnects automatically. If [f] returns an error (other than a disconnection) it, [iter_heads] terminates and returns the error. *) -val iter_heads : t -> (head -> unit tzresult Lwt.t) -> unit tzresult Lwt.t +val iter_heads : t -> (header -> unit tzresult Lwt.t) -> unit tzresult Lwt.t (** {2 Helpers } *) diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.ml index 6912eb61d180..fd241d16ee47 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.ml @@ -457,12 +457,24 @@ let nth_predecessor node_ctxt n block = in (head_of_block_level res, List.map head_of_block_level preds) +let header_of_head node_ctxt Layer1.{hash; level} = + let open Lwt_result_syntax in + let+ header = Layer1.fetch_tezos_shell_header node_ctxt.cctxt hash in + {Layer1.hash; level; header} + +let nth_predecessor_header node_ctxt n block = + let open Lwt_result_syntax in + let* res, preds = nth_predecessor node_ctxt n (Layer1.head_of_header block) in + let* res = header_of_head node_ctxt res + and* preds = List.map_ep (header_of_head node_ctxt) preds in + return (res, preds) + let get_tezos_reorg_for_new_head node_ctxt old_head new_head = let open Lwt_result_syntax in let old_head = match old_head with | `Level l -> `Level l - | `Head h -> `Head (block_level_of_head h) + | `Head Layer1.{hash; level} -> `Head (hash, level) in let+ reorg = Layer1.get_tezos_reorg_for_new_head @@ -483,6 +495,16 @@ let get_predecessor node_ctxt head = let+ res = get_predecessor node_ctxt (block_level_of_head head) in head_of_block_level res +let get_predecessor_header_opt node_ctxt head = + let open Lwt_result_syntax in + let* res = get_predecessor_opt node_ctxt (Layer1.head_of_header head) in + Option.map_es (header_of_head node_ctxt) res + +let get_predecessor_header node_ctxt head = + let open Lwt_result_syntax in + let* res = get_predecessor node_ctxt (Layer1.head_of_header head) in + header_of_head node_ctxt res + (* TODO: https://gitlab.com/tezos/tezos/-/issues/4128 Unit test the function tick_search. *) diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.mli index 35be8cb4316c..eead4d447f69 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.mli @@ -224,6 +224,21 @@ val get_predecessor : _ t -> Layer1.head -> Layer1.head tzresult Lwt.t val nth_predecessor : _ t -> int -> Layer1.head -> (Layer1.head * Layer1.head list) tzresult Lwt.t +(** Same as {!get_predecessor_opt} with headers. *) +val get_predecessor_header_opt : + _ t -> Layer1.header -> Layer1.header option tzresult Lwt.t + +(** Same as {!get_predecessor} with headers. *) +val get_predecessor_header : + _ t -> Layer1.header -> Layer1.header tzresult Lwt.t + +(** Same as {!nth_predecessor} with headers. *) +val nth_predecessor_header : + _ t -> + int -> + Layer1.header -> + (Layer1.header * Layer1.header list) tzresult Lwt.t + (** [get_tezos_reorg_for_new_head node_ctxt old_head new_head] returns the L1 reorganization between [old_head] and [new_head]. *) val get_tezos_reorg_for_new_head : diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/test/helpers/helpers.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/test/helpers/helpers.ml index 5a5b48da0d7a..85fb36ce7ef4 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/test/helpers/helpers.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/test/helpers/helpers.ml @@ -180,6 +180,24 @@ module Make (PVM : Pvm.S) = struct in return_unit + let head_of_level ~predecessor level = + let hash = block_hash_of_level level in + let timestamp = Time.Protocol.of_seconds (Int64.of_int32 level) in + let header : Block_header.shell_header = + { + level; + predecessor; + timestamp; + (* dummy values below *) + proto_level = 0; + validation_passes = 3; + operations_hash = Tezos_crypto.Hashed.Operation_list_list_hash.zero; + fitness = []; + context = Tezos_crypto.Hashed.Context_hash.zero; + } + in + {Layer1.hash; level; header} + let append_l2_block (node_ctxt : _ Node_context.t) messages = let open Lwt_result_syntax in let* predecessor_l2_block = @@ -191,25 +209,18 @@ module Make (PVM : Pvm.S) = struct | None -> failwith "No genesis block, please add one with add_l2_genesis_block" in - let level = - Raw_level.(to_int32 @@ succ predecessor_l2_block.header.level) - in - let hash = block_hash_of_level level in + let pred_level = Raw_level.to_int32 predecessor_l2_block.header.level in let predecessor = - Layer1. - { - hash = predecessor_l2_block.header.block_hash; - level = Raw_level.to_int32 predecessor_l2_block.header.level; - } + head_of_level + ~predecessor:predecessor_l2_block.header.predecessor + pred_level in - let head = Layer1.{hash; level} in - let predecessor_timestamp = - Time.Protocol.of_seconds (Int64.of_int32 level) + let head = + head_of_level ~predecessor:predecessor.hash (Int32.succ pred_level) in Daemon.Internal_for_tests.process_messages node_ctxt ~predecessor - ~predecessor_timestamp head messages end -- GitLab From 56033664f85a55c736361ad47467c168ffeaec70 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Mon, 17 Apr 2023 12:55:57 +0200 Subject: [PATCH 4/6] SCORU/Node/017: use block headers --- .../lib_sc_rollup_node/commitment.ml | 4 +- .../lib_sc_rollup_node/commitment_sig.ml | 2 +- .../lib_sc_rollup_node/daemon.ml | 106 +++++++++++------- .../lib_sc_rollup_node/inbox.ml | 53 ++++----- .../lib_sc_rollup_node/inbox.mli | 7 +- .../lib_sc_rollup_node/interpreter.ml | 15 ++- .../lib_sc_rollup_node/interpreter.mli | 4 +- .../lib_sc_rollup_node/layer1.ml | 30 ++++- .../lib_sc_rollup_node/layer1.mli | 12 +- .../lib_sc_rollup_node/node_context.ml | 24 +++- .../lib_sc_rollup_node/node_context.mli | 15 +++ .../test/helpers/helpers.ml | 37 +++--- 12 files changed, 202 insertions(+), 107 deletions(-) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/commitment.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/commitment.ml index 237c288a0ba9..e9fcb6c4e348 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/commitment.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/commitment.ml @@ -175,8 +175,8 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct Some commitment else return_none - let process_head (node_ctxt : _ Node_context.t) ~predecessor Layer1.{level; _} - ctxt = + let process_head (node_ctxt : _ Node_context.t) ~predecessor + Layer1.{level; header = _; _} ctxt = let open Lwt_result_syntax in let current_level = Raw_level.of_int32_exn level in let* commitment = diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/commitment_sig.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/commitment_sig.ml index 96f2306dd8f0..fccdc19b1854 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/commitment_sig.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/commitment_sig.ml @@ -50,7 +50,7 @@ module type S = sig val process_head : Node_context.rw -> predecessor:Block_hash.t -> - Layer1.head -> + Layer1.header -> Context.rw -> Protocol.Alpha_context.Sc_rollup.Commitment.Hash.t option tzresult Lwt.t diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/daemon.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/daemon.ml index c57632ef5789..d066e525e344 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/daemon.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/daemon.ml @@ -84,7 +84,7 @@ module Make (PVM : Pvm.S) = struct for the first time. {b Note}: this function does not process inboxes for the rollup, which is done instead by {!Inbox.process_head}. *) let process_included_l1_operation (type kind) (node_ctxt : Node_context.rw) - head ~source (operation : kind manager_operation) + (head : Layer1.header) ~source (operation : kind manager_operation) (result : kind successful_manager_operation_result) = let open Lwt_result_syntax in match (operation, result) with @@ -227,8 +227,8 @@ module Make (PVM : Pvm.S) = struct (_result : kind successful_manager_operation_result) = return_unit - let process_l1_operation (type kind) ~finalized node_ctxt head ~source - (operation : kind manager_operation) + let process_l1_operation (type kind) ~finalized node_ctxt + (head : Layer1.header) ~source (operation : kind manager_operation) (result : kind Apply_results.manager_operation_result) = let open Lwt_result_syntax in let is_for_my_rollup : type kind. kind manager_operation -> bool = function @@ -263,10 +263,11 @@ module Make (PVM : Pvm.S) = struct (* No action for non successful operations *) return_unit - let process_l1_block_operations ~finalized node_ctxt - (Layer1.{hash; _} as head) = + let process_l1_block_operations ~finalized node_ctxt (head : Layer1.header) = let open Lwt_result_syntax in - let* block = Layer1.fetch_tezos_block node_ctxt.Node_context.cctxt hash in + let* block = + Layer1.fetch_tezos_block node_ctxt.Node_context.cctxt head.hash + in let apply (type kind) accu ~source (operation : kind manager_operation) result = let open Lwt_result_syntax in @@ -286,46 +287,53 @@ module Make (PVM : Pvm.S) = struct in return_unit - let before_origination (node_ctxt : _ Node_context.t) Layer1.{level; _} = + let before_origination (node_ctxt : _ Node_context.t) (header : Layer1.header) + = let origination_level = Raw_level.to_int32 node_ctxt.genesis_info.level in - level < origination_level + header.level < origination_level let rec processed_finalized_block (node_ctxt : _ Node_context.t) - Layer1.({hash; level} as block) = + (block : Layer1.header) = let open Lwt_result_syntax in let* last_finalized = Node_context.get_finalized_head_opt node_ctxt in let already_finalized = match last_finalized with - | Some finalized -> level <= Raw_level.to_int32 finalized.header.level + | Some finalized -> + block.level <= Raw_level.to_int32 finalized.header.level | None -> false in unless (already_finalized || before_origination node_ctxt block) @@ fun () -> - let* predecessor = Node_context.get_predecessor_opt node_ctxt block in + let* predecessor = + Node_context.get_predecessor_header_opt node_ctxt block + in let* () = Option.iter_es (processed_finalized_block node_ctxt) predecessor in - let*! () = Daemon_event.head_processing hash level ~finalized:true in + let*! () = + Daemon_event.head_processing block.hash block.level ~finalized:true + in let* () = process_l1_block_operations ~finalized:true node_ctxt block in - let* () = Node_context.mark_finalized_head node_ctxt hash in + let* () = Node_context.mark_finalized_head node_ctxt block.hash in return_unit - let previous_context (node_ctxt : _ Node_context.t) ~predecessor - Layer1.{hash = _; level} = + let previous_context (node_ctxt : _ Node_context.t) + ~(predecessor : Layer1.header) = let open Lwt_result_syntax in - if level <= Raw_level.to_int32 node_ctxt.genesis_info.level then + if predecessor.level < Raw_level.to_int32 node_ctxt.genesis_info.level then (* This is before we have interpreted the boot sector, so we start with an empty context in genesis *) return (Context.empty node_ctxt.context) else Node_context.checkout_context node_ctxt predecessor.Layer1.hash - let rec process_head (node_ctxt : _ Node_context.t) - Layer1.({hash; level} as head) = + let rec process_head (node_ctxt : _ Node_context.t) (head : Layer1.header) = let open Lwt_result_syntax in - let* already_processed = Node_context.is_processed node_ctxt hash in + let* already_processed = Node_context.is_processed node_ctxt head.hash in unless (already_processed || before_origination node_ctxt head) @@ fun () -> - let*! () = Daemon_event.head_processing hash level ~finalized:false in - let* predecessor = Node_context.get_predecessor_opt node_ctxt head in + let*! () = + Daemon_event.head_processing head.hash head.level ~finalized:false + in + let* predecessor = Node_context.get_predecessor_header_opt node_ctxt head in match predecessor with | None -> (* Predecessor not available on the L1, which means the block does not @@ -333,14 +341,18 @@ module Make (PVM : Pvm.S) = struct return_unit | Some predecessor -> let* () = process_head node_ctxt predecessor in - let* ctxt = previous_context node_ctxt ~predecessor head in - let* () = Node_context.save_level node_ctxt head in + let* ctxt = previous_context node_ctxt ~predecessor in + let* () = + Node_context.save_level + node_ctxt + {Layer1.hash = head.hash; level = head.level} + in let* inbox_hash, inbox, inbox_witness, messages = Inbox.process_head node_ctxt ~predecessor head in let* () = when_ (Node_context.dal_supported node_ctxt) @@ fun () -> - Dal_slots_tracker.process_head node_ctxt head + Dal_slots_tracker.process_head node_ctxt (Layer1.head_of_header head) in let* () = process_l1_block_operations ~finalized:false node_ctxt head in (* Avoid storing and publishing commitments if the head is not final. *) @@ -362,7 +374,7 @@ module Make (PVM : Pvm.S) = struct head ctxt in - let level = Raw_level.of_int32_exn level in + let level = Raw_level.of_int32_exn head.level in let* previous_commitment_hash = if level = node_ctxt.genesis_info.Sc_rollup.Commitment.level then (* Previous commitment for rollup genesis is itself. *) @@ -374,7 +386,7 @@ module Make (PVM : Pvm.S) = struct let header = Sc_rollup_block. { - block_hash = hash; + block_hash = head.hash; level; predecessor = predecessor.hash; commitment_hash; @@ -388,7 +400,7 @@ module Make (PVM : Pvm.S) = struct Sc_rollup_block.{header; content = (); num_ticks; initial_tick} in let* finalized_block, _ = - Node_context.nth_predecessor + Node_context.nth_predecessor_header node_ctxt node_ctxt.block_finality_time head @@ -396,7 +408,7 @@ module Make (PVM : Pvm.S) = struct let* () = processed_finalized_block node_ctxt finalized_block in let* () = Node_context.save_l2_head node_ctxt l2_block in let*! () = - Daemon_event.new_head_processed hash (Raw_level.to_int32 level) + Daemon_event.new_head_processed head.hash (Raw_level.to_int32 level) in return_unit @@ -404,7 +416,7 @@ module Make (PVM : Pvm.S) = struct also processes any missing blocks that were not processed. Every time a head is processed we also process head~2 as finalized (which may recursively imply the processing of head~3, etc). *) - let on_layer_1_head node_ctxt head = + let on_layer_1_head node_ctxt (head : Layer1.header) = let open Lwt_result_syntax in let* old_head = Node_context.last_processed_head_opt node_ctxt in let old_head = @@ -424,8 +436,9 @@ module Make (PVM : Pvm.S) = struct in `Level (Int32.pred origination_level) in + let stripped_head = Layer1.head_of_header head in let*! reorg = - Node_context.get_tezos_reorg_for_new_head node_ctxt old_head head + Node_context.get_tezos_reorg_for_new_head node_ctxt old_head stripped_head in let*? reorg = match reorg with @@ -441,7 +454,7 @@ module Make (PVM : Pvm.S) = struct trace -> (* The reorganization could not be computed entirely because of missing info on the Layer 1. We fallback to a recursive process_head. *) - Ok {Reorg.no_reorg with new_chain = [head]} + Ok {Reorg.no_reorg with new_chain = [stripped_head]} | _ -> reorg in (* TODO: https://gitlab.com/tezos/tezos/-/issues/3348 @@ -457,13 +470,25 @@ module Make (PVM : Pvm.S) = struct }) in let*! () = Daemon_event.processing_heads_iteration reorg.new_chain in - let* () = List.iter_es (process_head node_ctxt) reorg.new_chain in + let get_header Layer1.{hash; level} = + if Block_hash.equal hash head.hash then return head + else + let+ header = Layer1.fetch_tezos_shell_header node_ctxt.cctxt hash in + {Layer1.hash; level; header} + in + let* () = + List.iter_es + (fun block -> + let* header = get_header block in + process_head node_ctxt header) + reorg.new_chain + in let* () = Components.Commitment.Publisher.publish_commitments () in let* () = Components.Commitment.Publisher.cement_commitments () in let*! () = Daemon_event.new_heads_processed reorg.new_chain in - let* () = Components.Refutation_coordinator.process head in + let* () = Components.Refutation_coordinator.process stripped_head in let* () = Components.Batcher.batch () in - let* () = Components.Batcher.new_head head in + let* () = Components.Batcher.new_head stripped_head in let*! () = Injector.inject ~header () in return_unit @@ -479,7 +504,9 @@ module Make (PVM : Pvm.S) = struct let*! () = message "Shutting down Commitment Publisher@." in let*! () = Components.Commitment.Publisher.shutdown () in Layer1.iter_heads node_ctxt.l1_ctxt @@ fun head -> - let* () = Components.Refutation_coordinator.process head in + let* () = + Components.Refutation_coordinator.process (Layer1.head_of_header head) + in let*! () = Injector.inject () in return_unit @@ -606,16 +633,17 @@ module Make (PVM : Pvm.S) = struct corresponding to [messages]. It is used by the unit tests to build an L2 chain. *) let process_messages (node_ctxt : _ Node_context.t) ~is_migration_block - ~predecessor ~predecessor_timestamp head messages = + ~predecessor head messages = let open Lwt_result_syntax in - let* ctxt = previous_context node_ctxt ~predecessor head in - let* () = Node_context.save_level node_ctxt head in + let* ctxt = previous_context node_ctxt ~predecessor in + let* () = + Node_context.save_level node_ctxt (Layer1.head_of_header head) + in let* inbox_hash, inbox, inbox_witness, messages = Inbox.Internal_for_tests.process_messages node_ctxt ~is_migration_block ~predecessor - ~predecessor_timestamp ~level:head.level messages in diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/inbox.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/inbox.ml index 39e235d2a6b8..fcafe33af0b0 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/inbox.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/inbox.ml @@ -78,22 +78,7 @@ let get_messages Node_context.{cctxt; _} head = block.operations {apply; apply_internal}) in - let ({predecessor; _} : Block_header.shell_header) = block.header.shell in - let* { - timestamp = predecessor_timestamp; - proto_level = predecessor_proto_level; - _; - } = - Layer1.fetch_tezos_shell_header cctxt predecessor - in - let is_migration_block = - block.header.shell.proto_level <> predecessor_proto_level - in - return - ( is_migration_block, - List.rev rev_messages, - predecessor_timestamp, - predecessor ) + return (List.rev rev_messages) let same_inbox_as_layer_1 node_ctxt head_hash inbox = let open Lwt_result_syntax in @@ -134,9 +119,12 @@ let add_messages ~is_migration_block ~predecessor_timestamp ~predecessor inbox messages_with_protocol_internal_messages ) let process_messages (node_ctxt : _ Node_context.t) ~is_migration_block - ~predecessor ~predecessor_timestamp ~level messages = + ~(predecessor : Layer1.header) ~level messages = let open Lwt_result_syntax in - let* inbox = Node_context.inbox_of_head node_ctxt predecessor in + let* inbox = + Node_context.inbox_of_head node_ctxt (Layer1.head_of_header predecessor) + in + let predecessor_timestamp = predecessor.header.timestamp in let inbox_metrics = Metrics.Inbox.metrics in Prometheus.Gauge.set inbox_metrics.head_inbox_level @@ Int32.to_float level ; let* ( _messages_history, @@ -167,25 +155,25 @@ let process_messages (node_ctxt : _ Node_context.t) ~is_migration_block return (inbox_hash, inbox, witness_hash, messages_with_protocol_internal_messages) -let process_head (node_ctxt : _ Node_context.t) ~predecessor - Layer1.{level; hash = head_hash} = +let process_head (node_ctxt : _ Node_context.t) ~(predecessor : Layer1.header) + (head : Layer1.header) = let open Lwt_result_syntax in let first_inbox_level = Raw_level.to_int32 node_ctxt.genesis_info.level |> Int32.succ in - if level >= first_inbox_level then ( + if head.level >= first_inbox_level then (* We compute the inbox of this block using the inbox of its predecessor. That way, the computation of inboxes is robust to chain reorganization. *) - let* ( is_migration_block, - collected_messages, - predecessor_timestamp, - predecessor_hash ) = - get_messages node_ctxt head_hash - in - assert (Block_hash.(predecessor.Layer1.hash = predecessor_hash)) ; + let* collected_messages = get_messages node_ctxt head.hash in let*! () = - Inbox_event.get_messages head_hash level (List.length collected_messages) + Inbox_event.get_messages + head.hash + head.level + (List.length collected_messages) + in + let is_migration_block = + head.header.proto_level <> predecessor.header.proto_level in let* (( _inbox_hash, inbox, @@ -195,12 +183,11 @@ let process_head (node_ctxt : _ Node_context.t) ~predecessor node_ctxt ~is_migration_block ~predecessor - ~predecessor_timestamp - ~level + ~level:head.level collected_messages in - let* () = same_inbox_as_layer_1 node_ctxt head_hash inbox in - return res) + let* () = same_inbox_as_layer_1 node_ctxt head.hash inbox in + return res else let* inbox = Node_context.genesis_inbox node_ctxt in return diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/inbox.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/inbox.mli index 33e895f82593..a723ad47e53e 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/inbox.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/inbox.mli @@ -42,8 +42,8 @@ open Sc_rollup [operations] of the [head] block. *) val process_head : Node_context.rw -> - predecessor:Layer1.head -> - Layer1.head -> + predecessor:Layer1.header -> + Layer1.header -> (Sc_rollup.Inbox.Hash.t * Sc_rollup.Inbox.t * Sc_rollup.Inbox_merkelized_payload_hashes.Hash.t @@ -88,8 +88,7 @@ module Internal_for_tests : sig val process_messages : Node_context.rw -> is_migration_block:bool -> - predecessor:Layer1.head -> - predecessor_timestamp:Timestamp.time -> + predecessor:Layer1.header -> level:int32 -> Sc_rollup.Inbox_message.t list -> (Sc_rollup.Inbox.Hash.t diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/interpreter.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/interpreter.ml index cc5fb9ca2338..41ad610367b3 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/interpreter.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/interpreter.ml @@ -38,8 +38,8 @@ module type S = sig val process_head : Node_context.rw -> 'a Context.t -> - predecessor:Layer1.head -> - Layer1.head -> + predecessor:Layer1.header -> + Layer1.header -> Sc_rollup.Inbox.t * Sc_rollup.Inbox_message.t list -> ('a Context.t * int * int64 * Sc_rollup.Tick.t) tzresult Lwt.t @@ -165,14 +165,19 @@ module Make (PVM : Pvm.S) : S with module PVM = PVM = struct (** [process_head node_ctxt ctxt ~predecessor head] runs the PVM for the given head. *) - let process_head (node_ctxt : _ Node_context.t) ctxt ~predecessor head - inbox_messages = + let process_head (node_ctxt : _ Node_context.t) ctxt + ~(predecessor : Layer1.header) (head : Layer1.header) inbox_messages = let open Lwt_result_syntax in let first_inbox_level = Raw_level.to_int32 node_ctxt.genesis_info.level |> Int32.succ in if head.Layer1.level >= first_inbox_level then - transition_pvm node_ctxt ctxt predecessor head inbox_messages + transition_pvm + node_ctxt + ctxt + (Layer1.head_of_header predecessor) + (Layer1.head_of_header head) + inbox_messages else if head.Layer1.level = Raw_level.to_int32 node_ctxt.genesis_info.level then let* ctxt, state = genesis_state head.hash node_ctxt ctxt in diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/interpreter.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/interpreter.mli index 3bc4a0aa7aee..99dd231a3ab9 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/interpreter.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/interpreter.mli @@ -45,8 +45,8 @@ module type S = sig val process_head : Node_context.rw -> 'a Context.t -> - predecessor:Layer1.head -> - Layer1.head -> + predecessor:Layer1.header -> + Layer1.header -> Sc_rollup.Inbox.t * Sc_rollup.Inbox_message.t list -> ('a Context.t * int * int64 * Sc_rollup.Tick.t) tzresult Lwt.t diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.ml index 70c02794a585..501d6c403e33 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.ml @@ -58,14 +58,31 @@ let () = *) +type header = { + hash : Block_hash.t; + level : int32; + header : Block_header.shell_header; +} + +let header_encoding = + let open Data_encoding in + conv + (fun {hash; level = _; header} -> (hash, header)) + (fun (hash, header) -> {hash; level = header.level; header}) + (merge_objs + (obj1 (req "hash" Block_hash.encoding)) + Block_header.shell_header_encoding) + type head = {hash : Block_hash.t; level : int32} let head_encoding = - Data_encoding.( - conv - (fun {hash; level} -> (hash, level)) - (fun (hash, level) -> {hash; level}) - (obj2 (req "hash" Block_hash.encoding) (req "level" Data_encoding.int32))) + let open Data_encoding in + conv + (fun {hash; level} -> (hash, level)) + (fun (hash, level) -> {hash; level}) + (obj2 (req "hash" Block_hash.encoding) (req "level" Data_encoding.int32)) + +let head_of_header {hash; level; header = _} = {hash; level} module Blocks_cache = Aches_lwt.Lache.Make_option @@ -79,7 +96,8 @@ let blocks_cache : blocks_cache = Blocks_cache.create 32 include Octez_crawler.Layer_1 let iter_heads l1_ctxt f = - iter_heads l1_ctxt @@ fun (hash, {shell = {level; _}; _}) -> f {hash; level} + iter_heads l1_ctxt @@ fun (hash, {shell = {level; _} as header; _}) -> + f {hash; level; header} (** diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.mli index c9697e4fe5c0..b6f34af8ddac 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.mli @@ -30,10 +30,20 @@ subscribing to the head monitoring RPC offered by the Tezos node. *) +type header = { + hash : Block_hash.t; + level : int32; + header : Block_header.shell_header; +} + type head = {hash : Block_hash.t; level : int32} +val header_encoding : header Data_encoding.t + val head_encoding : head Data_encoding.t +val head_of_header : header -> head + include module type of Octez_crawler.Layer_1 (* TODO: https://gitlab.com/tezos/tezos/-/issues/3311 @@ -43,7 +53,7 @@ include module type of Octez_crawler.Layer_1 chain. In case of a disconnection with the layer 1 node, it reconnects automatically. If [f] returns an error (other than a disconnection) it, [iter_heads] terminates and returns the error. *) -val iter_heads : t -> (head -> unit tzresult Lwt.t) -> unit tzresult Lwt.t +val iter_heads : t -> (header -> unit tzresult Lwt.t) -> unit tzresult Lwt.t (** {2 Helpers } *) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.ml index 7d25d833265f..d7909111fed8 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.ml @@ -455,12 +455,24 @@ let nth_predecessor node_ctxt n block = in (head_of_block_level res, List.map head_of_block_level preds) +let header_of_head node_ctxt Layer1.{hash; level} = + let open Lwt_result_syntax in + let+ header = Layer1.fetch_tezos_shell_header node_ctxt.cctxt hash in + {Layer1.hash; level; header} + +let nth_predecessor_header node_ctxt n block = + let open Lwt_result_syntax in + let* res, preds = nth_predecessor node_ctxt n (Layer1.head_of_header block) in + let* res = header_of_head node_ctxt res + and* preds = List.map_ep (header_of_head node_ctxt) preds in + return (res, preds) + let get_tezos_reorg_for_new_head node_ctxt old_head new_head = let open Lwt_result_syntax in let old_head = match old_head with | `Level l -> `Level l - | `Head h -> `Head (block_level_of_head h) + | `Head Layer1.{hash; level} -> `Head (hash, level) in let+ reorg = Layer1.get_tezos_reorg_for_new_head @@ -481,6 +493,16 @@ let get_predecessor node_ctxt head = let+ res = get_predecessor node_ctxt (block_level_of_head head) in head_of_block_level res +let get_predecessor_header_opt node_ctxt head = + let open Lwt_result_syntax in + let* res = get_predecessor_opt node_ctxt (Layer1.head_of_header head) in + Option.map_es (header_of_head node_ctxt) res + +let get_predecessor_header node_ctxt head = + let open Lwt_result_syntax in + let* res = get_predecessor node_ctxt (Layer1.head_of_header head) in + header_of_head node_ctxt res + (* TODO: https://gitlab.com/tezos/tezos/-/issues/4128 Unit test the function tick_search. *) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.mli index 3d2bb256c51d..2bbf577df8fe 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.mli @@ -222,6 +222,21 @@ val get_predecessor : _ t -> Layer1.head -> Layer1.head tzresult Lwt.t val nth_predecessor : _ t -> int -> Layer1.head -> (Layer1.head * Layer1.head list) tzresult Lwt.t +(** Same as {!get_predecessor_opt} with headers. *) +val get_predecessor_header_opt : + _ t -> Layer1.header -> Layer1.header option tzresult Lwt.t + +(** Same as {!get_predecessor} with headers. *) +val get_predecessor_header : + _ t -> Layer1.header -> Layer1.header tzresult Lwt.t + +(** Same as {!nth_predecessor} with headers. *) +val nth_predecessor_header : + _ t -> + int -> + Layer1.header -> + (Layer1.header * Layer1.header list) tzresult Lwt.t + (** [get_tezos_reorg_for_new_head node_ctxt old_head new_head] returns the L1 reorganization between [old_head] and [new_head]. *) val get_tezos_reorg_for_new_head : diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/test/helpers/helpers.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/test/helpers/helpers.ml index 202233df253f..1178838d8360 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/test/helpers/helpers.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/test/helpers/helpers.ml @@ -180,6 +180,24 @@ module Make (PVM : Pvm.S) = struct in return_unit + let head_of_level ~predecessor level = + let hash = block_hash_of_level level in + let timestamp = Time.Protocol.of_seconds (Int64.of_int32 level) in + let header : Block_header.shell_header = + { + level; + predecessor; + timestamp; + (* dummy values below *) + proto_level = 0; + validation_passes = 3; + operations_hash = Tezos_crypto.Hashed.Operation_list_list_hash.zero; + fitness = []; + context = Tezos_crypto.Hashed.Context_hash.zero; + } + in + {Layer1.hash; level; header} + let append_l2_block (node_ctxt : _ Node_context.t) ?(is_migration_block = false) messages = let open Lwt_result_syntax in @@ -192,26 +210,19 @@ module Make (PVM : Pvm.S) = struct | None -> failwith "No genesis block, please add one with add_l2_genesis_block" in - let level = - Raw_level.(to_int32 @@ succ predecessor_l2_block.header.level) - in - let hash = block_hash_of_level level in + let pred_level = Raw_level.to_int32 predecessor_l2_block.header.level in let predecessor = - Layer1. - { - hash = predecessor_l2_block.header.block_hash; - level = Raw_level.to_int32 predecessor_l2_block.header.level; - } + head_of_level + ~predecessor:predecessor_l2_block.header.predecessor + pred_level in - let head = Layer1.{hash; level} in - let predecessor_timestamp = - Time.Protocol.of_seconds (Int64.of_int32 level) + let head = + head_of_level ~predecessor:predecessor.hash (Int32.succ pred_level) in Daemon.Internal_for_tests.process_messages node_ctxt ~is_migration_block ~predecessor - ~predecessor_timestamp head messages end -- GitLab From 711e33e355542936bcf61afd23ca84ecad2a02ba Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 18 Apr 2023 10:35:53 +0200 Subject: [PATCH 5/6] Injector: only need shell header --- src/lib_injector/injector_sigs.ml | 7 +++++-- src/proto_016_PtMumbai/lib_sc_rollup_node/daemon.ml | 11 +---------- src/proto_016_PtMumbai/lib_sc_rollup_node/injector.ml | 10 ++++------ src/proto_017_PtNairob/lib_sc_rollup_node/daemon.ml | 11 +---------- src/proto_017_PtNairob/lib_sc_rollup_node/injector.ml | 10 ++++------ src/proto_alpha/lib_sc_rollup_node/daemon.ml | 11 +---------- src/proto_alpha/lib_sc_rollup_node/injector.ml | 10 ++++------ 7 files changed, 20 insertions(+), 50 deletions(-) diff --git a/src/lib_injector/injector_sigs.ml b/src/lib_injector/injector_sigs.ml index b3a1bd85ec88..f36dd6d3ae29 100644 --- a/src/lib_injector/injector_sigs.ml +++ b/src/lib_injector/injector_sigs.ml @@ -236,7 +236,7 @@ module type PROTOCOL_CLIENT = sig (** [time_until_next_block state block_header] computes the time until the block following [block_header], with respect to the current time. *) val time_until_next_block : - state -> Tezos_base.Block_header.t option -> Ptime.span + state -> Tezos_base.Block_header.shell_header option -> Ptime.span end (** Output signature for functor {!Injector_functor.Make}. *) @@ -332,7 +332,10 @@ module type S = sig operations. [header] must be provided for the [`Delay_block] strategy to compute the next block timestamp. *) val inject : - ?tags:tag list -> ?header:Tezos_base.Block_header.t -> unit -> unit Lwt.t + ?tags:tag list -> + ?header:Tezos_base.Block_header.shell_header -> + unit -> + unit Lwt.t (** Shutdown the injectors, waiting for the ongoing request to be processed. *) val shutdown : unit -> unit Lwt.t diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/daemon.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/daemon.ml index 058db320e91b..8d1270b24f8e 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/daemon.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/daemon.ml @@ -463,15 +463,6 @@ module Make (PVM : Pvm.S) = struct (* TODO: https://gitlab.com/tezos/tezos/-/issues/3348 Rollback state information on reorganization, i.e. for reorg.old_chain. *) - let* new_head = Layer1.fetch_tezos_block node_ctxt.cctxt head.Layer1.hash in - let header = - Block_header.( - raw - { - shell = new_head.header.shell; - protocol_data = new_head.header.protocol_data; - }) - in let*! () = Daemon_event.processing_heads_iteration reorg.new_chain in let get_header Layer1.{hash; level} = if Block_hash.equal hash head.hash then return head @@ -492,7 +483,7 @@ module Make (PVM : Pvm.S) = struct let* () = Components.Refutation_coordinator.process stripped_head in let* () = Components.Batcher.batch () in let* () = Components.Batcher.new_head stripped_head in - let*! () = Injector.inject ~header () in + let*! () = Injector.inject ~header:head.header () in return_unit let daemonize (node_ctxt : _ Node_context.t) = diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/injector.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/injector.ml index 1c10f32696dd..bc0d0cf333a8 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/injector.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/injector.ml @@ -415,7 +415,7 @@ module Proto_client = struct Data_encoding.Binary.to_bytes_exn Operation.encoding op let time_until_next_block (node_ctxt : Node_context.ro) - (header : Tezos_base.Block_header.t option) = + (header : Tezos_base.Block_header.shell_header option) = let open Result_syntax in let Constants.Parametric.{minimal_block_delay; delay_increment_per_round; _} = @@ -432,12 +432,10 @@ module Proto_client = struct ~first_round_duration:minimal_block_delay ~delay_increment_per_round in - let* predecessor_round = - Fitness.round_from_raw header.shell.fitness - in + let* predecessor_round = Fitness.round_from_raw header.fitness in Round.timestamp_of_round durations - ~predecessor_timestamp:header.shell.timestamp + ~predecessor_timestamp:header.timestamp ~predecessor_round ~round:Round.zero in @@ -447,7 +445,7 @@ module Proto_client = struct ~default: (WithExceptions.Result.get_ok ~loc:__LOC__ - Timestamp.(header.shell.timestamp +? minimal_block_delay)) + Timestamp.(header.timestamp +? minimal_block_delay)) in Ptime.diff (Time.System.of_protocol_exn next_level_timestamp) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/daemon.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/daemon.ml index d066e525e344..c68f10befc14 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/daemon.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/daemon.ml @@ -460,15 +460,6 @@ module Make (PVM : Pvm.S) = struct (* TODO: https://gitlab.com/tezos/tezos/-/issues/3348 Rollback state information on reorganization, i.e. for reorg.old_chain. *) - let* new_head = Layer1.fetch_tezos_block node_ctxt.cctxt head.Layer1.hash in - let header = - Block_header.( - raw - { - shell = new_head.header.shell; - protocol_data = new_head.header.protocol_data; - }) - in let*! () = Daemon_event.processing_heads_iteration reorg.new_chain in let get_header Layer1.{hash; level} = if Block_hash.equal hash head.hash then return head @@ -489,7 +480,7 @@ module Make (PVM : Pvm.S) = struct let* () = Components.Refutation_coordinator.process stripped_head in let* () = Components.Batcher.batch () in let* () = Components.Batcher.new_head stripped_head in - let*! () = Injector.inject ~header () in + let*! () = Injector.inject ~header:head.header () in return_unit let daemonize (node_ctxt : _ Node_context.t) = diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/injector.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/injector.ml index 1c10f32696dd..bc0d0cf333a8 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/injector.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/injector.ml @@ -415,7 +415,7 @@ module Proto_client = struct Data_encoding.Binary.to_bytes_exn Operation.encoding op let time_until_next_block (node_ctxt : Node_context.ro) - (header : Tezos_base.Block_header.t option) = + (header : Tezos_base.Block_header.shell_header option) = let open Result_syntax in let Constants.Parametric.{minimal_block_delay; delay_increment_per_round; _} = @@ -432,12 +432,10 @@ module Proto_client = struct ~first_round_duration:minimal_block_delay ~delay_increment_per_round in - let* predecessor_round = - Fitness.round_from_raw header.shell.fitness - in + let* predecessor_round = Fitness.round_from_raw header.fitness in Round.timestamp_of_round durations - ~predecessor_timestamp:header.shell.timestamp + ~predecessor_timestamp:header.timestamp ~predecessor_round ~round:Round.zero in @@ -447,7 +445,7 @@ module Proto_client = struct ~default: (WithExceptions.Result.get_ok ~loc:__LOC__ - Timestamp.(header.shell.timestamp +? minimal_block_delay)) + Timestamp.(header.timestamp +? minimal_block_delay)) in Ptime.diff (Time.System.of_protocol_exn next_level_timestamp) diff --git a/src/proto_alpha/lib_sc_rollup_node/daemon.ml b/src/proto_alpha/lib_sc_rollup_node/daemon.ml index d066e525e344..c68f10befc14 100644 --- a/src/proto_alpha/lib_sc_rollup_node/daemon.ml +++ b/src/proto_alpha/lib_sc_rollup_node/daemon.ml @@ -460,15 +460,6 @@ module Make (PVM : Pvm.S) = struct (* TODO: https://gitlab.com/tezos/tezos/-/issues/3348 Rollback state information on reorganization, i.e. for reorg.old_chain. *) - let* new_head = Layer1.fetch_tezos_block node_ctxt.cctxt head.Layer1.hash in - let header = - Block_header.( - raw - { - shell = new_head.header.shell; - protocol_data = new_head.header.protocol_data; - }) - in let*! () = Daemon_event.processing_heads_iteration reorg.new_chain in let get_header Layer1.{hash; level} = if Block_hash.equal hash head.hash then return head @@ -489,7 +480,7 @@ module Make (PVM : Pvm.S) = struct let* () = Components.Refutation_coordinator.process stripped_head in let* () = Components.Batcher.batch () in let* () = Components.Batcher.new_head stripped_head in - let*! () = Injector.inject ~header () in + let*! () = Injector.inject ~header:head.header () in return_unit let daemonize (node_ctxt : _ Node_context.t) = diff --git a/src/proto_alpha/lib_sc_rollup_node/injector.ml b/src/proto_alpha/lib_sc_rollup_node/injector.ml index 1c10f32696dd..bc0d0cf333a8 100644 --- a/src/proto_alpha/lib_sc_rollup_node/injector.ml +++ b/src/proto_alpha/lib_sc_rollup_node/injector.ml @@ -415,7 +415,7 @@ module Proto_client = struct Data_encoding.Binary.to_bytes_exn Operation.encoding op let time_until_next_block (node_ctxt : Node_context.ro) - (header : Tezos_base.Block_header.t option) = + (header : Tezos_base.Block_header.shell_header option) = let open Result_syntax in let Constants.Parametric.{minimal_block_delay; delay_increment_per_round; _} = @@ -432,12 +432,10 @@ module Proto_client = struct ~first_round_duration:minimal_block_delay ~delay_increment_per_round in - let* predecessor_round = - Fitness.round_from_raw header.shell.fitness - in + let* predecessor_round = Fitness.round_from_raw header.fitness in Round.timestamp_of_round durations - ~predecessor_timestamp:header.shell.timestamp + ~predecessor_timestamp:header.timestamp ~predecessor_round ~round:Round.zero in @@ -447,7 +445,7 @@ module Proto_client = struct ~default: (WithExceptions.Result.get_ok ~loc:__LOC__ - Timestamp.(header.shell.timestamp +? minimal_block_delay)) + Timestamp.(header.timestamp +? minimal_block_delay)) in Ptime.diff (Time.System.of_protocol_exn next_level_timestamp) -- GitLab From 4da49c573f8e57d727cf4fc3daa7153e714fb431 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 18 Apr 2023 11:21:46 +0200 Subject: [PATCH 6/6] SCORU/Node: preemptively cache block headers when monitoring --- .../lib_sc_rollup_node/layer1.ml | 16 ++++++++++------ .../lib_sc_rollup_node/layer1.mli | 4 ++++ .../lib_sc_rollup_node/layer1.ml | 16 ++++++++++------ .../lib_sc_rollup_node/layer1.mli | 4 ++++ src/proto_alpha/lib_sc_rollup_node/layer1.ml | 16 ++++++++++------ src/proto_alpha/lib_sc_rollup_node/layer1.mli | 4 ++++ 6 files changed, 42 insertions(+), 18 deletions(-) diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.ml index d3ddb6c753c5..c551b9252139 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.ml @@ -90,13 +90,22 @@ module Blocks_cache = type blocks_cache = Alpha_block_services.block_info Blocks_cache.t +type headers_cache = Block_header.shell_header Blocks_cache.t + (** Global blocks cache for the smart rollup node. *) let blocks_cache : blocks_cache = Blocks_cache.create 32 +(** Global block headers cache for the smart rollup node. *) +let headers_cache : headers_cache = Blocks_cache.create 32 + include Octez_crawler.Layer_1 +let cache_shell_header hash header = + Blocks_cache.put headers_cache hash (Lwt.return_some header) + let iter_heads l1_ctxt f = iter_heads l1_ctxt @@ fun (hash, {shell = {level; _} as header; _}) -> + cache_shell_header hash header ; f {hash; level; header} (** @@ -129,12 +138,7 @@ let fetch_tezos_shell_header cctxt hash = | Ok shell_header -> return_some shell_header in let+ shell_header = - let res = - Blocks_cache.bind blocks_cache hash (function - | Some block_info -> Lwt.return_some block_info.header.shell - | None -> Lwt.return_none) - in - match res with Some lwt -> lwt | None -> fetch hash + Blocks_cache.bind_or_put headers_cache hash fetch Lwt.return in match (shell_header, !errors) with | None, None -> diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.mli index b6f34af8ddac..845e97a4f1c3 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.mli @@ -57,6 +57,10 @@ val iter_heads : t -> (header -> unit tzresult Lwt.t) -> unit tzresult Lwt.t (** {2 Helpers } *) +(** [cache_shell_header hash header] saves in the local cache the shell [header] + for the block [hash]. *) +val cache_shell_header : Block_hash.t -> Block_header.shell_header -> unit + (** [fetch_tezos_shell_header cctxt hash] returns the block shell header of [hash]. Looks for the block in the blocks cache first, and fetches it from the L1 node otherwise. *) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.ml index 501d6c403e33..517fe9692479 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.ml @@ -90,13 +90,22 @@ module Blocks_cache = type blocks_cache = Alpha_block_services.block_info Blocks_cache.t +type headers_cache = Block_header.shell_header Blocks_cache.t + (** Global blocks cache for the smart rollup node. *) let blocks_cache : blocks_cache = Blocks_cache.create 32 +(** Global block headers cache for the smart rollup node. *) +let headers_cache : headers_cache = Blocks_cache.create 32 + include Octez_crawler.Layer_1 +let cache_shell_header hash header = + Blocks_cache.put headers_cache hash (Lwt.return_some header) + let iter_heads l1_ctxt f = iter_heads l1_ctxt @@ fun (hash, {shell = {level; _} as header; _}) -> + cache_shell_header hash header ; f {hash; level; header} (** @@ -129,12 +138,7 @@ let fetch_tezos_shell_header cctxt hash = | Ok shell_header -> return_some shell_header in let+ shell_header = - let res = - Blocks_cache.bind blocks_cache hash (function - | Some block_info -> Lwt.return_some block_info.header.shell - | None -> Lwt.return_none) - in - match res with Some lwt -> lwt | None -> fetch hash + Blocks_cache.bind_or_put headers_cache hash fetch Lwt.return in match (shell_header, !errors) with | None, None -> diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.mli index b6f34af8ddac..845e97a4f1c3 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.mli @@ -57,6 +57,10 @@ val iter_heads : t -> (header -> unit tzresult Lwt.t) -> unit tzresult Lwt.t (** {2 Helpers } *) +(** [cache_shell_header hash header] saves in the local cache the shell [header] + for the block [hash]. *) +val cache_shell_header : Block_hash.t -> Block_header.shell_header -> unit + (** [fetch_tezos_shell_header cctxt hash] returns the block shell header of [hash]. Looks for the block in the blocks cache first, and fetches it from the L1 node otherwise. *) diff --git a/src/proto_alpha/lib_sc_rollup_node/layer1.ml b/src/proto_alpha/lib_sc_rollup_node/layer1.ml index 501d6c403e33..517fe9692479 100644 --- a/src/proto_alpha/lib_sc_rollup_node/layer1.ml +++ b/src/proto_alpha/lib_sc_rollup_node/layer1.ml @@ -90,13 +90,22 @@ module Blocks_cache = type blocks_cache = Alpha_block_services.block_info Blocks_cache.t +type headers_cache = Block_header.shell_header Blocks_cache.t + (** Global blocks cache for the smart rollup node. *) let blocks_cache : blocks_cache = Blocks_cache.create 32 +(** Global block headers cache for the smart rollup node. *) +let headers_cache : headers_cache = Blocks_cache.create 32 + include Octez_crawler.Layer_1 +let cache_shell_header hash header = + Blocks_cache.put headers_cache hash (Lwt.return_some header) + let iter_heads l1_ctxt f = iter_heads l1_ctxt @@ fun (hash, {shell = {level; _} as header; _}) -> + cache_shell_header hash header ; f {hash; level; header} (** @@ -129,12 +138,7 @@ let fetch_tezos_shell_header cctxt hash = | Ok shell_header -> return_some shell_header in let+ shell_header = - let res = - Blocks_cache.bind blocks_cache hash (function - | Some block_info -> Lwt.return_some block_info.header.shell - | None -> Lwt.return_none) - in - match res with Some lwt -> lwt | None -> fetch hash + Blocks_cache.bind_or_put headers_cache hash fetch Lwt.return in match (shell_header, !errors) with | None, None -> diff --git a/src/proto_alpha/lib_sc_rollup_node/layer1.mli b/src/proto_alpha/lib_sc_rollup_node/layer1.mli index b6f34af8ddac..845e97a4f1c3 100644 --- a/src/proto_alpha/lib_sc_rollup_node/layer1.mli +++ b/src/proto_alpha/lib_sc_rollup_node/layer1.mli @@ -57,6 +57,10 @@ val iter_heads : t -> (header -> unit tzresult Lwt.t) -> unit tzresult Lwt.t (** {2 Helpers } *) +(** [cache_shell_header hash header] saves in the local cache the shell [header] + for the block [hash]. *) +val cache_shell_header : Block_hash.t -> Block_header.shell_header -> unit + (** [fetch_tezos_shell_header cctxt hash] returns the block shell header of [hash]. Looks for the block in the blocks cache first, and fetches it from the L1 node otherwise. *) -- GitLab