Module Mavryk_shell.Prevalidator_classification

type error_classification = [
  1. | `Branch_delayed of Mavryk_base.TzPervasives.tztrace
  2. | `Branch_refused of Mavryk_base.TzPervasives.tztrace
  3. | `Refused of Mavryk_base.TzPervasives.tztrace
  4. | `Outdated of Mavryk_base.TzPervasives.tztrace
]

Classifications which correspond to errors

type classification = [
  1. | `Validated
  2. | error_classification
]

Classification of an operation in the mempool

type 'protocol_data bounded_map

map bounded_map gets the underling map of the bounded_map.

val cardinal : 'protocol_data bounded_map -> int

cardinal bounded_map gets the cardinal of the underling map of the bounded_map

type parameters = {
  1. map_size_limit : int;
  2. on_discarded_operation : Mavryk_base.TzPervasives.Operation_hash.t -> unit;
}

This module implements a sized-map data-structure.

type 'protocol_data t = private {
  1. parameters : parameters;
  2. refused : 'protocol_data bounded_map;
  3. outdated : 'protocol_data bounded_map;
  4. branch_refused : 'protocol_data bounded_map;
  5. branch_delayed : 'protocol_data bounded_map;
  6. mutable validated : 'protocol_data Shell_operation.operation Sized_map.t;
  7. mutable unparsable : Mavryk_base.TzPervasives.Operation_hash.Set.t;
  8. mutable in_mempool : ('protocol_data Shell_operation.operation * classification) Mavryk_base.TzPervasives.Operation_hash.Map.t;
}

Invariants ensured by this module, provided that the caller does not add an operation which is already present in t:

  • The field in_mempool is the set of all operation hashes present in fields: refused; outdated; branch_refused; branch_delayed; validated.
  • An operation cannot be at the same time in two of the fields: refused; outdated; branch_refused; branch_delayed; validated.

Note: unparsable operations are handled in a different way because they cannot be handled as a operation since this datatype requires an operation to be parsable. Hence, unparsable operations are handled differently. In particular, unparsable operations are removed on flush.

Note: We could always enforce these invariants by checking in add whether the operation is already present. However, this would make the behavior of add less predictable, so we do not think this to be an improvement from the point of view of the caller.

val create : parameters -> 'protocol_data t

create parameters returns an empty t whose bounded maps hold at most parameters.map_size_limit values. The on_discarded_operation is called when a new operation is added and an old one is discarded because the limit was reached.

Invalid_argument is raised if ring_size is 0 or less.

val is_empty : 'protocol_data t -> bool

is_empty t returns true iff t doesn't contain any operation.

val is_in_mempool : Mavryk_base.TzPervasives.Operation_hash.t -> 'protocol_data t -> ('protocol_data Shell_operation.operation * classification) option

is_in_mempool oph classes indicates whether oph is present in field in_mempool of classes. It returns the corresponding operation and its classification if present, and None otherwise.

val is_known_unparsable : Mavryk_base.TzPervasives.Operation_hash.t -> 'protocol_data t -> bool

is_known_unparsable oph returns true if the oph is associated to an operation which is known to be unparsable. false otherwise.

val remove : Mavryk_base.TzPervasives.Operation_hash.t -> 'protocol_data t -> ('protocol_data Shell_operation.operation * classification) option

remove oph classes removes operation of hash oph from all fields of classes. The function is O(log n) with n the number of operations in the corresponding class.

If oph was found, its classification as well as the operation it was bound to are returned. If oph was not found, None is returned.

val add : classification -> 'protocol_data Shell_operation.operation -> 'protocol_data t -> unit

add ~notify classification op classes adds the operation op classified as classification to the classifier classes. The classes.parameters.on_discarded_operation callback is called for any operation discarded in this process. Currently, an operation is discarded in the following cases:

  • the corresponding error class field is full. In that case, the new operation is added to the class, and the removed one is discarded.
  • an operation is classified as Refused.

Note that a Refused operation may thus be passed twice to on_discarded_operation: as soon as it is added, and if it is removed because the classes.refused bounded map is full.

As a summary:

  • Validated operations are never discarded
  • Branch_refused and Branch_delayed are discarded 0 or 1 time (if the corresponding bounded_map is full)
  • Refused is discarded 1 or 2 times (if the corresponding bounded_map is full)
val add_unparsable : Mavryk_base.TzPervasives.Operation_hash.t -> 'protocol_data t -> unit

add_unparsable oph classes adds oph as an unparsable operation. unparsable operations are removed automatically by the recycle_operations function. on_discard_operation is also called on those operations.

type 'block block_tools = {
  1. bhash : 'block -> Mavryk_base.TzPervasives.Block_hash.t;
    (*

    The hash of a block

    *)
  2. operations : 'block -> Mavryk_base.Operation.t list list;
    (*

    The list of operations of a block ordered by their validation pass

    *)
  3. all_operation_hashes : 'block -> Mavryk_base.TzPervasives.Operation_hash.t list list;
    (*

    The list of hashes of operations of a block ordered by their validation pass. Could be implemented using operations but this lets an alternative implementation to be provided.

    *)
}

Functions to query data on a polymorphic block-like type 'block.

type 'block chain_tools = {
  1. clear_or_cancel : Mavryk_base.TzPervasives.Operation_hash.t -> unit;
    (*

    Removes the operation from the distributed database.

    *)
  2. inject_operation : Mavryk_base.TzPervasives.Operation_hash.t -> Mavryk_base.Operation.t -> unit Lwt.t;
    (*

    Puts the operation in the distributed database. Returns false if the hash is already in the distributed database

    *)
  3. new_blocks : from_block:'block -> to_block:'block -> ('block * 'block list) 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).

    • raises assert

      failure when the two provided blocks do not belong to the same chain.

    *)
  4. read_predecessor_opt : 'block -> 'block option Lwt.t;
    (*

    read_predecessor_opt block returns the direct predecessor of block or None if it cannot be found.

    *)
}

A wrapper over chain-related modules, to make client code easier to emulate, and hence to test

val recycle_operations : from_branch:'block -> to_branch:'block -> live_blocks:Mavryk_base.TzPervasives.Block_hash.Set.t -> classes:'protocol_data t -> parse: (Mavryk_base.TzPervasives.Operation_hash.t -> Mavryk_base.Operation.t -> 'protocol_data Shell_operation.operation option) -> pending: 'protocol_data Shell_operation.operation Mavryk_base.TzPervasives.Operation_hash.Map.t -> block_store:'block block_tools -> chain:'block chain_tools -> handle_branch_refused:bool -> 'protocol_data Shell_operation.operation Mavryk_base.TzPervasives.Operation_hash.Map.t Lwt.t

recycle_operations returns the new pending operations when a reorganisation or a head update occurs. Returned operations come from:

1. operations in from_branch that are NOT in to_branch, 2. operations in the relevant classes of classification 3. operations the pending map

This function guarantees that the branch of all returned operations is in live_blocks (live_blocks acts as a filter).

Operation which where included in from_branch and which are NOT in to_branch need to be parsed again using the parse argument. If the parsing fails those operations are just dropped. This may happen if those operations comes from another protocol.

See also Internal_for_tests.handle_live_operations.