From 0196d0f09a6210790d933a736fa16eedfbd386cd Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 25 May 2023 09:55:55 +0200 Subject: [PATCH 1/7] Crawler: remove useless error monad --- src/lib_crawler/layer_1.ml | 8 ++++---- src/lib_crawler/layer_1.mli | 2 +- src/lib_injector/injector_functor.ml | 2 +- src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.ml | 2 +- src/proto_017_PtNairob/lib_sc_rollup_node/node_context.ml | 2 +- src/proto_alpha/lib_sc_rollup_node/node_context.ml | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lib_crawler/layer_1.ml b/src/lib_crawler/layer_1.ml index fd424a189c2d..0cadd52561a0 100644 --- a/src/lib_crawler/layer_1.ml +++ b/src/lib_crawler/layer_1.ml @@ -100,8 +100,8 @@ let rec connect ~name ?(count = 0) ~delay cctxt = connect ~name ~delay ~count:(count + 1) cctxt let start ~name ~reconnection_delay (cctxt : #Client_context.full) = - let open Lwt_result_syntax in - let*! () = Layer1_event.starting ~name in + let open Lwt_syntax in + let* () = Layer1_event.starting ~name in let+ heads, stopper = connect ~name ~delay:reconnection_delay cctxt in { name; @@ -113,7 +113,7 @@ let start ~name ~reconnection_delay (cctxt : #Client_context.full) = } let reconnect l1_ctxt = - let open Lwt_result_syntax in + let open Lwt_syntax in let* heads, stopper = connect ~name:l1_ctxt.name @@ -165,7 +165,7 @@ let iter_heads l1_ctxt f = in when_ l1_ctxt.running @@ fun () -> let*! () = Layer1_event.connection_lost ~name:l1_ctxt.name in - let* l1_ctxt = reconnect l1_ctxt in + let*! l1_ctxt = reconnect l1_ctxt in loop l1_ctxt in Lwt.catch diff --git a/src/lib_crawler/layer_1.mli b/src/lib_crawler/layer_1.mli index bb50c95d567c..8571018d1b1b 100644 --- a/src/lib_crawler/layer_1.mli +++ b/src/lib_crawler/layer_1.mli @@ -43,7 +43,7 @@ val start : name:string -> reconnection_delay:float -> #Client_context.full -> - t tzresult Lwt.t + t Lwt.t (** [shutdown t] properly shuts the layer 1 down. *) val shutdown : t -> unit Lwt.t diff --git a/src/lib_injector/injector_functor.ml b/src/lib_injector/injector_functor.ml index 16961853ff51..cc5fb99770ba 100644 --- a/src/lib_injector/injector_functor.ml +++ b/src/lib_injector/injector_functor.ml @@ -1440,7 +1440,7 @@ module Make (Parameters : PARAMETERS) = struct Signature.Public_key_hash.Map.empty signers in - let* l1_ctxt = Layer_1.start ~name:"injector" ~reconnection_delay cctxt in + let*! l1_ctxt = Layer_1.start ~name:"injector" ~reconnection_delay cctxt in let* head_protocols = protocols_of_head cctxt in let* () = Signature.Public_key_hash.Map.iter_es 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 5bfd2bcaddb4..8d0bc699e189 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 @@ -315,7 +315,7 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file Context.load mode (Configuration.default_context_dir data_dir) in let* () = Context.Rollup.check_or_set_address mode context rollup_address in - let* l1_ctxt = + let*! l1_ctxt = Layer1.start ~name:"sc_rollup_node" ~reconnection_delay cctxt in let publisher = Configuration.Operator_purpose_map.find Publish operators in 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 d344d4301c54..29283f359e9d 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 @@ -315,7 +315,7 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file Context.load mode (Configuration.default_context_dir data_dir) in let* () = Context.Rollup.check_or_set_address mode context rollup_address in - let* l1_ctxt = + let*! l1_ctxt = Layer1.start ~name:"sc_rollup_node" ~reconnection_delay cctxt in let publisher = Configuration.Operator_purpose_map.find Publish operators in 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 733d325c437d..d4f5afbd72c4 100644 --- a/src/proto_alpha/lib_sc_rollup_node/node_context.ml +++ b/src/proto_alpha/lib_sc_rollup_node/node_context.ml @@ -302,7 +302,7 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file Context.load mode (Configuration.default_context_dir data_dir) in let* () = Context.Rollup.check_or_set_address mode context rollup_address in - let* l1_ctxt = + let*! l1_ctxt = Layer1.start ~name:"sc_rollup_node" ~reconnection_delay cctxt in let publisher = Configuration.Operator_purpose_map.find Publish operators in -- GitLab From 1e1a63a71b5514d55319c958cbf647610cb1a173 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 25 May 2023 09:56:48 +0200 Subject: [PATCH 2/7] Crawler: allow to monitor blocks of protocol and wait for first --- src/lib_crawler/layer_1.ml | 32 ++++++++++++++++++++++++++------ src/lib_crawler/layer_1.mli | 16 +++++++++++----- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/lib_crawler/layer_1.ml b/src/lib_crawler/layer_1.ml index 0cadd52561a0..524c59462d84 100644 --- a/src/lib_crawler/layer_1.ml +++ b/src/lib_crawler/layer_1.ml @@ -58,6 +58,7 @@ let () = type t = { name : string; + protocols : Protocol_hash.t list option; reconnection_delay : float; heads : (Block_hash.t * Block_header.t) Lwt_stream.t; cctxt : Client_context.full; @@ -65,7 +66,7 @@ type t = { mutable running : bool; } -let rec connect ~name ?(count = 0) ~delay cctxt = +let rec connect ~name ?(count = 0) ~delay ~protocols cctxt = let open Lwt_syntax in let* () = if count = 0 then return_unit @@ -83,7 +84,9 @@ let rec connect ~name ?(count = 0) ~delay cctxt = let* () = Layer1_event.wait_reconnect ~name delay in Lwt_unix.sleep delay in - let* res = Tezos_shell_services.Monitor_services.heads cctxt cctxt#chain in + let* res = + Tezos_shell_services.Monitor_services.heads ?protocols cctxt cctxt#chain + in match res with | Ok (heads, stopper) -> let heads = @@ -94,21 +97,24 @@ let rec connect ~name ?(count = 0) ~delay cctxt = (hash, header)) heads in - return_ok (heads, stopper) + return (heads, stopper) | Error e -> let* () = Layer1_event.cannot_connect ~name ~count e in - connect ~name ~delay ~count:(count + 1) cctxt + connect ~name ~delay ~protocols ~count:(count + 1) cctxt -let start ~name ~reconnection_delay (cctxt : #Client_context.full) = +let start ~name ~reconnection_delay ?protocols (cctxt : #Client_context.full) = let open Lwt_syntax in let* () = Layer1_event.starting ~name in - let+ heads, stopper = connect ~name ~delay:reconnection_delay cctxt in + let+ heads, stopper = + connect ~name ~delay:reconnection_delay ~protocols cctxt + in { name; cctxt = (cctxt :> Client_context.full); heads; stopper; reconnection_delay; + protocols; running = true; } @@ -119,6 +125,7 @@ let reconnect l1_ctxt = ~name:l1_ctxt.name ~count:1 ~delay:l1_ctxt.reconnection_delay + ~protocols:l1_ctxt.protocols l1_ctxt.cctxt in return {l1_ctxt with heads; stopper} @@ -172,6 +179,18 @@ let iter_heads l1_ctxt f = (fun () -> Lwt.no_cancel @@ loop l1_ctxt) (function Iter_error e -> Lwt.return_error e | exn -> fail (Exn exn)) +let wait_first l1_ctxt = + let rec loop l1_ctxt = + let open Lwt_syntax in + let* head = Lwt_stream.peek l1_ctxt.heads in + match head with + | Some head -> return head + | None -> + let* l1_ctxt = reconnect l1_ctxt in + loop l1_ctxt + in + Lwt.no_cancel @@ loop l1_ctxt + (** [predecessors_of_blocks hashes] given a list of successive block hashes, from newest to oldest, returns an associative list that associates a hash to its predecessor in this list. *) @@ -325,6 +344,7 @@ module Internal_for_tests = struct heads; cctxt = (cctxt :> Client_context.full); stopper = Fun.id; + protocols = None; running = false; } end diff --git a/src/lib_crawler/layer_1.mli b/src/lib_crawler/layer_1.mli index 8571018d1b1b..f5573d58d6e3 100644 --- a/src/lib_crawler/layer_1.mli +++ b/src/lib_crawler/layer_1.mli @@ -34,14 +34,16 @@ type t (** {2 Monitoring the Layer 1 chain} *) -(** [start ~name ~reconnection_delay cctxt] connects to a Tezos node and starts - monitoring new heads. One can iterate on the heads by calling {!iter_heads} - on its result. [reconnection_delay] gives an initial delay for the - reconnection which is used in an exponential backoff. The [name] is used to - differentiate events. *) +(** [start ~name ~reconnection_delay ?protocols cctxt] connects to a Tezos node + and starts monitoring new heads. One can iterate on the heads by calling + {!iter_heads} on its result. [reconnection_delay] gives an initial delay for + the reconnection which is used in an exponential backoff. The [name] is used + to differentiate events. If [protocols] is provided, only heads of these + protocols will be monitored. *) val start : name:string -> reconnection_delay:float -> + ?protocols:Protocol_hash.t list -> #Client_context.full -> t Lwt.t @@ -57,6 +59,10 @@ val iter_heads : (Block_hash.t * Block_header.t -> unit tzresult Lwt.t) -> unit tzresult Lwt.t +(** [wait_first t] waits for the first head to appear in the stream and + returns it. *) +val wait_first : t -> (Block_hash.t * Block_header.t) Lwt.t + (** {2 Helper functions for the Layer 1 chain} *) (** [get_predecessor_opt ?max_read state head] returns the predecessor of block -- GitLab From 46a251570b401cb9f58efc8852d6de3fca90015a Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 25 May 2023 10:19:52 +0200 Subject: [PATCH 3/7] SCORU/Node: wait for first block --- src/proto_alpha/lib_sc_rollup_node/daemon.ml | 11 ++++++++ src/proto_alpha/lib_sc_rollup_node/event.ml | 28 +++++++++++++++++++ src/proto_alpha/lib_sc_rollup_node/event.mli | 6 ++++ .../lib_sc_rollup_node/node_context.ml | 6 +--- .../lib_sc_rollup_node/node_context.mli | 3 +- 5 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/daemon.ml b/src/proto_alpha/lib_sc_rollup_node/daemon.ml index 082adf54406b..b72c30cc1bb8 100644 --- a/src/proto_alpha/lib_sc_rollup_node/daemon.ml +++ b/src/proto_alpha/lib_sc_rollup_node/daemon.ml @@ -640,12 +640,23 @@ let run ~data_dir ?log_kernel_debug_file (configuration : Configuration.t) ()) configuration.sc_rollup_node_operators in + let*! () = Event.waiting_first_block () in + let*! l1_ctxt = + Layer1.start + ~name:"sc_rollup_node" + ~reconnection_delay:configuration.reconnection_delay + ~protocols:[Protocol.hash] + cctxt + in + let*! head, _ = Layer1.wait_first l1_ctxt in + let*! () = Event.received_first_block head in let* node_ctxt = Node_context.init cctxt ~data_dir ?log_kernel_debug_file Read_write + l1_ctxt configuration in run node_ctxt configuration diff --git a/src/proto_alpha/lib_sc_rollup_node/event.ml b/src/proto_alpha/lib_sc_rollup_node/event.ml index 79b27226eef8..02326620e5b9 100644 --- a/src/proto_alpha/lib_sc_rollup_node/event.ml +++ b/src/proto_alpha/lib_sc_rollup_node/event.ml @@ -125,6 +125,30 @@ module Simple = struct for the rollup node." () + let waiting_first_block = + declare_0 + ~section + ~name:"waiting_first_block" + ~level:Notice + ~msg: + (Format.asprintf + "Waiting for first block of protocol %a to appear." + Protocol_hash.pp + Protocol.hash) + () + + let received_first_block = + declare_1 + ~section + ~name:"received_first_block" + ~level:Notice + ~msg: + (Format.asprintf + "First block of protocol %a received: {block}." + Protocol_hash.pp + Protocol.hash) + ("block", Block_hash.encoding) + let acquiring_lock = declare_0 ~section @@ -166,4 +190,8 @@ let kernel_debug_dont_wait msg = let warn_dal_enabled_no_node () = Simple.(emit warn_dal_enabled_no_node) () +let waiting_first_block () = Simple.(emit waiting_first_block) () + +let received_first_block b = Simple.(emit received_first_block) b + let acquiring_lock () = Simple.(emit acquiring_lock) () diff --git a/src/proto_alpha/lib_sc_rollup_node/event.mli b/src/proto_alpha/lib_sc_rollup_node/event.mli index 188c37b99008..0f61860e51f5 100644 --- a/src/proto_alpha/lib_sc_rollup_node/event.mli +++ b/src/proto_alpha/lib_sc_rollup_node/event.mli @@ -76,6 +76,12 @@ val kernel_debug_dont_wait : string -> unit protocol but the rollup node has no DAL node. *) val warn_dal_enabled_no_node : unit -> unit Lwt.t +(** Emit event that the node is waiting for the first block of its protocol. *) +val waiting_first_block : unit -> unit Lwt.t + +(** Emit event that the node received the first block of its protocol. *) +val received_first_block : Block_hash.t -> unit Lwt.t + (** [acquiring_lock ()] emits an event to indicate that the node is attempting to acquire a lock on the data directory. *) val acquiring_lock : unit -> unit Lwt.t 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 d4f5afbd72c4..9128bab97ab0 100644 --- a/src/proto_alpha/lib_sc_rollup_node/node_context.ml +++ b/src/proto_alpha/lib_sc_rollup_node/node_context.ml @@ -268,7 +268,7 @@ let check_config config = () let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file - mode + mode l1_ctxt Configuration.( { sc_rollup_address = rollup_address; @@ -279,7 +279,6 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file loser_mode; l2_blocks_cache_size; dal_node_endpoint; - reconnection_delay; _; } as configuration) = let open Lwt_result_syntax in @@ -302,9 +301,6 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file Context.load mode (Configuration.default_context_dir data_dir) in let* () = Context.Rollup.check_or_set_address mode context rollup_address in - let*! l1_ctxt = - Layer1.start ~name:"sc_rollup_node" ~reconnection_delay cctxt - in let publisher = Configuration.Operator_purpose_map.find Publish operators in let* protocol_constants = retrieve_constants cctxt and* lcc = get_last_cemented_commitment cctxt rollup_address 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 4478dae14e0d..bb833c88f24d 100644 --- a/src/proto_alpha/lib_sc_rollup_node/node_context.mli +++ b/src/proto_alpha/lib_sc_rollup_node/node_context.mli @@ -122,7 +122,7 @@ val get_fee_parameter : protocol. *) val protocol_max_batch_size : int -(** [init cctxt ~data_dir mode configuration] initializes the rollup +(** [init cctxt ~data_dir mode l1_ctxt configuration] initializes the rollup representation. The rollup origination level and kind are fetched via an RPC call to the layer1 node that [cctxt] uses for RPC requests. *) @@ -131,6 +131,7 @@ val init : data_dir:string -> ?log_kernel_debug_file:string -> 'a Store_sigs.mode -> + Layer1.t -> Configuration.t -> 'a t tzresult Lwt.t -- GitLab From 1671517670c164401900a3216f80bc4e07465635 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 25 May 2023 10:20:22 +0200 Subject: [PATCH 4/7] SCORU/Node: shutdown after protocol migration --- src/proto_alpha/lib_sc_rollup_node/daemon.ml | 45 ++++++++++++++++++- src/proto_alpha/lib_sc_rollup_node/event.ml | 11 +++++ src/proto_alpha/lib_sc_rollup_node/event.mli | 3 ++ .../lib_sc_rollup_node/node_context.ml | 5 ++- .../lib_sc_rollup_node/node_context.mli | 10 +++-- 5 files changed, 69 insertions(+), 5 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/daemon.ml b/src/proto_alpha/lib_sc_rollup_node/daemon.ml index b72c30cc1bb8..6f02adc867c4 100644 --- a/src/proto_alpha/lib_sc_rollup_node/daemon.ml +++ b/src/proto_alpha/lib_sc_rollup_node/daemon.ml @@ -290,6 +290,44 @@ let previous_context (node_ctxt : _ Node_context.t) return (Context.empty node_ctxt.context) else Node_context.checkout_context node_ctxt predecessor.Layer1.hash +let classify_head (node_ctxt : _ Node_context.t) + ?(predecessor : Layer1.header option) (head : Layer1.header) = + let open Lwt_result_syntax in + if head.header.proto_level = node_ctxt.proto_level then + (* Same protocol as supported one, ok *) + return `Supported_proto + else if head.header.proto_level = node_ctxt.proto_level + 1 then + let* predecessor = + match predecessor with + | Some p -> return p + | None -> Node_context.get_predecessor_header node_ctxt head + in + if predecessor.header.proto_level = node_ctxt.proto_level then + (* Migration block from supported protocol to the next one, ok *) + return `Supported_migration + else return `Unsupported_proto + else return `Unsupported_proto + +let exit_on_other_proto node_ctxt ?predecessor head = + let open Lwt_result_syntax in + let* proto_class = classify_head node_ctxt ?predecessor head in + match proto_class with + | `Supported_proto | `Supported_migration -> return_unit + | `Unsupported_proto -> + let*! () = Event.detected_protocol_migration () in + let*! _ = Lwt_exit.exit_and_wait 0 in + return_unit + +let exit_after_proto_migration node_ctxt ?predecessor head = + let open Lwt_result_syntax in + let* proto_class = classify_head node_ctxt ?predecessor head in + match proto_class with + | `Supported_proto -> return_unit + | `Supported_migration | `Unsupported_proto -> + let*! () = Event.detected_protocol_migration () in + let*! _ = Lwt_exit.exit_and_wait 0 in + return_unit + 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 head.hash in @@ -302,6 +340,7 @@ let rec process_head (node_ctxt : _ Node_context.t) (head : Layer1.header) = exist in the chain. *) return_unit | Some predecessor -> + let* () = exit_on_other_proto node_ctxt ~predecessor head in let* () = process_head node_ctxt predecessor in let* ctxt = previous_context node_ctxt ~predecessor in let* () = @@ -433,6 +472,7 @@ let on_layer_1_head node_ctxt (head : Layer1.header) = let* () = Batcher.batch () in let* () = Batcher.new_head stripped_head in let*! () = Injector.inject ~header:head.header () in + let* () = exit_after_proto_migration node_ctxt head in return_unit let daemonize (node_ctxt : _ Node_context.t) = @@ -449,6 +489,7 @@ let degraded_refutation_mode (node_ctxt : _ Node_context.t) = Layer1.iter_heads node_ctxt.l1_ctxt @@ fun head -> let* () = Refutation_coordinator.process (Layer1.head_of_header head) in let*! () = Injector.inject () in + let* () = exit_on_other_proto node_ctxt head in return_unit let install_finalizer node_ctxt rpc_server = @@ -648,7 +689,8 @@ let run ~data_dir ?log_kernel_debug_file (configuration : Configuration.t) ~protocols:[Protocol.hash] cctxt in - let*! head, _ = Layer1.wait_first l1_ctxt in + let*! head, {shell = {predecessor; _}; _} = Layer1.wait_first l1_ctxt in + let* predecessor = Layer1.fetch_tezos_shell_header cctxt predecessor in let*! () = Event.received_first_block head in let* node_ctxt = Node_context.init @@ -657,6 +699,7 @@ let run ~data_dir ?log_kernel_debug_file (configuration : Configuration.t) ?log_kernel_debug_file Read_write l1_ctxt + ~proto_level:predecessor.proto_level configuration in run node_ctxt configuration diff --git a/src/proto_alpha/lib_sc_rollup_node/event.ml b/src/proto_alpha/lib_sc_rollup_node/event.ml index 02326620e5b9..c35631692bfb 100644 --- a/src/proto_alpha/lib_sc_rollup_node/event.ml +++ b/src/proto_alpha/lib_sc_rollup_node/event.ml @@ -149,6 +149,14 @@ module Simple = struct Protocol.hash) ("block", Block_hash.encoding) + let detected_protocol_migration = + declare_0 + ~section + ~name:"detected_protocol_migration" + ~level:Notice + ~msg:"Detected protocol migration, the rollup node will now stop." + () + let acquiring_lock = declare_0 ~section @@ -194,4 +202,7 @@ let waiting_first_block () = Simple.(emit waiting_first_block) () let received_first_block b = Simple.(emit received_first_block) b +let detected_protocol_migration () = + Simple.(emit detected_protocol_migration) () + let acquiring_lock () = Simple.(emit acquiring_lock) () diff --git a/src/proto_alpha/lib_sc_rollup_node/event.mli b/src/proto_alpha/lib_sc_rollup_node/event.mli index 0f61860e51f5..cb90a98c4225 100644 --- a/src/proto_alpha/lib_sc_rollup_node/event.mli +++ b/src/proto_alpha/lib_sc_rollup_node/event.mli @@ -82,6 +82,9 @@ val waiting_first_block : unit -> unit Lwt.t (** Emit event that the node received the first block of its protocol. *) val received_first_block : Block_hash.t -> unit Lwt.t +(** Emit event that the node will shutdown because of protocol migration. *) +val detected_protocol_migration : unit -> unit Lwt.t + (** [acquiring_lock ()] emits an event to indicate that the node is attempting to acquire a lock on the data directory. *) val acquiring_lock : unit -> unit Lwt.t 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 9128bab97ab0..ea2fc259292e 100644 --- a/src/proto_alpha/lib_sc_rollup_node/node_context.ml +++ b/src/proto_alpha/lib_sc_rollup_node/node_context.ml @@ -50,6 +50,7 @@ type 'a t = { pvm : (module Pvm.S); fee_parameters : Configuration.fee_parameters; protocol_constants : Constants.t; + proto_level : int; loser_mode : Loser_mode.t; lockfile : Lwt_unix.file_descr; store : 'a store; @@ -268,7 +269,7 @@ let check_config config = () let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file - mode l1_ctxt + mode l1_ctxt ~proto_level Configuration.( { sc_rollup_address = rollup_address; @@ -365,6 +366,7 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file block_finality_time = 2; fee_parameters; protocol_constants; + proto_level; loser_mode; lockfile; store; @@ -987,6 +989,7 @@ module Internal_for_tests = struct block_finality_time = 2; fee_parameters = Configuration.default_fee_parameters; protocol_constants; + proto_level = 0; loser_mode = Loser_mode.no_failures; lockfile; store; 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 bb833c88f24d..8d61848a6492 100644 --- a/src/proto_alpha/lib_sc_rollup_node/node_context.mli +++ b/src/proto_alpha/lib_sc_rollup_node/node_context.mli @@ -68,6 +68,9 @@ type 'a t = { (** Fee parameters to use when injecting operations in layer 1. *) protocol_constants : Constants.t; (** Protocol constants retrieved from the Tezos node. *) + proto_level : int; + (** Protocol supported by this rollup node (represented as a protocol + level). *) loser_mode : Loser_mode.t; (** If different from [Loser_mode.no_failures], the rollup node issues wrong commitments (for tests). *) @@ -122,9 +125,9 @@ val get_fee_parameter : protocol. *) val protocol_max_batch_size : int -(** [init cctxt ~data_dir mode l1_ctxt configuration] initializes the rollup - representation. The rollup origination level and kind are fetched via an RPC - call to the layer1 node that [cctxt] uses for RPC requests. +(** [init cctxt ~data_dir mode l1_ctxt ~proto_level configuration] initializes + the rollup representation. The rollup origination level and kind are fetched + via an RPC call to the layer1 node that [cctxt] uses for RPC requests. *) val init : Protocol_client_context.full -> @@ -132,6 +135,7 @@ val init : ?log_kernel_debug_file:string -> 'a Store_sigs.mode -> Layer1.t -> + proto_level:int -> Configuration.t -> 'a t tzresult Lwt.t -- GitLab From 7319e62aa0cda9d8d47a2fc41104ac7f776fe6af Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 25 May 2023 11:04:06 +0200 Subject: [PATCH 5/7] SCORU/Node: test transition between two rollup nodes on migration --- tezt/lib_tezos/sc_rollup_node.ml | 6 +-- tezt/lib_tezos/sc_rollup_node.mli | 12 ++--- tezt/tests/sc_rollup.ml | 75 ++++++++++++++++++------------- 3 files changed, 55 insertions(+), 38 deletions(-) diff --git a/tezt/lib_tezos/sc_rollup_node.ml b/tezt/lib_tezos/sc_rollup_node.ml index ca739d3db0af..16b3c8641f13 100644 --- a/tezt/lib_tezos/sc_rollup_node.ml +++ b/tezt/lib_tezos/sc_rollup_node.ml @@ -352,8 +352,8 @@ let run ?(legacy = false) ?event_level ?event_sections_levels ?loser_mode node in do_runlike_command ?event_level ?event_sections_levels node cmd -let run ?legacy ?event_level ?event_sections_levels ?loser_mode node - rollup_address arguments = +let run ?legacy ?event_level ?event_sections_levels ?loser_mode + ?(wait_ready = true) node rollup_address arguments = let* () = run ?legacy @@ -364,7 +364,7 @@ let run ?legacy ?event_level ?event_sections_levels ?loser_mode node rollup_address arguments in - let* () = wait_for_ready node in + let* () = if wait_ready then wait_for_ready node else unit in return () let spawn_run node rollup_address extra_arguments = diff --git a/tezt/lib_tezos/sc_rollup_node.mli b/tezt/lib_tezos/sc_rollup_node.mli index 26874680ba95..cdd746fbbea5 100644 --- a/tezt/lib_tezos/sc_rollup_node.mli +++ b/tezt/lib_tezos/sc_rollup_node.mli @@ -108,18 +108,20 @@ val base_dir : t -> string If no [msg] is given, the stderr is ignored.*) val check_error : ?exit_code:int -> ?msg:Base.rex -> t -> unit Lwt.t -(** [run ?event_level ?event_sections_levels ?loser_mode node rollup_address - arguments ] launches the given smart contract rollup node for the rollup at - [rollup_address] with the given extra arguments. [event_level] and - [event_sections_levels] allow to select which events we want the node to +(** [run ?event_level ?event_sections_levels ?loser_mode ?wait_ready node + rollup_address arguments ] launches the given smart contract rollup node for + the rollup at [rollup_address] with the given extra arguments. [event_level] + and [event_sections_levels] allow to select which events we want the node to emit (see {!Daemon}). [legacy] (by default [false]) must be set if we want to use the legacy [run] command of the node (which requires a config file to - exist). *) + exist). If [wait_ready] is [false], tezt does not wait for the node to be + ready. *) val run : ?legacy:bool -> ?event_level:Daemon.Level.default_level -> ?event_sections_levels:(string * Daemon.Level.level) list -> ?loser_mode:string -> + ?wait_ready:bool -> t -> string -> string list -> diff --git a/tezt/tests/sc_rollup.ml b/tezt/tests/sc_rollup.ml index 87ddd7a03d80..252a2bf428fe 100644 --- a/tezt/tests/sc_rollup.ml +++ b/tezt/tests/sc_rollup.ml @@ -383,7 +383,7 @@ let test_l2_migration_scenario ?parameters_ty ?(mode = Sc_rollup_node.Operator) let* tezos_node, tezos_client = setup_l1 ?commitment_period ?challenge_window ?timeout migrate_from in - let* rollup_node, rollup_client, sc_rollup = + let* rollup_node_from, rollup_client_from, sc_rollup = setup_rollup ~protocol:migrate_from ?parameters_ty @@ -394,10 +394,35 @@ let test_l2_migration_scenario ?parameters_ty ?(mode = Sc_rollup_node.Operator) tezos_node tezos_client in + (* Rollup node and client for other protocol *) + let data_dir = Sc_rollup_node.data_dir rollup_node_from in + let rollup_node_to = + Sc_rollup_node.create + ~protocol:migrate_to + ~data_dir + ~base_dir:(Client.base_dir tezos_client) + ~default_operator:operator + mode + tezos_node + in + let rollup_client_to = + Sc_rollup_client.create ~protocol:migrate_to rollup_node_to + in + let* prior_res = - scenario_prior ~sc_rollup rollup_node rollup_client tezos_node tezos_client + scenario_prior + ~sc_rollup + ~rollup_node_from + ~rollup_client_from + ~rollup_node_to + ~rollup_client_to + tezos_node + tezos_client in let migration_level = Node.get_level tezos_node + 1 in + let rollup_node_from_processed_migration_level = + Sc_rollup_node.wait_for_level ~timeout:10. rollup_node_from migration_level + in let patch_config = Node.Config_file.set_sandbox_network_with_user_activated_upgrades [(migration_level, migrate_to)] @@ -413,24 +438,13 @@ let test_l2_migration_scenario ?parameters_ty ?(mode = Sc_rollup_node.Operator) let* () = Node.run ~patch_config tezos_node nodes_args in let* () = Node.wait_for_ready tezos_node in let* () = Client.bake_for_and_wait tezos_client in - (* Rollup node and client for other protocol *) - let data_dir = Sc_rollup_node.data_dir rollup_node in - let rollup_node = - Sc_rollup_node.create - ~protocol:migrate_to - ~data_dir - ~base_dir:(Client.base_dir tezos_client) - ~default_operator:operator - mode - tezos_node - in - let rollup_client = - Sc_rollup_client.create ~protocol:migrate_to rollup_node - in + let* _ = rollup_node_from_processed_migration_level in scenario_after ~sc_rollup - rollup_node - rollup_client + ~rollup_node_from + ~rollup_client_from + ~rollup_node_to + ~rollup_client_to tezos_node tezos_client prior_res @@ -1457,27 +1471,28 @@ let test_rollup_node_simple_migration ~kind ~migrate_from ~migrate_to = let description = "node can read data after store migration" in let commitment_period = 10 in let challenge_window = 10 in - let scenario_prior ~sc_rollup rollup_node _rollup_client _tezos_node - tezos_client = - let* () = Sc_rollup_node.run rollup_node sc_rollup [] in + let scenario_prior ~sc_rollup ~rollup_node_from ~rollup_client_from:_ + ~rollup_node_to ~rollup_client_to:_ _tezos_node tezos_client = + let* () = Sc_rollup_node.run rollup_node_from sc_rollup [] + and* () = + Sc_rollup_node.run ~wait_ready:false rollup_node_to sc_rollup [] + in let* () = send_messages commitment_period tezos_client in - let* _ = Sc_rollup_node.wait_sync rollup_node ~timeout:10. in - let* () = Sc_rollup_node.terminate rollup_node in + let* _ = Sc_rollup_node.wait_sync rollup_node_from ~timeout:10. in unit in - let scenario_after ~sc_rollup rollup_node rollup_client tezos_node - tezos_client () = + let scenario_after ~sc_rollup:_ ~rollup_node_from:_ ~rollup_client_from:_ + ~rollup_node_to ~rollup_client_to tezos_node tezos_client () = let migration_level = Node.get_level tezos_node in - let* () = Sc_rollup_node.run rollup_node sc_rollup [] in + let* () = send_messages 1 tezos_client in + let* _ = Sc_rollup_node.wait_sync rollup_node_to ~timeout:10. in let*! _l2_block = Sc_rollup_client.rpc_get - rollup_client + rollup_client_to ["global"; "block"; string_of_int (migration_level - 1)] in - let* () = send_messages 1 tezos_client in - let* _ = Sc_rollup_node.wait_sync rollup_node ~timeout:10. in let*! _l2_block = - Sc_rollup_client.rpc_get rollup_client ["global"; "block"; "head"] + Sc_rollup_client.rpc_get rollup_client_to ["global"; "block"; "head"] in unit in -- GitLab From 7daf1ca8508b682a39d99c9ec724f727bbf16449 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 25 May 2023 10:19:52 +0200 Subject: [PATCH 6/7] SCORU/Node/Nairobi: backport !8870 - SCORU/Node: wait for first block - SCORU/Node: shutdown after protocol migration --- .../lib_sc_rollup_node/daemon.ml | 54 +++++++++++++++++++ .../lib_sc_rollup_node/event.ml | 39 ++++++++++++++ .../lib_sc_rollup_node/event.mli | 9 ++++ .../lib_sc_rollup_node/node_context.ml | 9 ++-- .../lib_sc_rollup_node/node_context.mli | 11 ++-- 5 files changed, 114 insertions(+), 8 deletions(-) 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 7a26c556ec3c..1034876b5e31 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/daemon.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/daemon.ml @@ -290,6 +290,44 @@ let previous_context (node_ctxt : _ Node_context.t) return (Context.empty node_ctxt.context) else Node_context.checkout_context node_ctxt predecessor.Layer1.hash +let classify_head (node_ctxt : _ Node_context.t) + ?(predecessor : Layer1.header option) (head : Layer1.header) = + let open Lwt_result_syntax in + if head.header.proto_level = node_ctxt.proto_level then + (* Same protocol as supported one, ok *) + return `Supported_proto + else if head.header.proto_level = node_ctxt.proto_level + 1 then + let* predecessor = + match predecessor with + | Some p -> return p + | None -> Node_context.get_predecessor_header node_ctxt head + in + if predecessor.header.proto_level = node_ctxt.proto_level then + (* Migration block from supported protocol to the next one, ok *) + return `Supported_migration + else return `Unsupported_proto + else return `Unsupported_proto + +let exit_on_other_proto node_ctxt ?predecessor head = + let open Lwt_result_syntax in + let* proto_class = classify_head node_ctxt ?predecessor head in + match proto_class with + | `Supported_proto | `Supported_migration -> return_unit + | `Unsupported_proto -> + let*! () = Event.detected_protocol_migration () in + let*! _ = Lwt_exit.exit_and_wait 0 in + return_unit + +let exit_after_proto_migration node_ctxt ?predecessor head = + let open Lwt_result_syntax in + let* proto_class = classify_head node_ctxt ?predecessor head in + match proto_class with + | `Supported_proto -> return_unit + | `Supported_migration | `Unsupported_proto -> + let*! () = Event.detected_protocol_migration () in + let*! _ = Lwt_exit.exit_and_wait 0 in + return_unit + 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 head.hash in @@ -302,6 +340,7 @@ let rec process_head (node_ctxt : _ Node_context.t) (head : Layer1.header) = exist in the chain. *) return_unit | Some predecessor -> + let* () = exit_on_other_proto node_ctxt ~predecessor head in let* () = process_head node_ctxt predecessor in let* ctxt = previous_context node_ctxt ~predecessor in let* () = @@ -433,6 +472,7 @@ let on_layer_1_head node_ctxt (head : Layer1.header) = let* () = Batcher.batch () in let* () = Batcher.new_head stripped_head in let*! () = Injector.inject ~header:head.header () in + let* () = exit_after_proto_migration node_ctxt head in return_unit let daemonize (node_ctxt : _ Node_context.t) = @@ -449,6 +489,7 @@ let degraded_refutation_mode (node_ctxt : _ Node_context.t) = Layer1.iter_heads node_ctxt.l1_ctxt @@ fun head -> let* () = Refutation_coordinator.process (Layer1.head_of_header head) in let*! () = Injector.inject () in + let* () = exit_on_other_proto node_ctxt head in return_unit let install_finalizer node_ctxt rpc_server = @@ -639,12 +680,25 @@ let run ~data_dir ?log_kernel_debug_file (configuration : Configuration.t) ()) configuration.sc_rollup_node_operators in + let*! () = Event.waiting_first_block () in + let*! l1_ctxt = + Layer1.start + ~name:"sc_rollup_node" + ~reconnection_delay:configuration.reconnection_delay + ~protocols:[Protocol.hash] + cctxt + in + let*! head, {shell = {predecessor; _}; _} = Layer1.wait_first l1_ctxt in + let* predecessor = Layer1.fetch_tezos_shell_header cctxt predecessor in + let*! () = Event.received_first_block head in let* node_ctxt = Node_context.init cctxt ~data_dir ?log_kernel_debug_file Read_write + l1_ctxt + ~proto_level:predecessor.proto_level configuration in run node_ctxt configuration diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/event.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/event.ml index 79b27226eef8..c35631692bfb 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/event.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/event.ml @@ -125,6 +125,38 @@ module Simple = struct for the rollup node." () + let waiting_first_block = + declare_0 + ~section + ~name:"waiting_first_block" + ~level:Notice + ~msg: + (Format.asprintf + "Waiting for first block of protocol %a to appear." + Protocol_hash.pp + Protocol.hash) + () + + let received_first_block = + declare_1 + ~section + ~name:"received_first_block" + ~level:Notice + ~msg: + (Format.asprintf + "First block of protocol %a received: {block}." + Protocol_hash.pp + Protocol.hash) + ("block", Block_hash.encoding) + + let detected_protocol_migration = + declare_0 + ~section + ~name:"detected_protocol_migration" + ~level:Notice + ~msg:"Detected protocol migration, the rollup node will now stop." + () + let acquiring_lock = declare_0 ~section @@ -166,4 +198,11 @@ let kernel_debug_dont_wait msg = let warn_dal_enabled_no_node () = Simple.(emit warn_dal_enabled_no_node) () +let waiting_first_block () = Simple.(emit waiting_first_block) () + +let received_first_block b = Simple.(emit received_first_block) b + +let detected_protocol_migration () = + Simple.(emit detected_protocol_migration) () + let acquiring_lock () = Simple.(emit acquiring_lock) () diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/event.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/event.mli index 188c37b99008..cb90a98c4225 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/event.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/event.mli @@ -76,6 +76,15 @@ val kernel_debug_dont_wait : string -> unit protocol but the rollup node has no DAL node. *) val warn_dal_enabled_no_node : unit -> unit Lwt.t +(** Emit event that the node is waiting for the first block of its protocol. *) +val waiting_first_block : unit -> unit Lwt.t + +(** Emit event that the node received the first block of its protocol. *) +val received_first_block : Block_hash.t -> unit Lwt.t + +(** Emit event that the node will shutdown because of protocol migration. *) +val detected_protocol_migration : unit -> unit Lwt.t + (** [acquiring_lock ()] emits an event to indicate that the node is attempting to acquire a lock on the data directory. *) val acquiring_lock : unit -> unit Lwt.t 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 29283f359e9d..1dca83cda29d 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 @@ -48,6 +48,7 @@ type 'a t = { pvm : (module Pvm.S); fee_parameters : Configuration.fee_parameters; protocol_constants : Constants.t; + proto_level : int; loser_mode : Loser_mode.t; lockfile : Lwt_unix.file_descr; store : 'a store; @@ -277,7 +278,7 @@ let check_config config = () let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file - mode + mode l1_ctxt ~proto_level Configuration.( { sc_rollup_address = rollup_address; @@ -287,7 +288,6 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file loser_mode; l2_blocks_cache_size; dal_node_endpoint; - reconnection_delay; _; } as configuration) = let open Lwt_result_syntax in @@ -315,9 +315,6 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file Context.load mode (Configuration.default_context_dir data_dir) in let* () = Context.Rollup.check_or_set_address mode context rollup_address in - let*! l1_ctxt = - Layer1.start ~name:"sc_rollup_node" ~reconnection_delay cctxt - in let publisher = Configuration.Operator_purpose_map.find Publish operators in let* protocol_constants = retrieve_constants cctxt and* lcc = get_last_cemented_commitment cctxt rollup_address @@ -368,6 +365,7 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file block_finality_time = 2; fee_parameters; protocol_constants; + proto_level; loser_mode; lockfile; store; @@ -986,6 +984,7 @@ module Internal_for_tests = struct block_finality_time = 2; fee_parameters = Configuration.default_fee_parameters; protocol_constants; + proto_level = 0; loser_mode = Loser_mode.no_failures; lockfile; store; 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 bf462508f6a2..292952b71810 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 @@ -63,6 +63,9 @@ type 'a t = { (** Fee parameters to use when injecting operations in layer 1. *) protocol_constants : Constants.t; (** Protocol constants retrieved from the Tezos node. *) + proto_level : int; + (** Protocol supported by this rollup node (represented as a protocol + level). *) loser_mode : Loser_mode.t; (** If different from [Loser_mode.no_failures], the rollup node issues wrong commitments (for tests). *) @@ -117,15 +120,17 @@ val get_fee_parameter : protocol. *) val protocol_max_batch_size : int -(** [init cctxt ~data_dir mode configuration] initializes the rollup - representation. The rollup origination level and kind are fetched via an RPC - call to the layer1 node that [cctxt] uses for RPC requests. +(** [init cctxt ~data_dir mode l1_ctxt ~proto_level configuration] initializes + the rollup representation. The rollup origination level and kind are fetched + via an RPC call to the layer1 node that [cctxt] uses for RPC requests. *) val init : Protocol_client_context.full -> data_dir:string -> ?log_kernel_debug_file:string -> 'a Store_sigs.mode -> + Layer1.t -> + proto_level:int -> Configuration.t -> 'a t tzresult Lwt.t -- GitLab From f8b5b408446d44ab4a1424aea37b00b4e9342a41 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 25 May 2023 10:19:52 +0200 Subject: [PATCH 7/7] SCORU/Node/Mumbai: backport !8870 - SCORU/Node: wait for first block - SCORU/Node: shutdown after protocol migration --- .../lib_sc_rollup_node/daemon.ml | 54 +++++++++++++++++++ .../lib_sc_rollup_node/event.ml | 39 ++++++++++++++ .../lib_sc_rollup_node/event.mli | 9 ++++ .../lib_sc_rollup_node/node_context.ml | 9 ++-- .../lib_sc_rollup_node/node_context.mli | 11 ++-- 5 files changed, 114 insertions(+), 8 deletions(-) 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 b321330df625..625f5f05f32b 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/daemon.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/daemon.ml @@ -292,6 +292,44 @@ let previous_context (node_ctxt : _ Node_context.t) return (Context.empty node_ctxt.context) else Node_context.checkout_context node_ctxt predecessor.Layer1.hash +let classify_head (node_ctxt : _ Node_context.t) + ?(predecessor : Layer1.header option) (head : Layer1.header) = + let open Lwt_result_syntax in + if head.header.proto_level = node_ctxt.proto_level then + (* Same protocol as supported one, ok *) + return `Supported_proto + else if head.header.proto_level = node_ctxt.proto_level + 1 then + let* predecessor = + match predecessor with + | Some p -> return p + | None -> Node_context.get_predecessor_header node_ctxt head + in + if predecessor.header.proto_level = node_ctxt.proto_level then + (* Migration block from supported protocol to the next one, ok *) + return `Supported_migration + else return `Unsupported_proto + else return `Unsupported_proto + +let exit_on_other_proto node_ctxt ?predecessor head = + let open Lwt_result_syntax in + let* proto_class = classify_head node_ctxt ?predecessor head in + match proto_class with + | `Supported_proto | `Supported_migration -> return_unit + | `Unsupported_proto -> + let*! () = Event.detected_protocol_migration () in + let*! _ = Lwt_exit.exit_and_wait 0 in + return_unit + +let exit_after_proto_migration node_ctxt ?predecessor head = + let open Lwt_result_syntax in + let* proto_class = classify_head node_ctxt ?predecessor head in + match proto_class with + | `Supported_proto -> return_unit + | `Supported_migration | `Unsupported_proto -> + let*! () = Event.detected_protocol_migration () in + let*! _ = Lwt_exit.exit_and_wait 0 in + return_unit + 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 head.hash in @@ -304,6 +342,7 @@ let rec process_head (node_ctxt : _ Node_context.t) (head : Layer1.header) = exist in the chain. *) return_unit | Some predecessor -> + let* () = exit_on_other_proto node_ctxt ~predecessor head in let* () = process_head node_ctxt predecessor in let* ctxt = previous_context node_ctxt ~predecessor in let* () = @@ -435,6 +474,7 @@ let on_layer_1_head node_ctxt (head : Layer1.header) = let* () = Batcher.batch () in let* () = Batcher.new_head stripped_head in let*! () = Injector.inject ~header:head.header () in + let* () = exit_after_proto_migration node_ctxt head in return_unit let daemonize (node_ctxt : _ Node_context.t) = @@ -451,6 +491,7 @@ let degraded_refutation_mode (node_ctxt : _ Node_context.t) = Layer1.iter_heads node_ctxt.l1_ctxt @@ fun head -> let* () = Refutation_coordinator.process (Layer1.head_of_header head) in let*! () = Injector.inject () in + let* () = exit_on_other_proto node_ctxt head in return_unit let install_finalizer node_ctxt rpc_server = @@ -645,12 +686,25 @@ let run ~data_dir ?log_kernel_debug_file (configuration : Configuration.t) ()) configuration.sc_rollup_node_operators in + let*! () = Event.waiting_first_block () in + let*! l1_ctxt = + Layer1.start + ~name:"sc_rollup_node" + ~reconnection_delay:configuration.reconnection_delay + ~protocols:[Protocol.hash] + cctxt + in + let*! head, {shell = {predecessor; _}; _} = Layer1.wait_first l1_ctxt in + let* predecessor = Layer1.fetch_tezos_shell_header cctxt predecessor in + let*! () = Event.received_first_block head in let* node_ctxt = Node_context.init cctxt ~data_dir ?log_kernel_debug_file Read_write + l1_ctxt + ~proto_level:predecessor.proto_level configuration in run node_ctxt configuration diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/event.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/event.ml index 79b27226eef8..c35631692bfb 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/event.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/event.ml @@ -125,6 +125,38 @@ module Simple = struct for the rollup node." () + let waiting_first_block = + declare_0 + ~section + ~name:"waiting_first_block" + ~level:Notice + ~msg: + (Format.asprintf + "Waiting for first block of protocol %a to appear." + Protocol_hash.pp + Protocol.hash) + () + + let received_first_block = + declare_1 + ~section + ~name:"received_first_block" + ~level:Notice + ~msg: + (Format.asprintf + "First block of protocol %a received: {block}." + Protocol_hash.pp + Protocol.hash) + ("block", Block_hash.encoding) + + let detected_protocol_migration = + declare_0 + ~section + ~name:"detected_protocol_migration" + ~level:Notice + ~msg:"Detected protocol migration, the rollup node will now stop." + () + let acquiring_lock = declare_0 ~section @@ -166,4 +198,11 @@ let kernel_debug_dont_wait msg = let warn_dal_enabled_no_node () = Simple.(emit warn_dal_enabled_no_node) () +let waiting_first_block () = Simple.(emit waiting_first_block) () + +let received_first_block b = Simple.(emit received_first_block) b + +let detected_protocol_migration () = + Simple.(emit detected_protocol_migration) () + let acquiring_lock () = Simple.(emit acquiring_lock) () diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/event.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/event.mli index 188c37b99008..cb90a98c4225 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/event.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/event.mli @@ -76,6 +76,15 @@ val kernel_debug_dont_wait : string -> unit protocol but the rollup node has no DAL node. *) val warn_dal_enabled_no_node : unit -> unit Lwt.t +(** Emit event that the node is waiting for the first block of its protocol. *) +val waiting_first_block : unit -> unit Lwt.t + +(** Emit event that the node received the first block of its protocol. *) +val received_first_block : Block_hash.t -> unit Lwt.t + +(** Emit event that the node will shutdown because of protocol migration. *) +val detected_protocol_migration : unit -> unit Lwt.t + (** [acquiring_lock ()] emits an event to indicate that the node is attempting to acquire a lock on the data directory. *) val acquiring_lock : unit -> unit Lwt.t 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 8d0bc699e189..ba977cc57828 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 @@ -48,6 +48,7 @@ type 'a t = { pvm : (module Pvm.S); fee_parameters : Configuration.fee_parameters; protocol_constants : Constants.t; + proto_level : int; loser_mode : Loser_mode.t; lockfile : Lwt_unix.file_descr; store : 'a store; @@ -277,7 +278,7 @@ let check_config config = () let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file - mode + mode l1_ctxt ~proto_level Configuration.( { sc_rollup_address = rollup_address; @@ -287,7 +288,6 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file loser_mode; l2_blocks_cache_size; dal_node_endpoint; - reconnection_delay; _; } as configuration) = let open Lwt_result_syntax in @@ -315,9 +315,6 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file Context.load mode (Configuration.default_context_dir data_dir) in let* () = Context.Rollup.check_or_set_address mode context rollup_address in - let*! l1_ctxt = - Layer1.start ~name:"sc_rollup_node" ~reconnection_delay cctxt - in let publisher = Configuration.Operator_purpose_map.find Publish operators in let* protocol_constants = retrieve_constants cctxt and* lcc = get_last_cemented_commitment cctxt rollup_address @@ -368,6 +365,7 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file block_finality_time = 2; fee_parameters; protocol_constants; + proto_level; loser_mode; lockfile; store; @@ -1007,6 +1005,7 @@ module Internal_for_tests = struct block_finality_time = 2; fee_parameters = Configuration.default_fee_parameters; protocol_constants; + proto_level = 0; loser_mode = Loser_mode.no_failures; lockfile; store; 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 ccb0969dfee6..f2fdb44a470f 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 @@ -63,6 +63,9 @@ type 'a t = { (** Fee parameters to use when injecting operations in layer 1. *) protocol_constants : Constants.t; (** Protocol constants retrieved from the Tezos node. *) + proto_level : int; + (** Protocol supported by this rollup node (represented as a protocol + level). *) loser_mode : Loser_mode.t; (** If different from [Loser_mode.no_failures], the rollup node issues wrong commitments (for tests). *) @@ -119,15 +122,17 @@ val get_fee_parameter : protocol. *) val protocol_max_batch_size : int -(** [init cctxt ~data_dir mode configuration] initializes the rollup - representation. The rollup origination level and kind are fetched via an RPC - call to the layer1 node that [cctxt] uses for RPC requests. +(** [init cctxt ~data_dir mode l1_ctxt ~proto_level configuration] initializes + the rollup representation. The rollup origination level and kind are fetched + via an RPC call to the layer1 node that [cctxt] uses for RPC requests. *) val init : Protocol_client_context.full -> data_dir:string -> ?log_kernel_debug_file:string -> 'a Store_sigs.mode -> + Layer1.t -> + proto_level:int -> Configuration.t -> 'a t tzresult Lwt.t -- GitLab