Module Store.Chain

The module for handling chain-related operations such as setting the head of the chain, updating the chain state, forking testchains, ...

type nonrec chain_store = chain_store

The abstract type alias of a chain store.

type t = chain_store

The type alias of chain_store.

type testchain

The abstract type for testchain.

A type alias of a block identifier.

val global_store : chain_store -> store

global_store chain_store returns the global store of chain_store allowing to retrieve global infos.

chain_id chain_store returns chain id of chain_store.

val chain_dir : chain_store -> [ `Chain_dir ] Mavryk_store_shared.Naming.directory

chain_dir chain_store returns the path of directory of chain_store.

history_mode chain_store returns the history mode of the chain_store.

genesis chain_store returns the Genesis.t of the chain_store.

val genesis_block : chain_store -> Block.t Lwt.t

genesis chain_store returns the genesis block of the chain_store.

val current_head : chain_store -> Block.t Lwt.t

current_head chain_store returns the current head of the chain_store.

expiration chain_store returns the expiration date of the testchain's chain_store.

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_preserved_block_level

The checkpoint will tend to designate the highest block among all chain head's last_preserved_block_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.

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.

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_preserved_block_level < head.last_preserved_block_level

On Archive history mode: savepoint = genesis.

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 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

mempool chain_store returns the mempool associated to the chain_store.

block_of_identifier chain_store identifier tries to return the block of the given identifier inside the given chain_store.

val block_of_identifier_opt : chain_store -> block_identifier -> Block.t option Lwt.t

block_of_identifier_opt chain_store identifier optional version of block_of_identifier.

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.

live_blocks chain_store returns the set of previously computed live blocks for the current_head's chain_store.

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.

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 lpbl(new_head) if it was below this level or unchanged otherwise;
  • The savepoint will be updated to : min(max_op_ttl(lpbl(new_head)), lpbl(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: lpbl(new_head) is the last preserved block level of the new head.

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.

is_ancestor chain_store ~head ~ancestor checks whether the ancestor is a predecessor or head in chain_store.

is_in_chain chain_store block_descr checks that block_descr is an ancestor of chain_store's current head.

val is_acceptable_block : chain_store -> Mavryk_store_shared.Store_types.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.

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_protocol_locator : chain_store -> ?max_size:int -> proto_level:int -> Mavryk_base.TzPervasives.Block_locator.seed -> Mavryk_base.TzPervasives.Block_locator.t option 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.

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 testchain : chain_store -> testchain option Lwt.t

testchain chain_store returns the active testchain to the given chain_store if it has been instantiated.

val testchain_forked_block : testchain -> Mavryk_base.TzPervasives.Block_hash.t

testchain_forked_block testchain returns the hash of the forked block of its parent chain.

val testchain_store : testchain -> chain_store

testchain_store testchain returns the chain store associated to this testchain.

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 shutdown_testchain : chain_store -> unit Mavryk_base.TzPervasives.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.

Chain's protocols

val find_protocol_info : t -> protocol_level:int -> Mavryk_store_shared.Store_types.Protocol_levels.protocol_info option Lwt.t

find_protocol_info chain_store ~protocol_level returns the protocol info associated to the given protocol_level.

val find_activation_block : chain_store -> protocol_level:int -> Mavryk_store_shared.Store_types.block_descriptor option Lwt.t

find_activation_block chain_store ~protocol_level returns the block that activated the protocol of level protocol_level.

val find_protocol : chain_store -> protocol_level:int -> Mavryk_base.TzPervasives.Protocol_hash.t option Lwt.t

find_protocol chain_store ~protocol_level returns the protocol with the level protocol_level.

val expect_predecessor_context_hash : chain_store -> protocol_level:int -> bool Mavryk_base.TzPervasives.tzresult 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.

all_protocol_levels chain_store returns all the protocols registered in chain_store.

val may_update_protocol_level : chain_store -> ?pred:Block.block -> ?protocol_level:int -> expect_predecessor_context:bool -> (Block.block * Mavryk_base.TzPervasives.Protocol_hash.t) -> unit Mavryk_base.TzPervasives.tzresult 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_ancestor_protocol_level : chain_store -> head:Block.block -> unit Mavryk_base.TzPervasives.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 watcher : chain_store -> Block.t Lwt_stream.t * Lwt_watcher.stopper

watcher chain_store instantiates a new block watcher for chain_store.

val validated_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 get_rpc_directory : chain_store -> Block.t -> (chain_store * Block.t) Mavryk_rpc.Directory.t option Lwt.t

get_rpc_directory chain_store block returns the RPC directory associated to the block.

val set_rpc_directory : chain_store -> protocol_hash:Mavryk_base.TzPervasives.Protocol_hash.t -> next_protocol_hash:Mavryk_base.TzPervasives.Protocol_hash.t -> (chain_store * Block.t) Mavryk_rpc.Directory.t -> unit 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 register_gc_callback : chain_store -> (Mavryk_base.TzPervasives.Block_hash.t -> unit Mavryk_base.TzPervasives.tzresult Lwt.t) option -> unit

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_split_callback : chain_store -> (unit -> unit Mavryk_base.TzPervasives.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.