From 174edec2936bfbf41ef0d7a07dae1ac6754ecc1a Mon Sep 17 00:00:00 2001 From: Thomas Letan Date: Wed, 8 Jun 2022 13:07:54 +0200 Subject: [PATCH 1/2] Sc_rollup,tests: Instantiate and test the WASM PVM --- manifest/main.ml | 1 + opam/tezos-protocol-012-Psithaca-tests.opam | 1 + opam/tezos-protocol-013-PtJakart-tests.opam | 1 + opam/tezos-protocol-alpha-tests.opam | 1 + .../lib_protocol/test/integration/dune | 1 + .../lib_protocol/test/integration/dune | 1 + .../lib_protocol/alpha_context.mli | 18 ++- .../lib_protocol/sc_rollup_wasm.ml | 49 ++++--- .../lib_protocol/sc_rollup_wasm.mli | 21 ++- .../lib_protocol/test/integration/dune | 1 + .../lib_protocol/test/integration/main.ml | 1 + .../test/integration/test_sc_rollup_wasm.ml | 124 ++++++++++++++++++ 12 files changed, 195 insertions(+), 25 deletions(-) create mode 100644 src/proto_alpha/lib_protocol/test/integration/test_sc_rollup_wasm.ml diff --git a/manifest/main.ml b/manifest/main.ml index a0c936aca62e..e0c38f598add 100644 --- a/manifest/main.ml +++ b/manifest/main.ml @@ -3026,6 +3026,7 @@ end = struct ~opam:(sf "tezos-protocol-%s-tests" name_dash) ~deps: [ + tezos_context; alcotest_lwt; tezos_base |> open_ ~m:"TzPervasives" |> open_ ~m:"TzPervasives.Error_monad.Legacy_monad_globals"; diff --git a/opam/tezos-protocol-012-Psithaca-tests.opam b/opam/tezos-protocol-012-Psithaca-tests.opam index f62ee638c59f..fdd75d7d57f6 100644 --- a/opam/tezos-protocol-012-Psithaca-tests.opam +++ b/opam/tezos-protocol-012-Psithaca-tests.opam @@ -21,6 +21,7 @@ depends: [ "tezos-micheline" {with-test} "tezos-benchmark-012-Psithaca" {with-test} "tezos-benchmark-type-inference-012-Psithaca" {with-test} + "tezos-context" {with-test} "tezos-test-helpers" {with-test} "alcotest" { with-test & >= "1.5.0" } "qcheck-alcotest" { with-test & >= "0.15" } diff --git a/opam/tezos-protocol-013-PtJakart-tests.opam b/opam/tezos-protocol-013-PtJakart-tests.opam index 258bfa157678..797df43436f7 100644 --- a/opam/tezos-protocol-013-PtJakart-tests.opam +++ b/opam/tezos-protocol-013-PtJakart-tests.opam @@ -20,6 +20,7 @@ depends: [ "tezos-micheline" {with-test} "tezos-benchmark-013-PtJakart" {with-test} "tezos-benchmark-type-inference-013-PtJakart" {with-test} + "tezos-context" {with-test} "tezos-test-helpers" {with-test} "alcotest" { with-test & >= "1.5.0" } "qcheck-alcotest" { with-test & >= "0.15" } diff --git a/opam/tezos-protocol-alpha-tests.opam b/opam/tezos-protocol-alpha-tests.opam index 4968c0436361..4280987546ed 100644 --- a/opam/tezos-protocol-alpha-tests.opam +++ b/opam/tezos-protocol-alpha-tests.opam @@ -20,6 +20,7 @@ depends: [ "tezos-micheline" {with-test} "tezos-benchmark-alpha" {with-test} "tezos-benchmark-type-inference-alpha" {with-test} + "tezos-context" {with-test} "tezos-test-helpers" {with-test} "alcotest" { with-test & >= "1.5.0" } "qcheck-alcotest" { with-test & >= "0.15" } diff --git a/src/proto_012_Psithaca/lib_protocol/test/integration/dune b/src/proto_012_Psithaca/lib_protocol/test/integration/dune index 3c92107104c7..b3b8ba6e47ab 100644 --- a/src/proto_012_Psithaca/lib_protocol/test/integration/dune +++ b/src/proto_012_Psithaca/lib_protocol/test/integration/dune @@ -4,6 +4,7 @@ (executable (name main) (libraries + tezos-context alcotest-lwt tezos-base tezos-client-012-Psithaca diff --git a/src/proto_013_PtJakart/lib_protocol/test/integration/dune b/src/proto_013_PtJakart/lib_protocol/test/integration/dune index f2d87626111a..5917491bddf1 100644 --- a/src/proto_013_PtJakart/lib_protocol/test/integration/dune +++ b/src/proto_013_PtJakart/lib_protocol/test/integration/dune @@ -4,6 +4,7 @@ (executable (name main) (libraries + tezos-context alcotest-lwt tezos-base tezos-client-013-PtJakart diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 2a464b7c7052..079e751a7ad9 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2646,8 +2646,18 @@ module Sc_rollup : sig (proof * 'a) option Lwt.t end + type 'a proof = { + tree_proof : 'a; + given : input option; + requested : input_request; + } + module Make (C : P) : sig - include PVM.S with type context = C.Tree.t and type state = C.tree + include + PVM.S + with type context = C.Tree.t + and type state = C.tree + and type proof = C.proof proof val get_tick : state -> Tick.t Lwt.t @@ -2658,6 +2668,12 @@ module Sc_rollup : sig val produce_proof : context -> input option -> state -> (proof, string) result Lwt.t end + + module ProtocolImplementation : + PVM.S + with type context = Context.t + and type state = Context.tree + and type proof = Context.Proof.tree Context.Proof.t proof end module Number_of_messages : Bounded.Int32.S diff --git a/src/proto_alpha/lib_protocol/sc_rollup_wasm.ml b/src/proto_alpha/lib_protocol/sc_rollup_wasm.ml index 06dd1950bbf0..67da1e56427b 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_wasm.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_wasm.ml @@ -68,39 +68,46 @@ module V2_0_0 = struct val get_status : state -> status Lwt.t end + (* TODO: https://gitlab.com/tezos/tezos/-/issues/3091 + + The tree proof contains enough information to derive given and requested. + Get rid of the duplication by writing the projection functions and + removing the [given] and [requested] fields. + *) + type 'a proof = { + tree_proof : 'a; + given : PS.input option; + requested : PS.input_request; + } + + let proof_encoding e = + let open Data_encoding in + conv + (fun {tree_proof; given; requested} -> (tree_proof, given, requested)) + (fun (tree_proof, given, requested) -> {tree_proof; given; requested}) + (obj3 + (req "tree_proof" e) + (req "given" (option PS.input_encoding)) + (req "requested" PS.input_request_encoding)) + module Make (Context : P) : - S with type context = Context.Tree.t and type state = Context.tree = struct + S + with type context = Context.Tree.t + and type state = Context.tree + and type proof = Context.proof proof = struct module Tree = Context.Tree type context = Context.Tree.t type hash = State_hash.t - (* TODO: https://gitlab.com/tezos/tezos/-/issues/3091 - - The tree proof contains enough information to derive given and requested. - Get rid of the duplication by writing the projection functions and - removing the [given] and [requested] fields. - *) - type proof = { - tree_proof : Context.proof; - given : PS.input option; - requested : PS.input_request; - } + type nonrec proof = Context.proof proof let proof_input_given p = p.given let proof_input_requested p = p.requested - let proof_encoding = - let open Data_encoding in - conv - (fun {tree_proof; given; requested} -> (tree_proof, given, requested)) - (fun (tree_proof, given, requested) -> {tree_proof; given; requested}) - (obj3 - (req "tree_proof" Context.proof_encoding) - (req "given" (option PS.input_encoding)) - (req "requested" PS.input_request_encoding)) + let proof_encoding = proof_encoding Context.proof_encoding let proof_start_state p = Context.proof_before p.tree_proof diff --git a/src/proto_alpha/lib_protocol/sc_rollup_wasm.mli b/src/proto_alpha/lib_protocol/sc_rollup_wasm.mli index 8d62fe9e1efb..b9615deefbd6 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_wasm.mli +++ b/src/proto_alpha/lib_protocol/sc_rollup_wasm.mli @@ -59,8 +59,6 @@ module V2_0_0 : sig val get_status : state -> status Lwt.t end - module ProtocolImplementation : S with type context = Context.t - module type P = sig module Tree : Context.TREE with type key = string list and type value = bytes @@ -82,6 +80,23 @@ module V2_0_0 : sig Tree.t -> tree -> (tree -> (tree * 'a) Lwt.t) -> (proof * 'a) option Lwt.t end + type 'a proof = { + tree_proof : 'a; + given : Sc_rollup_PVM_sem.input option; + requested : Sc_rollup_PVM_sem.input_request; + } + + val proof_encoding : 'a Data_encoding.t -> 'a proof Data_encoding.t + module Make (Context : P) : - S with type context = Context.Tree.t and type state = Context.tree + S + with type context = Context.Tree.t + and type state = Context.tree + and type proof = Context.proof proof + + module ProtocolImplementation : + S + with type context = Context.t + and type state = Context.tree + and type proof = Context.Proof.tree Context.Proof.t proof end diff --git a/src/proto_alpha/lib_protocol/test/integration/dune b/src/proto_alpha/lib_protocol/test/integration/dune index 9e468e08764a..3136d7705e9b 100644 --- a/src/proto_alpha/lib_protocol/test/integration/dune +++ b/src/proto_alpha/lib_protocol/test/integration/dune @@ -4,6 +4,7 @@ (executable (name main) (libraries + tezos-context alcotest-lwt tezos-base tezos-client-alpha diff --git a/src/proto_alpha/lib_protocol/test/integration/main.ml b/src/proto_alpha/lib_protocol/test/integration/main.ml index e8dc7b74eb26..cc4b5cd0f515 100644 --- a/src/proto_alpha/lib_protocol/test/integration/main.ml +++ b/src/proto_alpha/lib_protocol/test/integration/main.ml @@ -40,5 +40,6 @@ let () = ("storage tests", Test_storage_functions.tests); ("token movements", Test_token.tests); ("frozen bonds", Test_frozen_bonds.tests); + ("sc rollup wasm", Test_sc_rollup_wasm.tests); ] |> Lwt_main.run diff --git a/src/proto_alpha/lib_protocol/test/integration/test_sc_rollup_wasm.ml b/src/proto_alpha/lib_protocol/test/integration/test_sc_rollup_wasm.ml new file mode 100644 index 000000000000..e1abcf782286 --- /dev/null +++ b/src/proto_alpha/lib_protocol/test/integration/test_sc_rollup_wasm.ml @@ -0,0 +1,124 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Nomadic Labs *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: sc rollup wasm + Invocation: dune exec \ + src/proto_alpha/lib_protocol/test/integration/main.exe \ + -- test "^sc rollup wasm$" + Subject: Test the WASM 2.0 PVM. +*) + +open Protocol +open Alpha_context +module Context_binary = Tezos_context_memory.Context_binary + +module Tree : + Protocol.Environment.Context.TREE + with type t = Context_binary.t + and type tree = Context_binary.tree + and type key = string list + and type value = bytes = struct + type t = Context_binary.t + + type tree = Context_binary.tree + + type key = Context_binary.key + + type value = Context_binary.value + + include Context_binary.Tree +end + +module WASM_P : + Protocol.Alpha_context.Sc_rollup.Wasm_2_0_0PVM.P + with type Tree.t = Context_binary.t + and type Tree.tree = Context_binary.tree + and type Tree.key = string list + and type Tree.value = bytes + and type proof = Context_binary.Proof.tree Context_binary.Proof.t = struct + module Tree = Tree + + type tree = Tree.tree + + type proof = Context_binary.Proof.tree Context_binary.Proof.t + + let proof_encoding = + Tezos_context_helpers.Merkle_proof_encoding.V2.Tree2.tree_proof_encoding + + let kinded_hash_to_state_hash : + Context_binary.Proof.kinded_hash -> Sc_rollup.State_hash.t = function + | `Value hash | `Node hash -> + Sc_rollup.State_hash.hash_bytes [Context_hash.to_bytes hash] + + let proof_before proof = + kinded_hash_to_state_hash proof.Context_binary.Proof.before + + let proof_after proof = + kinded_hash_to_state_hash proof.Context_binary.Proof.after + + let produce_proof context tree step = + let open Lwt_syntax in + let* context = Context_binary.add_tree context [] tree in + let _hash = Context_binary.commit ~time:Time.Protocol.epoch context in + let index = Context_binary.index context in + match Context_binary.Tree.kinded_key tree with + | Some k -> + let* p = Context_binary.produce_tree_proof index k step in + return (Some p) + | None -> + Stdlib.failwith + "produce_proof: internal error, [kinded_key] returned [None]" + + let verify_proof proof step = + let open Lwt_syntax in + let* result = Context_binary.verify_tree_proof proof step in + match result with + | Ok v -> return (Some v) + | Error _ -> + (* We skip the error analysis here since proof verification is not a + job for the rollup node. *) + return None +end + +module Verifier = Alpha_context.Sc_rollup.Wasm_2_0_0PVM.ProtocolImplementation + +module Prover = Alpha_context.Sc_rollup.Wasm_2_0_0PVM.Make (WASM_P) + +let should_boot () = + let open Lwt_result_syntax in + let context = Context_binary.empty in + let*! s = Prover.initial_state context "" in + let*! s = Prover.eval s in + let*! p_res = Prover.produce_proof context None s in + match p_res with + | Ok proof -> + let*! is_correct = Verifier.verify_proof proof in + if is_correct then return_unit else Stdlib.failwith "incorrect proof" + | Error err -> Stdlib.failwith ("Could not produce a proof " ^ err) + +let tests = [Tztest.tztest "should boot" `Quick should_boot] -- GitLab From 78d974cc425d0e0ba96b59892fcfaf2b765f1d01 Mon Sep 17 00:00:00 2001 From: Thomas Letan Date: Thu, 9 Jun 2022 13:29:00 +0200 Subject: [PATCH 2/2] Env,proto: Expose a dummy WASM [step] function to the protocol In this patch, we enrich the V6 protocol with a functor to derive a WASM step function. The functor is parameterized with an Irmin tree, so that it can easily be used with different context implementation. This is necessary as long as (1) the functor of the WASM PVM is parameterized by a tree, and (2) the protocol only knows about one Irmin tree (32-arity, specific to Tezos needs). --- .../environment_V6.ml | 11 +++++++ src/lib_protocol_environment/sigs/v6.dune.inc | 2 ++ .../sigs/v6/wasm_2_0_0.mli | 29 +++++++++++++++++++ .../lib_protocol/sc_rollup_wasm.ml | 20 +++++++++++-- 4 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 src/lib_protocol_environment/sigs/v6/wasm_2_0_0.mli diff --git a/src/lib_protocol_environment/environment_V6.ml b/src/lib_protocol_environment/environment_V6.ml index ff54bdbdc560..2aedf2545728 100644 --- a/src/lib_protocol_environment/environment_V6.ml +++ b/src/lib_protocol_environment/environment_V6.ml @@ -1100,6 +1100,17 @@ struct let complete ctxt s = Base58.complete ctxt s end + module Wasm_2_0_0 = struct + module Make + (Tree : Context.TREE with type key = string list and type value = bytes) = + struct + (* TODO: https://gitlab.com/tezos/tezos/-/issues/3090 + The expected implementation of this function is the step + function implemented in `lib_webassembly'. *) + let step (t : Tree.tree) = Lwt.return t + end + end + module Lift (P : Updater.PROTOCOL) = struct let environment_version = Protocol.V6 diff --git a/src/lib_protocol_environment/sigs/v6.dune.inc b/src/lib_protocol_environment/sigs/v6.dune.inc index 503ca1755b03..33785133acf1 100644 --- a/src/lib_protocol_environment/sigs/v6.dune.inc +++ b/src/lib_protocol_environment/sigs/v6.dune.inc @@ -77,6 +77,8 @@ v6/updater.mli v6/RPC_context.mli + ;; SCORU + v6/wasm_2_0_0.mli ) (action (with-stdout-to %{targets} (chdir %{workspace_root}} (run %{libexec:tezos-protocol-environment:s_packer} "sigs" %{deps}))))) diff --git a/src/lib_protocol_environment/sigs/v6/wasm_2_0_0.mli b/src/lib_protocol_environment/sigs/v6/wasm_2_0_0.mli new file mode 100644 index 000000000000..ca448ec3bcd8 --- /dev/null +++ b/src/lib_protocol_environment/sigs/v6/wasm_2_0_0.mli @@ -0,0 +1,29 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 Trili Tech *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Make + (Tree : Context.TREE with type key = string list and type value = bytes) : sig + val step : Tree.tree -> Tree.tree Lwt.t +end diff --git a/src/proto_alpha/lib_protocol/sc_rollup_wasm.ml b/src/proto_alpha/lib_protocol/sc_rollup_wasm.ml index 67da1e56427b..15e55c241dcd 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_wasm.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_wasm.ml @@ -141,6 +141,12 @@ module V2_0_0 = struct val ( let* ) : 'a t -> ('a -> 'b t) -> 'b t end + val get : tree t + + val set : tree -> unit t + + val lift : 'a Lwt.t -> 'a t + val find_value : Tree.key -> 'a Data_encoding.t -> 'a option t val set_value : Tree.key -> 'a Data_encoding.t -> 'a -> unit t @@ -175,6 +181,12 @@ module V2_0_0 = struct | None -> internal_error "Error during decoding" state | Some v -> return (state, Some v) + let get s = Lwt.return (s, Some s) + + let set s _ = Lwt.return (s, Some ()) + + let lift m s = Lwt.map (fun r -> (s, Some r)) m + let find_value key encoding state = let open Lwt_syntax in let* obytes = Tree.find state key in @@ -295,6 +307,7 @@ module V2_0_0 = struct end) end + module WASM_machine = Wasm_2_0_0.Make (Tree) open State type state = State.state @@ -367,14 +380,15 @@ module V2_0_0 = struct let set_input input = state_of @@ set_input_monadic input - let reboot = return () - let eval_step = (* TODO: https://gitlab.com/tezos/tezos/-/issues/3090 Call into tickified parsing/evaluation exposed in lib_webassembly. *) - reboot + let open Monad.Syntax in + let* s = get in + let* s = lift (WASM_machine.step s) in + set s let ticked m = let open Monad.Syntax in -- GitLab