diff --git a/manifest/main.ml b/manifest/main.ml index 1d9f3774298f67fef638a544b2fb67517421b6b4..8a060de81d9d43f5e3c8dc3710a7e999e092f2cc 100644 --- a/manifest/main.ml +++ b/manifest/main.ml @@ -4114,8 +4114,9 @@ let octez_smart_rollup_node_lib = prometheus_app; octez_injector |> open_; octez_version_value |> open_; - octez_smart_rollup_lib |> open_; octez_layer2_store |> open_; + octez_crawler |> open_; + octez_smart_rollup_lib |> open_; ] let octez_scoru_wasm_helpers = diff --git a/opam/octez-smart-rollup-node.opam b/opam/octez-smart-rollup-node.opam index fbf24bc6872bdba1328349389bc880411c3b8991..db2390f3e97b11b02daa681a69a4690dbc4b415c 100644 --- a/opam/octez-smart-rollup-node.opam +++ b/opam/octez-smart-rollup-node.opam @@ -20,8 +20,9 @@ depends: [ "prometheus-app" { >= "1.2" } "octez-injector" "tezos-version" - "octez-smart-rollup" "tezos-layer2-store" + "octez-crawler" + "octez-smart-rollup" ] build: [ ["rm" "-r" "vendors" "contrib"] diff --git a/src/lib_smart_rollup_node/dune b/src/lib_smart_rollup_node/dune index d5c967b2ecdf3e40e62cf975f92447735f8c861b..ae2cce70ad79b6defb412285bad0d9b8a6beeda7 100644 --- a/src/lib_smart_rollup_node/dune +++ b/src/lib_smart_rollup_node/dune @@ -17,8 +17,9 @@ prometheus-app octez-injector tezos-version.value - octez-smart-rollup - tezos_layer2_store) + tezos_layer2_store + octez-crawler + octez-smart-rollup) (flags (:standard) -open Tezos_base.TzPervasives @@ -28,5 +29,6 @@ -open Tezos_client_base_unix -open Octez_injector -open Tezos_version_value - -open Octez_smart_rollup - -open Tezos_layer2_store)) + -open Tezos_layer2_store + -open Octez_crawler + -open Octez_smart_rollup)) diff --git a/src/proto_alpha/lib_sc_rollup_node/layer1.ml b/src/lib_smart_rollup_node/layer1.ml similarity index 85% rename from src/proto_alpha/lib_sc_rollup_node/layer1.ml rename to src/lib_smart_rollup_node/layer1.ml index ec67b468980861cffff52594c78bb699803ed56f..7764afd7b36758accba01d3c4dcb378034d597f3 100644 --- a/src/proto_alpha/lib_sc_rollup_node/layer1.ml +++ b/src/lib_smart_rollup_node/layer1.ml @@ -24,8 +24,6 @@ (* *) (*****************************************************************************) -open Protocol_client_context - (** Errors @@ -36,7 +34,7 @@ open Protocol_client_context type error += Cannot_find_block of Block_hash.t let () = - Sc_rollup_node_errors.register_error_kind + register_error_kind ~id:"sc_rollup.node.cannot_find_block" ~title:"Cannot find block from L1" ~description:"A block couldn't be found from the L1 node" @@ -88,10 +86,20 @@ module Blocks_cache = Aches_lwt.Lache.Make_option (Aches.Rache.Transfer (Aches.Rache.LRU) (Block_hash)) -type blocks_cache = Alpha_block_services.block_info Blocks_cache.t +type block = .. + +type fetch_block_rpc = + Client_context.full -> + ?metadata:[`Always | `Never] -> + ?chain:Tezos_shell_services.Block_services.chain -> + ?block:Tezos_shell_services.Block_services.block -> + unit -> + block tzresult Lwt.t type headers_cache = Block_header.shell_header Blocks_cache.t +type blocks_cache = block Blocks_cache.t + open Octez_crawler.Layer_1 type nonrec t = { @@ -125,6 +133,8 @@ let shutdown {l1; _} = shutdown l1 let cache_shell_header {headers_cache; _} hash header = Blocks_cache.put headers_cache hash (Lwt.return_some header) +let client_context {cctxt; _} = cctxt + let iter_heads l1_ctxt f = iter_heads l1_ctxt.l1 @@ fun (hash, {shell = {level; _} as header; _}) -> cache_shell_header l1_ctxt hash header ; @@ -164,7 +174,7 @@ end (** [fetch_tezos_block cctxt hash] returns a block shell header of [hash]. Looks for the block in the blocks cache first, and fetches it from the L1 node otherwise. *) -let fetch_tezos_shell_header {cctxt; blocks_cache; headers_cache; _} hash = +let fetch_tezos_shell_header {cctxt; headers_cache; _} hash = let open Lwt_syntax in trace (Cannot_find_block hash) @@ @@ -184,21 +194,7 @@ let fetch_tezos_shell_header {cctxt; blocks_cache; headers_cache; _} hash = | Ok shell_header -> return_some shell_header in let+ shell_header = - let do_cached_header_fetch () = - Blocks_cache.bind_or_put headers_cache hash fetch Lwt.return - in - match Blocks_cache.bind blocks_cache hash Lwt.return with - | None -> do_cached_header_fetch () - | Some block -> ( - (* There is already a full block being fetched. *) - let* block in - match block with - | None -> - (* Fetching full block failed. *) - do_cached_header_fetch () - | Some block -> - (* The full block is already in the cache. *) - return_some block.header.shell) + Blocks_cache.bind_or_put headers_cache hash fetch Lwt.return in match (shell_header, !errors) with | None, None -> @@ -211,22 +207,18 @@ let fetch_tezos_shell_header {cctxt; blocks_cache; headers_cache; _} hash = | None, Some errs -> Error errs | Some shell_header, _ -> Ok shell_header -(** [fetch_tezos_block cctxt hash] returns a block info given a block - hash. Looks for the block in the blocks cache first, and fetches it from the - L1 node otherwise. *) -let fetch_tezos_block {cctxt; blocks_cache; headers_cache; _} hash = +(** [fetch_tezos_block cctxt fetch extract_header hash] returns a block info + given a block hash. Looks for the block in the blocks cache first, and + fetches it from the L1 node otherwise. *) +let fetch_tezos_block (fetch : fetch_block_rpc) extract_header + ({cctxt; blocks_cache; _} as l1_ctxt) hash = let open Lwt_syntax in trace (Cannot_find_block hash) @@ let errors = ref None in let fetch hash = let* block = - Alpha_block_services.info - cctxt - ~chain:`Main - ~block:(`Hash (hash, 0)) - ~metadata:`Always - () + fetch cctxt ~chain:`Main ~block:(`Hash (hash, 0)) ~metadata:`Always () in match block with | Error errs -> @@ -245,7 +237,7 @@ let fetch_tezos_block {cctxt; blocks_cache; headers_cache; _} hash = hash | None, Some errs -> Error errs | Some block, _ -> - Blocks_cache.put headers_cache hash (Lwt.return_some block.header.shell) ; + cache_shell_header l1_ctxt hash (extract_header block) ; Ok block let make_prefetching_schedule {prefetch_blocks; _} blocks = @@ -263,13 +255,15 @@ let make_prefetching_schedule {prefetch_blocks; _} blocks = | [], _ | _, [] -> blocks_with_prefetching | (first, _) :: rest, _ -> (first, first_prefetch) :: rest -let prefetch_tezos_blocks l1_ctxt = function +let prefetch_tezos_blocks fetch extract_header l1_ctxt = function | [] -> () | blocks -> Lwt.async @@ fun () -> List.iter_p (fun {hash; _} -> let open Lwt_syntax in - let+ _maybe_block = fetch_tezos_block l1_ctxt hash in + let+ _maybe_block = + fetch_tezos_block fetch extract_header l1_ctxt hash + in ()) blocks diff --git a/src/proto_alpha/lib_sc_rollup_node/layer1.mli b/src/lib_smart_rollup_node/layer1.mli similarity index 79% rename from src/proto_alpha/lib_sc_rollup_node/layer1.mli rename to src/lib_smart_rollup_node/layer1.mli index 2b00c462c563872c8899d77425bde1b19fa8dba3..2f1a9671c1b2e5d561ffcfd20a5cf6b7f688493c 100644 --- a/src/proto_alpha/lib_sc_rollup_node/layer1.mli +++ b/src/lib_smart_rollup_node/layer1.mli @@ -30,6 +30,8 @@ subscribing to the head monitoring RPC offered by the Tezos node. *) +type error += Cannot_find_block of Block_hash.t + type header = { hash : Block_hash.t; level : int32; @@ -46,6 +48,19 @@ val head_of_header : header -> head type t +(** An extensible type for the protocol specific full blocks. This allows to + have a single cache for blocks from all protocols. *) +type block = .. + +(** Type of protocol specific functions for fetching protocol specific blocks. *) +type fetch_block_rpc = + Client_context.full -> + ?metadata:[`Always | `Never] -> + ?chain:Tezos_shell_services.Block_services.chain -> + ?block:Tezos_shell_services.Block_services.block -> + unit -> + block tzresult Lwt.t + (** [start ~name ~reconnection_delay ~l1_blocks_cache_size ?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 @@ -65,9 +80,6 @@ val start : (** [shutdown t] properly shuts the layer 1 down. *) val shutdown : t -> unit Lwt.t -(* TODO: https://gitlab.com/tezos/tezos/-/issues/3311 - Allow to retrieve L1 blocks through Tezos node storage locally. *) - (** [iter_heads t f] calls [f] on all new heads appearing in the 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, @@ -100,19 +112,27 @@ val get_tezos_reorg_for_new_head : (** {2 Helpers } *) +(** Register a block header in the cache. *) +val cache_shell_header : t -> Block_hash.t -> Block_header.shell_header -> unit + +(** Returns the client context used by the L1 monitor. *) +val client_context : t -> Client_context.full + (** [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. *) val fetch_tezos_shell_header : t -> Block_hash.t -> Block_header.shell_header tzresult Lwt.t -(** [fetch_tezos_block cctxt hash] returns a block info given a block hash. - Looks for the block in the blocks cache first, and fetches it from the L1 - node otherwise. *) +(** [fetch_tezos_block fetch extract_header cctxt hash] returns a block info + given a block hash. Looks for the block in the blocks cache first, and + fetches it from the L1 node otherwise. *) val fetch_tezos_block : + fetch_block_rpc -> + (block -> Block_header.shell_header) -> t -> Block_hash.t -> - Protocol_client_context.Alpha_block_services.block_info tzresult Lwt.t + block tzresult Lwt.t (** [make_prefetching_schedule l1_ctxt blocks] returns the list [blocks] with each element associated to a list of blocks to prefetch of at most @@ -121,10 +141,15 @@ val fetch_tezos_block : [b4;b5;b6]); ...]. *) val make_prefetching_schedule : t -> 'block trace -> ('block * 'block list) list -(** [prefetch_tezos_blocks l1_ctxt blocks] prefetches the blocks - asynchronously. NOTE: the number of blocks to prefetch must not be greater - than the size of the blocks cache otherwise they will be lost. *) -val prefetch_tezos_blocks : t -> head list -> unit +(** [prefetch_tezos_blocks fetch extract_header l1_ctxt blocks] prefetches the + blocks asynchronously. NOTE: the number of blocks to prefetch must not be + greater than the size of the blocks cache otherwise they will be lost. *) +val prefetch_tezos_blocks : + fetch_block_rpc -> + (block -> Block_header.shell_header) -> + t -> + head list -> + unit (**/**) 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 2f4e386a992f5ef0e2d887c2c3acf277a51e0f25..b05bb7cfdd91973d23d49d43985594ae0451c247 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/daemon.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/daemon.ml @@ -261,7 +261,7 @@ let process_l1_operation (type kind) node_ctxt (head : Layer1.header) ~source let process_l1_block_operations node_ctxt (head : Layer1.header) = let open Lwt_result_syntax in let* block = - Layer1.fetch_tezos_block node_ctxt.Node_context.l1_ctxt head.hash + Layer1_helpers.fetch_tezos_block node_ctxt.Node_context.l1_ctxt head.hash in let apply (type kind) accu ~source (operation : kind manager_operation) result = @@ -496,7 +496,7 @@ let on_layer_1_head (daemon_components : (module Daemon_components.S)) node_ctxt let* () = List.iter_es (fun (block, to_prefetch) -> - Layer1.prefetch_tezos_blocks node_ctxt.l1_ctxt to_prefetch ; + Layer1_helpers.prefetch_tezos_blocks node_ctxt.l1_ctxt to_prefetch ; let* header = get_header block in let catching_up = block.level < head.level in process_head daemon_components node_ctxt ~catching_up header) diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/dal_slots_tracker.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/dal_slots_tracker.ml index be36b93d62b970bbc6dc769e4d39cae4c37f3c4a..93bff8ef31e7efb263769d6eaddb3756bff69398 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/dal_slots_tracker.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/dal_slots_tracker.ml @@ -85,7 +85,7 @@ let slots_info node_ctxt (Layer1.{hash; _} as head) = return None | Some published_block_hash -> let* {metadata; _} = - Layer1.fetch_tezos_block node_ctxt.Node_context.l1_ctxt hash + Layer1_helpers.fetch_tezos_block node_ctxt.Node_context.l1_ctxt hash in let*? metadata = Option.to_result 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 0669089f1761e73a19ceeb6215383a8c2ede2caf..2eb75aa2daddaa9726b057886a7342f973572d45 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/inbox.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/inbox.ml @@ -33,7 +33,7 @@ let lift promise = Lwt.map Environment.wrap_tzresult promise let get_messages Node_context.{l1_ctxt; _} head = let open Lwt_result_syntax in - let* block = Layer1.fetch_tezos_block l1_ctxt head in + let* block = Layer1_helpers.fetch_tezos_block l1_ctxt head in let apply (type kind) accu ~source:_ (operation : kind manager_operation) _result = let open Result_syntax in 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 32ae0fcb1f8cdc77310825defe82ae24aac02ef6..bdcf20eef54075daa0b94582e4d2d58b05147ddd 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/interpreter.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/interpreter.ml @@ -33,7 +33,7 @@ open Alpha_context let get_boot_sector block_hash (node_ctxt : _ Node_context.t) = let open Lwt_result_syntax in let exception Found_boot_sector of string in - let* block = Layer1.fetch_tezos_block node_ctxt.l1_ctxt block_hash in + let* block = Layer1_helpers.fetch_tezos_block node_ctxt.l1_ctxt block_hash in let missing_boot_sector () = failwith "Boot sector not found in Tezos block %a" Block_hash.pp block_hash in diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.ml deleted file mode 100644 index 2a0d14b66fe9f02aaec85ac4ae9b95c035df079b..0000000000000000000000000000000000000000 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.ml +++ /dev/null @@ -1,275 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 Nomadic Labs, *) -(* Copyright (c) 2023 Functori, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -open Protocol_client_context - -(** - - Errors - ====== - -*) - -type error += Cannot_find_block of Block_hash.t - -let () = - Sc_rollup_node_errors.register_error_kind - ~id:"sc_rollup.node.cannot_find_block" - ~title:"Cannot find block from L1" - ~description:"A block couldn't be found from the L1 node" - ~pp:(fun ppf hash -> - Format.fprintf - ppf - "Block with hash %a was not found on the L1 node." - Block_hash.pp - hash) - `Temporary - Data_encoding.(obj1 (req "hash" Block_hash.encoding)) - (function Cannot_find_block hash -> Some hash | _ -> None) - (fun hash -> Cannot_find_block hash) - -(** - - State - ===== - -*) - -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 = - 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 - (Aches.Rache.Transfer (Aches.Rache.LRU) (Block_hash)) - -type blocks_cache = Alpha_block_services.block_info Blocks_cache.t - -type headers_cache = Block_header.shell_header Blocks_cache.t - -open Octez_crawler.Layer_1 - -type nonrec t = { - l1 : t; - cctxt : Client_context.full; - blocks_cache : blocks_cache; - (** Global blocks cache for the smart rollup node. *) - headers_cache : headers_cache; - (** Global block headers cache for the smart rollup node. *) - prefetch_blocks : int; (** Number of blocks to prefetch by default. *) -} - -let start ~name ~reconnection_delay ~l1_blocks_cache_size ?protocols - ?(prefetch_blocks = l1_blocks_cache_size) cctxt = - let open Lwt_result_syntax in - let*? () = - if prefetch_blocks > l1_blocks_cache_size then - error_with - "Blocks to prefetch must be less than the cache size: %d" - l1_blocks_cache_size - else Ok () - in - let*! l1 = start ~name ~reconnection_delay ?protocols cctxt in - let blocks_cache = Blocks_cache.create l1_blocks_cache_size in - let headers_cache = Blocks_cache.create l1_blocks_cache_size in - let cctxt = (cctxt :> Client_context.full) in - return {l1; cctxt; blocks_cache; headers_cache; prefetch_blocks} - -let shutdown {l1; _} = shutdown l1 - -let cache_shell_header {headers_cache; _} hash header = - Blocks_cache.put headers_cache hash (Lwt.return_some header) - -let iter_heads l1_ctxt f = - iter_heads l1_ctxt.l1 @@ fun (hash, {shell = {level; _} as header; _}) -> - cache_shell_header l1_ctxt hash header ; - f {hash; level; header} - -let wait_first l1_ctxt = - let open Lwt_syntax in - let+ hash, {shell = {level; _} as header; _} = wait_first l1_ctxt.l1 in - {hash; level; header} - -let get_predecessor_opt ?max_read {l1; _} = get_predecessor_opt ?max_read l1 - -let get_predecessor ?max_read {l1; _} = get_predecessor ?max_read l1 - -let get_tezos_reorg_for_new_head {l1; _} ?get_old_predecessor old_head new_head - = - get_tezos_reorg_for_new_head l1 ?get_old_predecessor old_head new_head - -module Internal_for_tests = struct - let dummy cctxt = - { - l1 = Internal_for_tests.dummy cctxt; - cctxt = (cctxt :> Client_context.full); - blocks_cache = Blocks_cache.create 1; - headers_cache = Blocks_cache.create 1; - prefetch_blocks = 0; - } -end - -(** - - Helpers - ======= - -*) - -(** [fetch_tezos_block l1_ctxt hash] returns a block shell header of - [hash]. Looks for the block in the blocks cache first, and fetches it from - the L1 node otherwise. *) -let fetch_tezos_shell_header {cctxt; blocks_cache; headers_cache; _} hash = - let open Lwt_syntax in - trace (Cannot_find_block hash) - @@ - let errors = ref None in - let fetch hash = - let* shell_header = - Tezos_shell_services.Shell_services.Blocks.Header.shell_header - cctxt - ~chain:`Main - ~block:(`Hash (hash, 0)) - () - in - match shell_header with - | Error errs -> - errors := Some errs ; - return_none - | Ok shell_header -> return_some shell_header - in - let+ shell_header = - let do_cached_header_fetch () = - Blocks_cache.bind_or_put headers_cache hash fetch Lwt.return - in - match Blocks_cache.bind blocks_cache hash Lwt.return with - | None -> do_cached_header_fetch () - | Some block -> ( - (* There is already a full block being fetched. *) - let* block in - match block with - | None -> - (* Fetching full block failed. *) - do_cached_header_fetch () - | Some block -> - (* The full block is already in the cache. *) - return_some block.header.shell) - in - match (shell_header, !errors) with - | None, None -> - (* This should not happen if {!find_in_cache} behaves correctly, - i.e. calls {!fetch} for cache misses. *) - error_with - "Fetching Tezos block %a failed unexpectedly" - Block_hash.pp - hash - | None, Some errs -> Error errs - | Some shell_header, _ -> Ok shell_header - -(** [fetch_tezos_block l1_ctxt hash] returns a block info given a block - hash. Looks for the block in the blocks cache first, and fetches it from the - L1 node otherwise. *) -let fetch_tezos_block {cctxt; blocks_cache; headers_cache; _} hash = - let open Lwt_syntax in - trace (Cannot_find_block hash) - @@ - let errors = ref None in - let fetch hash = - let* block = - Alpha_block_services.info - cctxt - ~chain:`Main - ~block:(`Hash (hash, 0)) - ~metadata:`Always - () - in - match block with - | Error errs -> - errors := Some errs ; - return_none - | Ok block -> return_some block - in - let+ block = Blocks_cache.bind_or_put blocks_cache hash fetch Lwt.return in - match (block, !errors) with - | None, None -> - (* This should not happen if {!find_in_cache} behaves correctly, - i.e. calls {!fetch} for cache misses. *) - error_with - "Fetching Tezos block %a failed unexpectedly" - Block_hash.pp - hash - | None, Some errs -> Error errs - | Some block, _ -> - Blocks_cache.put headers_cache hash (Lwt.return_some block.header.shell) ; - Ok block - -let make_prefetching_schedule {prefetch_blocks; _} blocks = - let blocks_with_prefetching, _, first_prefetch = - List.fold_left - (fun (acc, nb_prefetch, prefetch) b -> - let nb_prefetch = nb_prefetch + 1 in - let prefetch = b :: prefetch in - if nb_prefetch >= prefetch_blocks then ((b, prefetch) :: acc, 0, []) - else ((b, []) :: acc, nb_prefetch, prefetch)) - ([], 0, []) - (List.rev blocks) - in - match (blocks_with_prefetching, first_prefetch) with - | [], _ | _, [] -> blocks_with_prefetching - | (first, _) :: rest, _ -> (first, first_prefetch) :: rest - -let prefetch_tezos_blocks l1_ctxt = function - | [] -> () - | blocks -> - Lwt.async @@ fun () -> - List.iter_p - (fun {hash; _} -> - let open Lwt_syntax in - let+ _maybe_block = fetch_tezos_block l1_ctxt hash in - ()) - blocks diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.mli deleted file mode 100644 index 2b00c462c563872c8899d77425bde1b19fa8dba3..0000000000000000000000000000000000000000 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1.mli +++ /dev/null @@ -1,136 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 Nomadic Labs, *) -(* Copyright (c) 2023 Functori, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -(** This module maintains information about the layer 1 chain. - - This module follows the evolution of the layer 1 chain by - 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 - -type t - -(** [start ~name ~reconnection_delay ~l1_blocks_cache_size ?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. [l1_blocks_cache_size] - is the size of the caches for the blocks and headers. If [protocols] is - provided, only heads of these protocols will be monitored. *) -val start : - name:string -> - reconnection_delay:float -> - l1_blocks_cache_size:int -> - ?protocols:Protocol_hash.t list -> - ?prefetch_blocks:int -> - #Client_context.full -> - t tzresult Lwt.t - -(** [shutdown t] properly shuts the layer 1 down. *) -val shutdown : t -> unit Lwt.t - -(* TODO: https://gitlab.com/tezos/tezos/-/issues/3311 - Allow to retrieve L1 blocks through Tezos node storage locally. *) - -(** [iter_heads t f] calls [f] on all new heads appearing in the 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 -> (header -> 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 -> header Lwt.t - -val get_predecessor_opt : - ?max_read:int -> - t -> - Block_hash.t * int32 -> - (Block_hash.t * int32) option tzresult Lwt.t - -val get_predecessor : - ?max_read:int -> - t -> - Block_hash.t * int32 -> - (Block_hash.t * int32) tzresult Lwt.t - -val get_tezos_reorg_for_new_head : - t -> - ?get_old_predecessor: - (Block_hash.t * int32 -> (Block_hash.t * int32) tzresult Lwt.t) -> - [`Head of Block_hash.t * int32 | `Level of int32] -> - Block_hash.t * int32 -> - (Block_hash.t * int32) Reorg.t tzresult Lwt.t - -(** {2 Helpers } *) - -(** [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. *) -val fetch_tezos_shell_header : - t -> Block_hash.t -> Block_header.shell_header tzresult Lwt.t - -(** [fetch_tezos_block cctxt hash] returns a block info given a block hash. - Looks for the block in the blocks cache first, and fetches it from the L1 - node otherwise. *) -val fetch_tezos_block : - t -> - Block_hash.t -> - Protocol_client_context.Alpha_block_services.block_info tzresult Lwt.t - -(** [make_prefetching_schedule l1_ctxt blocks] returns the list [blocks] with - each element associated to a list of blocks to prefetch of at most - [l1_ctxt.prefetch_blocks]. If [blocks = [b1; ...; bn]] and [prefetch_blocks - = 3] then the result will be [(b1, [b1;b2;b3]); (b2, []); (b3, []); (b4, - [b4;b5;b6]); ...]. *) -val make_prefetching_schedule : t -> 'block trace -> ('block * 'block list) list - -(** [prefetch_tezos_blocks l1_ctxt blocks] prefetches the blocks - asynchronously. NOTE: the number of blocks to prefetch must not be greater - than the size of the blocks cache otherwise they will be lost. *) -val prefetch_tezos_blocks : t -> head list -> unit - -(**/**) - -module Internal_for_tests : sig - (** Create a dummy Layer 1 object that does not follow any L1 chain. This - function is only to be used as a placeholder for unit tests (that do not - exercise the Layer 1 connection). *) - val dummy : #Client_context.full -> t -end diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1_helpers.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1_helpers.ml new file mode 100644 index 0000000000000000000000000000000000000000..8312c25843735023a287a1287b424eb69e6e2757 --- /dev/null +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1_helpers.ml @@ -0,0 +1,54 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol_client_context + +type Layer1.block += Block of Alpha_block_services.block_info + +let fetch cctxt ?metadata ?chain ?block () = + let open Lwt_result_syntax in + let+ block = Alpha_block_services.info cctxt ?metadata ?chain ?block () in + Block block + +let extract_header = function + | Block block -> block.header.shell + | _ -> + invalid_arg ("Internal error: Block is not of protocol " ^ Protocol.name) + +let fetch_tezos_block l1_ctxt hash = + let open Lwt_result_syntax in + let+ block = Layer1.fetch_tezos_block fetch extract_header l1_ctxt hash in + match block with + | Block block -> block + | _ -> + Format.kasprintf + invalid_arg + "Internal error: Block %a is not of protocol %s" + Block_hash.pp + hash + Protocol.name + +let prefetch_tezos_blocks = Layer1.prefetch_tezos_blocks fetch extract_header diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1_helpers.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1_helpers.mli new file mode 100644 index 0000000000000000000000000000000000000000..3b6fc64abf0ad9e4548664e3a949b88e3e2551b2 --- /dev/null +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/layer1_helpers.mli @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Octez_smart_rollup_node.Layer1 + +(** [fetch_tezos_block cctxt hash] returns a block info given a block hash. + Looks for the block in the blocks cache first, and fetches it from the L1 + node otherwise. *) +val fetch_tezos_block : + t -> + Block_hash.t -> + Protocol_client_context.Alpha_block_services.block_info tzresult Lwt.t + +(** [prefetch_tezos_blocks l1_ctxt blocks] prefetches the blocks + asynchronously. NOTE: the number of blocks to prefetch must not be greater + than the size of the blocks cache otherwise they will be lost. *) +val prefetch_tezos_blocks : t -> head list -> unit diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/simulation.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/simulation.ml index b7177b4885ef847f1d83a7ec2afa082082d82a42..a13a580a5e13fc4b64f146066ec77d784688b77b 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/simulation.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/simulation.ml @@ -46,7 +46,9 @@ type t = { let simulate_info_per_level (node_ctxt : [`Read] Node_context.t) predecessor = let open Lwt_result_syntax in - let* block_info = Layer1.fetch_tezos_block node_ctxt.l1_ctxt predecessor in + let* block_info = + Layer1_helpers.fetch_tezos_block node_ctxt.l1_ctxt predecessor + in let predecessor_timestamp = block_info.header.shell.timestamp in return {predecessor_timestamp; predecessor} 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 32b4f107f6dd37f92bcf4fea97584bc8d773b71c..504a1a82122af16442d2283b4ead04dfc7ef804d 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 @@ -26,6 +26,7 @@ open Octez_smart_rollup open Protocol open Alpha_context +open Octez_smart_rollup_node let uid = ref 0 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 87f777338e06f0f0f76082de5b94e1ee3f533dd9..5d89cafafb687e4d7666f90f3131d90b0bb7a44d 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/daemon.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/daemon.ml @@ -259,7 +259,7 @@ let process_l1_operation (type kind) node_ctxt (head : Layer1.header) ~source let process_l1_block_operations node_ctxt (head : Layer1.header) = let open Lwt_result_syntax in let* block = - Layer1.fetch_tezos_block node_ctxt.Node_context.l1_ctxt head.hash + Layer1_helpers.fetch_tezos_block node_ctxt.Node_context.l1_ctxt head.hash in let apply (type kind) accu ~source (operation : kind manager_operation) result = @@ -494,7 +494,7 @@ let on_layer_1_head (daemon_components : (module Daemon_components.S)) node_ctxt let* () = List.iter_es (fun (block, to_prefetch) -> - Layer1.prefetch_tezos_blocks node_ctxt.l1_ctxt to_prefetch ; + Layer1_helpers.prefetch_tezos_blocks node_ctxt.l1_ctxt to_prefetch ; let* header = get_header block in let catching_up = block.level < head.level in process_head daemon_components node_ctxt ~catching_up header) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/dal_slots_tracker.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/dal_slots_tracker.ml index 8bb3ffd88b51fc85f351d32c347c2fe1ab0d782c..ced86b18711fdb30acf89937ac8f6334c9940159 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/dal_slots_tracker.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/dal_slots_tracker.ml @@ -85,7 +85,7 @@ let slots_info node_ctxt (Layer1.{hash; _} as head) = return None | Some published_block_hash -> let* {metadata; _} = - Layer1.fetch_tezos_block node_ctxt.Node_context.l1_ctxt hash + Layer1_helpers.fetch_tezos_block node_ctxt.Node_context.l1_ctxt hash in let*? metadata = Option.to_result 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 40c50eda8accd06d6e4ed3c83c833a180317dcb9..e756a7b9db7bc5240446d9ecaad5ddc763dae401 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/inbox.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/inbox.ml @@ -33,7 +33,7 @@ let lift promise = Lwt.map Environment.wrap_tzresult promise let get_messages Node_context.{l1_ctxt; _} head = let open Lwt_result_syntax in - let* block = Layer1.fetch_tezos_block l1_ctxt head in + let* block = Layer1_helpers.fetch_tezos_block l1_ctxt head in let apply (type kind) accu ~source:_ (operation : kind manager_operation) _result = let open Result_syntax in 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 5e00fc32543f5547fbc56f20f02104f2e89fd0aa..bb64d5d879b609c11cc5a860722ba7c2d6da4951 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/interpreter.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/interpreter.ml @@ -33,7 +33,7 @@ open Alpha_context let get_boot_sector block_hash (node_ctxt : _ Node_context.t) = let open Lwt_result_syntax in let exception Found_boot_sector of string in - let* block = Layer1.fetch_tezos_block node_ctxt.l1_ctxt block_hash in + let* block = Layer1_helpers.fetch_tezos_block node_ctxt.l1_ctxt block_hash in let missing_boot_sector () = failwith "Boot sector not found in Tezos block %a" Block_hash.pp block_hash in diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.ml deleted file mode 100644 index ec67b468980861cffff52594c78bb699803ed56f..0000000000000000000000000000000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.ml +++ /dev/null @@ -1,275 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 Nomadic Labs, *) -(* Copyright (c) 2023 Functori, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -open Protocol_client_context - -(** - - Errors - ====== - -*) - -type error += Cannot_find_block of Block_hash.t - -let () = - Sc_rollup_node_errors.register_error_kind - ~id:"sc_rollup.node.cannot_find_block" - ~title:"Cannot find block from L1" - ~description:"A block couldn't be found from the L1 node" - ~pp:(fun ppf hash -> - Format.fprintf - ppf - "Block with hash %a was not found on the L1 node." - Block_hash.pp - hash) - `Temporary - Data_encoding.(obj1 (req "hash" Block_hash.encoding)) - (function Cannot_find_block hash -> Some hash | _ -> None) - (fun hash -> Cannot_find_block hash) - -(** - - State - ===== - -*) - -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 = - 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 - (Aches.Rache.Transfer (Aches.Rache.LRU) (Block_hash)) - -type blocks_cache = Alpha_block_services.block_info Blocks_cache.t - -type headers_cache = Block_header.shell_header Blocks_cache.t - -open Octez_crawler.Layer_1 - -type nonrec t = { - l1 : t; - cctxt : Client_context.full; - blocks_cache : blocks_cache; - (** Global blocks cache for the smart rollup node. *) - headers_cache : headers_cache; - (** Global block headers cache for the smart rollup node. *) - prefetch_blocks : int; (** Number of blocks to prefetch by default. *) -} - -let start ~name ~reconnection_delay ~l1_blocks_cache_size ?protocols - ?(prefetch_blocks = l1_blocks_cache_size) cctxt = - let open Lwt_result_syntax in - let*? () = - if prefetch_blocks > l1_blocks_cache_size then - error_with - "Blocks to prefetch must be less than the cache size: %d" - l1_blocks_cache_size - else Ok () - in - let*! l1 = start ~name ~reconnection_delay ?protocols cctxt in - let blocks_cache = Blocks_cache.create l1_blocks_cache_size in - let headers_cache = Blocks_cache.create l1_blocks_cache_size in - let cctxt = (cctxt :> Client_context.full) in - return {l1; cctxt; blocks_cache; headers_cache; prefetch_blocks} - -let shutdown {l1; _} = shutdown l1 - -let cache_shell_header {headers_cache; _} hash header = - Blocks_cache.put headers_cache hash (Lwt.return_some header) - -let iter_heads l1_ctxt f = - iter_heads l1_ctxt.l1 @@ fun (hash, {shell = {level; _} as header; _}) -> - cache_shell_header l1_ctxt hash header ; - f {hash; level; header} - -let wait_first l1_ctxt = - let open Lwt_syntax in - let+ hash, {shell = {level; _} as header; _} = wait_first l1_ctxt.l1 in - {hash; level; header} - -let get_predecessor_opt ?max_read {l1; _} = get_predecessor_opt ?max_read l1 - -let get_predecessor ?max_read {l1; _} = get_predecessor ?max_read l1 - -let get_tezos_reorg_for_new_head {l1; _} ?get_old_predecessor old_head new_head - = - get_tezos_reorg_for_new_head l1 ?get_old_predecessor old_head new_head - -module Internal_for_tests = struct - let dummy cctxt = - { - l1 = Internal_for_tests.dummy cctxt; - cctxt = (cctxt :> Client_context.full); - blocks_cache = Blocks_cache.create 1; - headers_cache = Blocks_cache.create 1; - prefetch_blocks = 0; - } -end - -(** - - Helpers - ======= - -*) - -(** [fetch_tezos_block cctxt hash] returns a block shell header of - [hash]. Looks for the block in the blocks cache first, and fetches it from - the L1 node otherwise. *) -let fetch_tezos_shell_header {cctxt; blocks_cache; headers_cache; _} hash = - let open Lwt_syntax in - trace (Cannot_find_block hash) - @@ - let errors = ref None in - let fetch hash = - let* shell_header = - Tezos_shell_services.Shell_services.Blocks.Header.shell_header - cctxt - ~chain:`Main - ~block:(`Hash (hash, 0)) - () - in - match shell_header with - | Error errs -> - errors := Some errs ; - return_none - | Ok shell_header -> return_some shell_header - in - let+ shell_header = - let do_cached_header_fetch () = - Blocks_cache.bind_or_put headers_cache hash fetch Lwt.return - in - match Blocks_cache.bind blocks_cache hash Lwt.return with - | None -> do_cached_header_fetch () - | Some block -> ( - (* There is already a full block being fetched. *) - let* block in - match block with - | None -> - (* Fetching full block failed. *) - do_cached_header_fetch () - | Some block -> - (* The full block is already in the cache. *) - return_some block.header.shell) - in - match (shell_header, !errors) with - | None, None -> - (* This should not happen if {!find_in_cache} behaves correctly, - i.e. calls {!fetch} for cache misses. *) - error_with - "Fetching Tezos block %a failed unexpectedly" - Block_hash.pp - hash - | None, Some errs -> Error errs - | Some shell_header, _ -> Ok shell_header - -(** [fetch_tezos_block cctxt hash] returns a block info given a block - hash. Looks for the block in the blocks cache first, and fetches it from the - L1 node otherwise. *) -let fetch_tezos_block {cctxt; blocks_cache; headers_cache; _} hash = - let open Lwt_syntax in - trace (Cannot_find_block hash) - @@ - let errors = ref None in - let fetch hash = - let* block = - Alpha_block_services.info - cctxt - ~chain:`Main - ~block:(`Hash (hash, 0)) - ~metadata:`Always - () - in - match block with - | Error errs -> - errors := Some errs ; - return_none - | Ok block -> return_some block - in - let+ block = Blocks_cache.bind_or_put blocks_cache hash fetch Lwt.return in - match (block, !errors) with - | None, None -> - (* This should not happen if {!find_in_cache} behaves correctly, - i.e. calls {!fetch} for cache misses. *) - error_with - "Fetching Tezos block %a failed unexpectedly" - Block_hash.pp - hash - | None, Some errs -> Error errs - | Some block, _ -> - Blocks_cache.put headers_cache hash (Lwt.return_some block.header.shell) ; - Ok block - -let make_prefetching_schedule {prefetch_blocks; _} blocks = - let blocks_with_prefetching, _, first_prefetch = - List.fold_left - (fun (acc, nb_prefetch, prefetch) b -> - let nb_prefetch = nb_prefetch + 1 in - let prefetch = b :: prefetch in - if nb_prefetch >= prefetch_blocks then ((b, prefetch) :: acc, 0, []) - else ((b, []) :: acc, nb_prefetch, prefetch)) - ([], 0, []) - (List.rev blocks) - in - match (blocks_with_prefetching, first_prefetch) with - | [], _ | _, [] -> blocks_with_prefetching - | (first, _) :: rest, _ -> (first, first_prefetch) :: rest - -let prefetch_tezos_blocks l1_ctxt = function - | [] -> () - | blocks -> - Lwt.async @@ fun () -> - List.iter_p - (fun {hash; _} -> - let open Lwt_syntax in - let+ _maybe_block = fetch_tezos_block l1_ctxt hash in - ()) - blocks diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.mli deleted file mode 100644 index 2b00c462c563872c8899d77425bde1b19fa8dba3..0000000000000000000000000000000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/layer1.mli +++ /dev/null @@ -1,136 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 Nomadic Labs, *) -(* Copyright (c) 2023 Functori, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -(** This module maintains information about the layer 1 chain. - - This module follows the evolution of the layer 1 chain by - 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 - -type t - -(** [start ~name ~reconnection_delay ~l1_blocks_cache_size ?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. [l1_blocks_cache_size] - is the size of the caches for the blocks and headers. If [protocols] is - provided, only heads of these protocols will be monitored. *) -val start : - name:string -> - reconnection_delay:float -> - l1_blocks_cache_size:int -> - ?protocols:Protocol_hash.t list -> - ?prefetch_blocks:int -> - #Client_context.full -> - t tzresult Lwt.t - -(** [shutdown t] properly shuts the layer 1 down. *) -val shutdown : t -> unit Lwt.t - -(* TODO: https://gitlab.com/tezos/tezos/-/issues/3311 - Allow to retrieve L1 blocks through Tezos node storage locally. *) - -(** [iter_heads t f] calls [f] on all new heads appearing in the 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 -> (header -> 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 -> header Lwt.t - -val get_predecessor_opt : - ?max_read:int -> - t -> - Block_hash.t * int32 -> - (Block_hash.t * int32) option tzresult Lwt.t - -val get_predecessor : - ?max_read:int -> - t -> - Block_hash.t * int32 -> - (Block_hash.t * int32) tzresult Lwt.t - -val get_tezos_reorg_for_new_head : - t -> - ?get_old_predecessor: - (Block_hash.t * int32 -> (Block_hash.t * int32) tzresult Lwt.t) -> - [`Head of Block_hash.t * int32 | `Level of int32] -> - Block_hash.t * int32 -> - (Block_hash.t * int32) Reorg.t tzresult Lwt.t - -(** {2 Helpers } *) - -(** [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. *) -val fetch_tezos_shell_header : - t -> Block_hash.t -> Block_header.shell_header tzresult Lwt.t - -(** [fetch_tezos_block cctxt hash] returns a block info given a block hash. - Looks for the block in the blocks cache first, and fetches it from the L1 - node otherwise. *) -val fetch_tezos_block : - t -> - Block_hash.t -> - Protocol_client_context.Alpha_block_services.block_info tzresult Lwt.t - -(** [make_prefetching_schedule l1_ctxt blocks] returns the list [blocks] with - each element associated to a list of blocks to prefetch of at most - [l1_ctxt.prefetch_blocks]. If [blocks = [b1; ...; bn]] and [prefetch_blocks - = 3] then the result will be [(b1, [b1;b2;b3]); (b2, []); (b3, []); (b4, - [b4;b5;b6]); ...]. *) -val make_prefetching_schedule : t -> 'block trace -> ('block * 'block list) list - -(** [prefetch_tezos_blocks l1_ctxt blocks] prefetches the blocks - asynchronously. NOTE: the number of blocks to prefetch must not be greater - than the size of the blocks cache otherwise they will be lost. *) -val prefetch_tezos_blocks : t -> head list -> unit - -(**/**) - -module Internal_for_tests : sig - (** Create a dummy Layer 1 object that does not follow any L1 chain. This - function is only to be used as a placeholder for unit tests (that do not - exercise the Layer 1 connection). *) - val dummy : #Client_context.full -> t -end diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/layer1_helpers.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/layer1_helpers.ml new file mode 100644 index 0000000000000000000000000000000000000000..8312c25843735023a287a1287b424eb69e6e2757 --- /dev/null +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/layer1_helpers.ml @@ -0,0 +1,54 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol_client_context + +type Layer1.block += Block of Alpha_block_services.block_info + +let fetch cctxt ?metadata ?chain ?block () = + let open Lwt_result_syntax in + let+ block = Alpha_block_services.info cctxt ?metadata ?chain ?block () in + Block block + +let extract_header = function + | Block block -> block.header.shell + | _ -> + invalid_arg ("Internal error: Block is not of protocol " ^ Protocol.name) + +let fetch_tezos_block l1_ctxt hash = + let open Lwt_result_syntax in + let+ block = Layer1.fetch_tezos_block fetch extract_header l1_ctxt hash in + match block with + | Block block -> block + | _ -> + Format.kasprintf + invalid_arg + "Internal error: Block %a is not of protocol %s" + Block_hash.pp + hash + Protocol.name + +let prefetch_tezos_blocks = Layer1.prefetch_tezos_blocks fetch extract_header diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/layer1_helpers.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/layer1_helpers.mli new file mode 100644 index 0000000000000000000000000000000000000000..3b6fc64abf0ad9e4548664e3a949b88e3e2551b2 --- /dev/null +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/layer1_helpers.mli @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Octez_smart_rollup_node.Layer1 + +(** [fetch_tezos_block cctxt hash] returns a block info given a block hash. + Looks for the block in the blocks cache first, and fetches it from the L1 + node otherwise. *) +val fetch_tezos_block : + t -> + Block_hash.t -> + Protocol_client_context.Alpha_block_services.block_info tzresult Lwt.t + +(** [prefetch_tezos_blocks l1_ctxt blocks] prefetches the blocks + asynchronously. NOTE: the number of blocks to prefetch must not be greater + than the size of the blocks cache otherwise they will be lost. *) +val prefetch_tezos_blocks : t -> head list -> unit diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/simulation.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/simulation.ml index b7177b4885ef847f1d83a7ec2afa082082d82a42..a13a580a5e13fc4b64f146066ec77d784688b77b 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/simulation.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/simulation.ml @@ -46,7 +46,9 @@ type t = { let simulate_info_per_level (node_ctxt : [`Read] Node_context.t) predecessor = let open Lwt_result_syntax in - let* block_info = Layer1.fetch_tezos_block node_ctxt.l1_ctxt predecessor in + let* block_info = + Layer1_helpers.fetch_tezos_block node_ctxt.l1_ctxt predecessor + in let predecessor_timestamp = block_info.header.shell.timestamp in return {predecessor_timestamp; predecessor} 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 ce6ecd282b50126157c46c359a789588dd2295c8..1bc441f7de89d82094e734236edf120bc364f046 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 @@ -26,6 +26,7 @@ open Octez_smart_rollup open Protocol open Alpha_context +open Octez_smart_rollup_node let uid = ref 0 diff --git a/src/proto_alpha/lib_sc_rollup_node/daemon.ml b/src/proto_alpha/lib_sc_rollup_node/daemon.ml index 4c10d33d5f476fde6b48d2264f7c6175b5d1e1b6..bf66812a90f44752f0a8dcabb3c41ad80a019f7a 100644 --- a/src/proto_alpha/lib_sc_rollup_node/daemon.ml +++ b/src/proto_alpha/lib_sc_rollup_node/daemon.ml @@ -259,7 +259,7 @@ let process_l1_operation (type kind) node_ctxt (head : Layer1.header) ~source let process_l1_block_operations node_ctxt (head : Layer1.header) = let open Lwt_result_syntax in let* block = - Layer1.fetch_tezos_block node_ctxt.Node_context.l1_ctxt head.hash + Layer1_helpers.fetch_tezos_block node_ctxt.Node_context.l1_ctxt head.hash in let apply (type kind) accu ~source (operation : kind manager_operation) result = @@ -495,7 +495,7 @@ let on_layer_1_head (daemon_components : (module Daemon_components.S)) node_ctxt let* () = List.iter_es (fun (block, to_prefetch) -> - Layer1.prefetch_tezos_blocks node_ctxt.l1_ctxt to_prefetch ; + Layer1_helpers.prefetch_tezos_blocks node_ctxt.l1_ctxt to_prefetch ; let* header = get_header block in let catching_up = block.level < head.level in process_head daemon_components node_ctxt ~catching_up header) diff --git a/src/proto_alpha/lib_sc_rollup_node/dal_slots_tracker.ml b/src/proto_alpha/lib_sc_rollup_node/dal_slots_tracker.ml index 3d932a0ac38d6c41d90e8e40c1b06bd44a95ae61..9d73b5447eb2e7bb4a121336d43fbee1d721a009 100644 --- a/src/proto_alpha/lib_sc_rollup_node/dal_slots_tracker.ml +++ b/src/proto_alpha/lib_sc_rollup_node/dal_slots_tracker.ml @@ -84,7 +84,7 @@ let slots_info node_ctxt (Layer1.{hash; _} as head) = return None | Some published_block_hash -> let* {metadata; _} = - Layer1.fetch_tezos_block node_ctxt.Node_context.l1_ctxt hash + Layer1_helpers.fetch_tezos_block node_ctxt.Node_context.l1_ctxt hash in let*? metadata = Option.to_result diff --git a/src/proto_alpha/lib_sc_rollup_node/inbox.ml b/src/proto_alpha/lib_sc_rollup_node/inbox.ml index ff490d6cb7d9425011ff664137936241e5a50114..d711228ed16683fefcb1fd7f450fbcd2e9b2eb44 100644 --- a/src/proto_alpha/lib_sc_rollup_node/inbox.ml +++ b/src/proto_alpha/lib_sc_rollup_node/inbox.ml @@ -33,7 +33,7 @@ let lift promise = Lwt.map Environment.wrap_tzresult promise let get_messages Node_context.{l1_ctxt; _} head = let open Lwt_result_syntax in - let* block = Layer1.fetch_tezos_block l1_ctxt head in + let* block = Layer1_helpers.fetch_tezos_block l1_ctxt head in let apply (type kind) accu ~source:_ (operation : kind manager_operation) _result = let open Result_syntax in diff --git a/src/proto_alpha/lib_sc_rollup_node/interpreter.ml b/src/proto_alpha/lib_sc_rollup_node/interpreter.ml index 06748f6e0f015513c80f7f506506ad9c24b33e21..77143300570d37e02ae8c5f3acd219e5d964a4de 100644 --- a/src/proto_alpha/lib_sc_rollup_node/interpreter.ml +++ b/src/proto_alpha/lib_sc_rollup_node/interpreter.ml @@ -33,7 +33,7 @@ open Alpha_context let get_boot_sector block_hash (node_ctxt : _ Node_context.t) = let open Lwt_result_syntax in let exception Found_boot_sector of string in - let* block = Layer1.fetch_tezos_block node_ctxt.l1_ctxt block_hash in + let* block = Layer1_helpers.fetch_tezos_block node_ctxt.l1_ctxt block_hash in let missing_boot_sector () = failwith "Boot sector not found in Tezos block %a" Block_hash.pp block_hash in diff --git a/src/proto_alpha/lib_sc_rollup_node/layer1_helpers.ml b/src/proto_alpha/lib_sc_rollup_node/layer1_helpers.ml new file mode 100644 index 0000000000000000000000000000000000000000..8312c25843735023a287a1287b424eb69e6e2757 --- /dev/null +++ b/src/proto_alpha/lib_sc_rollup_node/layer1_helpers.ml @@ -0,0 +1,54 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol_client_context + +type Layer1.block += Block of Alpha_block_services.block_info + +let fetch cctxt ?metadata ?chain ?block () = + let open Lwt_result_syntax in + let+ block = Alpha_block_services.info cctxt ?metadata ?chain ?block () in + Block block + +let extract_header = function + | Block block -> block.header.shell + | _ -> + invalid_arg ("Internal error: Block is not of protocol " ^ Protocol.name) + +let fetch_tezos_block l1_ctxt hash = + let open Lwt_result_syntax in + let+ block = Layer1.fetch_tezos_block fetch extract_header l1_ctxt hash in + match block with + | Block block -> block + | _ -> + Format.kasprintf + invalid_arg + "Internal error: Block %a is not of protocol %s" + Block_hash.pp + hash + Protocol.name + +let prefetch_tezos_blocks = Layer1.prefetch_tezos_blocks fetch extract_header diff --git a/src/proto_alpha/lib_sc_rollup_node/layer1_helpers.mli b/src/proto_alpha/lib_sc_rollup_node/layer1_helpers.mli new file mode 100644 index 0000000000000000000000000000000000000000..3b6fc64abf0ad9e4548664e3a949b88e3e2551b2 --- /dev/null +++ b/src/proto_alpha/lib_sc_rollup_node/layer1_helpers.mli @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Octez_smart_rollup_node.Layer1 + +(** [fetch_tezos_block cctxt hash] returns a block info given a block hash. + Looks for the block in the blocks cache first, and fetches it from the L1 + node otherwise. *) +val fetch_tezos_block : + t -> + Block_hash.t -> + Protocol_client_context.Alpha_block_services.block_info tzresult Lwt.t + +(** [prefetch_tezos_blocks l1_ctxt blocks] prefetches the blocks + asynchronously. NOTE: the number of blocks to prefetch must not be greater + than the size of the blocks cache otherwise they will be lost. *) +val prefetch_tezos_blocks : t -> head list -> unit diff --git a/src/proto_alpha/lib_sc_rollup_node/simulation.ml b/src/proto_alpha/lib_sc_rollup_node/simulation.ml index b7177b4885ef847f1d83a7ec2afa082082d82a42..a13a580a5e13fc4b64f146066ec77d784688b77b 100644 --- a/src/proto_alpha/lib_sc_rollup_node/simulation.ml +++ b/src/proto_alpha/lib_sc_rollup_node/simulation.ml @@ -46,7 +46,9 @@ type t = { let simulate_info_per_level (node_ctxt : [`Read] Node_context.t) predecessor = let open Lwt_result_syntax in - let* block_info = Layer1.fetch_tezos_block node_ctxt.l1_ctxt predecessor in + let* block_info = + Layer1_helpers.fetch_tezos_block node_ctxt.l1_ctxt predecessor + in let predecessor_timestamp = block_info.header.shell.timestamp in return {predecessor_timestamp; predecessor} 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 efb908bcb9beac14683830f259d97ebbd76ab637..e888c6b40313f6e550b8a8b8c8698e0d9a9c3501 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 @@ -26,6 +26,7 @@ open Octez_smart_rollup open Protocol open Alpha_context +open Octez_smart_rollup_node let uid = ref 0