477 for (
auto& line : strVec)
480 if (
std::count(line.begin(), line.end(),
':') != 1)
486 if (result.
size() == line.size())
499 boost::filesystem::path p(dbPath);
500 legacy(
"database_path", boost::filesystem::absolute(p).
string());
508 if (strTemp ==
"main")
510 else if (strTemp ==
"testnet")
512 else if (strTemp ==
"devnet")
515 NETWORK_ID = beast::lexicalCastThrow<uint32_t>(strTemp);
523 PEERS_MAX = beast::lexicalCastThrow<std::size_t>(strTemp);
530 peers_in_max = beast::lexicalCastThrow<std::size_t>(strTemp);
531 if (*peers_in_max > 1000)
532 Throw<std::runtime_error>(
533 "Invalid value specified in [" SECTION_PEERS_IN_MAX
534 "] section; the value must be less or equal than 1000");
540 peers_out_max = beast::lexicalCastThrow<std::size_t>(strTemp);
541 if (*peers_out_max < 10 || *peers_out_max > 1000)
542 Throw<std::runtime_error>(
543 "Invalid value specified in [" SECTION_PEERS_OUT_MAX
544 "] section; the value must be in range 10-1000");
548 if ((peers_in_max && !peers_out_max) ||
549 (peers_out_max && !peers_in_max))
550 Throw<std::runtime_error>(
"Both sections [" SECTION_PEERS_IN_MAX
552 "and [" SECTION_PEERS_OUT_MAX
553 "] must be configured");
555 if (peers_in_max && peers_out_max)
564 if (boost::iequals(strTemp,
"tiny"))
566 else if (boost::iequals(strTemp,
"small"))
568 else if (boost::iequals(strTemp,
"medium"))
570 else if (boost::iequals(strTemp,
"large"))
572 else if (boost::iequals(strTemp,
"huge"))
576 4, beast::lexicalCastThrow<std::size_t>(strTemp));
583 ELB_SUPPORT = beast::lexicalCastThrow<bool>(strTemp);
589 SSL_VERIFY = beast::lexicalCastThrow<bool>(strTemp);
593 if (boost::iequals(strTemp,
"all"))
595 else if (boost::iequals(strTemp,
"trusted"))
597 else if (boost::iequals(strTemp,
"drop_untrusted"))
600 Throw<std::runtime_error>(
601 "Invalid value specified in [" SECTION_RELAY_VALIDATIONS
607 if (boost::iequals(strTemp,
"all"))
609 else if (boost::iequals(strTemp,
"trusted"))
611 else if (boost::iequals(strTemp,
"drop_untrusted"))
614 Throw<std::runtime_error>(
615 "Invalid value specified in [" SECTION_RELAY_PROPOSALS
619 if (
exists(SECTION_VALIDATION_SEED) &&
exists(SECTION_VALIDATOR_TOKEN))
620 Throw<std::runtime_error>(
"Cannot have both [" SECTION_VALIDATION_SEED
621 "] and [" SECTION_VALIDATOR_TOKEN
622 "] config sections");
636 if (boost::iequals(strTemp,
"full"))
639 else if (boost::iequals(strTemp,
"none"))
647 if (boost::iequals(strTemp,
"none"))
649 else if (boost::iequals(strTemp,
"full"))
652 FETCH_DEPTH = beast::lexicalCastThrow<std::uint32_t>(strTemp);
660 if (
exists(SECTION_VALIDATION_SEED) ||
exists(SECTION_VALIDATOR_TOKEN))
666 PATH_SEARCH = beast::lexicalCastThrow<int>(strTemp);
679 if (SWEEP_INTERVAL < 10 || SWEEP_INTERVAL > 600)
680 Throw<std::runtime_error>(
"Invalid " SECTION_SWEEP_INTERVAL
681 ": must be between 10 and 600 inclusive");
686 WORKERS = beast::lexicalCastThrow<int>(strTemp);
688 if (WORKERS < 1 || WORKERS > 1024)
689 Throw<std::runtime_error>(
690 "Invalid " SECTION_WORKERS
691 ": must be between 1 and 1024 inclusive.");
696 IO_WORKERS = beast::lexicalCastThrow<int>(strTemp);
698 if (IO_WORKERS < 1 || IO_WORKERS > 1024)
699 Throw<std::runtime_error>(
700 "Invalid " SECTION_IO_WORKERS
701 ": must be between 1 and 1024 inclusive.");
708 if (PREFETCH_WORKERS < 1 || PREFETCH_WORKERS > 1024)
709 Throw<std::runtime_error>(
710 "Invalid " SECTION_PREFETCH_WORKERS
711 ": must be between 1 and 1024 inclusive.");
715 COMPRESSION = beast::lexicalCastThrow<bool>(strTemp);
720 if (
exists(SECTION_REDUCE_RELAY))
722 auto sec =
section(SECTION_REDUCE_RELAY);
730 if (sec.exists(
"vp_base_squelch_enable") && sec.exists(
"vp_enable"))
731 Throw<std::runtime_error>(
732 "Invalid " SECTION_REDUCE_RELAY
733 " cannot specify both vp_base_squelch_enable and vp_enable "
735 "vp_enable was deprecated and replaced by "
736 "vp_base_squelch_enable");
738 if (sec.exists(
"vp_base_squelch_enable"))
740 sec.value_or(
"vp_base_squelch_enable",
false);
741 else if (sec.exists(
"vp_enable"))
743 sec.value_or(
"vp_enable",
false);
753 sec.value_or(
"vp_base_squelch_max_selected_peers", 5);
755 Throw<std::runtime_error>(
756 "Invalid " SECTION_REDUCE_RELAY
757 " vp_base_squelch_max_selected_peers must be "
758 "greater than or equal to 3");
765 if (TX_RELAY_PERCENTAGE < 10 || TX_RELAY_PERCENTAGE > 100 ||
767 Throw<std::runtime_error>(
768 "Invalid " SECTION_REDUCE_RELAY
769 ", tx_min_peers must be greater than or equal to 10"
770 ", tx_relay_percentage must be greater than or equal to 10 "
771 "and less than or equal to 100");
777 beast::lexicalCastThrow<int>(strTemp),
786 Throw<std::runtime_error>(
787 "Invalid " SECTION_SERVER_DOMAIN
788 ": the domain name does not appear to meet the requirements.");
794 if (
exists(SECTION_OVERLAY))
796 auto const sec =
section(SECTION_OVERLAY);
802 if (
auto val = sec.get(
"max_unknown_time"))
804 seconds{beast::lexicalCastThrow<std::uint32_t>(*val)};
808 Throw<std::runtime_error>(
809 "Invalid value 'max_unknown_time' in " SECTION_OVERLAY
810 ": must be of the form '<number>' representing seconds.");
814 Throw<std::runtime_error>(
815 "Invalid value 'max_unknown_time' in " SECTION_OVERLAY
816 ": the time must be between 300 and 1800 seconds, inclusive.");
820 if (
auto val = sec.get(
"max_diverged_time"))
822 seconds{beast::lexicalCastThrow<std::uint32_t>(*val)};
826 Throw<std::runtime_error>(
827 "Invalid value 'max_diverged_time' in " SECTION_OVERLAY
828 ": must be of the form '<number>' representing seconds.");
833 Throw<std::runtime_error>(
834 "Invalid value 'max_diverged_time' in " SECTION_OVERLAY
835 ": the time must be between 60 and 900 seconds, inclusive.");
840 secConfig, SECTION_AMENDMENT_MAJORITY_TIME, strTemp,
j_))
843 boost::regex
const re(
844 "^\\s*(\\d+)\\s*(minutes|hours|days|weeks)\\s*(\\s+.*)?$");
846 if (!boost::regex_match(strTemp,
match, re))
847 Throw<std::runtime_error>(
848 "Invalid " SECTION_AMENDMENT_MAJORITY_TIME
849 ", must be: [0-9]+ [minutes|hours|days|weeks]");
852 beast::lexicalCastThrow<std::uint32_t>(
match[1].str());
854 if (boost::iequals(
match[2],
"minutes"))
856 else if (boost::iequals(
match[2],
"hours"))
858 else if (boost::iequals(
match[2],
"days"))
860 else if (boost::iequals(
match[2],
"weeks"))
864 Throw<std::runtime_error>(
865 "Invalid " SECTION_AMENDMENT_MAJORITY_TIME
866 ", the minimum amount of time an amendment must hold a "
867 "majority is 15 minutes");
884 boost::filesystem::path validatorsFile;
888 validatorsFile = strTemp;
890 if (validatorsFile.empty())
891 Throw<std::runtime_error>(
892 "Invalid path specified in [" SECTION_VALIDATORS_FILE
"]");
894 if (!validatorsFile.is_absolute() && !
CONFIG_DIR.empty())
897 if (!boost::filesystem::exists(validatorsFile))
898 Throw<std::runtime_error>(
899 "The file specified in [" SECTION_VALIDATORS_FILE
902 validatorsFile.string());
905 !boost::filesystem::is_regular_file(validatorsFile) &&
906 !boost::filesystem::is_symlink(validatorsFile))
907 Throw<std::runtime_error>(
908 "Invalid file specified in [" SECTION_VALIDATORS_FILE
910 validatorsFile.string());
916 if (!validatorsFile.empty())
918 if (!boost::filesystem::exists(validatorsFile))
919 validatorsFile.clear();
921 !boost::filesystem::is_regular_file(validatorsFile) &&
922 !boost::filesystem::is_symlink(validatorsFile))
923 validatorsFile.clear();
927 if (!validatorsFile.empty() &&
928 boost::filesystem::exists(validatorsFile) &&
929 (boost::filesystem::is_regular_file(validatorsFile) ||
930 boost::filesystem::is_symlink(validatorsFile)))
932 boost::system::error_code ec;
936 Throw<std::runtime_error>(
937 "Failed to read '" + validatorsFile.string() +
"'." +
954 auto valSiteEntries =
958 section(SECTION_VALIDATOR_LIST_SITES).
append(*valSiteEntries);
966 auto valListThreshold =
969 if (valListThreshold)
970 section(SECTION_VALIDATOR_LIST_THRESHOLD)
971 .
append(*valListThreshold);
973 if (!entries && !valKeyEntries && !valListKeys)
974 Throw<std::runtime_error>(
975 "The file specified in [" SECTION_VALIDATORS_FILE
977 "does not contain a [" SECTION_VALIDATORS
979 "[" SECTION_VALIDATOR_KEYS
981 "[" SECTION_VALIDATOR_LIST_KEYS
984 validatorsFile.string());
988 auto const& listThreshold =
989 section(SECTION_VALIDATOR_LIST_THRESHOLD);
990 if (listThreshold.lines().empty())
992 else if (listThreshold.values().size() == 1)
994 auto strTemp = listThreshold.values()[0];
995 auto const listThreshold =
996 beast::lexicalCastThrow<std::size_t>(strTemp);
997 if (listThreshold == 0)
1001 section(SECTION_VALIDATOR_LIST_KEYS).values().size())
1003 Throw<std::runtime_error>(
1004 "Value in config section "
1005 "[" SECTION_VALIDATOR_LIST_THRESHOLD
1006 "] exceeds the number of configured list keys");
1008 return listThreshold;
1012 Throw<std::runtime_error>(
1014 "[" SECTION_VALIDATOR_LIST_THRESHOLD
1015 "] should contain single value only");
1023 if (!
section(SECTION_VALIDATOR_LIST_SITES).lines().empty() &&
1024 section(SECTION_VALIDATOR_LIST_KEYS).lines().empty())
1026 Throw<std::runtime_error>(
1028 "] config section is missing");
1033 auto const part =
section(
"features");
1034 for (
auto const& s : part.values())
1039 Throw<std::runtime_error>(
1040 "Unknown feature: " + s +
" in config file.");
1056 Throw<std::runtime_error>(
1057 "The minimum number of required peers (network_quorum) exceeds "
1058 "the maximum number of allowed peers (peers_max)");