Mavryk_protocol_environment.ContextAbstract type of a cache. A cache is made of subcaches. Each subcache has its own size limit. The limit of its subcache is called a layout and can be initialized via the set_cache_layout function.
type t = private | Context : {kind : 'a kind;impl_name : string;ctxt : 'a;ops : ('a, 'b) ops;equality_witness : ('a, 'b) equality_witness;cache : cache;} -> tA context is purely functional description of a state. This state is used to interpret operations, and more generally, to validate blocks.
This type is private because a context must be constructed using make, which is a smart constructor.
val equal_config :
Mavryk_context_sigs.Config.t ->
Mavryk_context_sigs.Config.t ->
boolmem t k is an Lwt promise that resolves to true iff k is bound to a value in t.
find t k is an Lwt promise that resolves to Some v if k is bound to the value v in t and None otherwise.
list t key is the list of files and sub-nodes stored under k in t. The result order is not specified but is stable.
offset and length are used for pagination.
length t key is an Lwt promise that resolves to the number of files and sub-nodes stored under k in t.
It is equivalent to let+ l = list t k in List.length l but has a constant-time complexity.
add t k v is an Lwt promise that resolves to c such that:
k is bound to v in c;c is similar to t otherwise.If k was already bound in t to a value that is physically equal to v, the result of the function is a promise that resolves to t. Otherwise, the previous binding of k in t disappears.
remove t k v is an Lwt promise that resolves to c such that:
k is unbound in c;c is similar to t otherwise.val fold :
?depth:Mavryk_context_sigs.Context.depth ->
t ->
key ->
order:[ `Sorted | `Undefined ] ->
init:'a ->
f:(key -> tree -> 'a -> 'a Lwt.t) ->
'a Lwt.tfold ?depth t root ~order ~init ~f recursively folds over the trees and values of t. The f callbacks are called with a key relative to root. f is never called with an empty key for values; i.e., folding over a value is a no-op.
The depth is 0-indexed. If depth is set (by default it is not), then f is only called when the conditions described by the parameter is true:
Eq d folds over nodes and values of depth exactly d.Lt d folds over nodes and values of depth strictly less than d.Le d folds over nodes and values of depth less than or equal to d.Gt d folds over nodes and values of depth strictly more than d.Ge d folds over nodes and values of depth more than or equal to d.If order is `Sorted (the default), the elements are traversed in lexicographic order of their keys. For large nodes, it is memory-consuming, use `Undefined for a more memory efficient fold.
val config : t -> Mavryk_context_sigs.Config.tconfig t is t's hash configuration.
module Tree : sig ... endval set_protocol : t -> Mavryk_crypto.Hashed.Protocol_hash.t -> t Lwt.tval get_protocol : t -> Mavryk_crypto.Hashed.Protocol_hash.t Lwt.tval fork_test_chain :
t ->
protocol:Mavryk_crypto.Hashed.Protocol_hash.t ->
expiration:Mavryk_base.TzPervasives.Time.Protocol.t ->
t Lwt.tval set_hash_version :
t ->
Mavryk_crypto.Hashed.Context_hash.Version.t ->
t Mavryk_base.TzPervasives.tzresult Lwt.tval get_hash_version : t -> Mavryk_crypto.Hashed.Context_hash.Version.tmodule Proof : sig ... endtype tree_proof := Proof.tree Proof.ttype stream_proof := Proof.stream Proof.tval verify_tree_proof : (tree_proof, 'a) verifierval verify_stream_proof : (stream_proof, 'a) verifierval make :
kind:'a kind ->
impl_name:string ->
ctxt:'a ->
ops:('a, 'b) ops ->
equality_witness:('a, 'b) equality_witness ->
tmake kind impl_name ctxt ops equality_witness builds a context value. In this context, the cache is uninitialized: one must call load_cache to obtain a context with a valid cache. Otherwise, the context is not usable for all protocol-level features based on the cache, e.g., smart contract execution.
Abstract type for cached values.
This type is an extensible type since values stored in the cache are heterogeneous. Notice that the cache must be cleared during during protocol stitching because the data constructors of this type are incompatible between two protocols: if there remains values built with a data constructor of an old protocol, the new protocol will be confused to find that some keys it is interesting in have unexploitable values.
module Cache : sig ... endSee Context.CACHE in sigs/v3/context.mli for documentation.
A cache is a block-dependent value: to know whether a cache can be reused or recycled in a given block, we need the block that produces it.
During its loading, a cache can be populated in two different ways:
The first mode is intended to be used after a rebooting of the node for example. The main benefit being that it does not impact the validation time of a block since the cache's values will be reconstructed beforehand. The second mode is intended to be used for RPCs where reactivity is important: we do not want to recompute the full cache to execute the RPC but only the values which are necessary.
type source_of_cache = [ | `Force_loadForce the cache domain to be reloaded from the context.
*)| `LoadLoad a cache by iterating over the keys of its domain and by building a cached value for each key.
This operation can introduce a significant slowdown proportional to the number of entries in the cache, and depending on their nature. As a consequence, loading a cache from that source should be done when the system has no strict constraint on execution time, e.g., during startup.
*)| `LazySame as Load except that cached values are built on demand.
This strategy makes load_cache run a lot faster and the overall cost of loading the cache is only proportional to the number of entries *actually used* (and also depends on their nature).
Notice that, contrary to the `Load source of cache, this loading mode may also introduce latencies when entries are actually used since they are reconstructed on-the-fly.
RPCs are a typical place where this Lazy loading makes sense since the number of entries used is generally low, and the cache cannot be inherited (as in the next case).
*)| `Inherited of block_cache * Mavryk_crypto.Hashed.Context_hash.tWhen we already have some block_cache.cache in memory coming from the validation of some block block_cache.context_hash, we can reuse or recycle its entries to reconstruct a cache to check some other block identified by a given Context_hash.t, which typically comes after block_cache.context_hash in the chain.
This source is usually the most efficient way to build a cache in memory since the cache entries only change marginally from one block to one of its close descendants.
*) ]type builder = cache_key -> cache_value Mavryk_base.TzPervasives.tzresult Lwt.tTo load_cache in memory, we need to iterate over its domain and for each key found in the domain, a builder produces the associated value.
val load_cache :
Mavryk_crypto.Hashed.Block_hash.t ->
t ->
source_of_cache ->
builder ->
t Mavryk_base.TzPervasives.tzresult Lwt.tload_cache predecessor ctxt source builder populates the in-memory cache values cached in the current context during the validation of predecessor block. To achieve that, the function uses the strategy described by source, exploiting the builder to create cached values that are not already available in memory.
The builder is assumed to never fail when evaluated on the keys of the cache domain. Indeed, if a key had an associated value in the cache at some point in the past, it should have been a valid key. In other words, the construction of cache should be reproducible. For this reason, an error in builder is fatal.