Source file shared_arg.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
open Cmdliner
open Filename.Infix
type net_config =
| BuiltIn of Config_file.blockchain_network
| Url of Uri.t
| Filename of string
type t = {
disable_config_validation : bool;
data_dir : string option;
config_file : string;
network : net_config option;
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;
advertised_net_port : int option;
discovery_addr : string option;
rpc_listen_addrs : string list;
private_mode : bool;
disable_mempool : bool;
disable_mempool_precheck : bool;
enable_testchain : bool;
cors_origins : string list;
cors_headers : string list;
rpc_tls : Config_file.tls option;
log_output : Lwt_log_sink_unix.Output.t option;
bootstrap_threshold : int option;
history_mode : History_mode.t option;
synchronisation_threshold : int option;
latency : int option;
allow_all_rpc : P2p_point.Id.addr_port_id list;
media_type : Media_type.Command_line.t;
metrics_addr : string list;
operation_metadata_size_limit :
Shell_limits.operation_metadata_size_limit option;
}
type error +=
| Invalid_network_config of string * string
| Network_http_error of (Cohttp.Code.status_code * string)
let () =
register_error_kind
`Permanent
~id:"node.network.invalid_config"
~title:"Invalid network config"
~description:"The network config provided by --network argument is invalid."
~pp:(fun ppf (path, error) ->
Format.fprintf ppf "The network config at %s is invalid (%s)." path error)
Data_encoding.(
obj2 (req "path" Data_encoding.string) (req "error" Data_encoding.string))
(function
| Invalid_network_config (path, exn) -> Some (path, exn) | _ -> None)
(fun (path, exn) -> Invalid_network_config (path, exn)) ;
let http_status_enc =
let open Data_encoding in
let open Cohttp.Code in
conv code_of_status status_of_code int31
in
register_error_kind
`Permanent
~id:"node.network.http_error"
~title:"HTTP error when downloading network config"
~description:
"The node encountered an HTTP error when downloading the network config."
~pp:(fun ppf (status, body) ->
Format.fprintf
ppf
"Downloading network config resulted in: %s (%s)."
(Cohttp.Code.string_of_status status)
body)
Data_encoding.(
obj2 (req "status" http_status_enc) (req "body" Data_encoding.string))
(function
| Network_http_error (status, body) -> Some (status, body) | _ -> None)
(fun (status, body) -> Network_http_error (status, body))
let decode_net_config source json =
let open Result_syntax in
match
Data_encoding.Json.destruct Config_file.blockchain_network_encoding json
with
| net_cfg -> return net_cfg
| exception Json_encoding.Cannot_destruct (path, exn) ->
let path = Json_query.json_pointer_of_path path in
tzfail (Invalid_network_config (path, Printexc.to_string exn))
| exception
(( Json_encoding.Unexpected _ | Json_encoding.No_case_matched _
| Json_encoding.Bad_array_size _ | Json_encoding.Missing_field _
| Json_encoding.Unexpected_field _ | Json_encoding.Bad_schema _ ) as exn)
->
tzfail (Invalid_network_config (source, Printexc.to_string exn))
let load_net_config =
let open Lwt_result_syntax in
function
| BuiltIn net -> return net
| Url uri ->
let*! resp, body = Cohttp_lwt_unix.Client.get uri in
let*! body_str = Cohttp_lwt.Body.to_string body in
let* netconfig =
match resp.status with
| `OK -> (
try return (Ezjsonm.from_string body_str)
with Ezjsonm.Parse_error (_, msg) ->
tzfail (Invalid_network_config (Uri.to_string uri, msg)))
| #Cohttp.Code.status_code ->
tzfail (Network_http_error (resp.status, body_str))
in
let*? net_config = decode_net_config (Uri.to_string uri) netconfig in
return net_config
| Filename filename ->
let* netconfig = Lwt_utils_unix.Json.read_file filename in
let*? net_config = decode_net_config filename netconfig in
return net_config
let wrap data_dir config_file network connections max_download_speed
max_upload_speed binary_chunks_size peer_table_size listen_addr
advertised_net_port discovery_addr peers no_bootstrap_peers
bootstrap_threshold private_mode disable_mempool disable_mempool_precheck
enable_testchain expected_pow rpc_listen_addrs rpc_tls cors_origins
log_output history_mode synchronisation_threshold latency
disable_config_validation allow_all_rpc media_type metrics_addr
operation_metadata_size_limit =
let actual_data_dir =
Option.value ~default:Config_file.default_data_dir data_dir
in
let config_file =
Option.value
~default:(actual_data_dir // Data_version.default_config_file_name)
config_file
in
let rpc_tls =
Option.map (fun (cert, key) -> {Config_file.cert; key}) rpc_tls
in
{
disable_config_validation;
data_dir;
config_file;
network;
connections;
max_download_speed;
max_upload_speed;
binary_chunks_size;
expected_pow;
peers;
no_bootstrap_peers;
listen_addr;
advertised_net_port;
discovery_addr;
rpc_listen_addrs;
private_mode;
disable_mempool;
disable_mempool_precheck;
enable_testchain;
cors_origins;
cors_headers;
rpc_tls;
log_output;
peer_table_size;
bootstrap_threshold;
history_mode;
synchronisation_threshold;
latency;
allow_all_rpc;
media_type;
metrics_addr;
operation_metadata_size_limit;
}
let process_command run =
match Lwt_main.run @@ Lwt_exit.wrap_and_exit run with
| Ok () -> `Ok ()
| Error err -> `Error (false, Format.asprintf "%a" pp_print_trace err)
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 Lwt_log_sink_unix.Output.of_string s with
| Some res -> `Ok res
| None -> `Error s),
Lwt_log_sink_unix.Output.pp )
let history_mode_converter =
let open History_mode in
let parse_history_mode s =
let delim = ':' in
let args = String.split_on_char delim s in
match args with
| ["archive"] | ["Archive"] -> Some Archive
| ["full"] | ["Full"] -> Some default_full
| ["full"; n] | ["Full"; n] ->
Option.map (fun offset -> Full (Some {offset})) (int_of_string_opt n)
| ["rolling"] | ["Rolling"] -> Some default_rolling
| ["rolling"; n] | ["Rolling"; n] ->
Option.map
(fun offset -> Rolling (Some {offset}))
(int_of_string_opt n)
| ["experimental-rolling"] -> Some default_rolling
| _ -> None
in
( (fun arg ->
match parse_history_mode arg with
| Some hm -> `Ok hm
| None -> `Error arg),
pp )
let network_printer ppf = function
| BuiltIn ({alias; _} : Config_file.blockchain_network) ->
let alias = WithExceptions.Option.get ~loc:__LOC__ alias in
Format.fprintf ppf "built-in network: %s" alias
| Url url -> Format.fprintf ppf "URL network: %s" (Uri.to_string url)
| Filename file -> Format.fprintf ppf "local file network: %s" file
let network_parser =
let parse_network_name s =
List.assoc_opt
~equal:String.equal
(String.lowercase_ascii s)
Config_file.builtin_blockchain_networks
|> Option.map (fun net -> Result.ok (BuiltIn net))
in
let parse_network_url s =
let uri = Uri.of_string s in
match Uri.scheme uri with
| Some "http" | Some "https" -> Some (Ok (Url uri))
| Some _ | None -> None
in
let parse_file_config filename =
if Sys.file_exists filename then Some (Result.ok (Filename filename))
else None
in
let parse_error s =
Error
(`Msg
(Format.asprintf
"invalid value '%s', expected one of '%a', a URL or an existing \
filename"
s
(Format.pp_print_list
~pp_sep:(fun ppf () -> Format.fprintf ppf ", ")
Format.pp_print_string)
(List.map fst Config_file.builtin_blockchain_networks)))
in
let parser s =
let ( <||> ) = Option.either_f
and ( <|!> ) opt default = Option.value_f ~default opt in
( (parse_network_name s <||> fun () -> parse_network_url s) <||> fun () ->
parse_file_config s )
<|!> fun () -> parse_error s
in
( (parser : string -> (net_config, [`Msg of string]) result),
(network_printer : net_config Cmdliner.Arg.printer) )
let docs = Manpage.misc_section
let disable_config_validation =
let doc = "Disable the node configuration validation." in
Arg.(value & flag & info ~docs ~doc ["disable-config-validation"])
let history_mode =
let doc =
Format.sprintf
"Set the mode for the chain's data history storage. Possible values \
are $(i,archive), $(i,full) $(b,(default)), $(i,full:N), \
$(i,rolling), $(i,rolling:N). Archive mode retains all data since the \
genesis block. Full mode only maintains block headers and operations \
allowing replaying the chain since the genesis if wanted. Rolling \
mode retains only the most recent data and deletes the rest. For both \
Full and Rolling modes, it is possible to adjust the number of cycles \
to preserve by using the $(i,:N) annotation. The default number of \
preserved cycles is %d. The value $(i,experimental-rolling) is \
deprecated but is equivalent to $(i,rolling) which should be used \
instead."
History_mode.default_additional_cycles.offset
in
Arg.(
value
& opt (some history_mode_converter) None
& info ~docs ~doc ~docv:"<mode>" ["history-mode"])
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. Parent \
directories are created if necessary."
in
let env = Cmd.Env.info ~doc Config_file.data_dir_env_name in
Arg.(
value
& opt (some string) None
& info ~docs ~env ~doc ~docv:"DIR" ["data-dir"; "d"])
let config_file =
let doc = "The main configuration file." in
Arg.(
value
& opt (some string) None
& info ~docs ~doc ~docv:"FILE" ["config-file"])
let network =
let open Cmdliner in
let doc =
"Select which network to run. Possible values are: "
^ String.concat
", "
(List.map fst Config_file.builtin_blockchain_networks)
^ ". Default is mainnet. You can also specify custom networks by passing \
a path to a file containing the custom network configuration, or by \
passing a URL from which such a file can be downloaded. If you have a \
file named after a built-in network, you can prefix its name with \
'./' so that the node treats it as a file. Otherwise it will be \
treated as a proper name of the built-in network. With commands other \
than 'config init', specifying this option causes the node to fail if \
the configuration implies another network."
in
Arg.(
value
& opt (some (conv network_parser)) None
& info ~docs ~doc ~docv:"NETWORK" ["network"])
let metrics_addr =
let doc = "Port on which to provide metrics over HTTP." in
Arg.(
value & opt_all string []
& info
~docs
~doc
~docv:
"ADDR:PORT or :PORT (by default ADDR is localhost and PORT is 9932)"
["metrics-addr"])
let operation_metadata_size_limit =
let converter =
let parse s =
if String.(equal (lowercase_ascii s) "unlimited") then
`Ok Shell_limits.Unlimited
else
match int_of_string_opt s with
| None -> `Error s
| Some i -> `Ok (Limited i)
in
let pp fmt = function
| Shell_limits.Unlimited -> Format.fprintf fmt "unlimited"
| Limited i -> Format.pp_print_int fmt i
in
((fun arg -> parse arg), pp)
in
let doc =
let default =
match
Shell_limits.default_limits.block_validator_limits
.operation_metadata_size_limit
with
| Shell_limits.Unlimited -> "$(i,unlimited)"
| Limited i -> Format.sprintf "$(i,%d) bytes" i
in
Format.sprintf
"Size limit (in bytes) for operation's metadata to be stored on disk. \
Default limit is %s. Use $(i,unlimited) to disregard this limit."
default
in
Arg.(
value
& opt (some converter) None
& info ~docs ~doc ~docv:"<limit-in-bytes>" ["metadata-size-limit"])
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 on the command line. Sets \
synchronisation_threshold to max(NUM / 4, 2) unless it is already \
defined on the command line."
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 advertised_net_port =
let doc =
"The alternative TCP port at which this instance can be reached. This \
instance does not actually binds to it. The port may be used by a NAT \
server to forward connections to the instance listenning port."
in
Arg.(
value
& opt (some int) None
& info ~docs ~doc ~docv:"PORT" ["advertised-net-port"])
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 =
"[DEPRECATED: use synchronisation_threshold instead] The number of peers \
to synchronize with before declaring the node bootstrapped."
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. Optionally, the expected identity of the peer can be \
given using the b58 hash format of its public key."
in
Arg.(
value & opt_all string []
& info ~docs ~doc ~docv:"ADDR:PORT[#ID]" ["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"])
let disable_mempool_precheck =
let doc =
"If set to [true], the node's prevalidator will fully execute operations \
before gossiping valid operations over the network. Default value is \
[false], in which case the node's prevalidator only performs a fast \
check over operations before gossiping them. If set to [true], this \
option can slow down your node and should be used for testing or \
debugging purposes."
in
Arg.(value & flag & info ~docs ~doc ["disable-mempool-precheck"])
let enable_testchain =
let doc =
"DEPRECATED. If set to [true], the node will spawn a testchain during \
the protocol's testing voting period. Default value is [false]. It will \
increase the node storage usage and computation by additionally \
validating the test network blocks."
in
Arg.(value & flag & info ~docs ~doc ["enable-testchain"])
let synchronisation_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" ["synchronisation-threshold"])
let latency =
let doc =
"[latency] is the time interval (in seconds) used to determine if a peer \
is synchronized with a chain. For instance, a peer whose known head has \
a timestamp T is considered synchronized if T >= now - max_latency. \
This parameter's default value was set with the chain's current \
protocol's baking rate in mind (and some allowance for network \
latency)."
in
Arg.(
value & opt (some int) None & info ~docs ~doc ~docv:"NUM" ["sync-latency"])
let docs = Manpage.rpc_section
let rpc_listen_addrs =
let doc =
"The TCP socket address at which this RPC server instance can be reached."
in
Arg.(
value & opt_all string [] & 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 file file)) 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 =
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 allow_all_rpc =
let addr_port_id str =
match P2p_point.Id.parse_addr_port_id str with
| Ok addr -> `Ok addr
| Error e -> `Error (P2p_point.Id.string_of_parsing_error e)
in
let doc =
"Apply allow-all policy to a given RPC listening address rather than the \
safe default."
in
Arg.(
value
& opt_all (addr_port_id, P2p_point.Id.pp_addr_port_id) []
& info ~docs ~doc ~docv:"ADDR:PORT" ["allow-all-rpc"])
let media_type =
let media_type str =
match Media_type.Command_line.parse_cli_parameter str with
| Some media_type -> `Ok media_type
| None -> `Error "media-type parameter must be `json`, `binary`, or `any`"
in
let doc = "Set the media-types supported by the server." in
Arg.(
value
& opt
(media_type, Media_type.Command_line.pp_parameter)
Media_type.Command_line.Any
& info ~docs ~doc ~docv:"MEDIATYPE" ["media-type"])
let args =
let open Term in
const wrap $ data_dir $ config_file $ network $ connections
$ max_download_speed $ max_upload_speed $ binary_chunks_size
$ peer_table_size $ listen_addr $ advertised_net_port $ discovery_addr
$ peers $ no_bootstrap_peers $ bootstrap_threshold $ private_mode
$ disable_mempool $ disable_mempool_precheck $ enable_testchain
$ expected_pow $ rpc_listen_addrs $ rpc_tls $ cors_origins $ cors_headers
$ log_output $ history_mode $ synchronisation_threshold $ latency
$ disable_config_validation $ allow_all_rpc $ media_type $ metrics_addr
$ operation_metadata_size_limit
end
let read_config_file args =
let open Lwt_result_syntax in
if Sys.file_exists args.config_file then Config_file.read args.config_file
else return Config_file.default_config
let read_data_dir args =
let open Lwt_result_syntax in
let* cfg = read_config_file args in
let {data_dir; _} = args in
let data_dir = Option.value ~default:cfg.data_dir data_dir in
return data_dir
type error +=
| Network_configuration_mismatch of {
configuration_file_chain_name : Distributed_db_version.Name.t;
command_line_chain_name : Distributed_db_version.Name.t;
}
type error += Invalid_command_line_arguments of string
let () =
register_error_kind
`Permanent
~id:"node.config.network_configuration_mismatch"
~title:"Network configuration mismatch"
~description:
"You specified a --network argument on the command line, but it does not \
match your current configuration"
~pp:(fun ppf (configuration_file_chain_name, command_line_chain_name) ->
Format.fprintf
ppf
"@[Specified@ --network@ has@ chain@ name@ %s,@ but@ current@ \
configuration@ implies@ expected@ chain@ name@ %s.@ Use:@ octez-node \
config init --network <NETWORK>@ to@ configure@ your@ node.@]"
command_line_chain_name
configuration_file_chain_name)
Data_encoding.(
obj2
(req "configuration_file_chain_name" string)
(req "command_line_chain_name" string))
(function
| Network_configuration_mismatch
{configuration_file_chain_name; command_line_chain_name} ->
Some
( (configuration_file_chain_name :> string),
(command_line_chain_name :> string) )
| _ -> None)
(fun (configuration_file_chain_name, command_line_chain_name) ->
Network_configuration_mismatch
{
configuration_file_chain_name =
Distributed_db_version.Name.of_string configuration_file_chain_name;
command_line_chain_name =
Distributed_db_version.Name.of_string command_line_chain_name;
}) ;
register_error_kind
`Permanent
~id:"node.config.invalidcommandlinearguments"
~title:"Invalid command line arguments"
~description:"Given command line arguments are invalid"
~pp:(fun ppf explanation ->
Format.fprintf
ppf
"@[Specified command line arguments are invalid: %s@]"
explanation)
Data_encoding.(obj1 (req "explanation" string))
(function Invalid_command_line_arguments x -> Some x | _ -> None)
(fun explanation -> Invalid_command_line_arguments explanation)
module Event = struct
include Internal_event.Simple
let disabled_bootstrap_peers =
Internal_event.Simple.declare_0
~section:["node"; "main"]
~name:"disabled_bootstrap_peers"
~msg:"disabled bootstrap peers"
()
let testchain_is_deprecated =
Internal_event.Simple.declare_0
~section:["node"; "main"]
~level:Warning
~name:"enable_testchain_is_deprecated"
~msg:"The command-line option `--enable-testchain` is deprecated."
()
end
let patch_network ?(cfg = Config_file.default_config) blockchain_network =
let open Lwt_result_syntax in
return {cfg with blockchain_network}
let patch_config ?(may_override_network = false) ?(emit = Event.emit)
?(ignore_bootstrap_peers = false) ?(cfg = Config_file.default_config) args =
let open Lwt_result_syntax in
let {
data_dir;
disable_config_validation;
connections;
max_download_speed;
max_upload_speed;
binary_chunks_size;
peer_table_size;
expected_pow;
peers;
no_bootstrap_peers;
listen_addr;
advertised_net_port;
private_mode;
discovery_addr;
disable_mempool;
disable_mempool_precheck;
enable_testchain;
rpc_listen_addrs;
rpc_tls;
cors_origins;
;
log_output;
bootstrap_threshold;
history_mode;
network = network_arg;
config_file = _;
synchronisation_threshold;
latency;
allow_all_rpc;
media_type;
metrics_addr;
operation_metadata_size_limit;
} =
args
in
let* synchronisation_threshold =
match (bootstrap_threshold, synchronisation_threshold) with
| Some _, Some _ ->
tzfail
(Invalid_command_line_arguments
"--bootstrap-threshold is deprecated; use \
--synchronisation-threshold instead. Do not use both at the same \
time.")
| None, Some threshold | Some threshold, None -> return_some threshold
| None, None -> return_none
in
let* cfg =
match network_arg with
| None -> return cfg
| Some network_arg ->
let* network_arg = load_net_config network_arg in
if
Distributed_db_version.Name.equal
cfg.blockchain_network.chain_name
network_arg.chain_name
|| may_override_network
then patch_network ~cfg network_arg
else
let*! context_dir =
Lwt_unix.file_exists @@ Data_version.context_dir
@@ Option.value ~default:cfg.data_dir args.data_dir
in
let*! store_dir =
Lwt_unix.file_exists @@ Data_version.store_dir
@@ Option.value ~default:cfg.data_dir args.data_dir
in
if context_dir || store_dir then
tzfail
(Network_configuration_mismatch
{
configuration_file_chain_name =
cfg.blockchain_network.chain_name;
command_line_chain_name = network_arg.chain_name;
})
else patch_network ~cfg network_arg
in
let* bootstrap_peers =
if no_bootstrap_peers || ignore_bootstrap_peers then
let*! () = emit Event.disabled_bootstrap_peers () in
return peers
else
let cfg_peers =
match cfg.p2p.bootstrap_peers with
| Some peers -> peers
| None -> cfg.blockchain_network.default_bootstrap_peers
in
return (cfg_peers @ peers)
in
let* () =
Option.iter_es
(fun connections ->
fail_when
(connections > 100 && disable_config_validation = false)
(Invalid_command_line_arguments
"The number of expected connections is limited to `100`. This \
maximum cap may be overridden by manually modifying the \
configuration file. However, this should be done carefully. \
Exceeding this number of connections may degrade the performance \
of your node."))
connections
in
let ( synchronisation_threshold,
min_connections,
expected_connections,
max_connections,
peer_table_size ) =
match connections with
| None -> (synchronisation_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
match synchronisation_threshold with
| None ->
( Some (max (x / 4) 2),
Some (if x = 1 then x else x / 2),
Some x,
Some (3 * x / 2),
peer_table_size )
| Some threshold ->
( Some threshold,
Some (if x = 1 then x else x / 2),
Some x,
Some (3 * x / 2),
peer_table_size ))
in
let*! () =
if enable_testchain then emit Event.testchain_is_deprecated ()
else Lwt.return_unit
in
Config_file.update
~disable_config_validation
?data_dir
?min_connections
?expected_connections
?max_connections
?max_download_speed
?max_upload_speed
?binary_chunks_size
?peer_table_size
?expected_pow
~bootstrap_peers:(Some bootstrap_peers)
?listen_addr
?advertised_net_port
?discovery_addr
~rpc_listen_addrs
~allow_all_rpc
~media_type
~metrics_addr
?operation_metadata_size_limit
~private_mode
~disable_mempool
~disable_mempool_precheck
~enable_testchain
~cors_origins
~cors_headers
?rpc_tls
?log_output
?synchronisation_threshold
?history_mode
?latency
cfg
let read_and_patch_config_file ?may_override_network ?emit
?ignore_bootstrap_peers args =
let open Lwt_result_syntax in
let* cfg = read_config_file args in
patch_config ?may_override_network ?emit ?ignore_bootstrap_peers ~cfg args