diff --git a/manifest/main.ml b/manifest/main.ml index 5bc04e1d536fa85bd2e91b2c7f14b64140d8203e..ff6b942f324c8fd8286347ce6d635b598ec5a469 100644 --- a/manifest/main.ml +++ b/manifest/main.ml @@ -4811,6 +4811,7 @@ end = struct ("test_dal_slot_proof", N.(number >= 016)); ("test_tx_rollup_l2_apply", N.(number >= 015 && number <= 016)); ("test_tx_rollup_l2", N.(number >= 015 && number <= 016)); + ("test_global_counter_storage", N.(number >= 018)); ] |> List.filter_map (fun (n, b) -> if b then Some n else None) in diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index 68c78822f3cb4dbadf204ccb496d930914be933b..37056f33d14d466f912a7eda65461e35c7537a36 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -193,6 +193,8 @@ "Sc_rollup_refutation_storage", "Zk_rollup_errors", + "Global_counter_storage", + "Destination_storage", "Alpha_context", diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index f67e2eb7ffb6e5dbd30711c25f25c4c228c2f9fd..c863baea61e46e0ceed457bde4dd804ab18a3175 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -206,6 +206,7 @@ Dal_slot_storage Sc_rollup_refutation_storage Zk_rollup_errors + Global_counter_storage Destination_storage Alpha_context Script_string @@ -487,6 +488,7 @@ dal_slot_storage.ml dal_slot_storage.mli sc_rollup_refutation_storage.ml sc_rollup_refutation_storage.mli zk_rollup_errors.ml + global_counter_storage.ml global_counter_storage.mli destination_storage.ml destination_storage.mli alpha_context.ml alpha_context.mli script_string.ml script_string.mli @@ -769,6 +771,7 @@ dal_slot_storage.ml dal_slot_storage.mli sc_rollup_refutation_storage.ml sc_rollup_refutation_storage.mli zk_rollup_errors.ml + global_counter_storage.ml global_counter_storage.mli destination_storage.ml destination_storage.mli alpha_context.ml alpha_context.mli script_string.ml script_string.mli @@ -1035,6 +1038,7 @@ dal_slot_storage.ml dal_slot_storage.mli sc_rollup_refutation_storage.ml sc_rollup_refutation_storage.mli zk_rollup_errors.ml + global_counter_storage.ml global_counter_storage.mli destination_storage.ml destination_storage.mli alpha_context.ml alpha_context.mli script_string.ml script_string.mli diff --git a/src/proto_alpha/lib_protocol/global_counter_storage.ml b/src/proto_alpha/lib_protocol/global_counter_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..15c8685d8b5e4d28d5d35387ca7a20057081acf7 --- /dev/null +++ b/src/proto_alpha/lib_protocol/global_counter_storage.ml @@ -0,0 +1,11 @@ +let get ctxt = + let open Lwt_result_syntax in + let* value_opt = Storage.Global_counter.find ctxt in + return (Option.value ~default:Z.zero value_opt) + +let increment ctxt = + let open Lwt_result_syntax in + let* value = get ctxt in + match Z.to_int value with + | 0 -> Storage.Global_counter.init ctxt Z.one + | v -> Storage.Global_counter.update ctxt (Z.add (Z.of_int v) Z.one) diff --git a/src/proto_alpha/lib_protocol/global_counter_storage.mli b/src/proto_alpha/lib_protocol/global_counter_storage.mli new file mode 100644 index 0000000000000000000000000000000000000000..a0e62f1d6ac84e368e80b53edd1128c63590d3e7 --- /dev/null +++ b/src/proto_alpha/lib_protocol/global_counter_storage.mli @@ -0,0 +1,3 @@ +val increment : Raw_context.t -> Raw_context.t tzresult Lwt.t + +val get : Raw_context.t -> Z.t tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index 2a2850b7f2ce336d827709472e943900b780649d..7ad9a9cd38556ce496bc7e49ebc300e47993f8b3 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -2127,6 +2127,13 @@ module Zk_rollup = struct end) end +module Global_counter = + Make_single_data_storage (Registered) (Raw_context) + (struct + let name = ["global_counter"] + end) + (Encoding.Z) + module Legacy = struct module Grand_parent_branch = Make_single_data_storage (Registered) (Raw_context) diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index b1280cff1f984ab5abe2a312d8823a8257597271..945a3d243af03283689f2361af50216b2d024c0f 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -933,6 +933,9 @@ module Zk_rollup : sig and type value = Zk_rollup_operation_repr.t * Ticket_hash_repr.t option end +module Global_counter : + Single_data_storage with type t := Raw_context.t and type value = Z.t + module Legacy : sig (** [Grand_parent_branch] stores a single value composed of the great-grand parent hash and the grand parent's payload *) diff --git a/src/proto_alpha/lib_protocol/test/unit/dune b/src/proto_alpha/lib_protocol/test/unit/dune index 75d1f001ab4b3a83ca7b8e1d72fa5a8d39b43c5a..7e8ddde754d3b931486692473c130014467905fe 100644 --- a/src/proto_alpha/lib_protocol/test/unit/dune +++ b/src/proto_alpha/lib_protocol/test/unit/dune @@ -71,7 +71,8 @@ test_sc_rollup_inbox_legacy test_sc_rollup_wasm test_local_contexts - test_dal_slot_proof)) + test_dal_slot_proof + test_global_counter_storage)) (executable (name main) diff --git a/src/proto_alpha/lib_protocol/test/unit/test_global_counter_storage.ml b/src/proto_alpha/lib_protocol/test/unit/test_global_counter_storage.ml new file mode 100644 index 0000000000000000000000000000000000000000..7a0b3c5ae02ecae47acf72cae2f16cf5880009f4 --- /dev/null +++ b/src/proto_alpha/lib_protocol/test/unit/test_global_counter_storage.ml @@ -0,0 +1,100 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 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: Protocol Global_counter_storage + Invocation: dune exec src/proto_alpha/lib_protocol/test/unit/main.exe \ + -- --file test_global_counter_storage.ml + Subject: Tests for the global counter storage module +*) + +open Protocol + +let new_context () = + let open Lwt_result_syntax in + let* b, _ = Context.init1 () in + let+ inc = Incremental.begin_construction b in + let alpha_ctxt = Incremental.alpha_ctxt inc in + Alpha_context.Internal_for_tests.to_raw alpha_ctxt + +module Gloabal_counter_test = struct + let test_get_initial_global_counter () = + let open Lwt_result_wrap_syntax in + let* ctxt = new_context () in + let*@ global_counter = Global_counter_storage.get ctxt in + Assert.equal_int ~loc:__LOC__ 0 (Z.to_int global_counter) + + let test_increment_global_counter () = + let open Lwt_result_wrap_syntax in + let* ctxt = new_context () in + let*@ ctxt = Global_counter_storage.increment ctxt in + let*@ global_counter = Global_counter_storage.get ctxt in + Assert.equal_int ~loc:__LOC__ 1 (Z.to_int global_counter) + + let test_increment_global_counter_multiple_times () = + let open Lwt_result_wrap_syntax in + let* init_ctxt = new_context () in + let rec increment_global_counter_multiple_times ctxt n = + match n with + | 0 -> return ctxt + | x -> + let*@ new_ctxt = Global_counter_storage.increment ctxt in + increment_global_counter_multiple_times new_ctxt (x - 1) + in + let times_counter_incremented = 100 in + let* updated_ctxt = + increment_global_counter_multiple_times + init_ctxt + times_counter_incremented + in + let*@ global_counter = Global_counter_storage.get updated_ctxt in + Assert.equal_int + ~loc:__LOC__ + times_counter_incremented + (Z.to_int global_counter) + + let tests = + [ + Tztest.tztest + "global counter is zero if increment never called" + `Quick + test_get_initial_global_counter; + Tztest.tztest + "global counter is one if incremented once" + `Quick + test_increment_global_counter; + Tztest.tztest + "global counter is correct when incremented multiple times" + `Quick + test_increment_global_counter_multiple_times; + ] +end + +let tests = Gloabal_counter_test.tests + +let () = + Alcotest_lwt.run ~__FILE__ Protocol.name [("global counter storage", tests)] + |> Lwt_main.run