Commit 65593eb3 authored by Grégoire Henry's avatar Grégoire Henry Committed by Julien

P2p: change version selection

This patch is not compatible with current mainnet `nedes`, but three
other patches provides a three-stage migration plan.

Instead of sending a list of triplet `(name, major, miner)`, we now
only announce only one triplet `(chain_name, distributed_db_version,
p2p_version)`.

The `chain_name` must be the exact same on each host.

The two others `*_version` are negotiated independently with the
following algorithm:
- announce the greater known version;
- choose the minimal number between the announced one and the received
  one;
- accept the connection only the chosen version is known locally.

This algorithm is fairly complete unless we introduce "hole" in the
sequence of acceptable version numbers.
parent 32a1d264
......@@ -2,6 +2,7 @@
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* Copyright (c) 2019 Nomadic Labs, <contact@nomadic-labs.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
......@@ -74,10 +75,11 @@ let sandbox () =
let check_network ctxt =
Shell_services.P2p.versions ctxt >>= function
| Error _ ->
| Error _
| Ok [] ->
Lwt.return_none
| Ok versions ->
match String.split_on_char '_' (P2p_version.best versions).name with
| Ok (version :: _) ->
match String.split_on_char '_' (version.chain_name :> string) with
| "SANDBOXED" :: _ ->
sandbox () ;
Lwt.return_some `Sandbox
......@@ -87,7 +89,8 @@ let check_network ctxt =
| "TEZOS" :: "ALPHANET" :: _date :: [] ->
alphanet () ;
Lwt.return_some `Alphanet
| "TEZOS" :: "BETANET" :: _date :: [] ->
| "TEZOS" :: "BETANET" :: _ :: []
| "TEZOS" :: "MAINNET" :: [] ->
mainnet () ;
Lwt.return_some `Mainnet
| _ ->
......
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* Copyright (c) 2019 Nomadic Labs, <contact@nomadic-labs.com> *)
(* *)
(* 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. *)
(* *)
(*****************************************************************************)
(** Distributed_db protocol version. *)
type name = string
let pp_name = Format.pp_print_string
let name_encoding = Data_encoding.string
let chain_name = "TEZOS"
let sandboxed_chain_name = "SANDBOXED_TEZOS"
type t = int
let pp = Format.pp_print_int
let encoding = Data_encoding.uint16
let zero = 0
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* Copyright (c) 2019 Nomadic Labs, <contact@nomadic-labs.com> *)
(* *)
(* 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. *)
(* *)
(*****************************************************************************)
(** Distributed_db protocol version. *)
type name = private string
val pp_name: Format.formatter -> name -> unit
val name_encoding: name Data_encoding.t
val chain_name: name
val sandboxed_chain_name: name
(** An abstract version number for the high-level distributed_db messages. *)
type t = private int
val pp: Format.formatter -> t -> unit
val encoding: t Data_encoding.t
val zero: t
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* Copyright (c) 2019 Nomadic Labs, <contact@nomadic-labs.com> *)
(* *)
(* 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. *)
(* *)
(*****************************************************************************)
type t = {
chain_name : Distributed_db_version.name ;
distributed_db_version : Distributed_db_version.t ;
p2p_version : P2p_version.t ;
}
let pp ppf { chain_name ; distributed_db_version ; p2p_version } =
Format.fprintf ppf
"%a.%a (p2p: %a)"
Distributed_db_version.pp_name chain_name
Distributed_db_version.pp distributed_db_version
P2p_version.pp p2p_version
let encoding =
let open Data_encoding in
conv
(fun { chain_name ; distributed_db_version ; p2p_version } ->
(chain_name, distributed_db_version, p2p_version))
(fun (chain_name, distributed_db_version, p2p_version) ->
{ chain_name ; distributed_db_version ; p2p_version })
(obj3
(req "chain_name" Distributed_db_version.name_encoding)
(req "distributed_db_version" Distributed_db_version.encoding)
(req "p2p_version" P2p_version.encoding))
let greatest = function
| [] -> raise (Invalid_argument "greatest_int")
| h :: t -> List.fold_left max h t
let announced
~chain_name
~distributed_db_versions
~p2p_versions =
assert (distributed_db_versions <> []) ;
assert (p2p_versions <> []) ;
{ chain_name ;
distributed_db_version = greatest distributed_db_versions ;
p2p_version = greatest p2p_versions ;
}
let may_select_version accepted_versions remote_version =
let best_local_version = greatest accepted_versions in
if best_local_version <= remote_version then
Some best_local_version
else if List.mem remote_version accepted_versions then
Some remote_version
else
None
let select
~chain_name
~distributed_db_versions
~p2p_versions
remote =
assert (distributed_db_versions <> []) ;
assert (p2p_versions <> []) ;
if chain_name <> remote.chain_name then
None
else
let open Option in
may_select_version
distributed_db_versions
remote.distributed_db_version >>= fun distributed_db_version ->
may_select_version
p2p_versions
remote.p2p_version >>= fun p2p_version ->
some { chain_name ;
distributed_db_version ;
p2p_version }
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* Copyright (c) 2019 Nomadic Labs, <contact@nomadic-labs.com> *)
(* *)
(* 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. *)
(* *)
(*****************************************************************************)
type t = {
chain_name : Distributed_db_version.name ;
distributed_db_version : Distributed_db_version.t ;
p2p_version : P2p_version.t ;
}
val pp: Format.formatter -> t -> unit
val encoding: t Data_encoding.t
(** [announced supported] computes the network protocol version
announced on peer connection, given the [supported] versions for
the higher-level messages. *)
val announced:
chain_name: Distributed_db_version.name ->
distributed_db_versions: Distributed_db_version.t list ->
p2p_versions: P2p_version.t list ->
t
(** [select acceptables remote] computes network protocol version to
be used on a given connection where [remote] is version annouced
by the remote peer, and [acceptables] the locally accepted
versions for the higher-level messages. *)
val select:
chain_name: Distributed_db_version.name ->
distributed_db_versions: Distributed_db_version.t list ->
p2p_versions: P2p_version.t list ->
t -> t option
......@@ -75,7 +75,7 @@ module Info = struct
peer_id : P2p_peer_id.t ;
id_point : Id.t ;
remote_socket_port : P2p_addr.port ;
versions : P2p_version.t list ;
announced_version : Network_version.t ;
private_node : bool ;
local_metadata : 'meta ;
remote_metadata : 'meta ;
......@@ -85,36 +85,40 @@ module Info = struct
let open Data_encoding in
conv
(fun { incoming ; peer_id ; id_point ; remote_socket_port ;
versions ; private_node ; local_metadata ; remote_metadata } ->
announced_version ; private_node ;
local_metadata ; remote_metadata } ->
(incoming, peer_id, id_point, remote_socket_port,
versions, private_node, local_metadata, remote_metadata))
announced_version, private_node,
local_metadata, remote_metadata))
(fun (incoming, peer_id, id_point, remote_socket_port,
versions, private_node, local_metadata, remote_metadata) ->
announced_version, private_node,
local_metadata, remote_metadata) ->
{ incoming ; peer_id ; id_point ; remote_socket_port ;
versions ; private_node ; local_metadata ; remote_metadata })
announced_version ; private_node ;
local_metadata ; remote_metadata })
(obj8
(req "incoming" bool)
(req "peer_id" P2p_peer_id.encoding)
(req "id_point" Id.encoding)
(req "remote_socket_port" uint16)
(req "versions" (list P2p_version.encoding))
(req "announced_version" Network_version.encoding)
(req "private" bool)
(req "local_metadata" metadata_encoding)
(req "remote_metadata" metadata_encoding))
let pp pp_meta ppf
{ incoming ; id_point = (remote_addr, remote_port) ;
remote_socket_port ; peer_id ; versions ; private_node ;
remote_socket_port ; peer_id ; announced_version ;
private_node ;
local_metadata = _ ; remote_metadata } =
let version = List.hd versions in
let point = match remote_port with
| None -> remote_addr, remote_socket_port
| Some port -> remote_addr, port in
Format.fprintf ppf "%s %a %a (%a)%s%a"
Format.fprintf ppf "%s %a %a (%a) %s%a"
(if incoming then "↘" else "↗")
P2p_peer_id.pp peer_id
P2p_point.Id.pp point
P2p_version.pp version
Network_version.pp announced_version
(if private_node then " private" else "")
pp_meta remote_metadata
......
......@@ -53,7 +53,7 @@ module Info : sig
peer_id : P2p_peer_id.t;
id_point : Id.t;
remote_socket_port : P2p_addr.port;
versions : P2p_version.t list ;
announced_version : Network_version.t ;
private_node : bool ;
local_metadata : 'meta ;
remote_metadata : 'meta ;
......
......@@ -2,6 +2,7 @@
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* Copyright (c) 2019 Nomadic Labs, <contact@nomadic-labs.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
......@@ -23,38 +24,11 @@
(* *)
(*****************************************************************************)
type t = {
name : string ;
major : int ;
minor : int ;
}
type t = int
let pp ppf { name ; major ; minor } =
Format.fprintf ppf "%s.%d.%d" name major minor
let pp = Format.pp_print_int
let encoding = Data_encoding.uint16
let encoding =
let open Data_encoding in
conv
(fun { name; major; minor } -> (name, major, minor))
(fun (name, major, minor) -> { name; major; minor })
(obj3
(req "name" string)
(req "major" uint16)
(req "minor" uint16))
let zero = 0
let common la lb =
let la = List.sort (fun l r -> compare r l) la in
let lb = List.sort (fun l r -> compare r l) lb in
let rec find = function
| [], _ | _, [] -> None
| ((a :: ta) as la), ((b :: tb) as lb) ->
if a = b then Some a
else if a > b then find (ta, lb)
else find (la, tb)
in find (la, lb)
let best lv =
if lv = [] then
invalid_arg "P2p_version.best"
else
List.hd (List.sort (fun l r -> compare r l) lv)
let supported = [ zero ]
......@@ -2,6 +2,7 @@
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* Copyright (c) 2019 Nomadic Labs, <contact@nomadic-labs.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
......@@ -23,24 +24,14 @@
(* *)
(*****************************************************************************)
(** Network protocol version. *)
(** P2p-layer protocol version. *)
(** Type of a network protocol version. *)
type t = {
name : string ;
major : int ;
minor : int ;
}
(** An abstract version number for the low-level p2p layer. *)
type t = private int
val pp : Format.formatter -> t -> unit
val encoding : t Data_encoding.t
val pp: Format.formatter -> t -> unit
val encoding: t Data_encoding.t
(** Selects the prefered common version for a pair of version
lists. Used during network protocol negociation. If any, it is the
maximum one, in lexicographic order (name, then major, minor). *)
val common : t list -> t list -> t option
(** Gives the prefered version in a list: the one selected by
{!common} among the list of compatible ones. *)
val best : t list -> t
val supported: t list
val zero: t
......@@ -61,6 +61,9 @@ module P2p_connection = P2p_connection
module P2p_stat = P2p_stat
module P2p_version = P2p_version
module Distributed_db_version = Distributed_db_version
module Network_version = Network_version
module Lwt_exit = Lwt_exit
include Utils.Infix
......
......@@ -58,6 +58,9 @@ module P2p_connection = P2p_connection
module P2p_stat = P2p_stat
module P2p_version = P2p_version
module Distributed_db_version = Distributed_db_version
module Network_version = Network_version
module Lwt_exit = Lwt_exit
include (module type of (struct include Utils.Infix end))
......
......@@ -50,7 +50,8 @@ type 'msg app_message_encoding = 'msg P2p_pool.encoding =
type 'msg message_config = 'msg P2p_pool.message_config = {
encoding : 'msg app_message_encoding list ;
versions : P2p_version.t list;
chain_name : Distributed_db_version.name ;
distributed_db_versions : Distributed_db_version.t list ;
}
type config = {
......@@ -359,12 +360,12 @@ module Fake = struct
current_inflow = 0 ;
current_outflow = 0 ;
}
let connection_info faked_metadata = {
let connection_info announced_version faked_metadata = {
P2p_connection.Info.incoming = false ;
peer_id = id.peer_id ;
id_point = (Ipaddr.V6.unspecified, None) ;
remote_socket_port = 0 ;
versions = [] ;
announced_version ;
local_metadata = faked_metadata ;
remote_metadata = faked_metadata ;
private_node = false ;
......@@ -373,7 +374,7 @@ module Fake = struct
end
type ('msg, 'peer_meta, 'conn_meta) t = {
versions : P2p_version.t list ;
announced_version : Network_version.t ;
peer_id : P2p_peer.Id.t ;
maintain : unit -> unit Lwt.t ;
roll : unit -> unit Lwt.t ;
......@@ -456,7 +457,11 @@ let create ~config ~limits peer_cfg conn_cfg msg_cfg =
check_limits limits >>=? fun () ->
Real.create ~config ~limits peer_cfg conn_cfg msg_cfg >>=? fun net ->
return {
versions = msg_cfg.versions ;
announced_version =
Network_version.announced
~chain_name: msg_cfg.chain_name
~distributed_db_versions: msg_cfg.distributed_db_versions
~p2p_versions: P2p_version.supported ;
peer_id = Real.peer_id net ;
maintain = Real.maintain net ;
roll = Real.roll net ;
......@@ -487,33 +492,40 @@ let activate t =
log_info "activate P2P layer !";
t.activate ()
let faked_network peer_cfg faked_metadata = {
versions = [] ;
peer_id = Fake.id.peer_id ;
maintain = Lwt.return ;
roll = Lwt.return ;
shutdown = Lwt.return ;
connections = (fun () -> []) ;
find_connection = (fun _ -> None) ;
disconnect = (fun ?wait:_ _ -> Lwt.return_unit) ;
connection_info = (fun _ -> Fake.connection_info faked_metadata) ;
connection_local_metadata = (fun _ -> 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 ()) ;
set_peer_metadata = (fun _ _ -> ()) ;
recv = (fun _ -> Lwt_utils.never_ending ()) ;
recv_any = (fun () -> Lwt_utils.never_ending ()) ;
send = (fun _ _ -> fail P2p_errors.Connection_closed) ;
try_send = (fun _ _ -> false) ;
fold_connections = (fun ~init ~f:_ -> init) ;
iter_connections = (fun _f -> ()) ;
on_new_connection = (fun _f -> ()) ;
broadcast = ignore ;
pool = None ;
activate = (fun _ -> ()) ;
}
let faked_network (msg_cfg : 'msg message_config) peer_cfg faked_metadata =
let announced_version =
Network_version.announced
~chain_name: msg_cfg.chain_name
~distributed_db_versions: msg_cfg.distributed_db_versions
~p2p_versions: P2p_version.supported in
{
announced_version ;
peer_id = Fake.id.peer_id ;
maintain = Lwt.return ;
roll = Lwt.return ;
shutdown = Lwt.return ;
connections = (fun () -> []) ;
find_connection = (fun _ -> None) ;
disconnect = (fun ?wait:_ _ -> Lwt.return_unit) ;
connection_info =
(fun _ -> Fake.connection_info announced_version faked_metadata) ;
connection_local_metadata = (fun _ -> 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 ()) ;
set_peer_metadata = (fun _ _ -> ()) ;
recv = (fun _ -> Lwt_utils.never_ending ()) ;
recv_any = (fun () -> Lwt_utils.never_ending ()) ;
send = (fun _ _ -> fail P2p_errors.Connection_closed) ;
try_send = (fun _ _ -> false) ;
fold_connections = (fun ~init ~f:_ -> init) ;
iter_connections = (fun _f -> ()) ;
on_new_connection = (fun _f -> ()) ;
broadcast = ignore ;
pool = None ;
activate = (fun _ -> ()) ;
}
let peer_id net = net.peer_id
let maintain net = net.maintain ()
......@@ -616,7 +628,7 @@ let build_rpc_directory net =
let dir =
RPC_directory.register0 dir P2p_services.S.versions begin fun () () ->
return net.versions
return [net.announced_version]
end in
let dir =
......
......@@ -55,7 +55,8 @@ type 'msg app_message_encoding = Encoding : {
type 'msg message_config = {
encoding : 'msg app_message_encoding list ;
versions : P2p_version.t list;
chain_name : Distributed_db_version.name ;
distributed_db_versions : Distributed_db_version.t list ;
}
(** Network configuration *)
......@@ -179,6 +180,7 @@ type ('msg, 'peer_meta, 'conn_meta) net = ('msg, 'peer_meta, 'conn_meta) t
(** 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 ->
'conn_meta ->
('msg, 'peer_meta, 'conn_meta) net
......
......@@ -24,9 +24,9 @@
(* *)
(*****************************************************************************)
(* TODO Test cancelation of a (pending) connection *)
(* TODO Test cancellation of a (pending) connection *)
(* TODO do not recompute list_known_points at each requests... but
(* TODO do not recompute list_known_points at each requests... but
only once in a while, e.g. every minutes or when a point
or the associated peer_id is blacklisted. *)
......@@ -223,11 +223,14 @@ type 'peer_meta peer_meta_config = {
type 'msg message_config = {
encoding : 'msg encoding list ;
versions : P2p_version.t list;
chain_name : Distributed_db_version.name ;
distributed_db_versions : Distributed_db_version.t list ;
}
type ('msg, 'peer_meta, 'conn_meta) t = {
config : config ;
announced_version : Network_version.t ;
custom_p2p_versions : P2p_version.t list ;
peer_meta_config : 'peer_meta peer_meta_config ;
conn_meta_config : 'conn_meta P2p_socket.metadata_config ;
message_config : 'msg message_config ;
......@@ -253,7 +256,7 @@ type ('msg, 'peer_meta, 'conn_meta) t = {
mutable new_connection_hook :
(P2p_peer.Id.t -> ('msg, 'peer_meta, 'conn_meta) connection -> unit) list ;
mutable latest_accepted_swap : Time.t ;
mutable latest_succesfull_swap : Time.t ;
mutable latest_succesfull_swap : Time.t ;
}
and events = {
......@@ -272,6 +275,7 @@ and ('msg, 'peer_meta, 'conn_meta) connection = {
(('msg, 'peer_meta, 'conn_meta) connection, 'peer_meta, 'conn_meta) P2p_peer_state.Info.t ;
point_info :
('msg, 'peer_meta, 'conn_meta) connection P2p_point_state.Info.t option ;
negotiated_version : Network_version.t ;
answerer : ('msg, 'conn_meta) Answerer.t Lazy.t ;
mutable last_sent_swap_request : (Time.t * P2p_peer.Id.t) option ;
mutable wait_close : bool ;
......@@ -457,7 +461,7 @@ let broadcast_bootstrap_msg pool =
(***************************************************************************)
(* this function duplicates bit of code from the modules below to avoid
creating mutually recurvive modules *)
creating mutually recursive modules *)
let connection_of_peer_id pool peer_id =
Option.apply
(P2p_peer.Table.find_opt pool.known_peer_ids peer_id) ~f:begin fun p ->
......@@ -506,7 +510,7 @@ module Points = struct
let fold_known pool ~init ~f =
P2p_point.Table.fold f pool.known_points init
let fold_connected pool ~init ~f =
let fold_connected pool ~init ~f =
P2p_point.Table.fold f pool.connected_points init
let banned pool (addr, _port) =
......@@ -786,7 +790,7 @@ and raw_authenticate pool ?point_info canceler fd point =
~proof_of_work_target:pool.config.proof_of_work_target
~incoming fd point
?listening_port:pool.config.listening_port
pool.config.identity pool.message_config.versions
pool.config.identity pool.announced_version
pool.conn_meta_config
end ~on_error: begin fun err ->
begin match err with
......@@ -839,9 +843,12 @@ and raw_authenticate pool ?point_info canceler fd point =
| None, None -> None
| Some _ as point_info, _ | _, (Some _ as point_info) -> point_info in
let peer_info = register_peer pool info.peer_id in
let acceptable_versions =
P2p_version.common info.versions pool.message_config.versions
in
let acceptable_version =
Network_version.select
~chain_name:pool.message_config.chain_name
~distributed_db_versions:pool.message_config.distributed_db_versions
~p2p_versions:pool.custom_p2p_versions
info.announced_version in
let acceptable_point =
Option.unopt_map connection_point_info
~default:(not pool.config.private_mode)
......@@ -866,11 +873,19 @@ and raw_authenticate pool ?point_info canceler fd point =
(* TODO: in some circumstances cancel and accept... *)
false
| Running _ -> false
| Disconnected -> true
in
| Disconnected -> true in
(* To Verify : the thread must ? not be interrupted between
point removal from incoming and point registration into
active connection to prevent flooding attack.
incoming_connections + active_connection must reflect/dominate
the actual number of ongoing connections.
On the other hand, if we wait too long for Ack, we will reject
incoming connections, thus giving an entry point for dos attack
by giving late Nack.
*)
if incoming then
P2p_point.Table.remove pool.incoming point ;
match acceptable_versions with
match acceptable_version with
| Some version when acceptable_peer_id && acceptable_point -> begin
log pool (Accepting_request (point, info.id_point, info.peer_id)) ;
Option.iter connection_point_info
......@@ -906,7 +921,7 @@ and raw_authenticate pool ?point_info canceler fd point =
let id_point =
match info.id_point, Option.map ~f:P2p_point_state.Info.point point_info with
| (addr, _), Some (_, port) -> addr, Some port
| id_point, None -> id_point in
| id_point, None -> id_point in
return
(create_connection
pool conn
......@@ -923,10 +938,14 @@ and raw_authenticate pool ?point_info canceler fd point =
Option.iter ~f:P2p_point_state.set_disconnected point_info ;
(* FIXME P2p_peer_state.set_disconnected ~requested:true peer_info ; *)
end ;
fail (P2p_errors.Rejected info.peer_id)
match acceptable_version with