Commit eb1d90ae authored by Philippe B.'s avatar Philippe B. 🏂 Committed by Romain

P2p: centralize config datatypes in one module

The p2p layer is parametrized by several "generic" datatypes.

These datatypes appear as polymorphic parameters in P2p functions.
They aren't simply placeholders in the sense that the p2p layer
can "operate" on them using functions passed as records in `P2p.create`.

For instance,

```
type 'peer_meta peer_meta_config = {
  peer_meta_encoding : 'peer_meta Data_encoding.t;
  peer_meta_initial : unit -> 'peer_meta;
  score : 'peer_meta -> float;
}
```

defines a `'peer_meta` ADT. The P2p operate on it using the function
provided in a record `peer_meta_config`, passed by the upper layer.

Before this commit, these types where duplicated in several places.
They were initially defined in the module that primarly use them, and
then re-exported in `P2p`.

This commit centralizes their definition and documentation in a
"leaf module" `P2p_params`, reducing redundancy.
parent 3df09470
......@@ -28,35 +28,6 @@ include Internal_event.Legacy_logging.Make (struct
let name = "p2p"
end)
type 'peer_meta peer_meta_config = 'peer_meta P2p_pool.peer_meta_config = {
peer_meta_encoding : 'peer_meta Data_encoding.t;
peer_meta_initial : unit -> 'peer_meta;
score : 'peer_meta -> float;
}
type 'conn_meta conn_meta_config = 'conn_meta P2p_socket.metadata_config = {
conn_meta_encoding : 'conn_meta Data_encoding.t;
conn_meta_value : P2p_peer.Id.t -> 'conn_meta;
private_node : 'conn_meta -> bool;
}
type 'msg app_message_encoding = 'msg P2p_message.encoding =
| Encoding : {
tag : int;
title : string;
encoding : 'a Data_encoding.t;
wrap : 'a -> 'msg;
unwrap : 'msg -> 'a option;
max_length : int option;
}
-> 'msg app_message_encoding
type 'msg message_config = 'msg P2p_connect_handler.message_config = {
encoding : 'msg app_message_encoding list;
chain_name : Distributed_db_version.Name.t;
distributed_db_versions : Distributed_db_version.t list;
}
type config = {
listening_port : P2p_addr.port option;
listening_addr : P2p_addr.t option;
......@@ -602,7 +573,8 @@ let activate t =
log_info "activate P2P layer !" ;
t.activate ()
let faked_network (msg_cfg : 'msg message_config) peer_cfg faked_metadata =
let faked_network (msg_cfg : 'msg P2p_params.message_config) peer_cfg
faked_metadata =
let announced_version =
Network_version.announced
~chain_name:msg_cfg.chain_name
......@@ -624,7 +596,7 @@ let faked_network (msg_cfg : 'msg message_config) peer_cfg faked_metadata =
connection_remote_metadata = (fun _ -> faked_metadata);
connection_stat = (fun _ -> Fake.empty_stat);
global_stat = (fun () -> Fake.empty_stat);
get_peer_metadata = (fun _ -> peer_cfg.peer_meta_initial ());
get_peer_metadata = (fun _ -> peer_cfg.P2p_params.peer_meta_initial ());
set_peer_metadata = (fun _ _ -> ());
recv = (fun _ -> Lwt_utils.never_ending ());
recv_any = (fun () -> Lwt_utils.never_ending ());
......
......@@ -62,39 +62,15 @@
Addresses or peers can be *greylisted*. As for banning, greylisting
can be enforced via the API, but also dynamically when the peer isn't
able to authenticate. Eventually greylisted peers are whitelisted again. *)
(** Most types of the P2p layer are parameterized by three types ['peer_meta],
['conn_meta], [`msg]. The concrete types, and function operating on them,
are defined by the calling layer. *)
(** Metadata for a peer. Typically contains information used to compute the
score of a peer. This is used to classify peers when choosing "good"
neighbors. *)
type 'peer_meta peer_meta_config = {
peer_meta_encoding : 'peer_meta Data_encoding.t;
(** Encoding of the peer meta data. *)
peer_meta_initial : unit -> 'peer_meta;
(** Initial value for this peer meta-data *)
score : 'peer_meta -> float; (** Score of a peer. *)
}
able to authenticate. Eventually greylisted peers are whitelisted again.
(* Metadata for a connection. *)
type 'conn_meta conn_meta_config = {
conn_meta_encoding : 'conn_meta Data_encoding.t;
conn_meta_value : P2p_peer.Id.t -> 'conn_meta;
private_node : 'conn_meta -> bool;
}
Many types used in the P2p layer are parameterized by three type parameters:
- ['msg]: type of messages exchanged between peers
- ['peer_meta]: type of the metadata associated with peers (score, etc.)
- ['conn_meta]: type of the metadata associated with connections
(* Configuration for the application protocol. ['msg] represents
the type of the application level protocol *)
type 'msg message_config = {
encoding : 'msg P2p_message.encoding list; (** Encoding of the messages. *)
chain_name : Distributed_db_version.Name.t;
(** Identifier for this P2p protocol when establishing session. *)
distributed_db_versions : Distributed_db_version.t list;
(** List of versions supported by this P2p protocol. *)
}
The concrete types, and functions operating on them, are defined by the
calling layer, and passed to [P2p.create]. See module [P2p_params]. *)
(** Network configuration *)
type config = {
......@@ -180,11 +156,7 @@ type limits = {
peers. Default value is 64 kB. Max value is 64kB. *)
}
(** Type of a P2P layer instance, parametrized by:
['msg]: type of messages exchanged between peers
['peer_meta]: type of the metadata associated with peers (score, etc.)
['conn_meta]: type of the metadata associated with connection (ack_cfg)
*)
(** Type of a P2P layer instance *)
type ('msg, 'peer_meta, 'conn_meta) t
type ('msg, 'peer_meta, 'conn_meta) net = ('msg, 'peer_meta, 'conn_meta) t
......@@ -202,8 +174,8 @@ val connect_handler :
(** A faked p2p layer, which do not initiate any connection
nor open any listening socket *)
val faked_network :
'msg message_config ->
'peer_meta peer_meta_config ->
'msg P2p_params.message_config ->
'peer_meta P2p_params.peer_meta_config ->
'conn_meta ->
('msg, 'peer_meta, 'conn_meta) net
......@@ -211,9 +183,9 @@ val faked_network :
val create :
config:config ->
limits:limits ->
'peer_meta peer_meta_config ->
'conn_meta conn_meta_config ->
'msg message_config ->
'peer_meta P2p_params.peer_meta_config ->
'conn_meta P2p_params.conn_meta_config ->
'msg P2p_params.message_config ->
('msg, 'peer_meta, 'conn_meta) net tzresult Lwt.t
val activate : ('msg, 'peer_meta, 'conn_meta) net -> unit
......
......@@ -27,12 +27,6 @@ include Internal_event.Legacy_logging.Make (struct
let name = "p2p.connect_handler"
end)
type 'msg message_config = {
encoding : 'msg P2p_message.encoding list;
chain_name : Distributed_db_version.Name.t;
distributed_db_versions : Distributed_db_version.t list;
}
type config = {
incoming_app_message_queue_size : int option;
private_mode : bool;
......@@ -57,8 +51,8 @@ type ('msg, 'peer_meta, 'conn_meta) t = {
triggers : P2p_trigger.t;
io_sched : P2p_io_scheduler.t;
announced_version : Network_version.t;
conn_meta_config : 'conn_meta P2p_socket.metadata_config;
message_config : 'msg message_config;
conn_meta_config : 'conn_meta P2p_params.conn_meta_config;
message_config : 'msg P2p_params.message_config;
custom_p2p_versions : P2p_version.t list;
encoding : 'msg P2p_message.t Data_encoding.t;
incoming : Lwt_canceler.t P2p_point.Table.t;
......@@ -75,13 +69,14 @@ let create ?(p2p_versions = P2p_version.supported) config pool message_config
message_config;
announced_version =
Network_version.announced
~chain_name:message_config.chain_name
~distributed_db_versions:message_config.distributed_db_versions
~chain_name:message_config.P2p_params.chain_name
~distributed_db_versions:
message_config.P2p_params.distributed_db_versions
~p2p_versions;
custom_p2p_versions = p2p_versions;
incoming = P2p_point.Table.create 53;
io_sched;
encoding = P2p_message.encoding message_config.encoding;
encoding = P2p_message.encoding message_config.P2p_params.encoding;
triggers;
new_connection_hook = [];
log;
......
......@@ -80,12 +80,6 @@ type config = {
(** The proof of work target we require from peers. *)
}
type 'msg message_config = {
encoding : 'msg P2p_message.encoding list;
chain_name : Distributed_db_version.Name.t;
distributed_db_versions : Distributed_db_version.t list;
}
(** [create ?p2p_version config pool message_config socket_meta_config
scheduler triggers log answerer] returns a connection handler.
......@@ -98,8 +92,8 @@ val create :
?p2p_versions:P2p_version.t list ->
config ->
('msg, 'peer, 'conn) P2p_pool.t ->
'msg message_config ->
'conn P2p_socket.metadata_config ->
'msg P2p_params.message_config ->
'conn P2p_params.conn_meta_config ->
P2p_io_scheduler.t ->
P2p_trigger.t ->
log:(P2p_connection.P2p_event.t -> unit) ->
......
......@@ -24,17 +24,6 @@
(* *)
(*****************************************************************************)
type 'msg encoding =
| Encoding : {
tag : int;
title : string;
encoding : 'a Data_encoding.t;
wrap : 'a -> 'msg;
unwrap : 'msg -> 'a option;
max_length : int option;
}
-> 'msg encoding
type 'msg t =
| Bootstrap
| Advertise of P2p_point.Id.t list
......@@ -95,7 +84,7 @@ let encoding msg_encoding =
None)
(fun (point, peer_id, ()) -> Swap_ack (point, peer_id)) ]
@ ListLabels.map msg_encoding ~f:(function
| Encoding
| P2p_params.Encoding
{tag; title; encoding; wrap; unwrap; max_length = _ (* ?? *)}
->
Data_encoding.case
......
......@@ -45,17 +45,6 @@
mechanism on an actual network. Is it the added complexity
worth it, wouldn't it be enough to rely on [Advertise]? *)
type 'msg encoding =
| Encoding : {
tag : int;
title : string;
encoding : 'a Data_encoding.t;
wrap : 'a -> 'msg;
unwrap : 'msg -> 'a option;
max_length : int option;
}
-> 'msg encoding
type 'msg t =
| Bootstrap (** Welcome message sent by a peer upon connection *)
| Advertise of P2p_point.Id.t list
......@@ -67,4 +56,4 @@ type 'msg t =
| Message of 'msg (** Generic upper-layer message *)
| Disconnect (** Ending of connection *)
val encoding : 'a encoding list -> 'a t Data_encoding.t
val encoding : 'a P2p_params.app_message_encoding list -> 'a t Data_encoding.t
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <[email protected]> *)
(* Copyright (c) 2019 Nomadic Labs, <[email protected]> *)
(* *)
(* 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. *)
(* *)
(*****************************************************************************)
(** Types of the abstract data types (ADT) which parameterize the P2p layer.
Many types used in the P2p layer are parameterized by three type parameters:
- ['msg]: type of messages exchanged between peers
- ['peer_meta]: type of the metadata associated with peers (score, etc.)
- ['conn_meta]: type of the metadata associated with connections
These types are kept abstract from the P2p layer. It can only operate on
them via a set of functions packed in a "configuration" record
passed by the upper layer (see also [P2p] and [P2p.create]).
This module defines the type of these configuration records. *)
(** Metadata for a peer *)
type 'peer_meta peer_meta_config = {
peer_meta_encoding : 'peer_meta Data_encoding.t;
peer_meta_initial : unit -> 'peer_meta; (** Constructor *)
score : 'peer_meta -> float; (** Score of a peer, used for ordering *)
}
(** Metadata for a connection. *)
type 'conn_meta conn_meta_config = {
conn_meta_encoding : 'conn_meta Data_encoding.t;
conn_meta_value : P2p_peer.Id.t -> 'conn_meta; (** Constructor *)
private_node : 'conn_meta -> bool;
(** Returns true if peer at the other end of the connection is in private
mode *)
}
type 'msg app_message_encoding =
| Encoding : {
tag : int;
title : string;
encoding : 'a Data_encoding.t;
wrap : 'a -> 'msg;
unwrap : 'msg -> 'a option;
max_length : int option;
}
-> 'msg app_message_encoding
(** Application-level messages encoding, and version parameters *)
type 'msg message_config = {
encoding : 'msg app_message_encoding list; (** Encoding of the messages. *)
chain_name : Distributed_db_version.Name.t;
(** Identifier for this P2p protocol when establishing session. *)
distributed_db_versions : Distributed_db_version.t list;
(* TODO these last two fields aren't logically related to the `msg type,
they should be moved somewhere else *)
(** List of versions supported by this P2p protocol. *)
}
......@@ -45,15 +45,9 @@ type config = {
max_known_peer_ids : (int * int) option;
}
type 'peer peer_meta_config = {
peer_meta_encoding : 'peer Data_encoding.t;
peer_meta_initial : unit -> 'peer;
score : 'peer -> float;
}
type ('msg, 'peer, 'conn) t = {
config : config;
peer_meta_config : 'peer peer_meta_config;
peer_meta_config : 'peer P2p_params.peer_meta_config;
(* Set of points corresponding to this peer *)
my_id_points : unit P2p_point.Table.t;
known_peer_ids :
......
......@@ -65,15 +65,9 @@ type config = {
(** Like [max_known_points], but for known peer_ids. *)
}
type 'peer peer_meta_config = {
peer_meta_encoding : 'peer Data_encoding.t;
peer_meta_initial : unit -> 'peer;
score : 'peer -> float;
}
val create :
config ->
'peer peer_meta_config ->
'peer P2p_params.peer_meta_config ->
P2p_trigger.t ->
log:(P2p_connection.P2p_event.t -> unit) ->
('msg, 'peer, 'conn) t Lwt.t
......
......@@ -185,16 +185,12 @@ module Connection_message = struct
else return (message, buf)
end
type 'meta metadata_config = {
conn_meta_encoding : 'meta Data_encoding.t;
conn_meta_value : P2p_peer.Id.t -> 'meta;
private_node : 'meta -> bool;
}
module Metadata = struct
let write ~canceler metadata_config cryptobox_data fd message =
let encoded_message_len =
Data_encoding.Binary.length metadata_config.conn_meta_encoding message
Data_encoding.Binary.length
metadata_config.P2p_params.conn_meta_encoding
message
in
let buf = Bytes.create encoded_message_len in
match
......@@ -215,7 +211,7 @@ module Metadata = struct
Crypto.read_chunk ~canceler fd cryptobox_data
>>=? fun buf ->
let length = Bytes.length buf in
let encoding = metadata_config.conn_meta_encoding in
let encoding = metadata_config.P2p_params.conn_meta_encoding in
match Data_encoding.Binary.read encoding buf 0 length with
| None ->
fail P2p_errors.Decoding_error
......@@ -328,7 +324,9 @@ let authenticate ~canceler ~proof_of_work_target ~incoming fd
Crypto_box.generate_nonces ~incoming ~sent_msg ~recv_msg
in
let cryptobox_data = {Crypto.channel_key; local_nonce; remote_nonce} in
let local_metadata = metadata_config.conn_meta_value remote_peer_id in
let local_metadata =
metadata_config.P2p_params.conn_meta_value remote_peer_id
in
Metadata.write ~canceler metadata_config fd cryptobox_data local_metadata
>>=? fun () ->
Metadata.read ~canceler metadata_config fd cryptobox_data
......
......@@ -44,22 +44,6 @@
(** {1 Types} *)
(** This defines an abstract data type ['meta]. Mainly a placeholder to be
used by the calling layer. ['meta] objects are communicated at session
initiation and both ends ['meta'] are known once session is set up. ['meta]
object should at least contain the private status of the node. *)
(* TODO:
- this type is duplicated at several places. Define it once for all in a
separate module (with [msg_config] and [peer_config]).
- the parameter [P2p_peer.Id.t] provides more control when constructing a
['meta] but may not be useful. *)
type 'meta metadata_config = {
conn_meta_encoding : 'meta Data_encoding.t;
conn_meta_value : P2p_peer.Id.t -> 'meta;
private_node : 'meta -> bool;
}
(** Type of a connection that successfully passed the authentication
phase, but has not been accepted yet. Parametrized by the type
of expected parameter in the `ack` message. *)
......@@ -130,7 +114,7 @@ val authenticate :
?listening_port:int ->
P2p_identity.t ->
Network_version.t ->
'meta metadata_config ->
'meta P2p_params.conn_meta_config ->
('meta P2p_connection.Info.t * 'meta authenticated_connection) tzresult Lwt.t
(** [kick ac] sends a [Nack] message to the remote peer, notifying it
......
......@@ -30,10 +30,10 @@ end)
type message = Ping
let msg_config : message P2p_connect_handler.message_config =
let msg_config : message P2p_params.message_config =
{
encoding =
[ P2p_message.Encoding
[ P2p_params.Encoding
{
tag = 0x10;
title = "Ping";
......@@ -48,14 +48,14 @@ let msg_config : message P2p_connect_handler.message_config =
type metadata = unit
let peer_meta_config : metadata P2p_pool.peer_meta_config =
let peer_meta_config : metadata P2p_params.peer_meta_config =
{
peer_meta_encoding = Data_encoding.empty;
peer_meta_initial = (fun _ -> ());
score = (fun () -> 0.);
}
let conn_meta_config : metadata P2p_socket.metadata_config =
let conn_meta_config : metadata P2p_params.conn_meta_config =
{
conn_meta_encoding = Data_encoding.empty;
conn_meta_value = (fun _ -> ());
......
......@@ -52,7 +52,7 @@ let version =
type metadata = unit
let conn_meta_config : metadata P2p_socket.metadata_config =
let conn_meta_config : metadata P2p_params.conn_meta_config =
{
conn_meta_encoding = Data_encoding.empty;
conn_meta_value = (fun _ -> ());
......
......@@ -172,7 +172,7 @@ type t =
let encoding =
let open Data_encoding in
let case ?max_length ~tag ~title encoding unwrap wrap =
P2p_message.Encoding {tag; title; encoding; wrap; unwrap; max_length}
P2p_params.Encoding {tag; title; encoding; wrap; unwrap; max_length}
in
[ case
~tag:0x10
......@@ -318,7 +318,7 @@ let encoding =
let distributed_db_versions = [Distributed_db_version.zero]
let cfg chain_name : _ P2p.message_config =
let cfg chain_name : _ P2p_params.message_config =
{encoding; chain_name; distributed_db_versions}
let raw_encoding = P2p_message.encoding encoding
......
......@@ -47,11 +47,11 @@ type t =
| Operations_for_block of
Block_hash.t * int * Operation.t list * Operation_list_list_hash.path
val encoding : t P2p_message.encoding list
val encoding : t P2p_params.app_message_encoding list
val distributed_db_versions : Distributed_db_version.t list
val cfg : Distributed_db_version.Name.t -> t P2p.message_config
val cfg : Distributed_db_version.Name.t -> t P2p_params.message_config
val pp_json : Format.formatter -> t -> unit
......
......@@ -97,14 +97,14 @@ type t = {
shutdown : unit -> unit Lwt.t;
}
let peer_metadata_cfg : _ P2p.peer_meta_config =
let peer_metadata_cfg : _ P2p_params.peer_meta_config =
{
peer_meta_encoding = Peer_metadata.encoding;
peer_meta_initial = Peer_metadata.empty;
score = Peer_metadata.score;
}
let connection_metadata_cfg cfg : _ P2p.conn_meta_config =
let connection_metadata_cfg cfg : _ P2p_params.conn_meta_config =
{
conn_meta_encoding = Connection_metadata.encoding;
private_node = (fun {private_node; _} -> private_node);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment