(*****************************************************************************) (* *) (* Open Source License *) (* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) (* Copyright (c) 2018-2021 Nomadic Labs, *) (* *) (* 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. *) (* *) (*****************************************************************************) (** Tezos Shell - Prevalidation of pending operations (a.k.a Mempool) *) (** The prevalidator is in charge of the [mempool] (a.k.a. the set of known not-invalid-for-sure operations that are not yet included in the blockchain). The prevalidator also maintains a sorted subset of the mempool that might correspond to a valid block on top of the current head. The "in-progress" context produced by the application of those operations is called the (pre)validation context. Before including an operation into the mempool, the prevalidation worker tries to append (in application mode)/evaluate (precheck mode) the operation to/in the prevalidation context. Only an operation that passes the application/precheck will be broadcast. If the operation is ill-formed, it will not be added into the mempool and then it will be ignored by the node and will never be broadcast. If the operation is only [branch_refused] or [branch_delayed], it may be added to the mempool if it passes the application/precheck in the future. See the {{!page-prevalidator} prevalidator implementation overview} to learn more. *) (** An (abstract) prevalidator context. Separate prevalidator contexts should be used for separate chains (e.g., mainchain vs testchain). *) type t (** This record contains the differents limits and settings that can be updated from a node configuration for a prevalidator *) type limits = { max_refused_operations : int; (** The maximum number of operations tracked by the mempool for each of the [refused], [branch delayed], [branch refused] and [outdated] operation classifications. Default is [1000] *) operation_timeout : Time.System.Span.t; (** The maximum time allowed to fetch the contents of an operation advertised by a remote peer. Default is [10] seconds *) operations_batch_size : int; (** Maximum number of pending operations processed (or classified) at the end of each request to the prevalidator worker. Default is [50] *) disable_precheck : bool; (** If [disable_precheck] is [true] (default is [false]) operations are executed by the protocol before being propagated. This flag is intended to be used for testing and debugging. *) } (** Sane default values for {!limits} *) val default_limits : limits (** Creates/tear-down a new prevalidator context. *) val create : limits -> (module Prevalidator_filters.FILTER) -> Distributed_db.chain_db -> t tzresult Lwt.t val shutdown : t -> unit Lwt.t (** Notify the prevalidator that the identified peer has sent a bunch of operations relevant to the specified context. *) val notify_operations : t -> P2p_peer.Id.t -> Mempool.t -> unit Lwt.t (** [inject_operation t ~force op] notifies the prevalidator worker of a new injected operation. If [force] is set to [true] the operation is injected without any check. [force] should be used for test purpose only. *) val inject_operation : t -> force:bool -> Operation.t -> unit tzresult Lwt.t (** Notify the prevalidator that a new head has been selected. [update] is used as an optimisation to know which operations previously classified require to be prevalidated again. *) val flush : t -> Chain_validator_worker_state.Event.update -> Block_hash.t -> Block_hash.Set.t -> Operation_hash.Set.t -> unit tzresult Lwt.t (** Returns the list of prevalidation contexts running and their associated chain *) val running_workers : unit -> (Chain_id.t * Protocol_hash.t * t) list (** Worker status and events *) (* None indicates the there are no workers for the current protocol. *) val status : t -> Worker_types.worker_status val pending_requests : t -> (Time.System.t * Prevalidator_worker_state.Request.view) list val current_request : t -> (Time.System.t * Time.System.t * Prevalidator_worker_state.Request.view) option val information : t -> Worker_types.worker_information val pipeline_length : t -> int val rpc_directory : t option RPC_directory.t (**/**) module Internal_for_tests : sig (** Documented in {!Prevalidator}, because this is only exported for tests. *) type 'prevalidation_t tools = { advertise_current_head : mempool:Mempool.t -> Store.Block.t -> unit; chain_tools : Store.Block.t Prevalidator_classification.chain_tools; create : predecessor:Store.Block.t -> live_operations:Operation_hash.Set.t -> timestamp:Time.Protocol.t -> unit -> 'prevalidation_t tzresult Lwt.t; fetch : ?peer:P2p_peer.Id.t -> ?timeout:Time.System.Span.t -> Operation_hash.t -> Operation.t tzresult Lwt.t; read_block : Block_hash.t -> Store.Block.t tzresult Lwt.t; send_get_current_head : ?peer:P2p_peer_id.t -> unit -> unit; set_mempool : head:Block_hash.t -> Mempool.t -> unit tzresult Lwt.t; } (** Documented in {!Prevalidator}, because this is only exported for tests. *) type worker_tools = { push_request : (unit, Empty.t) Prevalidator_worker_state.Request.t -> bool Lwt.t; push_request_now : (unit, Empty.t) Prevalidator_worker_state.Request.t -> unit; } (** The corresponding internal type of the mempool (see {!Prevalidator.S}), that is independent from the protocol. *) type ('a, 'b) types_state_shell (** Create a pristine value of {!type_state_shell} *) val mk_types_state_shell : predecessor:Store.Block.t -> tools:'prevalidation_t tools -> worker:worker_tools -> ('protocol_data, 'prevalidation_t) types_state_shell module Make (Filter : Prevalidator_filters.FILTER) (Prevalidation_t : Prevalidation.T with type validation_state = Filter.Proto.validation_state and type protocol_operation = Filter.Proto.operation and type operation_receipt = Filter.Proto.operation_receipt) : sig (** The corresponding internal type of the mempool (see {!Prevalidator.S}), that depends on the protocol *) type types_state (** Create a pristine value of {!type_state} *) val mk_types_state : shell: ( Prevalidation_t.protocol_operation, Prevalidation_t.t ) types_state_shell -> validation_state:Prevalidation_t.t -> types_state Lwt.t (** [to_shell pv] returns the shell part of [pv] *) val to_shell : types_state -> (Prevalidation_t.protocol_operation, Prevalidation_t.t) types_state_shell (** Documented in {!Prevalidator.S} *) val handle_unprocessed : types_state -> unit Lwt.t (** Documented in {!Prevalidator.S} (as are all the functions of this module) *) module Requests : sig val on_advertise : _ types_state_shell -> unit val on_arrived : types_state -> Operation_hash.t -> Operation.t -> (unit, Empty.t) result Lwt.t val on_ban : types_state -> Operation_hash.t -> unit tzresult Lwt.t val on_flush : handle_branch_refused:bool -> types_state -> Store.Block.t -> Block_hash.Set.t -> Operation_hash.Set.t -> unit tzresult Lwt.t val on_inject : types_state -> force:bool -> Operation.t -> unit tzresult Lwt.t val on_notify : _ types_state_shell -> P2p_peer_id.t -> Mempool.t -> unit Lwt.t end end end