From a28c644142dfd14965e4311bd36c471e862522ac Mon Sep 17 00:00:00 2001 From: Yann Regis-Gianas Date: Tue, 14 Jun 2022 13:19:52 +0200 Subject: [PATCH 1/3] Proto,SCORU: Remove is_opening_move in Sc_rollup_refute It is simpler to separate the initialisation of a game and playing the first move. Hence, we now encode the game initialization through the absence of refutation. Signed-off-by: Yann Regis-Gianas --- .../lib_client/client_proto_context.ml | 5 ++- .../lib_client/client_proto_context.mli | 3 +- .../lib_client/operation_result.ml | 10 +++--- .../lib_protocol/alpha_context.mli | 11 ++++-- src/proto_alpha/lib_protocol/apply.ml | 16 ++++----- .../lib_protocol/operation_repr.ml | 19 +++++------ .../lib_protocol/operation_repr.mli | 3 +- .../lib_protocol/sc_rollup_arith.ml | 2 +- .../sc_rollup_refutation_storage.ml | 29 +++++++++------- .../sc_rollup_refutation_storage.mli | 15 +++++--- .../lib_protocol/test/helpers/op.ml | 4 +-- .../lib_protocol/test/helpers/op.mli | 3 +- .../precheck/manager_operation_helpers.ml | 3 +- .../test/unit/test_sc_rollup_game.ml | 34 ++++++------------- 14 files changed, 77 insertions(+), 80 deletions(-) diff --git a/src/proto_alpha/lib_client/client_proto_context.ml b/src/proto_alpha/lib_client/client_proto_context.ml index 942150f4e84f..65c526da7b73 100644 --- a/src/proto_alpha/lib_client/client_proto_context.ml +++ b/src/proto_alpha/lib_client/client_proto_context.ml @@ -1378,15 +1378,14 @@ let sc_rollup_dal_slot_subscribe (cctxt : #full) ~chain ~block ?confirmations let sc_rollup_refute (cctxt : #full) ~chain ~block ?confirmations ?dry_run ?verbose_signing ?simulation ?fee ?gas_limit ?storage_limit ?counter ~source - ~rollup ~refutation ~opponent ~is_opening_move ~src_pk ~src_sk - ~fee_parameter () = + ~rollup ~refutation ~opponent ~src_pk ~src_sk ~fee_parameter () = let op = Annotated_manager_operation.Single_manager (Injection.prepare_manager_operation ~fee:(Limit.of_option fee) ~gas_limit:(Limit.of_option gas_limit) ~storage_limit:(Limit.of_option storage_limit) - (Sc_rollup_refute {rollup; refutation; opponent; is_opening_move})) + (Sc_rollup_refute {rollup; refutation; opponent})) in Injection.inject_manager_operation cctxt diff --git a/src/proto_alpha/lib_client/client_proto_context.mli b/src/proto_alpha/lib_client/client_proto_context.mli index 51108bfecc88..6ffed7c6c1e8 100644 --- a/src/proto_alpha/lib_client/client_proto_context.mli +++ b/src/proto_alpha/lib_client/client_proto_context.mli @@ -896,9 +896,8 @@ val sc_rollup_refute : ?counter:counter -> source:public_key_hash -> rollup:Alpha_context.Sc_rollup.t -> - refutation:Alpha_context.Sc_rollup.Game.refutation -> + refutation:Alpha_context.Sc_rollup.Game.refutation option -> opponent:Alpha_context.Sc_rollup.Staker.t -> - is_opening_move:bool -> src_pk:public_key -> src_sk:Client_keys.sk_uri -> fee_parameter:Injection.fee_parameter -> diff --git a/src/proto_alpha/lib_client/operation_result.ml b/src/proto_alpha/lib_client/operation_result.ml index b46390cce1f8..698a03b80621 100644 --- a/src/proto_alpha/lib_client/operation_result.ml +++ b/src/proto_alpha/lib_client/operation_result.ml @@ -284,18 +284,18 @@ let pp_manager_operation_content (type kind) source ppf commitment Sc_rollup.Address.pp rollup - | Sc_rollup_refute {rollup; opponent; refutation; is_opening_move} -> + | Sc_rollup_refute {rollup; opponent; refutation} -> Format.fprintf ppf - "Refute staker %a in the smart contract rollup at address %a using \ - refutation %a %s" + "Refute staker %a in the smart contract rollup at address %a using %a" Sc_rollup.Staker.pp opponent Sc_rollup.Address.pp rollup - Sc_rollup.Game.pp_refutation + (fun fmt -> function + | None -> Format.pp_print_string fmt "opening move of the game" + | Some refutation -> Sc_rollup.Game.pp_refutation fmt refutation) refutation - (if is_opening_move then "(opening move of game)" else "") | Sc_rollup_timeout {rollup; stakers = {alice; bob}} -> Format.fprintf ppf diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 5f39846ca8a1..a66eec891f45 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -3316,13 +3316,19 @@ module Sc_rollup : sig Staker.t -> ((Game.t * Game.Index.t) option * context) tzresult Lwt.t + val start_game : + context -> + t -> + player:Signature.public_key_hash -> + opponent:Signature.public_key_hash -> + context tzresult Lwt.t + val game_move : context -> t -> player:Staker.t -> opponent:Staker.t -> Game.refutation -> - is_opening_move:bool -> (Game.outcome option * context) tzresult Lwt.t val timeout : @@ -3827,8 +3833,7 @@ and _ manager_operation = | Sc_rollup_refute : { rollup : Sc_rollup.t; opponent : Sc_rollup.Staker.t; - refutation : Sc_rollup.Game.refutation; - is_opening_move : bool; + refutation : Sc_rollup.Game.refutation option; } -> Kind.sc_rollup_refute manager_operation | Sc_rollup_timeout : { diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 5f4a7d5531d1..c9c5fe2456a8 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -1813,14 +1813,14 @@ let apply_external_manager_operation_content : {staked_hash; consumed_gas; published_at_level; balance_updates} in return (ctxt, result, []) - | Sc_rollup_refute {rollup; opponent; refutation; is_opening_move} -> - Sc_rollup.Refutation_storage.game_move - ctxt - rollup - ~player:source - ~opponent - refutation - ~is_opening_move + | Sc_rollup_refute {rollup; opponent; refutation} -> + let open Sc_rollup.Refutation_storage in + let player = source in + (match refutation with + | None -> + start_game ctxt rollup ~player ~opponent >>=? fun ctxt -> + return (None, ctxt) + | Some refutation -> game_move ctxt rollup ~player ~opponent refutation) >>=? fun (outcome, ctxt) -> (match outcome with | None -> return (Sc_rollup.Game.Ongoing, ctxt, []) diff --git a/src/proto_alpha/lib_protocol/operation_repr.ml b/src/proto_alpha/lib_protocol/operation_repr.ml index 6e1d211ae0c7..5501508072a0 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.ml +++ b/src/proto_alpha/lib_protocol/operation_repr.ml @@ -422,8 +422,7 @@ and _ manager_operation = | Sc_rollup_refute : { rollup : Sc_rollup_repr.t; opponent : Sc_rollup_repr.Staker.t; - refutation : Sc_rollup_game_repr.refutation; - is_opening_move : bool; + refutation : Sc_rollup_game_repr.refutation option; } -> Kind.sc_rollup_refute manager_operation | Sc_rollup_timeout : { @@ -1074,22 +1073,22 @@ module Encoding = struct tag = sc_rollup_operation_refute_tag; name = "sc_rollup_refute"; encoding = - obj4 + obj3 (req "rollup" Sc_rollup_repr.encoding) (req "opponent" Sc_rollup_repr.Staker.encoding) - (req "refutation" Sc_rollup_game_repr.refutation_encoding) - (req "is_opening_move" bool); + (req + "refutation" + (option Sc_rollup_game_repr.refutation_encoding)); select = (function | Manager (Sc_rollup_refute _ as op) -> Some op | _ -> None); proj = (function - | Sc_rollup_refute {rollup; opponent; refutation; is_opening_move} - -> - (rollup, opponent, refutation, is_opening_move)); + | Sc_rollup_refute {rollup; opponent; refutation} -> + (rollup, opponent, refutation)); inj = - (fun (rollup, opponent, refutation, is_opening_move) -> - Sc_rollup_refute {rollup; opponent; refutation; is_opening_move}); + (fun (rollup, opponent, refutation) -> + Sc_rollup_refute {rollup; opponent; refutation}); } let[@coq_axiom_with_reason "gadt"] sc_rollup_timeout_case = diff --git a/src/proto_alpha/lib_protocol/operation_repr.mli b/src/proto_alpha/lib_protocol/operation_repr.mli index b6a429197737..bd860141546e 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.mli +++ b/src/proto_alpha/lib_protocol/operation_repr.mli @@ -487,8 +487,7 @@ and _ manager_operation = | Sc_rollup_refute : { rollup : Sc_rollup_repr.t; opponent : Sc_rollup_repr.Staker.t; - refutation : Sc_rollup_game_repr.refutation; - is_opening_move : bool; + refutation : Sc_rollup_game_repr.refutation option; } -> Kind.sc_rollup_refute manager_operation | Sc_rollup_timeout : { diff --git a/src/proto_alpha/lib_protocol/sc_rollup_arith.ml b/src/proto_alpha/lib_protocol/sc_rollup_arith.ml index 52be4709cd90..06453b59bd23 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_arith.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_arith.ml @@ -745,7 +745,7 @@ module Make (Context : P) : let* status = Status.get in match status with | Halted -> return State_hash.zero - | _ -> return @@ Context.hash_tree state + | _ -> return @@ State_hash.context_hash_to_state_hash (Tree.hash state) in let open Lwt_syntax in let* state = Monad.run m state in diff --git a/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.ml b/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.ml index cc6860fcaeb2..330897dbe538 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.ml @@ -244,20 +244,25 @@ let init_game ctxt rollup ~refuter ~defender = let* ctxt, _ = Store.Opponent.init (ctxt, rollup) defender refuter in return (game, ctxt) -let game_move ctxt rollup ~player ~opponent refutation ~is_opening_move = +let start_game ctxt rollup ~player ~opponent = let open Lwt_tzresult_syntax in - let ({alice; bob} as stakers : Sc_rollup_game_repr.Index.t) = - Sc_rollup_game_repr.Index.make player opponent - in - let* game, ctxt = - if is_opening_move then - init_game ctxt rollup ~refuter:player ~defender:opponent - else get_game ctxt rollup stakers + let idx = Sc_rollup_game_repr.Index.make player opponent in + let* game, ctxt = init_game ctxt rollup ~refuter:player ~defender:opponent in + let* ctxt, _ = Store.Game.update (ctxt, rollup) idx game in + let* ctxt, _ = + Store.Game_timeout.update (ctxt, rollup) idx (timeout_level ctxt) in + return ctxt + +let game_move ctxt rollup ~player ~opponent refutation = + let open Lwt_tzresult_syntax in + let idx = Sc_rollup_game_repr.Index.make player opponent in + let* game, ctxt = get_game ctxt rollup idx in let* () = fail_unless - (let turn = match game.turn with Alice -> alice | Bob -> bob in - Sc_rollup_repr.Staker.equal turn player) + (Sc_rollup_repr.Staker.equal + player + (Sc_rollup_game_repr.Index.staker idx game.turn)) Sc_rollup_wrong_turn in let* move_result = @@ -266,9 +271,9 @@ let game_move ctxt rollup ~player ~opponent refutation ~is_opening_move = match move_result with | Either.Left outcome -> return (Some outcome, ctxt) | Either.Right new_game -> - let* ctxt, _ = Store.Game.update (ctxt, rollup) stakers new_game in + let* ctxt, _ = Store.Game.update (ctxt, rollup) idx new_game in let* ctxt, _ = - Store.Game_timeout.update (ctxt, rollup) stakers (timeout_level ctxt) + Store.Game_timeout.update (ctxt, rollup) idx (timeout_level ctxt) in return (None, ctxt) diff --git a/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.mli b/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.mli index 53039131d443..084dbe6a66d8 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.mli +++ b/src/proto_alpha/lib_protocol/sc_rollup_refutation_storage.mli @@ -69,10 +69,18 @@ val conflicting_stakers_uncarbonated : Sc_rollup_repr.Staker.t -> conflict list tzresult Lwt.t -(** [game_move ctxt rollup player opponent refutation is_opening_move] +(** [start_game ctxt rollup ~player ~opponent] initiates a refutation + game between [player] and [opponent] in the given [rollup]. *) +val start_game : + Raw_context.t -> + Sc_rollup_repr.t -> + player:Signature.public_key_hash -> + opponent:Signature.public_key_hash -> + Raw_context.t tzresult Lwt.t + +(** [game_move ctxt rollup player opponent refutation] handles the storage-side logic for when one of the players makes a - move in the game. It initializes the game if [is_opening_move] is - [true]. Otherwise, it checks the game already exists. Then it checks + move in the game. It checks the game already exists. Then it checks that [player] is the player whose turn it is; if so, it applies [refutation] using the [play] function. @@ -112,7 +120,6 @@ val game_move : player:Sc_rollup_repr.Staker.t -> opponent:Sc_rollup_repr.Staker.t -> Sc_rollup_game_repr.refutation -> - is_opening_move:bool -> (Sc_rollup_game_repr.outcome option * Raw_context.t) tzresult Lwt.t (* TODO: #2902 update reference to timeout period in doc-string *) diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.ml b/src/proto_alpha/lib_protocol/test/helpers/op.ml index 1d80225e91e0..d949d5ff8924 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/op.ml @@ -856,7 +856,7 @@ let sc_rollup_add_messages ?force_reveal ?counter ?fee ?gas_limit ?storage_limit sign account.sk ctxt to_sign_op let sc_rollup_refute ?force_reveal ?counter ?fee ?gas_limit ?storage_limit ctxt - (src : Contract.t) rollup opponent refutation is_opening_move = + (src : Contract.t) rollup opponent refutation = manager_operation ?force_reveal ?counter @@ -865,7 +865,7 @@ let sc_rollup_refute ?force_reveal ?counter ?fee ?gas_limit ?storage_limit ctxt ?storage_limit ~source:src ctxt - (Sc_rollup_refute {rollup; opponent; refutation; is_opening_move}) + (Sc_rollup_refute {rollup; opponent; refutation}) >>=? fun to_sign_op -> Context.Contract.manager ctxt src >|=? fun account -> sign account.sk ctxt to_sign_op diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.mli b/src/proto_alpha/lib_protocol/test/helpers/op.mli index cfe438b5fdd8..75c54b5bcdd6 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/op.mli @@ -603,8 +603,7 @@ val sc_rollup_refute : Contract.t -> Sc_rollup.t -> public_key_hash -> - Sc_rollup.Game.refutation -> - bool -> + Sc_rollup.Game.refutation option -> Operation.packed tzresult Lwt.t val sc_rollup_timeout : diff --git a/src/proto_alpha/lib_protocol/test/integration/precheck/manager_operation_helpers.ml b/src/proto_alpha/lib_protocol/test/integration/precheck/manager_operation_helpers.ml index 2e8f8b4bf0f6..7be15c0804d5 100644 --- a/src/proto_alpha/lib_protocol/test/integration/precheck/manager_operation_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/integration/precheck/manager_operation_helpers.ml @@ -570,8 +570,7 @@ let mk_sc_rollup_refute ?counter ?fee ?gas_limit ?storage_limit ?force_reveal source infos.sc_rollup infos.account2.pkh - refutation - false + (Some refutation) let mk_sc_rollup_add_messages ?counter ?fee ?gas_limit ?storage_limit ?force_reveal ~source (infos : infos) = diff --git a/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_game.ml b/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_game.ml index ebb14a1fa84a..f202a5f6a04f 100644 --- a/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_game.ml +++ b/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_game.ml @@ -150,16 +150,12 @@ let test_poorly_distributed_dissection () = if i = size - 1 then (None, tick_of_int_exn 10000) else (Some (if i = 0 then start_hash else hash_int i), tick_of_int_exn i) in + let* ctxt = + T.lift @@ R.start_game ctxt rollup ~player:refuter ~opponent:defender + in let move = init_refutation ~init_tick start_hash in let* outcome, _ctxt = - T.lift - @@ R.game_move - ctxt - rollup - ~player:refuter - ~opponent:defender - move - ~is_opening_move:true + T.lift @@ R.game_move ctxt rollup ~player:refuter ~opponent:defender move in let expected_reason = "Maximum tick increment in dissection must be less than half total \ @@ -176,19 +172,15 @@ let test_single_valid_game_move () = else if i = 31 then (None, tick_of_int_exn 10000) else (Some (hash_int i), tick_of_int_exn (i * 200))) in + let* ctxt = + T.lift @@ R.start_game ctxt rollup ~player:refuter ~opponent:defender + in let move = Sc_rollup_game_repr. {choice = Sc_rollup_tick_repr.initial; step = Dissection dissection} in let* outcome, _ctxt = - T.lift - @@ R.game_move - ctxt - rollup - ~player:refuter - ~opponent:defender - move - ~is_opening_move:true + T.lift @@ R.game_move ctxt rollup ~player:refuter ~opponent:defender move in Assert.is_none ~loc:__LOC__ ~pp:Sc_rollup_game_repr.pp_outcome outcome @@ -271,15 +263,9 @@ let staker_injectivity_gen ~refuter2_plays = let* ctxt = publish_commitment ctxt refuter2 commit4 in (* Start the games. [refuter2] plays only if [refuter2_plays] is [true]. *) let game_move ctxt ~player ~opponent = + let* ctxt = T.lift @@ R.start_game ctxt rollup ~player ~opponent in let+ _, ctxt = - T.lift - @@ R.game_move - ctxt - rollup - ~player - ~opponent - refutation - ~is_opening_move:true + T.lift @@ R.game_move ctxt rollup ~player ~opponent refutation in ctxt in -- GitLab From 1fc373f4707fb98a13900cd01811f9667145bcfa Mon Sep 17 00:00:00 2001 From: Yann Regis-Gianas Date: Thu, 16 Jun 2022 09:07:30 +0200 Subject: [PATCH 2/3] Proto,SCORU: Fix invalid encoding The JSON back-end of Data_encoding needs special form of encodings. Signed-off-by: Yann Regis-Gianas --- src/proto_alpha/lib_protocol/sc_rollup_game_repr.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/proto_alpha/lib_protocol/sc_rollup_game_repr.ml b/src/proto_alpha/lib_protocol/sc_rollup_game_repr.ml index 11422287b432..1bea47bf9392 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_game_repr.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_game_repr.ml @@ -311,7 +311,7 @@ let reason_encoding = case ~title:"Conflict_resolved" (Tag 0) - unit + (constant "conflict_resolved") (function Conflict_resolved -> Some () | _ -> None) (fun () -> Conflict_resolved); case @@ -323,7 +323,7 @@ let reason_encoding = case ~title:"Timeout" (Tag 2) - unit + (constant "timeout") (function Timeout -> Some () | _ -> None) (fun () -> Timeout); ] @@ -350,7 +350,7 @@ let status_encoding = case ~title:"Ongoing" (Tag 0) - unit + (constant "ongoing") (function Ongoing -> Some () | _ -> None) (fun () -> Ongoing); case -- GitLab From fe37f65d7b71e23b0bdf6eeca54f24415bda9f33 Mon Sep 17 00:00:00 2001 From: Yann Regis-Gianas Date: Mon, 27 Jun 2022 17:23:44 +0200 Subject: [PATCH 3/3] Proto,SCORU: Document Sc_rollup_refute Signed-off-by: Yann Regis-Gianas --- src/proto_alpha/lib_protocol/operation_repr.mli | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/proto_alpha/lib_protocol/operation_repr.mli b/src/proto_alpha/lib_protocol/operation_repr.mli index bd860141546e..38939f4c9608 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.mli +++ b/src/proto_alpha/lib_protocol/operation_repr.mli @@ -490,6 +490,13 @@ and _ manager_operation = refutation : Sc_rollup_game_repr.refutation option; } -> Kind.sc_rollup_refute manager_operation + (** [Sc_rollup_refute { rollup; opponent; refutation }] makes a move + in a refutation game between the source of the operation and the + [opponent] under the given [rollup]. Both players must be stakers + on commitments in conflict. When [refutation = None], the game is + initialized. Next, when [refutation = Some move], [move] is the + next play for the current player. See {!Sc_rollup_game_repr} for + details. **) | Sc_rollup_timeout : { rollup : Sc_rollup_repr.t; stakers : Sc_rollup_game_repr.Index.t; -- GitLab