diff --git a/src/lib_context/context.ml b/src/lib_context/context.ml index a81395adc4150d8719e2a0f3f20b158cf09662fc..9d59f4df857c62d201f75d5e28cd87067b2fe2eb 100644 --- a/src/lib_context/context.ml +++ b/src/lib_context/context.ml @@ -305,7 +305,8 @@ module Make (Encoding : module type of Tezos_context_encoding.Context) = struct type kinded_key = [`Node of Store.node_key | `Value of Store.contents_key] - module Tree = Tezos_context_helpers.Context.Make_tree (Store) + module Tree = Tezos_context_helpers.Context.Make_tree (Conf) (Store) + include Tezos_context_helpers.Context.Make_config (Conf) include Tezos_context_helpers.Context.Make_proof (Store) (Conf) let mem ctxt key = Tree.mem ctxt.tree (data_key key) diff --git a/src/lib_context/helpers/context.ml b/src/lib_context/helpers/context.ml index b62dcc4a1760ff4178f3cec5dfb21b3e3861a2a5..73e1b3cbc45561cd0cbc9c238157050b4d426bd4 100644 --- a/src/lib_context/helpers/context.ml +++ b/src/lib_context/helpers/context.ml @@ -54,8 +54,19 @@ let encode_proof_version ~is_stream ~is_binary = (if is_stream then stream_mask else 0) lor if is_binary then binary_mask else 0 -module Make_tree (Store : DB) = struct +module Make_config (Conf : Conf) = struct + let equal_config = Tezos_context_sigs.Config.equal + + let config _ = + Tezos_context_sigs.Config.v + ~entries:Conf.entries + ~stable_hash:Conf.stable_hash + ~inode_child_order:Conf.inode_child_order +end + +module Make_tree (Conf : Conf) (Store : DB) = struct include Store.Tree + include Make_config (Conf) let pp = Irmin.Type.pp Store.tree_t diff --git a/src/lib_context/helpers/context.mli b/src/lib_context/helpers/context.mli index dc0c2282312b8e1142de0a4ee25ae478197e5c94..9b07120a806be4f2dd59e2c19ca000bafd022e26 100644 --- a/src/lib_context/helpers/context.mli +++ b/src/lib_context/helpers/context.mli @@ -28,7 +28,7 @@ open Tezos_context_encoding.Context module type DB = Irmin.Generic_key.S with module Schema = Schema -module Make_tree (DB : DB) : sig +module Make_tree (Conf : Conf) (DB : DB) : sig include Tezos_context_sigs.Context.TREE with type t := DB.t @@ -96,6 +96,13 @@ module Make_proof (DB : DB) (Store_conf : Tezos_context_encoding.Context.Conf) : val verify_stream_proof : (stream_proof, 'a) verifier end +module Make_config (Conf : Irmin_pack.Conf.S) : sig + val equal_config : + Tezos_context_sigs.Config.t -> Tezos_context_sigs.Config.t -> bool + + val config : 'a -> Tezos_context_sigs.Config.t +end + type error += Unsupported_context_hash_version of Context_hash.Version.t (** See [Tezos_context_sigs.Context.Proof_types.t] *) diff --git a/src/lib_context/memory/context.ml b/src/lib_context/memory/context.ml index 94144d130260ed859d803a9120165e3b8e76c401..b80cd99a549d721647d91fa0ce8e8f9588c84726 100644 --- a/src/lib_context/memory/context.ml +++ b/src/lib_context/memory/context.ml @@ -43,13 +43,14 @@ module Make (Encoding : module type of Tezos_context_encoding.Context) = struct end module Tree = struct - include Tezos_context_helpers.Context.Make_tree (Store) + include Tezos_context_helpers.Context.Make_tree (Conf) (Store) let shallow repo key = Store.Tree.shallow repo (Kinded_key.to_irmin_key key) end include Tree include Tezos_context_helpers.Context.Make_proof (Store) (Conf) + include Tezos_context_helpers.Context.Make_config (Conf) let produce_tree_proof t key = produce_tree_proof diff --git a/src/lib_context/sigs/config.ml b/src/lib_context/sigs/config.ml new file mode 100644 index 0000000000000000000000000000000000000000..4df3a9542ee449b2910906c51f4023a12e79deeb --- /dev/null +++ b/src/lib_context/sigs/config.ml @@ -0,0 +1,48 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018-2021 Tarides *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +type inode_child_order = + [`Seeded_hash | `Hash_bits | `Custom of depth:int -> bytes -> int] + +let equal_inode_child_order x y = + match (x, y) with + | (`Seeded_hash, `Seeded_hash) -> true + | (`Hash_bits, `Hash_bits) -> true + | (`Custom x, `Custom y) -> x == y + | _ -> false + +type t = { + entries : int; + stable_hash : int; + inode_child_order : inode_child_order; +} + +let equal x y = + x.entries = y.entries + && x.stable_hash = y.stable_hash + && equal_inode_child_order x.inode_child_order y.inode_child_order + +let v ~entries ~stable_hash ~inode_child_order = + {entries; stable_hash; inode_child_order} diff --git a/src/lib_context/sigs/config.mli b/src/lib_context/sigs/config.mli new file mode 100644 index 0000000000000000000000000000000000000000..fb76f74c558d237527ef40658132cb9a77f08d68 --- /dev/null +++ b/src/lib_context/sigs/config.mli @@ -0,0 +1,39 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018-2021 Tarides *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +(** The type for context configuration. *) +type t + +(** The equality function for context configurations. If two context have the + same configuration, they will generate the same context hashes. *) +val equal : t -> t -> bool + +(** Constructor. *) +val v : + entries:int -> + stable_hash:int -> + inode_child_order: + [`Custom of depth:int -> bytes -> int | `Hash_bits | `Seeded_hash] -> + t diff --git a/src/lib_context/sigs/context.ml b/src/lib_context/sigs/context.ml index c410617b2ac81560040335ab9dcd07c5fc35b48a..c4bdde89cf82bca831655e36e3e8dfb32d583c0d 100644 --- a/src/lib_context/sigs/context.ml +++ b/src/lib_context/sigs/context.ml @@ -117,6 +117,11 @@ module type VIEW = sig init:'a -> f:(key -> tree -> 'a -> 'a Lwt.t) -> 'a Lwt.t + + (** {2 Configuration} *) + + (** [config t] is [t]'s hash configuration. *) + val config : t -> Config.t end module Kind = struct @@ -397,6 +402,8 @@ module type PROOF_ENCODING = sig end module type S = sig + val equal_config : Config.t -> Config.t -> bool + include VIEW with type key = string list and type value = bytes module Proof : PROOF diff --git a/src/lib_protocol_environment/dummy_context.ml b/src/lib_protocol_environment/dummy_context.ml index 9252db4464b93709abd333d3daa5cb482077d8df..f4d38d04b099bff9465d8c0b42b2c3adc4e8ecaf 100644 --- a/src/lib_protocol_environment/dummy_context.ml +++ b/src/lib_protocol_environment/dummy_context.ml @@ -70,6 +70,8 @@ module M = struct let length _ _ = assert false let fold ?depth:_ _ _ ~order:_ ~init:_ ~f:_ = assert false + + let config _ = assert false end include Tree @@ -88,6 +90,10 @@ module M = struct let verify_tree_proof _ _ = assert false let verify_stream_proof _ _ = assert false + + let equal_config _ _ = assert false + + let config _ = assert false end open Tezos_protocol_environment diff --git a/src/lib_protocol_environment/environment_context.ml b/src/lib_protocol_environment/environment_context.ml index 2ab84d00add7e61363cd683288f9a6cbcfc3021a..f7772ef49446868b3fe2213cc5c7f546c1a3d8e3 100644 --- a/src/lib_protocol_environment/environment_context.ml +++ b/src/lib_protocol_environment/environment_context.ml @@ -268,8 +268,12 @@ module Context = struct let clear ?depth (Tree {ops = (module Ops); tree; _}) = Ops.Tree.clear ?depth tree + + let config (Tree {ops = (module Ops); tree; _}) = Ops.Tree.config tree end + let config (Context {ops = (module Ops); ctxt; _}) = Ops.config ctxt + (* Proof *) module Proof = Tezos_context_sigs.Context.Proof_types @@ -379,6 +383,8 @@ module Context = struct in return (Proof_context.inject tree, r) + let equal_config = Tezos_context_sigs.Config.equal + type cache_key = Environment_cache.key type block_cache = {context_hash : Context_hash.t; cache : cache} diff --git a/src/lib_protocol_environment/environment_context_intf.ml b/src/lib_protocol_environment/environment_context_intf.ml index 04b87aa0d014d8fafebe66558848ce6d529c7d79..a6796d261e8f64b853b05ee1db8e6b54fba38600 100644 --- a/src/lib_protocol_environment/environment_context_intf.ml +++ b/src/lib_protocol_environment/environment_context_intf.ml @@ -257,6 +257,10 @@ end module V5 = struct type depth = V4.depth + type config = Tezos_context_sigs.Config.t + + let equal_config = Tezos_context_sigs.Config.equal + module type VIEW = VIEW module Kind = Kind @@ -264,6 +268,8 @@ module V5 = struct module type TREE = TREE module type S = sig + val equal_config : config -> config -> bool + include VIEW with type key = string list and type value = bytes module Tree : sig diff --git a/src/lib_protocol_environment/proxy_context.ml b/src/lib_protocol_environment/proxy_context.ml index 7f08e778adec26b765365bab7b22102621bb3ae0..9c2a74a36d1392cf1027bc3ecf82675e67b97187 100644 --- a/src/lib_protocol_environment/proxy_context.ml +++ b/src/lib_protocol_environment/proxy_context.ml @@ -295,6 +295,8 @@ module C = struct let list = raw_list let clear ?depth t = Local.Tree.clear ?depth t.tree + + let config t = Local.Tree.config t.tree end module Proof = Local.Proof @@ -314,6 +316,10 @@ module C = struct let verify_tree_proof p f = verify Local.verify_tree_proof p f let verify_stream_proof p f = verify Local.verify_stream_proof p f + + let config t = Local.config t.M.local + + let equal_config = Local.equal_config end open Tezos_protocol_environment diff --git a/src/lib_protocol_environment/sigs/v5/context.mli b/src/lib_protocol_environment/sigs/v5/context.mli index 46b9b26408fe869d2cd5f97695bebb2e8ac62cea..d366f09ce2ea210f8d15d6687ed45362517fc9c2 100644 --- a/src/lib_protocol_environment/sigs/v5/context.mli +++ b/src/lib_protocol_environment/sigs/v5/context.mli @@ -31,6 +31,13 @@ (** The tree depth of a fold. See the [fold] function for more information. *) type depth = [`Eq of int | `Le of int | `Lt of int | `Ge of int | `Gt of int] +(** The type for context configuration. *) +type config + +(** The equality function for context configurations. If two context have the + same configuration, they will generate the same context hashes. *) +val equal_config : config -> config -> bool + module type VIEW = sig (** The type for context views. *) type t @@ -122,6 +129,11 @@ module type VIEW = sig init:'a -> f:(key -> tree -> 'a -> 'a Lwt.t) -> 'a Lwt.t + + (** {2 Configuration} *) + + (** [config t] is [t]'s hash configuration. *) + val config : t -> config end module Kind : sig diff --git a/src/proto_alpha/lib_protocol/raw_context.ml b/src/proto_alpha/lib_protocol/raw_context.ml index 0f35d3e8ebb0f85978909f184e21b166e5976107..b9894c351ad3cf6ecb0f0a169c434742a8432250 100644 --- a/src/proto_alpha/lib_protocol/raw_context.ml +++ b/src/proto_alpha/lib_protocol/raw_context.ml @@ -1026,6 +1026,8 @@ let list ctxt ?offset ?length k = Context.list (context ctxt) ?offset ?length k let fold ?depth ctxt k ~order ~init ~f = Context.fold ?depth (context ctxt) k ~order ~init ~f +let config ctxt = Context.config (context ctxt) + module Proof = Context.Proof module Tree : @@ -1091,6 +1093,8 @@ let verify_tree_proof proof f = Context.verify_tree_proof proof f let verify_stream_proof proof f = Context.verify_stream_proof proof f +let equal_config = Context.equal_config + let project x = x let absolute_key _ k = k diff --git a/src/proto_alpha/lib_protocol/raw_context_intf.ml b/src/proto_alpha/lib_protocol/raw_context_intf.ml index 39a29d1edfe5b60303be80dd8536edbccce685af..2b6cef34026af43c2653787acf9d73b72f83f489 100644 --- a/src/proto_alpha/lib_protocol/raw_context_intf.ml +++ b/src/proto_alpha/lib_protocol/raw_context_intf.ml @@ -31,6 +31,10 @@ (** The tree depth of a fold. See the [fold] function for more information. *) type depth = [`Eq of int | `Le of int | `Lt of int | `Ge of int | `Gt of int] +(** The type for context configuration. If two trees or stores have the + same configuration, they will generate the same context hash. *) +type config = Context.config + module type VIEW = sig (* Same as [Environment_context.VIEW] but with extra getters and setters functions. *) @@ -176,6 +180,11 @@ module type VIEW = sig init:'a -> f:(key -> tree -> 'a -> 'a Lwt.t) -> 'a Lwt.t + + (** {2 Hash configurations} *) + + (** [config t] is [t]'s hash configuration. *) + val config : t -> config end module Kind = struct @@ -503,6 +512,10 @@ module type T = sig (** [verify_stream] is the verifier of stream proofs. *) val verify_stream_proof : (stream_proof, 'a) verifier + (** The equality function for context configurations. If two context have the + same configuration, they will generate the same context hashes. *) + val equal_config : config -> config -> bool + (** Internally used in {!Storage_functors} to escape from a view. *) val project : t -> root diff --git a/src/proto_alpha/lib_protocol/storage_functors.ml b/src/proto_alpha/lib_protocol/storage_functors.ml index 1b15d18dddcc8ee8331a16afddc9e3d10fa2ae8d..658e8702eceed442e8dc07dfac9ff37918ba4483 100644 --- a/src/proto_alpha/lib_protocol/storage_functors.ml +++ b/src/proto_alpha/lib_protocol/storage_functors.ml @@ -112,6 +112,8 @@ module Make_subcontext (R : REGISTER) (C : Raw_context.T) (N : NAME) : let fold ?depth t k ~order ~init ~f = C.fold ?depth t (to_key k) ~order ~init ~f + let config t = C.config t + module Tree = C.Tree module Proof = C.Proof @@ -119,6 +121,8 @@ module Make_subcontext (R : REGISTER) (C : Raw_context.T) (N : NAME) : let verify_stream_proof = C.verify_stream_proof + let equal_config = C.equal_config + let project = C.project let absolute_key c k = C.absolute_key c (to_key k) @@ -781,6 +785,10 @@ module Make_indexed_subcontext (C : Raw_context.T) (I : INDEX) : let (t, i) = unpack c in C.fold ?depth t (to_key i k) ~order ~init ~f + let config c = + let (t, _) = unpack c in + C.config t + module Tree = struct include C.Tree @@ -795,6 +803,8 @@ module Make_indexed_subcontext (C : Raw_context.T) (I : INDEX) : let verify_stream_proof = C.verify_stream_proof + let equal_config = C.equal_config + let project c = let (t, _) = unpack c in C.project t