1#include <xrpld/core/Config.h>
3#include <xrpl/basics/FileUtilities.h>
4#include <xrpl/basics/Log.h>
5#include <xrpl/basics/StringUtilities.h>
6#include <xrpl/basics/chrono.h>
7#include <xrpl/basics/contract.h>
8#include <xrpl/beast/core/LexicalCast.h>
9#include <xrpl/beast/utility/Journal.h>
10#include <xrpl/beast/utility/instrumentation.h>
11#include <xrpl/config/BasicConfig.h>
12#include <xrpl/config/Constants.h>
13#include <xrpl/net/HTTPClient.h>
14#include <xrpl/protocol/Feature.h>
15#include <xrpl/protocol/SystemParameters.h>
16#include <xrpl/rdb/DBInit.h>
17#include <xrpl/rdb/DatabaseCon.h>
19#include <boost/algorithm/string/classification.hpp>
20#include <boost/algorithm/string/predicate.hpp>
21#include <boost/algorithm/string/replace.hpp>
22#include <boost/algorithm/string/split.hpp>
23#include <boost/algorithm/string/trim.hpp>
24#include <boost/multiprecision/detail/endian.hpp>
25#include <boost/predef.h>
26#include <boost/regex.hpp>
27#include <boost/regex/v5/regex.hpp>
28#include <boost/regex/v5/regex_match.hpp>
53#include <sysinfoapi.h>
57[[nodiscard]] std::uint64_t
60 if (MEMORYSTATUSEX msx{
sizeof(MEMORYSTATUSEX)}; GlobalMemoryStatusEx(&msx))
61 return static_cast<std::uint64_t
>(msx.ullTotalPhys);
71#include <sys/sysinfo.h>
75[[nodiscard]] std::uint64_t
78 if (
struct sysinfo si{}; sysinfo(&si) == 0)
79 return static_cast<std::uint64_t
>(si.totalram) * si.mem_unit;
89#include <sys/sysctl.h>
93[[nodiscard]] std::uint64_t
96 int mib[] = {CTL_HW, HW_MEMSIZE};
98 size_t size =
sizeof(ram);
100 if (sysctl(mib, 2, &ram, &size,
nullptr, 0) == 0)
101 return static_cast<std::uint64_t
>(ram);
114inline constexpr std::array<std::pair<SizedItem, std::array<int, 5>>, 13>
141 []()
constexpr ->
bool {
154 "Mismatch between sized item enum & array indices");
160#define SECTION_DEFAULT_NAME ""
170 boost::algorithm::replace_all(strData,
"\r\n",
"\n");
173 boost::algorithm::replace_all(strData,
"\r",
"\n");
175 boost::algorithm::split(vLines, strData, boost::algorithm::is_any_of(
"\n"));
181 secResult[strSection] = IniFileSections::mapped_type();
184 for (
auto& strValue : vLines)
189 if (strValue.empty() || strValue[0] ==
'#')
193 else if (strValue[0] ==
'[' && strValue[strValue.length() - 1] ==
']')
196 strSection = strValue.
substr(1, strValue.length() - 2);
197 secResult.
emplace(strSection, IniFileSections::mapped_type{});
202 if (!strValue.empty())
203 secResult[strSection].push_back(strValue);
210IniFileSections::mapped_type*
213 if (
auto it = secSource.
find(strSection); it != secSource.
end())
214 return &(it->second);
228 if ((pmtEntries !=
nullptr) && pmtEntries->size() == 1)
230 strValue = (*pmtEntries)[0];
234 if (pmtEntries !=
nullptr)
236 JLOG(j.
warn()) <<
"Section '" << strSection <<
"': requires 1 line not "
237 << pmtEntries->
size() <<
" lines.";
259 if (
auto const v =
std::getenv(name); v !=
nullptr)
273 XRPL_ASSERT(
nodeSize == 0,
"xrpl::Config::setupControl : node size not set");
275 quiet_ = bQuiet || bSilent;
284 auto const& threshold =
288 return (limit == 0) || (ramSize_ < limit);
291 XRPL_ASSERT(ns != threshold.second.end(),
"xrpl::Config::setupControl : valid node size");
293 if (ns != threshold.second.end())
302 XRPL_ASSERT(
nodeSize <= 4,
"xrpl::Config::setupControl : node size is set");
317 if (!strConf.
empty())
345 if (!strHome.empty())
347 auto strXdgConfigHome =
getEnvVar(
"XDG_CONFIG_HOME");
348 auto strXdgDataHome =
getEnvVar(
"XDG_DATA_HOME");
349 if (strXdgConfigHome.empty())
352 strXdgConfigHome = strHome +
"/.config";
354 if (strXdgDataHome.empty())
357 strXdgDataHome = strHome +
"/.local/share";
362 dataDir = strXdgDataHome +
"/" +
systemName();
397 if (!dataDir.
empty())
433 auto const& section = config[name];
441 ss <<
"Invalid value '" << *optResult <<
"' for key 'port' in [" << name <<
"]";
488 for (
auto& line : strVec)
491 if (
std::count(line.begin(), line.end(),
':') != 1)
497 if (result.
size() == line.size())
519 if (strTemp ==
"main")
523 else if (strTemp ==
"testnet")
527 else if (strTemp ==
"devnet")
550 if (*peersInMaxOpt > 1000)
554 "] section; the value must be less or equal than 1000");
562 if (*peersOutMaxOpt < 10 || *peersOutMaxOpt > 1000)
566 "] section; the value must be in range 10-1000");
571 if ((peersInMaxOpt && !peersOutMaxOpt) || (peersOutMaxOpt && !peersInMaxOpt))
578 if (peersInMaxOpt && peersOutMaxOpt)
587 if (boost::iequals(strTemp,
"tiny"))
591 else if (boost::iequals(strTemp,
"small"))
595 else if (boost::iequals(strTemp,
"medium"))
599 else if (boost::iequals(strTemp,
"large"))
603 else if (boost::iequals(strTemp,
"huge"))
627 if (boost::iequals(strTemp,
"all"))
631 else if (boost::iequals(strTemp,
"trusted"))
635 else if (boost::iequals(strTemp,
"drop_untrusted"))
649 if (boost::iequals(strTemp,
"all"))
653 else if (boost::iequals(strTemp,
"trusted"))
657 else if (boost::iequals(strTemp,
"drop_untrusted"))
691 if (boost::iequals(strTemp,
"full"))
695 else if (boost::iequals(strTemp,
"none"))
707 if (boost::iequals(strTemp,
"none"))
711 else if (boost::iequals(strTemp,
"full"))
748 ": must be between 10 and 600 inclusive");
760 ": must be between 1 and 1024 inclusive.");
772 ": must be between 1 and 1024 inclusive.");
784 ": must be between 1 and 1024 inclusive.");
810 " cannot specify both vp_base_squelch_enable and vp_enable "
812 "vp_enable was deprecated and replaced by "
813 "vp_base_squelch_enable");
843 " vp_base_squelch_max_selected_peers must be "
844 "greater than or equal to 3");
858 ", tx_min_peers must be greater than or equal to 10"
859 ", tx_relay_percentage must be greater than or equal to 10 "
860 "and less than or equal to 100");
876 ": the domain name does not appear to meet the requirements.");
897 ": must be of the form '<number>' representing seconds.");
904 ": the time must be between 300 and 1800 seconds, inclusive.");
916 ": must be of the form '<number>' representing seconds.");
923 ": the time must be between 60 and 900 seconds, inclusive.");
934 if (
auto val = sec.get(key))
941 ": must be of the form '<number>' representing a count of manifests.");
962 boost::regex
const re(R
"(^\s*(\d+)\s*(minutes|hours|days|weeks)\s*(\s+.*)?$)");
964 if (!boost::regex_match(strTemp, match, re))
968 ", must be: [0-9]+ [minutes|hours|days|weeks]");
973 if (boost::iequals(match[2],
"minutes"))
977 else if (boost::iequals(match[2],
"hours"))
981 else if (boost::iequals(match[2],
"days"))
985 else if (boost::iequals(match[2],
"weeks"))
994 ", the minimum amount of time an amendment must hold a "
995 "majority is 15 minutes");
1017 validatorsFile = strTemp;
1019 if (validatorsFile.
empty())
1026 validatorsFile =
configDir / validatorsFile;
1033 "does not exist: " +
1034 validatorsFile.
string());
1042 "]: " + validatorsFile.
string());
1049 if (!validatorsFile.
empty())
1055 validatorsFile.
clear();
1069 "Failed to read '" + validatorsFile.
string() +
"'." +
1077 if (entries !=
nullptr)
1082 if (valKeyEntries !=
nullptr)
1087 if (valSiteEntries !=
nullptr)
1092 if (valListKeys !=
nullptr)
1097 if (valListThreshold !=
nullptr)
1100 if ((entries ==
nullptr) && (valKeyEntries ==
nullptr) && (valListKeys ==
nullptr))
1105 "does not contain a [" +
1115 validatorsFile.
string());
1121 if (listThreshold.lines().empty())
1123 return std::nullopt;
1125 if (listThreshold.values().size() == 1)
1127 auto strTemp = listThreshold.values()[0];
1129 if (listThreshold == 0)
1131 return std::nullopt;
1137 "Value in config section "
1140 "] exceeds the number of configured list keys");
1142 return listThreshold;
1165 for (
auto const& s : part.values())
1191 "The minimum number of required peers (network_quorum) exceeds "
1192 "the maximum number of allowed peers (peers_max)");
1202 if (!logFile.empty() && !logFile.is_absolute())
1209 if (!logFile.empty())
1211 auto logDir = logFile.parent_path();
1222 std::cerr <<
"Unable to create log file path " << logDir <<
": " << ec.
message()
1235 XRPL_ASSERT(index <
kSizedItems.size(),
"xrpl::Config::getValueFor : valid index input");
1236 XRPL_ASSERT(!node || *node <= 4,
"xrpl::Config::getValueFor : unset or valid node");
1284 bool showRiskWarning =
false;
1286 if (
set(safetyLevel,
"safety_level", sqlite))
1288 if (boost::iequals(safetyLevel,
"low"))
1291 journalMode =
"memory";
1292 synchronous =
"off";
1293 tempStore =
"memory";
1294 showRiskWarning =
true;
1296 else if (!boost::iequals(safetyLevel,
"high"))
1305 if (
set(journalMode,
"journal_mode", sqlite) && !safetyLevel.
empty())
1308 "Configuration file may not define both "
1309 "\"safety_level\" and \"journal_mode\"");
1311 bool const higherRisk =
1312 boost::iequals(journalMode,
"memory") || boost::iequals(journalMode,
"off");
1313 showRiskWarning = showRiskWarning || higherRisk;
1314 if (higherRisk || boost::iequals(journalMode,
"delete") ||
1315 boost::iequals(journalMode,
"truncate") || boost::iequals(journalMode,
"persist") ||
1316 boost::iequals(journalMode,
"wal"))
1328 if (
set(synchronous,
"synchronous", sqlite) && !safetyLevel.
empty())
1331 "Configuration file may not define both "
1332 "\"safety_level\" and \"synchronous\"");
1334 bool const higherRisk = boost::iequals(synchronous,
"off");
1335 showRiskWarning = showRiskWarning || higherRisk;
1336 if (higherRisk || boost::iequals(synchronous,
"normal") ||
1337 boost::iequals(synchronous,
"full") || boost::iequals(synchronous,
"extra"))
1349 if (
set(tempStore,
"temp_store", sqlite) && !safetyLevel.
empty())
1352 "Configuration file may not define both "
1353 "\"safety_level\" and \"temp_store\"");
1355 bool const higherRisk = boost::iequals(tempStore,
"memory");
1356 showRiskWarning = showRiskWarning || higherRisk;
1357 if (higherRisk || boost::iequals(tempStore,
"default") ||
1358 boost::iequals(tempStore,
"file"))
1370 JLOG(j->warn()) <<
"reducing the data integrity guarantees from the "
1371 "default [sqlite] behavior is not recommended for "
1372 "nodes storing large amounts of history, because of the "
1373 "difficulty inherent in rebuilding corrupted data.";
1376 result->size() == 3,
"xrpl::setup_DatabaseCon::globalPragma : result size is 3");
1386 setPragma(setup.
lgrPragma[0],
"journal_size_limit", 1582080);
1390 int64_t journalSizeLimit = 1582080;
1396 if (pageSize < 512 || pageSize > 65536)
1399 if ((pageSize & (pageSize - 1)) != 0)
1403 setPragma(setup.
txPragma[0],
"page_size", pageSize);
1404 setPragma(setup.
txPragma[1],
"journal_size_limit", journalSizeLimit);
1405 setPragma(setup.
txPragma[2],
"max_page_count", 4294967294);
1406 setPragma(setup.
txPragma[3],
"mmap_size", 17179869184);
A generic endpoint for log messages.
void build(IniFileSections const &ifs)
bool exists(std::string const &name) const
Returns true if a section with the given name exists.
void legacy(std::string const §ion, std::string value)
Set a value that is not a key/value pair.
Section & section(std::string const &name)
Returns the section with the given name.
static constexpr int kMinJobQueueTx
std::filesystem::path configFile_
std::optional< std::size_t > maxUntrustedCount
std::chrono::seconds maxDivergedTime
std::unordered_set< uint256, beast::Uhash<> > features
static constexpr int kMaxJobQueueTx
std::optional< int > sweepInterval
std::size_t txReduceRelayMinPeers
static constexpr std::size_t kMinManifestCount
std::optional< std::size_t > maxTrustedCount
std::size_t vpReduceRelaySquelchMaxSelectedPeers
////////////////// !
std::filesystem::path getDebugLogFile() const
Returns the full path and filename of the debug log file.
static constexpr std::size_t kMaxManifestCount
void setup(std::string const &strConf, bool bQuiet, bool bSilent, bool bStandalone)
std::chrono::seconds maxUnknownTime
static char const *const kDatabaseDirName
std::uint64_t const ramSize_
int relayUntrustedProposals
int relayUntrustedValidations
std::vector< std::string > ipsFixed
bool vpReduceRelayBaseSquelchEnable
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
std::string sslVerifyFile
std::optional< std::size_t > maxSubscriptionsPerConnection
std::size_t txRelayPercentage
bool txReduceRelayMetrics
static char const *const kConfigLegacyName
std::optional< std::size_t > validatorListThreshold
std::filesystem::path debugLogfile_
bool runStandalone_
Operate in stand-alone mode.
bool txReduceRelayEnable
////////////// END OF TEMPORARY CODE BLOCK /////////////////////
static char const *const kConfigFileName
std::vector< std::string > ips
bool signingEnabled_
Determines if the server will sign a tx, given an account's secret seed.
void setupControl(bool bQuiet, bool bSilent, bool bStandalone)
std::uint32_t ledgerHistory
int getValueFor(SizedItem item, std::optional< std::size_t > node=std::nullopt) const
Retrieve the default value for the item at the specified node size.
static char const *const kValidatorsFileName
std::size_t networkQuorum
std::filesystem::path configDir
std::chrono::seconds amendmentMajorityTime
static void initializeSSLContext(std::string const &sslVerifyDir, std::string const &sslVerifyFile, bool sslVerify, beast::Journal j)
Holds a collection of configuration values.
std::vector< std::string > const & values() const
Returns all the values in the section.
void append(std::vector< std::string > const &lines)
Append a set of lines to this section.
T create_directories(T... args)
T current_path(T... args)
T hardware_concurrency(T... args)
T is_directory(T... args)
T is_regular_file(T... args)
constexpr Out lexicalCastThrow(In in)
Convert from one type to another, throw on error.
constexpr Out lexicalCast(In in, Out defaultValue=Out())
Convert from one type to another.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
bool set(T &target, std::string const &name, Section const §ion)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
constexpr std::uint32_t kSqliteTuningCutoff
bool isProperlyFormedTomlDomain(std::string_view domain)
Determines if the given string looks like a TOML-file hosting domain.
static std::string getEnvVar(char const *name)
FeeSetup setupFeeVote(Section const §ion)
bool getSingleSection(IniFileSections &secSource, std::string const &strSection, std::string &strValue, beast::Journal j)
IniFileSections::mapped_type * getIniFileSection(IniFileSections &secSource, std::string const &strSection)
constexpr std::array< std::pair< SizedItem, std::array< int, 5 > >, 13 > kSizedItems
IniFileSections parseIniFile(std::string const &strInput, bool const bTrim)
bool getIfExists(Section const §ion, std::string const &name, T &v)
std::string commonDbPragmaJournal(std::string_view journalMode)
std::string trimWhitespace(std::string str)
Remove leading and trailing ASCII whitespace.
std::chrono::duration< int, std::ratio_multiply< days::period, std::ratio< 7 > > > weeks
std::string commonDbPragmaTemp(std::string_view tempStore)
static std::string const & systemName()
std::string getFileContents(std::error_code &ec, std::filesystem::path const &sourcePath, std::optional< std::size_t > maxSize=std::nullopt)
static void checkZeroPorts(Config const &config)
std::chrono::duration< int, std::ratio_multiply< std::chrono::hours::period, std::ratio< 24 > > > days
DatabaseCon::Setup setupDatabaseCon(Config const &c, std::optional< beast::Journal > j=std::nullopt)
std::optional< uint256 > getRegisteredFeature(std::string const &name)
std::unordered_map< std::string, std::vector< std::string > > IniFileSections
std::string commonDbPragmaSync(std::string_view synchronous)
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
T regex_replace(T... args)
std::array< std::string, 4 > txPragma
static std::unique_ptr< std::vector< std::string > const > globalPragma
std::filesystem::path dataDir
std::array< std::string, 1 > lgrPragma
Fee schedule for startup / standalone, and to vote for.
XRPAmount accountReserve
The account reserve requirement in drops.
XRPAmount ownerReserve
The per-owned item reserve requirement in drops.
XRPAmount referenceFee
The cost of a reference transaction in drops.
static constexpr auto kPageSize
static constexpr auto kTxRelayPercentage
static constexpr auto kFastLoad
static constexpr auto kTxMetrics
static constexpr auto kAccountReserve
static constexpr auto kUseTxTables
static constexpr auto kReferenceFee
static constexpr auto kVpBaseSquelchEnable
static constexpr auto kPort
static constexpr auto kMaxUnknownTime
static constexpr auto kJournalSizeLimit
static constexpr auto kTxMinPeers
static constexpr auto kVpEnable
static constexpr auto kMaxTrustedCount
static constexpr auto kMaxUntrustedCount
static constexpr auto kVpBaseSquelchMaxSelectedPeers
static constexpr auto kMaxDivergedTime
static constexpr auto kTxEnable
static constexpr auto kOwnerReserve
static constexpr auto kAmendmentMajorityTime
static constexpr auto kMaxSubscriptionsPerConnection
static constexpr auto kPeersInMax
static constexpr auto kMaxTransactions
static constexpr auto kRelayProposals
static constexpr auto kSweepInterval
static constexpr auto kNodeSize
static constexpr auto kServerDomain
static constexpr auto kIps
static constexpr auto kOverlay
static constexpr auto kReduceRelay
static constexpr auto kValidatorListThreshold
static constexpr auto kValidators
static constexpr auto kSslVerifyFile
static constexpr auto kValidatorListKeys
static constexpr auto kSslVerifyDir
static constexpr auto kNetworkQuorum
static constexpr auto kValidationSeed
static constexpr auto kSigningSupport
static constexpr auto kCompression
static constexpr auto kPeersMax
static constexpr auto kPathSearchOld
static constexpr auto kServer
static constexpr auto kLedgerHistory
static constexpr auto kElbSupport
static constexpr auto kValidatorKeys
static constexpr auto kPeerPrivate
static constexpr auto kSslVerify
static constexpr auto kPeersOutMax
static constexpr auto kFeeDefault
static constexpr auto kValidatorsFile
static constexpr auto kPathSearchMax
static constexpr auto kRelayValidations
static constexpr auto kNodeDatabase
static constexpr auto kIpsFixed
static constexpr auto kDatabasePath
static constexpr auto kPathSearch
static constexpr auto kLedgerReplay
static constexpr auto kPrefetchWorkers
static constexpr auto kDebugLogfile
static constexpr auto kSqlite
static constexpr auto kValidatorToken
static constexpr auto kPathSearchFast
static constexpr auto kVoting
static constexpr auto kLedgerTxTables
static constexpr auto kBetaRpcApi
static constexpr auto kIoWorkers
static constexpr auto kFetchDepth
static constexpr auto kValidatorListSites
static constexpr auto kWorkers
static constexpr auto kNetworkId
static constexpr auto kFeatures