From 0b21947a2f052982ffd4fe815275e4a41dc3fc88 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 18 Jul 2023 12:32:33 +0200 Subject: [PATCH 01/17] Proto/Alpha/SCORU: expose Inbox history proof encoding in Alpha_context --- src/proto_alpha/lib_protocol/alpha_context.mli | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 691c1b093922..a319cbc5d89b 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2996,6 +2996,8 @@ module Sc_rollup : sig val old_levels_messages : t -> history_proof + val history_proof_encoding : history_proof Data_encoding.t + val equal_history_proof : history_proof -> history_proof -> bool val pp_history_proof : Format.formatter -> history_proof -> unit -- GitLab From 2232fa21cac29b2f1b1855f62177e50913dd1a9f Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 29 Jun 2023 14:05:04 +0200 Subject: [PATCH 02/17] SCORU/Node: add protocol agnostic representation for games --- src/lib_smart_rollup/game.ml | 336 ++++++++++++++++++++++++++-------- src/lib_smart_rollup/game.mli | 91 +++++++-- 2 files changed, 335 insertions(+), 92 deletions(-) diff --git a/src/lib_smart_rollup/game.ml b/src/lib_smart_rollup/game.ml index ab17ca00e1db..ad90253534a8 100644 --- a/src/lib_smart_rollup/game.ml +++ b/src/lib_smart_rollup/game.ml @@ -23,90 +23,280 @@ (* *) (*****************************************************************************) -type dissection_chunk = {state_hash : State_hash.t option; tick : Z.t} +module V1 = struct + type dissection_chunk = {state_hash : State_hash.t option; tick : Z.t} -type step = Dissection of dissection_chunk list | Proof of string + type step = Dissection of dissection_chunk list | Proof of string -type refutation = - | Start of { - player_commitment_hash : Commitment.Hash.t; - opponent_commitment_hash : Commitment.Hash.t; - } - | Move of {choice : Z.t; step : step} + type refutation = + | Start of { + player_commitment_hash : Commitment.Hash.t; + opponent_commitment_hash : Commitment.Hash.t; + } + | Move of {choice : Z.t; step : step} -type index = { - alice : Signature.Public_key_hash.t; - bob : Signature.Public_key_hash.t; -} + type index = { + alice : Signature.Public_key_hash.t; + bob : Signature.Public_key_hash.t; + } -let make_index a b = - let alice, bob = - if Signature.Public_key_hash.(a > b) then (b, a) else (a, b) - in - {alice; bob} + let make_index a b = + let alice, bob = + if Signature.Public_key_hash.(a > b) then (b, a) else (a, b) + in + {alice; bob} -let index_encoding = - let open Data_encoding in - conv - (fun {alice; bob} -> (alice, bob)) - (fun (alice, bob) -> make_index alice bob) - (obj2 - (req "alice" Signature.Public_key_hash.encoding) - (req "bob" Signature.Public_key_hash.encoding)) - -let dissection_chunk_encoding = - let open Data_encoding in - conv - (fun {state_hash; tick} -> (state_hash, tick)) - (fun (state_hash, tick) -> {state_hash; tick}) - (obj2 (opt "state" State_hash.encoding) (req "tick" n)) + let equal_dissection_chunk c1 c2 = + Z.equal c1.tick c2.tick + && Option.equal State_hash.equal c1.state_hash c2.state_hash -let dissection_encoding = Data_encoding.list dissection_chunk_encoding + let index_encoding = + let open Data_encoding in + conv + (fun {alice; bob} -> (alice, bob)) + (fun (alice, bob) -> make_index alice bob) + (obj2 + (req "alice" Signature.Public_key_hash.encoding) + (req "bob" Signature.Public_key_hash.encoding)) -let step_encoding = - let open Data_encoding in - union - ~tag_size:`Uint8 - [ - case - ~title:"Dissection" - (Tag 0) - dissection_encoding - (function Dissection d -> Some d | _ -> None) - (fun d -> Dissection d); - case - ~title:"Proof" - (Tag 1) - (string' Hex) - (function Proof p -> Some p | _ -> None) - (fun p -> Proof p); - ] + let dissection_chunk_encoding = + let open Data_encoding in + conv + (fun {state_hash; tick} -> (state_hash, tick)) + (fun (state_hash, tick) -> {state_hash; tick}) + (obj2 (opt "state" State_hash.encoding) (req "tick" n)) + + let dissection_encoding = Data_encoding.list dissection_chunk_encoding + + let step_encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + ~title:"Dissection" + (Tag 0) + dissection_encoding + (function Dissection d -> Some d | _ -> None) + (fun d -> Dissection d); + case + ~title:"Proof" + (Tag 1) + (string' Hex) + (function Proof p -> Some p | _ -> None) + (fun p -> Proof p); + ] + + let refutation_encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + ~title:"Start" + (Tag 0) + (obj3 + (req "refutation_kind" (constant "start")) + (req "player_commitment_hash" Commitment.Hash.encoding) + (req "opponent_commitment_hash" Commitment.Hash.encoding)) + (function + | Start {player_commitment_hash; opponent_commitment_hash} -> + Some ((), player_commitment_hash, opponent_commitment_hash) + | _ -> None) + (fun ((), player_commitment_hash, opponent_commitment_hash) -> + Start {player_commitment_hash; opponent_commitment_hash}); + case + ~title:"Move" + (Tag 1) + (obj3 + (req "refutation_kind" (constant "move")) + (req "choice" n) + (req "step" step_encoding)) + (function + | Move {choice; step} -> Some ((), choice, step) | _ -> None) + (fun ((), choice, step) -> Move {choice; step}); + ] + + type conflict = { + other : Signature.Public_key_hash.t; + their_commitment : Commitment.t; + our_commitment : Commitment.t; + parent_commitment : Commitment.Hash.t; + } -let refutation_encoding = + let conflict_encoding = + Data_encoding.( + conv + (fun {other; their_commitment; our_commitment; parent_commitment} -> + (other, their_commitment, our_commitment, parent_commitment)) + (fun (other, their_commitment, our_commitment, parent_commitment) -> + {other; their_commitment; our_commitment; parent_commitment}) + (obj4 + (req "other" Signature.Public_key_hash.encoding) + (req "their_commitment" Commitment.encoding) + (req "our_commitment" Commitment.encoding) + (req "parent_commitment" Commitment.Hash.encoding))) + + type player = Alice | Bob + + type game_state = + | Dissecting of { + dissection : dissection_chunk list; + default_number_of_sections : int; + } + | Final_move of { + agreed_start_chunk : dissection_chunk; + refuted_stop_chunk : dissection_chunk; + } + + type t = { + turn : player; + inbox_snapshot : Inbox.V1.history_proof; + dal_snapshot : Dal.Slot_history.t; + start_level : int32; + inbox_level : int32; + game_state : game_state; + } + + let game_state_equal gs1 gs2 = + match (gs1, gs2) with + | ( Dissecting + { + dissection = dissection1; + default_number_of_sections = default_number_of_sections1; + }, + Dissecting + { + dissection = dissection2; + default_number_of_sections = default_number_of_sections2; + } ) -> + Compare.Int.equal + default_number_of_sections1 + default_number_of_sections2 + && List.equal equal_dissection_chunk dissection1 dissection2 + | Dissecting _, _ -> false + | ( Final_move + { + agreed_start_chunk = agreed_start_chunk1; + refuted_stop_chunk = refuted_stop_chunk1; + }, + Final_move + { + agreed_start_chunk = agreed_start_chunk2; + refuted_stop_chunk = refuted_stop_chunk2; + } ) -> + equal_dissection_chunk agreed_start_chunk1 agreed_start_chunk2 + && equal_dissection_chunk refuted_stop_chunk1 refuted_stop_chunk2 + | Final_move _, _ -> false + + let player_encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + ~title:"Alice" + (Tag 0) + (constant "alice") + (function Alice -> Some () | _ -> None) + (fun () -> Alice); + case + ~title:"Bob" + (Tag 1) + (constant "bob") + (function Bob -> Some () | _ -> None) + (fun () -> Bob); + ] + + let game_state_encoding = + let open Data_encoding in + union + ~tag_size:`Uint8 + [ + case + ~title:"Dissecting" + (Tag 0) + (obj3 + (req "kind" (constant "Dissecting")) + (req "dissection" dissection_encoding) + (req "default_number_of_sections" uint8)) + (function + | Dissecting {dissection; default_number_of_sections} -> + Some ((), dissection, default_number_of_sections) + | _ -> None) + (fun ((), dissection, default_number_of_sections) -> + Dissecting {dissection; default_number_of_sections}); + case + ~title:"Final_move" + (Tag 1) + (obj3 + (req "kind" (constant "Final_move")) + (req "agreed_start_chunk" dissection_chunk_encoding) + (req "refuted_stop_chunk" dissection_chunk_encoding)) + (function + | Final_move {agreed_start_chunk; refuted_stop_chunk} -> + Some ((), agreed_start_chunk, refuted_stop_chunk) + | _ -> None) + (fun ((), agreed_start_chunk, refuted_stop_chunk) -> + Final_move {agreed_start_chunk; refuted_stop_chunk}); + ] + + let encoding = + let open Data_encoding in + conv + (fun { + turn; + inbox_snapshot; + dal_snapshot; + start_level; + inbox_level; + game_state; + } -> + ( turn, + inbox_snapshot, + dal_snapshot, + start_level, + inbox_level, + game_state )) + (fun ( turn, + inbox_snapshot, + dal_snapshot, + start_level, + inbox_level, + game_state ) -> + { + turn; + inbox_snapshot; + dal_snapshot; + start_level; + inbox_level; + game_state; + }) + (obj6 + (req "turn" player_encoding) + (req "inbox_snapshot" Inbox.V1.history_proof_encoding) + (req "dal_snapshot" (dynamic_size Dal.Slot_history.encoding)) + (req "start_level" int32) + (req "inbox_level" int32) + (req "game_state" game_state_encoding)) +end + +type versioned = V1 of V1.t + +let versioned_encoding = let open Data_encoding in union - ~tag_size:`Uint8 [ case - ~title:"Start" + ~title:"smart_rollup_game.V1" (Tag 0) - (obj3 - (req "refutation_kind" (constant "start")) - (req "player_commitment_hash" Commitment.Hash.encoding) - (req "opponent_commitment_hash" Commitment.Hash.encoding)) - (function - | Start {player_commitment_hash; opponent_commitment_hash} -> - Some ((), player_commitment_hash, opponent_commitment_hash) - | _ -> None) - (fun ((), player_commitment_hash, opponent_commitment_hash) -> - Start {player_commitment_hash; opponent_commitment_hash}); - case - ~title:"Move" - (Tag 1) - (obj3 - (req "refutation_kind" (constant "move")) - (req "choice" n) - (req "step" step_encoding)) - (function Move {choice; step} -> Some ((), choice, step) | _ -> None) - (fun ((), choice, step) -> Move {choice; step}); + V1.encoding + (function V1 game -> Some game) + (fun game -> V1 game); ] + +include V1 + +let of_versioned = function V1 g -> g [@@inline] + +let to_versioned g = V1 g [@@inline] diff --git a/src/lib_smart_rollup/game.mli b/src/lib_smart_rollup/game.mli index 9c2676b00bfd..455fcf96b152 100644 --- a/src/lib_smart_rollup/game.mli +++ b/src/lib_smart_rollup/game.mli @@ -23,31 +23,84 @@ (* *) (*****************************************************************************) -type dissection_chunk = {state_hash : State_hash.t option; tick : Z.t} +module V1 : sig + type dissection_chunk = {state_hash : State_hash.t option; tick : Z.t} -type step = Dissection of dissection_chunk list | Proof of string + type step = Dissection of dissection_chunk list | Proof of string -type refutation = - | Start of { - player_commitment_hash : Commitment.Hash.t; - opponent_commitment_hash : Commitment.Hash.t; - } - | Move of {choice : Z.t; step : step} + type refutation = + | Start of { + player_commitment_hash : Commitment.Hash.t; + opponent_commitment_hash : Commitment.Hash.t; + } + | Move of {choice : Z.t; step : step} -type index = { - alice : Signature.Public_key_hash.t; - bob : Signature.Public_key_hash.t; -} + type index = { + alice : Signature.Public_key_hash.t; + bob : Signature.Public_key_hash.t; + } -val dissection_chunk_encoding : dissection_chunk Data_encoding.t + val dissection_chunk_encoding : dissection_chunk Data_encoding.t -val dissection_encoding : dissection_chunk list Data_encoding.t + val dissection_encoding : dissection_chunk list Data_encoding.t -val step_encoding : step Data_encoding.t + val step_encoding : step Data_encoding.t -val refutation_encoding : refutation Data_encoding.t + val refutation_encoding : refutation Data_encoding.t -val index_encoding : index Data_encoding.t + val index_encoding : index Data_encoding.t -val make_index : - Signature.Public_key_hash.t -> Signature.Public_key_hash.t -> index + val make_index : + Signature.Public_key_hash.t -> Signature.Public_key_hash.t -> index + + type player = Alice | Bob + + type game_state = + | Dissecting of { + dissection : dissection_chunk list; + default_number_of_sections : int; + } + | Final_move of { + agreed_start_chunk : dissection_chunk; + refuted_stop_chunk : dissection_chunk; + } + + type t = { + turn : player; + inbox_snapshot : Inbox.V1.history_proof; + dal_snapshot : Dal.Slot_history.t; + start_level : int32; + inbox_level : int32; + game_state : game_state; + } + + type conflict = { + other : Signature.Public_key_hash.t; + their_commitment : Commitment.t; + our_commitment : Commitment.t; + parent_commitment : Commitment.Hash.t; + } + + val game_state_equal : game_state -> game_state -> bool + + val player_encoding : player Data_encoding.t + + val game_state_encoding : game_state Data_encoding.t + + val encoding : t Data_encoding.t + + val conflict_encoding : conflict Data_encoding.t +end + +include Versioned_data.S with type t = V1.t + +include + module type of V1 + with type dissection_chunk = V1.dissection_chunk + and type step = V1.step + and type refutation = V1.refutation + and type index = V1.index + and type player = V1.player + and type game_state = V1.game_state + and type conflict = V1.conflict + and type t = V1.t -- GitLab From 14435b6fcd0db677cd5a0018117fcc734f58928f Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 29 Jun 2023 15:14:06 +0200 Subject: [PATCH 03/17] SCORU/Node/Alpha: conversion functions for game structures --- .../sc_rollup_proto_types.ml | 292 +++++++++++++----- .../sc_rollup_proto_types.mli | 32 ++ 2 files changed, 239 insertions(+), 85 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_layer2/sc_rollup_proto_types.ml b/src/proto_alpha/lib_sc_rollup_layer2/sc_rollup_proto_types.ml index b85e403c010d..85b565a104fa 100644 --- a/src/proto_alpha/lib_sc_rollup_layer2/sc_rollup_proto_types.ml +++ b/src/proto_alpha/lib_sc_rollup_layer2/sc_rollup_proto_types.ml @@ -110,6 +110,8 @@ end module Inbox = struct type t = Sc_rollup.Inbox.t + type history_proof = Sc_rollup.Inbox.history_proof + let to_repr inbox = inbox |> Data_encoding.Binary.to_string_exn Sc_rollup.Inbox.encoding @@ -135,6 +137,106 @@ module Inbox = struct |> Data_encoding.Binary.of_string_exn Octez_smart_rollup.Inbox.versioned_encoding |> Octez_smart_rollup.Inbox.of_versioned + + let history_proof_of_octez (hist : Octez_smart_rollup.Inbox.history_proof) : + history_proof = + hist + |> Data_encoding.Binary.to_string_exn + Octez_smart_rollup.Inbox.history_proof_encoding + |> Data_encoding.Binary.of_string_exn Sc_rollup.Inbox.history_proof_encoding + + let history_proof_to_octez (hist : history_proof) : + Octez_smart_rollup.Inbox.history_proof = + hist + |> Data_encoding.Binary.to_string_exn Sc_rollup.Inbox.history_proof_encoding + |> Data_encoding.Binary.of_string_exn + Octez_smart_rollup.Inbox.history_proof_encoding +end + +module Dal = struct + module Slot_index = struct + type t = Dal.Slot_index.t + + let of_octez ~number_of_slots (i : Octez_smart_rollup.Dal.Slot_index.t) : t + = + match Dal.Slot_index.of_int_opt ~number_of_slots i with + | None -> Format.ksprintf invalid_arg "Dal.Slot_index.of_octez: %d" i + | Some i -> i + + let to_octez : t -> Octez_smart_rollup.Dal.Slot_index.t = + Dal.Slot_index.to_int + end + + module Page_index = struct + type t = Dal.Page.Index.t + + let of_octez : Octez_smart_rollup.Dal.Page_index.t -> t = Fun.id + + let to_octez : t -> Octez_smart_rollup.Dal.Page_index.t = Fun.id + end + + module Slot_header = struct + type t = Dal.Slot.Header.t + + let of_octez ~number_of_slots + Octez_smart_rollup.Dal.Slot_header. + {id = {published_level; index}; commitment} : t = + Dal.Slot.Header. + { + id = + { + published_level = Raw_level.of_int32_exn published_level; + index = Slot_index.of_octez ~number_of_slots index; + }; + commitment; + } + + let to_octez Dal.Slot.Header.{id = {published_level; index}; commitment} : + Octez_smart_rollup.Dal.Slot_header.t = + Octez_smart_rollup.Dal.Slot_header. + { + id = + { + published_level = Raw_level.to_int32 published_level; + index = Slot_index.to_octez index; + }; + commitment; + } + end + + module Slot_history = struct + type t = Dal.Slots_history.t + + let of_octez (h : Octez_smart_rollup.Dal.Slot_history.t) : t = + h + |> Data_encoding.Binary.to_bytes_exn + Octez_smart_rollup.Dal.Slot_history.encoding + |> Data_encoding.Binary.of_bytes_exn Dal.Slots_history.encoding + + let to_octez (h : t) : Octez_smart_rollup.Dal.Slot_history.t = + h + |> Data_encoding.Binary.to_bytes_exn Dal.Slots_history.encoding + |> Data_encoding.Binary.of_bytes_exn + Octez_smart_rollup.Dal.Slot_history.encoding + end + + module Slot_history_cache = struct + type t = Dal.Slots_history.History_cache.t + + let of_octez (h : Octez_smart_rollup.Dal.Slot_history_cache.t) : t = + h + |> Data_encoding.Binary.to_bytes_exn + Octez_smart_rollup.Dal.Slot_history_cache.encoding + |> Data_encoding.Binary.of_bytes_exn + Dal.Slots_history.History_cache.encoding + + let to_octez (h : t) : Octez_smart_rollup.Dal.Slot_history_cache.t = + h + |> Data_encoding.Binary.to_bytes_exn + Dal.Slots_history.History_cache.encoding + |> Data_encoding.Binary.of_bytes_exn + Octez_smart_rollup.Dal.Slot_history_cache.encoding + end end module Game = struct @@ -146,6 +248,14 @@ module Game = struct type index = Sc_rollup.Game.Index.t + type player = Sc_rollup.Game.player + + type game_state = Sc_rollup.Game.game_state + + type t = Sc_rollup.Game.t + + type conflict = Sc_rollup.Refutation_storage.conflict + let dissection_chunk_of_octez Octez_smart_rollup.Game.{state_hash; tick} : dissection_chunk = { @@ -223,104 +333,116 @@ module Game = struct let index_to_octez Sc_rollup.Game.Index.{alice; bob} = Octez_smart_rollup.Game.make_index alice bob -end - -module Kind = struct - type t = Sc_rollup.Kind.t - - let of_octez : Octez_smart_rollup.Kind.t -> t = function - | Example_arith -> Example_arith - | Wasm_2_0_0 -> Wasm_2_0_0 - - let to_octez : t -> Octez_smart_rollup.Kind.t = function - | Example_arith -> Example_arith - | Wasm_2_0_0 -> Wasm_2_0_0 -end - -module Dal = struct - module Slot_index = struct - type t = Dal.Slot_index.t - - let of_octez ~number_of_slots (i : Octez_smart_rollup.Dal.Slot_index.t) : t - = - match Dal.Slot_index.of_int_opt ~number_of_slots i with - | None -> Format.ksprintf invalid_arg "Dal.Slot_index.of_octez: %d" i - | Some i -> i - let to_octez : t -> Octez_smart_rollup.Dal.Slot_index.t = - Dal.Slot_index.to_int - end + let player_of_octez : Octez_smart_rollup.Game.player -> player = function + | Alice -> Alice + | Bob -> Bob - module Page_index = struct - type t = Dal.Page.Index.t + let player_to_octez : player -> Octez_smart_rollup.Game.player = function + | Alice -> Alice + | Bob -> Bob - let of_octez : Octez_smart_rollup.Dal.Page_index.t -> t = Fun.id - - let to_octez : t -> Octez_smart_rollup.Dal.Page_index.t = Fun.id - end + let game_state_of_octez : Octez_smart_rollup.Game.game_state -> game_state = + function + | Dissecting {dissection; default_number_of_sections} -> + Dissecting + { + dissection = List.map dissection_chunk_of_octez dissection; + default_number_of_sections; + } + | Final_move {agreed_start_chunk; refuted_stop_chunk} -> + Final_move + { + agreed_start_chunk = dissection_chunk_of_octez agreed_start_chunk; + refuted_stop_chunk = dissection_chunk_of_octez refuted_stop_chunk; + } - module Slot_header = struct - type t = Dal.Slot.Header.t + let game_state_to_octez : game_state -> Octez_smart_rollup.Game.game_state = + function + | Dissecting {dissection; default_number_of_sections} -> + Dissecting + { + dissection = List.map dissection_chunk_to_octez dissection; + default_number_of_sections; + } + | Final_move {agreed_start_chunk; refuted_stop_chunk} -> + Final_move + { + agreed_start_chunk = dissection_chunk_to_octez agreed_start_chunk; + refuted_stop_chunk = dissection_chunk_to_octez refuted_stop_chunk; + } - let of_octez ~number_of_slots - Octez_smart_rollup.Dal.Slot_header. - {id = {published_level; index}; commitment} : t = - Dal.Slot.Header. + let of_octez + Octez_smart_rollup.Game. { - id = - { - published_level = Raw_level.of_int32_exn published_level; - index = Slot_index.of_octez ~number_of_slots index; - }; - commitment; - } + turn; + inbox_snapshot; + dal_snapshot; + start_level; + inbox_level; + game_state; + } : t = + { + turn = player_of_octez turn; + inbox_snapshot = Inbox.history_proof_of_octez inbox_snapshot; + dal_snapshot = Dal.Slot_history.of_octez dal_snapshot; + start_level = Raw_level.of_int32_exn start_level; + inbox_level = Raw_level.of_int32_exn inbox_level; + game_state = game_state_of_octez game_state; + } - let to_octez Dal.Slot.Header.{id = {published_level; index}; commitment} : - Octez_smart_rollup.Dal.Slot_header.t = - Octez_smart_rollup.Dal.Slot_header. + let to_octez + Sc_rollup.Game. { - id = - { - published_level = Raw_level.to_int32 published_level; - index = Slot_index.to_octez index; - }; - commitment; - } - end - - module Slot_history = struct - type t = Dal.Slots_history.t + turn; + inbox_snapshot; + dal_snapshot; + start_level; + inbox_level; + game_state; + } : Octez_smart_rollup.Game.t = + { + turn = player_to_octez turn; + inbox_snapshot = Inbox.history_proof_to_octez inbox_snapshot; + dal_snapshot = Dal.Slot_history.to_octez dal_snapshot; + start_level = Raw_level.to_int32 start_level; + inbox_level = Raw_level.to_int32 inbox_level; + game_state = game_state_to_octez game_state; + } - let of_octez (h : Octez_smart_rollup.Dal.Slot_history.t) : t = - h - |> Data_encoding.Binary.to_bytes_exn - Octez_smart_rollup.Dal.Slot_history.encoding - |> Data_encoding.Binary.of_bytes_exn Dal.Slots_history.encoding + let conflict_of_octez + Octez_smart_rollup.Game. + {other; their_commitment; our_commitment; parent_commitment} : conflict + = + { + other; + their_commitment = Commitment.of_octez their_commitment; + our_commitment = Commitment.of_octez our_commitment; + parent_commitment; + } - let to_octez (h : t) : Octez_smart_rollup.Dal.Slot_history.t = - h - |> Data_encoding.Binary.to_bytes_exn Dal.Slots_history.encoding - |> Data_encoding.Binary.of_bytes_exn - Octez_smart_rollup.Dal.Slot_history.encoding - end + let conflict_to_octez + Sc_rollup.Refutation_storage. + {other; their_commitment; our_commitment; parent_commitment} : + Octez_smart_rollup.Game.conflict = + { + other; + their_commitment = Commitment.to_octez their_commitment; + our_commitment = Commitment.to_octez our_commitment; + parent_commitment; + } +end - module Slot_history_cache = struct - type t = Dal.Slots_history.History_cache.t +module Kind = struct + type t = Sc_rollup.Kind.t - let of_octez (h : Octez_smart_rollup.Dal.Slot_history_cache.t) : t = - h - |> Data_encoding.Binary.to_bytes_exn - Octez_smart_rollup.Dal.Slot_history_cache.encoding - |> Data_encoding.Binary.of_bytes_exn - Dal.Slots_history.History_cache.encoding + let of_octez : Octez_smart_rollup.Kind.t -> t = function + | Example_arith -> Example_arith + | Wasm_2_0_0 -> Wasm_2_0_0 - let to_octez (h : t) : Octez_smart_rollup.Dal.Slot_history_cache.t = - h - |> Data_encoding.Binary.to_bytes_exn - Dal.Slots_history.History_cache.encoding - |> Data_encoding.Binary.of_bytes_exn - Octez_smart_rollup.Dal.Slot_history_cache.encoding - end + let to_octez : t -> Octez_smart_rollup.Kind.t = function + | Example_arith -> Example_arith + | Wasm_2_0_0 -> Wasm_2_0_0 end module Constants = struct diff --git a/src/proto_alpha/lib_sc_rollup_layer2/sc_rollup_proto_types.mli b/src/proto_alpha/lib_sc_rollup_layer2/sc_rollup_proto_types.mli index e1426d860a98..b00d3991fe0d 100644 --- a/src/proto_alpha/lib_sc_rollup_layer2/sc_rollup_proto_types.mli +++ b/src/proto_alpha/lib_sc_rollup_layer2/sc_rollup_proto_types.mli @@ -76,9 +76,17 @@ end module Inbox : sig type t = Sc_rollup.Inbox.t + type history_proof = Sc_rollup.Inbox.history_proof + val of_octez : Octez_smart_rollup.Inbox.t -> t val to_octez : t -> Octez_smart_rollup.Inbox.t + + val history_proof_of_octez : + Octez_smart_rollup.Inbox.history_proof -> history_proof + + val history_proof_to_octez : + history_proof -> Octez_smart_rollup.Inbox.history_proof end module Game : sig @@ -107,6 +115,30 @@ module Game : sig val index_of_octez : Octez_smart_rollup.Game.index -> index val index_to_octez : index -> Octez_smart_rollup.Game.index + + type player = Sc_rollup.Game.player + + val player_of_octez : Octez_smart_rollup.Game.player -> player + + val player_to_octez : player -> Octez_smart_rollup.Game.player + + type game_state = Sc_rollup.Game.game_state + + val game_state_of_octez : Octez_smart_rollup.Game.game_state -> game_state + + val game_state_to_octez : game_state -> Octez_smart_rollup.Game.game_state + + type t = Sc_rollup.Game.t + + val of_octez : Octez_smart_rollup.Game.t -> t + + val to_octez : t -> Octez_smart_rollup.Game.t + + type conflict = Sc_rollup.Refutation_storage.conflict + + val conflict_of_octez : Octez_smart_rollup.Game.conflict -> conflict + + val conflict_to_octez : conflict -> Octez_smart_rollup.Game.conflict end module Kind : sig -- GitLab From 720a94af0d78e2bcf36befe61cf8560d000608cb Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 27 Jul 2023 15:44:52 +0200 Subject: [PATCH 04/17] SCORU/Node/Nairobi: conversion functions for game structures --- .../sc_rollup_proto_types.ml | 306 +++++++++++++----- .../sc_rollup_proto_types.mli | 32 ++ 2 files changed, 254 insertions(+), 84 deletions(-) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_layer2/sc_rollup_proto_types.ml b/src/proto_017_PtNairob/lib_sc_rollup_layer2/sc_rollup_proto_types.ml index e8c04d28ba95..28c86619eca1 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_layer2/sc_rollup_proto_types.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_layer2/sc_rollup_proto_types.ml @@ -125,6 +125,8 @@ end module Inbox = struct type t = Sc_rollup.Inbox.t + type history_proof = Sc_rollup.Inbox.history_proof + let to_repr inbox = inbox |> Data_encoding.Binary.to_string_exn Sc_rollup.Inbox.encoding @@ -150,6 +152,121 @@ module Inbox = struct |> Data_encoding.Binary.of_string_exn Octez_smart_rollup.Inbox.versioned_encoding |> Octez_smart_rollup.Inbox.of_versioned + + (* Workaround because history_proof encoding not in Alpha_context *) + let proto_history_proof_encoding : + Sc_rollup.Inbox.history_proof Data_encoding.t = + let level_proof_encoding = + let open Data_encoding in + conv + (fun {Sc_rollup.Inbox.hash; level} -> (hash, level)) + (fun (hash, level) -> {hash; level}) + (obj2 + (req "hash" Sc_rollup.Inbox_merkelized_payload_hashes.Hash.encoding) + (req "level" Raw_level.encoding)) + in + Sc_rollup.Inbox.Skip_list.encoding + Sc_rollup.Inbox.Hash.encoding + level_proof_encoding + + let history_proof_of_octez (hist : Octez_smart_rollup.Inbox.history_proof) : + history_proof = + hist + |> Data_encoding.Binary.to_string_exn + Octez_smart_rollup.Inbox.history_proof_encoding + |> Data_encoding.Binary.of_string_exn proto_history_proof_encoding + + let history_proof_to_octez (hist : history_proof) : + Octez_smart_rollup.Inbox.history_proof = + hist + |> Data_encoding.Binary.to_string_exn proto_history_proof_encoding + |> Data_encoding.Binary.of_string_exn + Octez_smart_rollup.Inbox.history_proof_encoding +end + +module Dal = struct + module Slot_index = struct + type t = Dal.Slot_index.t + + let of_octez (i : Octez_smart_rollup.Dal.Slot_index.t) : t = + match Dal.Slot_index.of_int_opt i with + | None -> Format.ksprintf invalid_arg "Dal.Slot_index.of_octez: %d" i + | Some i -> i + + let to_octez : t -> Octez_smart_rollup.Dal.Slot_index.t = + Dal.Slot_index.to_int + end + + module Page_index = struct + type t = Dal.Page.Index.t + + let of_octez : Octez_smart_rollup.Dal.Page_index.t -> t = Fun.id + + let to_octez : t -> Octez_smart_rollup.Dal.Page_index.t = Fun.id + end + + module Slot_header = struct + type t = Dal.Slot.Header.t + + let of_octez + Octez_smart_rollup.Dal.Slot_header. + {id = {published_level; index}; commitment} : t = + Dal.Slot.Header. + { + id = + { + published_level = Raw_level.of_int32_exn published_level; + index = Slot_index.of_octez index; + }; + commitment; + } + + let to_octez Dal.Slot.Header.{id = {published_level; index}; commitment} : + Octez_smart_rollup.Dal.Slot_header.t = + Octez_smart_rollup.Dal.Slot_header. + { + id = + { + published_level = Raw_level.to_int32 published_level; + index = Slot_index.to_octez index; + }; + commitment; + } + end + + module Slot_history = struct + type t = Dal.Slots_history.t + + let of_octez (h : Octez_smart_rollup.Dal.Slot_history.t) : t = + h + |> Data_encoding.Binary.to_bytes_exn + Octez_smart_rollup.Dal.Slot_history.encoding + |> Data_encoding.Binary.of_bytes_exn Dal.Slots_history.encoding + + let to_octez (h : t) : Octez_smart_rollup.Dal.Slot_history.t = + h + |> Data_encoding.Binary.to_bytes_exn Dal.Slots_history.encoding + |> Data_encoding.Binary.of_bytes_exn + Octez_smart_rollup.Dal.Slot_history.encoding + end + + module Slot_history_cache = struct + type t = Dal.Slots_history.History_cache.t + + let of_octez (h : Octez_smart_rollup.Dal.Slot_history_cache.t) : t = + h + |> Data_encoding.Binary.to_bytes_exn + Octez_smart_rollup.Dal.Slot_history_cache.encoding + |> Data_encoding.Binary.of_bytes_exn + Dal.Slots_history.History_cache.encoding + + let to_octez (h : t) : Octez_smart_rollup.Dal.Slot_history_cache.t = + h + |> Data_encoding.Binary.to_bytes_exn + Dal.Slots_history.History_cache.encoding + |> Data_encoding.Binary.of_bytes_exn + Octez_smart_rollup.Dal.Slot_history_cache.encoding + end end module Game = struct @@ -161,6 +278,14 @@ module Game = struct type index = Sc_rollup.Game.Index.t + type player = Sc_rollup.Game.player + + type game_state = Sc_rollup.Game.game_state + + type t = Sc_rollup.Game.t + + type conflict = Sc_rollup.Refutation_storage.conflict + let dissection_chunk_of_octez Octez_smart_rollup.Game.{state_hash; tick} : dissection_chunk = { @@ -238,101 +363,114 @@ module Game = struct let index_to_octez Sc_rollup.Game.Index.{alice; bob} = Octez_smart_rollup.Game.make_index alice bob -end - -module Kind = struct - type t = Sc_rollup.Kind.t - - let of_octez : Octez_smart_rollup.Kind.t -> t = function - | Example_arith -> Example_arith - | Wasm_2_0_0 -> Wasm_2_0_0 - - let to_octez : t -> Octez_smart_rollup.Kind.t = function - | Example_arith -> Example_arith - | Wasm_2_0_0 -> Wasm_2_0_0 -end - -module Dal = struct - module Slot_index = struct - type t = Dal.Slot_index.t - - let of_octez (i : Octez_smart_rollup.Dal.Slot_index.t) : t = - match Dal.Slot_index.of_int_opt i with - | None -> Format.ksprintf invalid_arg "Dal.Slot_index.of_octez: %d" i - | Some i -> i - let to_octez : t -> Octez_smart_rollup.Dal.Slot_index.t = - Dal.Slot_index.to_int - end + let player_of_octez : Octez_smart_rollup.Game.player -> player = function + | Alice -> Alice + | Bob -> Bob - module Page_index = struct - type t = Dal.Page.Index.t - - let of_octez : Octez_smart_rollup.Dal.Page_index.t -> t = Fun.id + let player_to_octez : player -> Octez_smart_rollup.Game.player = function + | Alice -> Alice + | Bob -> Bob - let to_octez : t -> Octez_smart_rollup.Dal.Page_index.t = Fun.id - end + let game_state_of_octez : Octez_smart_rollup.Game.game_state -> game_state = + function + | Dissecting {dissection; default_number_of_sections} -> + Dissecting + { + dissection = List.map dissection_chunk_of_octez dissection; + default_number_of_sections; + } + | Final_move {agreed_start_chunk; refuted_stop_chunk} -> + Final_move + { + agreed_start_chunk = dissection_chunk_of_octez agreed_start_chunk; + refuted_stop_chunk = dissection_chunk_of_octez refuted_stop_chunk; + } - module Slot_header = struct - type t = Dal.Slot.Header.t + let game_state_to_octez : game_state -> Octez_smart_rollup.Game.game_state = + function + | Dissecting {dissection; default_number_of_sections} -> + Dissecting + { + dissection = List.map dissection_chunk_to_octez dissection; + default_number_of_sections; + } + | Final_move {agreed_start_chunk; refuted_stop_chunk} -> + Final_move + { + agreed_start_chunk = dissection_chunk_to_octez agreed_start_chunk; + refuted_stop_chunk = dissection_chunk_to_octez refuted_stop_chunk; + } - let of_octez - Octez_smart_rollup.Dal.Slot_header. - {id = {published_level; index}; commitment} : t = - Dal.Slot.Header. + let of_octez + Octez_smart_rollup.Game. { - id = - { - published_level = Raw_level.of_int32_exn published_level; - index = Slot_index.of_octez index; - }; - commitment; - } + turn; + inbox_snapshot; + dal_snapshot; + start_level; + inbox_level; + game_state; + } : t = + { + turn = player_of_octez turn; + inbox_snapshot = Inbox.history_proof_of_octez inbox_snapshot; + dal_snapshot = Dal.Slot_history.of_octez dal_snapshot; + start_level = Raw_level.of_int32_exn start_level; + inbox_level = Raw_level.of_int32_exn inbox_level; + game_state = game_state_of_octez game_state; + } - let to_octez Dal.Slot.Header.{id = {published_level; index}; commitment} : - Octez_smart_rollup.Dal.Slot_header.t = - Octez_smart_rollup.Dal.Slot_header. + let to_octez + Sc_rollup.Game. { - id = - { - published_level = Raw_level.to_int32 published_level; - index = Slot_index.to_octez index; - }; - commitment; - } - end - - module Slot_history = struct - type t = Dal.Slots_history.t + turn; + inbox_snapshot; + dal_snapshot; + start_level; + inbox_level; + game_state; + } : Octez_smart_rollup.Game.t = + { + turn = player_to_octez turn; + inbox_snapshot = Inbox.history_proof_to_octez inbox_snapshot; + dal_snapshot = Dal.Slot_history.to_octez dal_snapshot; + start_level = Raw_level.to_int32 start_level; + inbox_level = Raw_level.to_int32 inbox_level; + game_state = game_state_to_octez game_state; + } - let of_octez (h : Octez_smart_rollup.Dal.Slot_history.t) : t = - h - |> Data_encoding.Binary.to_bytes_exn - Octez_smart_rollup.Dal.Slot_history.encoding - |> Data_encoding.Binary.of_bytes_exn Dal.Slots_history.encoding + let conflict_of_octez + Octez_smart_rollup.Game. + {other; their_commitment; our_commitment; parent_commitment} : conflict + = + { + other; + their_commitment = Commitment.of_octez their_commitment; + our_commitment = Commitment.of_octez our_commitment; + parent_commitment = Commitment_hash.of_octez parent_commitment; + } - let to_octez (h : t) : Octez_smart_rollup.Dal.Slot_history.t = - h - |> Data_encoding.Binary.to_bytes_exn Dal.Slots_history.encoding - |> Data_encoding.Binary.of_bytes_exn - Octez_smart_rollup.Dal.Slot_history.encoding - end + let conflict_to_octez + Sc_rollup.Refutation_storage. + {other; their_commitment; our_commitment; parent_commitment} : + Octez_smart_rollup.Game.conflict = + { + other; + their_commitment = Commitment.to_octez their_commitment; + our_commitment = Commitment.to_octez our_commitment; + parent_commitment = Commitment_hash.to_octez parent_commitment; + } +end - module Slot_history_cache = struct - type t = Dal.Slots_history.History_cache.t +module Kind = struct + type t = Sc_rollup.Kind.t - let of_octez (h : Octez_smart_rollup.Dal.Slot_history_cache.t) : t = - h - |> Data_encoding.Binary.to_bytes_exn - Octez_smart_rollup.Dal.Slot_history_cache.encoding - |> Data_encoding.Binary.of_bytes_exn - Dal.Slots_history.History_cache.encoding + let of_octez : Octez_smart_rollup.Kind.t -> t = function + | Example_arith -> Example_arith + | Wasm_2_0_0 -> Wasm_2_0_0 - let to_octez (h : t) : Octez_smart_rollup.Dal.Slot_history_cache.t = - h - |> Data_encoding.Binary.to_bytes_exn - Dal.Slots_history.History_cache.encoding - |> Data_encoding.Binary.of_bytes_exn - Octez_smart_rollup.Dal.Slot_history_cache.encoding - end + let to_octez : t -> Octez_smart_rollup.Kind.t = function + | Example_arith -> Example_arith + | Wasm_2_0_0 -> Wasm_2_0_0 end diff --git a/src/proto_017_PtNairob/lib_sc_rollup_layer2/sc_rollup_proto_types.mli b/src/proto_017_PtNairob/lib_sc_rollup_layer2/sc_rollup_proto_types.mli index 905a7b7bde6d..131d236b838f 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_layer2/sc_rollup_proto_types.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_layer2/sc_rollup_proto_types.mli @@ -76,9 +76,17 @@ end module Inbox : sig type t = Sc_rollup.Inbox.t + type history_proof = Sc_rollup.Inbox.history_proof + val of_octez : Octez_smart_rollup.Inbox.t -> t val to_octez : t -> Octez_smart_rollup.Inbox.t + + val history_proof_of_octez : + Octez_smart_rollup.Inbox.history_proof -> history_proof + + val history_proof_to_octez : + history_proof -> Octez_smart_rollup.Inbox.history_proof end module Game : sig @@ -107,6 +115,30 @@ module Game : sig val index_of_octez : Octez_smart_rollup.Game.index -> index val index_to_octez : index -> Octez_smart_rollup.Game.index + + type player = Sc_rollup.Game.player + + val player_of_octez : Octez_smart_rollup.Game.player -> player + + val player_to_octez : player -> Octez_smart_rollup.Game.player + + type game_state = Sc_rollup.Game.game_state + + val game_state_of_octez : Octez_smart_rollup.Game.game_state -> game_state + + val game_state_to_octez : game_state -> Octez_smart_rollup.Game.game_state + + type t = Sc_rollup.Game.t + + val of_octez : Octez_smart_rollup.Game.t -> t + + val to_octez : t -> Octez_smart_rollup.Game.t + + type conflict = Sc_rollup.Refutation_storage.conflict + + val conflict_of_octez : Octez_smart_rollup.Game.conflict -> conflict + + val conflict_to_octez : conflict -> Octez_smart_rollup.Game.conflict end module Kind : sig -- GitLab From 79f15d0600ede173ddba8708743679fe2df84f67 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 29 Jun 2023 15:14:06 +0200 Subject: [PATCH 05/17] SCORU/Node/Oxford: conversion functions for game structures --- .../sc_rollup_proto_types.ml | 308 +++++++++++++----- .../sc_rollup_proto_types.mli | 32 ++ 2 files changed, 255 insertions(+), 85 deletions(-) diff --git a/src/proto_018_Proxford/lib_sc_rollup_layer2/sc_rollup_proto_types.ml b/src/proto_018_Proxford/lib_sc_rollup_layer2/sc_rollup_proto_types.ml index b85e403c010d..4b70ebeefd24 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_layer2/sc_rollup_proto_types.ml +++ b/src/proto_018_Proxford/lib_sc_rollup_layer2/sc_rollup_proto_types.ml @@ -110,6 +110,8 @@ end module Inbox = struct type t = Sc_rollup.Inbox.t + type history_proof = Sc_rollup.Inbox.history_proof + let to_repr inbox = inbox |> Data_encoding.Binary.to_string_exn Sc_rollup.Inbox.encoding @@ -135,6 +137,122 @@ module Inbox = struct |> Data_encoding.Binary.of_string_exn Octez_smart_rollup.Inbox.versioned_encoding |> Octez_smart_rollup.Inbox.of_versioned + + (* Workaround because history_proof encoding not in Alpha_context *) + let proto_history_proof_encoding : + Sc_rollup.Inbox.history_proof Data_encoding.t = + let level_proof_encoding = + let open Data_encoding in + conv + (fun {Sc_rollup.Inbox.hash; level} -> (hash, level)) + (fun (hash, level) -> {hash; level}) + (obj2 + (req "hash" Sc_rollup.Inbox_merkelized_payload_hashes.Hash.encoding) + (req "level" Raw_level.encoding)) + in + Sc_rollup.Inbox.Skip_list.encoding + Sc_rollup.Inbox.Hash.encoding + level_proof_encoding + + let history_proof_of_octez (hist : Octez_smart_rollup.Inbox.history_proof) : + history_proof = + hist + |> Data_encoding.Binary.to_string_exn + Octez_smart_rollup.Inbox.history_proof_encoding + |> Data_encoding.Binary.of_string_exn proto_history_proof_encoding + + let history_proof_to_octez (hist : history_proof) : + Octez_smart_rollup.Inbox.history_proof = + hist + |> Data_encoding.Binary.to_string_exn proto_history_proof_encoding + |> Data_encoding.Binary.of_string_exn + Octez_smart_rollup.Inbox.history_proof_encoding +end + +module Dal = struct + module Slot_index = struct + type t = Dal.Slot_index.t + + let of_octez ~number_of_slots (i : Octez_smart_rollup.Dal.Slot_index.t) : t + = + match Dal.Slot_index.of_int_opt ~number_of_slots i with + | None -> Format.ksprintf invalid_arg "Dal.Slot_index.of_octez: %d" i + | Some i -> i + + let to_octez : t -> Octez_smart_rollup.Dal.Slot_index.t = + Dal.Slot_index.to_int + end + + module Page_index = struct + type t = Dal.Page.Index.t + + let of_octez : Octez_smart_rollup.Dal.Page_index.t -> t = Fun.id + + let to_octez : t -> Octez_smart_rollup.Dal.Page_index.t = Fun.id + end + + module Slot_header = struct + type t = Dal.Slot.Header.t + + let of_octez ~number_of_slots + Octez_smart_rollup.Dal.Slot_header. + {id = {published_level; index}; commitment} : t = + Dal.Slot.Header. + { + id = + { + published_level = Raw_level.of_int32_exn published_level; + index = Slot_index.of_octez ~number_of_slots index; + }; + commitment; + } + + let to_octez Dal.Slot.Header.{id = {published_level; index}; commitment} : + Octez_smart_rollup.Dal.Slot_header.t = + Octez_smart_rollup.Dal.Slot_header. + { + id = + { + published_level = Raw_level.to_int32 published_level; + index = Slot_index.to_octez index; + }; + commitment; + } + end + + module Slot_history = struct + type t = Dal.Slots_history.t + + let of_octez (h : Octez_smart_rollup.Dal.Slot_history.t) : t = + h + |> Data_encoding.Binary.to_bytes_exn + Octez_smart_rollup.Dal.Slot_history.encoding + |> Data_encoding.Binary.of_bytes_exn Dal.Slots_history.encoding + + let to_octez (h : t) : Octez_smart_rollup.Dal.Slot_history.t = + h + |> Data_encoding.Binary.to_bytes_exn Dal.Slots_history.encoding + |> Data_encoding.Binary.of_bytes_exn + Octez_smart_rollup.Dal.Slot_history.encoding + end + + module Slot_history_cache = struct + type t = Dal.Slots_history.History_cache.t + + let of_octez (h : Octez_smart_rollup.Dal.Slot_history_cache.t) : t = + h + |> Data_encoding.Binary.to_bytes_exn + Octez_smart_rollup.Dal.Slot_history_cache.encoding + |> Data_encoding.Binary.of_bytes_exn + Dal.Slots_history.History_cache.encoding + + let to_octez (h : t) : Octez_smart_rollup.Dal.Slot_history_cache.t = + h + |> Data_encoding.Binary.to_bytes_exn + Dal.Slots_history.History_cache.encoding + |> Data_encoding.Binary.of_bytes_exn + Octez_smart_rollup.Dal.Slot_history_cache.encoding + end end module Game = struct @@ -146,6 +264,14 @@ module Game = struct type index = Sc_rollup.Game.Index.t + type player = Sc_rollup.Game.player + + type game_state = Sc_rollup.Game.game_state + + type t = Sc_rollup.Game.t + + type conflict = Sc_rollup.Refutation_storage.conflict + let dissection_chunk_of_octez Octez_smart_rollup.Game.{state_hash; tick} : dissection_chunk = { @@ -223,104 +349,116 @@ module Game = struct let index_to_octez Sc_rollup.Game.Index.{alice; bob} = Octez_smart_rollup.Game.make_index alice bob -end - -module Kind = struct - type t = Sc_rollup.Kind.t - - let of_octez : Octez_smart_rollup.Kind.t -> t = function - | Example_arith -> Example_arith - | Wasm_2_0_0 -> Wasm_2_0_0 - - let to_octez : t -> Octez_smart_rollup.Kind.t = function - | Example_arith -> Example_arith - | Wasm_2_0_0 -> Wasm_2_0_0 -end - -module Dal = struct - module Slot_index = struct - type t = Dal.Slot_index.t - - let of_octez ~number_of_slots (i : Octez_smart_rollup.Dal.Slot_index.t) : t - = - match Dal.Slot_index.of_int_opt ~number_of_slots i with - | None -> Format.ksprintf invalid_arg "Dal.Slot_index.of_octez: %d" i - | Some i -> i - let to_octez : t -> Octez_smart_rollup.Dal.Slot_index.t = - Dal.Slot_index.to_int - end + let player_of_octez : Octez_smart_rollup.Game.player -> player = function + | Alice -> Alice + | Bob -> Bob - module Page_index = struct - type t = Dal.Page.Index.t + let player_to_octez : player -> Octez_smart_rollup.Game.player = function + | Alice -> Alice + | Bob -> Bob - let of_octez : Octez_smart_rollup.Dal.Page_index.t -> t = Fun.id - - let to_octez : t -> Octez_smart_rollup.Dal.Page_index.t = Fun.id - end + let game_state_of_octez : Octez_smart_rollup.Game.game_state -> game_state = + function + | Dissecting {dissection; default_number_of_sections} -> + Dissecting + { + dissection = List.map dissection_chunk_of_octez dissection; + default_number_of_sections; + } + | Final_move {agreed_start_chunk; refuted_stop_chunk} -> + Final_move + { + agreed_start_chunk = dissection_chunk_of_octez agreed_start_chunk; + refuted_stop_chunk = dissection_chunk_of_octez refuted_stop_chunk; + } - module Slot_header = struct - type t = Dal.Slot.Header.t + let game_state_to_octez : game_state -> Octez_smart_rollup.Game.game_state = + function + | Dissecting {dissection; default_number_of_sections} -> + Dissecting + { + dissection = List.map dissection_chunk_to_octez dissection; + default_number_of_sections; + } + | Final_move {agreed_start_chunk; refuted_stop_chunk} -> + Final_move + { + agreed_start_chunk = dissection_chunk_to_octez agreed_start_chunk; + refuted_stop_chunk = dissection_chunk_to_octez refuted_stop_chunk; + } - let of_octez ~number_of_slots - Octez_smart_rollup.Dal.Slot_header. - {id = {published_level; index}; commitment} : t = - Dal.Slot.Header. + let of_octez + Octez_smart_rollup.Game. { - id = - { - published_level = Raw_level.of_int32_exn published_level; - index = Slot_index.of_octez ~number_of_slots index; - }; - commitment; - } + turn; + inbox_snapshot; + dal_snapshot; + start_level; + inbox_level; + game_state; + } : t = + { + turn = player_of_octez turn; + inbox_snapshot = Inbox.history_proof_of_octez inbox_snapshot; + dal_snapshot = Dal.Slot_history.of_octez dal_snapshot; + start_level = Raw_level.of_int32_exn start_level; + inbox_level = Raw_level.of_int32_exn inbox_level; + game_state = game_state_of_octez game_state; + } - let to_octez Dal.Slot.Header.{id = {published_level; index}; commitment} : - Octez_smart_rollup.Dal.Slot_header.t = - Octez_smart_rollup.Dal.Slot_header. + let to_octez + Sc_rollup.Game. { - id = - { - published_level = Raw_level.to_int32 published_level; - index = Slot_index.to_octez index; - }; - commitment; - } - end - - module Slot_history = struct - type t = Dal.Slots_history.t + turn; + inbox_snapshot; + dal_snapshot; + start_level; + inbox_level; + game_state; + } : Octez_smart_rollup.Game.t = + { + turn = player_to_octez turn; + inbox_snapshot = Inbox.history_proof_to_octez inbox_snapshot; + dal_snapshot = Dal.Slot_history.to_octez dal_snapshot; + start_level = Raw_level.to_int32 start_level; + inbox_level = Raw_level.to_int32 inbox_level; + game_state = game_state_to_octez game_state; + } - let of_octez (h : Octez_smart_rollup.Dal.Slot_history.t) : t = - h - |> Data_encoding.Binary.to_bytes_exn - Octez_smart_rollup.Dal.Slot_history.encoding - |> Data_encoding.Binary.of_bytes_exn Dal.Slots_history.encoding + let conflict_of_octez + Octez_smart_rollup.Game. + {other; their_commitment; our_commitment; parent_commitment} : conflict + = + { + other; + their_commitment = Commitment.of_octez their_commitment; + our_commitment = Commitment.of_octez our_commitment; + parent_commitment; + } - let to_octez (h : t) : Octez_smart_rollup.Dal.Slot_history.t = - h - |> Data_encoding.Binary.to_bytes_exn Dal.Slots_history.encoding - |> Data_encoding.Binary.of_bytes_exn - Octez_smart_rollup.Dal.Slot_history.encoding - end + let conflict_to_octez + Sc_rollup.Refutation_storage. + {other; their_commitment; our_commitment; parent_commitment} : + Octez_smart_rollup.Game.conflict = + { + other; + their_commitment = Commitment.to_octez their_commitment; + our_commitment = Commitment.to_octez our_commitment; + parent_commitment; + } +end - module Slot_history_cache = struct - type t = Dal.Slots_history.History_cache.t +module Kind = struct + type t = Sc_rollup.Kind.t - let of_octez (h : Octez_smart_rollup.Dal.Slot_history_cache.t) : t = - h - |> Data_encoding.Binary.to_bytes_exn - Octez_smart_rollup.Dal.Slot_history_cache.encoding - |> Data_encoding.Binary.of_bytes_exn - Dal.Slots_history.History_cache.encoding + let of_octez : Octez_smart_rollup.Kind.t -> t = function + | Example_arith -> Example_arith + | Wasm_2_0_0 -> Wasm_2_0_0 - let to_octez (h : t) : Octez_smart_rollup.Dal.Slot_history_cache.t = - h - |> Data_encoding.Binary.to_bytes_exn - Dal.Slots_history.History_cache.encoding - |> Data_encoding.Binary.of_bytes_exn - Octez_smart_rollup.Dal.Slot_history_cache.encoding - end + let to_octez : t -> Octez_smart_rollup.Kind.t = function + | Example_arith -> Example_arith + | Wasm_2_0_0 -> Wasm_2_0_0 end module Constants = struct diff --git a/src/proto_018_Proxford/lib_sc_rollup_layer2/sc_rollup_proto_types.mli b/src/proto_018_Proxford/lib_sc_rollup_layer2/sc_rollup_proto_types.mli index e1426d860a98..b00d3991fe0d 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_layer2/sc_rollup_proto_types.mli +++ b/src/proto_018_Proxford/lib_sc_rollup_layer2/sc_rollup_proto_types.mli @@ -76,9 +76,17 @@ end module Inbox : sig type t = Sc_rollup.Inbox.t + type history_proof = Sc_rollup.Inbox.history_proof + val of_octez : Octez_smart_rollup.Inbox.t -> t val to_octez : t -> Octez_smart_rollup.Inbox.t + + val history_proof_of_octez : + Octez_smart_rollup.Inbox.history_proof -> history_proof + + val history_proof_to_octez : + history_proof -> Octez_smart_rollup.Inbox.history_proof end module Game : sig @@ -107,6 +115,30 @@ module Game : sig val index_of_octez : Octez_smart_rollup.Game.index -> index val index_to_octez : index -> Octez_smart_rollup.Game.index + + type player = Sc_rollup.Game.player + + val player_of_octez : Octez_smart_rollup.Game.player -> player + + val player_to_octez : player -> Octez_smart_rollup.Game.player + + type game_state = Sc_rollup.Game.game_state + + val game_state_of_octez : Octez_smart_rollup.Game.game_state -> game_state + + val game_state_to_octez : game_state -> Octez_smart_rollup.Game.game_state + + type t = Sc_rollup.Game.t + + val of_octez : Octez_smart_rollup.Game.t -> t + + val to_octez : t -> Octez_smart_rollup.Game.t + + type conflict = Sc_rollup.Refutation_storage.conflict + + val conflict_of_octez : Octez_smart_rollup.Game.conflict -> conflict + + val conflict_to_octez : conflict -> Octez_smart_rollup.Game.conflict end module Kind : sig -- GitLab From 909b399a9cfabbd43d4afd62cd87f2347ea62dbf Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 29 Jun 2023 15:14:06 +0200 Subject: [PATCH 06/17] SCORU/Node/Mumbai: conversion functions for game structures --- .../sc_rollup_proto_types.ml | 306 +++++++++++++----- .../sc_rollup_proto_types.mli | 32 ++ 2 files changed, 254 insertions(+), 84 deletions(-) diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_layer2/sc_rollup_proto_types.ml b/src/proto_016_PtMumbai/lib_sc_rollup_layer2/sc_rollup_proto_types.ml index 5bb9d6dbb492..4df8dba798d2 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_layer2/sc_rollup_proto_types.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_layer2/sc_rollup_proto_types.ml @@ -94,6 +94,8 @@ end module Inbox = struct type t = Sc_rollup.Inbox.t + type history_proof = Sc_rollup.Inbox.history_proof + let to_repr inbox = inbox |> Data_encoding.Binary.to_string_exn Sc_rollup.Inbox.encoding @@ -119,6 +121,121 @@ module Inbox = struct |> Data_encoding.Binary.of_string_exn Octez_smart_rollup.Inbox.versioned_encoding |> Octez_smart_rollup.Inbox.of_versioned + + (* Workaround because history_proof encoding not in Alpha_context *) + let proto_history_proof_encoding : + Sc_rollup.Inbox.history_proof Data_encoding.t = + let level_proof_encoding = + let open Data_encoding in + conv + (fun {Sc_rollup.Inbox.hash; level} -> (hash, level)) + (fun (hash, level) -> {hash; level}) + (obj2 + (req "hash" Sc_rollup.Inbox_merkelized_payload_hashes.Hash.encoding) + (req "level" Raw_level.encoding)) + in + Sc_rollup.Inbox.Skip_list.encoding + Sc_rollup.Inbox.Hash.encoding + level_proof_encoding + + let history_proof_of_octez (hist : Octez_smart_rollup.Inbox.history_proof) : + history_proof = + hist + |> Data_encoding.Binary.to_string_exn + Octez_smart_rollup.Inbox.history_proof_encoding + |> Data_encoding.Binary.of_string_exn proto_history_proof_encoding + + let history_proof_to_octez (hist : history_proof) : + Octez_smart_rollup.Inbox.history_proof = + hist + |> Data_encoding.Binary.to_string_exn proto_history_proof_encoding + |> Data_encoding.Binary.of_string_exn + Octez_smart_rollup.Inbox.history_proof_encoding +end + +module Dal = struct + module Slot_index = struct + type t = Dal.Slot_index.t + + let of_octez (i : Octez_smart_rollup.Dal.Slot_index.t) : t = + match Dal.Slot_index.of_int i with + | None -> Format.ksprintf invalid_arg "Dal.Slot_index.of_octez: %d" i + | Some i -> i + + let to_octez : t -> Octez_smart_rollup.Dal.Slot_index.t = + Dal.Slot_index.to_int + end + + module Page_index = struct + type t = Dal.Page.Index.t + + let of_octez : Octez_smart_rollup.Dal.Page_index.t -> t = Fun.id + + let to_octez : t -> Octez_smart_rollup.Dal.Page_index.t = Fun.id + end + + module Slot_header = struct + type t = Dal.Slot.Header.t + + let of_octez + Octez_smart_rollup.Dal.Slot_header. + {id = {published_level; index}; commitment} : t = + Dal.Slot.Header. + { + id = + { + published_level = Raw_level.of_int32_exn published_level; + index = Slot_index.of_octez index; + }; + commitment; + } + + let to_octez Dal.Slot.Header.{id = {published_level; index}; commitment} : + Octez_smart_rollup.Dal.Slot_header.t = + Octez_smart_rollup.Dal.Slot_header. + { + id = + { + published_level = Raw_level.to_int32 published_level; + index = Slot_index.to_octez index; + }; + commitment; + } + end + + module Slot_history = struct + type t = Dal.Slots_history.t + + let of_octez (h : Octez_smart_rollup.Dal.Slot_history.t) : t = + h + |> Data_encoding.Binary.to_bytes_exn + Octez_smart_rollup.Dal.Slot_history.encoding + |> Data_encoding.Binary.of_bytes_exn Dal.Slots_history.encoding + + let to_octez (h : t) : Octez_smart_rollup.Dal.Slot_history.t = + h + |> Data_encoding.Binary.to_bytes_exn Dal.Slots_history.encoding + |> Data_encoding.Binary.of_bytes_exn + Octez_smart_rollup.Dal.Slot_history.encoding + end + + module Slot_history_cache = struct + type t = Dal.Slots_history.History_cache.t + + let of_octez (h : Octez_smart_rollup.Dal.Slot_history_cache.t) : t = + h + |> Data_encoding.Binary.to_bytes_exn + Octez_smart_rollup.Dal.Slot_history_cache.encoding + |> Data_encoding.Binary.of_bytes_exn + Dal.Slots_history.History_cache.encoding + + let to_octez (h : t) : Octez_smart_rollup.Dal.Slot_history_cache.t = + h + |> Data_encoding.Binary.to_bytes_exn + Dal.Slots_history.History_cache.encoding + |> Data_encoding.Binary.of_bytes_exn + Octez_smart_rollup.Dal.Slot_history_cache.encoding + end end module Commitment = struct @@ -161,6 +278,14 @@ module Game = struct type index = Sc_rollup.Game.Index.t + type player = Sc_rollup.Game.player + + type game_state = Sc_rollup.Game.game_state + + type t = Sc_rollup.Game.t + + type conflict = Sc_rollup.Refutation_storage.conflict + let dissection_chunk_of_octez Octez_smart_rollup.Game.{state_hash; tick} : dissection_chunk = { @@ -238,101 +363,114 @@ module Game = struct let index_to_octez Sc_rollup.Game.Index.{alice; bob} = Octez_smart_rollup.Game.make_index alice bob -end - -module Kind = struct - type t = Sc_rollup.Kind.t - - let of_octez : Octez_smart_rollup.Kind.t -> t = function - | Example_arith -> Example_arith - | Wasm_2_0_0 -> Wasm_2_0_0 - - let to_octez : t -> Octez_smart_rollup.Kind.t = function - | Example_arith -> Example_arith - | Wasm_2_0_0 -> Wasm_2_0_0 -end - -module Dal = struct - module Slot_index = struct - type t = Dal.Slot_index.t - - let of_octez (i : Octez_smart_rollup.Dal.Slot_index.t) : t = - match Dal.Slot_index.of_int i with - | None -> Format.ksprintf invalid_arg "Dal.Slot_index.of_octez: %d" i - | Some i -> i - let to_octez : t -> Octez_smart_rollup.Dal.Slot_index.t = - Dal.Slot_index.to_int - end + let player_of_octez : Octez_smart_rollup.Game.player -> player = function + | Alice -> Alice + | Bob -> Bob - module Page_index = struct - type t = Dal.Page.Index.t - - let of_octez : Octez_smart_rollup.Dal.Page_index.t -> t = Fun.id + let player_to_octez : player -> Octez_smart_rollup.Game.player = function + | Alice -> Alice + | Bob -> Bob - let to_octez : t -> Octez_smart_rollup.Dal.Page_index.t = Fun.id - end + let game_state_of_octez : Octez_smart_rollup.Game.game_state -> game_state = + function + | Dissecting {dissection; default_number_of_sections} -> + Dissecting + { + dissection = List.map dissection_chunk_of_octez dissection; + default_number_of_sections; + } + | Final_move {agreed_start_chunk; refuted_stop_chunk} -> + Final_move + { + agreed_start_chunk = dissection_chunk_of_octez agreed_start_chunk; + refuted_stop_chunk = dissection_chunk_of_octez refuted_stop_chunk; + } - module Slot_header = struct - type t = Dal.Slot.Header.t + let game_state_to_octez : game_state -> Octez_smart_rollup.Game.game_state = + function + | Dissecting {dissection; default_number_of_sections} -> + Dissecting + { + dissection = List.map dissection_chunk_to_octez dissection; + default_number_of_sections; + } + | Final_move {agreed_start_chunk; refuted_stop_chunk} -> + Final_move + { + agreed_start_chunk = dissection_chunk_to_octez agreed_start_chunk; + refuted_stop_chunk = dissection_chunk_to_octez refuted_stop_chunk; + } - let of_octez - Octez_smart_rollup.Dal.Slot_header. - {id = {published_level; index}; commitment} : t = - Dal.Slot.Header. + let of_octez + Octez_smart_rollup.Game. { - id = - { - published_level = Raw_level.of_int32_exn published_level; - index = Slot_index.of_octez index; - }; - commitment; - } + turn; + inbox_snapshot; + dal_snapshot; + start_level; + inbox_level; + game_state; + } : t = + { + turn = player_of_octez turn; + inbox_snapshot = Inbox.history_proof_of_octez inbox_snapshot; + dal_snapshot = Dal.Slot_history.of_octez dal_snapshot; + start_level = Raw_level.of_int32_exn start_level; + inbox_level = Raw_level.of_int32_exn inbox_level; + game_state = game_state_of_octez game_state; + } - let to_octez Dal.Slot.Header.{id = {published_level; index}; commitment} : - Octez_smart_rollup.Dal.Slot_header.t = - Octez_smart_rollup.Dal.Slot_header. + let to_octez + Sc_rollup.Game. { - id = - { - published_level = Raw_level.to_int32 published_level; - index = Slot_index.to_octez index; - }; - commitment; - } - end - - module Slot_history = struct - type t = Dal.Slots_history.t + turn; + inbox_snapshot; + dal_snapshot; + start_level; + inbox_level; + game_state; + } : Octez_smart_rollup.Game.t = + { + turn = player_to_octez turn; + inbox_snapshot = Inbox.history_proof_to_octez inbox_snapshot; + dal_snapshot = Dal.Slot_history.to_octez dal_snapshot; + start_level = Raw_level.to_int32 start_level; + inbox_level = Raw_level.to_int32 inbox_level; + game_state = game_state_to_octez game_state; + } - let of_octez (h : Octez_smart_rollup.Dal.Slot_history.t) : t = - h - |> Data_encoding.Binary.to_bytes_exn - Octez_smart_rollup.Dal.Slot_history.encoding - |> Data_encoding.Binary.of_bytes_exn Dal.Slots_history.encoding + let conflict_of_octez + Octez_smart_rollup.Game. + {other; their_commitment; our_commitment; parent_commitment} : conflict + = + { + other; + their_commitment = Commitment.of_octez their_commitment; + our_commitment = Commitment.of_octez our_commitment; + parent_commitment = Commitment_hash.of_octez parent_commitment; + } - let to_octez (h : t) : Octez_smart_rollup.Dal.Slot_history.t = - h - |> Data_encoding.Binary.to_bytes_exn Dal.Slots_history.encoding - |> Data_encoding.Binary.of_bytes_exn - Octez_smart_rollup.Dal.Slot_history.encoding - end + let conflict_to_octez + Sc_rollup.Refutation_storage. + {other; their_commitment; our_commitment; parent_commitment} : + Octez_smart_rollup.Game.conflict = + { + other; + their_commitment = Commitment.to_octez their_commitment; + our_commitment = Commitment.to_octez our_commitment; + parent_commitment = Commitment_hash.to_octez parent_commitment; + } +end - module Slot_history_cache = struct - type t = Dal.Slots_history.History_cache.t +module Kind = struct + type t = Sc_rollup.Kind.t - let of_octez (h : Octez_smart_rollup.Dal.Slot_history_cache.t) : t = - h - |> Data_encoding.Binary.to_bytes_exn - Octez_smart_rollup.Dal.Slot_history_cache.encoding - |> Data_encoding.Binary.of_bytes_exn - Dal.Slots_history.History_cache.encoding + let of_octez : Octez_smart_rollup.Kind.t -> t = function + | Example_arith -> Example_arith + | Wasm_2_0_0 -> Wasm_2_0_0 - let to_octez (h : t) : Octez_smart_rollup.Dal.Slot_history_cache.t = - h - |> Data_encoding.Binary.to_bytes_exn - Dal.Slots_history.History_cache.encoding - |> Data_encoding.Binary.of_bytes_exn - Octez_smart_rollup.Dal.Slot_history_cache.encoding - end + let to_octez : t -> Octez_smart_rollup.Kind.t = function + | Example_arith -> Example_arith + | Wasm_2_0_0 -> Wasm_2_0_0 end diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_layer2/sc_rollup_proto_types.mli b/src/proto_016_PtMumbai/lib_sc_rollup_layer2/sc_rollup_proto_types.mli index 905a7b7bde6d..131d236b838f 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_layer2/sc_rollup_proto_types.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_layer2/sc_rollup_proto_types.mli @@ -76,9 +76,17 @@ end module Inbox : sig type t = Sc_rollup.Inbox.t + type history_proof = Sc_rollup.Inbox.history_proof + val of_octez : Octez_smart_rollup.Inbox.t -> t val to_octez : t -> Octez_smart_rollup.Inbox.t + + val history_proof_of_octez : + Octez_smart_rollup.Inbox.history_proof -> history_proof + + val history_proof_to_octez : + history_proof -> Octez_smart_rollup.Inbox.history_proof end module Game : sig @@ -107,6 +115,30 @@ module Game : sig val index_of_octez : Octez_smart_rollup.Game.index -> index val index_to_octez : index -> Octez_smart_rollup.Game.index + + type player = Sc_rollup.Game.player + + val player_of_octez : Octez_smart_rollup.Game.player -> player + + val player_to_octez : player -> Octez_smart_rollup.Game.player + + type game_state = Sc_rollup.Game.game_state + + val game_state_of_octez : Octez_smart_rollup.Game.game_state -> game_state + + val game_state_to_octez : game_state -> Octez_smart_rollup.Game.game_state + + type t = Sc_rollup.Game.t + + val of_octez : Octez_smart_rollup.Game.t -> t + + val to_octez : t -> Octez_smart_rollup.Game.t + + type conflict = Sc_rollup.Refutation_storage.conflict + + val conflict_of_octez : Octez_smart_rollup.Game.conflict -> conflict + + val conflict_to_octez : conflict -> Octez_smart_rollup.Game.conflict end module Kind : sig -- GitLab From 2bb289637d4d2255e7ec350e47df65017b4a7168 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 29 Jun 2023 13:38:59 +0200 Subject: [PATCH 07/17] SCORU/Node: move refutation coordinator worker types --- .../refutation_coordinator_types.ml | 0 .../refutation_coordinator_types.mli | 0 .../refutation_coordinator_types.ml | 56 ------------------- .../refutation_coordinator_types.mli | 38 ------------- .../refutation_coordinator_types.ml | 56 ------------------- .../refutation_coordinator_types.mli | 38 ------------- .../refutation_coordinator_types.ml | 56 ------------------- .../refutation_coordinator_types.mli | 38 ------------- 8 files changed, 282 deletions(-) rename src/{proto_016_PtMumbai/lib_sc_rollup_node => lib_smart_rollup_node}/refutation_coordinator_types.ml (100%) rename src/{proto_016_PtMumbai/lib_sc_rollup_node => lib_smart_rollup_node}/refutation_coordinator_types.mli (100%) delete mode 100644 src/proto_017_PtNairob/lib_sc_rollup_node/refutation_coordinator_types.ml delete mode 100644 src/proto_017_PtNairob/lib_sc_rollup_node/refutation_coordinator_types.mli delete mode 100644 src/proto_018_Proxford/lib_sc_rollup_node/refutation_coordinator_types.ml delete mode 100644 src/proto_018_Proxford/lib_sc_rollup_node/refutation_coordinator_types.mli delete mode 100644 src/proto_alpha/lib_sc_rollup_node/refutation_coordinator_types.ml delete mode 100644 src/proto_alpha/lib_sc_rollup_node/refutation_coordinator_types.mli diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_coordinator_types.ml b/src/lib_smart_rollup_node/refutation_coordinator_types.ml similarity index 100% rename from src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_coordinator_types.ml rename to src/lib_smart_rollup_node/refutation_coordinator_types.ml diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_coordinator_types.mli b/src/lib_smart_rollup_node/refutation_coordinator_types.mli similarity index 100% rename from src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_coordinator_types.mli rename to src/lib_smart_rollup_node/refutation_coordinator_types.mli diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_coordinator_types.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_coordinator_types.ml deleted file mode 100644 index 314698ed82ff..000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_coordinator_types.ml +++ /dev/null @@ -1,56 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 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. *) -(* *) -(*****************************************************************************) - -module Request = struct - type ('a, 'b) t = Process : Layer1.head -> (unit, error trace) t - - type view = View : _ t -> view - - let view req = View req - - let encoding = - let open Data_encoding in - union - [ - case - (Tag 0) - ~title:"Process" - (obj2 - (req "request" (constant "process")) - (req "block" Layer1.head_encoding)) - (function View (Process b) -> Some ((), b)) - (fun ((), b) -> View (Process b)); - ] - - let pp ppf (View r) = - match r with - | Process {Layer1.hash; level} -> - Format.fprintf - ppf - "Processing new L1 head %a at level %ld" - Block_hash.pp - hash - level -end diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_coordinator_types.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_coordinator_types.mli deleted file mode 100644 index f26d46885c77..000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_coordinator_types.mli +++ /dev/null @@ -1,38 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 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. *) -(* *) -(*****************************************************************************) - -module Request : sig - (** Type of requests accepted by the refutation coordinator. *) - type ('a, 'b) t = - | Process : Layer1.head -> (unit, error trace) t - (** Request to process new refutation games. *) - - type view = View : _ t -> view - - include - Worker_intf.REQUEST - with type ('a, 'request_error) t := ('a, 'request_error) t - and type view := view -end diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_coordinator_types.ml b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_coordinator_types.ml deleted file mode 100644 index 314698ed82ff..000000000000 --- a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_coordinator_types.ml +++ /dev/null @@ -1,56 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 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. *) -(* *) -(*****************************************************************************) - -module Request = struct - type ('a, 'b) t = Process : Layer1.head -> (unit, error trace) t - - type view = View : _ t -> view - - let view req = View req - - let encoding = - let open Data_encoding in - union - [ - case - (Tag 0) - ~title:"Process" - (obj2 - (req "request" (constant "process")) - (req "block" Layer1.head_encoding)) - (function View (Process b) -> Some ((), b)) - (fun ((), b) -> View (Process b)); - ] - - let pp ppf (View r) = - match r with - | Process {Layer1.hash; level} -> - Format.fprintf - ppf - "Processing new L1 head %a at level %ld" - Block_hash.pp - hash - level -end diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_coordinator_types.mli b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_coordinator_types.mli deleted file mode 100644 index f26d46885c77..000000000000 --- a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_coordinator_types.mli +++ /dev/null @@ -1,38 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 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. *) -(* *) -(*****************************************************************************) - -module Request : sig - (** Type of requests accepted by the refutation coordinator. *) - type ('a, 'b) t = - | Process : Layer1.head -> (unit, error trace) t - (** Request to process new refutation games. *) - - type view = View : _ t -> view - - include - Worker_intf.REQUEST - with type ('a, 'request_error) t := ('a, 'request_error) t - and type view := view -end diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_coordinator_types.ml b/src/proto_alpha/lib_sc_rollup_node/refutation_coordinator_types.ml deleted file mode 100644 index 314698ed82ff..000000000000 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_coordinator_types.ml +++ /dev/null @@ -1,56 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 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. *) -(* *) -(*****************************************************************************) - -module Request = struct - type ('a, 'b) t = Process : Layer1.head -> (unit, error trace) t - - type view = View : _ t -> view - - let view req = View req - - let encoding = - let open Data_encoding in - union - [ - case - (Tag 0) - ~title:"Process" - (obj2 - (req "request" (constant "process")) - (req "block" Layer1.head_encoding)) - (function View (Process b) -> Some ((), b)) - (fun ((), b) -> View (Process b)); - ] - - let pp ppf (View r) = - match r with - | Process {Layer1.hash; level} -> - Format.fprintf - ppf - "Processing new L1 head %a at level %ld" - Block_hash.pp - hash - level -end diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_coordinator_types.mli b/src/proto_alpha/lib_sc_rollup_node/refutation_coordinator_types.mli deleted file mode 100644 index f26d46885c77..000000000000 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_coordinator_types.mli +++ /dev/null @@ -1,38 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 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. *) -(* *) -(*****************************************************************************) - -module Request : sig - (** Type of requests accepted by the refutation coordinator. *) - type ('a, 'b) t = - | Process : Layer1.head -> (unit, error trace) t - (** Request to process new refutation games. *) - - type view = View : _ t -> view - - include - Worker_intf.REQUEST - with type ('a, 'request_error) t := ('a, 'request_error) t - and type view := view -end -- GitLab From 4560cb00d1a4b2a42a11c4150941811f860e97cd Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 25 Jul 2023 17:57:26 +0200 Subject: [PATCH 08/17] SCORU/Node: move refutation player worker types --- .../refutation_player_types.ml | 29 ++++---- .../refutation_player_types.mli | 9 +-- .../refutation_player_types.mli | 45 ------------ .../refutation_player_types.ml | 73 ------------------- .../refutation_player_types.mli | 45 ------------ .../refutation_player_types.ml | 73 ------------------- .../refutation_player_types.ml | 73 ------------------- .../refutation_player_types.mli | 45 ------------ 8 files changed, 17 insertions(+), 375 deletions(-) rename src/{proto_016_PtMumbai/lib_sc_rollup_node => lib_smart_rollup_node}/refutation_player_types.ml (82%) rename src/{proto_018_Proxford/lib_sc_rollup_node => lib_smart_rollup_node}/refutation_player_types.mli (92%) delete mode 100644 src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player_types.mli delete mode 100644 src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player_types.ml delete mode 100644 src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player_types.mli delete mode 100644 src/proto_018_Proxford/lib_sc_rollup_node/refutation_player_types.ml delete mode 100644 src/proto_alpha/lib_sc_rollup_node/refutation_player_types.ml delete mode 100644 src/proto_alpha/lib_sc_rollup_node/refutation_player_types.mli diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player_types.ml b/src/lib_smart_rollup_node/refutation_player_types.ml similarity index 82% rename from src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player_types.ml rename to src/lib_smart_rollup_node/refutation_player_types.ml index 5cb43af30509..8ff59d0b8645 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player_types.ml +++ b/src/lib_smart_rollup_node/refutation_player_types.ml @@ -22,15 +22,11 @@ (* DEALINGS IN THE SOFTWARE. *) (* *) (*****************************************************************************) -open Protocol -open Alpha_context module Request = struct type ('a, 'b) t = - | Play : Sc_rollup.Game.t -> (unit, error trace) t - | Play_opening : - Sc_rollup.Refutation_storage.conflict - -> (unit, error trace) t + | Play : Game.t -> (unit, error trace) t + | Play_opening : Game.conflict -> (unit, error trace) t type view = View : _ t -> view @@ -43,9 +39,7 @@ module Request = struct case (Tag 0) ~title:"Play" - (obj2 - (req "request" (constant "play")) - (req "game" Sc_rollup.Game.encoding)) + (obj2 (req "request" (constant "play")) (req "game" Game.encoding)) (function View (Play g) -> Some ((), g) | _ -> None) (fun ((), g) -> View (Play g)); case @@ -53,21 +47,28 @@ module Request = struct ~title:"Play opening" (obj2 (req "request" (constant "play_opening")) - (req "conflict" Sc_rollup.Refutation_storage.conflict_encoding)) + (req "conflict" Game.conflict_encoding)) (function View (Play_opening c) -> Some ((), c) | _ -> None) (fun ((), c) -> View (Play_opening c)); ] let pp ppf (View r) = match r with - | Play game -> Format.fprintf ppf "Playing game %a" Sc_rollup.Game.pp game + | Play game -> + Format.fprintf + ppf + "Playing game %a" + Data_encoding.Json.pp + (Data_encoding.Json.construct Game.encoding game) | Play_opening conflict -> Format.fprintf ppf "Playing opening move for conflict against staker %a at our \ commitment %a" - Sc_rollup.Staker.pp + Signature.Public_key_hash.pp conflict.other - Sc_rollup.Commitment.pp - conflict.our_commitment + Data_encoding.Json.pp + (Data_encoding.Json.construct + Commitment.encoding + conflict.our_commitment) end diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_player_types.mli b/src/lib_smart_rollup_node/refutation_player_types.mli similarity index 92% rename from src/proto_018_Proxford/lib_sc_rollup_node/refutation_player_types.mli rename to src/lib_smart_rollup_node/refutation_player_types.mli index d29fd8289f45..9479a391e48c 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_player_types.mli +++ b/src/lib_smart_rollup_node/refutation_player_types.mli @@ -23,17 +23,12 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context - module Request : sig (** Type of requests accepted by the refutation player. *) type ('a, 'b) t = - | Play : Sc_rollup.Game.t -> (unit, error trace) t + | Play : Game.t -> (unit, error trace) t (** Play a step of an ongoing refutation game. *) - | Play_opening : - Sc_rollup.Refutation_storage.conflict - -> (unit, error trace) t + | Play_opening : Game.conflict -> (unit, error trace) t (** Play the opening move of a refutation game. *) type view = View : _ t -> view diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player_types.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player_types.mli deleted file mode 100644 index d29fd8289f45..000000000000 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player_types.mli +++ /dev/null @@ -1,45 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -open Protocol -open Alpha_context - -module Request : sig - (** Type of requests accepted by the refutation player. *) - type ('a, 'b) t = - | Play : Sc_rollup.Game.t -> (unit, error trace) t - (** Play a step of an ongoing refutation game. *) - | Play_opening : - Sc_rollup.Refutation_storage.conflict - -> (unit, error trace) t - (** Play the opening move of a refutation game. *) - - type view = View : _ t -> view - - include - Worker_intf.REQUEST - with type ('a, 'request_error) t := ('a, 'request_error) t - and type view := view -end diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player_types.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player_types.ml deleted file mode 100644 index 5cb43af30509..000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player_types.ml +++ /dev/null @@ -1,73 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) -open Protocol -open Alpha_context - -module Request = struct - type ('a, 'b) t = - | Play : Sc_rollup.Game.t -> (unit, error trace) t - | Play_opening : - Sc_rollup.Refutation_storage.conflict - -> (unit, error trace) t - - type view = View : _ t -> view - - let view req = View req - - let encoding = - let open Data_encoding in - union - [ - case - (Tag 0) - ~title:"Play" - (obj2 - (req "request" (constant "play")) - (req "game" Sc_rollup.Game.encoding)) - (function View (Play g) -> Some ((), g) | _ -> None) - (fun ((), g) -> View (Play g)); - case - (Tag 1) - ~title:"Play opening" - (obj2 - (req "request" (constant "play_opening")) - (req "conflict" Sc_rollup.Refutation_storage.conflict_encoding)) - (function View (Play_opening c) -> Some ((), c) | _ -> None) - (fun ((), c) -> View (Play_opening c)); - ] - - let pp ppf (View r) = - match r with - | Play game -> Format.fprintf ppf "Playing game %a" Sc_rollup.Game.pp game - | Play_opening conflict -> - Format.fprintf - ppf - "Playing opening move for conflict against staker %a at our \ - commitment %a" - Sc_rollup.Staker.pp - conflict.other - Sc_rollup.Commitment.pp - conflict.our_commitment -end diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player_types.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player_types.mli deleted file mode 100644 index d29fd8289f45..000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player_types.mli +++ /dev/null @@ -1,45 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -open Protocol -open Alpha_context - -module Request : sig - (** Type of requests accepted by the refutation player. *) - type ('a, 'b) t = - | Play : Sc_rollup.Game.t -> (unit, error trace) t - (** Play a step of an ongoing refutation game. *) - | Play_opening : - Sc_rollup.Refutation_storage.conflict - -> (unit, error trace) t - (** Play the opening move of a refutation game. *) - - type view = View : _ t -> view - - include - Worker_intf.REQUEST - with type ('a, 'request_error) t := ('a, 'request_error) t - and type view := view -end diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_player_types.ml b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_player_types.ml deleted file mode 100644 index 5cb43af30509..000000000000 --- a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_player_types.ml +++ /dev/null @@ -1,73 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) -open Protocol -open Alpha_context - -module Request = struct - type ('a, 'b) t = - | Play : Sc_rollup.Game.t -> (unit, error trace) t - | Play_opening : - Sc_rollup.Refutation_storage.conflict - -> (unit, error trace) t - - type view = View : _ t -> view - - let view req = View req - - let encoding = - let open Data_encoding in - union - [ - case - (Tag 0) - ~title:"Play" - (obj2 - (req "request" (constant "play")) - (req "game" Sc_rollup.Game.encoding)) - (function View (Play g) -> Some ((), g) | _ -> None) - (fun ((), g) -> View (Play g)); - case - (Tag 1) - ~title:"Play opening" - (obj2 - (req "request" (constant "play_opening")) - (req "conflict" Sc_rollup.Refutation_storage.conflict_encoding)) - (function View (Play_opening c) -> Some ((), c) | _ -> None) - (fun ((), c) -> View (Play_opening c)); - ] - - let pp ppf (View r) = - match r with - | Play game -> Format.fprintf ppf "Playing game %a" Sc_rollup.Game.pp game - | Play_opening conflict -> - Format.fprintf - ppf - "Playing opening move for conflict against staker %a at our \ - commitment %a" - Sc_rollup.Staker.pp - conflict.other - Sc_rollup.Commitment.pp - conflict.our_commitment -end diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_player_types.ml b/src/proto_alpha/lib_sc_rollup_node/refutation_player_types.ml deleted file mode 100644 index 5cb43af30509..000000000000 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_player_types.ml +++ /dev/null @@ -1,73 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) -open Protocol -open Alpha_context - -module Request = struct - type ('a, 'b) t = - | Play : Sc_rollup.Game.t -> (unit, error trace) t - | Play_opening : - Sc_rollup.Refutation_storage.conflict - -> (unit, error trace) t - - type view = View : _ t -> view - - let view req = View req - - let encoding = - let open Data_encoding in - union - [ - case - (Tag 0) - ~title:"Play" - (obj2 - (req "request" (constant "play")) - (req "game" Sc_rollup.Game.encoding)) - (function View (Play g) -> Some ((), g) | _ -> None) - (fun ((), g) -> View (Play g)); - case - (Tag 1) - ~title:"Play opening" - (obj2 - (req "request" (constant "play_opening")) - (req "conflict" Sc_rollup.Refutation_storage.conflict_encoding)) - (function View (Play_opening c) -> Some ((), c) | _ -> None) - (fun ((), c) -> View (Play_opening c)); - ] - - let pp ppf (View r) = - match r with - | Play game -> Format.fprintf ppf "Playing game %a" Sc_rollup.Game.pp game - | Play_opening conflict -> - Format.fprintf - ppf - "Playing opening move for conflict against staker %a at our \ - commitment %a" - Sc_rollup.Staker.pp - conflict.other - Sc_rollup.Commitment.pp - conflict.our_commitment -end diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_player_types.mli b/src/proto_alpha/lib_sc_rollup_node/refutation_player_types.mli deleted file mode 100644 index d29fd8289f45..000000000000 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_player_types.mli +++ /dev/null @@ -1,45 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -open Protocol -open Alpha_context - -module Request : sig - (** Type of requests accepted by the refutation player. *) - type ('a, 'b) t = - | Play : Sc_rollup.Game.t -> (unit, error trace) t - (** Play a step of an ongoing refutation game. *) - | Play_opening : - Sc_rollup.Refutation_storage.conflict - -> (unit, error trace) t - (** Play the opening move of a refutation game. *) - - type view = View : _ t -> view - - include - Worker_intf.REQUEST - with type ('a, 'request_error) t := ('a, 'request_error) t - and type view := view -end -- GitLab From 0068c51ee44d28fdcdc0a267c7829000fcedb14e Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 29 Jun 2023 16:43:46 +0200 Subject: [PATCH 09/17] SCORU/Node/Alpha: remove protocol deps from refutation coordinator and player --- .../refutation_coordinator.ml | 34 +++++--- .../lib_sc_rollup_node/refutation_game.ml | 85 +++++++++++-------- .../lib_sc_rollup_node/refutation_game.mli | 13 ++- .../refutation_game_event.ml | 27 +++--- .../lib_sc_rollup_node/refutation_player.ml | 25 +++--- .../lib_sc_rollup_node/refutation_player.mli | 13 ++- 6 files changed, 103 insertions(+), 94 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_coordinator.ml b/src/proto_alpha/lib_sc_rollup_node/refutation_coordinator.ml index 21403e6efef2..1ed4e1eb8efa 100644 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_coordinator.ml +++ b/src/proto_alpha/lib_sc_rollup_node/refutation_coordinator.ml @@ -23,10 +23,7 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context open Refutation_coordinator_types -include Refutation_game module Player = Refutation_player module Pkh_map = Signature.Public_key_hash.Map module Pkh_table = Signature.Public_key_hash.Table @@ -37,19 +34,30 @@ type state = { pending_opponents : unit Pkh_table.t; } -let get_conflicts cctxt head_block = - Plugin.RPC.Sc_rollup.conflicts cctxt (cctxt#chain, head_block) +let get_conflicts cctxt head_block rollup staker = + let open Lwt_result_syntax in + let+ conflicts = + Plugin.RPC.Sc_rollup.conflicts cctxt (cctxt#chain, head_block) rollup staker + in + List.map Sc_rollup_proto_types.Game.conflict_to_octez conflicts -let get_ongoing_games cctxt head_block = - Plugin.RPC.Sc_rollup.ongoing_refutation_games cctxt (cctxt#chain, head_block) +let get_ongoing_games cctxt head_block rollup staker = + let open Lwt_result_syntax in + let+ games = + Plugin.RPC.Sc_rollup.ongoing_refutation_games + cctxt + (cctxt#chain, head_block) + rollup + staker + in + List.map + (fun (game, staker1, staker2) -> + (Sc_rollup_proto_types.Game.to_octez game, staker1, staker2)) + games let untracked_conflicts opponent_players conflicts = List.filter - (fun conflict -> - not - @@ Pkh_map.mem - conflict.Sc_rollup.Refutation_storage.other - opponent_players) + (fun conflict -> not @@ Pkh_map.mem conflict.Game.other opponent_players) conflicts (* Transform the list of ongoing games [(Game.t * pkh * pkh) list] @@ -99,7 +107,7 @@ let on_process Layer1.{hash; level} state = let* () = List.iter_ep (fun conflict -> - let other = conflict.Sc_rollup.Refutation_storage.other in + let other = conflict.Octez_smart_rollup.Game.other in Pkh_table.replace state.pending_opponents other () ; let game = Pkh_map.find_opt other ongoing_game_map in Player.init_and_play node_ctxt ~self ~conflict ~game ~level) diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_game.ml b/src/proto_alpha/lib_sc_rollup_node/refutation_game.ml index afabcca77936..046d067eb0b9 100644 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_game.ml +++ b/src/proto_alpha/lib_sc_rollup_node/refutation_game.ml @@ -55,7 +55,7 @@ let node_role ~self Sc_rollup.Game.Index.{alice; bob} = type role = Our_turn of {opponent : public_key_hash} | Their_turn -let turn ~self game players = +let turn ~self (game : Octez_smart_rollup.Game.t) players = let Sc_rollup.Game.Index.{alice; bob} = players in match (node_role ~self players, game.turn) with | Alice, Alice -> Our_turn {opponent = bob} @@ -70,11 +70,7 @@ let inject_next_move node_ctxt source ~refutation ~opponent = let open Lwt_result_syntax in let refute_operation = L1_operation.Refute - { - rollup = node_ctxt.Node_context.rollup_address; - refutation = Sc_rollup_proto_types.Game.refutation_to_octez refutation; - opponent; - } + {rollup = node_ctxt.Node_context.rollup_address; refutation; opponent} in let* _hash = Injector.add_pending_operation ~source refute_operation in return_unit @@ -167,23 +163,24 @@ let metadata (node_ctxt : _ Node_context.t) = let origination_level = Raw_level.of_int32_exn node_ctxt.genesis_info.level in Sc_rollup.Metadata.{address; origination_level} -let generate_proof (node_ctxt : _ Node_context.t) game start_state = +let generate_proof (node_ctxt : _ Node_context.t) + (game : Octez_smart_rollup.Game.t) start_state = let open Lwt_result_syntax in let module PVM = (val Pvm.of_kind node_ctxt.kind) in - let snapshot = game.inbox_snapshot in + let snapshot = + Sc_rollup_proto_types.Inbox.history_proof_of_octez game.inbox_snapshot + in (* NOTE: [snapshot_level_int32] below refers to the level of the snapshotted inbox (from the skip list) which also matches [game.start_level - 1]. *) let snapshot_level_int32 = - Raw_level.to_int32 (Sc_rollup.Inbox.Skip_list.content snapshot).level + (Octez_smart_rollup.Inbox.Skip_list.content game.inbox_snapshot).level in let get_snapshot_head () = let+ hash = Node_context.hash_of_level node_ctxt snapshot_level_int32 in Layer1.{hash; level = snapshot_level_int32} in let* context = - let* start_hash = - Node_context.hash_of_level node_ctxt (Raw_level.to_int32 game.inbox_level) - in + let* start_hash = Node_context.hash_of_level node_ctxt game.inbox_level in let+ context = Node_context.checkout_context node_ctxt start_hash in Context.index context in @@ -301,13 +298,13 @@ let generate_proof (node_ctxt : _ Node_context.t) game start_state = trace (Sc_rollup_node_errors.Cannot_produce_proof { - inbox_level = Raw_level.to_int32 game.inbox_level; + inbox_level = game.inbox_level; start_tick = Sc_rollup.Tick.to_z start_tick; }) @@ (Sc_rollup.Proof.produce ~metadata (module P) - game.inbox_level + (Raw_level.of_int32_exn game.inbox_level) ~is_reveal_enabled >|= Environment.wrap_tzresult) in @@ -320,7 +317,7 @@ let generate_proof (node_ctxt : _ Node_context.t) game start_state = Sc_rollup.Proof.valid ~metadata snapshot - game.inbox_level + (Raw_level.of_int32_exn game.inbox_level) dal_slots_history dal_parameters ~dal_attestation_lag @@ -329,7 +326,11 @@ let generate_proof (node_ctxt : _ Node_context.t) game start_state = ~is_reveal_enabled >|= Environment.wrap_tzresult in - if Result.is_ok res then return proof else assert false + assert (Result.is_ok res) ; + let proof = + Data_encoding.Binary.to_string_exn Sc_rollup.Proof.encoding proof + in + return proof type pvm_intermediate_state = | Hash of Sc_rollup.State_hash.t @@ -343,7 +344,7 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok node_ctxt ?start_state ~tick:(Sc_rollup.Tick.to_z tick) - last_level + (Raw_level.of_int32_exn last_level) in let state_hash_of_eval_state Pvm_plugin_sig.{state_hash; _} = state_hash in let start_hash, start_tick, start_state = @@ -353,14 +354,16 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok (state_hash, tick, Some state) in let start_chunk = - Sc_rollup.Dissection_chunk.{state_hash = Some start_hash; tick = start_tick} + Sc_rollup.Dissection_chunk. + {state_hash = Some start_hash; tick = Sc_rollup.Tick.of_z start_tick} in let our_state, our_tick = our_view in let our_state_hash = Option.map (fun Pvm_plugin_sig.{state_hash; _} -> state_hash) our_state in let our_stop_chunk = - Sc_rollup.Dissection_chunk.{state_hash = our_state_hash; tick = our_tick} + Sc_rollup.Dissection_chunk. + {state_hash = our_state_hash; tick = Sc_rollup.Tick.of_z our_tick} in let module PVM = (val Pvm.of_kind node_ctxt.kind) in let* dissection = @@ -375,6 +378,9 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok ~our_stop_chunk ~default_number_of_sections in + let dissection = + List.map Sc_rollup_proto_types.Game.dissection_chunk_to_octez dissection + in let*! () = Refutation_game_event.computed_dissection ~opponent @@ -389,7 +395,8 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok performs a new dissection of the execution trace or provides a refutation proof to serve as the next move of the [game]. *) let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent - game dissection = + (game : Octez_smart_rollup.Game.t) + (dissection : Octez_smart_rollup.Game.dissection_chunk list) = let open Lwt_result_syntax in let rec traverse ok = function | [] -> @@ -400,8 +407,7 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent tzfail Sc_rollup_node_errors .Unreliable_tezos_node_returning_inconsistent_game - | Sc_rollup.Dissection_chunk.{state_hash = their_hash; tick} :: dissection - -> ( + | Octez_smart_rollup.Game.{state_hash = their_hash; tick} :: dissection -> ( let start_state = match ok with | Hash _, _ -> None @@ -411,8 +417,8 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent Interpreter.state_of_tick node_ctxt ?start_state - ~tick:(Sc_rollup.Tick.to_z tick) - game.inbox_level + ~tick + (Raw_level.of_int32_exn game.inbox_level) in match (their_hash, our) with | None, None -> @@ -421,12 +427,12 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent assert false | Some _, None | None, Some _ -> return (ok, (our, tick)) | Some their_hash, Some ({state_hash = our_hash; _} as our_state) -> - if Sc_rollup.State_hash.equal our_hash their_hash then + if Octez_smart_rollup.State_hash.equal our_hash their_hash then traverse (Evaluated our_state, tick) dissection else return (ok, (our, tick))) in match dissection with - | Sc_rollup.Dissection_chunk.{state_hash = Some hash; tick} :: dissection -> + | {state_hash = Some hash; tick} :: dissection -> let* ok, ko = traverse (Hash hash, tick) dissection in let* dissection = new_dissection @@ -439,7 +445,7 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent in let _, choice = ok in let _, ko_tick = ko in - let chosen_section_len = Sc_rollup.Tick.distance ko_tick choice in + let chosen_section_len = Z.abs (Z.sub choice ko_tick) in return (choice, chosen_section_len, dissection) | [] | {state_hash = None; _} :: _ -> (* @@ -450,14 +456,14 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent tzfail Sc_rollup_node_errors.Unreliable_tezos_node_returning_inconsistent_game -let next_move node_ctxt ~opponent game = +let next_move node_ctxt ~opponent (game : Octez_smart_rollup.Game.t) = let open Lwt_result_syntax in let final_move start_tick = let* start_state = Interpreter.state_of_tick node_ctxt - ~tick:(Sc_rollup.Tick.to_z start_tick) - game.inbox_level + ~tick:start_tick + (Raw_level.of_int32_exn game.inbox_level) in match start_state with | None -> @@ -467,7 +473,7 @@ let next_move node_ctxt ~opponent game = | Some {state = start_state; _} -> let* proof = generate_proof node_ctxt game start_state in let choice = start_tick in - return (Move {choice; step = Proof proof}) + return (Octez_smart_rollup.Game.Move {choice; step = Proof proof}) in match game.game_state with @@ -481,7 +487,9 @@ let next_move node_ctxt ~opponent game = dissection in if Z.(equal chosen_section_len one) then final_move choice - else return (Move {choice; step = Dissection dissection}) + else + return + (Octez_smart_rollup.Game.Move {choice; step = Dissection dissection}) | Final_move {agreed_start_chunk; refuted_stop_chunk = _} -> let choice = agreed_start_chunk.tick in final_move choice @@ -541,15 +549,18 @@ let play node_ctxt ~self game opponent = play_timeout node_ctxt self index | None -> return_unit) -let play_opening_move node_ctxt self conflict = +let play_opening_move node_ctxt self + (conflict : Octez_smart_rollup.Game.conflict) = let open Lwt_syntax in - let open Sc_rollup.Refutation_storage in let* () = Refutation_game_event.conflict_detected conflict in let player_commitment_hash = - Sc_rollup.Commitment.hash_uncarbonated conflict.our_commitment + Octez_smart_rollup.Commitment.hash conflict.our_commitment in let opponent_commitment_hash = - Sc_rollup.Commitment.hash_uncarbonated conflict.their_commitment + Octez_smart_rollup.Commitment.hash conflict.their_commitment + in + let refutation = + Octez_smart_rollup.Game.Start + {player_commitment_hash; opponent_commitment_hash} in - let refutation = Start {player_commitment_hash; opponent_commitment_hash} in inject_next_move node_ctxt self ~refutation ~opponent:conflict.other diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_game.mli b/src/proto_alpha/lib_sc_rollup_node/refutation_game.mli index 3229857d1aa7..1f8668ebb042 100644 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_game.mli +++ b/src/proto_alpha/lib_sc_rollup_node/refutation_game.mli @@ -23,24 +23,21 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context - (** This module implements the refutation game logic of the rollup node. *) (** [play_opening_move node_ctxt self conflict] injects the opening refutation game move for [conflict]. *) val play_opening_move : [< `Read | `Write > `Read] Node_context.t -> - public_key_hash -> - Sc_rollup.Refutation_storage.conflict -> + Signature.public_key_hash -> + Octez_smart_rollup.Game.conflict -> (unit, tztrace) result Lwt.t (** [play head_block node_ctxt ~self game opponent] injects the next move in the refutation [game] played by [self] and [opponent]. *) val play : Node_context.rw -> - self:public_key_hash -> - Sc_rollup.Game.t -> - public_key_hash -> + self:Signature.public_key_hash -> + Octez_smart_rollup.Game.t -> + Signature.public_key_hash -> (unit, tztrace) result Lwt.t diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_game_event.ml b/src/proto_alpha/lib_sc_rollup_node/refutation_game_event.ml index ceb5ef25e148..9a6ebaf4c50c 100644 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_game_event.ml +++ b/src/proto_alpha/lib_sc_rollup_node/refutation_game_event.ml @@ -64,11 +64,11 @@ module Simple = struct at level {level} with staker {other} that hash issued commitment \ {their_commitment_hash} both based on {parent_commitment_hash}." ~level:Notice - ("our_commitment_hash", Sc_rollup.Commitment.Hash.encoding) - ("level", Raw_level.encoding) - ("other", Sc_rollup.Staker.encoding) - ("their_commitment_hash", Sc_rollup.Commitment.Hash.encoding) - ("parent_commitment_hash", Sc_rollup.Commitment.Hash.encoding) + ("our_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) + ("level", Data_encoding.int32) + ("other", Signature.Public_key_hash.encoding) + ("their_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) + ("parent_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) let potential_conflict_detected = declare_4 @@ -112,9 +112,10 @@ module Simple = struct {end_tick}: {dissection}." ~level:Debug ("opponent", Signature.Public_key_hash.encoding) - ("start_tick", Sc_rollup.Tick.encoding) - ("end_tick", Sc_rollup.Tick.encoding) - ("dissection", Data_encoding.list dissection_chunk_encoding) + ("start_tick", Data_encoding.z) + ("end_tick", Data_encoding.z) + ( "dissection", + Data_encoding.list Octez_smart_rollup.Game.dissection_chunk_encoding ) module Worker (ARG : sig val section : string list @@ -166,8 +167,8 @@ module Simple = struct ~level:Notice ("opponent", Signature.Public_key_hash.encoding) ~pp1:Signature.Public_key_hash.pp - ("commitment", Sc_rollup.Commitment.encoding) - ~pp2:Sc_rollup.Commitment.pp + ("commitment", Octez_smart_rollup.Commitment.encoding) + ~pp2:Octez_smart_rollup.Commitment.pp let stopped = declare_1 @@ -201,12 +202,12 @@ let timeout address = Simple.(emit timeout address) let invalid_move () = Simple.(emit invalid_move ()) -let conflict_detected (conflict : Sc_rollup.Refutation_storage.conflict) = +let conflict_detected (conflict : Octez_smart_rollup.Game.conflict) = let our_commitment_hash = - Sc_rollup.Commitment.hash_uncarbonated conflict.our_commitment + Octez_smart_rollup.Commitment.hash conflict.our_commitment in let their_commitment_hash = - Sc_rollup.Commitment.hash_uncarbonated conflict.their_commitment + Octez_smart_rollup.Commitment.hash conflict.their_commitment in let parent_commitment_hash = conflict.parent_commitment in let other = conflict.other in diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_player.ml b/src/proto_alpha/lib_sc_rollup_node/refutation_player.ml index 72901a452bf2..3d7c8d596905 100644 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_player.ml +++ b/src/proto_alpha/lib_sc_rollup_node/refutation_player.ml @@ -23,23 +23,22 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context open Refutation_player_types open Refutation_game module Types = struct type state = { node_ctxt : Node_context.rw; - self : public_key_hash; - opponent : public_key_hash; - mutable last_move_cache : (Sc_rollup.Game.game_state * int32) option; + self : Signature.public_key_hash; + opponent : Signature.public_key_hash; + mutable last_move_cache : + (Octez_smart_rollup.Game.game_state * int32) option; } type parameters = { node_ctxt : Node_context.rw; - self : public_key_hash; - conflict : Sc_rollup.Refutation_storage.conflict; + self : Signature.public_key_hash; + conflict : Octez_smart_rollup.Game.conflict; } end @@ -110,8 +109,8 @@ let init node_ctxt ~self ~conflict = let open Lwt_result_syntax in let*! () = Refutation_game_event.Player.started - conflict.Sc_rollup.Refutation_storage.other - conflict.Sc_rollup.Refutation_storage.our_commitment + conflict.Game.other + conflict.Game.our_commitment in let worker_promise, worker_waker = Lwt.task () in let* worker = @@ -140,10 +139,7 @@ let should_move ~level game last_move_cache = match last_move_cache with | None -> true | Some (last_move_game_state, last_move_level) -> - (not - (Sc_rollup.Game.game_state_equal - game.Sc_rollup.Game.game_state - last_move_game_state)) + (not (Game.game_state_equal game.Game.game_state last_move_game_state)) || Int32.( sub level last_move_level > of_int Configuration.refutation_player_buffer_levels) @@ -153,8 +149,7 @@ let play w game ~(level : int32) = let state = Worker.state w in if should_move ~level game state.last_move_cache then ( let* pushed = Worker.Queue.push_request w (Request.Play game) in - if pushed then - state.last_move_cache <- Some (game.Sc_rollup.Game.game_state, level) ; + if pushed then state.last_move_cache <- Some (game.Game.game_state, level) ; return_unit) else return_unit diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_player.mli b/src/proto_alpha/lib_sc_rollup_node/refutation_player.mli index 92592e7c7cc5..64cca0e7e56a 100644 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_player.mli +++ b/src/proto_alpha/lib_sc_rollup_node/refutation_player.mli @@ -23,9 +23,6 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context - (** Worker module for a single refutation game player. The node's refutation coordinator will spawn a new refutation player for each refutation game. *) @@ -40,20 +37,20 @@ type worker = Worker.infinite Worker.queue Worker.t is passed, the worker will play the opening move for [conflict]. *) val init_and_play : Node_context.rw -> - self:public_key_hash -> - conflict:Sc_rollup.Refutation_storage.conflict -> - game:Sc_rollup.Game.t option -> + self:Signature.public_key_hash -> + conflict:Game.conflict -> + game:Game.t option -> level:int32 -> unit tzresult Lwt.t (** [play worker game ~level] makes the [worker] play the next move depending on the [game] state for their conflict. *) -val play : worker -> Sc_rollup.Game.t -> level:int32 -> unit Lwt.t +val play : worker -> Game.t -> level:int32 -> unit Lwt.t (** Shutdown a refutaiton game player. *) val shutdown : worker -> unit Lwt.t (** [current_games ()] lists the opponents' this node is playing refutation games against, alongside the worker that takes care of each game. *) -val current_games : unit -> (public_key_hash * worker) list +val current_games : unit -> (Signature.public_key_hash * worker) list -- GitLab From 576100cc25cc3100e2cc91ece63ede198b579791 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 29 Jun 2023 16:43:46 +0200 Subject: [PATCH 10/17] SCORU/Node/Oxford: remove protocol deps from refutation coordinator and player --- .../refutation_coordinator.ml | 34 +++++--- .../lib_sc_rollup_node/refutation_game.ml | 85 +++++++++++-------- .../lib_sc_rollup_node/refutation_game.mli | 13 ++- .../refutation_game_event.ml | 27 +++--- .../lib_sc_rollup_node/refutation_player.ml | 25 +++--- .../lib_sc_rollup_node/refutation_player.mli | 13 ++- 6 files changed, 103 insertions(+), 94 deletions(-) diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_coordinator.ml b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_coordinator.ml index 21403e6efef2..1ed4e1eb8efa 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_coordinator.ml +++ b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_coordinator.ml @@ -23,10 +23,7 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context open Refutation_coordinator_types -include Refutation_game module Player = Refutation_player module Pkh_map = Signature.Public_key_hash.Map module Pkh_table = Signature.Public_key_hash.Table @@ -37,19 +34,30 @@ type state = { pending_opponents : unit Pkh_table.t; } -let get_conflicts cctxt head_block = - Plugin.RPC.Sc_rollup.conflicts cctxt (cctxt#chain, head_block) +let get_conflicts cctxt head_block rollup staker = + let open Lwt_result_syntax in + let+ conflicts = + Plugin.RPC.Sc_rollup.conflicts cctxt (cctxt#chain, head_block) rollup staker + in + List.map Sc_rollup_proto_types.Game.conflict_to_octez conflicts -let get_ongoing_games cctxt head_block = - Plugin.RPC.Sc_rollup.ongoing_refutation_games cctxt (cctxt#chain, head_block) +let get_ongoing_games cctxt head_block rollup staker = + let open Lwt_result_syntax in + let+ games = + Plugin.RPC.Sc_rollup.ongoing_refutation_games + cctxt + (cctxt#chain, head_block) + rollup + staker + in + List.map + (fun (game, staker1, staker2) -> + (Sc_rollup_proto_types.Game.to_octez game, staker1, staker2)) + games let untracked_conflicts opponent_players conflicts = List.filter - (fun conflict -> - not - @@ Pkh_map.mem - conflict.Sc_rollup.Refutation_storage.other - opponent_players) + (fun conflict -> not @@ Pkh_map.mem conflict.Game.other opponent_players) conflicts (* Transform the list of ongoing games [(Game.t * pkh * pkh) list] @@ -99,7 +107,7 @@ let on_process Layer1.{hash; level} state = let* () = List.iter_ep (fun conflict -> - let other = conflict.Sc_rollup.Refutation_storage.other in + let other = conflict.Octez_smart_rollup.Game.other in Pkh_table.replace state.pending_opponents other () ; let game = Pkh_map.find_opt other ongoing_game_map in Player.init_and_play node_ctxt ~self ~conflict ~game ~level) diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game.ml b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game.ml index afabcca77936..046d067eb0b9 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game.ml +++ b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game.ml @@ -55,7 +55,7 @@ let node_role ~self Sc_rollup.Game.Index.{alice; bob} = type role = Our_turn of {opponent : public_key_hash} | Their_turn -let turn ~self game players = +let turn ~self (game : Octez_smart_rollup.Game.t) players = let Sc_rollup.Game.Index.{alice; bob} = players in match (node_role ~self players, game.turn) with | Alice, Alice -> Our_turn {opponent = bob} @@ -70,11 +70,7 @@ let inject_next_move node_ctxt source ~refutation ~opponent = let open Lwt_result_syntax in let refute_operation = L1_operation.Refute - { - rollup = node_ctxt.Node_context.rollup_address; - refutation = Sc_rollup_proto_types.Game.refutation_to_octez refutation; - opponent; - } + {rollup = node_ctxt.Node_context.rollup_address; refutation; opponent} in let* _hash = Injector.add_pending_operation ~source refute_operation in return_unit @@ -167,23 +163,24 @@ let metadata (node_ctxt : _ Node_context.t) = let origination_level = Raw_level.of_int32_exn node_ctxt.genesis_info.level in Sc_rollup.Metadata.{address; origination_level} -let generate_proof (node_ctxt : _ Node_context.t) game start_state = +let generate_proof (node_ctxt : _ Node_context.t) + (game : Octez_smart_rollup.Game.t) start_state = let open Lwt_result_syntax in let module PVM = (val Pvm.of_kind node_ctxt.kind) in - let snapshot = game.inbox_snapshot in + let snapshot = + Sc_rollup_proto_types.Inbox.history_proof_of_octez game.inbox_snapshot + in (* NOTE: [snapshot_level_int32] below refers to the level of the snapshotted inbox (from the skip list) which also matches [game.start_level - 1]. *) let snapshot_level_int32 = - Raw_level.to_int32 (Sc_rollup.Inbox.Skip_list.content snapshot).level + (Octez_smart_rollup.Inbox.Skip_list.content game.inbox_snapshot).level in let get_snapshot_head () = let+ hash = Node_context.hash_of_level node_ctxt snapshot_level_int32 in Layer1.{hash; level = snapshot_level_int32} in let* context = - let* start_hash = - Node_context.hash_of_level node_ctxt (Raw_level.to_int32 game.inbox_level) - in + let* start_hash = Node_context.hash_of_level node_ctxt game.inbox_level in let+ context = Node_context.checkout_context node_ctxt start_hash in Context.index context in @@ -301,13 +298,13 @@ let generate_proof (node_ctxt : _ Node_context.t) game start_state = trace (Sc_rollup_node_errors.Cannot_produce_proof { - inbox_level = Raw_level.to_int32 game.inbox_level; + inbox_level = game.inbox_level; start_tick = Sc_rollup.Tick.to_z start_tick; }) @@ (Sc_rollup.Proof.produce ~metadata (module P) - game.inbox_level + (Raw_level.of_int32_exn game.inbox_level) ~is_reveal_enabled >|= Environment.wrap_tzresult) in @@ -320,7 +317,7 @@ let generate_proof (node_ctxt : _ Node_context.t) game start_state = Sc_rollup.Proof.valid ~metadata snapshot - game.inbox_level + (Raw_level.of_int32_exn game.inbox_level) dal_slots_history dal_parameters ~dal_attestation_lag @@ -329,7 +326,11 @@ let generate_proof (node_ctxt : _ Node_context.t) game start_state = ~is_reveal_enabled >|= Environment.wrap_tzresult in - if Result.is_ok res then return proof else assert false + assert (Result.is_ok res) ; + let proof = + Data_encoding.Binary.to_string_exn Sc_rollup.Proof.encoding proof + in + return proof type pvm_intermediate_state = | Hash of Sc_rollup.State_hash.t @@ -343,7 +344,7 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok node_ctxt ?start_state ~tick:(Sc_rollup.Tick.to_z tick) - last_level + (Raw_level.of_int32_exn last_level) in let state_hash_of_eval_state Pvm_plugin_sig.{state_hash; _} = state_hash in let start_hash, start_tick, start_state = @@ -353,14 +354,16 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok (state_hash, tick, Some state) in let start_chunk = - Sc_rollup.Dissection_chunk.{state_hash = Some start_hash; tick = start_tick} + Sc_rollup.Dissection_chunk. + {state_hash = Some start_hash; tick = Sc_rollup.Tick.of_z start_tick} in let our_state, our_tick = our_view in let our_state_hash = Option.map (fun Pvm_plugin_sig.{state_hash; _} -> state_hash) our_state in let our_stop_chunk = - Sc_rollup.Dissection_chunk.{state_hash = our_state_hash; tick = our_tick} + Sc_rollup.Dissection_chunk. + {state_hash = our_state_hash; tick = Sc_rollup.Tick.of_z our_tick} in let module PVM = (val Pvm.of_kind node_ctxt.kind) in let* dissection = @@ -375,6 +378,9 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok ~our_stop_chunk ~default_number_of_sections in + let dissection = + List.map Sc_rollup_proto_types.Game.dissection_chunk_to_octez dissection + in let*! () = Refutation_game_event.computed_dissection ~opponent @@ -389,7 +395,8 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok performs a new dissection of the execution trace or provides a refutation proof to serve as the next move of the [game]. *) let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent - game dissection = + (game : Octez_smart_rollup.Game.t) + (dissection : Octez_smart_rollup.Game.dissection_chunk list) = let open Lwt_result_syntax in let rec traverse ok = function | [] -> @@ -400,8 +407,7 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent tzfail Sc_rollup_node_errors .Unreliable_tezos_node_returning_inconsistent_game - | Sc_rollup.Dissection_chunk.{state_hash = their_hash; tick} :: dissection - -> ( + | Octez_smart_rollup.Game.{state_hash = their_hash; tick} :: dissection -> ( let start_state = match ok with | Hash _, _ -> None @@ -411,8 +417,8 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent Interpreter.state_of_tick node_ctxt ?start_state - ~tick:(Sc_rollup.Tick.to_z tick) - game.inbox_level + ~tick + (Raw_level.of_int32_exn game.inbox_level) in match (their_hash, our) with | None, None -> @@ -421,12 +427,12 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent assert false | Some _, None | None, Some _ -> return (ok, (our, tick)) | Some their_hash, Some ({state_hash = our_hash; _} as our_state) -> - if Sc_rollup.State_hash.equal our_hash their_hash then + if Octez_smart_rollup.State_hash.equal our_hash their_hash then traverse (Evaluated our_state, tick) dissection else return (ok, (our, tick))) in match dissection with - | Sc_rollup.Dissection_chunk.{state_hash = Some hash; tick} :: dissection -> + | {state_hash = Some hash; tick} :: dissection -> let* ok, ko = traverse (Hash hash, tick) dissection in let* dissection = new_dissection @@ -439,7 +445,7 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent in let _, choice = ok in let _, ko_tick = ko in - let chosen_section_len = Sc_rollup.Tick.distance ko_tick choice in + let chosen_section_len = Z.abs (Z.sub choice ko_tick) in return (choice, chosen_section_len, dissection) | [] | {state_hash = None; _} :: _ -> (* @@ -450,14 +456,14 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent tzfail Sc_rollup_node_errors.Unreliable_tezos_node_returning_inconsistent_game -let next_move node_ctxt ~opponent game = +let next_move node_ctxt ~opponent (game : Octez_smart_rollup.Game.t) = let open Lwt_result_syntax in let final_move start_tick = let* start_state = Interpreter.state_of_tick node_ctxt - ~tick:(Sc_rollup.Tick.to_z start_tick) - game.inbox_level + ~tick:start_tick + (Raw_level.of_int32_exn game.inbox_level) in match start_state with | None -> @@ -467,7 +473,7 @@ let next_move node_ctxt ~opponent game = | Some {state = start_state; _} -> let* proof = generate_proof node_ctxt game start_state in let choice = start_tick in - return (Move {choice; step = Proof proof}) + return (Octez_smart_rollup.Game.Move {choice; step = Proof proof}) in match game.game_state with @@ -481,7 +487,9 @@ let next_move node_ctxt ~opponent game = dissection in if Z.(equal chosen_section_len one) then final_move choice - else return (Move {choice; step = Dissection dissection}) + else + return + (Octez_smart_rollup.Game.Move {choice; step = Dissection dissection}) | Final_move {agreed_start_chunk; refuted_stop_chunk = _} -> let choice = agreed_start_chunk.tick in final_move choice @@ -541,15 +549,18 @@ let play node_ctxt ~self game opponent = play_timeout node_ctxt self index | None -> return_unit) -let play_opening_move node_ctxt self conflict = +let play_opening_move node_ctxt self + (conflict : Octez_smart_rollup.Game.conflict) = let open Lwt_syntax in - let open Sc_rollup.Refutation_storage in let* () = Refutation_game_event.conflict_detected conflict in let player_commitment_hash = - Sc_rollup.Commitment.hash_uncarbonated conflict.our_commitment + Octez_smart_rollup.Commitment.hash conflict.our_commitment in let opponent_commitment_hash = - Sc_rollup.Commitment.hash_uncarbonated conflict.their_commitment + Octez_smart_rollup.Commitment.hash conflict.their_commitment + in + let refutation = + Octez_smart_rollup.Game.Start + {player_commitment_hash; opponent_commitment_hash} in - let refutation = Start {player_commitment_hash; opponent_commitment_hash} in inject_next_move node_ctxt self ~refutation ~opponent:conflict.other diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game.mli b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game.mli index 3229857d1aa7..1f8668ebb042 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game.mli +++ b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game.mli @@ -23,24 +23,21 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context - (** This module implements the refutation game logic of the rollup node. *) (** [play_opening_move node_ctxt self conflict] injects the opening refutation game move for [conflict]. *) val play_opening_move : [< `Read | `Write > `Read] Node_context.t -> - public_key_hash -> - Sc_rollup.Refutation_storage.conflict -> + Signature.public_key_hash -> + Octez_smart_rollup.Game.conflict -> (unit, tztrace) result Lwt.t (** [play head_block node_ctxt ~self game opponent] injects the next move in the refutation [game] played by [self] and [opponent]. *) val play : Node_context.rw -> - self:public_key_hash -> - Sc_rollup.Game.t -> - public_key_hash -> + self:Signature.public_key_hash -> + Octez_smart_rollup.Game.t -> + Signature.public_key_hash -> (unit, tztrace) result Lwt.t diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game_event.ml b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game_event.ml index ceb5ef25e148..9a6ebaf4c50c 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game_event.ml +++ b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game_event.ml @@ -64,11 +64,11 @@ module Simple = struct at level {level} with staker {other} that hash issued commitment \ {their_commitment_hash} both based on {parent_commitment_hash}." ~level:Notice - ("our_commitment_hash", Sc_rollup.Commitment.Hash.encoding) - ("level", Raw_level.encoding) - ("other", Sc_rollup.Staker.encoding) - ("their_commitment_hash", Sc_rollup.Commitment.Hash.encoding) - ("parent_commitment_hash", Sc_rollup.Commitment.Hash.encoding) + ("our_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) + ("level", Data_encoding.int32) + ("other", Signature.Public_key_hash.encoding) + ("their_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) + ("parent_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) let potential_conflict_detected = declare_4 @@ -112,9 +112,10 @@ module Simple = struct {end_tick}: {dissection}." ~level:Debug ("opponent", Signature.Public_key_hash.encoding) - ("start_tick", Sc_rollup.Tick.encoding) - ("end_tick", Sc_rollup.Tick.encoding) - ("dissection", Data_encoding.list dissection_chunk_encoding) + ("start_tick", Data_encoding.z) + ("end_tick", Data_encoding.z) + ( "dissection", + Data_encoding.list Octez_smart_rollup.Game.dissection_chunk_encoding ) module Worker (ARG : sig val section : string list @@ -166,8 +167,8 @@ module Simple = struct ~level:Notice ("opponent", Signature.Public_key_hash.encoding) ~pp1:Signature.Public_key_hash.pp - ("commitment", Sc_rollup.Commitment.encoding) - ~pp2:Sc_rollup.Commitment.pp + ("commitment", Octez_smart_rollup.Commitment.encoding) + ~pp2:Octez_smart_rollup.Commitment.pp let stopped = declare_1 @@ -201,12 +202,12 @@ let timeout address = Simple.(emit timeout address) let invalid_move () = Simple.(emit invalid_move ()) -let conflict_detected (conflict : Sc_rollup.Refutation_storage.conflict) = +let conflict_detected (conflict : Octez_smart_rollup.Game.conflict) = let our_commitment_hash = - Sc_rollup.Commitment.hash_uncarbonated conflict.our_commitment + Octez_smart_rollup.Commitment.hash conflict.our_commitment in let their_commitment_hash = - Sc_rollup.Commitment.hash_uncarbonated conflict.their_commitment + Octez_smart_rollup.Commitment.hash conflict.their_commitment in let parent_commitment_hash = conflict.parent_commitment in let other = conflict.other in diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_player.ml b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_player.ml index 72901a452bf2..3d7c8d596905 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_player.ml +++ b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_player.ml @@ -23,23 +23,22 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context open Refutation_player_types open Refutation_game module Types = struct type state = { node_ctxt : Node_context.rw; - self : public_key_hash; - opponent : public_key_hash; - mutable last_move_cache : (Sc_rollup.Game.game_state * int32) option; + self : Signature.public_key_hash; + opponent : Signature.public_key_hash; + mutable last_move_cache : + (Octez_smart_rollup.Game.game_state * int32) option; } type parameters = { node_ctxt : Node_context.rw; - self : public_key_hash; - conflict : Sc_rollup.Refutation_storage.conflict; + self : Signature.public_key_hash; + conflict : Octez_smart_rollup.Game.conflict; } end @@ -110,8 +109,8 @@ let init node_ctxt ~self ~conflict = let open Lwt_result_syntax in let*! () = Refutation_game_event.Player.started - conflict.Sc_rollup.Refutation_storage.other - conflict.Sc_rollup.Refutation_storage.our_commitment + conflict.Game.other + conflict.Game.our_commitment in let worker_promise, worker_waker = Lwt.task () in let* worker = @@ -140,10 +139,7 @@ let should_move ~level game last_move_cache = match last_move_cache with | None -> true | Some (last_move_game_state, last_move_level) -> - (not - (Sc_rollup.Game.game_state_equal - game.Sc_rollup.Game.game_state - last_move_game_state)) + (not (Game.game_state_equal game.Game.game_state last_move_game_state)) || Int32.( sub level last_move_level > of_int Configuration.refutation_player_buffer_levels) @@ -153,8 +149,7 @@ let play w game ~(level : int32) = let state = Worker.state w in if should_move ~level game state.last_move_cache then ( let* pushed = Worker.Queue.push_request w (Request.Play game) in - if pushed then - state.last_move_cache <- Some (game.Sc_rollup.Game.game_state, level) ; + if pushed then state.last_move_cache <- Some (game.Game.game_state, level) ; return_unit) else return_unit diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_player.mli b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_player.mli index 92592e7c7cc5..64cca0e7e56a 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_player.mli +++ b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_player.mli @@ -23,9 +23,6 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context - (** Worker module for a single refutation game player. The node's refutation coordinator will spawn a new refutation player for each refutation game. *) @@ -40,20 +37,20 @@ type worker = Worker.infinite Worker.queue Worker.t is passed, the worker will play the opening move for [conflict]. *) val init_and_play : Node_context.rw -> - self:public_key_hash -> - conflict:Sc_rollup.Refutation_storage.conflict -> - game:Sc_rollup.Game.t option -> + self:Signature.public_key_hash -> + conflict:Game.conflict -> + game:Game.t option -> level:int32 -> unit tzresult Lwt.t (** [play worker game ~level] makes the [worker] play the next move depending on the [game] state for their conflict. *) -val play : worker -> Sc_rollup.Game.t -> level:int32 -> unit Lwt.t +val play : worker -> Game.t -> level:int32 -> unit Lwt.t (** Shutdown a refutaiton game player. *) val shutdown : worker -> unit Lwt.t (** [current_games ()] lists the opponents' this node is playing refutation games against, alongside the worker that takes care of each game. *) -val current_games : unit -> (public_key_hash * worker) list +val current_games : unit -> (Signature.public_key_hash * worker) list -- GitLab From 5e44b427936a53ccaa4fdc4061b5c1578c79bb6a Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 29 Jun 2023 16:43:46 +0200 Subject: [PATCH 11/17] SCORU/Node/Nairobi: remove protocol deps from refutation coordinator and player --- .../refutation_coordinator.ml | 46 ++++---- .../lib_sc_rollup_node/refutation_game.ml | 100 ++++++++++-------- .../lib_sc_rollup_node/refutation_game.mli | 13 +-- .../refutation_game_event.ml | 27 ++--- .../lib_sc_rollup_node/refutation_player.ml | 25 ++--- .../lib_sc_rollup_node/refutation_player.mli | 13 +-- 6 files changed, 116 insertions(+), 108 deletions(-) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_coordinator.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_coordinator.ml index 627b7399a5e9..470bf57ca178 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_coordinator.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_coordinator.ml @@ -23,10 +23,7 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context open Refutation_coordinator_types -include Refutation_game module Player = Refutation_player module Pkh_map = Signature.Public_key_hash.Map module Pkh_table = Signature.Public_key_hash.Table @@ -37,27 +34,34 @@ type state = { pending_opponents : unit Pkh_table.t; } -let get_conflicts cctxt head_block address key = - Plugin.RPC.Sc_rollup.conflicts - cctxt - (cctxt#chain, head_block) - (Sc_rollup_proto_types.Address.of_octez address) - key +let get_conflicts cctxt head_block rollup staker = + let open Lwt_result_syntax in + let+ conflicts = + Plugin.RPC.Sc_rollup.conflicts + cctxt + (cctxt#chain, head_block) + (Sc_rollup_proto_types.Address.of_octez rollup) + staker + in + List.map Sc_rollup_proto_types.Game.conflict_to_octez conflicts -let get_ongoing_games cctxt head_block address key = - Plugin.RPC.Sc_rollup.ongoing_refutation_games - cctxt - (cctxt#chain, head_block) - (Sc_rollup_proto_types.Address.of_octez address) - key +let get_ongoing_games cctxt head_block rollup staker = + let open Lwt_result_syntax in + let+ games = + Plugin.RPC.Sc_rollup.ongoing_refutation_games + cctxt + (cctxt#chain, head_block) + (Sc_rollup_proto_types.Address.of_octez rollup) + staker + in + List.map + (fun (game, staker1, staker2) -> + (Sc_rollup_proto_types.Game.to_octez game, staker1, staker2)) + games let untracked_conflicts opponent_players conflicts = List.filter - (fun conflict -> - not - @@ Pkh_map.mem - conflict.Sc_rollup.Refutation_storage.other - opponent_players) + (fun conflict -> not @@ Pkh_map.mem conflict.Game.other opponent_players) conflicts (* Transform the list of ongoing games [(Game.t * pkh * pkh) list] @@ -107,7 +111,7 @@ let on_process Layer1.{hash; level} state = let* () = List.iter_ep (fun conflict -> - let other = conflict.Sc_rollup.Refutation_storage.other in + let other = conflict.Octez_smart_rollup.Game.other in Pkh_table.replace state.pending_opponents other () ; let game = Pkh_map.find_opt other ongoing_game_map in Player.init_and_play node_ctxt ~self ~conflict ~game ~level) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.ml index 5a6b60aaa7ed..e59d0f8a10a3 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.ml @@ -55,7 +55,7 @@ let node_role ~self Sc_rollup.Game.Index.{alice; bob} = type role = Our_turn of {opponent : public_key_hash} | Their_turn -let turn ~self game players = +let turn ~self (game : Octez_smart_rollup.Game.t) players = let Sc_rollup.Game.Index.{alice; bob} = players in match (node_role ~self players, game.turn) with | Alice, Alice -> Our_turn {opponent = bob} @@ -70,11 +70,7 @@ let inject_next_move node_ctxt source ~refutation ~opponent = let open Lwt_result_syntax in let refute_operation = L1_operation.Refute - { - rollup = node_ctxt.Node_context.rollup_address; - refutation = Sc_rollup_proto_types.Game.refutation_to_octez refutation; - opponent; - } + {rollup = node_ctxt.Node_context.rollup_address; refutation; opponent} in let* _hash = Injector.add_pending_operation ~source refute_operation in return_unit @@ -159,23 +155,24 @@ let metadata (node_ctxt : _ Node_context.t) = let origination_level = Raw_level.of_int32_exn node_ctxt.genesis_info.level in Sc_rollup.Metadata.{address; origination_level} -let generate_proof (node_ctxt : _ Node_context.t) game start_state = +let generate_proof (node_ctxt : _ Node_context.t) + (game : Octez_smart_rollup.Game.t) start_state = let open Lwt_result_syntax in let module PVM = (val Pvm.of_kind node_ctxt.kind) in - let snapshot = game.inbox_snapshot in + let snapshot = + Sc_rollup_proto_types.Inbox.history_proof_of_octez game.inbox_snapshot + in (* NOTE: [snapshot_level_int32] below refers to the level of the snapshotted inbox (from the skip list) which also matches [game.start_level - 1]. *) let snapshot_level_int32 = - Raw_level.to_int32 (Sc_rollup.Inbox.Skip_list.content snapshot).level + (Octez_smart_rollup.Inbox.Skip_list.content game.inbox_snapshot).level in let get_snapshot_head () = let+ hash = Node_context.hash_of_level node_ctxt snapshot_level_int32 in Layer1.{hash; level = snapshot_level_int32} in let* context = - let* start_hash = - Node_context.hash_of_level node_ctxt (Raw_level.to_int32 game.inbox_level) - in + let* start_hash = Node_context.hash_of_level node_ctxt game.inbox_level in let+ context = Node_context.checkout_context node_ctxt start_hash in Context.index context in @@ -295,10 +292,13 @@ let generate_proof (node_ctxt : _ Node_context.t) game start_state = trace (Sc_rollup_node_errors.Cannot_produce_proof { - inbox_level = Raw_level.to_int32 game.inbox_level; + inbox_level = game.inbox_level; start_tick = Sc_rollup.Tick.to_z start_tick; }) - @@ (Sc_rollup.Proof.produce ~metadata (module P) game.inbox_level + @@ (Sc_rollup.Proof.produce + ~metadata + (module P) + (Raw_level.of_int32_exn game.inbox_level) >|= Environment.wrap_tzresult) in let*? pvm_step = @@ -310,7 +310,7 @@ let generate_proof (node_ctxt : _ Node_context.t) game start_state = Sc_rollup.Proof.valid ~metadata snapshot - game.inbox_level + (Raw_level.of_int32_exn game.inbox_level) dal_slots_history dal_parameters ~dal_attestation_lag @@ -318,10 +318,14 @@ let generate_proof (node_ctxt : _ Node_context.t) game start_state = unserialized_proof >|= Environment.wrap_tzresult in - if Result.is_ok res then return proof else assert false + assert (Result.is_ok res) ; + let proof = + Data_encoding.Binary.to_string_exn Sc_rollup.Proof.encoding proof + in + return proof type pvm_intermediate_state = - | Hash of Sc_rollup.State_hash.t + | Hash of Octez_smart_rollup.State_hash.t | Evaluated of Fuel.Accounted.t Pvm_plugin_sig.eval_state let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok @@ -332,7 +336,7 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok node_ctxt ?start_state ~tick:(Sc_rollup.Tick.to_z tick) - last_level + (Raw_level.of_int32_exn last_level) in let state_hash_of_eval_state Pvm_plugin_sig.{state_hash; _} = Sc_rollup_proto_types.State_hash.of_octez state_hash @@ -341,10 +345,14 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok match ok with | Hash hash, tick -> (hash, tick, None) | Evaluated ({state_hash; _} as state), tick -> - (Sc_rollup_proto_types.State_hash.of_octez state_hash, tick, Some state) + (state_hash, tick, Some state) in let start_chunk = - Sc_rollup.Dissection_chunk.{state_hash = Some start_hash; tick = start_tick} + Sc_rollup.Dissection_chunk. + { + state_hash = Some (Sc_rollup_proto_types.State_hash.of_octez start_hash); + tick = Sc_rollup.Tick.of_z start_tick; + } in let our_state, our_tick = our_view in let our_state_hash = @@ -354,7 +362,8 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok our_state in let our_stop_chunk = - Sc_rollup.Dissection_chunk.{state_hash = our_state_hash; tick = our_tick} + Sc_rollup.Dissection_chunk. + {state_hash = our_state_hash; tick = Sc_rollup.Tick.of_z our_tick} in let module PVM = (val Pvm.of_kind node_ctxt.kind) in let* dissection = @@ -369,6 +378,9 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok ~our_stop_chunk ~default_number_of_sections in + let dissection = + List.map Sc_rollup_proto_types.Game.dissection_chunk_to_octez dissection + in let*! () = Refutation_game_event.computed_dissection ~opponent @@ -383,7 +395,8 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok performs a new dissection of the execution trace or provides a refutation proof to serve as the next move of the [game]. *) let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent - game dissection = + (game : Octez_smart_rollup.Game.t) + (dissection : Octez_smart_rollup.Game.dissection_chunk list) = let open Lwt_result_syntax in let rec traverse ok = function | [] -> @@ -394,8 +407,7 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent tzfail Sc_rollup_node_errors .Unreliable_tezos_node_returning_inconsistent_game - | Sc_rollup.Dissection_chunk.{state_hash = their_hash; tick} :: dissection - -> ( + | Octez_smart_rollup.Game.{state_hash = their_hash; tick} :: dissection -> ( let start_state = match ok with | Hash _, _ -> None @@ -405,8 +417,8 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent Interpreter.state_of_tick node_ctxt ?start_state - ~tick:(Sc_rollup.Tick.to_z tick) - game.inbox_level + ~tick + (Raw_level.of_int32_exn game.inbox_level) in match (their_hash, our) with | None, None -> @@ -415,15 +427,12 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent assert false | Some _, None | None, Some _ -> return (ok, (our, tick)) | Some their_hash, Some ({state_hash = our_hash; _} as our_state) -> - if - Sc_rollup.State_hash.equal - (Sc_rollup_proto_types.State_hash.of_octez our_hash) - their_hash - then traverse (Evaluated our_state, tick) dissection + if Octez_smart_rollup.State_hash.equal our_hash their_hash then + traverse (Evaluated our_state, tick) dissection else return (ok, (our, tick))) in match dissection with - | Sc_rollup.Dissection_chunk.{state_hash = Some hash; tick} :: dissection -> + | {state_hash = Some hash; tick} :: dissection -> let* ok, ko = traverse (Hash hash, tick) dissection in let* dissection = new_dissection @@ -436,7 +445,7 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent in let _, choice = ok in let _, ko_tick = ko in - let chosen_section_len = Sc_rollup.Tick.distance ko_tick choice in + let chosen_section_len = Z.abs (Z.sub choice ko_tick) in return (choice, chosen_section_len, dissection) | [] | {state_hash = None; _} :: _ -> (* @@ -447,14 +456,14 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent tzfail Sc_rollup_node_errors.Unreliable_tezos_node_returning_inconsistent_game -let next_move node_ctxt ~opponent game = +let next_move node_ctxt ~opponent (game : Octez_smart_rollup.Game.t) = let open Lwt_result_syntax in let final_move start_tick = let* start_state = Interpreter.state_of_tick node_ctxt - ~tick:(Sc_rollup.Tick.to_z start_tick) - game.inbox_level + ~tick:start_tick + (Raw_level.of_int32_exn game.inbox_level) in match start_state with | None -> @@ -464,7 +473,7 @@ let next_move node_ctxt ~opponent game = | Some {state = start_state; _} -> let* proof = generate_proof node_ctxt game start_state in let choice = start_tick in - return (Move {choice; step = Proof proof}) + return (Octez_smart_rollup.Game.Move {choice; step = Proof proof}) in match game.game_state with @@ -478,7 +487,9 @@ let next_move node_ctxt ~opponent game = dissection in if Z.(equal chosen_section_len one) then final_move choice - else return (Move {choice; step = Dissection dissection}) + else + return + (Octez_smart_rollup.Game.Move {choice; step = Dissection dissection}) | Final_move {agreed_start_chunk; refuted_stop_chunk = _} -> let choice = agreed_start_chunk.tick in final_move choice @@ -538,15 +549,18 @@ let play node_ctxt ~self game opponent = play_timeout node_ctxt self index | None -> return_unit) -let play_opening_move node_ctxt self conflict = +let play_opening_move node_ctxt self + (conflict : Octez_smart_rollup.Game.conflict) = let open Lwt_syntax in - let open Sc_rollup.Refutation_storage in let* () = Refutation_game_event.conflict_detected conflict in let player_commitment_hash = - Sc_rollup.Commitment.hash_uncarbonated conflict.our_commitment + Octez_smart_rollup.Commitment.hash conflict.our_commitment in let opponent_commitment_hash = - Sc_rollup.Commitment.hash_uncarbonated conflict.their_commitment + Octez_smart_rollup.Commitment.hash conflict.their_commitment + in + let refutation = + Octez_smart_rollup.Game.Start + {player_commitment_hash; opponent_commitment_hash} in - let refutation = Start {player_commitment_hash; opponent_commitment_hash} in inject_next_move node_ctxt self ~refutation ~opponent:conflict.other diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.mli index 3229857d1aa7..1f8668ebb042 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.mli @@ -23,24 +23,21 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context - (** This module implements the refutation game logic of the rollup node. *) (** [play_opening_move node_ctxt self conflict] injects the opening refutation game move for [conflict]. *) val play_opening_move : [< `Read | `Write > `Read] Node_context.t -> - public_key_hash -> - Sc_rollup.Refutation_storage.conflict -> + Signature.public_key_hash -> + Octez_smart_rollup.Game.conflict -> (unit, tztrace) result Lwt.t (** [play head_block node_ctxt ~self game opponent] injects the next move in the refutation [game] played by [self] and [opponent]. *) val play : Node_context.rw -> - self:public_key_hash -> - Sc_rollup.Game.t -> - public_key_hash -> + self:Signature.public_key_hash -> + Octez_smart_rollup.Game.t -> + Signature.public_key_hash -> (unit, tztrace) result Lwt.t diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game_event.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game_event.ml index b9231bfc5f90..70f35ed9369b 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game_event.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game_event.ml @@ -64,11 +64,11 @@ module Simple = struct at level {level} with staker {other} that hash issued commitment \ {their_commitment_hash} both based on {parent_commitment_hash}." ~level:Notice - ("our_commitment_hash", Sc_rollup.Commitment.Hash.encoding) - ("level", Raw_level.encoding) - ("other", Sc_rollup.Staker.encoding) - ("their_commitment_hash", Sc_rollup.Commitment.Hash.encoding) - ("parent_commitment_hash", Sc_rollup.Commitment.Hash.encoding) + ("our_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) + ("level", Data_encoding.int32) + ("other", Signature.Public_key_hash.encoding) + ("their_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) + ("parent_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) let potential_conflict_detected = declare_4 @@ -112,9 +112,10 @@ module Simple = struct {end_tick}: {dissection}." ~level:Debug ("opponent", Signature.Public_key_hash.encoding) - ("start_tick", Sc_rollup.Tick.encoding) - ("end_tick", Sc_rollup.Tick.encoding) - ("dissection", Data_encoding.list dissection_chunk_encoding) + ("start_tick", Data_encoding.z) + ("end_tick", Data_encoding.z) + ( "dissection", + Data_encoding.list Octez_smart_rollup.Game.dissection_chunk_encoding ) module Worker (ARG : sig val section : string list @@ -166,8 +167,8 @@ module Simple = struct ~level:Notice ("opponent", Signature.Public_key_hash.encoding) ~pp1:Signature.Public_key_hash.pp - ("commitment", Sc_rollup.Commitment.encoding) - ~pp2:Sc_rollup.Commitment.pp + ("commitment", Octez_smart_rollup.Commitment.encoding) + ~pp2:Octez_smart_rollup.Commitment.pp let stopped = declare_1 @@ -201,12 +202,12 @@ let timeout address = Simple.(emit timeout address) let invalid_move () = Simple.(emit invalid_move ()) -let conflict_detected (conflict : Sc_rollup.Refutation_storage.conflict) = +let conflict_detected (conflict : Octez_smart_rollup.Game.conflict) = let our_commitment_hash = - Sc_rollup.Commitment.hash_uncarbonated conflict.our_commitment + Octez_smart_rollup.Commitment.hash conflict.our_commitment in let their_commitment_hash = - Sc_rollup.Commitment.hash_uncarbonated conflict.their_commitment + Octez_smart_rollup.Commitment.hash conflict.their_commitment in let parent_commitment_hash = conflict.parent_commitment in let other = conflict.other in diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player.ml index 72901a452bf2..3d7c8d596905 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player.ml @@ -23,23 +23,22 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context open Refutation_player_types open Refutation_game module Types = struct type state = { node_ctxt : Node_context.rw; - self : public_key_hash; - opponent : public_key_hash; - mutable last_move_cache : (Sc_rollup.Game.game_state * int32) option; + self : Signature.public_key_hash; + opponent : Signature.public_key_hash; + mutable last_move_cache : + (Octez_smart_rollup.Game.game_state * int32) option; } type parameters = { node_ctxt : Node_context.rw; - self : public_key_hash; - conflict : Sc_rollup.Refutation_storage.conflict; + self : Signature.public_key_hash; + conflict : Octez_smart_rollup.Game.conflict; } end @@ -110,8 +109,8 @@ let init node_ctxt ~self ~conflict = let open Lwt_result_syntax in let*! () = Refutation_game_event.Player.started - conflict.Sc_rollup.Refutation_storage.other - conflict.Sc_rollup.Refutation_storage.our_commitment + conflict.Game.other + conflict.Game.our_commitment in let worker_promise, worker_waker = Lwt.task () in let* worker = @@ -140,10 +139,7 @@ let should_move ~level game last_move_cache = match last_move_cache with | None -> true | Some (last_move_game_state, last_move_level) -> - (not - (Sc_rollup.Game.game_state_equal - game.Sc_rollup.Game.game_state - last_move_game_state)) + (not (Game.game_state_equal game.Game.game_state last_move_game_state)) || Int32.( sub level last_move_level > of_int Configuration.refutation_player_buffer_levels) @@ -153,8 +149,7 @@ let play w game ~(level : int32) = let state = Worker.state w in if should_move ~level game state.last_move_cache then ( let* pushed = Worker.Queue.push_request w (Request.Play game) in - if pushed then - state.last_move_cache <- Some (game.Sc_rollup.Game.game_state, level) ; + if pushed then state.last_move_cache <- Some (game.Game.game_state, level) ; return_unit) else return_unit diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player.mli index 92592e7c7cc5..64cca0e7e56a 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player.mli @@ -23,9 +23,6 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context - (** Worker module for a single refutation game player. The node's refutation coordinator will spawn a new refutation player for each refutation game. *) @@ -40,20 +37,20 @@ type worker = Worker.infinite Worker.queue Worker.t is passed, the worker will play the opening move for [conflict]. *) val init_and_play : Node_context.rw -> - self:public_key_hash -> - conflict:Sc_rollup.Refutation_storage.conflict -> - game:Sc_rollup.Game.t option -> + self:Signature.public_key_hash -> + conflict:Game.conflict -> + game:Game.t option -> level:int32 -> unit tzresult Lwt.t (** [play worker game ~level] makes the [worker] play the next move depending on the [game] state for their conflict. *) -val play : worker -> Sc_rollup.Game.t -> level:int32 -> unit Lwt.t +val play : worker -> Game.t -> level:int32 -> unit Lwt.t (** Shutdown a refutaiton game player. *) val shutdown : worker -> unit Lwt.t (** [current_games ()] lists the opponents' this node is playing refutation games against, alongside the worker that takes care of each game. *) -val current_games : unit -> (public_key_hash * worker) list +val current_games : unit -> (Signature.public_key_hash * worker) list -- GitLab From 96540f109ce10bdee86c132a9b0c81abdbcfa0ff Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 29 Jun 2023 16:43:46 +0200 Subject: [PATCH 12/17] SCORU/Node/Mumbai: remove protocol deps from refutation coordinator and player --- .../refutation_coordinator.ml | 46 ++++---- .../lib_sc_rollup_node/refutation_game.ml | 100 ++++++++++-------- .../lib_sc_rollup_node/refutation_game.mli | 13 +-- .../refutation_game_event.ml | 27 ++--- .../lib_sc_rollup_node/refutation_player.ml | 33 +++--- .../lib_sc_rollup_node/refutation_player.mli | 13 +-- 6 files changed, 119 insertions(+), 113 deletions(-) diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_coordinator.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_coordinator.ml index 627b7399a5e9..470bf57ca178 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_coordinator.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_coordinator.ml @@ -23,10 +23,7 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context open Refutation_coordinator_types -include Refutation_game module Player = Refutation_player module Pkh_map = Signature.Public_key_hash.Map module Pkh_table = Signature.Public_key_hash.Table @@ -37,27 +34,34 @@ type state = { pending_opponents : unit Pkh_table.t; } -let get_conflicts cctxt head_block address key = - Plugin.RPC.Sc_rollup.conflicts - cctxt - (cctxt#chain, head_block) - (Sc_rollup_proto_types.Address.of_octez address) - key +let get_conflicts cctxt head_block rollup staker = + let open Lwt_result_syntax in + let+ conflicts = + Plugin.RPC.Sc_rollup.conflicts + cctxt + (cctxt#chain, head_block) + (Sc_rollup_proto_types.Address.of_octez rollup) + staker + in + List.map Sc_rollup_proto_types.Game.conflict_to_octez conflicts -let get_ongoing_games cctxt head_block address key = - Plugin.RPC.Sc_rollup.ongoing_refutation_games - cctxt - (cctxt#chain, head_block) - (Sc_rollup_proto_types.Address.of_octez address) - key +let get_ongoing_games cctxt head_block rollup staker = + let open Lwt_result_syntax in + let+ games = + Plugin.RPC.Sc_rollup.ongoing_refutation_games + cctxt + (cctxt#chain, head_block) + (Sc_rollup_proto_types.Address.of_octez rollup) + staker + in + List.map + (fun (game, staker1, staker2) -> + (Sc_rollup_proto_types.Game.to_octez game, staker1, staker2)) + games let untracked_conflicts opponent_players conflicts = List.filter - (fun conflict -> - not - @@ Pkh_map.mem - conflict.Sc_rollup.Refutation_storage.other - opponent_players) + (fun conflict -> not @@ Pkh_map.mem conflict.Game.other opponent_players) conflicts (* Transform the list of ongoing games [(Game.t * pkh * pkh) list] @@ -107,7 +111,7 @@ let on_process Layer1.{hash; level} state = let* () = List.iter_ep (fun conflict -> - let other = conflict.Sc_rollup.Refutation_storage.other in + let other = conflict.Octez_smart_rollup.Game.other in Pkh_table.replace state.pending_opponents other () ; let game = Pkh_map.find_opt other ongoing_game_map in Player.init_and_play node_ctxt ~self ~conflict ~game ~level) diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.ml index 38b0f8895d1c..7a1639c7ebd1 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.ml @@ -55,7 +55,7 @@ let node_role ~self Sc_rollup.Game.Index.{alice; bob} = type role = Our_turn of {opponent : public_key_hash} | Their_turn -let turn ~self game players = +let turn ~self (game : Octez_smart_rollup.Game.t) players = let Sc_rollup.Game.Index.{alice; bob} = players in match (node_role ~self players, game.turn) with | Alice, Alice -> Our_turn {opponent = bob} @@ -70,11 +70,7 @@ let inject_next_move node_ctxt source ~refutation ~opponent = let open Lwt_result_syntax in let refute_operation = L1_operation.Refute - { - rollup = node_ctxt.Node_context.rollup_address; - refutation = Sc_rollup_proto_types.Game.refutation_to_octez refutation; - opponent; - } + {rollup = node_ctxt.Node_context.rollup_address; refutation; opponent} in let* _hash = Injector.add_pending_operation ~source refute_operation in return_unit @@ -159,23 +155,24 @@ let metadata (node_ctxt : _ Node_context.t) = let origination_level = Raw_level.of_int32_exn node_ctxt.genesis_info.level in Sc_rollup.Metadata.{address; origination_level} -let generate_proof (node_ctxt : _ Node_context.t) game start_state = +let generate_proof (node_ctxt : _ Node_context.t) + (game : Octez_smart_rollup.Game.t) start_state = let open Lwt_result_syntax in let module PVM = (val Pvm.of_kind node_ctxt.kind) in - let snapshot = game.inbox_snapshot in + let snapshot = + Sc_rollup_proto_types.Inbox.history_proof_of_octez game.inbox_snapshot + in (* NOTE: [snapshot_level_int32] below refers to the level of the snapshotted inbox (from the skip list) which also matches [game.start_level - 1]. *) let snapshot_level_int32 = - Raw_level.to_int32 (Sc_rollup.Inbox.Skip_list.content snapshot).level + (Octez_smart_rollup.Inbox.Skip_list.content game.inbox_snapshot).level in let get_snapshot_head () = let+ hash = Node_context.hash_of_level node_ctxt snapshot_level_int32 in Layer1.{hash; level = snapshot_level_int32} in let* context = - let* start_hash = - Node_context.hash_of_level node_ctxt (Raw_level.to_int32 game.inbox_level) - in + let* start_hash = Node_context.hash_of_level node_ctxt game.inbox_level in let+ context = Node_context.checkout_context node_ctxt start_hash in Context.index context in @@ -294,10 +291,13 @@ let generate_proof (node_ctxt : _ Node_context.t) game start_state = trace (Sc_rollup_node_errors.Cannot_produce_proof { - inbox_level = Raw_level.to_int32 game.inbox_level; + inbox_level = game.inbox_level; start_tick = Sc_rollup.Tick.to_z start_tick; }) - @@ (Sc_rollup.Proof.produce ~metadata (module P) game.inbox_level + @@ (Sc_rollup.Proof.produce + ~metadata + (module P) + (Raw_level.of_int32_exn game.inbox_level) >|= Environment.wrap_tzresult) in let*? pvm_step = @@ -309,7 +309,7 @@ let generate_proof (node_ctxt : _ Node_context.t) game start_state = Sc_rollup.Proof.valid ~metadata snapshot - game.inbox_level + (Raw_level.of_int32_exn game.inbox_level) dal_slots_history dal_parameters ~dal_attestation_lag @@ -317,10 +317,14 @@ let generate_proof (node_ctxt : _ Node_context.t) game start_state = unserialized_proof >|= Environment.wrap_tzresult in - if Result.is_ok res then return proof else assert false + assert (Result.is_ok res) ; + let proof = + Data_encoding.Binary.to_string_exn Sc_rollup.Proof.encoding proof + in + return proof type pvm_intermediate_state = - | Hash of Sc_rollup.State_hash.t + | Hash of Octez_smart_rollup.State_hash.t | Evaluated of Fuel.Accounted.t Pvm_plugin_sig.eval_state let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok @@ -331,7 +335,7 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok node_ctxt ?start_state ~tick:(Sc_rollup.Tick.to_z tick) - last_level + (Raw_level.of_int32_exn last_level) in let state_hash_of_eval_state Pvm_plugin_sig.{state_hash; _} = Sc_rollup_proto_types.State_hash.of_octez state_hash @@ -340,10 +344,14 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok match ok with | Hash hash, tick -> (hash, tick, None) | Evaluated ({state_hash; _} as state), tick -> - (Sc_rollup_proto_types.State_hash.of_octez state_hash, tick, Some state) + (state_hash, tick, Some state) in let start_chunk = - Sc_rollup.Dissection_chunk.{state_hash = Some start_hash; tick = start_tick} + Sc_rollup.Dissection_chunk. + { + state_hash = Some (Sc_rollup_proto_types.State_hash.of_octez start_hash); + tick = Sc_rollup.Tick.of_z start_tick; + } in let our_state, our_tick = our_view in let our_state_hash = @@ -353,7 +361,8 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok our_state in let our_stop_chunk = - Sc_rollup.Dissection_chunk.{state_hash = our_state_hash; tick = our_tick} + Sc_rollup.Dissection_chunk. + {state_hash = our_state_hash; tick = Sc_rollup.Tick.of_z our_tick} in let module PVM = (val Pvm.of_kind node_ctxt.kind) in let* dissection = @@ -368,6 +377,9 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok ~our_stop_chunk ~default_number_of_sections in + let dissection = + List.map Sc_rollup_proto_types.Game.dissection_chunk_to_octez dissection + in let*! () = Refutation_game_event.computed_dissection ~opponent @@ -382,7 +394,8 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok performs a new dissection of the execution trace or provides a refutation proof to serve as the next move of the [game]. *) let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent - game dissection = + (game : Octez_smart_rollup.Game.t) + (dissection : Octez_smart_rollup.Game.dissection_chunk list) = let open Lwt_result_syntax in let rec traverse ok = function | [] -> @@ -393,8 +406,7 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent tzfail Sc_rollup_node_errors .Unreliable_tezos_node_returning_inconsistent_game - | Sc_rollup.Dissection_chunk.{state_hash = their_hash; tick} :: dissection - -> ( + | Octez_smart_rollup.Game.{state_hash = their_hash; tick} :: dissection -> ( let start_state = match ok with | Hash _, _ -> None @@ -404,8 +416,8 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent Interpreter.state_of_tick node_ctxt ?start_state - ~tick:(Sc_rollup.Tick.to_z tick) - game.inbox_level + ~tick + (Raw_level.of_int32_exn game.inbox_level) in match (their_hash, our) with | None, None -> @@ -414,15 +426,12 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent assert false | Some _, None | None, Some _ -> return (ok, (our, tick)) | Some their_hash, Some ({state_hash = our_hash; _} as our_state) -> - if - Sc_rollup.State_hash.equal - (Sc_rollup_proto_types.State_hash.of_octez our_hash) - their_hash - then traverse (Evaluated our_state, tick) dissection + if Octez_smart_rollup.State_hash.equal our_hash their_hash then + traverse (Evaluated our_state, tick) dissection else return (ok, (our, tick))) in match dissection with - | Sc_rollup.Dissection_chunk.{state_hash = Some hash; tick} :: dissection -> + | {state_hash = Some hash; tick} :: dissection -> let* ok, ko = traverse (Hash hash, tick) dissection in let* dissection = new_dissection @@ -435,7 +444,7 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent in let _, choice = ok in let _, ko_tick = ko in - let chosen_section_len = Sc_rollup.Tick.distance ko_tick choice in + let chosen_section_len = Z.abs (Z.sub choice ko_tick) in return (choice, chosen_section_len, dissection) | [] | {state_hash = None; _} :: _ -> (* @@ -446,14 +455,14 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent tzfail Sc_rollup_node_errors.Unreliable_tezos_node_returning_inconsistent_game -let next_move node_ctxt ~opponent game = +let next_move node_ctxt ~opponent (game : Octez_smart_rollup.Game.t) = let open Lwt_result_syntax in let final_move start_tick = let* start_state = Interpreter.state_of_tick node_ctxt - ~tick:(Sc_rollup.Tick.to_z start_tick) - game.inbox_level + ~tick:start_tick + (Raw_level.of_int32_exn game.inbox_level) in match start_state with | None -> @@ -463,7 +472,7 @@ let next_move node_ctxt ~opponent game = | Some {state = start_state; _} -> let* proof = generate_proof node_ctxt game start_state in let choice = start_tick in - return (Move {choice; step = Proof proof}) + return (Octez_smart_rollup.Game.Move {choice; step = Proof proof}) in match game.game_state with @@ -477,7 +486,9 @@ let next_move node_ctxt ~opponent game = dissection in if Z.(equal chosen_section_len one) then final_move choice - else return (Move {choice; step = Dissection dissection}) + else + return + (Octez_smart_rollup.Game.Move {choice; step = Dissection dissection}) | Final_move {agreed_start_chunk; refuted_stop_chunk = _} -> let choice = agreed_start_chunk.tick in final_move choice @@ -537,15 +548,18 @@ let play node_ctxt ~self game opponent = play_timeout node_ctxt self index | None -> return_unit) -let play_opening_move node_ctxt self conflict = +let play_opening_move node_ctxt self + (conflict : Octez_smart_rollup.Game.conflict) = let open Lwt_syntax in - let open Sc_rollup.Refutation_storage in let* () = Refutation_game_event.conflict_detected conflict in let player_commitment_hash = - Sc_rollup.Commitment.hash_uncarbonated conflict.our_commitment + Octez_smart_rollup.Commitment.hash conflict.our_commitment in let opponent_commitment_hash = - Sc_rollup.Commitment.hash_uncarbonated conflict.their_commitment + Octez_smart_rollup.Commitment.hash conflict.their_commitment + in + let refutation = + Octez_smart_rollup.Game.Start + {player_commitment_hash; opponent_commitment_hash} in - let refutation = Start {player_commitment_hash; opponent_commitment_hash} in inject_next_move node_ctxt self ~refutation ~opponent:conflict.other diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.mli index 3229857d1aa7..1f8668ebb042 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.mli @@ -23,24 +23,21 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context - (** This module implements the refutation game logic of the rollup node. *) (** [play_opening_move node_ctxt self conflict] injects the opening refutation game move for [conflict]. *) val play_opening_move : [< `Read | `Write > `Read] Node_context.t -> - public_key_hash -> - Sc_rollup.Refutation_storage.conflict -> + Signature.public_key_hash -> + Octez_smart_rollup.Game.conflict -> (unit, tztrace) result Lwt.t (** [play head_block node_ctxt ~self game opponent] injects the next move in the refutation [game] played by [self] and [opponent]. *) val play : Node_context.rw -> - self:public_key_hash -> - Sc_rollup.Game.t -> - public_key_hash -> + self:Signature.public_key_hash -> + Octez_smart_rollup.Game.t -> + Signature.public_key_hash -> (unit, tztrace) result Lwt.t diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game_event.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game_event.ml index e12ea5dbc4c3..62d74b7e753b 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game_event.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game_event.ml @@ -64,11 +64,11 @@ module Simple = struct at level {level} with staker {other} that hash issued commitment \ {their_commitment_hash} both based on {parent_commitment_hash}." ~level:Notice - ("our_commitment_hash", Sc_rollup.Commitment.Hash.encoding) - ("level", Raw_level.encoding) - ("other", Sc_rollup.Staker.encoding) - ("their_commitment_hash", Sc_rollup.Commitment.Hash.encoding) - ("parent_commitment_hash", Sc_rollup.Commitment.Hash.encoding) + ("our_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) + ("level", Data_encoding.int32) + ("other", Signature.Public_key_hash.encoding) + ("their_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) + ("parent_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) let potential_conflict_detected = declare_4 @@ -112,9 +112,10 @@ module Simple = struct {end_tick}: {dissection}." ~level:Debug ("opponent", Signature.Public_key_hash.encoding) - ("start_tick", Sc_rollup.Tick.encoding) - ("end_tick", Sc_rollup.Tick.encoding) - ("dissection", Data_encoding.list dissection_chunk_encoding) + ("start_tick", Data_encoding.z) + ("end_tick", Data_encoding.z) + ( "dissection", + Data_encoding.list Octez_smart_rollup.Game.dissection_chunk_encoding ) module Worker (ARG : sig val section : string list @@ -166,8 +167,8 @@ module Simple = struct ~level:Notice ("opponent", Signature.Public_key_hash.encoding) ~pp1:Signature.Public_key_hash.pp - ("commitment", Sc_rollup.Commitment.encoding) - ~pp2:Sc_rollup.Commitment.pp + ("commitment", Octez_smart_rollup.Commitment.encoding) + ~pp2:Octez_smart_rollup.Commitment.pp let stopped = declare_1 @@ -201,12 +202,12 @@ let timeout address = Simple.(emit timeout address) let invalid_move () = Simple.(emit invalid_move ()) -let conflict_detected (conflict : Sc_rollup.Refutation_storage.conflict) = +let conflict_detected (conflict : Octez_smart_rollup.Game.conflict) = let our_commitment_hash = - Sc_rollup.Commitment.hash_uncarbonated conflict.our_commitment + Octez_smart_rollup.Commitment.hash conflict.our_commitment in let their_commitment_hash = - Sc_rollup.Commitment.hash_uncarbonated conflict.their_commitment + Octez_smart_rollup.Commitment.hash conflict.their_commitment in let parent_commitment_hash = conflict.parent_commitment in let other = conflict.other in diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player.ml index 1258a6fa25d6..3d7c8d596905 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player.ml @@ -23,23 +23,22 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context open Refutation_player_types open Refutation_game module Types = struct type state = { node_ctxt : Node_context.rw; - self : public_key_hash; - opponent : public_key_hash; - mutable last_move_cache : (Sc_rollup.Game.game_state * int32) option; + self : Signature.public_key_hash; + opponent : Signature.public_key_hash; + mutable last_move_cache : + (Octez_smart_rollup.Game.game_state * int32) option; } type parameters = { node_ctxt : Node_context.rw; - self : public_key_hash; - conflict : Sc_rollup.Refutation_storage.conflict; + self : Signature.public_key_hash; + conflict : Octez_smart_rollup.Game.conflict; } end @@ -110,8 +109,8 @@ let init node_ctxt ~self ~conflict = let open Lwt_result_syntax in let*! () = Refutation_game_event.Player.started - conflict.Sc_rollup.Refutation_storage.other - conflict.Sc_rollup.Refutation_storage.our_commitment + conflict.Game.other + conflict.Game.our_commitment in let worker_promise, worker_waker = Lwt.task () in let* worker = @@ -131,10 +130,6 @@ let init node_ctxt ~self ~conflict = in Lwt.return worker -(* Number of levels the player waits until trying to play - for a game state it already played for. *) -let buffer_levels = 5l - (* Play if: - There's a new game state to play against or - The current level is past the buffer for re-playing in the @@ -144,19 +139,17 @@ let should_move ~level game last_move_cache = match last_move_cache with | None -> true | Some (last_move_game_state, last_move_level) -> - (not - (Sc_rollup.Game.game_state_equal - game.Sc_rollup.Game.game_state - last_move_game_state)) - || Int32.(sub level last_move_level > buffer_levels) + (not (Game.game_state_equal game.Game.game_state last_move_game_state)) + || Int32.( + sub level last_move_level + > of_int Configuration.refutation_player_buffer_levels) let play w game ~(level : int32) = let open Lwt_syntax in let state = Worker.state w in if should_move ~level game state.last_move_cache then ( let* pushed = Worker.Queue.push_request w (Request.Play game) in - if pushed then - state.last_move_cache <- Some (game.Sc_rollup.Game.game_state, level) ; + if pushed then state.last_move_cache <- Some (game.Game.game_state, level) ; return_unit) else return_unit diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player.mli index 92592e7c7cc5..64cca0e7e56a 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player.mli @@ -23,9 +23,6 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context - (** Worker module for a single refutation game player. The node's refutation coordinator will spawn a new refutation player for each refutation game. *) @@ -40,20 +37,20 @@ type worker = Worker.infinite Worker.queue Worker.t is passed, the worker will play the opening move for [conflict]. *) val init_and_play : Node_context.rw -> - self:public_key_hash -> - conflict:Sc_rollup.Refutation_storage.conflict -> - game:Sc_rollup.Game.t option -> + self:Signature.public_key_hash -> + conflict:Game.conflict -> + game:Game.t option -> level:int32 -> unit tzresult Lwt.t (** [play worker game ~level] makes the [worker] play the next move depending on the [game] state for their conflict. *) -val play : worker -> Sc_rollup.Game.t -> level:int32 -> unit Lwt.t +val play : worker -> Game.t -> level:int32 -> unit Lwt.t (** Shutdown a refutaiton game player. *) val shutdown : worker -> unit Lwt.t (** [current_games ()] lists the opponents' this node is playing refutation games against, alongside the worker that takes care of each game. *) -val current_games : unit -> (public_key_hash * worker) list +val current_games : unit -> (Signature.public_key_hash * worker) list -- GitLab From 447a19b7143cc3db25afe75e56eab77114c52596 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 29 Jun 2023 21:57:54 +0200 Subject: [PATCH 13/17] SCORU/Node/Alpha: extract refutation game helpers Remove protocol dependency from Refutation_game module. --- .../lib_sc_rollup_node/refutation_game.ml | 362 ++--------------- .../refutation_game_helpers.ml | 364 ++++++++++++++++++ .../refutation_game_helpers.mli | 81 ++++ 3 files changed, 469 insertions(+), 338 deletions(-) create mode 100644 src/proto_alpha/lib_sc_rollup_node/refutation_game_helpers.ml create mode 100644 src/proto_alpha/lib_sc_rollup_node/refutation_game_helpers.mli diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_game.ml b/src/proto_alpha/lib_sc_rollup_node/refutation_game.ml index 046d067eb0b9..1253dc7ef02d 100644 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_game.ml +++ b/src/proto_alpha/lib_sc_rollup_node/refutation_game.ml @@ -42,21 +42,19 @@ starts a game to refute C' by starting a game with one of its staker. *) -open Protocol -open Alpha_context -open Sc_rollup.Game +open Game +open Refutation_game_helpers -let node_role ~self Sc_rollup.Game.Index.{alice; bob} = - if Sc_rollup.Staker.equal alice self then Alice - else if Sc_rollup.Staker.equal bob self then Bob +let node_role ~self {alice; bob} = + if Signature.Public_key_hash.equal alice self then Alice + else if Signature.Public_key_hash.equal bob self then Bob else (* By validity of [ongoing_game] RPC. *) assert false -type role = Our_turn of {opponent : public_key_hash} | Their_turn +type role = Our_turn of {opponent : Signature.public_key_hash} | Their_turn -let turn ~self (game : Octez_smart_rollup.Game.t) players = - let Sc_rollup.Game.Index.{alice; bob} = players in +let turn ~self game ({alice; bob} as players) = match (node_role ~self players, game.turn) with | Alice, Alice -> Our_turn {opponent = bob} | Bob, Bob -> Our_turn {opponent = alice} @@ -75,311 +73,33 @@ let inject_next_move node_ctxt source ~refutation ~opponent = let* _hash = Injector.add_pending_operation ~source refute_operation in return_unit -(** This function computes the inclusion/membership proof of the page - identified by [page_id] in the slot whose data are provided in - [slot_data]. *) -let page_membership_proof params page_index slot_data = - (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/4048 - Rely on DAL node to compute page membership proof and drop - the dal-crypto dependency from the rollup node. *) - let proof = - let open Result_syntax in - (* The computation of the page's proof below can be a bit costly. In fact, - it involves initialising a cryptobox environment and some non-trivial - crypto processing. *) - let* dal = Cryptobox.make params in - let* polynomial = Cryptobox.polynomial_from_slot dal slot_data in - Cryptobox.prove_page dal polynomial page_index - in - let open Lwt_result_syntax in - match proof with - | Ok proof -> return proof - | Error e -> - failwith - "%s" - (match e with - | `Fail s -> "Fail " ^ s - | `Page_index_out_of_range -> "Page_index_out_of_range" - | `Slot_wrong_size s -> "Slot_wrong_size: " ^ s - | `Invalid_degree_strictly_less_than_expected _ as commit_error -> - Cryptobox.string_of_commit_error commit_error) - -(** When the PVM is waiting for a Dal page input, this function attempts to - retrieve the page's content from the store, the data of its slot. Then it - computes the proof that the page is part of the slot and returns the - content along with the proof. - - If the PVM is not waiting for a Dal page input, or if the slot is known to - be unconfirmed on L1, this function returns [None]. If the data of the - slot are not saved to the store, the function returns a failure - in the error monad. *) -let page_info_from_pvm_state (node_ctxt : _ Node_context.t) ~dal_attestation_lag - (dal_params : Dal.parameters) start_state = - let open Lwt_result_syntax in - let module PVM = (val Pvm.of_kind node_ctxt.kind) in - (* TODO: https://gitlab.com/tezos/tezos/-/issues/5871 - Use constants for correct protocol. *) - let is_reveal_enabled = - node_ctxt.current_protocol.constants.sc_rollup.reveal_activation_level - |> WithExceptions.Option.get ~loc:__LOC__ - |> Sc_rollup_proto_types.Constants.reveal_activation_level_of_octez - |> Sc_rollup.is_reveal_enabled_predicate - in - let*! input_request = PVM.is_input_state ~is_reveal_enabled start_state in - match input_request with - | Sc_rollup.(Needs_reveal (Request_dal_page page_id)) -> ( - let Dal.Page.{slot_id; page_index} = page_id in - let* pages = - Dal_pages_request.slot_pages ~dal_attestation_lag node_ctxt slot_id - in - match pages with - | None -> return_none (* The slot is not confirmed. *) - | Some pages -> ( - let pages_per_slot = dal_params.slot_size / dal_params.page_size in - (* check invariant that pages' length is correct. *) - (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/4031 - It's better to do the check when the slots are saved into disk. *) - (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/3997 - This check is not resilient to dal parameters change. *) - match List.nth_opt pages page_index with - | Some content -> - let* page_proof = - page_membership_proof dal_params page_index - @@ Bytes.concat Bytes.empty pages - in - return_some (content, page_proof) - | None -> - failwith - "Page index %d too big or negative.\n\ - Number of pages in a slot is %d." - page_index - pages_per_slot)) - | _ -> return_none - -let metadata (node_ctxt : _ Node_context.t) = - let address = - Sc_rollup_proto_types.Address.of_octez node_ctxt.rollup_address - in - let origination_level = Raw_level.of_int32_exn node_ctxt.genesis_info.level in - Sc_rollup.Metadata.{address; origination_level} - -let generate_proof (node_ctxt : _ Node_context.t) - (game : Octez_smart_rollup.Game.t) start_state = - let open Lwt_result_syntax in - let module PVM = (val Pvm.of_kind node_ctxt.kind) in - let snapshot = - Sc_rollup_proto_types.Inbox.history_proof_of_octez game.inbox_snapshot - in - (* NOTE: [snapshot_level_int32] below refers to the level of the snapshotted - inbox (from the skip list) which also matches [game.start_level - 1]. *) - let snapshot_level_int32 = - (Octez_smart_rollup.Inbox.Skip_list.content game.inbox_snapshot).level - in - let get_snapshot_head () = - let+ hash = Node_context.hash_of_level node_ctxt snapshot_level_int32 in - Layer1.{hash; level = snapshot_level_int32} - in - let* context = - let* start_hash = Node_context.hash_of_level node_ctxt game.inbox_level in - let+ context = Node_context.checkout_context node_ctxt start_hash in - Context.index context - in - let* dal_slots_history = - if Node_context.dal_supported node_ctxt then - let* snapshot_head = get_snapshot_head () in - Dal_slots_tracker.slots_history_of_hash node_ctxt snapshot_head - else return Dal.Slots_history.genesis - in - let* dal_slots_history_cache = - if Node_context.dal_supported node_ctxt then - let* snapshot_head = get_snapshot_head () in - Dal_slots_tracker.slots_history_cache_of_hash node_ctxt snapshot_head - else return (Dal.Slots_history.History_cache.empty ~capacity:0L) - in - (* We fetch the value of protocol constants at block snapshot level - where the game started. *) - let* parametric_constants = - let cctxt = node_ctxt.cctxt in - Protocol.Constants_services.parametric - (new Protocol_client_context.wrap_full cctxt) - (cctxt#chain, `Level snapshot_level_int32) - in - let dal_l1_parameters = parametric_constants.dal in - let dal_parameters = dal_l1_parameters.cryptobox_parameters in - let dal_attestation_lag = dal_l1_parameters.attestation_lag in - - let* page_info = - page_info_from_pvm_state - ~dal_attestation_lag - node_ctxt - dal_parameters - start_state - in - let module P = struct - include PVM - - let context = context - - let state = start_state - - let reveal hash = - let open Lwt_syntax in - let* res = - Reveals.get - ~dac_client:node_ctxt.dac_client - ~data_dir:node_ctxt.data_dir - ~pvm_kind:(Sc_rollup_proto_types.Kind.to_octez PVM.kind) - hash - in - match res with Ok data -> return @@ Some data | Error _ -> return None - - module Inbox_with_history = struct - let inbox = snapshot - - let get_history inbox_hash = - let open Lwt_syntax in - let+ inbox = Node_context.find_inbox node_ctxt inbox_hash in - match inbox with - | Error err -> - Format.kasprintf - Stdlib.failwith - "Refutation game: Cannot get inbox history for %a, %a" - Sc_rollup.Inbox.Hash.pp - inbox_hash - pp_print_trace - err - | Ok inbox -> - Option.map - (fun i -> - Sc_rollup.Inbox.take_snapshot - (Sc_rollup_proto_types.Inbox.of_octez i)) - inbox - - let get_payloads_history witness = - Lwt.map - (WithExceptions.Result.to_exn_f - ~error:(Format.kasprintf Stdlib.failwith "%a" pp_print_trace)) - @@ - let open Lwt_result_syntax in - let* {is_first_block; predecessor; predecessor_timestamp; messages} = - Node_context.get_messages node_ctxt witness - in - let*? hist = - Inbox.payloads_history_of_messages - ~is_first_block - ~predecessor - ~predecessor_timestamp - messages - in - return hist - end - - module Dal_with_history = struct - let confirmed_slots_history = dal_slots_history - - let get_history ptr = - Dal.Slots_history.History_cache.find ptr dal_slots_history_cache - |> Lwt.return - - let dal_attestation_lag = dal_attestation_lag - - let dal_parameters = dal_parameters - - let page_info = page_info - end - end in - let metadata = metadata node_ctxt in - let*! start_tick = PVM.get_tick start_state in - let is_reveal_enabled = - Sc_rollup.is_reveal_enabled_predicate - parametric_constants.sc_rollup.reveal_activation_level - in - let* proof = - trace - (Sc_rollup_node_errors.Cannot_produce_proof - { - inbox_level = game.inbox_level; - start_tick = Sc_rollup.Tick.to_z start_tick; - }) - @@ (Sc_rollup.Proof.produce - ~metadata - (module P) - (Raw_level.of_int32_exn game.inbox_level) - ~is_reveal_enabled - >|= Environment.wrap_tzresult) - in - let*? pvm_step = - Sc_rollup.Proof.unserialize_pvm_step ~pvm:(module PVM) proof.pvm_step - |> Environment.wrap_tzresult - in - let unserialized_proof = {proof with pvm_step} in - let*! res = - Sc_rollup.Proof.valid - ~metadata - snapshot - (Raw_level.of_int32_exn game.inbox_level) - dal_slots_history - dal_parameters - ~dal_attestation_lag - ~pvm:(module PVM) - unserialized_proof - ~is_reveal_enabled - >|= Environment.wrap_tzresult - in - assert (Result.is_ok res) ; - let proof = - Data_encoding.Binary.to_string_exn Sc_rollup.Proof.encoding proof - in - return proof - type pvm_intermediate_state = - | Hash of Sc_rollup.State_hash.t + | Hash of State_hash.t | Evaluated of Fuel.Accounted.t Pvm_plugin_sig.eval_state let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok our_view = let open Lwt_result_syntax in - let state_of_tick ?start_state tick = - Interpreter.state_of_tick - node_ctxt - ?start_state - ~tick:(Sc_rollup.Tick.to_z tick) - (Raw_level.of_int32_exn last_level) - in - let state_hash_of_eval_state Pvm_plugin_sig.{state_hash; _} = state_hash in let start_hash, start_tick, start_state = match ok with | Hash hash, tick -> (hash, tick, None) | Evaluated ({state_hash; _} as state), tick -> (state_hash, tick, Some state) in - let start_chunk = - Sc_rollup.Dissection_chunk. - {state_hash = Some start_hash; tick = Sc_rollup.Tick.of_z start_tick} - in + let start_chunk = Game.{state_hash = Some start_hash; tick = start_tick} in let our_state, our_tick = our_view in let our_state_hash = Option.map (fun Pvm_plugin_sig.{state_hash; _} -> state_hash) our_state in - let our_stop_chunk = - Sc_rollup.Dissection_chunk. - {state_hash = our_state_hash; tick = Sc_rollup.Tick.of_z our_tick} - in - let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let our_stop_chunk = Game.{state_hash = our_state_hash; tick = our_tick} in let* dissection = - Game_helpers.make_dissection - ~state_of_tick - ~state_hash_of_eval_state - ?start_state + make_dissection + node_ctxt + ~start_state ~start_chunk ~our_stop_chunk - @@ PVM.new_dissection - ~start_chunk - ~our_stop_chunk - ~default_number_of_sections - in - let dissection = - List.map Sc_rollup_proto_types.Game.dissection_chunk_to_octez dissection + ~default_number_of_sections + ~last_level in let*! () = Refutation_game_event.computed_dissection @@ -414,11 +134,7 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent | Evaluated ok_state, _ -> Some ok_state in let* our = - Interpreter.state_of_tick - node_ctxt - ?start_state - ~tick - (Raw_level.of_int32_exn game.inbox_level) + state_of_tick node_ctxt ?start_state ~tick game.inbox_level in match (their_hash, our) with | None, None -> @@ -460,10 +176,7 @@ let next_move node_ctxt ~opponent (game : Octez_smart_rollup.Game.t) = let open Lwt_result_syntax in let final_move start_tick = let* start_state = - Interpreter.state_of_tick - node_ctxt - ~tick:start_tick - (Raw_level.of_int32_exn game.inbox_level) + state_of_tick node_ctxt ~tick:start_tick game.inbox_level in match start_state with | None -> @@ -502,11 +215,7 @@ let play_next_move node_ctxt game self opponent = let play_timeout (node_ctxt : _ Node_context.t) self stakers = let open Lwt_result_syntax in let timeout_operation = - L1_operation.Timeout - { - rollup = node_ctxt.rollup_address; - stakers = Sc_rollup_proto_types.Game.index_to_octez stakers; - } + L1_operation.Timeout {rollup = node_ctxt.rollup_address; stakers} in let source = Node_context.get_operator node_ctxt Timeout |> Option.value ~default:self @@ -515,39 +224,16 @@ let play_timeout (node_ctxt : _ Node_context.t) self stakers = let* _hash = Injector.add_pending_operation ~source timeout_operation in return_unit -let timeout_reached ~self head_block node_ctxt staker1 staker2 = - let open Lwt_result_syntax in - let Node_context.{rollup_address; cctxt; _} = node_ctxt in - let* game_result = - Plugin.RPC.Sc_rollup.timeout_reached - (new Protocol_client_context.wrap_full cctxt) - (cctxt#chain, head_block) - rollup_address - staker1 - staker2 - in - let open Sc_rollup.Game in - match game_result with - | Some (Loser {loser; _}) -> - let is_it_me = Signature.Public_key_hash.(self = loser) in - if is_it_me then return_none else return (Some loser) - | _ -> return_none - let play node_ctxt ~self game opponent = let open Lwt_result_syntax in - let index = Sc_rollup.Game.Index.make self opponent in - let head_block = `Head 0 in + let index = make_index self opponent in match turn ~self game index with | Our_turn {opponent} -> play_next_move node_ctxt game self opponent - | Their_turn -> ( - let* timeout_reached = - timeout_reached ~self head_block node_ctxt self opponent - in - match timeout_reached with - | Some opponent -> - let*! () = Refutation_game_event.timeout_detected opponent in - play_timeout node_ctxt self index - | None -> return_unit) + | Their_turn -> + let* timeout_reached = timeout_reached node_ctxt ~self ~opponent in + when_ timeout_reached @@ fun () -> + let*! () = Refutation_game_event.timeout_detected opponent in + play_timeout node_ctxt self index let play_opening_move node_ctxt self (conflict : Octez_smart_rollup.Game.conflict) = diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_game_helpers.ml b/src/proto_alpha/lib_sc_rollup_node/refutation_game_helpers.ml new file mode 100644 index 000000000000..850e54227fb8 --- /dev/null +++ b/src/proto_alpha/lib_sc_rollup_node/refutation_game_helpers.ml @@ -0,0 +1,364 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** This function computes the inclusion/membership proof of the page + identified by [page_id] in the slot whose data are provided in + [slot_data]. *) +let page_membership_proof params page_index slot_data = + (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/4048 + Rely on DAL node to compute page membership proof and drop + the dal-crypto dependency from the rollup node. *) + let proof = + let open Result_syntax in + (* The computation of the page's proof below can be a bit costly. In fact, + it involves initialising a cryptobox environment and some non-trivial + crypto processing. *) + let* dal = Cryptobox.make params in + let* polynomial = Cryptobox.polynomial_from_slot dal slot_data in + Cryptobox.prove_page dal polynomial page_index + in + let open Lwt_result_syntax in + match proof with + | Ok proof -> return proof + | Error e -> + failwith + "%s" + (match e with + | `Fail s -> "Fail " ^ s + | `Page_index_out_of_range -> "Page_index_out_of_range" + | `Slot_wrong_size s -> "Slot_wrong_size: " ^ s + | `Invalid_degree_strictly_less_than_expected _ as commit_error -> + Cryptobox.string_of_commit_error commit_error) + +(** When the PVM is waiting for a Dal page input, this function attempts to + retrieve the page's content from the store, the data of its slot. Then it + computes the proof that the page is part of the slot and returns the + content along with the proof. + + If the PVM is not waiting for a Dal page input, or if the slot is known to + be unconfirmed on L1, this function returns [None]. If the data of the + slot are not saved to the store, the function returns a failure + in the error monad. *) +let page_info_from_pvm_state (node_ctxt : _ Node_context.t) ~dal_attestation_lag + (dal_params : Dal.parameters) start_state = + let open Lwt_result_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + (* TODO: https://gitlab.com/tezos/tezos/-/issues/5871 + Use constants for correct protocol. *) + let is_reveal_enabled = + node_ctxt.current_protocol.constants.sc_rollup.reveal_activation_level + |> WithExceptions.Option.get ~loc:__LOC__ + |> Sc_rollup_proto_types.Constants.reveal_activation_level_of_octez + |> Sc_rollup.is_reveal_enabled_predicate + in + let*! input_request = PVM.is_input_state ~is_reveal_enabled start_state in + match input_request with + | Sc_rollup.(Needs_reveal (Request_dal_page page_id)) -> ( + let Dal.Page.{slot_id; page_index} = page_id in + let* pages = + Dal_pages_request.slot_pages ~dal_attestation_lag node_ctxt slot_id + in + match pages with + | None -> return_none (* The slot is not confirmed. *) + | Some pages -> ( + let pages_per_slot = dal_params.slot_size / dal_params.page_size in + (* check invariant that pages' length is correct. *) + (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/4031 + It's better to do the check when the slots are saved into disk. *) + (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/3997 + This check is not resilient to dal parameters change. *) + match List.nth_opt pages page_index with + | Some content -> + let* page_proof = + page_membership_proof dal_params page_index + @@ Bytes.concat Bytes.empty pages + in + return_some (content, page_proof) + | None -> + failwith + "Page index %d too big or negative.\n\ + Number of pages in a slot is %d." + page_index + pages_per_slot)) + | _ -> return_none + +let metadata (node_ctxt : _ Node_context.t) = + let address = node_ctxt.rollup_address in + let origination_level = Raw_level.of_int32_exn node_ctxt.genesis_info.level in + Sc_rollup.Metadata.{address; origination_level} + +let generate_proof (node_ctxt : _ Node_context.t) + (game : Octez_smart_rollup.Game.t) start_state = + let open Lwt_result_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let snapshot = + Sc_rollup_proto_types.Inbox.history_proof_of_octez game.inbox_snapshot + in + (* NOTE: [snapshot_level_int32] below refers to the level of the snapshotted + inbox (from the skip list) which also matches [game.start_level - 1]. *) + let snapshot_level_int32 = + (Octez_smart_rollup.Inbox.Skip_list.content game.inbox_snapshot).level + in + let get_snapshot_head () = + let+ hash = Node_context.hash_of_level node_ctxt snapshot_level_int32 in + Layer1.{hash; level = snapshot_level_int32} + in + let* context = + let* start_hash = Node_context.hash_of_level node_ctxt game.inbox_level in + let+ context = Node_context.checkout_context node_ctxt start_hash in + Context.index context + in + let* dal_slots_history = + if Node_context.dal_supported node_ctxt then + let* snapshot_head = get_snapshot_head () in + Dal_slots_tracker.slots_history_of_hash node_ctxt snapshot_head + else return Dal.Slots_history.genesis + in + let* dal_slots_history_cache = + if Node_context.dal_supported node_ctxt then + let* snapshot_head = get_snapshot_head () in + Dal_slots_tracker.slots_history_cache_of_hash node_ctxt snapshot_head + else return (Dal.Slots_history.History_cache.empty ~capacity:0L) + in + (* We fetch the value of protocol constants at block snapshot level + where the game started. *) + let* parametric_constants = + let cctxt = node_ctxt.cctxt in + Protocol.Constants_services.parametric + (new Protocol_client_context.wrap_full cctxt) + (cctxt#chain, `Level snapshot_level_int32) + in + let dal_l1_parameters = parametric_constants.dal in + let dal_parameters = dal_l1_parameters.cryptobox_parameters in + let dal_attestation_lag = dal_l1_parameters.attestation_lag in + + let* page_info = + page_info_from_pvm_state + ~dal_attestation_lag + node_ctxt + dal_parameters + start_state + in + let module P = struct + include PVM + + let context = context + + let state = start_state + + let reveal hash = + let open Lwt_syntax in + let* res = + Reveals.get + ~dac_client:node_ctxt.dac_client + ~data_dir:node_ctxt.data_dir + ~pvm_kind:(Sc_rollup_proto_types.Kind.to_octez PVM.kind) + hash + in + match res with Ok data -> return @@ Some data | Error _ -> return None + + module Inbox_with_history = struct + let inbox = snapshot + + let get_history inbox_hash = + let open Lwt_syntax in + let+ inbox = Node_context.find_inbox node_ctxt inbox_hash in + match inbox with + | Error err -> + Format.kasprintf + Stdlib.failwith + "Refutation game: Cannot get inbox history for %a, %a" + Sc_rollup.Inbox.Hash.pp + inbox_hash + pp_print_trace + err + | Ok inbox -> + Option.map + (fun i -> + Sc_rollup.Inbox.take_snapshot + (Sc_rollup_proto_types.Inbox.of_octez i)) + inbox + + let get_payloads_history witness = + Lwt.map + (WithExceptions.Result.to_exn_f + ~error:(Format.kasprintf Stdlib.failwith "%a" pp_print_trace)) + @@ + let open Lwt_result_syntax in + let* {is_first_block; predecessor; predecessor_timestamp; messages} = + Node_context.get_messages node_ctxt witness + in + let*? hist = + Inbox.payloads_history_of_messages + ~is_first_block + ~predecessor + ~predecessor_timestamp + messages + in + return hist + end + + module Dal_with_history = struct + let confirmed_slots_history = dal_slots_history + + let get_history ptr = + Dal.Slots_history.History_cache.find ptr dal_slots_history_cache + |> Lwt.return + + let dal_attestation_lag = dal_attestation_lag + + let dal_parameters = dal_parameters + + let page_info = page_info + end + end in + let metadata = metadata node_ctxt in + let*! start_tick = PVM.get_tick start_state in + let is_reveal_enabled = + Sc_rollup.is_reveal_enabled_predicate + parametric_constants.sc_rollup.reveal_activation_level + in + let* proof = + trace + (Sc_rollup_node_errors.Cannot_produce_proof + { + inbox_level = game.inbox_level; + start_tick = Sc_rollup.Tick.to_z start_tick; + }) + @@ (Sc_rollup.Proof.produce + ~metadata + (module P) + (Raw_level.of_int32_exn game.inbox_level) + ~is_reveal_enabled + >|= Environment.wrap_tzresult) + in + let*? pvm_step = + Sc_rollup.Proof.unserialize_pvm_step ~pvm:(module PVM) proof.pvm_step + |> Environment.wrap_tzresult + in + let unserialized_proof = {proof with pvm_step} in + let*! res = + Sc_rollup.Proof.valid + ~metadata + snapshot + (Raw_level.of_int32_exn game.inbox_level) + dal_slots_history + dal_parameters + ~dal_attestation_lag + ~pvm:(module PVM) + unserialized_proof + ~is_reveal_enabled + >|= Environment.wrap_tzresult + in + assert (Result.is_ok res) ; + let proof = + Data_encoding.Binary.to_string_exn Sc_rollup.Proof.encoding proof + in + return proof + +let state_of_tick node_ctxt ?start_state ~tick level = + Interpreter.state_of_tick + node_ctxt + ?start_state + ~tick + (Raw_level.of_int32_exn level) + +let make_dissection (node_ctxt : _ Node_context.t) ~start_state ~start_chunk + ~our_stop_chunk ~default_number_of_sections ~last_level = + let open Lwt_result_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let state_of_tick ?start_state tick = + state_of_tick + node_ctxt + ?start_state + ~tick:(Sc_rollup.Tick.to_z tick) + last_level + in + let state_hash_of_eval_state Pvm_plugin_sig.{state_hash; _} = state_hash in + let start_chunk = + Sc_rollup_proto_types.Game.dissection_chunk_of_octez start_chunk + in + let our_stop_chunk = + Sc_rollup_proto_types.Game.dissection_chunk_of_octez our_stop_chunk + in + let+ dissection = + Game_helpers.make_dissection + ~state_of_tick + ~state_hash_of_eval_state + ?start_state + ~start_chunk + ~our_stop_chunk + @@ PVM.new_dissection + ~start_chunk + ~our_stop_chunk + ~default_number_of_sections + in + List.map Sc_rollup_proto_types.Game.dissection_chunk_to_octez dissection + +let timeout_reached node_ctxt ~self ~opponent = + let open Lwt_result_syntax in + let Node_context.{rollup_address; cctxt; _} = node_ctxt in + let+ game_result = + Plugin.RPC.Sc_rollup.timeout_reached + (new Protocol_client_context.wrap_full cctxt) + (cctxt#chain, `Head 0) + rollup_address + self + opponent + in + let open Sc_rollup.Game in + match game_result with + | Some (Loser {loser; _}) -> + let is_it_me = Signature.Public_key_hash.(self = loser) in + not is_it_me + | _ -> false + +let get_conflicts cctxt rollup staker = + let open Lwt_result_syntax in + let cctxt = new Protocol_client_context.wrap_full cctxt in + let+ conflicts = + Plugin.RPC.Sc_rollup.conflicts cctxt (cctxt#chain, `Head 0) rollup staker + in + List.map Sc_rollup_proto_types.Game.conflict_to_octez conflicts + +let get_ongoing_games cctxt rollup staker = + let open Lwt_result_syntax in + let cctxt = new Protocol_client_context.wrap_full cctxt in + let+ games = + Plugin.RPC.Sc_rollup.ongoing_refutation_games + cctxt + (cctxt#chain, `Head 0) + rollup + staker + in + List.map + (fun (game, staker1, staker2) -> + (Sc_rollup_proto_types.Game.to_octez game, staker1, staker2)) + games diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_game_helpers.mli b/src/proto_alpha/lib_sc_rollup_node/refutation_game_helpers.mli new file mode 100644 index 000000000000..8799f5deb3aa --- /dev/null +++ b/src/proto_alpha/lib_sc_rollup_node/refutation_game_helpers.mli @@ -0,0 +1,81 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [generate_proof node_ctxt (game) start_state] generates a serialized proof + for the current [game] for the execution step starting with + [start_state]. *) +val generate_proof : + Node_context.rw -> Game.t -> Context.tree -> string tzresult Lwt.t + +(** [state_of_tick node_ctxt ?start_state ~tick level] returns [Some + (state, hash)] for a given [tick] if this [tick] happened before + [level]. Otherwise, returns [None]. If provided, the evaluation is resumed + from [start_state]. *) +val state_of_tick : + _ Node_context.t -> + ?start_state:Fuel.Accounted.t Pvm_plugin_sig.eval_state -> + tick:Z.t -> + int32 -> + Fuel.Accounted.t Pvm_plugin_sig.eval_state option tzresult Lwt.t + +(** [make_dissection node_ctxt ~start_state ~start_chunk ~our_stop_chunk + ~default_number_of_sections ~last_level] computes a dissection from between + [start_chunk] and [our_stop_chunk] at level [last_level]. This dissection + has [default_number_of_sections] if there are enough ticks. *) +val make_dissection : + _ Node_context.t -> + start_state:Fuel.Accounted.t Pvm_plugin_sig.eval_state option -> + start_chunk:Game.dissection_chunk -> + our_stop_chunk:Game.dissection_chunk -> + default_number_of_sections:int -> + last_level:int32 -> + Game.dissection_chunk trace tzresult Lwt.t + +(** [timeout_reached node_ctxt ~self ~opponent] returns [true] if the + timeout is reached against opponent in head of the L1 chain. *) +val timeout_reached : + _ Node_context.t -> + self:Signature.public_key_hash -> + opponent:Signature.public_key_hash -> + bool tzresult Lwt.t + +(** [get_conflicts cctxt rollup signer] returns the conflicts for commitments + staked on by [signer]. *) +val get_conflicts : + Client_context.full -> + Address.t -> + Signature.public_key_hash -> + Game.conflict list tzresult Lwt.t + +(** [get_ongoing_games cctxt rollup signer] returns the games that [signer] is + currently playing. *) +val get_ongoing_games : + Client_context.full -> + Address.t -> + Signature.public_key_hash -> + (Game.t * Signature.public_key_hash * Signature.public_key_hash) list tzresult + Lwt.t -- GitLab From ef69598c450b4f4e19914fe33a0ecebe80e51680 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 29 Jun 2023 21:57:54 +0200 Subject: [PATCH 14/17] SCORU/Node/Oxford: extract refutation game helpers Remove protocol dependency from Refutation_game module. --- .../lib_sc_rollup_node/refutation_game.ml | 362 ++--------------- .../refutation_game_helpers.ml | 364 ++++++++++++++++++ .../refutation_game_helpers.mli | 81 ++++ 3 files changed, 469 insertions(+), 338 deletions(-) create mode 100644 src/proto_018_Proxford/lib_sc_rollup_node/refutation_game_helpers.ml create mode 100644 src/proto_018_Proxford/lib_sc_rollup_node/refutation_game_helpers.mli diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game.ml b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game.ml index 046d067eb0b9..1253dc7ef02d 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game.ml +++ b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game.ml @@ -42,21 +42,19 @@ starts a game to refute C' by starting a game with one of its staker. *) -open Protocol -open Alpha_context -open Sc_rollup.Game +open Game +open Refutation_game_helpers -let node_role ~self Sc_rollup.Game.Index.{alice; bob} = - if Sc_rollup.Staker.equal alice self then Alice - else if Sc_rollup.Staker.equal bob self then Bob +let node_role ~self {alice; bob} = + if Signature.Public_key_hash.equal alice self then Alice + else if Signature.Public_key_hash.equal bob self then Bob else (* By validity of [ongoing_game] RPC. *) assert false -type role = Our_turn of {opponent : public_key_hash} | Their_turn +type role = Our_turn of {opponent : Signature.public_key_hash} | Their_turn -let turn ~self (game : Octez_smart_rollup.Game.t) players = - let Sc_rollup.Game.Index.{alice; bob} = players in +let turn ~self game ({alice; bob} as players) = match (node_role ~self players, game.turn) with | Alice, Alice -> Our_turn {opponent = bob} | Bob, Bob -> Our_turn {opponent = alice} @@ -75,311 +73,33 @@ let inject_next_move node_ctxt source ~refutation ~opponent = let* _hash = Injector.add_pending_operation ~source refute_operation in return_unit -(** This function computes the inclusion/membership proof of the page - identified by [page_id] in the slot whose data are provided in - [slot_data]. *) -let page_membership_proof params page_index slot_data = - (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/4048 - Rely on DAL node to compute page membership proof and drop - the dal-crypto dependency from the rollup node. *) - let proof = - let open Result_syntax in - (* The computation of the page's proof below can be a bit costly. In fact, - it involves initialising a cryptobox environment and some non-trivial - crypto processing. *) - let* dal = Cryptobox.make params in - let* polynomial = Cryptobox.polynomial_from_slot dal slot_data in - Cryptobox.prove_page dal polynomial page_index - in - let open Lwt_result_syntax in - match proof with - | Ok proof -> return proof - | Error e -> - failwith - "%s" - (match e with - | `Fail s -> "Fail " ^ s - | `Page_index_out_of_range -> "Page_index_out_of_range" - | `Slot_wrong_size s -> "Slot_wrong_size: " ^ s - | `Invalid_degree_strictly_less_than_expected _ as commit_error -> - Cryptobox.string_of_commit_error commit_error) - -(** When the PVM is waiting for a Dal page input, this function attempts to - retrieve the page's content from the store, the data of its slot. Then it - computes the proof that the page is part of the slot and returns the - content along with the proof. - - If the PVM is not waiting for a Dal page input, or if the slot is known to - be unconfirmed on L1, this function returns [None]. If the data of the - slot are not saved to the store, the function returns a failure - in the error monad. *) -let page_info_from_pvm_state (node_ctxt : _ Node_context.t) ~dal_attestation_lag - (dal_params : Dal.parameters) start_state = - let open Lwt_result_syntax in - let module PVM = (val Pvm.of_kind node_ctxt.kind) in - (* TODO: https://gitlab.com/tezos/tezos/-/issues/5871 - Use constants for correct protocol. *) - let is_reveal_enabled = - node_ctxt.current_protocol.constants.sc_rollup.reveal_activation_level - |> WithExceptions.Option.get ~loc:__LOC__ - |> Sc_rollup_proto_types.Constants.reveal_activation_level_of_octez - |> Sc_rollup.is_reveal_enabled_predicate - in - let*! input_request = PVM.is_input_state ~is_reveal_enabled start_state in - match input_request with - | Sc_rollup.(Needs_reveal (Request_dal_page page_id)) -> ( - let Dal.Page.{slot_id; page_index} = page_id in - let* pages = - Dal_pages_request.slot_pages ~dal_attestation_lag node_ctxt slot_id - in - match pages with - | None -> return_none (* The slot is not confirmed. *) - | Some pages -> ( - let pages_per_slot = dal_params.slot_size / dal_params.page_size in - (* check invariant that pages' length is correct. *) - (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/4031 - It's better to do the check when the slots are saved into disk. *) - (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/3997 - This check is not resilient to dal parameters change. *) - match List.nth_opt pages page_index with - | Some content -> - let* page_proof = - page_membership_proof dal_params page_index - @@ Bytes.concat Bytes.empty pages - in - return_some (content, page_proof) - | None -> - failwith - "Page index %d too big or negative.\n\ - Number of pages in a slot is %d." - page_index - pages_per_slot)) - | _ -> return_none - -let metadata (node_ctxt : _ Node_context.t) = - let address = - Sc_rollup_proto_types.Address.of_octez node_ctxt.rollup_address - in - let origination_level = Raw_level.of_int32_exn node_ctxt.genesis_info.level in - Sc_rollup.Metadata.{address; origination_level} - -let generate_proof (node_ctxt : _ Node_context.t) - (game : Octez_smart_rollup.Game.t) start_state = - let open Lwt_result_syntax in - let module PVM = (val Pvm.of_kind node_ctxt.kind) in - let snapshot = - Sc_rollup_proto_types.Inbox.history_proof_of_octez game.inbox_snapshot - in - (* NOTE: [snapshot_level_int32] below refers to the level of the snapshotted - inbox (from the skip list) which also matches [game.start_level - 1]. *) - let snapshot_level_int32 = - (Octez_smart_rollup.Inbox.Skip_list.content game.inbox_snapshot).level - in - let get_snapshot_head () = - let+ hash = Node_context.hash_of_level node_ctxt snapshot_level_int32 in - Layer1.{hash; level = snapshot_level_int32} - in - let* context = - let* start_hash = Node_context.hash_of_level node_ctxt game.inbox_level in - let+ context = Node_context.checkout_context node_ctxt start_hash in - Context.index context - in - let* dal_slots_history = - if Node_context.dal_supported node_ctxt then - let* snapshot_head = get_snapshot_head () in - Dal_slots_tracker.slots_history_of_hash node_ctxt snapshot_head - else return Dal.Slots_history.genesis - in - let* dal_slots_history_cache = - if Node_context.dal_supported node_ctxt then - let* snapshot_head = get_snapshot_head () in - Dal_slots_tracker.slots_history_cache_of_hash node_ctxt snapshot_head - else return (Dal.Slots_history.History_cache.empty ~capacity:0L) - in - (* We fetch the value of protocol constants at block snapshot level - where the game started. *) - let* parametric_constants = - let cctxt = node_ctxt.cctxt in - Protocol.Constants_services.parametric - (new Protocol_client_context.wrap_full cctxt) - (cctxt#chain, `Level snapshot_level_int32) - in - let dal_l1_parameters = parametric_constants.dal in - let dal_parameters = dal_l1_parameters.cryptobox_parameters in - let dal_attestation_lag = dal_l1_parameters.attestation_lag in - - let* page_info = - page_info_from_pvm_state - ~dal_attestation_lag - node_ctxt - dal_parameters - start_state - in - let module P = struct - include PVM - - let context = context - - let state = start_state - - let reveal hash = - let open Lwt_syntax in - let* res = - Reveals.get - ~dac_client:node_ctxt.dac_client - ~data_dir:node_ctxt.data_dir - ~pvm_kind:(Sc_rollup_proto_types.Kind.to_octez PVM.kind) - hash - in - match res with Ok data -> return @@ Some data | Error _ -> return None - - module Inbox_with_history = struct - let inbox = snapshot - - let get_history inbox_hash = - let open Lwt_syntax in - let+ inbox = Node_context.find_inbox node_ctxt inbox_hash in - match inbox with - | Error err -> - Format.kasprintf - Stdlib.failwith - "Refutation game: Cannot get inbox history for %a, %a" - Sc_rollup.Inbox.Hash.pp - inbox_hash - pp_print_trace - err - | Ok inbox -> - Option.map - (fun i -> - Sc_rollup.Inbox.take_snapshot - (Sc_rollup_proto_types.Inbox.of_octez i)) - inbox - - let get_payloads_history witness = - Lwt.map - (WithExceptions.Result.to_exn_f - ~error:(Format.kasprintf Stdlib.failwith "%a" pp_print_trace)) - @@ - let open Lwt_result_syntax in - let* {is_first_block; predecessor; predecessor_timestamp; messages} = - Node_context.get_messages node_ctxt witness - in - let*? hist = - Inbox.payloads_history_of_messages - ~is_first_block - ~predecessor - ~predecessor_timestamp - messages - in - return hist - end - - module Dal_with_history = struct - let confirmed_slots_history = dal_slots_history - - let get_history ptr = - Dal.Slots_history.History_cache.find ptr dal_slots_history_cache - |> Lwt.return - - let dal_attestation_lag = dal_attestation_lag - - let dal_parameters = dal_parameters - - let page_info = page_info - end - end in - let metadata = metadata node_ctxt in - let*! start_tick = PVM.get_tick start_state in - let is_reveal_enabled = - Sc_rollup.is_reveal_enabled_predicate - parametric_constants.sc_rollup.reveal_activation_level - in - let* proof = - trace - (Sc_rollup_node_errors.Cannot_produce_proof - { - inbox_level = game.inbox_level; - start_tick = Sc_rollup.Tick.to_z start_tick; - }) - @@ (Sc_rollup.Proof.produce - ~metadata - (module P) - (Raw_level.of_int32_exn game.inbox_level) - ~is_reveal_enabled - >|= Environment.wrap_tzresult) - in - let*? pvm_step = - Sc_rollup.Proof.unserialize_pvm_step ~pvm:(module PVM) proof.pvm_step - |> Environment.wrap_tzresult - in - let unserialized_proof = {proof with pvm_step} in - let*! res = - Sc_rollup.Proof.valid - ~metadata - snapshot - (Raw_level.of_int32_exn game.inbox_level) - dal_slots_history - dal_parameters - ~dal_attestation_lag - ~pvm:(module PVM) - unserialized_proof - ~is_reveal_enabled - >|= Environment.wrap_tzresult - in - assert (Result.is_ok res) ; - let proof = - Data_encoding.Binary.to_string_exn Sc_rollup.Proof.encoding proof - in - return proof - type pvm_intermediate_state = - | Hash of Sc_rollup.State_hash.t + | Hash of State_hash.t | Evaluated of Fuel.Accounted.t Pvm_plugin_sig.eval_state let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok our_view = let open Lwt_result_syntax in - let state_of_tick ?start_state tick = - Interpreter.state_of_tick - node_ctxt - ?start_state - ~tick:(Sc_rollup.Tick.to_z tick) - (Raw_level.of_int32_exn last_level) - in - let state_hash_of_eval_state Pvm_plugin_sig.{state_hash; _} = state_hash in let start_hash, start_tick, start_state = match ok with | Hash hash, tick -> (hash, tick, None) | Evaluated ({state_hash; _} as state), tick -> (state_hash, tick, Some state) in - let start_chunk = - Sc_rollup.Dissection_chunk. - {state_hash = Some start_hash; tick = Sc_rollup.Tick.of_z start_tick} - in + let start_chunk = Game.{state_hash = Some start_hash; tick = start_tick} in let our_state, our_tick = our_view in let our_state_hash = Option.map (fun Pvm_plugin_sig.{state_hash; _} -> state_hash) our_state in - let our_stop_chunk = - Sc_rollup.Dissection_chunk. - {state_hash = our_state_hash; tick = Sc_rollup.Tick.of_z our_tick} - in - let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let our_stop_chunk = Game.{state_hash = our_state_hash; tick = our_tick} in let* dissection = - Game_helpers.make_dissection - ~state_of_tick - ~state_hash_of_eval_state - ?start_state + make_dissection + node_ctxt + ~start_state ~start_chunk ~our_stop_chunk - @@ PVM.new_dissection - ~start_chunk - ~our_stop_chunk - ~default_number_of_sections - in - let dissection = - List.map Sc_rollup_proto_types.Game.dissection_chunk_to_octez dissection + ~default_number_of_sections + ~last_level in let*! () = Refutation_game_event.computed_dissection @@ -414,11 +134,7 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent | Evaluated ok_state, _ -> Some ok_state in let* our = - Interpreter.state_of_tick - node_ctxt - ?start_state - ~tick - (Raw_level.of_int32_exn game.inbox_level) + state_of_tick node_ctxt ?start_state ~tick game.inbox_level in match (their_hash, our) with | None, None -> @@ -460,10 +176,7 @@ let next_move node_ctxt ~opponent (game : Octez_smart_rollup.Game.t) = let open Lwt_result_syntax in let final_move start_tick = let* start_state = - Interpreter.state_of_tick - node_ctxt - ~tick:start_tick - (Raw_level.of_int32_exn game.inbox_level) + state_of_tick node_ctxt ~tick:start_tick game.inbox_level in match start_state with | None -> @@ -502,11 +215,7 @@ let play_next_move node_ctxt game self opponent = let play_timeout (node_ctxt : _ Node_context.t) self stakers = let open Lwt_result_syntax in let timeout_operation = - L1_operation.Timeout - { - rollup = node_ctxt.rollup_address; - stakers = Sc_rollup_proto_types.Game.index_to_octez stakers; - } + L1_operation.Timeout {rollup = node_ctxt.rollup_address; stakers} in let source = Node_context.get_operator node_ctxt Timeout |> Option.value ~default:self @@ -515,39 +224,16 @@ let play_timeout (node_ctxt : _ Node_context.t) self stakers = let* _hash = Injector.add_pending_operation ~source timeout_operation in return_unit -let timeout_reached ~self head_block node_ctxt staker1 staker2 = - let open Lwt_result_syntax in - let Node_context.{rollup_address; cctxt; _} = node_ctxt in - let* game_result = - Plugin.RPC.Sc_rollup.timeout_reached - (new Protocol_client_context.wrap_full cctxt) - (cctxt#chain, head_block) - rollup_address - staker1 - staker2 - in - let open Sc_rollup.Game in - match game_result with - | Some (Loser {loser; _}) -> - let is_it_me = Signature.Public_key_hash.(self = loser) in - if is_it_me then return_none else return (Some loser) - | _ -> return_none - let play node_ctxt ~self game opponent = let open Lwt_result_syntax in - let index = Sc_rollup.Game.Index.make self opponent in - let head_block = `Head 0 in + let index = make_index self opponent in match turn ~self game index with | Our_turn {opponent} -> play_next_move node_ctxt game self opponent - | Their_turn -> ( - let* timeout_reached = - timeout_reached ~self head_block node_ctxt self opponent - in - match timeout_reached with - | Some opponent -> - let*! () = Refutation_game_event.timeout_detected opponent in - play_timeout node_ctxt self index - | None -> return_unit) + | Their_turn -> + let* timeout_reached = timeout_reached node_ctxt ~self ~opponent in + when_ timeout_reached @@ fun () -> + let*! () = Refutation_game_event.timeout_detected opponent in + play_timeout node_ctxt self index let play_opening_move node_ctxt self (conflict : Octez_smart_rollup.Game.conflict) = diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game_helpers.ml b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game_helpers.ml new file mode 100644 index 000000000000..850e54227fb8 --- /dev/null +++ b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game_helpers.ml @@ -0,0 +1,364 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** This function computes the inclusion/membership proof of the page + identified by [page_id] in the slot whose data are provided in + [slot_data]. *) +let page_membership_proof params page_index slot_data = + (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/4048 + Rely on DAL node to compute page membership proof and drop + the dal-crypto dependency from the rollup node. *) + let proof = + let open Result_syntax in + (* The computation of the page's proof below can be a bit costly. In fact, + it involves initialising a cryptobox environment and some non-trivial + crypto processing. *) + let* dal = Cryptobox.make params in + let* polynomial = Cryptobox.polynomial_from_slot dal slot_data in + Cryptobox.prove_page dal polynomial page_index + in + let open Lwt_result_syntax in + match proof with + | Ok proof -> return proof + | Error e -> + failwith + "%s" + (match e with + | `Fail s -> "Fail " ^ s + | `Page_index_out_of_range -> "Page_index_out_of_range" + | `Slot_wrong_size s -> "Slot_wrong_size: " ^ s + | `Invalid_degree_strictly_less_than_expected _ as commit_error -> + Cryptobox.string_of_commit_error commit_error) + +(** When the PVM is waiting for a Dal page input, this function attempts to + retrieve the page's content from the store, the data of its slot. Then it + computes the proof that the page is part of the slot and returns the + content along with the proof. + + If the PVM is not waiting for a Dal page input, or if the slot is known to + be unconfirmed on L1, this function returns [None]. If the data of the + slot are not saved to the store, the function returns a failure + in the error monad. *) +let page_info_from_pvm_state (node_ctxt : _ Node_context.t) ~dal_attestation_lag + (dal_params : Dal.parameters) start_state = + let open Lwt_result_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + (* TODO: https://gitlab.com/tezos/tezos/-/issues/5871 + Use constants for correct protocol. *) + let is_reveal_enabled = + node_ctxt.current_protocol.constants.sc_rollup.reveal_activation_level + |> WithExceptions.Option.get ~loc:__LOC__ + |> Sc_rollup_proto_types.Constants.reveal_activation_level_of_octez + |> Sc_rollup.is_reveal_enabled_predicate + in + let*! input_request = PVM.is_input_state ~is_reveal_enabled start_state in + match input_request with + | Sc_rollup.(Needs_reveal (Request_dal_page page_id)) -> ( + let Dal.Page.{slot_id; page_index} = page_id in + let* pages = + Dal_pages_request.slot_pages ~dal_attestation_lag node_ctxt slot_id + in + match pages with + | None -> return_none (* The slot is not confirmed. *) + | Some pages -> ( + let pages_per_slot = dal_params.slot_size / dal_params.page_size in + (* check invariant that pages' length is correct. *) + (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/4031 + It's better to do the check when the slots are saved into disk. *) + (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/3997 + This check is not resilient to dal parameters change. *) + match List.nth_opt pages page_index with + | Some content -> + let* page_proof = + page_membership_proof dal_params page_index + @@ Bytes.concat Bytes.empty pages + in + return_some (content, page_proof) + | None -> + failwith + "Page index %d too big or negative.\n\ + Number of pages in a slot is %d." + page_index + pages_per_slot)) + | _ -> return_none + +let metadata (node_ctxt : _ Node_context.t) = + let address = node_ctxt.rollup_address in + let origination_level = Raw_level.of_int32_exn node_ctxt.genesis_info.level in + Sc_rollup.Metadata.{address; origination_level} + +let generate_proof (node_ctxt : _ Node_context.t) + (game : Octez_smart_rollup.Game.t) start_state = + let open Lwt_result_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let snapshot = + Sc_rollup_proto_types.Inbox.history_proof_of_octez game.inbox_snapshot + in + (* NOTE: [snapshot_level_int32] below refers to the level of the snapshotted + inbox (from the skip list) which also matches [game.start_level - 1]. *) + let snapshot_level_int32 = + (Octez_smart_rollup.Inbox.Skip_list.content game.inbox_snapshot).level + in + let get_snapshot_head () = + let+ hash = Node_context.hash_of_level node_ctxt snapshot_level_int32 in + Layer1.{hash; level = snapshot_level_int32} + in + let* context = + let* start_hash = Node_context.hash_of_level node_ctxt game.inbox_level in + let+ context = Node_context.checkout_context node_ctxt start_hash in + Context.index context + in + let* dal_slots_history = + if Node_context.dal_supported node_ctxt then + let* snapshot_head = get_snapshot_head () in + Dal_slots_tracker.slots_history_of_hash node_ctxt snapshot_head + else return Dal.Slots_history.genesis + in + let* dal_slots_history_cache = + if Node_context.dal_supported node_ctxt then + let* snapshot_head = get_snapshot_head () in + Dal_slots_tracker.slots_history_cache_of_hash node_ctxt snapshot_head + else return (Dal.Slots_history.History_cache.empty ~capacity:0L) + in + (* We fetch the value of protocol constants at block snapshot level + where the game started. *) + let* parametric_constants = + let cctxt = node_ctxt.cctxt in + Protocol.Constants_services.parametric + (new Protocol_client_context.wrap_full cctxt) + (cctxt#chain, `Level snapshot_level_int32) + in + let dal_l1_parameters = parametric_constants.dal in + let dal_parameters = dal_l1_parameters.cryptobox_parameters in + let dal_attestation_lag = dal_l1_parameters.attestation_lag in + + let* page_info = + page_info_from_pvm_state + ~dal_attestation_lag + node_ctxt + dal_parameters + start_state + in + let module P = struct + include PVM + + let context = context + + let state = start_state + + let reveal hash = + let open Lwt_syntax in + let* res = + Reveals.get + ~dac_client:node_ctxt.dac_client + ~data_dir:node_ctxt.data_dir + ~pvm_kind:(Sc_rollup_proto_types.Kind.to_octez PVM.kind) + hash + in + match res with Ok data -> return @@ Some data | Error _ -> return None + + module Inbox_with_history = struct + let inbox = snapshot + + let get_history inbox_hash = + let open Lwt_syntax in + let+ inbox = Node_context.find_inbox node_ctxt inbox_hash in + match inbox with + | Error err -> + Format.kasprintf + Stdlib.failwith + "Refutation game: Cannot get inbox history for %a, %a" + Sc_rollup.Inbox.Hash.pp + inbox_hash + pp_print_trace + err + | Ok inbox -> + Option.map + (fun i -> + Sc_rollup.Inbox.take_snapshot + (Sc_rollup_proto_types.Inbox.of_octez i)) + inbox + + let get_payloads_history witness = + Lwt.map + (WithExceptions.Result.to_exn_f + ~error:(Format.kasprintf Stdlib.failwith "%a" pp_print_trace)) + @@ + let open Lwt_result_syntax in + let* {is_first_block; predecessor; predecessor_timestamp; messages} = + Node_context.get_messages node_ctxt witness + in + let*? hist = + Inbox.payloads_history_of_messages + ~is_first_block + ~predecessor + ~predecessor_timestamp + messages + in + return hist + end + + module Dal_with_history = struct + let confirmed_slots_history = dal_slots_history + + let get_history ptr = + Dal.Slots_history.History_cache.find ptr dal_slots_history_cache + |> Lwt.return + + let dal_attestation_lag = dal_attestation_lag + + let dal_parameters = dal_parameters + + let page_info = page_info + end + end in + let metadata = metadata node_ctxt in + let*! start_tick = PVM.get_tick start_state in + let is_reveal_enabled = + Sc_rollup.is_reveal_enabled_predicate + parametric_constants.sc_rollup.reveal_activation_level + in + let* proof = + trace + (Sc_rollup_node_errors.Cannot_produce_proof + { + inbox_level = game.inbox_level; + start_tick = Sc_rollup.Tick.to_z start_tick; + }) + @@ (Sc_rollup.Proof.produce + ~metadata + (module P) + (Raw_level.of_int32_exn game.inbox_level) + ~is_reveal_enabled + >|= Environment.wrap_tzresult) + in + let*? pvm_step = + Sc_rollup.Proof.unserialize_pvm_step ~pvm:(module PVM) proof.pvm_step + |> Environment.wrap_tzresult + in + let unserialized_proof = {proof with pvm_step} in + let*! res = + Sc_rollup.Proof.valid + ~metadata + snapshot + (Raw_level.of_int32_exn game.inbox_level) + dal_slots_history + dal_parameters + ~dal_attestation_lag + ~pvm:(module PVM) + unserialized_proof + ~is_reveal_enabled + >|= Environment.wrap_tzresult + in + assert (Result.is_ok res) ; + let proof = + Data_encoding.Binary.to_string_exn Sc_rollup.Proof.encoding proof + in + return proof + +let state_of_tick node_ctxt ?start_state ~tick level = + Interpreter.state_of_tick + node_ctxt + ?start_state + ~tick + (Raw_level.of_int32_exn level) + +let make_dissection (node_ctxt : _ Node_context.t) ~start_state ~start_chunk + ~our_stop_chunk ~default_number_of_sections ~last_level = + let open Lwt_result_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let state_of_tick ?start_state tick = + state_of_tick + node_ctxt + ?start_state + ~tick:(Sc_rollup.Tick.to_z tick) + last_level + in + let state_hash_of_eval_state Pvm_plugin_sig.{state_hash; _} = state_hash in + let start_chunk = + Sc_rollup_proto_types.Game.dissection_chunk_of_octez start_chunk + in + let our_stop_chunk = + Sc_rollup_proto_types.Game.dissection_chunk_of_octez our_stop_chunk + in + let+ dissection = + Game_helpers.make_dissection + ~state_of_tick + ~state_hash_of_eval_state + ?start_state + ~start_chunk + ~our_stop_chunk + @@ PVM.new_dissection + ~start_chunk + ~our_stop_chunk + ~default_number_of_sections + in + List.map Sc_rollup_proto_types.Game.dissection_chunk_to_octez dissection + +let timeout_reached node_ctxt ~self ~opponent = + let open Lwt_result_syntax in + let Node_context.{rollup_address; cctxt; _} = node_ctxt in + let+ game_result = + Plugin.RPC.Sc_rollup.timeout_reached + (new Protocol_client_context.wrap_full cctxt) + (cctxt#chain, `Head 0) + rollup_address + self + opponent + in + let open Sc_rollup.Game in + match game_result with + | Some (Loser {loser; _}) -> + let is_it_me = Signature.Public_key_hash.(self = loser) in + not is_it_me + | _ -> false + +let get_conflicts cctxt rollup staker = + let open Lwt_result_syntax in + let cctxt = new Protocol_client_context.wrap_full cctxt in + let+ conflicts = + Plugin.RPC.Sc_rollup.conflicts cctxt (cctxt#chain, `Head 0) rollup staker + in + List.map Sc_rollup_proto_types.Game.conflict_to_octez conflicts + +let get_ongoing_games cctxt rollup staker = + let open Lwt_result_syntax in + let cctxt = new Protocol_client_context.wrap_full cctxt in + let+ games = + Plugin.RPC.Sc_rollup.ongoing_refutation_games + cctxt + (cctxt#chain, `Head 0) + rollup + staker + in + List.map + (fun (game, staker1, staker2) -> + (Sc_rollup_proto_types.Game.to_octez game, staker1, staker2)) + games diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game_helpers.mli b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game_helpers.mli new file mode 100644 index 000000000000..8799f5deb3aa --- /dev/null +++ b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game_helpers.mli @@ -0,0 +1,81 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [generate_proof node_ctxt (game) start_state] generates a serialized proof + for the current [game] for the execution step starting with + [start_state]. *) +val generate_proof : + Node_context.rw -> Game.t -> Context.tree -> string tzresult Lwt.t + +(** [state_of_tick node_ctxt ?start_state ~tick level] returns [Some + (state, hash)] for a given [tick] if this [tick] happened before + [level]. Otherwise, returns [None]. If provided, the evaluation is resumed + from [start_state]. *) +val state_of_tick : + _ Node_context.t -> + ?start_state:Fuel.Accounted.t Pvm_plugin_sig.eval_state -> + tick:Z.t -> + int32 -> + Fuel.Accounted.t Pvm_plugin_sig.eval_state option tzresult Lwt.t + +(** [make_dissection node_ctxt ~start_state ~start_chunk ~our_stop_chunk + ~default_number_of_sections ~last_level] computes a dissection from between + [start_chunk] and [our_stop_chunk] at level [last_level]. This dissection + has [default_number_of_sections] if there are enough ticks. *) +val make_dissection : + _ Node_context.t -> + start_state:Fuel.Accounted.t Pvm_plugin_sig.eval_state option -> + start_chunk:Game.dissection_chunk -> + our_stop_chunk:Game.dissection_chunk -> + default_number_of_sections:int -> + last_level:int32 -> + Game.dissection_chunk trace tzresult Lwt.t + +(** [timeout_reached node_ctxt ~self ~opponent] returns [true] if the + timeout is reached against opponent in head of the L1 chain. *) +val timeout_reached : + _ Node_context.t -> + self:Signature.public_key_hash -> + opponent:Signature.public_key_hash -> + bool tzresult Lwt.t + +(** [get_conflicts cctxt rollup signer] returns the conflicts for commitments + staked on by [signer]. *) +val get_conflicts : + Client_context.full -> + Address.t -> + Signature.public_key_hash -> + Game.conflict list tzresult Lwt.t + +(** [get_ongoing_games cctxt rollup signer] returns the games that [signer] is + currently playing. *) +val get_ongoing_games : + Client_context.full -> + Address.t -> + Signature.public_key_hash -> + (Game.t * Signature.public_key_hash * Signature.public_key_hash) list tzresult + Lwt.t -- GitLab From 07b938a41051b179b4fdb8c46f22b6619e6a53a3 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 29 Jun 2023 21:57:54 +0200 Subject: [PATCH 15/17] SCORU/Node/Nairobi: extract refutation game helpers Remove protocol dependency from Refutation_game module. --- .../lib_sc_rollup_node/refutation_game.ml | 364 ++---------------- .../refutation_game_helpers.ml | 364 ++++++++++++++++++ .../refutation_game_helpers.mli | 81 ++++ 3 files changed, 470 insertions(+), 339 deletions(-) create mode 100644 src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game_helpers.ml create mode 100644 src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game_helpers.mli diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.ml index e59d0f8a10a3..1253dc7ef02d 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.ml @@ -43,20 +43,18 @@ *) -open Protocol -open Alpha_context -open Sc_rollup.Game +open Game +open Refutation_game_helpers -let node_role ~self Sc_rollup.Game.Index.{alice; bob} = - if Sc_rollup.Staker.equal alice self then Alice - else if Sc_rollup.Staker.equal bob self then Bob +let node_role ~self {alice; bob} = + if Signature.Public_key_hash.equal alice self then Alice + else if Signature.Public_key_hash.equal bob self then Bob else (* By validity of [ongoing_game] RPC. *) assert false -type role = Our_turn of {opponent : public_key_hash} | Their_turn +type role = Our_turn of {opponent : Signature.public_key_hash} | Their_turn -let turn ~self (game : Octez_smart_rollup.Game.t) players = - let Sc_rollup.Game.Index.{alice; bob} = players in +let turn ~self game ({alice; bob} as players) = match (node_role ~self players, game.turn) with | Alice, Alice -> Our_turn {opponent = bob} | Bob, Bob -> Our_turn {opponent = alice} @@ -75,311 +73,33 @@ let inject_next_move node_ctxt source ~refutation ~opponent = let* _hash = Injector.add_pending_operation ~source refute_operation in return_unit -(** This function computes the inclusion/membership proof of the page - identified by [page_id] in the slot whose data are provided in - [slot_data]. *) -let page_membership_proof params page_index slot_data = - (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/4048 - Rely on DAL node to compute page membership proof and drop - the dal-crypto dependency from the rollup node. *) - let proof = - let open Result_syntax in - (* The computation of the page's proof below can be a bit costly. In fact, - it involves initialising a cryptobox environment and some non-trivial - crypto processing. *) - let* dal = Cryptobox.make params in - let* polynomial = Cryptobox.polynomial_from_slot dal slot_data in - Cryptobox.prove_page dal polynomial page_index - in - let open Lwt_result_syntax in - match proof with - | Ok proof -> return proof - | Error e -> - failwith - "%s" - (match e with - | `Fail s -> "Fail " ^ s - | `Page_index_out_of_range -> "Page_index_out_of_range" - | `Slot_wrong_size s -> "Slot_wrong_size: " ^ s - | `Invalid_degree_strictly_less_than_expected _ as commit_error -> - Cryptobox.string_of_commit_error commit_error) - -(** When the PVM is waiting for a Dal page input, this function attempts to - retrieve the page's content from the store, the data of its slot. Then it - computes the proof that the page is part of the slot and returns the - content along with the proof. - - If the PVM is not waiting for a Dal page input, or if the slot is known to - be unconfirmed on L1, this function returns [None]. If the data of the - slot are not saved to the store, the function returns a failure - in the error monad. *) -let page_info_from_pvm_state (node_ctxt : _ Node_context.t) ~dal_attestation_lag - (dal_params : Dal.parameters) start_state = - let open Lwt_result_syntax in - let module PVM = (val Pvm.of_kind node_ctxt.kind) in - let*! input_request = PVM.is_input_state start_state in - match input_request with - | Sc_rollup.(Needs_reveal (Request_dal_page page_id)) -> ( - let Dal.Page.{slot_id; page_index} = page_id in - let* pages = - Dal_pages_request.slot_pages ~dal_attestation_lag node_ctxt slot_id - in - match pages with - | None -> return_none (* The slot is not confirmed. *) - | Some pages -> ( - let pages_per_slot = dal_params.slot_size / dal_params.page_size in - (* check invariant that pages' length is correct. *) - (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/4031 - It's better to do the check when the slots are saved into disk. *) - (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/3997 - This check is not resilient to dal parameters change. *) - match List.nth_opt pages page_index with - | Some content -> - let* page_proof = - page_membership_proof dal_params page_index - @@ Bytes.concat Bytes.empty pages - in - return_some (content, page_proof) - | None -> - failwith - "Page index %d too big or negative.\n\ - Number of pages in a slot is %d." - page_index - pages_per_slot)) - | _ -> return_none - -let metadata (node_ctxt : _ Node_context.t) = - let address = - Sc_rollup_proto_types.Address.of_octez node_ctxt.rollup_address - in - let origination_level = Raw_level.of_int32_exn node_ctxt.genesis_info.level in - Sc_rollup.Metadata.{address; origination_level} - -let generate_proof (node_ctxt : _ Node_context.t) - (game : Octez_smart_rollup.Game.t) start_state = - let open Lwt_result_syntax in - let module PVM = (val Pvm.of_kind node_ctxt.kind) in - let snapshot = - Sc_rollup_proto_types.Inbox.history_proof_of_octez game.inbox_snapshot - in - (* NOTE: [snapshot_level_int32] below refers to the level of the snapshotted - inbox (from the skip list) which also matches [game.start_level - 1]. *) - let snapshot_level_int32 = - (Octez_smart_rollup.Inbox.Skip_list.content game.inbox_snapshot).level - in - let get_snapshot_head () = - let+ hash = Node_context.hash_of_level node_ctxt snapshot_level_int32 in - Layer1.{hash; level = snapshot_level_int32} - in - let* context = - let* start_hash = Node_context.hash_of_level node_ctxt game.inbox_level in - let+ context = Node_context.checkout_context node_ctxt start_hash in - Context.index context - in - let* dal_slots_history = - if Node_context.dal_supported node_ctxt then - let* snapshot_head = get_snapshot_head () in - Dal_slots_tracker.slots_history_of_hash node_ctxt snapshot_head - else return Dal.Slots_history.genesis - in - let* dal_slots_history_cache = - if Node_context.dal_supported node_ctxt then - let* snapshot_head = get_snapshot_head () in - Dal_slots_tracker.slots_history_cache_of_hash node_ctxt snapshot_head - else return (Dal.Slots_history.History_cache.empty ~capacity:0L) - in - (* We fetch the value of protocol constants at block snapshot level - where the game started. *) - let* parametric_constants = - let cctxt = node_ctxt.cctxt in - Protocol.Constants_services.parametric - (new Protocol_client_context.wrap_full cctxt) - (cctxt#chain, `Level snapshot_level_int32) - in - let dal_l1_parameters = parametric_constants.dal in - let dal_parameters = dal_l1_parameters.cryptobox_parameters in - let dal_attestation_lag = dal_l1_parameters.attestation_lag in - - let* page_info = - page_info_from_pvm_state - ~dal_attestation_lag - node_ctxt - dal_parameters - start_state - in - let module P = struct - include PVM - - let context = context - - let state = start_state - - let reveal hash = - let open Lwt_syntax in - let* res = - Reveals.get - ~data_dir:node_ctxt.data_dir - ~pvm_kind:(Sc_rollup_proto_types.Kind.to_octez PVM.kind) - ~hash - in - match res with Ok data -> return @@ Some data | Error _ -> return None - - module Inbox_with_history = struct - let inbox = snapshot - - let get_history inbox_hash = - let open Lwt_syntax in - let+ inbox = - Node_context.find_inbox - node_ctxt - (Sc_rollup_proto_types.Inbox_hash.to_octez inbox_hash) - in - match inbox with - | Error err -> - Format.kasprintf - Stdlib.failwith - "Refutation game: Cannot get inbox history for %a, %a" - Sc_rollup.Inbox.Hash.pp - inbox_hash - pp_print_trace - err - | Ok inbox -> - Option.map - (fun i -> - Sc_rollup.Inbox.take_snapshot - (Sc_rollup_proto_types.Inbox.of_octez i)) - inbox - - let get_payloads_history witness = - Lwt.map - (WithExceptions.Result.to_exn_f - ~error:(Format.kasprintf Stdlib.failwith "%a" pp_print_trace)) - @@ - let open Lwt_result_syntax in - let* {is_first_block; predecessor; predecessor_timestamp; messages} = - Node_context.get_messages - node_ctxt - (Sc_rollup_proto_types.Merkelized_payload_hashes_hash.to_octez - witness) - in - let*? hist = - Inbox.payloads_history_of_messages - ~is_first_block - ~predecessor - ~predecessor_timestamp - messages - in - return hist - end - - module Dal_with_history = struct - let confirmed_slots_history = dal_slots_history - - let get_history ptr = - Dal.Slots_history.History_cache.find ptr dal_slots_history_cache - |> Lwt.return - - let dal_attestation_lag = dal_attestation_lag - - let dal_parameters = dal_parameters - - let page_info = page_info - end - end in - let metadata = metadata node_ctxt in - let*! start_tick = PVM.get_tick start_state in - let* proof = - trace - (Sc_rollup_node_errors.Cannot_produce_proof - { - inbox_level = game.inbox_level; - start_tick = Sc_rollup.Tick.to_z start_tick; - }) - @@ (Sc_rollup.Proof.produce - ~metadata - (module P) - (Raw_level.of_int32_exn game.inbox_level) - >|= Environment.wrap_tzresult) - in - let*? pvm_step = - Sc_rollup.Proof.unserialize_pvm_step ~pvm:(module PVM) proof.pvm_step - |> Environment.wrap_tzresult - in - let unserialized_proof = {proof with pvm_step} in - let*! res = - Sc_rollup.Proof.valid - ~metadata - snapshot - (Raw_level.of_int32_exn game.inbox_level) - dal_slots_history - dal_parameters - ~dal_attestation_lag - ~pvm:(module PVM) - unserialized_proof - >|= Environment.wrap_tzresult - in - assert (Result.is_ok res) ; - let proof = - Data_encoding.Binary.to_string_exn Sc_rollup.Proof.encoding proof - in - return proof - type pvm_intermediate_state = - | Hash of Octez_smart_rollup.State_hash.t + | Hash of State_hash.t | Evaluated of Fuel.Accounted.t Pvm_plugin_sig.eval_state let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok our_view = let open Lwt_result_syntax in - let state_of_tick ?start_state tick = - Interpreter.state_of_tick - node_ctxt - ?start_state - ~tick:(Sc_rollup.Tick.to_z tick) - (Raw_level.of_int32_exn last_level) - in - let state_hash_of_eval_state Pvm_plugin_sig.{state_hash; _} = - Sc_rollup_proto_types.State_hash.of_octez state_hash - in let start_hash, start_tick, start_state = match ok with | Hash hash, tick -> (hash, tick, None) | Evaluated ({state_hash; _} as state), tick -> (state_hash, tick, Some state) in - let start_chunk = - Sc_rollup.Dissection_chunk. - { - state_hash = Some (Sc_rollup_proto_types.State_hash.of_octez start_hash); - tick = Sc_rollup.Tick.of_z start_tick; - } - in + let start_chunk = Game.{state_hash = Some start_hash; tick = start_tick} in let our_state, our_tick = our_view in let our_state_hash = - Option.map - (fun Pvm_plugin_sig.{state_hash; _} -> - Sc_rollup_proto_types.State_hash.of_octez state_hash) - our_state - in - let our_stop_chunk = - Sc_rollup.Dissection_chunk. - {state_hash = our_state_hash; tick = Sc_rollup.Tick.of_z our_tick} + Option.map (fun Pvm_plugin_sig.{state_hash; _} -> state_hash) our_state in - let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let our_stop_chunk = Game.{state_hash = our_state_hash; tick = our_tick} in let* dissection = - Game_helpers.make_dissection - ~state_of_tick - ~state_hash_of_eval_state - ?start_state + make_dissection + node_ctxt + ~start_state ~start_chunk ~our_stop_chunk - @@ PVM.new_dissection - ~start_chunk - ~our_stop_chunk - ~default_number_of_sections - in - let dissection = - List.map Sc_rollup_proto_types.Game.dissection_chunk_to_octez dissection + ~default_number_of_sections + ~last_level in let*! () = Refutation_game_event.computed_dissection @@ -414,11 +134,7 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent | Evaluated ok_state, _ -> Some ok_state in let* our = - Interpreter.state_of_tick - node_ctxt - ?start_state - ~tick - (Raw_level.of_int32_exn game.inbox_level) + state_of_tick node_ctxt ?start_state ~tick game.inbox_level in match (their_hash, our) with | None, None -> @@ -460,10 +176,7 @@ let next_move node_ctxt ~opponent (game : Octez_smart_rollup.Game.t) = let open Lwt_result_syntax in let final_move start_tick = let* start_state = - Interpreter.state_of_tick - node_ctxt - ~tick:start_tick - (Raw_level.of_int32_exn game.inbox_level) + state_of_tick node_ctxt ~tick:start_tick game.inbox_level in match start_state with | None -> @@ -502,11 +215,7 @@ let play_next_move node_ctxt game self opponent = let play_timeout (node_ctxt : _ Node_context.t) self stakers = let open Lwt_result_syntax in let timeout_operation = - L1_operation.Timeout - { - rollup = node_ctxt.rollup_address; - stakers = Sc_rollup_proto_types.Game.index_to_octez stakers; - } + L1_operation.Timeout {rollup = node_ctxt.rollup_address; stakers} in let source = Node_context.get_operator node_ctxt Timeout |> Option.value ~default:self @@ -515,39 +224,16 @@ let play_timeout (node_ctxt : _ Node_context.t) self stakers = let* _hash = Injector.add_pending_operation ~source timeout_operation in return_unit -let timeout_reached ~self head_block node_ctxt staker1 staker2 = - let open Lwt_result_syntax in - let Node_context.{rollup_address; cctxt; _} = node_ctxt in - let* game_result = - Plugin.RPC.Sc_rollup.timeout_reached - (new Protocol_client_context.wrap_full cctxt) - (cctxt#chain, head_block) - (Sc_rollup_proto_types.Address.of_octez rollup_address) - staker1 - staker2 - in - let open Sc_rollup.Game in - match game_result with - | Some (Loser {loser; _}) -> - let is_it_me = Signature.Public_key_hash.(self = loser) in - if is_it_me then return_none else return (Some loser) - | _ -> return_none - let play node_ctxt ~self game opponent = let open Lwt_result_syntax in - let index = Sc_rollup.Game.Index.make self opponent in - let head_block = `Head 0 in + let index = make_index self opponent in match turn ~self game index with | Our_turn {opponent} -> play_next_move node_ctxt game self opponent - | Their_turn -> ( - let* timeout_reached = - timeout_reached ~self head_block node_ctxt self opponent - in - match timeout_reached with - | Some opponent -> - let*! () = Refutation_game_event.timeout_detected opponent in - play_timeout node_ctxt self index - | None -> return_unit) + | Their_turn -> + let* timeout_reached = timeout_reached node_ctxt ~self ~opponent in + when_ timeout_reached @@ fun () -> + let*! () = Refutation_game_event.timeout_detected opponent in + play_timeout node_ctxt self index let play_opening_move node_ctxt self (conflict : Octez_smart_rollup.Game.conflict) = diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game_helpers.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game_helpers.ml new file mode 100644 index 000000000000..2299dfa88d46 --- /dev/null +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game_helpers.ml @@ -0,0 +1,364 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** This function computes the inclusion/membership proof of the page + identified by [page_id] in the slot whose data are provided in + [slot_data]. *) +let page_membership_proof params page_index slot_data = + (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/4048 + Rely on DAL node to compute page membership proof and drop + the dal-crypto dependency from the rollup node. *) + let proof = + let open Result_syntax in + (* The computation of the page's proof below can be a bit costly. In fact, + it involves initialising a cryptobox environment and some non-trivial + crypto processing. *) + let* dal = Cryptobox.make params in + let* polynomial = Cryptobox.polynomial_from_slot dal slot_data in + Cryptobox.prove_page dal polynomial page_index + in + let open Lwt_result_syntax in + match proof with + | Ok proof -> return proof + | Error e -> + failwith + "%s" + (match e with + | `Fail s -> "Fail " ^ s + | `Page_index_out_of_range -> "Page_index_out_of_range" + | `Slot_wrong_size s -> "Slot_wrong_size: " ^ s + | `Invalid_degree_strictly_less_than_expected _ as commit_error -> + Cryptobox.string_of_commit_error commit_error) + +(** When the PVM is waiting for a Dal page input, this function attempts to + retrieve the page's content from the store, the data of its slot. Then it + computes the proof that the page is part of the slot and returns the + content along with the proof. + + If the PVM is not waiting for a Dal page input, or if the slot is known to + be unconfirmed on L1, this function returns [None]. If the data of the + slot are not saved to the store, the function returns a failure + in the error monad. *) +let page_info_from_pvm_state (node_ctxt : _ Node_context.t) ~dal_attestation_lag + (dal_params : Dal.parameters) start_state = + let open Lwt_result_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let*! input_request = PVM.is_input_state start_state in + match input_request with + | Sc_rollup.(Needs_reveal (Request_dal_page page_id)) -> ( + let Dal.Page.{slot_id; page_index} = page_id in + let* pages = + Dal_pages_request.slot_pages ~dal_attestation_lag node_ctxt slot_id + in + match pages with + | None -> return_none (* The slot is not confirmed. *) + | Some pages -> ( + let pages_per_slot = dal_params.slot_size / dal_params.page_size in + (* check invariant that pages' length is correct. *) + (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/4031 + It's better to do the check when the slots are saved into disk. *) + (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/3997 + This check is not resilient to dal parameters change. *) + match List.nth_opt pages page_index with + | Some content -> + let* page_proof = + page_membership_proof dal_params page_index + @@ Bytes.concat Bytes.empty pages + in + return_some (content, page_proof) + | None -> + failwith + "Page index %d too big or negative.\n\ + Number of pages in a slot is %d." + page_index + pages_per_slot)) + | _ -> return_none + +let metadata (node_ctxt : _ Node_context.t) = + let address = + Sc_rollup_proto_types.Address.of_octez node_ctxt.rollup_address + in + let origination_level = Raw_level.of_int32_exn node_ctxt.genesis_info.level in + Sc_rollup.Metadata.{address; origination_level} + +let generate_proof (node_ctxt : _ Node_context.t) + (game : Octez_smart_rollup.Game.t) start_state = + let open Lwt_result_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let snapshot = + Sc_rollup_proto_types.Inbox.history_proof_of_octez game.inbox_snapshot + in + (* NOTE: [snapshot_level_int32] below refers to the level of the snapshotted + inbox (from the skip list) which also matches [game.start_level - 1]. *) + let snapshot_level_int32 = + (Octez_smart_rollup.Inbox.Skip_list.content game.inbox_snapshot).level + in + let get_snapshot_head () = + let+ hash = Node_context.hash_of_level node_ctxt snapshot_level_int32 in + Layer1.{hash; level = snapshot_level_int32} + in + let* context = + let* start_hash = Node_context.hash_of_level node_ctxt game.inbox_level in + let+ context = Node_context.checkout_context node_ctxt start_hash in + Context.index context + in + let* dal_slots_history = + if Node_context.dal_supported node_ctxt then + let* snapshot_head = get_snapshot_head () in + Dal_slots_tracker.slots_history_of_hash node_ctxt snapshot_head + else return Dal.Slots_history.genesis + in + let* dal_slots_history_cache = + if Node_context.dal_supported node_ctxt then + let* snapshot_head = get_snapshot_head () in + Dal_slots_tracker.slots_history_cache_of_hash node_ctxt snapshot_head + else return (Dal.Slots_history.History_cache.empty ~capacity:0L) + in + (* We fetch the value of protocol constants at block snapshot level + where the game started. *) + let* parametric_constants = + let cctxt = node_ctxt.cctxt in + Protocol.Constants_services.parametric + (new Protocol_client_context.wrap_full cctxt) + (cctxt#chain, `Level snapshot_level_int32) + in + let dal_l1_parameters = parametric_constants.dal in + let dal_parameters = dal_l1_parameters.cryptobox_parameters in + let dal_attestation_lag = dal_l1_parameters.attestation_lag in + + let* page_info = + page_info_from_pvm_state + ~dal_attestation_lag + node_ctxt + dal_parameters + start_state + in + let module P = struct + include PVM + + let context = context + + let state = start_state + + let reveal hash = + let open Lwt_syntax in + let* res = + Reveals.get + ~data_dir:node_ctxt.data_dir + ~pvm_kind:(Sc_rollup_proto_types.Kind.to_octez PVM.kind) + ~hash + in + match res with Ok data -> return @@ Some data | Error _ -> return None + + module Inbox_with_history = struct + let inbox = snapshot + + let get_history inbox_hash = + let open Lwt_syntax in + let+ inbox = + Node_context.find_inbox + node_ctxt + (Sc_rollup_proto_types.Inbox_hash.to_octez inbox_hash) + in + match inbox with + | Error err -> + Format.kasprintf + Stdlib.failwith + "Refutation game: Cannot get inbox history for %a, %a" + Sc_rollup.Inbox.Hash.pp + inbox_hash + pp_print_trace + err + | Ok inbox -> + Option.map + (fun i -> + Sc_rollup.Inbox.take_snapshot + (Sc_rollup_proto_types.Inbox.of_octez i)) + inbox + + let get_payloads_history witness = + Lwt.map + (WithExceptions.Result.to_exn_f + ~error:(Format.kasprintf Stdlib.failwith "%a" pp_print_trace)) + @@ + let open Lwt_result_syntax in + let* {is_first_block; predecessor; predecessor_timestamp; messages} = + Node_context.get_messages + node_ctxt + (Sc_rollup_proto_types.Merkelized_payload_hashes_hash.to_octez + witness) + in + let*? hist = + Inbox.payloads_history_of_messages + ~is_first_block + ~predecessor + ~predecessor_timestamp + messages + in + return hist + end + + module Dal_with_history = struct + let confirmed_slots_history = dal_slots_history + + let get_history ptr = + Dal.Slots_history.History_cache.find ptr dal_slots_history_cache + |> Lwt.return + + let dal_attestation_lag = dal_attestation_lag + + let dal_parameters = dal_parameters + + let page_info = page_info + end + end in + let metadata = metadata node_ctxt in + let*! start_tick = PVM.get_tick start_state in + let* proof = + trace + (Sc_rollup_node_errors.Cannot_produce_proof + { + inbox_level = game.inbox_level; + start_tick = Sc_rollup.Tick.to_z start_tick; + }) + @@ (Sc_rollup.Proof.produce + ~metadata + (module P) + (Raw_level.of_int32_exn game.inbox_level) + >|= Environment.wrap_tzresult) + in + let*? pvm_step = + Sc_rollup.Proof.unserialize_pvm_step ~pvm:(module PVM) proof.pvm_step + |> Environment.wrap_tzresult + in + let unserialized_proof = {proof with pvm_step} in + let*! res = + Sc_rollup.Proof.valid + ~metadata + snapshot + (Raw_level.of_int32_exn game.inbox_level) + dal_slots_history + dal_parameters + ~dal_attestation_lag + ~pvm:(module PVM) + unserialized_proof + >|= Environment.wrap_tzresult + in + assert (Result.is_ok res) ; + let proof = + Data_encoding.Binary.to_string_exn Sc_rollup.Proof.encoding proof + in + return proof + +let state_of_tick node_ctxt ?start_state ~tick level = + Interpreter.state_of_tick + node_ctxt + ?start_state + ~tick + (Raw_level.of_int32_exn level) + +let make_dissection (node_ctxt : _ Node_context.t) ~start_state ~start_chunk + ~our_stop_chunk ~default_number_of_sections ~last_level = + let open Lwt_result_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let state_of_tick ?start_state tick = + state_of_tick + node_ctxt + ?start_state + ~tick:(Sc_rollup.Tick.to_z tick) + last_level + in + let state_hash_of_eval_state Pvm_plugin_sig.{state_hash; _} = + Sc_rollup_proto_types.State_hash.of_octez state_hash + in + let start_chunk = + Sc_rollup_proto_types.Game.dissection_chunk_of_octez start_chunk + in + let our_stop_chunk = + Sc_rollup_proto_types.Game.dissection_chunk_of_octez our_stop_chunk + in + let+ dissection = + Game_helpers.make_dissection + ~state_of_tick + ~state_hash_of_eval_state + ?start_state + ~start_chunk + ~our_stop_chunk + @@ PVM.new_dissection + ~start_chunk + ~our_stop_chunk + ~default_number_of_sections + in + List.map Sc_rollup_proto_types.Game.dissection_chunk_to_octez dissection + +let timeout_reached node_ctxt ~self ~opponent = + let open Lwt_result_syntax in + let Node_context.{rollup_address; cctxt; _} = node_ctxt in + let+ game_result = + Plugin.RPC.Sc_rollup.timeout_reached + (new Protocol_client_context.wrap_full cctxt) + (cctxt#chain, `Head 0) + (Sc_rollup_proto_types.Address.of_octez rollup_address) + self + opponent + in + let open Sc_rollup.Game in + match game_result with + | Some (Loser {loser; _}) -> + let is_it_me = Signature.Public_key_hash.(self = loser) in + not is_it_me + | _ -> false + +let get_conflicts cctxt rollup staker = + let open Lwt_result_syntax in + let cctxt = new Protocol_client_context.wrap_full cctxt in + let+ conflicts = + Plugin.RPC.Sc_rollup.conflicts + cctxt + (cctxt#chain, `Head 0) + (Sc_rollup_proto_types.Address.of_octez rollup) + staker + in + List.map Sc_rollup_proto_types.Game.conflict_to_octez conflicts + +let get_ongoing_games cctxt rollup staker = + let open Lwt_result_syntax in + let cctxt = new Protocol_client_context.wrap_full cctxt in + let+ games = + Plugin.RPC.Sc_rollup.ongoing_refutation_games + cctxt + (cctxt#chain, `Head 0) + (Sc_rollup_proto_types.Address.of_octez rollup) + staker + in + List.map + (fun (game, staker1, staker2) -> + (Sc_rollup_proto_types.Game.to_octez game, staker1, staker2)) + games diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game_helpers.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game_helpers.mli new file mode 100644 index 000000000000..8799f5deb3aa --- /dev/null +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game_helpers.mli @@ -0,0 +1,81 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [generate_proof node_ctxt (game) start_state] generates a serialized proof + for the current [game] for the execution step starting with + [start_state]. *) +val generate_proof : + Node_context.rw -> Game.t -> Context.tree -> string tzresult Lwt.t + +(** [state_of_tick node_ctxt ?start_state ~tick level] returns [Some + (state, hash)] for a given [tick] if this [tick] happened before + [level]. Otherwise, returns [None]. If provided, the evaluation is resumed + from [start_state]. *) +val state_of_tick : + _ Node_context.t -> + ?start_state:Fuel.Accounted.t Pvm_plugin_sig.eval_state -> + tick:Z.t -> + int32 -> + Fuel.Accounted.t Pvm_plugin_sig.eval_state option tzresult Lwt.t + +(** [make_dissection node_ctxt ~start_state ~start_chunk ~our_stop_chunk + ~default_number_of_sections ~last_level] computes a dissection from between + [start_chunk] and [our_stop_chunk] at level [last_level]. This dissection + has [default_number_of_sections] if there are enough ticks. *) +val make_dissection : + _ Node_context.t -> + start_state:Fuel.Accounted.t Pvm_plugin_sig.eval_state option -> + start_chunk:Game.dissection_chunk -> + our_stop_chunk:Game.dissection_chunk -> + default_number_of_sections:int -> + last_level:int32 -> + Game.dissection_chunk trace tzresult Lwt.t + +(** [timeout_reached node_ctxt ~self ~opponent] returns [true] if the + timeout is reached against opponent in head of the L1 chain. *) +val timeout_reached : + _ Node_context.t -> + self:Signature.public_key_hash -> + opponent:Signature.public_key_hash -> + bool tzresult Lwt.t + +(** [get_conflicts cctxt rollup signer] returns the conflicts for commitments + staked on by [signer]. *) +val get_conflicts : + Client_context.full -> + Address.t -> + Signature.public_key_hash -> + Game.conflict list tzresult Lwt.t + +(** [get_ongoing_games cctxt rollup signer] returns the games that [signer] is + currently playing. *) +val get_ongoing_games : + Client_context.full -> + Address.t -> + Signature.public_key_hash -> + (Game.t * Signature.public_key_hash * Signature.public_key_hash) list tzresult + Lwt.t -- GitLab From 13c36858303f4264f333d48db200e3d42711da7f Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 29 Jun 2023 21:57:54 +0200 Subject: [PATCH 16/17] SCORU/Node/Mumbai: extract refutation game helpers Remove protocol dependency from Refutation_game module. --- .../lib_sc_rollup_node/refutation_game.ml | 363 ++--------------- .../refutation_game_helpers.ml | 364 ++++++++++++++++++ .../refutation_game_helpers.mli | 81 ++++ 3 files changed, 470 insertions(+), 338 deletions(-) create mode 100644 src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game_helpers.ml create mode 100644 src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game_helpers.mli diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.ml index 7a1639c7ebd1..0ebfd48eab6c 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.ml @@ -42,21 +42,19 @@ starts a game to refute C' by starting a game with one of its staker. *) -open Protocol -open Alpha_context -open Sc_rollup.Game +open Game +open Refutation_game_helpers -let node_role ~self Sc_rollup.Game.Index.{alice; bob} = - if Sc_rollup.Staker.equal alice self then Alice - else if Sc_rollup.Staker.equal bob self then Bob +let node_role ~self {alice; bob} = + if Signature.Public_key_hash.equal alice self then Alice + else if Signature.Public_key_hash.equal bob self then Bob else (* By validity of [ongoing_game] RPC. *) assert false -type role = Our_turn of {opponent : public_key_hash} | Their_turn +type role = Our_turn of {opponent : Signature.public_key_hash} | Their_turn -let turn ~self (game : Octez_smart_rollup.Game.t) players = - let Sc_rollup.Game.Index.{alice; bob} = players in +let turn ~self game ({alice; bob} as players) = match (node_role ~self players, game.turn) with | Alice, Alice -> Our_turn {opponent = bob} | Bob, Bob -> Our_turn {opponent = alice} @@ -75,310 +73,33 @@ let inject_next_move node_ctxt source ~refutation ~opponent = let* _hash = Injector.add_pending_operation ~source refute_operation in return_unit -(** This function computes the inclusion/membership proof of the page - identified by [page_id] in the slot whose data are provided in - [slot_data]. *) -let page_membership_proof params page_index slot_data = - (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/4048 - Rely on DAL node to compute page membership proof and drop - the dal-crypto dependency from the rollup node. *) - let proof = - let open Result_syntax in - (* The computation of the page's proof below can be a bit costly. In fact, - it involves initialising a cryptobox environment and some non-trivial - crypto processing. *) - let* dal = Cryptobox.make params in - let* polynomial = Cryptobox.polynomial_from_slot dal slot_data in - Cryptobox.prove_page dal polynomial page_index - in - let open Lwt_result_syntax in - match proof with - | Ok proof -> return proof - | Error e -> - failwith - "%s" - (match e with - | `Fail s -> "Fail " ^ s - | `Page_index_out_of_range -> "Page_index_out_of_range" - | `Slot_wrong_size s -> "Slot_wrong_size: " ^ s - | `Invalid_degree_strictly_less_than_expected _ as commit_error -> - Cryptobox.string_of_commit_error commit_error) - -(** When the PVM is waiting for a Dal page input, this function attempts to - retrieve the page's content from the store, the data of its slot. Then it - computes the proof that the page is part of the slot and returns the content - along with the proof. - - If the PVM is not waiting for a Dal page input, or if the slot is known to - be unconfirmed on L1, this function returns [None]. If the data of the slot - are not saved to the store, the function returns a failure in the error - monad. *) -let page_info_from_pvm_state (node_ctxt : _ Node_context.t) ~dal_attestation_lag - (dal_params : Dal.parameters) start_state = - let open Lwt_result_syntax in - let module PVM = (val Pvm.of_kind node_ctxt.kind) in - let*! input_request = PVM.is_input_state start_state in - match input_request with - | Sc_rollup.(Needs_reveal (Request_dal_page page_id)) -> ( - let Dal.Page.{slot_id; page_index} = page_id in - let* pages = - Dal_pages_request.slot_pages ~dal_attestation_lag node_ctxt slot_id - in - match pages with - | None -> return_none (* The slot is not confirmed. *) - | Some pages -> ( - let pages_per_slot = dal_params.slot_size / dal_params.page_size in - (* check invariant that pages' length is correct. *) - (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/4031 - It's better to do the check when the slots are saved into disk. *) - (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/3997 - This check is not resilient to dal parameters change. *) - match List.nth_opt pages page_index with - | Some content -> - let* page_proof = - page_membership_proof dal_params page_index - @@ Bytes.concat Bytes.empty pages - in - return_some (content, page_proof) - | None -> - failwith - "Page index %d too big or negative.\n\ - Number of pages in a slot is %d." - page_index - pages_per_slot)) - | _ -> return_none - -let metadata (node_ctxt : _ Node_context.t) = - let address = - Sc_rollup_proto_types.Address.of_octez node_ctxt.rollup_address - in - let origination_level = Raw_level.of_int32_exn node_ctxt.genesis_info.level in - Sc_rollup.Metadata.{address; origination_level} - -let generate_proof (node_ctxt : _ Node_context.t) - (game : Octez_smart_rollup.Game.t) start_state = - let open Lwt_result_syntax in - let module PVM = (val Pvm.of_kind node_ctxt.kind) in - let snapshot = - Sc_rollup_proto_types.Inbox.history_proof_of_octez game.inbox_snapshot - in - (* NOTE: [snapshot_level_int32] below refers to the level of the snapshotted - inbox (from the skip list) which also matches [game.start_level - 1]. *) - let snapshot_level_int32 = - (Octez_smart_rollup.Inbox.Skip_list.content game.inbox_snapshot).level - in - let get_snapshot_head () = - let+ hash = Node_context.hash_of_level node_ctxt snapshot_level_int32 in - Layer1.{hash; level = snapshot_level_int32} - in - let* context = - let* start_hash = Node_context.hash_of_level node_ctxt game.inbox_level in - let+ context = Node_context.checkout_context node_ctxt start_hash in - Context.index context - in - let* dal_slots_history = - if Node_context.dal_supported node_ctxt then - let* snapshot_head = get_snapshot_head () in - Dal_slots_tracker.slots_history_of_hash node_ctxt snapshot_head - else return Dal.Slots_history.genesis - in - let* dal_slots_history_cache = - if Node_context.dal_supported node_ctxt then - let* snapshot_head = get_snapshot_head () in - Dal_slots_tracker.slots_history_cache_of_hash node_ctxt snapshot_head - else return (Dal.Slots_history.History_cache.empty ~capacity:0L) - in - (* We fetch the value of protocol constants at block snapshot level - where the game started. *) - let* parametric_constants = - let cctxt = node_ctxt.cctxt in - Protocol.Constants_services.parametric - (new Protocol_client_context.wrap_full cctxt) - (cctxt#chain, `Level snapshot_level_int32) - in - let dal_l1_parameters = parametric_constants.dal in - let dal_parameters = dal_l1_parameters.cryptobox_parameters in - let dal_attestation_lag = dal_l1_parameters.attestation_lag in - - let* page_info = - page_info_from_pvm_state - ~dal_attestation_lag - node_ctxt - dal_parameters - start_state - in - let module P = struct - include PVM - - let context = context - - let state = start_state - - let reveal hash = - let open Lwt_syntax in - let* res = - Reveals.get - ~data_dir:node_ctxt.data_dir - ~pvm_kind:(Sc_rollup_proto_types.Kind.to_octez PVM.kind) - ~hash - in - match res with Ok data -> return @@ Some data | Error _ -> return None - - module Inbox_with_history = struct - let inbox = snapshot - - let get_history inbox_hash = - let open Lwt_syntax in - let+ inbox = - Node_context.find_inbox - node_ctxt - (Sc_rollup_proto_types.Inbox_hash.to_octez inbox_hash) - in - match inbox with - | Error err -> - Format.kasprintf - Stdlib.failwith - "Refutation game: Cannot get inbox history for %a, %a" - Sc_rollup.Inbox.Hash.pp - inbox_hash - pp_print_trace - err - | Ok inbox -> - Option.map - (fun i -> - Sc_rollup.Inbox.take_snapshot - (Sc_rollup_proto_types.Inbox.of_octez i)) - inbox - - let get_payloads_history witness = - Lwt.map - (WithExceptions.Result.to_exn_f - ~error:(Format.kasprintf Stdlib.failwith "%a" pp_print_trace)) - @@ - let open Lwt_result_syntax in - let* {predecessor; predecessor_timestamp; messages; _} = - Node_context.get_messages - node_ctxt - (Sc_rollup_proto_types.Merkelized_payload_hashes_hash.to_octez - witness) - in - let*? hist = - Inbox.payloads_history_of_messages - ~predecessor - ~predecessor_timestamp - messages - in - return hist - end - - module Dal_with_history = struct - let confirmed_slots_history = dal_slots_history - - let get_history ptr = - Dal.Slots_history.History_cache.find ptr dal_slots_history_cache - |> Lwt.return - - let dal_attestation_lag = dal_attestation_lag - - let dal_parameters = dal_parameters - - let page_info = page_info - end - end in - let metadata = metadata node_ctxt in - let*! start_tick = PVM.get_tick start_state in - let* proof = - trace - (Sc_rollup_node_errors.Cannot_produce_proof - { - inbox_level = game.inbox_level; - start_tick = Sc_rollup.Tick.to_z start_tick; - }) - @@ (Sc_rollup.Proof.produce - ~metadata - (module P) - (Raw_level.of_int32_exn game.inbox_level) - >|= Environment.wrap_tzresult) - in - let*? pvm_step = - Sc_rollup.Proof.unserialize_pvm_step ~pvm:(module PVM) proof.pvm_step - |> Environment.wrap_tzresult - in - let unserialized_proof = {proof with pvm_step} in - let*! res = - Sc_rollup.Proof.valid - ~metadata - snapshot - (Raw_level.of_int32_exn game.inbox_level) - dal_slots_history - dal_parameters - ~dal_attestation_lag - ~pvm:(module PVM) - unserialized_proof - >|= Environment.wrap_tzresult - in - assert (Result.is_ok res) ; - let proof = - Data_encoding.Binary.to_string_exn Sc_rollup.Proof.encoding proof - in - return proof - type pvm_intermediate_state = - | Hash of Octez_smart_rollup.State_hash.t + | Hash of State_hash.t | Evaluated of Fuel.Accounted.t Pvm_plugin_sig.eval_state let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok our_view = let open Lwt_result_syntax in - let state_of_tick ?start_state tick = - Interpreter.state_of_tick - node_ctxt - ?start_state - ~tick:(Sc_rollup.Tick.to_z tick) - (Raw_level.of_int32_exn last_level) - in - let state_hash_of_eval_state Pvm_plugin_sig.{state_hash; _} = - Sc_rollup_proto_types.State_hash.of_octez state_hash - in let start_hash, start_tick, start_state = match ok with | Hash hash, tick -> (hash, tick, None) | Evaluated ({state_hash; _} as state), tick -> (state_hash, tick, Some state) in - let start_chunk = - Sc_rollup.Dissection_chunk. - { - state_hash = Some (Sc_rollup_proto_types.State_hash.of_octez start_hash); - tick = Sc_rollup.Tick.of_z start_tick; - } - in + let start_chunk = Game.{state_hash = Some start_hash; tick = start_tick} in let our_state, our_tick = our_view in let our_state_hash = - Option.map - (fun Pvm_plugin_sig.{state_hash; _} -> - Sc_rollup_proto_types.State_hash.of_octez state_hash) - our_state - in - let our_stop_chunk = - Sc_rollup.Dissection_chunk. - {state_hash = our_state_hash; tick = Sc_rollup.Tick.of_z our_tick} + Option.map (fun Pvm_plugin_sig.{state_hash; _} -> state_hash) our_state in - let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let our_stop_chunk = Game.{state_hash = our_state_hash; tick = our_tick} in let* dissection = - Game_helpers.make_dissection - ~state_of_tick - ~state_hash_of_eval_state - ?start_state + make_dissection + node_ctxt + ~start_state ~start_chunk ~our_stop_chunk - @@ PVM.new_dissection - ~start_chunk - ~our_stop_chunk - ~default_number_of_sections - in - let dissection = - List.map Sc_rollup_proto_types.Game.dissection_chunk_to_octez dissection + ~default_number_of_sections + ~last_level in let*! () = Refutation_game_event.computed_dissection @@ -413,11 +134,7 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent | Evaluated ok_state, _ -> Some ok_state in let* our = - Interpreter.state_of_tick - node_ctxt - ?start_state - ~tick - (Raw_level.of_int32_exn game.inbox_level) + state_of_tick node_ctxt ?start_state ~tick game.inbox_level in match (their_hash, our) with | None, None -> @@ -459,10 +176,7 @@ let next_move node_ctxt ~opponent (game : Octez_smart_rollup.Game.t) = let open Lwt_result_syntax in let final_move start_tick = let* start_state = - Interpreter.state_of_tick - node_ctxt - ~tick:start_tick - (Raw_level.of_int32_exn game.inbox_level) + state_of_tick node_ctxt ~tick:start_tick game.inbox_level in match start_state with | None -> @@ -501,11 +215,7 @@ let play_next_move node_ctxt game self opponent = let play_timeout (node_ctxt : _ Node_context.t) self stakers = let open Lwt_result_syntax in let timeout_operation = - L1_operation.Timeout - { - rollup = node_ctxt.rollup_address; - stakers = Sc_rollup_proto_types.Game.index_to_octez stakers; - } + L1_operation.Timeout {rollup = node_ctxt.rollup_address; stakers} in let source = Node_context.get_operator node_ctxt Timeout |> Option.value ~default:self @@ -514,39 +224,16 @@ let play_timeout (node_ctxt : _ Node_context.t) self stakers = let* _hash = Injector.add_pending_operation ~source timeout_operation in return_unit -let timeout_reached ~self head_block node_ctxt staker1 staker2 = - let open Lwt_result_syntax in - let Node_context.{rollup_address; cctxt; _} = node_ctxt in - let* game_result = - Plugin.RPC.Sc_rollup.timeout_reached - (new Protocol_client_context.wrap_full cctxt) - (cctxt#chain, head_block) - (Sc_rollup_proto_types.Address.of_octez rollup_address) - staker1 - staker2 - in - let open Sc_rollup.Game in - match game_result with - | Some (Loser {loser; _}) -> - let is_it_me = Signature.Public_key_hash.(self = loser) in - if is_it_me then return_none else return (Some loser) - | _ -> return_none - let play node_ctxt ~self game opponent = let open Lwt_result_syntax in - let index = Sc_rollup.Game.Index.make self opponent in - let head_block = `Head 0 in + let index = make_index self opponent in match turn ~self game index with | Our_turn {opponent} -> play_next_move node_ctxt game self opponent - | Their_turn -> ( - let* timeout_reached = - timeout_reached ~self head_block node_ctxt self opponent - in - match timeout_reached with - | Some opponent -> - let*! () = Refutation_game_event.timeout_detected opponent in - play_timeout node_ctxt self index - | None -> return_unit) + | Their_turn -> + let* timeout_reached = timeout_reached node_ctxt ~self ~opponent in + when_ timeout_reached @@ fun () -> + let*! () = Refutation_game_event.timeout_detected opponent in + play_timeout node_ctxt self index let play_opening_move node_ctxt self (conflict : Octez_smart_rollup.Game.conflict) = diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game_helpers.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game_helpers.ml new file mode 100644 index 000000000000..0b9cc943bd16 --- /dev/null +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game_helpers.ml @@ -0,0 +1,364 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +(** This function computes the inclusion/membership proof of the page + identified by [page_id] in the slot whose data are provided in + [slot_data]. *) +let page_membership_proof params page_index slot_data = + (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/4048 + Rely on DAL node to compute page membership proof and drop + the dal-crypto dependency from the rollup node. *) + let proof = + let open Result_syntax in + (* The computation of the page's proof below can be a bit costly. In fact, + it involves initialising a cryptobox environment and some non-trivial + crypto processing. *) + let* dal = Cryptobox.make params in + let* polynomial = Cryptobox.polynomial_from_slot dal slot_data in + Cryptobox.prove_page dal polynomial page_index + in + let open Lwt_result_syntax in + match proof with + | Ok proof -> return proof + | Error e -> + failwith + "%s" + (match e with + | `Fail s -> "Fail " ^ s + | `Page_index_out_of_range -> "Page_index_out_of_range" + | `Slot_wrong_size s -> "Slot_wrong_size: " ^ s + | `Invalid_degree_strictly_less_than_expected _ as commit_error -> + Cryptobox.string_of_commit_error commit_error) + +(** When the PVM is waiting for a Dal page input, this function attempts to + retrieve the page's content from the store, the data of its slot. Then it + computes the proof that the page is part of the slot and returns the + content along with the proof. + + If the PVM is not waiting for a Dal page input, or if the slot is known to + be unconfirmed on L1, this function returns [None]. If the data of the + slot are not saved to the store, the function returns a failure + in the error monad. *) +let page_info_from_pvm_state (node_ctxt : _ Node_context.t) ~dal_attestation_lag + (dal_params : Dal.parameters) start_state = + let open Lwt_result_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let*! input_request = PVM.is_input_state start_state in + match input_request with + | Sc_rollup.(Needs_reveal (Request_dal_page page_id)) -> ( + let Dal.Page.{slot_id; page_index} = page_id in + let* pages = + Dal_pages_request.slot_pages ~dal_attestation_lag node_ctxt slot_id + in + match pages with + | None -> return_none (* The slot is not confirmed. *) + | Some pages -> ( + let pages_per_slot = dal_params.slot_size / dal_params.page_size in + (* check invariant that pages' length is correct. *) + (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/4031 + It's better to do the check when the slots are saved into disk. *) + (* FIXME/DAL: https://gitlab.com/tezos/tezos/-/issues/3997 + This check is not resilient to dal parameters change. *) + match List.nth_opt pages page_index with + | Some content -> + let* page_proof = + page_membership_proof dal_params page_index + @@ Bytes.concat Bytes.empty pages + in + return_some (content, page_proof) + | None -> + failwith + "Page index %d too big or negative.\n\ + Number of pages in a slot is %d." + page_index + pages_per_slot)) + | _ -> return_none + +let metadata (node_ctxt : _ Node_context.t) = + let address = + Sc_rollup_proto_types.Address.of_octez node_ctxt.rollup_address + in + let origination_level = Raw_level.of_int32_exn node_ctxt.genesis_info.level in + Sc_rollup.Metadata.{address; origination_level} + +let generate_proof (node_ctxt : _ Node_context.t) + (game : Octez_smart_rollup.Game.t) start_state = + let open Lwt_result_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let snapshot = + Sc_rollup_proto_types.Inbox.history_proof_of_octez game.inbox_snapshot + in + (* NOTE: [snapshot_level_int32] below refers to the level of the snapshotted + inbox (from the skip list) which also matches [game.start_level - 1]. *) + let snapshot_level_int32 = + (Octez_smart_rollup.Inbox.Skip_list.content game.inbox_snapshot).level + in + let get_snapshot_head () = + let+ hash = Node_context.hash_of_level node_ctxt snapshot_level_int32 in + Layer1.{hash; level = snapshot_level_int32} + in + let* context = + let* start_hash = Node_context.hash_of_level node_ctxt game.inbox_level in + let+ context = Node_context.checkout_context node_ctxt start_hash in + Context.index context + in + let* dal_slots_history = + if Node_context.dal_supported node_ctxt then + let* snapshot_head = get_snapshot_head () in + Dal_slots_tracker.slots_history_of_hash node_ctxt snapshot_head + else return Dal.Slots_history.genesis + in + let* dal_slots_history_cache = + if Node_context.dal_supported node_ctxt then + let* snapshot_head = get_snapshot_head () in + Dal_slots_tracker.slots_history_cache_of_hash node_ctxt snapshot_head + else return (Dal.Slots_history.History_cache.empty ~capacity:0L) + in + (* We fetch the value of protocol constants at block snapshot level + where the game started. *) + let* parametric_constants = + let cctxt = node_ctxt.cctxt in + Protocol.Constants_services.parametric + (new Protocol_client_context.wrap_full cctxt) + (cctxt#chain, `Level snapshot_level_int32) + in + let dal_l1_parameters = parametric_constants.dal in + let dal_parameters = dal_l1_parameters.cryptobox_parameters in + let dal_attestation_lag = dal_l1_parameters.attestation_lag in + + let* page_info = + page_info_from_pvm_state + ~dal_attestation_lag + node_ctxt + dal_parameters + start_state + in + let module P = struct + include PVM + + let context = context + + let state = start_state + + let reveal hash = + let open Lwt_syntax in + let* res = + Reveals.get + ~data_dir:node_ctxt.data_dir + ~pvm_kind:(Sc_rollup_proto_types.Kind.to_octez PVM.kind) + ~hash + in + match res with Ok data -> return @@ Some data | Error _ -> return None + + module Inbox_with_history = struct + let inbox = snapshot + + let get_history inbox_hash = + let open Lwt_syntax in + let+ inbox = + Node_context.find_inbox + node_ctxt + (Sc_rollup_proto_types.Inbox_hash.to_octez inbox_hash) + in + match inbox with + | Error err -> + Format.kasprintf + Stdlib.failwith + "Refutation game: Cannot get inbox history for %a, %a" + Sc_rollup.Inbox.Hash.pp + inbox_hash + pp_print_trace + err + | Ok inbox -> + Option.map + (fun i -> + Sc_rollup.Inbox.take_snapshot + (Sc_rollup_proto_types.Inbox.of_octez i)) + inbox + + let get_payloads_history witness = + Lwt.map + (WithExceptions.Result.to_exn_f + ~error:(Format.kasprintf Stdlib.failwith "%a" pp_print_trace)) + @@ + let open Lwt_result_syntax in + let* {is_first_block = _; predecessor; predecessor_timestamp; messages} + = + Node_context.get_messages + node_ctxt + (Sc_rollup_proto_types.Merkelized_payload_hashes_hash.to_octez + witness) + in + let*? hist = + Inbox.payloads_history_of_messages + ~predecessor + ~predecessor_timestamp + messages + in + return hist + end + + module Dal_with_history = struct + let confirmed_slots_history = dal_slots_history + + let get_history ptr = + Dal.Slots_history.History_cache.find ptr dal_slots_history_cache + |> Lwt.return + + let dal_attestation_lag = dal_attestation_lag + + let dal_parameters = dal_parameters + + let page_info = page_info + end + end in + let metadata = metadata node_ctxt in + let*! start_tick = PVM.get_tick start_state in + let* proof = + trace + (Sc_rollup_node_errors.Cannot_produce_proof + { + inbox_level = game.inbox_level; + start_tick = Sc_rollup.Tick.to_z start_tick; + }) + @@ (Sc_rollup.Proof.produce + ~metadata + (module P) + (Raw_level.of_int32_exn game.inbox_level) + >|= Environment.wrap_tzresult) + in + let*? pvm_step = + Sc_rollup.Proof.unserialize_pvm_step ~pvm:(module PVM) proof.pvm_step + |> Environment.wrap_tzresult + in + let unserialized_proof = {proof with pvm_step} in + let*! res = + Sc_rollup.Proof.valid + ~metadata + snapshot + (Raw_level.of_int32_exn game.inbox_level) + dal_slots_history + dal_parameters + ~dal_attestation_lag + ~pvm:(module PVM) + unserialized_proof + >|= Environment.wrap_tzresult + in + assert (Result.is_ok res) ; + let proof = + Data_encoding.Binary.to_string_exn Sc_rollup.Proof.encoding proof + in + return proof + +let state_of_tick node_ctxt ?start_state ~tick level = + Interpreter.state_of_tick + node_ctxt + ?start_state + ~tick + (Raw_level.of_int32_exn level) + +let make_dissection (node_ctxt : _ Node_context.t) ~start_state ~start_chunk + ~our_stop_chunk ~default_number_of_sections ~last_level = + let open Lwt_result_syntax in + let module PVM = (val Pvm.of_kind node_ctxt.kind) in + let state_of_tick ?start_state tick = + state_of_tick + node_ctxt + ?start_state + ~tick:(Sc_rollup.Tick.to_z tick) + last_level + in + let state_hash_of_eval_state Pvm_plugin_sig.{state_hash; _} = + Sc_rollup_proto_types.State_hash.of_octez state_hash + in + let start_chunk = + Sc_rollup_proto_types.Game.dissection_chunk_of_octez start_chunk + in + let our_stop_chunk = + Sc_rollup_proto_types.Game.dissection_chunk_of_octez our_stop_chunk + in + let+ dissection = + Game_helpers.make_dissection + ~state_of_tick + ~state_hash_of_eval_state + ?start_state + ~start_chunk + ~our_stop_chunk + @@ PVM.new_dissection + ~start_chunk + ~our_stop_chunk + ~default_number_of_sections + in + List.map Sc_rollup_proto_types.Game.dissection_chunk_to_octez dissection + +let timeout_reached node_ctxt ~self ~opponent = + let open Lwt_result_syntax in + let Node_context.{rollup_address; cctxt; _} = node_ctxt in + let+ game_result = + Plugin.RPC.Sc_rollup.timeout_reached + (new Protocol_client_context.wrap_full cctxt) + (cctxt#chain, `Head 0) + (Sc_rollup_proto_types.Address.of_octez rollup_address) + self + opponent + in + let open Sc_rollup.Game in + match game_result with + | Some (Loser {loser; _}) -> + let is_it_me = Signature.Public_key_hash.(self = loser) in + not is_it_me + | _ -> false + +let get_conflicts cctxt rollup staker = + let open Lwt_result_syntax in + let cctxt = new Protocol_client_context.wrap_full cctxt in + let+ conflicts = + Plugin.RPC.Sc_rollup.conflicts + cctxt + (cctxt#chain, `Head 0) + (Sc_rollup_proto_types.Address.of_octez rollup) + staker + in + List.map Sc_rollup_proto_types.Game.conflict_to_octez conflicts + +let get_ongoing_games cctxt rollup staker = + let open Lwt_result_syntax in + let cctxt = new Protocol_client_context.wrap_full cctxt in + let+ games = + Plugin.RPC.Sc_rollup.ongoing_refutation_games + cctxt + (cctxt#chain, `Head 0) + (Sc_rollup_proto_types.Address.of_octez rollup) + staker + in + List.map + (fun (game, staker1, staker2) -> + (Sc_rollup_proto_types.Game.to_octez game, staker1, staker2)) + games diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game_helpers.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game_helpers.mli new file mode 100644 index 000000000000..8799f5deb3aa --- /dev/null +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game_helpers.mli @@ -0,0 +1,81 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** [generate_proof node_ctxt (game) start_state] generates a serialized proof + for the current [game] for the execution step starting with + [start_state]. *) +val generate_proof : + Node_context.rw -> Game.t -> Context.tree -> string tzresult Lwt.t + +(** [state_of_tick node_ctxt ?start_state ~tick level] returns [Some + (state, hash)] for a given [tick] if this [tick] happened before + [level]. Otherwise, returns [None]. If provided, the evaluation is resumed + from [start_state]. *) +val state_of_tick : + _ Node_context.t -> + ?start_state:Fuel.Accounted.t Pvm_plugin_sig.eval_state -> + tick:Z.t -> + int32 -> + Fuel.Accounted.t Pvm_plugin_sig.eval_state option tzresult Lwt.t + +(** [make_dissection node_ctxt ~start_state ~start_chunk ~our_stop_chunk + ~default_number_of_sections ~last_level] computes a dissection from between + [start_chunk] and [our_stop_chunk] at level [last_level]. This dissection + has [default_number_of_sections] if there are enough ticks. *) +val make_dissection : + _ Node_context.t -> + start_state:Fuel.Accounted.t Pvm_plugin_sig.eval_state option -> + start_chunk:Game.dissection_chunk -> + our_stop_chunk:Game.dissection_chunk -> + default_number_of_sections:int -> + last_level:int32 -> + Game.dissection_chunk trace tzresult Lwt.t + +(** [timeout_reached node_ctxt ~self ~opponent] returns [true] if the + timeout is reached against opponent in head of the L1 chain. *) +val timeout_reached : + _ Node_context.t -> + self:Signature.public_key_hash -> + opponent:Signature.public_key_hash -> + bool tzresult Lwt.t + +(** [get_conflicts cctxt rollup signer] returns the conflicts for commitments + staked on by [signer]. *) +val get_conflicts : + Client_context.full -> + Address.t -> + Signature.public_key_hash -> + Game.conflict list tzresult Lwt.t + +(** [get_ongoing_games cctxt rollup signer] returns the games that [signer] is + currently playing. *) +val get_ongoing_games : + Client_context.full -> + Address.t -> + Signature.public_key_hash -> + (Game.t * Signature.public_key_hash * Signature.public_key_hash) list tzresult + Lwt.t -- GitLab From abade65c16d5ee961cdbd48e21d44b739975cc4c Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Thu, 29 Jun 2023 23:19:49 +0200 Subject: [PATCH 17/17] SCORU/Node: Move refutation modules outside of proto directories --- .../protocol_plugin_sig.ml | 79 ++++-- .../refutation_coordinator.ml | 63 ++--- .../refutation_coordinator.mli | 9 +- .../refutation_game.ml | 53 ++-- .../refutation_game.mli | 4 +- .../refutation_game_event.ml | 20 +- .../refutation_player.ml | 9 +- .../refutation_player.mli | 0 .../rollup_node_daemon.ml | 27 +- .../refutation_coordinator.ml | 257 ----------------- .../refutation_coordinator.mli | 47 ---- .../lib_sc_rollup_node/refutation_game.ml | 252 ----------------- .../lib_sc_rollup_node/refutation_game.mli | 43 --- .../refutation_game_event.ml | 261 ------------------ .../lib_sc_rollup_node/refutation_player.ml | 178 ------------ .../lib_sc_rollup_node/rollup_node_plugin.ml | 2 +- .../refutation_coordinator.ml | 257 ----------------- .../lib_sc_rollup_node/refutation_game.ml | 252 ----------------- .../lib_sc_rollup_node/refutation_game.mli | 43 --- .../lib_sc_rollup_node/refutation_player.ml | 178 ------------ .../lib_sc_rollup_node/refutation_player.mli | 56 ---- .../lib_sc_rollup_node/rollup_node_plugin.ml | 2 +- .../lib_sc_rollup_node/daemon_helpers.ml | 2 +- .../refutation_coordinator.mli | 47 ---- .../refutation_game_event.ml | 261 ------------------ .../lib_sc_rollup_node/refutation_player.ml | 178 ------------ .../lib_sc_rollup_node/refutation_player.mli | 56 ---- .../lib_sc_rollup_node/rollup_node_plugin.ml | 2 +- .../lib_sc_rollup_node/daemon_helpers.ml | 2 +- .../refutation_coordinator.ml | 253 ----------------- .../refutation_coordinator.mli | 47 ---- .../lib_sc_rollup_node/refutation_game.ml | 252 ----------------- .../lib_sc_rollup_node/refutation_game.mli | 43 --- .../refutation_game_event.ml | 261 ------------------ .../lib_sc_rollup_node/refutation_player.mli | 56 ---- .../lib_sc_rollup_node/rollup_node_plugin.ml | 2 +- 36 files changed, 144 insertions(+), 3410 deletions(-) rename src/{proto_018_Proxford/lib_sc_rollup_node => lib_smart_rollup_node}/refutation_coordinator.ml (83%) rename src/{proto_017_PtNairob/lib_sc_rollup_node => lib_smart_rollup_node}/refutation_coordinator.mli (92%) rename src/{proto_018_Proxford/lib_sc_rollup_node => lib_smart_rollup_node}/refutation_game.ml (85%) rename src/{proto_018_Proxford/lib_sc_rollup_node => lib_smart_rollup_node}/refutation_game.mli (94%) rename src/{proto_017_PtNairob/lib_sc_rollup_node => lib_smart_rollup_node}/refutation_game_event.ml (93%) rename src/{proto_alpha/lib_sc_rollup_node => lib_smart_rollup_node}/refutation_player.ml (96%) rename src/{proto_016_PtMumbai/lib_sc_rollup_node => lib_smart_rollup_node}/refutation_player.mli (100%) delete mode 100644 src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_coordinator.ml delete mode 100644 src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_coordinator.mli delete mode 100644 src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.ml delete mode 100644 src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.mli delete mode 100644 src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game_event.ml delete mode 100644 src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player.ml delete mode 100644 src/proto_017_PtNairob/lib_sc_rollup_node/refutation_coordinator.ml delete mode 100644 src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.ml delete mode 100644 src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.mli delete mode 100644 src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player.ml delete mode 100644 src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player.mli delete mode 100644 src/proto_018_Proxford/lib_sc_rollup_node/refutation_coordinator.mli delete mode 100644 src/proto_018_Proxford/lib_sc_rollup_node/refutation_game_event.ml delete mode 100644 src/proto_018_Proxford/lib_sc_rollup_node/refutation_player.ml delete mode 100644 src/proto_018_Proxford/lib_sc_rollup_node/refutation_player.mli delete mode 100644 src/proto_alpha/lib_sc_rollup_node/refutation_coordinator.ml delete mode 100644 src/proto_alpha/lib_sc_rollup_node/refutation_coordinator.mli delete mode 100644 src/proto_alpha/lib_sc_rollup_node/refutation_game.ml delete mode 100644 src/proto_alpha/lib_sc_rollup_node/refutation_game.mli delete mode 100644 src/proto_alpha/lib_sc_rollup_node/refutation_game_event.ml delete mode 100644 src/proto_alpha/lib_sc_rollup_node/refutation_player.mli diff --git a/src/lib_smart_rollup_node/protocol_plugin_sig.ml b/src/lib_smart_rollup_node/protocol_plugin_sig.ml index 46c78dd7fdf2..48044883eac5 100644 --- a/src/lib_smart_rollup_node/protocol_plugin_sig.ml +++ b/src/lib_smart_rollup_node/protocol_plugin_sig.ml @@ -131,26 +131,63 @@ module type INTERPRETER = sig ('a Context.t * Context.tree) tzresult Lwt.t end -(** Protocol specific refutation coordinator. NOTE: The refutation coordinator - has to be stopped and the new one restarted on protocol change. *) -module type REFUTATION_COORDINATOR = sig - (** [init node_ctxt] initializes the refutation coordinator worker. *) - val init : Node_context.rw -> unit tzresult Lwt.t - - (** [process head] processes a new l1 head. This means that the coordinator - will: - {ol - {li Gather all existing conflicts} - {li Launch new refutation players for each conflict concerning - the operator that doesn't have a player in this node} - {li Kill all players whose conflict has disappeared from L1} - {li Make all players play a step in the refutation} - } - *) - val process : Layer1.head -> unit tzresult Lwt.t - - (** [shutdown ()] stops the refutation coordinator. *) - val shutdown : unit -> unit Lwt.t +(** Protocol specific refutation helper functions. *) +module type REFUTATION_GAME_HELPERS = sig + (** [generate_proof node_ctxt (game) start_state] generates a serialized proof + for the current [game] for the execution step starting with + [start_state]. *) + val generate_proof : + Node_context.rw -> Game.t -> Context.tree -> string tzresult Lwt.t + + (** [state_of_tick node_ctxt ?start_state ~tick level] returns [Some + (state, hash)] for a given [tick] if this [tick] happened before + [level]. Otherwise, returns [None]. If provided, the evaluation is resumed + from [start_state]. *) + val state_of_tick : + _ Node_context.t -> + ?start_state:Fuel.Accounted.t Pvm_plugin_sig.eval_state -> + tick:Z.t -> + int32 -> + Fuel.Accounted.t Pvm_plugin_sig.eval_state option tzresult Lwt.t + + (** [make_dissection node_ctxt ~start_state ~start_chunk ~our_stop_chunk + ~default_number_of_sections ~last_level] computes a dissection from between + [start_chunk] and [our_stop_chunk] at level [last_level]. This dissection + has [default_number_of_sections] if there are enough ticks. *) + val make_dissection : + _ Node_context.t -> + start_state:Fuel.Accounted.t Pvm_plugin_sig.eval_state option -> + start_chunk:Game.dissection_chunk -> + our_stop_chunk:Game.dissection_chunk -> + default_number_of_sections:int -> + last_level:int32 -> + Game.dissection_chunk trace tzresult Lwt.t + + (** [timeout_reached node_ctxt ~self ~opponent] returns [true] if the + timeout is reached against opponent in head of the L1 chain. *) + val timeout_reached : + _ Node_context.t -> + self:Signature.public_key_hash -> + opponent:Signature.public_key_hash -> + bool tzresult Lwt.t + + (** [get_conflicts cctxt rollup signer] returns the conflicts for commitments + staked on by [signer]. *) + val get_conflicts : + Client_context.full -> + Address.t -> + Signature.public_key_hash -> + Game.conflict list tzresult Lwt.t + + (** [get_ongoing_games cctxt rollup signer] returns the games that [signer] is + currently playing. *) + val get_ongoing_games : + Client_context.full -> + Address.t -> + Signature.public_key_hash -> + (Game.t * Signature.public_key_hash * Signature.public_key_hash) list + tzresult + Lwt.t end (** Protocol specific constants for the batcher. *) @@ -269,7 +306,7 @@ module type S = sig module Interpreter : INTERPRETER - module Refutation_coordinator : REFUTATION_COORDINATOR + module Refutation_game_helpers : REFUTATION_GAME_HELPERS module Batcher_constants : BATCHER_CONSTANTS diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_coordinator.ml b/src/lib_smart_rollup_node/refutation_coordinator.ml similarity index 83% rename from src/proto_018_Proxford/lib_sc_rollup_node/refutation_coordinator.ml rename to src/lib_smart_rollup_node/refutation_coordinator.ml index 1ed4e1eb8efa..d87e0ab1e3e8 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_coordinator.ml +++ b/src/lib_smart_rollup_node/refutation_coordinator.ml @@ -28,32 +28,7 @@ module Player = Refutation_player module Pkh_map = Signature.Public_key_hash.Map module Pkh_table = Signature.Public_key_hash.Table -type state = { - node_ctxt : Node_context.rw; - cctxt : Protocol_client_context.full; - pending_opponents : unit Pkh_table.t; -} - -let get_conflicts cctxt head_block rollup staker = - let open Lwt_result_syntax in - let+ conflicts = - Plugin.RPC.Sc_rollup.conflicts cctxt (cctxt#chain, head_block) rollup staker - in - List.map Sc_rollup_proto_types.Game.conflict_to_octez conflicts - -let get_ongoing_games cctxt head_block rollup staker = - let open Lwt_result_syntax in - let+ games = - Plugin.RPC.Sc_rollup.ongoing_refutation_games - cctxt - (cctxt#chain, head_block) - rollup - staker - in - List.map - (fun (game, staker1, staker2) -> - (Sc_rollup_proto_types.Game.to_octez game, staker1, staker2)) - games +type state = {node_ctxt : Node_context.rw; pending_opponents : unit Pkh_table.t} let untracked_conflicts opponent_players conflicts = List.filter @@ -74,9 +49,8 @@ let make_game_map self ongoing_games = Pkh_map.empty ongoing_games -let on_process Layer1.{hash; level} state = +let on_process Layer1.{level; _} state = let node_ctxt = state.node_ctxt in - let head_block = `Hash (hash, 0) in let open Lwt_result_syntax in let refute_signer = Node_context.get_operator node_ctxt Refute in match refute_signer with @@ -85,9 +59,14 @@ let on_process Layer1.{hash; level} state = return_unit | Some self -> let Node_context.{rollup_address; _} = node_ctxt in + let* plugin = Protocol_plugins.last_proto_plugin node_ctxt in + let module Plugin = (val plugin) in (* Current conflicts in L1 *) let* conflicts = - get_conflicts state.cctxt head_block rollup_address self + Plugin.Refutation_game_helpers.get_conflicts + state.node_ctxt.cctxt + rollup_address + self in (* Map of opponents the node is playing against to the corresponding player worker *) @@ -99,7 +78,10 @@ let on_process Layer1.{hash; level} state = let new_conflicts = untracked_conflicts opponent_players conflicts in (* L1 ongoing games *) let* ongoing_games = - get_ongoing_games state.cctxt head_block rollup_address self + Plugin.Refutation_game_helpers.get_ongoing_games + state.node_ctxt.cctxt + rollup_address + self in (* Map between opponents and their corresponding games *) let ongoing_game_map = make_game_map self ongoing_games in @@ -135,10 +117,7 @@ let on_process Layer1.{hash; level} state = module Types = struct type nonrec state = state - type parameters = { - node_ctxt : Node_context.rw; - cctxt : Protocol_client_context.full; - } + type parameters = Node_context.rw end module Name = struct @@ -174,8 +153,8 @@ module Handlers = struct type launch_error = error trace - let on_launch _w () Types.{node_ctxt; cctxt} = - return {node_ctxt; cctxt; pending_opponents = Pkh_table.create 5} + let on_launch _w () node_ctxt = + Lwt_result.return {node_ctxt; pending_opponents = Pkh_table.create 5} let on_error (type a b) _w st (r : (a, b) Request.t) (errs : b) : unit tzresult Lwt.t = @@ -204,10 +183,7 @@ let worker_promise, worker_waker = Lwt.task () let start node_ctxt = let open Lwt_result_syntax in let*! () = Refutation_game_event.Coordinator.starting () in - let cctxt = - new Protocol_client_context.wrap_full node_ctxt.Node_context.cctxt - in - let+ worker = Worker.launch table () {node_ctxt; cctxt} (module Handlers) in + let+ worker = Worker.launch table () node_ctxt (module Handlers) in Lwt.wakeup worker_waker worker let init node_ctxt = @@ -218,18 +194,19 @@ let init node_ctxt = return_unit | Lwt.Fail exn -> (* Worker crashed, not recoverable. *) - fail [Sc_rollup_node_errors.No_refutation_coordinator; Exn exn] + fail [Rollup_node_errors.No_refutation_coordinator; Exn exn] | Lwt.Sleep -> (* Never started, start it. *) start node_ctxt (* This is a refutation coordinator for a single scoru *) let worker = + let open Result_syntax in lazy (match Lwt.state worker_promise with - | Lwt.Return worker -> ok worker + | Lwt.Return worker -> return worker | Lwt.Fail _ | Lwt.Sleep -> - error Sc_rollup_node_errors.No_refutation_coordinator) + tzfail Rollup_node_errors.No_refutation_coordinator) let process b = let open Lwt_result_syntax in diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_coordinator.mli b/src/lib_smart_rollup_node/refutation_coordinator.mli similarity index 92% rename from src/proto_017_PtNairob/lib_sc_rollup_node/refutation_coordinator.mli rename to src/lib_smart_rollup_node/refutation_coordinator.mli index 12a35582b9b2..d2303ca95f38 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_coordinator.mli +++ b/src/lib_smart_rollup_node/refutation_coordinator.mli @@ -32,15 +32,16 @@ (** Initiatilize the refuation coordinator. *) val init : Node_context.rw -> unit tzresult Lwt.t -(** Process a new l1 head. This means that the coordinator will: +(** [process head] processes a new l1 head. This means that the coordinator + will: {ol {li Gather all existing conflicts} - {li Launch new refutation players for each conflict that doesn't - have a player in this node} + {li Launch new refutation players for each conflict concerning + the operator that doesn't have a player in this node} {li Kill all players whose conflict has disappeared from L1} {li Make all players play a step in the refutation} } - *) +*) val process : Layer1.head -> unit tzresult Lwt.t (** Shutdown the refutation coordinator. *) diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game.ml b/src/lib_smart_rollup_node/refutation_game.ml similarity index 85% rename from src/proto_018_Proxford/lib_sc_rollup_node/refutation_game.ml rename to src/lib_smart_rollup_node/refutation_game.ml index 1253dc7ef02d..1725425e3840 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game.ml +++ b/src/lib_smart_rollup_node/refutation_game.ml @@ -44,7 +44,6 @@ *) open Game -open Refutation_game_helpers let node_role ~self {alice; bob} = if Signature.Public_key_hash.equal alice self then Alice @@ -77,8 +76,8 @@ type pvm_intermediate_state = | Hash of State_hash.t | Evaluated of Fuel.Accounted.t Pvm_plugin_sig.eval_state -let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok - our_view = +let new_dissection (module Plugin : Protocol_plugin_sig.S) ~opponent + ~default_number_of_sections node_ctxt last_level ok our_view = let open Lwt_result_syntax in let start_hash, start_tick, start_state = match ok with @@ -93,7 +92,7 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok in let our_stop_chunk = Game.{state_hash = our_state_hash; tick = our_tick} in let* dissection = - make_dissection + Plugin.Refutation_game_helpers.make_dissection node_ctxt ~start_state ~start_chunk @@ -114,7 +113,8 @@ let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok dissection] traverses the current [dissection] and returns a move which performs a new dissection of the execution trace or provides a refutation proof to serve as the next move of the [game]. *) -let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent +let generate_next_dissection (module Plugin : Protocol_plugin_sig.S) + ~default_number_of_sections node_ctxt ~opponent (game : Octez_smart_rollup.Game.t) (dissection : Octez_smart_rollup.Game.dissection_chunk list) = let open Lwt_result_syntax in @@ -125,8 +125,7 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent retrieved game does not respect this, we cannot trust the Tezos node we are connected to and prefer to stop here. *) tzfail - Sc_rollup_node_errors - .Unreliable_tezos_node_returning_inconsistent_game + Rollup_node_errors.Unreliable_tezos_node_returning_inconsistent_game | Octez_smart_rollup.Game.{state_hash = their_hash; tick} :: dissection -> ( let start_state = match ok with @@ -134,7 +133,11 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent | Evaluated ok_state, _ -> Some ok_state in let* our = - state_of_tick node_ctxt ?start_state ~tick game.inbox_level + Plugin.Refutation_game_helpers.state_of_tick + node_ctxt + ?start_state + ~tick + game.inbox_level in match (their_hash, our) with | None, None -> @@ -152,6 +155,7 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent let* ok, ko = traverse (Hash hash, tick) dissection in let* dissection = new_dissection + (module Plugin) ~opponent ~default_number_of_sections node_ctxt @@ -170,21 +174,29 @@ let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent A dissection always contains strictly more than one element. *) tzfail - Sc_rollup_node_errors.Unreliable_tezos_node_returning_inconsistent_game + Rollup_node_errors.Unreliable_tezos_node_returning_inconsistent_game -let next_move node_ctxt ~opponent (game : Octez_smart_rollup.Game.t) = +let next_move (module Plugin : Protocol_plugin_sig.S) node_ctxt ~opponent + (game : Octez_smart_rollup.Game.t) = let open Lwt_result_syntax in let final_move start_tick = let* start_state = - state_of_tick node_ctxt ~tick:start_tick game.inbox_level + Plugin.Refutation_game_helpers.state_of_tick + node_ctxt + ~tick:start_tick + game.inbox_level in match start_state with | None -> tzfail - Sc_rollup_node_errors - .Unreliable_tezos_node_returning_inconsistent_game + Rollup_node_errors.Unreliable_tezos_node_returning_inconsistent_game | Some {state = start_state; _} -> - let* proof = generate_proof node_ctxt game start_state in + let* proof = + Plugin.Refutation_game_helpers.generate_proof + node_ctxt + game + start_state + in let choice = start_tick in return (Octez_smart_rollup.Game.Move {choice; step = Proof proof}) in @@ -193,6 +205,7 @@ let next_move node_ctxt ~opponent (game : Octez_smart_rollup.Game.t) = | Dissecting {dissection; default_number_of_sections} -> let* choice, chosen_section_len, dissection = generate_next_dissection + (module Plugin) ~default_number_of_sections node_ctxt ~opponent @@ -207,9 +220,9 @@ let next_move node_ctxt ~opponent (game : Octez_smart_rollup.Game.t) = let choice = agreed_start_chunk.tick in final_move choice -let play_next_move node_ctxt game self opponent = +let play_next_move plugin node_ctxt game self opponent = let open Lwt_result_syntax in - let* refutation = next_move node_ctxt ~opponent game in + let* refutation = next_move plugin node_ctxt ~opponent game in inject_next_move node_ctxt self ~refutation ~opponent let play_timeout (node_ctxt : _ Node_context.t) self stakers = @@ -227,10 +240,14 @@ let play_timeout (node_ctxt : _ Node_context.t) self stakers = let play node_ctxt ~self game opponent = let open Lwt_result_syntax in let index = make_index self opponent in + let* plugin = Protocol_plugins.last_proto_plugin node_ctxt in match turn ~self game index with - | Our_turn {opponent} -> play_next_move node_ctxt game self opponent + | Our_turn {opponent} -> play_next_move plugin node_ctxt game self opponent | Their_turn -> - let* timeout_reached = timeout_reached node_ctxt ~self ~opponent in + let module Plugin = (val plugin) in + let* timeout_reached = + Plugin.Refutation_game_helpers.timeout_reached node_ctxt ~self ~opponent + in when_ timeout_reached @@ fun () -> let*! () = Refutation_game_event.timeout_detected opponent in play_timeout node_ctxt self index diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game.mli b/src/lib_smart_rollup_node/refutation_game.mli similarity index 94% rename from src/proto_018_Proxford/lib_sc_rollup_node/refutation_game.mli rename to src/lib_smart_rollup_node/refutation_game.mli index 1f8668ebb042..f718e20af1bd 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game.mli +++ b/src/lib_smart_rollup_node/refutation_game.mli @@ -33,8 +33,8 @@ val play_opening_move : Octez_smart_rollup.Game.conflict -> (unit, tztrace) result Lwt.t -(** [play head_block node_ctxt ~self game opponent] injects the next move in the - refutation [game] played by [self] and [opponent]. *) +(** [play head_block plugin node_ctxt ~self game opponent] injects the next move + in the refutation [game] played by [self] and [opponent]. *) val play : Node_context.rw -> self:Signature.public_key_hash -> diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game_event.ml b/src/lib_smart_rollup_node/refutation_game_event.ml similarity index 93% rename from src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game_event.ml rename to src/lib_smart_rollup_node/refutation_game_event.ml index 70f35ed9369b..73964d94f9c0 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game_event.ml +++ b/src/lib_smart_rollup_node/refutation_game_event.ml @@ -23,12 +23,10 @@ (* *) (*****************************************************************************) -open Protocol.Alpha_context - (* TODO: https://gitlab.com/tezos/tezos/-/issues/2880 Add corresponding .mli file. *) -let section = [Protocol.name; "sc_rollup_node"; "refutation_game"] +let section = ["sc_rollup_node"; "refutation_game"] module Simple = struct include Internal_event.Simple @@ -79,10 +77,10 @@ module Simple = struct {our_commitment_hash} at level {level} with staker {other} that hash \ issued commitment {their_commitment_hash}." ~level:Notice - ("our_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) + ("our_commitment_hash", Commitment.Hash.encoding) ("level", Data_encoding.int32) ("other", Signature.Public_key_hash.encoding) - ("their_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) + ("their_commitment_hash", Commitment.Hash.encoding) let timeout_detected = declare_1 @@ -91,17 +89,7 @@ module Simple = struct ~msg: "The rollup node has detected that opponent {other} can be timed out." ~level:Notice - ("other", Sc_rollup.Staker.encoding) - - let dissection_chunk_encoding = - let open Data_encoding in - let open Sc_rollup.Dissection_chunk in - conv - (fun {state_hash; tick} -> (state_hash, tick)) - (fun (state_hash, tick) -> {state_hash; tick}) - (obj2 - (opt "state" Sc_rollup.State_hash.encoding) - (req "tick" Sc_rollup.Tick.encoding)) + ("other", Signature.Public_key_hash.encoding) let computed_dissection = declare_4 diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_player.ml b/src/lib_smart_rollup_node/refutation_player.ml similarity index 96% rename from src/proto_alpha/lib_sc_rollup_node/refutation_player.ml rename to src/lib_smart_rollup_node/refutation_player.ml index 3d7c8d596905..c615511eb3b7 100644 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_player.ml +++ b/src/lib_smart_rollup_node/refutation_player.ml @@ -76,7 +76,7 @@ module Handlers = struct type launch_error = error trace let on_launch _w _name Types.{node_ctxt; self; conflict} = - return + Lwt_result.return Types.{node_ctxt; self; opponent = conflict.other; last_move_cache = None} let on_error (type a b) _w st (r : (a, b) Request.t) (errs : b) : @@ -114,7 +114,7 @@ let init node_ctxt ~self ~conflict = in let worker_promise, worker_waker = Lwt.task () in let* worker = - trace Sc_rollup_node_errors.Refutation_player_failed_to_start + trace Rollup_node_errors.Refutation_player_failed_to_start @@ Worker.launch table conflict.other @@ -123,10 +123,11 @@ let init node_ctxt ~self ~conflict = in let () = Lwt.wakeup worker_waker worker in let worker = + let open Result_syntax in match Lwt.state worker_promise with - | Lwt.Return worker -> ok worker + | Lwt.Return worker -> return worker | Lwt.Fail _ | Lwt.Sleep -> - error Sc_rollup_node_errors.Refutation_player_failed_to_start + tzfail Rollup_node_errors.Refutation_player_failed_to_start in Lwt.return worker diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player.mli b/src/lib_smart_rollup_node/refutation_player.mli similarity index 100% rename from src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player.mli rename to src/lib_smart_rollup_node/refutation_player.mli diff --git a/src/lib_smart_rollup_node/rollup_node_daemon.ml b/src/lib_smart_rollup_node/rollup_node_daemon.ml index 7528eef257ee..9d9171661ad9 100644 --- a/src/lib_smart_rollup_node/rollup_node_daemon.ml +++ b/src/lib_smart_rollup_node/rollup_node_daemon.ml @@ -57,24 +57,22 @@ let previous_context (node_ctxt : _ Node_context.t) return (Context.empty node_ctxt.context) else Node_context.checkout_context node_ctxt predecessor.Layer1.hash -let start_workers ?(degraded = false) (configuration : Configuration.t) +let start_workers (configuration : Configuration.t) (plugin : (module Protocol_plugin_sig.S)) (node_ctxt : _ Node_context.t) = let open Lwt_result_syntax in let module Plugin = (val plugin) in + let* () = Publisher.init node_ctxt in let* () = - unless degraded @@ fun () -> - let* () = Publisher.init node_ctxt in match Configuration.Operator_purpose_map.find Add_messages node_ctxt.operators with | None -> return_unit | Some signer -> Batcher.init plugin configuration.batcher ~signer node_ctxt in - let* () = Plugin.Refutation_coordinator.init node_ctxt in + let* () = Refutation_coordinator.init node_ctxt in return_unit -let handle_protocol_migration ?degraded ~catching_up state - (head : Layer1.header) = +let handle_protocol_migration ~catching_up state (head : Layer1.header) = let open Lwt_result_syntax in let* head_proto = Node_context.protocol_of_level state.node_ctxt head.level in let new_protocol = head_proto.protocol in @@ -90,10 +88,7 @@ let handle_protocol_migration ?degraded ~catching_up state let*? constants, new_plugin = protocol_info state.node_ctxt.cctxt new_protocol head.hash in - let* constants - and* () = - start_workers ?degraded state.configuration new_plugin state.node_ctxt - in + let* constants in let new_protocol = { Node_context.hash = new_protocol; @@ -273,7 +268,7 @@ let on_layer_1_head ({node_ctxt; _} as state) (head : Layer1.header) = let* () = Publisher.publish_commitments () in let* () = Publisher.cement_commitments () in let*! () = Daemon_event.new_heads_processed reorg.new_chain in - let* () = Plugin.Refutation_coordinator.process stripped_head in + let* () = Refutation_coordinator.process stripped_head in let* () = Batcher.new_head stripped_head in let*! () = Injector.inject ~header:head.header () in return_unit @@ -291,13 +286,9 @@ let degraded_refutation_mode state = let*! () = message "Shutting down Commitment Publisher@." in let*! () = Publisher.shutdown () in Layer1.iter_heads state.node_ctxt.l1_ctxt @@ fun head -> - let* () = - handle_protocol_migration ~degraded:true ~catching_up:false state head - in + let* () = handle_protocol_migration ~catching_up:false state head in let module Plugin = (val state.plugin) in - let* () = - Plugin.Refutation_coordinator.process (Layer1.head_of_header head) - in + let* () = Refutation_coordinator.process (Layer1.head_of_header head) in let*! () = Injector.inject () in return_unit @@ -315,7 +306,7 @@ let install_finalizer state = let* () = message "Shutting down Commitment Publisher@." in let* () = Publisher.shutdown () in let* () = message "Shutting down Refutation Coordinator@." in - let* () = Plugin.Refutation_coordinator.shutdown () in + let* () = Refutation_coordinator.shutdown () in let* (_ : unit tzresult) = Node_context.close state.node_ctxt in let* () = Event.shutdown_node exit_status in Tezos_base_unix.Internal_event_unix.close () diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_coordinator.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_coordinator.ml deleted file mode 100644 index 470bf57ca178..000000000000 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_coordinator.ml +++ /dev/null @@ -1,257 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 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 Refutation_coordinator_types -module Player = Refutation_player -module Pkh_map = Signature.Public_key_hash.Map -module Pkh_table = Signature.Public_key_hash.Table - -type state = { - node_ctxt : Node_context.rw; - cctxt : Protocol_client_context.full; - pending_opponents : unit Pkh_table.t; -} - -let get_conflicts cctxt head_block rollup staker = - let open Lwt_result_syntax in - let+ conflicts = - Plugin.RPC.Sc_rollup.conflicts - cctxt - (cctxt#chain, head_block) - (Sc_rollup_proto_types.Address.of_octez rollup) - staker - in - List.map Sc_rollup_proto_types.Game.conflict_to_octez conflicts - -let get_ongoing_games cctxt head_block rollup staker = - let open Lwt_result_syntax in - let+ games = - Plugin.RPC.Sc_rollup.ongoing_refutation_games - cctxt - (cctxt#chain, head_block) - (Sc_rollup_proto_types.Address.of_octez rollup) - staker - in - List.map - (fun (game, staker1, staker2) -> - (Sc_rollup_proto_types.Game.to_octez game, staker1, staker2)) - games - -let untracked_conflicts opponent_players conflicts = - List.filter - (fun conflict -> not @@ Pkh_map.mem conflict.Game.other opponent_players) - conflicts - -(* Transform the list of ongoing games [(Game.t * pkh * pkh) list] - into a mapping from opponents' pkhs to their corresponding game - state. -*) -let make_game_map self ongoing_games = - List.fold_left - (fun acc (game, alice, bob) -> - let opponent_pkh = - if Signature.Public_key_hash.equal self alice then bob else alice - in - Pkh_map.add opponent_pkh game acc) - Pkh_map.empty - ongoing_games - -let on_process Layer1.{hash; level} state = - let node_ctxt = state.node_ctxt in - let head_block = `Hash (hash, 0) in - let open Lwt_result_syntax in - 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 -> - let Node_context.{rollup_address; _} = node_ctxt in - (* Current conflicts in L1 *) - let* conflicts = - get_conflicts state.cctxt head_block rollup_address self - in - (* Map of opponents the node is playing against to the corresponding - player worker *) - let opponent_players = - Pkh_map.of_seq @@ List.to_seq @@ Player.current_games () - in - (* Conflicts for which we need to start new refutation players. - Some of these might be ongoing. *) - let new_conflicts = untracked_conflicts opponent_players conflicts in - (* L1 ongoing games *) - let* ongoing_games = - get_ongoing_games state.cctxt head_block rollup_address self - in - (* Map between opponents and their corresponding games *) - let ongoing_game_map = make_game_map self ongoing_games in - (* Launch new players for new conflicts, and play one step *) - let* () = - List.iter_ep - (fun conflict -> - let other = conflict.Octez_smart_rollup.Game.other in - Pkh_table.replace state.pending_opponents other () ; - let game = Pkh_map.find_opt other ongoing_game_map in - Player.init_and_play node_ctxt ~self ~conflict ~game ~level) - new_conflicts - in - let*! () = - (* Play one step of the refutation game in every remaining player *) - Pkh_map.iter_p - (fun opponent worker -> - match Pkh_map.find opponent ongoing_game_map with - | Some game -> - Pkh_table.remove state.pending_opponents opponent ; - Player.play worker game ~level - | None -> - (* Kill finished players: those who don't aren't - playing against pending opponents that don't have - ongoing games in the L1 *) - if not @@ Pkh_table.mem state.pending_opponents opponent then - Player.shutdown worker - else Lwt.return_unit) - opponent_players - in - return_unit - -module Types = struct - type nonrec state = state - - type parameters = { - node_ctxt : Node_context.rw; - cctxt : Protocol_client_context.full; - } -end - -module Name = struct - (* We only have a single coordinator in the node *) - type t = unit - - let encoding = Data_encoding.unit - - let base = - (* But we can have multiple instances in the unit tests. This is just to - avoid conflicts in the events declarations. *) - Refutation_game_event.Coordinator.section @ ["worker"] - - let pp _ _ = () - - let equal () () = true -end - -module Worker = Worker.MakeSingle (Name) (Request) (Types) - -type worker = Worker.infinite Worker.queue Worker.t - -module Handlers = struct - type self = worker - - let on_request : - type r request_error. - worker -> (r, request_error) Request.t -> (r, request_error) result Lwt.t - = - fun w request -> - let state = Worker.state w in - match request with Request.Process b -> on_process b state - - type launch_error = error trace - - let on_launch _w () Types.{node_ctxt; cctxt} = - return {node_ctxt; cctxt; pending_opponents = Pkh_table.create 5} - - let on_error (type a b) _w st (r : (a, b) Request.t) (errs : b) : - unit tzresult Lwt.t = - let open Lwt_result_syntax in - let request_view = Request.view r in - let emit_and_return_errors errs = - let*! () = - Refutation_game_event.Coordinator.request_failed request_view st errs - in - return_unit - in - match r with Request.Process _ -> emit_and_return_errors errs - - let on_completion _w r _ st = - Refutation_game_event.Coordinator.request_completed (Request.view r) st - - let on_no_request _ = Lwt.return_unit - - let on_close _w = Lwt.return_unit -end - -let table = Worker.create_table Queue - -let worker_promise, worker_waker = Lwt.task () - -let start node_ctxt = - let open Lwt_result_syntax in - let*! () = Refutation_game_event.Coordinator.starting () in - let cctxt = - new Protocol_client_context.wrap_full node_ctxt.Node_context.cctxt - in - let+ worker = Worker.launch table () {node_ctxt; cctxt} (module Handlers) in - Lwt.wakeup worker_waker worker - -let init node_ctxt = - let open Lwt_result_syntax in - match Lwt.state worker_promise with - | Lwt.Return _ -> - (* Worker already started, nothing to do. *) - return_unit - | Lwt.Fail exn -> - (* Worker crashed, not recoverable. *) - fail [Sc_rollup_node_errors.No_refutation_coordinator; Exn exn] - | Lwt.Sleep -> - (* Never started, start it. *) - start node_ctxt - -(* This is a refutation coordinator for a single scoru *) -let worker = - lazy - (match Lwt.state worker_promise with - | Lwt.Return worker -> ok worker - | Lwt.Fail _ | Lwt.Sleep -> - error Sc_rollup_node_errors.No_refutation_coordinator) - -let process b = - let open Lwt_result_syntax in - let*? w = Lazy.force worker in - let*! (_pushed : bool) = Worker.Queue.push_request w (Request.Process b) in - return_unit - -let shutdown () = - let open Lwt_syntax in - let w = Lazy.force worker in - match w with - | Error _ -> - (* There is no refutation coordinator, nothing to do *) - Lwt.return_unit - | Ok w -> - (* Shut down all current refutation players *) - let games = Player.current_games () in - let* () = - List.iter_s (fun (_opponent, player) -> Player.shutdown player) games - in - Worker.shutdown w diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_coordinator.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_coordinator.mli deleted file mode 100644 index 12a35582b9b2..000000000000 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_coordinator.mli +++ /dev/null @@ -1,47 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 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. *) -(* *) -(*****************************************************************************) - -(** Component for managing refutation games. - This module is implemented as a single worker in the rollup node, - which takes care of processing new L1 heads, and coordinating - the refutation game players. (See {!Refutation_player}). -*) - -(** Initiatilize the refuation coordinator. *) -val init : Node_context.rw -> unit tzresult Lwt.t - -(** Process a new l1 head. This means that the coordinator will: - {ol - {li Gather all existing conflicts} - {li Launch new refutation players for each conflict that doesn't - have a player in this node} - {li Kill all players whose conflict has disappeared from L1} - {li Make all players play a step in the refutation} - } - *) -val process : Layer1.head -> unit tzresult Lwt.t - -(** Shutdown the refutation coordinator. *) -val shutdown : unit -> unit Lwt.t diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.ml deleted file mode 100644 index 0ebfd48eab6c..000000000000 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.ml +++ /dev/null @@ -1,252 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -(** This module implements the refutation game logic of the rollup - node. - - When a new L1 block arises, the rollup node asks the L1 node for - the current game it is part of, if any. - - If a game is running and it is the rollup operator turn, the rollup - node injects the next move of the winning strategy. - - If a game is running and it is not the rollup operator turn, the - rollup node asks the L1 node whether the timeout is reached to play - the timeout argument if possible. - - Otherwise, if no game is running, the rollup node asks the L1 node - whether there is a conflict with one of its disputable commitments. If - there is such a conflict with a commitment C', then the rollup node - starts a game to refute C' by starting a game with one of its staker. - -*) - -open Game -open Refutation_game_helpers - -let node_role ~self {alice; bob} = - if Signature.Public_key_hash.equal alice self then Alice - else if Signature.Public_key_hash.equal bob self then Bob - else (* By validity of [ongoing_game] RPC. *) - assert false - -type role = Our_turn of {opponent : Signature.public_key_hash} | Their_turn - -let turn ~self game ({alice; bob} as players) = - match (node_role ~self players, game.turn) with - | Alice, Alice -> Our_turn {opponent = bob} - | Bob, Bob -> Our_turn {opponent = alice} - | Alice, Bob -> Their_turn - | Bob, Alice -> Their_turn - -(** [inject_next_move node_ctxt source ~refutation ~opponent ~commitment - ~opponent_commitment] submits an L1 operation (signed by [source]) to issue - the next move in the refutation game. *) -let inject_next_move node_ctxt source ~refutation ~opponent = - let open Lwt_result_syntax in - let refute_operation = - L1_operation.Refute - {rollup = node_ctxt.Node_context.rollup_address; refutation; opponent} - in - let* _hash = Injector.add_pending_operation ~source refute_operation in - return_unit - -type pvm_intermediate_state = - | Hash of State_hash.t - | Evaluated of Fuel.Accounted.t Pvm_plugin_sig.eval_state - -let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok - our_view = - let open Lwt_result_syntax in - let start_hash, start_tick, start_state = - match ok with - | Hash hash, tick -> (hash, tick, None) - | Evaluated ({state_hash; _} as state), tick -> - (state_hash, tick, Some state) - in - let start_chunk = Game.{state_hash = Some start_hash; tick = start_tick} in - let our_state, our_tick = our_view in - let our_state_hash = - Option.map (fun Pvm_plugin_sig.{state_hash; _} -> state_hash) our_state - in - let our_stop_chunk = Game.{state_hash = our_state_hash; tick = our_tick} in - let* dissection = - make_dissection - node_ctxt - ~start_state - ~start_chunk - ~our_stop_chunk - ~default_number_of_sections - ~last_level - in - let*! () = - Refutation_game_event.computed_dissection - ~opponent - ~start_tick - ~end_tick:our_tick - dissection - in - return dissection - -(** [generate_from_dissection ~default_number_of_sections node_ctxt game - dissection] traverses the current [dissection] and returns a move which - performs a new dissection of the execution trace or provides a refutation - proof to serve as the next move of the [game]. *) -let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent - (game : Octez_smart_rollup.Game.t) - (dissection : Octez_smart_rollup.Game.dissection_chunk list) = - let open Lwt_result_syntax in - let rec traverse ok = function - | [] -> - (* The game invariant states that the dissection from the - opponent must contain a tick we disagree with. If the - retrieved game does not respect this, we cannot trust the - Tezos node we are connected to and prefer to stop here. *) - tzfail - Sc_rollup_node_errors - .Unreliable_tezos_node_returning_inconsistent_game - | Octez_smart_rollup.Game.{state_hash = their_hash; tick} :: dissection -> ( - let start_state = - match ok with - | Hash _, _ -> None - | Evaluated ok_state, _ -> Some ok_state - in - let* our = - state_of_tick node_ctxt ?start_state ~tick game.inbox_level - in - match (their_hash, our) with - | None, None -> - (* This case is absurd since: [None] can only occur at the - end and the two players disagree about the end. *) - assert false - | Some _, None | None, Some _ -> return (ok, (our, tick)) - | Some their_hash, Some ({state_hash = our_hash; _} as our_state) -> - if Octez_smart_rollup.State_hash.equal our_hash their_hash then - traverse (Evaluated our_state, tick) dissection - else return (ok, (our, tick))) - in - match dissection with - | {state_hash = Some hash; tick} :: dissection -> - let* ok, ko = traverse (Hash hash, tick) dissection in - let* dissection = - new_dissection - ~opponent - ~default_number_of_sections - node_ctxt - game.inbox_level - ok - ko - in - let _, choice = ok in - let _, ko_tick = ko in - let chosen_section_len = Z.abs (Z.sub choice ko_tick) in - return (choice, chosen_section_len, dissection) - | [] | {state_hash = None; _} :: _ -> - (* - By wellformedness of dissection. - A dissection always starts with a tick of the form [(Some hash, tick)]. - A dissection always contains strictly more than one element. - *) - tzfail - Sc_rollup_node_errors.Unreliable_tezos_node_returning_inconsistent_game - -let next_move node_ctxt ~opponent (game : Octez_smart_rollup.Game.t) = - let open Lwt_result_syntax in - let final_move start_tick = - let* start_state = - state_of_tick node_ctxt ~tick:start_tick game.inbox_level - in - match start_state with - | None -> - tzfail - Sc_rollup_node_errors - .Unreliable_tezos_node_returning_inconsistent_game - | Some {state = start_state; _} -> - let* proof = generate_proof node_ctxt game start_state in - let choice = start_tick in - return (Octez_smart_rollup.Game.Move {choice; step = Proof proof}) - in - - match game.game_state with - | Dissecting {dissection; default_number_of_sections} -> - let* choice, chosen_section_len, dissection = - generate_next_dissection - ~default_number_of_sections - node_ctxt - ~opponent - game - dissection - in - if Z.(equal chosen_section_len one) then final_move choice - else - return - (Octez_smart_rollup.Game.Move {choice; step = Dissection dissection}) - | Final_move {agreed_start_chunk; refuted_stop_chunk = _} -> - let choice = agreed_start_chunk.tick in - final_move choice - -let play_next_move node_ctxt game self opponent = - let open Lwt_result_syntax in - let* refutation = next_move node_ctxt ~opponent game in - inject_next_move node_ctxt self ~refutation ~opponent - -let play_timeout (node_ctxt : _ Node_context.t) self stakers = - let open Lwt_result_syntax in - let timeout_operation = - L1_operation.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 - let* _hash = Injector.add_pending_operation ~source timeout_operation in - return_unit - -let play node_ctxt ~self game opponent = - let open Lwt_result_syntax in - let index = make_index self opponent in - match turn ~self game index with - | Our_turn {opponent} -> play_next_move node_ctxt game self opponent - | Their_turn -> - let* timeout_reached = timeout_reached node_ctxt ~self ~opponent in - when_ timeout_reached @@ fun () -> - let*! () = Refutation_game_event.timeout_detected opponent in - play_timeout node_ctxt self index - -let play_opening_move node_ctxt self - (conflict : Octez_smart_rollup.Game.conflict) = - let open Lwt_syntax in - let* () = Refutation_game_event.conflict_detected conflict in - let player_commitment_hash = - Octez_smart_rollup.Commitment.hash conflict.our_commitment - in - let opponent_commitment_hash = - Octez_smart_rollup.Commitment.hash conflict.their_commitment - in - let refutation = - Octez_smart_rollup.Game.Start - {player_commitment_hash; opponent_commitment_hash} - in - inject_next_move node_ctxt self ~refutation ~opponent:conflict.other diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.mli deleted file mode 100644 index 1f8668ebb042..000000000000 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game.mli +++ /dev/null @@ -1,43 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -(** This module implements the refutation game logic of the rollup node. *) - -(** [play_opening_move node_ctxt self conflict] injects the opening refutation - game move for [conflict]. *) -val play_opening_move : - [< `Read | `Write > `Read] Node_context.t -> - Signature.public_key_hash -> - Octez_smart_rollup.Game.conflict -> - (unit, tztrace) result Lwt.t - -(** [play head_block node_ctxt ~self game opponent] injects the next move in the - refutation [game] played by [self] and [opponent]. *) -val play : - Node_context.rw -> - self:Signature.public_key_hash -> - Octez_smart_rollup.Game.t -> - Signature.public_key_hash -> - (unit, tztrace) result Lwt.t diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game_event.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game_event.ml deleted file mode 100644 index 62d74b7e753b..000000000000 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_game_event.ml +++ /dev/null @@ -1,261 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -open Protocol.Alpha_context - -(* TODO: https://gitlab.com/tezos/tezos/-/issues/2880 - Add corresponding .mli file. *) - -let section = [Protocol.name; "sc_rollup_node"; "refutation_game"] - -module Simple = struct - include Internal_event.Simple - - let timeout = - declare_1 - ~section - ~name:"sc_rollup_node_timeout" - ~msg: - "The rollup node has been slashed because of a timeout issued by \ - {address}" - ~level:Notice - ("address", Tezos_crypto.Signature.Public_key_hash.encoding) - - let invalid_move = - declare_0 - ~section - ~name:"sc_rollup_node_invalid_move" - ~msg: - "The rollup node is about to make an invalid move in the refutation \ - game! It is stopped to avoid being slashed. The problem should be \ - reported immediately or the rollup node should be upgraded to have a \ - chance to be back before the timeout is reached." - ~level:Notice - () - - let conflict_detected = - declare_5 - ~section - ~name:"sc_rollup_node_conflict_detected" - ~msg: - "A conflict has been found with our commitment {our_commitment_hash} \ - at level {level} with staker {other} that hash issued commitment \ - {their_commitment_hash} both based on {parent_commitment_hash}." - ~level:Notice - ("our_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) - ("level", Data_encoding.int32) - ("other", Signature.Public_key_hash.encoding) - ("their_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) - ("parent_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) - - let potential_conflict_detected = - declare_4 - ~section - ~name:"sc_rollup_node_potential_conflict_detected" - ~msg: - "A potential conflict has been found with our commitment \ - {our_commitment_hash} at level {level} with staker {other} that hash \ - issued commitment {their_commitment_hash}." - ~level:Notice - ("our_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) - ("level", Data_encoding.int32) - ("other", Signature.Public_key_hash.encoding) - ("their_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) - - let timeout_detected = - declare_1 - ~section - ~name:"sc_rollup_node_timeout_detected" - ~msg: - "The rollup node has detected that opponent {other} can be timed out." - ~level:Notice - ("other", Sc_rollup.Staker.encoding) - - let dissection_chunk_encoding = - let open Data_encoding in - let open Sc_rollup.Dissection_chunk in - conv - (fun {state_hash; tick} -> (state_hash, tick)) - (fun (state_hash, tick) -> {state_hash; tick}) - (obj2 - (opt "state" Sc_rollup.State_hash.encoding) - (req "tick" Sc_rollup.Tick.encoding)) - - let computed_dissection = - declare_4 - ~section - ~name:"sc_rollup_node_computed_dissection" - ~msg: - "Computed dissection against {opponent} between ticks {start_tick} and \ - {end_tick}: {dissection}." - ~level:Debug - ("opponent", Signature.Public_key_hash.encoding) - ("start_tick", Data_encoding.z) - ("end_tick", Data_encoding.z) - ( "dissection", - Data_encoding.list Octez_smart_rollup.Game.dissection_chunk_encoding ) - - module Worker (ARG : sig - val section : string list - end) - (Request : Worker_intf.REQUEST) = - struct - include ARG - - let request_failed = - declare_3 - ~section - ~name:"request_failed" - ~msg:"request {view} failed ({worker_status}): {errors}" - ~level:Notice - ("view", Request.encoding) - ~pp1:Request.pp - ("worker_status", Worker_types.request_status_encoding) - ~pp2:Worker_types.pp_status - ("errors", Error_monad.trace_encoding) - ~pp3:Error_monad.pp_print_trace - - let request_completed = - declare_2 - ~section - ~name:"request_completed" - ~msg:"{view} {worker_status}" - ~level:Debug - ("view", Request.encoding) - ("worker_status", Worker_types.request_status_encoding) - ~pp1:Request.pp - ~pp2:Worker_types.pp_status - end - - module Player = struct - include - Worker - (struct - let section = section @ ["player"] - end) - (Refutation_player_types.Request) - - let started = - declare_2 - ~section - ~name:"player_started" - ~msg: - "refutation player started to play against {opponent}, defenfing \ - commitment {commitment}" - ~level:Notice - ("opponent", Signature.Public_key_hash.encoding) - ~pp1:Signature.Public_key_hash.pp - ("commitment", Octez_smart_rollup.Commitment.encoding) - ~pp2:Octez_smart_rollup.Commitment.pp - - let stopped = - declare_1 - ~section - ~name:"player_stopped" - ~msg:"refutation player for opponent {opponent} has been stopped" - ~level:Notice - ("opponent", Signature.Public_key_hash.encoding) - ~pp1:Signature.Public_key_hash.pp - end - - module Coordinator = struct - include - Worker - (struct - let section = section @ ["coordinator"] - end) - (Refutation_coordinator_types.Request) - - let starting = - declare_0 - ~section - ~name:"coordinator_starting" - ~msg:"Starting refutation coordinator for the smart rollup node" - ~level:Notice - () - end -end - -let timeout address = Simple.(emit timeout address) - -let invalid_move () = Simple.(emit invalid_move ()) - -let conflict_detected (conflict : Octez_smart_rollup.Game.conflict) = - let our_commitment_hash = - Octez_smart_rollup.Commitment.hash conflict.our_commitment - in - let their_commitment_hash = - Octez_smart_rollup.Commitment.hash conflict.their_commitment - in - let parent_commitment_hash = conflict.parent_commitment in - let other = conflict.other in - let level = conflict.our_commitment.inbox_level in - Simple.( - emit - conflict_detected - ( our_commitment_hash, - level, - other, - their_commitment_hash, - parent_commitment_hash )) - -let potential_conflict_detected ~our_commitment_hash ~their_commitment_hash - ~other ~level = - Simple.( - emit - potential_conflict_detected - (our_commitment_hash, level, other, their_commitment_hash)) - -let timeout_detected other = Simple.(emit timeout_detected other) - -let computed_dissection ~opponent ~start_tick ~end_tick dissection = - Simple.(emit computed_dissection (opponent, start_tick, end_tick, dissection)) - -module Player = struct - let section = Simple.Player.section - - let request_failed view worker_status errors = - Simple.(emit Player.request_failed (view, worker_status, errors)) - - let request_completed view worker_status = - Simple.(emit Player.request_completed (view, worker_status)) - - let started opponent commitment = - Simple.(emit Player.started (opponent, commitment)) - - let stopped opponent = Simple.(emit Player.stopped opponent) -end - -module Coordinator = struct - let section = Simple.Coordinator.section - - let request_failed view worker_status errors = - Simple.(emit Coordinator.request_failed (view, worker_status, errors)) - - let request_completed view worker_status = - Simple.(emit Coordinator.request_completed (view, worker_status)) - - let starting = Simple.(emit Coordinator.starting) -end diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player.ml deleted file mode 100644 index 3d7c8d596905..000000000000 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/refutation_player.ml +++ /dev/null @@ -1,178 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 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 Refutation_player_types -open Refutation_game - -module Types = struct - type state = { - node_ctxt : Node_context.rw; - self : Signature.public_key_hash; - opponent : Signature.public_key_hash; - mutable last_move_cache : - (Octez_smart_rollup.Game.game_state * int32) option; - } - - type parameters = { - node_ctxt : Node_context.rw; - self : Signature.public_key_hash; - conflict : Octez_smart_rollup.Game.conflict; - } -end - -module Name = struct - let base = Refutation_game_event.Player.section @ ["worker"] - - include Signature.Public_key_hash -end - -module Worker = Worker.MakeSingle (Name) (Request) (Types) - -type worker = Worker.infinite Worker.queue Worker.t - -let table = Worker.create_table Queue - -let on_play game Types.{node_ctxt; self; opponent; _} = - play node_ctxt ~self game opponent - -let on_play_opening conflict (Types.{node_ctxt; self; _} : Types.state) = - play_opening_move node_ctxt self conflict - -module Handlers = struct - type self = worker - - let on_request : - type r request_error. - worker -> (r, request_error) Request.t -> (r, request_error) result Lwt.t - = - fun w request -> - let state = Worker.state w in - match request with - | Request.Play game -> on_play game state - | Request.Play_opening conflict -> on_play_opening conflict state - - type launch_error = error trace - - let on_launch _w _name Types.{node_ctxt; self; conflict} = - return - Types.{node_ctxt; self; opponent = conflict.other; last_move_cache = None} - - let on_error (type a b) _w st (r : (a, b) Request.t) (errs : b) : - unit tzresult Lwt.t = - let open Lwt_result_syntax in - let request_view = Request.view r in - let emit_and_return_errors errs = - let*! () = - Refutation_game_event.Player.request_failed request_view st errs - in - return_unit - in - match r with - | Request.Play _ -> emit_and_return_errors errs - | Request.Play_opening _ -> emit_and_return_errors errs - - let on_completion _w r _ st = - Refutation_game_event.Player.request_completed (Request.view r) st - - let on_no_request _ = Lwt.return_unit - - let on_close w = - let open Lwt_syntax in - let state = Worker.state w in - let* () = Refutation_game_event.Player.stopped state.opponent in - return_unit -end - -let init node_ctxt ~self ~conflict = - let open Lwt_result_syntax in - let*! () = - Refutation_game_event.Player.started - conflict.Game.other - conflict.Game.our_commitment - in - let worker_promise, worker_waker = Lwt.task () in - let* worker = - trace Sc_rollup_node_errors.Refutation_player_failed_to_start - @@ Worker.launch - table - conflict.other - {node_ctxt; self; conflict} - (module Handlers) - in - let () = Lwt.wakeup worker_waker worker in - let worker = - match Lwt.state worker_promise with - | Lwt.Return worker -> ok worker - | Lwt.Fail _ | Lwt.Sleep -> - error Sc_rollup_node_errors.Refutation_player_failed_to_start - in - Lwt.return worker - -(* Play if: - - There's a new game state to play against or - - The current level is past the buffer for re-playing in the - same game state. -*) -let should_move ~level game last_move_cache = - match last_move_cache with - | None -> true - | Some (last_move_game_state, last_move_level) -> - (not (Game.game_state_equal game.Game.game_state last_move_game_state)) - || Int32.( - sub level last_move_level - > of_int Configuration.refutation_player_buffer_levels) - -let play w game ~(level : int32) = - let open Lwt_syntax in - let state = Worker.state w in - if should_move ~level game state.last_move_cache then ( - let* pushed = Worker.Queue.push_request w (Request.Play game) in - if pushed then state.last_move_cache <- Some (game.Game.game_state, level) ; - return_unit) - else return_unit - -let play_opening w conflict = - let open Lwt_syntax in - let* (_pushed : bool) = - Worker.Queue.push_request w (Request.Play_opening conflict) - in - return_unit - -let init_and_play node_ctxt ~self ~conflict ~game ~level = - let open Lwt_result_syntax in - let* worker = init node_ctxt ~self ~conflict in - let*! () = - match game with - | None -> play_opening worker conflict - | Some game -> play worker game ~level - in - return_unit - -let current_games () = - List.map - (fun (_name, worker) -> ((Worker.state worker).opponent, worker)) - (Worker.list table) - -let shutdown = Worker.shutdown diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/rollup_node_plugin.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/rollup_node_plugin.ml index d54d5b667423..4c5dd5e5cfe4 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/rollup_node_plugin.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/rollup_node_plugin.ml @@ -30,7 +30,7 @@ module Plugin : Protocol_plugin_sig.S = struct module Dal_slots_tracker = Dal_slots_tracker module Inbox = Inbox module Interpreter = Interpreter - module Refutation_coordinator = Refutation_coordinator + module Refutation_game_helpers = Refutation_game_helpers module Batcher_constants = Batcher_constants module Layer1_helpers = Layer1_helpers module L1_processing = Daemon_helpers diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_coordinator.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_coordinator.ml deleted file mode 100644 index 470bf57ca178..000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_coordinator.ml +++ /dev/null @@ -1,257 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 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 Refutation_coordinator_types -module Player = Refutation_player -module Pkh_map = Signature.Public_key_hash.Map -module Pkh_table = Signature.Public_key_hash.Table - -type state = { - node_ctxt : Node_context.rw; - cctxt : Protocol_client_context.full; - pending_opponents : unit Pkh_table.t; -} - -let get_conflicts cctxt head_block rollup staker = - let open Lwt_result_syntax in - let+ conflicts = - Plugin.RPC.Sc_rollup.conflicts - cctxt - (cctxt#chain, head_block) - (Sc_rollup_proto_types.Address.of_octez rollup) - staker - in - List.map Sc_rollup_proto_types.Game.conflict_to_octez conflicts - -let get_ongoing_games cctxt head_block rollup staker = - let open Lwt_result_syntax in - let+ games = - Plugin.RPC.Sc_rollup.ongoing_refutation_games - cctxt - (cctxt#chain, head_block) - (Sc_rollup_proto_types.Address.of_octez rollup) - staker - in - List.map - (fun (game, staker1, staker2) -> - (Sc_rollup_proto_types.Game.to_octez game, staker1, staker2)) - games - -let untracked_conflicts opponent_players conflicts = - List.filter - (fun conflict -> not @@ Pkh_map.mem conflict.Game.other opponent_players) - conflicts - -(* Transform the list of ongoing games [(Game.t * pkh * pkh) list] - into a mapping from opponents' pkhs to their corresponding game - state. -*) -let make_game_map self ongoing_games = - List.fold_left - (fun acc (game, alice, bob) -> - let opponent_pkh = - if Signature.Public_key_hash.equal self alice then bob else alice - in - Pkh_map.add opponent_pkh game acc) - Pkh_map.empty - ongoing_games - -let on_process Layer1.{hash; level} state = - let node_ctxt = state.node_ctxt in - let head_block = `Hash (hash, 0) in - let open Lwt_result_syntax in - 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 -> - let Node_context.{rollup_address; _} = node_ctxt in - (* Current conflicts in L1 *) - let* conflicts = - get_conflicts state.cctxt head_block rollup_address self - in - (* Map of opponents the node is playing against to the corresponding - player worker *) - let opponent_players = - Pkh_map.of_seq @@ List.to_seq @@ Player.current_games () - in - (* Conflicts for which we need to start new refutation players. - Some of these might be ongoing. *) - let new_conflicts = untracked_conflicts opponent_players conflicts in - (* L1 ongoing games *) - let* ongoing_games = - get_ongoing_games state.cctxt head_block rollup_address self - in - (* Map between opponents and their corresponding games *) - let ongoing_game_map = make_game_map self ongoing_games in - (* Launch new players for new conflicts, and play one step *) - let* () = - List.iter_ep - (fun conflict -> - let other = conflict.Octez_smart_rollup.Game.other in - Pkh_table.replace state.pending_opponents other () ; - let game = Pkh_map.find_opt other ongoing_game_map in - Player.init_and_play node_ctxt ~self ~conflict ~game ~level) - new_conflicts - in - let*! () = - (* Play one step of the refutation game in every remaining player *) - Pkh_map.iter_p - (fun opponent worker -> - match Pkh_map.find opponent ongoing_game_map with - | Some game -> - Pkh_table.remove state.pending_opponents opponent ; - Player.play worker game ~level - | None -> - (* Kill finished players: those who don't aren't - playing against pending opponents that don't have - ongoing games in the L1 *) - if not @@ Pkh_table.mem state.pending_opponents opponent then - Player.shutdown worker - else Lwt.return_unit) - opponent_players - in - return_unit - -module Types = struct - type nonrec state = state - - type parameters = { - node_ctxt : Node_context.rw; - cctxt : Protocol_client_context.full; - } -end - -module Name = struct - (* We only have a single coordinator in the node *) - type t = unit - - let encoding = Data_encoding.unit - - let base = - (* But we can have multiple instances in the unit tests. This is just to - avoid conflicts in the events declarations. *) - Refutation_game_event.Coordinator.section @ ["worker"] - - let pp _ _ = () - - let equal () () = true -end - -module Worker = Worker.MakeSingle (Name) (Request) (Types) - -type worker = Worker.infinite Worker.queue Worker.t - -module Handlers = struct - type self = worker - - let on_request : - type r request_error. - worker -> (r, request_error) Request.t -> (r, request_error) result Lwt.t - = - fun w request -> - let state = Worker.state w in - match request with Request.Process b -> on_process b state - - type launch_error = error trace - - let on_launch _w () Types.{node_ctxt; cctxt} = - return {node_ctxt; cctxt; pending_opponents = Pkh_table.create 5} - - let on_error (type a b) _w st (r : (a, b) Request.t) (errs : b) : - unit tzresult Lwt.t = - let open Lwt_result_syntax in - let request_view = Request.view r in - let emit_and_return_errors errs = - let*! () = - Refutation_game_event.Coordinator.request_failed request_view st errs - in - return_unit - in - match r with Request.Process _ -> emit_and_return_errors errs - - let on_completion _w r _ st = - Refutation_game_event.Coordinator.request_completed (Request.view r) st - - let on_no_request _ = Lwt.return_unit - - let on_close _w = Lwt.return_unit -end - -let table = Worker.create_table Queue - -let worker_promise, worker_waker = Lwt.task () - -let start node_ctxt = - let open Lwt_result_syntax in - let*! () = Refutation_game_event.Coordinator.starting () in - let cctxt = - new Protocol_client_context.wrap_full node_ctxt.Node_context.cctxt - in - let+ worker = Worker.launch table () {node_ctxt; cctxt} (module Handlers) in - Lwt.wakeup worker_waker worker - -let init node_ctxt = - let open Lwt_result_syntax in - match Lwt.state worker_promise with - | Lwt.Return _ -> - (* Worker already started, nothing to do. *) - return_unit - | Lwt.Fail exn -> - (* Worker crashed, not recoverable. *) - fail [Sc_rollup_node_errors.No_refutation_coordinator; Exn exn] - | Lwt.Sleep -> - (* Never started, start it. *) - start node_ctxt - -(* This is a refutation coordinator for a single scoru *) -let worker = - lazy - (match Lwt.state worker_promise with - | Lwt.Return worker -> ok worker - | Lwt.Fail _ | Lwt.Sleep -> - error Sc_rollup_node_errors.No_refutation_coordinator) - -let process b = - let open Lwt_result_syntax in - let*? w = Lazy.force worker in - let*! (_pushed : bool) = Worker.Queue.push_request w (Request.Process b) in - return_unit - -let shutdown () = - let open Lwt_syntax in - let w = Lazy.force worker in - match w with - | Error _ -> - (* There is no refutation coordinator, nothing to do *) - Lwt.return_unit - | Ok w -> - (* Shut down all current refutation players *) - let games = Player.current_games () in - let* () = - List.iter_s (fun (_opponent, player) -> Player.shutdown player) games - in - Worker.shutdown w diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.ml deleted file mode 100644 index 1253dc7ef02d..000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.ml +++ /dev/null @@ -1,252 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -(** This module implements the refutation game logic of the rollup - node. - - When a new L1 block arises, the rollup node asks the L1 node for - the current game it is part of, if any. - - If a game is running and it is the rollup operator turn, the rollup - node injects the next move of the winning strategy. - - If a game is running and it is not the rollup operator turn, the - rollup node asks the L1 node whether the timeout is reached to play - the timeout argument if possible. - - Otherwise, if no game is running, the rollup node asks the L1 node - whether there is a conflict with one of its disputable commitments. If - there is such a conflict with a commitment C', then the rollup node - starts a game to refute C' by starting a game with one of its staker. - -*) - -open Game -open Refutation_game_helpers - -let node_role ~self {alice; bob} = - if Signature.Public_key_hash.equal alice self then Alice - else if Signature.Public_key_hash.equal bob self then Bob - else (* By validity of [ongoing_game] RPC. *) - assert false - -type role = Our_turn of {opponent : Signature.public_key_hash} | Their_turn - -let turn ~self game ({alice; bob} as players) = - match (node_role ~self players, game.turn) with - | Alice, Alice -> Our_turn {opponent = bob} - | Bob, Bob -> Our_turn {opponent = alice} - | Alice, Bob -> Their_turn - | Bob, Alice -> Their_turn - -(** [inject_next_move node_ctxt source ~refutation ~opponent ~commitment - ~opponent_commitment] submits an L1 operation (signed by [source]) to - issue the next move in the refutation game. *) -let inject_next_move node_ctxt source ~refutation ~opponent = - let open Lwt_result_syntax in - let refute_operation = - L1_operation.Refute - {rollup = node_ctxt.Node_context.rollup_address; refutation; opponent} - in - let* _hash = Injector.add_pending_operation ~source refute_operation in - return_unit - -type pvm_intermediate_state = - | Hash of State_hash.t - | Evaluated of Fuel.Accounted.t Pvm_plugin_sig.eval_state - -let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok - our_view = - let open Lwt_result_syntax in - let start_hash, start_tick, start_state = - match ok with - | Hash hash, tick -> (hash, tick, None) - | Evaluated ({state_hash; _} as state), tick -> - (state_hash, tick, Some state) - in - let start_chunk = Game.{state_hash = Some start_hash; tick = start_tick} in - let our_state, our_tick = our_view in - let our_state_hash = - Option.map (fun Pvm_plugin_sig.{state_hash; _} -> state_hash) our_state - in - let our_stop_chunk = Game.{state_hash = our_state_hash; tick = our_tick} in - let* dissection = - make_dissection - node_ctxt - ~start_state - ~start_chunk - ~our_stop_chunk - ~default_number_of_sections - ~last_level - in - let*! () = - Refutation_game_event.computed_dissection - ~opponent - ~start_tick - ~end_tick:our_tick - dissection - in - return dissection - -(** [generate_from_dissection ~default_number_of_sections node_ctxt game - dissection] traverses the current [dissection] and returns a move which - performs a new dissection of the execution trace or provides a refutation - proof to serve as the next move of the [game]. *) -let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent - (game : Octez_smart_rollup.Game.t) - (dissection : Octez_smart_rollup.Game.dissection_chunk list) = - let open Lwt_result_syntax in - let rec traverse ok = function - | [] -> - (* The game invariant states that the dissection from the - opponent must contain a tick we disagree with. If the - retrieved game does not respect this, we cannot trust the - Tezos node we are connected to and prefer to stop here. *) - tzfail - Sc_rollup_node_errors - .Unreliable_tezos_node_returning_inconsistent_game - | Octez_smart_rollup.Game.{state_hash = their_hash; tick} :: dissection -> ( - let start_state = - match ok with - | Hash _, _ -> None - | Evaluated ok_state, _ -> Some ok_state - in - let* our = - state_of_tick node_ctxt ?start_state ~tick game.inbox_level - in - match (their_hash, our) with - | None, None -> - (* This case is absurd since: [None] can only occur at the - end and the two players disagree about the end. *) - assert false - | Some _, None | None, Some _ -> return (ok, (our, tick)) - | Some their_hash, Some ({state_hash = our_hash; _} as our_state) -> - if Octez_smart_rollup.State_hash.equal our_hash their_hash then - traverse (Evaluated our_state, tick) dissection - else return (ok, (our, tick))) - in - match dissection with - | {state_hash = Some hash; tick} :: dissection -> - let* ok, ko = traverse (Hash hash, tick) dissection in - let* dissection = - new_dissection - ~opponent - ~default_number_of_sections - node_ctxt - game.inbox_level - ok - ko - in - let _, choice = ok in - let _, ko_tick = ko in - let chosen_section_len = Z.abs (Z.sub choice ko_tick) in - return (choice, chosen_section_len, dissection) - | [] | {state_hash = None; _} :: _ -> - (* - By wellformedness of dissection. - A dissection always starts with a tick of the form [(Some hash, tick)]. - A dissection always contains strictly more than one element. - *) - tzfail - Sc_rollup_node_errors.Unreliable_tezos_node_returning_inconsistent_game - -let next_move node_ctxt ~opponent (game : Octez_smart_rollup.Game.t) = - let open Lwt_result_syntax in - let final_move start_tick = - let* start_state = - state_of_tick node_ctxt ~tick:start_tick game.inbox_level - in - match start_state with - | None -> - tzfail - Sc_rollup_node_errors - .Unreliable_tezos_node_returning_inconsistent_game - | Some {state = start_state; _} -> - let* proof = generate_proof node_ctxt game start_state in - let choice = start_tick in - return (Octez_smart_rollup.Game.Move {choice; step = Proof proof}) - in - - match game.game_state with - | Dissecting {dissection; default_number_of_sections} -> - let* choice, chosen_section_len, dissection = - generate_next_dissection - ~default_number_of_sections - node_ctxt - ~opponent - game - dissection - in - if Z.(equal chosen_section_len one) then final_move choice - else - return - (Octez_smart_rollup.Game.Move {choice; step = Dissection dissection}) - | Final_move {agreed_start_chunk; refuted_stop_chunk = _} -> - let choice = agreed_start_chunk.tick in - final_move choice - -let play_next_move node_ctxt game self opponent = - let open Lwt_result_syntax in - let* refutation = next_move node_ctxt ~opponent game in - inject_next_move node_ctxt self ~refutation ~opponent - -let play_timeout (node_ctxt : _ Node_context.t) self stakers = - let open Lwt_result_syntax in - let timeout_operation = - L1_operation.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 - let* _hash = Injector.add_pending_operation ~source timeout_operation in - return_unit - -let play node_ctxt ~self game opponent = - let open Lwt_result_syntax in - let index = make_index self opponent in - match turn ~self game index with - | Our_turn {opponent} -> play_next_move node_ctxt game self opponent - | Their_turn -> - let* timeout_reached = timeout_reached node_ctxt ~self ~opponent in - when_ timeout_reached @@ fun () -> - let*! () = Refutation_game_event.timeout_detected opponent in - play_timeout node_ctxt self index - -let play_opening_move node_ctxt self - (conflict : Octez_smart_rollup.Game.conflict) = - let open Lwt_syntax in - let* () = Refutation_game_event.conflict_detected conflict in - let player_commitment_hash = - Octez_smart_rollup.Commitment.hash conflict.our_commitment - in - let opponent_commitment_hash = - Octez_smart_rollup.Commitment.hash conflict.their_commitment - in - let refutation = - Octez_smart_rollup.Game.Start - {player_commitment_hash; opponent_commitment_hash} - in - inject_next_move node_ctxt self ~refutation ~opponent:conflict.other diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.mli deleted file mode 100644 index 1f8668ebb042..000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_game.mli +++ /dev/null @@ -1,43 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -(** This module implements the refutation game logic of the rollup node. *) - -(** [play_opening_move node_ctxt self conflict] injects the opening refutation - game move for [conflict]. *) -val play_opening_move : - [< `Read | `Write > `Read] Node_context.t -> - Signature.public_key_hash -> - Octez_smart_rollup.Game.conflict -> - (unit, tztrace) result Lwt.t - -(** [play head_block node_ctxt ~self game opponent] injects the next move in the - refutation [game] played by [self] and [opponent]. *) -val play : - Node_context.rw -> - self:Signature.public_key_hash -> - Octez_smart_rollup.Game.t -> - Signature.public_key_hash -> - (unit, tztrace) result Lwt.t diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player.ml deleted file mode 100644 index 3d7c8d596905..000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player.ml +++ /dev/null @@ -1,178 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 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 Refutation_player_types -open Refutation_game - -module Types = struct - type state = { - node_ctxt : Node_context.rw; - self : Signature.public_key_hash; - opponent : Signature.public_key_hash; - mutable last_move_cache : - (Octez_smart_rollup.Game.game_state * int32) option; - } - - type parameters = { - node_ctxt : Node_context.rw; - self : Signature.public_key_hash; - conflict : Octez_smart_rollup.Game.conflict; - } -end - -module Name = struct - let base = Refutation_game_event.Player.section @ ["worker"] - - include Signature.Public_key_hash -end - -module Worker = Worker.MakeSingle (Name) (Request) (Types) - -type worker = Worker.infinite Worker.queue Worker.t - -let table = Worker.create_table Queue - -let on_play game Types.{node_ctxt; self; opponent; _} = - play node_ctxt ~self game opponent - -let on_play_opening conflict (Types.{node_ctxt; self; _} : Types.state) = - play_opening_move node_ctxt self conflict - -module Handlers = struct - type self = worker - - let on_request : - type r request_error. - worker -> (r, request_error) Request.t -> (r, request_error) result Lwt.t - = - fun w request -> - let state = Worker.state w in - match request with - | Request.Play game -> on_play game state - | Request.Play_opening conflict -> on_play_opening conflict state - - type launch_error = error trace - - let on_launch _w _name Types.{node_ctxt; self; conflict} = - return - Types.{node_ctxt; self; opponent = conflict.other; last_move_cache = None} - - let on_error (type a b) _w st (r : (a, b) Request.t) (errs : b) : - unit tzresult Lwt.t = - let open Lwt_result_syntax in - let request_view = Request.view r in - let emit_and_return_errors errs = - let*! () = - Refutation_game_event.Player.request_failed request_view st errs - in - return_unit - in - match r with - | Request.Play _ -> emit_and_return_errors errs - | Request.Play_opening _ -> emit_and_return_errors errs - - let on_completion _w r _ st = - Refutation_game_event.Player.request_completed (Request.view r) st - - let on_no_request _ = Lwt.return_unit - - let on_close w = - let open Lwt_syntax in - let state = Worker.state w in - let* () = Refutation_game_event.Player.stopped state.opponent in - return_unit -end - -let init node_ctxt ~self ~conflict = - let open Lwt_result_syntax in - let*! () = - Refutation_game_event.Player.started - conflict.Game.other - conflict.Game.our_commitment - in - let worker_promise, worker_waker = Lwt.task () in - let* worker = - trace Sc_rollup_node_errors.Refutation_player_failed_to_start - @@ Worker.launch - table - conflict.other - {node_ctxt; self; conflict} - (module Handlers) - in - let () = Lwt.wakeup worker_waker worker in - let worker = - match Lwt.state worker_promise with - | Lwt.Return worker -> ok worker - | Lwt.Fail _ | Lwt.Sleep -> - error Sc_rollup_node_errors.Refutation_player_failed_to_start - in - Lwt.return worker - -(* Play if: - - There's a new game state to play against or - - The current level is past the buffer for re-playing in the - same game state. -*) -let should_move ~level game last_move_cache = - match last_move_cache with - | None -> true - | Some (last_move_game_state, last_move_level) -> - (not (Game.game_state_equal game.Game.game_state last_move_game_state)) - || Int32.( - sub level last_move_level - > of_int Configuration.refutation_player_buffer_levels) - -let play w game ~(level : int32) = - let open Lwt_syntax in - let state = Worker.state w in - if should_move ~level game state.last_move_cache then ( - let* pushed = Worker.Queue.push_request w (Request.Play game) in - if pushed then state.last_move_cache <- Some (game.Game.game_state, level) ; - return_unit) - else return_unit - -let play_opening w conflict = - let open Lwt_syntax in - let* (_pushed : bool) = - Worker.Queue.push_request w (Request.Play_opening conflict) - in - return_unit - -let init_and_play node_ctxt ~self ~conflict ~game ~level = - let open Lwt_result_syntax in - let* worker = init node_ctxt ~self ~conflict in - let*! () = - match game with - | None -> play_opening worker conflict - | Some game -> play worker game ~level - in - return_unit - -let current_games () = - List.map - (fun (_name, worker) -> ((Worker.state worker).opponent, worker)) - (Worker.list table) - -let shutdown = Worker.shutdown diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player.mli deleted file mode 100644 index 64cca0e7e56a..000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/refutation_player.mli +++ /dev/null @@ -1,56 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 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. *) -(* *) -(*****************************************************************************) - -(** Worker module for a single refutation game player. The node's refutation - coordinator will spawn a new refutation player for each refutation game. -*) -module Worker : Worker.T - -(** Type for a refutation game player. *) -type worker = Worker.infinite Worker.queue Worker.t - -(** [init_and_play node_ctxt ~self ~conflict ~game ~level] initializes a new - refutation game player for signer [self]. After initizialization, the - worker will play the next move depending on the [game] state. If no [game] - is passed, the worker will play the opening move for [conflict]. *) -val init_and_play : - Node_context.rw -> - self:Signature.public_key_hash -> - conflict:Game.conflict -> - game:Game.t option -> - level:int32 -> - unit tzresult Lwt.t - -(** [play worker game ~level] makes the [worker] play the next move depending - on the [game] state for their conflict. - *) -val play : worker -> Game.t -> level:int32 -> unit Lwt.t - -(** Shutdown a refutaiton game player. *) -val shutdown : worker -> unit Lwt.t - -(** [current_games ()] lists the opponents' this node is playing refutation - games against, alongside the worker that takes care of each game. *) -val current_games : unit -> (Signature.public_key_hash * worker) list diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/rollup_node_plugin.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/rollup_node_plugin.ml index d54d5b667423..4c5dd5e5cfe4 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/rollup_node_plugin.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/rollup_node_plugin.ml @@ -30,7 +30,7 @@ module Plugin : Protocol_plugin_sig.S = struct module Dal_slots_tracker = Dal_slots_tracker module Inbox = Inbox module Interpreter = Interpreter - module Refutation_coordinator = Refutation_coordinator + module Refutation_game_helpers = Refutation_game_helpers module Batcher_constants = Batcher_constants module Layer1_helpers = Layer1_helpers module L1_processing = Daemon_helpers diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/daemon_helpers.ml b/src/proto_018_Proxford/lib_sc_rollup_node/daemon_helpers.ml index 57315ced452c..5e4a5a985102 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_node/daemon_helpers.ml +++ b/src/proto_018_Proxford/lib_sc_rollup_node/daemon_helpers.ml @@ -99,7 +99,7 @@ let accuser_publish_commitment_when_refutable node_ctxt ~other rollup Refutation_game_event.potential_conflict_detected ~our_commitment_hash ~their_commitment_hash - ~level:their_commitment.inbox_level + ~level:(Raw_level.to_int32 their_commitment.inbox_level) ~other in assert (Sc_rollup.Address.(node_ctxt.rollup_address = rollup)) ; diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_coordinator.mli b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_coordinator.mli deleted file mode 100644 index 12a35582b9b2..000000000000 --- a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_coordinator.mli +++ /dev/null @@ -1,47 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 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. *) -(* *) -(*****************************************************************************) - -(** Component for managing refutation games. - This module is implemented as a single worker in the rollup node, - which takes care of processing new L1 heads, and coordinating - the refutation game players. (See {!Refutation_player}). -*) - -(** Initiatilize the refuation coordinator. *) -val init : Node_context.rw -> unit tzresult Lwt.t - -(** Process a new l1 head. This means that the coordinator will: - {ol - {li Gather all existing conflicts} - {li Launch new refutation players for each conflict that doesn't - have a player in this node} - {li Kill all players whose conflict has disappeared from L1} - {li Make all players play a step in the refutation} - } - *) -val process : Layer1.head -> unit tzresult Lwt.t - -(** Shutdown the refutation coordinator. *) -val shutdown : unit -> unit Lwt.t diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game_event.ml b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game_event.ml deleted file mode 100644 index 9a6ebaf4c50c..000000000000 --- a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_game_event.ml +++ /dev/null @@ -1,261 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -open Protocol.Alpha_context - -(* TODO: https://gitlab.com/tezos/tezos/-/issues/2880 - Add corresponding .mli file. *) - -let section = [Protocol.name; "sc_rollup_node"; "refutation_game"] - -module Simple = struct - include Internal_event.Simple - - let timeout = - declare_1 - ~section - ~name:"sc_rollup_node_timeout" - ~msg: - "The rollup node has been slashed because of a timeout issued by \ - {address}" - ~level:Notice - ("address", Signature.Public_key_hash.encoding) - - let invalid_move = - declare_0 - ~section - ~name:"sc_rollup_node_invalid_move" - ~msg: - "The rollup node is about to make an invalid move in the refutation \ - game! It is stopped to avoid being slashed. The problem should be \ - reported immediately or the rollup node should be upgraded to have a \ - chance to be back before the timeout is reached." - ~level:Notice - () - - let conflict_detected = - declare_5 - ~section - ~name:"sc_rollup_node_conflict_detected" - ~msg: - "A conflict has been found with our commitment {our_commitment_hash} \ - at level {level} with staker {other} that hash issued commitment \ - {their_commitment_hash} both based on {parent_commitment_hash}." - ~level:Notice - ("our_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) - ("level", Data_encoding.int32) - ("other", Signature.Public_key_hash.encoding) - ("their_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) - ("parent_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) - - let potential_conflict_detected = - declare_4 - ~section - ~name:"sc_rollup_node_potential_conflict_detected" - ~msg: - "A potential conflict has been found with our commitment \ - {our_commitment_hash} at level {level} with staker {other} that hash \ - issued commitment {their_commitment_hash}." - ~level:Notice - ("our_commitment_hash", Sc_rollup.Commitment.Hash.encoding) - ("level", Raw_level.encoding) - ("other", Sc_rollup.Staker.encoding) - ("their_commitment_hash", Sc_rollup.Commitment.Hash.encoding) - - let timeout_detected = - declare_1 - ~section - ~name:"sc_rollup_node_timeout_detected" - ~msg: - "The rollup node has detected that opponent {other} can be timed out." - ~level:Notice - ("other", Sc_rollup.Staker.encoding) - - let dissection_chunk_encoding = - let open Data_encoding in - let open Sc_rollup.Dissection_chunk in - conv - (fun {state_hash; tick} -> (state_hash, tick)) - (fun (state_hash, tick) -> {state_hash; tick}) - (obj2 - (opt "state" Sc_rollup.State_hash.encoding) - (req "tick" Sc_rollup.Tick.encoding)) - - let computed_dissection = - declare_4 - ~section - ~name:"sc_rollup_node_computed_dissection" - ~msg: - "Computed dissection against {opponent} between ticks {start_tick} and \ - {end_tick}: {dissection}." - ~level:Debug - ("opponent", Signature.Public_key_hash.encoding) - ("start_tick", Data_encoding.z) - ("end_tick", Data_encoding.z) - ( "dissection", - Data_encoding.list Octez_smart_rollup.Game.dissection_chunk_encoding ) - - module Worker (ARG : sig - val section : string list - end) - (Request : Worker_intf.REQUEST) = - struct - include ARG - - let request_failed = - declare_3 - ~section - ~name:"request_failed" - ~msg:"request {view} failed ({worker_status}): {errors}" - ~level:Notice - ("view", Request.encoding) - ~pp1:Request.pp - ("worker_status", Worker_types.request_status_encoding) - ~pp2:Worker_types.pp_status - ("errors", Error_monad.trace_encoding) - ~pp3:Error_monad.pp_print_trace - - let request_completed = - declare_2 - ~section - ~name:"request_completed" - ~msg:"{view} {worker_status}" - ~level:Debug - ("view", Request.encoding) - ("worker_status", Worker_types.request_status_encoding) - ~pp1:Request.pp - ~pp2:Worker_types.pp_status - end - - module Player = struct - include - Worker - (struct - let section = section @ ["player"] - end) - (Refutation_player_types.Request) - - let started = - declare_2 - ~section - ~name:"player_started" - ~msg: - "refutation player started to play against {opponent}, defenfing \ - commitment {commitment}" - ~level:Notice - ("opponent", Signature.Public_key_hash.encoding) - ~pp1:Signature.Public_key_hash.pp - ("commitment", Octez_smart_rollup.Commitment.encoding) - ~pp2:Octez_smart_rollup.Commitment.pp - - let stopped = - declare_1 - ~section - ~name:"player_stopped" - ~msg:"refutation player for opponent {opponent} has been stopped" - ~level:Notice - ("opponent", Signature.Public_key_hash.encoding) - ~pp1:Signature.Public_key_hash.pp - end - - module Coordinator = struct - include - Worker - (struct - let section = section @ ["coordinator"] - end) - (Refutation_coordinator_types.Request) - - let starting = - declare_0 - ~section - ~name:"coordinator_starting" - ~msg:"Starting refutation coordinator for the smart rollup node" - ~level:Notice - () - end -end - -let timeout address = Simple.(emit timeout address) - -let invalid_move () = Simple.(emit invalid_move ()) - -let conflict_detected (conflict : Octez_smart_rollup.Game.conflict) = - let our_commitment_hash = - Octez_smart_rollup.Commitment.hash conflict.our_commitment - in - let their_commitment_hash = - Octez_smart_rollup.Commitment.hash conflict.their_commitment - in - let parent_commitment_hash = conflict.parent_commitment in - let other = conflict.other in - let level = conflict.our_commitment.inbox_level in - Simple.( - emit - conflict_detected - ( our_commitment_hash, - level, - other, - their_commitment_hash, - parent_commitment_hash )) - -let potential_conflict_detected ~our_commitment_hash ~their_commitment_hash - ~other ~level = - Simple.( - emit - potential_conflict_detected - (our_commitment_hash, level, other, their_commitment_hash)) - -let timeout_detected other = Simple.(emit timeout_detected other) - -let computed_dissection ~opponent ~start_tick ~end_tick dissection = - Simple.(emit computed_dissection (opponent, start_tick, end_tick, dissection)) - -module Player = struct - let section = Simple.Player.section - - let request_failed view worker_status errors = - Simple.(emit Player.request_failed (view, worker_status, errors)) - - let request_completed view worker_status = - Simple.(emit Player.request_completed (view, worker_status)) - - let started opponent commitment = - Simple.(emit Player.started (opponent, commitment)) - - let stopped opponent = Simple.(emit Player.stopped opponent) -end - -module Coordinator = struct - let section = Simple.Coordinator.section - - let request_failed view worker_status errors = - Simple.(emit Coordinator.request_failed (view, worker_status, errors)) - - let request_completed view worker_status = - Simple.(emit Coordinator.request_completed (view, worker_status)) - - let starting = Simple.(emit Coordinator.starting) -end diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_player.ml b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_player.ml deleted file mode 100644 index 3d7c8d596905..000000000000 --- a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_player.ml +++ /dev/null @@ -1,178 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 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 Refutation_player_types -open Refutation_game - -module Types = struct - type state = { - node_ctxt : Node_context.rw; - self : Signature.public_key_hash; - opponent : Signature.public_key_hash; - mutable last_move_cache : - (Octez_smart_rollup.Game.game_state * int32) option; - } - - type parameters = { - node_ctxt : Node_context.rw; - self : Signature.public_key_hash; - conflict : Octez_smart_rollup.Game.conflict; - } -end - -module Name = struct - let base = Refutation_game_event.Player.section @ ["worker"] - - include Signature.Public_key_hash -end - -module Worker = Worker.MakeSingle (Name) (Request) (Types) - -type worker = Worker.infinite Worker.queue Worker.t - -let table = Worker.create_table Queue - -let on_play game Types.{node_ctxt; self; opponent; _} = - play node_ctxt ~self game opponent - -let on_play_opening conflict (Types.{node_ctxt; self; _} : Types.state) = - play_opening_move node_ctxt self conflict - -module Handlers = struct - type self = worker - - let on_request : - type r request_error. - worker -> (r, request_error) Request.t -> (r, request_error) result Lwt.t - = - fun w request -> - let state = Worker.state w in - match request with - | Request.Play game -> on_play game state - | Request.Play_opening conflict -> on_play_opening conflict state - - type launch_error = error trace - - let on_launch _w _name Types.{node_ctxt; self; conflict} = - return - Types.{node_ctxt; self; opponent = conflict.other; last_move_cache = None} - - let on_error (type a b) _w st (r : (a, b) Request.t) (errs : b) : - unit tzresult Lwt.t = - let open Lwt_result_syntax in - let request_view = Request.view r in - let emit_and_return_errors errs = - let*! () = - Refutation_game_event.Player.request_failed request_view st errs - in - return_unit - in - match r with - | Request.Play _ -> emit_and_return_errors errs - | Request.Play_opening _ -> emit_and_return_errors errs - - let on_completion _w r _ st = - Refutation_game_event.Player.request_completed (Request.view r) st - - let on_no_request _ = Lwt.return_unit - - let on_close w = - let open Lwt_syntax in - let state = Worker.state w in - let* () = Refutation_game_event.Player.stopped state.opponent in - return_unit -end - -let init node_ctxt ~self ~conflict = - let open Lwt_result_syntax in - let*! () = - Refutation_game_event.Player.started - conflict.Game.other - conflict.Game.our_commitment - in - let worker_promise, worker_waker = Lwt.task () in - let* worker = - trace Sc_rollup_node_errors.Refutation_player_failed_to_start - @@ Worker.launch - table - conflict.other - {node_ctxt; self; conflict} - (module Handlers) - in - let () = Lwt.wakeup worker_waker worker in - let worker = - match Lwt.state worker_promise with - | Lwt.Return worker -> ok worker - | Lwt.Fail _ | Lwt.Sleep -> - error Sc_rollup_node_errors.Refutation_player_failed_to_start - in - Lwt.return worker - -(* Play if: - - There's a new game state to play against or - - The current level is past the buffer for re-playing in the - same game state. -*) -let should_move ~level game last_move_cache = - match last_move_cache with - | None -> true - | Some (last_move_game_state, last_move_level) -> - (not (Game.game_state_equal game.Game.game_state last_move_game_state)) - || Int32.( - sub level last_move_level - > of_int Configuration.refutation_player_buffer_levels) - -let play w game ~(level : int32) = - let open Lwt_syntax in - let state = Worker.state w in - if should_move ~level game state.last_move_cache then ( - let* pushed = Worker.Queue.push_request w (Request.Play game) in - if pushed then state.last_move_cache <- Some (game.Game.game_state, level) ; - return_unit) - else return_unit - -let play_opening w conflict = - let open Lwt_syntax in - let* (_pushed : bool) = - Worker.Queue.push_request w (Request.Play_opening conflict) - in - return_unit - -let init_and_play node_ctxt ~self ~conflict ~game ~level = - let open Lwt_result_syntax in - let* worker = init node_ctxt ~self ~conflict in - let*! () = - match game with - | None -> play_opening worker conflict - | Some game -> play worker game ~level - in - return_unit - -let current_games () = - List.map - (fun (_name, worker) -> ((Worker.state worker).opponent, worker)) - (Worker.list table) - -let shutdown = Worker.shutdown diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_player.mli b/src/proto_018_Proxford/lib_sc_rollup_node/refutation_player.mli deleted file mode 100644 index 64cca0e7e56a..000000000000 --- a/src/proto_018_Proxford/lib_sc_rollup_node/refutation_player.mli +++ /dev/null @@ -1,56 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 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. *) -(* *) -(*****************************************************************************) - -(** Worker module for a single refutation game player. The node's refutation - coordinator will spawn a new refutation player for each refutation game. -*) -module Worker : Worker.T - -(** Type for a refutation game player. *) -type worker = Worker.infinite Worker.queue Worker.t - -(** [init_and_play node_ctxt ~self ~conflict ~game ~level] initializes a new - refutation game player for signer [self]. After initizialization, the - worker will play the next move depending on the [game] state. If no [game] - is passed, the worker will play the opening move for [conflict]. *) -val init_and_play : - Node_context.rw -> - self:Signature.public_key_hash -> - conflict:Game.conflict -> - game:Game.t option -> - level:int32 -> - unit tzresult Lwt.t - -(** [play worker game ~level] makes the [worker] play the next move depending - on the [game] state for their conflict. - *) -val play : worker -> Game.t -> level:int32 -> unit Lwt.t - -(** Shutdown a refutaiton game player. *) -val shutdown : worker -> unit Lwt.t - -(** [current_games ()] lists the opponents' this node is playing refutation - games against, alongside the worker that takes care of each game. *) -val current_games : unit -> (Signature.public_key_hash * worker) list diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/rollup_node_plugin.ml b/src/proto_018_Proxford/lib_sc_rollup_node/rollup_node_plugin.ml index d54d5b667423..4c5dd5e5cfe4 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_node/rollup_node_plugin.ml +++ b/src/proto_018_Proxford/lib_sc_rollup_node/rollup_node_plugin.ml @@ -30,7 +30,7 @@ module Plugin : Protocol_plugin_sig.S = struct module Dal_slots_tracker = Dal_slots_tracker module Inbox = Inbox module Interpreter = Interpreter - module Refutation_coordinator = Refutation_coordinator + module Refutation_game_helpers = Refutation_game_helpers module Batcher_constants = Batcher_constants module Layer1_helpers = Layer1_helpers module L1_processing = Daemon_helpers diff --git a/src/proto_alpha/lib_sc_rollup_node/daemon_helpers.ml b/src/proto_alpha/lib_sc_rollup_node/daemon_helpers.ml index 57315ced452c..5e4a5a985102 100644 --- a/src/proto_alpha/lib_sc_rollup_node/daemon_helpers.ml +++ b/src/proto_alpha/lib_sc_rollup_node/daemon_helpers.ml @@ -99,7 +99,7 @@ let accuser_publish_commitment_when_refutable node_ctxt ~other rollup Refutation_game_event.potential_conflict_detected ~our_commitment_hash ~their_commitment_hash - ~level:their_commitment.inbox_level + ~level:(Raw_level.to_int32 their_commitment.inbox_level) ~other in assert (Sc_rollup.Address.(node_ctxt.rollup_address = rollup)) ; diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_coordinator.ml b/src/proto_alpha/lib_sc_rollup_node/refutation_coordinator.ml deleted file mode 100644 index 1ed4e1eb8efa..000000000000 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_coordinator.ml +++ /dev/null @@ -1,253 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 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 Refutation_coordinator_types -module Player = Refutation_player -module Pkh_map = Signature.Public_key_hash.Map -module Pkh_table = Signature.Public_key_hash.Table - -type state = { - node_ctxt : Node_context.rw; - cctxt : Protocol_client_context.full; - pending_opponents : unit Pkh_table.t; -} - -let get_conflicts cctxt head_block rollup staker = - let open Lwt_result_syntax in - let+ conflicts = - Plugin.RPC.Sc_rollup.conflicts cctxt (cctxt#chain, head_block) rollup staker - in - List.map Sc_rollup_proto_types.Game.conflict_to_octez conflicts - -let get_ongoing_games cctxt head_block rollup staker = - let open Lwt_result_syntax in - let+ games = - Plugin.RPC.Sc_rollup.ongoing_refutation_games - cctxt - (cctxt#chain, head_block) - rollup - staker - in - List.map - (fun (game, staker1, staker2) -> - (Sc_rollup_proto_types.Game.to_octez game, staker1, staker2)) - games - -let untracked_conflicts opponent_players conflicts = - List.filter - (fun conflict -> not @@ Pkh_map.mem conflict.Game.other opponent_players) - conflicts - -(* Transform the list of ongoing games [(Game.t * pkh * pkh) list] - into a mapping from opponents' pkhs to their corresponding game - state. -*) -let make_game_map self ongoing_games = - List.fold_left - (fun acc (game, alice, bob) -> - let opponent_pkh = - if Signature.Public_key_hash.equal self alice then bob else alice - in - Pkh_map.add opponent_pkh game acc) - Pkh_map.empty - ongoing_games - -let on_process Layer1.{hash; level} state = - let node_ctxt = state.node_ctxt in - let head_block = `Hash (hash, 0) in - let open Lwt_result_syntax in - 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 -> - let Node_context.{rollup_address; _} = node_ctxt in - (* Current conflicts in L1 *) - let* conflicts = - get_conflicts state.cctxt head_block rollup_address self - in - (* Map of opponents the node is playing against to the corresponding - player worker *) - let opponent_players = - Pkh_map.of_seq @@ List.to_seq @@ Player.current_games () - in - (* Conflicts for which we need to start new refutation players. - Some of these might be ongoing. *) - let new_conflicts = untracked_conflicts opponent_players conflicts in - (* L1 ongoing games *) - let* ongoing_games = - get_ongoing_games state.cctxt head_block rollup_address self - in - (* Map between opponents and their corresponding games *) - let ongoing_game_map = make_game_map self ongoing_games in - (* Launch new players for new conflicts, and play one step *) - let* () = - List.iter_ep - (fun conflict -> - let other = conflict.Octez_smart_rollup.Game.other in - Pkh_table.replace state.pending_opponents other () ; - let game = Pkh_map.find_opt other ongoing_game_map in - Player.init_and_play node_ctxt ~self ~conflict ~game ~level) - new_conflicts - in - let*! () = - (* Play one step of the refutation game in every remaining player *) - Pkh_map.iter_p - (fun opponent worker -> - match Pkh_map.find opponent ongoing_game_map with - | Some game -> - Pkh_table.remove state.pending_opponents opponent ; - Player.play worker game ~level - | None -> - (* Kill finished players: those who don't aren't - playing against pending opponents that don't have - ongoing games in the L1 *) - if not @@ Pkh_table.mem state.pending_opponents opponent then - Player.shutdown worker - else Lwt.return_unit) - opponent_players - in - return_unit - -module Types = struct - type nonrec state = state - - type parameters = { - node_ctxt : Node_context.rw; - cctxt : Protocol_client_context.full; - } -end - -module Name = struct - (* We only have a single coordinator in the node *) - type t = unit - - let encoding = Data_encoding.unit - - let base = - (* But we can have multiple instances in the unit tests. This is just to - avoid conflicts in the events declarations. *) - Refutation_game_event.Coordinator.section @ ["worker"] - - let pp _ _ = () - - let equal () () = true -end - -module Worker = Worker.MakeSingle (Name) (Request) (Types) - -type worker = Worker.infinite Worker.queue Worker.t - -module Handlers = struct - type self = worker - - let on_request : - type r request_error. - worker -> (r, request_error) Request.t -> (r, request_error) result Lwt.t - = - fun w request -> - let state = Worker.state w in - match request with Request.Process b -> on_process b state - - type launch_error = error trace - - let on_launch _w () Types.{node_ctxt; cctxt} = - return {node_ctxt; cctxt; pending_opponents = Pkh_table.create 5} - - let on_error (type a b) _w st (r : (a, b) Request.t) (errs : b) : - unit tzresult Lwt.t = - let open Lwt_result_syntax in - let request_view = Request.view r in - let emit_and_return_errors errs = - let*! () = - Refutation_game_event.Coordinator.request_failed request_view st errs - in - return_unit - in - match r with Request.Process _ -> emit_and_return_errors errs - - let on_completion _w r _ st = - Refutation_game_event.Coordinator.request_completed (Request.view r) st - - let on_no_request _ = Lwt.return_unit - - let on_close _w = Lwt.return_unit -end - -let table = Worker.create_table Queue - -let worker_promise, worker_waker = Lwt.task () - -let start node_ctxt = - let open Lwt_result_syntax in - let*! () = Refutation_game_event.Coordinator.starting () in - let cctxt = - new Protocol_client_context.wrap_full node_ctxt.Node_context.cctxt - in - let+ worker = Worker.launch table () {node_ctxt; cctxt} (module Handlers) in - Lwt.wakeup worker_waker worker - -let init node_ctxt = - let open Lwt_result_syntax in - match Lwt.state worker_promise with - | Lwt.Return _ -> - (* Worker already started, nothing to do. *) - return_unit - | Lwt.Fail exn -> - (* Worker crashed, not recoverable. *) - fail [Sc_rollup_node_errors.No_refutation_coordinator; Exn exn] - | Lwt.Sleep -> - (* Never started, start it. *) - start node_ctxt - -(* This is a refutation coordinator for a single scoru *) -let worker = - lazy - (match Lwt.state worker_promise with - | Lwt.Return worker -> ok worker - | Lwt.Fail _ | Lwt.Sleep -> - error Sc_rollup_node_errors.No_refutation_coordinator) - -let process b = - let open Lwt_result_syntax in - let*? w = Lazy.force worker in - let*! (_pushed : bool) = Worker.Queue.push_request w (Request.Process b) in - return_unit - -let shutdown () = - let open Lwt_syntax in - let w = Lazy.force worker in - match w with - | Error _ -> - (* There is no refutation coordinator, nothing to do *) - Lwt.return_unit - | Ok w -> - (* Shut down all current refutation players *) - let games = Player.current_games () in - let* () = - List.iter_s (fun (_opponent, player) -> Player.shutdown player) games - in - Worker.shutdown w diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_coordinator.mli b/src/proto_alpha/lib_sc_rollup_node/refutation_coordinator.mli deleted file mode 100644 index 12a35582b9b2..000000000000 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_coordinator.mli +++ /dev/null @@ -1,47 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 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. *) -(* *) -(*****************************************************************************) - -(** Component for managing refutation games. - This module is implemented as a single worker in the rollup node, - which takes care of processing new L1 heads, and coordinating - the refutation game players. (See {!Refutation_player}). -*) - -(** Initiatilize the refuation coordinator. *) -val init : Node_context.rw -> unit tzresult Lwt.t - -(** Process a new l1 head. This means that the coordinator will: - {ol - {li Gather all existing conflicts} - {li Launch new refutation players for each conflict that doesn't - have a player in this node} - {li Kill all players whose conflict has disappeared from L1} - {li Make all players play a step in the refutation} - } - *) -val process : Layer1.head -> unit tzresult Lwt.t - -(** Shutdown the refutation coordinator. *) -val shutdown : unit -> unit Lwt.t diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_game.ml b/src/proto_alpha/lib_sc_rollup_node/refutation_game.ml deleted file mode 100644 index 1253dc7ef02d..000000000000 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_game.ml +++ /dev/null @@ -1,252 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -(** This module implements the refutation game logic of the rollup - node. - - When a new L1 block arises, the rollup node asks the L1 node for - the current game it is part of, if any. - - If a game is running and it is the rollup operator turn, the rollup - node injects the next move of the winning strategy. - - If a game is running and it is not the rollup operator turn, the - rollup node asks the L1 node whether the timeout is reached to play - the timeout argument if possible. - - Otherwise, if no game is running, the rollup node asks the L1 node - whether there is a conflict with one of its disputable commitments. If - there is such a conflict with a commitment C', then the rollup node - starts a game to refute C' by starting a game with one of its staker. - -*) - -open Game -open Refutation_game_helpers - -let node_role ~self {alice; bob} = - if Signature.Public_key_hash.equal alice self then Alice - else if Signature.Public_key_hash.equal bob self then Bob - else (* By validity of [ongoing_game] RPC. *) - assert false - -type role = Our_turn of {opponent : Signature.public_key_hash} | Their_turn - -let turn ~self game ({alice; bob} as players) = - match (node_role ~self players, game.turn) with - | Alice, Alice -> Our_turn {opponent = bob} - | Bob, Bob -> Our_turn {opponent = alice} - | Alice, Bob -> Their_turn - | Bob, Alice -> Their_turn - -(** [inject_next_move node_ctxt source ~refutation ~opponent ~commitment - ~opponent_commitment] submits an L1 operation (signed by [source]) to - issue the next move in the refutation game. *) -let inject_next_move node_ctxt source ~refutation ~opponent = - let open Lwt_result_syntax in - let refute_operation = - L1_operation.Refute - {rollup = node_ctxt.Node_context.rollup_address; refutation; opponent} - in - let* _hash = Injector.add_pending_operation ~source refute_operation in - return_unit - -type pvm_intermediate_state = - | Hash of State_hash.t - | Evaluated of Fuel.Accounted.t Pvm_plugin_sig.eval_state - -let new_dissection ~opponent ~default_number_of_sections node_ctxt last_level ok - our_view = - let open Lwt_result_syntax in - let start_hash, start_tick, start_state = - match ok with - | Hash hash, tick -> (hash, tick, None) - | Evaluated ({state_hash; _} as state), tick -> - (state_hash, tick, Some state) - in - let start_chunk = Game.{state_hash = Some start_hash; tick = start_tick} in - let our_state, our_tick = our_view in - let our_state_hash = - Option.map (fun Pvm_plugin_sig.{state_hash; _} -> state_hash) our_state - in - let our_stop_chunk = Game.{state_hash = our_state_hash; tick = our_tick} in - let* dissection = - make_dissection - node_ctxt - ~start_state - ~start_chunk - ~our_stop_chunk - ~default_number_of_sections - ~last_level - in - let*! () = - Refutation_game_event.computed_dissection - ~opponent - ~start_tick - ~end_tick:our_tick - dissection - in - return dissection - -(** [generate_from_dissection ~default_number_of_sections node_ctxt game - dissection] traverses the current [dissection] and returns a move which - performs a new dissection of the execution trace or provides a refutation - proof to serve as the next move of the [game]. *) -let generate_next_dissection ~default_number_of_sections node_ctxt ~opponent - (game : Octez_smart_rollup.Game.t) - (dissection : Octez_smart_rollup.Game.dissection_chunk list) = - let open Lwt_result_syntax in - let rec traverse ok = function - | [] -> - (* The game invariant states that the dissection from the - opponent must contain a tick we disagree with. If the - retrieved game does not respect this, we cannot trust the - Tezos node we are connected to and prefer to stop here. *) - tzfail - Sc_rollup_node_errors - .Unreliable_tezos_node_returning_inconsistent_game - | Octez_smart_rollup.Game.{state_hash = their_hash; tick} :: dissection -> ( - let start_state = - match ok with - | Hash _, _ -> None - | Evaluated ok_state, _ -> Some ok_state - in - let* our = - state_of_tick node_ctxt ?start_state ~tick game.inbox_level - in - match (their_hash, our) with - | None, None -> - (* This case is absurd since: [None] can only occur at the - end and the two players disagree about the end. *) - assert false - | Some _, None | None, Some _ -> return (ok, (our, tick)) - | Some their_hash, Some ({state_hash = our_hash; _} as our_state) -> - if Octez_smart_rollup.State_hash.equal our_hash their_hash then - traverse (Evaluated our_state, tick) dissection - else return (ok, (our, tick))) - in - match dissection with - | {state_hash = Some hash; tick} :: dissection -> - let* ok, ko = traverse (Hash hash, tick) dissection in - let* dissection = - new_dissection - ~opponent - ~default_number_of_sections - node_ctxt - game.inbox_level - ok - ko - in - let _, choice = ok in - let _, ko_tick = ko in - let chosen_section_len = Z.abs (Z.sub choice ko_tick) in - return (choice, chosen_section_len, dissection) - | [] | {state_hash = None; _} :: _ -> - (* - By wellformedness of dissection. - A dissection always starts with a tick of the form [(Some hash, tick)]. - A dissection always contains strictly more than one element. - *) - tzfail - Sc_rollup_node_errors.Unreliable_tezos_node_returning_inconsistent_game - -let next_move node_ctxt ~opponent (game : Octez_smart_rollup.Game.t) = - let open Lwt_result_syntax in - let final_move start_tick = - let* start_state = - state_of_tick node_ctxt ~tick:start_tick game.inbox_level - in - match start_state with - | None -> - tzfail - Sc_rollup_node_errors - .Unreliable_tezos_node_returning_inconsistent_game - | Some {state = start_state; _} -> - let* proof = generate_proof node_ctxt game start_state in - let choice = start_tick in - return (Octez_smart_rollup.Game.Move {choice; step = Proof proof}) - in - - match game.game_state with - | Dissecting {dissection; default_number_of_sections} -> - let* choice, chosen_section_len, dissection = - generate_next_dissection - ~default_number_of_sections - node_ctxt - ~opponent - game - dissection - in - if Z.(equal chosen_section_len one) then final_move choice - else - return - (Octez_smart_rollup.Game.Move {choice; step = Dissection dissection}) - | Final_move {agreed_start_chunk; refuted_stop_chunk = _} -> - let choice = agreed_start_chunk.tick in - final_move choice - -let play_next_move node_ctxt game self opponent = - let open Lwt_result_syntax in - let* refutation = next_move node_ctxt ~opponent game in - inject_next_move node_ctxt self ~refutation ~opponent - -let play_timeout (node_ctxt : _ Node_context.t) self stakers = - let open Lwt_result_syntax in - let timeout_operation = - L1_operation.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 - let* _hash = Injector.add_pending_operation ~source timeout_operation in - return_unit - -let play node_ctxt ~self game opponent = - let open Lwt_result_syntax in - let index = make_index self opponent in - match turn ~self game index with - | Our_turn {opponent} -> play_next_move node_ctxt game self opponent - | Their_turn -> - let* timeout_reached = timeout_reached node_ctxt ~self ~opponent in - when_ timeout_reached @@ fun () -> - let*! () = Refutation_game_event.timeout_detected opponent in - play_timeout node_ctxt self index - -let play_opening_move node_ctxt self - (conflict : Octez_smart_rollup.Game.conflict) = - let open Lwt_syntax in - let* () = Refutation_game_event.conflict_detected conflict in - let player_commitment_hash = - Octez_smart_rollup.Commitment.hash conflict.our_commitment - in - let opponent_commitment_hash = - Octez_smart_rollup.Commitment.hash conflict.their_commitment - in - let refutation = - Octez_smart_rollup.Game.Start - {player_commitment_hash; opponent_commitment_hash} - in - inject_next_move node_ctxt self ~refutation ~opponent:conflict.other diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_game.mli b/src/proto_alpha/lib_sc_rollup_node/refutation_game.mli deleted file mode 100644 index 1f8668ebb042..000000000000 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_game.mli +++ /dev/null @@ -1,43 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -(** This module implements the refutation game logic of the rollup node. *) - -(** [play_opening_move node_ctxt self conflict] injects the opening refutation - game move for [conflict]. *) -val play_opening_move : - [< `Read | `Write > `Read] Node_context.t -> - Signature.public_key_hash -> - Octez_smart_rollup.Game.conflict -> - (unit, tztrace) result Lwt.t - -(** [play head_block node_ctxt ~self game opponent] injects the next move in the - refutation [game] played by [self] and [opponent]. *) -val play : - Node_context.rw -> - self:Signature.public_key_hash -> - Octez_smart_rollup.Game.t -> - Signature.public_key_hash -> - (unit, tztrace) result Lwt.t diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_game_event.ml b/src/proto_alpha/lib_sc_rollup_node/refutation_game_event.ml deleted file mode 100644 index 9a6ebaf4c50c..000000000000 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_game_event.ml +++ /dev/null @@ -1,261 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* Permission is hereby granted, free of charge, to any person obtaining a *) -(* copy of this software and associated documentation files (the "Software"),*) -(* to deal in the Software without restriction, including without limitation *) -(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) -(* and/or sell copies of the Software, and to permit persons to whom the *) -(* Software is furnished to do so, subject to the following conditions: *) -(* *) -(* The above copyright notice and this permission notice shall be included *) -(* in all copies or substantial portions of the Software. *) -(* *) -(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) -(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) -(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) -(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) -(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) -(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) -(* DEALINGS IN THE SOFTWARE. *) -(* *) -(*****************************************************************************) - -open Protocol.Alpha_context - -(* TODO: https://gitlab.com/tezos/tezos/-/issues/2880 - Add corresponding .mli file. *) - -let section = [Protocol.name; "sc_rollup_node"; "refutation_game"] - -module Simple = struct - include Internal_event.Simple - - let timeout = - declare_1 - ~section - ~name:"sc_rollup_node_timeout" - ~msg: - "The rollup node has been slashed because of a timeout issued by \ - {address}" - ~level:Notice - ("address", Signature.Public_key_hash.encoding) - - let invalid_move = - declare_0 - ~section - ~name:"sc_rollup_node_invalid_move" - ~msg: - "The rollup node is about to make an invalid move in the refutation \ - game! It is stopped to avoid being slashed. The problem should be \ - reported immediately or the rollup node should be upgraded to have a \ - chance to be back before the timeout is reached." - ~level:Notice - () - - let conflict_detected = - declare_5 - ~section - ~name:"sc_rollup_node_conflict_detected" - ~msg: - "A conflict has been found with our commitment {our_commitment_hash} \ - at level {level} with staker {other} that hash issued commitment \ - {their_commitment_hash} both based on {parent_commitment_hash}." - ~level:Notice - ("our_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) - ("level", Data_encoding.int32) - ("other", Signature.Public_key_hash.encoding) - ("their_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) - ("parent_commitment_hash", Octez_smart_rollup.Commitment.Hash.encoding) - - let potential_conflict_detected = - declare_4 - ~section - ~name:"sc_rollup_node_potential_conflict_detected" - ~msg: - "A potential conflict has been found with our commitment \ - {our_commitment_hash} at level {level} with staker {other} that hash \ - issued commitment {their_commitment_hash}." - ~level:Notice - ("our_commitment_hash", Sc_rollup.Commitment.Hash.encoding) - ("level", Raw_level.encoding) - ("other", Sc_rollup.Staker.encoding) - ("their_commitment_hash", Sc_rollup.Commitment.Hash.encoding) - - let timeout_detected = - declare_1 - ~section - ~name:"sc_rollup_node_timeout_detected" - ~msg: - "The rollup node has detected that opponent {other} can be timed out." - ~level:Notice - ("other", Sc_rollup.Staker.encoding) - - let dissection_chunk_encoding = - let open Data_encoding in - let open Sc_rollup.Dissection_chunk in - conv - (fun {state_hash; tick} -> (state_hash, tick)) - (fun (state_hash, tick) -> {state_hash; tick}) - (obj2 - (opt "state" Sc_rollup.State_hash.encoding) - (req "tick" Sc_rollup.Tick.encoding)) - - let computed_dissection = - declare_4 - ~section - ~name:"sc_rollup_node_computed_dissection" - ~msg: - "Computed dissection against {opponent} between ticks {start_tick} and \ - {end_tick}: {dissection}." - ~level:Debug - ("opponent", Signature.Public_key_hash.encoding) - ("start_tick", Data_encoding.z) - ("end_tick", Data_encoding.z) - ( "dissection", - Data_encoding.list Octez_smart_rollup.Game.dissection_chunk_encoding ) - - module Worker (ARG : sig - val section : string list - end) - (Request : Worker_intf.REQUEST) = - struct - include ARG - - let request_failed = - declare_3 - ~section - ~name:"request_failed" - ~msg:"request {view} failed ({worker_status}): {errors}" - ~level:Notice - ("view", Request.encoding) - ~pp1:Request.pp - ("worker_status", Worker_types.request_status_encoding) - ~pp2:Worker_types.pp_status - ("errors", Error_monad.trace_encoding) - ~pp3:Error_monad.pp_print_trace - - let request_completed = - declare_2 - ~section - ~name:"request_completed" - ~msg:"{view} {worker_status}" - ~level:Debug - ("view", Request.encoding) - ("worker_status", Worker_types.request_status_encoding) - ~pp1:Request.pp - ~pp2:Worker_types.pp_status - end - - module Player = struct - include - Worker - (struct - let section = section @ ["player"] - end) - (Refutation_player_types.Request) - - let started = - declare_2 - ~section - ~name:"player_started" - ~msg: - "refutation player started to play against {opponent}, defenfing \ - commitment {commitment}" - ~level:Notice - ("opponent", Signature.Public_key_hash.encoding) - ~pp1:Signature.Public_key_hash.pp - ("commitment", Octez_smart_rollup.Commitment.encoding) - ~pp2:Octez_smart_rollup.Commitment.pp - - let stopped = - declare_1 - ~section - ~name:"player_stopped" - ~msg:"refutation player for opponent {opponent} has been stopped" - ~level:Notice - ("opponent", Signature.Public_key_hash.encoding) - ~pp1:Signature.Public_key_hash.pp - end - - module Coordinator = struct - include - Worker - (struct - let section = section @ ["coordinator"] - end) - (Refutation_coordinator_types.Request) - - let starting = - declare_0 - ~section - ~name:"coordinator_starting" - ~msg:"Starting refutation coordinator for the smart rollup node" - ~level:Notice - () - end -end - -let timeout address = Simple.(emit timeout address) - -let invalid_move () = Simple.(emit invalid_move ()) - -let conflict_detected (conflict : Octez_smart_rollup.Game.conflict) = - let our_commitment_hash = - Octez_smart_rollup.Commitment.hash conflict.our_commitment - in - let their_commitment_hash = - Octez_smart_rollup.Commitment.hash conflict.their_commitment - in - let parent_commitment_hash = conflict.parent_commitment in - let other = conflict.other in - let level = conflict.our_commitment.inbox_level in - Simple.( - emit - conflict_detected - ( our_commitment_hash, - level, - other, - their_commitment_hash, - parent_commitment_hash )) - -let potential_conflict_detected ~our_commitment_hash ~their_commitment_hash - ~other ~level = - Simple.( - emit - potential_conflict_detected - (our_commitment_hash, level, other, their_commitment_hash)) - -let timeout_detected other = Simple.(emit timeout_detected other) - -let computed_dissection ~opponent ~start_tick ~end_tick dissection = - Simple.(emit computed_dissection (opponent, start_tick, end_tick, dissection)) - -module Player = struct - let section = Simple.Player.section - - let request_failed view worker_status errors = - Simple.(emit Player.request_failed (view, worker_status, errors)) - - let request_completed view worker_status = - Simple.(emit Player.request_completed (view, worker_status)) - - let started opponent commitment = - Simple.(emit Player.started (opponent, commitment)) - - let stopped opponent = Simple.(emit Player.stopped opponent) -end - -module Coordinator = struct - let section = Simple.Coordinator.section - - let request_failed view worker_status errors = - Simple.(emit Coordinator.request_failed (view, worker_status, errors)) - - let request_completed view worker_status = - Simple.(emit Coordinator.request_completed (view, worker_status)) - - let starting = Simple.(emit Coordinator.starting) -end diff --git a/src/proto_alpha/lib_sc_rollup_node/refutation_player.mli b/src/proto_alpha/lib_sc_rollup_node/refutation_player.mli deleted file mode 100644 index 64cca0e7e56a..000000000000 --- a/src/proto_alpha/lib_sc_rollup_node/refutation_player.mli +++ /dev/null @@ -1,56 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2023 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. *) -(* *) -(*****************************************************************************) - -(** Worker module for a single refutation game player. The node's refutation - coordinator will spawn a new refutation player for each refutation game. -*) -module Worker : Worker.T - -(** Type for a refutation game player. *) -type worker = Worker.infinite Worker.queue Worker.t - -(** [init_and_play node_ctxt ~self ~conflict ~game ~level] initializes a new - refutation game player for signer [self]. After initizialization, the - worker will play the next move depending on the [game] state. If no [game] - is passed, the worker will play the opening move for [conflict]. *) -val init_and_play : - Node_context.rw -> - self:Signature.public_key_hash -> - conflict:Game.conflict -> - game:Game.t option -> - level:int32 -> - unit tzresult Lwt.t - -(** [play worker game ~level] makes the [worker] play the next move depending - on the [game] state for their conflict. - *) -val play : worker -> Game.t -> level:int32 -> unit Lwt.t - -(** Shutdown a refutaiton game player. *) -val shutdown : worker -> unit Lwt.t - -(** [current_games ()] lists the opponents' this node is playing refutation - games against, alongside the worker that takes care of each game. *) -val current_games : unit -> (Signature.public_key_hash * worker) list diff --git a/src/proto_alpha/lib_sc_rollup_node/rollup_node_plugin.ml b/src/proto_alpha/lib_sc_rollup_node/rollup_node_plugin.ml index d54d5b667423..4c5dd5e5cfe4 100644 --- a/src/proto_alpha/lib_sc_rollup_node/rollup_node_plugin.ml +++ b/src/proto_alpha/lib_sc_rollup_node/rollup_node_plugin.ml @@ -30,7 +30,7 @@ module Plugin : Protocol_plugin_sig.S = struct module Dal_slots_tracker = Dal_slots_tracker module Inbox = Inbox module Interpreter = Interpreter - module Refutation_coordinator = Refutation_coordinator + module Refutation_game_helpers = Refutation_game_helpers module Batcher_constants = Batcher_constants module Layer1_helpers = Layer1_helpers module L1_processing = Daemon_helpers -- GitLab