diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/RPC_server.ml b/src/proto_016_PtMumbai/bin_sc_rollup_node/RPC_server.ml index 2c12e8358aba2802295b066cb5bfc6ecfc602925..454e1e15d14e2d06c193668ff7b0863cfc5aafc5 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/RPC_server.ml +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/RPC_server.ml @@ -29,14 +29,14 @@ open Protocol let get_head store = let open Lwt_result_syntax in - let*! head = State.last_processed_head_opt store in + let*! head = Node_context.last_processed_head_opt store in match head with | None -> failwith "No head" | Some {header = {block_hash; _}; _} -> return block_hash -let get_finalized store = +let get_finalized node_ctxt = let open Lwt_result_syntax in - let*! head = State.get_finalized_head_opt store in + let*! head = Node_context.get_finalized_head_opt node_ctxt in match head with | None -> failwith "No finalized head" | Some {header = {block_hash; _}; _} -> return block_hash @@ -45,39 +45,36 @@ let get_last_cemented (node_ctxt : _ Node_context.t) = let open Lwt_result_syntax in protect @@ fun () -> let* lcc_hash = - State.hash_of_level + Node_context.hash_of_level node_ctxt (Alpha_context.Raw_level.to_int32 node_ctxt.lcc.level) in return lcc_hash -let get_head_hash_opt store = +let get_head_hash_opt node_ctxt = let open Lwt_option_syntax in - let+ {header = {block_hash; _}; _} = State.last_processed_head_opt store in + let+ {header = {block_hash; _}; _} = + Node_context.last_processed_head_opt node_ctxt + in block_hash -let get_head_level_opt store = +let get_head_level_opt node_ctxt = let open Lwt_option_syntax in - let+ {header = {level; _}; _} = State.last_processed_head_opt store in + let+ {header = {level; _}; _} = + Node_context.last_processed_head_opt node_ctxt + in Alpha_context.Raw_level.to_int32 level -let get_l2_block_exn store block = - let open Lwt_result_syntax in - let*! b = Store.L2_blocks.get store block in - return b - module Slot_pages_map = struct open Protocol open Alpha_context include Map.Make (Dal.Slot_index) end -let get_dal_confirmed_slot_pages store block = +let get_dal_confirmed_slot_pages node_ctxt block = let open Lwt_result_syntax in let*! slot_pages = - Store.Dal_slot_pages.list_secondary_keys_with_values - store - ~primary_key:block + Node_context.list_slot_pages node_ctxt ~confirmed_in_block_hash:block in (* Slot pages are sorted in lexicographic order of slot index and page number.*) @@ -96,23 +93,24 @@ let get_dal_confirmed_slot_pages store block = in return @@ Slot_pages_map.bindings slot_pages_map -let get_dal_slot_page store block slot_index slot_page = +let get_dal_slot_page node_ctxt block slot_index slot_page = let open Lwt_result_syntax in let*! processed = - Store.Dal_processed_slots.find - store - ~primary_key:block - ~secondary_key:slot_index + Node_context.processed_slot + node_ctxt + ~confirmed_in_block_hash:block + slot_index in match processed with | None -> return ("Slot page has not been downloaded", None) | Some `Unconfirmed -> return ("Slot was not confirmed", None) | Some `Confirmed -> ( let*! contents_opt = - Store.Dal_slot_pages.find - store - ~primary_key:block - ~secondary_key:(slot_index, slot_page) + Node_context.find_slot_page + node_ctxt + ~confirmed_in_block_hash:block + ~slot_index + ~page_index:slot_page in match contents_opt with | None -> assert false @@ -190,10 +188,10 @@ module Block_directory = Make_directory (struct let open Lwt_result_syntax in let+ block = match block with - | `Head -> get_head node_ctxt.Node_context.store + | `Head -> get_head node_ctxt | `Hash b -> return b - | `Level l -> State.hash_of_level node_ctxt l - | `Finalized -> get_finalized node_ctxt.Node_context.store + | `Level l -> Node_context.hash_of_level node_ctxt l + | `Finalized -> get_finalized node_ctxt | `Cemented -> get_last_cemented node_ctxt in (Node_context.readonly node_ctxt, block) @@ -208,10 +206,10 @@ module Outbox_directory = Make_directory (struct let open Lwt_result_syntax in let+ block = match block with - | `Head -> get_head node_ctxt.Node_context.store + | `Head -> get_head node_ctxt | `Hash b -> return b - | `Level l -> State.hash_of_level node_ctxt l - | `Finalized -> get_finalized node_ctxt.Node_context.store + | `Level l -> Node_context.hash_of_level node_ctxt l + | `Finalized -> get_finalized node_ctxt | `Cemented -> get_last_cemented node_ctxt in (Node_context.readonly node_ctxt, block, level) @@ -229,9 +227,9 @@ module Common = struct Block_directory.register0 Sc_rollup_services.Global.Block.num_messages @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in - let* l2_block = get_l2_block_exn node_ctxt.store block in - let*! {messages; _} = - Store.Messages.get node_ctxt.store l2_block.header.inbox_witness + let* l2_block = Node_context.get_l2_block node_ctxt block in + let* {messages; _} = + Node_context.get_messages node_ctxt l2_block.header.inbox_witness in return @@ Z.of_int (List.length messages) @@ -241,11 +239,11 @@ module Common = struct let () = Global_directory.register0 Sc_rollup_services.Global.current_tezos_head - @@ fun node_ctxt () () -> get_head_hash_opt node_ctxt.store >>= return + @@ fun node_ctxt () () -> get_head_hash_opt node_ctxt >>= return let () = Global_directory.register0 Sc_rollup_services.Global.current_tezos_level - @@ fun node_ctxt () () -> get_head_level_opt node_ctxt.store >>= return + @@ fun node_ctxt () () -> get_head_level_opt node_ctxt >>= return let () = Block_directory.register0 Sc_rollup_services.Global.Block.hash @@ -253,17 +251,19 @@ module Common = struct let () = Block_directory.register0 Sc_rollup_services.Global.Block.level - @@ fun (node_ctxt, block) () () -> State.level_of_hash node_ctxt block + @@ fun (node_ctxt, block) () () -> + Node_context.level_of_hash node_ctxt block let () = Block_directory.register0 Sc_rollup_services.Global.Block.inbox - @@ fun (node_ctxt, block) () () -> Inbox.inbox_of_hash node_ctxt block + @@ fun (node_ctxt, block) () () -> + Node_context.get_inbox_by_block_hash node_ctxt block let () = Block_directory.register0 Sc_rollup_services.Global.Block.ticks @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in - let+ l2_block = get_l2_block_exn node_ctxt.store block in + let+ l2_block = Node_context.get_l2_block node_ctxt block in Z.of_int64 l2_block.num_ticks end @@ -299,7 +299,7 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct Some map | None -> None in - let* level = State.level_of_hash node_ctxt block in + let* level = Node_context.level_of_hash node_ctxt block in let* sim = Simulation.start_simulation node_ctxt @@ -372,12 +372,12 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct let open Lwt_result_syntax in let*! res = let open Lwt_option_syntax in - let* head = State.last_processed_head_opt node_ctxt.store in + let* head = Node_context.last_processed_head_opt node_ctxt in let commitment_hash = Sc_rollup_block.most_recent_commitment head.header in let* commitment = - Store.Commitments.find node_ctxt.store commitment_hash + Node_context.find_commitment node_ctxt commitment_hash in return (commitment, commitment_hash) in @@ -397,7 +397,7 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct available only when the commitment has been published and included in a block. *) let*! published_at_level_info = - Store.Commitments_published_at_level.find node_ctxt.store hash + Node_context.commitment_published_at_level node_ctxt hash in let first_published, published = match published_at_level_info with @@ -422,7 +422,7 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let*! slots = - Store.Dal_slots_headers.list_values node_ctxt.store ~primary_key:block + Node_context.get_all_slot_headers node_ctxt ~published_in_block_hash:block in return slots @@ -430,12 +430,12 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct Block_directory.register0 Sc_rollup_services.Global.Block.dal_confirmed_slot_pages @@ fun (node_ctxt, block) () () -> - get_dal_confirmed_slot_pages node_ctxt.store block + get_dal_confirmed_slot_pages node_ctxt block let () = Block_directory.register0 Sc_rollup_services.Global.Block.dal_slot_page @@ fun (node_ctxt, block) {index; page} () -> - get_dal_slot_page node_ctxt.store block index page + get_dal_slot_page node_ctxt block index page let () = Outbox_directory.register0 Sc_rollup_services.Global.Block.Outbox.messages @@ -498,7 +498,7 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct let inbox_info_of_level (node_ctxt : _ Node_context.t) inbox_level = let open Alpha_context in let open Lwt_syntax in - let+ finalized_head = State.get_finalized_head_opt node_ctxt.store in + let+ finalized_head = Node_context.get_finalized_head_opt node_ctxt in let finalized = match finalized_head with | None -> false @@ -540,14 +540,11 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct | None -> return (Sc_rollup_services.Included (info, inbox_info)) | Some commitment_level -> ( - let* block = - State.hash_of_level + let*! block = + Node_context.find_l2_block_by_level node_ctxt (Alpha_context.Raw_level.to_int32 commitment_level) in - let*! block = - Store.L2_blocks.find node_ctxt.store block - in match block with | None -> (* Commitment not computed yet for inbox *) @@ -561,8 +558,8 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct in (* Commitment computed *) let*! published_at = - Store.Commitments_published_at_level.find - node_ctxt.store + Node_context.commitment_published_at_level + node_ctxt commitment_hash in match published_at with @@ -576,9 +573,9 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct published_at_level = Some published_at_level; } -> (* Commitment published *) - let*! commitment = - Store.Commitments.get - node_ctxt.store + let* commitment = + Node_context.get_commitment + node_ctxt commitment_hash in let commitment_info = diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/commitment.ml b/src/proto_016_PtMumbai/bin_sc_rollup_node/commitment.ml index 82ab504670bb7955eae9121bd9ff0e7d080ce9a8..264d970213bce2930ea7a562bfda72d750aaf2d0 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/commitment.ml +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/commitment.ml @@ -70,10 +70,11 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct let tick_of_level (node_ctxt : _ Node_context.t) inbox_level = let open Lwt_result_syntax in - let* block_hash = - State.hash_of_level node_ctxt (Raw_level.to_int32 inbox_level) + let* block = + Node_context.get_l2_block_by_level + node_ctxt + (Raw_level.to_int32 inbox_level) in - let*! block = Store.L2_blocks.get node_ctxt.store block_hash in return (Sc_rollup_block.final_tick block) let build_commitment (node_ctxt : _ Node_context.t) @@ -128,14 +129,11 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct Some genesis_commitment else let* last_commitment_hash = - let*! pred = Store.L2_blocks.find node_ctxt.store predecessor in - match pred with - | None -> failwith "Missing block %a" Block_hash.pp predecessor - | Some pred -> - return (Sc_rollup_block.most_recent_commitment pred.header) + let+ pred = Node_context.get_l2_block node_ctxt predecessor in + Sc_rollup_block.most_recent_commitment pred.header in - let*! last_commitment = - Store.Commitments.get node_ctxt.store last_commitment_hash + let* last_commitment = + Node_context.get_commitment node_ctxt last_commitment_hash in let next_commitment_level = next_commitment_level node_ctxt last_commitment.inbox_level @@ -163,11 +161,8 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct match commitment with | None -> return_none | Some commitment -> - let commitment_hash = - Sc_rollup.Commitment.hash_uncarbonated commitment - in - let*! () = - Store.Commitments.add node_ctxt.store commitment_hash commitment + let*! commitment_hash = + Node_context.save_commitment node_ctxt commitment in return_some commitment_hash @@ -178,7 +173,7 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct | None -> node_ctxt.genesis_info.level | Some lpc -> lpc.inbox_level in - let* head = State.last_processed_head_opt node_ctxt.store in + let* head = Node_context.last_processed_head_opt node_ctxt in let next_head_level = Option.map (fun (b : Sc_rollup_block.t) -> Raw_level.succ b.header.level) @@ -189,7 +184,7 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct in let rec gather acc (commitment_hash : Sc_rollup.Commitment.Hash.t) = let* commitment = - Store.Commitments.find node_ctxt.store commitment_hash + Node_context.find_commitment node_ctxt commitment_hash in match commitment with | None -> return acc @@ -204,9 +199,7 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct return acc | Some commitment -> let* published_info = - Store.Commitments_published_at_level.find - node_ctxt.store - commitment_hash + Node_context.commitment_published_at_level node_ctxt commitment_hash in let past_curfew = match (published_info, next_head_level) with @@ -219,7 +212,7 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct (* We keep the commitment and go back to the previous one. *) gather acc commitment.predecessor in - let* finalized_block = State.get_finalized_head_opt node_ctxt.store in + let* finalized_block = Node_context.get_finalized_head_opt node_ctxt in match finalized_block with | None -> return_nil | Some finalized -> @@ -255,9 +248,7 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct let earliest_cementing_level node_ctxt commitment_hash = let open Lwt_option_syntax in let+ {first_published_at_level; _} = - Store.Commitments_published_at_level.find - node_ctxt.Node_context.store - commitment_hash + Node_context.commitment_published_at_level node_ctxt commitment_hash in add_level first_published_at_level (sc_rollup_challenge_window node_ctxt) @@ -273,20 +264,17 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct (head : Sc_rollup_block.t) = let open Lwt_option_syntax in let commitment_hash = Sc_rollup_block.most_recent_commitment head.header in - let* commitment = Store.Commitments.find node_ctxt.store commitment_hash in + let* commitment = Node_context.find_commitment node_ctxt commitment_hash in let*? cementable_level_bound = sub_level commitment.inbox_level (sc_rollup_challenge_window node_ctxt) in if Raw_level.(cementable_level_bound <= node_ctxt.lcc.level) then fail else - let* cementable_bound_block_hash = - State.hash_of_level_opt + let* cementable_bound_block = + Node_context.find_l2_block_by_level node_ctxt (Raw_level.to_int32 cementable_level_bound) in - let* cementable_bound_block = - Store.L2_blocks.find node_ctxt.store cementable_bound_block_hash - in let cementable_commitment = Sc_rollup_block.most_recent_commitment cementable_bound_block.header in @@ -300,12 +288,12 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct let*! x = x in match x with None -> return_nil | Some x -> f x in - let*& head = State.last_processed_head_opt node_ctxt.Node_context.store in + let*& head = Node_context.last_processed_head_opt node_ctxt in let head_level = head.header.level in let rec gather acc (commitment_hash : Sc_rollup.Commitment.Hash.t) = let open Lwt_syntax in let* commitment = - Store.Commitments.find node_ctxt.store commitment_hash + Node_context.find_commitment node_ctxt commitment_hash in match commitment with | None -> return acc diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/daemon.ml b/src/proto_016_PtMumbai/bin_sc_rollup_node/daemon.ml index 6d4996a4cfd67f1071cdf57f731e19c2178d17f8..6e1284961044173e273c105ed727e7fa53413a5f 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/daemon.ml +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/daemon.ml @@ -52,8 +52,8 @@ module Make (PVM : Pvm.S) = struct Sc_rollup.Commitment.hash_uncarbonated commitment in let*! () = - Store.Commitments_published_at_level.add - node_ctxt.store + Node_context.set_commitment_published_at_level + node_ctxt commitment_hash { first_published_at_level = published_at_level; @@ -69,20 +69,21 @@ module Make (PVM : Pvm.S) = struct Sc_rollup.Commitment.hash_uncarbonated commitment in let*! known_commitment = - Store.Commitments.mem node_ctxt.store commitment_hash + Node_context.commitment_exists node_ctxt commitment_hash in if not known_commitment then return_unit else let*! republication = - Store.Commitments_published_at_level.mem - node_ctxt.store + Node_context.commitment_was_published + node_ctxt + ~source:Anyone commitment_hash in if republication then return_unit else let*! () = - Store.Commitments_published_at_level.add - node_ctxt.store + Node_context.set_commitment_published_at_level + node_ctxt commitment_hash { first_published_at_level = published_at_level; @@ -93,11 +94,10 @@ module Make (PVM : Pvm.S) = struct | Sc_rollup_cement {commitment; _}, Sc_rollup_cement_result {inbox_level; _} -> (* Cemented commitment ---------------------------------------------- *) - let* inbox_block_hash = - State.hash_of_level node_ctxt (Raw_level.to_int32 inbox_level) - in - let*! inbox_block = - Store.L2_blocks.get node_ctxt.store inbox_block_hash + let* inbox_block = + Node_context.get_l2_block_by_level + node_ctxt + (Raw_level.to_int32 inbox_level) in let*? () = (* We stop the node if we disagree with a cemented commitment *) @@ -141,10 +141,9 @@ module Make (PVM : Pvm.S) = struct | Dal_publish_slot_header slot_header, Dal_publish_slot_header_result _ -> assert (Node_context.dal_enabled node_ctxt) ; let*! () = - Store.Dal_slots_headers.add - node_ctxt.store - ~primary_key:head.Layer1.hash - ~secondary_key:slot_header.header.id.index + Node_context.save_slot_header + node_ctxt + ~published_in_block_hash:head.Layer1.hash slot_header.header in return_unit @@ -228,7 +227,7 @@ module Make (PVM : Pvm.S) = struct let rec processed_finalized_block (node_ctxt : _ Node_context.t) Layer1.({hash; level} as block) = let open Lwt_result_syntax in - let*! last_finalized = State.get_finalized_head_opt node_ctxt.store in + let*! last_finalized = Node_context.get_finalized_head_opt node_ctxt in let already_finalized = match last_finalized with | Some finalized -> level <= Raw_level.to_int32 finalized.header.level @@ -242,14 +241,14 @@ module Make (PVM : Pvm.S) = struct in let*! () = Daemon_event.head_processing hash level ~finalized:true in let* () = process_l1_block_operations ~finalized:true node_ctxt block in - let*! () = State.mark_finalized_head node_ctxt.store hash in + let*! () = Node_context.mark_finalized_head node_ctxt hash in return_unit let process_head (node_ctxt : _ Node_context.t) Layer1.({hash; level} as head) = let open Lwt_result_syntax in let*! () = Daemon_event.head_processing hash level ~finalized:false in - let*! () = State.save_level node_ctxt.store head in + let*! () = Node_context.save_level node_ctxt head in let* inbox_hash, inbox, inbox_witness, messages, ctxt = Inbox.process_head node_ctxt head in @@ -277,15 +276,8 @@ module Make (PVM : Pvm.S) = struct (* Previous commitment for rollup genesis is itself. *) return node_ctxt.genesis_info.Sc_rollup.Commitment.commitment_hash else - let*! pred = Store.L2_blocks.find node_ctxt.store predecessor in - match pred with - | None -> - failwith - "Missing L2 predecessor %a for previous commitment" - Block_hash.pp - predecessor - | Some pred -> - return (Sc_rollup_block.most_recent_commitment pred.header) + let+ pred = Node_context.get_l2_block node_ctxt predecessor in + Sc_rollup_block.most_recent_commitment pred.header in let header = Sc_rollup_block. @@ -310,7 +302,7 @@ module Make (PVM : Pvm.S) = struct head in let* () = processed_finalized_block node_ctxt finalized_block in - let*! () = State.save_l2_block node_ctxt.store l2_block in + let*! () = Node_context.save_l2_head node_ctxt l2_block in let*! () = Daemon_event.new_head_processed hash (Raw_level.to_int32 level) in @@ -338,9 +330,7 @@ module Make (PVM : Pvm.S) = struct imply the processing of head~3, etc). *) let on_layer_1_head node_ctxt head = let open Lwt_result_syntax in - let*! old_head = - State.last_processed_head_opt node_ctxt.Node_context.store - in + let*! old_head = Node_context.last_processed_head_opt node_ctxt in let old_head = match old_head with | Some h -> @@ -426,27 +416,22 @@ module Make (PVM : Pvm.S) = struct l1_ctxt.heads in let*! () = Event.connection_lost () in - let* l1_ctxt = - Layer1.reconnect configuration node_ctxt.l1_ctxt node_ctxt.store - in + let* l1_ctxt = Layer1.reconnect configuration node_ctxt.l1_ctxt in loop l1_ctxt in protect @@ fun () -> Lwt.no_cancel @@ loop node_ctxt.l1_ctxt - let install_finalizer {Node_context.l1_ctxt; store; _} rpc_server = + let install_finalizer node_ctxt rpc_server = let open Lwt_syntax in Lwt_exit.register_clean_up_callback ~loc:__LOC__ @@ fun exit_status -> - let message = l1_ctxt.cctxt#message in - let* () = message "Shutting down L1@." in - let* () = Layer1.shutdown l1_ctxt in + let message = node_ctxt.Node_context.cctxt#message in let* () = message "Shutting down RPC server@." in let* () = Components.RPC_server.shutdown rpc_server in let* () = message "Shutting down Injector@." in let* () = Injector.shutdown () in let* () = message "Shutting down Batcher@." in let* () = Components.Batcher.shutdown () in - let* () = message "Closing store@." in - let* () = Store.close store in + let* () = Node_context.close node_ctxt in let* () = Event.shutdown_node exit_status in Tezos_base_unix.Internal_event_unix.close () @@ -570,26 +555,8 @@ let run ~data_dir (configuration : Configuration.t) ()) configuration.sc_rollup_node_operators in - let*! store = - Store.load Read_write Configuration.(default_storage_dir data_dir) - in - let*! context = - Context.load Read_write (Configuration.default_context_dir data_dir) - in - let* l1_ctxt, kind = Layer1.start configuration cctxt store in let* node_ctxt = - Node_context.init - cctxt - dal_cctxt - ~data_dir - l1_ctxt - configuration.sc_rollup_address - kind - configuration.sc_rollup_node_operators - configuration.fee_parameters - ~loser_mode:configuration.loser_mode - store - context + Node_context.init cctxt dal_cctxt ~data_dir Read_write configuration in let module Daemon = Make ((val Components.pvm_of_kind node_ctxt.kind)) in Daemon.run node_ctxt configuration diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/dal_pages_request.ml b/src/proto_016_PtMumbai/bin_sc_rollup_node/dal_pages_request.ml index da4c8280bd33837e88958d5ead67929445501507..4a4db2a8f35ea881a7f45dd258d8cd2ac68126ae 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/dal_pages_request.ml +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/dal_pages_request.ml @@ -61,7 +61,7 @@ let () = let store_entry_from_published_level ~dal_attestation_lag ~published_level node_ctxt = - State.hash_of_level node_ctxt + Node_context.hash_of_level node_ctxt @@ Int32.( add (of_int dal_attestation_lag) (Raw_level.to_int32 published_level)) @@ -90,11 +90,11 @@ let get_slot_pages = Lwt.return let check_confirmation_status_and_download - ({Node_context.store; dal_cctxt; _} as node_ctxt) ~confirmed_in_block_hash + ({Node_context.dal_cctxt; _} as node_ctxt) ~confirmed_in_block_hash ~published_in_block_hash index = let open Lwt_result_syntax in let* confirmed_in_block_level = - State.level_of_hash node_ctxt confirmed_in_block_hash + Node_context.level_of_hash node_ctxt confirmed_in_block_hash in let confirmed_in_head = Layer1.{hash = confirmed_in_block_hash; level = confirmed_in_block_level} @@ -103,15 +103,12 @@ let check_confirmation_status_and_download Dal_slots_tracker.is_slot_confirmed node_ctxt confirmed_in_head index in if is_confirmed then - let*! {commitment; _} = - Store.Dal_slots_headers.get - store - ~primary_key:published_in_block_hash - ~secondary_key:index + let* {commitment; _} = + Node_context.get_slot_header node_ctxt ~published_in_block_hash index in let* pages = get_slot_pages dal_cctxt commitment in let save_pages node_ctxt = - Dal_slots_tracker.save_confirmed_slot + Node_context.save_confirmed_slot node_ctxt confirmed_in_block_hash index @@ -120,14 +117,11 @@ let check_confirmation_status_and_download return (Delayed_write_monad.delay_write (Some pages) save_pages) else let save_slot node_ctxt = - Dal_slots_tracker.save_unconfirmed_slot - node_ctxt - confirmed_in_block_hash - index + Node_context.save_unconfirmed_slot node_ctxt confirmed_in_block_hash index in return (Delayed_write_monad.delay_write None save_slot) -let slot_pages ~dal_attestation_lag ({Node_context.store; _} as node_ctxt) +let slot_pages ~dal_attestation_lag node_ctxt Dal.Slot.Header.{published_level; index} = let open Lwt_result_syntax in let* confirmed_in_block_hash = @@ -137,15 +131,14 @@ let slot_pages ~dal_attestation_lag ({Node_context.store; _} as node_ctxt) node_ctxt in let*! processed = - Store.Dal_processed_slots.find - store - ~primary_key:confirmed_in_block_hash - ~secondary_key:index + Node_context.processed_slot node_ctxt ~confirmed_in_block_hash index in match processed with | None -> let* published_in_block_hash = - State.hash_of_level node_ctxt (Raw_level.to_int32 published_level) + Node_context.hash_of_level + node_ctxt + (Raw_level.to_int32 published_level) in check_confirmation_status_and_download node_ctxt @@ -155,9 +148,7 @@ let slot_pages ~dal_attestation_lag ({Node_context.store; _} as node_ctxt) | Some `Unconfirmed -> return (Delayed_write_monad.no_write None) | Some `Confirmed -> let*! pages = - Store.Dal_slot_pages.list_secondary_keys_with_values - store - ~primary_key:confirmed_in_block_hash + Node_context.list_slot_pages node_ctxt ~confirmed_in_block_hash in let pages = List.filter_map @@ -167,8 +158,7 @@ let slot_pages ~dal_attestation_lag ({Node_context.store; _} as node_ctxt) in return (Delayed_write_monad.no_write (Some pages)) -let page_content ~dal_attestation_lag ({Node_context.store; _} as node_ctxt) - page_id = +let page_content ~dal_attestation_lag node_ctxt page_id = let open Lwt_result_syntax in let open Delayed_write_monad.Lwt_result_syntax in let Dal.Page.{slot_id; page_index} = page_id in @@ -180,10 +170,7 @@ let page_content ~dal_attestation_lag ({Node_context.store; _} as node_ctxt) node_ctxt in let*! processed = - Store.Dal_processed_slots.find - store - ~primary_key:confirmed_in_block_hash - ~secondary_key:index + Node_context.processed_slot node_ctxt ~confirmed_in_block_hash index in match processed with | None -> ( @@ -196,7 +183,9 @@ let page_content ~dal_attestation_lag ({Node_context.store; _} as node_ctxt) the logic of that function when determining the confirmation status of a slot. *) let* published_in_block_hash = - State.hash_of_level node_ctxt (Raw_level.to_int32 published_level) + Node_context.hash_of_level + node_ctxt + (Raw_level.to_int32 published_level) in let>* pages = check_confirmation_status_and_download @@ -214,18 +203,17 @@ let page_content ~dal_attestation_lag ({Node_context.store; _} as node_ctxt) | Some `Unconfirmed -> return None | Some `Confirmed -> ( let*! page_opt = - Store.Dal_slot_pages.find - store - ~primary_key:confirmed_in_block_hash - ~secondary_key:(index, page_index) + Node_context.find_slot_page + node_ctxt + ~confirmed_in_block_hash + ~slot_index:index + ~page_index in match page_opt with | Some v -> return @@ Some v | None -> let*! pages = - Store.Dal_slot_pages.list_secondary_keys_with_values - store - ~primary_key:confirmed_in_block_hash + Node_context.list_slot_pages node_ctxt ~confirmed_in_block_hash in if page_index < 0 || List.compare_length_with pages page_index <= 0 then tzfail @@ Dal_invalid_page_for_slot page_id diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/dal_slots_tracker.ml b/src/proto_016_PtMumbai/bin_sc_rollup_node/dal_slots_tracker.ml index 66accb28c14f0d15b1b71994a113584c384fb450..ac9e6b73ca295cbaec968f3d7ef22c2ff74674c4 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/dal_slots_tracker.ml +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/dal_slots_tracker.ml @@ -100,9 +100,9 @@ let slots_info node_ctxt (Layer1.{hash; _} as head) = metadata.protocol_data.dal_attestation in let*! published_slots_indexes = - Store.Dal_slots_headers.list_secondary_keys - node_ctxt.store - ~primary_key:published_block_hash + Node_context.get_slot_indexes + node_ctxt + ~published_in_block_hash:published_block_hash in let confirmed_slots_indexes_list = List.filter @@ -146,38 +146,8 @@ let to_slot_index_list (constants : Constants.Parametric.t) bitset = Use a shared storage between dal and rollup node to store slots data. *) -let save_unconfirmed_slot {Node_context.store; _} current_block_hash slot_index - = - (* No page is actually saved *) - Store.Dal_processed_slots.add - store - ~primary_key:current_block_hash - ~secondary_key:slot_index - `Unconfirmed - -let save_confirmed_slot {Node_context.store; _} current_block_hash slot_index - pages = - (* Adding multiple entries with the same primary key amounts to updating the - contents of an in-memory map, hence pages must be added sequentially. *) - let open Lwt_syntax in - let* () = - List.iteri_s - (fun page_number page -> - Store.Dal_slot_pages.add - store - ~primary_key:current_block_hash - ~secondary_key:(slot_index, page_number) - page) - pages - in - Store.Dal_processed_slots.add - store - ~primary_key:current_block_hash - ~secondary_key:slot_index - `Confirmed - let download_and_save_slots - ({Node_context.store; dal_cctxt; protocol_constants; _} as node_context) + ({Node_context.dal_cctxt; protocol_constants; _} as node_context) ~current_block_hash {published_block_hash; confirmed_slots_indexes} = let open Lwt_result_syntax in let*? all_slots = @@ -203,43 +173,41 @@ let download_and_save_slots let*! () = List.iter_p (fun s_slot -> - save_unconfirmed_slot node_context current_block_hash s_slot) + Node_context.save_unconfirmed_slot + node_context + current_block_hash + s_slot) not_confirmed in let* () = [] (* Preparing for the pre-fetching logic. *) |> List.iter_ep (fun s_slot -> - (* slot_header is missing but the slot with index s_slot has been + (* fails if slot_header is missing but the slot with index s_slot has been confirmed. This scenario should not be possible. *) - let*! slot_header_is_stored = - Store.Dal_slots_headers.mem - store - ~primary_key:published_block_hash - ~secondary_key:s_slot + let* {commitment; _} = + Node_context.get_slot_header + node_context + ~published_in_block_hash:published_block_hash + s_slot + in + (* The slot with index s_slot is confirmed. We can + proceed retrieving it from the dal node and save it + in the store. *) + let* pages = Dal_node_client.get_slot_pages dal_cctxt commitment in + let*! () = + Node_context.save_confirmed_slot + node_context + current_block_hash + s_slot + pages in - if not slot_header_is_stored then - failwith "Slot header was not found in store" - else - let*! {commitment; _} = - Store.Dal_slots_headers.get - store - ~primary_key:published_block_hash - ~secondary_key:s_slot - in - (* The slot with index s_slot is confirmed. We can - proceed retrieving it from the dal node and save it - in the store. *) - let* pages = Dal_node_client.get_slot_pages dal_cctxt commitment in - let*! () = - save_confirmed_slot node_context current_block_hash s_slot pages - in - let*! () = - Dal_slots_tracker_event.slot_has_been_confirmed - s_slot - published_block_hash - current_block_hash - in - return_unit) + let*! () = + Dal_slots_tracker_event.slot_has_been_confirmed + s_slot + published_block_hash + current_block_hash + in + return_unit) in return_unit @@ -256,16 +224,13 @@ module Confirmed_slots_history = struct node_ctxt.Node_context.protocol_constants.parametric confirmed_slots_indexes in - let*! confirmed_slots_indexes_with_header = - List.map_p - (fun slot_index -> - Store.Dal_slots_headers.get - node_ctxt.Node_context.store - ~primary_key:published_block_hash - ~secondary_key:slot_index) - relevant_slots_indexes - in - return confirmed_slots_indexes_with_header + List.map_ep + (fun slot_index -> + Node_context.get_slot_header + node_ctxt + ~published_in_block_hash:published_block_hash + slot_index) + relevant_slots_indexes let read_slots_history_from_l1 {Node_context.l1_ctxt = {cctxt; _}; _} block = let open Lwt_result_syntax in @@ -294,8 +259,7 @@ module Confirmed_slots_history = struct Layer1.{hash = block_hash; level = block_level} ~entry_kind ~find ~default = let open Lwt_result_syntax in - let open Node_context in - let*! confirmed_slots_history_opt = find node_ctxt.store block_hash in + let*! confirmed_slots_history_opt = find node_ctxt block_hash in let block_level = Raw_level.of_int32_exn block_level in let should_process_dal_slots = should_process_dal_slots node_ctxt block_level @@ -327,7 +291,7 @@ module Confirmed_slots_history = struct node_ctxt block ~entry_kind:"slots history" - ~find:Store.Dal_confirmed_slots_history.find + ~find:Node_context.find_confirmed_slots_history ~default:read_slots_history_from_l1 let slots_history_cache_of_hash node_ctxt block = @@ -335,7 +299,7 @@ module Confirmed_slots_history = struct node_ctxt block ~entry_kind:"slots history cache" - ~find:Store.Dal_confirmed_slots_histories.find + ~find:Node_context.find_confirmed_slots_histories ~default:(fun node_ctxt _block -> let num_slots = node_ctxt.Node_context.protocol_constants.parametric.dal @@ -354,7 +318,7 @@ module Confirmed_slots_history = struct @@ Dal.Slots_history.History_cache.empty ~capacity:(Int64.of_int @@ (num_slots * 60000))) - let update (Node_context.{store; l1_ctxt; _} as node_ctxt) + let update (Node_context.{l1_ctxt; _} as node_ctxt) Layer1.({hash = head_hash; _} as head) confirmation_info = let open Lwt_result_syntax in let* slots_to_save = @@ -384,10 +348,16 @@ module Confirmed_slots_history = struct (* TODO/DAL: https://gitlab.com/tezos/tezos/-/issues/3856 Attempt to improve this process. *) let*! () = - Store.Dal_confirmed_slots_history.add store head_hash slots_history + Node_context.save_confirmed_slots_history + node_ctxt + head_hash + slots_history in let*! () = - Store.Dal_confirmed_slots_histories.add store head_hash slots_cache + Node_context.save_confirmed_slots_histories + node_ctxt + head_hash + slots_cache in return () end diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/dal_slots_tracker.mli b/src/proto_016_PtMumbai/bin_sc_rollup_node/dal_slots_tracker.mli index 458d3735649f52a2329da5a84d25daf87b330334..bd1f4ce7620128e5a0d2b9a63c9214074239b8d2 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/dal_slots_tracker.mli +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/dal_slots_tracker.mli @@ -38,22 +38,6 @@ open Alpha_context val is_slot_confirmed : _ Node_context.t -> Layer1.head -> Dal.Slot_index.t -> bool tzresult Lwt.t -(** [save_unconfirmed_slot node_ctxt hash slot_index] saves in [node_ctxt.store] - that [slot_index] is unconfirmed in the block with hash in [node_ctxt.store]. -*) -val save_unconfirmed_slot : - Node_context.rw -> Block_hash.t -> Dal.Slot_index.t -> unit Lwt.t - -(** [save_confirmed_slot node_ctxt hash slot_index] saves in [node_ctxt.store] - that [slot_index] is confirmed in the block with hashin [node_ctxt.store]. - The contents of the slot are set to [pages] in [node_ctxt.store]. *) -val save_confirmed_slot : - Node_context.rw -> - Block_hash.t -> - Dal.Slot_index.t -> - Dal.Page.content list -> - unit Lwt.t - (** [process_head node_ctxt head] performs the following operations: {ul {li it reads the endorsements for headers published attestation_lag diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/inbox.ml b/src/proto_016_PtMumbai/bin_sc_rollup_node/inbox.ml index 8080b46c2a9463dab8ebdb70d4e077f7809a3671..32eae4f3464068c2d0459907ed0a3464a0d0d5cb 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/inbox.ml +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/inbox.ml @@ -31,60 +31,6 @@ open Alpha_context let lift promise = Lwt.map Environment.wrap_tzresult promise -let genesis_inbox node_ctxt = - let genesis_level = - Raw_level.to_int32 node_ctxt.Node_context.genesis_info.level - in - Plugin.RPC.Sc_rollup.inbox - node_ctxt.cctxt - (node_ctxt.cctxt#chain, `Level genesis_level) - -module State = struct - let add_messages = Store.Messages.add - - let add_inbox = Store.Inboxes.add - - let level_of_hash = State.level_of_hash - - (** [inbox_of_head node_ctxt store block] returns the latest inbox at the - given [block]. This function always returns [Some inbox] for all levels - at and after the rollup genesis. *) - let inbox_of_head node_ctxt Layer1.{hash = block_hash; level = block_level} = - let open Lwt_result_syntax in - let open Node_context in - let*! possible_inbox = - let open Lwt_option_syntax in - let* l2_block = Store.L2_blocks.find node_ctxt.store block_hash in - Store.Inboxes.find node_ctxt.store l2_block.header.inbox_hash - in - (* Pre-condition: forall l. (l > genesis_level) => inbox[l] <> None. *) - match possible_inbox with - | None -> - (* The inbox exists for each tezos block the rollup should care about. - That is, every block after the origination level. We then join - the bandwagon and build the inbox on top of the protocol's inbox - at the end of the origination level. *) - let genesis_level = Raw_level.to_int32 node_ctxt.genesis_info.level in - if block_level = genesis_level then - let+ inbox = genesis_inbox node_ctxt in - inbox - else if block_level > genesis_level then - (* Invariant broken, the inbox for this level should exist. *) - failwith - "The inbox for block hash %a (level = %ld) is missing." - Block_hash.pp - block_hash - block_level - else - (* The rollup node should not care about levels before the genesis - level. *) - failwith - "Asking for the inbox before the genesis level (i.e. %ld), out of \ - the scope of the rollup's node" - block_level - | Some inbox -> return inbox -end - let get_messages Node_context.{l1_ctxt; _} head = let open Lwt_result_syntax in let* block = Layer1.fetch_tezos_block l1_ctxt head in @@ -168,11 +114,9 @@ let add_messages ~predecessor_timestamp ~predecessor inbox messages = let witness_hash = Sc_rollup.Inbox_merkelized_payload_hashes.hash witness in - let inbox_hash = Sc_rollup.Inbox.hash inbox in return ( messages_history, witness_hash, - inbox_hash, inbox, messages_with_protocol_internal_messages ) @@ -191,7 +135,7 @@ let process_head (node_ctxt : _ Node_context.t) *) let* predecessor = Layer1.get_predecessor node_ctxt.l1_ctxt head in - let* inbox = State.inbox_of_head node_ctxt predecessor in + let* inbox = Node_context.inbox_of_head node_ctxt predecessor in let inbox_metrics = Metrics.Inbox.metrics in Prometheus.Gauge.set inbox_metrics.head_inbox_level @@ Int32.to_float level ; let*? level = Environment.wrap_tzresult @@ Raw_level.of_int32 level in @@ -213,7 +157,6 @@ let process_head (node_ctxt : _ Node_context.t) in let* ( _messages_history, witness_hash, - inbox_hash, inbox, messages_with_protocol_internal_messages ) = add_messages @@ -225,8 +168,8 @@ let process_head (node_ctxt : _ Node_context.t) Metrics.Inbox.Stats.head_messages_list := messages_with_protocol_internal_messages ; let*! () = - State.add_messages - node_ctxt.store + Node_context.save_messages + node_ctxt witness_hash { predecessor = predecessor_hash; @@ -235,7 +178,7 @@ let process_head (node_ctxt : _ Node_context.t) } in let* () = same_inbox_as_layer_1 node_ctxt head_hash inbox in - let*! () = State.add_inbox node_ctxt.store inbox_hash inbox in + let*! inbox_hash = Node_context.save_inbox node_ctxt inbox in return ( inbox_hash, inbox, @@ -243,7 +186,7 @@ let process_head (node_ctxt : _ Node_context.t) messages_with_protocol_internal_messages, ctxt )) else - let* inbox = genesis_inbox node_ctxt in + let* inbox = Node_context.genesis_inbox node_ctxt in return ( Sc_rollup.Inbox.hash inbox, inbox, @@ -251,13 +194,6 @@ let process_head (node_ctxt : _ Node_context.t) [], Context.empty node_ctxt.context ) -let inbox_of_hash node_ctxt hash = - let open Lwt_result_syntax in - let* level = State.level_of_hash node_ctxt hash in - State.inbox_of_head node_ctxt {hash; level} - -let inbox_of_head = State.inbox_of_head - let start () = Inbox_event.starting () let payloads_history_of_messages ~predecessor ~predecessor_timestamp messages = diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/inbox.mli b/src/proto_016_PtMumbai/bin_sc_rollup_node/inbox.mli index 7323c3b5197693b11dacc4c72778ce29703442d4..f1b33285c0769b4c631d2d2ee2717a2822b9b010 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/inbox.mli +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/inbox.mli @@ -50,16 +50,6 @@ val process_head : tzresult Lwt.t -(** [inbox_of_hash node_ctxt block_hash] returns the rollup inbox at the end of - the given validation of [block_hash]. NOTE: It requires the L2 block for - [block_hash] to have been saved. *) -val inbox_of_hash : _ Node_context.t -> Block_hash.t -> Inbox.t tzresult Lwt.t - -(** [inbox_of_head node_ctxt block_head] returns the rollup inbox at the end of - the given validation of [block_head]. NOTE: It requires the L2 block for - [block_hash] to have been saved. *) -val inbox_of_head : _ Node_context.t -> Layer1.head -> Inbox.t tzresult Lwt.t - (** [start ()] initializes the inbox to track the messages being published. *) val start : unit -> unit Lwt.t @@ -72,7 +62,6 @@ val add_messages : Inbox_message.t list -> (Inbox_merkelized_payload_hashes.History.t * Inbox_merkelized_payload_hashes.Hash.t - * Inbox.Hash.t * Inbox.t * Inbox_message.t list) tzresult diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/interpreter.ml b/src/proto_016_PtMumbai/bin_sc_rollup_node/interpreter.ml index 6b51421e12864f70a00ef6056d7154c845097f80..761bfbfea8434ce566af6c0541ecd678c59abe91 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/interpreter.ml +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/interpreter.ml @@ -199,9 +199,9 @@ module Make (PVM : Pvm.S) : S with module PVM = PVM = struct ctxt Layer1.{hash = block.header.predecessor; level = pred_level} in - let*! inbox = Store.Inboxes.get node_ctxt.store block.header.inbox_hash in - let*! {predecessor; predecessor_timestamp; messages} = - Store.Messages.get node_ctxt.store block.header.inbox_witness + let* inbox = Node_context.get_inbox node_ctxt block.header.inbox_hash in + let* {predecessor; predecessor_timestamp; messages} = + Node_context.get_messages node_ctxt block.header.inbox_witness in let messages = Sc_rollup.Inbox_message.Internal Start_of_level @@ -223,7 +223,7 @@ module Make (PVM : Pvm.S) : S with module PVM = PVM = struct [None].*) let state_of_tick node_ctxt tick level = let open Lwt_result_syntax in - let* closest_block = State.block_before node_ctxt.Node_context.store tick in + let* closest_block = Node_context.block_before node_ctxt tick in match closest_block with | None -> return None | Some event -> diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/layer1.ml b/src/proto_016_PtMumbai/bin_sc_rollup_node/layer1.ml index b47052ff448da78c91c85397d916e47ae7cd1d0d..e83767528c5768ffa042decc9685030549121ccb 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/layer1.ml +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/layer1.ml @@ -166,7 +166,7 @@ let get_predecessor state ({hash; _} as head) = | None -> tzfail (Cannot_find_predecessor hash) | Some pred -> return pred -let rec connect ?(count = 0) ~delay cctxt genesis_info store = +let rec connect ?(count = 0) ~delay cctxt genesis_info = let open Lwt_syntax in let* () = if count = 0 then return_unit @@ -197,9 +197,9 @@ let rec connect ?(count = 0) ~delay cctxt genesis_info store = return_ok (heads, stopper) | Error e -> let* () = Event.cannot_connect ~count e in - connect ~delay ~count:(count + 1) cctxt genesis_info store + connect ~delay ~count:(count + 1) cctxt genesis_info -let start configuration (cctxt : Protocol_client_context.full) store = +let start configuration (cctxt : Protocol_client_context.full) = let open Lwt_result_syntax in let*! () = Layer1_event.starting () in let* kind = @@ -217,12 +217,12 @@ let start configuration (cctxt : Protocol_client_context.full) store = configuration.sc_rollup_address in let+ heads, stopper = - connect ~delay:configuration.reconnection_delay cctxt genesis_info store + connect ~delay:configuration.reconnection_delay cctxt genesis_info in ( {cctxt; heads; blocks_cache = Blocks_cache.create 32; stopper; genesis_info}, kind ) -let reconnect configuration l1_ctxt store = +let reconnect configuration l1_ctxt = let open Lwt_result_syntax in let* heads, stopper = connect @@ -230,7 +230,6 @@ let reconnect configuration l1_ctxt store = ~delay:configuration.reconnection_delay l1_ctxt.cctxt l1_ctxt.genesis_info - store in return {l1_ctxt with heads; stopper} diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/layer1.mli b/src/proto_016_PtMumbai/bin_sc_rollup_node/layer1.mli index ab5c194a6212972e7af2d8e572d702ff889780e5..1127f09957eae353021912c6fb5f49fa81ccd4b4 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/layer1.mli +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/layer1.mli @@ -47,20 +47,19 @@ type t = private { (* TODO: https://gitlab.com/tezos/tezos/-/issues/3311 Allow to retrieve L1 blocks through Tezos node storage locally. *) -(** [start configuration cctxt store] returns a stream of [chain_event] obtained +(** [start configuration cctxt] returns a stream of [chain_event] obtained from the monitoring of the Tezos node set up by the client [cctxt]. The layer 1 state is stored in the data directory declared in [configuration]. *) val start : Configuration.t -> Protocol_client_context.full -> - _ Store.t -> (t * Protocol.Alpha_context.Sc_rollup.Kind.t) tzresult Lwt.t -(** [reconnect cfg l1_ctxt store] reconnects (and retries with delay) to the +(** [reconnect cfg l1_ctxt] reconnects (and retries with delay) to the Tezos node. The delay for each reconnection is increased with a randomized exponential backoff (capped to 1.5h) . *) -val reconnect : Configuration.t -> t -> _ Store.t -> t tzresult Lwt.t +val reconnect : Configuration.t -> t -> t tzresult Lwt.t (** [get_predecessor_opt state head] returns the predecessor of block [head], when [head] is not the genesis block. *) diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/node_context.ml b/src/proto_016_PtMumbai/bin_sc_rollup_node/node_context.ml index d05a41ceac5549802df864f44a4e67940cc2fd1a..baaa4fd6a1eb7d8ab5ea3e133c63d6f2638dcb2f 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/node_context.ml +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/node_context.ml @@ -28,6 +28,8 @@ open Alpha_context type lcc = {commitment : Sc_rollup.Commitment.Hash.t; level : Raw_level.t} +type 'a store = 'a Store.t + type 'a t = { cctxt : Protocol_client_context.full; dal_cctxt : Dal_node_client.cctxt; @@ -42,7 +44,7 @@ type 'a t = { fee_parameters : Configuration.fee_parameters; protocol_constants : Constants.t; loser_mode : Loser_mode.t; - store : 'a Store.t; + store : 'a store; context : 'a Context.index; mutable lcc : lcc; mutable lpc : Sc_rollup.Commitment.t option; @@ -109,9 +111,21 @@ let get_last_published_commitment (cctxt : Protocol_client_context.full) | Ok None -> return_none | Ok (Some (_staked_hash, staked_commitment)) -> return_some staked_commitment -let init (cctxt : Protocol_client_context.full) dal_cctxt ~data_dir l1_ctxt - rollup_address kind operators fee_parameters ~loser_mode store context = +let init (cctxt : Protocol_client_context.full) dal_cctxt ~data_dir mode + Configuration.( + { + sc_rollup_address = rollup_address; + sc_rollup_node_operators = operators; + fee_parameters; + loser_mode; + _; + } as configuration) = let open Lwt_result_syntax in + let*! store = Store.load mode Configuration.(default_storage_dir data_dir) in + let*! context = + Context.load mode (Configuration.default_context_dir data_dir) + in + let* l1_ctxt, kind = Layer1.start configuration 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 @@ -141,6 +155,17 @@ let init (cctxt : Protocol_client_context.full) dal_cctxt ~data_dir l1_ctxt context; } +let close {cctxt; store; context; l1_ctxt; _} = + let open Lwt_syntax in + let message = cctxt#message in + let* () = message "Shutting down L1@." in + let* () = Layer1.shutdown l1_ctxt in + let* () = message "Closing context@." in + let* () = Context.close context in + let* () = message "Closing store@." in + let* () = Store.close store in + return_unit + let checkout_context node_ctxt block_hash = let open Lwt_result_syntax in let*! l2_block = Store.L2_blocks.find node_ctxt.store block_hash in @@ -175,6 +200,108 @@ let readonly (node_ctxt : _ t) = type 'a delayed_write = ('a, rw) Delayed_write_monad.t +(** Abstraction over store *) + +let trace_lwt_with x = + Format.kasprintf + (fun s p -> trace (Exn (Failure s)) @@ protect @@ fun () -> p >>= return) + x + +let trace_lwt_result_with x = + Format.kasprintf + (fun s p -> trace (Exn (Failure s)) @@ protect @@ fun () -> p) + x + +let hash_of_level_opt {store; cctxt; _} level = + let open Lwt_syntax in + let* hash = Store.Levels_to_hashes.find store level in + match hash with + | Some hash -> return_some hash + | None -> + let+ hash = + Tezos_shell_services.Shell_services.Blocks.hash + cctxt + ~chain:cctxt#chain + ~block:(`Level level) + () + in + Result.to_option hash + +let hash_of_level node_ctxt level = + let open Lwt_result_syntax in + let*! hash = hash_of_level_opt node_ctxt level in + match hash with + | Some h -> return h + | None -> failwith "Cannot retrieve hash of level %ld" level + +let level_of_hash {l1_ctxt; store; _} hash = + let open Lwt_result_syntax in + let*! block = Store.L2_blocks.find store hash in + match block with + | Some {header = {level; _}; _} -> return (Raw_level.to_int32 level) + | None -> + let+ {level; _} = Layer1.fetch_tezos_shell_header l1_ctxt hash in + level + +let save_level {store; _} Layer1.{hash; level} = + Store.Levels_to_hashes.add store level hash + +let save_l2_head {store; _} (head : Sc_rollup_block.t) = + let open Lwt_syntax in + let* () = Store.L2_blocks.add store head.header.block_hash head in + Store.L2_head.set store head + +let is_processed {store; _} head = Store.L2_blocks.mem store head + +let last_processed_head_opt {store; _} = Store.L2_head.find store + +let mark_finalized_head {store; _} head_hash = + let open Lwt_syntax in + let* block = Store.L2_blocks.find store head_hash in + match block with + | None -> return_unit + | Some block -> Store.Last_finalized_head.set store block + +let get_finalized_head_opt {store; _} = Store.Last_finalized_head.find store + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/4532 + Make this logarithmic, by storing pointers to muliple predecessor and + by dichotomy. *) +let block_before {store; _} tick = + let open Lwt_result_syntax in + let*! head = Store.L2_head.find store in + match head with + | None -> return_none + | Some head -> + let rec search block_hash = + let*! block = Store.L2_blocks.find store block_hash in + match block with + | None -> failwith "Missing block %a" Block_hash.pp block_hash + | Some block -> + if Sc_rollup.Tick.(block.initial_tick <= tick) then + return_some block + else search block.header.predecessor + in + search head.header.block_hash + +let get_l2_block {store; _} block_hash = + trace_lwt_with "Could not retrieve L2 block for %a" Block_hash.pp block_hash + @@ Store.L2_blocks.get store block_hash + +let find_l2_block {store; _} block_hash = Store.L2_blocks.find store block_hash + +let get_l2_block_by_level node_ctxt level = + let open Lwt_result_syntax in + trace_lwt_result_with "Could not retrieve L2 block at level %ld" level + @@ let* block_hash = hash_of_level node_ctxt level in + let*! block = Store.L2_blocks.get node_ctxt.store block_hash in + return block + +let find_l2_block_by_level node_ctxt level = + let open Lwt_option_syntax in + let* block_hash = hash_of_level_opt node_ctxt level in + Store.L2_blocks.find node_ctxt.store block_hash + let get_full_l2_block {store; _} block_hash = let open Lwt_syntax in let* block = Store.L2_blocks.get store block_hash in @@ -184,3 +311,195 @@ let get_full_l2_block {store; _} block_hash = Option.map_s (Store.Commitments.get store) block.header.commitment_hash in return {block with content = {Sc_rollup_block.inbox; messages; commitment}} + +let get_commitment {store; _} commitment_hash = + trace_lwt_with + "Could not retrieve commitment %a" + Sc_rollup.Commitment.Hash.pp + commitment_hash + @@ Store.Commitments.get store commitment_hash + +let find_commitment {store; _} hash = Store.Commitments.find store hash + +let commitment_exists {store; _} hash = Store.Commitments.mem store hash + +let save_commitment {store; _} commitment = + let open Lwt_syntax in + let hash = Sc_rollup.Commitment.hash_uncarbonated commitment in + let+ () = Store.Commitments.add store hash commitment in + hash + +let commitment_published_at_level {store; _} commitment = + Store.Commitments_published_at_level.find store commitment + +let set_commitment_published_at_level {store; _} = + Store.Commitments_published_at_level.add store + +type commitment_source = Anyone | Us + +let commitment_was_published {store; _} ~source commitment_hash = + let open Lwt_syntax in + match source with + | Anyone -> Store.Commitments_published_at_level.mem store commitment_hash + | Us -> ( + let+ info = + Store.Commitments_published_at_level.find store commitment_hash + in + match info with + | Some {published_at_level = Some _; _} -> true + | _ -> false) + +let get_inbox {store; _} inbox_hash = + trace_lwt_with + "Could not retrieve inbox %a" + Sc_rollup.Inbox.Hash.pp + inbox_hash + @@ Store.Inboxes.get store inbox_hash + +let find_inbox {store; _} hash = Store.Inboxes.find store hash + +let save_inbox {store; _} inbox = + let open Lwt_syntax in + let hash = Sc_rollup.Inbox.hash inbox in + let+ () = Store.Inboxes.add store hash inbox in + hash + +let find_inbox_by_block_hash {store; _} block_hash = + let open Lwt_option_syntax in + let* l2_block = Store.L2_blocks.find store block_hash in + Store.Inboxes.find store l2_block.header.inbox_hash + +let genesis_inbox node_ctxt = + let genesis_level = Raw_level.to_int32 node_ctxt.genesis_info.level in + Plugin.RPC.Sc_rollup.inbox + node_ctxt.cctxt + (node_ctxt.cctxt#chain, `Level genesis_level) + +let inbox_of_head node_ctxt Layer1.{hash = block_hash; level = block_level} = + let open Lwt_result_syntax in + let*! possible_inbox = find_inbox_by_block_hash node_ctxt block_hash in + (* Pre-condition: forall l. (l > genesis_level) => inbox[l] <> None. *) + match possible_inbox with + | None -> + (* The inbox exists for each tezos block the rollup should care about. + That is, every block after the origination level. We then join + the bandwagon and build the inbox on top of the protocol's inbox + at the end of the origination level. *) + let genesis_level = Raw_level.to_int32 node_ctxt.genesis_info.level in + if block_level = genesis_level then genesis_inbox node_ctxt + else if block_level > genesis_level then + (* Invariant broken, the inbox for this level should exist. *) + failwith + "The inbox for block hash %a (level = %ld) is missing." + Block_hash.pp + block_hash + block_level + else + (* The rollup node should not care about levels before the genesis + level. *) + failwith + "Asking for the inbox before the genesis level (i.e. %ld), out of \ + the scope of the rollup's node" + block_level + | Some inbox -> return inbox + +let get_inbox_by_block_hash node_ctxt hash = + let open Lwt_result_syntax in + let* level = level_of_hash node_ctxt hash in + inbox_of_head node_ctxt {hash; level} + +let get_messages {store; _} messages_hash = + trace_lwt_with + "Could not retrieve messages with payloads merkelized hash %a" + Sc_rollup.Inbox_merkelized_payload_hashes.Hash.pp + messages_hash + @@ Store.Messages.get store messages_hash + +let find_messages {store; _} hash = Store.Messages.find store hash + +let save_messages {store; _} = Store.Messages.add store + +let get_slot_header {store; _} ~published_in_block_hash slot_index = + trace_lwt_with + "Could not retrieve slot header for slot index %a published in block %a" + Dal.Slot_index.pp + slot_index + Block_hash.pp + published_in_block_hash + @@ Store.Dal_slots_headers.get + store + ~primary_key:published_in_block_hash + ~secondary_key:slot_index + +let get_all_slot_headers {store; _} ~published_in_block_hash = + Store.Dal_slots_headers.list_values store ~primary_key:published_in_block_hash + +let get_slot_indexes {store; _} ~published_in_block_hash = + Store.Dal_slots_headers.list_secondary_keys + store + ~primary_key:published_in_block_hash + +let save_slot_header {store; _} ~published_in_block_hash + (slot_header : Dal.Slot.Header.t) = + Store.Dal_slots_headers.add + store + ~primary_key:published_in_block_hash + ~secondary_key:slot_header.id.index + slot_header + +let processed_slot {store; _} ~confirmed_in_block_hash slot_index = + Store.Dal_processed_slots.find + store + ~primary_key:confirmed_in_block_hash + ~secondary_key:slot_index + +let list_slot_pages {store; _} ~confirmed_in_block_hash = + Store.Dal_slot_pages.list_secondary_keys_with_values + store + ~primary_key:confirmed_in_block_hash + +let find_slot_page {store; _} ~confirmed_in_block_hash ~slot_index ~page_index = + Store.Dal_slot_pages.find + store + ~primary_key:confirmed_in_block_hash + ~secondary_key:(slot_index, page_index) + +let save_unconfirmed_slot {store; _} current_block_hash slot_index = + (* No page is actually saved *) + Store.Dal_processed_slots.add + store + ~primary_key:current_block_hash + ~secondary_key:slot_index + `Unconfirmed + +let save_confirmed_slot {store; _} current_block_hash slot_index pages = + (* Adding multiple entries with the same primary key amounts to updating the + contents of an in-memory map, hence pages must be added sequentially. *) + let open Lwt_syntax in + let* () = + List.iteri_s + (fun page_number page -> + Store.Dal_slot_pages.add + store + ~primary_key:current_block_hash + ~secondary_key:(slot_index, page_number) + page) + pages + in + Store.Dal_processed_slots.add + store + ~primary_key:current_block_hash + ~secondary_key:slot_index + `Confirmed + +let find_confirmed_slots_history {store; _} = + Store.Dal_confirmed_slots_history.find store + +let save_confirmed_slots_history {store; _} = + Store.Dal_confirmed_slots_history.add store + +let find_confirmed_slots_histories {store; _} = + Store.Dal_confirmed_slots_histories.find store + +let save_confirmed_slots_histories {store; _} = + Store.Dal_confirmed_slots_histories.add store diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/node_context.mli b/src/proto_016_PtMumbai/bin_sc_rollup_node/node_context.mli index fc1769ceff9d8faffe243813396365e37b798a2c..83fdb0420a28bc8aee0a36eb8dd73871d972cb3c 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/node_context.mli +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/node_context.mli @@ -30,6 +30,9 @@ open Alpha_context type lcc = {commitment : Sc_rollup.Commitment.Hash.t; level : Raw_level.t} +(** Abstract type for store to force access through this module. *) +type 'a store constraint 'a = [< `Read | `Write > `Read] + type 'a t = { cctxt : Protocol_client_context.full; (** Client context used by the rollup node. *) @@ -56,7 +59,7 @@ type 'a t = { loser_mode : Loser_mode.t; (** If different from [Loser_mode.no_failures], the rollup node issues wrong commitments (for tests). *) - store : 'a Store.t; (** The store for the persistent storage. *) + store : 'a store; (** The store for the persistent storage. *) context : 'a Context.index; (** The persistent context for the rollup node. *) mutable lcc : lcc; (** Last cemented commitment and its level. *) @@ -90,25 +93,21 @@ val is_operator : _ t -> Tezos_crypto.Signature.Public_key_hash.t -> bool *) val get_fee_parameter : _ t -> Configuration.purpose -> Injection.fee_parameter -(** [init cctxt dal_cctxt ~data_dir l1_ctxt sc_rollup genesis_info kind operators fees - ~loser_mode store context] initialises 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 dal_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. *) val init : Protocol_client_context.full -> Dal_node_client.cctxt -> data_dir:string -> - Layer1.t -> - Sc_rollup.t -> - Protocol.Alpha_context.Sc_rollup.Kind.t -> - Configuration.operators -> - Configuration.fee_parameters -> - loser_mode:Loser_mode.t -> - 'a Store.t -> - 'a Context.index -> + 'a Store_sigs.mode -> + Configuration.t -> 'a t tzresult Lwt.t +(** Closes the store, context and Layer 1 monitor. *) +val close : _ t -> unit Lwt.t + (** [checkout_context node_ctxt block_hash] returns the context at block [block_hash]. *) val checkout_context : 'a t -> Block_hash.t -> 'a Context.t tzresult Lwt.t @@ -127,7 +126,246 @@ val readonly : _ t -> ro (** Monad for values with delayed write effects in the node context. *) type 'a delayed_write = ('a, rw) Delayed_write_monad.t +(** {2 Abstraction over store} *) + +(** {3 Layer 2 blocks} *) + +(** [is_processed store hash] returns [true] if the block with [hash] has + already been processed by the daemon. *) +val is_processed : _ t -> Block_hash.t -> bool Lwt.t + +(** [get_l2_block t hash] returns the Layer 2 block known by the rollup node for + Layer 1 block [hash]. *) +val get_l2_block : _ t -> Block_hash.t -> Sc_rollup_block.t tzresult Lwt.t + +(** Same as {!get_l2_block} but returns [None] when the Layer 2 block is not + available. *) +val find_l2_block : _ t -> Block_hash.t -> Sc_rollup_block.t option Lwt.t + +(** Same as {!get_l2_block} but retrieves the Layer 2 block by its level. *) +val get_l2_block_by_level : _ t -> int32 -> Sc_rollup_block.t tzresult Lwt.t + +(** Same as {!get_l2_block_by_level} but returns [None] when the Layer 2 block + is not available. *) +val find_l2_block_by_level : _ t -> int32 -> Sc_rollup_block.t option Lwt.t + (** [get_full_l2_block node_ctxt hash] returns the full L2 block for L1 block hash [hash]. The result contains the L2 block and its content (inbox, messages, commitment). *) val get_full_l2_block : _ t -> Block_hash.t -> Sc_rollup_block.full Lwt.t + +(** [save_level t head] registers the correspondences [head.level |-> + head.hash] in the store. *) +val save_level : rw -> Layer1.head -> unit Lwt.t + +(** [save_l2_head t l2_block] remembers that the [l2_block.head] is + processed. The system should not have to come back to it. *) +val save_l2_head : rw -> Sc_rollup_block.t -> unit Lwt.t + +(** [last_processed_head_opt store] returns the last processed head if it + exists. *) +val last_processed_head_opt : _ t -> Sc_rollup_block.t option Lwt.t + +(** [mark_finalized_head store head] remembers that the [head] is finalized. By + construction, every block whose level is smaller than [head]'s is also + finalized. *) +val mark_finalized_head : rw -> Block_hash.t -> unit Lwt.t + +(** [last_finalized_head_opt store] returns the last finalized head if it exists. *) +val get_finalized_head_opt : _ t -> Sc_rollup_block.t option Lwt.t + +(** [hash_of_level node_ctxt level] returns the current block hash for a given + [level]. *) +val hash_of_level : _ t -> int32 -> Block_hash.t tzresult Lwt.t + +(** [hash_of_level_opt] is like {!hash_of_level} but returns [None] if the + [level] is not known. *) +val hash_of_level_opt : _ t -> int32 -> Block_hash.t option Lwt.t + +(** [level_of_hash node_ctxt hash] returns the level for Tezos block hash [hash] + if it is known by the Tezos Layer 1 node. *) +val level_of_hash : _ t -> Block_hash.t -> int32 tzresult Lwt.t + +(** [block_before store tick] returns the last layer 2 block whose initial tick + is before [tick]. *) +val block_before : + _ t -> Sc_rollup.Tick.t -> Sc_rollup_block.t option tzresult Lwt.t + +(** {3 Commitments} *) + +(** [get_commitment t hash] returns the commitment with [hash] stored by the + rollup node. *) +val get_commitment : + _ t -> Sc_rollup.Commitment.Hash.t -> Sc_rollup.Commitment.t tzresult Lwt.t + +(** Same as {!get_commitment} but returns [None] if this commitment hash is not + known by the rollup node. *) +val find_commitment : + _ t -> Sc_rollup.Commitment.Hash.t -> Sc_rollup.Commitment.t option Lwt.t + +(** [commitment_exists t hash] returns [true] if the commitment with [hash] is + known (i.e. stored) by the rollup node. *) +val commitment_exists : _ t -> Sc_rollup.Commitment.Hash.t -> bool Lwt.t + +(** [save_commitment t commitment] saves a commitment in the store an returns is + hash. *) +val save_commitment : + rw -> Sc_rollup.Commitment.t -> Sc_rollup.Commitment.Hash.t Lwt.t + +(** [commitment_published_at_level t hash] returns the levels at which the + commitment was first published and the one at which it was included by in a + Layer 1 block. It returns [None] if the commitment is not known by the + rollup node or if it was never published by the rollup node (and included on + L1). *) +val commitment_published_at_level : + _ t -> + Sc_rollup.Commitment.Hash.t -> + Store.Commitments_published_at_level.element option Lwt.t + +(** [save_commitment_published_at_level t hash levels] saves the + publication/inclusion information for a commitment with [hash]. *) +val set_commitment_published_at_level : + rw -> + Sc_rollup.Commitment.Hash.t -> + Store.Commitments_published_at_level.element -> + unit Lwt.t + +type commitment_source = Anyone | Us + +(** [commitment_was_published t hash] returns [true] if the commitment is known + as being already published on L1. The [source] indicates if we want to know + the publication status for commitments we published ourselves [`Us] or that + [`Anyone] published. *) +val commitment_was_published : + _ t -> source:commitment_source -> Sc_rollup.Commitment.Hash.t -> bool Lwt.t + +(** {3 Inboxes} *) + +(** [get_inbox t inbox_hash] retrieves the inbox whose hash is [inbox_hash] from + the rollup node's storage. *) +val get_inbox : + _ t -> Sc_rollup.Inbox.Hash.t -> Sc_rollup.Inbox.t tzresult Lwt.t + +(** Same as {!get_inbox} but returns [None] if this inbox is not known. *) +val find_inbox : _ t -> Sc_rollup.Inbox.Hash.t -> Sc_rollup.Inbox.t option Lwt.t + +(** [save_inbox t inbox] remembers the [inbox] in the storage. It is associated + to its hash which is returned. *) +val save_inbox : rw -> Sc_rollup.Inbox.t -> Sc_rollup.Inbox.Hash.t Lwt.t + +(** [inbox_of_head node_ctxt block] returns the latest inbox at the given + [block]. This function always returns [inbox] for all levels at and + after the rollup genesis. NOTE: It requires the L2 block for [block.hash] to + have been saved. *) +val inbox_of_head : _ t -> Layer1.head -> Sc_rollup.Inbox.t tzresult Lwt.t + +(** Same as {!get_inbox} but uses the Layer 1 block hash for this inbox instead. *) +val get_inbox_by_block_hash : + _ t -> Block_hash.t -> Sc_rollup.Inbox.t tzresult Lwt.t + +(** [genesis_inbox t] is the genesis inbox for the rollup [t.sc_rollup_address]. *) +val genesis_inbox : _ t -> Sc_rollup.Inbox.t tzresult Lwt.t + +(** [get_messages t witness_hash] retrieves the messages for the merkelized + payloads hash [witness_hash] stored by the rollup node. *) +val get_messages : + _ t -> + Sc_rollup.Inbox_merkelized_payload_hashes.Hash.t -> + Store.Messages.info tzresult Lwt.t + +(** Same as {!get_messages} but returns [None] if the payloads hash is not known. *) +val find_messages : + _ t -> + Sc_rollup.Inbox_merkelized_payload_hashes.Hash.t -> + Store.Messages.info option Lwt.t + +(** [save_messages t payloads_hash messages] associates the list of [messages] + to the [payloads_hash]. The payload hash must be computed by calling, + e.g. {!Sc_rollup.Inbox.add_all_messages}. *) +val save_messages : + rw -> + Sc_rollup.Inbox_merkelized_payload_hashes.Hash.t -> + Store.Messages.info -> + unit Lwt.t + +(** {3 DAL} *) + +(** [get_slot_header t ~published_in_block_hash slot_index] returns the slot + header for the [slot_index] that was published in the provided block hash on + Layer 1. *) +val get_slot_header : + _ t -> + published_in_block_hash:Block_hash.t -> + Dal.Slot_index.t -> + Dal.Slot.Header.t tzresult Lwt.t + +(** [get_all_slot_headers t ~published_in_block_hash] returns the slot headers + for all the slots that were published in the provided block hash on Layer + 1. *) +val get_all_slot_headers : + _ t -> published_in_block_hash:Block_hash.t -> Dal.Slot.Header.t list Lwt.t + +(** [get_slot_indexes t ~published_in_block_hash] returns the slot indexes whose + headers were published in the provided block hash on Layer 1. *) +val get_slot_indexes : + _ t -> published_in_block_hash:Block_hash.t -> Dal.Slot_index.t list Lwt.t + +(** [save_slot_header t ~published_in_block_hash header] saves the [header] as + being published for its index in the provided block hash on Layer 1. *) +val save_slot_header : + rw -> published_in_block_hash:Block_hash.t -> Dal.Slot.Header.t -> unit Lwt.t + +(** [processed_slot t ~confirmed_in_block_hash index] returns [None] if the slot + pages was never processed nor downloaded, [Some `Unconfirmed] if the slot + was not confirmed and [Some `Confirmed] if the slot is confirmed and the + associated pages are available. *) +val processed_slot : + _ t -> + confirmed_in_block_hash:Block_hash.t -> + Dal.Slot_index.t -> + [`Unconfirmed | `Confirmed] option Lwt.t + +(** [list_slot_pages t ~confirmed_in_block_hash] lists all slots and their pages + that were confirmed and stored by the rollup node for + [confirmed_in_block_hash]. *) +val list_slot_pages : + _ t -> + confirmed_in_block_hash:Block_hash.t -> + ((Dal.Slot_index.t * int) * bytes) list Lwt.t + +(** [find_slot_page t ~confirmed_in_block_hash slot_index page_index] retrieves + a pages (with index [page_index]) for a slot [slot_index] that was confirmed + in the provided block hash. It returns [None] if the slot was not processed + or if the page index is out of bounds. *) +val find_slot_page : + _ t -> + confirmed_in_block_hash:Block_hash.t -> + slot_index:Dal.Slot_index.t -> + page_index:int -> + bytes option Lwt.t + +(** [save_unconfirmed_slot node_ctxt hash slot_index] saves in [node_ctxt.store] + that [slot_index] is unconfirmed in the block with hash in [node_ctxt.store]. +*) +val save_unconfirmed_slot : rw -> Block_hash.t -> Dal.Slot_index.t -> unit Lwt.t + +(** [save_confirmed_slot node_ctxt hash slot_index] saves in [node_ctxt.store] + that [slot_index] is confirmed in the block with hashin [node_ctxt.store]. + The contents of the slot are set to [pages] in [node_ctxt.store]. *) +val save_confirmed_slot : + rw -> Block_hash.t -> Dal.Slot_index.t -> bytes list -> unit Lwt.t + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/4636 + Missing docstrings. *) + +val find_confirmed_slots_history : + _ t -> Block_hash.t -> Dal.Slots_history.t option Lwt.t + +val save_confirmed_slots_history : + rw -> Block_hash.t -> Dal.Slots_history.t -> unit Lwt.t + +val find_confirmed_slots_histories : + _ t -> Block_hash.t -> Dal.Slots_history.History_cache.t option Lwt.t + +val save_confirmed_slots_histories : + rw -> Block_hash.t -> Dal.Slots_history.History_cache.t -> unit Lwt.t diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/outbox.ml b/src/proto_016_PtMumbai/bin_sc_rollup_node/outbox.ml index 6b1c60ff71fc468e9bb037d375595501a7377726..66a5a55a2425fca6949e6c27e1926e2c91866787 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/outbox.ml +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/outbox.ml @@ -30,7 +30,9 @@ module Make (PVM : Pvm.S) = struct let get_state_of_lcc node_ctxt = let open Lwt_result_syntax in let* block_hash = - State.hash_of_level node_ctxt (Raw_level.to_int32 node_ctxt.lcc.level) + Node_context.hash_of_level + node_ctxt + (Raw_level.to_int32 node_ctxt.lcc.level) in let* ctxt = Node_context.checkout_context node_ctxt block_hash in let*! state = PVM.State.find ctxt in diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/refutation_game.ml b/src/proto_016_PtMumbai/bin_sc_rollup_node/refutation_game.ml index 4178c1117dc43da9f7be312a02cf6864c31da357..fed8e13eb4431867f9ffefc38e4dbdb99c2c1844 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/refutation_game.ml +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/refutation_game.ml @@ -165,11 +165,13 @@ module Make (Interpreter : Interpreter.S) : let snapshot_level_int32 = Int32.pred Raw_level.(to_int32 game.start_level) in - let* snapshot_hash = State.hash_of_level node_ctxt snapshot_level_int32 in + let* snapshot_hash = + Node_context.hash_of_level node_ctxt snapshot_level_int32 + in let snapshot_head = Layer1.{hash = snapshot_hash; level = snapshot_level_int32} in - let* snapshot_inbox = Inbox.inbox_of_head node_ctxt snapshot_head in + let* snapshot_inbox = Node_context.inbox_of_head node_ctxt snapshot_head in let* snapshot_ctxt = Node_context.checkout_context node_ctxt snapshot_hash in @@ -223,19 +225,25 @@ module Make (Interpreter : Interpreter.S) : let get_history inbox_hash = let open Lwt_option_syntax in - let+ inbox = Store.Inboxes.find node_ctxt.store inbox_hash in + let+ inbox = Node_context.find_inbox node_ctxt inbox_hash in Sc_rollup.Inbox.take_snapshot inbox let get_payloads_history witness = - let open Lwt_syntax in - let+ {predecessor; predecessor_timestamp; messages} = - Store.Messages.get node_ctxt.store witness + Lwt.map + (WithExceptions.Result.to_exn_f + ~error:(Format.kasprintf Stdlib.failwith "%a" pp_print_trace)) + @@ + let open Lwt_result_syntax in + let* {predecessor; predecessor_timestamp; messages} = + Node_context.get_messages node_ctxt witness + in + let*? hist = + Inbox.payloads_history_of_messages + ~predecessor + ~predecessor_timestamp + messages in - Inbox.payloads_history_of_messages - ~predecessor - ~predecessor_timestamp - messages - |> WithExceptions.Result.get_ok ~loc:__LOC__ + return hist end module Dal_with_history = struct diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/state.ml b/src/proto_016_PtMumbai/bin_sc_rollup_node/state.ml deleted file mode 100644 index dcd13e4db0ac97db361b0594860dc33bde3a024e..0000000000000000000000000000000000000000 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/state.ml +++ /dev/null @@ -1,150 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* 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 -open Alpha_context -module Raw_store = Store - -module Store = struct - (* TODO: https://gitlab.com/tezos/tezos/-/issues/4392 - Use file. *) - module L2_head = - Store.Make_mutable_value - (struct - let path = ["l2_head"] - end) - (struct - type value = Sc_rollup_block.t - - let name = "l2_block" - - let encoding = Sc_rollup_block.encoding - end) - - (* TODO: https://gitlab.com/tezos/tezos/-/issues/4392 - Use file. *) - module Last_finalized_head = - Store.Make_mutable_value - (struct - let path = ["finalized_head"] - end) - (struct - type value = Sc_rollup_block.t - - let name = "l2_block" - - let encoding = Sc_rollup_block.encoding - end) - - (** Table from L1 levels to blocks hashes. *) - module Levels_to_hashes = - Store.Make_updatable_map - (struct - let path = ["tezos"; "levels"] - end) - (struct - type key = int32 - - let to_path_representation = Int32.to_string - end) - (struct - type value = Block_hash.t - - let name = "block_hash" - - let encoding = Block_hash.encoding - end) -end - -let hash_of_level_opt Node_context.{store; cctxt; _} level = - let open Lwt_syntax in - let* hash = Store.Levels_to_hashes.find store level in - match hash with - | Some hash -> return_some hash - | None -> - let+ hash = - Tezos_shell_services.Shell_services.Blocks.hash - cctxt - ~chain:cctxt#chain - ~block:(`Level level) - () - in - Result.to_option hash - -let hash_of_level node_ctxt level = - let open Lwt_result_syntax in - let*! hash = hash_of_level_opt node_ctxt level in - match hash with - | Some h -> return h - | None -> failwith "Cannot retrieve hash of level %ld" level - -let level_of_hash {Node_context.l1_ctxt; store; _} hash = - let open Lwt_result_syntax in - let*! block = Raw_store.L2_blocks.find store hash in - match block with - | Some {header = {level; _}; _} -> return (Raw_level.to_int32 level) - | None -> - let+ {level; _} = Layer1.fetch_tezos_shell_header l1_ctxt hash in - level - -let save_level store Layer1.{hash; level} = - Store.Levels_to_hashes.add store level hash - -let save_l2_block store (head : Sc_rollup_block.t) = - let open Lwt_syntax in - let* () = Raw_store.L2_blocks.add store head.header.block_hash head in - Store.L2_head.set store head - -let is_processed store head = Raw_store.L2_blocks.mem store head - -let last_processed_head_opt store = Store.L2_head.find store - -let mark_finalized_head store head_hash = - let open Lwt_syntax in - let* block = Raw_store.L2_blocks.find store head_hash in - match block with - | None -> return_unit - | Some block -> Store.Last_finalized_head.set store block - -let get_finalized_head_opt store = Store.Last_finalized_head.find store - -(* TODO: https://gitlab.com/tezos/tezos/-/issues/4532 - Make this logarithmic, by storing pointers to muliple predecessor and - by dichotomy. *) -let block_before store tick = - let open Lwt_result_syntax in - let*! head = Store.L2_head.find store in - match head with - | None -> return_none - | Some head -> - let rec search block_hash = - let*! block = Raw_store.L2_blocks.find store block_hash in - match block with - | None -> failwith "Missing block %a" Block_hash.pp block_hash - | Some block -> - if Sc_rollup.Tick.(block.initial_tick <= tick) then - return_some block - else search block.header.predecessor - in - search head.header.block_hash diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/state.mli b/src/proto_016_PtMumbai/bin_sc_rollup_node/state.mli deleted file mode 100644 index c67158f14744b84f3860cab56e34f56fe557e482..0000000000000000000000000000000000000000 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/state.mli +++ /dev/null @@ -1,69 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* 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.Alpha_context - -(** [is_processed store hash] returns [true] if the block with [hash] has - already been processed by the daemon. *) -val is_processed : _ Store.t -> Block_hash.t -> bool Lwt.t - -(** [mark_processed_head store head] remembers that the [head] is processed. The - system should not have to come back to it. *) -val save_l2_block : Store.rw -> Sc_rollup_block.t -> unit Lwt.t - -(** [last_processed_head_opt store] returns the last processed head if it - exists. *) -val last_processed_head_opt : _ Store.t -> Sc_rollup_block.t option Lwt.t - -(** [mark_finalized_head store head] remembers that the [head] is finalized. By - construction, every block whose level is smaller than [head]'s is also - finalized. *) -val mark_finalized_head : Store.rw -> Block_hash.t -> unit Lwt.t - -(** [last_finalized_head_opt store] returns the last finalized head if it exists. *) -val get_finalized_head_opt : _ Store.t -> Sc_rollup_block.t option Lwt.t - -(** [hash_of_level node_ctxt level] returns the current block hash for a given - [level]. *) -val hash_of_level : _ Node_context.t -> int32 -> Block_hash.t tzresult Lwt.t - -(** [hash_of_level_opt] is like {!hash_of_level} but returns [None] if the - [level] is not known. *) -val hash_of_level_opt : _ Node_context.t -> int32 -> Block_hash.t option Lwt.t - -(** [save_level store head] registers the correspondences [head.level |-> - head.hash] in the store. *) -val save_level : Store.rw -> Layer1.head -> unit Lwt.t - -(** [level_of_hash node_ctxt hash] returns the level for Tezos block hash [hash] - if it is known by the Tezos Layer 1 node. *) -val level_of_hash : _ Node_context.t -> Block_hash.t -> int32 tzresult Lwt.t - -(** [block_before store tick] returns the last layer 2 block whose initial tick - is before [tick]. *) -val block_before : - [> `Read] Store.store -> - Sc_rollup.Tick.t -> - Sc_rollup_block.t option tzresult Lwt.t diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/store.ml b/src/proto_016_PtMumbai/bin_sc_rollup_node/store.ml index 84de5a5e8635e812968da360482f80b58f222714..5c22868889fb6f85aa755626b191475fe6494249 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/store.ml +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/store.ml @@ -148,21 +148,6 @@ module Commitments = let encoding = Sc_rollup.Commitment.encoding end) -(* TODO: https://gitlab.com/tezos/tezos/-/issues/4392 - Use file. *) -module Last_stored_commitment_level = - Make_mutable_value - (struct - let path = ["commitments"; "last_stored_level"] - end) - (struct - type value = Raw_level.t - - let name = "raw_level" - - let encoding = Raw_level.encoding - end) - module Commitments_published_at_level = struct type element = { first_published_at_level : Raw_level.t; @@ -199,6 +184,55 @@ module Commitments_published_at_level = struct end) end +(* TODO: https://gitlab.com/tezos/tezos/-/issues/4392 + Use file. *) +module L2_head = + Make_mutable_value + (struct + let path = ["l2_head"] + end) + (struct + type value = Sc_rollup_block.t + + let name = "l2_block" + + let encoding = Sc_rollup_block.encoding + end) + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/4392 + Use file. *) +module Last_finalized_head = + Make_mutable_value + (struct + let path = ["finalized_head"] + end) + (struct + type value = Sc_rollup_block.t + + let name = "l2_block" + + let encoding = Sc_rollup_block.encoding + end) + +(** Table from L1 levels to blocks hashes. *) +module Levels_to_hashes = + Make_updatable_map + (struct + let path = ["tezos"; "levels"] + end) + (struct + type key = int32 + + let to_path_representation = Int32.to_string + end) + (struct + type value = Block_hash.t + + let name = "block_hash" + + let encoding = Block_hash.encoding + end) + (* Published slot headers per block hash, stored as a list of bindings from `Dal_slot_index.t` to `Dal.Slot.t`. The encoding function converts this diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/store.mli b/src/proto_016_PtMumbai/bin_sc_rollup_node/store.mli index 51af89bcf21cdaf14f9162003d1a02dd247ba378..4c2d9524da08bc40f3ed0790ce49a1ae8d82ecb4 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/store.mli +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/store.mli @@ -92,13 +92,6 @@ module Commitments : and type value := Sc_rollup.Commitment.t and type 'a store := 'a store -(** Storage containing the inbox level of the last commitment produced by the - rollup node. *) -module Last_stored_commitment_level : - Store_sigs.Mutable_value - with type value := Raw_level.t - and type 'a store := 'a store - (** Storage mapping commitment hashes to the level when they were published by the rollup node. It only contains hashes of commitments published by this rollup node. *) @@ -119,6 +112,22 @@ module Commitments_published_at_level : sig and type 'a store := 'a store end +module L2_head : + Store_sigs.Mutable_value + with type value := Sc_rollup_block.t + and type 'a store := 'a store + +module Last_finalized_head : + Store_sigs.Mutable_value + with type value := Sc_rollup_block.t + and type 'a store := 'a store + +module Levels_to_hashes : + Store_sigs.Map + with type key := int32 + and type value := Block_hash.t + and type 'a store := 'a store + (** Published slot headers per block hash, stored as a list of bindings from [Dal_slot_index.t] to [Dal.Slot.t]. The encoding function converts this diff --git a/src/proto_alpha/bin_sc_rollup_node/RPC_server.ml b/src/proto_alpha/bin_sc_rollup_node/RPC_server.ml index 2c12e8358aba2802295b066cb5bfc6ecfc602925..454e1e15d14e2d06c193668ff7b0863cfc5aafc5 100644 --- a/src/proto_alpha/bin_sc_rollup_node/RPC_server.ml +++ b/src/proto_alpha/bin_sc_rollup_node/RPC_server.ml @@ -29,14 +29,14 @@ open Protocol let get_head store = let open Lwt_result_syntax in - let*! head = State.last_processed_head_opt store in + let*! head = Node_context.last_processed_head_opt store in match head with | None -> failwith "No head" | Some {header = {block_hash; _}; _} -> return block_hash -let get_finalized store = +let get_finalized node_ctxt = let open Lwt_result_syntax in - let*! head = State.get_finalized_head_opt store in + let*! head = Node_context.get_finalized_head_opt node_ctxt in match head with | None -> failwith "No finalized head" | Some {header = {block_hash; _}; _} -> return block_hash @@ -45,39 +45,36 @@ let get_last_cemented (node_ctxt : _ Node_context.t) = let open Lwt_result_syntax in protect @@ fun () -> let* lcc_hash = - State.hash_of_level + Node_context.hash_of_level node_ctxt (Alpha_context.Raw_level.to_int32 node_ctxt.lcc.level) in return lcc_hash -let get_head_hash_opt store = +let get_head_hash_opt node_ctxt = let open Lwt_option_syntax in - let+ {header = {block_hash; _}; _} = State.last_processed_head_opt store in + let+ {header = {block_hash; _}; _} = + Node_context.last_processed_head_opt node_ctxt + in block_hash -let get_head_level_opt store = +let get_head_level_opt node_ctxt = let open Lwt_option_syntax in - let+ {header = {level; _}; _} = State.last_processed_head_opt store in + let+ {header = {level; _}; _} = + Node_context.last_processed_head_opt node_ctxt + in Alpha_context.Raw_level.to_int32 level -let get_l2_block_exn store block = - let open Lwt_result_syntax in - let*! b = Store.L2_blocks.get store block in - return b - module Slot_pages_map = struct open Protocol open Alpha_context include Map.Make (Dal.Slot_index) end -let get_dal_confirmed_slot_pages store block = +let get_dal_confirmed_slot_pages node_ctxt block = let open Lwt_result_syntax in let*! slot_pages = - Store.Dal_slot_pages.list_secondary_keys_with_values - store - ~primary_key:block + Node_context.list_slot_pages node_ctxt ~confirmed_in_block_hash:block in (* Slot pages are sorted in lexicographic order of slot index and page number.*) @@ -96,23 +93,24 @@ let get_dal_confirmed_slot_pages store block = in return @@ Slot_pages_map.bindings slot_pages_map -let get_dal_slot_page store block slot_index slot_page = +let get_dal_slot_page node_ctxt block slot_index slot_page = let open Lwt_result_syntax in let*! processed = - Store.Dal_processed_slots.find - store - ~primary_key:block - ~secondary_key:slot_index + Node_context.processed_slot + node_ctxt + ~confirmed_in_block_hash:block + slot_index in match processed with | None -> return ("Slot page has not been downloaded", None) | Some `Unconfirmed -> return ("Slot was not confirmed", None) | Some `Confirmed -> ( let*! contents_opt = - Store.Dal_slot_pages.find - store - ~primary_key:block - ~secondary_key:(slot_index, slot_page) + Node_context.find_slot_page + node_ctxt + ~confirmed_in_block_hash:block + ~slot_index + ~page_index:slot_page in match contents_opt with | None -> assert false @@ -190,10 +188,10 @@ module Block_directory = Make_directory (struct let open Lwt_result_syntax in let+ block = match block with - | `Head -> get_head node_ctxt.Node_context.store + | `Head -> get_head node_ctxt | `Hash b -> return b - | `Level l -> State.hash_of_level node_ctxt l - | `Finalized -> get_finalized node_ctxt.Node_context.store + | `Level l -> Node_context.hash_of_level node_ctxt l + | `Finalized -> get_finalized node_ctxt | `Cemented -> get_last_cemented node_ctxt in (Node_context.readonly node_ctxt, block) @@ -208,10 +206,10 @@ module Outbox_directory = Make_directory (struct let open Lwt_result_syntax in let+ block = match block with - | `Head -> get_head node_ctxt.Node_context.store + | `Head -> get_head node_ctxt | `Hash b -> return b - | `Level l -> State.hash_of_level node_ctxt l - | `Finalized -> get_finalized node_ctxt.Node_context.store + | `Level l -> Node_context.hash_of_level node_ctxt l + | `Finalized -> get_finalized node_ctxt | `Cemented -> get_last_cemented node_ctxt in (Node_context.readonly node_ctxt, block, level) @@ -229,9 +227,9 @@ module Common = struct Block_directory.register0 Sc_rollup_services.Global.Block.num_messages @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in - let* l2_block = get_l2_block_exn node_ctxt.store block in - let*! {messages; _} = - Store.Messages.get node_ctxt.store l2_block.header.inbox_witness + let* l2_block = Node_context.get_l2_block node_ctxt block in + let* {messages; _} = + Node_context.get_messages node_ctxt l2_block.header.inbox_witness in return @@ Z.of_int (List.length messages) @@ -241,11 +239,11 @@ module Common = struct let () = Global_directory.register0 Sc_rollup_services.Global.current_tezos_head - @@ fun node_ctxt () () -> get_head_hash_opt node_ctxt.store >>= return + @@ fun node_ctxt () () -> get_head_hash_opt node_ctxt >>= return let () = Global_directory.register0 Sc_rollup_services.Global.current_tezos_level - @@ fun node_ctxt () () -> get_head_level_opt node_ctxt.store >>= return + @@ fun node_ctxt () () -> get_head_level_opt node_ctxt >>= return let () = Block_directory.register0 Sc_rollup_services.Global.Block.hash @@ -253,17 +251,19 @@ module Common = struct let () = Block_directory.register0 Sc_rollup_services.Global.Block.level - @@ fun (node_ctxt, block) () () -> State.level_of_hash node_ctxt block + @@ fun (node_ctxt, block) () () -> + Node_context.level_of_hash node_ctxt block let () = Block_directory.register0 Sc_rollup_services.Global.Block.inbox - @@ fun (node_ctxt, block) () () -> Inbox.inbox_of_hash node_ctxt block + @@ fun (node_ctxt, block) () () -> + Node_context.get_inbox_by_block_hash node_ctxt block let () = Block_directory.register0 Sc_rollup_services.Global.Block.ticks @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in - let+ l2_block = get_l2_block_exn node_ctxt.store block in + let+ l2_block = Node_context.get_l2_block node_ctxt block in Z.of_int64 l2_block.num_ticks end @@ -299,7 +299,7 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct Some map | None -> None in - let* level = State.level_of_hash node_ctxt block in + let* level = Node_context.level_of_hash node_ctxt block in let* sim = Simulation.start_simulation node_ctxt @@ -372,12 +372,12 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct let open Lwt_result_syntax in let*! res = let open Lwt_option_syntax in - let* head = State.last_processed_head_opt node_ctxt.store in + let* head = Node_context.last_processed_head_opt node_ctxt in let commitment_hash = Sc_rollup_block.most_recent_commitment head.header in let* commitment = - Store.Commitments.find node_ctxt.store commitment_hash + Node_context.find_commitment node_ctxt commitment_hash in return (commitment, commitment_hash) in @@ -397,7 +397,7 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct available only when the commitment has been published and included in a block. *) let*! published_at_level_info = - Store.Commitments_published_at_level.find node_ctxt.store hash + Node_context.commitment_published_at_level node_ctxt hash in let first_published, published = match published_at_level_info with @@ -422,7 +422,7 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct @@ fun (node_ctxt, block) () () -> let open Lwt_result_syntax in let*! slots = - Store.Dal_slots_headers.list_values node_ctxt.store ~primary_key:block + Node_context.get_all_slot_headers node_ctxt ~published_in_block_hash:block in return slots @@ -430,12 +430,12 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct Block_directory.register0 Sc_rollup_services.Global.Block.dal_confirmed_slot_pages @@ fun (node_ctxt, block) () () -> - get_dal_confirmed_slot_pages node_ctxt.store block + get_dal_confirmed_slot_pages node_ctxt block let () = Block_directory.register0 Sc_rollup_services.Global.Block.dal_slot_page @@ fun (node_ctxt, block) {index; page} () -> - get_dal_slot_page node_ctxt.store block index page + get_dal_slot_page node_ctxt block index page let () = Outbox_directory.register0 Sc_rollup_services.Global.Block.Outbox.messages @@ -498,7 +498,7 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct let inbox_info_of_level (node_ctxt : _ Node_context.t) inbox_level = let open Alpha_context in let open Lwt_syntax in - let+ finalized_head = State.get_finalized_head_opt node_ctxt.store in + let+ finalized_head = Node_context.get_finalized_head_opt node_ctxt in let finalized = match finalized_head with | None -> false @@ -540,14 +540,11 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct | None -> return (Sc_rollup_services.Included (info, inbox_info)) | Some commitment_level -> ( - let* block = - State.hash_of_level + let*! block = + Node_context.find_l2_block_by_level node_ctxt (Alpha_context.Raw_level.to_int32 commitment_level) in - let*! block = - Store.L2_blocks.find node_ctxt.store block - in match block with | None -> (* Commitment not computed yet for inbox *) @@ -561,8 +558,8 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct in (* Commitment computed *) let*! published_at = - Store.Commitments_published_at_level.find - node_ctxt.store + Node_context.commitment_published_at_level + node_ctxt commitment_hash in match published_at with @@ -576,9 +573,9 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct published_at_level = Some published_at_level; } -> (* Commitment published *) - let*! commitment = - Store.Commitments.get - node_ctxt.store + let* commitment = + Node_context.get_commitment + node_ctxt commitment_hash in let commitment_info = diff --git a/src/proto_alpha/bin_sc_rollup_node/commitment.ml b/src/proto_alpha/bin_sc_rollup_node/commitment.ml index 82ab504670bb7955eae9121bd9ff0e7d080ce9a8..264d970213bce2930ea7a562bfda72d750aaf2d0 100644 --- a/src/proto_alpha/bin_sc_rollup_node/commitment.ml +++ b/src/proto_alpha/bin_sc_rollup_node/commitment.ml @@ -70,10 +70,11 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct let tick_of_level (node_ctxt : _ Node_context.t) inbox_level = let open Lwt_result_syntax in - let* block_hash = - State.hash_of_level node_ctxt (Raw_level.to_int32 inbox_level) + let* block = + Node_context.get_l2_block_by_level + node_ctxt + (Raw_level.to_int32 inbox_level) in - let*! block = Store.L2_blocks.get node_ctxt.store block_hash in return (Sc_rollup_block.final_tick block) let build_commitment (node_ctxt : _ Node_context.t) @@ -128,14 +129,11 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct Some genesis_commitment else let* last_commitment_hash = - let*! pred = Store.L2_blocks.find node_ctxt.store predecessor in - match pred with - | None -> failwith "Missing block %a" Block_hash.pp predecessor - | Some pred -> - return (Sc_rollup_block.most_recent_commitment pred.header) + let+ pred = Node_context.get_l2_block node_ctxt predecessor in + Sc_rollup_block.most_recent_commitment pred.header in - let*! last_commitment = - Store.Commitments.get node_ctxt.store last_commitment_hash + let* last_commitment = + Node_context.get_commitment node_ctxt last_commitment_hash in let next_commitment_level = next_commitment_level node_ctxt last_commitment.inbox_level @@ -163,11 +161,8 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct match commitment with | None -> return_none | Some commitment -> - let commitment_hash = - Sc_rollup.Commitment.hash_uncarbonated commitment - in - let*! () = - Store.Commitments.add node_ctxt.store commitment_hash commitment + let*! commitment_hash = + Node_context.save_commitment node_ctxt commitment in return_some commitment_hash @@ -178,7 +173,7 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct | None -> node_ctxt.genesis_info.level | Some lpc -> lpc.inbox_level in - let* head = State.last_processed_head_opt node_ctxt.store in + let* head = Node_context.last_processed_head_opt node_ctxt in let next_head_level = Option.map (fun (b : Sc_rollup_block.t) -> Raw_level.succ b.header.level) @@ -189,7 +184,7 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct in let rec gather acc (commitment_hash : Sc_rollup.Commitment.Hash.t) = let* commitment = - Store.Commitments.find node_ctxt.store commitment_hash + Node_context.find_commitment node_ctxt commitment_hash in match commitment with | None -> return acc @@ -204,9 +199,7 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct return acc | Some commitment -> let* published_info = - Store.Commitments_published_at_level.find - node_ctxt.store - commitment_hash + Node_context.commitment_published_at_level node_ctxt commitment_hash in let past_curfew = match (published_info, next_head_level) with @@ -219,7 +212,7 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct (* We keep the commitment and go back to the previous one. *) gather acc commitment.predecessor in - let* finalized_block = State.get_finalized_head_opt node_ctxt.store in + let* finalized_block = Node_context.get_finalized_head_opt node_ctxt in match finalized_block with | None -> return_nil | Some finalized -> @@ -255,9 +248,7 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct let earliest_cementing_level node_ctxt commitment_hash = let open Lwt_option_syntax in let+ {first_published_at_level; _} = - Store.Commitments_published_at_level.find - node_ctxt.Node_context.store - commitment_hash + Node_context.commitment_published_at_level node_ctxt commitment_hash in add_level first_published_at_level (sc_rollup_challenge_window node_ctxt) @@ -273,20 +264,17 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct (head : Sc_rollup_block.t) = let open Lwt_option_syntax in let commitment_hash = Sc_rollup_block.most_recent_commitment head.header in - let* commitment = Store.Commitments.find node_ctxt.store commitment_hash in + let* commitment = Node_context.find_commitment node_ctxt commitment_hash in let*? cementable_level_bound = sub_level commitment.inbox_level (sc_rollup_challenge_window node_ctxt) in if Raw_level.(cementable_level_bound <= node_ctxt.lcc.level) then fail else - let* cementable_bound_block_hash = - State.hash_of_level_opt + let* cementable_bound_block = + Node_context.find_l2_block_by_level node_ctxt (Raw_level.to_int32 cementable_level_bound) in - let* cementable_bound_block = - Store.L2_blocks.find node_ctxt.store cementable_bound_block_hash - in let cementable_commitment = Sc_rollup_block.most_recent_commitment cementable_bound_block.header in @@ -300,12 +288,12 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct let*! x = x in match x with None -> return_nil | Some x -> f x in - let*& head = State.last_processed_head_opt node_ctxt.Node_context.store in + let*& head = Node_context.last_processed_head_opt node_ctxt in let head_level = head.header.level in let rec gather acc (commitment_hash : Sc_rollup.Commitment.Hash.t) = let open Lwt_syntax in let* commitment = - Store.Commitments.find node_ctxt.store commitment_hash + Node_context.find_commitment node_ctxt commitment_hash in match commitment with | None -> return acc diff --git a/src/proto_alpha/bin_sc_rollup_node/daemon.ml b/src/proto_alpha/bin_sc_rollup_node/daemon.ml index e0b99967f67f4a52e069775544df76a733978e68..b46e5b40eb6611c48603dc252e684c0927ba768d 100644 --- a/src/proto_alpha/bin_sc_rollup_node/daemon.ml +++ b/src/proto_alpha/bin_sc_rollup_node/daemon.ml @@ -52,8 +52,8 @@ module Make (PVM : Pvm.S) = struct Sc_rollup.Commitment.hash_uncarbonated commitment in let*! () = - Store.Commitments_published_at_level.add - node_ctxt.store + Node_context.set_commitment_published_at_level + node_ctxt commitment_hash { first_published_at_level = published_at_level; @@ -69,20 +69,21 @@ module Make (PVM : Pvm.S) = struct Sc_rollup.Commitment.hash_uncarbonated commitment in let*! known_commitment = - Store.Commitments.mem node_ctxt.store commitment_hash + Node_context.commitment_exists node_ctxt commitment_hash in if not known_commitment then return_unit else let*! republication = - Store.Commitments_published_at_level.mem - node_ctxt.store + Node_context.commitment_was_published + node_ctxt + ~source:Anyone commitment_hash in if republication then return_unit else let*! () = - Store.Commitments_published_at_level.add - node_ctxt.store + Node_context.set_commitment_published_at_level + node_ctxt commitment_hash { first_published_at_level = published_at_level; @@ -93,11 +94,10 @@ module Make (PVM : Pvm.S) = struct | Sc_rollup_cement {commitment; _}, Sc_rollup_cement_result {inbox_level; _} -> (* Cemented commitment ---------------------------------------------- *) - let* inbox_block_hash = - State.hash_of_level node_ctxt (Raw_level.to_int32 inbox_level) - in - let*! inbox_block = - Store.L2_blocks.get node_ctxt.store inbox_block_hash + let* inbox_block = + Node_context.get_l2_block_by_level + node_ctxt + (Raw_level.to_int32 inbox_level) in let*? () = (* We stop the node if we disagree with a cemented commitment *) @@ -142,10 +142,9 @@ module Make (PVM : Pvm.S) = struct -> assert (Node_context.dal_enabled node_ctxt) ; let*! () = - Store.Dal_slots_headers.add - node_ctxt.store - ~primary_key:head.Layer1.hash - ~secondary_key:slot_header.id.index + Node_context.save_slot_header + node_ctxt + ~published_in_block_hash:head.Layer1.hash slot_header in return_unit @@ -229,7 +228,7 @@ module Make (PVM : Pvm.S) = struct let rec processed_finalized_block (node_ctxt : _ Node_context.t) Layer1.({hash; level} as block) = let open Lwt_result_syntax in - let*! last_finalized = State.get_finalized_head_opt node_ctxt.store in + let*! last_finalized = Node_context.get_finalized_head_opt node_ctxt in let already_finalized = match last_finalized with | Some finalized -> level <= Raw_level.to_int32 finalized.header.level @@ -243,14 +242,14 @@ module Make (PVM : Pvm.S) = struct in let*! () = Daemon_event.head_processing hash level ~finalized:true in let* () = process_l1_block_operations ~finalized:true node_ctxt block in - let*! () = State.mark_finalized_head node_ctxt.store hash in + let*! () = Node_context.mark_finalized_head node_ctxt hash in return_unit let process_head (node_ctxt : _ Node_context.t) Layer1.({hash; level} as head) = let open Lwt_result_syntax in let*! () = Daemon_event.head_processing hash level ~finalized:false in - let*! () = State.save_level node_ctxt.store head in + let*! () = Node_context.save_level node_ctxt head in let* inbox_hash, inbox, inbox_witness, messages, ctxt = Inbox.process_head node_ctxt head in @@ -278,15 +277,8 @@ module Make (PVM : Pvm.S) = struct (* Previous commitment for rollup genesis is itself. *) return node_ctxt.genesis_info.Sc_rollup.Commitment.commitment_hash else - let*! pred = Store.L2_blocks.find node_ctxt.store predecessor in - match pred with - | None -> - failwith - "Missing L2 predecessor %a for previous commitment" - Block_hash.pp - predecessor - | Some pred -> - return (Sc_rollup_block.most_recent_commitment pred.header) + let+ pred = Node_context.get_l2_block node_ctxt predecessor in + Sc_rollup_block.most_recent_commitment pred.header in let header = Sc_rollup_block. @@ -311,7 +303,7 @@ module Make (PVM : Pvm.S) = struct head in let* () = processed_finalized_block node_ctxt finalized_block in - let*! () = State.save_l2_block node_ctxt.store l2_block in + let*! () = Node_context.save_l2_head node_ctxt l2_block in let*! () = Daemon_event.new_head_processed hash (Raw_level.to_int32 level) in @@ -339,9 +331,7 @@ module Make (PVM : Pvm.S) = struct imply the processing of head~3, etc). *) let on_layer_1_head node_ctxt head = let open Lwt_result_syntax in - let*! old_head = - State.last_processed_head_opt node_ctxt.Node_context.store - in + let*! old_head = Node_context.last_processed_head_opt node_ctxt in let old_head = match old_head with | Some h -> @@ -427,27 +417,22 @@ module Make (PVM : Pvm.S) = struct l1_ctxt.heads in let*! () = Event.connection_lost () in - let* l1_ctxt = - Layer1.reconnect configuration node_ctxt.l1_ctxt node_ctxt.store - in + let* l1_ctxt = Layer1.reconnect configuration node_ctxt.l1_ctxt in loop l1_ctxt in protect @@ fun () -> Lwt.no_cancel @@ loop node_ctxt.l1_ctxt - let install_finalizer {Node_context.l1_ctxt; store; _} rpc_server = + let install_finalizer node_ctxt rpc_server = let open Lwt_syntax in Lwt_exit.register_clean_up_callback ~loc:__LOC__ @@ fun exit_status -> - let message = l1_ctxt.cctxt#message in - let* () = message "Shutting down L1@." in - let* () = Layer1.shutdown l1_ctxt in + let message = node_ctxt.Node_context.cctxt#message in let* () = message "Shutting down RPC server@." in let* () = Components.RPC_server.shutdown rpc_server in let* () = message "Shutting down Injector@." in let* () = Injector.shutdown () in let* () = message "Shutting down Batcher@." in let* () = Components.Batcher.shutdown () in - let* () = message "Closing store@." in - let* () = Store.close store in + let* () = Node_context.close node_ctxt in let* () = Event.shutdown_node exit_status in Tezos_base_unix.Internal_event_unix.close () @@ -566,26 +551,8 @@ let run ~data_dir (configuration : Configuration.t) ()) configuration.sc_rollup_node_operators in - let*! store = - Store.load Read_write Configuration.(default_storage_dir data_dir) - in - let*! context = - Context.load Read_write (Configuration.default_context_dir data_dir) - in - let* l1_ctxt, kind = Layer1.start configuration cctxt store in let* node_ctxt = - Node_context.init - cctxt - dal_cctxt - ~data_dir - l1_ctxt - configuration.sc_rollup_address - kind - configuration.sc_rollup_node_operators - configuration.fee_parameters - ~loser_mode:configuration.loser_mode - store - context + Node_context.init cctxt dal_cctxt ~data_dir Read_write configuration in let module Daemon = Make ((val Components.pvm_of_kind node_ctxt.kind)) in Daemon.run node_ctxt configuration diff --git a/src/proto_alpha/bin_sc_rollup_node/dal_pages_request.ml b/src/proto_alpha/bin_sc_rollup_node/dal_pages_request.ml index da4c8280bd33837e88958d5ead67929445501507..4a4db2a8f35ea881a7f45dd258d8cd2ac68126ae 100644 --- a/src/proto_alpha/bin_sc_rollup_node/dal_pages_request.ml +++ b/src/proto_alpha/bin_sc_rollup_node/dal_pages_request.ml @@ -61,7 +61,7 @@ let () = let store_entry_from_published_level ~dal_attestation_lag ~published_level node_ctxt = - State.hash_of_level node_ctxt + Node_context.hash_of_level node_ctxt @@ Int32.( add (of_int dal_attestation_lag) (Raw_level.to_int32 published_level)) @@ -90,11 +90,11 @@ let get_slot_pages = Lwt.return let check_confirmation_status_and_download - ({Node_context.store; dal_cctxt; _} as node_ctxt) ~confirmed_in_block_hash + ({Node_context.dal_cctxt; _} as node_ctxt) ~confirmed_in_block_hash ~published_in_block_hash index = let open Lwt_result_syntax in let* confirmed_in_block_level = - State.level_of_hash node_ctxt confirmed_in_block_hash + Node_context.level_of_hash node_ctxt confirmed_in_block_hash in let confirmed_in_head = Layer1.{hash = confirmed_in_block_hash; level = confirmed_in_block_level} @@ -103,15 +103,12 @@ let check_confirmation_status_and_download Dal_slots_tracker.is_slot_confirmed node_ctxt confirmed_in_head index in if is_confirmed then - let*! {commitment; _} = - Store.Dal_slots_headers.get - store - ~primary_key:published_in_block_hash - ~secondary_key:index + let* {commitment; _} = + Node_context.get_slot_header node_ctxt ~published_in_block_hash index in let* pages = get_slot_pages dal_cctxt commitment in let save_pages node_ctxt = - Dal_slots_tracker.save_confirmed_slot + Node_context.save_confirmed_slot node_ctxt confirmed_in_block_hash index @@ -120,14 +117,11 @@ let check_confirmation_status_and_download return (Delayed_write_monad.delay_write (Some pages) save_pages) else let save_slot node_ctxt = - Dal_slots_tracker.save_unconfirmed_slot - node_ctxt - confirmed_in_block_hash - index + Node_context.save_unconfirmed_slot node_ctxt confirmed_in_block_hash index in return (Delayed_write_monad.delay_write None save_slot) -let slot_pages ~dal_attestation_lag ({Node_context.store; _} as node_ctxt) +let slot_pages ~dal_attestation_lag node_ctxt Dal.Slot.Header.{published_level; index} = let open Lwt_result_syntax in let* confirmed_in_block_hash = @@ -137,15 +131,14 @@ let slot_pages ~dal_attestation_lag ({Node_context.store; _} as node_ctxt) node_ctxt in let*! processed = - Store.Dal_processed_slots.find - store - ~primary_key:confirmed_in_block_hash - ~secondary_key:index + Node_context.processed_slot node_ctxt ~confirmed_in_block_hash index in match processed with | None -> let* published_in_block_hash = - State.hash_of_level node_ctxt (Raw_level.to_int32 published_level) + Node_context.hash_of_level + node_ctxt + (Raw_level.to_int32 published_level) in check_confirmation_status_and_download node_ctxt @@ -155,9 +148,7 @@ let slot_pages ~dal_attestation_lag ({Node_context.store; _} as node_ctxt) | Some `Unconfirmed -> return (Delayed_write_monad.no_write None) | Some `Confirmed -> let*! pages = - Store.Dal_slot_pages.list_secondary_keys_with_values - store - ~primary_key:confirmed_in_block_hash + Node_context.list_slot_pages node_ctxt ~confirmed_in_block_hash in let pages = List.filter_map @@ -167,8 +158,7 @@ let slot_pages ~dal_attestation_lag ({Node_context.store; _} as node_ctxt) in return (Delayed_write_monad.no_write (Some pages)) -let page_content ~dal_attestation_lag ({Node_context.store; _} as node_ctxt) - page_id = +let page_content ~dal_attestation_lag node_ctxt page_id = let open Lwt_result_syntax in let open Delayed_write_monad.Lwt_result_syntax in let Dal.Page.{slot_id; page_index} = page_id in @@ -180,10 +170,7 @@ let page_content ~dal_attestation_lag ({Node_context.store; _} as node_ctxt) node_ctxt in let*! processed = - Store.Dal_processed_slots.find - store - ~primary_key:confirmed_in_block_hash - ~secondary_key:index + Node_context.processed_slot node_ctxt ~confirmed_in_block_hash index in match processed with | None -> ( @@ -196,7 +183,9 @@ let page_content ~dal_attestation_lag ({Node_context.store; _} as node_ctxt) the logic of that function when determining the confirmation status of a slot. *) let* published_in_block_hash = - State.hash_of_level node_ctxt (Raw_level.to_int32 published_level) + Node_context.hash_of_level + node_ctxt + (Raw_level.to_int32 published_level) in let>* pages = check_confirmation_status_and_download @@ -214,18 +203,17 @@ let page_content ~dal_attestation_lag ({Node_context.store; _} as node_ctxt) | Some `Unconfirmed -> return None | Some `Confirmed -> ( let*! page_opt = - Store.Dal_slot_pages.find - store - ~primary_key:confirmed_in_block_hash - ~secondary_key:(index, page_index) + Node_context.find_slot_page + node_ctxt + ~confirmed_in_block_hash + ~slot_index:index + ~page_index in match page_opt with | Some v -> return @@ Some v | None -> let*! pages = - Store.Dal_slot_pages.list_secondary_keys_with_values - store - ~primary_key:confirmed_in_block_hash + Node_context.list_slot_pages node_ctxt ~confirmed_in_block_hash in if page_index < 0 || List.compare_length_with pages page_index <= 0 then tzfail @@ Dal_invalid_page_for_slot page_id diff --git a/src/proto_alpha/bin_sc_rollup_node/dal_slots_tracker.ml b/src/proto_alpha/bin_sc_rollup_node/dal_slots_tracker.ml index db274826cb33d7d4967de0801f83bebc9c6bddf5..ad568be9b752ad7a23e9f79d47d342541e20ad0c 100644 --- a/src/proto_alpha/bin_sc_rollup_node/dal_slots_tracker.ml +++ b/src/proto_alpha/bin_sc_rollup_node/dal_slots_tracker.ml @@ -100,9 +100,9 @@ let slots_info node_ctxt (Layer1.{hash; _} as head) = metadata.protocol_data.dal_attestation in let*! published_slots_indexes = - Store.Dal_slots_headers.list_secondary_keys - node_ctxt.store - ~primary_key:published_block_hash + Node_context.get_slot_indexes + node_ctxt + ~published_in_block_hash:published_block_hash in let confirmed_slots_indexes_list = List.filter @@ -146,38 +146,8 @@ let to_slot_index_list (constants : Constants.Parametric.t) bitset = Use a shared storage between dal and rollup node to store slots data. *) -let save_unconfirmed_slot {Node_context.store; _} current_block_hash slot_index - = - (* No page is actually saved *) - Store.Dal_processed_slots.add - store - ~primary_key:current_block_hash - ~secondary_key:slot_index - `Unconfirmed - -let save_confirmed_slot {Node_context.store; _} current_block_hash slot_index - pages = - (* Adding multiple entries with the same primary key amounts to updating the - contents of an in-memory map, hence pages must be added sequentially. *) - let open Lwt_syntax in - let* () = - List.iteri_s - (fun page_number page -> - Store.Dal_slot_pages.add - store - ~primary_key:current_block_hash - ~secondary_key:(slot_index, page_number) - page) - pages - in - Store.Dal_processed_slots.add - store - ~primary_key:current_block_hash - ~secondary_key:slot_index - `Confirmed - let download_and_save_slots - ({Node_context.store; dal_cctxt; protocol_constants; _} as node_context) + ({Node_context.dal_cctxt; protocol_constants; _} as node_context) ~current_block_hash {published_block_hash; confirmed_slots_indexes} = let open Lwt_result_syntax in let*? all_slots = @@ -203,43 +173,41 @@ let download_and_save_slots let*! () = List.iter_p (fun s_slot -> - save_unconfirmed_slot node_context current_block_hash s_slot) + Node_context.save_unconfirmed_slot + node_context + current_block_hash + s_slot) not_confirmed in let* () = [] (* Preparing for the pre-fetching logic. *) |> List.iter_ep (fun s_slot -> - (* slot_header is missing but the slot with index s_slot has been + (* fails if slot_header is missing but the slot with index s_slot has been confirmed. This scenario should not be possible. *) - let*! slot_header_is_stored = - Store.Dal_slots_headers.mem - store - ~primary_key:published_block_hash - ~secondary_key:s_slot + let* {commitment; _} = + Node_context.get_slot_header + node_context + ~published_in_block_hash:published_block_hash + s_slot + in + (* The slot with index s_slot is confirmed. We can + proceed retrieving it from the dal node and save it + in the store. *) + let* pages = Dal_node_client.get_slot_pages dal_cctxt commitment in + let*! () = + Node_context.save_confirmed_slot + node_context + current_block_hash + s_slot + pages in - if not slot_header_is_stored then - failwith "Slot header was not found in store" - else - let*! {commitment; _} = - Store.Dal_slots_headers.get - store - ~primary_key:published_block_hash - ~secondary_key:s_slot - in - (* The slot with index s_slot is confirmed. We can - proceed retrieving it from the dal node and save it - in the store. *) - let* pages = Dal_node_client.get_slot_pages dal_cctxt commitment in - let*! () = - save_confirmed_slot node_context current_block_hash s_slot pages - in - let*! () = - Dal_slots_tracker_event.slot_has_been_confirmed - s_slot - published_block_hash - current_block_hash - in - return_unit) + let*! () = + Dal_slots_tracker_event.slot_has_been_confirmed + s_slot + published_block_hash + current_block_hash + in + return_unit) in return_unit @@ -256,16 +224,13 @@ module Confirmed_slots_history = struct node_ctxt.Node_context.protocol_constants.parametric confirmed_slots_indexes in - let*! confirmed_slots_indexes_with_header = - List.map_p - (fun slot_index -> - Store.Dal_slots_headers.get - node_ctxt.Node_context.store - ~primary_key:published_block_hash - ~secondary_key:slot_index) - relevant_slots_indexes - in - return confirmed_slots_indexes_with_header + List.map_ep + (fun slot_index -> + Node_context.get_slot_header + node_ctxt + ~published_in_block_hash:published_block_hash + slot_index) + relevant_slots_indexes let read_slots_history_from_l1 {Node_context.l1_ctxt = {cctxt; _}; _} block = let open Lwt_result_syntax in @@ -294,8 +259,7 @@ module Confirmed_slots_history = struct Layer1.{hash = block_hash; level = block_level} ~entry_kind ~find ~default = let open Lwt_result_syntax in - let open Node_context in - let*! confirmed_slots_history_opt = find node_ctxt.store block_hash in + let*! confirmed_slots_history_opt = find node_ctxt block_hash in let block_level = Raw_level.of_int32_exn block_level in let should_process_dal_slots = should_process_dal_slots node_ctxt block_level @@ -327,7 +291,7 @@ module Confirmed_slots_history = struct node_ctxt block ~entry_kind:"slots history" - ~find:Store.Dal_confirmed_slots_history.find + ~find:Node_context.find_confirmed_slots_history ~default:read_slots_history_from_l1 let slots_history_cache_of_hash node_ctxt block = @@ -335,7 +299,7 @@ module Confirmed_slots_history = struct node_ctxt block ~entry_kind:"slots history cache" - ~find:Store.Dal_confirmed_slots_histories.find + ~find:Node_context.find_confirmed_slots_histories ~default:(fun node_ctxt _block -> let num_slots = node_ctxt.Node_context.protocol_constants.parametric.dal @@ -354,7 +318,7 @@ module Confirmed_slots_history = struct @@ Dal.Slots_history.History_cache.empty ~capacity:(Int64.of_int @@ (num_slots * 60000))) - let update (Node_context.{store; l1_ctxt; _} as node_ctxt) + let update (Node_context.{l1_ctxt; _} as node_ctxt) Layer1.({hash = head_hash; _} as head) confirmation_info = let open Lwt_result_syntax in let* slots_to_save = @@ -384,10 +348,16 @@ module Confirmed_slots_history = struct (* TODO/DAL: https://gitlab.com/tezos/tezos/-/issues/3856 Attempt to improve this process. *) let*! () = - Store.Dal_confirmed_slots_history.add store head_hash slots_history + Node_context.save_confirmed_slots_history + node_ctxt + head_hash + slots_history in let*! () = - Store.Dal_confirmed_slots_histories.add store head_hash slots_cache + Node_context.save_confirmed_slots_histories + node_ctxt + head_hash + slots_cache in return () end diff --git a/src/proto_alpha/bin_sc_rollup_node/dal_slots_tracker.mli b/src/proto_alpha/bin_sc_rollup_node/dal_slots_tracker.mli index 458d3735649f52a2329da5a84d25daf87b330334..bd1f4ce7620128e5a0d2b9a63c9214074239b8d2 100644 --- a/src/proto_alpha/bin_sc_rollup_node/dal_slots_tracker.mli +++ b/src/proto_alpha/bin_sc_rollup_node/dal_slots_tracker.mli @@ -38,22 +38,6 @@ open Alpha_context val is_slot_confirmed : _ Node_context.t -> Layer1.head -> Dal.Slot_index.t -> bool tzresult Lwt.t -(** [save_unconfirmed_slot node_ctxt hash slot_index] saves in [node_ctxt.store] - that [slot_index] is unconfirmed in the block with hash in [node_ctxt.store]. -*) -val save_unconfirmed_slot : - Node_context.rw -> Block_hash.t -> Dal.Slot_index.t -> unit Lwt.t - -(** [save_confirmed_slot node_ctxt hash slot_index] saves in [node_ctxt.store] - that [slot_index] is confirmed in the block with hashin [node_ctxt.store]. - The contents of the slot are set to [pages] in [node_ctxt.store]. *) -val save_confirmed_slot : - Node_context.rw -> - Block_hash.t -> - Dal.Slot_index.t -> - Dal.Page.content list -> - unit Lwt.t - (** [process_head node_ctxt head] performs the following operations: {ul {li it reads the endorsements for headers published attestation_lag diff --git a/src/proto_alpha/bin_sc_rollup_node/inbox.ml b/src/proto_alpha/bin_sc_rollup_node/inbox.ml index 8080b46c2a9463dab8ebdb70d4e077f7809a3671..32eae4f3464068c2d0459907ed0a3464a0d0d5cb 100644 --- a/src/proto_alpha/bin_sc_rollup_node/inbox.ml +++ b/src/proto_alpha/bin_sc_rollup_node/inbox.ml @@ -31,60 +31,6 @@ open Alpha_context let lift promise = Lwt.map Environment.wrap_tzresult promise -let genesis_inbox node_ctxt = - let genesis_level = - Raw_level.to_int32 node_ctxt.Node_context.genesis_info.level - in - Plugin.RPC.Sc_rollup.inbox - node_ctxt.cctxt - (node_ctxt.cctxt#chain, `Level genesis_level) - -module State = struct - let add_messages = Store.Messages.add - - let add_inbox = Store.Inboxes.add - - let level_of_hash = State.level_of_hash - - (** [inbox_of_head node_ctxt store block] returns the latest inbox at the - given [block]. This function always returns [Some inbox] for all levels - at and after the rollup genesis. *) - let inbox_of_head node_ctxt Layer1.{hash = block_hash; level = block_level} = - let open Lwt_result_syntax in - let open Node_context in - let*! possible_inbox = - let open Lwt_option_syntax in - let* l2_block = Store.L2_blocks.find node_ctxt.store block_hash in - Store.Inboxes.find node_ctxt.store l2_block.header.inbox_hash - in - (* Pre-condition: forall l. (l > genesis_level) => inbox[l] <> None. *) - match possible_inbox with - | None -> - (* The inbox exists for each tezos block the rollup should care about. - That is, every block after the origination level. We then join - the bandwagon and build the inbox on top of the protocol's inbox - at the end of the origination level. *) - let genesis_level = Raw_level.to_int32 node_ctxt.genesis_info.level in - if block_level = genesis_level then - let+ inbox = genesis_inbox node_ctxt in - inbox - else if block_level > genesis_level then - (* Invariant broken, the inbox for this level should exist. *) - failwith - "The inbox for block hash %a (level = %ld) is missing." - Block_hash.pp - block_hash - block_level - else - (* The rollup node should not care about levels before the genesis - level. *) - failwith - "Asking for the inbox before the genesis level (i.e. %ld), out of \ - the scope of the rollup's node" - block_level - | Some inbox -> return inbox -end - let get_messages Node_context.{l1_ctxt; _} head = let open Lwt_result_syntax in let* block = Layer1.fetch_tezos_block l1_ctxt head in @@ -168,11 +114,9 @@ let add_messages ~predecessor_timestamp ~predecessor inbox messages = let witness_hash = Sc_rollup.Inbox_merkelized_payload_hashes.hash witness in - let inbox_hash = Sc_rollup.Inbox.hash inbox in return ( messages_history, witness_hash, - inbox_hash, inbox, messages_with_protocol_internal_messages ) @@ -191,7 +135,7 @@ let process_head (node_ctxt : _ Node_context.t) *) let* predecessor = Layer1.get_predecessor node_ctxt.l1_ctxt head in - let* inbox = State.inbox_of_head node_ctxt predecessor in + let* inbox = Node_context.inbox_of_head node_ctxt predecessor in let inbox_metrics = Metrics.Inbox.metrics in Prometheus.Gauge.set inbox_metrics.head_inbox_level @@ Int32.to_float level ; let*? level = Environment.wrap_tzresult @@ Raw_level.of_int32 level in @@ -213,7 +157,6 @@ let process_head (node_ctxt : _ Node_context.t) in let* ( _messages_history, witness_hash, - inbox_hash, inbox, messages_with_protocol_internal_messages ) = add_messages @@ -225,8 +168,8 @@ let process_head (node_ctxt : _ Node_context.t) Metrics.Inbox.Stats.head_messages_list := messages_with_protocol_internal_messages ; let*! () = - State.add_messages - node_ctxt.store + Node_context.save_messages + node_ctxt witness_hash { predecessor = predecessor_hash; @@ -235,7 +178,7 @@ let process_head (node_ctxt : _ Node_context.t) } in let* () = same_inbox_as_layer_1 node_ctxt head_hash inbox in - let*! () = State.add_inbox node_ctxt.store inbox_hash inbox in + let*! inbox_hash = Node_context.save_inbox node_ctxt inbox in return ( inbox_hash, inbox, @@ -243,7 +186,7 @@ let process_head (node_ctxt : _ Node_context.t) messages_with_protocol_internal_messages, ctxt )) else - let* inbox = genesis_inbox node_ctxt in + let* inbox = Node_context.genesis_inbox node_ctxt in return ( Sc_rollup.Inbox.hash inbox, inbox, @@ -251,13 +194,6 @@ let process_head (node_ctxt : _ Node_context.t) [], Context.empty node_ctxt.context ) -let inbox_of_hash node_ctxt hash = - let open Lwt_result_syntax in - let* level = State.level_of_hash node_ctxt hash in - State.inbox_of_head node_ctxt {hash; level} - -let inbox_of_head = State.inbox_of_head - let start () = Inbox_event.starting () let payloads_history_of_messages ~predecessor ~predecessor_timestamp messages = diff --git a/src/proto_alpha/bin_sc_rollup_node/inbox.mli b/src/proto_alpha/bin_sc_rollup_node/inbox.mli index 7323c3b5197693b11dacc4c72778ce29703442d4..f1b33285c0769b4c631d2d2ee2717a2822b9b010 100644 --- a/src/proto_alpha/bin_sc_rollup_node/inbox.mli +++ b/src/proto_alpha/bin_sc_rollup_node/inbox.mli @@ -50,16 +50,6 @@ val process_head : tzresult Lwt.t -(** [inbox_of_hash node_ctxt block_hash] returns the rollup inbox at the end of - the given validation of [block_hash]. NOTE: It requires the L2 block for - [block_hash] to have been saved. *) -val inbox_of_hash : _ Node_context.t -> Block_hash.t -> Inbox.t tzresult Lwt.t - -(** [inbox_of_head node_ctxt block_head] returns the rollup inbox at the end of - the given validation of [block_head]. NOTE: It requires the L2 block for - [block_hash] to have been saved. *) -val inbox_of_head : _ Node_context.t -> Layer1.head -> Inbox.t tzresult Lwt.t - (** [start ()] initializes the inbox to track the messages being published. *) val start : unit -> unit Lwt.t @@ -72,7 +62,6 @@ val add_messages : Inbox_message.t list -> (Inbox_merkelized_payload_hashes.History.t * Inbox_merkelized_payload_hashes.Hash.t - * Inbox.Hash.t * Inbox.t * Inbox_message.t list) tzresult diff --git a/src/proto_alpha/bin_sc_rollup_node/interpreter.ml b/src/proto_alpha/bin_sc_rollup_node/interpreter.ml index 6b51421e12864f70a00ef6056d7154c845097f80..761bfbfea8434ce566af6c0541ecd678c59abe91 100644 --- a/src/proto_alpha/bin_sc_rollup_node/interpreter.ml +++ b/src/proto_alpha/bin_sc_rollup_node/interpreter.ml @@ -199,9 +199,9 @@ module Make (PVM : Pvm.S) : S with module PVM = PVM = struct ctxt Layer1.{hash = block.header.predecessor; level = pred_level} in - let*! inbox = Store.Inboxes.get node_ctxt.store block.header.inbox_hash in - let*! {predecessor; predecessor_timestamp; messages} = - Store.Messages.get node_ctxt.store block.header.inbox_witness + let* inbox = Node_context.get_inbox node_ctxt block.header.inbox_hash in + let* {predecessor; predecessor_timestamp; messages} = + Node_context.get_messages node_ctxt block.header.inbox_witness in let messages = Sc_rollup.Inbox_message.Internal Start_of_level @@ -223,7 +223,7 @@ module Make (PVM : Pvm.S) : S with module PVM = PVM = struct [None].*) let state_of_tick node_ctxt tick level = let open Lwt_result_syntax in - let* closest_block = State.block_before node_ctxt.Node_context.store tick in + let* closest_block = Node_context.block_before node_ctxt tick in match closest_block with | None -> return None | Some event -> diff --git a/src/proto_alpha/bin_sc_rollup_node/layer1.ml b/src/proto_alpha/bin_sc_rollup_node/layer1.ml index b47052ff448da78c91c85397d916e47ae7cd1d0d..e83767528c5768ffa042decc9685030549121ccb 100644 --- a/src/proto_alpha/bin_sc_rollup_node/layer1.ml +++ b/src/proto_alpha/bin_sc_rollup_node/layer1.ml @@ -166,7 +166,7 @@ let get_predecessor state ({hash; _} as head) = | None -> tzfail (Cannot_find_predecessor hash) | Some pred -> return pred -let rec connect ?(count = 0) ~delay cctxt genesis_info store = +let rec connect ?(count = 0) ~delay cctxt genesis_info = let open Lwt_syntax in let* () = if count = 0 then return_unit @@ -197,9 +197,9 @@ let rec connect ?(count = 0) ~delay cctxt genesis_info store = return_ok (heads, stopper) | Error e -> let* () = Event.cannot_connect ~count e in - connect ~delay ~count:(count + 1) cctxt genesis_info store + connect ~delay ~count:(count + 1) cctxt genesis_info -let start configuration (cctxt : Protocol_client_context.full) store = +let start configuration (cctxt : Protocol_client_context.full) = let open Lwt_result_syntax in let*! () = Layer1_event.starting () in let* kind = @@ -217,12 +217,12 @@ let start configuration (cctxt : Protocol_client_context.full) store = configuration.sc_rollup_address in let+ heads, stopper = - connect ~delay:configuration.reconnection_delay cctxt genesis_info store + connect ~delay:configuration.reconnection_delay cctxt genesis_info in ( {cctxt; heads; blocks_cache = Blocks_cache.create 32; stopper; genesis_info}, kind ) -let reconnect configuration l1_ctxt store = +let reconnect configuration l1_ctxt = let open Lwt_result_syntax in let* heads, stopper = connect @@ -230,7 +230,6 @@ let reconnect configuration l1_ctxt store = ~delay:configuration.reconnection_delay l1_ctxt.cctxt l1_ctxt.genesis_info - store in return {l1_ctxt with heads; stopper} diff --git a/src/proto_alpha/bin_sc_rollup_node/layer1.mli b/src/proto_alpha/bin_sc_rollup_node/layer1.mli index ab5c194a6212972e7af2d8e572d702ff889780e5..1127f09957eae353021912c6fb5f49fa81ccd4b4 100644 --- a/src/proto_alpha/bin_sc_rollup_node/layer1.mli +++ b/src/proto_alpha/bin_sc_rollup_node/layer1.mli @@ -47,20 +47,19 @@ type t = private { (* TODO: https://gitlab.com/tezos/tezos/-/issues/3311 Allow to retrieve L1 blocks through Tezos node storage locally. *) -(** [start configuration cctxt store] returns a stream of [chain_event] obtained +(** [start configuration cctxt] returns a stream of [chain_event] obtained from the monitoring of the Tezos node set up by the client [cctxt]. The layer 1 state is stored in the data directory declared in [configuration]. *) val start : Configuration.t -> Protocol_client_context.full -> - _ Store.t -> (t * Protocol.Alpha_context.Sc_rollup.Kind.t) tzresult Lwt.t -(** [reconnect cfg l1_ctxt store] reconnects (and retries with delay) to the +(** [reconnect cfg l1_ctxt] reconnects (and retries with delay) to the Tezos node. The delay for each reconnection is increased with a randomized exponential backoff (capped to 1.5h) . *) -val reconnect : Configuration.t -> t -> _ Store.t -> t tzresult Lwt.t +val reconnect : Configuration.t -> t -> t tzresult Lwt.t (** [get_predecessor_opt state head] returns the predecessor of block [head], when [head] is not the genesis block. *) diff --git a/src/proto_alpha/bin_sc_rollup_node/node_context.ml b/src/proto_alpha/bin_sc_rollup_node/node_context.ml index 70d8d58886bba1da308e400703ca2992676c7df9..c7d2d10a0facb1d5dfe36853b1d36d9c59d9c3ca 100644 --- a/src/proto_alpha/bin_sc_rollup_node/node_context.ml +++ b/src/proto_alpha/bin_sc_rollup_node/node_context.ml @@ -28,6 +28,8 @@ open Alpha_context type lcc = {commitment : Sc_rollup.Commitment.Hash.t; level : Raw_level.t} +type 'a store = 'a Store.t + type 'a t = { cctxt : Protocol_client_context.full; dal_cctxt : Dal_node_client.cctxt; @@ -42,7 +44,7 @@ type 'a t = { fee_parameters : Configuration.fee_parameters; protocol_constants : Constants.t; loser_mode : Loser_mode.t; - store : 'a Store.t; + store : 'a store; context : 'a Context.index; mutable lcc : lcc; mutable lpc : Sc_rollup.Commitment.t option; @@ -109,9 +111,21 @@ let get_last_published_commitment (cctxt : Protocol_client_context.full) | Ok None -> return_none | Ok (Some (_staked_hash, staked_commitment)) -> return_some staked_commitment -let init (cctxt : Protocol_client_context.full) dal_cctxt ~data_dir l1_ctxt - rollup_address kind operators fee_parameters ~loser_mode store context = +let init (cctxt : Protocol_client_context.full) dal_cctxt ~data_dir mode + Configuration.( + { + sc_rollup_address = rollup_address; + sc_rollup_node_operators = operators; + fee_parameters; + loser_mode; + _; + } as configuration) = let open Lwt_result_syntax in + let*! store = Store.load mode Configuration.(default_storage_dir data_dir) in + let*! context = + Context.load mode (Configuration.default_context_dir data_dir) + in + let* l1_ctxt, kind = Layer1.start configuration 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 @@ -141,6 +155,17 @@ let init (cctxt : Protocol_client_context.full) dal_cctxt ~data_dir l1_ctxt context; } +let close {cctxt; store; context; l1_ctxt; _} = + let open Lwt_syntax in + let message = cctxt#message in + let* () = message "Shutting down L1@." in + let* () = Layer1.shutdown l1_ctxt in + let* () = message "Closing context@." in + let* () = Context.close context in + let* () = message "Closing store@." in + let* () = Store.close store in + return_unit + let checkout_context node_ctxt block_hash = let open Lwt_result_syntax in let*! l2_block = Store.L2_blocks.find node_ctxt.store block_hash in @@ -175,6 +200,108 @@ let readonly (node_ctxt : _ t) = type 'a delayed_write = ('a, rw) Delayed_write_monad.t +(** Abstraction over store *) + +let trace_lwt_with x = + Format.kasprintf + (fun s p -> trace (Exn (Failure s)) @@ protect @@ fun () -> p >>= return) + x + +let trace_lwt_result_with x = + Format.kasprintf + (fun s p -> trace (Exn (Failure s)) @@ protect @@ fun () -> p) + x + +let hash_of_level_opt {store; cctxt; _} level = + let open Lwt_syntax in + let* hash = Store.Levels_to_hashes.find store level in + match hash with + | Some hash -> return_some hash + | None -> + let+ hash = + Tezos_shell_services.Shell_services.Blocks.hash + cctxt + ~chain:cctxt#chain + ~block:(`Level level) + () + in + Result.to_option hash + +let hash_of_level node_ctxt level = + let open Lwt_result_syntax in + let*! hash = hash_of_level_opt node_ctxt level in + match hash with + | Some h -> return h + | None -> failwith "Cannot retrieve hash of level %ld" level + +let level_of_hash {l1_ctxt; store; _} hash = + let open Lwt_result_syntax in + let*! block = Store.L2_blocks.find store hash in + match block with + | Some {header = {level; _}; _} -> return (Raw_level.to_int32 level) + | None -> + let+ {level; _} = Layer1.fetch_tezos_shell_header l1_ctxt hash in + level + +let save_level {store; _} Layer1.{hash; level} = + Store.Levels_to_hashes.add store level hash + +let save_l2_head {store; _} (head : Sc_rollup_block.t) = + let open Lwt_syntax in + let* () = Store.L2_blocks.add store head.header.block_hash head in + Store.L2_head.set store head + +let is_processed {store; _} head = Store.L2_blocks.mem store head + +let last_processed_head_opt {store; _} = Store.L2_head.find store + +let mark_finalized_head {store; _} head_hash = + let open Lwt_syntax in + let* block = Store.L2_blocks.find store head_hash in + match block with + | None -> return_unit + | Some block -> Store.Last_finalized_head.set store block + +let get_finalized_head_opt {store; _} = Store.Last_finalized_head.find store + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/4532 + Make this logarithmic, by storing pointers to muliple predecessor and + by dichotomy. *) +let block_before {store; _} tick = + let open Lwt_result_syntax in + let*! head = Store.L2_head.find store in + match head with + | None -> return_none + | Some head -> + let rec search block_hash = + let*! block = Store.L2_blocks.find store block_hash in + match block with + | None -> failwith "Missing block %a" Block_hash.pp block_hash + | Some block -> + if Sc_rollup.Tick.(block.initial_tick <= tick) then + return_some block + else search block.header.predecessor + in + search head.header.block_hash + +let get_l2_block {store; _} block_hash = + trace_lwt_with "Could not retrieve L2 block for %a" Block_hash.pp block_hash + @@ Store.L2_blocks.get store block_hash + +let find_l2_block {store; _} block_hash = Store.L2_blocks.find store block_hash + +let get_l2_block_by_level node_ctxt level = + let open Lwt_result_syntax in + trace_lwt_result_with "Could not retrieve L2 block at level %ld" level + @@ let* block_hash = hash_of_level node_ctxt level in + let*! block = Store.L2_blocks.get node_ctxt.store block_hash in + return block + +let find_l2_block_by_level node_ctxt level = + let open Lwt_option_syntax in + let* block_hash = hash_of_level_opt node_ctxt level in + Store.L2_blocks.find node_ctxt.store block_hash + let get_full_l2_block {store; _} block_hash = let open Lwt_syntax in let* block = Store.L2_blocks.get store block_hash in @@ -184,3 +311,195 @@ let get_full_l2_block {store; _} block_hash = Option.map_s (Store.Commitments.get store) block.header.commitment_hash in return {block with content = {Sc_rollup_block.inbox; messages; commitment}} + +let get_commitment {store; _} commitment_hash = + trace_lwt_with + "Could not retrieve commitment %a" + Sc_rollup.Commitment.Hash.pp + commitment_hash + @@ Store.Commitments.get store commitment_hash + +let find_commitment {store; _} hash = Store.Commitments.find store hash + +let commitment_exists {store; _} hash = Store.Commitments.mem store hash + +let save_commitment {store; _} commitment = + let open Lwt_syntax in + let hash = Sc_rollup.Commitment.hash_uncarbonated commitment in + let+ () = Store.Commitments.add store hash commitment in + hash + +let commitment_published_at_level {store; _} commitment = + Store.Commitments_published_at_level.find store commitment + +let set_commitment_published_at_level {store; _} = + Store.Commitments_published_at_level.add store + +type commitment_source = Anyone | Us + +let commitment_was_published {store; _} ~source commitment_hash = + let open Lwt_syntax in + match source with + | Anyone -> Store.Commitments_published_at_level.mem store commitment_hash + | Us -> ( + let+ info = + Store.Commitments_published_at_level.find store commitment_hash + in + match info with + | Some {published_at_level = Some _; _} -> true + | _ -> false) + +let get_inbox {store; _} inbox_hash = + trace_lwt_with + "Could not retrieve inbox %a" + Sc_rollup.Inbox.Hash.pp + inbox_hash + @@ Store.Inboxes.get store inbox_hash + +let find_inbox {store; _} hash = Store.Inboxes.find store hash + +let save_inbox {store; _} inbox = + let open Lwt_syntax in + let hash = Sc_rollup.Inbox.hash inbox in + let+ () = Store.Inboxes.add store hash inbox in + hash + +let find_inbox_by_block_hash {store; _} block_hash = + let open Lwt_option_syntax in + let* l2_block = Store.L2_blocks.find store block_hash in + Store.Inboxes.find store l2_block.header.inbox_hash + +let genesis_inbox node_ctxt = + let genesis_level = Raw_level.to_int32 node_ctxt.genesis_info.level in + Plugin.RPC.Sc_rollup.inbox + node_ctxt.cctxt + (node_ctxt.cctxt#chain, `Level genesis_level) + +let inbox_of_head node_ctxt Layer1.{hash = block_hash; level = block_level} = + let open Lwt_result_syntax in + let*! possible_inbox = find_inbox_by_block_hash node_ctxt block_hash in + (* Pre-condition: forall l. (l > genesis_level) => inbox[l] <> None. *) + match possible_inbox with + | None -> + (* The inbox exists for each tezos block the rollup should care about. + That is, every block after the origination level. We then join + the bandwagon and build the inbox on top of the protocol's inbox + at the end of the origination level. *) + let genesis_level = Raw_level.to_int32 node_ctxt.genesis_info.level in + if block_level = genesis_level then genesis_inbox node_ctxt + else if block_level > genesis_level then + (* Invariant broken, the inbox for this level should exist. *) + failwith + "The inbox for block hash %a (level = %ld) is missing." + Block_hash.pp + block_hash + block_level + else + (* The rollup node should not care about levels before the genesis + level. *) + failwith + "Asking for the inbox before the genesis level (i.e. %ld), out of \ + the scope of the rollup's node" + block_level + | Some inbox -> return inbox + +let get_inbox_by_block_hash node_ctxt hash = + let open Lwt_result_syntax in + let* level = level_of_hash node_ctxt hash in + inbox_of_head node_ctxt {hash; level} + +let get_messages {store; _} messages_hash = + trace_lwt_with + "Could not retrieve messages with payloads merkelized hash %a" + Sc_rollup.Inbox_merkelized_payload_hashes.Hash.pp + messages_hash + @@ Store.Messages.get store messages_hash + +let find_messages {store; _} hash = Store.Messages.find store hash + +let save_messages {store; _} = Store.Messages.add store + +let get_slot_header {store; _} ~published_in_block_hash slot_index = + trace_lwt_with + "Could not retrieve slot header for slot index %a published in block %a" + Dal.Slot_index.pp + slot_index + Block_hash.pp + published_in_block_hash + @@ Store.Dal_slots_headers.get + store + ~primary_key:published_in_block_hash + ~secondary_key:slot_index + +let get_all_slot_headers {store; _} ~published_in_block_hash = + Store.Dal_slots_headers.list_values store ~primary_key:published_in_block_hash + +let get_slot_indexes {store; _} ~published_in_block_hash = + Store.Dal_slots_headers.list_secondary_keys + store + ~primary_key:published_in_block_hash + +let save_slot_header {store; _} ~published_in_block_hash + (slot_header : Dal.Slot.Header.t) = + Store.Dal_slots_headers.add + store + ~primary_key:published_in_block_hash + ~secondary_key:slot_header.id.index + slot_header + +let processed_slot {store; _} ~confirmed_in_block_hash slot_index = + Store.Dal_processed_slots.find + store + ~primary_key:confirmed_in_block_hash + ~secondary_key:slot_index + +let list_slot_pages {store; _} ~confirmed_in_block_hash = + Store.Dal_slot_pages.list_secondary_keys_with_values + store + ~primary_key:confirmed_in_block_hash + +let find_slot_page {store; _} ~confirmed_in_block_hash ~slot_index ~page_index = + Store.Dal_slot_pages.find + store + ~primary_key:confirmed_in_block_hash + ~secondary_key:(slot_index, page_index) + +let save_unconfirmed_slot {store; _} current_block_hash slot_index = + (* No page is actually saved *) + Store.Dal_processed_slots.add + store + ~primary_key:current_block_hash + ~secondary_key:slot_index + `Unconfirmed + +let save_confirmed_slot {store; _} current_block_hash slot_index pages = + (* Adding multiple entries with the same primary key amounts to updating the + contents of an in-memory map, hence pages must be added sequentially. *) + let open Lwt_syntax in + let* () = + List.iteri_s + (fun page_number page -> + Store.Dal_slot_pages.add + store + ~primary_key:current_block_hash + ~secondary_key:(slot_index, page_number) + page) + pages + in + Store.Dal_processed_slots.add + store + ~primary_key:current_block_hash + ~secondary_key:slot_index + `Confirmed + +let find_confirmed_slots_history {store; _} = + Store.Dal_confirmed_slots_history.find store + +let save_confirmed_slots_history {store; _} = + Store.Dal_confirmed_slots_history.add store + +let find_confirmed_slots_histories {store; _} = + Store.Dal_confirmed_slots_histories.find store + +let save_confirmed_slots_histories {store; _} = + Store.Dal_confirmed_slots_histories.add store diff --git a/src/proto_alpha/bin_sc_rollup_node/node_context.mli b/src/proto_alpha/bin_sc_rollup_node/node_context.mli index bed9f201fb975ade46e88334bd69b0ec97686847..4b255f17e7ada15a6815077a84b7d11642abcc35 100644 --- a/src/proto_alpha/bin_sc_rollup_node/node_context.mli +++ b/src/proto_alpha/bin_sc_rollup_node/node_context.mli @@ -30,6 +30,9 @@ open Alpha_context type lcc = {commitment : Sc_rollup.Commitment.Hash.t; level : Raw_level.t} +(** Abstract type for store to force access through this module. *) +type 'a store constraint 'a = [< `Read | `Write > `Read] + type 'a t = { cctxt : Protocol_client_context.full; (** Client context used by the rollup node. *) @@ -56,7 +59,7 @@ type 'a t = { loser_mode : Loser_mode.t; (** If different from [Loser_mode.no_failures], the rollup node issues wrong commitments (for tests). *) - store : 'a Store.t; (** The store for the persistent storage. *) + store : 'a store; (** The store for the persistent storage. *) context : 'a Context.index; (** The persistent context for the rollup node. *) mutable lcc : lcc; (** Last cemented commitment and its level. *) @@ -88,25 +91,21 @@ val is_operator : _ t -> Signature.Public_key_hash.t -> bool *) val get_fee_parameter : _ t -> Configuration.purpose -> Injection.fee_parameter -(** [init cctxt dal_cctxt ~data_dir l1_ctxt sc_rollup genesis_info kind operators fees - ~loser_mode store context] initialises 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 dal_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. *) val init : Protocol_client_context.full -> Dal_node_client.cctxt -> data_dir:string -> - Layer1.t -> - Sc_rollup.t -> - Protocol.Alpha_context.Sc_rollup.Kind.t -> - Configuration.operators -> - Configuration.fee_parameters -> - loser_mode:Loser_mode.t -> - 'a Store.t -> - 'a Context.index -> + 'a Store_sigs.mode -> + Configuration.t -> 'a t tzresult Lwt.t +(** Closes the store, context and Layer 1 monitor. *) +val close : _ t -> unit Lwt.t + (** [checkout_context node_ctxt block_hash] returns the context at block [block_hash]. *) val checkout_context : 'a t -> Block_hash.t -> 'a Context.t tzresult Lwt.t @@ -125,7 +124,246 @@ val readonly : _ t -> ro (** Monad for values with delayed write effects in the node context. *) type 'a delayed_write = ('a, rw) Delayed_write_monad.t +(** {2 Abstraction over store} *) + +(** {3 Layer 2 blocks} *) + +(** [is_processed store hash] returns [true] if the block with [hash] has + already been processed by the daemon. *) +val is_processed : _ t -> Block_hash.t -> bool Lwt.t + +(** [get_l2_block t hash] returns the Layer 2 block known by the rollup node for + Layer 1 block [hash]. *) +val get_l2_block : _ t -> Block_hash.t -> Sc_rollup_block.t tzresult Lwt.t + +(** Same as {!get_l2_block} but returns [None] when the Layer 2 block is not + available. *) +val find_l2_block : _ t -> Block_hash.t -> Sc_rollup_block.t option Lwt.t + +(** Same as {!get_l2_block} but retrieves the Layer 2 block by its level. *) +val get_l2_block_by_level : _ t -> int32 -> Sc_rollup_block.t tzresult Lwt.t + +(** Same as {!get_l2_block_by_level} but returns [None] when the Layer 2 block + is not available. *) +val find_l2_block_by_level : _ t -> int32 -> Sc_rollup_block.t option Lwt.t + (** [get_full_l2_block node_ctxt hash] returns the full L2 block for L1 block hash [hash]. The result contains the L2 block and its content (inbox, messages, commitment). *) val get_full_l2_block : _ t -> Block_hash.t -> Sc_rollup_block.full Lwt.t + +(** [save_level t head] registers the correspondences [head.level |-> + head.hash] in the store. *) +val save_level : rw -> Layer1.head -> unit Lwt.t + +(** [save_l2_head t l2_block] remembers that the [l2_block.head] is + processed. The system should not have to come back to it. *) +val save_l2_head : rw -> Sc_rollup_block.t -> unit Lwt.t + +(** [last_processed_head_opt store] returns the last processed head if it + exists. *) +val last_processed_head_opt : _ t -> Sc_rollup_block.t option Lwt.t + +(** [mark_finalized_head store head] remembers that the [head] is finalized. By + construction, every block whose level is smaller than [head]'s is also + finalized. *) +val mark_finalized_head : rw -> Block_hash.t -> unit Lwt.t + +(** [last_finalized_head_opt store] returns the last finalized head if it exists. *) +val get_finalized_head_opt : _ t -> Sc_rollup_block.t option Lwt.t + +(** [hash_of_level node_ctxt level] returns the current block hash for a given + [level]. *) +val hash_of_level : _ t -> int32 -> Block_hash.t tzresult Lwt.t + +(** [hash_of_level_opt] is like {!hash_of_level} but returns [None] if the + [level] is not known. *) +val hash_of_level_opt : _ t -> int32 -> Block_hash.t option Lwt.t + +(** [level_of_hash node_ctxt hash] returns the level for Tezos block hash [hash] + if it is known by the Tezos Layer 1 node. *) +val level_of_hash : _ t -> Block_hash.t -> int32 tzresult Lwt.t + +(** [block_before store tick] returns the last layer 2 block whose initial tick + is before [tick]. *) +val block_before : + _ t -> Sc_rollup.Tick.t -> Sc_rollup_block.t option tzresult Lwt.t + +(** {3 Commitments} *) + +(** [get_commitment t hash] returns the commitment with [hash] stored by the + rollup node. *) +val get_commitment : + _ t -> Sc_rollup.Commitment.Hash.t -> Sc_rollup.Commitment.t tzresult Lwt.t + +(** Same as {!get_commitment} but returns [None] if this commitment hash is not + known by the rollup node. *) +val find_commitment : + _ t -> Sc_rollup.Commitment.Hash.t -> Sc_rollup.Commitment.t option Lwt.t + +(** [commitment_exists t hash] returns [true] if the commitment with [hash] is + known (i.e. stored) by the rollup node. *) +val commitment_exists : _ t -> Sc_rollup.Commitment.Hash.t -> bool Lwt.t + +(** [save_commitment t commitment] saves a commitment in the store an returns is + hash. *) +val save_commitment : + rw -> Sc_rollup.Commitment.t -> Sc_rollup.Commitment.Hash.t Lwt.t + +(** [commitment_published_at_level t hash] returns the levels at which the + commitment was first published and the one at which it was included by in a + Layer 1 block. It returns [None] if the commitment is not known by the + rollup node or if it was never published by the rollup node (and included on + L1). *) +val commitment_published_at_level : + _ t -> + Sc_rollup.Commitment.Hash.t -> + Store.Commitments_published_at_level.element option Lwt.t + +(** [save_commitment_published_at_level t hash levels] saves the + publication/inclusion information for a commitment with [hash]. *) +val set_commitment_published_at_level : + rw -> + Sc_rollup.Commitment.Hash.t -> + Store.Commitments_published_at_level.element -> + unit Lwt.t + +type commitment_source = Anyone | Us + +(** [commitment_was_published t hash] returns [true] if the commitment is known + as being already published on L1. The [source] indicates if we want to know + the publication status for commitments we published ourselves [`Us] or that + [`Anyone] published. *) +val commitment_was_published : + _ t -> source:commitment_source -> Sc_rollup.Commitment.Hash.t -> bool Lwt.t + +(** {3 Inboxes} *) + +(** [get_inbox t inbox_hash] retrieves the inbox whose hash is [inbox_hash] from + the rollup node's storage. *) +val get_inbox : + _ t -> Sc_rollup.Inbox.Hash.t -> Sc_rollup.Inbox.t tzresult Lwt.t + +(** Same as {!get_inbox} but returns [None] if this inbox is not known. *) +val find_inbox : _ t -> Sc_rollup.Inbox.Hash.t -> Sc_rollup.Inbox.t option Lwt.t + +(** [save_inbox t inbox] remembers the [inbox] in the storage. It is associated + to its hash which is returned. *) +val save_inbox : rw -> Sc_rollup.Inbox.t -> Sc_rollup.Inbox.Hash.t Lwt.t + +(** [inbox_of_head node_ctxt block] returns the latest inbox at the given + [block]. This function always returns [inbox] for all levels at and + after the rollup genesis. NOTE: It requires the L2 block for [block.hash] to + have been saved. *) +val inbox_of_head : _ t -> Layer1.head -> Sc_rollup.Inbox.t tzresult Lwt.t + +(** Same as {!get_inbox} but uses the Layer 1 block hash for this inbox instead. *) +val get_inbox_by_block_hash : + _ t -> Block_hash.t -> Sc_rollup.Inbox.t tzresult Lwt.t + +(** [genesis_inbox t] is the genesis inbox for the rollup [t.sc_rollup_address]. *) +val genesis_inbox : _ t -> Sc_rollup.Inbox.t tzresult Lwt.t + +(** [get_messages t witness_hash] retrieves the messages for the merkelized + payloads hash [witness_hash] stored by the rollup node. *) +val get_messages : + _ t -> + Sc_rollup.Inbox_merkelized_payload_hashes.Hash.t -> + Store.Messages.info tzresult Lwt.t + +(** Same as {!get_messages} but returns [None] if the payloads hash is not known. *) +val find_messages : + _ t -> + Sc_rollup.Inbox_merkelized_payload_hashes.Hash.t -> + Store.Messages.info option Lwt.t + +(** [save_messages t payloads_hash messages] associates the list of [messages] + to the [payloads_hash]. The payload hash must be computed by calling, + e.g. {!Sc_rollup.Inbox.add_all_messages}. *) +val save_messages : + rw -> + Sc_rollup.Inbox_merkelized_payload_hashes.Hash.t -> + Store.Messages.info -> + unit Lwt.t + +(** {3 DAL} *) + +(** [get_slot_header t ~published_in_block_hash slot_index] returns the slot + header for the [slot_index] that was published in the provided block hash on + Layer 1. *) +val get_slot_header : + _ t -> + published_in_block_hash:Block_hash.t -> + Dal.Slot_index.t -> + Dal.Slot.Header.t tzresult Lwt.t + +(** [get_all_slot_headers t ~published_in_block_hash] returns the slot headers + for all the slots that were published in the provided block hash on Layer + 1. *) +val get_all_slot_headers : + _ t -> published_in_block_hash:Block_hash.t -> Dal.Slot.Header.t list Lwt.t + +(** [get_slot_indexes t ~published_in_block_hash] returns the slot indexes whose + headers were published in the provided block hash on Layer 1. *) +val get_slot_indexes : + _ t -> published_in_block_hash:Block_hash.t -> Dal.Slot_index.t list Lwt.t + +(** [save_slot_header t ~published_in_block_hash header] saves the [header] as + being published for its index in the provided block hash on Layer 1. *) +val save_slot_header : + rw -> published_in_block_hash:Block_hash.t -> Dal.Slot.Header.t -> unit Lwt.t + +(** [processed_slot t ~confirmed_in_block_hash index] returns [None] if the slot + pages was never processed nor downloaded, [Some `Unconfirmed] if the slot + was not confirmed and [Some `Confirmed] if the slot is confirmed and the + associated pages are available. *) +val processed_slot : + _ t -> + confirmed_in_block_hash:Block_hash.t -> + Dal.Slot_index.t -> + [`Unconfirmed | `Confirmed] option Lwt.t + +(** [list_slot_pages t ~confirmed_in_block_hash] lists all slots and their pages + that were confirmed and stored by the rollup node for + [confirmed_in_block_hash]. *) +val list_slot_pages : + _ t -> + confirmed_in_block_hash:Block_hash.t -> + ((Dal.Slot_index.t * int) * bytes) list Lwt.t + +(** [find_slot_page t ~confirmed_in_block_hash slot_index page_index] retrieves + a pages (with index [page_index]) for a slot [slot_index] that was confirmed + in the provided block hash. It returns [None] if the slot was not processed + or if the page index is out of bounds. *) +val find_slot_page : + _ t -> + confirmed_in_block_hash:Block_hash.t -> + slot_index:Dal.Slot_index.t -> + page_index:int -> + bytes option Lwt.t + +(** [save_unconfirmed_slot node_ctxt hash slot_index] saves in [node_ctxt.store] + that [slot_index] is unconfirmed in the block with hash in [node_ctxt.store]. +*) +val save_unconfirmed_slot : rw -> Block_hash.t -> Dal.Slot_index.t -> unit Lwt.t + +(** [save_confirmed_slot node_ctxt hash slot_index] saves in [node_ctxt.store] + that [slot_index] is confirmed in the block with hashin [node_ctxt.store]. + The contents of the slot are set to [pages] in [node_ctxt.store]. *) +val save_confirmed_slot : + rw -> Block_hash.t -> Dal.Slot_index.t -> bytes list -> unit Lwt.t + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/4636 + Missing docstrings. *) + +val find_confirmed_slots_history : + _ t -> Block_hash.t -> Dal.Slots_history.t option Lwt.t + +val save_confirmed_slots_history : + rw -> Block_hash.t -> Dal.Slots_history.t -> unit Lwt.t + +val find_confirmed_slots_histories : + _ t -> Block_hash.t -> Dal.Slots_history.History_cache.t option Lwt.t + +val save_confirmed_slots_histories : + rw -> Block_hash.t -> Dal.Slots_history.History_cache.t -> unit Lwt.t diff --git a/src/proto_alpha/bin_sc_rollup_node/outbox.ml b/src/proto_alpha/bin_sc_rollup_node/outbox.ml index 6b1c60ff71fc468e9bb037d375595501a7377726..66a5a55a2425fca6949e6c27e1926e2c91866787 100644 --- a/src/proto_alpha/bin_sc_rollup_node/outbox.ml +++ b/src/proto_alpha/bin_sc_rollup_node/outbox.ml @@ -30,7 +30,9 @@ module Make (PVM : Pvm.S) = struct let get_state_of_lcc node_ctxt = let open Lwt_result_syntax in let* block_hash = - State.hash_of_level node_ctxt (Raw_level.to_int32 node_ctxt.lcc.level) + Node_context.hash_of_level + node_ctxt + (Raw_level.to_int32 node_ctxt.lcc.level) in let* ctxt = Node_context.checkout_context node_ctxt block_hash in let*! state = PVM.State.find ctxt in diff --git a/src/proto_alpha/bin_sc_rollup_node/refutation_game.ml b/src/proto_alpha/bin_sc_rollup_node/refutation_game.ml index e97eb8c2975ec36286d0ca82aab7b3b4c968e09b..cafd561296a17e8aa3f70fffac780347be3c9d72 100644 --- a/src/proto_alpha/bin_sc_rollup_node/refutation_game.ml +++ b/src/proto_alpha/bin_sc_rollup_node/refutation_game.ml @@ -165,11 +165,13 @@ module Make (Interpreter : Interpreter.S) : let snapshot_level_int32 = Int32.pred Raw_level.(to_int32 game.start_level) in - let* snapshot_hash = State.hash_of_level node_ctxt snapshot_level_int32 in + let* snapshot_hash = + Node_context.hash_of_level node_ctxt snapshot_level_int32 + in let snapshot_head = Layer1.{hash = snapshot_hash; level = snapshot_level_int32} in - let* snapshot_inbox = Inbox.inbox_of_head node_ctxt snapshot_head in + let* snapshot_inbox = Node_context.inbox_of_head node_ctxt snapshot_head in let* snapshot_ctxt = Node_context.checkout_context node_ctxt snapshot_hash in @@ -223,19 +225,25 @@ module Make (Interpreter : Interpreter.S) : let get_history inbox_hash = let open Lwt_option_syntax in - let+ inbox = Store.Inboxes.find node_ctxt.store inbox_hash in + let+ inbox = Node_context.find_inbox node_ctxt inbox_hash in Sc_rollup.Inbox.take_snapshot inbox let get_payloads_history witness = - let open Lwt_syntax in - let+ {predecessor; predecessor_timestamp; messages} = - Store.Messages.get node_ctxt.store witness + Lwt.map + (WithExceptions.Result.to_exn_f + ~error:(Format.kasprintf Stdlib.failwith "%a" pp_print_trace)) + @@ + let open Lwt_result_syntax in + let* {predecessor; predecessor_timestamp; messages} = + Node_context.get_messages node_ctxt witness + in + let*? hist = + Inbox.payloads_history_of_messages + ~predecessor + ~predecessor_timestamp + messages in - Inbox.payloads_history_of_messages - ~predecessor - ~predecessor_timestamp - messages - |> WithExceptions.Result.get_ok ~loc:__LOC__ + return hist end module Dal_with_history = struct diff --git a/src/proto_alpha/bin_sc_rollup_node/state.ml b/src/proto_alpha/bin_sc_rollup_node/state.ml deleted file mode 100644 index dcd13e4db0ac97db361b0594860dc33bde3a024e..0000000000000000000000000000000000000000 --- a/src/proto_alpha/bin_sc_rollup_node/state.ml +++ /dev/null @@ -1,150 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* 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 -open Alpha_context -module Raw_store = Store - -module Store = struct - (* TODO: https://gitlab.com/tezos/tezos/-/issues/4392 - Use file. *) - module L2_head = - Store.Make_mutable_value - (struct - let path = ["l2_head"] - end) - (struct - type value = Sc_rollup_block.t - - let name = "l2_block" - - let encoding = Sc_rollup_block.encoding - end) - - (* TODO: https://gitlab.com/tezos/tezos/-/issues/4392 - Use file. *) - module Last_finalized_head = - Store.Make_mutable_value - (struct - let path = ["finalized_head"] - end) - (struct - type value = Sc_rollup_block.t - - let name = "l2_block" - - let encoding = Sc_rollup_block.encoding - end) - - (** Table from L1 levels to blocks hashes. *) - module Levels_to_hashes = - Store.Make_updatable_map - (struct - let path = ["tezos"; "levels"] - end) - (struct - type key = int32 - - let to_path_representation = Int32.to_string - end) - (struct - type value = Block_hash.t - - let name = "block_hash" - - let encoding = Block_hash.encoding - end) -end - -let hash_of_level_opt Node_context.{store; cctxt; _} level = - let open Lwt_syntax in - let* hash = Store.Levels_to_hashes.find store level in - match hash with - | Some hash -> return_some hash - | None -> - let+ hash = - Tezos_shell_services.Shell_services.Blocks.hash - cctxt - ~chain:cctxt#chain - ~block:(`Level level) - () - in - Result.to_option hash - -let hash_of_level node_ctxt level = - let open Lwt_result_syntax in - let*! hash = hash_of_level_opt node_ctxt level in - match hash with - | Some h -> return h - | None -> failwith "Cannot retrieve hash of level %ld" level - -let level_of_hash {Node_context.l1_ctxt; store; _} hash = - let open Lwt_result_syntax in - let*! block = Raw_store.L2_blocks.find store hash in - match block with - | Some {header = {level; _}; _} -> return (Raw_level.to_int32 level) - | None -> - let+ {level; _} = Layer1.fetch_tezos_shell_header l1_ctxt hash in - level - -let save_level store Layer1.{hash; level} = - Store.Levels_to_hashes.add store level hash - -let save_l2_block store (head : Sc_rollup_block.t) = - let open Lwt_syntax in - let* () = Raw_store.L2_blocks.add store head.header.block_hash head in - Store.L2_head.set store head - -let is_processed store head = Raw_store.L2_blocks.mem store head - -let last_processed_head_opt store = Store.L2_head.find store - -let mark_finalized_head store head_hash = - let open Lwt_syntax in - let* block = Raw_store.L2_blocks.find store head_hash in - match block with - | None -> return_unit - | Some block -> Store.Last_finalized_head.set store block - -let get_finalized_head_opt store = Store.Last_finalized_head.find store - -(* TODO: https://gitlab.com/tezos/tezos/-/issues/4532 - Make this logarithmic, by storing pointers to muliple predecessor and - by dichotomy. *) -let block_before store tick = - let open Lwt_result_syntax in - let*! head = Store.L2_head.find store in - match head with - | None -> return_none - | Some head -> - let rec search block_hash = - let*! block = Raw_store.L2_blocks.find store block_hash in - match block with - | None -> failwith "Missing block %a" Block_hash.pp block_hash - | Some block -> - if Sc_rollup.Tick.(block.initial_tick <= tick) then - return_some block - else search block.header.predecessor - in - search head.header.block_hash diff --git a/src/proto_alpha/bin_sc_rollup_node/state.mli b/src/proto_alpha/bin_sc_rollup_node/state.mli deleted file mode 100644 index c67158f14744b84f3860cab56e34f56fe557e482..0000000000000000000000000000000000000000 --- a/src/proto_alpha/bin_sc_rollup_node/state.mli +++ /dev/null @@ -1,69 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* 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.Alpha_context - -(** [is_processed store hash] returns [true] if the block with [hash] has - already been processed by the daemon. *) -val is_processed : _ Store.t -> Block_hash.t -> bool Lwt.t - -(** [mark_processed_head store head] remembers that the [head] is processed. The - system should not have to come back to it. *) -val save_l2_block : Store.rw -> Sc_rollup_block.t -> unit Lwt.t - -(** [last_processed_head_opt store] returns the last processed head if it - exists. *) -val last_processed_head_opt : _ Store.t -> Sc_rollup_block.t option Lwt.t - -(** [mark_finalized_head store head] remembers that the [head] is finalized. By - construction, every block whose level is smaller than [head]'s is also - finalized. *) -val mark_finalized_head : Store.rw -> Block_hash.t -> unit Lwt.t - -(** [last_finalized_head_opt store] returns the last finalized head if it exists. *) -val get_finalized_head_opt : _ Store.t -> Sc_rollup_block.t option Lwt.t - -(** [hash_of_level node_ctxt level] returns the current block hash for a given - [level]. *) -val hash_of_level : _ Node_context.t -> int32 -> Block_hash.t tzresult Lwt.t - -(** [hash_of_level_opt] is like {!hash_of_level} but returns [None] if the - [level] is not known. *) -val hash_of_level_opt : _ Node_context.t -> int32 -> Block_hash.t option Lwt.t - -(** [save_level store head] registers the correspondences [head.level |-> - head.hash] in the store. *) -val save_level : Store.rw -> Layer1.head -> unit Lwt.t - -(** [level_of_hash node_ctxt hash] returns the level for Tezos block hash [hash] - if it is known by the Tezos Layer 1 node. *) -val level_of_hash : _ Node_context.t -> Block_hash.t -> int32 tzresult Lwt.t - -(** [block_before store tick] returns the last layer 2 block whose initial tick - is before [tick]. *) -val block_before : - [> `Read] Store.store -> - Sc_rollup.Tick.t -> - Sc_rollup_block.t option tzresult Lwt.t diff --git a/src/proto_alpha/bin_sc_rollup_node/store.ml b/src/proto_alpha/bin_sc_rollup_node/store.ml index 84de5a5e8635e812968da360482f80b58f222714..5c22868889fb6f85aa755626b191475fe6494249 100644 --- a/src/proto_alpha/bin_sc_rollup_node/store.ml +++ b/src/proto_alpha/bin_sc_rollup_node/store.ml @@ -148,21 +148,6 @@ module Commitments = let encoding = Sc_rollup.Commitment.encoding end) -(* TODO: https://gitlab.com/tezos/tezos/-/issues/4392 - Use file. *) -module Last_stored_commitment_level = - Make_mutable_value - (struct - let path = ["commitments"; "last_stored_level"] - end) - (struct - type value = Raw_level.t - - let name = "raw_level" - - let encoding = Raw_level.encoding - end) - module Commitments_published_at_level = struct type element = { first_published_at_level : Raw_level.t; @@ -199,6 +184,55 @@ module Commitments_published_at_level = struct end) end +(* TODO: https://gitlab.com/tezos/tezos/-/issues/4392 + Use file. *) +module L2_head = + Make_mutable_value + (struct + let path = ["l2_head"] + end) + (struct + type value = Sc_rollup_block.t + + let name = "l2_block" + + let encoding = Sc_rollup_block.encoding + end) + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/4392 + Use file. *) +module Last_finalized_head = + Make_mutable_value + (struct + let path = ["finalized_head"] + end) + (struct + type value = Sc_rollup_block.t + + let name = "l2_block" + + let encoding = Sc_rollup_block.encoding + end) + +(** Table from L1 levels to blocks hashes. *) +module Levels_to_hashes = + Make_updatable_map + (struct + let path = ["tezos"; "levels"] + end) + (struct + type key = int32 + + let to_path_representation = Int32.to_string + end) + (struct + type value = Block_hash.t + + let name = "block_hash" + + let encoding = Block_hash.encoding + end) + (* Published slot headers per block hash, stored as a list of bindings from `Dal_slot_index.t` to `Dal.Slot.t`. The encoding function converts this diff --git a/src/proto_alpha/bin_sc_rollup_node/store.mli b/src/proto_alpha/bin_sc_rollup_node/store.mli index 51af89bcf21cdaf14f9162003d1a02dd247ba378..4c2d9524da08bc40f3ed0790ce49a1ae8d82ecb4 100644 --- a/src/proto_alpha/bin_sc_rollup_node/store.mli +++ b/src/proto_alpha/bin_sc_rollup_node/store.mli @@ -92,13 +92,6 @@ module Commitments : and type value := Sc_rollup.Commitment.t and type 'a store := 'a store -(** Storage containing the inbox level of the last commitment produced by the - rollup node. *) -module Last_stored_commitment_level : - Store_sigs.Mutable_value - with type value := Raw_level.t - and type 'a store := 'a store - (** Storage mapping commitment hashes to the level when they were published by the rollup node. It only contains hashes of commitments published by this rollup node. *) @@ -119,6 +112,22 @@ module Commitments_published_at_level : sig and type 'a store := 'a store end +module L2_head : + Store_sigs.Mutable_value + with type value := Sc_rollup_block.t + and type 'a store := 'a store + +module Last_finalized_head : + Store_sigs.Mutable_value + with type value := Sc_rollup_block.t + and type 'a store := 'a store + +module Levels_to_hashes : + Store_sigs.Map + with type key := int32 + and type value := Block_hash.t + and type 'a store := 'a store + (** Published slot headers per block hash, stored as a list of bindings from [Dal_slot_index.t] to [Dal.Slot.t]. The encoding function converts this