12 #include <rapidjson/document.h> 13 #include <rapidjson/filereadstream.h> 14 #include <boost/algorithm/string.hpp> 15 #include <boost/filesystem.hpp> 16 #include <boost/program_options.hpp> 17 #include <boost/uuid/uuid_generators.hpp> 18 #include <boost/uuid/uuid_io.hpp> 33 template <
typename T,
typename Func>
34 inline void find_argument(boost::program_options::variables_map &vm,
37 assert(
nullptr != name);
38 if (
auto it = vm.find(name); it != vm.end()) {
39 if (it->second.defaulted()) {
42 std::forward<Func>(f)(it->second.as<T>());
47 inline std::optional<T> find_argument(
48 boost::program_options::variables_map &vm,
const std::string &name) {
49 if (
auto it = vm.find(name); it != vm.end()) {
50 if (!it->second.defaulted()) {
51 return it->second.as<T>();
57 const std::string def_rpc_http_host =
"0.0.0.0";
58 const std::string def_rpc_ws_host =
"0.0.0.0";
59 const std::string def_openmetrics_http_host =
"0.0.0.0";
60 const uint16_t def_rpc_http_port = 9933;
61 const uint16_t def_rpc_ws_port = 9944;
62 const uint16_t def_openmetrics_http_port = 9615;
63 const uint32_t def_ws_max_connections = 500;
64 const uint16_t def_p2p_port = 30363;
65 const bool def_dev_mode =
false;
71 const auto def_sync_method =
73 const auto def_runtime_exec_method =
75 const auto def_use_wavm_cache_ =
false;
76 const auto def_purge_wavm_cache_ =
false;
77 const auto def_offchain_worker_mode =
79 const bool def_enable_offchain_indexing =
false;
80 const bool def_subcommand_chain_info =
false;
81 const std::optional<kagome::primitives::BlockId> def_block_to_recover =
83 const auto def_offchain_worker =
"WhenValidating";
84 const uint32_t def_out_peers = 25;
85 const uint32_t def_in_peers = 25;
86 const uint32_t def_in_peers_light = 100;
87 const auto def_lucky_peers = 4;
88 const uint32_t def_random_walk_interval = 15;
89 const auto def_full_sync =
"Full";
90 const auto def_wasm_execution =
"Interpreted";
96 const std::string &randomNodeName() {
97 static std::string name;
99 auto uuid = boost::uuids::random_generator()();
103 if (name.length() > max_len) {
104 name = name.substr(0, max_len);
109 std::optional<kagome::application::AppConfiguration::SyncMethod>
110 str_to_sync_method(std::string_view str) {
121 std::optional<kagome::application::AppConfiguration::RuntimeExecutionMethod>
122 str_to_runtime_exec_method(std::string_view str) {
124 if (str ==
"Interpreted") {
125 return REM::Interpret;
127 if (str ==
"Compiled") {
133 std::optional<kagome::application::AppConfiguration::OffchainWorkerMode>
134 str_to_offchain_worker_mode(std::string_view str) {
136 if (str ==
"Always") {
139 if (str ==
"Newer") {
142 if (str ==
"WhenValidating") {
143 return Mode::WhenValidating;
148 std::optional<kagome::primitives::BlockId> str_to_recovery_state(
149 std::string_view str) {
152 if (res.has_value()) {
153 return {{res.value()}};
156 auto result = std::from_chars(str.data(), str.data() + str.size(), bn);
157 if (result.ec != std::errc::invalid_argument &&
std::to_string(bn) == str) {
164 auto &devAccounts() {
167 std::tuple<const char *, std::string_view, std::string_view>;
168 static const std::array<Account, 6> accounts{
169 Account{
"alice",
"Alice", dev.alice},
170 Account{
"bob",
"Bob", dev.bob},
171 Account{
"charlie",
"Charlie", dev.charlie},
172 Account{
"dave",
"Dave", dev.dave},
173 Account{
"eve",
"Eve", dev.eve},
174 Account{
"ferdie",
"Ferdie", dev.ferdie},
183 : logger_(
std::move(logger)),
185 save_node_key_(false),
186 is_telemetry_enabled_(true),
187 p2p_port_(def_p2p_port),
188 max_blocks_in_response_(kAbsolutMaxBlocksInResponse),
189 rpc_http_host_(def_rpc_http_host),
190 rpc_ws_host_(def_rpc_ws_host),
191 openmetrics_http_host_(def_openmetrics_http_host),
192 rpc_http_port_(def_rpc_http_port),
193 rpc_ws_port_(def_rpc_ws_port),
194 openmetrics_http_port_(def_openmetrics_http_port),
195 out_peers_(def_out_peers),
196 in_peers_(def_in_peers),
197 in_peers_light_(def_in_peers_light),
198 lucky_peers_(def_lucky_peers),
199 dev_mode_(def_dev_mode),
200 node_name_(randomNodeName()),
202 max_ws_connections_(def_ws_max_connections),
203 random_walk_interval_(def_random_walk_interval),
204 sync_method_{def_sync_method},
220 return boost::filesystem::temp_directory_path() /
"kagome/runtimes-cache";
224 std::string runtime_hash)
const {
229 std::string chain_id)
const {
243 const std::string &filepath) {
244 assert(!filepath.empty());
251 std::vector<std::string> &target) {
252 for (
auto it = val.FindMember(name); it != val.MemberEnd(); ++it) {
253 auto &value = it->value;
254 target.emplace_back(value.GetString(), value.GetStringLength());
256 return not target.empty();
260 const rapidjson::Value &val,
262 std::vector<libp2p::multi::Multiaddress> &target) {
263 for (
auto it = val.FindMember(name); it != val.MemberEnd(); ++it) {
264 auto &value = it->value;
265 auto ma_res = libp2p::multi::Multiaddress::create(
266 std::string(value.GetString(), value.GetStringLength()));
270 target.emplace_back(std::move(ma_res.value()));
272 return not target.empty();
276 const rapidjson::Value &val,
278 std::vector<telemetry::TelemetryEndpoint> &target) {
279 auto it = val.FindMember(name);
280 if (it != val.MemberEnd() and it->value.IsArray()) {
281 for (
auto &v : it->value.GetArray()) {
284 if (result.has_value()) {
285 target.emplace_back(std::move(result.value()));
297 std::string &target) {
298 auto m = val.FindMember(name);
299 if (val.MemberEnd() != m && m->value.IsString()) {
300 target.assign(m->value.GetString(), m->value.GetStringLength());
309 auto m = val.FindMember(name);
310 if (val.MemberEnd() != m && m->value.IsBool()) {
311 target = m->value.GetBool();
322 && (i & ~std::numeric_limits<uint16_t>::max()) == 0) {
323 target =
static_cast<uint16_t
>(i);
332 if (
auto m = val.FindMember(name);
333 val.MemberEnd() != m && m->value.IsInt()) {
334 const auto v = m->value.GetInt();
335 if ((v & (1u << 31u)) == 0) {
336 target =
static_cast<uint32_t
>(v);
346 if (
auto m = val.FindMember(name);
347 val.MemberEnd() != m && m->value.IsInt()) {
348 target = m->value.GetInt();
355 const rapidjson::Value &val) {
356 bool validator_mode =
false;
357 load_bool(val,
"validator", validator_mode);
358 if (validator_mode) {
367 const rapidjson::Value &val) {
368 std::string chain_spec_path_str;
369 load_str(val,
"chain", chain_spec_path_str);
374 const rapidjson::Value &val) {
375 std::string base_path_str;
376 load_str(val,
"base-path", base_path_str);
379 std::string database_engine_str;
380 if (
load_str(val,
"database", database_engine_str)) {
381 if (
"rocksdb" == database_engine_str) {
385 "Unsupported database backend was specified {}, " 386 "available options are [rocksdb]",
387 database_engine_str);
394 const rapidjson::Value &val) {
416 const rapidjson::Value &val) {
424 "Chain path {} does not exist, " 425 "please specify a valid path with --chain option",
432 "Base path {} does not exist, " 433 "please specify a valid path with -d option",
440 "Listen addresses are set. The p2p port value would be ignored " 445 "please specify a valid path with -p option");
452 "please specify a valid path with --ws-port option");
458 "RPC http port is 0, " 459 "please specify a valid path with --rpc-port option");
465 "Node name exceeds the maximum length of {} characters",
479 const std::string &filepath) {
480 assert(!filepath.empty());
485 "Configuration file path is invalid: {}, " 486 "please specify a valid path with -c option",
491 using FileReadStream = rapidjson::FileReadStream;
492 using Document = rapidjson::Document;
494 std::array<char, 1024> buffer_size{};
495 FileReadStream input_stream(
496 file.get(), buffer_size.data(), buffer_size.size());
499 document.ParseStream(input_stream);
500 if (document.HasParseError()) {
502 "Configuration file {} parse failed with error {}",
504 document.GetParseError());
509 auto it = document.FindMember(handler.segment_name);
510 if (document.MemberEnd() != it) {
511 handler.handler(it->value);
517 std::string
const &host, uint16_t port)
const {
518 boost::asio::ip::tcp::endpoint endpoint;
519 boost::system::error_code err;
521 endpoint.address(boost::asio::ip::address::from_string(host, err));
523 SL_ERROR(
logger_,
"RPC address '{}' is invalid", host);
531 outcome::result<boost::asio::ip::tcp::endpoint>
533 const libp2p::multi::Multiaddress &multiaddress)
const {
534 using proto = libp2p::multi::Protocol::Code;
535 constexpr
auto NOT_SUPPORTED = std::errc::address_family_not_supported;
536 constexpr
auto BAD_ADDRESS = std::errc::bad_address;
537 auto host = multiaddress.getFirstValueForProtocol(proto::IP4);
539 host = multiaddress.getFirstValueForProtocol(proto::IP6);
543 "Address cannot be used to bind to ({}). Only IPv4 and IPv6 " 544 "interfaces are supported",
545 multiaddress.getStringAddress());
546 return NOT_SUPPORTED;
548 auto port = multiaddress.getFirstValueForProtocol(proto::TCP);
550 return NOT_SUPPORTED;
552 uint16_t port_number = 0;
554 auto wide_port = std::stoul(port.value());
555 constexpr
auto max_port = std::numeric_limits<uint16_t>::max();
556 if (wide_port > max_port or 0 == wide_port) {
559 "Port value ({}) cannot be zero or greater than {} (address {})",
562 multiaddress.getStringAddress());
565 port_number =
static_cast<uint16_t
>(wide_port);
569 "Passed value {} is not a valid port number within address {}",
571 multiaddress.getStringAddress());
578 auto temp_context = std::make_shared<boost::asio::io_context>();
579 constexpr
auto kZeroPortTolerance = 0;
584 "Endpoint cannot be constructed from address {}",
585 addr.getStringAddress());
589 boost::system::error_code error_code;
591 temp_context, endpoint.value(), kZeroPortTolerance,
logger_);
592 acceptor->cancel(error_code);
593 acceptor->close(error_code);
596 logger_,
"Unable to listen on address {}", addr.getStringAddress());
603 std::optional<telemetry::TelemetryEndpoint>
605 const std::string &record)
const {
613 const auto len = record.length();
614 constexpr
auto kSpaceChar =
' ';
615 if (kSpaceChar != record.at(len - 2)) {
617 "record '{}' could not be parsed as a valid telemetry endpoint. " 618 "The desired format is '<endpoint uri> <verbosity: 0-9>'",
624 uint8_t verbosity_level{0};
626 auto verbosity_char = record.substr(len - 1);
627 int verbosity_level_parsed = std::stoi(verbosity_char);
630 if (verbosity_level_parsed < 0 or verbosity_level_parsed > 9) {
631 throw std::out_of_range(
"verbosity level value is out of range");
633 verbosity_level =
static_cast<uint8_t
>(verbosity_level_parsed);
634 }
catch (std::invalid_argument
const &e) {
636 "record '{}' could not be parsed as a valid telemetry endpoint. " 637 "The desired format is '<endpoint uri> <verbosity: 0-9>'. " 638 "Verbosity level does not meet the format: {}",
642 }
catch (std::out_of_range
const &e) {
644 "record '{}' could not be parsed as a valid telemetry endpoint. " 645 "The desired format is '<endpoint uri> <verbosity: 0-9>'. " 646 "Verbosity level does not meet the format: {}",
653 auto uri_part = record.substr(0, len - 2);
655 if (not uri_part.empty() and
'/' == uri_part.at(0)) {
657 auto ma_res = libp2p::multi::Multiaddress::create(uri_part);
658 if (ma_res.has_error()) {
660 "Telemetry endpoint '{}' cannot be interpreted as a valid " 661 "multiaddress and was skipped due to error: {}",
663 ma_res.error().message());
669 auto parts = ma_res.value().getProtocolsWithValues();
670 if (parts.size() != 3) {
672 "Telemetry endpoint '{}' has unknown format and was skipped",
676 auto host = parts[0].second;
677 auto schema = parts[2].first.name.substr(std::strlen(
"x-parity-"));
678 auto path = std::regex_replace(parts[2].second, std::regex(
"%2F"),
"/");
679 uri_part = fmt::format(
"{}://{}{}", schema, host, path);
684 if (uri.error().has_value()) {
686 "record '{}' could not be parsed as a valid telemetry endpoint. " 687 "The desired format is '<endpoint uri> <verbosity: 0-9>'. " 688 "Endpoint URI parsing failed: {}",
690 uri.error().value());
698 namespace po = boost::program_options;
701 po::options_description desc(
"General options");
703 (
"help,h",
"show this help message")
704 (
"log,l", po::value<std::vector<std::string>>(),
705 "Sets a custom logging filter. Syntax is `<target>=<level>`, e.g. -llibp2p=off.\n" 706 "Log levels (most to least verbose) are trace, debug, verbose, info, warn, error, critical, off. By default, all targets log `info`.\n" 707 "The global log level can be set with -l<level>.")
708 (
"validator",
"Enable validator node")
709 (
"config-file,c", po::value<std::string>(),
"Filepath to load configuration from.")
712 po::options_description blockhain_desc(
"Blockchain options");
713 blockhain_desc.add_options()
714 (
"chain", po::value<std::string>(),
"required, chainspec file path")
715 (
"offchain-worker", po::value<std::string>()->default_value(def_offchain_worker),
716 "Should execute offchain workers on every block.\n" 717 "Possible values: Always, Never, WhenValidating. WhenValidating is used by default.")
718 (
"chain-info", po::bool_switch(),
"Print chain info as JSON")
721 po::options_description storage_desc(
"Storage options");
722 storage_desc.add_options()
723 (
"base-path,d", po::value<std::string>(),
"required, node base path (keeps storage and keys for known chains)")
724 (
"keystore", po::value<std::string>(),
"required, node keystore")
725 (
"tmp",
"Use temporary storage path")
726 (
"database", po::value<std::string>()->default_value(
"rocksdb"),
"Database backend to use [rocksdb]")
727 (
"enable-offchain-indexing", po::value<bool>(),
"enable Offchain Indexing API, which allow block import to write to offchain DB)")
728 (
"recovery", po::value<std::string>(),
"recovers block storage to state after provided block presented by number or hash, and stop after that")
731 po::options_description network_desc(
"Network options");
732 network_desc.add_options()
733 (
"listen-addr", po::value<std::vector<std::string>>()->multitoken(),
"multiaddresses the node listens for open connections on")
734 (
"public-addr", po::value<std::vector<std::string>>()->multitoken(),
"multiaddresses that other nodes use to connect to it")
735 (
"node-key", po::value<std::string>(),
"the secret key to use for libp2p networking")
736 (
"node-key-file", po::value<std::string>(),
"path to the secret key used for libp2p networking (raw binary or hex-encoded")
737 (
"save-node-key", po::bool_switch(),
"save generated libp2p networking key, key will be reused on node restart")
738 (
"bootnodes", po::value<std::vector<std::string>>()->multitoken(),
"multiaddresses of bootstrap nodes")
739 (
"port,p", po::value<uint16_t>(),
"port for peer to peer interactions")
740 (
"rpc-host", po::value<std::string>(),
"address for RPC over HTTP")
741 (
"rpc-port", po::value<uint16_t>(),
"port for RPC over HTTP")
742 (
"ws-host", po::value<std::string>(),
"address for RPC over Websocket protocol")
743 (
"ws-port", po::value<uint16_t>(),
"port for RPC over Websocket protocol")
744 (
"ws-max-connections", po::value<uint32_t>(),
"maximum number of WS RPC server connections")
745 (
"prometheus-host", po::value<std::string>(),
"address for OpenMetrics over HTTP")
746 (
"prometheus-port", po::value<uint16_t>(),
"port for OpenMetrics over HTTP")
747 (
"out-peers", po::value<uint32_t>()->default_value(def_out_peers),
"number of outgoing connections we're trying to maintain")
748 (
"in-peers", po::value<uint32_t>()->default_value(def_in_peers),
"maximum number of inbound full nodes peers")
749 (
"in-peers-light", po::value<uint32_t>()->default_value(def_in_peers_light),
"maximum number of inbound light nodes peers")
750 (
"lucky-peers", po::value<int32_t>()->default_value(def_lucky_peers),
"number of \"lucky\" peers (peers that are being gossiped to). -1 for broadcast." )
751 (
"max-blocks-in-response", po::value<uint32_t>(),
"max block per response while syncing")
752 (
"name", po::value<std::string>(),
"the human-readable name for this node")
753 (
"no-telemetry", po::bool_switch(),
"Disables telemetry broadcasting")
754 (
"telemetry-url", po::value<std::vector<std::string>>()->multitoken(),
755 "the URL of the telemetry server to connect to and verbosity level (0-9),\n" 756 "e.g. --telemetry-url 'wss://foo/bar 0'")
757 (
"random-walk-interval", po::value<uint32_t>()->default_value(def_random_walk_interval),
"Kademlia random walk interval")
760 po::options_description development_desc(
"Additional options");
761 development_desc.add_options()
762 (
"dev",
"if node run in development mode")
763 (
"dev-with-wipe",
"if needed to wipe base path (only for dev mode)")
764 (
"sync", po::value<std::string>()->default_value(def_full_sync),
765 "choose the desired sync method (Full, Fast). Full is used by default.")
766 (
"wasm-execution", po::value<std::string>()->default_value(def_wasm_execution),
767 "choose the desired wasm execution method (Compiled, Interpreted)")
768 (
"unsafe-cached-wavm-runtime",
"use WAVM runtime cache")
769 (
"purge-wavm-cache",
"purge WAVM runtime cache")
774 for (
auto &[flag, name, dev] : devAccounts()) {
775 development_desc.add_options()(flag, po::bool_switch());
778 po::variables_map vm;
781 po::parsed_options parsed = po::command_line_parser(argc, argv)
783 .allow_unregistered()
785 po::store(parsed, vm);
788 desc.add(blockhain_desc)
791 .add(development_desc);
793 if (vm.count(
"help") > 0) {
794 std::cout << desc << std::endl;
801 po::store(po::parse_command_line(argc, argv, desc), vm);
802 po::store(parsed, vm);
804 }
catch (
const std::exception &e) {
805 std::cerr <<
"Error: " << e.what() <<
'\n' 806 <<
"Try run with option '--help' for more information" 812 if (vm.count(
"dev") > 0 or vm.count(
"dev-with-wipe") > 0) {
813 constexpr
auto with_kagome_embeddings =
814 #ifdef USE_KAGOME_EMBEDDINGS 818 #endif // USE_KAGOME_EMBEDDINGS 820 if constexpr (not with_kagome_embeddings) {
821 std::cerr <<
"Warning: developers mode is not available. " 822 "Application was built without developers embeddings " 823 "(EMBEDDINGS option is OFF)." 829 auto dev_env_path = fs::temp_directory_path() /
"kagome_dev";
834 if (vm.count(
"dev-with-wipe") > 0) {
835 boost::filesystem::remove_all(dev_env_path);
849 if (not chain_spec.has_value()) {
850 std::cerr <<
"Warning: developers mode chain spec is corrupted." 855 if (chain_spec.value()->bootNodes().empty()) {
857 <<
"Warning: developers mode chain spec bootnodes is empty." 862 auto ma_res = chain_spec.value()->bootNodes()[0];
865 boost::filesystem::create_directories(path);
868 ofs.open((path / key_descr.first).native(), std::ios::ate);
869 ofs << key_descr.second;
886 std::optional<std::string> dev_account_flag;
887 for (
auto &[flag, name, dev] : devAccounts()) {
888 if (
auto val = find_argument<bool>(vm, flag); val && *val) {
889 if (dev_account_flag) {
891 logger_,
"--{} conflicts with --{}", flag, *dev_account_flag);
894 dev_account_flag = flag;
900 find_argument<std::string>(vm,
"config-file", [&](std::string
const &path) {
902 std::cerr <<
"Warning: config file has ignored because dev mode" 909 if (vm.end() != vm.find(
"validator")) {
914 find_argument<std::string>(
918 <<
" does not exist." << std::endl;
921 if (vm.end() != vm.find(
"tmp")) {
922 base_path_ = (boost::filesystem::temp_directory_path()
923 / boost::filesystem::unique_path());
925 find_argument<std::string>(
926 vm,
"base-path", [&](
const std::string &val) {
base_path_ = val; });
929 find_argument<std::string>(
930 vm,
"keystore", [&](
const std::string &val) {
keystore_path_ = val; });
932 bool unknown_database_engine_is_set =
false;
933 find_argument<std::string>(vm,
"database", [&](
const std::string &val) {
934 if (
"rocksdb" == val) {
937 unknown_database_engine_is_set =
true;
939 "Unsupported database backend was specified {}, " 940 "available options are [rocksdb]",
944 if (unknown_database_engine_is_set) {
948 std::vector<std::string> boot_nodes;
949 find_argument<std::vector<std::string>>(
950 vm,
"bootnodes", [&](
const std::vector<std::string> &val) {
953 if (not boot_nodes.empty()) {
956 for (
auto &addr_str : boot_nodes) {
957 auto ma_res = libp2p::multi::Multiaddress::create(addr_str);
958 if (not ma_res.has_value()) {
959 auto err_msg =
"Bootnode '" + addr_str
960 +
"' is invalid: " + ma_res.error().message();
961 SL_ERROR(
logger_,
"{}", err_msg);
962 std::cout << err_msg << std::endl;
965 auto peer_id_base58_opt = ma_res.value().getPeerId();
966 if (not peer_id_base58_opt) {
967 auto err_msg =
"Bootnode '" + addr_str +
"' has not peer_id";
968 SL_ERROR(
logger_,
"{}", err_msg);
969 std::cout << err_msg << std::endl;
972 boot_nodes_.emplace_back(std::move(ma_res.value()));
976 std::optional<std::string> node_key;
977 find_argument<std::string>(
978 vm,
"node-key", [&](
const std::string &val) { node_key.emplace(val); });
979 if (node_key.has_value()) {
980 auto key_res = crypto::Ed25519PrivateKey::fromHex(node_key.value());
981 if (not key_res.has_value()) {
982 auto err_msg =
"Node key '" + node_key.value()
983 +
"' is invalid: " + key_res.error().message();
984 SL_ERROR(
logger_,
"{}", err_msg);
985 std::cout << err_msg << std::endl;
988 node_key_.emplace(std::move(key_res.value()));
992 find_argument<std::string>(
993 vm,
"node-key-file", [&](
const std::string &val) {
1001 find_argument<uint16_t>(vm,
"port", [&](uint16_t val) {
p2p_port_ = val; });
1003 auto parse_multiaddrs =
1004 [&](
const std::string ¶m_name,
1005 std::vector<libp2p::multi::Multiaddress> &output_field) ->
bool {
1006 std::vector<std::string> addrs;
1007 find_argument<std::vector<std::string>>(
1008 vm, param_name.c_str(), [&](
const auto &val) { addrs = val; });
1010 if (not addrs.empty()) {
1011 output_field.clear();
1013 for (
auto &s : addrs) {
1014 auto ma_res = libp2p::multi::Multiaddress::create(s);
1017 "Address {} passed as value to {} is invalid: {}",
1020 ma_res.error().message());
1023 output_field.emplace_back(std::move(ma_res.value()));
1041 "Public addresses are not specified. Using listen addresses as " 1042 "node's public addresses");
1049 auto ma_res = libp2p::multi::Multiaddress::create(
1054 "Cannot construct IPv6 listen multiaddress from port {}. Error: " 1057 ma_res.error().message());
1060 "Automatically added IPv6 listen address {}",
1061 ma_res.value().getStringAddress());
1068 auto ma_res = libp2p::multi::Multiaddress::create(
1073 "Cannot construct IPv4 listen multiaddress from port {}. Error: " 1076 ma_res.error().message());
1079 "Automatically added IPv4 listen address {}",
1080 ma_res.value().getStringAddress());
1088 "One of configured listen addresses is unavailable, the node " 1093 find_argument<uint32_t>(vm,
"max-blocks-in-response", [&](uint32_t val) {
1097 find_argument<std::vector<std::string>>(
1098 vm,
"log", [&](
const std::vector<std::string> &val) {
1102 find_argument<std::string>(
1103 vm,
"rpc-host", [&](std::string
const &val) {
rpc_http_host_ = val; });
1105 find_argument<std::string>(
1106 vm,
"ws-host", [&](std::string
const &val) {
rpc_ws_host_ = val; });
1108 find_argument<std::string>(
1109 vm,
"prometheus-host", [&](std::string
const &val) {
1113 find_argument<uint16_t>(
1116 find_argument<uint16_t>(
1117 vm,
"ws-port", [&](uint16_t val) {
rpc_ws_port_ = val; });
1119 find_argument<uint16_t>(vm,
"prometheus-port", [&](uint16_t val) {
1123 find_argument<uint32_t>(
1124 vm,
"out-peers", [&](uint32_t val) {
out_peers_ = val; });
1126 find_argument<uint32_t>(
1127 vm,
"in-peers", [&](uint32_t val) {
in_peers_ = val; });
1129 find_argument<uint32_t>(
1132 find_argument<int32_t>(
1133 vm,
"lucky-peers", [&](int32_t val) {
lucky_peers_ = val; });
1135 find_argument<uint32_t>(vm,
"ws-max-connections", [&](uint32_t val) {
1139 find_argument<uint32_t>(vm,
"random-walk-interval", [&](uint32_t val) {
1148 find_argument<std::string>(
1149 vm,
"name", [&](std::string
const &val) {
node_name_ = val; });
1151 auto parse_telemetry_urls =
1152 [&](
const std::string ¶m_name,
1153 std::vector<telemetry::TelemetryEndpoint> &output_field) ->
bool {
1154 std::vector<std::string> tokens;
1155 find_argument<std::vector<std::string>>(
1156 vm, param_name.c_str(), [&](
const auto &val) { tokens = val; });
1158 for (
const auto &token : tokens) {
1160 if (result.has_value()) {
1169 find_argument<bool>(vm,
"no-telemetry", [&](
bool telemetry_disabled) {
1179 bool sync_method_value_error =
false;
1180 find_argument<std::string>(
1181 vm,
"sync", [
this, &sync_method_value_error](std::string
const &val) {
1182 auto sync_method_opt = str_to_sync_method(val);
1183 if (not sync_method_opt) {
1184 sync_method_value_error =
true;
1185 SL_ERROR(
logger_,
"Invalid sync method specified: '{}'", val);
1190 if (sync_method_value_error) {
1194 bool exec_method_value_error =
false;
1195 find_argument<std::string>(
1198 [
this, &exec_method_value_error](std::string
const &val) {
1199 auto runtime_exec_method_opt = str_to_runtime_exec_method(val);
1200 if (not runtime_exec_method_opt) {
1201 exec_method_value_error =
true;
1203 "Invalid runtime execution method specified: '{}'",
1209 if (exec_method_value_error) {
1213 if (vm.count(
"unsafe-cached-wavm-runtime") > 0) {
1217 if (vm.count(
"purge-wavm-cache") > 0) {
1220 boost::system::error_code ec;
1224 "Failed to purge cache in {} ['{}']",
1231 bool offchain_worker_value_error =
false;
1232 find_argument<std::string>(
1235 [
this, &offchain_worker_value_error](std::string
const &val) {
1236 auto offchain_worker_mode_opt = str_to_offchain_worker_mode(val);
1237 if (offchain_worker_mode_opt) {
1240 offchain_worker_value_error =
true;
1242 logger_,
"Invalid offchain worker mode specified: '{}'", val);
1245 if (offchain_worker_value_error) {
1249 if (vm.count(
"enable-offchain-indexing") > 0) {
1253 find_argument<bool>(vm,
"chain-info", [&](
bool subcommand_chain_info) {
1257 bool has_recovery =
false;
1258 find_argument<std::string>(vm,
"recovery", [&](
const std::string &val) {
1259 has_recovery =
true;
1262 SL_ERROR(
logger_,
"Invalid recovery state specified: '{}'", val);
1271 std::cout << desc << std::endl;
const std::vector< std::pair< const char *, const char * > > embedded_keys
boost::asio::ip::tcp::endpoint rpc_ws_endpoint_
boost::asio::ip::tcp::endpoint rpc_http_endpoint_
struct kagome::network::Roles::@11 flags
std::optional< primitives::BlockId > recovery_state_
StorageBackend storage_backend_
bool subcommand_chain_info_
std::string openmetrics_http_host_
bool load_u16(const rapidjson::Value &val, char const *name, uint16_t &target)
boost::asio::ip::tcp::endpoint openmetrics_http_endpoint_
uint32_t max_ws_connections_
static const DevMnemonicPhrase & get()
bool load_str(const rapidjson::Value &val, char const *name, std::string &target)
void parse_additional_segment(const rapidjson::Value &val)
boost::filesystem::path chainSpecPath() const override
std::string_view to_string(SlotType s)
boost::filesystem::path keystorePath(std::string chain_id) const override
bool load_i32(const rapidjson::Value &val, char const *name, int32_t &target)
static constexpr uint32_t kAbsolutMinBlocksInResponse
std::vector< libp2p::multi::Multiaddress > boot_nodes_
bool enable_offchain_indexing_
static outcome::result< std::shared_ptr< ChainSpecImpl > > loadFrom(const std::string &config_path)
std::optional< crypto::Ed25519PrivateKey > node_key_
std::vector< std::string > logger_tuning_config_
void parse_network_segment(const rapidjson::Value &val)
std::optional< telemetry::TelemetryEndpoint > parseTelemetryEndpoint(const std::string &record) const
static Uri parse(std::string_view uri)
std::optional< boost::filesystem::path > keystore_path_
FilePtr open_file(const std::string &filepath)
void parse_general_segment(const rapidjson::Value &val)
boost::filesystem::path chain_spec_path_
std::string rpc_http_host_
bool is_telemetry_enabled_
const char *const embedded_chainspec
bool createDirectoryRecursive(const path &path)
static constexpr uint32_t kAbsolutMaxBlocksInResponse
std::vector< libp2p::multi::Multiaddress > listen_addresses_
boost::filesystem::path base_path_
std::unique_ptr< Acceptor > acceptOnFreePort(std::shared_ptr< boost::asio::io_context > context, Endpoint endpoint, uint16_t port_tolerance, const log::Logger &logger)
std::optional< std::string > dev_mnemonic_phrase_
std::shared_ptr< soralog::Logger > Logger
bool initializeFromArgs(int argc, const char **argv)
std::vector< libp2p::multi::Multiaddress > public_addresses_
boost::filesystem::path runtimeCacheDirPath() const override
uint32_t max_blocks_in_response_
const std::string & buildVersion()
std::vector< SegmentHandler > handlers_
bool load_u32(const rapidjson::Value &val, char const *name, uint32_t &target)
boost::filesystem::path runtimeCachePath(std::string runtime_hash) const override
static constexpr uint32_t kNodeNameMaxLength
std::unique_ptr< std::FILE, decltype(&std::fclose)> FilePtr
boost::filesystem::path databasePath(std::string chain_id) const override
uint32_t random_walk_interval_
void parse_storage_segment(const rapidjson::Value &val)
std::optional< std::string > node_key_file_
bool load_ms(const rapidjson::Value &val, char const *name, std::vector< std::string > &target)
bool load_telemetry_uris(const rapidjson::Value &val, char const *name, std::vector< telemetry::TelemetryEndpoint > &target)
bool load_bool(const rapidjson::Value &val, char const *name, bool &target)
void read_config_from_file(const std::string &filepath)
AppConfigurationImpl(log::Logger logger)
bool testListenAddresses() const
boost::filesystem::path chainPath(std::string chain_id) const override
void parse_blockchain_segment(const rapidjson::Value &val)
RuntimeExecutionMethod runtime_exec_method_
uint16_t openmetrics_http_port_
bool load_ma(const rapidjson::Value &val, char const *name, std::vector< libp2p::multi::Multiaddress > &target)
boost::asio::ip::tcp::endpoint getEndpointFrom(const std::string &host, uint16_t port) const
std::vector< telemetry::TelemetryEndpoint > telemetry_endpoints_
static outcome::result< Blob< size_ > > fromHex(std::string_view hex)
OffchainWorkerMode offchain_worker_mode_