465 for (
auto& line : strVec)
468 if (
std::count(line.begin(), line.end(),
':') != 1)
474 if (result.
size() == line.size())
487 boost::filesystem::path p(dbPath);
488 legacy(
"database_path", boost::filesystem::absolute(p).
string());
496 if (strTemp ==
"main")
498 else if (strTemp ==
"testnet")
500 else if (strTemp ==
"devnet")
503 NETWORK_ID = beast::lexicalCastThrow<uint32_t>(strTemp);
511 PEERS_MAX = beast::lexicalCastThrow<std::size_t>(strTemp);
518 peers_in_max = beast::lexicalCastThrow<std::size_t>(strTemp);
519 if (*peers_in_max > 1000)
520 Throw<std::runtime_error>(
"Invalid value specified in [" SECTION_PEERS_IN_MAX
521 "] section; the value must be less or equal than 1000");
527 peers_out_max = beast::lexicalCastThrow<std::size_t>(strTemp);
528 if (*peers_out_max < 10 || *peers_out_max > 1000)
529 Throw<std::runtime_error>(
"Invalid value specified in [" SECTION_PEERS_OUT_MAX
530 "] section; the value must be in range 10-1000");
534 if ((peers_in_max && !peers_out_max) || (peers_out_max && !peers_in_max))
535 Throw<std::runtime_error>(
"Both sections [" SECTION_PEERS_IN_MAX
537 "and [" SECTION_PEERS_OUT_MAX
"] must be configured");
539 if (peers_in_max && peers_out_max)
548 if (boost::iequals(strTemp,
"tiny"))
550 else if (boost::iequals(strTemp,
"small"))
552 else if (boost::iequals(strTemp,
"medium"))
554 else if (boost::iequals(strTemp,
"large"))
556 else if (boost::iequals(strTemp,
"huge"))
566 ELB_SUPPORT = beast::lexicalCastThrow<bool>(strTemp);
572 SSL_VERIFY = beast::lexicalCastThrow<bool>(strTemp);
576 if (boost::iequals(strTemp,
"all"))
578 else if (boost::iequals(strTemp,
"trusted"))
580 else if (boost::iequals(strTemp,
"drop_untrusted"))
583 Throw<std::runtime_error>(
"Invalid value specified in [" SECTION_RELAY_VALIDATIONS
589 if (boost::iequals(strTemp,
"all"))
591 else if (boost::iequals(strTemp,
"trusted"))
593 else if (boost::iequals(strTemp,
"drop_untrusted"))
596 Throw<std::runtime_error>(
"Invalid value specified in [" SECTION_RELAY_PROPOSALS
600 if (
exists(SECTION_VALIDATION_SEED) &&
exists(SECTION_VALIDATOR_TOKEN))
601 Throw<std::runtime_error>(
"Cannot have both [" SECTION_VALIDATION_SEED
602 "] and [" SECTION_VALIDATOR_TOKEN
"] config sections");
616 if (boost::iequals(strTemp,
"full"))
618 else if (boost::iequals(strTemp,
"none"))
626 if (boost::iequals(strTemp,
"none"))
628 else if (boost::iequals(strTemp,
"full"))
631 FETCH_DEPTH = beast::lexicalCastThrow<std::uint32_t>(strTemp);
639 if (
exists(SECTION_VALIDATION_SEED) ||
exists(SECTION_VALIDATOR_TOKEN))
645 PATH_SEARCH = beast::lexicalCastThrow<int>(strTemp);
658 if (SWEEP_INTERVAL < 10 || SWEEP_INTERVAL > 600)
659 Throw<std::runtime_error>(
"Invalid " SECTION_SWEEP_INTERVAL
660 ": must be between 10 and 600 inclusive");
665 WORKERS = beast::lexicalCastThrow<int>(strTemp);
667 if (WORKERS < 1 || WORKERS > 1024)
668 Throw<std::runtime_error>(
"Invalid " SECTION_WORKERS
669 ": must be between 1 and 1024 inclusive.");
674 IO_WORKERS = beast::lexicalCastThrow<int>(strTemp);
676 if (IO_WORKERS < 1 || IO_WORKERS > 1024)
677 Throw<std::runtime_error>(
"Invalid " SECTION_IO_WORKERS
678 ": must be between 1 and 1024 inclusive.");
685 if (PREFETCH_WORKERS < 1 || PREFETCH_WORKERS > 1024)
686 Throw<std::runtime_error>(
"Invalid " SECTION_PREFETCH_WORKERS
687 ": must be between 1 and 1024 inclusive.");
691 COMPRESSION = beast::lexicalCastThrow<bool>(strTemp);
696 if (
exists(SECTION_REDUCE_RELAY))
698 auto sec =
section(SECTION_REDUCE_RELAY);
706 if (sec.exists(
"vp_base_squelch_enable") && sec.exists(
"vp_enable"))
707 Throw<std::runtime_error>(
"Invalid " SECTION_REDUCE_RELAY
708 " cannot specify both vp_base_squelch_enable and vp_enable "
710 "vp_enable was deprecated and replaced by "
711 "vp_base_squelch_enable");
713 if (sec.exists(
"vp_base_squelch_enable"))
715 else if (sec.exists(
"vp_enable"))
726 sec.value_or(
"vp_base_squelch_max_selected_peers", 5);
728 Throw<std::runtime_error>(
"Invalid " SECTION_REDUCE_RELAY
729 " vp_base_squelch_max_selected_peers must be "
730 "greater than or equal to 3");
738 Throw<std::runtime_error>(
"Invalid " SECTION_REDUCE_RELAY
739 ", tx_min_peers must be greater than or equal to 10"
740 ", tx_relay_percentage must be greater than or equal to 10 "
741 "and less than or equal to 100");
754 Throw<std::runtime_error>(
755 "Invalid " SECTION_SERVER_DOMAIN
756 ": the domain name does not appear to meet the requirements.");
762 if (
exists(SECTION_OVERLAY))
764 auto const sec =
section(SECTION_OVERLAY);
770 if (
auto val = sec.get(
"max_unknown_time"))
775 Throw<std::runtime_error>(
"Invalid value 'max_unknown_time' in " SECTION_OVERLAY
776 ": must be of the form '<number>' representing seconds.");
780 Throw<std::runtime_error>(
781 "Invalid value 'max_unknown_time' in " SECTION_OVERLAY
782 ": the time must be between 300 and 1800 seconds, inclusive.");
786 if (
auto val = sec.get(
"max_diverged_time"))
791 Throw<std::runtime_error>(
"Invalid value 'max_diverged_time' in " SECTION_OVERLAY
792 ": must be of the form '<number>' representing seconds.");
797 Throw<std::runtime_error>(
"Invalid value 'max_diverged_time' in " SECTION_OVERLAY
798 ": the time must be between 60 and 900 seconds, inclusive.");
805 boost::regex
const re(
"^\\s*(\\d+)\\s*(minutes|hours|days|weeks)\\s*(\\s+.*)?$");
807 if (!boost::regex_match(strTemp,
match, re))
808 Throw<std::runtime_error>(
"Invalid " SECTION_AMENDMENT_MAJORITY_TIME
809 ", must be: [0-9]+ [minutes|hours|days|weeks]");
813 if (boost::iequals(
match[2],
"minutes"))
815 else if (boost::iequals(
match[2],
"hours"))
817 else if (boost::iequals(
match[2],
"days"))
819 else if (boost::iequals(
match[2],
"weeks"))
823 Throw<std::runtime_error>(
"Invalid " SECTION_AMENDMENT_MAJORITY_TIME
824 ", the minimum amount of time an amendment must hold a "
825 "majority is 15 minutes");
842 boost::filesystem::path validatorsFile;
846 validatorsFile = strTemp;
848 if (validatorsFile.empty())
849 Throw<std::runtime_error>(
"Invalid path specified in [" SECTION_VALIDATORS_FILE
852 if (!validatorsFile.is_absolute() && !
CONFIG_DIR.empty())
855 if (!boost::filesystem::exists(validatorsFile))
856 Throw<std::runtime_error>(
857 "The file specified in [" SECTION_VALIDATORS_FILE
860 validatorsFile.string());
863 !boost::filesystem::is_regular_file(validatorsFile) &&
864 !boost::filesystem::is_symlink(validatorsFile))
865 Throw<std::runtime_error>(
866 "Invalid file specified in [" SECTION_VALIDATORS_FILE
"]: " +
867 validatorsFile.string());
873 if (!validatorsFile.empty())
875 if (!boost::filesystem::exists(validatorsFile))
876 validatorsFile.clear();
878 !boost::filesystem::is_regular_file(validatorsFile) &&
879 !boost::filesystem::is_symlink(validatorsFile))
880 validatorsFile.clear();
884 if (!validatorsFile.empty() && boost::filesystem::exists(validatorsFile) &&
885 (boost::filesystem::is_regular_file(validatorsFile) ||
886 boost::filesystem::is_symlink(validatorsFile)))
888 boost::system::error_code ec;
892 Throw<std::runtime_error>(
893 "Failed to read '" + validatorsFile.string() +
"'." +
912 section(SECTION_VALIDATOR_LIST_SITES).
append(*valSiteEntries);
919 auto valListThreshold =
getIniFileSection(iniFile, SECTION_VALIDATOR_LIST_THRESHOLD);
921 if (valListThreshold)
922 section(SECTION_VALIDATOR_LIST_THRESHOLD).
append(*valListThreshold);
924 if (!entries && !valKeyEntries && !valListKeys)
925 Throw<std::runtime_error>(
926 "The file specified in [" SECTION_VALIDATORS_FILE
928 "does not contain a [" SECTION_VALIDATORS
930 "[" SECTION_VALIDATOR_KEYS
932 "[" SECTION_VALIDATOR_LIST_KEYS
935 validatorsFile.string());
939 auto const& listThreshold =
section(SECTION_VALIDATOR_LIST_THRESHOLD);
940 if (listThreshold.lines().empty())
942 else if (listThreshold.values().size() == 1)
944 auto strTemp = listThreshold.values()[0];
945 auto const listThreshold = beast::lexicalCastThrow<std::size_t>(strTemp);
946 if (listThreshold == 0)
948 else if (listThreshold >
section(SECTION_VALIDATOR_LIST_KEYS).values().size())
950 Throw<std::runtime_error>(
951 "Value in config section "
952 "[" SECTION_VALIDATOR_LIST_THRESHOLD
953 "] exceeds the number of configured list keys");
955 return listThreshold;
959 Throw<std::runtime_error>(
961 "[" SECTION_VALIDATOR_LIST_THRESHOLD
"] should contain single value only");
968 if (!
section(SECTION_VALIDATOR_LIST_SITES).lines().empty() &&
969 section(SECTION_VALIDATOR_LIST_KEYS).lines().empty())
971 Throw<std::runtime_error>(
972 "[" +
std::string(SECTION_VALIDATOR_LIST_KEYS) +
"] config section is missing");
977 auto const part =
section(
"features");
978 for (
auto const& s : part.values())
983 Throw<std::runtime_error>(
"Unknown feature: " + s +
" in config file.");
999 Throw<std::runtime_error>(
1000 "The minimum number of required peers (network_quorum) exceeds "
1001 "the maximum number of allowed peers (peers_max)");
1079 Throw<std::runtime_error>(
"database_path must be set.");
1084 auto const& sqlite = c.
section(
"sqlite");
1093 bool showRiskWarning =
false;
1095 if (
set(safety_level,
"safety_level", sqlite))
1097 if (boost::iequals(safety_level,
"low"))
1100 journal_mode =
"memory";
1101 synchronous =
"off";
1102 temp_store =
"memory";
1103 showRiskWarning =
true;
1105 else if (!boost::iequals(safety_level,
"high"))
1107 Throw<std::runtime_error>(
"Invalid safety_level value: " + safety_level);
1114 if (
set(journal_mode,
"journal_mode", sqlite) && !safety_level.
empty())
1116 Throw<std::runtime_error>(
1117 "Configuration file may not define both "
1118 "\"safety_level\" and \"journal_mode\"");
1121 boost::iequals(journal_mode,
"memory") || boost::iequals(journal_mode,
"off");
1122 showRiskWarning = showRiskWarning || higherRisk;
1123 if (higherRisk || boost::iequals(journal_mode,
"delete") ||
1124 boost::iequals(journal_mode,
"truncate") ||
1125 boost::iequals(journal_mode,
"persist") || boost::iequals(journal_mode,
"wal"))
1127 result->emplace_back(
1132 Throw<std::runtime_error>(
"Invalid journal_mode value: " + journal_mode);
1138 if (
set(synchronous,
"synchronous", sqlite) && !safety_level.
empty())
1140 Throw<std::runtime_error>(
1141 "Configuration file may not define both "
1142 "\"safety_level\" and \"synchronous\"");
1144 bool higherRisk = boost::iequals(synchronous,
"off");
1145 showRiskWarning = showRiskWarning || higherRisk;
1146 if (higherRisk || boost::iequals(synchronous,
"normal") ||
1147 boost::iequals(synchronous,
"full") || boost::iequals(synchronous,
"extra"))
1153 Throw<std::runtime_error>(
"Invalid synchronous value: " + synchronous);
1159 if (
set(temp_store,
"temp_store", sqlite) && !safety_level.
empty())
1161 Throw<std::runtime_error>(
1162 "Configuration file may not define both "
1163 "\"safety_level\" and \"temp_store\"");
1165 bool higherRisk = boost::iequals(temp_store,
"memory");
1166 showRiskWarning = showRiskWarning || higherRisk;
1167 if (higherRisk || boost::iequals(temp_store,
"default") ||
1168 boost::iequals(temp_store,
"file"))
1174 Throw<std::runtime_error>(
"Invalid temp_store value: " + temp_store);
1180 JLOG(j->warn()) <<
"reducing the data integrity guarantees from the "
1181 "default [sqlite] behavior is not recommended for "
1182 "nodes storing large amounts of history, because of the "
1183 "difficulty inherent in rebuilding corrupted data.";
1186 result->size() == 3,
"xrpl::setup_DatabaseCon::globalPragma : result size is 3");
1196 setPragma(setup.
lgrPragma[0],
"journal_size_limit", 1582080);
1200 int64_t journal_size_limit = 1582080;
1203 auto& s = c.
section(
"sqlite");
1204 set(journal_size_limit,
"journal_size_limit", s);
1205 set(page_size,
"page_size", s);
1206 if (page_size < 512 || page_size > 65536)
1207 Throw<std::runtime_error>(
"Invalid page_size. Must be between 512 and 65536.");
1209 if (page_size & (page_size - 1))
1210 Throw<std::runtime_error>(
"Invalid page_size. Must be a power of 2.");
1213 setPragma(setup.
txPragma[0],
"page_size", page_size);
1214 setPragma(setup.
txPragma[1],
"journal_size_limit", journal_size_limit);
1215 setPragma(setup.
txPragma[2],
"max_page_count", 4294967294);
1216 setPragma(setup.
txPragma[3],
"mmap_size", 17179869184);