From b9592894e603aba7974d62e3019b2ea6c05676f7 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 23 Aug 2022 17:24:41 +0200 Subject: [PATCH 1/5] Tezt/Test: fail if no conflict was detected in the refutation tests --- tezt/tests/sc_rollup.ml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tezt/tests/sc_rollup.ml b/tezt/tests/sc_rollup.ml index 85d663ab1534..b97d25884b01 100644 --- a/tezt/tests/sc_rollup.ml +++ b/tezt/tests/sc_rollup.ml @@ -234,6 +234,13 @@ let check_l1_block_contains ~kind ~what ?(extra = fun _ -> true) block = contents ; contents +(** Wait for the rollup node to detect a conflict *) +let wait_for_conflict_detected sc_node = + Sc_rollup_node.wait_for + sc_node + "sc_rollup_node_conflict_detected.v0" + (fun _ -> Some ()) + (* Configuration of a rollup node ------------------------------ @@ -2645,6 +2652,13 @@ let test_refutation_scenario ?commitment_period ?challenge_window ~variant ~kind let bootstrap1_key = Constant.bootstrap1.public_key_hash in let bootstrap2_key = Constant.bootstrap2.public_key_hash in + let conflict_detected = ref false in + let _ = + let* () = wait_for_conflict_detected sc_rollup_node in + conflict_detected := true ; + unit + in + let sc_rollup_node2 = Sc_rollup_node.create Operator node client ~default_operator:bootstrap2_key in @@ -2688,6 +2702,9 @@ let test_refutation_scenario ?commitment_period ?challenge_window ~variant ~kind in let* () = bake_levels ~hook (final_level - List.length inputs) client in + if not !conflict_detected then + Test.fail "Honest node did not detect the conflict" ; + let* honest_deposit_json = RPC.Client.call client @@ RPC.get_chain_block_context_contract_frozen_bonds ~id:bootstrap1_key () -- GitLab From 7f834c527d4046d6450eba1f6c338fb56a37156a Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Wed, 19 Oct 2022 15:23:23 +0200 Subject: [PATCH 2/5] Scoru,Tezt: fix refutation tests (for arith) --- tezt/tests/sc_rollup.ml | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/tezt/tests/sc_rollup.ml b/tezt/tests/sc_rollup.ml index b97d25884b01..c709da17ebe4 100644 --- a/tezt/tests/sc_rollup.ml +++ b/tezt/tests/sc_rollup.ml @@ -2668,32 +2668,28 @@ let test_refutation_scenario ?commitment_period ?challenge_window ~variant ~kind let* () = Sc_rollup_node.run sc_rollup_node [] and* () = Sc_rollup_node.run sc_rollup_node2 [] in - let start_level = Node.get_level node in - let stop_loser level = if List.mem level stop_loser_at then Sc_rollup_node.terminate sc_rollup_node2 else unit in - let rec consume_inputs i = function + let rec consume_inputs = function | [] -> unit | inputs :: next_batches as all -> - let level = start_level + i in + let* level = Client.level client in + let* () = stop_loser level in if List.mem level empty_levels then let* () = Client.bake_for_and_wait client in - consume_inputs (i + 1) all + consume_inputs all else let* () = - Lwt_list.iter_s - (send_text_messages ~src:Constant.bootstrap3.alias client) - inputs + send_text_messages ~src:Constant.bootstrap3.alias client inputs in - let* () = Client.bake_for_and_wait client in - consume_inputs (i + 1) next_batches + consume_inputs next_batches in - let* () = consume_inputs 0 inputs in + let* () = consume_inputs inputs in let* after_inputs_level = Client.level client in let hook i = @@ -2733,8 +2729,8 @@ let rec swap i l = else match l with [_] | [] -> l | x :: y :: l -> y :: swap (i - 1) (x :: l) let inputs_for n = - List.init n @@ fun i -> - [swap i ["3 3 +"; "1"; "1 1 x"; "3 7 8 + * y"; "2 2 out"]] + List.concat @@ List.init n + @@ fun i -> [swap i ["3 3 +"; "1"; "1 1 x"; "3 7 8 + * y"; "2 2 out"]] let test_refutation protocols ~kind = let challenge_window = 10 in @@ -2750,11 +2746,11 @@ let test_refutation protocols ~kind = ("inbox_proof_one_empty_level", ("6 0 0", inputs_for 10, 80, [2], [])); ( "inbox_proof_many_empty_levels", ("9 0 0", inputs_for 10, 80, [2; 3; 4], []) ); - ("pvm_proof_0", ("5 0 1", inputs_for 10, 80, [], [])); + ("pvm_proof_0", ("5 1 1", inputs_for 10, 80, [], [])); ("pvm_proof_1", ("7 1 2", inputs_for 10, 80, [], [])); ("pvm_proof_2", ("7 2 5", inputs_for 7, 80, [], [])); ("pvm_proof_3", ("9 2 5", inputs_for 7, 80, [4; 5], [])); - ("timeout", ("5 0 1", inputs_for 10, 80, [], [35])); + ("timeout", ("5 1 1", inputs_for 10, 80, [], [35])); ] |> List.iter (fun (variant, inputs) -> test_refutation_scenario -- GitLab From 13001e1fddfe7fa15f267d24663bcdf49a957d26 Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Mon, 21 Nov 2022 09:50:43 +0100 Subject: [PATCH 3/5] Scoru,Node: fix fueled interpreter --- src/proto_alpha/bin_sc_rollup_node/fuel.ml | 2 +- .../bin_sc_rollup_node/fueled_pvm.ml | 60 ++++++++++++------- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/proto_alpha/bin_sc_rollup_node/fuel.ml b/src/proto_alpha/bin_sc_rollup_node/fuel.ml index 73a6f6c0dc9e..e05b7638f1b1 100644 --- a/src/proto_alpha/bin_sc_rollup_node/fuel.ml +++ b/src/proto_alpha/bin_sc_rollup_node/fuel.ml @@ -74,7 +74,7 @@ module Accounted : S = struct type t = int64 let of_ticks i = - assert (Int64.compare i 0L > 0) ; + assert (Int64.compare i 0L >= 0) ; i let one_tick_consumption = 1L diff --git a/src/proto_alpha/bin_sc_rollup_node/fueled_pvm.ml b/src/proto_alpha/bin_sc_rollup_node/fueled_pvm.ml index 284ea35f6ab0..3d42bf1d9530 100644 --- a/src/proto_alpha/bin_sc_rollup_node/fueled_pvm.ml +++ b/src/proto_alpha/bin_sc_rollup_node/fueled_pvm.ml @@ -93,7 +93,7 @@ module Make (PVM : Pvm.S) = struct let continue_with_fuel consumption initial_fuel state f = let open Delayed_write_monad.Lwt_result_syntax in match F.consume consumption initial_fuel with - | None -> return (state, 0L) + | None -> return (state, initial_fuel, 0L) | Some fuel_left -> f fuel_left state exception Error_wrapper of tztrace @@ -138,9 +138,9 @@ module Make (PVM : Pvm.S) = struct metadata) end in let builtins = (module Builtins : Tezos_scoru_wasm.Builtins.S) in - let eval_tick fuel tick failing_ticks state = + let eval_tick fuel failing_ticks state = let max_steps = F.max_ticks fuel in - let normal_eval state = + let normal_eval ?(max_steps = max_steps) state = Lwt.catch (fun () -> let*! state, executed_ticks = @@ -151,7 +151,7 @@ module Make (PVM : Pvm.S) = struct | Error_wrapper error -> Lwt.return (Error error) | exn -> raise exn) in - let failure_insertion_eval state failing_ticks' = + let failure_insertion_eval state tick failing_ticks' = let*! () = Interpreter_event.intended_failure ~level @@ -163,8 +163,25 @@ module Make (PVM : Pvm.S) = struct return (state, 1L, failing_ticks') in match failing_ticks with - | xtick :: failing_ticks' when xtick = tick -> - failure_insertion_eval state failing_ticks' + | xtick :: failing_ticks' -> + let jump = Int64.(max 0L (pred xtick)) in + if Compare.Int64.(jump = 0L) then + (* Insert the failure in the first tick. *) + failure_insertion_eval state xtick failing_ticks' + else + (* Jump just before the tick where we'll insert a failure. + Nevertheless, we don't execute more than [max_steps]. *) + let max_steps = Int64.max 0L max_steps |> Int64.min max_steps in + let open Delayed_write_monad.Lwt_result_syntax in + let>* state, executed_ticks, _failing_ticks = + normal_eval ~max_steps state + in + (* Insert the failure. *) + let>* state, executed_ticks', failing_ticks' = + failure_insertion_eval state xtick failing_ticks' + in + let executed_ticks = Int64.add executed_ticks executed_ticks' in + return (state, executed_ticks, failing_ticks') | _ -> normal_eval state in let rec go (fuel : fuel) current_tick failing_ticks state = @@ -172,15 +189,19 @@ module Make (PVM : Pvm.S) = struct if F.is_empty fuel then return (state, fuel, current_tick, failing_ticks) else match input_request with - | No_input_required -> + | No_input_required -> ( let>* next_state, executed_ticks, failing_ticks = - eval_tick fuel current_tick failing_ticks state + eval_tick fuel failing_ticks state in - go - fuel - (Int64.add current_tick executed_ticks) - failing_ticks - next_state + let fuel_executed = F.of_ticks executed_ticks in + match F.consume fuel_executed fuel with + | None -> return (state, fuel, current_tick, failing_ticks) + | Some fuel -> + go + fuel + (Int64.add current_tick executed_ticks) + failing_ticks + next_state) | Needs_reveal (Reveal_raw_data hash) -> ( let* data = get_reveal ~data_dir:node_ctxt.data_dir reveal_map hash @@ -243,8 +264,7 @@ module Make (PVM : Pvm.S) = struct failing_ticks state in - let consumption = F.of_ticks tick in - continue_with_fuel consumption fuel state @@ fun fuel state -> + continue_with_fuel F.one_tick_consumption fuel state @@ fun fuel state -> let>* input, failing_ticks = match failing_ticks with | xtick :: failing_ticks' -> @@ -258,10 +278,10 @@ module Make (PVM : Pvm.S) = struct in return (mutate input, failing_ticks') else return (input, failing_ticks) - | _ -> return (input, failing_ticks) + | [] -> return (input, failing_ticks) in let*! state = PVM.set_input (Inbox_message input) state in - let>* state, _fuel, tick, _failing_ticks = + let>* state, fuel, tick, _failing_ticks = eval_until_input node_ctxt reveal_map @@ -272,7 +292,7 @@ module Make (PVM : Pvm.S) = struct failing_ticks state in - return (state, tick) + return (state, fuel, tick) let eval_messages ~reveal_map ~fuel node_ctxt ~message_counter_offset state inbox_level messages = @@ -295,7 +315,7 @@ module Make (PVM : Pvm.S) = struct ~level ~message_index in - let>* state, executed_ticks = + let>* state, fuel, _executed_ticks = feed_input node_ctxt reveal_map @@ -306,7 +326,7 @@ module Make (PVM : Pvm.S) = struct state input in - return (state, F.of_ticks executed_ticks)) + return (state, fuel)) (state, fuel) messages -- GitLab From 22c816061b28c7922db193a5ff7705c721060cd6 Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Mon, 21 Nov 2022 13:41:18 +0100 Subject: [PATCH 4/5] Scoru,Proto: count the number of internal messages The internal messages even if ignored are now considered in the state --- .../lib_protocol/sc_rollup_arith.ml | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/proto_alpha/lib_protocol/sc_rollup_arith.ml b/src/proto_alpha/lib_protocol/sc_rollup_arith.ml index 8b160e5183c3..6be368695bad 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_arith.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_arith.ml @@ -657,6 +657,26 @@ module Make (Context : P) : | Some c -> Format.fprintf fmt "Some %a" Z.pp_print c end) + (** Store an internal message counter. This is used to distinguish + an unparsable external message and a internal message, which we both + treat as no-ops. *) + module Internal_message_counter = Make_var (struct + type t = Z.t + + let initial = Z.zero + + let encoding = Data_encoding.n + + let name = "internal_message_counter" + + let pp fmt c = Z.pp_print fmt c + end) + + let incr_internal_message_counter = + let open Monad.Syntax in + let* current_counter = Internal_message_counter.get in + Internal_message_counter.set (Z.succ current_counter) + module Next_message = Make_var (struct type t = string option @@ -927,6 +947,7 @@ module Make (Context : P) : | Error _ -> return None | Ok (External payload) -> return (Some payload) | Ok (Internal (Transfer {payload; destination; _})) -> ( + let* () = incr_internal_message_counter in let* (metadata : Sc_rollup_metadata_repr.t option) = Metadata.get in match metadata with | Some {address; _} when Address.(destination = address) -> ( @@ -934,8 +955,12 @@ module Make (Context : P) : | String (_, payload) -> return (Some payload) | _ -> return None) | _ -> return None) - | Ok (Internal Start_of_level) -> return None - | Ok (Internal End_of_level) -> return None + | Ok (Internal Start_of_level) -> + let* () = incr_internal_message_counter in + return None + | Ok (Internal End_of_level) -> + let* () = incr_internal_message_counter in + return None in match payload with | Some payload -> -- GitLab From 189bef91f0055def079d91430dd64278a6dc6412 Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Mon, 21 Nov 2022 09:06:01 +0100 Subject: [PATCH 5/5] Scoru,Tezt: reactivate tezt tests --- tezt/tests/sc_rollup.ml | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/tezt/tests/sc_rollup.ml b/tezt/tests/sc_rollup.ml index c709da17ebe4..6f52454f41ec 100644 --- a/tezt/tests/sc_rollup.ml +++ b/tezt/tests/sc_rollup.ml @@ -3613,15 +3613,6 @@ let register ~kind ~protocols = protocols ~kind ; test_reinject_failed_commitment protocols ~kind ; - (* TODO: https://gitlab.com/tezos/tezos/-/issues/4020 - When looking at the logs of these tests, it appears that they do - not come with enough inspection of the state of the rollup to - ensure the property they are trying to exhibit. For instance, - just checking that the dishonest player has no stack at the end - of the scenario does not prove they have been slashed, and it - appeared that in some instances, they haven’t been able to - publish a commitment to begin with. *) - (* test_refutation protocols ~kind ; *) test_late_rollup_node protocols ~kind ; test_interrupt_rollup_node protocols ~kind ; test_outbox_message ~regression:true ~earliness:0 protocols ~kind ; @@ -3689,6 +3680,9 @@ let register ~protocols = (* DAC tests, not supported yet by the Wasm PVM *) test_rollup_arith_uses_reveals protocols ~kind:"arith" ; test_reveals_fails_on_wrong_hash protocols ~kind:"arith" ; + (* TODO: https://gitlab.com/tezos/tezos/-/issues/3653 + Loser mode does not work for the wasm PVM. *) + test_refutation protocols ~kind:"arith" ; (* Shared tezts - will be executed for both PVMs. *) register ~kind:"wasm_2_0_0" ~protocols ; register ~kind:"arith" ~protocols -- GitLab