Removed unused src/bin_node.
This commit is contained in:
parent
378e4a5904
commit
044f4dfa59
@ -1,35 +0,0 @@
|
|||||||
(executable
|
|
||||||
(name main)
|
|
||||||
(public_name tezos-node)
|
|
||||||
(libraries tezos-base
|
|
||||||
tezos-stdlib-unix
|
|
||||||
tezos-shell-services
|
|
||||||
tezos-rpc-http
|
|
||||||
tezos-p2p
|
|
||||||
tezos-shell
|
|
||||||
tezos-protocol-updater
|
|
||||||
tezos-embedded-protocol-genesis
|
|
||||||
tezos-embedded-protocol-demo
|
|
||||||
tezos-embedded-protocol-alpha
|
|
||||||
cmdliner
|
|
||||||
tls)
|
|
||||||
(flags (:standard -w -9+27-30-32-40@8
|
|
||||||
-safe-string
|
|
||||||
-open Tezos_base__TzPervasives
|
|
||||||
-open Tezos_stdlib_unix
|
|
||||||
-open Tezos_shell_services
|
|
||||||
-open Tezos_rpc_http
|
|
||||||
-open Tezos_p2p
|
|
||||||
-open Tezos_shell
|
|
||||||
-open Tezos_protocol_updater
|
|
||||||
-linkall)))
|
|
||||||
|
|
||||||
(install
|
|
||||||
(section bin)
|
|
||||||
(files (tezos-sandboxed-node.sh as tezos-sandboxed-node.sh)))
|
|
||||||
|
|
||||||
(alias
|
|
||||||
(name runtest_indent)
|
|
||||||
(deps (glob_files *.ml{,i}))
|
|
||||||
(action
|
|
||||||
(run bash %{libexec:tezos-stdlib:test-ocp-indent.sh} %{deps})))
|
|
@ -1,75 +0,0 @@
|
|||||||
(*****************************************************************************)
|
|
||||||
(* *)
|
|
||||||
(* Open Source License *)
|
|
||||||
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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. *)
|
|
||||||
(* *)
|
|
||||||
(*****************************************************************************)
|
|
||||||
|
|
||||||
let () =
|
|
||||||
if Filename.basename Sys.argv.(0) = Updater.compiler_name then begin
|
|
||||||
try
|
|
||||||
Tezos_protocol_compiler.Compiler.main
|
|
||||||
Tezos_protocol_compiler_native.Native.driver ;
|
|
||||||
Pervasives.exit 0
|
|
||||||
with exn ->
|
|
||||||
Format.eprintf "%a\n%!" Opterrors.report_error exn;
|
|
||||||
Pervasives.exit 1
|
|
||||||
end
|
|
||||||
|
|
||||||
let term =
|
|
||||||
let open Cmdliner.Term in
|
|
||||||
ret (const (`Help (`Pager, None)))
|
|
||||||
|
|
||||||
let description = [
|
|
||||||
`S "DESCRIPTION" ;
|
|
||||||
`P "Entry point for initializing, configuring and running a Tezos node." ;
|
|
||||||
`P Node_identity_command.Manpage.command_description ;
|
|
||||||
`P Node_run_command.Manpage.command_description ;
|
|
||||||
`P Node_config_command.Manpage.command_description ;
|
|
||||||
]
|
|
||||||
|
|
||||||
let man =
|
|
||||||
description @
|
|
||||||
Node_run_command.Manpage.examples
|
|
||||||
|
|
||||||
let info =
|
|
||||||
let version =
|
|
||||||
Tezos_base.Current_git_info.abbreviated_commit_hash ^
|
|
||||||
" ("^Tezos_base.Current_git_info.committer_date^")" in
|
|
||||||
Cmdliner.Term.info
|
|
||||||
~doc:"The Tezos node"
|
|
||||||
~man
|
|
||||||
~version
|
|
||||||
"tezos-node"
|
|
||||||
|
|
||||||
let commands = [
|
|
||||||
Node_run_command.cmd ;
|
|
||||||
Node_config_command.cmd ;
|
|
||||||
Node_identity_command.cmd ;
|
|
||||||
]
|
|
||||||
|
|
||||||
let () =
|
|
||||||
Random.self_init () ;
|
|
||||||
match Cmdliner.Term.eval_choice (term, info) commands with
|
|
||||||
| `Error _ -> exit 1
|
|
||||||
| `Help -> exit 0
|
|
||||||
| `Version -> exit 1
|
|
||||||
| `Ok () -> exit 0
|
|
@ -1,164 +0,0 @@
|
|||||||
(*****************************************************************************)
|
|
||||||
(* *)
|
|
||||||
(* Open Source License *)
|
|
||||||
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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. *)
|
|
||||||
(* *)
|
|
||||||
(*****************************************************************************)
|
|
||||||
|
|
||||||
(** Commands *)
|
|
||||||
|
|
||||||
let show (args : Node_shared_arg.t) =
|
|
||||||
if not @@ Sys.file_exists args.config_file then
|
|
||||||
Format.eprintf
|
|
||||||
"\n\
|
|
||||||
Warning: no config file at %s,\n\
|
|
||||||
\ displaying the default configuration.\n@."
|
|
||||||
args.config_file ;
|
|
||||||
Node_shared_arg.read_and_patch_config_file args >>=? fun cfg ->
|
|
||||||
Node_config_file.check cfg >>= fun () ->
|
|
||||||
print_endline @@ Node_config_file.to_string cfg ;
|
|
||||||
return_unit
|
|
||||||
|
|
||||||
let reset (args : Node_shared_arg.t) =
|
|
||||||
if Sys.file_exists args.config_file then
|
|
||||||
Format.eprintf
|
|
||||||
"Ignoring previous configuration file: %s.@."
|
|
||||||
args.config_file ;
|
|
||||||
Node_shared_arg.read_and_patch_config_file args >>=? fun cfg ->
|
|
||||||
Node_config_file.check cfg >>= fun () ->
|
|
||||||
Node_config_file.write args.config_file cfg
|
|
||||||
|
|
||||||
let init (args : Node_shared_arg.t) =
|
|
||||||
if Sys.file_exists args.config_file then
|
|
||||||
failwith
|
|
||||||
"Pre-existing config file at %s, use `reset`."
|
|
||||||
args.config_file
|
|
||||||
else
|
|
||||||
Node_shared_arg.read_and_patch_config_file args >>=? fun cfg ->
|
|
||||||
Node_config_file.check cfg >>= fun () ->
|
|
||||||
Node_config_file.write args.config_file cfg
|
|
||||||
|
|
||||||
let update (args : Node_shared_arg.t) =
|
|
||||||
if not (Sys.file_exists args.config_file) then
|
|
||||||
failwith
|
|
||||||
"Missing configuration file at %s. \
|
|
||||||
Use `%s config init [options]` to generate a new file"
|
|
||||||
args.config_file Sys.argv.(0)
|
|
||||||
else
|
|
||||||
Node_shared_arg.read_and_patch_config_file args >>=? fun cfg ->
|
|
||||||
Node_config_file.check cfg >>= fun () ->
|
|
||||||
Node_config_file.write args.config_file cfg
|
|
||||||
|
|
||||||
(** Main *)
|
|
||||||
|
|
||||||
module Term = struct
|
|
||||||
|
|
||||||
type subcommand = Show | Reset | Init | Update
|
|
||||||
|
|
||||||
let process subcommand args =
|
|
||||||
let res =
|
|
||||||
match subcommand with
|
|
||||||
| Show -> show args
|
|
||||||
| Reset -> reset args
|
|
||||||
| Init -> init args
|
|
||||||
| Update -> update args in
|
|
||||||
match Lwt_main.run res with
|
|
||||||
| Ok () -> `Ok ()
|
|
||||||
| Error err -> `Error (false, Format.asprintf "%a" pp_print_error err)
|
|
||||||
|
|
||||||
let subcommand_arg =
|
|
||||||
let parser = function
|
|
||||||
| "show" -> `Ok Show
|
|
||||||
| "reset" -> `Ok Reset
|
|
||||||
| "init" -> `Ok Init
|
|
||||||
| "update" -> `Ok Update
|
|
||||||
| s -> `Error ("invalid argument: " ^ s)
|
|
||||||
and printer ppf = function
|
|
||||||
| Show -> Format.fprintf ppf "show"
|
|
||||||
| Reset -> Format.fprintf ppf "reset"
|
|
||||||
| Init -> Format.fprintf ppf "init"
|
|
||||||
| Update -> Format.fprintf ppf "update" in
|
|
||||||
let open Cmdliner.Arg in
|
|
||||||
let doc =
|
|
||||||
"Operation to perform. \
|
|
||||||
Possible values: $(b,show), $(b,reset), $(b,init), $(b,update)." in
|
|
||||||
value & pos 0 (parser, printer) Show & info [] ~docv:"OPERATION" ~doc
|
|
||||||
|
|
||||||
let term =
|
|
||||||
let open Cmdliner.Term in
|
|
||||||
ret (const process $ subcommand_arg $ Node_shared_arg.Term.args)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
module Manpage = struct
|
|
||||||
|
|
||||||
let command_description =
|
|
||||||
"The $(b,config) command is meant to inspect and amend the \
|
|
||||||
configuration of the Tezos node. \
|
|
||||||
This command is complementary to manually editing the tezos \
|
|
||||||
node configuration file. Its arguments are a subset of the $(i,run) \
|
|
||||||
command ones."
|
|
||||||
|
|
||||||
let description = [
|
|
||||||
`S "DESCRIPTION" ;
|
|
||||||
`P (command_description ^ " Several operations are possible: ");
|
|
||||||
`P "$(b,show) reads, parses and displays Tezos current config file. \
|
|
||||||
Use this command to see exactly what config file will be used by \
|
|
||||||
Tezos. If additional command-line arguments are provided, \
|
|
||||||
the displayed configuration will be amended accordingly. \
|
|
||||||
This is the default operation." ;
|
|
||||||
`P "$(b,reset) will overwrite the current configuration file with a \
|
|
||||||
factory default one. \
|
|
||||||
If additional command-line arguments are provided, \
|
|
||||||
they will amend the generated file. \
|
|
||||||
It assumes that a configuration file already exists \
|
|
||||||
and will abort otherwise." ;
|
|
||||||
`P "$(b,init) is like reset but assumes that \
|
|
||||||
no configuration file is present \
|
|
||||||
and will abort otherwise." ;
|
|
||||||
`P "$(b,update) is the main option to edit the configuration file of Tezos. \
|
|
||||||
It will parse command line arguments and add or replace corresponding \
|
|
||||||
entries in the Tezos configuration file."
|
|
||||||
]
|
|
||||||
|
|
||||||
let schema = Data_encoding.Json.schema (Node_config_file.encoding)
|
|
||||||
let options = [
|
|
||||||
`S "OPTIONS" ;
|
|
||||||
`P "All options available in the config file";
|
|
||||||
`Pre (Format.asprintf "@[%a@]" Json_schema.pp schema)
|
|
||||||
]
|
|
||||||
|
|
||||||
let man =
|
|
||||||
description @
|
|
||||||
Node_shared_arg.Manpage.args @
|
|
||||||
options @
|
|
||||||
Node_shared_arg.Manpage.bugs
|
|
||||||
|
|
||||||
let info =
|
|
||||||
Cmdliner.Term.info
|
|
||||||
~doc:"Manage node configuration"
|
|
||||||
~man
|
|
||||||
"config"
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
let cmd =
|
|
||||||
Term.term, Manpage.info
|
|
@ -1,30 +0,0 @@
|
|||||||
(*****************************************************************************)
|
|
||||||
(* *)
|
|
||||||
(* Open Source License *)
|
|
||||||
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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. *)
|
|
||||||
(* *)
|
|
||||||
(*****************************************************************************)
|
|
||||||
|
|
||||||
val cmd : unit Cmdliner.Term.t * Cmdliner.Term.info
|
|
||||||
|
|
||||||
module Manpage : sig
|
|
||||||
val command_description: string
|
|
||||||
end
|
|
@ -1,776 +0,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. *)
|
|
||||||
(* *)
|
|
||||||
(*****************************************************************************)
|
|
||||||
|
|
||||||
let (//) = Filename.concat
|
|
||||||
|
|
||||||
let home =
|
|
||||||
try Sys.getenv "HOME"
|
|
||||||
with Not_found -> "/root"
|
|
||||||
|
|
||||||
let default_data_dir = home // ".tezos-node"
|
|
||||||
let default_rpc_port = 8732
|
|
||||||
let default_p2p_port = 9732
|
|
||||||
let default_discovery_port = 10732
|
|
||||||
|
|
||||||
type t = {
|
|
||||||
data_dir : string ;
|
|
||||||
p2p : p2p ;
|
|
||||||
rpc : rpc ;
|
|
||||||
log : Logging_unix.cfg ;
|
|
||||||
shell : shell ;
|
|
||||||
}
|
|
||||||
|
|
||||||
and p2p = {
|
|
||||||
expected_pow : float ;
|
|
||||||
bootstrap_peers : string list ;
|
|
||||||
listen_addr : string option ;
|
|
||||||
discovery_addr : string option ;
|
|
||||||
private_mode : bool ;
|
|
||||||
limits : P2p.limits ;
|
|
||||||
disable_mempool : bool ;
|
|
||||||
}
|
|
||||||
|
|
||||||
and rpc = {
|
|
||||||
listen_addr : string option ;
|
|
||||||
cors_origins : string list ;
|
|
||||||
cors_headers : string list ;
|
|
||||||
tls : tls option ;
|
|
||||||
}
|
|
||||||
|
|
||||||
and tls = {
|
|
||||||
cert : string ;
|
|
||||||
key : string ;
|
|
||||||
}
|
|
||||||
|
|
||||||
and shell = {
|
|
||||||
block_validator_limits : Node.block_validator_limits ;
|
|
||||||
prevalidator_limits : Node.prevalidator_limits ;
|
|
||||||
peer_validator_limits : Node.peer_validator_limits ;
|
|
||||||
chain_validator_limits : Node.chain_validator_limits ;
|
|
||||||
}
|
|
||||||
|
|
||||||
let default_p2p_limits : P2p.limits = {
|
|
||||||
connection_timeout = 10. ;
|
|
||||||
authentication_timeout = 5. ;
|
|
||||||
greylist_timeout = 86400 ; (* one day *)
|
|
||||||
maintenance_idle_time = 120. ; (* two minutes *)
|
|
||||||
min_connections = 10 ;
|
|
||||||
expected_connections = 50 ;
|
|
||||||
max_connections = 100 ;
|
|
||||||
backlog = 20 ;
|
|
||||||
max_incoming_connections = 20 ;
|
|
||||||
max_download_speed = None ;
|
|
||||||
max_upload_speed = None ;
|
|
||||||
read_buffer_size = 1 lsl 14 ;
|
|
||||||
read_queue_size = None ;
|
|
||||||
write_queue_size = None ;
|
|
||||||
incoming_app_message_queue_size = None ;
|
|
||||||
incoming_message_queue_size = None ;
|
|
||||||
outgoing_message_queue_size = None ;
|
|
||||||
known_points_history_size = 500 ;
|
|
||||||
known_peer_ids_history_size = 500 ;
|
|
||||||
max_known_points = Some (400, 300) ;
|
|
||||||
max_known_peer_ids = Some (400, 300) ;
|
|
||||||
swap_linger = 30. ;
|
|
||||||
binary_chunks_size = None ;
|
|
||||||
}
|
|
||||||
|
|
||||||
let default_p2p = {
|
|
||||||
expected_pow = 26. ;
|
|
||||||
bootstrap_peers = [] ;
|
|
||||||
listen_addr = Some ("[::]:" ^ string_of_int default_p2p_port) ;
|
|
||||||
discovery_addr = None ;
|
|
||||||
private_mode = false ;
|
|
||||||
limits = default_p2p_limits ;
|
|
||||||
disable_mempool = false ;
|
|
||||||
}
|
|
||||||
|
|
||||||
let default_rpc = {
|
|
||||||
listen_addr = None ;
|
|
||||||
cors_origins = [] ;
|
|
||||||
cors_headers = [] ;
|
|
||||||
tls = None ;
|
|
||||||
}
|
|
||||||
|
|
||||||
let default_shell = {
|
|
||||||
block_validator_limits = Node.default_block_validator_limits ;
|
|
||||||
prevalidator_limits = Node.default_prevalidator_limits ;
|
|
||||||
peer_validator_limits = Node.default_peer_validator_limits ;
|
|
||||||
chain_validator_limits = Node.default_chain_validator_limits ;
|
|
||||||
}
|
|
||||||
|
|
||||||
let default_config = {
|
|
||||||
data_dir = default_data_dir ;
|
|
||||||
p2p = default_p2p ;
|
|
||||||
rpc = default_rpc ;
|
|
||||||
log = Logging_unix.default_cfg ;
|
|
||||||
shell = default_shell ;
|
|
||||||
}
|
|
||||||
|
|
||||||
let limit : P2p.limits Data_encoding.t =
|
|
||||||
let open Data_encoding in
|
|
||||||
conv
|
|
||||||
(fun { P2p.connection_timeout ; authentication_timeout ; greylist_timeout ;
|
|
||||||
maintenance_idle_time ;
|
|
||||||
min_connections ; expected_connections ; max_connections ;
|
|
||||||
backlog ; max_incoming_connections ;
|
|
||||||
max_download_speed ; max_upload_speed ;
|
|
||||||
read_buffer_size ; read_queue_size ; write_queue_size ;
|
|
||||||
incoming_app_message_queue_size ;
|
|
||||||
incoming_message_queue_size ; outgoing_message_queue_size ;
|
|
||||||
known_points_history_size ; known_peer_ids_history_size ;
|
|
||||||
max_known_points ; max_known_peer_ids ;
|
|
||||||
swap_linger ; binary_chunks_size
|
|
||||||
} ->
|
|
||||||
(((( connection_timeout, authentication_timeout,
|
|
||||||
min_connections, expected_connections,
|
|
||||||
max_connections, backlog, max_incoming_connections,
|
|
||||||
max_download_speed, max_upload_speed, swap_linger),
|
|
||||||
( binary_chunks_size, read_buffer_size, read_queue_size, write_queue_size,
|
|
||||||
incoming_app_message_queue_size,
|
|
||||||
incoming_message_queue_size, outgoing_message_queue_size,
|
|
||||||
known_points_history_size, known_peer_ids_history_size,
|
|
||||||
max_known_points)),
|
|
||||||
( max_known_peer_ids, greylist_timeout, maintenance_idle_time))))
|
|
||||||
(fun (((( connection_timeout, authentication_timeout,
|
|
||||||
min_connections, expected_connections,
|
|
||||||
max_connections, backlog, max_incoming_connections,
|
|
||||||
max_download_speed, max_upload_speed, swap_linger),
|
|
||||||
( binary_chunks_size, read_buffer_size, read_queue_size, write_queue_size,
|
|
||||||
incoming_app_message_queue_size,
|
|
||||||
incoming_message_queue_size, outgoing_message_queue_size,
|
|
||||||
known_points_history_size, known_peer_ids_history_size,
|
|
||||||
max_known_points)),
|
|
||||||
( max_known_peer_ids, greylist_timeout, maintenance_idle_time))) ->
|
|
||||||
{ connection_timeout ; authentication_timeout ; greylist_timeout ;
|
|
||||||
maintenance_idle_time ;
|
|
||||||
min_connections ; expected_connections ;
|
|
||||||
max_connections ; backlog ; max_incoming_connections ;
|
|
||||||
max_download_speed ; max_upload_speed ;
|
|
||||||
read_buffer_size ; read_queue_size ; write_queue_size ;
|
|
||||||
incoming_app_message_queue_size ;
|
|
||||||
incoming_message_queue_size ; outgoing_message_queue_size ;
|
|
||||||
known_points_history_size ; known_peer_ids_history_size ;
|
|
||||||
max_known_points ; max_known_peer_ids ; swap_linger ;
|
|
||||||
binary_chunks_size
|
|
||||||
})
|
|
||||||
(merge_objs
|
|
||||||
(merge_objs
|
|
||||||
(obj10
|
|
||||||
(dft "connection-timeout"
|
|
||||||
~description: "Delay acceptable when initiating a \
|
|
||||||
connection to a new peer, in seconds."
|
|
||||||
float default_p2p_limits.authentication_timeout)
|
|
||||||
(dft "authentication-timeout"
|
|
||||||
~description: "Delay granted to a peer to perform authentication, \
|
|
||||||
in seconds."
|
|
||||||
float default_p2p_limits.authentication_timeout)
|
|
||||||
(dft "min-connections"
|
|
||||||
~description: "Strict minimum number of connections (triggers an \
|
|
||||||
urgent maintenance)."
|
|
||||||
uint16
|
|
||||||
default_p2p_limits.min_connections)
|
|
||||||
(dft "expected-connections"
|
|
||||||
~description: "Targeted number of connections to reach when \
|
|
||||||
bootstrapping / maintaining."
|
|
||||||
uint16
|
|
||||||
default_p2p_limits.expected_connections)
|
|
||||||
(dft "max-connections"
|
|
||||||
~description: "Maximum number of connections (exceeding peers are \
|
|
||||||
disconnected)."
|
|
||||||
uint16
|
|
||||||
default_p2p_limits.max_connections)
|
|
||||||
(dft "backlog"
|
|
||||||
~description: "Number above which pending incoming connections are \
|
|
||||||
immediately rejected."
|
|
||||||
uint8
|
|
||||||
default_p2p_limits.backlog)
|
|
||||||
(dft "max-incoming-connections"
|
|
||||||
~description: "Number above which pending incoming connections are \
|
|
||||||
immediately rejected."
|
|
||||||
uint8
|
|
||||||
default_p2p_limits.max_incoming_connections)
|
|
||||||
(opt "max-download-speed"
|
|
||||||
~description: "Max download speeds in KiB/s."
|
|
||||||
int31)
|
|
||||||
(opt "max-upload-speed"
|
|
||||||
~description: "Max upload speeds in KiB/s."
|
|
||||||
int31)
|
|
||||||
(dft "swap-linger" float default_p2p_limits.swap_linger))
|
|
||||||
(obj10
|
|
||||||
(opt "binary-chunks-size" uint8)
|
|
||||||
(dft "read-buffer-size"
|
|
||||||
~description: "Size of the buffer passed to read(2)."
|
|
||||||
int31
|
|
||||||
default_p2p_limits.read_buffer_size)
|
|
||||||
(opt "read-queue-size" int31)
|
|
||||||
(opt "write-queue-size" int31)
|
|
||||||
(opt "incoming-app-message-queue-size" int31)
|
|
||||||
(opt "incoming-message-queue-size" int31)
|
|
||||||
(opt "outgoing-message-queue-size" int31)
|
|
||||||
(dft "known_points_history_size" uint16
|
|
||||||
default_p2p_limits.known_points_history_size)
|
|
||||||
(dft "known_peer_ids_history_size" uint16
|
|
||||||
default_p2p_limits.known_points_history_size)
|
|
||||||
(opt "max_known_points" (tup2 uint16 uint16))
|
|
||||||
))
|
|
||||||
(obj3
|
|
||||||
(opt "max_known_peer_ids" (tup2 uint16 uint16))
|
|
||||||
(dft "greylist-timeout"
|
|
||||||
~description: "GC delay for the greylists tables, in seconds."
|
|
||||||
int31 default_p2p_limits.greylist_timeout)
|
|
||||||
(dft "maintenance-idle-time"
|
|
||||||
~description: "How long to wait at most, in seconds, \
|
|
||||||
before running a maintenance loop."
|
|
||||||
float default_p2p_limits.maintenance_idle_time)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
let p2p =
|
|
||||||
let open Data_encoding in
|
|
||||||
conv
|
|
||||||
(fun { expected_pow ; bootstrap_peers ; listen_addr ; discovery_addr ;
|
|
||||||
private_mode ; limits ; disable_mempool } ->
|
|
||||||
( expected_pow, bootstrap_peers, listen_addr, discovery_addr ,
|
|
||||||
private_mode, limits, disable_mempool ))
|
|
||||||
(fun ( expected_pow, bootstrap_peers, listen_addr, discovery_addr,
|
|
||||||
private_mode, limits, disable_mempool ) ->
|
|
||||||
{ expected_pow ; bootstrap_peers ; listen_addr ; discovery_addr ;
|
|
||||||
private_mode ; limits ; disable_mempool })
|
|
||||||
(obj7
|
|
||||||
(dft "expected-proof-of-work"
|
|
||||||
~description: "Floating point number between 0 and 256 that represents a \
|
|
||||||
difficulty, 24 signifies for example that at least 24 leading \
|
|
||||||
zeroes are expected in the hash."
|
|
||||||
float default_p2p.expected_pow)
|
|
||||||
(dft "bootstrap-peers"
|
|
||||||
~description: "List of hosts. Tezos can connect to both IPv6 and IPv4 hosts. \
|
|
||||||
If the port is not specified, default port 9732 will be assumed."
|
|
||||||
(list string) default_p2p.bootstrap_peers)
|
|
||||||
(opt "listen-addr"
|
|
||||||
~description: "Host to listen to. If the port is not \
|
|
||||||
specified, the default port 8732 will be \
|
|
||||||
assumed."
|
|
||||||
string)
|
|
||||||
(dft "discovery-addr"
|
|
||||||
~description: "Host for local peer discovery. If the port is not \
|
|
||||||
specified, the default port 10732 will be \
|
|
||||||
assumed."
|
|
||||||
(option string) default_p2p.discovery_addr)
|
|
||||||
(dft "private-mode"
|
|
||||||
~description: "Specify if the node is in private mode or \
|
|
||||||
not. A node in private mode rejects incoming \
|
|
||||||
connections from untrusted peers and only \
|
|
||||||
opens outgoing connections to peers listed in \
|
|
||||||
'bootstrap-peers' or provided with '--peer' \
|
|
||||||
option. Moreover, these peers will keep the \
|
|
||||||
identity and the address of the private node \
|
|
||||||
secret."
|
|
||||||
bool false)
|
|
||||||
(dft "limits"
|
|
||||||
~description: "Network limits"
|
|
||||||
limit default_p2p_limits)
|
|
||||||
(dft "disable_mempool"
|
|
||||||
~description: "If set to [true], the node will not participate in \
|
|
||||||
the propagation of pending operations (mempool). \
|
|
||||||
Default value is [false]. \
|
|
||||||
It can be used to decrease the memory and \
|
|
||||||
computation footprints of the node."
|
|
||||||
bool false)
|
|
||||||
)
|
|
||||||
|
|
||||||
let rpc : rpc Data_encoding.t =
|
|
||||||
let open Data_encoding in
|
|
||||||
conv
|
|
||||||
(fun { cors_origins ; cors_headers ; listen_addr ; tls } ->
|
|
||||||
let cert, key =
|
|
||||||
match tls with
|
|
||||||
| None -> None, None
|
|
||||||
| Some { cert ; key } -> Some cert, Some key in
|
|
||||||
(listen_addr, cors_origins, cors_headers, cert, key ))
|
|
||||||
(fun (listen_addr, cors_origins, cors_headers, cert, key ) ->
|
|
||||||
let tls =
|
|
||||||
match cert, key with
|
|
||||||
| None, _ | _, None -> None
|
|
||||||
| Some cert, Some key -> Some { cert ; key } in
|
|
||||||
{ listen_addr ; cors_origins ; cors_headers ; tls })
|
|
||||||
(obj5
|
|
||||||
(opt "listen-addr"
|
|
||||||
~description: "Host to listen to. If the port is not specified, \
|
|
||||||
the default port 8732 will be assumed."
|
|
||||||
string)
|
|
||||||
(dft "cors-origin"
|
|
||||||
~description: "Cross Origin Resource Sharing parameters, see \
|
|
||||||
https://en.wikipedia.org/wiki/Cross-origin_resource_sharing."
|
|
||||||
(list string) default_rpc.cors_origins)
|
|
||||||
(dft "cors-headers"
|
|
||||||
~description: "Cross Origin Resource Sharing parameters, see \
|
|
||||||
https://en.wikipedia.org/wiki/Cross-origin_resource_sharing."
|
|
||||||
(list string) default_rpc.cors_headers)
|
|
||||||
(opt "crt"
|
|
||||||
~description: "Certificate file (necessary when TLS is used)."
|
|
||||||
string)
|
|
||||||
(opt "key"
|
|
||||||
~description: "Key file (necessary when TLS is used)."
|
|
||||||
string)
|
|
||||||
)
|
|
||||||
|
|
||||||
let worker_limits_encoding
|
|
||||||
default_size
|
|
||||||
default_level
|
|
||||||
default_zombie_lifetime
|
|
||||||
default_zombie_memory =
|
|
||||||
let open Data_encoding in
|
|
||||||
conv
|
|
||||||
(fun { Worker_types.backlog_size ; backlog_level ; zombie_lifetime ; zombie_memory } ->
|
|
||||||
(backlog_size, backlog_level, zombie_lifetime, zombie_memory))
|
|
||||||
(fun (backlog_size, backlog_level, zombie_lifetime, zombie_memory) ->
|
|
||||||
{ backlog_size ; backlog_level ; zombie_lifetime ; zombie_memory })
|
|
||||||
(obj4
|
|
||||||
(dft "worker_backlog_size" uint16 default_size)
|
|
||||||
(dft "worker_backlog_level" Logging_unix.level_encoding default_level)
|
|
||||||
(dft "worker_zombie_lifetime" float default_zombie_lifetime)
|
|
||||||
(dft "worker_zombie_memory" float default_zombie_memory))
|
|
||||||
|
|
||||||
let timeout_encoding =
|
|
||||||
Data_encoding.ranged_float 0. 500.
|
|
||||||
|
|
||||||
let block_validator_limits_encoding =
|
|
||||||
let open Data_encoding in
|
|
||||||
conv
|
|
||||||
(fun { Node.protocol_timeout ; worker_limits } ->
|
|
||||||
(protocol_timeout, worker_limits))
|
|
||||||
(fun (protocol_timeout, worker_limits) ->
|
|
||||||
{ protocol_timeout ; worker_limits})
|
|
||||||
(merge_objs
|
|
||||||
(obj1
|
|
||||||
(dft "protocol_request_timeout" timeout_encoding
|
|
||||||
default_shell.block_validator_limits.protocol_timeout))
|
|
||||||
(worker_limits_encoding
|
|
||||||
default_shell.block_validator_limits.worker_limits.backlog_size
|
|
||||||
default_shell.block_validator_limits.worker_limits.backlog_level
|
|
||||||
default_shell.block_validator_limits.worker_limits.zombie_lifetime
|
|
||||||
default_shell.block_validator_limits.worker_limits.zombie_memory))
|
|
||||||
|
|
||||||
let prevalidator_limits_encoding =
|
|
||||||
let open Data_encoding in
|
|
||||||
conv
|
|
||||||
(fun { Node.operation_timeout ; max_refused_operations ; worker_limits } ->
|
|
||||||
((operation_timeout, max_refused_operations), worker_limits))
|
|
||||||
(fun ((operation_timeout, max_refused_operations), worker_limits) ->
|
|
||||||
{ operation_timeout ; max_refused_operations ; worker_limits})
|
|
||||||
(merge_objs
|
|
||||||
(obj2
|
|
||||||
(dft "operations_request_timeout" timeout_encoding
|
|
||||||
default_shell.prevalidator_limits.operation_timeout)
|
|
||||||
(dft "max_refused_operations" uint16
|
|
||||||
default_shell.prevalidator_limits.max_refused_operations))
|
|
||||||
(worker_limits_encoding
|
|
||||||
default_shell.prevalidator_limits.worker_limits.backlog_size
|
|
||||||
default_shell.prevalidator_limits.worker_limits.backlog_level
|
|
||||||
default_shell.prevalidator_limits.worker_limits.zombie_lifetime
|
|
||||||
default_shell.prevalidator_limits.worker_limits.zombie_memory))
|
|
||||||
|
|
||||||
let peer_validator_limits_encoding =
|
|
||||||
let open Data_encoding in
|
|
||||||
let default_limits = default_shell.peer_validator_limits in
|
|
||||||
conv
|
|
||||||
(fun { Node.block_header_timeout ; block_operations_timeout ;
|
|
||||||
protocol_timeout ; new_head_request_timeout ; worker_limits } ->
|
|
||||||
((block_header_timeout, block_operations_timeout,
|
|
||||||
protocol_timeout, new_head_request_timeout), worker_limits))
|
|
||||||
(fun ((block_header_timeout, block_operations_timeout,
|
|
||||||
protocol_timeout, new_head_request_timeout), worker_limits) ->
|
|
||||||
{ block_header_timeout ; block_operations_timeout ;
|
|
||||||
protocol_timeout ; new_head_request_timeout ; worker_limits })
|
|
||||||
(merge_objs
|
|
||||||
(obj4
|
|
||||||
(dft "block_header_request_timeout" timeout_encoding default_limits.block_header_timeout)
|
|
||||||
(dft "block_operations_request_timeout" timeout_encoding default_limits.block_operations_timeout)
|
|
||||||
(dft "protocol_request_timeout" timeout_encoding default_limits.protocol_timeout)
|
|
||||||
(dft "new_head_request_timeout" timeout_encoding default_limits.new_head_request_timeout))
|
|
||||||
(worker_limits_encoding
|
|
||||||
default_limits.worker_limits.backlog_size
|
|
||||||
default_limits.worker_limits.backlog_level
|
|
||||||
default_limits.worker_limits.zombie_lifetime
|
|
||||||
default_limits.worker_limits.zombie_memory))
|
|
||||||
|
|
||||||
let chain_validator_limits_encoding =
|
|
||||||
let open Data_encoding in
|
|
||||||
conv
|
|
||||||
(fun { Node.bootstrap_threshold ; worker_limits } ->
|
|
||||||
(bootstrap_threshold, worker_limits))
|
|
||||||
(fun (bootstrap_threshold, worker_limits) ->
|
|
||||||
{ bootstrap_threshold ; worker_limits})
|
|
||||||
(merge_objs
|
|
||||||
(obj1
|
|
||||||
(dft "bootstrap_threshold"
|
|
||||||
~description:
|
|
||||||
"Set the number of peers with whom a chain synchronization must \
|
|
||||||
be completed to bootstrap the node."
|
|
||||||
uint8
|
|
||||||
default_shell.chain_validator_limits.bootstrap_threshold))
|
|
||||||
(worker_limits_encoding
|
|
||||||
default_shell.chain_validator_limits.worker_limits.backlog_size
|
|
||||||
default_shell.chain_validator_limits.worker_limits.backlog_level
|
|
||||||
default_shell.chain_validator_limits.worker_limits.zombie_lifetime
|
|
||||||
default_shell.chain_validator_limits.worker_limits.zombie_memory))
|
|
||||||
|
|
||||||
let shell =
|
|
||||||
let open Data_encoding in
|
|
||||||
conv
|
|
||||||
(fun { peer_validator_limits ; block_validator_limits ;
|
|
||||||
prevalidator_limits ; chain_validator_limits } ->
|
|
||||||
(peer_validator_limits, block_validator_limits,
|
|
||||||
prevalidator_limits, chain_validator_limits))
|
|
||||||
(fun (peer_validator_limits, block_validator_limits,
|
|
||||||
prevalidator_limits, chain_validator_limits) ->
|
|
||||||
{ peer_validator_limits ; block_validator_limits ;
|
|
||||||
prevalidator_limits ; chain_validator_limits })
|
|
||||||
(obj4
|
|
||||||
(dft "peer_validator" peer_validator_limits_encoding default_shell.peer_validator_limits)
|
|
||||||
(dft "block_validator" block_validator_limits_encoding default_shell.block_validator_limits)
|
|
||||||
(dft "prevalidator" prevalidator_limits_encoding default_shell.prevalidator_limits)
|
|
||||||
(dft "chain_validator" chain_validator_limits_encoding default_shell.chain_validator_limits)
|
|
||||||
)
|
|
||||||
|
|
||||||
let encoding =
|
|
||||||
let open Data_encoding in
|
|
||||||
conv
|
|
||||||
(fun { data_dir ; rpc ; p2p ; log ; shell } ->
|
|
||||||
(data_dir, rpc, p2p, log, shell))
|
|
||||||
(fun (data_dir, rpc, p2p, log, shell) ->
|
|
||||||
{ data_dir ; rpc ; p2p ; log ; shell })
|
|
||||||
(obj5
|
|
||||||
(dft "data-dir"
|
|
||||||
~description: "Location of the data dir on disk."
|
|
||||||
string default_data_dir)
|
|
||||||
(dft "rpc"
|
|
||||||
~description: "Configuration of rpc parameters"
|
|
||||||
rpc default_rpc)
|
|
||||||
(req "p2p"
|
|
||||||
~description: "Configuration of network parameters" p2p)
|
|
||||||
(dft "log"
|
|
||||||
~description: "Configuration of network parameters"
|
|
||||||
Logging_unix.cfg_encoding Logging_unix.default_cfg)
|
|
||||||
(dft "shell"
|
|
||||||
~description: "Configuration of network parameters"
|
|
||||||
shell default_shell))
|
|
||||||
|
|
||||||
let read fp =
|
|
||||||
if Sys.file_exists fp then begin
|
|
||||||
Lwt_utils_unix.Json.read_file fp >>=? fun json ->
|
|
||||||
try return (Data_encoding.Json.destruct encoding json)
|
|
||||||
with exn -> fail (Exn exn)
|
|
||||||
end else
|
|
||||||
return default_config
|
|
||||||
|
|
||||||
let write fp cfg =
|
|
||||||
Node_data_version.ensure_data_dir (Filename.dirname fp) >>=? fun () ->
|
|
||||||
Lwt_utils_unix.Json.write_file fp
|
|
||||||
(Data_encoding.Json.construct encoding cfg)
|
|
||||||
|
|
||||||
let to_string cfg =
|
|
||||||
Data_encoding.Json.to_string
|
|
||||||
(Data_encoding.Json.construct encoding cfg)
|
|
||||||
|
|
||||||
let update
|
|
||||||
?data_dir
|
|
||||||
?min_connections
|
|
||||||
?expected_connections
|
|
||||||
?max_connections
|
|
||||||
?max_download_speed
|
|
||||||
?max_upload_speed
|
|
||||||
?binary_chunks_size
|
|
||||||
?peer_table_size
|
|
||||||
?expected_pow
|
|
||||||
?bootstrap_peers
|
|
||||||
?listen_addr
|
|
||||||
?discovery_addr
|
|
||||||
?rpc_listen_addr
|
|
||||||
?(private_mode = false)
|
|
||||||
?(disable_mempool = false)
|
|
||||||
?(cors_origins = [])
|
|
||||||
?(cors_headers = [])
|
|
||||||
?rpc_tls
|
|
||||||
?log_output
|
|
||||||
?bootstrap_threshold
|
|
||||||
cfg = let data_dir = Option.unopt ~default:cfg.data_dir data_dir in
|
|
||||||
Node_data_version.ensure_data_dir data_dir >>=? fun () ->
|
|
||||||
let peer_table_size =
|
|
||||||
Option.map peer_table_size ~f:(fun i -> i, i / 4 * 3) in
|
|
||||||
let unopt_list ~default = function
|
|
||||||
| [] -> default
|
|
||||||
| l -> l in
|
|
||||||
let limits : P2p.limits = {
|
|
||||||
cfg.p2p.limits with
|
|
||||||
min_connections =
|
|
||||||
Option.unopt
|
|
||||||
~default:cfg.p2p.limits.min_connections
|
|
||||||
min_connections ;
|
|
||||||
expected_connections =
|
|
||||||
Option.unopt
|
|
||||||
~default:cfg.p2p.limits.expected_connections
|
|
||||||
expected_connections ;
|
|
||||||
max_connections =
|
|
||||||
Option.unopt
|
|
||||||
~default:cfg.p2p.limits.max_connections
|
|
||||||
max_connections ;
|
|
||||||
max_download_speed =
|
|
||||||
Option.first_some
|
|
||||||
max_download_speed cfg.p2p.limits.max_download_speed ;
|
|
||||||
max_upload_speed =
|
|
||||||
Option.first_some
|
|
||||||
max_upload_speed cfg.p2p.limits.max_upload_speed ;
|
|
||||||
max_known_points =
|
|
||||||
Option.first_some
|
|
||||||
peer_table_size cfg.p2p.limits.max_known_points ;
|
|
||||||
max_known_peer_ids =
|
|
||||||
Option.first_some
|
|
||||||
peer_table_size cfg.p2p.limits.max_known_peer_ids ;
|
|
||||||
binary_chunks_size =
|
|
||||||
Option.map ~f:(fun x -> x lsl 10) binary_chunks_size ;
|
|
||||||
} in
|
|
||||||
let p2p : p2p = {
|
|
||||||
expected_pow =
|
|
||||||
Option.unopt ~default:cfg.p2p.expected_pow expected_pow ;
|
|
||||||
bootstrap_peers =
|
|
||||||
Option.unopt ~default:cfg.p2p.bootstrap_peers bootstrap_peers ;
|
|
||||||
listen_addr =
|
|
||||||
Option.first_some listen_addr cfg.p2p.listen_addr ;
|
|
||||||
discovery_addr =
|
|
||||||
Option.first_some discovery_addr cfg.p2p.discovery_addr ;
|
|
||||||
private_mode = cfg.p2p.private_mode || private_mode ;
|
|
||||||
limits ;
|
|
||||||
disable_mempool = cfg.p2p.disable_mempool || disable_mempool ;
|
|
||||||
}
|
|
||||||
and rpc : rpc = {
|
|
||||||
listen_addr =
|
|
||||||
Option.first_some rpc_listen_addr cfg.rpc.listen_addr ;
|
|
||||||
cors_origins =
|
|
||||||
unopt_list ~default:cfg.rpc.cors_origins cors_origins ;
|
|
||||||
cors_headers =
|
|
||||||
unopt_list ~default:cfg.rpc.cors_headers cors_headers ;
|
|
||||||
tls =
|
|
||||||
Option.first_some rpc_tls cfg.rpc.tls ;
|
|
||||||
}
|
|
||||||
and log : Logging_unix.cfg = {
|
|
||||||
cfg.log with
|
|
||||||
output = Option.unopt ~default:cfg.log.output log_output ;
|
|
||||||
}
|
|
||||||
and shell : shell = {
|
|
||||||
peer_validator_limits = cfg.shell.peer_validator_limits ;
|
|
||||||
block_validator_limits = cfg.shell.block_validator_limits ;
|
|
||||||
prevalidator_limits = cfg.shell.prevalidator_limits ;
|
|
||||||
chain_validator_limits =
|
|
||||||
Option.unopt_map
|
|
||||||
~default:cfg.shell.chain_validator_limits
|
|
||||||
~f:(fun bootstrap_threshold ->
|
|
||||||
{ cfg.shell.chain_validator_limits
|
|
||||||
with bootstrap_threshold })
|
|
||||||
bootstrap_threshold
|
|
||||||
}
|
|
||||||
in
|
|
||||||
return { data_dir ; p2p ; rpc ; log ; shell }
|
|
||||||
|
|
||||||
let resolve_addr ~default_addr ?default_port ?(passive = false) peer =
|
|
||||||
let addr, port = P2p_point.Id.parse_addr_port peer in
|
|
||||||
let node = if addr = "" || addr = "_" then default_addr else addr
|
|
||||||
and service =
|
|
||||||
match port, default_port with
|
|
||||||
| "", None -> invalid_arg ""
|
|
||||||
| "", Some default_port -> string_of_int default_port
|
|
||||||
| port, _ -> port in
|
|
||||||
Lwt_utils_unix.getaddrinfo ~passive ~node ~service
|
|
||||||
|
|
||||||
let resolve_addrs ~default_addr ?default_port ?passive peers =
|
|
||||||
Lwt_list.fold_left_s begin fun a peer ->
|
|
||||||
resolve_addr ~default_addr ?default_port ?passive peer >>= fun points ->
|
|
||||||
Lwt.return (List.rev_append points a)
|
|
||||||
end [] peers
|
|
||||||
|
|
||||||
let resolve_discovery_addrs discovery_addr =
|
|
||||||
resolve_addr
|
|
||||||
~default_addr:Ipaddr.V4.(to_string broadcast)
|
|
||||||
~default_port:default_discovery_port
|
|
||||||
~passive:true
|
|
||||||
discovery_addr
|
|
||||||
>>= fun addrs ->
|
|
||||||
let rec to_ipv4 acc = function
|
|
||||||
| [] -> Lwt.return (List.rev acc)
|
|
||||||
| (ip, port) :: xs -> begin match Ipaddr.v4_of_v6 ip with
|
|
||||||
| Some v -> to_ipv4 ((v, port) :: acc) xs
|
|
||||||
| None ->
|
|
||||||
Format.eprintf
|
|
||||||
"Warning: failed to convert %S to an ipv4 address@."
|
|
||||||
(Ipaddr.V6.to_string ip) ;
|
|
||||||
to_ipv4 acc xs
|
|
||||||
end
|
|
||||||
in to_ipv4 [] addrs
|
|
||||||
|
|
||||||
let resolve_listening_addrs listen_addr =
|
|
||||||
resolve_addr
|
|
||||||
~default_addr:"::"
|
|
||||||
~default_port:default_p2p_port
|
|
||||||
~passive:true
|
|
||||||
listen_addr
|
|
||||||
|
|
||||||
let resolve_rpc_listening_addrs listen_addr =
|
|
||||||
resolve_addr
|
|
||||||
~default_addr:"::"
|
|
||||||
~default_port:default_rpc_port
|
|
||||||
~passive:true
|
|
||||||
listen_addr
|
|
||||||
|
|
||||||
let resolve_bootstrap_addrs peers =
|
|
||||||
resolve_addrs
|
|
||||||
~default_addr:"::"
|
|
||||||
~default_port:default_p2p_port
|
|
||||||
peers
|
|
||||||
|
|
||||||
let check_listening_addr config =
|
|
||||||
match config.p2p.listen_addr with
|
|
||||||
| None -> Lwt.return_unit
|
|
||||||
| Some addr ->
|
|
||||||
Lwt.catch begin fun () ->
|
|
||||||
resolve_listening_addrs addr >>= function
|
|
||||||
| [] ->
|
|
||||||
Format.eprintf "Warning: failed to resolve %S\n@." addr ;
|
|
||||||
Lwt.return_unit
|
|
||||||
| _ :: _ ->
|
|
||||||
Lwt.return_unit
|
|
||||||
end begin function
|
|
||||||
| (Invalid_argument msg) ->
|
|
||||||
Format.eprintf "Warning: failed to parse %S:\ %s\n@." addr msg ;
|
|
||||||
Lwt.return_unit
|
|
||||||
| exn -> Lwt.fail exn
|
|
||||||
end
|
|
||||||
|
|
||||||
let check_discovery_addr config =
|
|
||||||
match config.p2p.discovery_addr with
|
|
||||||
| None -> Lwt.return_unit
|
|
||||||
| Some addr ->
|
|
||||||
Lwt.catch begin fun () ->
|
|
||||||
resolve_discovery_addrs addr >>= function
|
|
||||||
| [] ->
|
|
||||||
Format.eprintf "Warning: failed to resolve %S\n@." addr ;
|
|
||||||
Lwt.return_unit
|
|
||||||
| _ :: _ ->
|
|
||||||
Lwt.return_unit
|
|
||||||
end begin function
|
|
||||||
| (Invalid_argument msg) ->
|
|
||||||
Format.eprintf "Warning: failed to parse %S:\ %s\n@." addr msg ;
|
|
||||||
Lwt.return_unit
|
|
||||||
| exn -> Lwt.fail exn
|
|
||||||
end
|
|
||||||
|
|
||||||
let check_rpc_listening_addr config =
|
|
||||||
match config.rpc.listen_addr with
|
|
||||||
| None -> Lwt.return_unit
|
|
||||||
| Some addr ->
|
|
||||||
Lwt.catch begin fun () ->
|
|
||||||
resolve_rpc_listening_addrs addr >>= function
|
|
||||||
| [] ->
|
|
||||||
Format.eprintf "Warning: failed to resolve %S\n@." addr ;
|
|
||||||
Lwt.return_unit
|
|
||||||
| _ :: _ ->
|
|
||||||
Lwt.return_unit
|
|
||||||
end begin function
|
|
||||||
| (Invalid_argument msg) ->
|
|
||||||
Format.eprintf "Warning: failed to parse %S:\ %s\n@." addr msg ;
|
|
||||||
Lwt.return_unit
|
|
||||||
| exn -> Lwt.fail exn
|
|
||||||
end
|
|
||||||
|
|
||||||
let check_bootstrap_peer addr =
|
|
||||||
Lwt.catch begin fun () ->
|
|
||||||
resolve_bootstrap_addrs [addr] >>= function
|
|
||||||
| [] ->
|
|
||||||
Format.eprintf "Warning: cannot resolve %S\n@." addr ;
|
|
||||||
Lwt.return_unit
|
|
||||||
| _ :: _ ->
|
|
||||||
Lwt.return_unit
|
|
||||||
end begin function
|
|
||||||
| (Invalid_argument msg) ->
|
|
||||||
Format.eprintf "Warning: failed to parse %S:\ %s\n@." addr msg ;
|
|
||||||
Lwt.return_unit
|
|
||||||
| exn -> Lwt.fail exn
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
let check_bootstrap_peers config =
|
|
||||||
Lwt_list.iter_p check_bootstrap_peer config.p2p.bootstrap_peers
|
|
||||||
|
|
||||||
|
|
||||||
let fail fmt =
|
|
||||||
Format.kasprintf (fun s -> prerr_endline s ; exit 1) fmt
|
|
||||||
|
|
||||||
let check_connections config =
|
|
||||||
if config.p2p.limits.min_connections > config.p2p.limits.expected_connections then
|
|
||||||
fail "Error: The minumum number of connections is greater than \
|
|
||||||
the expected number of connections"
|
|
||||||
config.p2p.limits.min_connections
|
|
||||||
config.p2p.limits.expected_connections ;
|
|
||||||
if config.p2p.limits.expected_connections > config.p2p.limits.max_connections then
|
|
||||||
fail "Error: The expected number of connections is greater than \
|
|
||||||
the maximum number of connections"
|
|
||||||
config.p2p.limits.expected_connections
|
|
||||||
config.p2p.limits.max_connections ;
|
|
||||||
begin
|
|
||||||
match config.p2p.limits.max_known_peer_ids with
|
|
||||||
| None -> ()
|
|
||||||
| Some (max_known_peer_ids, target_known_peer_ids) ->
|
|
||||||
if target_known_peer_ids > max_known_peer_ids then
|
|
||||||
fail "Error: The target number of known peer ids is greater than \
|
|
||||||
the maximum number of known peer ids."
|
|
||||||
target_known_peer_ids max_known_peer_ids ;
|
|
||||||
if config.p2p.limits.max_connections > target_known_peer_ids then
|
|
||||||
fail "Error: The target number of known peer ids is lower than \
|
|
||||||
the maximum number of connections."
|
|
||||||
target_known_peer_ids max_known_peer_ids ;
|
|
||||||
end ;
|
|
||||||
begin
|
|
||||||
match config.p2p.limits.max_known_points with
|
|
||||||
| None -> ()
|
|
||||||
| Some (max_known_points, target_known_points) ->
|
|
||||||
if target_known_points > max_known_points then
|
|
||||||
fail "Error: The target number of known points is greater than \
|
|
||||||
the maximum number of known points."
|
|
||||||
target_known_points max_known_points ;
|
|
||||||
if config.p2p.limits.max_connections > target_known_points then
|
|
||||||
fail "Error: The target number of known points is lower than \
|
|
||||||
the maximum number of connections."
|
|
||||||
target_known_points max_known_points ;
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
let check config =
|
|
||||||
check_listening_addr config >>= fun () ->
|
|
||||||
check_rpc_listening_addr config >>= fun () ->
|
|
||||||
check_discovery_addr config >>= fun () ->
|
|
||||||
check_bootstrap_peers config >>= fun () ->
|
|
||||||
check_connections config ;
|
|
||||||
Lwt.return_unit
|
|
@ -1,104 +0,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. *)
|
|
||||||
(* *)
|
|
||||||
(*****************************************************************************)
|
|
||||||
|
|
||||||
type t = {
|
|
||||||
data_dir : string ;
|
|
||||||
p2p : p2p ;
|
|
||||||
rpc : rpc ;
|
|
||||||
log : Logging_unix.cfg ;
|
|
||||||
shell : shell ;
|
|
||||||
}
|
|
||||||
|
|
||||||
and p2p = {
|
|
||||||
expected_pow : float ;
|
|
||||||
bootstrap_peers : string list ;
|
|
||||||
listen_addr : string option ;
|
|
||||||
discovery_addr : string option ;
|
|
||||||
private_mode : bool ;
|
|
||||||
limits : P2p.limits ;
|
|
||||||
disable_mempool : bool ;
|
|
||||||
}
|
|
||||||
|
|
||||||
and rpc = {
|
|
||||||
listen_addr : string option ;
|
|
||||||
cors_origins : string list ;
|
|
||||||
cors_headers : string list ;
|
|
||||||
tls : tls option ;
|
|
||||||
}
|
|
||||||
|
|
||||||
and tls = {
|
|
||||||
cert : string ;
|
|
||||||
key : string ;
|
|
||||||
}
|
|
||||||
|
|
||||||
and shell = {
|
|
||||||
block_validator_limits : Node.block_validator_limits ;
|
|
||||||
prevalidator_limits : Node.prevalidator_limits ;
|
|
||||||
peer_validator_limits : Node.peer_validator_limits ;
|
|
||||||
chain_validator_limits : Node.chain_validator_limits ;
|
|
||||||
}
|
|
||||||
|
|
||||||
val default_data_dir: string
|
|
||||||
val default_p2p_port: int
|
|
||||||
val default_rpc_port: int
|
|
||||||
val default_p2p: p2p
|
|
||||||
val default_config: t
|
|
||||||
|
|
||||||
val update:
|
|
||||||
?data_dir:string ->
|
|
||||||
?min_connections:int ->
|
|
||||||
?expected_connections:int ->
|
|
||||||
?max_connections:int ->
|
|
||||||
?max_download_speed:int ->
|
|
||||||
?max_upload_speed:int ->
|
|
||||||
?binary_chunks_size:int->
|
|
||||||
?peer_table_size:int ->
|
|
||||||
?expected_pow:float ->
|
|
||||||
?bootstrap_peers:string list ->
|
|
||||||
?listen_addr:string ->
|
|
||||||
?discovery_addr:string ->
|
|
||||||
?rpc_listen_addr:string ->
|
|
||||||
?private_mode:bool ->
|
|
||||||
?disable_mempool:bool ->
|
|
||||||
?cors_origins:string list ->
|
|
||||||
?cors_headers:string list ->
|
|
||||||
?rpc_tls:tls ->
|
|
||||||
?log_output:Logging_unix.Output.t ->
|
|
||||||
?bootstrap_threshold:int ->
|
|
||||||
t -> t tzresult Lwt.t
|
|
||||||
|
|
||||||
val to_string: t -> string
|
|
||||||
val read: string -> t tzresult Lwt.t
|
|
||||||
val write: string -> t -> unit tzresult Lwt.t
|
|
||||||
|
|
||||||
val resolve_listening_addrs: string -> (P2p_addr.t * int) list Lwt.t
|
|
||||||
val resolve_discovery_addrs: string -> (Ipaddr.V4.t * int) list Lwt.t
|
|
||||||
val resolve_rpc_listening_addrs: string -> (P2p_addr.t * int) list Lwt.t
|
|
||||||
val resolve_bootstrap_addrs: string list -> (P2p_addr.t * int) list Lwt.t
|
|
||||||
|
|
||||||
val encoding: t Data_encoding.t
|
|
||||||
|
|
||||||
val check: t -> unit Lwt.t
|
|
@ -1,136 +0,0 @@
|
|||||||
(*****************************************************************************)
|
|
||||||
(* *)
|
|
||||||
(* Open Source License *)
|
|
||||||
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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 = string
|
|
||||||
|
|
||||||
let data_version = "0.0.1"
|
|
||||||
|
|
||||||
let default_identity_file_name = "identity.json"
|
|
||||||
|
|
||||||
let version_encoding = Data_encoding.(obj1 (req "version" string))
|
|
||||||
|
|
||||||
let version_file_name = "version.json"
|
|
||||||
|
|
||||||
let pp ppf version = Format.pp_print_string ppf version
|
|
||||||
|
|
||||||
type error += Invalid_data_dir_version of t * t
|
|
||||||
type error += Invalid_data_dir of string
|
|
||||||
type error += No_data_dir_version_file of string
|
|
||||||
type error += Could_not_read_data_dir_version of string
|
|
||||||
|
|
||||||
let () =
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id: "invalidDataDir"
|
|
||||||
~title: "Invalid data directory"
|
|
||||||
~description: "The data directory cannot be accessed or created"
|
|
||||||
~pp:(fun ppf path ->
|
|
||||||
Format.fprintf ppf
|
|
||||||
"Invalid data directory '%s'."
|
|
||||||
path)
|
|
||||||
Data_encoding.(obj1 (req "datadir_path" string))
|
|
||||||
(function
|
|
||||||
| Invalid_data_dir path ->
|
|
||||||
Some path
|
|
||||||
| _ -> None)
|
|
||||||
(fun path -> Invalid_data_dir path) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id: "invalidDataDirVersion"
|
|
||||||
~title: "Invalid data directory version"
|
|
||||||
~description: "The data directory version was not the one that was expected"
|
|
||||||
~pp:(fun ppf (exp, got) ->
|
|
||||||
Format.fprintf ppf
|
|
||||||
"Invalid data directory version '%s' (expected '%s')."
|
|
||||||
got exp)
|
|
||||||
Data_encoding.(obj2
|
|
||||||
(req "expected_version" string)
|
|
||||||
(req "actual_version" string))
|
|
||||||
(function
|
|
||||||
| Invalid_data_dir_version (expected, actual) ->
|
|
||||||
Some (expected, actual)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (expected, actual) -> Invalid_data_dir_version (expected, actual)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id: "couldNotReadDataDirVersion"
|
|
||||||
~title: "Could not read data directory version file"
|
|
||||||
~description: "Data directory version file was invalid."
|
|
||||||
Data_encoding.(obj1 (req "version_path" string))
|
|
||||||
~pp:(fun ppf path ->
|
|
||||||
Format.fprintf ppf
|
|
||||||
"Tried to read version file at '%s', \
|
|
||||||
\ but the file could not be parsed."
|
|
||||||
path)
|
|
||||||
(function Could_not_read_data_dir_version path -> Some path | _ -> None)
|
|
||||||
(fun path -> Could_not_read_data_dir_version path);
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id: "noDataDirVersionFile"
|
|
||||||
~title: "Data directory version file does not exist"
|
|
||||||
~description: "Data directory version file does not exist"
|
|
||||||
Data_encoding.(obj1 (req "version_path" string))
|
|
||||||
~pp:(fun ppf path ->
|
|
||||||
Format.fprintf ppf
|
|
||||||
"Expected to find data directory version file at '%s', \
|
|
||||||
\ but the file does not exist."
|
|
||||||
path)
|
|
||||||
(function No_data_dir_version_file path -> Some path | _ -> None)
|
|
||||||
(fun path -> No_data_dir_version_file path)
|
|
||||||
|
|
||||||
let version_file data_dir =
|
|
||||||
(Filename.concat data_dir version_file_name)
|
|
||||||
|
|
||||||
let check_data_dir_version data_dir =
|
|
||||||
let version_file = version_file data_dir in
|
|
||||||
fail_unless (Sys.file_exists version_file)
|
|
||||||
(No_data_dir_version_file version_file) >>=? fun () ->
|
|
||||||
Lwt_utils_unix.Json.read_file version_file
|
|
||||||
|> trace (Could_not_read_data_dir_version version_file) >>=? fun json ->
|
|
||||||
begin
|
|
||||||
try return (Data_encoding.Json.destruct version_encoding json)
|
|
||||||
with _ -> fail (Could_not_read_data_dir_version version_file)
|
|
||||||
end >>=? fun version ->
|
|
||||||
fail_unless
|
|
||||||
(String.equal data_version version)
|
|
||||||
(Invalid_data_dir_version (data_version, version)) >>=? fun () ->
|
|
||||||
return_unit
|
|
||||||
|
|
||||||
let ensure_data_dir data_dir =
|
|
||||||
let write_version () =
|
|
||||||
Lwt_utils_unix.Json.write_file
|
|
||||||
(version_file data_dir)
|
|
||||||
(Data_encoding.Json.construct version_encoding data_version) in
|
|
||||||
try if Sys.file_exists data_dir then
|
|
||||||
match Sys.readdir data_dir with
|
|
||||||
| [||] -> write_version ()
|
|
||||||
| [| single |] when single = default_identity_file_name -> write_version ()
|
|
||||||
| _ -> check_data_dir_version data_dir
|
|
||||||
else begin
|
|
||||||
Lwt_utils_unix.create_dir ~perm:0o700 data_dir >>= fun () ->
|
|
||||||
write_version ()
|
|
||||||
end
|
|
||||||
with Sys_error _ | Unix.Unix_error _ ->
|
|
||||||
fail (Invalid_data_dir data_dir)
|
|
@ -1,38 +0,0 @@
|
|||||||
(*****************************************************************************)
|
|
||||||
(* *)
|
|
||||||
(* Open Source License *)
|
|
||||||
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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
|
|
||||||
|
|
||||||
type error += Invalid_data_dir_version of t * t
|
|
||||||
type error += Could_not_read_data_dir_version of string
|
|
||||||
|
|
||||||
val data_version : t
|
|
||||||
val default_identity_file_name : string
|
|
||||||
|
|
||||||
val pp : Format.formatter -> t -> unit
|
|
||||||
|
|
||||||
val version_encoding : t Data_encoding.encoding
|
|
||||||
|
|
||||||
val ensure_data_dir : string -> unit tzresult Lwt.t
|
|
@ -1,171 +0,0 @@
|
|||||||
(*****************************************************************************)
|
|
||||||
(* *)
|
|
||||||
(* Open Source License *)
|
|
||||||
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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. *)
|
|
||||||
(* *)
|
|
||||||
(*****************************************************************************)
|
|
||||||
|
|
||||||
let (//) = Filename.concat
|
|
||||||
|
|
||||||
(** Commands *)
|
|
||||||
|
|
||||||
let identity_file data_dir = data_dir // Node_data_version.default_identity_file_name
|
|
||||||
|
|
||||||
let show { Node_config_file.data_dir } =
|
|
||||||
Node_identity_file.read (identity_file data_dir) >>=? fun id ->
|
|
||||||
Format.printf "Peer_id: %a.@." P2p_peer.Id.pp id.peer_id ;
|
|
||||||
return_unit
|
|
||||||
|
|
||||||
let generate { Node_config_file.data_dir ; p2p } =
|
|
||||||
let identity_file = identity_file data_dir in
|
|
||||||
if Sys.file_exists identity_file then
|
|
||||||
fail (Node_identity_file.Existent_identity_file identity_file)
|
|
||||||
else
|
|
||||||
let target = Crypto_box.make_target p2p.expected_pow in
|
|
||||||
Format.eprintf "Generating a new identity... (level: %.2f) " p2p.expected_pow ;
|
|
||||||
let id =
|
|
||||||
P2p_identity.generate_with_animation Format.err_formatter target in
|
|
||||||
Node_identity_file.write identity_file id >>=? fun () ->
|
|
||||||
Format.eprintf
|
|
||||||
"Stored the new identity (%a) into '%s'.@."
|
|
||||||
P2p_peer.Id.pp id.peer_id identity_file ;
|
|
||||||
return_unit
|
|
||||||
|
|
||||||
let check { Node_config_file.data_dir ; p2p = { expected_pow } } =
|
|
||||||
Node_identity_file.read
|
|
||||||
~expected_pow (identity_file data_dir) >>=? fun id ->
|
|
||||||
Format.printf
|
|
||||||
"Peer_id: %a. Proof of work is higher than %.2f.@."
|
|
||||||
P2p_peer.Id.pp id.peer_id expected_pow ;
|
|
||||||
return_unit
|
|
||||||
|
|
||||||
(** Main *)
|
|
||||||
|
|
||||||
module Term = struct
|
|
||||||
|
|
||||||
type subcommand = Show | Generate | Check
|
|
||||||
|
|
||||||
let process subcommand data_dir config_file expected_pow =
|
|
||||||
let res =
|
|
||||||
begin
|
|
||||||
match data_dir, config_file with
|
|
||||||
| None, None ->
|
|
||||||
let default_config =
|
|
||||||
Node_config_file.default_data_dir // "config.json" in
|
|
||||||
if Sys.file_exists default_config then
|
|
||||||
Node_config_file.read default_config
|
|
||||||
else
|
|
||||||
return Node_config_file.default_config
|
|
||||||
| None, Some config_file ->
|
|
||||||
Node_config_file.read config_file
|
|
||||||
| Some data_dir, None ->
|
|
||||||
Node_config_file.read (data_dir // "config.json") >>=? fun cfg ->
|
|
||||||
return { cfg with data_dir }
|
|
||||||
| Some data_dir, Some config_file ->
|
|
||||||
Node_config_file.read config_file >>=? fun cfg ->
|
|
||||||
return { cfg with data_dir }
|
|
||||||
end >>=? fun cfg ->
|
|
||||||
Node_config_file.update ?expected_pow cfg >>=? fun cfg ->
|
|
||||||
match subcommand with
|
|
||||||
| Show -> show cfg
|
|
||||||
| Generate -> generate cfg
|
|
||||||
| Check -> check cfg in
|
|
||||||
match Lwt_main.run res with
|
|
||||||
| Ok () -> `Ok ()
|
|
||||||
| Error err -> `Error (false, Format.asprintf "%a" pp_print_error err)
|
|
||||||
|
|
||||||
let subcommand_arg =
|
|
||||||
let parser = function
|
|
||||||
| "show" -> `Ok Show
|
|
||||||
| "generate" -> `Ok Generate
|
|
||||||
| "check" -> `Ok Check
|
|
||||||
| s -> `Error ("invalid argument: " ^ s)
|
|
||||||
and printer fmt = function
|
|
||||||
| Show -> Format.fprintf fmt "show"
|
|
||||||
| Generate -> Format.fprintf fmt "generate"
|
|
||||||
| Check -> Format.fprintf fmt "check" in
|
|
||||||
let doc =
|
|
||||||
"Operation to perform. \
|
|
||||||
Possible values: $(b,show), $(b,generate), $(b,check)." in
|
|
||||||
let open Cmdliner.Arg in
|
|
||||||
value & pos 0 (parser, printer) Show & info [] ~docv:"OPERATION" ~doc
|
|
||||||
|
|
||||||
let expected_pow =
|
|
||||||
let open Cmdliner in
|
|
||||||
let doc =
|
|
||||||
"Expected amount of proof-of-work for the node identity. \
|
|
||||||
The optional parameter should be a float between 0 and 256, where
|
|
||||||
0 disables the proof-of-work mechanism." in
|
|
||||||
Arg.(value & pos 1 (some float) None & info [] ~docv:"DIFFICULTY" ~doc)
|
|
||||||
|
|
||||||
let term =
|
|
||||||
Cmdliner.Term.(ret (const process
|
|
||||||
$ subcommand_arg
|
|
||||||
$ Node_shared_arg.Term.data_dir
|
|
||||||
$ Node_shared_arg.Term.config_file
|
|
||||||
$ expected_pow))
|
|
||||||
end
|
|
||||||
|
|
||||||
module Manpage = struct
|
|
||||||
|
|
||||||
let command_description =
|
|
||||||
"The $(b,identity) command is meant to create and manage node \
|
|
||||||
identities. An $(i,identity) uniquely identifies a peer on the \
|
|
||||||
network and consists of a cryptographic key pair as well as a \
|
|
||||||
proof-of-work stamp that certifies \
|
|
||||||
that enough CPU time has been dedicated to produce the identity, \
|
|
||||||
to avoid sybil attacks. An identity with enough proof-of-work is \
|
|
||||||
required to participate in the Tezos network, therefore this command \
|
|
||||||
is necessary to launch Tezos the first time."
|
|
||||||
|
|
||||||
let description = [
|
|
||||||
`S "DESCRIPTION" ;
|
|
||||||
`P (command_description ^ " Several options are possible:");
|
|
||||||
`P "$(b,show) reads, parses and displays the current identity of the node. \
|
|
||||||
Use this command to see what identity will be used by Tezos. \
|
|
||||||
This is the default operation." ;
|
|
||||||
`P "$(b,generate [difficulty]) generates an identity whose \
|
|
||||||
proof of work stamp difficulty is at least equal to $(i,difficulty). \
|
|
||||||
The value provided must be a floating point number between 0 and 256. \
|
|
||||||
It roughly reflects the numbers of expected leading zeroes in the hash \
|
|
||||||
of the identity data-structure. \
|
|
||||||
Therefore, a value of 0 means no proof-of-work, and the difficulty \
|
|
||||||
doubles for each increment of 1 in the difficulty value." ;
|
|
||||||
`P "$(b,check [difficulty]) checks that an identity is valid and that its \
|
|
||||||
proof of work stamp difficulty is at least equal to $(i,difficulty)." ;
|
|
||||||
]
|
|
||||||
|
|
||||||
let man =
|
|
||||||
description @
|
|
||||||
(* [ `S misc_docs ] @ *)
|
|
||||||
Node_shared_arg.Manpage.bugs
|
|
||||||
|
|
||||||
let info =
|
|
||||||
Cmdliner.Term.info
|
|
||||||
~doc: "Manage node identities"
|
|
||||||
~man
|
|
||||||
"identity"
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
let cmd =
|
|
||||||
Term.term, Manpage.info
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
|||||||
(*****************************************************************************)
|
|
||||||
(* *)
|
|
||||||
(* Open Source License *)
|
|
||||||
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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. *)
|
|
||||||
(* *)
|
|
||||||
(*****************************************************************************)
|
|
||||||
|
|
||||||
val cmd: unit Cmdliner.Term.t * Cmdliner.Term.info
|
|
||||||
|
|
||||||
module Manpage : sig
|
|
||||||
val command_description: string
|
|
||||||
end
|
|
@ -1,158 +0,0 @@
|
|||||||
(*****************************************************************************)
|
|
||||||
(* *)
|
|
||||||
(* Open Source License *)
|
|
||||||
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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 error += No_identity_file of string
|
|
||||||
type error += Insufficient_proof_of_work of { expected: float }
|
|
||||||
type error += Identity_mismatch of {
|
|
||||||
filename: string ;
|
|
||||||
peer_id: Crypto_box.Public_key_hash.t ;
|
|
||||||
}
|
|
||||||
type error += Identity_keys_mismatch of {
|
|
||||||
filename: string ;
|
|
||||||
expected_key:Crypto_box.public_key ;
|
|
||||||
}
|
|
||||||
|
|
||||||
let () =
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"main.identity.no_file"
|
|
||||||
~title:"No identity file"
|
|
||||||
~description:"The node identity file cannot be found"
|
|
||||||
~pp:(fun ppf file ->
|
|
||||||
Format.fprintf ppf
|
|
||||||
"Cannot read the identity file: `%s`. \
|
|
||||||
See `%s identity --help` on how to generate an identity."
|
|
||||||
file Sys.argv.(0))
|
|
||||||
Data_encoding.(obj1 (req "file" string))
|
|
||||||
(function No_identity_file file -> Some file | _ -> None)
|
|
||||||
(fun file -> No_identity_file file)
|
|
||||||
|
|
||||||
let () =
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"main.identity.insufficient_proof_of_work"
|
|
||||||
~title:"Insufficient proof of work"
|
|
||||||
~description:"The proof of work embeded by the current identity is not sufficient"
|
|
||||||
~pp:(fun ppf expected ->
|
|
||||||
Format.fprintf ppf
|
|
||||||
"The current identity does not embed a sufficient stamp of proof-of-work. \
|
|
||||||
(expected level: %.2f). \
|
|
||||||
See `%s identity --help` on how to generate a new identity."
|
|
||||||
expected Sys.argv.(0))
|
|
||||||
Data_encoding.(obj1 (req "expected" float))
|
|
||||||
(function Insufficient_proof_of_work { expected } -> Some expected | _ -> None)
|
|
||||||
(fun expected -> Insufficient_proof_of_work { expected })
|
|
||||||
|
|
||||||
|
|
||||||
let () =
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"main.identity.identity_mismatch"
|
|
||||||
~title:"Identity mismatch"
|
|
||||||
~description:"The identity (public key hash) does not match the keys provided with it"
|
|
||||||
~pp:(fun ppf (file, public_key_hash) ->
|
|
||||||
Format.fprintf ppf
|
|
||||||
"The current identity (public key hash) does not match the keys in %s.
|
|
||||||
Expected identity %a."
|
|
||||||
file
|
|
||||||
Crypto_box.Public_key_hash.pp
|
|
||||||
public_key_hash)
|
|
||||||
Data_encoding.(obj2 (req "file" string) (req "public_key_hash" Crypto_box.Public_key_hash.encoding))
|
|
||||||
(function Identity_mismatch { filename ; peer_id } ->
|
|
||||||
Some (filename, peer_id) | _ -> None)
|
|
||||||
(fun (filename,peer_id) -> Identity_mismatch { filename ; peer_id })
|
|
||||||
|
|
||||||
let () =
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"main.identity.identity_keys_mismatch"
|
|
||||||
~title:"Identity keys mismatch"
|
|
||||||
~description:"The current identity file has non-matching keys (secret key/ public key pair is not valid)"
|
|
||||||
~pp:(fun ppf (file, public_key) ->
|
|
||||||
Format.fprintf ppf
|
|
||||||
"The current identity file %s has non-matching keys (secret key/ public key pair is not valid).
|
|
||||||
Expected public key %a."
|
|
||||||
file
|
|
||||||
Crypto_box.pp_pk
|
|
||||||
public_key)
|
|
||||||
Data_encoding.(obj2 (req "file" string) (req "public_key" Crypto_box.public_key_encoding))
|
|
||||||
(function
|
|
||||||
| Identity_keys_mismatch { filename ; expected_key } ->
|
|
||||||
Some (filename, expected_key)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (filename, expected_key) ->
|
|
||||||
Identity_keys_mismatch { filename ; expected_key })
|
|
||||||
|
|
||||||
let read ?expected_pow filename =
|
|
||||||
Lwt_unix.file_exists filename >>= function
|
|
||||||
| false ->
|
|
||||||
fail (No_identity_file filename)
|
|
||||||
| true ->
|
|
||||||
Lwt_utils_unix.Json.read_file filename >>=? fun json ->
|
|
||||||
let id = Data_encoding.Json.destruct P2p_identity.encoding json in
|
|
||||||
let pkh = Crypto_box.hash id.public_key in
|
|
||||||
(* check public_key hash *)
|
|
||||||
if not (Crypto_box.Public_key_hash.equal pkh id.peer_id) then
|
|
||||||
fail (Identity_mismatch { filename ; peer_id = pkh })
|
|
||||||
(* check public/private keys correspondance *)
|
|
||||||
else if not Crypto_box.(equal (neuterize id.secret_key) id.public_key) then
|
|
||||||
fail (Identity_keys_mismatch { filename ; expected_key = id.public_key })
|
|
||||||
else (* check PoW level *)
|
|
||||||
match expected_pow with
|
|
||||||
| None -> return id
|
|
||||||
| Some expected ->
|
|
||||||
let target = Crypto_box.make_target expected in
|
|
||||||
if
|
|
||||||
not (Crypto_box.check_proof_of_work
|
|
||||||
id.public_key id.proof_of_work_stamp target)
|
|
||||||
then
|
|
||||||
fail (Insufficient_proof_of_work { expected })
|
|
||||||
else
|
|
||||||
return id
|
|
||||||
|
|
||||||
type error += Existent_identity_file of string
|
|
||||||
|
|
||||||
let () =
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"main.identity.existent_file"
|
|
||||||
~title:"Cannot overwrite identity file"
|
|
||||||
~description:"Cannot implicitely overwrite the current identity file"
|
|
||||||
~pp:(fun ppf file ->
|
|
||||||
Format.fprintf ppf
|
|
||||||
"Cannot implicitely overwrite the current identity file: '%s'. \
|
|
||||||
See `%s identity --help` on how to generate a new identity."
|
|
||||||
file Sys.argv.(0))
|
|
||||||
Data_encoding.(obj1 (req "file" string))
|
|
||||||
(function Existent_identity_file file -> Some file | _ -> None)
|
|
||||||
(fun file -> Existent_identity_file file)
|
|
||||||
|
|
||||||
let write file identity =
|
|
||||||
if Sys.file_exists file then
|
|
||||||
fail (Existent_identity_file file)
|
|
||||||
else
|
|
||||||
Node_data_version.ensure_data_dir (Filename.dirname file) >>=? fun () ->
|
|
||||||
Lwt_utils_unix.Json.write_file file
|
|
||||||
(Data_encoding.Json.construct P2p_identity.encoding identity)
|
|
@ -1,35 +0,0 @@
|
|||||||
(*****************************************************************************)
|
|
||||||
(* *)
|
|
||||||
(* Open Source License *)
|
|
||||||
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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 error += No_identity_file of string
|
|
||||||
type error += Insufficient_proof_of_work of { expected: float }
|
|
||||||
|
|
||||||
val read:
|
|
||||||
?expected_pow:float ->
|
|
||||||
string -> P2p_identity.t tzresult Lwt.t
|
|
||||||
|
|
||||||
type error += Existent_identity_file of string
|
|
||||||
|
|
||||||
val write: string -> P2p_identity.t -> unit tzresult Lwt.t
|
|
@ -1,26 +0,0 @@
|
|||||||
(*****************************************************************************)
|
|
||||||
(* *)
|
|
||||||
(* Open Source License *)
|
|
||||||
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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. *)
|
|
||||||
(* *)
|
|
||||||
(*****************************************************************************)
|
|
||||||
|
|
||||||
include Tezos_stdlib.Logging.Make(struct let name = "node.main" end)
|
|
@ -1,26 +0,0 @@
|
|||||||
(*****************************************************************************)
|
|
||||||
(* *)
|
|
||||||
(* Open Source License *)
|
|
||||||
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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. *)
|
|
||||||
(* *)
|
|
||||||
(*****************************************************************************)
|
|
||||||
|
|
||||||
include Tezos_stdlib.Logging.LOG
|
|
@ -1,438 +0,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. *)
|
|
||||||
(* *)
|
|
||||||
(*****************************************************************************)
|
|
||||||
|
|
||||||
open Node_logging
|
|
||||||
|
|
||||||
let genesis : State.Chain.genesis = {
|
|
||||||
time =
|
|
||||||
Time.of_notation_exn "2018-06-30T16:07:32Z" ;
|
|
||||||
block =
|
|
||||||
Block_hash.of_b58check_exn
|
|
||||||
"BLockGenesisGenesisGenesisGenesisGenesisf79b5d1CoW2" ;
|
|
||||||
protocol =
|
|
||||||
Protocol_hash.of_b58check_exn
|
|
||||||
"ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im" ;
|
|
||||||
}
|
|
||||||
|
|
||||||
type error += Non_private_sandbox of P2p_addr.t
|
|
||||||
type error += RPC_Port_already_in_use of P2p_point.Id.t list
|
|
||||||
|
|
||||||
let () =
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"main.run.non_private_sandbox"
|
|
||||||
~title:"Forbidden public sandbox"
|
|
||||||
~description:"A sandboxed node should not listen on a public address."
|
|
||||||
~pp:begin fun ppf addr ->
|
|
||||||
Format.fprintf ppf
|
|
||||||
"The node is configured to listen on a public address (%a), \
|
|
||||||
while only 'private' networks are authorised with `--sandbox`.
|
|
||||||
See `%s run --help` on how to change the listening address."
|
|
||||||
Ipaddr.V6.pp addr Sys.argv.(0)
|
|
||||||
end
|
|
||||||
Data_encoding.(obj1 (req "addr" P2p_addr.encoding))
|
|
||||||
(function Non_private_sandbox addr -> Some addr | _ -> None)
|
|
||||||
(fun addr -> Non_private_sandbox addr);
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"main.run.port_already_in_use"
|
|
||||||
~title:"Cannot start sode: RPC port already in use"
|
|
||||||
~description:"An other tezos node is probably running on the same RPC port."
|
|
||||||
~pp:begin fun ppf addrlist ->
|
|
||||||
Format.fprintf ppf
|
|
||||||
"An other tezos node is probably running on one of these addresses (%a). \
|
|
||||||
Please choose another RPC port."
|
|
||||||
(Format.pp_print_list P2p_point.Id.pp) addrlist
|
|
||||||
end
|
|
||||||
Data_encoding.(obj1 (req "addrlist" (list P2p_point.Id.encoding)))
|
|
||||||
(function | RPC_Port_already_in_use addrlist -> Some addrlist | _ -> None)
|
|
||||||
(fun addrlist -> RPC_Port_already_in_use addrlist)
|
|
||||||
|
|
||||||
let (//) = Filename.concat
|
|
||||||
|
|
||||||
let store_dir data_dir = data_dir // "store"
|
|
||||||
let context_dir data_dir = data_dir // "context"
|
|
||||||
let protocol_dir data_dir = data_dir // "protocol"
|
|
||||||
let lock_file data_dir = data_dir // "lock"
|
|
||||||
|
|
||||||
let init_node ?sandbox ?checkpoint (config : Node_config_file.t) =
|
|
||||||
let patch_context json ctxt =
|
|
||||||
begin
|
|
||||||
match json with
|
|
||||||
| None -> Lwt.return ctxt
|
|
||||||
| Some json ->
|
|
||||||
Tezos_storage.Context.set ctxt
|
|
||||||
["sandbox_parameter"]
|
|
||||||
(Data_encoding.Binary.to_bytes_exn Data_encoding.json json)
|
|
||||||
end >>= fun ctxt ->
|
|
||||||
let module Proto = (val Registered_protocol.get_exn genesis.protocol) in
|
|
||||||
Proto.init ctxt {
|
|
||||||
level = 0l ;
|
|
||||||
proto_level = 0 ;
|
|
||||||
predecessor = genesis.block ;
|
|
||||||
timestamp = genesis.time ;
|
|
||||||
validation_passes = 0 ;
|
|
||||||
operations_hash = Operation_list_list_hash.empty ;
|
|
||||||
fitness = [] ;
|
|
||||||
context = Context_hash.zero ;
|
|
||||||
} >>= function
|
|
||||||
| Error _ -> assert false (* FIXME error *)
|
|
||||||
| Ok { context = ctxt ; _ } ->
|
|
||||||
Lwt.return ctxt in
|
|
||||||
begin
|
|
||||||
match sandbox with
|
|
||||||
| None -> Lwt.return_none
|
|
||||||
| Some sandbox_param ->
|
|
||||||
match sandbox_param with
|
|
||||||
| None -> Lwt.return_none
|
|
||||||
| Some file ->
|
|
||||||
Lwt_utils_unix.Json.read_file file >>= function
|
|
||||||
| Error err ->
|
|
||||||
lwt_warn
|
|
||||||
"Can't parse sandbox parameters: %s" file >>= fun () ->
|
|
||||||
lwt_debug "%a" pp_print_error err >>= fun () ->
|
|
||||||
Lwt.return_none
|
|
||||||
| Ok json ->
|
|
||||||
Lwt.return_some json
|
|
||||||
end >>= fun sandbox_param ->
|
|
||||||
(* TODO "WARN" when pow is below our expectation. *)
|
|
||||||
begin
|
|
||||||
match config.p2p.discovery_addr with
|
|
||||||
| None ->
|
|
||||||
lwt_log_notice "No local peer discovery." >>= fun () ->
|
|
||||||
return (None, None)
|
|
||||||
| Some addr ->
|
|
||||||
Node_config_file.resolve_discovery_addrs addr >>= function
|
|
||||||
| [] ->
|
|
||||||
failwith "Cannot resolve P2P discovery address: %S" addr
|
|
||||||
| (addr, port) :: _ ->
|
|
||||||
return (Some addr, Some port)
|
|
||||||
end >>=? fun (discovery_addr, discovery_port) ->
|
|
||||||
begin
|
|
||||||
match config.p2p.listen_addr with
|
|
||||||
| None ->
|
|
||||||
lwt_log_notice "Not listening to P2P calls." >>= fun () ->
|
|
||||||
return (None, None)
|
|
||||||
| Some addr ->
|
|
||||||
Node_config_file.resolve_listening_addrs addr >>= function
|
|
||||||
| [] ->
|
|
||||||
failwith "Cannot resolve P2P listening address: %S" addr
|
|
||||||
| (addr, port) :: _ -> return (Some addr, Some port)
|
|
||||||
end >>=? fun (listening_addr, listening_port) ->
|
|
||||||
begin
|
|
||||||
match listening_addr, sandbox with
|
|
||||||
| Some addr, Some _
|
|
||||||
when Ipaddr.V6.(compare addr unspecified) = 0 ->
|
|
||||||
return_none
|
|
||||||
| Some addr, Some _ when not (Ipaddr.V6.is_private addr) ->
|
|
||||||
fail (Non_private_sandbox addr)
|
|
||||||
| None, Some _ -> return_none
|
|
||||||
| _ ->
|
|
||||||
(Node_config_file.resolve_bootstrap_addrs
|
|
||||||
config.p2p.bootstrap_peers) >>= fun trusted_points ->
|
|
||||||
Node_identity_file.read
|
|
||||||
(config.data_dir //
|
|
||||||
Node_data_version.default_identity_file_name) >>=? fun identity ->
|
|
||||||
lwt_log_notice
|
|
||||||
"Peer's global id: %a"
|
|
||||||
P2p_peer.Id.pp identity.peer_id >>= fun () ->
|
|
||||||
let p2p_config : P2p.config =
|
|
||||||
{ listening_addr ;
|
|
||||||
listening_port ;
|
|
||||||
discovery_addr ;
|
|
||||||
discovery_port ;
|
|
||||||
trusted_points ;
|
|
||||||
peers_file =
|
|
||||||
(config.data_dir // "peers.json") ;
|
|
||||||
private_mode = config.p2p.private_mode ;
|
|
||||||
identity ;
|
|
||||||
proof_of_work_target =
|
|
||||||
Crypto_box.make_target config.p2p.expected_pow ;
|
|
||||||
disable_mempool = config.p2p.disable_mempool ;
|
|
||||||
trust_discovered_peers = (sandbox_param <> None) ;
|
|
||||||
}
|
|
||||||
in
|
|
||||||
return_some (p2p_config, config.p2p.limits)
|
|
||||||
end >>=? fun p2p_config ->
|
|
||||||
let node_config : Node.config = {
|
|
||||||
genesis ;
|
|
||||||
patch_context = Some (patch_context sandbox_param) ;
|
|
||||||
store_root = store_dir config.data_dir ;
|
|
||||||
context_root = context_dir config.data_dir ;
|
|
||||||
p2p = p2p_config ;
|
|
||||||
test_chain_max_tll = Some (48 * 3600) ; (* 2 days *)
|
|
||||||
checkpoint ;
|
|
||||||
} in
|
|
||||||
Node.create
|
|
||||||
~sandboxed:(sandbox <> None)
|
|
||||||
node_config
|
|
||||||
config.shell.peer_validator_limits
|
|
||||||
config.shell.block_validator_limits
|
|
||||||
config.shell.prevalidator_limits
|
|
||||||
config.shell.chain_validator_limits
|
|
||||||
|
|
||||||
(* Add default accepted CORS headers *)
|
|
||||||
let sanitize_cors_headers ~default headers =
|
|
||||||
List.map String.lowercase_ascii headers |>
|
|
||||||
String.Set.of_list |>
|
|
||||||
String.Set.(union (of_list default)) |>
|
|
||||||
String.Set.elements
|
|
||||||
|
|
||||||
let launch_rpc_server
|
|
||||||
(rpc_config : Node_config_file.rpc) node (addr, port) =
|
|
||||||
let host = Ipaddr.V6.to_string addr in
|
|
||||||
let dir = Node.build_rpc_directory node in
|
|
||||||
let mode =
|
|
||||||
match rpc_config.tls with
|
|
||||||
| None -> `TCP (`Port port)
|
|
||||||
| Some { cert ; key } ->
|
|
||||||
`TLS (`Crt_file_path cert, `Key_file_path key,
|
|
||||||
`No_password, `Port port) in
|
|
||||||
lwt_log_notice
|
|
||||||
"Starting a RPC server listening on %s:%d%s."
|
|
||||||
host port
|
|
||||||
(if rpc_config.tls = None then "" else " (TLS enabled)") >>= fun () ->
|
|
||||||
let cors_headers =
|
|
||||||
sanitize_cors_headers
|
|
||||||
~default:["Content-Type"] rpc_config.cors_headers in
|
|
||||||
Lwt.catch begin fun () ->
|
|
||||||
RPC_server.launch ~host mode dir
|
|
||||||
~media_types:Media_type.all_media_types
|
|
||||||
~cors:{ allowed_origins = rpc_config.cors_origins ;
|
|
||||||
allowed_headers = cors_headers } >>= return
|
|
||||||
end begin function
|
|
||||||
| Unix.Unix_error(Unix.EADDRINUSE, "bind","") ->
|
|
||||||
fail (RPC_Port_already_in_use [(addr,port)])
|
|
||||||
| exn -> Lwt.return (error_exn exn)
|
|
||||||
end
|
|
||||||
|
|
||||||
let init_rpc (rpc_config: Node_config_file.rpc) node =
|
|
||||||
match rpc_config.listen_addr with
|
|
||||||
| None ->
|
|
||||||
lwt_log_notice "Not listening to RPC calls." >>= fun () ->
|
|
||||||
return_nil
|
|
||||||
| Some addr ->
|
|
||||||
Node_config_file.resolve_rpc_listening_addrs addr >>= function
|
|
||||||
| [] ->
|
|
||||||
failwith "Cannot resolve listening address: %S" addr
|
|
||||||
| addrs ->
|
|
||||||
map_s (launch_rpc_server rpc_config node) addrs
|
|
||||||
|
|
||||||
let init_signal () =
|
|
||||||
let handler name id = try
|
|
||||||
fatal_error "Received the %s signal, triggering shutdown." name ;
|
|
||||||
Lwt_exit.exit id
|
|
||||||
with _ -> () in
|
|
||||||
ignore (Lwt_unix.on_signal Sys.sigint (handler "INT") : Lwt_unix.signal_handler_id) ;
|
|
||||||
ignore (Lwt_unix.on_signal Sys.sigterm (handler "TERM") : Lwt_unix.signal_handler_id)
|
|
||||||
|
|
||||||
let run ?verbosity ?sandbox ?checkpoint (config : Node_config_file.t) =
|
|
||||||
Node_data_version.ensure_data_dir config.data_dir >>=? fun () ->
|
|
||||||
Lwt_lock_file.create
|
|
||||||
~unlink_on_exit:true (lock_file config.data_dir) >>=? fun () ->
|
|
||||||
init_signal () ;
|
|
||||||
let log_cfg =
|
|
||||||
match verbosity with
|
|
||||||
| None -> config.log
|
|
||||||
| Some default_level -> { config.log with default_level } in
|
|
||||||
Logging_unix.init ~cfg:log_cfg () >>= fun () ->
|
|
||||||
Updater.init (protocol_dir config.data_dir) ;
|
|
||||||
lwt_log_notice "Starting the Tezos node..." >>= fun () ->
|
|
||||||
init_node ?sandbox ?checkpoint config >>=? fun node ->
|
|
||||||
init_rpc config.rpc node >>=? fun rpc ->
|
|
||||||
lwt_log_notice "The Tezos node is now running!" >>= fun () ->
|
|
||||||
Lwt_exit.termination_thread >>= fun x ->
|
|
||||||
lwt_log_notice "Shutting down the Tezos node..." >>= fun () ->
|
|
||||||
Node.shutdown node >>= fun () ->
|
|
||||||
lwt_log_notice "Shutting down the RPC server..." >>= fun () ->
|
|
||||||
Lwt_list.iter_s RPC_server.shutdown rpc >>= fun () ->
|
|
||||||
lwt_log_notice "BYE (%d)" x >>= fun () ->
|
|
||||||
Logging_unix.close () >>= fun () ->
|
|
||||||
return_unit
|
|
||||||
|
|
||||||
let process sandbox verbosity checkpoint args =
|
|
||||||
let verbosity =
|
|
||||||
match verbosity with
|
|
||||||
| [] -> None
|
|
||||||
| [_] -> Some Logging.Info
|
|
||||||
| _ -> Some Logging.Debug in
|
|
||||||
let run =
|
|
||||||
Node_shared_arg.read_and_patch_config_file
|
|
||||||
~ignore_bootstrap_peers:(match sandbox with
|
|
||||||
| Some _ -> true
|
|
||||||
| None -> false)
|
|
||||||
args >>=? fun config ->
|
|
||||||
begin match sandbox with
|
|
||||||
| Some _ ->
|
|
||||||
if config.data_dir = Node_config_file.default_data_dir
|
|
||||||
then failwith "Cannot use default data directory while in sandbox mode"
|
|
||||||
else return_unit
|
|
||||||
| None -> return_unit
|
|
||||||
end >>=? fun () ->
|
|
||||||
begin
|
|
||||||
match checkpoint with
|
|
||||||
| None -> return_none
|
|
||||||
| Some s ->
|
|
||||||
match String.split ',' s with
|
|
||||||
| [ lvl ; block ] ->
|
|
||||||
Lwt.return (Block_hash.of_b58check block) >>=? fun block ->
|
|
||||||
begin
|
|
||||||
match Int32.of_string_opt lvl with
|
|
||||||
| None ->
|
|
||||||
failwith "%s isn't a 32bit integer" lvl
|
|
||||||
| Some lvl ->
|
|
||||||
return lvl
|
|
||||||
end >>=? fun lvl ->
|
|
||||||
return_some (lvl, block)
|
|
||||||
| [] -> assert false
|
|
||||||
| [_] ->
|
|
||||||
failwith "Checkoints are expected to follow the format \
|
|
||||||
\"<level>,<block_hash>\". \
|
|
||||||
The character ',' is not present in %s" s
|
|
||||||
| _ ->
|
|
||||||
failwith "Checkoints are expected to follow the format \
|
|
||||||
\"<level>,<block_hash>\". \
|
|
||||||
The character ',' is present more than once in %s" s
|
|
||||||
end >>=? fun checkpoint ->
|
|
||||||
Lwt_lock_file.is_locked
|
|
||||||
(lock_file config.data_dir) >>=? function
|
|
||||||
| false ->
|
|
||||||
Lwt.catch
|
|
||||||
(fun () -> run ?sandbox ?verbosity ?checkpoint config)
|
|
||||||
(function
|
|
||||||
|Unix.Unix_error(Unix.EADDRINUSE, "bind","") ->
|
|
||||||
begin match config.rpc.listen_addr with
|
|
||||||
| None -> assert false
|
|
||||||
| Some addr ->
|
|
||||||
Node_config_file.resolve_rpc_listening_addrs addr >>= fun addrlist ->
|
|
||||||
fail (RPC_Port_already_in_use addrlist)
|
|
||||||
end
|
|
||||||
| exn -> Lwt.return (error_exn exn)
|
|
||||||
)
|
|
||||||
| true -> failwith "Data directory is locked by another process" in
|
|
||||||
match Lwt_main.run run with
|
|
||||||
| Ok () -> `Ok ()
|
|
||||||
| Error err -> `Error (false, Format.asprintf "%a" pp_print_error err)
|
|
||||||
|
|
||||||
module Term = struct
|
|
||||||
|
|
||||||
let verbosity =
|
|
||||||
let open Cmdliner in
|
|
||||||
let doc =
|
|
||||||
"Increase log level. Using $(b,-v) is equivalent to \
|
|
||||||
using $(b,TEZOS_LOG='* -> info'), and $(b,-vv) is equivalent to using \
|
|
||||||
$(b,TEZOS_LOG='* -> debug')." in
|
|
||||||
Arg.(value & flag_all &
|
|
||||||
info ~docs:Node_shared_arg.Manpage.misc_section ~doc ["v"])
|
|
||||||
|
|
||||||
let sandbox =
|
|
||||||
let open Cmdliner in
|
|
||||||
let doc =
|
|
||||||
"Run the daemon in sandbox mode. \
|
|
||||||
P2P to non-localhost addresses are disabled, and constants of \
|
|
||||||
the economic protocol can be altered with an optional JSON file. \
|
|
||||||
$(b,IMPORTANT): Using sandbox mode affects the node state and \
|
|
||||||
subsequent runs of Tezos node must also use sandbox mode. \
|
|
||||||
In order to run the node in normal mode afterwards, a full reset \
|
|
||||||
must be performed (by removing the node's data directory)."
|
|
||||||
in
|
|
||||||
Arg.(value & opt ~vopt:(Some None) (some (some string)) None &
|
|
||||||
info ~docs:Node_shared_arg.Manpage.misc_section
|
|
||||||
~doc ~docv:"FILE.json" ["sandbox"])
|
|
||||||
|
|
||||||
let checkpoint =
|
|
||||||
let open Cmdliner in
|
|
||||||
let doc =
|
|
||||||
"When asked to take a block hash as a checkpoint, the daemon \
|
|
||||||
will only accept the chains that contains that block and those \
|
|
||||||
that might reach it."
|
|
||||||
in
|
|
||||||
Arg.(value & opt (some string) None &
|
|
||||||
info ~docs:Node_shared_arg.Manpage.misc_section
|
|
||||||
~doc ~docv:"<level>,<block_hash>" ["checkpoint"])
|
|
||||||
|
|
||||||
let term =
|
|
||||||
Cmdliner.Term.(ret (const process $ sandbox $ verbosity $ checkpoint $
|
|
||||||
Node_shared_arg.Term.args))
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
module Manpage = struct
|
|
||||||
|
|
||||||
let command_description =
|
|
||||||
"The $(b,run) command is meant to run the Tezos node. \
|
|
||||||
Most of its command line arguments corresponds to config file \
|
|
||||||
entries, and will have priority over the latter if used."
|
|
||||||
|
|
||||||
let description = [
|
|
||||||
`S "DESCRIPTION" ;
|
|
||||||
`P command_description ;
|
|
||||||
]
|
|
||||||
|
|
||||||
let debug =
|
|
||||||
let log_sections = String.concat " " (List.rev !Logging.sections) in
|
|
||||||
[
|
|
||||||
`S "DEBUG" ;
|
|
||||||
`P ("The environment variable $(b,TEZOS_LOG) is used to fine-tune \
|
|
||||||
what is going to be logged. The syntax is \
|
|
||||||
$(b,TEZOS_LOG='<section> -> <level> [ ; ...]') \
|
|
||||||
where section is one of $(i,"
|
|
||||||
^ log_sections ^
|
|
||||||
") and level is one of $(i,fatal), $(i,error), $(i,warn), \
|
|
||||||
$(i,notice), $(i,info) or $(i,debug). \
|
|
||||||
A $(b,*) can be used as a wildcard \
|
|
||||||
in sections, i.e. $(b, client* -> debug). \
|
|
||||||
The rules are matched left to right, \
|
|
||||||
therefore the leftmost rule is highest priority ."
|
|
||||||
) ;
|
|
||||||
]
|
|
||||||
|
|
||||||
let examples =
|
|
||||||
[
|
|
||||||
`S "EXAMPLES" ;
|
|
||||||
`I ("$(b,Run in sandbox mode listening to RPC commands \
|
|
||||||
at localhost port 8732)",
|
|
||||||
"$(mname) run --sandbox --data-dir /custom/data/dir \
|
|
||||||
--rpc-addr localhost:8732" ) ;
|
|
||||||
`I ("$(b,Run a node that accepts network connections)",
|
|
||||||
"$(mname) run" ) ;
|
|
||||||
]
|
|
||||||
|
|
||||||
let man =
|
|
||||||
description @
|
|
||||||
Node_shared_arg.Manpage.args @
|
|
||||||
examples @
|
|
||||||
Node_shared_arg.Manpage.bugs
|
|
||||||
|
|
||||||
let info =
|
|
||||||
Cmdliner.Term.info
|
|
||||||
~doc:"Run the Tezos node"
|
|
||||||
~man
|
|
||||||
"run"
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
let cmd = Term.term, Manpage.info
|
|
@ -1,31 +0,0 @@
|
|||||||
(*****************************************************************************)
|
|
||||||
(* *)
|
|
||||||
(* Open Source License *)
|
|
||||||
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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. *)
|
|
||||||
(* *)
|
|
||||||
(*****************************************************************************)
|
|
||||||
|
|
||||||
val cmd: unit Cmdliner.Term.t * Cmdliner.Term.info
|
|
||||||
|
|
||||||
module Manpage : sig
|
|
||||||
val command_description: string
|
|
||||||
val examples: Cmdliner.Manpage.block list
|
|
||||||
end
|
|
@ -1,339 +0,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. *)
|
|
||||||
(* *)
|
|
||||||
(*****************************************************************************)
|
|
||||||
|
|
||||||
open Cmdliner
|
|
||||||
open Node_logging
|
|
||||||
|
|
||||||
let (//) = Filename.concat
|
|
||||||
|
|
||||||
type t = {
|
|
||||||
data_dir: string option ;
|
|
||||||
config_file: string ;
|
|
||||||
min_connections: int option ;
|
|
||||||
expected_connections: int option ;
|
|
||||||
max_connections: int option ;
|
|
||||||
max_download_speed: int option ;
|
|
||||||
max_upload_speed: int option ;
|
|
||||||
binary_chunks_size: int option ;
|
|
||||||
peer_table_size: int option ;
|
|
||||||
expected_pow: float option ;
|
|
||||||
peers: string list ;
|
|
||||||
no_bootstrap_peers: bool ;
|
|
||||||
listen_addr: string option ;
|
|
||||||
discovery_addr: string option ;
|
|
||||||
rpc_listen_addr: string option ;
|
|
||||||
private_mode: bool ;
|
|
||||||
disable_mempool: bool ;
|
|
||||||
cors_origins: string list ;
|
|
||||||
cors_headers: string list ;
|
|
||||||
rpc_tls: Node_config_file.tls option ;
|
|
||||||
log_output: Logging_unix.Output.t option ;
|
|
||||||
bootstrap_threshold: int option ;
|
|
||||||
}
|
|
||||||
|
|
||||||
let wrap
|
|
||||||
data_dir config_file
|
|
||||||
connections max_download_speed max_upload_speed binary_chunks_size
|
|
||||||
peer_table_size
|
|
||||||
listen_addr discovery_addr peers no_bootstrap_peers
|
|
||||||
bootstrap_threshold private_mode disable_mempool
|
|
||||||
expected_pow rpc_listen_addr rpc_tls
|
|
||||||
cors_origins cors_headers log_output =
|
|
||||||
|
|
||||||
let actual_data_dir =
|
|
||||||
Option.unopt ~default:Node_config_file.default_data_dir data_dir in
|
|
||||||
|
|
||||||
let config_file =
|
|
||||||
Option.unopt ~default:(actual_data_dir // "config.json") config_file in
|
|
||||||
|
|
||||||
let rpc_tls =
|
|
||||||
Option.map
|
|
||||||
~f:(fun (cert, key) -> { Node_config_file.cert ; key })
|
|
||||||
rpc_tls in
|
|
||||||
|
|
||||||
(* when `--connections` is used,
|
|
||||||
override all the bounds defined in the configuration file. *)
|
|
||||||
let bootstrap_threshold,
|
|
||||||
min_connections, expected_connections, max_connections,
|
|
||||||
peer_table_size =
|
|
||||||
match connections with
|
|
||||||
| None -> bootstrap_threshold, None, None, None, peer_table_size
|
|
||||||
| Some x ->
|
|
||||||
let peer_table_size =
|
|
||||||
match peer_table_size with
|
|
||||||
| None -> Some (8*x)
|
|
||||||
| Some _ -> peer_table_size in
|
|
||||||
begin match bootstrap_threshold with
|
|
||||||
| None -> Some (min (x/4) 2), Some (x/2), Some x, Some (3*x/2), peer_table_size
|
|
||||||
| Some bs -> Some bs, Some (x/2), Some x, Some (3*x/2), peer_table_size
|
|
||||||
end
|
|
||||||
in
|
|
||||||
{ data_dir ;
|
|
||||||
config_file ;
|
|
||||||
min_connections ;
|
|
||||||
expected_connections ;
|
|
||||||
max_connections ;
|
|
||||||
max_download_speed ;
|
|
||||||
max_upload_speed ;
|
|
||||||
binary_chunks_size ;
|
|
||||||
expected_pow ;
|
|
||||||
peers ;
|
|
||||||
no_bootstrap_peers ;
|
|
||||||
listen_addr ;
|
|
||||||
discovery_addr ;
|
|
||||||
rpc_listen_addr ;
|
|
||||||
private_mode ;
|
|
||||||
disable_mempool ;
|
|
||||||
cors_origins ;
|
|
||||||
cors_headers ;
|
|
||||||
rpc_tls ;
|
|
||||||
log_output ;
|
|
||||||
peer_table_size ;
|
|
||||||
bootstrap_threshold ;
|
|
||||||
}
|
|
||||||
|
|
||||||
module Manpage = struct
|
|
||||||
|
|
||||||
let misc_section = "MISC OPTIONS"
|
|
||||||
let p2p_section = "P2P OPTIONS"
|
|
||||||
let rpc_section = "RPC OPTIONS"
|
|
||||||
|
|
||||||
let args = [
|
|
||||||
`S p2p_section ;
|
|
||||||
`S rpc_section ;
|
|
||||||
`S misc_section ;
|
|
||||||
]
|
|
||||||
|
|
||||||
let bugs = [
|
|
||||||
`S "BUGS";
|
|
||||||
`P "Check bug reports at https://gitlab.com/tezos/tezos/issues.";
|
|
||||||
]
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
module Term = struct
|
|
||||||
|
|
||||||
let log_output_converter =
|
|
||||||
(fun s -> match Logging_unix.Output.of_string s with
|
|
||||||
| Some res -> `Ok res
|
|
||||||
| None -> `Error s),
|
|
||||||
Logging_unix.Output.pp
|
|
||||||
|
|
||||||
(* misc args *)
|
|
||||||
|
|
||||||
let docs = Manpage.misc_section
|
|
||||||
|
|
||||||
let log_output =
|
|
||||||
let doc =
|
|
||||||
"Log output. Either $(i,stdout), $(i,stderr), \
|
|
||||||
$(i,syslog:<facility>) or a file path." in
|
|
||||||
Arg.(value & opt (some log_output_converter) None &
|
|
||||||
info ~docs ~docv:"OUTPUT" ~doc ["log-output"])
|
|
||||||
|
|
||||||
let data_dir =
|
|
||||||
let doc =
|
|
||||||
"The directory where the Tezos node will store all its data." in
|
|
||||||
Arg.(value & opt (some string) None &
|
|
||||||
info ~docs ~doc ~docv:"DIR" ["data-dir"])
|
|
||||||
|
|
||||||
let config_file =
|
|
||||||
let doc = "The main configuration file." in
|
|
||||||
Arg.(value & opt (some string) None &
|
|
||||||
info ~docs ~doc ~docv:"FILE" ["config-file"])
|
|
||||||
|
|
||||||
(* P2p args *)
|
|
||||||
|
|
||||||
let docs = Manpage.p2p_section
|
|
||||||
|
|
||||||
let connections =
|
|
||||||
let doc =
|
|
||||||
"Sets min_connections, expected_connections, max_connections to NUM / 2, \
|
|
||||||
NUM, (3 * NUM) / 2, respectively. Sets peer_table_size to 8 * NUM \
|
|
||||||
unless it is already defined in the configuration file. Sets \
|
|
||||||
bootstrap_threshold to min(NUM / 4, 2) unless it is already defined in \
|
|
||||||
the configuration file." in
|
|
||||||
Arg.(value & opt (some int) None &
|
|
||||||
info ~docs ~doc ~docv:"NUM" ["connections"])
|
|
||||||
|
|
||||||
let max_download_speed =
|
|
||||||
let doc =
|
|
||||||
"The maximum number of bytes read per second." in
|
|
||||||
Arg.(value & opt (some int) None &
|
|
||||||
info ~docs ~doc ~docv:"NUM" ["max-download-speed"])
|
|
||||||
|
|
||||||
let max_upload_speed =
|
|
||||||
let doc =
|
|
||||||
"The maximum number of bytes sent per second." in
|
|
||||||
Arg.(value & opt (some int) None &
|
|
||||||
info ~docs ~doc ~docv:"NUM" ["max-upload-speed"])
|
|
||||||
|
|
||||||
let binary_chunks_size =
|
|
||||||
let doc =
|
|
||||||
"Size limit (in kB) of binary blocks that are sent to other peers." in
|
|
||||||
Arg.(value & opt (some int) None &
|
|
||||||
info ~docs ~doc ~docv:"NUM" ["binary-chunks-size"])
|
|
||||||
|
|
||||||
let peer_table_size =
|
|
||||||
let doc = "Maximum size of internal peer tables, \
|
|
||||||
used to store metadata/logs about a peer or about a \
|
|
||||||
to-be-authenticated host:port couple." in
|
|
||||||
Arg.(value & opt (some int) None &
|
|
||||||
info ~docs ~doc ~docv:"NUM" ["peer-table-size"])
|
|
||||||
|
|
||||||
let listen_addr =
|
|
||||||
let doc =
|
|
||||||
"The TCP address and port at which this instance can be reached." in
|
|
||||||
Arg.(value & opt (some string) None &
|
|
||||||
info ~docs ~doc ~docv:"ADDR:PORT" ["net-addr"])
|
|
||||||
|
|
||||||
let discovery_addr =
|
|
||||||
let doc = "The UDP address and port used for local peer discovery." in
|
|
||||||
Arg.(value & opt (some string) None &
|
|
||||||
info ~docs ~doc ~docv:"ADDR:PORT" ["discovery-addr"])
|
|
||||||
|
|
||||||
let no_bootstrap_peers =
|
|
||||||
let doc =
|
|
||||||
"Ignore the peers found in the config file (or the hard-coded \
|
|
||||||
bootstrap peers in the absence of config file)." in
|
|
||||||
Arg.(value & flag &
|
|
||||||
info ~docs ~doc ["no-bootstrap-peers"])
|
|
||||||
|
|
||||||
let bootstrap_threshold =
|
|
||||||
let doc =
|
|
||||||
"Set the number of peers with whom a chain synchronization must \
|
|
||||||
be completed to bootstrap the node" in
|
|
||||||
Arg.(value & opt (some int) None &
|
|
||||||
info ~docs ~doc ~docv:"NUM" ["bootstrap-threshold"])
|
|
||||||
|
|
||||||
let peers =
|
|
||||||
let doc =
|
|
||||||
"A peer to bootstrap the network from. \
|
|
||||||
Can be used several times to add several peers." in
|
|
||||||
Arg.(value & opt_all string [] &
|
|
||||||
info ~docs ~doc ~docv:"ADDR:PORT" ["peer"])
|
|
||||||
|
|
||||||
let expected_pow =
|
|
||||||
let doc =
|
|
||||||
"Expected level of proof-of-work for peers identity." in
|
|
||||||
Arg.(value & opt (some float) None &
|
|
||||||
info ~docs ~doc ~docv:"FLOAT" ["expected-pow"])
|
|
||||||
|
|
||||||
let private_mode =
|
|
||||||
let doc =
|
|
||||||
"Only open outgoing/accept incoming connections to/from peers \
|
|
||||||
listed in 'bootstrap-peers' or provided with '--peer' option." in
|
|
||||||
Arg.(value & flag & info ~docs ~doc ["private-mode"])
|
|
||||||
|
|
||||||
let disable_mempool =
|
|
||||||
let doc =
|
|
||||||
"If set to [true], the node will not participate in the propagation \
|
|
||||||
of pending operations (mempool). \
|
|
||||||
Default value is [false]. \
|
|
||||||
It can be used to decrease the memory and computation footprints \
|
|
||||||
of the node." in
|
|
||||||
Arg.(value & flag & info ~docs ~doc ["disable-mempool"])
|
|
||||||
|
|
||||||
(* rpc args *)
|
|
||||||
let docs = Manpage.rpc_section
|
|
||||||
|
|
||||||
let rpc_listen_addr =
|
|
||||||
let doc =
|
|
||||||
"The TCP socket address at which this RPC server \
|
|
||||||
instance can be reached." in
|
|
||||||
Arg.(value & opt (some string) None &
|
|
||||||
info ~docs ~doc ~docv:"ADDR:PORT" ["rpc-addr"])
|
|
||||||
|
|
||||||
let rpc_tls =
|
|
||||||
let doc =
|
|
||||||
"Enable TLS for this RPC server \
|
|
||||||
with the provided certificate and key." in
|
|
||||||
Arg.(value & opt (some (pair string string)) None &
|
|
||||||
info ~docs ~doc ~docv:"crt,key" ["rpc-tls"])
|
|
||||||
|
|
||||||
let cors_origins =
|
|
||||||
let doc =
|
|
||||||
"CORS origin allowed by the RPC server \
|
|
||||||
via Access-Control-Allow-Origin; may be used multiple times" in
|
|
||||||
Arg.(value & opt_all string [] &
|
|
||||||
info ~docs ~doc ~docv:"ORIGIN" ["cors-origin"])
|
|
||||||
|
|
||||||
let cors_headers =
|
|
||||||
let doc =
|
|
||||||
"Header reported by Access-Control-Allow-Headers \
|
|
||||||
reported during CORS preflighting; may be used multiple times" in
|
|
||||||
Arg.(value & opt_all string [] &
|
|
||||||
info ~docs ~doc ~docv:"HEADER" ["cors-header"])
|
|
||||||
|
|
||||||
let args =
|
|
||||||
let open Term in
|
|
||||||
const wrap $ data_dir $ config_file
|
|
||||||
$ connections
|
|
||||||
$ max_download_speed $ max_upload_speed $ binary_chunks_size
|
|
||||||
$ peer_table_size
|
|
||||||
$ listen_addr $ discovery_addr $ peers $ no_bootstrap_peers
|
|
||||||
$ bootstrap_threshold
|
|
||||||
$ private_mode $ disable_mempool
|
|
||||||
$ expected_pow $ rpc_listen_addr $ rpc_tls
|
|
||||||
$ cors_origins $ cors_headers
|
|
||||||
$ log_output
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
let read_and_patch_config_file ?(ignore_bootstrap_peers=false) args =
|
|
||||||
begin
|
|
||||||
if Sys.file_exists args.config_file then
|
|
||||||
Node_config_file.read args.config_file
|
|
||||||
else
|
|
||||||
return Node_config_file.default_config
|
|
||||||
end >>=? fun cfg ->
|
|
||||||
let { data_dir ;
|
|
||||||
min_connections ; expected_connections ; max_connections ;
|
|
||||||
max_download_speed ; max_upload_speed ; binary_chunks_size ;
|
|
||||||
peer_table_size ;
|
|
||||||
expected_pow ;
|
|
||||||
peers ; no_bootstrap_peers ;
|
|
||||||
listen_addr ; private_mode ;
|
|
||||||
discovery_addr ;
|
|
||||||
disable_mempool ;
|
|
||||||
rpc_listen_addr ; rpc_tls ;
|
|
||||||
cors_origins ; cors_headers ;
|
|
||||||
log_output ;
|
|
||||||
bootstrap_threshold ;
|
|
||||||
} = args in
|
|
||||||
let bootstrap_peers =
|
|
||||||
if no_bootstrap_peers || ignore_bootstrap_peers
|
|
||||||
then begin
|
|
||||||
log_info "Ignoring bootstrap peers" ;
|
|
||||||
peers
|
|
||||||
end else
|
|
||||||
cfg.p2p.bootstrap_peers @ peers in
|
|
||||||
Node_config_file.update
|
|
||||||
?data_dir ?min_connections ?expected_connections ?max_connections
|
|
||||||
?max_download_speed ?max_upload_speed ?binary_chunks_size
|
|
||||||
?peer_table_size ?expected_pow
|
|
||||||
~bootstrap_peers ?listen_addr ?discovery_addr ?rpc_listen_addr ~private_mode
|
|
||||||
~disable_mempool ~cors_origins ~cors_headers ?rpc_tls ?log_output
|
|
||||||
?bootstrap_threshold cfg
|
|
@ -1,64 +0,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. *)
|
|
||||||
(* *)
|
|
||||||
(*****************************************************************************)
|
|
||||||
|
|
||||||
type t = {
|
|
||||||
data_dir: string option ;
|
|
||||||
config_file: string ;
|
|
||||||
min_connections: int option ;
|
|
||||||
expected_connections: int option ;
|
|
||||||
max_connections: int option ;
|
|
||||||
max_download_speed: int option ;
|
|
||||||
max_upload_speed: int option ;
|
|
||||||
binary_chunks_size: int option ;
|
|
||||||
peer_table_size: int option ;
|
|
||||||
expected_pow: float option ;
|
|
||||||
peers: string list ;
|
|
||||||
no_bootstrap_peers: bool ;
|
|
||||||
listen_addr: string option ;
|
|
||||||
discovery_addr: string option ;
|
|
||||||
rpc_listen_addr: string option ;
|
|
||||||
private_mode: bool ;
|
|
||||||
disable_mempool: bool ;
|
|
||||||
cors_origins: string list ;
|
|
||||||
cors_headers: string list ;
|
|
||||||
rpc_tls: Node_config_file.tls option ;
|
|
||||||
log_output: Logging_unix.Output.t option ;
|
|
||||||
bootstrap_threshold: int option ;
|
|
||||||
}
|
|
||||||
|
|
||||||
module Term : sig
|
|
||||||
val args: t Cmdliner.Term.t
|
|
||||||
val data_dir: string option Cmdliner.Term.t
|
|
||||||
val config_file: string option Cmdliner.Term.t
|
|
||||||
end
|
|
||||||
|
|
||||||
val read_and_patch_config_file: ?ignore_bootstrap_peers:bool -> t -> Node_config_file.t tzresult Lwt.t
|
|
||||||
|
|
||||||
module Manpage : sig
|
|
||||||
val misc_section: string
|
|
||||||
val args: Cmdliner.Manpage.block list
|
|
||||||
val bugs: Cmdliner.Manpage.block list
|
|
||||||
end
|
|
@ -1,29 +0,0 @@
|
|||||||
opam-version: "2.0"
|
|
||||||
maintainer: "contact@tezos.com"
|
|
||||||
authors: [ "Tezos devteam" ]
|
|
||||||
homepage: "https://www.tezos.com/"
|
|
||||||
bug-reports: "https://gitlab.com/tezos/tezos/issues"
|
|
||||||
dev-repo: "git+https://gitlab.com/tezos/tezos.git"
|
|
||||||
license: "MIT"
|
|
||||||
depends: [
|
|
||||||
"ocamlfind" { build }
|
|
||||||
"dune" { build & >= "1.0.1" }
|
|
||||||
"tezos-base"
|
|
||||||
"tezos-rpc-http"
|
|
||||||
"tezos-p2p"
|
|
||||||
"tezos-shell"
|
|
||||||
"tezos-protocol-updater"
|
|
||||||
"tezos-embedded-protocol-genesis"
|
|
||||||
"tezos-embedded-protocol-demo"
|
|
||||||
"tezos-embedded-protocol-alpha"
|
|
||||||
"cmdliner"
|
|
||||||
"tls"
|
|
||||||
"cstruct" { < "3.4.0" } ## Because "tls" depends on a version of "nocrypto"
|
|
||||||
## that is not compatible with recent "cstruct"
|
|
||||||
]
|
|
||||||
build: [
|
|
||||||
[ "dune" "build" "-p" name "-j" jobs ]
|
|
||||||
]
|
|
||||||
run-test: [
|
|
||||||
[ "dune" "runtest" "-p" name "-j" jobs ]
|
|
||||||
]
|
|
@ -1,222 +0,0 @@
|
|||||||
#! /usr/bin/env bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
node_dirs=()
|
|
||||||
node_pids=()
|
|
||||||
|
|
||||||
start_sandboxed_node() {
|
|
||||||
|
|
||||||
id=$1
|
|
||||||
max_peer_id=${max_peer_id:-9}
|
|
||||||
shift 1
|
|
||||||
|
|
||||||
port=$((19730 + id))
|
|
||||||
rpc=$((18730 + id))
|
|
||||||
expected_pow="${expected_pow:-0.0}"
|
|
||||||
expected_connections="${expected_connections:-3}"
|
|
||||||
node_dir="$(mktemp -d -t tezos-node.XXXXXXXX)"
|
|
||||||
peers=("--no-bootstrap-peers")
|
|
||||||
for peer_port in $(seq 19730 $((19730 + max_peer_id))); do
|
|
||||||
peers+=("--peer")
|
|
||||||
peers+=("127.0.0.1:$peer_port")
|
|
||||||
done
|
|
||||||
peers+=("--private-mode")
|
|
||||||
node="${local_node}"
|
|
||||||
sandbox_param="--sandbox=$sandbox_file"
|
|
||||||
|
|
||||||
if ! [ -f "$sandbox_file" ]; then
|
|
||||||
cat > "$sandbox_file" <<EOF
|
|
||||||
{
|
|
||||||
"genesis_pubkey":
|
|
||||||
"edpkuSLWfVU1Vq7Jg9FucPyKmma6otcMHac9zG4oU1KMHSTBpJuGQ2"
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
node_dirs+=("$node_dir")
|
|
||||||
|
|
||||||
if [ -n "$USE_TLS" ]; then
|
|
||||||
$node config init \
|
|
||||||
--data-dir "$node_dir" \
|
|
||||||
--net-addr "127.0.0.1:$port" \
|
|
||||||
--rpc-addr "127.0.0.1:$rpc" \
|
|
||||||
--rpc-tls "${node_dir}/tezos.crt,${node_dir}/tezos.key" \
|
|
||||||
--expected-pow "$expected_pow" \
|
|
||||||
--connections "$expected_connections"
|
|
||||||
|
|
||||||
cat > "${node_dir}/tezos.crt" <<EOF
|
|
||||||
Certificate:
|
|
||||||
Data:
|
|
||||||
Version: 3 (0x2)
|
|
||||||
Serial Number: 1 (0x1)
|
|
||||||
Signature Algorithm: sha256WithRSAEncryption
|
|
||||||
Issuer: CN=Easy-RSA CA
|
|
||||||
Validity
|
|
||||||
Not Before: Mar 30 13:07:24 2018 GMT
|
|
||||||
Not After : Mar 27 13:07:24 2028 GMT
|
|
||||||
Subject: CN=tezos
|
|
||||||
Subject Public Key Info:
|
|
||||||
Public Key Algorithm: rsaEncryption
|
|
||||||
Public-Key: (2048 bit)
|
|
||||||
Modulus:
|
|
||||||
00:d3:61:ba:81:6a:0d:8f:0b:6f:84:65:ca:73:b5:
|
|
||||||
c6:2d:89:8e:83:90:9e:2c:e1:16:5f:2c:9d:44:00:
|
|
||||||
25:dd:a2:73:dc:41:06:81:fb:a1:0c:e9:17:db:63:
|
|
||||||
6b:c2:46:63:bc:31:4c:bc:76:50:a0:79:15:de:4a:
|
|
||||||
98:d1:eb:a3:d1:a9:4c:db:32:3e:05:23:be:60:b7:
|
|
||||||
5c:d1:4f:ec:fe:6d:a3:5f:75:0e:8d:e7:c5:d1:48:
|
|
||||||
6f:29:84:0a:cc:52:91:8b:8a:67:65:88:82:1a:a7:
|
|
||||||
31:6c:5c:00:1c:53:0e:fb:98:81:c7:5d:20:e8:72:
|
|
||||||
15:f1:53:e1:a8:e6:45:92:25:6b:a3:f6:67:da:63:
|
|
||||||
9f:fd:35:f6:54:04:c1:10:50:e9:5d:95:e3:12:7f:
|
|
||||||
e1:8f:bc:6c:65:48:f6:0c:eb:9e:d1:cb:30:1f:da:
|
|
||||||
ff:a2:d5:5d:bb:de:e5:df:b8:52:f3:70:6c:2d:8a:
|
|
||||||
e9:bb:85:7f:33:14:bc:fa:1e:c5:c4:b3:9f:f3:10:
|
|
||||||
a3:1c:00:f6:8f:84:ae:a3:a3:08:ae:b8:38:41:0a:
|
|
||||||
a7:84:88:bf:9d:e3:0d:42:51:75:dd:b2:5c:8b:9c:
|
|
||||||
fa:82:ff:0d:bd:6f:f7:c3:b5:e4:49:3a:5c:8c:cc:
|
|
||||||
7f:1c:80:7b:c1:47:ad:2c:fe:44:f1:fc:93:0e:ac:
|
|
||||||
4f:27
|
|
||||||
Exponent: 65537 (0x10001)
|
|
||||||
X509v3 extensions:
|
|
||||||
X509v3 Basic Constraints:
|
|
||||||
CA:FALSE
|
|
||||||
X509v3 Subject Key Identifier:
|
|
||||||
B4:C2:AB:C3:F6:64:80:94:43:46:7F:40:25:E4:D1:CF:01:33:44:DA
|
|
||||||
X509v3 Authority Key Identifier:
|
|
||||||
keyid:5E:27:08:3B:81:1D:FA:05:CC:D3:94:D4:2B:9B:92:5B:3B:F9:EA:A1
|
|
||||||
DirName:/CN=Easy-RSA CA
|
|
||||||
serial:D5:46:5A:8E:8B:18:BD:2B
|
|
||||||
|
|
||||||
X509v3 Extended Key Usage:
|
|
||||||
TLS Web Server Authentication
|
|
||||||
X509v3 Key Usage:
|
|
||||||
Digital Signature, Key Encipherment
|
|
||||||
X509v3 Subject Alternative Name:
|
|
||||||
DNS:tezos
|
|
||||||
Signature Algorithm: sha256WithRSAEncryption
|
|
||||||
2f:23:1a:9e:42:72:2b:57:ec:26:04:a2:a0:22:f3:31:0e:12:
|
|
||||||
c4:46:92:95:b6:c7:44:bf:ab:5b:5b:15:c3:69:a3:48:79:be:
|
|
||||||
f9:09:aa:42:8c:8a:83:6a:55:68:b7:6c:02:b4:1a:d4:98:52:
|
|
||||||
b1:2e:bf:6c:3f:da:ef:93:e0:c8:69:fd:b7:dd:f7:42:65:e1:
|
|
||||||
66:ab:99:c2:d7:81:62:e2:e9:63:98:8a:24:9b:34:da:8a:82:
|
|
||||||
03:00:08:29:00:3f:18:cd:94:00:a7:22:0c:25:be:fa:74:64:
|
|
||||||
ea:45:1f:62:e4:bd:f6:88:42:35:ca:7e:e4:a1:5f:a9:94:6d:
|
|
||||||
4e:80:38:7b:3c:65:41:c4:e3:bc:40:de:50:b6:61:8c:ae:3a:
|
|
||||||
de:d9:1e:af:e9:59:e3:c2:b2:5f:47:09:83:66:3c:d7:e5:4f:
|
|
||||||
ec:27:8c:90:69:1d:6a:95:3e:2f:bf:89:95:58:ae:25:6d:90:
|
|
||||||
bd:ce:41:63:91:58:e3:16:f9:08:70:c5:c1:5f:5d:f7:0d:a5:
|
|
||||||
77:e5:a3:84:82:53:bf:30:6a:10:df:1c:b1:1f:81:c8:e0:c7:
|
|
||||||
48:4d:74:47:21:48:3a:8a:80:f9:3c:43:c1:2c:0e:a4:40:51:
|
|
||||||
b7:f3:b7:27:98:ab:23:cb:b1:05:67:59:ab:cf:23:f8:1b:9f:
|
|
||||||
61:0d:8b:5e
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDSzCCAjOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAWMRQwEgYDVQQDDAtFYXN5
|
|
||||||
LVJTQSBDQTAeFw0xODAzMzAxMzA3MjRaFw0yODAzMjcxMzA3MjRaMBAxDjAMBgNV
|
|
||||||
BAMMBXRlem9zMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA02G6gWoN
|
|
||||||
jwtvhGXKc7XGLYmOg5CeLOEWXyydRAAl3aJz3EEGgfuhDOkX22NrwkZjvDFMvHZQ
|
|
||||||
oHkV3kqY0euj0alM2zI+BSO+YLdc0U/s/m2jX3UOjefF0UhvKYQKzFKRi4pnZYiC
|
|
||||||
GqcxbFwAHFMO+5iBx10g6HIV8VPhqOZFkiVro/Zn2mOf/TX2VATBEFDpXZXjEn/h
|
|
||||||
j7xsZUj2DOue0cswH9r/otVdu97l37hS83BsLYrpu4V/MxS8+h7FxLOf8xCjHAD2
|
|
||||||
j4Suo6MIrrg4QQqnhIi/neMNQlF13bJci5z6gv8NvW/3w7XkSTpcjMx/HIB7wUet
|
|
||||||
LP5E8fyTDqxPJwIDAQABo4GpMIGmMAkGA1UdEwQCMAAwHQYDVR0OBBYEFLTCq8P2
|
|
||||||
ZICUQ0Z/QCXk0c8BM0TaMEYGA1UdIwQ/MD2AFF4nCDuBHfoFzNOU1Cubkls7+eqh
|
|
||||||
oRqkGDAWMRQwEgYDVQQDDAtFYXN5LVJTQSBDQYIJANVGWo6LGL0rMBMGA1UdJQQM
|
|
||||||
MAoGCCsGAQUFBwMBMAsGA1UdDwQEAwIFoDAQBgNVHREECTAHggV0ZXpvczANBgkq
|
|
||||||
hkiG9w0BAQsFAAOCAQEALyMankJyK1fsJgSioCLzMQ4SxEaSlbbHRL+rW1sVw2mj
|
|
||||||
SHm++QmqQoyKg2pVaLdsArQa1JhSsS6/bD/a75PgyGn9t933QmXhZquZwteBYuLp
|
|
||||||
Y5iKJJs02oqCAwAIKQA/GM2UAKciDCW++nRk6kUfYuS99ohCNcp+5KFfqZRtToA4
|
|
||||||
ezxlQcTjvEDeULZhjK463tker+lZ48KyX0cJg2Y81+VP7CeMkGkdapU+L7+JlViu
|
|
||||||
JW2Qvc5BY5FY4xb5CHDFwV9d9w2ld+WjhIJTvzBqEN8csR+ByODHSE10RyFIOoqA
|
|
||||||
+TxDwSwOpEBRt/O3J5irI8uxBWdZq88j+BufYQ2LXg==
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
EOF
|
|
||||||
|
|
||||||
cat > "${node_dir}/tezos.key" <<EOF
|
|
||||||
-----BEGIN PRIVATE KEY-----
|
|
||||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDTYbqBag2PC2+E
|
|
||||||
ZcpztcYtiY6DkJ4s4RZfLJ1EACXdonPcQQaB+6EM6RfbY2vCRmO8MUy8dlCgeRXe
|
|
||||||
SpjR66PRqUzbMj4FI75gt1zRT+z+baNfdQ6N58XRSG8phArMUpGLimdliIIapzFs
|
|
||||||
XAAcUw77mIHHXSDochXxU+Go5kWSJWuj9mfaY5/9NfZUBMEQUOldleMSf+GPvGxl
|
|
||||||
SPYM657RyzAf2v+i1V273uXfuFLzcGwtium7hX8zFLz6HsXEs5/zEKMcAPaPhK6j
|
|
||||||
owiuuDhBCqeEiL+d4w1CUXXdslyLnPqC/w29b/fDteRJOlyMzH8cgHvBR60s/kTx
|
|
||||||
/JMOrE8nAgMBAAECggEBAKjMC9E4TSeDbEP/vRF1gJHwnLt3Criv7duGlvcsXxCD
|
|
||||||
n52s13OI6uySXpi05eI3r4EipTKCEJR03P+r9ij70M+mMFeB4YDdMDOveRE0j/4E
|
|
||||||
s0eRBFRRVuhuvUYbyTusW8lgdnzf63U5OgBb30K/GOHUwR3gwlycbeVOpI7pg3jV
|
|
||||||
sNdv9rHxQ0n8ohC2GUsrHBxuq83Jk1zeo/9R0ENPqvkReN9n/ldrjbxqDR1EPd/P
|
|
||||||
AloiZeA/3p3hTqQmaWmwv8nn5tT8SlICbQXgdlLkfBJwQHpsTaflf5oZX2Rafl+9
|
|
||||||
irFpjDMcCSdgpqbDtYpSiHDgTLaY1cO8P384eL6MXBECgYEA9tfPh36Cn5UnhzYf
|
|
||||||
MOUSrV7Qu61aFanvKLYq6MEYcIHkXvo59FANM1HTbvhRsyvpmSRZs1F8+hhkTzPh
|
|
||||||
aziLUGfvpy4MY+KRH1iXnrmySmTAf2Ry3ddmxLVALgSpNR8C+65WygmcRCB2X0Xc
|
|
||||||
rEbMGflYIet2fMPnndGVo2T0cv0CgYEA2zknU2a/leYxaz7spXEBhcsAtqtlFsHl
|
|
||||||
o+IybsCHyg8TQMo1pOydgTjEa5uGToTZWwm3hJHmyujQb/Brj/vDxSfAXskbHOIN
|
|
||||||
NN/P66rfGC25cn6qr459a7RXvhmdsMVisrE4j3sVJBmKBPZSs05drNyYw2INqvQZ
|
|
||||||
e+WOPGX2nfMCgYByEzQuSvH07ApTe1iY0RR7mLjgMvHR1zHWX7Ge1TYFMJIorn1A
|
|
||||||
AgrHr8YFn66qHd4bzufBbiRStBkPXUuMsJn5c78WRLqnIpqsoNWZHfpeVQd9GB/Z
|
|
||||||
k+VDfPwHCFJmYUmQpHYpcp2MAnCSAQhFeYZzbn8jVdzxNdwBXE1KMKqjxQKBgDaI
|
|
||||||
tjayFbDFbb+/DIFvZjCROmE2q9QIcgbdqywP6veh3mk8pDGdxuSxaXNXYgbAV42l
|
|
||||||
EikBXodVeRyPk0JjH+U4qUsq/fqmZSClGIUIoazTGxHXXsCDUsHrP/SDTM3/nDjV
|
|
||||||
iztuI+kyDTqEyDfgo77vtXTNPJctV/WROlveBYZvAoGBANCVDb/9bL+Sknwk8UUN
|
|
||||||
qqK1s+/HnLDBZZSGD6e3zfUoBsYtN1PkNmhxrLFsSaRzMEEbIgCCt2bs5vl/DWoi
|
|
||||||
lcQiNhsWRkdUDXpJd0WeqkGK3Gqb4KimoxdGrhhUQ2JmzqanOCuDpmKDDQDGe7Qy
|
|
||||||
XRWBqNomtTmVA25kchhzSMBQ
|
|
||||||
-----END PRIVATE KEY-----
|
|
||||||
EOF
|
|
||||||
|
|
||||||
else
|
|
||||||
$node config init \
|
|
||||||
--data-dir "$node_dir" \
|
|
||||||
--net-addr "127.0.0.1:$port" \
|
|
||||||
--rpc-addr "127.0.0.1:$rpc" \
|
|
||||||
--expected-pow "$expected_pow" \
|
|
||||||
--connections "$expected_connections"
|
|
||||||
fi
|
|
||||||
|
|
||||||
$node identity generate "$expected_pow" --data-dir "$node_dir"
|
|
||||||
$node run --data-dir "$node_dir" "${peers[@]}" "$sandbox_param" "$@" &
|
|
||||||
node_pids+=("$!")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup_nodes() {
|
|
||||||
[ -z "${node_pids[0]}" ] || kill "${node_pids[@]}"
|
|
||||||
for pid in "${node_pids[@]}" ; do wait "$pid" ; done
|
|
||||||
rm -rf "${node_dirs[@]}"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
main() {
|
|
||||||
|
|
||||||
local bin_dir="$(cd "$(dirname "$0")" && echo "$(pwd -P)/")"
|
|
||||||
if [ $(basename "$bin_dir") = "bin_node" ]; then
|
|
||||||
local_node="${local_node:-$bin_dir/../../_build/default/src/bin_node/main.exe}"
|
|
||||||
sandbox_file="${sandbox_file:-$bin_dir/../../scripts/sandbox.json}"
|
|
||||||
else
|
|
||||||
local_node="${local_node:-tezos-node}"
|
|
||||||
sandbox_file="${sandbox_file:-sandbox.json}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $# -lt 1 ] || [ "$1" -le 0 ] || [ 10 -le "$1" ]; then
|
|
||||||
echo "Small script to launch local and closed test network with a maximum of 9 nodes."
|
|
||||||
echo
|
|
||||||
echo "Usage: $0 <id>"
|
|
||||||
echo " where <id> should be an integer between 1 and 9."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
cleanup () {
|
|
||||||
set +e
|
|
||||||
echo Cleaning up...
|
|
||||||
cleanup_nodes
|
|
||||||
}
|
|
||||||
trap cleanup EXIT INT
|
|
||||||
|
|
||||||
start_sandboxed_node "$@"
|
|
||||||
wait $node_pids
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if [ "$0" == "$BASH_SOURCE" ]; then
|
|
||||||
main "$@"
|
|
||||||
fi
|
|
Loading…
Reference in New Issue
Block a user