https://gitlab.com/tezos/tezos
Tip revision: 0436c9b65fed22f830943ac7f65e2781d08c51ba authored by Anne-Laure on 29 June 2023, 09:16:39 UTC
PlonK: change SRS input
PlonK: change SRS input
Tip revision: 0436c9b
store.mli
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2020-2021 Nomadic Labs, <contact@nomadic-labs.com> *)
(* *)
(* 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. *)
(* *)
(*****************************************************************************)
(** Store abstraction over the disk storage. *)
(**
{2 Description}
This component handles the on-disk storage of static objects such
as blocks, operations, block's metadata, protocols and chain data.
The store also handle the chain's current state: current head,
invalid blocks, active testchains, ...
{2 Concurrency}
This module is designed to handle concurrent accesses to the
store. Data-races and deadlocks might still happen through the use
of potential dangerous calls that are documented as such. Both a
mutex and a lockfile are present to handle concurrent accesses at
process levels.
{2 Context handling}
The store manages the context and thus handles the context
initialization through {!Lib_context.Context.init}. This is done,
among others reasons, for a consistency checking when storing a
block. The store never commits a context on-disk.
{2 History mode handling}
This store handles the three different
{!Tezos_base.History_mode.t}:
- Archive: maintains every block that is part of the chain
including their metadata.
- Full <offset>: maintains every block that is part of the chain
but prune the metadata for blocks that are below the following
threshold level: [last_allowed_fork_level] of the current head -
[offset] cycles.
- Rolling <offset>: maintains rolling windows which contain recent
blocks that are part of the chain, along with their metadata. It
prunes everything that is below the following threshold level:
[last_allowed_fork_level] of the current head - [offset] cycles.
{2 Protocol store}
The store has a global protocol store which may be shared by
different chain stores.
{2 Chain stores and merging}
The store has a toplevel chain store which is called the
[main_chain_store] and which can be accessed through the store's
interface. It is either created if the associated directory is not
present or loaded if it was previously created. This
[main_chain_store] is able to recursively spawn testchains which
are also chain stores. Those testchains are also recursively able
to spawn their own testchains.
Each chain store possesses its own block store and therefore its
own historic. It also maintains a state throughout its run which is
composed of:
- [current_head]: the current head of the chain.
- [target]: the optional block for which the chain must pass. The
store will not allow to store blocks past this target's block if
they are not its successors.
- [checkpoint]: the block that represents the no fork point level:
blocks that are below this block are discarded.
- [savepoint]: the block that represents the lowest block with
metadata in the chain.
- [caboose]: the block that represents the lowest block known in the
chain (with or without metadata).
More details and invariants on these points are provided in the
{!Chain} module description below.
When a block is promoted as head of the chain (through
{!Chain.set_head}) the following happens:
- A check is made if this head is consistent (i.e. if it's not
below the checkpoint);
- If the [last_allowed_fork_level] of the head is different from
the previous head's one, then we can establish that a cycle has
been completed and we can start cementing this cycle by
"triggering a merge".
A merge phase consists of establishing the interval of blocks to
cement, which is trivially [last_allowed_fork_level(new_head)] to
[last_allowed_fork_level(prev_head)], but also, for Full and
Rolling history modes, keep some extra blocks so that we make sure
to keep blocks above
max_operation_ttl(last_allowed_fork_level(checkpoint)). This is
done to make sure that we can export snapshots at the checkpoint
level later on. This merging operation is asynchronous, the changes
will be committed on disk only when the merge succeeds. Before
that, we only retain the changes in RAM so we may keep storing new
blocks without blocking. If the process crashes while a merge is
happening, the state is reloaded before the merging point. More
details are given in {!Chain.set_head}.
{2 Files hierarchy}
The store directory is organized as follows:
- /<protocol_dir>/ the directory containing stored protocols
- /<protocol_dir>/<protocol_hash_b58>* files containing the encoded
protocol.
- /<chain_id_b58>/ the [chain_store_dir] directory containing the
main chain store.
[chain_store_dir] is a symbol for all chain stores directory
hierarchy.
- [chain_store_dir]/<lock> the lockfile.
- [chain_store_dir]/<config.json> the chain store's configuration
as a JSON file.
- [chain_store_dir]/<block_store> contains every file mentioned in
{!Block_store}'s format.
- [chain_store_dir]/<stored_data>* files containing encoded simple
data structures such as: genesis block, checkpoint, savepoint,
caboose, protocol levels, forked chains, alternate heads, invalid
blocks, etc.
- [chain_store_dir]/testchains/<testchain_id_b58>/ contains the
[chains_store_dir]'s test chain, based on a similar hierarchy.
*)
open Store_types
(** The abstract type to manipulate the global store. *)
type t
(** The type alias for the global store. *)
type store = t
(** The abstract type for a chain store. Equivalent to {!Chain.t}. *)
type chain_store
(** {3 Initialization} *)
(** [init ?patch_context ?commit_genesis ?history_mode
?block_cache_limit ~store_dir ~context_dir ~allow_testchains
genesis] initializes the store and a main chain store. If
[store_dir] (resp. [context_dir]) does not exist, a fresh store
(resp. context) is created. Otherwise, it loads the store
(resp. context) from reading the adequate directory. If
[allow_testchains] is passed, the store will be able to fork
chains and instantiate testchain's sub chain stores, for all
chains contained in the store. The chain store created is based on
the [genesis] provided. Its chain identifier will be computed
using the {!Chain_id.of_block_hash} function.
@param patch_context the handle called when initializing the
context. It usually is passed when creating a sandboxed chain.
@param commit_genesis overrides the default initial genesis commit
when the node is created. This is used for when the context must be
in readonly (e.g. started by an external validator) and we want to
prevent writing in the context. {b Warning} passing this argument
will initialize the context in readonly.
Default: {!Context.commit_genesis} is called with [genesis]
@param history_mode the history mode used throughout the store. If
a directory already exists and the given [history_mode] is
different, the initialization will fail.
Default: {!History_mode.default} (which should correspond to full
with 5 extra preserved cycles.)
@param block_cache_limit allows to override the size of the block
cache to use. The minimal value is 1.
@param readonly a flag that, if set to true, prevent writing
throughout the store {b and} context.
Default: false
*)
val init :
?patch_context:
(Tezos_protocol_environment.Context.t ->
Tezos_protocol_environment.Context.t tzresult Lwt.t) ->
?commit_genesis:(chain_id:Chain_id.t -> Context_hash.t tzresult Lwt.t) ->
?history_mode:History_mode.t ->
?readonly:bool ->
?block_cache_limit:int ->
store_dir:string ->
context_dir:string ->
allow_testchains:bool ->
Genesis.t ->
store tzresult Lwt.t
(** [main_chain_store global_store] returns the main chain store. *)
val main_chain_store : store -> chain_store
(** [close_store global_store] closes the underlying block store and
context along with every opened file descriptors for every chain
store and testchain present in [global_store]. If the store is
already closed, this function is idempotent. *)
val close_store : store -> unit Lwt.t
(** [may_switch_history_mode ?patch_context ~store_dir ~context_dir
genesis ~new_history_mode] tries switching the store located at
[store_dir] (if present) to [new_history_mode] when possible. *)
val may_switch_history_mode :
store_dir:string ->
context_dir:string ->
Genesis.t ->
new_history_mode:History_mode.t ->
unit tzresult Lwt.t
(** {3 Accessors} *)
(** [directory global_store] returns the path where [global_store] is
stored. This corresponds to the [store_dir] argument passed to the
[init] function. *)
val directory : store -> [`Store_dir] Naming.directory
(** [context_index global_store] returns the context's index
initialized in [global_store]. *)
val context_index : store -> Context_ops.index
(** [allow_testchains global_store] returns true if the store is
allowed to fork testchains. *)
val allow_testchains : store -> bool
(** [all_chain_stores global_store] returns every initialized chain
store in [global_store]. The resulting list also comprises the
initialized testchains. If [allow_testchains] is false, the list
will only contain a single element. *)
val all_chain_stores : store -> chain_store list Lwt.t
(** [get_chain_store global_store chain_id] returns the initialized
chain store in [global_store] associated to [chain_id]. *)
val get_chain_store : store -> Chain_id.t -> chain_store tzresult Lwt.t
(** [get_chain_store_opt global_store chain_id] optional version of
[get_chain_store]. *)
val get_chain_store_opt : store -> Chain_id.t -> chain_store option Lwt.t
val make_pp_store : store -> (Format.formatter -> unit -> unit) Lwt.t
val make_pp_chain_store :
chain_store -> (Format.formatter -> unit -> unit) Lwt.t
(** The module for handling block-related operations such as storing
and reading data associated to a single block. *)
module Block : sig
(** The abstract type for a block. *)
type t
(** The type alias for a block. *)
type block = t
(** The type for block's metadata. *)
type metadata = Block_repr.metadata = {
message : string option;
max_operations_ttl : int;
last_allowed_fork_level : Int32.t;
block_metadata : Bytes.t;
operations_metadata : Block_validation.operation_metadata list list;
}
(* FIXME: could be misleading. *)
(** [equal b1 b2] tests the equality between [b1] and [b2]. {b
Warning} only block hashes are compared. *)
val equal : block -> block -> bool
(** [is_known_valid chain_store bh] tests that the block [bh] is
known and valid in [chain_store] (i.e. the block is present in
the block store). *)
val is_known_valid : chain_store -> Block_hash.t -> bool Lwt.t
(** [is_known_invalid chain_store bh] tests that the block [bh] is
invalid in [chain_store] (i.e. the block is present in the
invalid blocks file). *)
val is_known_invalid : chain_store -> Block_hash.t -> bool Lwt.t
(** [is_known_validated chain_store bh] tests that the block [bh]
is validated in [chain_store] (i.e. the block is present in the
validated block cache). *)
val is_known_validated : chain_store -> Block_hash.t -> bool Lwt.t
(** [is_known chain_store bh] tests that the block [bh] is either
known valid or known invalid in [chain_store]. *)
val is_known : chain_store -> Block_hash.t -> bool Lwt.t
(** [is_genesis chain_store bh] tests that the block [bh] is the
genesis initialized in [chain_store]. *)
val is_genesis : chain_store -> Block_hash.t -> bool
(** [validity chain_store bh] computes the
{!Block_locator.validity} ([Unknown], [Known_valid] or
[Known_invalid]) for the block [bh] in [chain_store]. *)
val validity : chain_store -> Block_hash.t -> Block_locator.validity Lwt.t
(** [read_block chain_store ?distance bh] tries to read in the
[chain_store] the block [bh] or the predecessing block at the
offset [distance] of [bh]. By default, [distance] is 0.*)
val read_block :
chain_store -> ?distance:int -> Block_hash.t -> block tzresult Lwt.t
(** [read_block_opt chain_store ?distance bh] optional version of
[read_block]. *)
val read_block_opt :
chain_store -> ?distance:int -> Block_hash.t -> block option Lwt.t
(** [read_block_by_level chain_store level] reads in the
[chain_store] the block at [level]. The block retrieved will be
the (level(current_head) - level)-th predecessor of the
[chain_store]'s current head. *)
val read_block_by_level : chain_store -> int32 -> block tzresult Lwt.t
(** [read_block_by_level_opt chain_store level] optional version of
[read_block_by_level]. *)
val read_block_by_level_opt : chain_store -> int32 -> block option Lwt.t
(** [read_block_metadata ?distance chain_store bh] reads in the
[chain_store] the metadata associated to the block [bh] or its
[distance]-th predecessor if given. Returns [None]
otherwise. By default, [distance] is 0.
{b Warning} If the block is already read, prefer the usage of
[get_block_metadata] which will memoize the result. *)
val read_block_metadata :
?distance:int ->
chain_store ->
Block_hash.t ->
metadata option tzresult Lwt.t
(** [read_block_metadata_opt ?distance chain_store bh] same as
[read_block_metadata] but returns [None] in case of errors. *)
val read_block_metadata_opt :
?distance:int -> chain_store -> Block_hash.t -> metadata option Lwt.t
(** [get_block_metadata chain_store block] reads in the
[chain_store] the metadata associated to the [block]. Returns
[None] if the metadata cannot be retrieved. This function also
memoize the result in the [block] structure so subsequent calls
will be disk I/O free. *)
val get_block_metadata : chain_store -> block -> metadata tzresult Lwt.t
(** [get_block_metadata_opt chain_store block] optional version of
[get_block_metadata] *)
val get_block_metadata_opt : chain_store -> block -> metadata option Lwt.t
(** [read_predecessor chain_store block] reads in the [chain_store]
the direct predecessor of [block]. Returns [None] if it cannot
be found. *)
val read_predecessor : chain_store -> block -> block tzresult Lwt.t
(** [read_predecessor_opt chain_store block] optional version of
[read_predecessor]. *)
val read_predecessor_opt : chain_store -> block -> block option Lwt.t
(** [read_predecessor_of_hash chain_store bh] reads in [chain_store]
the predecessor's block of [bh]. *)
val read_predecessor_of_hash :
chain_store -> Block_hash.t -> block tzresult Lwt.t
(** [read_ancestor_hash chain_store ~distance bh] retrieves in the
[chain_store] the hash of the ancestor of the block [bh] at
[distance] if it exists. Returns [None] otherwise. *)
val read_ancestor_hash :
chain_store ->
distance:int ->
Block_hash.t ->
Block_hash.t option tzresult Lwt.t
(** [read_ancestor_hash_opt chain_store ~distance bh] same as
[read_ancestor_hash] but returns [None] on errors. *)
val read_ancestor_hash_opt :
chain_store -> distance:int -> Block_hash.t -> Block_hash.t option Lwt.t
(** [read_ancestor_opt chain_store block] optional version of
[read_ancestor]. *)
val read_predecessor_of_hash_opt :
chain_store -> Block_hash.t -> block option Lwt.t
(** [read_validated_block chain_store bh] tries to read in the
[chain_store]'s validated block cache the block [bh].*)
val read_validated_block : chain_store -> Block_hash.t -> block tzresult Lwt.t
(** [read_validated_block_opt chain_store bh] optional version of
[read_validated_block].*)
val read_validated_block_opt :
chain_store -> Block_hash.t -> block option Lwt.t
(** [store_block chain_store ~block_header ~operations
validation_result] stores in [chain_store] the block with its
[block_header], [operations] and validation result. Inconsistent
blocks and validation will result in failures. Returns [None] if
the block was already stored. If the block is correctly stored,
the newly created block is returned.
If the block was successfully stored, then the block is removed
from the validated block cache.
{b Warning} The store will refuse to store blocks with no
associated context's commit. *)
val store_block :
chain_store ->
block_header:Block_header.t ->
operations:Operation.t list list ->
Block_validation.result ->
block option tzresult Lwt.t
(** [store_validated_block chain_store ~hash ~block_header ~operations]
stores in [chain_store]'s validated block cache the block with
its [block_header] and [operations]. *)
val store_validated_block :
chain_store ->
hash:Block_hash.t ->
block_header:Block_header.t ->
operations:Operation.t trace trace ->
unit tzresult Lwt.t
(** [resulting_context_hash chain_store block] returns the resulting
context hash of the [block]. This context depends on the
[block]'s protocol associated semantics, i.e., it can either be
the one contained in its block header or the stored result of
its application. *)
val resulting_context_hash :
chain_store -> block -> Context_hash.t tzresult Lwt.t
(** [context_exn chain_store block] checkouts the {b resulting}
context of the [block] which may differ from its block header's
one depending on the block's associated protocol semantics. *)
val context_exn :
chain_store -> block -> Tezos_protocol_environment.Context.t Lwt.t
(** [context_opt chain_store block] optional version of
[context_exn]. *)
val context_opt :
chain_store -> block -> Tezos_protocol_environment.Context.t option Lwt.t
(** [context chain_store block] error monad version of
[context_exn]. *)
val context :
chain_store -> block -> Tezos_protocol_environment.Context.t tzresult Lwt.t
(** [context_exists chain_store block] tests the existence of the
[block]'s commit in the context. *)
val context_exists : chain_store -> block -> bool Lwt.t
(** [testchain_status chain_store block] returns the test chain
status stored in context of [block] along with testchain's
genesis if the testchain is found [Forking] or [Running]. *)
val testchain_status :
chain_store ->
block ->
(Test_chain_status.t * Block_hash.t option) tzresult Lwt.t
(** [protocol_hash_exn chain_store block] reads the protocol
associated to [block] in its associated context. Fails when the
context is unknown. *)
val protocol_hash_exn : chain_store -> block -> Protocol_hash.t Lwt.t
(** [protocol_hash chain_store block] error monad version of
[protocol_hash_exn]. *)
val protocol_hash : chain_store -> block -> Protocol_hash.t tzresult Lwt.t
(** [read_invalid_block_opt chain_store bh] reads in the
[chain_store] the invalid block [bh] if it exists. *)
val read_invalid_block_opt :
chain_store -> Block_hash.t -> invalid_block option Lwt.t
(** [read_invalid_blocks chain_store] returns the map of all invalid
blocks of [chain_store]. *)
val read_invalid_blocks : chain_store -> invalid_block Block_hash.Map.t Lwt.t
(** [mark_invalid chain_store bh ~level errors] stores the block
[bh] at [level] with the given [errors]. Fails when trying to
mark the genesis block as invalid. *)
val mark_invalid :
chain_store ->
Block_hash.t ->
level:int32 ->
error list ->
unit tzresult Lwt.t
(** [unmark_invalid chain_store bh] unmarks invalid the block [bh]
in the [chain_store]. *)
val unmark_invalid : chain_store -> Block_hash.t -> unit tzresult Lwt.t
(** [descriptor block] returns the pair (hash x level) of [block]. *)
val descriptor : block -> block_descriptor
(** {3 Block field accessors} *)
val hash : block -> Block_hash.t
val header : block -> Block_header.t
val operations : block -> Operation.t list list
val shell_header : block -> Block_header.shell_header
val level : block -> int32
val proto_level : block -> int
val predecessor : block -> Block_hash.t
val timestamp : block -> Time.Protocol.t
val validation_passes : block -> int
val operations_hash : block -> Operation_list_list_hash.t
val fitness : block -> Fitness.t
val context_hash : block -> Context_hash.t
val protocol_data : block -> bytes
val block_metadata_hash : block -> Block_metadata_hash.t option
val operations_metadata_hashes :
block -> Operation_metadata_hash.t list list option
val operations_metadata_hashes_path :
block -> int -> Operation_metadata_hash.t list option
val all_operations_metadata_hash :
block -> Operation_metadata_list_list_hash.t option
(** {3 Block metadata field accessors} *)
val message : metadata -> string option
val max_operations_ttl : metadata -> int
val last_allowed_fork_level : metadata -> int32
val block_metadata : metadata -> Bytes.t
val operations_metadata :
metadata -> Block_validation.operation_metadata list list
(** [operations_path block nth] computes the [nth] operations list
of [block] along with the hash of all operations. *)
val operations_path :
block -> int -> Operation.t list * Operation_list_list_hash.path
(** [operations_hashes_path block nth] computes the [nth] operations
hash list of [block] along with the hash of all operations. *)
val operations_hashes_path :
block -> int -> Operation_hash.t list * Operation_list_list_hash.path
(** [all_operation_hashes block] computes the hash of all operations
in [block]. *)
val all_operation_hashes : block -> Operation_hash.t list list
end
(** The module for handling chain-related operations such as setting
the head of the chain, updating the chain state, forking
testchains, ... *)
module Chain : sig
(** The abstract type alias of a chain store. *)
type nonrec chain_store = chain_store
(** The type alias of [chain_store]. *)
type t = chain_store
(** The abstract type for testchain. *)
type testchain
(** A type alias of a block identifier. *)
type block_identifier = Block_services.block
(** [global_store chain_store] returns the global store of
[chain_store] allowing to retrieve global infos.*)
val global_store : chain_store -> store
(** [chain_id chain_store] returns chain id of [chain_store]. *)
val chain_id : chain_store -> Chain_id.t
(** [chain_dir chain_store] returns the path of directory of
[chain_store].*)
val chain_dir : chain_store -> [`Chain_dir] Naming.directory
(** [history_mode chain_store] returns the history mode of the
[chain_store].*)
val history_mode : chain_store -> History_mode.t
(** [genesis chain_store] returns the {!Genesis.t} of the
[chain_store]. *)
val genesis : chain_store -> Genesis.t
(** [genesis chain_store] returns the genesis block of the
[chain_store]. *)
val genesis_block : chain_store -> Block.t Lwt.t
(** [current_head chain_store] returns the current head of the
[chain_store]. *)
val current_head : chain_store -> Block.t Lwt.t
(** [expiration chain_store] returns the expiration date of the
testchain's [chain_store]. *)
val expiration : chain_store -> Time.Protocol.t option
(** [checkpoint chain_store] returns the checkpoint associated to
the [chain_store].
The checkpoint is a block descriptor
({!Store_types.block_descriptor}) pointing to a block that must be
part of the chain. The checkpoint maintains the set of following
invariants:
- The store will only accept blocks that are above its
checkpoint's level.
- The checkpoint is updated periodically such that the following
invariant holds:
[checkpoint.level >= all_head.last_allowed_fork_level]
The checkpoint will tend to designate the highest block among
all chain head's [last_allowed_fork_level] in a normal mode. This
is not always true. i.e. after a snapshot import where the
checkpoint will be set as the imported block and when the
[target] block is reached, the checkpoint will be set at this
point. *)
val checkpoint : chain_store -> block_descriptor Lwt.t
(** [target chain_store] returns the target block associated to the
[chain_store] if there is one or [None] if it has already been reached.
The target is a ({!Store_types.block_descriptor}) pointing to a
future block that must be reached by the chain. When a block is
received, if its level is equal to the target's block level then
its hash must be also be the same. Otherwise, the block is
considered as invalid and will be discarded.
The target should only be set manually. Whenever the target
block is reached, the checkpoint will be updated to this
block and the target will be set to [None]. *)
val target : chain_store -> block_descriptor option Lwt.t
(** [savepoint chain_store] returns the savepoint associated to the
[chain_store].
The savepoint is a block descriptor
({!Store_types.block_descriptor}) pointing to the lowest level
block that has its metadata and/or context pruned with the
following invariant:
[is_stored(block) \and has_metadata(block) => block.level >=
savepoint.level]
For Full and Rolling history modes, the savepoint will be
periodically updated at each store merge which happens when:
[pred(head).last_allowed_fork_level < head.last_allowed_fork_level]
On Archive history mode: [savepoint = genesis]. *)
val savepoint : chain_store -> block_descriptor Lwt.t
(** [caboose chain_store] returns the caboose associated to the
[chain_store].
The caboose is a block descriptor
({!Store_types.block_descriptor}) pointing to the lowest level
block that we know present in the chain store, if the history
mode is {b not} Archive, it might not contain its metadata
depending on the current savepoint:
[is_stored(block) => block.level >= caboose.level]
On Archive and Full history mode: [caboose = genesis] *)
val caboose : chain_store -> block_descriptor Lwt.t
(** [mempool chain_store] returns the mempool associated to the
[chain_store]. *)
val mempool : chain_store -> Mempool.t Lwt.t
(** [block_of_identifier chain_store identifier] tries to return the block
of the given [identifier] inside the given [chain_store]. *)
val block_of_identifier :
chain_store -> block_identifier -> Block.t tzresult Lwt.t
(** [block_of_identifier_opt chain_store identifier] optional version of [block_of_identifier]. *)
val block_of_identifier_opt :
chain_store -> block_identifier -> Block.t option Lwt.t
(** [set_mempool chain_store ~head mempool] sets the [mempool] of
the [chain_store]. Does nothing if [head] is not current_head
which might happen when a new head concurrently arrives just
before this operation being called. *)
val set_mempool :
chain_store -> head:Block_hash.t -> Mempool.t -> unit tzresult Lwt.t
(** [live_blocks chain_store] returns the set of previously computed
live blocks for the current_head's [chain_store]. *)
val live_blocks :
chain_store -> (Block_hash.Set.t * Operation_hash.Set.t) Lwt.t
(** [compute_live_blocks ~block chain_store] computes the set of
live blocks and live operations relative to [block]. Does nothing
if [block] is the [chain_store]'s current head as it was
previously updated in {!set_head}.
Note: this operation should not be costly in most cases as
recent blocks and operations are expected to be in a cache. *)
val compute_live_blocks :
chain_store ->
block:Block.t ->
(Block_hash.Set.t * Operation_hash.Set.t) tzresult Lwt.t
(** [set_head chain_store block] promotes the [block] as head of the
[chain_store] and triggers an asynchronous store merge if a
cycle is ready to be cemented. Triggering a merge will update
the savepoint, checkpoint and caboose consistently with the
[chain_store]'s history mode. This function returns the previous
head. Setting a new head will fail when the block is not fit to
be promoted as head (i.e. too old or no metadata).
After a merge:
- The checkpoint is updated to [lafl(new_head)] if it was below
this level or unchanged otherwise;
- The savepoint will be updated to :
min(max_op_ttl(lafl(new_head)), lafl(new_head) -
<cycle_length> * <history_mode_offset>) or will remain 0 in
Archive mode;
- The caboose will be updated to the same value as the savepoint
in Rolling mode.
Note: lafl(new_head) is the last allowed fork level of the new
head.
{b Warnings:}
- We expect blocks to be sequentially promoted as head using
this function;
- If a merge is triggered while another is happening, this
function will block until the first merge is resolved. *)
val set_head : chain_store -> Block.t -> Block.t tzresult Lwt.t
(** [is_ancestor chain_store ~head ~ancestor] checks whether the
[ancestor] is a predecessor or [head] in [chain_store]. *)
val is_ancestor :
chain_store ->
head:block_descriptor ->
ancestor:block_descriptor ->
bool Lwt.t
(** [is_in_chain chain_store block_descr] checks that [block_descr]
is an ancestor of [chain_store]'s current head. *)
val is_in_chain : chain_store -> block_descriptor -> bool Lwt.t
(** [is_acceptable_block chain_store block_descr] checks if
[block_descr] would be a valid block to be stored in
[chain_store]. Its predecessor is supposed to be already
stored. *)
val is_acceptable_block : chain_store -> block_descriptor -> bool Lwt.t
(** [compute_locator chain ?max_size head seed] computes a
locator of the [chain] from [head] to the chain's caboose or until
the locator contains [max_size] steps.
[max_size] defaults to 200. *)
val compute_locator :
chain_store ->
?max_size:int ->
Block.t ->
Block_locator.seed ->
Block_locator.t Lwt.t
(** [compute_protocol_locator chain ?max_size ~proto_level seed]
computes a locator for a specific protocol of level [proto_level]
in the [chain] from the latest block with this protocol to its
activation block or until the locator contains [max_size] steps.
[max_size] defaults to 200. *)
val compute_protocol_locator :
chain_store ->
?max_size:int ->
proto_level:int ->
Block_locator.seed ->
Block_locator.t option Lwt.t
(** [set_target chain_store target_descr] sets the target for
[chain_store]. If [target_descr] is already known,
[set_checkpoint] will be internally called. Fails if the target
is below the current checkpoint. *)
val set_target : chain_store -> block_descriptor -> unit tzresult Lwt.t
(** [testchain chain_store] returns the active testchain
to the given [chain_store] if it has been instantiated. *)
val testchain : chain_store -> testchain option Lwt.t
(** [testchain_forked_block testchain] returns the hash of the forked
block of its parent chain.*)
val testchain_forked_block : testchain -> Block_hash.t
(** [testchain_store testchain] returns the chain store associated
to this [testchain]. *)
val testchain_store : testchain -> chain_store
(** [fork testchain chain_store ~testchain_id ~forked_block
~genesis_hash ~genesis_header ~test_protocol ~expiration] forks
a testchain and activates it for [chain_store]. If a testchain
with [testchain_id] already existed, it is then loaded from the
store. If it was already activated, does nothing. It also
registers this chain in the set of activated testchains. *)
val fork_testchain :
chain_store ->
testchain_id:Chain_id.t ->
forked_block:Block.t ->
genesis_hash:Block_hash.t ->
genesis_header:Block_header.t ->
test_protocol:Protocol_hash.t ->
expiration:Time.Protocol.t ->
testchain tzresult Lwt.t
(** [shutdown_testchain chain_store] closes and deactivates the
testchain running for [chain_store]. Does nothing if no
testchain is found running for [chain_store]. *)
val shutdown_testchain : chain_store -> unit tzresult Lwt.t
(** {2 Chain's protocols} *)
(** [find_protocol_info chain_store ~protocol_level] returns the
protocol info associated to the given [protocol_level]. *)
val find_protocol_info :
t -> protocol_level:int -> Protocol_levels.protocol_info option Lwt.t
(** [find_activation_block chain_store ~protocol_level] returns the
block that activated the protocol of level [protocol_level]. *)
val find_activation_block :
chain_store -> protocol_level:int -> block_descriptor option Lwt.t
(** [find_protocol chain_store ~protocol_level] returns the protocol
with the level [protocol_level]. *)
val find_protocol :
chain_store -> protocol_level:int -> Protocol_hash.t option Lwt.t
(** [expects_predecessor_context_hash chain_store proto_level]
returns whether or not a protocol requires the context hash of a
block to target resulting context of it's predecessor. This
depends on the environment of each protocol.*)
val expect_predecessor_context_hash :
chain_store -> protocol_level:int -> bool tzresult Lwt.t
(** [all_protocol_levels chain_store] returns all the protocols
registered in [chain_store]. *)
val all_protocol_levels :
chain_store -> Protocol_levels.protocol_info Protocol_levels.t Lwt.t
(** [may_update_protocol_level chain_store ?pred ?protocol_level
~expect_predecessor_context (block, ph)] updates the protocol
level for the protocol [ph] in [chain_store] with the activation
[block]. If [pred] is not provided, it reads the [block]'s
predecessor and check that the [block]'s protocol level is
increasing compared to its predecessor. If [protocol_level] is
provided, we use this value instead of the protocol level found
in [block]. If a previous entry is found, it overwrites it. The
[expect_predecessor_context] argument specifies which context
hash semantics should be used. *)
val may_update_protocol_level :
chain_store ->
?pred:Block.block ->
?protocol_level:int ->
expect_predecessor_context:bool ->
Block.block * Protocol_hash.t ->
unit tzresult Lwt.t
(** [may_update_ancestor_protocol_level chain_store ~head
~expect_predecessor_context] tries to find the activation block
of the [head]'s protocol, checks that its an ancestor and tries
to update it if that's not the case. If the registered
activation block is not reachable (already pruned), this
function does nothing. The [expect_predecessor_context] argument
specifies which context hash semantics should be used. *)
val may_update_ancestor_protocol_level :
chain_store -> head:Block.block -> unit tzresult Lwt.t
(** [watcher chain_store] instantiates a new block watcher for
[chain_store]. *)
val watcher : chain_store -> Block.t Lwt_stream.t * Lwt_watcher.stopper
(** [validated_watcher chain_store] instantiates a new validated block
watcher for [chain_store]. *)
val validated_watcher :
chain_store -> Block.t Lwt_stream.t * Lwt_watcher.stopper
(** [get_rpc_directory chain_store block] returns the RPC directory
associated to the [block]. *)
val get_rpc_directory :
chain_store ->
Block.t ->
(chain_store * Block.t) Tezos_rpc.Directory.t option Lwt.t
(** [set_rpc_directory chain_store ph next_ph rpc_directory] sets a
[rpc_directory] for the protocol [ph] and next protocol [next_ph]
in [chain_store]. *)
val set_rpc_directory :
chain_store ->
protocol_hash:Protocol_hash.t ->
next_protocol_hash:Protocol_hash.t ->
(chain_store * Block.t) Tezos_rpc.Directory.t ->
unit Lwt.t
(** [register_gc_callback chain_store callback] installs a
[callback] that may be triggered during a block store merge in
order to garbage-collect old contexts. *)
val register_gc_callback :
chain_store -> (Block_hash.t -> unit tzresult Lwt.t) option -> unit
(** [register_split_callback chain_store callback] installs a
[callback] that may be triggered during a [set_head] in order to
split the context into a new chunk. *)
val register_split_callback :
chain_store -> (unit -> unit tzresult Lwt.t) option -> unit
end
(** [global_block_watcher global_store] instantiates a new block
watcher for every chain store active in [global_store]. *)
val global_block_watcher :
store -> (Chain.chain_store * Block.block) Lwt_stream.t * Lwt_watcher.stopper
(** The module for handling protocol-related operations. *)
module Protocol : sig
(** [mem global_store ph] checks the existence of the protocol [ph]
in [global_store]. *)
val mem : store -> Protocol_hash.t -> bool
(** [all global_store ph] returns the set of all stored protocol in
[global_store]. *)
val all : store -> Protocol_hash.Set.t
(** [read global_store ph] reads the protocol [ph] from the
[global_store]. Returns [None] if it does not exist. *)
val read : store -> Protocol_hash.t -> Protocol.t option Lwt.t
(** [store global_store ph protocol] stores the [protocol] under the
hash [ph] in the [global_store]. Returns [None] if it already
exists or [Some ph] if it was correctly stored.
{b Warning} No hash check is made, the caller must be careful
when storing protocols. *)
val store :
store -> Protocol_hash.t -> Protocol.t -> Protocol_hash.t option Lwt.t
(** [store_raw global_store ph bytes] raw version of [store]. *)
val store_raw :
store -> Protocol_hash.t -> bytes -> Protocol_hash.t option Lwt.t
(** [protocol_watcher global_store] instantiates a new protocol
watcher in [global_store]. *)
val protocol_watcher :
store -> Protocol_hash.t Lwt_stream.t * Lwt_watcher.stopper
end
(** The utility module used to traverse the chain. *)
module Chain_traversal : sig
(** [path chain_store from_block to_block] retrieves all blocks in
[chain_store] from [from_block] to [to_block] ([from_block] is
excluded from the result).
@raise Invalid_arg if [from_block] is above [to_block]. *)
val path :
chain_store ->
from_block:Block.t ->
to_block:Block.t ->
Block.t list option Lwt.t
(** [common_ancestor chain_store b1 b2] retrieves the common
ancestor of [b1] and [b2] in [chain_store]. Returns [None] if no
ancestor can be found. *)
val common_ancestor :
chain_store -> Block.t -> Block.t -> Block.t option Lwt.t
(** [new_blocks ~from_block ~to_block] returns a pair [(ancestor,
path)], where [ancestor] is the common ancestor of [from_block]
and [to_block] and where [path] is the chain from [ancestor]
(excluded) to [to_block] (included).
@raise assert failure when the two provided blocks do not belong
to the same [chain]. *)
val new_blocks :
chain_store ->
from_block:Block.t ->
to_block:Block.t ->
(Block.t * Block.t list) Lwt.t
end
val v_3_0_upgrade : store_dir:string -> Genesis.t -> unit tzresult Lwt.t
(**/**)
(** Unsafe set of functions intended for internal store manipulation
(e.g. snapshot, reconstruct, testing). Must not be used outside of
the [Tezos_store]. *)
module Unsafe : sig
val repr_of_block : Block.t -> Block_repr.t
val block_of_repr : Block_repr.t -> Block.t
end