package tezos-shell

  1. Overview
  2. Docs

A P2p_reader.t is a worker that answers the application messages (see Messages) received from a remote peer on a P2p.connection.

The worker behavior is parameterized by callback functions passed by the caller (see type callback).

Terminology:

  • *this peer* refers to the peer running the worker
  • the *remote peer* refers to the peer on the other side of the connection
  • a chain can be *active* or *inactive*. The activation status can refer to this peer, or to the remote peer. If not specified, active/inactive refers to this peer.

A chain can only be considered active for the remote peer if it is active for this peer. As a general rule, received messages that refer to a specific chain_id that is not active are ignored.

The protocol is defined as a message handling loop. We can classify a message in three categories. For each category, we describe the worker behavior when receiving the messages.

1. Administrative message

  • Deactivate chain_id marks chain chain_id as inactive for the remote peer. Call callback.disconnection gid where gid is the remote peer id.

2. Chain-related messages

These messages are used for peers to get the most recent view of the chains they manage.

  • Get_current_branch chain_id If chain_id is not active for this peer, simply ignores message and returns.

Only if chain_id is not active for the remote peer, sends a Get_current_branch chain_id message.

Then (in any case) sends a Current_branch (chain_id, chain_locator) message.

  • Current_branch (chain_id, locator) activates chain_id for the remote peer if it is not active yet. If the locator contains any block known to be invalid, the connection is closed and the remote peer is greylisted. If the locator head timestamp is more than 15s ahead of this peer system time, the message is ignored. Otherwise calls callback.notify_branch locator.
  • Get_protocol_branch chain_id proto_level If chain_id is not active for this peer, or if proto_level is unknown simply ignores message and returns. A proto_level is unknown if it is non-positive or if it is strictly higher than the one of the current head.

Otherwise, sends a message Protocol_branch (chain_id, protocol_locator) where protocol_locator encodes the longest branch where all the blocks are on proto_level. This branch is a subbranch of the current branch for the requested chain_id.

  • Protocol_branch chain_id proto_level locator is a no-op
  • Get_current_head chain_id: message is ignored if the chain chain_id is inactive for the remote peer. Otherwise, replies with Current_head (chain_id, head, mempool) where head is the current head for the requested chain. mempool is the current mempool, or an empty mempool if the remote peer's mempool is disabled.
  • Current_head (chain_id, header, mempool): message is ignored if the chain chain_id is inactive for the remote peer. If header is known to be invalid, or if the mempool is non empty while this peer's mempool is disabled, the connection is closed and the remote peer is greylisted. If header's timestamp is more than 15s ahead of this peer system time, the message is ignored. Otherwise, calls callback.notify_head.
  • Get_checkpoint chain_id: message is ignored if the chain chain_id is inactive for the remote peer. Otherwise, replies with Checkpoint (chain_id, checkpoint) where checkpoint is the current checkpoint for the requested chain.
  • Checkpoint chain_id header is a no-op

3. "Database" messages

These messages are used for peers to exchange "static" resources such as block headers, operations, protocols. The worker collaborates with the requesters defined in Distributed_db. Resources are requested by the requester, and the requester is notified by a P2p_reader upon reception of the resource.

  • Get_block_headers hashes Sends a Blocker_header header for each of the requested hash known to this peer.
  • Block_header block notifies the requester that the value has been received. Ignores message if value wasn't requested.
  • Get_predecessor_header hash n Sends Predecessor_header hash n header where header is the header of the nth predecessor of the block hash.
  • Predecessor_header hash n header is a no-op.

The other database messages work similarly

  • Get_operations hashes/Operation operation
  • Get_protocols hashes/Protocol
  • Get_operation_hashes_for_blocks/Operation_hashes_for_block
  • Get_operations_for_blocks/Operation_for_block
type t
module Message = Distributed_db_message

A Mutable structure akin to a hash-table, but with a size bound. Note that, different caches have different policies towards the size bounds: some uphold the bound strictly, some treat the bound as a suggestion. In addition, some caches count their elements somewhat sloppily.

type callback = {
  1. notify_branch : Tezos_base.P2p_peer.Id.t -> Tezos_base.Block_locator.t -> unit;
    (*

    callback function called on reception of a Current_branch message

    *)
  2. notify_head : Tezos_base.P2p_peer.Id.t -> Tezos_crypto.Block_hash.t -> Tezos_base.Block_header.t -> Tezos_base.Mempool.t -> unit;
    (*

    callback function called on reception of a Current_head message

    *)
  3. disconnection : Tezos_base.P2p_peer.Id.t -> unit;
}
type chain_db = {
  1. chain_store : Tezos_store.Store.Chain.t;
  2. operation_db : Distributed_db_requester.Raw_operation.t;
  3. block_header_db : Distributed_db_requester.Raw_block_header.t;
  4. operations_db : Distributed_db_requester.Raw_operations.t;
  5. callback : callback;
  6. active_peers : Tezos_base.P2p_peer.Set.t ref;
    (*

    Set of remote peers for which this chain is active.

    *)
  7. active_connections : connection Tezos_base.P2p_peer.Table.t;
}

Lookup for block header in any active chains

val run : register:(t -> unit) -> unregister:(unit -> unit) -> p2p -> Tezos_store.Store.t -> Distributed_db_requester.Raw_protocol.t -> chain_db Tezos_crypto.Chain_id.Table.t -> Tezos_base.P2p_peer.Id.t -> connection -> unit

run ~register ~unregister p2p state protocol_db active_chains peer_id conn runs an answering worker on a p2p connection connection. peer_id is the peer id of the remote peer. register is called once the worker is created, and unregister when the worker stops.

active_chains is the table of active chains (i.e. test chain, main chain...)

val shutdown : t -> unit Lwt.t