diff --git a/manifest/main.ml b/manifest/main.ml index a0c936aca62ef6153b88bcaa9399b4afa445b080..e0c38f598addf2a9169887ebbeb1378875be3c3f 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 f62ee638c59f9ca28c09b0ca0f0c4722af3c0fb8..fdd75d7d57f6758260d7e79722f6b66b8df3e143 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 258bfa1576781daf34bd99b778c4f969d937b54b..797df43436f7c50fdcb707fe5514d82b12c160a5 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 4968c04363611d32300786294b0de30800f649ec..4280987546ed400c7d33c5b1c6e8298a14eda470 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/lib_protocol_environment/environment_V6.ml b/src/lib_protocol_environment/environment_V6.ml index ff54bdbdc560f4073ac4e197ced2c54a3119ebe4..2aedf2545728a6ea792c23cb58a5d4071184f3dc 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 503ca1755b03a9b98ee2350521e688763235270a..33785133acf167d76d6a2c42335aae429b7e8a39 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 0000000000000000000000000000000000000000..ca448ec3bcd8ab1d8041c08d30734b7e7b549339 --- /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_012_Psithaca/lib_protocol/test/integration/dune b/src/proto_012_Psithaca/lib_protocol/test/integration/dune index 3c92107104c73f146e66eb7e9bf4dd38b6cecbc7..b3b8ba6e47abdeeaa0a9bf34a173b3647db46433 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 f2d87626111a32598aa6e3f3b6bbd27582a1dbbb..5917491bddf115cb6997835c2255a60df28124ec 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 2a464b7c70520458597572912d2e7446168b843b..079e751a7ad961f03c5590a544ed56c128d013f1 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 06dd1950bbf06ccfdde78ab24dc991f4380ceff0..15e55c241dcd1c6091c8c824a59f5d7f3f5f84ed 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 @@ -134,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 @@ -168,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 @@ -288,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 @@ -360,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 diff --git a/src/proto_alpha/lib_protocol/sc_rollup_wasm.mli b/src/proto_alpha/lib_protocol/sc_rollup_wasm.mli index 8d62fe9e1efbd894af75250de98d66e6da5fa189..b9615deefbd66b694c29865174f2940a2fff63ca 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 9e468e08764aadba3b606c3c2103ff1034813308..3136d7705e9bf52dcbb28157607cc9bf6e6e2e55 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 e8dc7b74eb260c497bdb9517c3ffc222bba1eebc..cc4b5cd0f515dbef68da4d16e39b597b35ac4724 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 0000000000000000000000000000000000000000..e1abcf782286338e23e79719d3fb9b0e2c19dc92 --- /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]