diff --git a/src/proto_alpha/bin_sc_rollup_node/RPC_server.ml b/src/proto_alpha/bin_sc_rollup_node/RPC_server.ml index d44edd6e42a8822ecd51021af94c06570ecc7db0..cc5fc58504f3b4fa4cbc8c259ff67cc213847a74 100644 --- a/src/proto_alpha/bin_sc_rollup_node/RPC_server.ml +++ b/src/proto_alpha/bin_sc_rollup_node/RPC_server.ml @@ -332,6 +332,15 @@ module Make (Simulation : Simulation.S) (Batcher : Batcher.S) = struct let*! hash = PVM.state_hash state in return hash + let () = + Block_directory.register0 + Sc_rollup_services.Global.Block.state_current_level + @@ fun (node_ctxt, block) () () -> + let open Lwt_result_syntax in + let* state = get_state node_ctxt block in + let*! current_level = PVM.get_current_level state in + return current_level + let () = Block_directory.register0 Sc_rollup_services.Global.Block.state_value @@ fun (node_ctxt, block) {key} () -> diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 9a6aac57e76fa380f7f9a9cceb3552137e42225f..be9ebb32a2db7855e7f6abb8ac5699c1ee61b2f2 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -3583,6 +3583,8 @@ module Sc_rollup : sig Dissection_chunk.t list -> unit tzresult + val get_current_level : state -> Raw_level.t option Lwt.t + module Internal_for_tests : sig val insert_failure : state -> state Lwt.t end diff --git a/src/proto_alpha/lib_protocol/sc_rollup_PVM_sig.ml b/src/proto_alpha/lib_protocol/sc_rollup_PVM_sig.ml index 618f9f00a5d70cab89c223f64fe7649f3e5df545..750fb56143b655aae2ff29ed213c9d310e7e23fe 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_PVM_sig.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_PVM_sig.ml @@ -545,6 +545,10 @@ module type S = sig Sc_rollup_dissection_chunk_repr.t list -> unit tzresult + (** [get_current_level state] returns the current level of the [state], + returns [None] if it is not possible to compute the level. *) + val get_current_level : state -> Raw_level_repr.t option Lwt.t + module Internal_for_tests : sig (** [insert_failure state] corrupts the PVM state. This is used in the loser mode of the rollup node. *) diff --git a/src/proto_alpha/lib_protocol/sc_rollup_arith.ml b/src/proto_alpha/lib_protocol/sc_rollup_arith.ml index 14c2dda296767c47073748ff5b0daf8f4f354293..55c930c3adc8b51d7fa1576f2b455db4a80fa6f8 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_arith.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_arith.ml @@ -1496,6 +1496,11 @@ module Make (Context : P) : | Some (_, false) -> fail Arith_invalid_claim_about_outbox | None -> fail Arith_output_proof_production_failed + let get_current_level state = + let open Lwt_syntax in + let* _state_, current_level = Monad.run Current_level.get state in + return current_level + module Internal_for_tests = struct let insert_failure state = let add n = Tree.add state ["failures"; string_of_int n] Bytes.empty in diff --git a/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml b/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml index 51dfa08cc84f4d491f5495bfc16632b61ea2874b..e87fe1f2711d341e5129d0de7e0dc36fff7f6af9 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml @@ -190,21 +190,20 @@ let stop_of_pvm_step (type state proof output) let (module P) = pvm in P.proof_stop_state proof -(* This takes an [input] and checks if it is at or above the given level, +(* This takes an [input] and checks if it is above the given level, and if it is at or below the origination level for this rollup. It returns [None] if this is the case. - We use this to check that the PVM proof is obeying [commit_level] - correctly---if the message obtained from the inbox proof is at or - above [commit_level] the [input_given] in the PVM proof should be - [None]. *) -let cut_at_level ~origination_level ~commit_level + We use this to check that the PVM proof is obeying [commit_inbox_level] + correctly---if the message obtained from the inbox proof is above + [commit_inbox_level] the [input_given] in the PVM proof should be [None]. *) +let cut_at_level ~origination_level ~commit_inbox_level (input : Sc_rollup_PVM_sig.input) = match input with | Inbox_message {inbox_level = input_level; _} -> if Raw_level_repr.( - input_level <= origination_level || commit_level <= input_level) + input_level <= origination_level || commit_inbox_level < input_level) then None else Some input | Reveal _data -> Some input @@ -298,7 +297,7 @@ end let valid (type state proof output) ~(pvm : (state, proof, output) Sc_rollups.PVM.implementation) ~metadata - snapshot commit_level dal_snapshot dal_parameters ~dal_attestation_lag + snapshot commit_inbox_level dal_snapshot dal_parameters ~dal_attestation_lag (proof : proof t) = let open Lwt_result_syntax in let (module P) = pvm in @@ -330,14 +329,14 @@ let valid (type state proof output) ~metadata dal_parameters ~dal_attestation_lag - ~commit_level + ~commit_level:commit_inbox_level page_id dal_snapshot proof |> Lwt.return in let input = - Option.bind input (cut_at_level ~origination_level ~commit_level) + Option.bind input (cut_at_level ~origination_level ~commit_inbox_level) in let* input_requested = P.verify_proof input proof.pvm_step in let* () = @@ -411,7 +410,7 @@ module type PVM_with_context_and_state = sig end end -let produce ~metadata pvm_and_state commit_level = +let produce ~metadata pvm_and_state commit_inbox_level = let open Lwt_result_syntax in let (module P : PVM_with_context_and_state) = pvm_and_state in let open P in @@ -476,7 +475,7 @@ let produce ~metadata pvm_and_state commit_level = ~metadata dal_parameters ~dal_attestation_lag - ~commit_level + ~commit_level:commit_inbox_level page_id ~page_info confirmed_slots_history @@ -484,8 +483,14 @@ let produce ~metadata pvm_and_state commit_level = |> Lwt.return in let input_given = - Option.bind input_given (cut_at_level ~origination_level ~commit_level) + Option.bind + input_given + (cut_at_level ~origination_level ~commit_inbox_level) in let* pvm_step_proof = P.produce_proof P.context input_given P.state in let*? pvm_step = serialize_pvm_step ~pvm:(module P) pvm_step_proof in return {pvm_step; input_proof} + +module Internal_for_tests = struct + let cut_at_level = cut_at_level +end diff --git a/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.mli b/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.mli index 7bb7c8fb9602d9393d478c0ca273bb85de8f5df0..a8fa3b3094f8efd9a6438f2749bffed30c6814fe 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.mli +++ b/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.mli @@ -225,10 +225,10 @@ module type PVM_with_context_and_state = sig end end -(** [produce ~metadata pvm_and_state inbox_context inbox_history commit_level] - will construct a full refutation game proof out of the [state] given - in [pvm_and_state]. It uses the [inbox] if necessary to provide - input in the proof. If the input is above or at [commit_level] it +(** [produce ~metadata pvm_and_state inbox_context inbox_history + commit_inbox_level] will construct a full refutation game proof out of + the [state] given in [pvm_and_state]. It uses the [inbox] if necessary to + provide input in the proof. If the input is above or at [commit_level] it will block it, and produce a proof that the PVM is blocked. If the input requested is a reveal the proof production will also fail. @@ -251,3 +251,15 @@ val produce : (module PVM_with_context_and_state) -> Raw_level_repr.t -> serialized t tzresult Lwt.t + +(**/**) + +module Internal_for_tests : sig + (** Export internal [cut_at_level] function. See the docstring in the + implementation file for more information. *) + val cut_at_level : + origination_level:Raw_level_repr.t -> + commit_inbox_level:Raw_level_repr.t -> + Sc_rollup_PVM_sig.input -> + Sc_rollup_PVM_sig.input option +end diff --git a/src/proto_alpha/lib_protocol/sc_rollup_stake_storage.ml b/src/proto_alpha/lib_protocol/sc_rollup_stake_storage.ml index aafc05e679112c080ab08dd8eea10ce79b6a3158..061ac7039b1f3fba4669b50401a5f4bfa50e821e 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_stake_storage.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_stake_storage.ml @@ -223,7 +223,7 @@ let assert_refine_conditions_met ctxt rollup lcc commitment = let current_level = (Raw_context.current_level ctxt).level in let* () = fail_unless - Raw_level_repr.(commitment.Commitment.inbox_level <= current_level) + Raw_level_repr.(commitment.Commitment.inbox_level < current_level) (Sc_rollup_commitment_from_future {current_level; inbox_level = commitment.inbox_level}) in diff --git a/src/proto_alpha/lib_protocol/sc_rollup_wasm.ml b/src/proto_alpha/lib_protocol/sc_rollup_wasm.ml index 942fcd9c7022d32e3610bbdd5dbeb0d8c73054a6..689131b6678604e8075c088ca5372bd8aaaa2361 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_wasm.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_wasm.ml @@ -661,6 +661,11 @@ module V2_0_0 = struct dissection) WASM_invalid_dissection_distribution + let get_current_level state = + let open Lwt_syntax in + let+ res = result_of get_last_message_read state in + Option.map fst res + module Internal_for_tests = struct let insert_failure state = let add n = Tree.add state ["failures"; string_of_int n] Bytes.empty in diff --git a/src/proto_alpha/lib_protocol/test/pbt/test_refutation_game.ml b/src/proto_alpha/lib_protocol/test/pbt/test_refutation_game.ml index 13b69f9ad4efaee036e3729eb094ecd8af2752d0..44b3031a73e709adff1a47f91110d1bff4fd255c 100644 --- a/src/proto_alpha/lib_protocol/test/pbt/test_refutation_game.ml +++ b/src/proto_alpha/lib_protocol/test/pbt/test_refutation_game.ml @@ -1007,6 +1007,8 @@ type strategy = | SOL_hater (** A SOL hater will not execute the SOL input. *) | EOL_hater (** A EOL hater will not execute the EOL input. *) | Info_hater (** A Info per level hater will corrupt the infos. *) + | Nostalgic + (** A nostalgic player will execute messages at origination level. *) let pp_strategy fmt = function | Random -> Format.pp_print_string fmt "Random" @@ -1017,6 +1019,7 @@ let pp_strategy fmt = function | SOL_hater -> Format.pp_print_string fmt "SOL hater" | EOL_hater -> Format.pp_print_string fmt "EOL hater" | Info_hater -> Format.pp_print_string fmt "Info per level hater" + | Nostalgic -> Format.pp_print_string fmt "Nostalgic" type player = { pkh : Tezos_crypto.Signature.Public_key_hash.t; @@ -1190,7 +1193,7 @@ module Player_client = struct return (tick, our_states, new_payloads_per_levels) | Info_hater -> let* corrupt_at_l = 0 -- List.length payloads_per_levels in - let dumb_timestamp = Time_repr.of_seconds 42L in + let dumb_timestamp = Timestamp.of_seconds 42L in let dumb_predecessor = Tezos_crypto.Block_hash.zero in let new_payloads_per_levels = @@ -1207,6 +1210,20 @@ module Player_client = struct in let _state, tick, our_states = eval_inputs new_payloads_per_levels in return (tick, our_states, new_payloads_per_levels) + | Nostalgic -> + (* [payloads_per_levels] starts at [orignation_level + 1], the nostalgic + player will execute messages at [origination_level]. *) + let* messages = + small_list (gen_arith_pvm_messages ~gen_size:(pure 0)) + in + let payloads_at_origination = + Sc_rollup_helpers.wrap_messages metadata.origination_level messages + in + let new_payloads_per_levels = + payloads_at_origination :: payloads_per_levels + in + let _state, tick, our_states = eval_inputs new_payloads_per_levels in + return (tick, our_states, new_payloads_per_levels) (** [gen ~inbox ~rollup ~origination_level ~start_level ~max_level player payloads_per_levels] generates a {!player_client} based on @@ -1460,7 +1477,7 @@ let gen_game ~p1_strategy ~p2_strategy = Raw_level.to_int32 genesis_info.level |> Int32.to_int in let start_level = origination_level + 1 in - let max_level = start_level + commitment_period - 1 in + let max_level = start_level + commitment_period in let* payloads_per_levels = gen_arith_pvm_payloads_for_levels ~start_level ~max_level in @@ -1627,7 +1644,7 @@ let test_wasm_dissection name kind = (** Create a test of [p1_strategy] against [p2_strategy]. One of them must be a {!Perfect} player, otherwise, we do not care about which cheater wins. *) -let test_game ~p1_strategy ~p2_strategy () = +let test_game ?(count = 100) ~p1_strategy ~p2_strategy () = let name = Format.asprintf "%a against %a" @@ -1653,7 +1670,7 @@ let test_game ~p1_strategy ~p2_strategy () = pp_player_client p2_client (if p1_start then "p1" else "p2")) - ~count:100 + ~count ~name ~gen:(gen_game ~p1_strategy ~p2_strategy) (fun ( block, @@ -1717,6 +1734,53 @@ let test_perfect_against_eol_hater = let test_perfect_against_info_hater = test_game ~p1_strategy:Perfect ~p2_strategy:Info_hater () +let test_perfect_against_nostalgic = + test_game ~p1_strategy:Perfect ~p2_strategy:Nostalgic ~count:5 () + +(* This test will behave as a regression test. *) +let test_cut_at_level = + let open QCheck2 in + Test.make + ~name:"cut at level properly cuts" + ~print:(fun (origination_level, commit_inbox_level, input_level) -> + Format.asprintf + "origination_level: %a, commit_inbox_level: %a, input_level: %a" + Raw_level_repr.pp + origination_level + Raw_level_repr.pp + commit_inbox_level + Raw_level_repr.pp + input_level) + Gen.( + let level = + map + (fun i -> Raw_level_repr.of_int32_exn (Int32.of_int i)) + (0 -- 1_000_000) + in + triple level level level) + (fun (origination_level, commit_inbox_level, input_level) -> + let input : Sc_rollup_PVM_sig.input = + Inbox_message + { + inbox_level = input_level; + message_counter = Z.zero; + payload = Sc_rollup_inbox_message_repr.unsafe_of_string "foo"; + } + in + let input_cut = + Sc_rollup_proof_repr.Internal_for_tests.cut_at_level + ~origination_level + ~commit_inbox_level + input + in + let should_be_none = + Raw_level_repr.( + input_level <= origination_level || commit_inbox_level < input_level) + in + match input_cut with + | Some _input -> not should_be_none + | None -> should_be_none) + let tests = ( "Refutation", qcheck_wrap @@ -1731,6 +1795,8 @@ let tests = test_perfect_against_sol_hater; test_perfect_against_eol_hater; test_perfect_against_info_hater; + test_perfect_against_nostalgic; + test_cut_at_level; ] ) (** {2 Entry point} *) diff --git a/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_storage.ml b/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_storage.ml index 58200a48ccf33355e4d5e9df936a055c5e6bb457..63a29f032ad2cf0c7f670d4c731f821a5e2fd76b 100644 --- a/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_storage.ml +++ b/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_storage.ml @@ -295,17 +295,21 @@ let assert_kinds_are_equal ~loc x y = x y -(* Artificially advance current level to make stake refinement possible *) +(* Artificially advance current level to make stake refinement possible. + The commitment can be posted after the inbox level commited. For example, + if you post a commitment for the inbox level 32, you will be able to + publish the commitment at level 33. +*) let advance_level_for_commitment ctxt (commitment : Commitment_repr.t) = let cur_level = Level_storage.(current ctxt).level in - if cur_level >= commitment.inbox_level then ctxt + if cur_level > commitment.inbox_level then ctxt else - Raw_context.Internal_for_tests.add_level - ctxt - (Int32.to_int - @@ Int32.sub - (Raw_level_repr.to_int32 commitment.inbox_level) - (Raw_level_repr.to_int32 cur_level)) + let offset = + let open Raw_level_repr in + let open Int32 in + succ @@ sub (to_int32 commitment.inbox_level) (to_int32 cur_level) + in + Raw_context.Internal_for_tests.add_level ctxt (Int32.to_int offset) let advance_level_n_refine_stake ctxt rollup staker ?staked_on commitment = let ctxt = advance_level_for_commitment ctxt commitment in @@ -485,24 +489,39 @@ let number_of_ticks_exn n = | None -> Stdlib.failwith "Bad Number_of_ticks" let valid_inbox_level ctxt = - let root_level = Raw_level_repr.to_int32 Level_storage.(current ctxt).level in + let root_level = Level_storage.(current ctxt).level in let commitment_freq = Constants_storage.sc_rollup_commitment_period_in_blocks ctxt in fun i -> - Raw_level_repr.of_int32_exn - (Int32.add root_level (Int32.mul (Int32.of_int commitment_freq) i)) + Raw_level_repr.add + root_level + Int32.(to_int (mul (of_int commitment_freq) i)) + +(** A more precise version of {!valid_inbox_level}. Not used everywhere + as it requires more information than {!valid_inbox_level} and is in + the lwt tzresult monad. *) +let proper_valid_inbox_level (ctxt, rollup) i = + let+ _, {level = genesis_level; _} = + Sc_rollup_storage.genesis_info ctxt rollup + in + let commitment_freq = + Constants_storage.sc_rollup_commitment_period_in_blocks ctxt + in + Raw_level_repr.add genesis_level (commitment_freq * i) -let produce_and_refine ctxt ~number_of_commitments ?(start_at_level = 1l) +let produce_and_refine ctxt ~number_of_commitments ?(start_at_level = 1) ~predecessor staker rollup = + let inbox_level = proper_valid_inbox_level (ctxt, rollup) in let rec aux ctxt n l predecessor result = if n = 0 then return @@ (List.rev result, ctxt) else + let* inbox_level = inbox_level l in let commitment = Commitment_repr. { predecessor; - inbox_level = valid_inbox_level ctxt 1l; + inbox_level; number_of_ticks = number_of_ticks_exn 1232909L; compressed_state = Sc_rollup_repr.State_hash.zero; } @@ -510,7 +529,7 @@ let produce_and_refine ctxt ~number_of_commitments ?(start_at_level = 1l) let* c, _level, ctxt = advance_level_n_refine_stake ctxt rollup staker commitment in - aux ctxt (n - 1) (Int32.succ l) c (c :: result) + aux ctxt (n - 1) (l + 1) c (c :: result) in aux ctxt number_of_commitments start_at_level predecessor [] @@ -766,7 +785,7 @@ let test_refine_commitment_fails_on_commitment_from_future () = inbox_level = Raw_level_repr.of_int32_exn 31l; }) -let test_refine_commitment_with_inbox_equal_current () = +let test_refine_commitment_with_inbox_greater_than_current () = let* ctxt, rollup, genesis_hash, staker = originate_rollup_and_deposit_with_one_staker () in @@ -784,10 +803,11 @@ let test_refine_commitment_with_inbox_equal_current () = let ctxt = Raw_context.Internal_for_tests.add_level ctxt - (Int32.to_int - @@ Int32.sub - (Raw_level_repr.to_int32 commitment.inbox_level) - (Raw_level_repr.to_int32 cur_level)) + Int32.( + to_int @@ succ + @@ sub + (Raw_level_repr.to_int32 commitment.inbox_level) + (Raw_level_repr.to_int32 cur_level)) in let* ctxt = lift @@ -2543,9 +2563,10 @@ let tests = `Quick test_refine_commitment_fails_on_commitment_from_future; Tztest.tztest - "staking on commitment with inbox level equal to current level is allowed" + "staking on commitment with inbox level greater than the current level \ + is allowed" `Quick - test_refine_commitment_with_inbox_equal_current; + test_refine_commitment_with_inbox_greater_than_current; Tztest.tztest "stake then publish" `Quick test_deposit_then_publish; Tztest.tztest "publish with no rollup" `Quick test_publish_missing_rollup; Tztest.tztest diff --git a/src/proto_alpha/lib_sc_rollup/sc_rollup_services.ml b/src/proto_alpha/lib_sc_rollup/sc_rollup_services.ml index 24199a2293dfa481632bf4918af29864e8468bb6..ad563962fe176f0932554e473576fcc55658366a 100644 --- a/src/proto_alpha/lib_sc_rollup/sc_rollup_services.ml +++ b/src/proto_alpha/lib_sc_rollup/sc_rollup_services.ml @@ -453,6 +453,13 @@ module Global = struct ~output:Sc_rollup.State_hash.encoding (path / "state_hash") + let state_current_level = + Tezos_rpc.Service.get_service + ~description:"Retrieve the current level of a PVM" + ~query:Tezos_rpc.Query.empty + ~output:(Data_encoding.option Raw_level.encoding) + (path / "state_current_level") + type state_value_query = {key : string} let state_value_query : state_value_query Tezos_rpc.Query.t = diff --git a/tezt/lib_tezos/sc_rollup_client.ml b/tezt/lib_tezos/sc_rollup_client.ml index c0b29db1a530a1d58587b328289db50b3c752ec3..108f4028939d90dad76e56c7d08e6e91d20fe69a 100644 --- a/tezt/lib_tezos/sc_rollup_client.ml +++ b/tezt/lib_tezos/sc_rollup_client.ml @@ -234,6 +234,10 @@ let state_hash ?hooks ?(block = "head") sc_client = rpc_get ?hooks sc_client ["global"; "block"; block; "state_hash"] |> Runnable.map JSON.as_string +let state_current_level ?hooks ?(block = "head") sc_client = + rpc_get ?hooks sc_client ["global"; "block"; block; "state_current_level"] + |> Runnable.map JSON.as_int + let status ?hooks ?(block = "head") sc_client = rpc_get ?hooks sc_client ["global"; "block"; block; "status"] |> Runnable.map JSON.as_string diff --git a/tezt/lib_tezos/sc_rollup_client.mli b/tezt/lib_tezos/sc_rollup_client.mli index aab60c108833d8daf67910b233316a0c53473503..4e88f5ee6415dc3b2448aa5d23f7b6e92f561bca 100644 --- a/tezt/lib_tezos/sc_rollup_client.mli +++ b/tezt/lib_tezos/sc_rollup_client.mli @@ -89,6 +89,11 @@ val ticks : ?hooks:Process.hooks -> ?block:string -> t -> int Runnable.process val state_hash : ?hooks:Process.hooks -> ?block:string -> t -> string Runnable.process +(** [state_current_level ?block client] gets the corresponding PVM state current + level for the [block] (default ["head"]). *) +val state_current_level : + ?hooks:Process_hooks.t -> ?block:string -> t -> int Runnable.process + (** [state_value ?block client key] gets the corresponding PVM state value mapped to [key] for the [block] (default ["head"]). *) val state_value : diff --git a/tezt/tests/expected/sc_rollup.ml/Alpha- arith - participant of a refutation game are slashed-rewarded.out b/tezt/tests/expected/sc_rollup.ml/Alpha- arith - participant of a refutation game are slashed-rewarded.out index 1338c8f12de3c3b1059c1a1675bf2a5f18ac1a72..c8424a7bfc4601f078c4a254d3eb3b1aa0d65f67 100644 --- a/tezt/tests/expected/sc_rollup.ml/Alpha- arith - participant of a refutation game are slashed-rewarded.out +++ b/tezt/tests/expected/sc_rollup.ml/Alpha- arith - participant of a refutation game are slashed-rewarded.out @@ -63,7 +63,7 @@ This sequence of operations was run: This smart contract rollup commitment publishing was successfully applied Consumed gas: 6921.767 Hash of commit: [SC_ROLLUP_COMMITMENT_HASH] - Commitment published at level: 5 + Commitment published at level: 6 Balance updates: [PUBLIC_KEY_HASH] ....................................................... -ꜩ10000 Frozen_bonds([PUBLIC_KEY_HASH],[SC_ROLLUP_HASH]) ... +ꜩ10000 @@ -99,7 +99,7 @@ This sequence of operations was run: This smart contract rollup commitment publishing was successfully applied Consumed gas: 7151.767 Hash of commit: [SC_ROLLUP_COMMITMENT_HASH] - Commitment published at level: 6 + Commitment published at level: 7 Balance updates: [PUBLIC_KEY_HASH] ....................................................... -ꜩ10000 Frozen_bonds([PUBLIC_KEY_HASH],[SC_ROLLUP_HASH]) ... +ꜩ10000 diff --git a/tezt/tests/sc_rollup.ml b/tezt/tests/sc_rollup.ml index 1a6d72fb4d6a7764dcf5f0e51811c1c887d7945a..7b7fd312d8bb2a7480df08f2b533578f7b26dc46 100644 --- a/tezt/tests/sc_rollup.ml +++ b/tezt/tests/sc_rollup.ml @@ -567,9 +567,10 @@ let test_stakers_commitments ~kind = let* {commitment_period_in_blocks; _} = get_sc_rollup_constants tezos_client in - (* Bake commitment_period_in_blocks blocks in order prevent commitment being posted for future inbox_level *) + (* Bake commitment_period_in_blocks blocks in order prevent commitment being + posted for future inbox_level *) let* () = - repeat commitment_period_in_blocks (fun () -> + repeat (commitment_period_in_blocks + 1) (fun () -> Client.bake_for_and_wait tezos_client) in let* commitment_1 = @@ -581,7 +582,7 @@ let test_stakers_commitments ~kind = tezos_client in let* () = - repeat commitment_period_in_blocks (fun () -> + repeat (commitment_period_in_blocks + 1) (fun () -> Client.bake_for_and_wait tezos_client) in let* commitment_2 = @@ -2513,9 +2514,10 @@ let test_consecutive_commitments _protocol _rollup_node _rollup_client sc_rollup let* predecessor, _ = last_cemented_commitment_hash_with_level ~sc_rollup tezos_client in - (* Bake commitment_period_in_blocks blocks in order prevent commitment being posted for future inbox_level *) + (* Bake commitment_period_in_blocks blocks in order prevent commitment being + posted for future inbox_level *) let* () = - repeat commitment_period_in_blocks (fun () -> + repeat (commitment_period_in_blocks + 1) (fun () -> Client.bake_for_and_wait tezos_client) in let* commit_hash = @@ -2527,7 +2529,7 @@ let test_consecutive_commitments _protocol _rollup_node _rollup_client sc_rollup tezos_client in let* () = - repeat (commitment_period_in_blocks + 1) (fun () -> + repeat (commitment_period_in_blocks + 2) (fun () -> Client.bake_for_and_wait tezos_client) in let* _commit_hash = @@ -2780,7 +2782,7 @@ let mk_forking_commitments node client ~sc_rollup ~operator1 ~operator2 = (* Compute the inbox level for which we'd like to commit *) let inbox_level = starting_level + (commitment_period_in_blocks * depth) in (* d is the delta between the target inbox level and the current level *) - let d = inbox_level - Node.get_level node in + let d = inbox_level - Node.get_level node + 1 in (* Bake sufficiently many blocks to be able to commit for the desired inbox level. We may actually bake no blocks if d <= 0 *) let* () = repeat d (fun () -> Client.bake_for_and_wait client) in @@ -3120,7 +3122,7 @@ let test_refutation_reward_and_punishment ~kind = let starting_level = Node.get_level node in let inbox_level = starting_level + commitment_period_in_blocks in (* d is the delta between the target inbox level and the current level *) - let d = inbox_level - Node.get_level node in + let d = inbox_level - Node.get_level node + 1 in (* Bake sufficiently many blocks to be able to commit for the desired inbox level. We may actually bake no blocks if d <= 0 *) let* () = repeat d (fun () -> Client.bake_for_and_wait client) in @@ -3580,6 +3582,57 @@ let test_rpcs ~kind = in unit +let test_messages_processed_by_commitment ~kind = + test_full_scenario + { + variant = None; + tags = ["commitment"; "evaluation"]; + description = "checks messages processed during a commitment period"; + } + ~kind + @@ fun _protocol sc_rollup_node sc_rollup_client sc_rollup _node client -> + let* () = Sc_rollup_node.run sc_rollup_node [] in + let* {commitment_period_in_blocks; _} = get_sc_rollup_constants client in + let* genesis_info = + RPC.Client.call ~hooks client + @@ RPC.get_chain_block_context_sc_rollups_sc_rollup_genesis_info sc_rollup + in + let init_level = JSON.(genesis_info |-> "level" |> as_int) in + let store_commitment_level = + init_level + commitment_period_in_blocks + block_finality_time + in + (* Bake enough blocks so [sc_rollup_node] posts a commitment. *) + let* () = + repeat (commitment_period_in_blocks + block_finality_time) (fun () -> + Client.bake_for_and_wait client) + in + (* Wait until the [sc_rollup_node] store the commitment. *) + let* (_ : int) = + Sc_rollup_node.wait_for_level + ~timeout:3. + sc_rollup_node + store_commitment_level + in + let* _, {inbox_level; _}, _ = + let*! stored_commitment_opt = + Sc_rollup_client.last_stored_commitment ~hooks sc_rollup_client + in + match stored_commitment_opt with + | Some stored_commitment -> return stored_commitment + | None -> failwith "The rollup node should have stored a commitment by now" + in + + let*! current_level = + Sc_rollup_client.state_current_level + ~block:(string_of_int inbox_level) + sc_rollup_client + in + Check.((current_level = inbox_level) int) + ~error_msg: + "The rollup node should process all the levels of a commitment period, \ + expected %L, got %R" ; + unit + let register ~kind ~protocols = test_origination ~kind protocols ; test_rollup_node_running ~kind protocols ; @@ -3750,7 +3803,8 @@ let register ~kind ~protocols = ~entrypoint:"aux" ~message_kind:`External protocols - ~kind + ~kind ; + test_messages_processed_by_commitment ~kind protocols let register ~protocols = (* PVM-independent tests. We still need to specify a PVM kind