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 cc5fc58504f3b4fa4cbc8c259ff67cc213847a74..d34d0ddebb97928f34056fa1cd1e6b1df5962875 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 @@ -39,12 +39,13 @@ let get_finalized store = | None -> failwith "No finalized head" | Some {hash; _} -> return hash -let get_last_cemented store = +let get_last_cemented (node_ctxt : _ Node_context.t) = let open Lwt_result_syntax in protect @@ fun () -> - let*! lcc_level = Store.Last_cemented_commitment_level.get store in let*! lcc_hash = - State.hash_of_level store (Alpha_context.Raw_level.to_int32 lcc_level) + State.hash_of_level + node_ctxt.store + (Alpha_context.Raw_level.to_int32 node_ctxt.lcc.level) in return lcc_hash @@ -191,7 +192,7 @@ module Block_directory = Make_directory (struct | `Hash b -> return b | `Level l -> State.hash_of_level node_ctxt.store l >>= return | `Finalized -> get_finalized node_ctxt.Node_context.store - | `Cemented -> get_last_cemented node_ctxt.Node_context.store + | `Cemented -> get_last_cemented node_ctxt in (Node_context.readonly node_ctxt, block) end) @@ -210,7 +211,7 @@ module Outbox_directory = Make_directory (struct | `Hash b -> return b | `Level l -> State.hash_of_level node_ctxt.store l >>= return | `Finalized -> get_finalized node_ctxt.Node_context.store - | `Cemented -> get_last_cemented node_ctxt.Node_context.store + | `Cemented -> get_last_cemented node_ctxt in (Node_context.readonly node_ctxt, block, level) end) @@ -373,10 +374,9 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct let open Lwt_result_syntax in let*! result = let open Lwt_option_syntax in - let* commitment, hash = - Commitment.last_commitment_with_hash - (module Store.Last_published_commitment_level) - node_ctxt.store + let*? commitment = node_ctxt.lpc in + let hash = + Alpha_context.Sc_rollup.Commitment.hash_uncarbonated commitment in (* The corresponding level in Store.Commitments.published_at_level is available only when the commitment has been published and included @@ -460,16 +460,16 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct let commitment_level_of_inbox_level (node_ctxt : _ Node_context.t) inbox_level = let open Alpha_context in - let open Lwt_option_syntax in - let+ last_published = - Store.Last_published_commitment_level.find node_ctxt.store - in + let open Option_syntax in + let+ last_published_commitment = node_ctxt.lpc in let commitment_period = Int32.of_int node_ctxt.protocol_constants.parametric.sc_rollup .commitment_period_in_blocks in - let last_published = Raw_level.to_int32 last_published in + let last_published = + Raw_level.to_int32 last_published_commitment.inbox_level + in let open Int32 in div (sub last_published inbox_level) commitment_period |> mul commitment_period |> sub last_published |> Raw_level.of_int32_exn @@ -477,7 +477,6 @@ 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* lcc = Store.Last_cemented_commitment_level.find node_ctxt.store in let+ finalized_head = State.get_finalized_head_opt node_ctxt.store in let finalized = match finalized_head with @@ -486,9 +485,7 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct Compare.Int32.(inbox_level <= finalized_level) in let cemented = - match lcc with - | None -> false - | Some lcc -> Compare.Int32.(inbox_level <= Raw_level.to_int32 lcc) + Compare.Int32.(inbox_level <= Raw_level.to_int32 node_ctxt.lcc.level) in Sc_rollup_services.{finalized; cemented} @@ -515,7 +512,7 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct let*! inbox_info = inbox_info_of_level node_ctxt info.l1_level in - let*! commitment_level = + let commitment_level = commitment_level_of_inbox_level node_ctxt info.l1_level in match commitment_level with 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 807d9591e5a4fbdfb24a7b57a9aab7191b3e6649..40019e6dd72693dccf4d89732750bace15adcae1 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/commitment.ml +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/commitment.ml @@ -46,8 +46,8 @@ open Alpha_context module type Mutable_level_store = Store_sigs.Mutable_value - with type value = Raw_level.t - and type 'a store = 'a Store.store + with type value := Raw_level.t + and type 'a store := 'a Store.store (* We persist the number of ticks to be included in the next commitment on disk, in a map that is indexed by @@ -102,6 +102,23 @@ let last_commitment_with_hash in return commitment_with_hash +let next_lcc_level node_ctxt = + Environment.wrap_tzresult @@ Raw_level.of_int32 + @@ Int32.add + (Raw_level.to_int32 node_ctxt.Node_context.lcc.level) + (sc_rollup_commitment_period node_ctxt) + +let next_publishable_level node_ctxt = + let lpc_level = + match node_ctxt.Node_context.lpc with + | None -> node_ctxt.genesis_info.level + | Some lpc -> lpc.inbox_level + in + Environment.wrap_tzresult @@ Raw_level.of_int32 + @@ Int32.add + (Raw_level.to_int32 lpc_level) + (sc_rollup_commitment_period node_ctxt) + let next_commitment_level node_ctxt (module Last_commitment_level : Mutable_level_store) = let open Lwt_syntax in @@ -138,22 +155,29 @@ let must_store_commitment node_ctxt current_level = Raw_level.equal current_level next_commitment_level -let update_last_stored_commitment store (commitment : Sc_rollup.Commitment.t) = +let update_last_stored_commitment (node_ctxt : _ Node_context.t) + (commitment : Sc_rollup.Commitment.t) = let open Lwt_syntax in let commitment_hash = Sc_rollup.Commitment.hash_uncarbonated commitment in let inbox_level = commitment.inbox_level in - let* lcc_level = Store.Last_cemented_commitment_level.get store in (* Do not change the order of these two operations. This guarantees that whenever `Store.Last_stored_commitment_level.get` returns `Some hash`, then the call to `Store.Commitments.get hash` will succeed. *) let* () = - Store.Commitments.add store inbox_level (commitment, commitment_hash) + Store.Commitments.add + node_ctxt.store + inbox_level + (commitment, commitment_hash) + in + let* () = + Store.Last_stored_commitment_level.set node_ctxt.store inbox_level in - let* () = Store.Last_stored_commitment_level.set store inbox_level in let* () = Commitment_event.commitment_stored commitment_hash commitment in - if commitment.inbox_level <= lcc_level then - Commitment_event.commitment_will_not_be_published lcc_level commitment + if commitment.inbox_level <= node_ctxt.lcc.level then + Commitment_event.commitment_will_not_be_published + node_ctxt.lcc.level + commitment else return () module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct @@ -204,7 +228,7 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct if must_store_commitment then let*! () = Commitment_event.compute_commitment block_hash current_level in let* commitment = build_commitment node_ctxt block_hash in - let*! () = update_last_stored_commitment node_ctxt.store commitment in + let*! () = update_last_stored_commitment node_ctxt commitment in return_unit else return_unit @@ -254,92 +278,62 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct let*! () = update_ticks node_ctxt current_level hash in store_commitment_if_necessary node_ctxt current_level hash - let sync_last_cemented_commitment_hash_with_level - ({cctxt; rollup_address; store; _} : _ Node_context.t) = - let open Lwt_result_syntax in - let* hash, inbox_level = - Plugin.RPC.Sc_rollup.last_cemented_commitment_hash_with_level - cctxt - (cctxt#chain, cctxt#block) - rollup_address - in - let*! () = Store.Last_cemented_commitment_level.set store inbox_level in - let*! () = Store.Last_cemented_commitment_hash.set store hash in - let*! () = - Commitment_event.last_cemented_commitment_updated hash inbox_level - in - return_unit - let get_commitment_and_publish ~check_lcc_hash ({store; _} as node_ctxt : _ Node_context.t) next_level_to_publish = let open Lwt_result_syntax in - let*! is_commitment_available = - Store.Commitments.mem store next_level_to_publish - in - if is_commitment_available then - let*! commitment, _commitment_hash = - Store.Commitments.get store next_level_to_publish - in - let* () = - if check_lcc_hash then - let open Lwt_result_syntax in - let*! lcc_hash = Store.Last_cemented_commitment_hash.get store in - if Sc_rollup.Commitment.Hash.equal lcc_hash commitment.predecessor - then return () - else - let*! () = - Commitment_event.commitment_parent_is_not_lcc - commitment.inbox_level + let*! commitment = Store.Commitments.find store next_level_to_publish in + match commitment with + | None -> + (* Commitment not available *) + return_unit + | Some (commitment, _commitment_hash) -> ( + let* () = + if check_lcc_hash then + let open Lwt_result_syntax in + if + Sc_rollup.Commitment.Hash.equal + node_ctxt.lcc.commitment commitment.predecessor - lcc_hash + then return () + else + let*! () = + Commitment_event.commitment_parent_is_not_lcc + commitment.inbox_level + commitment.predecessor + node_ctxt.lcc.commitment + in + tzfail + (Sc_rollup_node_errors.Commitment_predecessor_should_be_LCC + commitment) + else return_unit + in + let operator = Node_context.get_operator node_ctxt Publish in + match operator with + | None -> + (* Configured to not publish commitments *) + return_unit + | Some source -> + let publish_operation = + Sc_rollup_publish {rollup = node_ctxt.rollup_address; commitment} in - tzfail - (Sc_rollup_node_errors.Commitment_predecessor_should_be_LCC - commitment) - else return_unit - in - let operator = Node_context.get_operator node_ctxt Publish in - match operator with - | None -> - (* Configured to not publish commitments *) - return_unit - | Some source -> - let publish_operation = - Sc_rollup_publish {rollup = node_ctxt.rollup_address; commitment} - in - let* _hash = - Injector.add_pending_operation ~source publish_operation - in - (* TODO: https://gitlab.com/tezos/tezos/-/issues/3462 - Decouple commitments from head processing - - Move the following, in a part where we know the operation is - included. *) - let*! () = - Store.Last_published_commitment_level.set - store - commitment.inbox_level - in - return_unit - else return_unit + let* _hash = + Injector.add_pending_operation ~source publish_operation + in + (* TODO: https://gitlab.com/tezos/tezos/-/issues/3462 + Decouple commitments from head processing + + Move the following, in a part where we know the operation is + included. *) + node_ctxt.lpc <- Some commitment ; + return_unit) let publish_commitment node_ctxt = let open Lwt_result_syntax in (* Check level of next publishable commitment and avoid publishing if it is on or before the last cemented commitment. *) - let* next_lcc_level = - Lwt.map Environment.wrap_tzresult - @@ next_commitment_level - node_ctxt - (module Store.Last_cemented_commitment_level) - in - let* next_publishable_level = - Lwt.map Environment.wrap_tzresult - @@ next_commitment_level - node_ctxt - (module Store.Last_published_commitment_level) - in + let*? next_lcc_level = next_lcc_level node_ctxt in + let*? next_publishable_level = next_publishable_level node_ctxt in let check_lcc_hash, level_to_publish = if Raw_level.(next_publishable_level < next_lcc_level) then (* @@ -401,12 +395,7 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct let cement_commitment_if_possible node_ctxt Layer1.{level = head_level; _} = let open Lwt_result_syntax in - let* next_level_to_cement = - Lwt.map Environment.wrap_tzresult - @@ next_commitment_level - node_ctxt - (module Store.Last_cemented_commitment_level) - in + let*? next_level_to_cement = next_lcc_level node_ctxt in let*! commitment_with_hash = Store.Commitments.find node_ctxt.store next_level_to_cement in diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/commitment.mli b/src/proto_016_PtMumbai/bin_sc_rollup_node/commitment.mli index 2f4f72e075901eaf77050ae0031fc15990827303..724914264ebb57972317d453b7880483c24d05e3 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/commitment.mli +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/commitment.mli @@ -43,8 +43,8 @@ open Protocol.Alpha_context module type Mutable_level_store = Store_sigs.Mutable_value - with type value = Raw_level.t - and type 'a store = 'a Store.store + with type value := Raw_level.t + and type 'a store := 'a Store.store (** [last_commitment_with_hash (module Last_level_module: Mutable_level_store) store] returns the last commitment and relative hash diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/commitment_sig.ml b/src/proto_016_PtMumbai/bin_sc_rollup_node/commitment_sig.ml index 3dabbe89f68e157c36005c0aa958f7dcedd3e9f6..eeacadea5cf06683a23a232373fae6cb0ce5bd2e 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/commitment_sig.ml +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/commitment_sig.ml @@ -49,12 +49,6 @@ module type S = sig [PVM] to compute the hash of to be included in the commitment. *) val process_head : Node_context.rw -> Layer1.head -> unit tzresult Lwt.t - (** [sync_last_cemented_commitment_hash_with_level node_ctxt] fetches and - stores information about the last cemeneted commitment in the layer1 - chain. *) - val sync_last_cemented_commitment_hash_with_level : - Node_context.rw -> unit tzresult Lwt.t - (** [publish_commitment node_ctxt] publishes the earliest commitment stored in [store] that has not been published yet, unless its inbox level is below or equal to the inbox level of the last cemented commitment in 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 66e6d02f743206208f9522fa5efa76964a5c68db..7a650e390400bec424803da9f24cfcf52d1e5ac2 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/daemon.ml +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/daemon.ml @@ -34,13 +34,20 @@ module Make (PVM : Pvm.S) = struct for the first time. {b Note}: this function does not process inboxes for the rollup, which is done instead by {!Inbox.process_head}. *) let process_included_l1_operation (type kind) (node_ctxt : Node_context.rw) - head ~source:_ (operation : kind manager_operation) + head ~source (operation : kind manager_operation) (result : kind successful_manager_operation_result) = let open Lwt_result_syntax in match (operation, result) with | ( Sc_rollup_publish {commitment; _}, - Sc_rollup_publish_result {published_at_level; _} ) -> + Sc_rollup_publish_result {published_at_level; _} ) + when Node_context.is_operator node_ctxt source -> (* Published commitment --------------------------------------------- *) + let is_newest_lpc = + match node_ctxt.lpc with + | None -> true + | Some lpc -> Raw_level.(commitment.inbox_level > lpc.inbox_level) + in + if is_newest_lpc then node_ctxt.lpc <- Some commitment ; let commitment_hash = Sc_rollup.Commitment.hash_uncarbonated commitment in @@ -54,11 +61,12 @@ module Make (PVM : Pvm.S) = struct | Sc_rollup_cement {commitment; _}, Sc_rollup_cement_result {inbox_level; _} -> (* Cemented commitment ---------------------------------------------- *) + if Raw_level.(inbox_level > node_ctxt.lcc.level) then + node_ctxt.lcc <- {commitment; level = inbox_level} ; let*! () = - Store.Last_cemented_commitment_level.set node_ctxt.store inbox_level - in - let*! () = - Store.Last_cemented_commitment_hash.set node_ctxt.store commitment + Commitment_event.last_cemented_commitment_updated + commitment + inbox_level in return_unit | ( Sc_rollup_refute _, @@ -182,9 +190,6 @@ module Make (PVM : Pvm.S) = struct let*! () = Daemon_event.head_processing hash level ~finalized:true in let* () = process_l1_block_operations ~finalized:true node_ctxt block in let* () = Components.Commitment.process_head node_ctxt block in - (* At each block, there may be some refutation related actions to - be performed. *) - let* () = Components.Refutation_game.process block node_ctxt in let*! () = State.mark_finalized_head node_ctxt.store block in return_unit @@ -242,13 +247,6 @@ 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* () = - (* Get information about the last cemented commitment to determine the - commitment (if any) to publish next. We do this only once per - chain event to avoid spamming the layer1 node. *) - Components.Commitment.sync_last_cemented_commitment_hash_with_level - node_ctxt - in let*! old_head = State.last_processed_head_opt node_ctxt.Node_context.store in @@ -284,6 +282,7 @@ module Make (PVM : Pvm.S) = struct let* () = List.iter_es (process_head node_ctxt) reorg.new_chain in let* () = notify_injector node_ctxt new_head reorg in let*! () = Daemon_event.new_heads_processed reorg.new_chain in + let* () = Components.Refutation_game.process head node_ctxt in let* () = Components.Batcher.batch () in let* () = Components.Batcher.new_head head in let*! () = Injector.inject ~header () in 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 3b977dd7c24dc74ab8a779ea3dbf5ce08fdb2c81..f4d20c3970da48ba47043273bd194c824cfbed0b 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 @@ -26,6 +26,8 @@ open Protocol open Alpha_context +type lcc = {commitment : Sc_rollup.Commitment.Hash.t; level : Raw_level.t} + type 'a t = { cctxt : Protocol_client_context.full; dal_cctxt : Dal_node_client.cctxt; @@ -42,6 +44,8 @@ type 'a t = { loser_mode : Loser_mode.t; store : 'a Store.t; context : 'a Context.index; + mutable lcc : lcc; + mutable lpc : Sc_rollup.Commitment.t option; } type rw = [`Read | `Write] t @@ -69,27 +73,73 @@ let get_fee_parameter node_ctxt purpose = let retrieve_constants cctxt = Protocol.Constants_services.all cctxt (cctxt#chain, cctxt#block) +let get_last_cemented_commitment (cctxt : Protocol_client_context.full) + rollup_address = + let open Lwt_result_syntax in + let+ commitment, level = + Plugin.RPC.Sc_rollup.last_cemented_commitment_hash_with_level + cctxt + (cctxt#chain, `Head 0) + rollup_address + in + {commitment; level} + +let get_last_published_commitment (cctxt : Protocol_client_context.full) + rollup_address operator = + let open Lwt_result_syntax in + let*! res = + Plugin.RPC.Sc_rollup.staked_on_commitment + cctxt + (cctxt#chain, `Head 0) + rollup_address + operator + in + match res with + | Error trace + when TzTrace.fold + (fun exists -> function + | Environment.Ecoproto_error Sc_rollup_errors.Sc_rollup_not_staked + -> + true + | _ -> exists) + false + trace -> + return_none + | Error trace -> fail trace + | 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 open Lwt_result_syntax in - let+ protocol_constants = retrieve_constants cctxt in - { - cctxt; - dal_cctxt; - data_dir; - l1_ctxt; - rollup_address; - operators; - genesis_info = l1_ctxt.Layer1.genesis_info; - kind; - injector_retention_period = 0; - block_finality_time = 2; - fee_parameters; - protocol_constants; - loser_mode; - store; - context; - } + 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 + and* lpc = + Option.filter_map_es + (get_last_published_commitment cctxt rollup_address) + publisher + in + return + { + cctxt; + dal_cctxt; + data_dir; + l1_ctxt; + rollup_address; + operators; + genesis_info = l1_ctxt.Layer1.genesis_info; + lcc; + lpc; + kind; + injector_retention_period = 0; + block_finality_time = 2; + fee_parameters; + protocol_constants; + loser_mode; + store; + context; + } let checkout_context node_ctxt block_hash = let open Lwt_result_syntax in 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 2e5ed5bd3c4009ba035f5a336435e9a63f1358b5..db431e7a77fd6b23f25b851a8f3d97fdf7686cef 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 @@ -28,6 +28,8 @@ open Protocol open Alpha_context +type lcc = {commitment : Sc_rollup.Commitment.Hash.t; level : Raw_level.t} + type 'a t = { cctxt : Protocol_client_context.full; (** Client context used by the rollup node. *) @@ -55,7 +57,12 @@ type 'a 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. *) - context : 'a Context.index; (** The persistent context for the rollup node. *) + context : 'a Context.index; + (** The persistent context for the rollup node. *) + mutable lcc : lcc; (** Last cemented commitment and its level. *) + mutable lpc : Sc_rollup.Commitment.t option; + (** The last published commitment, i.e. commitment that the operator is + staked on. *) } (** Read/write node context {!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 27c1f166d986097312c2472d77c1e6e34b80b7c9..56b410ed25953567dde85aae6859533d457790b2 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/outbox.ml +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/outbox.ml @@ -29,11 +29,10 @@ open Protocol.Alpha_context module Make (PVM : Pvm.S) = struct let get_state_of_lcc node_ctxt = let open Lwt_result_syntax in - let*! lcc_level = - Store.Last_cemented_commitment_level.get node_ctxt.store - in let*! block_hash = - State.hash_of_level node_ctxt.store (Raw_level.to_int32 lcc_level) + State.hash_of_level + node_ctxt.store + (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 @@ -41,9 +40,6 @@ module Make (PVM : Pvm.S) = struct let proof_of_output node_ctxt output = let open Lwt_result_syntax in - let*! commitment_hash = - Store.Last_cemented_commitment_hash.get node_ctxt.store - in let* state = get_state_of_lcc node_ctxt in match state with | None -> @@ -59,7 +55,7 @@ module Make (PVM : Pvm.S) = struct let serialized_proof = Data_encoding.Binary.to_string_exn PVM.output_proof_encoding proof in - return @@ (commitment_hash, serialized_proof) + return @@ (node_ctxt.lcc.commitment, serialized_proof) | Error err -> failwith "Error producing outbox proof (%a)" diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/outbox.mli b/src/proto_016_PtMumbai/bin_sc_rollup_node/outbox.mli index d061ca3397c13813b49287698d443e3b2ec44472..613661e456a726c566ee5150d4b134f9ae9507c7 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/outbox.mli +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/outbox.mli @@ -33,5 +33,5 @@ module Make (PVM : Pvm.S) : sig val proof_of_output : Node_context.rw -> Sc_rollup.output -> - (Store.Last_cemented_commitment_hash.value * string) tzresult Lwt.t + (Sc_rollup.Commitment.Hash.t * string) tzresult Lwt.t end 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 2d615f718c4dd1205aecc397a064f2969e1e62ad..4fd308e17a66a95281267ad8be3564d1c96e2553 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/store.ml +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/store.ml @@ -266,45 +266,6 @@ module Last_stored_commitment_level = let encoding = Raw_level.encoding end) -module Last_published_commitment_level = - Make_mutable_value - (struct - let path = ["commitments"; "last_published_level"] - end) - (struct - type value = Raw_level.t - - let name = "raw_level" - - let encoding = Raw_level.encoding - end) - -module Last_cemented_commitment_level = - Make_mutable_value - (struct - let path = ["commitments"; "last_cemented_commitment"; "level"] - end) - (struct - type value = Raw_level.t - - let name = "raw_level" - - let encoding = Raw_level.encoding - end) - -module Last_cemented_commitment_hash = - Make_mutable_value - (struct - let path = ["commitments"; "last_cemented_commitment"; "hash"] - end) - (struct - type value = Sc_rollup.Commitment.Hash.t - - let name = "commitment_hash" - - let encoding = Sc_rollup.Commitment.Hash.encoding - end) - module Commitments_published_at_level = Make_updatable_map (struct 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 1dc192e93323b052d734d8f7a7bb57b5fcd24758..7fd56116bf0d9edbfb453dabbda1ac0a5fd9a390 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/store.mli +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/store.mli @@ -65,9 +65,9 @@ val readonly : _ t -> ro (** Extraneous state information for the PVM *) module StateInfo : Store_sigs.Append_only_map - with type key = Tezos_crypto.Block_hash.t - and type value = state_info - and type 'a store = 'a store + with type key := Tezos_crypto.Block_hash.t + and type value := state_info + and type 'a store := 'a store module StateHistoryRepr : sig type event = { @@ -77,7 +77,7 @@ module StateHistoryRepr : sig level : Raw_level.t; } - module TickMap : Map.S with type key = Sc_rollup.Tick.t + module TickMap : Map.S with type key := Sc_rollup.Tick.t type value = event TickMap.t end @@ -90,38 +90,36 @@ end module StateHistory : sig include Store_sigs.Mutable_value - with type value = StateHistoryRepr.value - and type 'a store = 'a store + with type value := StateHistoryRepr.value + and type 'a store := 'a store val insert : rw -> StateHistoryRepr.event -> unit Lwt.t val event_of_largest_tick_before : - _ t -> - StateHistoryRepr.TickMap.key -> - StateHistoryRepr.event option tzresult Lwt.t + _ t -> Sc_rollup.Tick.t -> StateHistoryRepr.event option tzresult Lwt.t end (** Storage for persisting messages downloaded from the L1 node, indexed by [Tezos_crypto.Block_hash.t]. *) module Messages : Store_sigs.Append_only_map - with type key = Tezos_crypto.Block_hash.t - and type value = Sc_rollup.Inbox_message.t list - and type 'a store = 'a store + with type key := Tezos_crypto.Block_hash.t + and type value := Sc_rollup.Inbox_message.t list + and type 'a store := 'a store (** Aggregated collection of messages from the L1 inbox *) module Inboxes : Store_sigs.Append_only_map - with type key = Tezos_crypto.Block_hash.t - and type value = Sc_rollup.Inbox.t - and type 'a store = 'a store + with type key := Tezos_crypto.Block_hash.t + and type value := Sc_rollup.Inbox.t + and type 'a store := 'a store (** Histories from the rollup node. **) module Histories : Store_sigs.Append_only_map - with type key = Tezos_crypto.Block_hash.t - and type value = Sc_rollup.Inbox.History.t - and type 'a store = 'a store + with type key := Tezos_crypto.Block_hash.t + and type value := Sc_rollup.Inbox.History.t + and type 'a store := 'a store (** messages histories from the rollup node. Each history contains the messages of one level. The store is indexed by a level in order to maintain a small @@ -129,62 +127,40 @@ module Histories : computing the proof. *) module Payloads_histories : Store_sigs.Append_only_map - with type key = Sc_rollup.Inbox_merkelized_payload_hashes.Hash.t - and type value = Sc_rollup.Inbox_merkelized_payload_hashes.History.t - and type 'a store = 'a store + with type key := Sc_rollup.Inbox_merkelized_payload_hashes.Hash.t + and type value := Sc_rollup.Inbox_merkelized_payload_hashes.History.t + and type 'a store := 'a store (** Storage containing commitments and corresponding commitment hashes that the rollup node has knowledge of. *) module Commitments : Store_sigs.Append_only_map - with type key = Raw_level.t - and type value = Sc_rollup.Commitment.t * Sc_rollup.Commitment.Hash.t - and type 'a store = 'a store + with type key := Raw_level.t + and type value := Sc_rollup.Commitment.t * Sc_rollup.Commitment.Hash.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 contianing the inbox level of the last commitment published by the - rollup node. *) -module Last_published_commitment_level : - Store_sigs.Mutable_value - with type value = Raw_level.t - and type 'a store = 'a store - -(** Storage containing the inbox level of the last commitment cemented for the - rollup. The commitment has not been necessarily generated by this rollup - node. *) -module Last_cemented_commitment_level : - Store_sigs.Mutable_value - with type value = Raw_level.t - and type 'a store = 'a store - -(** torage containing the hash of the last commitment cemented for the rollup. - The commitment has not been necessarily generated by this rollup node. *) -module Last_cemented_commitment_hash : - Store_sigs.Mutable_value - with type value = Sc_rollup.Commitment.Hash.t - and type 'a store = 'a store + 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. *) module Commitments_published_at_level : Store_sigs.Map - with type key = Sc_rollup.Commitment.Hash.t - and type value = Raw_level.t - and type 'a store = 'a store + with type key := Sc_rollup.Commitment.Hash.t + and type value := Raw_level.t + and type 'a store := 'a store (** Storage containing the hashes of contexts retrieved from the L1 node. *) module Contexts : Store_sigs.Append_only_map - with type key = Tezos_crypto.Block_hash.t - and type value = Context.hash - and type 'a store = 'a store + with type key := Tezos_crypto.Block_hash.t + and type value := Context.hash + and type 'a store := 'a store (** Published slot headers per block hash, stored as a list of bindings from [Dal_slot_index.t] @@ -192,24 +168,24 @@ module Contexts : list into a [Dal.Slot_index.t]-indexed map. *) module Dal_slots_headers : Store_sigs.Nested_map - with type primary_key = Tezos_crypto.Block_hash.t - and type secondary_key = Dal.Slot_index.t - and type value = Dal.Slot.Header.t - and type 'a store = 'a store + with type primary_key := Tezos_crypto.Block_hash.t + and type secondary_key := Dal.Slot_index.t + and type value := Dal.Slot.Header.t + and type 'a store := 'a store module Dal_confirmed_slots_history : Store_sigs.Append_only_map - with type key = Tezos_crypto.Block_hash.t - and type value = Dal.Slots_history.t - and type 'a store = 'a store + with type key := Tezos_crypto.Block_hash.t + and type value := Dal.Slots_history.t + and type 'a store := 'a store (** Confirmed DAL slots histories cache. See documentation of {Dal_slot_repr.Slots_history} for more details. *) module Dal_confirmed_slots_histories : Store_sigs.Append_only_map - with type key = Tezos_crypto.Block_hash.t - and type value = Dal.Slots_history.History_cache.t - and type 'a store = 'a store + with type key := Tezos_crypto.Block_hash.t + and type value := Dal.Slots_history.History_cache.t + and type 'a store := 'a store (** [Dal_slot_pages] is a [Store_utils.Nested_map] used to store the contents of dal slots fetched by the rollup node, as a list of pages. The values of @@ -219,10 +195,10 @@ module Dal_confirmed_slots_histories : *) module Dal_slot_pages : Store_sigs.Nested_map - with type primary_key = Tezos_crypto.Block_hash.t - and type secondary_key = Dal.Slot_index.t * Dal.Page.Index.t - and type value = Dal.Page.content - and type 'a store = 'a store + with type primary_key := Tezos_crypto.Block_hash.t + and type secondary_key := Dal.Slot_index.t * Dal.Page.Index.t + and type value := Dal.Page.content + and type 'a store := 'a store (** [Dal_processed_slots] is a [Store_utils.Nested_map] used to store the processing status of dal slots content fetched by the rollup node. The values of @@ -233,7 +209,7 @@ module Dal_slot_pages : *) module Dal_processed_slots : Store_sigs.Nested_map - with type primary_key = Tezos_crypto.Block_hash.t - and type secondary_key = Dal.Slot_index.t - and type value = [`Confirmed | `Unconfirmed] - and type 'a store = 'a store + with type primary_key := Tezos_crypto.Block_hash.t + and type secondary_key := Dal.Slot_index.t + and type value := [`Confirmed | `Unconfirmed] + and type 'a store := 'a store diff --git a/src/proto_016_PtMumbai/lib_plugin/RPC.ml b/src/proto_016_PtMumbai/lib_plugin/RPC.ml index 01b5d72c7029a1d53ff470c7a33d5883c18ad1da..c20476d3c9f69d6722c6e9250c6be536bc505374 100644 --- a/src/proto_016_PtMumbai/lib_plugin/RPC.ml +++ b/src/proto_016_PtMumbai/lib_plugin/RPC.ml @@ -2023,10 +2023,15 @@ module Sc_rollup = struct let staked_on_commitment = RPC_service.get_service ~description: - "The hash of the commitment on which the operator has staked on for \ - a smart rollup" + "The newest commitment on which the operator has staked on for a \ + smart rollup. Note that is can return a commitment that is before \ + the last cemented one." ~query:RPC_query.empty - ~output:(obj1 (req "hash" Sc_rollup.Commitment.Hash.encoding)) + ~output: + (option + (merge_objs + (obj1 (req "hash" Sc_rollup.Commitment.Hash.encoding)) + Sc_rollup.Commitment.encoding)) RPC_path.( path_sc_rollup / "staker" /: Sc_rollup.Staker.rpc_arg / "staked_on_commitment") @@ -2191,10 +2196,16 @@ module Sc_rollup = struct Registration.register2 ~chunked:false S.staked_on_commitment @@ fun ctxt address staker () () -> let open Lwt_result_syntax in - let+ branch, _ctxt = + let* commitment_hash, ctxt = Alpha_context.Sc_rollup.Stake_storage.find_staker ctxt address staker in - branch + let* commitment, _ctxt = + Alpha_context.Sc_rollup.Commitment.get_commitment + ctxt + address + commitment_hash + in + return_some (commitment_hash, commitment) let register_commitment () = Registration.register2 ~chunked:false S.commitment @@ -2315,6 +2326,16 @@ module Sc_rollup = struct () () + let staked_on_commitment ctxt block sc_rollup_address staker = + RPC_context.make_call2 + S.staked_on_commitment + ctxt + block + sc_rollup_address + staker + () + () + let commitment ctxt block sc_rollup_address commitment_hash = RPC_context.make_call2 S.commitment 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 a460b4b99a85b22dbc05bad570c499af5fdee460..a58e56651068d1c7c39476cffb2641feb6e26cf3 100644 --- a/src/proto_alpha/bin_sc_rollup_node/RPC_server.ml +++ b/src/proto_alpha/bin_sc_rollup_node/RPC_server.ml @@ -39,12 +39,13 @@ let get_finalized store = | None -> failwith "No finalized head" | Some {hash; _} -> return hash -let get_last_cemented store = +let get_last_cemented (node_ctxt : _ Node_context.t) = let open Lwt_result_syntax in protect @@ fun () -> - let*! lcc_level = Store.Last_cemented_commitment_level.get store in let*! lcc_hash = - State.hash_of_level store (Alpha_context.Raw_level.to_int32 lcc_level) + State.hash_of_level + node_ctxt.store + (Alpha_context.Raw_level.to_int32 node_ctxt.lcc.level) in return lcc_hash @@ -191,7 +192,7 @@ module Block_directory = Make_directory (struct | `Hash b -> return b | `Level l -> State.hash_of_level node_ctxt.store l >>= return | `Finalized -> get_finalized node_ctxt.Node_context.store - | `Cemented -> get_last_cemented node_ctxt.Node_context.store + | `Cemented -> get_last_cemented node_ctxt in (Node_context.readonly node_ctxt, block) end) @@ -210,7 +211,7 @@ module Outbox_directory = Make_directory (struct | `Hash b -> return b | `Level l -> State.hash_of_level node_ctxt.store l >>= return | `Finalized -> get_finalized node_ctxt.Node_context.store - | `Cemented -> get_last_cemented node_ctxt.Node_context.store + | `Cemented -> get_last_cemented node_ctxt in (Node_context.readonly node_ctxt, block, level) end) @@ -373,10 +374,9 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct let open Lwt_result_syntax in let*! result = let open Lwt_option_syntax in - let* commitment, hash = - Commitment.last_commitment_with_hash - (module Store.Last_published_commitment_level) - node_ctxt.store + let*? commitment = node_ctxt.lpc in + let hash = + Alpha_context.Sc_rollup.Commitment.hash_uncarbonated commitment in (* The corresponding level in Store.Commitments.published_at_level is available only when the commitment has been published and included @@ -460,16 +460,16 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct let commitment_level_of_inbox_level (node_ctxt : _ Node_context.t) inbox_level = let open Alpha_context in - let open Lwt_option_syntax in - let+ last_published = - Store.Last_published_commitment_level.find node_ctxt.store - in + let open Option_syntax in + let+ last_published_commitment = node_ctxt.lpc in let commitment_period = Int32.of_int node_ctxt.protocol_constants.parametric.sc_rollup .commitment_period_in_blocks in - let last_published = Raw_level.to_int32 last_published in + let last_published = + Raw_level.to_int32 last_published_commitment.inbox_level + in let open Int32 in div (sub last_published inbox_level) commitment_period |> mul commitment_period |> sub last_published |> Raw_level.of_int32_exn @@ -477,7 +477,6 @@ 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* lcc = Store.Last_cemented_commitment_level.find node_ctxt.store in let+ finalized_head = State.get_finalized_head_opt node_ctxt.store in let finalized = match finalized_head with @@ -486,9 +485,7 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct Compare.Int32.(inbox_level <= finalized_level) in let cemented = - match lcc with - | None -> false - | Some lcc -> Compare.Int32.(inbox_level <= Raw_level.to_int32 lcc) + Compare.Int32.(inbox_level <= Raw_level.to_int32 node_ctxt.lcc.level) in Sc_rollup_services.{finalized; cemented} @@ -515,7 +512,7 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct let*! inbox_info = inbox_info_of_level node_ctxt info.l1_level in - let*! commitment_level = + let commitment_level = commitment_level_of_inbox_level node_ctxt info.l1_level in match commitment_level with diff --git a/src/proto_alpha/bin_sc_rollup_node/commitment.ml b/src/proto_alpha/bin_sc_rollup_node/commitment.ml index 807d9591e5a4fbdfb24a7b57a9aab7191b3e6649..40019e6dd72693dccf4d89732750bace15adcae1 100644 --- a/src/proto_alpha/bin_sc_rollup_node/commitment.ml +++ b/src/proto_alpha/bin_sc_rollup_node/commitment.ml @@ -46,8 +46,8 @@ open Alpha_context module type Mutable_level_store = Store_sigs.Mutable_value - with type value = Raw_level.t - and type 'a store = 'a Store.store + with type value := Raw_level.t + and type 'a store := 'a Store.store (* We persist the number of ticks to be included in the next commitment on disk, in a map that is indexed by @@ -102,6 +102,23 @@ let last_commitment_with_hash in return commitment_with_hash +let next_lcc_level node_ctxt = + Environment.wrap_tzresult @@ Raw_level.of_int32 + @@ Int32.add + (Raw_level.to_int32 node_ctxt.Node_context.lcc.level) + (sc_rollup_commitment_period node_ctxt) + +let next_publishable_level node_ctxt = + let lpc_level = + match node_ctxt.Node_context.lpc with + | None -> node_ctxt.genesis_info.level + | Some lpc -> lpc.inbox_level + in + Environment.wrap_tzresult @@ Raw_level.of_int32 + @@ Int32.add + (Raw_level.to_int32 lpc_level) + (sc_rollup_commitment_period node_ctxt) + let next_commitment_level node_ctxt (module Last_commitment_level : Mutable_level_store) = let open Lwt_syntax in @@ -138,22 +155,29 @@ let must_store_commitment node_ctxt current_level = Raw_level.equal current_level next_commitment_level -let update_last_stored_commitment store (commitment : Sc_rollup.Commitment.t) = +let update_last_stored_commitment (node_ctxt : _ Node_context.t) + (commitment : Sc_rollup.Commitment.t) = let open Lwt_syntax in let commitment_hash = Sc_rollup.Commitment.hash_uncarbonated commitment in let inbox_level = commitment.inbox_level in - let* lcc_level = Store.Last_cemented_commitment_level.get store in (* Do not change the order of these two operations. This guarantees that whenever `Store.Last_stored_commitment_level.get` returns `Some hash`, then the call to `Store.Commitments.get hash` will succeed. *) let* () = - Store.Commitments.add store inbox_level (commitment, commitment_hash) + Store.Commitments.add + node_ctxt.store + inbox_level + (commitment, commitment_hash) + in + let* () = + Store.Last_stored_commitment_level.set node_ctxt.store inbox_level in - let* () = Store.Last_stored_commitment_level.set store inbox_level in let* () = Commitment_event.commitment_stored commitment_hash commitment in - if commitment.inbox_level <= lcc_level then - Commitment_event.commitment_will_not_be_published lcc_level commitment + if commitment.inbox_level <= node_ctxt.lcc.level then + Commitment_event.commitment_will_not_be_published + node_ctxt.lcc.level + commitment else return () module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct @@ -204,7 +228,7 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct if must_store_commitment then let*! () = Commitment_event.compute_commitment block_hash current_level in let* commitment = build_commitment node_ctxt block_hash in - let*! () = update_last_stored_commitment node_ctxt.store commitment in + let*! () = update_last_stored_commitment node_ctxt commitment in return_unit else return_unit @@ -254,92 +278,62 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct let*! () = update_ticks node_ctxt current_level hash in store_commitment_if_necessary node_ctxt current_level hash - let sync_last_cemented_commitment_hash_with_level - ({cctxt; rollup_address; store; _} : _ Node_context.t) = - let open Lwt_result_syntax in - let* hash, inbox_level = - Plugin.RPC.Sc_rollup.last_cemented_commitment_hash_with_level - cctxt - (cctxt#chain, cctxt#block) - rollup_address - in - let*! () = Store.Last_cemented_commitment_level.set store inbox_level in - let*! () = Store.Last_cemented_commitment_hash.set store hash in - let*! () = - Commitment_event.last_cemented_commitment_updated hash inbox_level - in - return_unit - let get_commitment_and_publish ~check_lcc_hash ({store; _} as node_ctxt : _ Node_context.t) next_level_to_publish = let open Lwt_result_syntax in - let*! is_commitment_available = - Store.Commitments.mem store next_level_to_publish - in - if is_commitment_available then - let*! commitment, _commitment_hash = - Store.Commitments.get store next_level_to_publish - in - let* () = - if check_lcc_hash then - let open Lwt_result_syntax in - let*! lcc_hash = Store.Last_cemented_commitment_hash.get store in - if Sc_rollup.Commitment.Hash.equal lcc_hash commitment.predecessor - then return () - else - let*! () = - Commitment_event.commitment_parent_is_not_lcc - commitment.inbox_level + let*! commitment = Store.Commitments.find store next_level_to_publish in + match commitment with + | None -> + (* Commitment not available *) + return_unit + | Some (commitment, _commitment_hash) -> ( + let* () = + if check_lcc_hash then + let open Lwt_result_syntax in + if + Sc_rollup.Commitment.Hash.equal + node_ctxt.lcc.commitment commitment.predecessor - lcc_hash + then return () + else + let*! () = + Commitment_event.commitment_parent_is_not_lcc + commitment.inbox_level + commitment.predecessor + node_ctxt.lcc.commitment + in + tzfail + (Sc_rollup_node_errors.Commitment_predecessor_should_be_LCC + commitment) + else return_unit + in + let operator = Node_context.get_operator node_ctxt Publish in + match operator with + | None -> + (* Configured to not publish commitments *) + return_unit + | Some source -> + let publish_operation = + Sc_rollup_publish {rollup = node_ctxt.rollup_address; commitment} in - tzfail - (Sc_rollup_node_errors.Commitment_predecessor_should_be_LCC - commitment) - else return_unit - in - let operator = Node_context.get_operator node_ctxt Publish in - match operator with - | None -> - (* Configured to not publish commitments *) - return_unit - | Some source -> - let publish_operation = - Sc_rollup_publish {rollup = node_ctxt.rollup_address; commitment} - in - let* _hash = - Injector.add_pending_operation ~source publish_operation - in - (* TODO: https://gitlab.com/tezos/tezos/-/issues/3462 - Decouple commitments from head processing - - Move the following, in a part where we know the operation is - included. *) - let*! () = - Store.Last_published_commitment_level.set - store - commitment.inbox_level - in - return_unit - else return_unit + let* _hash = + Injector.add_pending_operation ~source publish_operation + in + (* TODO: https://gitlab.com/tezos/tezos/-/issues/3462 + Decouple commitments from head processing + + Move the following, in a part where we know the operation is + included. *) + node_ctxt.lpc <- Some commitment ; + return_unit) let publish_commitment node_ctxt = let open Lwt_result_syntax in (* Check level of next publishable commitment and avoid publishing if it is on or before the last cemented commitment. *) - let* next_lcc_level = - Lwt.map Environment.wrap_tzresult - @@ next_commitment_level - node_ctxt - (module Store.Last_cemented_commitment_level) - in - let* next_publishable_level = - Lwt.map Environment.wrap_tzresult - @@ next_commitment_level - node_ctxt - (module Store.Last_published_commitment_level) - in + let*? next_lcc_level = next_lcc_level node_ctxt in + let*? next_publishable_level = next_publishable_level node_ctxt in let check_lcc_hash, level_to_publish = if Raw_level.(next_publishable_level < next_lcc_level) then (* @@ -401,12 +395,7 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct let cement_commitment_if_possible node_ctxt Layer1.{level = head_level; _} = let open Lwt_result_syntax in - let* next_level_to_cement = - Lwt.map Environment.wrap_tzresult - @@ next_commitment_level - node_ctxt - (module Store.Last_cemented_commitment_level) - in + let*? next_level_to_cement = next_lcc_level node_ctxt in let*! commitment_with_hash = Store.Commitments.find node_ctxt.store next_level_to_cement in diff --git a/src/proto_alpha/bin_sc_rollup_node/commitment.mli b/src/proto_alpha/bin_sc_rollup_node/commitment.mli index 2f4f72e075901eaf77050ae0031fc15990827303..724914264ebb57972317d453b7880483c24d05e3 100644 --- a/src/proto_alpha/bin_sc_rollup_node/commitment.mli +++ b/src/proto_alpha/bin_sc_rollup_node/commitment.mli @@ -43,8 +43,8 @@ open Protocol.Alpha_context module type Mutable_level_store = Store_sigs.Mutable_value - with type value = Raw_level.t - and type 'a store = 'a Store.store + with type value := Raw_level.t + and type 'a store := 'a Store.store (** [last_commitment_with_hash (module Last_level_module: Mutable_level_store) store] returns the last commitment and relative hash diff --git a/src/proto_alpha/bin_sc_rollup_node/commitment_sig.ml b/src/proto_alpha/bin_sc_rollup_node/commitment_sig.ml index 3dabbe89f68e157c36005c0aa958f7dcedd3e9f6..eeacadea5cf06683a23a232373fae6cb0ce5bd2e 100644 --- a/src/proto_alpha/bin_sc_rollup_node/commitment_sig.ml +++ b/src/proto_alpha/bin_sc_rollup_node/commitment_sig.ml @@ -49,12 +49,6 @@ module type S = sig [PVM] to compute the hash of to be included in the commitment. *) val process_head : Node_context.rw -> Layer1.head -> unit tzresult Lwt.t - (** [sync_last_cemented_commitment_hash_with_level node_ctxt] fetches and - stores information about the last cemeneted commitment in the layer1 - chain. *) - val sync_last_cemented_commitment_hash_with_level : - Node_context.rw -> unit tzresult Lwt.t - (** [publish_commitment node_ctxt] publishes the earliest commitment stored in [store] that has not been published yet, unless its inbox level is below or equal to the inbox level of the last cemented commitment in diff --git a/src/proto_alpha/bin_sc_rollup_node/daemon.ml b/src/proto_alpha/bin_sc_rollup_node/daemon.ml index e6ea1aca6944863bfdfb562f57bfb47afef62c19..4e66b4a5327191bb16ad7a996ebf6f0a45ad7179 100644 --- a/src/proto_alpha/bin_sc_rollup_node/daemon.ml +++ b/src/proto_alpha/bin_sc_rollup_node/daemon.ml @@ -34,13 +34,20 @@ module Make (PVM : Pvm.S) = struct for the first time. {b Note}: this function does not process inboxes for the rollup, which is done instead by {!Inbox.process_head}. *) let process_included_l1_operation (type kind) (node_ctxt : Node_context.rw) - head ~source:_ (operation : kind manager_operation) + head ~source (operation : kind manager_operation) (result : kind successful_manager_operation_result) = let open Lwt_result_syntax in match (operation, result) with | ( Sc_rollup_publish {commitment; _}, - Sc_rollup_publish_result {published_at_level; _} ) -> + Sc_rollup_publish_result {published_at_level; _} ) + when Node_context.is_operator node_ctxt source -> (* Published commitment --------------------------------------------- *) + let is_newest_lpc = + match node_ctxt.lpc with + | None -> true + | Some lpc -> Raw_level.(commitment.inbox_level > lpc.inbox_level) + in + if is_newest_lpc then node_ctxt.lpc <- Some commitment ; let commitment_hash = Sc_rollup.Commitment.hash_uncarbonated commitment in @@ -54,11 +61,12 @@ module Make (PVM : Pvm.S) = struct | Sc_rollup_cement {commitment; _}, Sc_rollup_cement_result {inbox_level; _} -> (* Cemented commitment ---------------------------------------------- *) + if Raw_level.(inbox_level > node_ctxt.lcc.level) then + node_ctxt.lcc <- {commitment; level = inbox_level} ; let*! () = - Store.Last_cemented_commitment_level.set node_ctxt.store inbox_level - in - let*! () = - Store.Last_cemented_commitment_hash.set node_ctxt.store commitment + Commitment_event.last_cemented_commitment_updated + commitment + inbox_level in return_unit | ( Sc_rollup_refute _, @@ -182,9 +190,6 @@ module Make (PVM : Pvm.S) = struct let*! () = Daemon_event.head_processing hash level ~finalized:true in let* () = process_l1_block_operations ~finalized:true node_ctxt block in let* () = Components.Commitment.process_head node_ctxt block in - (* At each block, there may be some refutation related actions to - be performed. *) - let* () = Components.Refutation_game.process block node_ctxt in let*! () = State.mark_finalized_head node_ctxt.store block in return_unit @@ -242,13 +247,6 @@ 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* () = - (* Get information about the last cemented commitment to determine the - commitment (if any) to publish next. We do this only once per - chain event to avoid spamming the layer1 node. *) - Components.Commitment.sync_last_cemented_commitment_hash_with_level - node_ctxt - in let*! old_head = State.last_processed_head_opt node_ctxt.Node_context.store in @@ -284,6 +282,7 @@ module Make (PVM : Pvm.S) = struct let* () = List.iter_es (process_head node_ctxt) reorg.new_chain in let* () = notify_injector node_ctxt new_head reorg in let*! () = Daemon_event.new_heads_processed reorg.new_chain in + let* () = Components.Refutation_game.process head node_ctxt in let* () = Components.Batcher.batch () in let* () = Components.Batcher.new_head head in let*! () = Injector.inject ~header () in 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 3b977dd7c24dc74ab8a779ea3dbf5ce08fdb2c81..f4d20c3970da48ba47043273bd194c824cfbed0b 100644 --- a/src/proto_alpha/bin_sc_rollup_node/node_context.ml +++ b/src/proto_alpha/bin_sc_rollup_node/node_context.ml @@ -26,6 +26,8 @@ open Protocol open Alpha_context +type lcc = {commitment : Sc_rollup.Commitment.Hash.t; level : Raw_level.t} + type 'a t = { cctxt : Protocol_client_context.full; dal_cctxt : Dal_node_client.cctxt; @@ -42,6 +44,8 @@ type 'a t = { loser_mode : Loser_mode.t; store : 'a Store.t; context : 'a Context.index; + mutable lcc : lcc; + mutable lpc : Sc_rollup.Commitment.t option; } type rw = [`Read | `Write] t @@ -69,27 +73,73 @@ let get_fee_parameter node_ctxt purpose = let retrieve_constants cctxt = Protocol.Constants_services.all cctxt (cctxt#chain, cctxt#block) +let get_last_cemented_commitment (cctxt : Protocol_client_context.full) + rollup_address = + let open Lwt_result_syntax in + let+ commitment, level = + Plugin.RPC.Sc_rollup.last_cemented_commitment_hash_with_level + cctxt + (cctxt#chain, `Head 0) + rollup_address + in + {commitment; level} + +let get_last_published_commitment (cctxt : Protocol_client_context.full) + rollup_address operator = + let open Lwt_result_syntax in + let*! res = + Plugin.RPC.Sc_rollup.staked_on_commitment + cctxt + (cctxt#chain, `Head 0) + rollup_address + operator + in + match res with + | Error trace + when TzTrace.fold + (fun exists -> function + | Environment.Ecoproto_error Sc_rollup_errors.Sc_rollup_not_staked + -> + true + | _ -> exists) + false + trace -> + return_none + | Error trace -> fail trace + | 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 open Lwt_result_syntax in - let+ protocol_constants = retrieve_constants cctxt in - { - cctxt; - dal_cctxt; - data_dir; - l1_ctxt; - rollup_address; - operators; - genesis_info = l1_ctxt.Layer1.genesis_info; - kind; - injector_retention_period = 0; - block_finality_time = 2; - fee_parameters; - protocol_constants; - loser_mode; - store; - context; - } + 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 + and* lpc = + Option.filter_map_es + (get_last_published_commitment cctxt rollup_address) + publisher + in + return + { + cctxt; + dal_cctxt; + data_dir; + l1_ctxt; + rollup_address; + operators; + genesis_info = l1_ctxt.Layer1.genesis_info; + lcc; + lpc; + kind; + injector_retention_period = 0; + block_finality_time = 2; + fee_parameters; + protocol_constants; + loser_mode; + store; + context; + } let checkout_context node_ctxt block_hash = let open Lwt_result_syntax in 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 2e5ed5bd3c4009ba035f5a336435e9a63f1358b5..db431e7a77fd6b23f25b851a8f3d97fdf7686cef 100644 --- a/src/proto_alpha/bin_sc_rollup_node/node_context.mli +++ b/src/proto_alpha/bin_sc_rollup_node/node_context.mli @@ -28,6 +28,8 @@ open Protocol open Alpha_context +type lcc = {commitment : Sc_rollup.Commitment.Hash.t; level : Raw_level.t} + type 'a t = { cctxt : Protocol_client_context.full; (** Client context used by the rollup node. *) @@ -55,7 +57,12 @@ type 'a 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. *) - context : 'a Context.index; (** The persistent context for the rollup node. *) + context : 'a Context.index; + (** The persistent context for the rollup node. *) + mutable lcc : lcc; (** Last cemented commitment and its level. *) + mutable lpc : Sc_rollup.Commitment.t option; + (** The last published commitment, i.e. commitment that the operator is + staked on. *) } (** Read/write node context {!t}. *) diff --git a/src/proto_alpha/bin_sc_rollup_node/outbox.ml b/src/proto_alpha/bin_sc_rollup_node/outbox.ml index 27c1f166d986097312c2472d77c1e6e34b80b7c9..56b410ed25953567dde85aae6859533d457790b2 100644 --- a/src/proto_alpha/bin_sc_rollup_node/outbox.ml +++ b/src/proto_alpha/bin_sc_rollup_node/outbox.ml @@ -29,11 +29,10 @@ open Protocol.Alpha_context module Make (PVM : Pvm.S) = struct let get_state_of_lcc node_ctxt = let open Lwt_result_syntax in - let*! lcc_level = - Store.Last_cemented_commitment_level.get node_ctxt.store - in let*! block_hash = - State.hash_of_level node_ctxt.store (Raw_level.to_int32 lcc_level) + State.hash_of_level + node_ctxt.store + (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 @@ -41,9 +40,6 @@ module Make (PVM : Pvm.S) = struct let proof_of_output node_ctxt output = let open Lwt_result_syntax in - let*! commitment_hash = - Store.Last_cemented_commitment_hash.get node_ctxt.store - in let* state = get_state_of_lcc node_ctxt in match state with | None -> @@ -59,7 +55,7 @@ module Make (PVM : Pvm.S) = struct let serialized_proof = Data_encoding.Binary.to_string_exn PVM.output_proof_encoding proof in - return @@ (commitment_hash, serialized_proof) + return @@ (node_ctxt.lcc.commitment, serialized_proof) | Error err -> failwith "Error producing outbox proof (%a)" diff --git a/src/proto_alpha/bin_sc_rollup_node/outbox.mli b/src/proto_alpha/bin_sc_rollup_node/outbox.mli index d061ca3397c13813b49287698d443e3b2ec44472..613661e456a726c566ee5150d4b134f9ae9507c7 100644 --- a/src/proto_alpha/bin_sc_rollup_node/outbox.mli +++ b/src/proto_alpha/bin_sc_rollup_node/outbox.mli @@ -33,5 +33,5 @@ module Make (PVM : Pvm.S) : sig val proof_of_output : Node_context.rw -> Sc_rollup.output -> - (Store.Last_cemented_commitment_hash.value * string) tzresult Lwt.t + (Sc_rollup.Commitment.Hash.t * string) tzresult Lwt.t end diff --git a/src/proto_alpha/bin_sc_rollup_node/store.ml b/src/proto_alpha/bin_sc_rollup_node/store.ml index 2d615f718c4dd1205aecc397a064f2969e1e62ad..4fd308e17a66a95281267ad8be3564d1c96e2553 100644 --- a/src/proto_alpha/bin_sc_rollup_node/store.ml +++ b/src/proto_alpha/bin_sc_rollup_node/store.ml @@ -266,45 +266,6 @@ module Last_stored_commitment_level = let encoding = Raw_level.encoding end) -module Last_published_commitment_level = - Make_mutable_value - (struct - let path = ["commitments"; "last_published_level"] - end) - (struct - type value = Raw_level.t - - let name = "raw_level" - - let encoding = Raw_level.encoding - end) - -module Last_cemented_commitment_level = - Make_mutable_value - (struct - let path = ["commitments"; "last_cemented_commitment"; "level"] - end) - (struct - type value = Raw_level.t - - let name = "raw_level" - - let encoding = Raw_level.encoding - end) - -module Last_cemented_commitment_hash = - Make_mutable_value - (struct - let path = ["commitments"; "last_cemented_commitment"; "hash"] - end) - (struct - type value = Sc_rollup.Commitment.Hash.t - - let name = "commitment_hash" - - let encoding = Sc_rollup.Commitment.Hash.encoding - end) - module Commitments_published_at_level = Make_updatable_map (struct diff --git a/src/proto_alpha/bin_sc_rollup_node/store.mli b/src/proto_alpha/bin_sc_rollup_node/store.mli index 1dc192e93323b052d734d8f7a7bb57b5fcd24758..7fd56116bf0d9edbfb453dabbda1ac0a5fd9a390 100644 --- a/src/proto_alpha/bin_sc_rollup_node/store.mli +++ b/src/proto_alpha/bin_sc_rollup_node/store.mli @@ -65,9 +65,9 @@ val readonly : _ t -> ro (** Extraneous state information for the PVM *) module StateInfo : Store_sigs.Append_only_map - with type key = Tezos_crypto.Block_hash.t - and type value = state_info - and type 'a store = 'a store + with type key := Tezos_crypto.Block_hash.t + and type value := state_info + and type 'a store := 'a store module StateHistoryRepr : sig type event = { @@ -77,7 +77,7 @@ module StateHistoryRepr : sig level : Raw_level.t; } - module TickMap : Map.S with type key = Sc_rollup.Tick.t + module TickMap : Map.S with type key := Sc_rollup.Tick.t type value = event TickMap.t end @@ -90,38 +90,36 @@ end module StateHistory : sig include Store_sigs.Mutable_value - with type value = StateHistoryRepr.value - and type 'a store = 'a store + with type value := StateHistoryRepr.value + and type 'a store := 'a store val insert : rw -> StateHistoryRepr.event -> unit Lwt.t val event_of_largest_tick_before : - _ t -> - StateHistoryRepr.TickMap.key -> - StateHistoryRepr.event option tzresult Lwt.t + _ t -> Sc_rollup.Tick.t -> StateHistoryRepr.event option tzresult Lwt.t end (** Storage for persisting messages downloaded from the L1 node, indexed by [Tezos_crypto.Block_hash.t]. *) module Messages : Store_sigs.Append_only_map - with type key = Tezos_crypto.Block_hash.t - and type value = Sc_rollup.Inbox_message.t list - and type 'a store = 'a store + with type key := Tezos_crypto.Block_hash.t + and type value := Sc_rollup.Inbox_message.t list + and type 'a store := 'a store (** Aggregated collection of messages from the L1 inbox *) module Inboxes : Store_sigs.Append_only_map - with type key = Tezos_crypto.Block_hash.t - and type value = Sc_rollup.Inbox.t - and type 'a store = 'a store + with type key := Tezos_crypto.Block_hash.t + and type value := Sc_rollup.Inbox.t + and type 'a store := 'a store (** Histories from the rollup node. **) module Histories : Store_sigs.Append_only_map - with type key = Tezos_crypto.Block_hash.t - and type value = Sc_rollup.Inbox.History.t - and type 'a store = 'a store + with type key := Tezos_crypto.Block_hash.t + and type value := Sc_rollup.Inbox.History.t + and type 'a store := 'a store (** messages histories from the rollup node. Each history contains the messages of one level. The store is indexed by a level in order to maintain a small @@ -129,62 +127,40 @@ module Histories : computing the proof. *) module Payloads_histories : Store_sigs.Append_only_map - with type key = Sc_rollup.Inbox_merkelized_payload_hashes.Hash.t - and type value = Sc_rollup.Inbox_merkelized_payload_hashes.History.t - and type 'a store = 'a store + with type key := Sc_rollup.Inbox_merkelized_payload_hashes.Hash.t + and type value := Sc_rollup.Inbox_merkelized_payload_hashes.History.t + and type 'a store := 'a store (** Storage containing commitments and corresponding commitment hashes that the rollup node has knowledge of. *) module Commitments : Store_sigs.Append_only_map - with type key = Raw_level.t - and type value = Sc_rollup.Commitment.t * Sc_rollup.Commitment.Hash.t - and type 'a store = 'a store + with type key := Raw_level.t + and type value := Sc_rollup.Commitment.t * Sc_rollup.Commitment.Hash.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 contianing the inbox level of the last commitment published by the - rollup node. *) -module Last_published_commitment_level : - Store_sigs.Mutable_value - with type value = Raw_level.t - and type 'a store = 'a store - -(** Storage containing the inbox level of the last commitment cemented for the - rollup. The commitment has not been necessarily generated by this rollup - node. *) -module Last_cemented_commitment_level : - Store_sigs.Mutable_value - with type value = Raw_level.t - and type 'a store = 'a store - -(** torage containing the hash of the last commitment cemented for the rollup. - The commitment has not been necessarily generated by this rollup node. *) -module Last_cemented_commitment_hash : - Store_sigs.Mutable_value - with type value = Sc_rollup.Commitment.Hash.t - and type 'a store = 'a store + 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. *) module Commitments_published_at_level : Store_sigs.Map - with type key = Sc_rollup.Commitment.Hash.t - and type value = Raw_level.t - and type 'a store = 'a store + with type key := Sc_rollup.Commitment.Hash.t + and type value := Raw_level.t + and type 'a store := 'a store (** Storage containing the hashes of contexts retrieved from the L1 node. *) module Contexts : Store_sigs.Append_only_map - with type key = Tezos_crypto.Block_hash.t - and type value = Context.hash - and type 'a store = 'a store + with type key := Tezos_crypto.Block_hash.t + and type value := Context.hash + and type 'a store := 'a store (** Published slot headers per block hash, stored as a list of bindings from [Dal_slot_index.t] @@ -192,24 +168,24 @@ module Contexts : list into a [Dal.Slot_index.t]-indexed map. *) module Dal_slots_headers : Store_sigs.Nested_map - with type primary_key = Tezos_crypto.Block_hash.t - and type secondary_key = Dal.Slot_index.t - and type value = Dal.Slot.Header.t - and type 'a store = 'a store + with type primary_key := Tezos_crypto.Block_hash.t + and type secondary_key := Dal.Slot_index.t + and type value := Dal.Slot.Header.t + and type 'a store := 'a store module Dal_confirmed_slots_history : Store_sigs.Append_only_map - with type key = Tezos_crypto.Block_hash.t - and type value = Dal.Slots_history.t - and type 'a store = 'a store + with type key := Tezos_crypto.Block_hash.t + and type value := Dal.Slots_history.t + and type 'a store := 'a store (** Confirmed DAL slots histories cache. See documentation of {Dal_slot_repr.Slots_history} for more details. *) module Dal_confirmed_slots_histories : Store_sigs.Append_only_map - with type key = Tezos_crypto.Block_hash.t - and type value = Dal.Slots_history.History_cache.t - and type 'a store = 'a store + with type key := Tezos_crypto.Block_hash.t + and type value := Dal.Slots_history.History_cache.t + and type 'a store := 'a store (** [Dal_slot_pages] is a [Store_utils.Nested_map] used to store the contents of dal slots fetched by the rollup node, as a list of pages. The values of @@ -219,10 +195,10 @@ module Dal_confirmed_slots_histories : *) module Dal_slot_pages : Store_sigs.Nested_map - with type primary_key = Tezos_crypto.Block_hash.t - and type secondary_key = Dal.Slot_index.t * Dal.Page.Index.t - and type value = Dal.Page.content - and type 'a store = 'a store + with type primary_key := Tezos_crypto.Block_hash.t + and type secondary_key := Dal.Slot_index.t * Dal.Page.Index.t + and type value := Dal.Page.content + and type 'a store := 'a store (** [Dal_processed_slots] is a [Store_utils.Nested_map] used to store the processing status of dal slots content fetched by the rollup node. The values of @@ -233,7 +209,7 @@ module Dal_slot_pages : *) module Dal_processed_slots : Store_sigs.Nested_map - with type primary_key = Tezos_crypto.Block_hash.t - and type secondary_key = Dal.Slot_index.t - and type value = [`Confirmed | `Unconfirmed] - and type 'a store = 'a store + with type primary_key := Tezos_crypto.Block_hash.t + and type secondary_key := Dal.Slot_index.t + and type value := [`Confirmed | `Unconfirmed] + and type 'a store := 'a store diff --git a/src/proto_alpha/lib_plugin/RPC.ml b/src/proto_alpha/lib_plugin/RPC.ml index c4148ba2ab6d93ab94c1a50ad5b73a2cf322f13b..2f35b20c79e1a8f5a1149bc6f66c937eeb4c7d32 100644 --- a/src/proto_alpha/lib_plugin/RPC.ml +++ b/src/proto_alpha/lib_plugin/RPC.ml @@ -2027,12 +2027,15 @@ module Sc_rollup = struct let staked_on_commitment = RPC_service.get_service ~description: - "The hash of the newest commitment on which the operator has staked \ - on for a smart rollup. The hash can be absent if the staked \ - commitment is before the last cemented commitment, and therefore \ - the hash no longer exists in the context." + "The newest commitment on which the operator has staked on for a \ + smart rollup. Note that is can return a commitment that is before \ + the last cemented one." ~query:RPC_query.empty - ~output:(option Sc_rollup.Commitment.Hash.encoding) + ~output: + (option + (merge_objs + (obj1 (req "hash" Sc_rollup.Commitment.Hash.encoding)) + Sc_rollup.Commitment.encoding)) RPC_path.( path_sc_rollup / "staker" /: Sc_rollup.Staker.rpc_arg / "staked_on_commitment") @@ -2199,10 +2202,19 @@ module Sc_rollup = struct Registration.register2 ~chunked:false S.staked_on_commitment @@ fun ctxt address staker () () -> let open Lwt_result_syntax in - let* _ctxt, res = + let* ctxt, commitment_hash = Alpha_context.Sc_rollup.Stake_storage.find_staker ctxt address staker in - return res + match commitment_hash with + | None -> return_none + | Some commitment_hash -> + let* commitment, _ctxt = + Alpha_context.Sc_rollup.Commitment.get_commitment + ctxt + address + commitment_hash + in + return_some (commitment_hash, commitment) let register_commitment () = Registration.register2 ~chunked:false S.commitment @@ -2323,6 +2335,16 @@ module Sc_rollup = struct () () + let staked_on_commitment ctxt block sc_rollup_address staker = + RPC_context.make_call2 + S.staked_on_commitment + ctxt + block + sc_rollup_address + staker + () + () + let commitment ctxt block sc_rollup_address commitment_hash = RPC_context.make_call2 S.commitment diff --git a/tezt/tests/sc_rollup.ml b/tezt/tests/sc_rollup.ml index 7fbb96e7cdf1742c116001360d016b51ee1f1392..549fca4e558dfd5ed765eb025438db001bac1ef5 100644 --- a/tezt/tests/sc_rollup.ml +++ b/tezt/tests/sc_rollup.ml @@ -354,7 +354,7 @@ let get_staked_on_commitment ~sc_rollup ~staker client = ~sc_rollup staker in - match JSON.(json |> as_string_opt) with + match JSON.(json |-> "hash" |> as_string_opt) with | Some hash -> return hash | None -> failwith (Format.sprintf "hash is missing %s" __LOC__) @@ -791,15 +791,8 @@ let basic_scenario sc_rollup_node _rollup_client _sc_rollup _node client = in unit -(* Reactivate when the following TODO is fixed: - - FIXME: https://gitlab.com/tezos/tezos/-/issues/3205 - - The rollup node should be able to restart properly after an - abnormal interruption at every point of its process. Currently, - the state is not persistent enough and the processing is not - idempotent enough to achieve that property. *) -let _sc_rollup_node_stops_scenario sc_rollup_node _node client = +let sc_rollup_node_stops_scenario sc_rollup_node _rollup_client _sc_rollup _node + client = let num_messages = 2 in let expected_level = (* We start at level 2 and each message also bakes a block. With 2 messages being sent twice, we @@ -2135,7 +2128,7 @@ let first_published_level_is_global _protocol sc_rollup_node sc_rollup_client `init_level + sc_rollup_commitment_period_in_blocks` is processed by the rollup node as finalized. *) let* () = bake_levels block_finality_time client in - let* commitment_finalized_level = + let* _commitment_finalized_level = Sc_rollup_node.wait_for_level ~timeout:3. sc_rollup_node @@ -2153,8 +2146,9 @@ let first_published_level_is_global _protocol sc_rollup_node sc_rollup_client %R)" ; (* Bake an additional block for the commitment to be included. *) let* () = Client.bake_for_and_wait client in - let* commitment_publish_level = - Sc_rollup_node.wait_for_level sc_rollup_node (commitment_finalized_level + 1) + let commitment_publish_level = Node.get_level node in + let* _ = + Sc_rollup_node.wait_for_level sc_rollup_node commitment_publish_level in let*! rollup_node1_published_commitment = Sc_rollup_client.last_published_commitment ~hooks sc_rollup_client @@ -2179,16 +2173,25 @@ let first_published_level_is_global _protocol sc_rollup_node sc_rollup_client in let* () = Sc_rollup_node.run sc_rollup_node' [] in - let* rollup_node2_catchup_level = + let* _ = Sc_rollup_node.wait_for_level ~timeout:3. sc_rollup_node' - commitment_finalized_level + commitment_publish_level + in + let*! rollup_node2_published_commitment = + Sc_rollup_client.last_published_commitment ~hooks sc_rollup_client' + in + Check.( + Option.bind rollup_node2_published_commitment first_published_at_level + = None) + (Check.option Check.int) + ~error_msg:"Rollup node 2 cannot publish commitment without any new block." ; + let* () = Client.bake_for_and_wait client in + let commitment_publish_level2 = Node.get_level node in + let* _ = + Sc_rollup_node.wait_for_level sc_rollup_node' commitment_publish_level2 in - Check.(rollup_node2_catchup_level = commitment_finalized_level) - Check.int - ~error_msg:"Current level has moved past cementation inbox level (%L = %R)" ; - (* Check that no commitment was published. *) let*! rollup_node2_published_commitment = Sc_rollup_client.last_published_commitment ~hooks sc_rollup_client' in @@ -3208,7 +3211,7 @@ let test_timeout = ~staker2:operator2.public_key_hash client -(* Testing rollup node catch up mechanism +(* Testing rollup node catch up mechanism I -------------------------------------- The rollup node must be able to catch up from the genesis @@ -3216,17 +3219,111 @@ let test_timeout = *) let test_late_rollup_node = test_full_scenario + ~commitment_period:3 { tags = ["late"]; variant = None; description = "a late rollup should catch up"; } - @@ fun _protocol sc_rollup_node _rollup_client _sc_rollup_address _node client + @@ fun _protocol sc_rollup_node _rollup_client sc_rollup_address node client + -> + let* () = bake_levels 65 client in + let* () = Sc_rollup_node.run sc_rollup_node [] in + let* () = bake_levels 30 client in + let* _status = Sc_rollup_node.wait_for_level ~timeout:2. sc_rollup_node 95 in + Log.info "First rollup node synchronized." ; + let sc_rollup_node2 = + Sc_rollup_node.create + Operator + node + client + ~default_operator: + Constant.bootstrap1.alias (* Same as other rollup_node *) + in + let* _configuration_filename = + Sc_rollup_node.config_init sc_rollup_node2 sc_rollup_address + in + Log.info "Start rollup node from scratch with same operator" ; + let* () = Sc_rollup_node.run sc_rollup_node2 [] in + let* _level = + Sc_rollup_node.wait_for_level + ~timeout:2. + sc_rollup_node2 + (Node.get_level node) + in + Log.info "Other rollup node synchronized." ; + let* () = Client.bake_for_and_wait client in + let* _level = + Sc_rollup_node.wait_for_level + ~timeout:2. + sc_rollup_node2 + (Node.get_level node) + in + Log.info "Other rollup node progresses." ; + unit + +(* Testing rollup node catch up mechanism II + -------------------------------------- + + An alternative rollup node must be able to catch up from the genesis + of the rollup when paired with a node in archive mode when there is + already an other rollup node with a different operator already operating + on the given rollup. This same alternative rollup node must be able to + catch up a second time when it is stopped midway. +*) +let test_late_rollup_node_2 = + test_full_scenario + ~commitment_period:3 + { + tags = ["late"]; + variant = None; + description = "a late alternative rollup should catch up"; + } + @@ fun _protocol sc_rollup_node _rollup_client sc_rollup_address node client -> let* () = bake_levels 65 client in let* () = Sc_rollup_node.run sc_rollup_node [] in let* () = bake_levels 30 client in let* _status = Sc_rollup_node.wait_for_level ~timeout:2. sc_rollup_node 95 in + Log.info "First rollup node synchronized." ; + let sc_rollup_node2 = + Sc_rollup_node.create + Operator + node + client + ~default_operator:Constant.bootstrap2.alias + in + let* _configuration_filename = + Sc_rollup_node.config_init sc_rollup_node2 sc_rollup_address + in + Log.info + "Starting alternative rollup node from scratch with a different operator." ; + let* () = Sc_rollup_node.run sc_rollup_node2 [] in + let* _level = + Sc_rollup_node.wait_for_level + ~timeout:2. + sc_rollup_node2 + (Node.get_level node) + in + Log.info "Alternative rollup node is synchronized." ; + let* () = Client.bake_for_and_wait client in + let* _level = + Sc_rollup_node.wait_for_level + ~timeout:2. + sc_rollup_node2 + (Node.get_level node) + in + Log.info "Both rollup nodes are progressing and are synchronized." ; + let* () = Sc_rollup_node.terminate sc_rollup_node2 in + Log.info "Alternative rollup node terminated." ; + let* () = bake_levels 30 client in + let* () = Sc_rollup_node.run sc_rollup_node2 [] in + Log.info "Alternative rollup node is re-running." ; + let* () = bake_levels 30 client in + let* _ = Sc_rollup_node.wait_for_level ~timeout:2. sc_rollup_node2 155 in + Log.info + "Alternative rollup node is synchronized once again after being terminated \ + once." ; unit (* Test interruption of rollup node before the first inbox is processed. Upon @@ -3924,14 +4021,11 @@ let register ~kind ~protocols = basic_scenario protocols ; test_rpcs ~kind protocols ; - (* See above at definition of sc_rollup_node_stops_scenario: - - test_rollup_inbox_of_rollup_node - ~kind - "stops" - sc_rollup_node_stops_scenario - protocols ; - *) + test_rollup_inbox_of_rollup_node + ~kind + ~variant:"stops" + sc_rollup_node_stops_scenario + protocols ; test_rollup_inbox_of_rollup_node ~kind ~variant:"disconnects" @@ -4031,6 +4125,7 @@ let register ~kind ~protocols = Uncomment this test as soon as the issue done. test_reinject_failed_commitment protocols ~kind ; *) test_late_rollup_node protocols ~kind ; + test_late_rollup_node_2 protocols ~kind ; test_interrupt_rollup_node protocols ~kind ; test_outbox_message ~regression:true