rippled
Config.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/basics/FileUtilities.h>
21 #include <ripple/basics/Log.h>
22 #include <ripple/basics/StringUtilities.h>
23 #include <ripple/basics/contract.h>
24 #include <ripple/beast/core/LexicalCast.h>
25 #include <ripple/core/Config.h>
26 #include <ripple/core/ConfigSections.h>
27 #include <ripple/json/json_reader.h>
28 #include <ripple/net/HTTPClient.h>
29 #include <ripple/protocol/Feature.h>
30 #include <ripple/protocol/SystemParameters.h>
31 #include <boost/algorithm/string.hpp>
32 #include <boost/format.hpp>
33 #include <boost/predef.h>
34 #include <boost/regex.hpp>
35 #include <boost/system/error_code.hpp>
36 #include <algorithm>
37 #include <cstdlib>
38 #include <iostream>
39 #include <iterator>
40 #include <regex>
41 #include <thread>
42 
43 #if BOOST_OS_WINDOWS
44 #include <sysinfoapi.h>
45 
46 namespace ripple {
47 namespace detail {
48 
49 [[nodiscard]] std::uint64_t
50 getMemorySize()
51 {
52  if (MEMORYSTATUSEX msx{sizeof(MEMORYSTATUSEX)}; GlobalMemoryStatusEx(&msx))
53  return static_cast<std::uint64_t>(msx.ullTotalPhys);
54 
55  return 0;
56 }
57 
58 } // namespace detail
59 } // namespace ripple
60 #endif
61 
62 #if BOOST_OS_LINUX
63 #include <sys/sysinfo.h>
64 
65 namespace ripple {
66 namespace detail {
67 
68 [[nodiscard]] std::uint64_t
69 getMemorySize()
70 {
71  if (struct sysinfo si; sysinfo(&si) == 0)
72  return static_cast<std::uint64_t>(si.totalram) * si.mem_unit;
73 
74  return 0;
75 }
76 
77 } // namespace detail
78 } // namespace ripple
79 
80 #endif
81 
82 #if BOOST_OS_MACOS
83 #include <sys/sysctl.h>
84 #include <sys/types.h>
85 
86 namespace ripple {
87 namespace detail {
88 
89 [[nodiscard]] std::uint64_t
90 getMemorySize()
91 {
92  int mib[] = {CTL_HW, HW_MEMSIZE};
93  std::int64_t ram = 0;
94  size_t size = sizeof(ram);
95 
96  if (sysctl(mib, 2, &ram, &size, NULL, 0) == 0)
97  return static_cast<std::uint64_t>(ram);
98 
99  return 0;
100 }
101 
102 } // namespace detail
103 } // namespace ripple
104 #endif
105 
106 namespace ripple {
107 
108 // clang-format off
109 // The configurable node sizes are "tiny", "small", "medium", "large", "huge"
112 {{
113  // FIXME: We should document each of these items, explaining exactly
114  // what they control and whether there exists an explicit
115  // config option that can be used to override the default.
116 
117  // tiny small medium large huge
118  {SizedItem::sweepInterval, {{ 10, 30, 60, 90, 120 }}},
119  {SizedItem::treeCacheSize, {{ 262144, 524288, 2097152, 4194304, 8388608 }}},
120  {SizedItem::treeCacheAge, {{ 30, 60, 90, 120, 900 }}},
121  {SizedItem::ledgerSize, {{ 32, 32, 64, 256, 384 }}},
122  {SizedItem::ledgerAge, {{ 30, 60, 180, 300, 600 }}},
123  {SizedItem::ledgerFetch, {{ 2, 3, 4, 5, 8 }}},
124  {SizedItem::hashNodeDBCache, {{ 4, 12, 24, 64, 128 }}},
125  {SizedItem::txnDBCache, {{ 4, 12, 24, 64, 128 }}},
126  {SizedItem::lgrDBCache, {{ 4, 8, 16, 32, 128 }}},
127  {SizedItem::openFinalLimit, {{ 8, 16, 32, 64, 128 }}},
128  {SizedItem::burstSize, {{ 4, 8, 16, 32, 48 }}},
129  {SizedItem::ramSizeGB, {{ 6, 8, 12, 24, 0 }}},
130  {SizedItem::accountIdCacheSize, {{ 20047, 50053, 77081, 150061, 300007 }}}
131 }};
132 
133 // Ensure that the order of entries in the table corresponds to the
134 // order of entries in the enum:
135 static_assert(
136  []() constexpr->bool {
137  std::underlying_type_t<SizedItem> idx = 0;
138 
139  for (auto const& i : sizedItems)
140  {
141  if (static_cast<std::underlying_type_t<SizedItem>>(i.first) != idx)
142  return false;
143 
144  ++idx;
145  }
146 
147  return true;
148  }(),
149  "Mismatch between sized item enum & array indices");
150 // clang-format on
151 
152 //
153 // TODO: Check permissions on config file before using it.
154 //
155 
156 #define SECTION_DEFAULT_NAME ""
157 
159 parseIniFile(std::string const& strInput, const bool bTrim)
160 {
161  std::string strData(strInput);
163  IniFileSections secResult;
164 
165  // Convert DOS format to unix.
166  boost::algorithm::replace_all(strData, "\r\n", "\n");
167 
168  // Convert MacOS format to unix.
169  boost::algorithm::replace_all(strData, "\r", "\n");
170 
171  boost::algorithm::split(vLines, strData, boost::algorithm::is_any_of("\n"));
172 
173  // Set the default Section name.
174  std::string strSection = SECTION_DEFAULT_NAME;
175 
176  // Initialize the default Section.
177  secResult[strSection] = IniFileSections::mapped_type();
178 
179  // Parse each line.
180  for (auto& strValue : vLines)
181  {
182  if (bTrim)
183  boost::algorithm::trim(strValue);
184 
185  if (strValue.empty() || strValue[0] == '#')
186  {
187  // Blank line or comment, do nothing.
188  }
189  else if (strValue[0] == '[' && strValue[strValue.length() - 1] == ']')
190  {
191  // New Section.
192  strSection = strValue.substr(1, strValue.length() - 2);
193  secResult.emplace(strSection, IniFileSections::mapped_type{});
194  }
195  else
196  {
197  // Another line for Section.
198  if (!strValue.empty())
199  secResult[strSection].push_back(strValue);
200  }
201  }
202 
203  return secResult;
204 }
205 
206 IniFileSections::mapped_type*
207 getIniFileSection(IniFileSections& secSource, std::string const& strSection)
208 {
209  IniFileSections::iterator it;
210  IniFileSections::mapped_type* smtResult;
211  it = secSource.find(strSection);
212  if (it == secSource.end())
213  smtResult = nullptr;
214  else
215  smtResult = &(it->second);
216  return smtResult;
217 }
218 
219 bool
221  IniFileSections& secSource,
222  std::string const& strSection,
223  std::string& strValue,
224  beast::Journal j)
225 {
226  IniFileSections::mapped_type* pmtEntries =
227  getIniFileSection(secSource, strSection);
228  bool bSingle = pmtEntries && 1 == pmtEntries->size();
229 
230  if (bSingle)
231  {
232  strValue = (*pmtEntries)[0];
233  }
234  else if (pmtEntries)
235  {
236  JLOG(j.warn()) << boost::str(
237  boost::format("Section [%s]: requires 1 line not %d lines.") %
238  strSection % pmtEntries->size());
239  }
240 
241  return bSingle;
242 }
243 
244 //------------------------------------------------------------------------------
245 //
246 // Config (DEPRECATED)
247 //
248 //------------------------------------------------------------------------------
249 
250 char const* const Config::configFileName = "rippled.cfg";
251 char const* const Config::databaseDirName = "db";
252 char const* const Config::validatorsFileName = "validators.txt";
253 
254 [[nodiscard]] static std::string
255 getEnvVar(char const* name)
256 {
257  std::string value;
258 
259  if (auto const v = std::getenv(name); v != nullptr)
260  value = v;
261 
262  return value;
263 }
264 
265 Config::Config()
266  : j_(beast::Journal::getNullSink())
267  , ramSize_(detail::getMemorySize() / (1024 * 1024 * 1024))
268 {
269 }
270 
271 void
272 Config::setupControl(bool bQuiet, bool bSilent, bool bStandalone)
273 {
274  assert(NODE_SIZE == 0);
275 
276  QUIET = bQuiet || bSilent;
277  SILENT = bSilent;
278  RUN_STANDALONE = 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::find_if(
289  threshold.second.begin(),
290  threshold.second.end(),
291  [this](std::size_t limit) {
292  return (limit == 0) || (ramSize_ < limit);
293  });
294 
295  assert(ns != threshold.second.end());
296 
297  if (ns != threshold.second.end())
298  NODE_SIZE = std::distance(threshold.second.begin(), ns);
299 
300  // Adjust the size based on the number of hardware threads of
301  // execution available to us:
302  if (auto const hc = std::thread::hardware_concurrency(); hc != 0)
303  NODE_SIZE = std::min<std::size_t>(hc / 2, NODE_SIZE);
304  }
305 
306  assert(NODE_SIZE <= 4);
307 }
308 
309 void
311  std::string const& strConf,
312  bool bQuiet,
313  bool bSilent,
314  bool bStandalone)
315 {
316  boost::filesystem::path dataDir;
317  std::string strDbPath, strConfFile;
318 
319  // Determine the config and data directories.
320  // If the config file is found in the current working
321  // directory, use the current working directory as the
322  // config directory and that with "db" as the data
323  // directory.
324 
325  setupControl(bQuiet, bSilent, bStandalone);
326 
327  strDbPath = databaseDirName;
328 
329  if (!strConf.empty())
330  strConfFile = strConf;
331  else
332  strConfFile = configFileName;
333 
334  if (!strConf.empty())
335  {
336  // --conf=<path> : everything is relative that file.
337  CONFIG_FILE = strConfFile;
338  CONFIG_DIR = boost::filesystem::absolute(CONFIG_FILE);
339  CONFIG_DIR.remove_filename();
340  dataDir = CONFIG_DIR / strDbPath;
341  }
342  else
343  {
344  CONFIG_DIR = boost::filesystem::current_path();
345  CONFIG_FILE = CONFIG_DIR / strConfFile;
346  dataDir = CONFIG_DIR / strDbPath;
347 
348  // Construct XDG config and data home.
349  // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
350  auto const strHome = getEnvVar("HOME");
351  auto strXdgConfigHome = getEnvVar("XDG_CONFIG_HOME");
352  auto strXdgDataHome = getEnvVar("XDG_DATA_HOME");
353 
354  if (boost::filesystem::exists(CONFIG_FILE)
355  // Can we figure out XDG dirs?
356  || (strHome.empty() &&
357  (strXdgConfigHome.empty() || strXdgDataHome.empty())))
358  {
359  // Current working directory is fine, put dbs in a subdir.
360  }
361  else
362  {
363  if (strXdgConfigHome.empty())
364  {
365  // $XDG_CONFIG_HOME was not set, use default based on $HOME.
366  strXdgConfigHome = strHome + "/.config";
367  }
368 
369  if (strXdgDataHome.empty())
370  {
371  // $XDG_DATA_HOME was not set, use default based on $HOME.
372  strXdgDataHome = strHome + "/.local/share";
373  }
374 
375  CONFIG_DIR = strXdgConfigHome + "/" + systemName();
376  CONFIG_FILE = CONFIG_DIR / strConfFile;
377  dataDir = strXdgDataHome + "/" + systemName();
378 
379  if (!boost::filesystem::exists(CONFIG_FILE))
380  {
381  CONFIG_DIR = "/etc/opt/" + systemName();
382  CONFIG_FILE = CONFIG_DIR / strConfFile;
383  dataDir = "/var/opt/" + systemName();
384  }
385  }
386  }
387 
388  // Update default values
389  load();
390  if (exists("reporting"))
391  {
392  RUN_REPORTING = true;
393  RUN_STANDALONE = true;
394  }
395  {
396  // load() may have set a new value for the dataDir
397  std::string const dbPath(legacy("database_path"));
398  if (!dbPath.empty())
399  dataDir = boost::filesystem::path(dbPath);
400  else if (RUN_STANDALONE)
401  dataDir.clear();
402  }
403 
404  if (!dataDir.empty())
405  {
406  boost::system::error_code ec;
407  boost::filesystem::create_directories(dataDir, ec);
408 
409  if (ec)
410  Throw<std::runtime_error>(
411  boost::str(boost::format("Can not create %s") % dataDir));
412 
413  legacy("database_path", boost::filesystem::absolute(dataDir).string());
414  }
415 
417 
418  if (RUN_STANDALONE)
419  LEDGER_HISTORY = 0;
420 
421  std::string ledgerTxDbType;
422  Section ledgerTxTablesSection = section("ledger_tx_tables");
423  get_if_exists(ledgerTxTablesSection, "use_tx_tables", USE_TX_TABLES);
424 
425  Section& nodeDbSection{section(ConfigSection::nodeDatabase())};
426  get_if_exists(nodeDbSection, "fast_load", FAST_LOAD);
427 }
428 
429 void
431 {
432  // NOTE: this writes to cerr because we want cout to be reserved
433  // for the writing of the json response (so that stdout can be part of a
434  // pipeline, for instance)
435  if (!QUIET)
436  std::cerr << "Loading: " << CONFIG_FILE << "\n";
437 
438  boost::system::error_code ec;
439  auto const fileContents = getFileContents(ec, CONFIG_FILE);
440 
441  if (ec)
442  {
443  std::cerr << "Failed to read '" << CONFIG_FILE << "'." << ec.value()
444  << ": " << ec.message() << std::endl;
445  return;
446  }
447 
448  loadFromString(fileContents);
449 }
450 
451 void
453 {
454  IniFileSections secConfig = parseIniFile(fileContents, true);
455 
456  build(secConfig);
457 
458  if (auto s = getIniFileSection(secConfig, SECTION_IPS))
459  IPS = *s;
460 
461  if (auto s = getIniFileSection(secConfig, SECTION_IPS_FIXED))
462  IPS_FIXED = *s;
463 
464  if (auto s = getIniFileSection(secConfig, SECTION_SNTP))
465  SNTP_SERVERS = *s;
466 
467  // if the user has specified ip:port then replace : with a space.
468  {
469  auto replaceColons = [](std::vector<std::string>& strVec) {
470  const static std::regex e(":([0-9]+)$");
471  for (auto& line : strVec)
472  {
473  // skip anything that might be an ipv6 address
474  if (std::count(line.begin(), line.end(), ':') != 1)
475  continue;
476 
477  std::string result = std::regex_replace(line, e, " $1");
478  // sanity check the result of the replace, should be same length
479  // as input
480  if (result.size() == line.size())
481  line = result;
482  }
483  };
484 
485  replaceColons(IPS_FIXED);
486  replaceColons(IPS);
487  }
488 
489  {
490  std::string dbPath;
491  if (getSingleSection(secConfig, "database_path", dbPath, j_))
492  {
493  boost::filesystem::path p(dbPath);
494  legacy("database_path", boost::filesystem::absolute(p).string());
495  }
496  }
497 
498  std::string strTemp;
499 
500  if (getSingleSection(secConfig, SECTION_NETWORK_ID, strTemp, j_))
501  {
502  if (strTemp == "main")
503  NETWORK_ID = 0;
504  else if (strTemp == "testnet")
505  NETWORK_ID = 1;
506  else if (strTemp == "devnet")
507  NETWORK_ID = 2;
508  else
509  NETWORK_ID = beast::lexicalCastThrow<uint32_t>(strTemp);
510  }
511 
512  if (getSingleSection(secConfig, SECTION_PEER_PRIVATE, strTemp, j_))
513  PEER_PRIVATE = beast::lexicalCastThrow<bool>(strTemp);
514 
515  if (getSingleSection(secConfig, SECTION_PEERS_MAX, strTemp, j_))
516  {
517  PEERS_MAX = beast::lexicalCastThrow<std::size_t>(strTemp);
518  }
519  else
520  {
521  std::optional<std::size_t> peers_in_max{};
522  if (getSingleSection(secConfig, SECTION_PEERS_IN_MAX, strTemp, j_))
523  {
524  peers_in_max = beast::lexicalCastThrow<std::size_t>(strTemp);
525  if (*peers_in_max > 1000)
526  Throw<std::runtime_error>(
527  "Invalid value specified in [" SECTION_PEERS_IN_MAX
528  "] section; the value must be less or equal than 1000");
529  }
530 
531  std::optional<std::size_t> peers_out_max{};
532  if (getSingleSection(secConfig, SECTION_PEERS_OUT_MAX, strTemp, j_))
533  {
534  peers_out_max = beast::lexicalCastThrow<std::size_t>(strTemp);
535  if (*peers_out_max < 10 || *peers_out_max > 1000)
536  Throw<std::runtime_error>(
537  "Invalid value specified in [" SECTION_PEERS_OUT_MAX
538  "] section; the value must be in range 10-1000");
539  }
540 
541  // if one section is configured then the other must be configured too
542  if ((peers_in_max && !peers_out_max) ||
543  (peers_out_max && !peers_in_max))
544  Throw<std::runtime_error>("Both sections [" SECTION_PEERS_IN_MAX
545  "]"
546  "and [" SECTION_PEERS_OUT_MAX
547  "] must be configured");
548 
549  if (peers_in_max && peers_out_max)
550  {
551  PEERS_IN_MAX = *peers_in_max;
552  PEERS_OUT_MAX = *peers_out_max;
553  }
554  }
555 
556  if (getSingleSection(secConfig, SECTION_NODE_SIZE, strTemp, j_))
557  {
558  if (boost::iequals(strTemp, "tiny"))
559  NODE_SIZE = 0;
560  else if (boost::iequals(strTemp, "small"))
561  NODE_SIZE = 1;
562  else if (boost::iequals(strTemp, "medium"))
563  NODE_SIZE = 2;
564  else if (boost::iequals(strTemp, "large"))
565  NODE_SIZE = 3;
566  else if (boost::iequals(strTemp, "huge"))
567  NODE_SIZE = 4;
568  else
569  NODE_SIZE = std::min<std::size_t>(
570  4, beast::lexicalCastThrow<std::size_t>(strTemp));
571  }
572 
573  if (getSingleSection(secConfig, SECTION_SIGNING_SUPPORT, strTemp, j_))
574  signingEnabled_ = beast::lexicalCastThrow<bool>(strTemp);
575 
576  if (getSingleSection(secConfig, SECTION_ELB_SUPPORT, strTemp, j_))
577  ELB_SUPPORT = beast::lexicalCastThrow<bool>(strTemp);
578 
579  getSingleSection(secConfig, SECTION_SSL_VERIFY_FILE, SSL_VERIFY_FILE, j_);
580  getSingleSection(secConfig, SECTION_SSL_VERIFY_DIR, SSL_VERIFY_DIR, j_);
581 
582  if (getSingleSection(secConfig, SECTION_SSL_VERIFY, strTemp, j_))
583  SSL_VERIFY = beast::lexicalCastThrow<bool>(strTemp);
584 
585  if (getSingleSection(secConfig, SECTION_RELAY_VALIDATIONS, strTemp, j_))
586  {
587  if (boost::iequals(strTemp, "all"))
589  else if (boost::iequals(strTemp, "trusted"))
591  else if (boost::iequals(strTemp, "drop_untrusted"))
593  else
594  Throw<std::runtime_error>(
595  "Invalid value specified in [" SECTION_RELAY_VALIDATIONS
596  "] section");
597  }
598 
599  if (getSingleSection(secConfig, SECTION_RELAY_PROPOSALS, strTemp, j_))
600  {
601  if (boost::iequals(strTemp, "all"))
603  else if (boost::iequals(strTemp, "trusted"))
605  else if (boost::iequals(strTemp, "drop_untrusted"))
607  else
608  Throw<std::runtime_error>(
609  "Invalid value specified in [" SECTION_RELAY_PROPOSALS
610  "] section");
611  }
612 
613  if (exists(SECTION_VALIDATION_SEED) && exists(SECTION_VALIDATOR_TOKEN))
614  Throw<std::runtime_error>("Cannot have both [" SECTION_VALIDATION_SEED
615  "] and [" SECTION_VALIDATOR_TOKEN
616  "] config sections");
617 
618  if (getSingleSection(secConfig, SECTION_NETWORK_QUORUM, strTemp, j_))
619  NETWORK_QUORUM = beast::lexicalCastThrow<std::size_t>(strTemp);
620 
621  FEES = setup_FeeVote(section("voting"));
622  /* [fee_default] is documented in the example config files as useful for
623  * things like offline transaction signing. Until that's completely
624  * deprecated, allow it to override the [voting] section. */
625  if (getSingleSection(secConfig, SECTION_FEE_DEFAULT, strTemp, j_))
626  FEES.reference_fee = beast::lexicalCastThrow<std::uint64_t>(strTemp);
627 
628  if (getSingleSection(secConfig, SECTION_LEDGER_HISTORY, strTemp, j_))
629  {
630  if (boost::iequals(strTemp, "full"))
632  std::numeric_limits<decltype(LEDGER_HISTORY)>::max();
633  else if (boost::iequals(strTemp, "none"))
634  LEDGER_HISTORY = 0;
635  else
636  LEDGER_HISTORY = beast::lexicalCastThrow<std::uint32_t>(strTemp);
637  }
638 
639  if (getSingleSection(secConfig, SECTION_FETCH_DEPTH, strTemp, j_))
640  {
641  if (boost::iequals(strTemp, "none"))
642  FETCH_DEPTH = 0;
643  else if (boost::iequals(strTemp, "full"))
644  FETCH_DEPTH = std::numeric_limits<decltype(FETCH_DEPTH)>::max();
645  else
646  FETCH_DEPTH = beast::lexicalCastThrow<std::uint32_t>(strTemp);
647 
648  if (FETCH_DEPTH < 10)
649  FETCH_DEPTH = 10;
650  }
651 
652  // By default, validators don't have pathfinding enabled, unless it is
653  // explicitly requested by the server's admin.
654  if (exists(SECTION_VALIDATION_SEED) || exists(SECTION_VALIDATOR_TOKEN))
655  PATH_SEARCH_MAX = 0;
656 
657  if (getSingleSection(secConfig, SECTION_PATH_SEARCH_OLD, strTemp, j_))
658  PATH_SEARCH_OLD = beast::lexicalCastThrow<int>(strTemp);
659  if (getSingleSection(secConfig, SECTION_PATH_SEARCH, strTemp, j_))
660  PATH_SEARCH = beast::lexicalCastThrow<int>(strTemp);
661  if (getSingleSection(secConfig, SECTION_PATH_SEARCH_FAST, strTemp, j_))
662  PATH_SEARCH_FAST = beast::lexicalCastThrow<int>(strTemp);
663  if (getSingleSection(secConfig, SECTION_PATH_SEARCH_MAX, strTemp, j_))
664  PATH_SEARCH_MAX = beast::lexicalCastThrow<int>(strTemp);
665 
666  if (getSingleSection(secConfig, SECTION_DEBUG_LOGFILE, strTemp, j_))
667  DEBUG_LOGFILE = strTemp;
668 
669  if (getSingleSection(secConfig, SECTION_SWEEP_INTERVAL, strTemp, j_))
670  {
671  SWEEP_INTERVAL = beast::lexicalCastThrow<std::size_t>(strTemp);
672 
673  if (SWEEP_INTERVAL < 10 || SWEEP_INTERVAL > 600)
674  Throw<std::runtime_error>("Invalid " SECTION_SWEEP_INTERVAL
675  ": must be between 10 and 600 inclusive");
676  }
677 
678  if (getSingleSection(secConfig, SECTION_WORKERS, strTemp, j_))
679  {
680  WORKERS = beast::lexicalCastThrow<int>(strTemp);
681 
682  if (WORKERS < 1 || WORKERS > 1024)
683  Throw<std::runtime_error>(
684  "Invalid " SECTION_WORKERS
685  ": must be between 1 and 1024 inclusive.");
686  }
687 
688  if (getSingleSection(secConfig, SECTION_IO_WORKERS, strTemp, j_))
689  {
690  IO_WORKERS = beast::lexicalCastThrow<int>(strTemp);
691 
692  if (IO_WORKERS < 1 || IO_WORKERS > 1024)
693  Throw<std::runtime_error>(
694  "Invalid " SECTION_IO_WORKERS
695  ": must be between 1 and 1024 inclusive.");
696  }
697 
698  if (getSingleSection(secConfig, SECTION_PREFETCH_WORKERS, strTemp, j_))
699  {
700  PREFETCH_WORKERS = beast::lexicalCastThrow<int>(strTemp);
701 
702  if (PREFETCH_WORKERS < 1 || PREFETCH_WORKERS > 1024)
703  Throw<std::runtime_error>(
704  "Invalid " SECTION_PREFETCH_WORKERS
705  ": must be between 1 and 1024 inclusive.");
706  }
707 
708  if (getSingleSection(secConfig, SECTION_COMPRESSION, strTemp, j_))
709  COMPRESSION = beast::lexicalCastThrow<bool>(strTemp);
710 
711  if (getSingleSection(secConfig, SECTION_LEDGER_REPLAY, strTemp, j_))
712  LEDGER_REPLAY = beast::lexicalCastThrow<bool>(strTemp);
713 
714  if (exists(SECTION_REDUCE_RELAY))
715  {
716  auto sec = section(SECTION_REDUCE_RELAY);
717  VP_REDUCE_RELAY_ENABLE = sec.value_or("vp_enable", false);
718  VP_REDUCE_RELAY_SQUELCH = sec.value_or("vp_squelch", false);
719  TX_REDUCE_RELAY_ENABLE = sec.value_or("tx_enable", false);
720  TX_REDUCE_RELAY_METRICS = sec.value_or("tx_metrics", false);
721  TX_REDUCE_RELAY_MIN_PEERS = sec.value_or("tx_min_peers", 20);
722  TX_RELAY_PERCENTAGE = sec.value_or("tx_relay_percentage", 25);
723  if (TX_RELAY_PERCENTAGE < 10 || TX_RELAY_PERCENTAGE > 100 ||
725  Throw<std::runtime_error>(
726  "Invalid " SECTION_REDUCE_RELAY
727  ", tx_min_peers must be greater or equal to 10"
728  ", tx_relay_percentage must be greater or equal to 10 "
729  "and less or equal to 100");
730  }
731 
732  if (getSingleSection(secConfig, SECTION_MAX_TRANSACTIONS, strTemp, j_))
733  {
735  beast::lexicalCastThrow<int>(strTemp),
738  }
739 
740  if (getSingleSection(secConfig, SECTION_SERVER_DOMAIN, strTemp, j_))
741  {
742  if (!isProperlyFormedTomlDomain(strTemp))
743  {
744  Throw<std::runtime_error>(
745  "Invalid " SECTION_SERVER_DOMAIN
746  ": the domain name does not appear to meet the requirements.");
747  }
748 
749  SERVER_DOMAIN = strTemp;
750  }
751 
752  if (exists(SECTION_OVERLAY))
753  {
754  auto const sec = section(SECTION_OVERLAY);
755 
756  using namespace std::chrono;
757 
758  try
759  {
760  if (auto val = sec.get("max_unknown_time"))
762  seconds{beast::lexicalCastThrow<std::uint32_t>(*val)};
763  }
764  catch (...)
765  {
766  Throw<std::runtime_error>(
767  "Invalid value 'max_unknown_time' in " SECTION_OVERLAY
768  ": must be of the form '<number>' representing seconds.");
769  }
770 
771  if (MAX_UNKNOWN_TIME < seconds{300} || MAX_UNKNOWN_TIME > seconds{1800})
772  Throw<std::runtime_error>(
773  "Invalid value 'max_unknown_time' in " SECTION_OVERLAY
774  ": the time must be between 300 and 1800 seconds, inclusive.");
775 
776  try
777  {
778  if (auto val = sec.get("max_diverged_time"))
780  seconds{beast::lexicalCastThrow<std::uint32_t>(*val)};
781  }
782  catch (...)
783  {
784  Throw<std::runtime_error>(
785  "Invalid value 'max_diverged_time' in " SECTION_OVERLAY
786  ": must be of the form '<number>' representing seconds.");
787  }
788 
790  {
791  Throw<std::runtime_error>(
792  "Invalid value 'max_diverged_time' in " SECTION_OVERLAY
793  ": the time must be between 60 and 900 seconds, inclusive.");
794  }
795  }
796 
797  if (getSingleSection(
798  secConfig, SECTION_AMENDMENT_MAJORITY_TIME, strTemp, j_))
799  {
800  using namespace std::chrono;
801  boost::regex const re(
802  "^\\s*(\\d+)\\s*(minutes|hours|days|weeks)\\s*(\\s+.*)?$");
803  boost::smatch match;
804  if (!boost::regex_match(strTemp, match, re))
805  Throw<std::runtime_error>(
806  "Invalid " SECTION_AMENDMENT_MAJORITY_TIME
807  ", must be: [0-9]+ [minutes|hours|days|weeks]");
808 
810  beast::lexicalCastThrow<std::uint32_t>(match[1].str());
811 
812  if (boost::iequals(match[2], "minutes"))
814  else if (boost::iequals(match[2], "hours"))
816  else if (boost::iequals(match[2], "days"))
818  else if (boost::iequals(match[2], "weeks"))
820 
822  Throw<std::runtime_error>(
823  "Invalid " SECTION_AMENDMENT_MAJORITY_TIME
824  ", the minimum amount of time an amendment must hold a "
825  "majority is 15 minutes");
826  }
827 
828  if (getSingleSection(secConfig, SECTION_BETA_RPC_API, strTemp, j_))
829  BETA_RPC_API = beast::lexicalCastThrow<bool>(strTemp);
830 
831  // Do not load trusted validator configuration for standalone mode
832  if (!RUN_STANDALONE)
833  {
834  // If a file was explicitly specified, then throw if the
835  // path is malformed or if the file does not exist or is
836  // not a file.
837  // If the specified file is not an absolute path, then look
838  // for it in the same directory as the config file.
839  // If no path was specified, then look for validators.txt
840  // in the same directory as the config file, but don't complain
841  // if we can't find it.
842  boost::filesystem::path validatorsFile;
843 
844  if (getSingleSection(secConfig, SECTION_VALIDATORS_FILE, strTemp, j_))
845  {
846  validatorsFile = strTemp;
847 
848  if (validatorsFile.empty())
849  Throw<std::runtime_error>(
850  "Invalid path specified in [" SECTION_VALIDATORS_FILE "]");
851 
852  if (!validatorsFile.is_absolute() && !CONFIG_DIR.empty())
853  validatorsFile = CONFIG_DIR / validatorsFile;
854 
855  if (!boost::filesystem::exists(validatorsFile))
856  Throw<std::runtime_error>(
857  "The file specified in [" SECTION_VALIDATORS_FILE
858  "] "
859  "does not exist: " +
860  validatorsFile.string());
861 
862  else if (
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  "]: " +
868  validatorsFile.string());
869  }
870  else if (!CONFIG_DIR.empty())
871  {
872  validatorsFile = CONFIG_DIR / validatorsFileName;
873 
874  if (!validatorsFile.empty())
875  {
876  if (!boost::filesystem::exists(validatorsFile))
877  validatorsFile.clear();
878  else if (
879  !boost::filesystem::is_regular_file(validatorsFile) &&
880  !boost::filesystem::is_symlink(validatorsFile))
881  validatorsFile.clear();
882  }
883  }
884 
885  if (!validatorsFile.empty() &&
886  boost::filesystem::exists(validatorsFile) &&
887  (boost::filesystem::is_regular_file(validatorsFile) ||
888  boost::filesystem::is_symlink(validatorsFile)))
889  {
890  boost::system::error_code ec;
891  auto const data = getFileContents(ec, validatorsFile);
892  if (ec)
893  {
894  Throw<std::runtime_error>(
895  "Failed to read '" + validatorsFile.string() + "'." +
896  std::to_string(ec.value()) + ": " + ec.message());
897  }
898 
899  auto iniFile = parseIniFile(data, true);
900 
901  auto entries = getIniFileSection(iniFile, SECTION_VALIDATORS);
902 
903  if (entries)
904  section(SECTION_VALIDATORS).append(*entries);
905 
906  auto valKeyEntries =
907  getIniFileSection(iniFile, SECTION_VALIDATOR_KEYS);
908 
909  if (valKeyEntries)
910  section(SECTION_VALIDATOR_KEYS).append(*valKeyEntries);
911 
912  auto valSiteEntries =
913  getIniFileSection(iniFile, SECTION_VALIDATOR_LIST_SITES);
914 
915  if (valSiteEntries)
916  section(SECTION_VALIDATOR_LIST_SITES).append(*valSiteEntries);
917 
918  auto valListKeys =
919  getIniFileSection(iniFile, SECTION_VALIDATOR_LIST_KEYS);
920 
921  if (valListKeys)
922  section(SECTION_VALIDATOR_LIST_KEYS).append(*valListKeys);
923 
924  if (!entries && !valKeyEntries && !valListKeys)
925  Throw<std::runtime_error>(
926  "The file specified in [" SECTION_VALIDATORS_FILE
927  "] "
928  "does not contain a [" SECTION_VALIDATORS
929  "], "
930  "[" SECTION_VALIDATOR_KEYS
931  "] or "
932  "[" SECTION_VALIDATOR_LIST_KEYS
933  "]"
934  " section: " +
935  validatorsFile.string());
936  }
937 
938  // Consolidate [validator_keys] and [validators]
939  section(SECTION_VALIDATORS)
940  .append(section(SECTION_VALIDATOR_KEYS).lines());
941 
942  if (!section(SECTION_VALIDATOR_LIST_SITES).lines().empty() &&
943  section(SECTION_VALIDATOR_LIST_KEYS).lines().empty())
944  {
945  Throw<std::runtime_error>(
946  "[" + std::string(SECTION_VALIDATOR_LIST_KEYS) +
947  "] config section is missing");
948  }
949  }
950 
951  {
952  auto const part = section("features");
953  for (auto const& s : part.values())
954  {
955  if (auto const f = getRegisteredFeature(s))
956  features.insert(*f);
957  else
958  Throw<std::runtime_error>(
959  "Unknown feature: " + s + " in config file.");
960  }
961  }
962 
963  // This doesn't properly belong here, but check to make sure that the
964  // value specified for network_quorum is achievable:
965  {
966  auto pm = PEERS_MAX;
967 
968  // FIXME this apparently magic value is actually defined as a constant
969  // elsewhere (see defaultMaxPeers) but we handle this check here.
970  if (pm == 0)
971  pm = 21;
972 
973  if (NETWORK_QUORUM > pm)
974  {
975  Throw<std::runtime_error>(
976  "The minimum number of required peers (network_quorum) exceeds "
977  "the maximum number of allowed peers (peers_max)");
978  }
979  }
980 }
981 
982 boost::filesystem::path
984 {
985  auto log_file = DEBUG_LOGFILE;
986 
987  if (!log_file.empty() && !log_file.is_absolute())
988  {
989  // Unless an absolute path for the log file is specified, the
990  // path is relative to the config file directory.
991  log_file = boost::filesystem::absolute(log_file, CONFIG_DIR);
992  }
993 
994  if (!log_file.empty())
995  {
996  auto log_dir = log_file.parent_path();
997 
998  if (!boost::filesystem::is_directory(log_dir))
999  {
1000  boost::system::error_code ec;
1001  boost::filesystem::create_directories(log_dir, ec);
1002 
1003  // If we fail, we warn but continue so that the calling code can
1004  // decide how to handle this situation.
1005  if (ec)
1006  {
1007  std::cerr << "Unable to create log file path " << log_dir
1008  << ": " << ec.message() << '\n';
1009  }
1010  }
1011  }
1012 
1013  return log_file;
1014 }
1015 
1016 int
1018 {
1019  auto const index = static_cast<std::underlying_type_t<SizedItem>>(item);
1020  assert(index < sizedItems.size());
1021  assert(!node || *node <= 4);
1022  return sizedItems.at(index).second.at(node.value_or(NODE_SIZE));
1023 }
1024 
1025 FeeSetup
1027 {
1028  FeeSetup setup;
1029  {
1030  std::uint64_t temp;
1031  if (set(temp, "reference_fee", section) &&
1033  setup.reference_fee = temp;
1034  }
1035  {
1036  std::uint32_t temp;
1037  if (set(temp, "account_reserve", section))
1038  setup.account_reserve = temp;
1039  if (set(temp, "owner_reserve", section))
1040  setup.owner_reserve = temp;
1041  }
1042  return setup;
1043 }
1044 
1045 } // namespace ripple
ripple::SizedItem::openFinalLimit
@ openFinalLimit
ripple::Section
Holds a collection of configuration values.
Definition: BasicConfig.h:42
ripple::FeeSetup::reference_fee
XRPAmount reference_fee
The cost of a reference transaction in drops.
Definition: Config.h:72
ripple::Config::SWEEP_INTERVAL
std::optional< int > SWEEP_INTERVAL
Definition: Config.h:249
ripple::getFileContents
std::string getFileContents(boost::system::error_code &ec, boost::filesystem::path const &sourcePath, std::optional< std::size_t > maxSize=std::nullopt)
Definition: FileUtilities.cpp:25
regex
std::string
STL class.
ripple::SizedItem
SizedItem
Definition: Config.h:48
ripple::Config::PATH_SEARCH
int PATH_SEARCH
Definition: Config.h:201
ripple::Config::LEDGER_REPLAY
bool LEDGER_REPLAY
Definition: Config.h:228
ripple::SizedItem::accountIdCacheSize
@ accountIdCacheSize
ripple::Config::validatorsFileName
static char const *const validatorsFileName
Definition: Config.h:95
std::vector< std::string >
std::map::find
T find(T... args)
std::size
T size(T... args)
ripple::Config::SSL_VERIFY_DIR
std::string SSL_VERIFY_DIR
Definition: Config.h:222
std::optional::value_or
T value_or(T... args)
ripple::Config::CONFIG_FILE
boost::filesystem::path CONFIG_FILE
Definition: Config.h:102
std::chrono::seconds
ripple::Config::NODE_SIZE
std::size_t NODE_SIZE
Definition: Config.h:218
iterator
ripple::Config::PEER_PRIVATE
bool PEER_PRIVATE
Definition: Config.h:178
ripple::Config::DEBUG_LOGFILE
boost::filesystem::path DEBUG_LOGFILE
Definition: Config.h:108
std::map::emplace
T emplace(T... args)
ripple::Config::setupControl
void setupControl(bool bQuiet, bool bSilent, bool bStandalone)
Definition: Config.cpp:272
ripple::SizedItem::treeCacheAge
@ treeCacheAge
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
std::distance
T distance(T... args)
std::cerr
ripple::SizedItem::hashNodeDBCache
@ hashNodeDBCache
ripple::Config::MIN_JOB_QUEUE_TX
static constexpr int MIN_JOB_QUEUE_TX
Definition: Config.h:234
iostream
ripple::SizedItem::ledgerFetch
@ ledgerFetch
ripple::Config::MAX_TRANSACTIONS
int MAX_TRANSACTIONS
Definition: Config.h:232
ripple::Config::FETCH_DEPTH
std::uint32_t FETCH_DEPTH
Definition: Config.h:213
algorithm
ripple::Config::PATH_SEARCH_MAX
int PATH_SEARCH_MAX
Definition: Config.h:203
ripple::Config::VP_REDUCE_RELAY_SQUELCH
bool VP_REDUCE_RELAY_SQUELCH
Definition: Config.h:263
ripple::get_if_exists
bool get_if_exists(Section const &section, std::string const &name, T &v)
Definition: BasicConfig.h:384
ripple::Config::IO_WORKERS
int IO_WORKERS
Definition: Config.h:241
ripple::Section::append
void append(std::vector< std::string > const &lines)
Append a set of lines to this section.
Definition: BasicConfig.cpp:38
std::underlying_type_t
ripple::Config::RUN_STANDALONE
bool RUN_STANDALONE
Operate in stand-alone mode.
Definition: Config.h:125
ripple::SizedItem::ramSizeGB
@ ramSizeGB
ripple::Config::load
void load()
Definition: Config.cpp:430
ripple::Config::j_
const beast::Journal j_
Definition: Config.h:112
ripple::Config::RELAY_UNTRUSTED_PROPOSALS
int RELAY_UNTRUSTED_PROPOSALS
Definition: Config.h:175
ripple::Config::SSL_VERIFY_FILE
std::string SSL_VERIFY_FILE
Definition: Config.h:221
ripple::Config::loadFromString
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition: Config.cpp:452
ripple::Config::getValueFor
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:1017
ripple::weeks
std::chrono::duration< int, std::ratio_multiply< days::period, std::ratio< 7 > >> weeks
Definition: chrono.h:41
thread
ripple::Config::FAST_LOAD
bool FAST_LOAD
Definition: Config.h:297
std::thread::hardware_concurrency
T hardware_concurrency(T... args)
ripple::Config::SNTP_SERVERS
std::vector< std::string > SNTP_SERVERS
Definition: Config.h:151
ripple::Config::IPS_FIXED
std::vector< std::string > IPS_FIXED
Definition: Config.h:150
ripple::Config::SSL_VERIFY
bool SSL_VERIFY
Definition: Config.h:220
ripple::BasicConfig::build
void build(IniFileSections const &ifs)
Definition: BasicConfig.cpp:176
ripple::Config::USE_TX_TABLES
bool USE_TX_TABLES
Definition: Config.h:131
std::getenv
T getenv(T... args)
std::to_string
T to_string(T... args)
ripple::set
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,...
Definition: BasicConfig.h:313
std::array
STL class.
ripple::Config::BETA_RPC_API
bool BETA_RPC_API
Definition: Config.h:294
ripple::BasicConfig::legacy
void legacy(std::string const &section, std::string value)
Set a value that is not a key/value pair.
Definition: BasicConfig.cpp:164
ripple::setup_FeeVote
FeeSetup setup_FeeVote(Section const &section)
Definition: Config.cpp:1026
ripple::Config::PEERS_OUT_MAX
std::size_t PEERS_OUT_MAX
Definition: Config.h:185
ripple::Config::AMENDMENT_MAJORITY_TIME
std::chrono::seconds AMENDMENT_MAJORITY_TIME
Definition: Config.h:237
ripple::SizedItem::lgrDBCache
@ lgrDBCache
ripple::Config::MAX_JOB_QUEUE_TX
static constexpr int MAX_JOB_QUEUE_TX
Definition: Config.h:233
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::SizedItem::burstSize
@ burstSize
std::uint64_t
ripple::Config::WORKERS
int WORKERS
Definition: Config.h:240
ripple::Config::PEERS_IN_MAX
std::size_t PEERS_IN_MAX
Definition: Config.h:186
ripple::Config::databaseDirName
static char const *const databaseDirName
Definition: Config.h:94
std::map
STL class.
std::regex
ripple::SizedItem::txnDBCache
@ txnDBCache
ripple::Config::PREFETCH_WORKERS
int PREFETCH_WORKERS
Definition: Config.h:242
ripple::Config::PATH_SEARCH_OLD
int PATH_SEARCH_OLD
Definition: Config.h:200
ripple::Config::LEDGER_HISTORY
std::uint32_t LEDGER_HISTORY
Definition: Config.h:212
ripple::parseIniFile
IniFileSections parseIniFile(std::string const &strInput, const bool bTrim)
Definition: Config.cpp:159
ripple::Config::NETWORK_QUORUM
std::size_t NETWORK_QUORUM
Definition: Config.h:169
ripple::sizedItems
constexpr std::array< std::pair< SizedItem, std::array< int, 5 > >, 13 > sizedItems
Definition: Config.cpp:112
ripple::Config::VP_REDUCE_RELAY_ENABLE
bool VP_REDUCE_RELAY_ENABLE
Definition: Config.h:254
ripple::Config::CONFIG_DIR
boost::filesystem::path CONFIG_DIR
Definition: Config.h:105
std::string::substr
T substr(T... args)
ripple::Config::PEERS_MAX
std::size_t PEERS_MAX
Definition: Config.h:184
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::Config::features
std::unordered_set< uint256, beast::uhash<> > features
Definition: Config.h:283
ripple::Config::PATH_SEARCH_FAST
int PATH_SEARCH_FAST
Definition: Config.h:202
ripple::getSingleSection
bool getSingleSection(IniFileSections &secSource, std::string const &strSection, std::string &strValue, beast::Journal j)
Definition: Config.cpp:220
ripple::Config::setup
void setup(std::string const &strConf, bool bQuiet, bool bSilent, bool bStandalone)
Definition: Config.cpp:310
cstdlib
std::endl
T endl(T... args)
ripple::Config::NETWORK_ID
uint32_t NETWORK_ID
Definition: Config.h:161
std::clamp
T clamp(T... args)
ripple::getEnvVar
static std::string getEnvVar(char const *name)
Definition: Config.cpp:255
ripple::SizedItem::treeCacheSize
@ treeCacheSize
ripple::Config::TX_REDUCE_RELAY_MIN_PEERS
std::size_t TX_REDUCE_RELAY_MIN_PEERS
Definition: Config.h:275
ripple::Config::SERVER_DOMAIN
std::string SERVER_DOMAIN
Definition: Config.h:285
ripple::Config::TX_REDUCE_RELAY_METRICS
bool TX_REDUCE_RELAY_METRICS
Definition: Config.h:272
ripple::Config::RELAY_UNTRUSTED_VALIDATIONS
int RELAY_UNTRUSTED_VALIDATIONS
Definition: Config.h:174
ripple::SizedItem::sweepInterval
@ sweepInterval
ripple::Config::COMPRESSION
bool COMPRESSION
Definition: Config.h:225
std::count
T count(T... args)
std::string::empty
T empty(T... args)
ripple::systemName
static std::string const & systemName()
Definition: SystemParameters.h:34
ripple::SizedItem::ledgerSize
@ ledgerSize
std::optional< std::size_t >
ripple::Config::IPS
std::vector< std::string > IPS
Definition: Config.h:149
ripple::Config::configFileName
static char const *const configFileName
Definition: Config.h:93
std::size_t
ripple::isProperlyFormedTomlDomain
bool isProperlyFormedTomlDomain(std::string const &domain)
Determines if the given string looks like a TOML-file hosting domain.
ripple::Config::TX_RELAY_PERCENTAGE
std::size_t TX_RELAY_PERCENTAGE
Definition: Config.h:278
ripple::FeeSetup
Fee schedule for startup / standalone, and to vote for.
Definition: Config.h:69
std::map::end
T end(T... args)
ripple::Config::QUIET
bool QUIET
Definition: Config.h:114
ripple::days
std::chrono::duration< int, std::ratio_multiply< std::chrono::hours::period, std::ratio< 24 > >> days
Definition: chrono.h:38
ripple::Config::TX_REDUCE_RELAY_ENABLE
bool TX_REDUCE_RELAY_ENABLE
Definition: Config.h:265
ripple::getRegisteredFeature
std::optional< uint256 > getRegisteredFeature(std::string const &name)
Definition: Feature.cpp:342
ripple::Config::SILENT
bool SILENT
Definition: Config.h:115
ripple::Config::getDebugLogFile
boost::filesystem::path getDebugLogFile() const
Returns the full path and filename of the debug log file.
Definition: Config.cpp:983
ripple::Config::FEES
FeeSetup FEES
Definition: Config.h:209
ripple::Config::signingEnabled_
bool signingEnabled_
Determines if the server will sign a tx, given an account's secret seed.
Definition: Config.h:139
std::numeric_limits
std::regex_replace
T regex_replace(T... args)
ripple::Config::ELB_SUPPORT
bool ELB_SUPPORT
Definition: Config.h:147
ripple::HTTPClient::initializeSSLContext
static void initializeSSLContext(Config const &config, beast::Journal j)
Definition: HTTPClient.cpp:38
ripple::ConfigSection::nodeDatabase
static std::string nodeDatabase()
Definition: ConfigSections.h:33
ripple::getIniFileSection
IniFileSections::mapped_type * getIniFileSection(IniFileSections &secSource, std::string const &strSection)
Definition: Config.cpp:207
ripple::BasicConfig::exists
bool exists(std::string const &name) const
Returns true if a section with the given name exists.
Definition: BasicConfig.cpp:121
ripple::SizedItem::ledgerAge
@ ledgerAge
ripple::Config::MAX_UNKNOWN_TIME
std::chrono::seconds MAX_UNKNOWN_TIME
Definition: Config.h:288
ripple::BasicConfig::section
Section & section(std::string const &name)
Returns the section with the given name.
Definition: BasicConfig.cpp:127
ripple::Config::MAX_DIVERGED_TIME
std::chrono::seconds MAX_DIVERGED_TIME
Definition: Config.h:291
ripple::IniFileSections
std::map< std::string, std::vector< std::string > > IniFileSections
Definition: BasicConfig.h:35
ripple::Config::RUN_REPORTING
bool RUN_REPORTING
Definition: Config.h:127
beast
Definition: base_uint.h:641
std::chrono