diff --git a/src/proto_alpha/bin_sc_rollup_node/commitment.ml b/src/proto_alpha/bin_sc_rollup_node/commitment.ml index bb61b46a1a17e04ac5f5b0bf5e543eb2f0a20a68..cd1bd5599a30a1a89eefcad2a7f27e5323fa1acd 100644 --- a/src/proto_alpha/bin_sc_rollup_node/commitment.ml +++ b/src/proto_alpha/bin_sc_rollup_node/commitment.ml @@ -27,10 +27,11 @@ (** The rollup node stores and publishes commitments for the PVM every [Constants.sc_rollup_commitment_period_in_blocks] levels. - Every time a finalized block is processed by the rollup node, - the latter determines whether the last commitment that the node - has produced referred to 20 blocks earlier. In this case, it - computes and stores a new commitment in a level-indexed map. + Every time a finalized block is processed by the rollup node, the latter + determines whether the last commitment that the node has produced referred + to [sc_rollup.commitment_period_in_blocks] blocks earlier. For mainnet, + [sc_rollup.commitment_period_in_blocks = 30]. In this case, it computes and + stores a new commitment in a level-indexed map. Stored commitments are signed by the rollup node operator and published on the layer1 chain. To ensure that commitments @@ -289,7 +290,7 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct Store.Commitments.mem store next_level_to_publish in if is_commitment_available then - let*! commitment, commitment_hash = + let*! commitment, _commitment_hash = Store.Commitments.get store next_level_to_publish in let* predecessor_published = @@ -318,40 +319,29 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct commitment) else return_unit in - let* operator = Node_context.get_operator_keys node_ctxt Publish in + let operator = Node_context.get_operator node_ctxt Publish in match operator with | None -> (* Configured to not publish commitments *) return_unit - | Some (source, src_pk, src_sk) -> - let* _oph, _op, _results = - Client_proto_context.sc_rollup_publish - cctxt - ~chain:cctxt#chain - ~block:cctxt#block - ~commitment - ~source - ~rollup:rollup_address - ~src_pk - ~src_sk - ~fee_parameter:Configuration.default_fee_parameter - () + | Some source -> + let publish_operation = + Sc_rollup_publish {rollup = node_ctxt.rollup_address; commitment} in + let* () = 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 - let*! () = - Commitment_event.publish_commitment_injected - commitment_hash - commitment - in return_unit else return_unit - (* TODO: https://gitlab.com/tezos/tezos/-/issues/2869 - use the Injector to publish commitments. *) let publish_commitment node_ctxt store = let open Lwt_result_syntax in (* Check level of next publishable commitment and avoid publishing if it is @@ -414,35 +404,20 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct () else return_false - let cement_commitment ({Node_context.cctxt; rollup_address; _} as node_ctxt) - commitment commitment_hash = + let cement_commitment (node_ctxt : Node_context.t) commitment_hash = let open Lwt_result_syntax in - let* operator = Node_context.get_operator_keys node_ctxt Cement in + let operator = Node_context.get_operator node_ctxt Cement in match operator with | None -> (* Configured to not cement commitments *) return_unit - | Some (source, src_pk, src_sk) -> - let* _oph, _op, _results = - Client_proto_context.sc_rollup_cement - cctxt - ~chain:cctxt#chain - ~block:cctxt#block - ~commitment:commitment_hash - ~source - ~rollup:rollup_address - ~src_pk - ~src_sk - ~fee_parameter:Configuration.default_fee_parameter - () + | Some source -> + let cement_operation = + Sc_rollup_cement + {rollup = node_ctxt.rollup_address; commitment = commitment_hash} in - let*! () = - Commitment_event.cement_commitment_injected commitment_hash commitment - in - return_unit + Injector.add_pending_operation ~source cement_operation - (* TODO: https://gitlab.com/tezos/tezos/-/issues/3008 - Use the injector to cement commitments. *) let cement_commitment_if_possible node_ctxt store (Layer1.Head {level = head_level; _}) = let open Lwt_result_syntax in @@ -459,7 +434,7 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct match commitment_with_hash with (* If `commitment_with_hash` is defined, the commitment to be cemented has been stored but not necessarily published by the rollup node. *) - | Some (commitment, commitment_hash) -> ( + | Some (_commitment, commitment_hash) -> ( let*! earliest_cementing_level = earliest_cementing_level node_ctxt store commitment_hash in @@ -475,8 +450,7 @@ module Make (PVM : Pvm.S) : Commitment_sig.S with module PVM = PVM = struct head_level commitment_hash in - if green_flag then - cement_commitment node_ctxt commitment commitment_hash + if green_flag then cement_commitment node_ctxt commitment_hash else return () | None -> return ()) | None -> return () diff --git a/src/proto_alpha/bin_sc_rollup_node/commitment_event.ml b/src/proto_alpha/bin_sc_rollup_node/commitment_event.ml index 21e3b871dde349146e61d3c8826d37806dfdddfc..cabbeba01348a5ed3db415e3860437a47d5cc298 100644 --- a/src/proto_alpha/bin_sc_rollup_node/commitment_event.ml +++ b/src/proto_alpha/bin_sc_rollup_node/commitment_event.ml @@ -113,22 +113,6 @@ module Simple = struct ("inbox_level", Raw_level.encoding) ("compressed_state", Sc_rollup.State_hash.encoding) ("number_of_ticks", Sc_rollup.Number_of_ticks.encoding) - - let commitment_injected kind = - declare_5 - ~section - ~name:(Printf.sprintf "sc_rollup_%s_commitment_injected" kind) - ~msg: - (kind - ^ " commitment {commitment_hash} was injected - predecessor: \ - {predecessor}, inbox_level: {inbox_level}, compressed_state: \ - {compressed_state}, number_of_ticks: {number_of_ticks}") - ~level:Notice - ("commitment_hash", Sc_rollup.Commitment.Hash.encoding) - ("predecessor", Sc_rollup.Commitment.Hash.encoding) - ("inbox_level", Raw_level.encoding) - ("compressed_state", Sc_rollup.State_hash.encoding) - ("number_of_ticks", Sc_rollup.Number_of_ticks.encoding) end let starting = Simple.(emit starting) @@ -157,12 +141,6 @@ let commitment_will_not_be_published lcc_level let commitment_stored = emit_commitment_event Simple.commitment_stored -let publish_commitment_injected = - emit_commitment_event (Simple.commitment_injected "publish") - -let cement_commitment_injected = - emit_commitment_event (Simple.commitment_injected "cement") - let last_cemented_commitment_updated head level = Simple.(emit last_cemented_commitment_updated (head, level)) diff --git a/src/proto_alpha/bin_sc_rollup_node/commitment_event.mli b/src/proto_alpha/bin_sc_rollup_node/commitment_event.mli index ed11abd1caadd6067e3a3606e4fe676b42084c4f..d818ad4d49315f2153c61e7619690f1455bd5e61 100644 --- a/src/proto_alpha/bin_sc_rollup_node/commitment_event.mli +++ b/src/proto_alpha/bin_sc_rollup_node/commitment_event.mli @@ -32,15 +32,6 @@ val starting : unit -> unit Lwt.t val stopping : unit -> unit Lwt.t -(** The functions below emit commitment events depending on whether they are - being published or cemented. *) - -val publish_commitment_injected : - Sc_rollup.Commitment.Hash.t -> Sc_rollup.Commitment.t -> unit Lwt.t - -val cement_commitment_injected : - Sc_rollup.Commitment.Hash.t -> Sc_rollup.Commitment.t -> unit Lwt.t - (** [commitment_stored commitment_hash commitment] emits the event that the [commitment] was stored. *) val commitment_stored : diff --git a/src/proto_alpha/bin_sc_rollup_node/configuration.ml b/src/proto_alpha/bin_sc_rollup_node/configuration.ml index 1bf62dae3f4d221aef7a2cfe3813455343c982b7..0d6607bc7047bf33684a6bd84124d9a05a693383 100644 --- a/src/proto_alpha/bin_sc_rollup_node/configuration.ml +++ b/src/proto_alpha/bin_sc_rollup_node/configuration.ml @@ -28,9 +28,9 @@ open Protocol.Alpha_context type mode = Observer | Batcher | Maintenance | Operator | Custom -type purpose = Publish | Add_messages | Cement | Refute +type purpose = Publish | Add_messages | Cement | Timeout | Refute -let purposes = [Publish; Add_messages; Cement; Refute] +let purposes = [Publish; Add_messages; Cement; Timeout; Refute] module Operator_purpose_map = Map.Make (struct type t = purpose @@ -104,12 +104,14 @@ let string_of_purpose = function | Publish -> "publish" | Add_messages -> "add_messages" | Cement -> "cement" + | Timeout -> "timeout" | Refute -> "refute" let purpose_of_string = function | "publish" -> Some Publish | "add_messages" -> Some Add_messages | "cement" -> Some Cement + | "timeout" -> Some Timeout | "refute" -> Some Refute | _ -> None @@ -118,8 +120,24 @@ let purpose_of_string_exn s = | Some p -> p | None -> invalid_arg ("purpose_of_string " ^ s) +let add_fallbacks map fallbacks = + List.fold_left + (fun map (missing_purpose, fallback_purpose) -> + if Operator_purpose_map.mem missing_purpose map then + (* No missing purpose, don't fallback *) + map + else + match Operator_purpose_map.find fallback_purpose map with + | None -> + (* Nothing to fallback on *) + map + | Some operator -> Operator_purpose_map.add missing_purpose operator map) + map + fallbacks + let make_purpose_map ~default bindings = let map = Operator_purpose_map.of_seq @@ List.to_seq bindings in + let map = add_fallbacks map [(Timeout, Refute)] in match default with | None -> map | Some default -> diff --git a/src/proto_alpha/bin_sc_rollup_node/configuration.mli b/src/proto_alpha/bin_sc_rollup_node/configuration.mli index f1101793810d3504f91bfb2fb08308c0f1672bec..0e7334060cb0ecee39ea68fa50abfa06371ac7dc 100644 --- a/src/proto_alpha/bin_sc_rollup_node/configuration.mli +++ b/src/proto_alpha/bin_sc_rollup_node/configuration.mli @@ -35,7 +35,7 @@ type mode = the signers *) (** Purposes for operators, indicating the kind of operations that they sign. *) -type purpose = Publish | Add_messages | Cement | Refute +type purpose = Publish | Add_messages | Cement | Timeout | Refute module Operator_purpose_map : Map.S with type key = purpose diff --git a/src/proto_alpha/bin_sc_rollup_node/daemon.ml b/src/proto_alpha/bin_sc_rollup_node/daemon.ml index d25ebbc934886a5e1be1d0bbf5ef2a17457680d5..76377c663739833eb1fe05aca80ba080cabe0a8b 100644 --- a/src/proto_alpha/bin_sc_rollup_node/daemon.ml +++ b/src/proto_alpha/bin_sc_rollup_node/daemon.ml @@ -205,6 +205,15 @@ module Make (PVM : Pvm.S) = struct let*! () = Layer1.mark_processed_head store head in return ()) + let notify_injector l1_ctxt store chain_event = + let open Lwt_result_syntax in + let open Layer1 in + let hash = chain_event_head_hash chain_event in + let* head = fetch_tezos_block l1_ctxt hash in + let* reorg = get_tezos_reorg_for_new_head l1_ctxt store hash in + let*! () = Injector.new_tezos_head head reorg in + return_unit + (* [on_layer_1_chain_event node_ctxt store chain_event] processes a list of heads, coming either from a list of [old_heads] persisted in the store, or from the current [chain_event]. [old_heads] is a list of heads @@ -237,6 +246,7 @@ module Make (PVM : Pvm.S) = struct node_ctxt store in + let* () = notify_injector node_ctxt.l1_ctxt store chain_event in let* non_final_heads = match chain_event with | SameBranch {new_head; intermediate_heads} -> @@ -285,6 +295,7 @@ module Make (PVM : Pvm.S) = struct in let*! () = Layer1.set_heads_not_finalized store non_final_heads in let*! () = Layer1.processed chain_event in + let*! () = Injector.inject () in return_unit let is_connection_error trace = @@ -381,6 +392,28 @@ module Make (PVM : Pvm.S) = struct in let*! () = Inbox.start () in let*! () = Components.Commitment.start () in + let signers = + Configuration.Operator_purpose_map.bindings node_ctxt.operators + |> List.fold_left + (fun acc (purpose, operator) -> + let purposes = + match Signature.Public_key_hash.Map.find operator acc with + | None -> [purpose] + | Some ps -> purpose :: ps + in + Signature.Public_key_hash.Map.add operator purposes acc) + Signature.Public_key_hash.Map.empty + |> Signature.Public_key_hash.Map.bindings + |> List.map (fun (operator, purposes) -> + (operator, `Each_block, purposes)) + in + let* () = + Injector.init + node_ctxt.cctxt + node_ctxt + ~data_dir:configuration.data_dir + ~signers + in let*! () = Event.node_is_ready diff --git a/src/proto_alpha/bin_sc_rollup_node/injector.ml b/src/proto_alpha/bin_sc_rollup_node/injector.ml new file mode 100644 index 0000000000000000000000000000000000000000..484e2fc263131dcd94408ef0165f6748b7f05a38 --- /dev/null +++ b/src/proto_alpha/bin_sc_rollup_node/injector.ml @@ -0,0 +1,155 @@ +(*****************************************************************************) +(* *) +(* 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 +open Injector_sigs + +module Parameters : + PARAMETERS + with type rollup_node_state = Node_context.t + and type Tag.t = Configuration.purpose = struct + type rollup_node_state = Node_context.t + + let events_section = ["sc_rollup.injector"] + + module Tag : TAG with type t = Configuration.purpose = struct + type t = Configuration.purpose + + let compare = Stdlib.compare + + let equal = Stdlib.( = ) + + let hash = Hashtbl.hash + + let string_of_tag = Configuration.string_of_purpose + + let pp ppf t = Format.pp_print_string ppf (string_of_tag t) + + let encoding : t Data_encoding.t = + let open Data_encoding in + string_enum + (List.map (fun t -> (string_of_tag t, t)) Configuration.purposes) + end + + (* TODO: https://gitlab.com/tezos/tezos/-/issues/3459 + Very coarse approximation for the number of operation we + expect for each block *) + let table_estimated_size : Tag.t -> int = function + | Publish -> 1 + | Add_messages -> 100 + | Cement -> 1 + | Timeout -> 1 + | Refute -> 1 + + let fee_parameter {Node_context.fee_parameter; _} _ = fee_parameter + + (* Below are dummy values that are only used to approximate the + size. It is thus important that they remain above the real + values if we want the computed size to be an over_approximation + (without having to do a simulation first). *) + (* TODO: https://gitlab.com/tezos/tezos/-/issues/3461 + Fee parameter per operation. + + See TORU issue: https://gitlab.com/tezos/tezos/-/issues/2812 + check the size, or compute them wrt operation kind *) + let approximate_fee_bound _ _ = + { + fee = Tez.of_mutez_exn 3_000_000L; + counter = Z.of_int 500_000; + gas_limit = Gas.Arith.integral_of_int_exn 500_000; + storage_limit = Z.of_int 500_000; + } + + (* TODO: https://gitlab.com/tezos/tezos/-/issues/3459 + Decide if some batches must have all the operations succeed. See + {!Injector_sigs.Parameter.batch_must_succeed}. *) + let batch_must_succeed _ = `At_least_one + + let ignore_failing_operation : + type kind. + kind manager_operation -> [`Ignore_keep | `Ignore_drop | `Don't_ignore] = + function + | Sc_rollup_timeout _ | Sc_rollup_refute _ -> + (* Failing timeout and refutation operations can be ignored. *) + `Ignore_drop + | _ -> `Don't_ignore + + (** Returns [true] if an included operation should be re-queued for injection + when the block in which it is included is reverted (due to a + reorganization). *) + let requeue_reverted_operation (type kind) _node_ctxt + (operation : kind manager_operation) = + let open Lwt_syntax in + match operation with + | Sc_rollup_publish _ -> + (* Commitments are always produced on finalized blocks. They don't need + to be recomputed, and as such are valid in another branch. *) + return_true + | Sc_rollup_cement _ -> + (* TODO: https://gitlab.com/tezos/tezos/-/issues/3348 + The cementation operations should be re-injected because the node only + keeps track of the last cemented level and the last published + commitment, without rollbacks. + *) + return_true + | Sc_rollup_add_messages _ -> + (* Messages posted to an inbox should be re-emitted (i.e. re-queued) in + case of a fork. *) + return_true + | Sc_rollup_timeout _ -> + (* Timeout should be re-submitted as the timeout may be reached as well + on the other branch *) + return_true + | Sc_rollup_refute _ -> + (* TODO: https://gitlab.com/tezos/tezos/-/issues/3459 + maybe check if game exists on other branch as well. + + Refutation should be re-submitted in case of fork. + *) + return_true + | Reveal _ | Transaction _ | Origination _ | Delegation _ + | Register_global_constant _ | Set_deposits_limit _ + | Increase_paid_storage _ | Tx_rollup_origination | Tx_rollup_submit_batch _ + | Tx_rollup_commit _ | Tx_rollup_return_bond _ + | Tx_rollup_finalize_commitment _ | Tx_rollup_remove_commitment _ + | Tx_rollup_rejection _ | Tx_rollup_dispatch_tickets _ | Transfer_ticket _ + | Dal_publish_slot_header _ | Sc_rollup_originate _ + | Sc_rollup_execute_outbox_message _ | Sc_rollup_recover_bond _ + | Sc_rollup_dal_slot_subscribe _ -> + (* These operations should never be handled by this injector *) + assert false + + let operation_tag (type kind) (operation : kind manager_operation) : + Tag.t option = + match operation with + | Sc_rollup_add_messages _ -> Some Add_messages + | Sc_rollup_cement _ -> Some Cement + | Sc_rollup_publish _ -> Some Publish + | Sc_rollup_timeout _ -> Some Timeout + | Sc_rollup_refute _ -> Some Refute + | _ -> None +end + +include Injector_functor.Make (Parameters) diff --git a/src/proto_alpha/bin_sc_rollup_node/injector.mli b/src/proto_alpha/bin_sc_rollup_node/injector.mli new file mode 100644 index 0000000000000000000000000000000000000000..c08bb06e06d7f07debf10827f5925e98764a73e8 --- /dev/null +++ b/src/proto_alpha/bin_sc_rollup_node/injector.mli @@ -0,0 +1,29 @@ +(*****************************************************************************) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +include + Injector_sigs.S + with type rollup_node_state := Node_context.t + and type tag := Configuration.purpose 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 c1da77faab236232c0b90321b88c259b2f9724fa..38712b2d60e59fc7405328b59cf7d141dcc206ec 100644 --- a/src/proto_alpha/bin_sc_rollup_node/node_context.ml +++ b/src/proto_alpha/bin_sc_rollup_node/node_context.ml @@ -39,13 +39,8 @@ type t = { loser_mode : Loser_mode.t; } -let get_operator_keys node_ctxt purpose = - let open Lwt_result_syntax in - match Configuration.Operator_purpose_map.find purpose node_ctxt.operators with - | None -> return_none - | Some operator -> - let+ _, pk, sk = Client_keys.get_key node_ctxt.cctxt operator in - Some (operator, pk, sk) +let get_operator node_ctxt purpose = + Configuration.Operator_purpose_map.find purpose node_ctxt.operators (* TODO: https://gitlab.com/tezos/tezos/-/issues/2901 The constants are retrieved from the latest tezos block. These constants can 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 3591bb45e4746d494c505599810dadc1aba37749..9dd96cfb344d55f50fd338018d3b8b822f20146c 100644 --- a/src/proto_alpha/bin_sc_rollup_node/node_context.mli +++ b/src/proto_alpha/bin_sc_rollup_node/node_context.mli @@ -51,16 +51,11 @@ type t = { issues wrong commitments (for tests). *) } -(** [get_operator_keys cctxt] returns a triple [(pkh, pk, sk)] corresponding - to the address, public key, and secret key URI of the rollup node operator. +(** [get_operator cctxt purpose] returns the public key hash for the operator + who has purpose [purpose], if any. *) -val get_operator_keys : - t -> - Configuration.purpose -> - (Signature.Public_key_hash.t * Signature.Public_key.t * Client_keys.sk_uri) - option - tzresult - Lwt.t +val get_operator : + t -> Configuration.purpose -> Signature.Public_key_hash.t option (** [init cctxt l1_ctxt sc_rollup operators_pkh] initialises the rollup representation. The rollup origination level and kind are fetched via an 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 45b4c1d7a070059d9569bb196021b6cb0f313c70..8e01e19e10379157b7fe8d85d076c1a19c21eae6 100644 --- a/src/proto_alpha/bin_sc_rollup_node/refutation_game.ml +++ b/src/proto_alpha/bin_sc_rollup_node/refutation_game.ml @@ -74,29 +74,15 @@ module Make (PVM : Pvm.S) : S with module PVM = PVM = struct | Alice, Bob -> Their_turn | Bob, Alice -> Their_turn - (** [inject_next_move node_ctxt signer ~refuation ~opponent] submits an L1 - operation (signed by [signer]) to issue the next move in the refutation - game. [node_ctxt] provides the connection to the Tezos node. *) - let inject_next_move node_ctxt (source, src_pk, src_sk) ~refutation ~opponent + (** [inject_next_move node_ctxt source ~refuation ~opponent] submits an L1 + operation (signed by [source]) to issue the next move in the refutation + game. *) + let inject_next_move (node_ctxt : Node_context.t) source ~refutation ~opponent = - let open Node_context in - let open Lwt_result_syntax in - let {rollup_address; cctxt; _} = node_ctxt in - let* _oph, _op, _results = - Client_proto_context.sc_rollup_refute - cctxt - ~chain:cctxt#chain - ~block:cctxt#block - ~refutation - ~opponent - ~source - ~rollup:rollup_address - ~src_pk - ~src_sk - ~fee_parameter:Configuration.default_fee_parameter - () + let refute_operation = + Sc_rollup_refute {rollup = node_ctxt.rollup_address; refutation; opponent} in - return_unit + Injector.add_pending_operation ~source refute_operation let generate_proof node_ctxt store game start_state = let open Lwt_result_syntax in @@ -226,44 +212,20 @@ module Make (PVM : Pvm.S) : S with module PVM = PVM = struct if Z.(equal chosen_section_len one) then final_move choice else return {choice; step = Dissection dissection} - let try_ f = - let open Lwt_result_syntax in - let*! _res = f () in - return_unit - - let play_next_move node_ctxt store game signer opponent = + let play_next_move node_ctxt store game self opponent = let open Lwt_result_syntax in let* refutation = next_move node_ctxt store game in - (* FIXME: #3008 - - We currently do not remember that we already have - injected a refutation move but it is not included yet. - Hence, we ignore errors here temporarily, waiting for - the injector to enter the scene. - *) - try_ @@ fun () -> - inject_next_move node_ctxt signer ~refutation:(Some refutation) ~opponent + inject_next_move node_ctxt self ~refutation:(Some refutation) ~opponent - let play_timeout node_ctxt (source, src_pk, src_sk) players = - let Sc_rollup.Game.Index.{alice; bob} = players in - let open Node_context in - let open Lwt_result_syntax in - let {rollup_address; cctxt; _} = node_ctxt in - let* _oph, _op, _results = - Client_proto_context.sc_rollup_timeout - cctxt - ~chain:cctxt#chain - ~block:cctxt#block - ~source - ~alice - ~bob - ~rollup:rollup_address - ~src_pk - ~src_sk - ~fee_parameter:Configuration.default_fee_parameter - () + let play_timeout (node_ctxt : Node_context.t) self stakers = + let timeout_operation = + Sc_rollup_timeout {rollup = node_ctxt.rollup_address; stakers} + in + let source = + Node_context.get_operator node_ctxt Timeout |> Option.value ~default:self + (* We fallback on the [Refute] operator if none is provided for [Timeout] *) in - return_unit + Injector.add_pending_operation ~source timeout_operation let timeout_reached ~self head_block node_ctxt players = let open Lwt_result_syntax in @@ -284,19 +246,17 @@ module Make (PVM : Pvm.S) : S with module PVM = PVM = struct | None -> return_false | Some _myself -> return_false - let play head_block node_ctxt store ((self, _, _) as signer) game staker1 - staker2 = + let play head_block node_ctxt store self game staker1 staker2 = let open Lwt_result_syntax in let players = (staker1, staker2) in let index = Sc_rollup.Game.Index.make staker1 staker2 in match turn ~self game index with - | Our_turn {opponent} -> play_next_move node_ctxt store game signer opponent + | Our_turn {opponent} -> play_next_move node_ctxt store game self opponent | Their_turn -> let* timeout_reached = timeout_reached ~self head_block node_ctxt players in - unless timeout_reached @@ fun () -> - try_ @@ fun () -> play_timeout node_ctxt signer index + unless timeout_reached @@ fun () -> play_timeout node_ctxt self index let ongoing_game head_block node_ctxt self = let Node_context.{rollup_address; cctxt; _} = node_ctxt in @@ -307,13 +267,13 @@ module Make (PVM : Pvm.S) : S with module PVM = PVM = struct self () - let play_opening_move node_ctxt signer conflict = + let play_opening_move node_ctxt self conflict = let open Lwt_syntax in let open Sc_rollup.Refutation_storage in let* () = Refutation_game_event.conflict_detected conflict in - inject_next_move node_ctxt signer ~refutation:None ~opponent:conflict.other + inject_next_move node_ctxt self ~refutation:None ~opponent:conflict.other - let start_game_if_conflict head_block node_ctxt ((self, _, _) as signer) = + let start_game_if_conflict head_block node_ctxt self = let open Lwt_result_syntax in let Node_context.{rollup_address; cctxt; _} = node_ctxt in let* conflicts = @@ -325,7 +285,7 @@ module Make (PVM : Pvm.S) : S with module PVM = PVM = struct () in let*! res = - Option.iter_es (play_opening_move node_ctxt signer) (List.hd conflicts) + Option.iter_es (play_opening_move node_ctxt self) (List.hd conflicts) in match res with | Ok r -> return r @@ -342,15 +302,15 @@ module Make (PVM : Pvm.S) : S with module PVM = PVM = struct let process (Layer1.Head {hash; _}) node_ctxt store = let head_block = `Hash (hash, 0) in let open Lwt_result_syntax in - let* signer = Node_context.get_operator_keys node_ctxt Refute in - match signer with + let refute_signer = Node_context.get_operator node_ctxt Refute in + match refute_signer with | None -> (* Not injecting refutations, don't play refutation games *) return_unit - | Some ((self, _, _) as signer) -> ( + | Some self -> ( let* res = ongoing_game head_block node_ctxt self in match res with | Some (game, staker1, staker2) -> - play head_block node_ctxt store signer game staker1 staker2 - | None -> start_game_if_conflict head_block node_ctxt signer) + play head_block node_ctxt store self game staker1 staker2 + | None -> start_game_if_conflict head_block node_ctxt self) end diff --git a/src/proto_alpha/lib_injector/injector_functor.ml b/src/proto_alpha/lib_injector/injector_functor.ml index b5d351877957832c5e670fc019803e004ee2e22b..fb59e8ed1338dbb033509c71d69bc5d8f0cf2552 100644 --- a/src/proto_alpha/lib_injector/injector_functor.ml +++ b/src/proto_alpha/lib_injector/injector_functor.ml @@ -709,7 +709,7 @@ module Make (Rollup : PARAMETERS) = struct (fun op -> Op_queue.remove state.queue op.L1_operation.hash) injected_operations in - add_injected_operations state oph operations_to_inject + add_injected_operations state oph injected_operations | `Ignored operations_to_drop -> (* Injection failed but we ignore the failure. *) let* () = diff --git a/src/proto_alpha/lib_injector/l1_operation.ml b/src/proto_alpha/lib_injector/l1_operation.ml index e801c9a852b16ee35dec9e335d70c3797a4f99f0..e426875631cb4fd615e8b39f7aa04243d51403ea 100644 --- a/src/proto_alpha/lib_injector/l1_operation.ml +++ b/src/proto_alpha/lib_injector/l1_operation.ml @@ -157,6 +157,30 @@ module Manager_operation = struct level (Format.pp_print_list pp_rollup_reveal) tickets_info + | Sc_rollup_add_messages {rollup; messages} -> + Format.fprintf + ppf + "publishing %d messages to rollup %a inbox" + (List.length messages) + Sc_rollup.Address.pp + rollup + | Sc_rollup_cement {rollup; commitment} -> + Format.fprintf + ppf + "cementing commitment %a of rollup %a" + Sc_rollup.Commitment.Hash.pp + commitment + Sc_rollup.Address.pp + rollup + | Sc_rollup_publish + {rollup; commitment = Sc_rollup.Commitment.{inbox_level; _}} -> + Format.fprintf + ppf + "publish commitment for level %a of rollup %a" + Raw_level.pp + inbox_level + Sc_rollup.Address.pp + rollup | _ -> pp_kind ppf op end