From 0c5dccf355f5d3bf8fd5de97ff07aa4165383b34 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 16 Apr 2024 14:32:40 +0200 Subject: [PATCH 01/16] Rollup node: type unsafe pvm patch --- src/lib_smart_rollup_node/pvm_patches.ml | 8 ++++++++ src/lib_smart_rollup_node/pvm_patches.mli | 11 +++++++++++ 2 files changed, 19 insertions(+) create mode 100644 src/lib_smart_rollup_node/pvm_patches.ml create mode 100644 src/lib_smart_rollup_node/pvm_patches.mli diff --git a/src/lib_smart_rollup_node/pvm_patches.ml b/src/lib_smart_rollup_node/pvm_patches.ml new file mode 100644 index 000000000000..1ac798acb89e --- /dev/null +++ b/src/lib_smart_rollup_node/pvm_patches.ml @@ -0,0 +1,8 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Functori *) +(* *) +(*****************************************************************************) + +type unsafe_patch = Increase_max_nb_ticks of int64 diff --git a/src/lib_smart_rollup_node/pvm_patches.mli b/src/lib_smart_rollup_node/pvm_patches.mli new file mode 100644 index 000000000000..e249ec9bbf28 --- /dev/null +++ b/src/lib_smart_rollup_node/pvm_patches.mli @@ -0,0 +1,11 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Functori *) +(* *) +(*****************************************************************************) + +(** The type of individual unsafe patch content. *) +type unsafe_patch = + | Increase_max_nb_ticks of int64 + (** Increase the maximum number of ticks. *) -- GitLab From d6d74b231109c7b3c73d1cd44efe425e0ba0c6d0 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Fri, 12 Apr 2024 12:02:56 +0200 Subject: [PATCH 02/16] Wasm: expose set_max_nb_ticks in Unsafe module --- src/lib_scoru_wasm/wasm_pvm.ml | 21 +++++++++++++++------ src/lib_scoru_wasm/wasm_pvm_sig.ml | 18 ++++++++++++++++-- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/lib_scoru_wasm/wasm_pvm.ml b/src/lib_scoru_wasm/wasm_pvm.ml index 5323e7fc5b10..91eabb8f5fb6 100644 --- a/src/lib_scoru_wasm/wasm_pvm.ml +++ b/src/lib_scoru_wasm/wasm_pvm.ml @@ -352,7 +352,22 @@ module Make_pvm (Wasm_vm : Wasm_vm_sig.S) (T : Tezos_tree_encoding.TREE) : let* pvm = Tree_encoding_runner.decode pvm_state_encoding tree in Wasm_vm.get_wasm_version pvm + module Unsafe = struct + let get_max_nb_ticks tree = + let open Lwt_syntax in + let+ pvm_state = Tree_encoding_runner.decode pvm_state_encoding tree in + pvm_state.max_nb_ticks + + let set_max_nb_ticks n tree = + let open Lwt_syntax in + let* pvm_state = Tree_encoding_runner.decode pvm_state_encoding tree in + let pvm_state = {pvm_state with max_nb_ticks = n} in + Tree_encoding_runner.encode pvm_state_encoding pvm_state tree + end + module Internal_for_tests = struct + include Unsafe + let get_tick_state tree = let open Lwt_syntax in let+ pvm_state = Tree_encoding_runner.decode pvm_state_encoding tree in @@ -373,12 +388,6 @@ module Make_pvm (Wasm_vm : Wasm_vm_sig.S) (T : Tezos_tree_encoding.TREE) : | Stuck error -> Lwt.return_some error | _ -> Lwt.return_none - let set_max_nb_ticks n tree = - let open Lwt_syntax in - let* pvm_state = Tree_encoding_runner.decode pvm_state_encoding tree in - let pvm_state = {pvm_state with max_nb_ticks = n} in - Tree_encoding_runner.encode pvm_state_encoding pvm_state tree - let set_maximum_reboots_per_input n tree = let open Lwt_syntax in let* pvm_state = Tree_encoding_runner.decode pvm_state_encoding tree in diff --git a/src/lib_scoru_wasm/wasm_pvm_sig.ml b/src/lib_scoru_wasm/wasm_pvm_sig.ml index 904d468a7758..225a49c7d721 100644 --- a/src/lib_scoru_wasm/wasm_pvm_sig.ml +++ b/src/lib_scoru_wasm/wasm_pvm_sig.ml @@ -25,6 +25,18 @@ (*****************************************************************************) open Wasm_pvm_state +module type Unsafe = sig + type tree + + (** Retrieve the maximum number of ticks for the PVM from the state. *) + val get_max_nb_ticks : tree -> Z.t Lwt.t + + (** Change the maximum number of ticks (per snapshot) of the WASM PVM. This is + to be used only for tests or to increase the tick limit in a non-refutable + setting. *) + val set_max_nb_ticks : Z.t -> tree -> tree Lwt.t +end + module type Internal_for_tests = sig open Internal_state @@ -37,8 +49,6 @@ module type Internal_for_tests = sig val is_stuck : tree -> Wasm_pvm_errors.t option Lwt.t - val set_max_nb_ticks : Z.t -> tree -> tree Lwt.t - val set_maximum_reboots_per_input : Z.t -> tree -> tree Lwt.t val decr_reboot_counter : tree -> tree Lwt.t @@ -60,6 +70,8 @@ module type Internal_for_tests = sig tree -> (tree * int64) Lwt.t + include Unsafe with type tree := tree + include Wasm_vm_sig.Internal_for_tests with type state := tree end @@ -90,6 +102,8 @@ module type S = sig function may raise an exception. *) val get_output : output_info -> tree -> string option Lwt.t + module Unsafe : Unsafe with type tree := tree + module Internal_for_tests : Internal_for_tests with type tree := tree end -- GitLab From b4993035862e5883827e68ec5f1629fbff0b9101 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Fri, 12 Apr 2024 12:41:20 +0200 Subject: [PATCH 03/16] Rollup node/Alpha: support for increasing tick limit in WASM PVM --- .../lib_sc_rollup_node/arith_pvm.ml | 10 +++++++ src/proto_alpha/lib_sc_rollup_node/pvm_sig.ml | 13 +++++++++ .../lib_sc_rollup_node/riscv_pvm.ml | 10 +++++++ .../lib_sc_rollup_node/wasm_2_0_0_pvm.ml | 29 +++++++++++++++++-- 4 files changed, 59 insertions(+), 3 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/arith_pvm.ml b/src/proto_alpha/lib_sc_rollup_node/arith_pvm.ml index db0ae2a698ba..e18910690a4e 100644 --- a/src/proto_alpha/lib_sc_rollup_node/arith_pvm.ml +++ b/src/proto_alpha/lib_sc_rollup_node/arith_pvm.ml @@ -63,6 +63,16 @@ module Impl : Pvm_sig.S = struct raise (Invalid_argument "No durable storage for arith PVM") end + module Unsafe_patches = struct + (** No unsafe patches for the arith PVM. *) + type t = | + + let of_patch (p : Pvm_patches.unsafe_patch) = + match p with Increase_max_nb_ticks _ -> assert false + + let apply _state (x : t) = match x with _ -> . + end + let new_dissection = Game_helpers.default_new_dissection let string_of_status = function diff --git a/src/proto_alpha/lib_sc_rollup_node/pvm_sig.ml b/src/proto_alpha/lib_sc_rollup_node/pvm_sig.ml index dedeb1637dcb..7afc012df23e 100644 --- a/src/proto_alpha/lib_sc_rollup_node/pvm_sig.ml +++ b/src/proto_alpha/lib_sc_rollup_node/pvm_sig.ml @@ -112,4 +112,17 @@ module type S = sig PVM state [state]. *) val lookup : state -> string list -> bytes option Lwt.t end + + (** Expose unsafe state patching functions for manual intervention. + At the moment this feature is only used to increase the maximum number of + ticks of the WASM PVM in a non refutable setting. *) + module Unsafe_patches : sig + type t + + (** [of_patch p] returns the PVM patch if it has a corresponding one. *) + val of_patch : Pvm_patches.unsafe_patch -> t tzresult + + (** [apply state patch] applies the unsafe patch [patch] on the state. *) + val apply : state -> t -> state Lwt.t + end end diff --git a/src/proto_alpha/lib_sc_rollup_node/riscv_pvm.ml b/src/proto_alpha/lib_sc_rollup_node/riscv_pvm.ml index e489ea2c2b38..5bdcea883a6a 100644 --- a/src/proto_alpha/lib_sc_rollup_node/riscv_pvm.ml +++ b/src/proto_alpha/lib_sc_rollup_node/riscv_pvm.ml @@ -207,3 +207,13 @@ module Inspect_durable_state = struct let lookup _state _keys = raise (Invalid_argument "No durable storage for riscv PVM") end + +module Unsafe_patches = struct + (** No unsafe patches for the riscv PVM. *) + type t = | + + let of_patch (p : Pvm_patches.unsafe_patch) = + match p with Increase_max_nb_ticks _ -> assert false + + let apply _state (x : t) = match x with _ -> . +end diff --git a/src/proto_alpha/lib_sc_rollup_node/wasm_2_0_0_pvm.ml b/src/proto_alpha/lib_sc_rollup_node/wasm_2_0_0_pvm.ml index 84c91db3619f..65c678722509 100644 --- a/src/proto_alpha/lib_sc_rollup_node/wasm_2_0_0_pvm.ml +++ b/src/proto_alpha/lib_sc_rollup_node/wasm_2_0_0_pvm.ml @@ -130,7 +130,9 @@ end module Durable_state = Make_durable_state (Make_wrapped_tree (Wasm_2_0_0_proof_format.Tree)) -module Impl : Pvm_sig.S = struct +type unsafe_patch = Increase_max_nb_ticks of int64 + +module Impl : Pvm_sig.S with type Unsafe_patches.t = unsafe_patch = struct module PVM = Sc_rollup.Wasm_2_0_0PVM.Make (Make_backend) (Wasm_2_0_0_proof_format) include PVM @@ -153,6 +155,29 @@ module Impl : Pvm_sig.S = struct Durable_state.lookup state key end + module Backend = Make_backend (Wasm_2_0_0_proof_format.Tree) + + module Unsafe_patches = struct + type t = unsafe_patch + + let of_patch (p : Pvm_patches.unsafe_patch) = + match p with + | Increase_max_nb_ticks max_nb_ticks -> + Ok (Increase_max_nb_ticks max_nb_ticks) + + let apply state (Increase_max_nb_ticks max_nb_ticks) = + let open Lwt_syntax in + let* registered_max_nb_ticks = Backend.Unsafe.get_max_nb_ticks state in + let max_nb_ticks = Z.of_int64 max_nb_ticks in + if Z.Compare.(max_nb_ticks < registered_max_nb_ticks) then + Format.ksprintf + invalid_arg + "Decreasing tick limit of WASM PVM from %s to %s is not allowed" + (Z.to_string registered_max_nb_ticks) + (Z.to_string max_nb_ticks) ; + Backend.Unsafe.set_max_nb_ticks max_nb_ticks state + end + let string_of_status : status -> string = function | Waiting_for_input_message -> "Waiting for input message" | Waiting_for_reveal (Sc_rollup.Reveal_raw_data hash) -> @@ -167,8 +192,6 @@ module Impl : Pvm_sig.S = struct "Waiting for DAL parameters" | Computing -> "Computing" - module Backend = Make_backend (Wasm_2_0_0_proof_format.Tree) - let eval_many ~reveal_builtins ~write_debug ~is_reveal_enabled:_ = Backend.compute_step_many ~wasm_entrypoint:Tezos_scoru_wasm.Constants.wasm_entrypoint -- GitLab From a3237c377b4bacfc8dc2c64276927bc0b28272dc Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Fri, 12 Apr 2024 12:41:20 +0200 Subject: [PATCH 04/16] Rollup node/ParisB: support for increasing tick limit in WASM PVM --- .../lib_sc_rollup_node/arith_pvm.ml | 10 +++++++ .../lib_sc_rollup_node/pvm_sig.ml | 13 +++++++++ .../lib_sc_rollup_node/wasm_2_0_0_pvm.ml | 29 +++++++++++++++++-- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/proto_019_PtParisB/lib_sc_rollup_node/arith_pvm.ml b/src/proto_019_PtParisB/lib_sc_rollup_node/arith_pvm.ml index db0ae2a698ba..e18910690a4e 100644 --- a/src/proto_019_PtParisB/lib_sc_rollup_node/arith_pvm.ml +++ b/src/proto_019_PtParisB/lib_sc_rollup_node/arith_pvm.ml @@ -63,6 +63,16 @@ module Impl : Pvm_sig.S = struct raise (Invalid_argument "No durable storage for arith PVM") end + module Unsafe_patches = struct + (** No unsafe patches for the arith PVM. *) + type t = | + + let of_patch (p : Pvm_patches.unsafe_patch) = + match p with Increase_max_nb_ticks _ -> assert false + + let apply _state (x : t) = match x with _ -> . + end + let new_dissection = Game_helpers.default_new_dissection let string_of_status = function diff --git a/src/proto_019_PtParisB/lib_sc_rollup_node/pvm_sig.ml b/src/proto_019_PtParisB/lib_sc_rollup_node/pvm_sig.ml index dedeb1637dcb..7afc012df23e 100644 --- a/src/proto_019_PtParisB/lib_sc_rollup_node/pvm_sig.ml +++ b/src/proto_019_PtParisB/lib_sc_rollup_node/pvm_sig.ml @@ -112,4 +112,17 @@ module type S = sig PVM state [state]. *) val lookup : state -> string list -> bytes option Lwt.t end + + (** Expose unsafe state patching functions for manual intervention. + At the moment this feature is only used to increase the maximum number of + ticks of the WASM PVM in a non refutable setting. *) + module Unsafe_patches : sig + type t + + (** [of_patch p] returns the PVM patch if it has a corresponding one. *) + val of_patch : Pvm_patches.unsafe_patch -> t tzresult + + (** [apply state patch] applies the unsafe patch [patch] on the state. *) + val apply : state -> t -> state Lwt.t + end end diff --git a/src/proto_019_PtParisB/lib_sc_rollup_node/wasm_2_0_0_pvm.ml b/src/proto_019_PtParisB/lib_sc_rollup_node/wasm_2_0_0_pvm.ml index 84c91db3619f..65c678722509 100644 --- a/src/proto_019_PtParisB/lib_sc_rollup_node/wasm_2_0_0_pvm.ml +++ b/src/proto_019_PtParisB/lib_sc_rollup_node/wasm_2_0_0_pvm.ml @@ -130,7 +130,9 @@ end module Durable_state = Make_durable_state (Make_wrapped_tree (Wasm_2_0_0_proof_format.Tree)) -module Impl : Pvm_sig.S = struct +type unsafe_patch = Increase_max_nb_ticks of int64 + +module Impl : Pvm_sig.S with type Unsafe_patches.t = unsafe_patch = struct module PVM = Sc_rollup.Wasm_2_0_0PVM.Make (Make_backend) (Wasm_2_0_0_proof_format) include PVM @@ -153,6 +155,29 @@ module Impl : Pvm_sig.S = struct Durable_state.lookup state key end + module Backend = Make_backend (Wasm_2_0_0_proof_format.Tree) + + module Unsafe_patches = struct + type t = unsafe_patch + + let of_patch (p : Pvm_patches.unsafe_patch) = + match p with + | Increase_max_nb_ticks max_nb_ticks -> + Ok (Increase_max_nb_ticks max_nb_ticks) + + let apply state (Increase_max_nb_ticks max_nb_ticks) = + let open Lwt_syntax in + let* registered_max_nb_ticks = Backend.Unsafe.get_max_nb_ticks state in + let max_nb_ticks = Z.of_int64 max_nb_ticks in + if Z.Compare.(max_nb_ticks < registered_max_nb_ticks) then + Format.ksprintf + invalid_arg + "Decreasing tick limit of WASM PVM from %s to %s is not allowed" + (Z.to_string registered_max_nb_ticks) + (Z.to_string max_nb_ticks) ; + Backend.Unsafe.set_max_nb_ticks max_nb_ticks state + end + let string_of_status : status -> string = function | Waiting_for_input_message -> "Waiting for input message" | Waiting_for_reveal (Sc_rollup.Reveal_raw_data hash) -> @@ -167,8 +192,6 @@ module Impl : Pvm_sig.S = struct "Waiting for DAL parameters" | Computing -> "Computing" - module Backend = Make_backend (Wasm_2_0_0_proof_format.Tree) - let eval_many ~reveal_builtins ~write_debug ~is_reveal_enabled:_ = Backend.compute_step_many ~wasm_entrypoint:Tezos_scoru_wasm.Constants.wasm_entrypoint -- GitLab From 45ae3e8bc5eeb6b7c02922800adb9121cbb938a8 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Fri, 12 Apr 2024 12:41:20 +0200 Subject: [PATCH 05/16] Rollup node/Nairobi: support for increasing tick limit in WASM PVM --- .../lib_sc_rollup_node/arith_pvm.ml | 10 +++++++ .../lib_sc_rollup_node/pvm_sig.ml | 13 +++++++++ .../lib_sc_rollup_node/wasm_2_0_0_pvm.ml | 29 +++++++++++++++++-- .../lib_sc_rollup_node/riscv_pvm.ml | 10 +++++++ 4 files changed, 59 insertions(+), 3 deletions(-) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/arith_pvm.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/arith_pvm.ml index 276d555ce826..c52e0b04cdeb 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/arith_pvm.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/arith_pvm.ml @@ -57,6 +57,16 @@ module Impl : Pvm_sig.S = struct raise (Invalid_argument "No durable storage for arith PVM") end + module Unsafe_patches = struct + (** No unsafe patches for the arith PVM. *) + type t = | + + let of_patch (p : Pvm_patches.unsafe_patch) = + match p with Increase_max_nb_ticks _ -> assert false + + let apply _state (x : t) = match x with _ -> . + end + let new_dissection = Game_helpers.default_new_dissection let string_of_status status = diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/pvm_sig.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/pvm_sig.ml index 1d7f5e8c1685..3b0cc19d9e57 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/pvm_sig.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/pvm_sig.ml @@ -98,4 +98,17 @@ module type S = sig PVM state [state]. *) val lookup : state -> string list -> bytes option Lwt.t end + + (** Expose unsafe state patching functions for manual intervention. + At the moment this feature is only used to increase the maximum number of + ticks of the WASM PVM in a non refutable setting. *) + module Unsafe_patches : sig + type t + + (** [of_patch p] returns the PVM patch if it has a corresponding one. *) + val of_patch : Pvm_patches.unsafe_patch -> t tzresult + + (** [apply state patch] applies the unsafe patch [patch] on the state. *) + val apply : state -> t -> state Lwt.t + end end diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/wasm_2_0_0_pvm.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/wasm_2_0_0_pvm.ml index 332381409f24..914584b5bf9a 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/wasm_2_0_0_pvm.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/wasm_2_0_0_pvm.ml @@ -162,7 +162,9 @@ end module Durable_state = Make_durable_state (Make_wrapped_tree (Wasm_2_0_0_proof_format.Tree)) -module Impl : Pvm_sig.S = struct +type unsafe_patch = Increase_max_nb_ticks of int64 + +module Impl : Pvm_sig.S with type Unsafe_patches.t = unsafe_patch = struct module PVM = Sc_rollup.Wasm_2_0_0PVM.Make (Make_backend) (Wasm_2_0_0_proof_format) include PVM @@ -179,6 +181,29 @@ module Impl : Pvm_sig.S = struct Durable_state.lookup state key end + module Backend = Make_backend (Wasm_2_0_0_proof_format.Tree) + + module Unsafe_patches = struct + type t = unsafe_patch + + let of_patch (p : Pvm_patches.unsafe_patch) = + match p with + | Increase_max_nb_ticks max_nb_ticks -> + Ok (Increase_max_nb_ticks max_nb_ticks) + + let apply state (Increase_max_nb_ticks max_nb_ticks) = + let open Lwt_syntax in + let* registered_max_nb_ticks = Backend.Unsafe.get_max_nb_ticks state in + let max_nb_ticks = Z.of_int64 max_nb_ticks in + if Z.Compare.(max_nb_ticks < registered_max_nb_ticks) then + Format.ksprintf + invalid_arg + "Decreasing tick limit of WASM PVM from %s to %s is not allowed" + (Z.to_string registered_max_nb_ticks) + (Z.to_string max_nb_ticks) ; + Backend.Unsafe.set_max_nb_ticks max_nb_ticks state + end + let string_of_status : status -> string = function | Waiting_for_input_message -> "Waiting for input message" | Waiting_for_reveal (Sc_rollup.Reveal_raw_data hash) -> @@ -191,8 +216,6 @@ module Impl : Pvm_sig.S = struct Format.asprintf "Waiting for page data %a" Dal.Page.pp page_id | Computing -> "Computing" - module Backend = Make_backend (Wasm_2_0_0_proof_format.Tree) - let eval_many ~reveal_builtins ~write_debug = Backend.compute_step_many ~wasm_entrypoint:Tezos_scoru_wasm.Constants.wasm_entrypoint diff --git a/src/proto_019_PtParisB/lib_sc_rollup_node/riscv_pvm.ml b/src/proto_019_PtParisB/lib_sc_rollup_node/riscv_pvm.ml index e489ea2c2b38..5bdcea883a6a 100644 --- a/src/proto_019_PtParisB/lib_sc_rollup_node/riscv_pvm.ml +++ b/src/proto_019_PtParisB/lib_sc_rollup_node/riscv_pvm.ml @@ -207,3 +207,13 @@ module Inspect_durable_state = struct let lookup _state _keys = raise (Invalid_argument "No durable storage for riscv PVM") end + +module Unsafe_patches = struct + (** No unsafe patches for the riscv PVM. *) + type t = | + + let of_patch (p : Pvm_patches.unsafe_patch) = + match p with Increase_max_nb_ticks _ -> assert false + + let apply _state (x : t) = match x with _ -> . +end -- GitLab From e42105368b1cf3de7311dae5159a4fc7a84f0761 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Fri, 12 Apr 2024 12:41:20 +0200 Subject: [PATCH 06/16] Rollup node/Oxford: support for increasing tick limit in WASM PVM --- .../lib_sc_rollup_node/arith_pvm.ml | 10 +++++++ .../lib_sc_rollup_node/pvm_sig.ml | 13 +++++++++ .../lib_sc_rollup_node/riscv_pvm.ml | 10 +++++++ .../lib_sc_rollup_node/wasm_2_0_0_pvm.ml | 29 +++++++++++++++++-- 4 files changed, 59 insertions(+), 3 deletions(-) diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/arith_pvm.ml b/src/proto_018_Proxford/lib_sc_rollup_node/arith_pvm.ml index b03bcdf4aa44..3f19be4f9ff3 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_node/arith_pvm.ml +++ b/src/proto_018_Proxford/lib_sc_rollup_node/arith_pvm.ml @@ -57,6 +57,16 @@ module Impl : Pvm_sig.S = struct raise (Invalid_argument "No durable storage for arith PVM") end + module Unsafe_patches = struct + (** No unsafe patches for the arith PVM. *) + type t = | + + let of_patch (p : Pvm_patches.unsafe_patch) = + match p with Increase_max_nb_ticks _ -> assert false + + let apply _state (x : t) = match x with _ -> . + end + let new_dissection = Game_helpers.default_new_dissection let string_of_status = function diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/pvm_sig.ml b/src/proto_018_Proxford/lib_sc_rollup_node/pvm_sig.ml index 402093322a9c..8adef28bf988 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_node/pvm_sig.ml +++ b/src/proto_018_Proxford/lib_sc_rollup_node/pvm_sig.ml @@ -100,4 +100,17 @@ module type S = sig PVM state [state]. *) val lookup : state -> string list -> bytes option Lwt.t end + + (** Expose unsafe state patching functions for manual intervention. + At the moment this feature is only used to increase the maximum number of + ticks of the WASM PVM in a non refutable setting. *) + module Unsafe_patches : sig + type t + + (** [of_patch p] returns the PVM patch if it has a corresponding one. *) + val of_patch : Pvm_patches.unsafe_patch -> t tzresult + + (** [apply state patch] applies the unsafe patch [patch] on the state. *) + val apply : state -> t -> state Lwt.t + end end diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/riscv_pvm.ml b/src/proto_018_Proxford/lib_sc_rollup_node/riscv_pvm.ml index ea93568f547d..a8d3682cc4c5 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_node/riscv_pvm.ml +++ b/src/proto_018_Proxford/lib_sc_rollup_node/riscv_pvm.ml @@ -201,3 +201,13 @@ module Inspect_durable_state = struct let lookup _state _keys = raise (Invalid_argument "No durable storage for riscv PVM") end + +module Unsafe_patches = struct + (** No unsafe patches for the riscv PVM. *) + type t = | + + let of_patch (p : Pvm_patches.unsafe_patch) = + match p with Increase_max_nb_ticks _ -> assert false + + let apply _state (x : t) = match x with _ -> . +end diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/wasm_2_0_0_pvm.ml b/src/proto_018_Proxford/lib_sc_rollup_node/wasm_2_0_0_pvm.ml index 37a19ee5787b..bd2225b2a757 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_node/wasm_2_0_0_pvm.ml +++ b/src/proto_018_Proxford/lib_sc_rollup_node/wasm_2_0_0_pvm.ml @@ -130,7 +130,9 @@ end module Durable_state = Make_durable_state (Make_wrapped_tree (Wasm_2_0_0_proof_format.Tree)) -module Impl : Pvm_sig.S = struct +type unsafe_patch = Increase_max_nb_ticks of int64 + +module Impl : Pvm_sig.S with type Unsafe_patches.t = unsafe_patch = struct module PVM = Sc_rollup.Wasm_2_0_0PVM.Make (Make_backend) (Wasm_2_0_0_proof_format) include PVM @@ -147,6 +149,29 @@ module Impl : Pvm_sig.S = struct Durable_state.lookup state key end + module Backend = Make_backend (Wasm_2_0_0_proof_format.Tree) + + module Unsafe_patches = struct + type t = unsafe_patch + + let of_patch (p : Pvm_patches.unsafe_patch) = + match p with + | Increase_max_nb_ticks max_nb_ticks -> + Ok (Increase_max_nb_ticks max_nb_ticks) + + let apply state (Increase_max_nb_ticks max_nb_ticks) = + let open Lwt_syntax in + let* registered_max_nb_ticks = Backend.Unsafe.get_max_nb_ticks state in + let max_nb_ticks = Z.of_int64 max_nb_ticks in + if Z.Compare.(max_nb_ticks < registered_max_nb_ticks) then + Format.ksprintf + invalid_arg + "Decreasing tick limit of WASM PVM from %s to %s is not allowed" + (Z.to_string registered_max_nb_ticks) + (Z.to_string max_nb_ticks) ; + Backend.Unsafe.set_max_nb_ticks max_nb_ticks state + end + let string_of_status : status -> string = function | Waiting_for_input_message -> "Waiting for input message" | Waiting_for_reveal (Sc_rollup.Reveal_raw_data hash) -> @@ -161,8 +186,6 @@ module Impl : Pvm_sig.S = struct "Waiting for DAL parameters" | Computing -> "Computing" - module Backend = Make_backend (Wasm_2_0_0_proof_format.Tree) - let eval_many ~reveal_builtins ~write_debug ~is_reveal_enabled:_ = Backend.compute_step_many ~wasm_entrypoint:Tezos_scoru_wasm.Constants.wasm_entrypoint -- GitLab From ad2a4fd1c5f7731e3575f655805b1af9b95e56ba Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 16 Apr 2024 14:32:20 +0200 Subject: [PATCH 07/16] Rollup node: unsafe PVM patches in PVM signature --- src/lib_smart_rollup_node/pvm_plugin_sig.ml | 8 ++++++++ .../lib_sc_rollup_node/pvm_plugin.ml | 13 +++++++++++++ .../lib_sc_rollup_node/pvm_plugin.ml | 13 +++++++++++++ .../lib_sc_rollup_node/pvm_plugin.ml | 14 ++++++++++++++ src/proto_alpha/lib_sc_rollup_node/pvm_plugin.ml | 14 ++++++++++++++ 5 files changed, 62 insertions(+) diff --git a/src/lib_smart_rollup_node/pvm_plugin_sig.ml b/src/lib_smart_rollup_node/pvm_plugin_sig.ml index 78f4483b9bb2..e8cded953126 100644 --- a/src/lib_smart_rollup_node/pvm_plugin_sig.ml +++ b/src/lib_smart_rollup_node/pvm_plugin_sig.ml @@ -117,6 +117,14 @@ module type S = sig val info_per_level_serialized : predecessor:Block_hash.t -> predecessor_timestamp:Time.Protocol.t -> string + module Unsafe : sig + val apply_patch : + Kind.t -> + Context.pvmstate -> + Pvm_patches.unsafe_patch -> + Context.pvmstate tzresult Lwt.t + end + module Wasm_2_0_0 : sig (** [decode_durable_state enc tree] decodes a value using the encoder [enc] from the provided [tree] *) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/pvm_plugin.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/pvm_plugin.ml index 9a69a4f65f5e..a348532f4808 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/pvm_plugin.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/pvm_plugin.ml @@ -140,3 +140,16 @@ module Wasm_2_0_0 = struct ~init ~f:(fun a b c -> f a (to_node_pvmstate b) c) end + +module Unsafe = struct + let apply_patch (kind : Octez_smart_rollup.Kind.t) state + (patch : Pvm_patches.unsafe_patch) = + let open Lwt_result_syntax in + let open (val Pvm.of_kind kind) in + let*? patch = Unsafe_patches.of_patch patch in + let* state = + protect @@ fun () -> + Unsafe_patches.apply (of_node_pvmstate state) patch |> Lwt_result.ok + in + return (to_node_pvmstate state) +end diff --git a/src/proto_018_Proxford/lib_sc_rollup_node/pvm_plugin.ml b/src/proto_018_Proxford/lib_sc_rollup_node/pvm_plugin.ml index f3e7d97b3334..af7dcb6d1e34 100644 --- a/src/proto_018_Proxford/lib_sc_rollup_node/pvm_plugin.ml +++ b/src/proto_018_Proxford/lib_sc_rollup_node/pvm_plugin.ml @@ -164,3 +164,16 @@ module Wasm_2_0_0 = struct ~init ~f:(fun a b c -> f a (to_node_pvmstate b) c) end + +module Unsafe = struct + let apply_patch (kind : Octez_smart_rollup.Kind.t) state + (patch : Pvm_patches.unsafe_patch) = + let open Lwt_result_syntax in + let open (val Pvm.of_kind kind) in + let*? patch = Unsafe_patches.of_patch patch in + let* state = + protect @@ fun () -> + Unsafe_patches.apply (of_node_pvmstate state) patch |> Lwt_result.ok + in + return (to_node_pvmstate state) +end diff --git a/src/proto_019_PtParisB/lib_sc_rollup_node/pvm_plugin.ml b/src/proto_019_PtParisB/lib_sc_rollup_node/pvm_plugin.ml index 9add3e39757f..8c403dae83ac 100644 --- a/src/proto_019_PtParisB/lib_sc_rollup_node/pvm_plugin.ml +++ b/src/proto_019_PtParisB/lib_sc_rollup_node/pvm_plugin.ml @@ -172,3 +172,17 @@ module Wasm_2_0_0 = struct ~init ~f:(fun a b c -> f a (to_node_pvmstate b) c) end + +module Unsafe = struct + let apply_patch (kind : Octez_smart_rollup.Kind.t) state + (patch : Pvm_patches.unsafe_patch) = + let open Lwt_result_syntax in + let open (val Pvm.of_kind kind) in + let*? patch = Unsafe_patches.of_patch patch in + let* state = + protect @@ fun () -> + Unsafe_patches.apply (Ctxt_wrapper.of_node_pvmstate state) patch + |> Lwt_result.ok + in + return (Ctxt_wrapper.to_node_pvmstate state) +end diff --git a/src/proto_alpha/lib_sc_rollup_node/pvm_plugin.ml b/src/proto_alpha/lib_sc_rollup_node/pvm_plugin.ml index 9add3e39757f..8c403dae83ac 100644 --- a/src/proto_alpha/lib_sc_rollup_node/pvm_plugin.ml +++ b/src/proto_alpha/lib_sc_rollup_node/pvm_plugin.ml @@ -172,3 +172,17 @@ module Wasm_2_0_0 = struct ~init ~f:(fun a b c -> f a (to_node_pvmstate b) c) end + +module Unsafe = struct + let apply_patch (kind : Octez_smart_rollup.Kind.t) state + (patch : Pvm_patches.unsafe_patch) = + let open Lwt_result_syntax in + let open (val Pvm.of_kind kind) in + let*? patch = Unsafe_patches.of_patch patch in + let* state = + protect @@ fun () -> + Unsafe_patches.apply (Ctxt_wrapper.of_node_pvmstate state) patch + |> Lwt_result.ok + in + return (Ctxt_wrapper.to_node_pvmstate state) +end -- GitLab From cdd717c9ad152a61f5643eab59c0c8f6a269e4e7 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 16 Apr 2024 11:33:26 +0200 Subject: [PATCH 08/16] Rollup node: hardcoded PVM patches --- src/lib_smart_rollup_node/pvm_patches.ml | 31 +++++++++++++++++++++++ src/lib_smart_rollup_node/pvm_patches.mli | 10 ++++++++ 2 files changed, 41 insertions(+) diff --git a/src/lib_smart_rollup_node/pvm_patches.ml b/src/lib_smart_rollup_node/pvm_patches.ml index 1ac798acb89e..05273d5db9d0 100644 --- a/src/lib_smart_rollup_node/pvm_patches.ml +++ b/src/lib_smart_rollup_node/pvm_patches.ml @@ -6,3 +6,34 @@ (*****************************************************************************) type unsafe_patch = Increase_max_nb_ticks of int64 + +type t = unsafe_patch list + +(* Patches for Etherlink PVM. *) +let etherlink_patches = [Increase_max_nb_ticks 50_000_000_000_000L] + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/7148 + Add hardcoded etherlink addresses on various networks. *) +let etherlink_addresses = [] + +let hardcoded_patches_list = + List.map (fun addr -> (addr, etherlink_patches)) etherlink_addresses + +let make rollup_address patches = + let hardcoded_patches = + List.assoc ~equal:Address.equal rollup_address hardcoded_patches_list + |> Option.value ~default:[] + in + hardcoded_patches @ patches + +let unsafe_patch_encoding = + let open Data_encoding in + union + [ + case + (Tag 0) + ~title:"increase_max_nb_tick" + (obj1 (req "increase_max_nb_tick" int64)) + (function Increase_max_nb_ticks ticks -> Some ticks) + (fun ticks -> Increase_max_nb_ticks ticks); + ] diff --git a/src/lib_smart_rollup_node/pvm_patches.mli b/src/lib_smart_rollup_node/pvm_patches.mli index e249ec9bbf28..081a5574d9bd 100644 --- a/src/lib_smart_rollup_node/pvm_patches.mli +++ b/src/lib_smart_rollup_node/pvm_patches.mli @@ -9,3 +9,13 @@ type unsafe_patch = | Increase_max_nb_ticks of int64 (** Increase the maximum number of ticks. *) + +(** The type of registered patches for the PVM. *) +type t = private unsafe_patch list + +(** Encoding for unsafe patches. *) +val unsafe_patch_encoding : unsafe_patch Data_encoding.t + +(** [make address patches] builds the patches from the provided list [patches] + and adds the hardcoded PVM patches for the rollup [address]. *) +val make : Address.t -> unsafe_patch list -> t -- GitLab From 4a18be9fb3e5458fc6d6d257003e90f788bc44a6 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 16 Apr 2024 11:30:34 +0200 Subject: [PATCH 09/16] Rollup node/Interpreter: apply registered PVM patches --- src/lib_smart_rollup_node/interpreter.ml | 15 +++++++++++++-- src/lib_smart_rollup_node/node_context.ml | 1 + src/lib_smart_rollup_node/node_context.mli | 1 + src/lib_smart_rollup_node/node_context_loader.ml | 6 ++++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/lib_smart_rollup_node/interpreter.ml b/src/lib_smart_rollup_node/interpreter.ml index 33765d2e2de6..4e94196c75e9 100644 --- a/src/lib_smart_rollup_node/interpreter.ml +++ b/src/lib_smart_rollup_node/interpreter.ml @@ -40,6 +40,15 @@ let get_boot_sector (module Plugin : Protocol_plugin_sig.PARTIAL) block_hash in return boot_sector +(** Apply potential unsafe patches to the PVM state. *) +let apply_unsafe_patches (module Plugin : Protocol_plugin_sig.PARTIAL) + (node_ctxt : _ Node_context.t) state = + let open Lwt_result_syntax in + List.fold_left_es + (Plugin.Pvm.Unsafe.apply_patch node_ctxt.kind) + state + (node_ctxt.unsafe_patches :> Pvm_patches.unsafe_patch list) + let genesis_state (module Plugin : Protocol_plugin_sig.PARTIAL) block_hash node_ctxt ctxt = let open Lwt_result_syntax in @@ -48,6 +57,9 @@ let genesis_state (module Plugin : Protocol_plugin_sig.PARTIAL) block_hash let*! genesis_state = Plugin.Pvm.install_boot_sector node_ctxt.kind initial_state boot_sector in + let* genesis_state = + apply_unsafe_patches (module Plugin) node_ctxt genesis_state + in let*! ctxt = Context.PVMState.set ctxt genesis_state in return (ctxt, genesis_state) @@ -102,8 +114,7 @@ let process_head plugin (node_ctxt : _ Node_context.t) ctxt if head.level >= first_inbox_level then transition_pvm plugin node_ctxt ctxt predecessor head inbox_and_messages else if head.Layer1.level = node_ctxt.genesis_info.level then - let* ctxt, state = genesis_state plugin head.hash node_ctxt ctxt in - let*! ctxt = Context.PVMState.set ctxt state in + let* ctxt, _state = genesis_state plugin head.hash node_ctxt ctxt in return (ctxt, 0, 0L, Z.zero) else return (ctxt, 0, 0L, Z.zero) diff --git a/src/lib_smart_rollup_node/node_context.ml b/src/lib_smart_rollup_node/node_context.ml index 35a3a74bc209..c6f36a2ac2e3 100644 --- a/src/lib_smart_rollup_node/node_context.ml +++ b/src/lib_smart_rollup_node/node_context.ml @@ -106,6 +106,7 @@ type 'a t = { injector_retention_period : int; block_finality_time : int; kind : Kind.t; + unsafe_patches : Pvm_patches.t; lockfile : Lwt_unix.file_descr; store : 'a store; context : 'a Context.t; diff --git a/src/lib_smart_rollup_node/node_context.mli b/src/lib_smart_rollup_node/node_context.mli index 7d246ee8577e..f28826f182d8 100644 --- a/src/lib_smart_rollup_node/node_context.mli +++ b/src/lib_smart_rollup_node/node_context.mli @@ -112,6 +112,7 @@ type 'a t = { block_finality_time : int; (** Deterministic block finality time for the layer 1 protocol. *) kind : Kind.t; (** Kind of the smart rollup. *) + unsafe_patches : Pvm_patches.t; (** Patches to apply to the PVM. *) lockfile : Lwt_unix.file_descr; (** A lock file acquired when the node starts. *) store : 'a store; (** The store for the persistent storage. *) diff --git a/src/lib_smart_rollup_node/node_context_loader.ml b/src/lib_smart_rollup_node/node_context_loader.ml index 856ebd23616a..e11bb84b62dc 100644 --- a/src/lib_smart_rollup_node/node_context_loader.ml +++ b/src/lib_smart_rollup_node/node_context_loader.ml @@ -171,6 +171,7 @@ let init (cctxt : #Client_context.full) ~data_dir ~irmin_cache_size }) last_whitelist_update in + let unsafe_patches = Pvm_patches.make rollup_address [] in let sync = create_sync_info () in let node_ctxt = { @@ -185,6 +186,7 @@ let init (cctxt : #Client_context.full) ~data_dir ~irmin_cache_size lpc = Reference.new_ lpc; private_info = Reference.new_ private_info; kind; + unsafe_patches; injector_retention_period = 0; block_finality_time = 2; lockfile; @@ -310,6 +312,9 @@ module For_snapshots = struct lpc = Reference.new_ lpc; private_info = Reference.new_ None; kind = metadata.kind; + unsafe_patches = + (* Only consider hardcoded patches for snapshot validation. *) + Pvm_patches.make metadata.rollup_address []; injector_retention_period = 0; block_finality_time = 2; lockfile; @@ -424,6 +429,7 @@ module Internal_for_tests = struct lpc; private_info = Reference.new_ None; kind; + unsafe_patches = Pvm_patches.make rollup_address []; injector_retention_period = 0; block_finality_time = 2; current_protocol; -- GitLab From 7270c3f487bfb6329ece953520c984c0cab03f81 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 16 Apr 2024 11:30:57 +0200 Subject: [PATCH 10/16] Rollup node: allow to provide additional unsafe pvm patches in config --- src/lib_smart_rollup_node/configuration.ml | 31 +++++++++++++++---- src/lib_smart_rollup_node/configuration.mli | 1 + .../node_context_loader.ml | 6 +++- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/lib_smart_rollup_node/configuration.ml b/src/lib_smart_rollup_node/configuration.ml index 7afa3667f2d9..552bb1a8caeb 100644 --- a/src/lib_smart_rollup_node/configuration.ml +++ b/src/lib_smart_rollup_node/configuration.ml @@ -64,6 +64,7 @@ type t = { fee_parameters : fee_parameters; mode : mode; loser_mode : Loser_mode.t; + unsafe_pvm_patches : Pvm_patches.unsafe_patch list; dal_node_endpoint : Uri.t option; dac_observer_endpoint : Uri.t option; dac_timeout : Z.t option; @@ -436,6 +437,7 @@ let encoding default_display : t Data_encoding.t = fee_parameters; mode; loser_mode; + unsafe_pvm_patches; dal_node_endpoint; dac_observer_endpoint; dac_timeout; @@ -461,8 +463,12 @@ let encoding default_display : t Data_encoding.t = rpc_addr, rpc_port, acl ), - (metrics_addr, reconnection_delay, fee_parameters, mode, loser_mode) - ), + ( metrics_addr, + reconnection_delay, + fee_parameters, + mode, + loser_mode, + unsafe_pvm_patches ) ), ( ( dal_node_endpoint, dac_observer_endpoint, dac_timeout, @@ -487,8 +493,12 @@ let encoding default_display : t Data_encoding.t = rpc_addr, rpc_port, acl ), - (metrics_addr, reconnection_delay, fee_parameters, mode, loser_mode) - ), + ( metrics_addr, + reconnection_delay, + fee_parameters, + mode, + loser_mode, + unsafe_pvm_patches ) ), ( ( dal_node_endpoint, dac_observer_endpoint, dac_timeout, @@ -519,6 +529,7 @@ let encoding default_display : t Data_encoding.t = fee_parameters; mode; loser_mode; + unsafe_pvm_patches; dal_node_endpoint; dac_observer_endpoint; dac_timeout; @@ -559,7 +570,7 @@ let encoding default_display : t Data_encoding.t = ~description:"Access control list" Tezos_rpc_http_server.RPC_server.Acl.policy_encoding default_acl)) - (obj5 + (obj6 (opt "metrics-addr" ~description:"Metrics address" string) (dft "reconnection_delay" @@ -584,7 +595,14 @@ let encoding default_display : t Data_encoding.t = "If enabled, the rollup node will issue wrong commitments \ (for test only!)" Loser_mode.encoding - Loser_mode.no_failures))) + Loser_mode.no_failures) + (dft + "unsafe-pvm-patches" + ~description: + "Unsafe patches to apply to the PVM. For tests only, don't \ + set this value in production." + (list Pvm_patches.unsafe_patch_encoding) + []))) (merge_objs (obj9 (opt "DAL node endpoint" Tezos_rpc.Encoding.uri_encoding) @@ -753,6 +771,7 @@ module Cli = struct fee_parameters = Operation_kind.Map.empty; mode; loser_mode = Option.value ~default:Loser_mode.no_failures loser_mode; + unsafe_pvm_patches = []; batcher = default_batcher; injector = { diff --git a/src/lib_smart_rollup_node/configuration.mli b/src/lib_smart_rollup_node/configuration.mli index f9f146d5db46..fefcc0373276 100644 --- a/src/lib_smart_rollup_node/configuration.mli +++ b/src/lib_smart_rollup_node/configuration.mli @@ -93,6 +93,7 @@ type t = { fee_parameters : fee_parameters; mode : mode; loser_mode : Loser_mode.t; + unsafe_pvm_patches : Pvm_patches.unsafe_patch list; (*DAL/FIXME: https://gitlab.com/tezos/tezos/-/issues/3718 Decide whether we want to handle connections to multiple Dal nodes for different slot indexes. diff --git a/src/lib_smart_rollup_node/node_context_loader.ml b/src/lib_smart_rollup_node/node_context_loader.ml index e11bb84b62dc..f33744f16c4e 100644 --- a/src/lib_smart_rollup_node/node_context_loader.ml +++ b/src/lib_smart_rollup_node/node_context_loader.ml @@ -171,7 +171,9 @@ let init (cctxt : #Client_context.full) ~data_dir ~irmin_cache_size }) last_whitelist_update in - let unsafe_patches = Pvm_patches.make rollup_address [] in + let unsafe_patches = + Pvm_patches.make rollup_address configuration.unsafe_pvm_patches + in let sync = create_sync_info () in let node_ctxt = { @@ -256,6 +258,7 @@ module For_snapshots = struct fee_parameters = Configuration.default_fee_parameters; mode; loser_mode; + unsafe_pvm_patches = []; dal_node_endpoint = None; dac_observer_endpoint = None; dac_timeout = None; @@ -359,6 +362,7 @@ module Internal_for_tests = struct fee_parameters = Configuration.default_fee_parameters; mode; loser_mode; + unsafe_pvm_patches = []; dal_node_endpoint = None; dac_observer_endpoint = None; dac_timeout = None; -- GitLab From e5446c6fbc008eeb0dced15166acf491f0fa66d7 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 16 Apr 2024 10:57:01 +0200 Subject: [PATCH 11/16] Rollup node: expose genesis_state function with unpatched version --- src/lib_smart_rollup_node/interpreter.ml | 43 ++++++++++++++--------- src/lib_smart_rollup_node/interpreter.mli | 22 +++++++++--- src/lib_smart_rollup_node/simulation.ml | 2 +- 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/src/lib_smart_rollup_node/interpreter.ml b/src/lib_smart_rollup_node/interpreter.ml index 4e94196c75e9..3f118eac92b5 100644 --- a/src/lib_smart_rollup_node/interpreter.ml +++ b/src/lib_smart_rollup_node/interpreter.ml @@ -23,11 +23,11 @@ (* *) (*****************************************************************************) -let get_boot_sector (module Plugin : Protocol_plugin_sig.PARTIAL) block_hash - (node_ctxt : _ Node_context.t) = +let get_boot_sector (module Plugin : Protocol_plugin_sig.PARTIAL) + genesis_block_hash (node_ctxt : _ Node_context.t) = let open Lwt_result_syntax in match node_ctxt.config.boot_sector_file with - | None -> Plugin.Layer1_helpers.get_boot_sector block_hash node_ctxt + | None -> Plugin.Layer1_helpers.get_boot_sector genesis_block_hash node_ctxt | Some boot_sector_file -> let*! boot_sector = Lwt_utils_unix.read_file boot_sector_file in let*? boot_sector = @@ -49,19 +49,27 @@ let apply_unsafe_patches (module Plugin : Protocol_plugin_sig.PARTIAL) state (node_ctxt.unsafe_patches :> Pvm_patches.unsafe_patch list) -let genesis_state (module Plugin : Protocol_plugin_sig.PARTIAL) block_hash - node_ctxt ctxt = +type original_genesis_state = Original of Context.pvmstate + +let genesis_state (module Plugin : Protocol_plugin_sig.PARTIAL) ?genesis_block + node_ctxt = let open Lwt_result_syntax in - let* boot_sector = get_boot_sector (module Plugin) block_hash node_ctxt in + let* genesis_block_hash = + match genesis_block with + | Some b -> return b + | None -> Node_context.hash_of_level node_ctxt node_ctxt.genesis_info.level + in + let* boot_sector = + get_boot_sector (module Plugin) genesis_block_hash node_ctxt + in let*! initial_state = Plugin.Pvm.initial_state node_ctxt.kind in - let*! genesis_state = + let*! unpatched_genesis_state = Plugin.Pvm.install_boot_sector node_ctxt.kind initial_state boot_sector in let* genesis_state = - apply_unsafe_patches (module Plugin) node_ctxt genesis_state + apply_unsafe_patches (module Plugin) node_ctxt unpatched_genesis_state in - let*! ctxt = Context.PVMState.set ctxt genesis_state in - return (ctxt, genesis_state) + return (genesis_state, Original unpatched_genesis_state) let state_of_head plugin node_ctxt ctxt Layer1.{hash; level} = let open Lwt_result_syntax in @@ -69,9 +77,11 @@ let state_of_head plugin node_ctxt ctxt Layer1.{hash; level} = match state with | None -> let genesis_level = node_ctxt.Node_context.genesis_info.level in - if level = genesis_level then genesis_state plugin hash node_ctxt ctxt + if level = genesis_level then + let+ state, _ = genesis_state plugin ~genesis_block:hash node_ctxt in + state else tzfail (Rollup_node_errors.Missing_PVM_state (hash, level)) - | Some state -> return (ctxt, state) + | Some state -> return state (** [transition_pvm plugin node_ctxt ctxt predecessor head] runs a PVM at the previous state from block [predecessor] by consuming as many messages as @@ -80,7 +90,7 @@ let transition_pvm (module Plugin : Protocol_plugin_sig.PARTIAL) node_ctxt ctxt predecessor Layer1.{hash = _; _} inbox_messages = let open Lwt_result_syntax in (* Retrieve the previous PVM state from store. *) - let* ctxt, predecessor_state = + let* predecessor_state = state_of_head (module Plugin) node_ctxt ctxt predecessor in let* eval_result = @@ -113,8 +123,9 @@ let process_head plugin (node_ctxt : _ Node_context.t) ctxt let first_inbox_level = node_ctxt.genesis_info.level |> Int32.succ in if head.level >= first_inbox_level then transition_pvm plugin node_ctxt ctxt predecessor head inbox_and_messages - else if head.Layer1.level = node_ctxt.genesis_info.level then - let* ctxt, _state = genesis_state plugin head.hash node_ctxt ctxt in + else if head.level = node_ctxt.genesis_info.level then + let* state, _ = genesis_state plugin ~genesis_block:head.hash node_ctxt in + let*! ctxt = Context.PVMState.set ctxt state in return (ctxt, 0, 0L, Z.zero) else return (ctxt, 0, 0L, Z.zero) @@ -127,7 +138,7 @@ let start_state_of_block plugin node_ctxt (block : Sc_rollup_block.t) = let* ctxt = Node_context.checkout_context node_ctxt block.header.predecessor in - let* _ctxt, state = + let* state = state_of_head plugin node_ctxt diff --git a/src/lib_smart_rollup_node/interpreter.mli b/src/lib_smart_rollup_node/interpreter.mli index 0d9cbbd9889e..e18c5576393e 100644 --- a/src/lib_smart_rollup_node/interpreter.mli +++ b/src/lib_smart_rollup_node/interpreter.mli @@ -40,10 +40,24 @@ val process_head : Octez_smart_rollup.Inbox.t * string list -> ('a Context.t * int * int64 * Z.t) tzresult Lwt.t +type original_genesis_state = Original of Context.pvmstate + +(** [genesis_state plugin ?genesis_block node_ctxt] returns a pair [s1, s2] + where [s1] is the PVM state at the genesis block and [s2] is the genesis + state without any patches applied. [s2] is meant to be used to compute the + genesis commitment. If there are no unsafe patches for the rollup [s2] is + the same as [s1]. *) +val genesis_state : + (module Protocol_plugin_sig.PARTIAL) -> + ?genesis_block:Block_hash.t -> + _ Node_context.t -> + (Context.pvmstate * original_genesis_state) tzresult Lwt.t + (** [state_of_tick plugin 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]. *) + state] for a given [tick] if this [tick] happened before [level] and where + [state] is the PVM evaluation state before [tick] happened. Otherwise, + returns [None]. If provided, the evaluation is resumed from + [start_state]. *) val state_of_tick : (module Protocol_plugin_sig.PARTIAL) -> Node_context.rw -> @@ -60,4 +74,4 @@ val state_of_head : 'a Node_context.t -> 'a Context.t -> Layer1.head -> - ('a Context.t * Context.pvmstate) tzresult Lwt.t + Context.pvmstate tzresult Lwt.t diff --git a/src/lib_smart_rollup_node/simulation.ml b/src/lib_smart_rollup_node/simulation.ml index 11dff5f68999..b8f10187ca17 100644 --- a/src/lib_smart_rollup_node/simulation.ml +++ b/src/lib_smart_rollup_node/simulation.ml @@ -89,7 +89,7 @@ let start_simulation node_ctxt ~reveal_map ?log_kernel_debug_file return (Context.empty node_ctxt.context) else Node_context.checkout_context node_ctxt hash in - let* ctxt, state = + let* state = Interpreter.state_of_head (module (val plugin)) node_ctxt ctxt head in let+ info_per_level = simulate_info_per_level node_ctxt hash in -- GitLab From 066edab201a5a4a2bc9c65c7c12a223102ba8c79 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 16 Apr 2024 11:11:34 +0200 Subject: [PATCH 12/16] Rollup node/Commitment: compute genesis commitment using unpatched state --- src/lib_smart_rollup_node/publisher.ml | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/lib_smart_rollup_node/publisher.ml b/src/lib_smart_rollup_node/publisher.ml index 98d96797fb05..95f987412099 100644 --- a/src/lib_smart_rollup_node/publisher.ml +++ b/src/lib_smart_rollup_node/publisher.ml @@ -128,15 +128,28 @@ let build_commitment (module Plugin : Protocol_plugin_sig.S) compressed_state; } +let genesis_pvm_state (module Plugin : Protocol_plugin_sig.S) + (node_ctxt : _ Node_context.t) ctxt = + let open Lwt_result_syntax in + match (node_ctxt.unsafe_patches :> Pvm_patches.unsafe_patch list) with + | [] -> ( + let*! pvm_state = Context.PVMState.find ctxt in + match pvm_state with + | Some pvm_state -> return pvm_state + | None -> failwith "PVM state for genesis commitment is not available") + | _ -> + (* If there are unsafe patches that were applied to the genesis PVM state, + we instead recompute the unpatched version to derive the commitment as + all the following ones will need to be chained to it. *) + let+ _, Original state = + Interpreter.genesis_state (module Plugin) node_ctxt + in + state + let genesis_commitment (module Plugin : Protocol_plugin_sig.S) (node_ctxt : _ Node_context.t) ctxt = let open Lwt_result_syntax in - let*! pvm_state = Context.PVMState.find ctxt in - let*? pvm_state = - match pvm_state with - | Some pvm_state -> Ok pvm_state - | None -> error_with "PVM state for genesis commitment is not available" - in + let* pvm_state = genesis_pvm_state (module Plugin) node_ctxt ctxt in let*! compressed_state = Plugin.Pvm.state_hash node_ctxt.kind pvm_state in let commitment = Octez_smart_rollup.Commitment. -- GitLab From a15d4164be6590600a120df1c11e12d0aa355ac5 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 16 Apr 2024 11:19:33 +0200 Subject: [PATCH 13/16] Rollup node: emit warning when patching genesis state --- src/lib_smart_rollup_node/interpreter.ml | 4 +++- src/lib_smart_rollup_node/interpreter_event.ml | 11 +++++++++++ src/lib_smart_rollup_node/pvm_patches.ml | 4 ++++ src/lib_smart_rollup_node/pvm_patches.mli | 3 +++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/lib_smart_rollup_node/interpreter.ml b/src/lib_smart_rollup_node/interpreter.ml index 3f118eac92b5..4b199972aec3 100644 --- a/src/lib_smart_rollup_node/interpreter.ml +++ b/src/lib_smart_rollup_node/interpreter.ml @@ -45,7 +45,9 @@ let apply_unsafe_patches (module Plugin : Protocol_plugin_sig.PARTIAL) (node_ctxt : _ Node_context.t) state = let open Lwt_result_syntax in List.fold_left_es - (Plugin.Pvm.Unsafe.apply_patch node_ctxt.kind) + (fun state patch -> + let*! () = Interpreter_event.patching_genesis_state patch in + Plugin.Pvm.Unsafe.apply_patch node_ctxt.kind state patch) state (node_ctxt.unsafe_patches :> Pvm_patches.unsafe_patch list) diff --git a/src/lib_smart_rollup_node/interpreter_event.ml b/src/lib_smart_rollup_node/interpreter_event.ml index 96ed2611c2ee..4a3122a33dd0 100644 --- a/src/lib_smart_rollup_node/interpreter_event.ml +++ b/src/lib_smart_rollup_node/interpreter_event.ml @@ -76,6 +76,15 @@ module Simple = struct ("content_hash", Data_encoding.string) ~pp1:Format.pp_print_string ~pp2:Format.pp_print_string + + let patching_genesis_state = + declare_1 + ~section + ~name:"smart_rollup_node_interpreter_patching_genesis_pvm_state" + ~msg:"Patching genesis PVM state: {patch}" + ~level:Warning + ("patch", Pvm_patches.unsafe_patch_encoding) + ~pp1:Pvm_patches.pp_unsafe_patch end (** [transition_pvm inbox_level hash tick n] emits the event that a PVM @@ -98,3 +107,5 @@ let missing_pre_image ~hash = Simple.(emit missing_pre_image) hash let fetched_incorrect_pre_image ~expected_hash ~content_hash = Simple.(emit fetched_incorrect_pre_image) (expected_hash, content_hash) + +let patching_genesis_state patch = Simple.(emit patching_genesis_state) patch diff --git a/src/lib_smart_rollup_node/pvm_patches.ml b/src/lib_smart_rollup_node/pvm_patches.ml index 05273d5db9d0..04e94b7ef634 100644 --- a/src/lib_smart_rollup_node/pvm_patches.ml +++ b/src/lib_smart_rollup_node/pvm_patches.ml @@ -37,3 +37,7 @@ let unsafe_patch_encoding = (function Increase_max_nb_ticks ticks -> Some ticks) (fun ticks -> Increase_max_nb_ticks ticks); ] + +let pp_unsafe_patch fmt = function + | Increase_max_nb_ticks nb -> + Format.fprintf fmt "Increase maximum number of ticks to %#Ld" nb diff --git a/src/lib_smart_rollup_node/pvm_patches.mli b/src/lib_smart_rollup_node/pvm_patches.mli index 081a5574d9bd..12f20b278f85 100644 --- a/src/lib_smart_rollup_node/pvm_patches.mli +++ b/src/lib_smart_rollup_node/pvm_patches.mli @@ -16,6 +16,9 @@ type t = private unsafe_patch list (** Encoding for unsafe patches. *) val unsafe_patch_encoding : unsafe_patch Data_encoding.t +(** Pretty printer for unsafe patches. *) +val pp_unsafe_patch : Format.formatter -> unsafe_patch -> unit + (** [make address patches] builds the patches from the provided list [patches] and adds the hardcoded PVM patches for the rollup [address]. *) val make : Address.t -> unsafe_patch list -> t -- GitLab From cafa11db360d8d3913b9cfe09c285c4c40988db3 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 16 Apr 2024 11:44:47 +0200 Subject: [PATCH 14/16] Rollup node: fail if patch is not applicable for rollup kind --- .../node_context_loader.ml | 15 +++++---- src/lib_smart_rollup_node/pvm_patches.ml | 31 ++++++++++++++----- src/lib_smart_rollup_node/pvm_patches.mli | 6 ++-- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/lib_smart_rollup_node/node_context_loader.ml b/src/lib_smart_rollup_node/node_context_loader.ml index f33744f16c4e..0a8d579d5603 100644 --- a/src/lib_smart_rollup_node/node_context_loader.ml +++ b/src/lib_smart_rollup_node/node_context_loader.ml @@ -171,8 +171,8 @@ let init (cctxt : #Client_context.full) ~data_dir ~irmin_cache_size }) last_whitelist_update in - let unsafe_patches = - Pvm_patches.make rollup_address configuration.unsafe_pvm_patches + let*? unsafe_patches = + Pvm_patches.make kind rollup_address configuration.unsafe_pvm_patches in let sync = create_sync_info () in let node_ctxt = @@ -302,6 +302,10 @@ module For_snapshots = struct in let global_block_watcher = Lwt_watcher.create_input () in let sync = create_sync_info () in + let*? unsafe_patches = + (* Only consider hardcoded patches for snapshot validation. *) + Pvm_patches.make metadata.kind metadata.rollup_address [] + in return { config; @@ -315,9 +319,7 @@ module For_snapshots = struct lpc = Reference.new_ lpc; private_info = Reference.new_ None; kind = metadata.kind; - unsafe_patches = - (* Only consider hardcoded patches for snapshot validation. *) - Pvm_patches.make metadata.rollup_address []; + unsafe_patches; injector_retention_period = 0; block_finality_time = 2; lockfile; @@ -420,6 +422,7 @@ module Internal_for_tests = struct in let global_block_watcher = Lwt_watcher.create_input () in let sync = create_sync_info () in + let*? unsafe_patches = Pvm_patches.make kind rollup_address [] in return { config; @@ -433,7 +436,7 @@ module Internal_for_tests = struct lpc; private_info = Reference.new_ None; kind; - unsafe_patches = Pvm_patches.make rollup_address []; + unsafe_patches; injector_retention_period = 0; block_finality_time = 2; current_protocol; diff --git a/src/lib_smart_rollup_node/pvm_patches.ml b/src/lib_smart_rollup_node/pvm_patches.ml index 04e94b7ef634..8b5f337b59c5 100644 --- a/src/lib_smart_rollup_node/pvm_patches.ml +++ b/src/lib_smart_rollup_node/pvm_patches.ml @@ -9,6 +9,8 @@ type unsafe_patch = Increase_max_nb_ticks of int64 type t = unsafe_patch list +let patch_kinds = function Increase_max_nb_ticks _ -> [Kind.Wasm_2_0_0] + (* Patches for Etherlink PVM. *) let etherlink_patches = [Increase_max_nb_ticks 50_000_000_000_000L] @@ -19,13 +21,6 @@ let etherlink_addresses = [] let hardcoded_patches_list = List.map (fun addr -> (addr, etherlink_patches)) etherlink_addresses -let make rollup_address patches = - let hardcoded_patches = - List.assoc ~equal:Address.equal rollup_address hardcoded_patches_list - |> Option.value ~default:[] - in - hardcoded_patches @ patches - let unsafe_patch_encoding = let open Data_encoding in union @@ -41,3 +36,25 @@ let unsafe_patch_encoding = let pp_unsafe_patch fmt = function | Increase_max_nb_ticks nb -> Format.fprintf fmt "Increase maximum number of ticks to %#Ld" nb + +let make kind rollup_address patches = + let open Result_syntax in + let hardcoded_patches = + List.assoc ~equal:Address.equal rollup_address hardcoded_patches_list + |> Option.value ~default:[] + in + let patches = hardcoded_patches @ patches in + let+ () = + List.iter_e + (fun patch -> + if not @@ List.mem ~equal:Kind.equal kind (patch_kinds patch) then + error_with + "Patch \"%a\" is not supported for rollup kind %a" + pp_unsafe_patch + patch + Kind.pp + kind + else Ok ()) + patches + in + patches diff --git a/src/lib_smart_rollup_node/pvm_patches.mli b/src/lib_smart_rollup_node/pvm_patches.mli index 12f20b278f85..149289620449 100644 --- a/src/lib_smart_rollup_node/pvm_patches.mli +++ b/src/lib_smart_rollup_node/pvm_patches.mli @@ -19,6 +19,6 @@ val unsafe_patch_encoding : unsafe_patch Data_encoding.t (** Pretty printer for unsafe patches. *) val pp_unsafe_patch : Format.formatter -> unsafe_patch -> unit -(** [make address patches] builds the patches from the provided list [patches] - and adds the hardcoded PVM patches for the rollup [address]. *) -val make : Address.t -> unsafe_patch list -> t +(** [make kind address patches] builds the patches from the provided list + [patches] and adds the hardcoded PVM patches for the rollup [address]. *) +val make : Kind.t -> Address.t -> unsafe_patch list -> t tzresult -- GitLab From c042b541d4a3574964b5b1eda14dbcfc7bd8abf9 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 16 Apr 2024 14:50:19 +0200 Subject: [PATCH 15/16] Doc: changelog --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index ffa112463799..a514658860b7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -208,6 +208,9 @@ Smart Rollup node - Administrative RPCs to inspect injector queues and clear them. (MR :gl:`!12497`) +- Support for unsafely increasing the WASM PVM's tick limit of a rollup. + (MR :gl:`!12907`) + Smart Rollup WASM Debugger -------------------------- -- GitLab From eebca5683581d8224435709e043f363e52655836 Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 16 Apr 2024 15:47:37 +0200 Subject: [PATCH 16/16] Test: check that PVM tick limit can be increased with an unsafe patch --- tezt/tests/sc_rollup.ml | 59 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/tezt/tests/sc_rollup.ml b/tezt/tests/sc_rollup.ml index b973bdaa82f1..7630b5bb610a 100644 --- a/tezt/tests/sc_rollup.ml +++ b/tezt/tests/sc_rollup.ml @@ -4681,6 +4681,62 @@ let test_arg_boot_sector_file ~kind = let* _ = Sc_rollup_node.wait_sync ~timeout:10. rollup_node in unit +let test_unsafe_genesis_patch ~kind = + let commitment_period = 3 in + let max_nb_tick = 50_000_000_000_000L in + let should_fail = match kind with "wasm_2_0_0" -> false | _ -> true in + test_full_scenario + ~kind + ~commitment_period + { + variant = None; + tags = ["node"; "unsafe_patch"]; + description = + sf + "Rollup can%s apply unsafe genesis PVM patches" + (if should_fail then "not" else ""); + } + @@ fun _protocol rollup_node rollup _node client -> + Log.info "Set patch in configuration" ; + let* _ = Sc_rollup_node.config_init rollup_node rollup in + Sc_rollup_node.Config_file.update rollup_node (fun config -> + let open JSON in + put + ( "unsafe-pvm-patches", + parse + ~origin:"increase-tick" + (sf {| [ { "increase_max_nb_tick" : "%Ld"} ] |} max_nb_tick) ) + config) ; + () ; + let* () = Sc_rollup_node.run ~wait_ready:false rollup_node rollup [] in + if should_fail then + Sc_rollup_node.check_error + ~exit_code:1 + ~msg:(rex "Patch .* is not supported") + rollup_node + else + let* () = bake_levels (commitment_period + 4) client in + let* _ = Sc_rollup_node.wait_sync ~timeout:10. rollup_node in + let* published_commitment = + Sc_rollup_node.RPC.call rollup_node + @@ Sc_rollup_rpc.get_local_last_published_commitment () + in + let* () = + check_published_commitment_in_l1 rollup client published_commitment + in + let* pvm_max_bytes = + Sc_rollup_node.RPC.call rollup_node ~rpc_hooks + @@ Sc_rollup_rpc.get_global_block_state ~key:"pvm/max_nb_ticks" () + in + let pvm_max = + pvm_max_bytes + |> Data_encoding.Binary.of_bytes_exn Data_encoding.n + |> Z.to_int64 + in + Check.((pvm_max = max_nb_tick) int64) + ~error_msg:"PVM max tick should have been increased to %R but is %L" ; + unit + let test_bootstrap_smart_rollup_originated = register_test ~supports:(From_protocol 018) @@ -5692,7 +5748,8 @@ let register ~kind ~protocols = test_consecutive_commitments protocols ~kind ; - test_outbox_message protocols ~kind + test_outbox_message protocols ~kind ; + test_unsafe_genesis_patch protocols ~kind let register ~protocols = (* PVM-independent tests. We still need to specify a PVM kind -- GitLab