xrpld
Loading...
Searching...
No Matches
Config.cpp
1#include <xrpld/core/Config.h>
2
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>
18
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/filesystem/operations.hpp>
25#include <boost/filesystem/path.hpp>
26#include <boost/format/free_funcs.hpp>
27#include <boost/multiprecision/detail/endian.hpp>
28#include <boost/predef.h>
29#include <boost/regex.hpp> // IWYU pragma: keep
30#include <boost/regex/v5/regex.hpp>
31#include <boost/regex/v5/regex_match.hpp>
32#include <boost/system/detail/error_code.hpp>
33
34#include <algorithm>
35#include <array>
36#include <chrono>
37#include <cstdint>
38#include <cstdlib>
39#include <iostream>
40#include <iterator>
41#include <limits>
42#include <memory>
43#include <optional>
44#include <regex>
45#include <sstream>
46#include <stdexcept>
47#include <string>
48#include <thread>
49#include <type_traits>
50#include <utility>
51#include <vector>
52
53#if BOOST_OS_WINDOWS
54#include <sysinfoapi.h>
55
56namespace xrpl::detail {
57
58[[nodiscard]] std::uint64_t
59getMemorySize()
60{
61 if (MEMORYSTATUSEX msx{sizeof(MEMORYSTATUSEX)}; GlobalMemoryStatusEx(&msx))
62 return static_cast<std::uint64_t>(msx.ullTotalPhys);
63
64 return 0;
65}
66
67} // namespace xrpl::detail
68
69#endif
70
71#if BOOST_OS_LINUX
72#include <sys/sysinfo.h> // IWYU pragma: keep
73
74namespace xrpl::detail {
75
76[[nodiscard]] std::uint64_t
77getMemorySize()
78{
79 if (struct sysinfo si{}; sysinfo(&si) == 0)
80 return static_cast<std::uint64_t>(si.totalram) * si.mem_unit;
81
82 return 0;
83}
84
85} // namespace xrpl::detail
86
87#endif
88
89#if BOOST_OS_MACOS
90#include <sys/sysctl.h>
91
92namespace xrpl::detail {
93
94[[nodiscard]] std::uint64_t
95getMemorySize()
96{
97 int mib[] = {CTL_HW, HW_MEMSIZE};
98 std::int64_t ram = 0;
99 size_t size = sizeof(ram);
100
101 if (sysctl(mib, 2, &ram, &size, NULL, 0) == 0)
102 return static_cast<std::uint64_t>(ram);
103
104 return 0;
105}
106
107} // namespace xrpl::detail
108
109#endif
110
111namespace xrpl {
112
113// clang-format off
114// The configurable node sizes are "tiny", "small", "medium", "large", "huge"
115inline constexpr std::array<std::pair<SizedItem, std::array<int, 5>>, 13>
117{{
118 // FIXME: We should document each of these items, explaining exactly
119 // what they control and whether there exists an explicit
120 // config option that can be used to override the default.
121
122 // tiny small medium large huge
123 {SizedItem::SweepInterval, {{ 10, 30, 60, 90, 120 }}},
124 {SizedItem::TreeCacheSize, {{ 262144, 524288, 2097152, 4194304, 8388608 }}},
125 {SizedItem::TreeCacheAge, {{ 30, 60, 90, 120, 900 }}},
126 {SizedItem::LedgerSize, {{ 32, 32, 64, 256, 384 }}},
127 {SizedItem::LedgerAge, {{ 30, 60, 180, 300, 600 }}},
128 {SizedItem::LedgerFetch, {{ 2, 3, 4, 5, 8 }}},
129 {SizedItem::HashNodeDbCache, {{ 4, 12, 24, 64, 128 }}},
130 {SizedItem::TxnDbCache, {{ 4, 12, 24, 64, 128 }}},
131 {SizedItem::LgrDbCache, {{ 4, 8, 16, 32, 128 }}},
132 {SizedItem::OpenFinalLimit, {{ 8, 16, 32, 64, 128 }}},
133 {SizedItem::BurstSize, {{ 4, 8, 16, 32, 48 }}},
134 {SizedItem::RamSizeGb, {{ 6, 8, 12, 24, 0 }}},
135 {SizedItem::AccountIdCacheSize, {{ 20047, 50053, 77081, 150061, 300007 }}}
136}};
137// clang-format on
138
139// Ensure that the order of entries in the table corresponds to the
140// order of entries in the enum:
141static_assert(
142 []() constexpr -> bool {
144
145 for (auto const& i : kSizedItems)
146 {
147 if (static_cast<std::underlying_type_t<SizedItem>>(i.first) != idx)
148 return false;
149
150 ++idx;
151 }
152
153 return true;
154 }(),
155 "Mismatch between sized item enum & array indices");
156
157//
158// TODO: Check permissions on config file before using it.
159//
160
161#define SECTION_DEFAULT_NAME ""
162
164parseIniFile(std::string const& strInput, bool const bTrim)
165{
166 std::string strData(strInput);
168 IniFileSections secResult;
169
170 // Convert DOS format to unix.
171 boost::algorithm::replace_all(strData, "\r\n", "\n");
172
173 // Convert MacOS format to unix.
174 boost::algorithm::replace_all(strData, "\r", "\n");
175
176 boost::algorithm::split(vLines, strData, boost::algorithm::is_any_of("\n"));
177
178 // Set the default Section name.
179 std::string strSection = SECTION_DEFAULT_NAME; // NOLINT(readability-redundant-string-init)
180
181 // Initialize the default Section.
182 secResult[strSection] = IniFileSections::mapped_type();
183
184 // Parse each line.
185 for (auto& strValue : vLines)
186 {
187 if (bTrim)
188 boost::algorithm::trim(strValue);
189
190 if (strValue.empty() || strValue[0] == '#')
191 {
192 // Blank line or comment, do nothing.
193 }
194 else if (strValue[0] == '[' && strValue[strValue.length() - 1] == ']')
195 {
196 // New Section.
197 strSection = strValue.substr(1, strValue.length() - 2);
198 secResult.emplace(strSection, IniFileSections::mapped_type{});
199 }
200 else
201 {
202 // Another line for Section.
203 if (!strValue.empty())
204 secResult[strSection].push_back(strValue);
205 }
206 }
207
208 return secResult;
209}
210
211IniFileSections::mapped_type*
212getIniFileSection(IniFileSections& secSource, std::string const& strSection)
213{
214 if (auto it = secSource.find(strSection); it != secSource.end())
215 return &(it->second);
216
217 return nullptr;
218}
219
220bool
222 IniFileSections& secSource,
223 std::string const& strSection,
224 std::string& strValue,
226{
227 auto const pmtEntries = getIniFileSection(secSource, strSection);
228
229 if ((pmtEntries != nullptr) && pmtEntries->size() == 1)
230 {
231 strValue = (*pmtEntries)[0];
232 return true;
233 }
234
235 if (pmtEntries != nullptr)
236 {
237 JLOG(j.warn()) << "Section '" << strSection << "': requires 1 line not "
238 << pmtEntries->size() << " lines.";
239 }
240
241 return false;
242}
243
244//------------------------------------------------------------------------------
245//
246// Config
247//
248//------------------------------------------------------------------------------
249
250char const* const Config::kConfigFileName = "xrpld.cfg";
251char const* const Config::kConfigLegacyName = "rippled.cfg";
252char const* const Config::kDatabaseDirName = "db";
253char const* const Config::kValidatorsFileName = "validators.txt";
254
255[[nodiscard]] static std::string
256getEnvVar(char const* name)
257{
258 std::string value;
259
260 if (auto const v = std::getenv(name); v != nullptr)
261 value = v;
262
263 return value;
264}
265
267 : j_(beast::Journal::getNullSink()), ramSize_(detail::getMemorySize() / (1024 * 1024 * 1024))
268{
269}
270
271void
272Config::setupControl(bool bQuiet, bool bSilent, bool bStandalone)
273{
274 XRPL_ASSERT(nodeSize == 0, "xrpl::Config::setupControl : node size not set");
275
276 quiet_ = bQuiet || bSilent;
277 silent_ = bSilent;
278 runStandalone_ = bStandalone;
279
280 // We try to autodetect the appropriate node size by checking available
281 // RAM and CPU resources. We default to "tiny" for standalone mode.
282 if (!bStandalone)
283 {
284 // First, check against 'minimum' RAM requirements per node size:
285 auto const& threshold =
287
288 auto ns = std::ranges::find_if(threshold.second, [this](std::size_t limit) {
289 return (limit == 0) || (ramSize_ < limit);
290 });
291
292 XRPL_ASSERT(ns != threshold.second.end(), "xrpl::Config::setupControl : valid node size");
293
294 if (ns != threshold.second.end())
295 nodeSize = std::distance(threshold.second.begin(), ns);
296
297 // Adjust the size based on the number of hardware threads of
298 // execution available to us:
299 if (auto const hc = std::thread::hardware_concurrency(); hc != 0)
301 }
302
303 XRPL_ASSERT(nodeSize <= 4, "xrpl::Config::setupControl : node size is set");
304}
305
306void
307Config::setup(std::string const& strConf, bool bQuiet, bool bSilent, bool bStandalone)
308{
309 setupControl(bQuiet, bSilent, bStandalone);
310
311 // Determine the config and data directories.
312 // If the config file is found in the current working
313 // directory, use the current working directory as the
314 // config directory and that with "db" as the data
315 // directory.
316 boost::filesystem::path dataDir;
317
318 if (!strConf.empty())
319 {
320 // --conf=<path> : everything is relative that file.
321 configFile_ = strConf;
322 configDir = boost::filesystem::absolute(configFile_);
323 configDir.remove_filename();
324 dataDir = configDir / kDatabaseDirName;
325 }
326 else
327 {
328 do
329 {
330 // Check if either of the config files exist in the current working
331 // directory, in which case the databases will be stored in a
332 // subdirectory.
333 configDir = boost::filesystem::current_path();
334 dataDir = configDir / kDatabaseDirName;
336 if (boost::filesystem::exists(configFile_))
337 break;
339 if (boost::filesystem::exists(configFile_))
340 break;
341
342 // Check if the home directory is set, and optionally the XDG config
343 // and/or data directories, as the config may be there. See
344 // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html.
345 auto const strHome = getEnvVar("HOME");
346 if (!strHome.empty())
347 {
348 auto strXdgConfigHome = getEnvVar("XDG_CONFIG_HOME");
349 auto strXdgDataHome = getEnvVar("XDG_DATA_HOME");
350 if (strXdgConfigHome.empty())
351 {
352 // $XDG_CONFIG_HOME was not set, use default based on $HOME.
353 strXdgConfigHome = strHome + "/.config";
354 }
355 if (strXdgDataHome.empty())
356 {
357 // $XDG_DATA_HOME was not set, use default based on $HOME.
358 strXdgDataHome = strHome + "/.local/share";
359 }
360
361 // Check if either of the config files exist in the XDG config
362 // dir.
363 dataDir = strXdgDataHome + "/" + systemName();
364 configDir = strXdgConfigHome + "/" + systemName();
366 if (boost::filesystem::exists(configFile_))
367 break;
369 if (boost::filesystem::exists(configFile_))
370 break;
371 }
372
373 // As a last resort, check the system config directory.
374 dataDir = "/var/lib/" + systemName();
375 configDir = "/etc/" + systemName();
377 if (boost::filesystem::exists(configFile_))
378 break;
380 } while (false);
381 }
382
383 // Update default values
384 load();
385 {
386 // load() may have set a new value for the dataDir
388 if (!dbPath.empty())
389 {
390 dataDir = boost::filesystem::path(dbPath);
391 }
392 else if (runStandalone_)
393 {
394 dataDir.clear();
395 }
396 }
397
398 if (!dataDir.empty())
399 {
400 boost::system::error_code ec;
401 boost::filesystem::create_directories(dataDir, ec);
402
403 if (ec)
404 Throw<std::runtime_error>(boost::str(boost::format("Can not create %s") % dataDir));
405
406 legacy(Sections::kDatabasePath, boost::filesystem::absolute(dataDir).string());
407 }
408
410
411 if (runStandalone_)
412 ledgerHistory = 0;
413
414 Section const ledgerTxTablesSection = section(Sections::kLedgerTxTables);
415 getIfExists(ledgerTxTablesSection, Keys::kUseTxTables, useTxTables_);
416
417 Section const& nodeDbSection{section(Sections::kNodeDatabase)};
418 getIfExists(nodeDbSection, Keys::kFastLoad, fastLoad);
419}
420
421// 0 ports are allowed for unit tests, but still not allowed to be present in
422// config file
423static void
424checkZeroPorts(Config const& config)
425{
426 if (!config.exists(Sections::kServer))
427 return;
428
429 for (auto const& name : config.section(Sections::kServer).values())
430 {
431 if (!config.exists(name))
432 return;
433
434 auto const& section = config[name];
435 auto const optResult = section.get(Keys::kPort);
436 if (optResult)
437 {
438 auto const port = beast::lexicalCast<std::uint16_t>(*optResult);
439 if (port == 0u)
440 {
442 ss << "Invalid value '" << *optResult << "' for key 'port' in [" << name << "]";
444 }
445 }
446 }
447}
448
449void
451{
452 // NOTE: this writes to cerr because we want cout to be reserved
453 // for the writing of the json response (so that stdout can be part of a
454 // pipeline, for instance)
455 if (!quiet_)
456 std::cerr << "Loading: " << configFile_ << "\n";
457
458 boost::system::error_code ec;
459 auto const fileContents = getFileContents(ec, configFile_);
460
461 if (ec)
462 {
463 std::cerr << "Failed to read '" << configFile_ << "'." << ec.value() << ": " << ec.message()
464 << std::endl;
465 return;
466 }
467
468 loadFromString(fileContents);
469 checkZeroPorts(*this);
470}
471
472void
474{
475 IniFileSections secConfig = parseIniFile(fileContents, true);
476
477 build(secConfig);
478
479 if (auto s = getIniFileSection(secConfig, Sections::kIps))
480 ips = *s;
481
482 if (auto s = getIniFileSection(secConfig, Sections::kIpsFixed))
483 ipsFixed = *s;
484
485 // if the user has specified ip:port then replace : with a space.
486 {
487 auto replaceColons = [](std::vector<std::string>& strVec) {
488 static std::regex const kE(":([0-9]+)$");
489 for (auto& line : strVec)
490 {
491 // skip anything that might be an ipv6 address
492 if (std::count(line.begin(), line.end(), ':') != 1)
493 continue;
494
495 std::string const result = std::regex_replace(line, kE, " $1");
496 // sanity check the result of the replace, should be same length
497 // as input
498 if (result.size() == line.size())
499 line = result;
500 }
501 };
502
503 replaceColons(ipsFixed);
504 replaceColons(ips);
505 }
506
507 {
508 std::string dbPath;
509 if (getSingleSection(secConfig, Sections::kDatabasePath, dbPath, j_))
510 {
511 boost::filesystem::path const p(dbPath);
512 legacy(Sections::kDatabasePath, boost::filesystem::absolute(p).string());
513 }
514 }
515
516 std::string strTemp;
517
518 if (getSingleSection(secConfig, Sections::kNetworkId, strTemp, j_))
519 {
520 if (strTemp == "main")
521 {
522 networkId = 0;
523 }
524 else if (strTemp == "testnet")
525 {
526 networkId = 1;
527 }
528 else if (strTemp == "devnet")
529 {
530 networkId = 2;
531 }
532 else
533 {
535 }
536 }
537
538 if (getSingleSection(secConfig, Sections::kPeerPrivate, strTemp, j_))
540
541 if (getSingleSection(secConfig, Sections::kPeersMax, strTemp, j_))
542 {
544 }
545 else
546 {
547 std::optional<std::size_t> peersInMaxOpt{};
548 if (getSingleSection(secConfig, Sections::kPeersInMax, strTemp, j_))
549 {
550 peersInMaxOpt = beast::lexicalCastThrow<std::size_t>(strTemp);
551 if (*peersInMaxOpt > 1000)
552 {
554 std::string("Invalid value specified in [") + Sections::kPeersInMax +
555 "] section; the value must be less or equal than 1000");
556 }
557 }
558
559 std::optional<std::size_t> peersOutMaxOpt{};
560 if (getSingleSection(secConfig, Sections::kPeersOutMax, strTemp, j_))
561 {
562 peersOutMaxOpt = beast::lexicalCastThrow<std::size_t>(strTemp);
563 if (*peersOutMaxOpt < 10 || *peersOutMaxOpt > 1000)
564 {
566 std::string("Invalid value specified in [") + Sections::kPeersOutMax +
567 "] section; the value must be in range 10-1000");
568 }
569 }
570
571 // if one section is configured then the other must be configured too
572 if ((peersInMaxOpt && !peersOutMaxOpt) || (peersOutMaxOpt && !peersInMaxOpt))
573 {
575 std::string("Both sections [") + Sections::kPeersInMax + "]" + " and [" +
576 Sections::kPeersOutMax + "] must be configured");
577 }
578
579 if (peersInMaxOpt && peersOutMaxOpt)
580 {
581 peersInMax = *peersInMaxOpt;
582 peersOutMax = *peersOutMaxOpt;
583 }
584 }
585
586 if (getSingleSection(secConfig, Sections::kNodeSize, strTemp, j_))
587 {
588 if (boost::iequals(strTemp, "tiny"))
589 {
590 nodeSize = 0;
591 }
592 else if (boost::iequals(strTemp, "small"))
593 {
594 nodeSize = 1;
595 }
596 else if (boost::iequals(strTemp, "medium"))
597 {
598 nodeSize = 2;
599 }
600 else if (boost::iequals(strTemp, "large"))
601 {
602 nodeSize = 3;
603 }
604 else if (boost::iequals(strTemp, "huge"))
605 {
606 nodeSize = 4;
607 }
608 else
609 {
611 }
612 }
613
614 if (getSingleSection(secConfig, Sections::kSigningSupport, strTemp, j_))
616
617 if (getSingleSection(secConfig, Sections::kElbSupport, strTemp, j_))
619
622
623 if (getSingleSection(secConfig, Sections::kSslVerify, strTemp, j_))
625
626 if (getSingleSection(secConfig, Sections::kRelayValidations, strTemp, j_))
627 {
628 if (boost::iequals(strTemp, "all"))
629 {
631 }
632 else if (boost::iequals(strTemp, "trusted"))
633 {
635 }
636 else if (boost::iequals(strTemp, "drop_untrusted"))
637 {
639 }
640 else
641 {
643 std::string("Invalid value specified in [") + Sections::kRelayValidations +
644 "] section");
645 }
646 }
647
648 if (getSingleSection(secConfig, Sections::kRelayProposals, strTemp, j_))
649 {
650 if (boost::iequals(strTemp, "all"))
651 {
653 }
654 else if (boost::iequals(strTemp, "trusted"))
655 {
657 }
658 else if (boost::iequals(strTemp, "drop_untrusted"))
659 {
661 }
662 else
663 {
665 std::string("Invalid value specified in [") + Sections::kRelayProposals +
666 "] section");
667 }
668 }
669
671 {
673 std::string("Cannot have both [") + Sections::kValidationSeed + "] and [" +
674 Sections::kValidatorToken + "] config sections");
675 }
676
677 if (getSingleSection(secConfig, Sections::kNetworkQuorum, strTemp, j_))
679
681 /* [fee_default] is documented in the example config files as useful for
682 * things like offline transaction signing. Until that's completely
683 * deprecated, allow it to override the [voting] section. */
684 if (getSingleSection(secConfig, Sections::kFeeDefault, strTemp, j_))
685 fees.referenceFee = beast::lexicalCastThrow<std::uint64_t>(strTemp);
686
687 if (getSingleSection(secConfig, Sections::kLedgerHistory, strTemp, j_))
688 {
689 if (boost::iequals(strTemp, "full"))
690 {
692 }
693 else if (boost::iequals(strTemp, "none"))
694 {
695 ledgerHistory = 0;
696 }
697 else
698 {
700 }
701 }
702
703 if (getSingleSection(secConfig, Sections::kFetchDepth, strTemp, j_))
704 {
705 if (boost::iequals(strTemp, "none"))
706 {
707 fetchDepth = 0;
708 }
709 else if (boost::iequals(strTemp, "full"))
710 {
711 fetchDepth = std::numeric_limits<decltype(fetchDepth)>::max();
712 }
713 else
714 {
716 }
717
719 }
720
721 // By default, validators don't have pathfinding enabled, unless it is
722 // explicitly requested by the server's admin.
724 pathSearchMax = 0;
725
726 if (getSingleSection(secConfig, Sections::kPathSearchOld, strTemp, j_))
728 if (getSingleSection(secConfig, Sections::kPathSearch, strTemp, j_))
730 if (getSingleSection(secConfig, Sections::kPathSearchFast, strTemp, j_))
732 if (getSingleSection(secConfig, Sections::kPathSearchMax, strTemp, j_))
734
735 if (getSingleSection(secConfig, Sections::kDebugLogfile, strTemp, j_))
736 debugLogfile_ = strTemp;
737
738 if (getSingleSection(secConfig, Sections::kSweepInterval, strTemp, j_))
739 {
741
743 {
746 ": must be between 10 and 600 inclusive");
747 }
748 }
749
750 if (getSingleSection(secConfig, Sections::kWorkers, strTemp, j_))
751 {
753
755 {
757 std::string("Invalid ") + Sections::kWorkers +
758 ": must be between 1 and 1024 inclusive.");
759 }
760 }
761
762 if (getSingleSection(secConfig, Sections::kIoWorkers, strTemp, j_))
763 {
765
767 {
769 std::string("Invalid ") + Sections::kIoWorkers +
770 ": must be between 1 and 1024 inclusive.");
771 }
772 }
773
774 if (getSingleSection(secConfig, Sections::kPrefetchWorkers, strTemp, j_))
775 {
777
779 {
782 ": must be between 1 and 1024 inclusive.");
783 }
784 }
785
786 if (getSingleSection(secConfig, Sections::kCompression, strTemp, j_))
788
789 if (getSingleSection(secConfig, Sections::kLedgerReplay, strTemp, j_))
791
793 {
795
797 // vp_enable config option is deprecated by vp_base_squelch_enable //
798 // This option is kept for backwards compatibility. When squelching //
799 // is the default algorithm, it must be replaced with: //
800 // VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE = //
801 // sec.value_or("vp_base_squelch_enable", true); //
802 if (sec.exists(Keys::kVpBaseSquelchEnable) && sec.exists(Keys::kVpEnable))
803 {
805 std::string("Invalid ") + Sections::kReduceRelay +
806 " cannot specify both vp_base_squelch_enable and vp_enable "
807 "options. "
808 "vp_enable was deprecated and replaced by "
809 "vp_base_squelch_enable");
810 }
811
812 if (sec.exists(Keys::kVpBaseSquelchEnable))
813 {
815 }
816 else if (sec.exists(Keys::kVpEnable))
817 {
819 }
820 else
821 {
823 }
825
827 // Temporary squelching config for the peers selected as a source of //
828 // validator messages. The config must be removed once squelching is //
829 // made the default routing algorithm. //
832 {
834 std::string("Invalid ") + Sections::kReduceRelay +
835 " vp_base_squelch_max_selected_peers must be "
836 "greater than or equal to 3");
837 }
839
840 txReduceRelayEnable = sec.valueOr(Keys::kTxEnable, false);
841 txReduceRelayMetrics = sec.valueOr(Keys::kTxMetrics, false);
842 txReduceRelayMinPeers = sec.valueOr(Keys::kTxMinPeers, 20);
845 {
847 std::string("Invalid ") + Sections::kReduceRelay +
848 ", tx_min_peers must be greater than or equal to 10"
849 ", tx_relay_percentage must be greater than or equal to 10 "
850 "and less than or equal to 100");
851 }
852 }
853
854 if (getSingleSection(secConfig, Sections::kMaxTransactions, strTemp, j_))
855 {
858 }
859
860 if (getSingleSection(secConfig, Sections::kServerDomain, strTemp, j_))
861 {
862 if (!isProperlyFormedTomlDomain(strTemp))
863 {
866 ": the domain name does not appear to meet the requirements.");
867 }
868
869 serverDomain = strTemp;
870 }
871
873 {
874 auto const sec = section(Sections::kOverlay);
875
876 using namespace std::chrono;
877
878 try
879 {
880 if (auto val = sec.get(Keys::kMaxUnknownTime))
882 }
883 catch (...)
884 {
886 std::string("Invalid value 'max_unknown_time' in ") + Sections::kOverlay +
887 ": must be of the form '<number>' representing seconds.");
888 }
889
890 if (maxUnknownTime < seconds{300} || maxUnknownTime > seconds{1800})
891 {
893 std::string("Invalid value 'max_unknown_time' in ") + Sections::kOverlay +
894 ": the time must be between 300 and 1800 seconds, inclusive.");
895 }
896
897 try
898 {
899 if (auto val = sec.get(Keys::kMaxDivergedTime))
901 }
902 catch (...)
903 {
905 std::string("Invalid value 'max_diverged_time' in ") + Sections::kOverlay +
906 ": must be of the form '<number>' representing seconds.");
907 }
908
910 {
912 std::string("Invalid value 'max_diverged_time' in ") + Sections::kOverlay +
913 ": the time must be between 60 and 900 seconds, inclusive.");
914 }
915 }
916
917 if (getSingleSection(secConfig, Sections::kAmendmentMajorityTime, strTemp, j_))
918 {
919 using namespace std::chrono;
920 boost::regex const re("^\\s*(\\d+)\\s*(minutes|hours|days|weeks)\\s*(\\s+.*)?$");
921 boost::smatch match;
922 if (!boost::regex_match(strTemp, match, re))
923 {
926 ", must be: [0-9]+ [minutes|hours|days|weeks]");
927 }
928
930
931 if (boost::iequals(match[2], "minutes"))
932 {
934 }
935 else if (boost::iequals(match[2], "hours"))
936 {
938 }
939 else if (boost::iequals(match[2], "days"))
940 {
942 }
943 else if (boost::iequals(match[2], "weeks"))
944 {
946 }
947
949 {
952 ", the minimum amount of time an amendment must hold a "
953 "majority is 15 minutes");
954 }
955 }
956
957 if (getSingleSection(secConfig, Sections::kBetaRpcApi, strTemp, j_))
959
960 // Do not load trusted validator configuration for standalone mode
961 if (!runStandalone_)
962 {
963 // If a file was explicitly specified, then throw if the
964 // path is malformed or if the file does not exist or is
965 // not a file.
966 // If the specified file is not an absolute path, then look
967 // for it in the same directory as the config file.
968 // If no path was specified, then look for validators.txt
969 // in the same directory as the config file, but don't complain
970 // if we can't find it.
971 boost::filesystem::path validatorsFile;
972
973 if (getSingleSection(secConfig, Sections::kValidatorsFile, strTemp, j_))
974 {
975 validatorsFile = strTemp;
976
977 if (validatorsFile.empty())
978 {
980 std::string("Invalid path specified in [") + Sections::kValidatorsFile + "]");
981 }
982
983 if (!validatorsFile.is_absolute() && !configDir.empty())
984 validatorsFile = configDir / validatorsFile;
985
986 if (!boost::filesystem::exists(validatorsFile))
987 {
989 std::string("The file specified in [") + Sections::kValidatorsFile +
990 "] "
991 "does not exist: " +
992 validatorsFile.string());
993 }
994 else if (
995 !boost::filesystem::is_regular_file(validatorsFile) &&
996 !boost::filesystem::is_symlink(validatorsFile))
997 {
999 std::string("Invalid file specified in [") + Sections::kValidatorsFile +
1000 "]: " + validatorsFile.string());
1001 }
1002 }
1003 else if (!configDir.empty())
1004 {
1005 validatorsFile = configDir / kValidatorsFileName;
1006
1007 if (!validatorsFile.empty())
1008 {
1009 if (!boost::filesystem::exists(validatorsFile) ||
1010 (!boost::filesystem::is_regular_file(validatorsFile) &&
1011 !boost::filesystem::is_symlink(validatorsFile)))
1012 {
1013 validatorsFile.clear();
1014 }
1015 }
1016 }
1017
1018 if (!validatorsFile.empty() && boost::filesystem::exists(validatorsFile) &&
1019 (boost::filesystem::is_regular_file(validatorsFile) ||
1020 boost::filesystem::is_symlink(validatorsFile)))
1021 {
1022 boost::system::error_code ec;
1023 auto const data = getFileContents(ec, validatorsFile);
1024 if (ec)
1025 {
1027 "Failed to read '" + validatorsFile.string() + "'." +
1028 std::to_string(ec.value()) + ": " + ec.message());
1029 }
1030
1031 auto iniFile = parseIniFile(data, true);
1032
1033 auto entries = getIniFileSection(iniFile, Sections::kValidators);
1034
1035 if (entries != nullptr)
1037
1038 auto valKeyEntries = getIniFileSection(iniFile, Sections::kValidatorKeys);
1039
1040 if (valKeyEntries != nullptr)
1041 section(Sections::kValidatorKeys).append(*valKeyEntries);
1042
1043 auto valSiteEntries = getIniFileSection(iniFile, Sections::kValidatorListSites);
1044
1045 if (valSiteEntries != nullptr)
1047
1048 auto valListKeys = getIniFileSection(iniFile, Sections::kValidatorListKeys);
1049
1050 if (valListKeys != nullptr)
1052
1053 auto valListThreshold = getIniFileSection(iniFile, Sections::kValidatorListThreshold);
1054
1055 if (valListThreshold != nullptr)
1057
1058 if ((entries == nullptr) && (valKeyEntries == nullptr) && (valListKeys == nullptr))
1059 {
1061 std::string("The file specified in [") + Sections::kValidatorsFile +
1062 "] "
1063 "does not contain a [" +
1065 "], "
1066 "[" +
1068 "] or "
1069 "[" +
1071 "]"
1072 " section: " +
1073 validatorsFile.string());
1074 }
1075 }
1076
1078 auto const& listThreshold = section(Sections::kValidatorListThreshold);
1079 if (listThreshold.lines().empty())
1080 {
1081 return std::nullopt;
1082 }
1083 if (listThreshold.values().size() == 1)
1084 {
1085 auto strTemp = listThreshold.values()[0];
1086 auto const listThreshold = beast::lexicalCastThrow<std::size_t>(strTemp);
1087 if (listThreshold == 0)
1088 {
1089 return std::nullopt; // NOTE: Explicitly ask for computed
1090 }
1091 if (listThreshold > section(Sections::kValidatorListKeys).values().size())
1092 {
1095 "Value in config section "
1096 "[") +
1098 "] exceeds the number of configured list keys");
1099 }
1100 return listThreshold;
1101 }
1102
1105 "Config section "
1106 "[") +
1107 Sections::kValidatorListThreshold + "] should contain single value only");
1108 }();
1109
1110 // Consolidate [validator_keys] and [validators]
1112
1115 {
1117 "[" + std::string(Sections::kValidatorListKeys) + "] config section is missing");
1118 }
1119 }
1120
1121 {
1122 auto const part = section(Sections::kFeatures);
1123 for (auto const& s : part.values())
1124 {
1125 if (auto const f = getRegisteredFeature(s))
1126 {
1127 features.insert(*f);
1128 }
1129 else
1130 {
1131 Throw<std::runtime_error>("Unknown feature: " + s + " in config file.");
1132 }
1133 }
1134 }
1135
1136 // This doesn't properly belong here, but check to make sure that the
1137 // value specified for network_quorum is achievable:
1138 {
1139 auto pm = peersMax;
1140
1141 // FIXME this apparently magic value is actually defined as a constant
1142 // elsewhere (see defaultMaxPeers) but we handle this check here.
1143 if (pm == 0)
1144 pm = 21;
1145
1146 if (networkQuorum > pm)
1147 {
1149 "The minimum number of required peers (network_quorum) exceeds "
1150 "the maximum number of allowed peers (peers_max)");
1151 }
1152 }
1153}
1154
1155boost::filesystem::path
1157{
1158 auto logFile = debugLogfile_;
1159
1160 if (!logFile.empty() && !logFile.is_absolute())
1161 {
1162 // Unless an absolute path for the log file is specified, the
1163 // path is relative to the config file directory.
1164 logFile = boost::filesystem::absolute(logFile, configDir);
1165 }
1166
1167 if (!logFile.empty())
1168 {
1169 auto logDir = logFile.parent_path();
1170
1171 if (!boost::filesystem::is_directory(logDir))
1172 {
1173 boost::system::error_code ec;
1174 boost::filesystem::create_directories(logDir, ec);
1175
1176 // If we fail, we warn but continue so that the calling code can
1177 // decide how to handle this situation.
1178 if (ec)
1179 {
1180 std::cerr << "Unable to create log file path " << logDir << ": " << ec.message()
1181 << '\n';
1182 }
1183 }
1184 }
1185
1186 return logFile;
1187}
1188
1189int
1191{
1192 auto const index = static_cast<std::underlying_type_t<SizedItem>>(item);
1193 XRPL_ASSERT(index < kSizedItems.size(), "xrpl::Config::getValueFor : valid index input");
1194 XRPL_ASSERT(!node || *node <= 4, "xrpl::Config::getValueFor : unset or valid node");
1195 return kSizedItems.at(index).second.at(node.value_or(nodeSize));
1196}
1197
1199setupFeeVote(Section const& section)
1200{
1201 FeeSetup setup;
1202 {
1203 std::uint64_t temp = 0;
1204 if (set(temp, Keys::kReferenceFee, section) &&
1206 setup.referenceFee = temp;
1207 }
1208 {
1209 std::uint32_t temp = 0;
1210 if (set(temp, Keys::kAccountReserve, section))
1211 setup.accountReserve = temp;
1212 if (set(temp, Keys::kOwnerReserve, section))
1213 setup.ownerReserve = temp;
1214 }
1215 return setup;
1216}
1217
1218DatabaseCon::Setup
1220{
1221 DatabaseCon::Setup setup;
1222
1223 setup.startUp = c.startUp;
1224 setup.standAlone = c.standalone();
1226 if (!setup.standAlone && setup.dataDir.empty())
1227 {
1228 Throw<std::runtime_error>("database_path must be set.");
1229 }
1230
1231 if (!setup.globalPragma)
1232 {
1233 auto const& sqlite = c.section(Sections::kSqlite);
1235 result->reserve(3);
1236
1237 // defaults
1238 std::string safetyLevel;
1239 std::string journalMode = "wal";
1240 std::string synchronous = "normal";
1241 std::string tempStore = "file";
1242 bool showRiskWarning = false;
1243
1244 if (set(safetyLevel, "safety_level", sqlite))
1245 {
1246 if (boost::iequals(safetyLevel, "low"))
1247 {
1248 // low safety defaults
1249 journalMode = "memory";
1250 synchronous = "off";
1251 tempStore = "memory";
1252 showRiskWarning = true;
1253 }
1254 else if (!boost::iequals(safetyLevel, "high"))
1255 {
1256 Throw<std::runtime_error>("Invalid safety_level value: " + safetyLevel);
1257 }
1258 }
1259
1260 {
1261 // #journal_mode Valid values : delete, truncate, persist,
1262 // memory, wal, off
1263 if (set(journalMode, "journal_mode", sqlite) && !safetyLevel.empty())
1264 {
1266 "Configuration file may not define both "
1267 "\"safety_level\" and \"journal_mode\"");
1268 }
1269 bool const higherRisk =
1270 boost::iequals(journalMode, "memory") || boost::iequals(journalMode, "off");
1271 showRiskWarning = showRiskWarning || higherRisk;
1272 if (higherRisk || boost::iequals(journalMode, "delete") ||
1273 boost::iequals(journalMode, "truncate") || boost::iequals(journalMode, "persist") ||
1274 boost::iequals(journalMode, "wal"))
1275 {
1276 result->emplace_back(
1277 boost::str(boost::format(kCommonDbPragmaJournal) % journalMode));
1278 }
1279 else
1280 {
1281 Throw<std::runtime_error>("Invalid journal_mode value: " + journalMode);
1282 }
1283 }
1284
1285 {
1286 // #synchronous Valid values : off, normal, full, extra
1287 if (set(synchronous, "synchronous", sqlite) && !safetyLevel.empty())
1288 {
1290 "Configuration file may not define both "
1291 "\"safety_level\" and \"synchronous\"");
1292 }
1293 bool const higherRisk = boost::iequals(synchronous, "off");
1294 showRiskWarning = showRiskWarning || higherRisk;
1295 if (higherRisk || boost::iequals(synchronous, "normal") ||
1296 boost::iequals(synchronous, "full") || boost::iequals(synchronous, "extra"))
1297 {
1298 result->emplace_back(boost::str(boost::format(kCommonDbPragmaSync) % synchronous));
1299 }
1300 else
1301 {
1302 Throw<std::runtime_error>("Invalid synchronous value: " + synchronous);
1303 }
1304 }
1305
1306 {
1307 // #temp_store Valid values : default, file, memory
1308 if (set(tempStore, "temp_store", sqlite) && !safetyLevel.empty())
1309 {
1311 "Configuration file may not define both "
1312 "\"safety_level\" and \"temp_store\"");
1313 }
1314 bool const higherRisk = boost::iequals(tempStore, "memory");
1315 showRiskWarning = showRiskWarning || higherRisk;
1316 if (higherRisk || boost::iequals(tempStore, "default") ||
1317 boost::iequals(tempStore, "file"))
1318 {
1319 result->emplace_back(boost::str(boost::format(kCommonDbPragmaTemp) % tempStore));
1320 }
1321 else
1322 {
1323 Throw<std::runtime_error>("Invalid temp_store value: " + tempStore);
1324 }
1325 }
1326
1327 if (showRiskWarning && j && c.ledgerHistory > kSqliteTuningCutoff)
1328 {
1329 JLOG(j->warn()) << "reducing the data integrity guarantees from the "
1330 "default [sqlite] behavior is not recommended for "
1331 "nodes storing large amounts of history, because of the "
1332 "difficulty inherent in rebuilding corrupted data.";
1333 }
1334 XRPL_ASSERT(
1335 result->size() == 3, "xrpl::setup_DatabaseCon::globalPragma : result size is 3");
1336 setup.globalPragma = std::move(result);
1337 }
1338 setup.useGlobalPragma = true;
1339
1340 auto setPragma = [](std::string& pragma, std::string const& key, int64_t value) {
1341 pragma = "PRAGMA " + key + "=" + std::to_string(value) + ";";
1342 };
1343
1344 // Lgr Pragma
1345 setPragma(setup.lgrPragma[0], "journal_size_limit", 1582080);
1346
1347 // TX Pragma
1348 int64_t pageSize = 4096;
1349 int64_t journalSizeLimit = 1582080;
1351 {
1352 auto& s = c.section(Sections::kSqlite);
1353 set(journalSizeLimit, Keys::kJournalSizeLimit, s);
1354 set(pageSize, Keys::kPageSize, s);
1355 if (pageSize < 512 || pageSize > 65536)
1356 Throw<std::runtime_error>("Invalid page_size. Must be between 512 and 65536.");
1357
1358 if ((pageSize & (pageSize - 1)) != 0)
1359 Throw<std::runtime_error>("Invalid page_size. Must be a power of 2.");
1360 }
1361
1362 setPragma(setup.txPragma[0], "page_size", pageSize);
1363 setPragma(setup.txPragma[1], "journal_size_limit", journalSizeLimit);
1364 setPragma(setup.txPragma[2], "max_page_count", 4294967294);
1365 setPragma(setup.txPragma[3], "mmap_size", 17179869184);
1366
1367 return setup;
1368}
1369} // namespace xrpl
T clamp(T... args)
A generic endpoint for log messages.
Definition Journal.h:38
Stream warn() const
Definition Journal.h:309
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 &section, 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.
int maxTransactions
Definition Config.h:211
bool useTxTables_
Definition Config.h:114
static constexpr int kMinJobQueueTx
Definition Config.h:213
std::size_t peersMax
Definition Config.h:165
int pathSearchMax
Definition Config.h:184
void load()
Definition Config.cpp:450
int pathSearchOld
Definition Config.h:181
std::chrono::seconds maxDivergedTime
Definition Config.h:269
bool sslVerify
Definition Config.h:200
bool silent_
Definition Config.h:102
uint32_t networkId
Definition Config.h:146
std::unordered_set< uint256, beast::Uhash<> > features
Definition Config.h:261
static constexpr int kMaxJobQueueTx
Definition Config.h:212
bool quiet_
Definition Config.h:101
std::optional< int > sweepInterval
Definition Config.h:228
std::uint32_t fetchDepth
Definition Config.h:193
beast::Journal const j_
Definition Config.h:99
bool standalone() const
Definition Config.h:316
std::size_t txReduceRelayMinPeers
Definition Config.h:253
boost::filesystem::path configFile_
Definition Config.h:89
std::size_t vpReduceRelaySquelchMaxSelectedPeers
Definition Config.h:239
void setup(std::string const &strConf, bool bQuiet, bool bSilent, bool bStandalone)
Definition Config.cpp:307
std::chrono::seconds maxUnknownTime
Definition Config.h:266
static char const *const kDatabaseDirName
Definition Config.h:81
std::size_t nodeSize
Definition Config.h:198
std::size_t peersOutMax
Definition Config.h:166
std::uint64_t const ramSize_
Definition Config.h:125
bool peerPrivate
Definition Config.h:159
int relayUntrustedProposals
Definition Config.h:156
int relayUntrustedValidations
Definition Config.h:155
int ioWorkers
Definition Config.h:220
std::vector< std::string > ipsFixed
Definition Config.h:135
bool vpReduceRelayBaseSquelchEnable
Definition Config.h:233
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition Config.cpp:473
FeeSetup fees
Definition Config.h:189
bool fastLoad
Definition Config.h:275
bool compression
Definition Config.h:205
std::string sslVerifyFile
Definition Config.h:201
std::size_t txRelayPercentage
Definition Config.h:256
bool txReduceRelayMetrics
Definition Config.h:250
boost::filesystem::path getDebugLogFile() const
Returns the full path and filename of the debug log file.
Definition Config.cpp:1156
bool ledgerReplay
Definition Config.h:208
static char const *const kConfigLegacyName
Definition Config.h:80
std::optional< std::size_t > validatorListThreshold
Definition Config.h:284
bool runStandalone_
Operate in stand-alone mode.
Definition Config.h:112
StartUpType startUp
Definition Config.h:137
int pathSearchFast
Definition Config.h:183
std::string sslVerifyDir
Definition Config.h:202
boost::filesystem::path configDir
Definition Config.h:92
bool txReduceRelayEnable
Definition Config.h:243
bool elbSupport
Definition Config.h:129
std::string serverDomain
Definition Config.h:263
int prefetchWorkers
Definition Config.h:221
static char const *const kConfigFileName
Definition Config.h:79
std::vector< std::string > ips
Definition Config.h:132
bool signingEnabled_
Determines if the server will sign a tx, given an account's secret seed.
Definition Config.h:122
void setupControl(bool bQuiet, bool bSilent, bool bStandalone)
Definition Config.cpp:272
int workers
Definition Config.h:219
int pathSearch
Definition Config.h:182
std::uint32_t ledgerHistory
Definition Config.h:192
boost::filesystem::path debugLogfile_
Definition Config.h:95
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.
Definition Config.cpp:1190
static char const *const kValidatorsFileName
Definition Config.h:82
std::size_t peersInMax
Definition Config.h:167
std::size_t networkQuorum
Definition Config.h:150
bool betaRpcApi
Definition Config.h:272
std::chrono::seconds amendmentMajorityTime
Definition Config.h:216
static void initializeSSLContext(std::string const &sslVerifyDir, std::string const &sslVerifyFile, bool sslVerify, beast::Journal j)
Holds a collection of configuration values.
Definition BasicConfig.h:24
std::vector< std::string > const & values() const
Returns all the values in the section.
Definition BasicConfig.h:58
void append(std::vector< std::string > const &lines)
Append a set of lines to this section.
T count(T... args)
T data(T... args)
T distance(T... args)
T emplace(T... args)
T empty(T... args)
T end(T... args)
T endl(T... args)
T find(T... args)
T getenv(T... args)
T hardware_concurrency(T... args)
T make_unique(T... args)
T max(T... args)
T min(T... args)
Out lexicalCastThrow(In in)
Convert from one type to another, throw on error.
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.
Definition algorithm.h:5
bool set(T &target, std::string const &name, Section const &section)
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
Definition DBInit.h:20
std::string getFileContents(boost::system::error_code &ec, boost::filesystem::path const &sourcePath, std::optional< std::size_t > maxSize=std::nullopt)
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)
Definition Config.cpp:256
FeeSetup setupFeeVote(Section const &section)
Definition Config.cpp:1199
bool getSingleSection(IniFileSections &secSource, std::string const &strSection, std::string &strValue, beast::Journal j)
Definition Config.cpp:221
IniFileSections::mapped_type * getIniFileSection(IniFileSections &secSource, std::string const &strSection)
Definition Config.cpp:212
constexpr std::array< std::pair< SizedItem, std::array< int, 5 > >, 13 > kSizedItems
Definition Config.cpp:117
IniFileSections parseIniFile(std::string const &strInput, bool const bTrim)
Definition Config.cpp:164
bool getIfExists(Section const &section, std::string const &name, T &v)
SizedItem
Definition Config.h:27
@ AccountIdCacheSize
Definition Config.h:40
std::chrono::duration< int, std::ratio_multiply< days::period, std::ratio< 7 > > > weeks
Definition chrono.h:21
constexpr char const * kCommonDbPragmaSync
Definition DBInit.h:13
static std::string const & systemName()
constexpr char const * kCommonDbPragmaTemp
Definition DBInit.h:14
static void checkZeroPorts(Config const &config)
Definition Config.cpp:424
std::chrono::duration< int, std::ratio_multiply< std::chrono::hours::period, std::ratio< 24 > > > days
Definition chrono.h:18
DatabaseCon::Setup setupDatabaseCon(Config const &c, std::optional< beast::Journal > j=std::nullopt)
Definition Config.cpp:1219
constexpr char const * kCommonDbPragmaJournal
Definition DBInit.h:12
std::optional< uint256 > getRegisteredFeature(std::string const &name)
std::unordered_map< std::string, std::vector< std::string > > IniFileSections
Definition BasicConfig.h:16
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:49
T regex_replace(T... args)
T size(T... args)
T str(T... args)
std::array< std::string, 4 > txPragma
Definition DatabaseCon.h:91
static std::unique_ptr< std::vector< std::string > const > globalPragma
Definition DatabaseCon.h:90
boost::filesystem::path dataDir
Definition DatabaseCon.h:75
std::array< std::string, 1 > lgrPragma
Definition DatabaseCon.h:92
Fee schedule for startup / standalone, and to vote for.
Definition Config.h:49
XRPAmount accountReserve
The account reserve requirement in drops.
Definition Config.h:54
XRPAmount ownerReserve
The per-owned item reserve requirement in drops.
Definition Config.h:57
XRPAmount referenceFee
The cost of a reference transaction in drops.
Definition Config.h:51
static constexpr auto kPageSize
Definition Constants.h:138
static constexpr auto kTxRelayPercentage
Definition Constants.h:169
static constexpr auto kFastLoad
Definition Constants.h:105
static constexpr auto kTxMetrics
Definition Constants.h:167
static constexpr auto kAccountReserve
Definition Constants.h:83
static constexpr auto kUseTxTables
Definition Constants.h:173
static constexpr auto kReferenceFee
Definition Constants.h:146
static constexpr auto kVpBaseSquelchEnable
Definition Constants.h:175
static constexpr auto kPort
Definition Constants.h:142
static constexpr auto kMaxUnknownTime
Definition Constants.h:121
static constexpr auto kJournalSizeLimit
Definition Constants.h:115
static constexpr auto kTxMinPeers
Definition Constants.h:168
static constexpr auto kVpEnable
Definition Constants.h:177
static constexpr auto kVpBaseSquelchMaxSelectedPeers
Definition Constants.h:176
static constexpr auto kMaxDivergedTime
Definition Constants.h:119
static constexpr auto kTxEnable
Definition Constants.h:166
static constexpr auto kOwnerReserve
Definition Constants.h:137
static constexpr auto kAmendmentMajorityTime
Definition Constants.h:8
static constexpr auto kPeersInMax
Definition Constants.h:40
static constexpr auto kMaxTransactions
Definition Constants.h:28
static constexpr auto kRelayProposals
Definition Constants.h:52
static constexpr auto kSweepInterval
Definition Constants.h:64
static constexpr auto kNodeSize
Definition Constants.h:33
static constexpr auto kServerDomain
Definition Constants.h:56
static constexpr auto kIps
Definition Constants.h:23
static constexpr auto kOverlay
Definition Constants.h:34
static constexpr auto kReduceRelay
Definition Constants.h:50
static constexpr auto kValidatorListThreshold
Definition Constants.h:71
static constexpr auto kValidators
Definition Constants.h:73
static constexpr auto kSslVerifyFile
Definition Constants.h:63
static constexpr auto kValidatorListKeys
Definition Constants.h:69
static constexpr auto kSslVerifyDir
Definition Constants.h:62
static constexpr auto kNetworkQuorum
Definition Constants.h:30
static constexpr auto kValidationSeed
Definition Constants.h:66
static constexpr auto kSigningSupport
Definition Constants.h:57
static constexpr auto kCompression
Definition Constants.h:11
static constexpr auto kPeersMax
Definition Constants.h:41
static constexpr auto kPathSearchOld
Definition Constants.h:38
static constexpr auto kServer
Definition Constants.h:55
static constexpr auto kLedgerHistory
Definition Constants.h:25
static constexpr auto kElbSupport
Definition Constants.h:15
static constexpr auto kValidatorKeys
Definition Constants.h:67
static constexpr auto kPeerPrivate
Definition Constants.h:39
static constexpr auto kSslVerify
Definition Constants.h:61
static constexpr auto kPeersOutMax
Definition Constants.h:42
static constexpr auto kFeeDefault
Definition Constants.h:17
static constexpr auto kValidatorsFile
Definition Constants.h:74
static constexpr auto kPathSearchMax
Definition Constants.h:37
static constexpr auto kRelayValidations
Definition Constants.h:53
static constexpr auto kNodeDatabase
Definition Constants.h:31
static constexpr auto kIpsFixed
Definition Constants.h:24
static constexpr auto kDatabasePath
Definition Constants.h:13
static constexpr auto kPathSearch
Definition Constants.h:35
static constexpr auto kLedgerReplay
Definition Constants.h:26
static constexpr auto kPrefetchWorkers
Definition Constants.h:49
static constexpr auto kDebugLogfile
Definition Constants.h:14
static constexpr auto kSqlite
Definition Constants.h:60
static constexpr auto kValidatorToken
Definition Constants.h:72
static constexpr auto kPathSearchFast
Definition Constants.h:36
static constexpr auto kVoting
Definition Constants.h:77
static constexpr auto kLedgerTxTables
Definition Constants.h:27
static constexpr auto kBetaRpcApi
Definition Constants.h:9
static constexpr auto kIoWorkers
Definition Constants.h:22
static constexpr auto kFetchDepth
Definition Constants.h:18
static constexpr auto kValidatorListSites
Definition Constants.h:70
static constexpr auto kWorkers
Definition Constants.h:78
static constexpr auto kNetworkId
Definition Constants.h:29
static constexpr auto kFeatures
Definition Constants.h:16
T substr(T... args)
T to_string(T... args)
T value_or(T... args)