From 1dd1c9f5dc29586c0a06117b9879243861cf6f25 Mon Sep 17 00:00:00 2001 From: intelliot Date: Wed, 15 Mar 2023 04:10:39 +0000 Subject: [PATCH] deploy: cb08f2b6ec425c4686c8c5c7fc4a3209e91166f2 --- Config_8cpp_source.html | 1939 +++++++++-------- Config_8h_source.html | 14 +- Config__test_8cpp_source.html | 679 +++--- Connect_8cpp_source.html | 15 +- Env_8cpp_source.html | 2 +- LedgerHistory_8cpp_source.html | 2 +- LedgerReplay__test_8cpp_source.html | 2 +- Main_8cpp_source.html | 2 +- Node_8cpp_source.html | 2 +- PeerFinder__test_8cpp_source.html | 2 +- RPCCall_8cpp_source.html | 2529 +++++++++++----------- RPCCall_8h_source.html | 8 +- RPCCall__test_8cpp_source.html | 2 +- RPCSub_8cpp_source.html | 2 +- SHAMapStoreImp_8cpp_source.html | 2 +- UnitaryShard_8cpp_source.html | 2 +- Version__test_8cpp_source.html | 2 +- classripple_1_1Config.html | 14 +- classripple_1_1Config__test-members.html | 21 +- classripple_1_1Config__test.html | 31 +- classripple_1_1RPCParser.html | 68 +- compression__test_8cpp_source.html | 2 +- envconfig_8cpp_source.html | 2 +- functions_func_p.html | 4 +- functions_func_r.html | 2 +- functions_func_s.html | 10 +- functions_func_t.html | 37 +- functions_func_v.html | 8 +- functions_func_w.html | 4 +- functions_n.html | 2 +- functions_p.html | 16 +- functions_q.html | 8 +- functions_r.html | 2 +- functions_s.html | 22 +- functions_t.html | 41 +- functions_v.html | 18 +- functions_w.html | 8 +- namespaceripple.html | 18 +- namespaceripple_1_1RPCCall.html | 4 +- nodestore_2impl_2Shard_8cpp_source.html | 2 +- reduce__relay__test_8cpp_source.html | 2 +- search/all_10.js | 6 +- search/all_11.js | 2 +- search/all_12.js | 6 +- search/all_13.js | 24 +- search/all_14.js | 2371 ++++++++++---------- search/all_15.js | 708 +++--- search/all_16.js | 500 ++--- search/all_17.js | 472 ++-- search/all_18.js | 144 +- search/all_19.js | 14 +- search/all_1a.js | 16 +- search/all_1b.js | 708 +++--- search/all_8.js | 2 +- search/all_e.js | 2 +- search/classes_0.js | 4 +- search/classes_1.js | 394 ++-- search/classes_10.js | 268 +-- search/classes_11.js | 22 +- search/classes_12.js | 256 +-- search/classes_13.js | 664 +++--- search/classes_14.js | 302 +-- search/classes_15.js | 408 ++-- search/classes_16.js | 252 +-- search/classes_17.js | 144 +- search/classes_18.js | 36 +- search/classes_19.js | 4 +- search/classes_1a.js | 10 +- search/classes_2.js | 228 +- search/classes_3.js | 426 ++-- search/classes_4.js | 202 +- search/classes_5.js | 182 +- search/classes_6.js | 154 +- search/classes_7.js | 56 +- search/classes_8.js | 80 +- search/classes_9.js | 410 ++-- search/classes_a.js | 46 +- search/classes_b.js | 32 +- search/classes_c.js | 214 +- search/classes_d.js | 274 +-- search/classes_e.js | 170 +- search/classes_f.js | 174 +- search/enums_0.js | 12 +- search/enums_1.js | 20 +- search/enums_10.js | 30 +- search/enums_11.js | 34 +- search/enums_12.js | 8 +- search/enums_13.js | 6 +- search/enums_14.js | 6 +- search/enums_2.js | 10 +- search/enums_3.js | 10 +- search/enums_4.js | 6 +- search/enums_5.js | 4 +- search/enums_6.js | 4 +- search/enums_7.js | 4 +- search/enums_8.js | 4 +- search/enums_9.js | 14 +- search/enums_a.js | 4 +- search/enums_b.js | 6 +- search/enums_c.js | 6 +- search/enums_d.js | 18 +- search/enums_e.js | 2 +- search/enums_f.js | 10 +- search/enumvalues_0.js | 44 +- search/enumvalues_1.js | 46 +- search/enumvalues_10.js | 4 +- search/enumvalues_11.js | 172 +- search/enumvalues_12.js | 176 +- search/enumvalues_13.js | 450 ++-- search/enumvalues_14.js | 28 +- search/enumvalues_15.js | 12 +- search/enumvalues_16.js | 18 +- search/enumvalues_17.js | 18 +- search/enumvalues_18.js | 2 +- search/enumvalues_2.js | 50 +- search/enumvalues_3.js | 52 +- search/enumvalues_4.js | 26 +- search/enumvalues_5.js | 36 +- search/enumvalues_6.js | 42 +- search/enumvalues_7.js | 24 +- search/enumvalues_8.js | 32 +- search/enumvalues_9.js | 96 +- search/enumvalues_a.js | 28 +- search/enumvalues_b.js | 164 +- search/enumvalues_c.js | 46 +- search/enumvalues_d.js | 66 +- search/enumvalues_e.js | 38 +- search/enumvalues_f.js | 42 +- search/files_0.js | 8 +- search/files_1.js | 4 +- search/files_10.js | 8 +- search/files_2.js | 68 +- search/files_3.js | 2 +- search/files_4.js | 4 +- search/files_5.js | 10 +- search/files_6.js | 14 +- search/files_7.js | 6 +- search/files_8.js | 8 +- search/files_9.js | 4 +- search/files_a.js | 4 +- search/files_b.js | 2 +- search/files_c.js | 8 +- search/files_d.js | 26 +- search/files_e.js | 10 +- search/files_f.js | 6 +- search/functions_0.js | 2 +- search/functions_1.js | 740 +++---- search/functions_10.js | 750 +++---- search/functions_11.js | 48 +- search/functions_12.js | 608 +++--- search/functions_13.js | 1342 ++++++------ search/functions_14.js | 2243 +++++++++---------- search/functions_15.js | 242 +-- search/functions_16.js | 174 +- search/functions_17.js | 298 +-- search/functions_18.js | 82 +- search/functions_19.js | 2 +- search/functions_1a.js | 10 +- search/functions_1b.js | 708 +++--- search/functions_2.js | 302 +-- search/functions_3.js | 924 ++++---- search/functions_4.js | 738 +++---- search/functions_5.js | 298 +-- search/functions_6.js | 534 ++--- search/functions_7.js | 1190 +++++----- search/functions_8.js | 186 +- search/functions_9.js | 844 ++++---- search/functions_a.js | 48 +- search/functions_b.js | 34 +- search/functions_c.js | 356 +-- search/functions_d.js | 608 +++--- search/functions_e.js | 324 +-- search/functions_f.js | 430 ++-- search/groups_0.js | 2 +- search/namespaces_0.js | 24 +- search/namespaces_1.js | 4 +- search/namespaces_2.js | 2 +- search/namespaces_3.js | 80 +- search/namespaces_4.js | 24 +- search/pages_0.js | 4 +- search/pages_1.js | 10 +- search/pages_2.js | 4 +- search/pages_3.js | 4 +- search/pages_4.js | 6 +- search/pages_5.js | 4 +- search/pages_6.js | 4 +- search/pages_7.js | 2 +- search/pages_8.js | 4 +- search/pages_9.js | 6 +- search/pages_a.js | 16 +- search/pages_b.js | 8 +- search/pages_c.js | 2 +- search/pages_d.js | 2 +- search/related_0.js | 8 +- search/related_1.js | 16 +- search/related_2.js | 4 +- search/related_3.js | 6 +- search/related_4.js | 2 +- search/related_5.js | 2 +- search/related_6.js | 18 +- search/related_7.js | 14 +- search/related_8.js | 34 +- search/related_9.js | 6 +- search/related_a.js | 10 +- search/related_b.js | 12 +- search/related_c.js | 4 +- search/related_d.js | 6 +- search/typedefs_0.js | 50 +- search/typedefs_1.js | 28 +- search/typedefs_10.js | 2 +- search/typedefs_11.js | 54 +- search/typedefs_12.js | 154 +- search/typedefs_13.js | 80 +- search/typedefs_14.js | 16 +- search/typedefs_15.js | 14 +- search/typedefs_16.js | 10 +- search/typedefs_17.js | 2 +- search/typedefs_18.js | 2 +- search/typedefs_2.js | 62 +- search/typedefs_3.js | 28 +- search/typedefs_4.js | 36 +- search/typedefs_5.js | 20 +- search/typedefs_6.js | 2 +- search/typedefs_7.js | 38 +- search/typedefs_8.js | 52 +- search/typedefs_9.js | 6 +- search/typedefs_a.js | 14 +- search/typedefs_b.js | 52 +- search/typedefs_c.js | 58 +- search/typedefs_d.js | 22 +- search/typedefs_e.js | 20 +- search/typedefs_f.js | 56 +- search/variables_0.js | 328 +-- search/variables_1.js | 148 +- search/variables_10.js | 42 +- search/variables_11.js | 330 +-- search/variables_12.js | 926 ++++---- search/variables_13.js | 380 ++-- search/variables_14.js | 70 +- search/variables_15.js | 124 +- search/variables_16.js | 96 +- search/variables_17.js | 18 +- search/variables_18.js | 4 +- search/variables_19.js | 2 +- search/variables_2.js | 336 +-- search/variables_3.js | 234 +- search/variables_4.js | 118 +- search/variables_5.js | 370 ++-- search/variables_6.js | 46 +- search/variables_7.js | 106 +- search/variables_8.js | 384 ++-- search/variables_9.js | 50 +- search/variables_a.js | 26 +- search/variables_b.js | 274 +-- search/variables_c.js | 1122 +++++----- search/variables_d.js | 200 +- search/variables_e.js | 98 +- search/variables_f.js | 312 +-- structripple_1_1RPCCallImp.html | 8 +- tx__reduce__relay__test_8cpp_source.html | 2 +- 260 files changed, 19839 insertions(+), 19673 deletions(-) diff --git a/Config_8cpp_source.html b/Config_8cpp_source.html index e396784fdf..bf9bb3eebd 100644 --- a/Config_8cpp_source.html +++ b/Config_8cpp_source.html @@ -108,969 +108,993 @@ $(function() {
37 #include <cstdlib>
38 #include <iostream>
39 #include <iterator>
-
40 #include <thread>
-
41 
-
42 #if BOOST_OS_WINDOWS
-
43 #include <sysinfoapi.h>
-
44 
-
45 namespace ripple {
-
46 namespace detail {
-
47 
-
48 [[nodiscard]] std::uint64_t
-
49 getMemorySize()
-
50 {
-
51  if (MEMORYSTATUSEX msx{sizeof(MEMORYSTATUSEX)}; GlobalMemoryStatusEx(&msx))
-
52  return static_cast<std::uint64_t>(msx.ullTotalPhys);
-
53 
-
54  return 0;
-
55 }
-
56 
-
57 } // namespace detail
-
58 } // namespace ripple
-
59 #endif
-
60 
-
61 #if BOOST_OS_LINUX
-
62 #include <sys/sysinfo.h>
-
63 
-
64 namespace ripple {
-
65 namespace detail {
-
66 
-
67 [[nodiscard]] std::uint64_t
-
68 getMemorySize()
-
69 {
-
70  struct sysinfo si;
-
71 
-
72  if (sysinfo(&si) == 0)
-
73  return static_cast<std::uint64_t>(si.totalram);
-
74 
-
75  return 0;
-
76 }
-
77 
-
78 } // namespace detail
-
79 } // namespace ripple
-
80 
-
81 #endif
-
82 
-
83 #if BOOST_OS_MACOS
-
84 #include <sys/sysctl.h>
-
85 #include <sys/types.h>
-
86 
-
87 namespace ripple {
-
88 namespace detail {
-
89 
-
90 [[nodiscard]] std::uint64_t
-
91 getMemorySize()
-
92 {
-
93  int mib[] = {CTL_HW, HW_MEMSIZE};
-
94  std::int64_t ram = 0;
-
95  size_t size = sizeof(ram);
-
96 
-
97  if (sysctl(mib, 2, &ram, &size, NULL, 0) == 0)
-
98  return static_cast<std::uint64_t>(ram);
-
99 
-
100  return 0;
-
101 }
-
102 
-
103 } // namespace detail
-
104 } // namespace ripple
-
105 #endif
-
106 
-
107 namespace ripple {
-
108 
-
109 // clang-format off
-
110 // The configurable node sizes are "tiny", "small", "medium", "large", "huge"
-
111 inline constexpr std::array<std::pair<SizedItem, std::array<int, 5>>, 13>
-
112 sizedItems
-
113 {{
-
114  // FIXME: We should document each of these items, explaining exactly
-
115  // what they control and whether there exists an explicit
-
116  // config option that can be used to override the default.
-
117 
-
118  // tiny small medium large huge
-
119  {SizedItem::sweepInterval, {{ 10, 30, 60, 90, 120 }}},
-
120  {SizedItem::treeCacheSize, {{ 262144, 524288, 2097152, 4194304, 8388608 }}},
-
121  {SizedItem::treeCacheAge, {{ 30, 60, 90, 120, 900 }}},
-
122  {SizedItem::ledgerSize, {{ 32, 32, 64, 256, 384 }}},
-
123  {SizedItem::ledgerAge, {{ 30, 60, 180, 300, 600 }}},
-
124  {SizedItem::ledgerFetch, {{ 2, 3, 4, 5, 8 }}},
-
125  {SizedItem::hashNodeDBCache, {{ 4, 12, 24, 64, 128 }}},
-
126  {SizedItem::txnDBCache, {{ 4, 12, 24, 64, 128 }}},
-
127  {SizedItem::lgrDBCache, {{ 4, 8, 16, 32, 128 }}},
-
128  {SizedItem::openFinalLimit, {{ 8, 16, 32, 64, 128 }}},
-
129  {SizedItem::burstSize, {{ 4, 8, 16, 32, 48 }}},
-
130  {SizedItem::ramSizeGB, {{ 8, 12, 16, 24, 32 }}},
-
131  {SizedItem::accountIdCacheSize, {{ 20047, 50053, 77081, 150061, 300007 }}}
-
132 }};
-
133 
-
134 // Ensure that the order of entries in the table corresponds to the
-
135 // order of entries in the enum:
-
136 static_assert(
-
137  []() constexpr->bool {
-
138  std::underlying_type_t<SizedItem> idx = 0;
-
139 
-
140  for (auto const& i : sizedItems)
-
141  {
-
142  if (static_cast<std::underlying_type_t<SizedItem>>(i.first) != idx)
-
143  return false;
-
144 
-
145  ++idx;
-
146  }
-
147 
-
148  return true;
-
149  }(),
-
150  "Mismatch between sized item enum & array indices");
-
151 // clang-format on
-
152 
-
153 //
-
154 // TODO: Check permissions on config file before using it.
-
155 //
-
156 
-
157 #define SECTION_DEFAULT_NAME ""
-
158 
-
159 IniFileSections
-
160 parseIniFile(std::string const& strInput, const bool bTrim)
-
161 {
-
162  std::string strData(strInput);
-
163  std::vector<std::string> vLines;
-
164  IniFileSections secResult;
-
165 
-
166  // Convert DOS format to unix.
-
167  boost::algorithm::replace_all(strData, "\r\n", "\n");
-
168 
-
169  // Convert MacOS format to unix.
-
170  boost::algorithm::replace_all(strData, "\r", "\n");
-
171 
-
172  boost::algorithm::split(vLines, strData, boost::algorithm::is_any_of("\n"));
-
173 
-
174  // Set the default Section name.
-
175  std::string strSection = SECTION_DEFAULT_NAME;
-
176 
-
177  // Initialize the default Section.
-
178  secResult[strSection] = IniFileSections::mapped_type();
-
179 
-
180  // Parse each line.
-
181  for (auto& strValue : vLines)
-
182  {
-
183  if (bTrim)
-
184  boost::algorithm::trim(strValue);
-
185 
-
186  if (strValue.empty() || strValue[0] == '#')
-
187  {
-
188  // Blank line or comment, do nothing.
-
189  }
-
190  else if (strValue[0] == '[' && strValue[strValue.length() - 1] == ']')
-
191  {
-
192  // New Section.
-
193  strSection = strValue.substr(1, strValue.length() - 2);
-
194  secResult.emplace(strSection, IniFileSections::mapped_type{});
-
195  }
-
196  else
-
197  {
-
198  // Another line for Section.
-
199  if (!strValue.empty())
-
200  secResult[strSection].push_back(strValue);
-
201  }
-
202  }
-
203 
-
204  return secResult;
-
205 }
-
206 
-
207 IniFileSections::mapped_type*
-
208 getIniFileSection(IniFileSections& secSource, std::string const& strSection)
-
209 {
-
210  IniFileSections::iterator it;
-
211  IniFileSections::mapped_type* smtResult;
-
212  it = secSource.find(strSection);
-
213  if (it == secSource.end())
-
214  smtResult = nullptr;
-
215  else
-
216  smtResult = &(it->second);
-
217  return smtResult;
-
218 }
-
219 
-
220 bool
-
221 getSingleSection(
-
222  IniFileSections& secSource,
-
223  std::string const& strSection,
-
224  std::string& strValue,
-
225  beast::Journal j)
-
226 {
-
227  IniFileSections::mapped_type* pmtEntries =
-
228  getIniFileSection(secSource, strSection);
-
229  bool bSingle = pmtEntries && 1 == pmtEntries->size();
-
230 
-
231  if (bSingle)
-
232  {
-
233  strValue = (*pmtEntries)[0];
-
234  }
-
235  else if (pmtEntries)
-
236  {
-
237  JLOG(j.warn()) << boost::str(
-
238  boost::format("Section [%s]: requires 1 line not %d lines.") %
-
239  strSection % pmtEntries->size());
-
240  }
-
241 
-
242  return bSingle;
-
243 }
-
244 
-
245 //------------------------------------------------------------------------------
-
246 //
-
247 // Config (DEPRECATED)
-
248 //
-
249 //------------------------------------------------------------------------------
-
250 
-
251 char const* const Config::configFileName = "rippled.cfg";
-
252 char const* const Config::databaseDirName = "db";
-
253 char const* const Config::validatorsFileName = "validators.txt";
-
254 
-
255 [[nodiscard]] static std::string
-
256 getEnvVar(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 
-
266 Config::Config()
-
267  : j_(beast::Journal::getNullSink()), ramSize_(detail::getMemorySize())
-
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 =
-
286  sizedItems[std::underlying_type_t<SizedItem>(SizedItem::ramSizeGB)];
-
287 
-
288  auto ns = std::find_if(
-
289  threshold.second.begin(),
-
290  threshold.second.end(),
-
291  [this](std::size_t limit) {
-
292  return (ramSize_ / (1024 * 1024 * 1024)) < limit;
-
293  });
-
294 
-
295  if (ns != threshold.second.end())
-
296  NODE_SIZE = std::distance(threshold.second.begin(), ns);
-
297 
-
298  // Adjust the size based on the number of hardware threads of
-
299  // execution available to us:
-
300  if (auto const hc = std::thread::hardware_concurrency())
-
301  {
-
302  if (hc == 1)
-
303  NODE_SIZE = 0;
-
304 
-
305  if (hc < 4)
-
306  NODE_SIZE = std::min<std::size_t>(NODE_SIZE, 1);
-
307  }
-
308  }
-
309 
-
310  assert(NODE_SIZE <= 4);
-
311 }
-
312 
-
313 void
-
314 Config::setup(
-
315  std::string const& strConf,
-
316  bool bQuiet,
-
317  bool bSilent,
-
318  bool bStandalone)
-
319 {
-
320  boost::filesystem::path dataDir;
-
321  std::string strDbPath, strConfFile;
-
322 
-
323  // Determine the config and data directories.
-
324  // If the config file is found in the current working
-
325  // directory, use the current working directory as the
-
326  // config directory and that with "db" as the data
-
327  // directory.
-
328 
-
329  setupControl(bQuiet, bSilent, bStandalone);
-
330 
-
331  strDbPath = databaseDirName;
-
332 
-
333  if (!strConf.empty())
-
334  strConfFile = strConf;
-
335  else
-
336  strConfFile = configFileName;
-
337 
-
338  if (!strConf.empty())
-
339  {
-
340  // --conf=<path> : everything is relative that file.
-
341  CONFIG_FILE = strConfFile;
-
342  CONFIG_DIR = boost::filesystem::absolute(CONFIG_FILE);
-
343  CONFIG_DIR.remove_filename();
-
344  dataDir = CONFIG_DIR / strDbPath;
-
345  }
-
346  else
-
347  {
-
348  CONFIG_DIR = boost::filesystem::current_path();
-
349  CONFIG_FILE = CONFIG_DIR / strConfFile;
-
350  dataDir = CONFIG_DIR / strDbPath;
-
351 
-
352  // Construct XDG config and data home.
-
353  // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
-
354  auto const strHome = getEnvVar("HOME");
-
355  auto strXdgConfigHome = getEnvVar("XDG_CONFIG_HOME");
-
356  auto strXdgDataHome = getEnvVar("XDG_DATA_HOME");
-
357 
-
358  if (boost::filesystem::exists(CONFIG_FILE)
-
359  // Can we figure out XDG dirs?
-
360  || (strHome.empty() &&
-
361  (strXdgConfigHome.empty() || strXdgDataHome.empty())))
-
362  {
-
363  // Current working directory is fine, put dbs in a subdir.
-
364  }
-
365  else
-
366  {
-
367  if (strXdgConfigHome.empty())
-
368  {
-
369  // $XDG_CONFIG_HOME was not set, use default based on $HOME.
-
370  strXdgConfigHome = strHome + "/.config";
-
371  }
-
372 
-
373  if (strXdgDataHome.empty())
-
374  {
-
375  // $XDG_DATA_HOME was not set, use default based on $HOME.
-
376  strXdgDataHome = strHome + "/.local/share";
-
377  }
-
378 
-
379  CONFIG_DIR = strXdgConfigHome + "/" + systemName();
-
380  CONFIG_FILE = CONFIG_DIR / strConfFile;
-
381  dataDir = strXdgDataHome + "/" + systemName();
-
382 
-
383  if (!boost::filesystem::exists(CONFIG_FILE))
-
384  {
-
385  CONFIG_DIR = "/etc/opt/" + systemName();
-
386  CONFIG_FILE = CONFIG_DIR / strConfFile;
-
387  dataDir = "/var/opt/" + systemName();
-
388  }
-
389  }
-
390  }
-
391 
-
392  // Update default values
-
393  load();
-
394  if (exists("reporting"))
-
395  {
-
396  RUN_REPORTING = true;
-
397  RUN_STANDALONE = true;
-
398  }
-
399  {
-
400  // load() may have set a new value for the dataDir
-
401  std::string const dbPath(legacy("database_path"));
-
402  if (!dbPath.empty())
-
403  dataDir = boost::filesystem::path(dbPath);
-
404  else if (RUN_STANDALONE)
-
405  dataDir.clear();
-
406  }
-
407 
-
408  if (!dataDir.empty())
-
409  {
-
410  boost::system::error_code ec;
-
411  boost::filesystem::create_directories(dataDir, ec);
-
412 
-
413  if (ec)
-
414  Throw<std::runtime_error>(
-
415  boost::str(boost::format("Can not create %s") % dataDir));
-
416 
-
417  legacy("database_path", boost::filesystem::absolute(dataDir).string());
-
418  }
-
419 
-
420  HTTPClient::initializeSSLContext(*this, j_);
-
421 
-
422  if (RUN_STANDALONE)
-
423  LEDGER_HISTORY = 0;
-
424 
-
425  std::string ledgerTxDbType;
-
426  Section ledgerTxTablesSection = section("ledger_tx_tables");
-
427  get_if_exists(ledgerTxTablesSection, "use_tx_tables", USE_TX_TABLES);
-
428 
-
429  Section& nodeDbSection{section(ConfigSection::nodeDatabase())};
-
430  get_if_exists(nodeDbSection, "fast_load", FAST_LOAD);
-
431 }
-
432 
-
433 void
-
434 Config::load()
-
435 {
-
436  // NOTE: this writes to cerr because we want cout to be reserved
-
437  // for the writing of the json response (so that stdout can be part of a
-
438  // pipeline, for instance)
-
439  if (!QUIET)
-
440  std::cerr << "Loading: " << CONFIG_FILE << "\n";
-
441 
-
442  boost::system::error_code ec;
-
443  auto const fileContents = getFileContents(ec, CONFIG_FILE);
-
444 
-
445  if (ec)
-
446  {
-
447  std::cerr << "Failed to read '" << CONFIG_FILE << "'." << ec.value()
-
448  << ": " << ec.message() << std::endl;
-
449  return;
-
450  }
-
451 
-
452  loadFromString(fileContents);
-
453 }
-
454 
-
455 void
-
456 Config::loadFromString(std::string const& fileContents)
-
457 {
-
458  IniFileSections secConfig = parseIniFile(fileContents, true);
-
459 
-
460  build(secConfig);
-
461 
-
462  if (auto s = getIniFileSection(secConfig, SECTION_IPS))
-
463  IPS = *s;
-
464 
-
465  if (auto s = getIniFileSection(secConfig, SECTION_IPS_FIXED))
-
466  IPS_FIXED = *s;
-
467 
-
468  if (auto s = getIniFileSection(secConfig, SECTION_SNTP))
-
469  SNTP_SERVERS = *s;
-
470 
-
471  {
-
472  std::string dbPath;
-
473  if (getSingleSection(secConfig, "database_path", dbPath, j_))
-
474  {
-
475  boost::filesystem::path p(dbPath);
-
476  legacy("database_path", boost::filesystem::absolute(p).string());
-
477  }
-
478  }
-
479 
-
480  std::string strTemp;
+
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  struct sysinfo si;
+
72 
+
73  if (sysinfo(&si) == 0)
+
74  return static_cast<std::uint64_t>(si.totalram);
+
75 
+
76  return 0;
+
77 }
+
78 
+
79 } // namespace detail
+
80 } // namespace ripple
+
81 
+
82 #endif
+
83 
+
84 #if BOOST_OS_MACOS
+
85 #include <sys/sysctl.h>
+
86 #include <sys/types.h>
+
87 
+
88 namespace ripple {
+
89 namespace detail {
+
90 
+
91 [[nodiscard]] std::uint64_t
+
92 getMemorySize()
+
93 {
+
94  int mib[] = {CTL_HW, HW_MEMSIZE};
+
95  std::int64_t ram = 0;
+
96  size_t size = sizeof(ram);
+
97 
+
98  if (sysctl(mib, 2, &ram, &size, NULL, 0) == 0)
+
99  return static_cast<std::uint64_t>(ram);
+
100 
+
101  return 0;
+
102 }
+
103 
+
104 } // namespace detail
+
105 } // namespace ripple
+
106 #endif
+
107 
+
108 namespace ripple {
+
109 
+
110 // clang-format off
+
111 // The configurable node sizes are "tiny", "small", "medium", "large", "huge"
+
112 inline constexpr std::array<std::pair<SizedItem, std::array<int, 5>>, 13>
+
113 sizedItems
+
114 {{
+
115  // FIXME: We should document each of these items, explaining exactly
+
116  // what they control and whether there exists an explicit
+
117  // config option that can be used to override the default.
+
118 
+
119  // tiny small medium large huge
+
120  {SizedItem::sweepInterval, {{ 10, 30, 60, 90, 120 }}},
+
121  {SizedItem::treeCacheSize, {{ 262144, 524288, 2097152, 4194304, 8388608 }}},
+
122  {SizedItem::treeCacheAge, {{ 30, 60, 90, 120, 900 }}},
+
123  {SizedItem::ledgerSize, {{ 32, 32, 64, 256, 384 }}},
+
124  {SizedItem::ledgerAge, {{ 30, 60, 180, 300, 600 }}},
+
125  {SizedItem::ledgerFetch, {{ 2, 3, 4, 5, 8 }}},
+
126  {SizedItem::hashNodeDBCache, {{ 4, 12, 24, 64, 128 }}},
+
127  {SizedItem::txnDBCache, {{ 4, 12, 24, 64, 128 }}},
+
128  {SizedItem::lgrDBCache, {{ 4, 8, 16, 32, 128 }}},
+
129  {SizedItem::openFinalLimit, {{ 8, 16, 32, 64, 128 }}},
+
130  {SizedItem::burstSize, {{ 4, 8, 16, 32, 48 }}},
+
131  {SizedItem::ramSizeGB, {{ 8, 12, 16, 24, 32 }}},
+
132  {SizedItem::accountIdCacheSize, {{ 20047, 50053, 77081, 150061, 300007 }}}
+
133 }};
+
134 
+
135 // Ensure that the order of entries in the table corresponds to the
+
136 // order of entries in the enum:
+
137 static_assert(
+
138  []() constexpr->bool {
+
139  std::underlying_type_t<SizedItem> idx = 0;
+
140 
+
141  for (auto const& i : sizedItems)
+
142  {
+
143  if (static_cast<std::underlying_type_t<SizedItem>>(i.first) != idx)
+
144  return false;
+
145 
+
146  ++idx;
+
147  }
+
148 
+
149  return true;
+
150  }(),
+
151  "Mismatch between sized item enum & array indices");
+
152 // clang-format on
+
153 
+
154 //
+
155 // TODO: Check permissions on config file before using it.
+
156 //
+
157 
+
158 #define SECTION_DEFAULT_NAME ""
+
159 
+
160 IniFileSections
+
161 parseIniFile(std::string const& strInput, const bool bTrim)
+
162 {
+
163  std::string strData(strInput);
+
164  std::vector<std::string> vLines;
+
165  IniFileSections secResult;
+
166 
+
167  // Convert DOS format to unix.
+
168  boost::algorithm::replace_all(strData, "\r\n", "\n");
+
169 
+
170  // Convert MacOS format to unix.
+
171  boost::algorithm::replace_all(strData, "\r", "\n");
+
172 
+
173  boost::algorithm::split(vLines, strData, boost::algorithm::is_any_of("\n"));
+
174 
+
175  // Set the default Section name.
+
176  std::string strSection = SECTION_DEFAULT_NAME;
+
177 
+
178  // Initialize the default Section.
+
179  secResult[strSection] = IniFileSections::mapped_type();
+
180 
+
181  // Parse each line.
+
182  for (auto& strValue : vLines)
+
183  {
+
184  if (bTrim)
+
185  boost::algorithm::trim(strValue);
+
186 
+
187  if (strValue.empty() || strValue[0] == '#')
+
188  {
+
189  // Blank line or comment, do nothing.
+
190  }
+
191  else if (strValue[0] == '[' && strValue[strValue.length() - 1] == ']')
+
192  {
+
193  // New Section.
+
194  strSection = strValue.substr(1, strValue.length() - 2);
+
195  secResult.emplace(strSection, IniFileSections::mapped_type{});
+
196  }
+
197  else
+
198  {
+
199  // Another line for Section.
+
200  if (!strValue.empty())
+
201  secResult[strSection].push_back(strValue);
+
202  }
+
203  }
+
204 
+
205  return secResult;
+
206 }
+
207 
+
208 IniFileSections::mapped_type*
+
209 getIniFileSection(IniFileSections& secSource, std::string const& strSection)
+
210 {
+
211  IniFileSections::iterator it;
+
212  IniFileSections::mapped_type* smtResult;
+
213  it = secSource.find(strSection);
+
214  if (it == secSource.end())
+
215  smtResult = nullptr;
+
216  else
+
217  smtResult = &(it->second);
+
218  return smtResult;
+
219 }
+
220 
+
221 bool
+
222 getSingleSection(
+
223  IniFileSections& secSource,
+
224  std::string const& strSection,
+
225  std::string& strValue,
+
226  beast::Journal j)
+
227 {
+
228  IniFileSections::mapped_type* pmtEntries =
+
229  getIniFileSection(secSource, strSection);
+
230  bool bSingle = pmtEntries && 1 == pmtEntries->size();
+
231 
+
232  if (bSingle)
+
233  {
+
234  strValue = (*pmtEntries)[0];
+
235  }
+
236  else if (pmtEntries)
+
237  {
+
238  JLOG(j.warn()) << boost::str(
+
239  boost::format("Section [%s]: requires 1 line not %d lines.") %
+
240  strSection % pmtEntries->size());
+
241  }
+
242 
+
243  return bSingle;
+
244 }
+
245 
+
246 //------------------------------------------------------------------------------
+
247 //
+
248 // Config (DEPRECATED)
+
249 //
+
250 //------------------------------------------------------------------------------
+
251 
+
252 char const* const Config::configFileName = "rippled.cfg";
+
253 char const* const Config::databaseDirName = "db";
+
254 char const* const Config::validatorsFileName = "validators.txt";
+
255 
+
256 [[nodiscard]] static std::string
+
257 getEnvVar(char const* name)
+
258 {
+
259  std::string value;
+
260 
+
261  if (auto const v = std::getenv(name); v != nullptr)
+
262  value = v;
+
263 
+
264  return value;
+
265 }
+
266 
+
267 Config::Config()
+
268  : j_(beast::Journal::getNullSink()), ramSize_(detail::getMemorySize())
+
269 {
+
270 }
+
271 
+
272 void
+
273 Config::setupControl(bool bQuiet, bool bSilent, bool bStandalone)
+
274 {
+
275  assert(NODE_SIZE == 0);
+
276 
+
277  QUIET = bQuiet || bSilent;
+
278  SILENT = bSilent;
+
279  RUN_STANDALONE = bStandalone;
+
280 
+
281  // We try to autodetect the appropriate node size by checking available
+
282  // RAM and CPU resources. We default to "tiny" for standalone mode.
+
283  if (!bStandalone)
+
284  {
+
285  // First, check against 'minimum' RAM requirements per node size:
+
286  auto const& threshold =
+
287  sizedItems[std::underlying_type_t<SizedItem>(SizedItem::ramSizeGB)];
+
288 
+
289  auto ns = std::find_if(
+
290  threshold.second.begin(),
+
291  threshold.second.end(),
+
292  [this](std::size_t limit) {
+
293  return (ramSize_ / (1024 * 1024 * 1024)) < limit;
+
294  });
+
295 
+
296  if (ns != threshold.second.end())
+
297  NODE_SIZE = std::distance(threshold.second.begin(), ns);
+
298 
+
299  // Adjust the size based on the number of hardware threads of
+
300  // execution available to us:
+
301  if (auto const hc = std::thread::hardware_concurrency())
+
302  {
+
303  if (hc == 1)
+
304  NODE_SIZE = 0;
+
305 
+
306  if (hc < 4)
+
307  NODE_SIZE = std::min<std::size_t>(NODE_SIZE, 1);
+
308  }
+
309  }
+
310 
+
311  assert(NODE_SIZE <= 4);
+
312 }
+
313 
+
314 void
+
315 Config::setup(
+
316  std::string const& strConf,
+
317  bool bQuiet,
+
318  bool bSilent,
+
319  bool bStandalone)
+
320 {
+
321  boost::filesystem::path dataDir;
+
322  std::string strDbPath, strConfFile;
+
323 
+
324  // Determine the config and data directories.
+
325  // If the config file is found in the current working
+
326  // directory, use the current working directory as the
+
327  // config directory and that with "db" as the data
+
328  // directory.
+
329 
+
330  setupControl(bQuiet, bSilent, bStandalone);
+
331 
+
332  strDbPath = databaseDirName;
+
333 
+
334  if (!strConf.empty())
+
335  strConfFile = strConf;
+
336  else
+
337  strConfFile = configFileName;
+
338 
+
339  if (!strConf.empty())
+
340  {
+
341  // --conf=<path> : everything is relative that file.
+
342  CONFIG_FILE = strConfFile;
+
343  CONFIG_DIR = boost::filesystem::absolute(CONFIG_FILE);
+
344  CONFIG_DIR.remove_filename();
+
345  dataDir = CONFIG_DIR / strDbPath;
+
346  }
+
347  else
+
348  {
+
349  CONFIG_DIR = boost::filesystem::current_path();
+
350  CONFIG_FILE = CONFIG_DIR / strConfFile;
+
351  dataDir = CONFIG_DIR / strDbPath;
+
352 
+
353  // Construct XDG config and data home.
+
354  // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
+
355  auto const strHome = getEnvVar("HOME");
+
356  auto strXdgConfigHome = getEnvVar("XDG_CONFIG_HOME");
+
357  auto strXdgDataHome = getEnvVar("XDG_DATA_HOME");
+
358 
+
359  if (boost::filesystem::exists(CONFIG_FILE)
+
360  // Can we figure out XDG dirs?
+
361  || (strHome.empty() &&
+
362  (strXdgConfigHome.empty() || strXdgDataHome.empty())))
+
363  {
+
364  // Current working directory is fine, put dbs in a subdir.
+
365  }
+
366  else
+
367  {
+
368  if (strXdgConfigHome.empty())
+
369  {
+
370  // $XDG_CONFIG_HOME was not set, use default based on $HOME.
+
371  strXdgConfigHome = strHome + "/.config";
+
372  }
+
373 
+
374  if (strXdgDataHome.empty())
+
375  {
+
376  // $XDG_DATA_HOME was not set, use default based on $HOME.
+
377  strXdgDataHome = strHome + "/.local/share";
+
378  }
+
379 
+
380  CONFIG_DIR = strXdgConfigHome + "/" + systemName();
+
381  CONFIG_FILE = CONFIG_DIR / strConfFile;
+
382  dataDir = strXdgDataHome + "/" + systemName();
+
383 
+
384  if (!boost::filesystem::exists(CONFIG_FILE))
+
385  {
+
386  CONFIG_DIR = "/etc/opt/" + systemName();
+
387  CONFIG_FILE = CONFIG_DIR / strConfFile;
+
388  dataDir = "/var/opt/" + systemName();
+
389  }
+
390  }
+
391  }
+
392 
+
393  // Update default values
+
394  load();
+
395  if (exists("reporting"))
+
396  {
+
397  RUN_REPORTING = true;
+
398  RUN_STANDALONE = true;
+
399  }
+
400  {
+
401  // load() may have set a new value for the dataDir
+
402  std::string const dbPath(legacy("database_path"));
+
403  if (!dbPath.empty())
+
404  dataDir = boost::filesystem::path(dbPath);
+
405  else if (RUN_STANDALONE)
+
406  dataDir.clear();
+
407  }
+
408 
+
409  if (!dataDir.empty())
+
410  {
+
411  boost::system::error_code ec;
+
412  boost::filesystem::create_directories(dataDir, ec);
+
413 
+
414  if (ec)
+
415  Throw<std::runtime_error>(
+
416  boost::str(boost::format("Can not create %s") % dataDir));
+
417 
+
418  legacy("database_path", boost::filesystem::absolute(dataDir).string());
+
419  }
+
420 
+
421  HTTPClient::initializeSSLContext(*this, j_);
+
422 
+
423  if (RUN_STANDALONE)
+
424  LEDGER_HISTORY = 0;
+
425 
+
426  std::string ledgerTxDbType;
+
427  Section ledgerTxTablesSection = section("ledger_tx_tables");
+
428  get_if_exists(ledgerTxTablesSection, "use_tx_tables", USE_TX_TABLES);
+
429 
+
430  Section& nodeDbSection{section(ConfigSection::nodeDatabase())};
+
431  get_if_exists(nodeDbSection, "fast_load", FAST_LOAD);
+
432 }
+
433 
+
434 void
+
435 Config::load()
+
436 {
+
437  // NOTE: this writes to cerr because we want cout to be reserved
+
438  // for the writing of the json response (so that stdout can be part of a
+
439  // pipeline, for instance)
+
440  if (!QUIET)
+
441  std::cerr << "Loading: " << CONFIG_FILE << "\n";
+
442 
+
443  boost::system::error_code ec;
+
444  auto const fileContents = getFileContents(ec, CONFIG_FILE);
+
445 
+
446  if (ec)
+
447  {
+
448  std::cerr << "Failed to read '" << CONFIG_FILE << "'." << ec.value()
+
449  << ": " << ec.message() << std::endl;
+
450  return;
+
451  }
+
452 
+
453  loadFromString(fileContents);
+
454 }
+
455 
+
456 void
+
457 Config::loadFromString(std::string const& fileContents)
+
458 {
+
459  IniFileSections secConfig = parseIniFile(fileContents, true);
+
460 
+
461  build(secConfig);
+
462 
+
463  if (auto s = getIniFileSection(secConfig, SECTION_IPS))
+
464  IPS = *s;
+
465 
+
466  if (auto s = getIniFileSection(secConfig, SECTION_IPS_FIXED))
+
467  IPS_FIXED = *s;
+
468 
+
469  if (auto s = getIniFileSection(secConfig, SECTION_SNTP))
+
470  SNTP_SERVERS = *s;
+
471 
+
472  // if the user has specified ip:port then replace : with a space.
+
473  {
+
474  auto replaceColons = [](std::vector<std::string>& strVec) {
+
475  const static std::regex e(":([0-9]+)$");
+
476  for (auto& line : strVec)
+
477  {
+
478  // skip anything that might be an ipv6 address
+
479  if (std::count(line.begin(), line.end(), ':') != 1)
+
480  continue;
481 
-
482  if (getSingleSection(secConfig, SECTION_PEER_PRIVATE, strTemp, j_))
-
483  PEER_PRIVATE = beast::lexicalCastThrow<bool>(strTemp);
-
484 
-
485  if (getSingleSection(secConfig, SECTION_PEERS_MAX, strTemp, j_))
-
486  {
-
487  PEERS_MAX = beast::lexicalCastThrow<std::size_t>(strTemp);
-
488  }
-
489  else
-
490  {
-
491  std::optional<std::size_t> peers_in_max{};
-
492  if (getSingleSection(secConfig, SECTION_PEERS_IN_MAX, strTemp, j_))
-
493  {
-
494  peers_in_max = beast::lexicalCastThrow<std::size_t>(strTemp);
-
495  if (*peers_in_max > 1000)
-
496  Throw<std::runtime_error>(
-
497  "Invalid value specified in [" SECTION_PEERS_IN_MAX
-
498  "] section; the value must be less or equal than 1000");
-
499  }
-
500 
-
501  std::optional<std::size_t> peers_out_max{};
-
502  if (getSingleSection(secConfig, SECTION_PEERS_OUT_MAX, strTemp, j_))
-
503  {
-
504  peers_out_max = beast::lexicalCastThrow<std::size_t>(strTemp);
-
505  if (*peers_out_max < 10 || *peers_out_max > 1000)
-
506  Throw<std::runtime_error>(
-
507  "Invalid value specified in [" SECTION_PEERS_OUT_MAX
-
508  "] section; the value must be in range 10-1000");
-
509  }
-
510 
-
511  // if one section is configured then the other must be configured too
-
512  if ((peers_in_max && !peers_out_max) ||
-
513  (peers_out_max && !peers_in_max))
-
514  Throw<std::runtime_error>("Both sections [" SECTION_PEERS_IN_MAX
-
515  "]"
-
516  "and [" SECTION_PEERS_OUT_MAX
-
517  "] must be configured");
-
518 
-
519  if (peers_in_max && peers_out_max)
-
520  {
-
521  PEERS_IN_MAX = *peers_in_max;
-
522  PEERS_OUT_MAX = *peers_out_max;
-
523  }
-
524  }
-
525 
-
526  if (getSingleSection(secConfig, SECTION_NODE_SIZE, strTemp, j_))
-
527  {
-
528  if (boost::iequals(strTemp, "tiny"))
-
529  NODE_SIZE = 0;
-
530  else if (boost::iequals(strTemp, "small"))
-
531  NODE_SIZE = 1;
-
532  else if (boost::iequals(strTemp, "medium"))
-
533  NODE_SIZE = 2;
-
534  else if (boost::iequals(strTemp, "large"))
-
535  NODE_SIZE = 3;
-
536  else if (boost::iequals(strTemp, "huge"))
-
537  NODE_SIZE = 4;
-
538  else
-
539  NODE_SIZE = std::min<std::size_t>(
-
540  4, beast::lexicalCastThrow<std::size_t>(strTemp));
-
541  }
-
542 
-
543  if (getSingleSection(secConfig, SECTION_SIGNING_SUPPORT, strTemp, j_))
-
544  signingEnabled_ = beast::lexicalCastThrow<bool>(strTemp);
-
545 
-
546  if (getSingleSection(secConfig, SECTION_ELB_SUPPORT, strTemp, j_))
-
547  ELB_SUPPORT = beast::lexicalCastThrow<bool>(strTemp);
+
482  std::string result = std::regex_replace(line, e, " $1");
+
483  // sanity check the result of the replace, should be same length
+
484  // as input
+
485  if (result.size() == line.size())
+
486  line = result;
+
487  }
+
488  };
+
489 
+
490  replaceColons(IPS_FIXED);
+
491  replaceColons(IPS);
+
492  }
+
493 
+
494  {
+
495  std::string dbPath;
+
496  if (getSingleSection(secConfig, "database_path", dbPath, j_))
+
497  {
+
498  boost::filesystem::path p(dbPath);
+
499  legacy("database_path", boost::filesystem::absolute(p).string());
+
500  }
+
501  }
+
502 
+
503  std::string strTemp;
+
504 
+
505  if (getSingleSection(secConfig, SECTION_PEER_PRIVATE, strTemp, j_))
+
506  PEER_PRIVATE = beast::lexicalCastThrow<bool>(strTemp);
+
507 
+
508  if (getSingleSection(secConfig, SECTION_PEERS_MAX, strTemp, j_))
+
509  {
+
510  PEERS_MAX = beast::lexicalCastThrow<std::size_t>(strTemp);
+
511  }
+
512  else
+
513  {
+
514  std::optional<std::size_t> peers_in_max{};
+
515  if (getSingleSection(secConfig, SECTION_PEERS_IN_MAX, strTemp, j_))
+
516  {
+
517  peers_in_max = beast::lexicalCastThrow<std::size_t>(strTemp);
+
518  if (*peers_in_max > 1000)
+
519  Throw<std::runtime_error>(
+
520  "Invalid value specified in [" SECTION_PEERS_IN_MAX
+
521  "] section; the value must be less or equal than 1000");
+
522  }
+
523 
+
524  std::optional<std::size_t> peers_out_max{};
+
525  if (getSingleSection(secConfig, SECTION_PEERS_OUT_MAX, strTemp, j_))
+
526  {
+
527  peers_out_max = beast::lexicalCastThrow<std::size_t>(strTemp);
+
528  if (*peers_out_max < 10 || *peers_out_max > 1000)
+
529  Throw<std::runtime_error>(
+
530  "Invalid value specified in [" SECTION_PEERS_OUT_MAX
+
531  "] section; the value must be in range 10-1000");
+
532  }
+
533 
+
534  // if one section is configured then the other must be configured too
+
535  if ((peers_in_max && !peers_out_max) ||
+
536  (peers_out_max && !peers_in_max))
+
537  Throw<std::runtime_error>("Both sections [" SECTION_PEERS_IN_MAX
+
538  "]"
+
539  "and [" SECTION_PEERS_OUT_MAX
+
540  "] must be configured");
+
541 
+
542  if (peers_in_max && peers_out_max)
+
543  {
+
544  PEERS_IN_MAX = *peers_in_max;
+
545  PEERS_OUT_MAX = *peers_out_max;
+
546  }
+
547  }
548 
-
549  getSingleSection(secConfig, SECTION_SSL_VERIFY_FILE, SSL_VERIFY_FILE, j_);
-
550  getSingleSection(secConfig, SECTION_SSL_VERIFY_DIR, SSL_VERIFY_DIR, j_);
-
551 
-
552  if (getSingleSection(secConfig, SECTION_SSL_VERIFY, strTemp, j_))
-
553  SSL_VERIFY = beast::lexicalCastThrow<bool>(strTemp);
-
554 
-
555  if (getSingleSection(secConfig, SECTION_RELAY_VALIDATIONS, strTemp, j_))
-
556  {
-
557  if (boost::iequals(strTemp, "all"))
-
558  RELAY_UNTRUSTED_VALIDATIONS = 1;
-
559  else if (boost::iequals(strTemp, "trusted"))
-
560  RELAY_UNTRUSTED_VALIDATIONS = 0;
-
561  else if (boost::iequals(strTemp, "drop_untrusted"))
-
562  RELAY_UNTRUSTED_VALIDATIONS = -1;
-
563  else
-
564  Throw<std::runtime_error>(
-
565  "Invalid value specified in [" SECTION_RELAY_VALIDATIONS
-
566  "] section");
-
567  }
+
549  if (getSingleSection(secConfig, SECTION_NODE_SIZE, strTemp, j_))
+
550  {
+
551  if (boost::iequals(strTemp, "tiny"))
+
552  NODE_SIZE = 0;
+
553  else if (boost::iequals(strTemp, "small"))
+
554  NODE_SIZE = 1;
+
555  else if (boost::iequals(strTemp, "medium"))
+
556  NODE_SIZE = 2;
+
557  else if (boost::iequals(strTemp, "large"))
+
558  NODE_SIZE = 3;
+
559  else if (boost::iequals(strTemp, "huge"))
+
560  NODE_SIZE = 4;
+
561  else
+
562  NODE_SIZE = std::min<std::size_t>(
+
563  4, beast::lexicalCastThrow<std::size_t>(strTemp));
+
564  }
+
565 
+
566  if (getSingleSection(secConfig, SECTION_SIGNING_SUPPORT, strTemp, j_))
+
567  signingEnabled_ = beast::lexicalCastThrow<bool>(strTemp);
568 
-
569  if (getSingleSection(secConfig, SECTION_RELAY_PROPOSALS, strTemp, j_))
-
570  {
-
571  if (boost::iequals(strTemp, "all"))
-
572  RELAY_UNTRUSTED_PROPOSALS = 1;
-
573  else if (boost::iequals(strTemp, "trusted"))
-
574  RELAY_UNTRUSTED_PROPOSALS = 0;
-
575  else if (boost::iequals(strTemp, "drop_untrusted"))
-
576  RELAY_UNTRUSTED_PROPOSALS = -1;
-
577  else
-
578  Throw<std::runtime_error>(
-
579  "Invalid value specified in [" SECTION_RELAY_PROPOSALS
-
580  "] section");
-
581  }
-
582 
-
583  if (exists(SECTION_VALIDATION_SEED) && exists(SECTION_VALIDATOR_TOKEN))
-
584  Throw<std::runtime_error>("Cannot have both [" SECTION_VALIDATION_SEED
-
585  "] and [" SECTION_VALIDATOR_TOKEN
-
586  "] config sections");
-
587 
-
588  if (getSingleSection(secConfig, SECTION_NETWORK_QUORUM, strTemp, j_))
-
589  NETWORK_QUORUM = beast::lexicalCastThrow<std::size_t>(strTemp);
-
590 
-
591  if (getSingleSection(secConfig, SECTION_FEE_ACCOUNT_RESERVE, strTemp, j_))
-
592  FEE_ACCOUNT_RESERVE = beast::lexicalCastThrow<std::uint64_t>(strTemp);
-
593 
-
594  if (getSingleSection(secConfig, SECTION_FEE_OWNER_RESERVE, strTemp, j_))
-
595  FEE_OWNER_RESERVE = beast::lexicalCastThrow<std::uint64_t>(strTemp);
-
596 
-
597  if (getSingleSection(secConfig, SECTION_FEE_DEFAULT, strTemp, j_))
-
598  FEE_DEFAULT = beast::lexicalCastThrow<std::uint64_t>(strTemp);
-
599 
-
600  if (getSingleSection(secConfig, SECTION_LEDGER_HISTORY, strTemp, j_))
-
601  {
-
602  if (boost::iequals(strTemp, "full"))
-
603  LEDGER_HISTORY =
-
604  std::numeric_limits<decltype(LEDGER_HISTORY)>::max();
-
605  else if (boost::iequals(strTemp, "none"))
-
606  LEDGER_HISTORY = 0;
-
607  else
-
608  LEDGER_HISTORY = beast::lexicalCastThrow<std::uint32_t>(strTemp);
-
609  }
+
569  if (getSingleSection(secConfig, SECTION_ELB_SUPPORT, strTemp, j_))
+
570  ELB_SUPPORT = beast::lexicalCastThrow<bool>(strTemp);
+
571 
+
572  getSingleSection(secConfig, SECTION_SSL_VERIFY_FILE, SSL_VERIFY_FILE, j_);
+
573  getSingleSection(secConfig, SECTION_SSL_VERIFY_DIR, SSL_VERIFY_DIR, j_);
+
574 
+
575  if (getSingleSection(secConfig, SECTION_SSL_VERIFY, strTemp, j_))
+
576  SSL_VERIFY = beast::lexicalCastThrow<bool>(strTemp);
+
577 
+
578  if (getSingleSection(secConfig, SECTION_RELAY_VALIDATIONS, strTemp, j_))
+
579  {
+
580  if (boost::iequals(strTemp, "all"))
+
581  RELAY_UNTRUSTED_VALIDATIONS = 1;
+
582  else if (boost::iequals(strTemp, "trusted"))
+
583  RELAY_UNTRUSTED_VALIDATIONS = 0;
+
584  else if (boost::iequals(strTemp, "drop_untrusted"))
+
585  RELAY_UNTRUSTED_VALIDATIONS = -1;
+
586  else
+
587  Throw<std::runtime_error>(
+
588  "Invalid value specified in [" SECTION_RELAY_VALIDATIONS
+
589  "] section");
+
590  }
+
591 
+
592  if (getSingleSection(secConfig, SECTION_RELAY_PROPOSALS, strTemp, j_))
+
593  {
+
594  if (boost::iequals(strTemp, "all"))
+
595  RELAY_UNTRUSTED_PROPOSALS = 1;
+
596  else if (boost::iequals(strTemp, "trusted"))
+
597  RELAY_UNTRUSTED_PROPOSALS = 0;
+
598  else if (boost::iequals(strTemp, "drop_untrusted"))
+
599  RELAY_UNTRUSTED_PROPOSALS = -1;
+
600  else
+
601  Throw<std::runtime_error>(
+
602  "Invalid value specified in [" SECTION_RELAY_PROPOSALS
+
603  "] section");
+
604  }
+
605 
+
606  if (exists(SECTION_VALIDATION_SEED) && exists(SECTION_VALIDATOR_TOKEN))
+
607  Throw<std::runtime_error>("Cannot have both [" SECTION_VALIDATION_SEED
+
608  "] and [" SECTION_VALIDATOR_TOKEN
+
609  "] config sections");
610 
-
611  if (getSingleSection(secConfig, SECTION_FETCH_DEPTH, strTemp, j_))
-
612  {
-
613  if (boost::iequals(strTemp, "none"))
-
614  FETCH_DEPTH = 0;
-
615  else if (boost::iequals(strTemp, "full"))
-
616  FETCH_DEPTH = std::numeric_limits<decltype(FETCH_DEPTH)>::max();
-
617  else
-
618  FETCH_DEPTH = beast::lexicalCastThrow<std::uint32_t>(strTemp);
+
611  if (getSingleSection(secConfig, SECTION_NETWORK_QUORUM, strTemp, j_))
+
612  NETWORK_QUORUM = beast::lexicalCastThrow<std::size_t>(strTemp);
+
613 
+
614  if (getSingleSection(secConfig, SECTION_FEE_ACCOUNT_RESERVE, strTemp, j_))
+
615  FEE_ACCOUNT_RESERVE = beast::lexicalCastThrow<std::uint64_t>(strTemp);
+
616 
+
617  if (getSingleSection(secConfig, SECTION_FEE_OWNER_RESERVE, strTemp, j_))
+
618  FEE_OWNER_RESERVE = beast::lexicalCastThrow<std::uint64_t>(strTemp);
619 
-
620  if (FETCH_DEPTH < 10)
-
621  FETCH_DEPTH = 10;
-
622  }
-
623 
-
624  // By default, validators don't have pathfinding enabled, unless it is
-
625  // explicitly requested by the server's admin.
-
626  if (exists(SECTION_VALIDATION_SEED) || exists(SECTION_VALIDATOR_TOKEN))
-
627  PATH_SEARCH_MAX = 0;
-
628 
-
629  if (getSingleSection(secConfig, SECTION_PATH_SEARCH_OLD, strTemp, j_))
-
630  PATH_SEARCH_OLD = beast::lexicalCastThrow<int>(strTemp);
-
631  if (getSingleSection(secConfig, SECTION_PATH_SEARCH, strTemp, j_))
-
632  PATH_SEARCH = beast::lexicalCastThrow<int>(strTemp);
-
633  if (getSingleSection(secConfig, SECTION_PATH_SEARCH_FAST, strTemp, j_))
-
634  PATH_SEARCH_FAST = beast::lexicalCastThrow<int>(strTemp);
-
635  if (getSingleSection(secConfig, SECTION_PATH_SEARCH_MAX, strTemp, j_))
-
636  PATH_SEARCH_MAX = beast::lexicalCastThrow<int>(strTemp);
-
637 
-
638  if (getSingleSection(secConfig, SECTION_DEBUG_LOGFILE, strTemp, j_))
-
639  DEBUG_LOGFILE = strTemp;
-
640 
-
641  if (getSingleSection(secConfig, SECTION_SWEEP_INTERVAL, strTemp, j_))
-
642  {
-
643  SWEEP_INTERVAL = beast::lexicalCastThrow<std::size_t>(strTemp);
-
644 
-
645  if (SWEEP_INTERVAL < 10 || SWEEP_INTERVAL > 600)
-
646  Throw<std::runtime_error>("Invalid " SECTION_SWEEP_INTERVAL
-
647  ": must be between 10 and 600 inclusive");
-
648  }
-
649 
-
650  if (getSingleSection(secConfig, SECTION_WORKERS, strTemp, j_))
-
651  {
-
652  WORKERS = beast::lexicalCastThrow<int>(strTemp);
-
653 
-
654  if (WORKERS < 1 || WORKERS > 1024)
-
655  Throw<std::runtime_error>(
-
656  "Invalid " SECTION_WORKERS
-
657  ": must be between 1 and 1024 inclusive.");
-
658  }
-
659 
-
660  if (getSingleSection(secConfig, SECTION_IO_WORKERS, strTemp, j_))
-
661  {
-
662  IO_WORKERS = beast::lexicalCastThrow<int>(strTemp);
+
620  if (getSingleSection(secConfig, SECTION_FEE_DEFAULT, strTemp, j_))
+
621  FEE_DEFAULT = beast::lexicalCastThrow<std::uint64_t>(strTemp);
+
622 
+
623  if (getSingleSection(secConfig, SECTION_LEDGER_HISTORY, strTemp, j_))
+
624  {
+
625  if (boost::iequals(strTemp, "full"))
+
626  LEDGER_HISTORY =
+
627  std::numeric_limits<decltype(LEDGER_HISTORY)>::max();
+
628  else if (boost::iequals(strTemp, "none"))
+
629  LEDGER_HISTORY = 0;
+
630  else
+
631  LEDGER_HISTORY = beast::lexicalCastThrow<std::uint32_t>(strTemp);
+
632  }
+
633 
+
634  if (getSingleSection(secConfig, SECTION_FETCH_DEPTH, strTemp, j_))
+
635  {
+
636  if (boost::iequals(strTemp, "none"))
+
637  FETCH_DEPTH = 0;
+
638  else if (boost::iequals(strTemp, "full"))
+
639  FETCH_DEPTH = std::numeric_limits<decltype(FETCH_DEPTH)>::max();
+
640  else
+
641  FETCH_DEPTH = beast::lexicalCastThrow<std::uint32_t>(strTemp);
+
642 
+
643  if (FETCH_DEPTH < 10)
+
644  FETCH_DEPTH = 10;
+
645  }
+
646 
+
647  // By default, validators don't have pathfinding enabled, unless it is
+
648  // explicitly requested by the server's admin.
+
649  if (exists(SECTION_VALIDATION_SEED) || exists(SECTION_VALIDATOR_TOKEN))
+
650  PATH_SEARCH_MAX = 0;
+
651 
+
652  if (getSingleSection(secConfig, SECTION_PATH_SEARCH_OLD, strTemp, j_))
+
653  PATH_SEARCH_OLD = beast::lexicalCastThrow<int>(strTemp);
+
654  if (getSingleSection(secConfig, SECTION_PATH_SEARCH, strTemp, j_))
+
655  PATH_SEARCH = beast::lexicalCastThrow<int>(strTemp);
+
656  if (getSingleSection(secConfig, SECTION_PATH_SEARCH_FAST, strTemp, j_))
+
657  PATH_SEARCH_FAST = beast::lexicalCastThrow<int>(strTemp);
+
658  if (getSingleSection(secConfig, SECTION_PATH_SEARCH_MAX, strTemp, j_))
+
659  PATH_SEARCH_MAX = beast::lexicalCastThrow<int>(strTemp);
+
660 
+
661  if (getSingleSection(secConfig, SECTION_DEBUG_LOGFILE, strTemp, j_))
+
662  DEBUG_LOGFILE = strTemp;
663 
-
664  if (IO_WORKERS < 1 || IO_WORKERS > 1024)
-
665  Throw<std::runtime_error>(
-
666  "Invalid " SECTION_IO_WORKERS
-
667  ": must be between 1 and 1024 inclusive.");
-
668  }
-
669 
-
670  if (getSingleSection(secConfig, SECTION_PREFETCH_WORKERS, strTemp, j_))
-
671  {
-
672  PREFETCH_WORKERS = beast::lexicalCastThrow<int>(strTemp);
-
673 
-
674  if (PREFETCH_WORKERS < 1 || PREFETCH_WORKERS > 1024)
-
675  Throw<std::runtime_error>(
-
676  "Invalid " SECTION_PREFETCH_WORKERS
-
677  ": must be between 1 and 1024 inclusive.");
-
678  }
-
679 
-
680  if (getSingleSection(secConfig, SECTION_COMPRESSION, strTemp, j_))
-
681  COMPRESSION = beast::lexicalCastThrow<bool>(strTemp);
+
664  if (getSingleSection(secConfig, SECTION_SWEEP_INTERVAL, strTemp, j_))
+
665  {
+
666  SWEEP_INTERVAL = beast::lexicalCastThrow<std::size_t>(strTemp);
+
667 
+
668  if (SWEEP_INTERVAL < 10 || SWEEP_INTERVAL > 600)
+
669  Throw<std::runtime_error>("Invalid " SECTION_SWEEP_INTERVAL
+
670  ": must be between 10 and 600 inclusive");
+
671  }
+
672 
+
673  if (getSingleSection(secConfig, SECTION_WORKERS, strTemp, j_))
+
674  {
+
675  WORKERS = beast::lexicalCastThrow<int>(strTemp);
+
676 
+
677  if (WORKERS < 1 || WORKERS > 1024)
+
678  Throw<std::runtime_error>(
+
679  "Invalid " SECTION_WORKERS
+
680  ": must be between 1 and 1024 inclusive.");
+
681  }
682 
-
683  if (getSingleSection(secConfig, SECTION_LEDGER_REPLAY, strTemp, j_))
-
684  LEDGER_REPLAY = beast::lexicalCastThrow<bool>(strTemp);
-
685 
-
686  if (exists(SECTION_REDUCE_RELAY))
-
687  {
-
688  auto sec = section(SECTION_REDUCE_RELAY);
-
689  VP_REDUCE_RELAY_ENABLE = sec.value_or("vp_enable", false);
-
690  VP_REDUCE_RELAY_SQUELCH = sec.value_or("vp_squelch", false);
-
691  TX_REDUCE_RELAY_ENABLE = sec.value_or("tx_enable", false);
-
692  TX_REDUCE_RELAY_METRICS = sec.value_or("tx_metrics", false);
-
693  TX_REDUCE_RELAY_MIN_PEERS = sec.value_or("tx_min_peers", 20);
-
694  TX_RELAY_PERCENTAGE = sec.value_or("tx_relay_percentage", 25);
-
695  if (TX_RELAY_PERCENTAGE < 10 || TX_RELAY_PERCENTAGE > 100 ||
-
696  TX_REDUCE_RELAY_MIN_PEERS < 10)
-
697  Throw<std::runtime_error>(
-
698  "Invalid " SECTION_REDUCE_RELAY
-
699  ", tx_min_peers must be greater or equal to 10"
-
700  ", tx_relay_percentage must be greater or equal to 10 "
-
701  "and less or equal to 100");
-
702  }
-
703 
-
704  if (getSingleSection(secConfig, SECTION_MAX_TRANSACTIONS, strTemp, j_))
-
705  {
-
706  MAX_TRANSACTIONS = std::clamp(
-
707  beast::lexicalCastThrow<int>(strTemp),
-
708  MIN_JOB_QUEUE_TX,
-
709  MAX_JOB_QUEUE_TX);
-
710  }
-
711 
-
712  if (getSingleSection(secConfig, SECTION_SERVER_DOMAIN, strTemp, j_))
-
713  {
-
714  if (!isProperlyFormedTomlDomain(strTemp))
-
715  {
-
716  Throw<std::runtime_error>(
-
717  "Invalid " SECTION_SERVER_DOMAIN
-
718  ": the domain name does not appear to meet the requirements.");
-
719  }
-
720 
-
721  SERVER_DOMAIN = strTemp;
-
722  }
-
723 
-
724  if (exists(SECTION_OVERLAY))
-
725  {
-
726  auto const sec = section(SECTION_OVERLAY);
-
727 
-
728  using namespace std::chrono;
-
729 
-
730  try
-
731  {
-
732  if (auto val = sec.get("max_unknown_time"))
-
733  MAX_UNKNOWN_TIME =
-
734  seconds{beast::lexicalCastThrow<std::uint32_t>(*val)};
-
735  }
-
736  catch (...)
-
737  {
-
738  Throw<std::runtime_error>(
-
739  "Invalid value 'max_unknown_time' in " SECTION_OVERLAY
-
740  ": must be of the form '<number>' representing seconds.");
-
741  }
-
742 
-
743  if (MAX_UNKNOWN_TIME < seconds{300} || MAX_UNKNOWN_TIME > seconds{1800})
-
744  Throw<std::runtime_error>(
-
745  "Invalid value 'max_unknown_time' in " SECTION_OVERLAY
-
746  ": the time must be between 300 and 1800 seconds, inclusive.");
-
747 
-
748  try
-
749  {
-
750  if (auto val = sec.get("max_diverged_time"))
-
751  MAX_DIVERGED_TIME =
-
752  seconds{beast::lexicalCastThrow<std::uint32_t>(*val)};
-
753  }
-
754  catch (...)
-
755  {
-
756  Throw<std::runtime_error>(
-
757  "Invalid value 'max_diverged_time' in " SECTION_OVERLAY
-
758  ": must be of the form '<number>' representing seconds.");
-
759  }
-
760 
-
761  if (MAX_DIVERGED_TIME < seconds{60} || MAX_DIVERGED_TIME > seconds{900})
-
762  {
-
763  Throw<std::runtime_error>(
-
764  "Invalid value 'max_diverged_time' in " SECTION_OVERLAY
-
765  ": the time must be between 60 and 900 seconds, inclusive.");
-
766  }
-
767  }
-
768 
-
769  if (getSingleSection(
-
770  secConfig, SECTION_AMENDMENT_MAJORITY_TIME, strTemp, j_))
-
771  {
-
772  using namespace std::chrono;
-
773  boost::regex const re(
-
774  "^\\s*(\\d+)\\s*(minutes|hours|days|weeks)\\s*(\\s+.*)?$");
-
775  boost::smatch match;
-
776  if (!boost::regex_match(strTemp, match, re))
-
777  Throw<std::runtime_error>(
-
778  "Invalid " SECTION_AMENDMENT_MAJORITY_TIME
-
779  ", must be: [0-9]+ [minutes|hours|days|weeks]");
-
780 
-
781  std::uint32_t duration =
-
782  beast::lexicalCastThrow<std::uint32_t>(match[1].str());
+
683  if (getSingleSection(secConfig, SECTION_IO_WORKERS, strTemp, j_))
+
684  {
+
685  IO_WORKERS = beast::lexicalCastThrow<int>(strTemp);
+
686 
+
687  if (IO_WORKERS < 1 || IO_WORKERS > 1024)
+
688  Throw<std::runtime_error>(
+
689  "Invalid " SECTION_IO_WORKERS
+
690  ": must be between 1 and 1024 inclusive.");
+
691  }
+
692 
+
693  if (getSingleSection(secConfig, SECTION_PREFETCH_WORKERS, strTemp, j_))
+
694  {
+
695  PREFETCH_WORKERS = beast::lexicalCastThrow<int>(strTemp);
+
696 
+
697  if (PREFETCH_WORKERS < 1 || PREFETCH_WORKERS > 1024)
+
698  Throw<std::runtime_error>(
+
699  "Invalid " SECTION_PREFETCH_WORKERS
+
700  ": must be between 1 and 1024 inclusive.");
+
701  }
+
702 
+
703  if (getSingleSection(secConfig, SECTION_COMPRESSION, strTemp, j_))
+
704  COMPRESSION = beast::lexicalCastThrow<bool>(strTemp);
+
705 
+
706  if (getSingleSection(secConfig, SECTION_LEDGER_REPLAY, strTemp, j_))
+
707  LEDGER_REPLAY = beast::lexicalCastThrow<bool>(strTemp);
+
708 
+
709  if (exists(SECTION_REDUCE_RELAY))
+
710  {
+
711  auto sec = section(SECTION_REDUCE_RELAY);
+
712  VP_REDUCE_RELAY_ENABLE = sec.value_or("vp_enable", false);
+
713  VP_REDUCE_RELAY_SQUELCH = sec.value_or("vp_squelch", false);
+
714  TX_REDUCE_RELAY_ENABLE = sec.value_or("tx_enable", false);
+
715  TX_REDUCE_RELAY_METRICS = sec.value_or("tx_metrics", false);
+
716  TX_REDUCE_RELAY_MIN_PEERS = sec.value_or("tx_min_peers", 20);
+
717  TX_RELAY_PERCENTAGE = sec.value_or("tx_relay_percentage", 25);
+
718  if (TX_RELAY_PERCENTAGE < 10 || TX_RELAY_PERCENTAGE > 100 ||
+
719  TX_REDUCE_RELAY_MIN_PEERS < 10)
+
720  Throw<std::runtime_error>(
+
721  "Invalid " SECTION_REDUCE_RELAY
+
722  ", tx_min_peers must be greater or equal to 10"
+
723  ", tx_relay_percentage must be greater or equal to 10 "
+
724  "and less or equal to 100");
+
725  }
+
726 
+
727  if (getSingleSection(secConfig, SECTION_MAX_TRANSACTIONS, strTemp, j_))
+
728  {
+
729  MAX_TRANSACTIONS = std::clamp(
+
730  beast::lexicalCastThrow<int>(strTemp),
+
731  MIN_JOB_QUEUE_TX,
+
732  MAX_JOB_QUEUE_TX);
+
733  }
+
734 
+
735  if (getSingleSection(secConfig, SECTION_SERVER_DOMAIN, strTemp, j_))
+
736  {
+
737  if (!isProperlyFormedTomlDomain(strTemp))
+
738  {
+
739  Throw<std::runtime_error>(
+
740  "Invalid " SECTION_SERVER_DOMAIN
+
741  ": the domain name does not appear to meet the requirements.");
+
742  }
+
743 
+
744  SERVER_DOMAIN = strTemp;
+
745  }
+
746 
+
747  if (exists(SECTION_OVERLAY))
+
748  {
+
749  auto const sec = section(SECTION_OVERLAY);
+
750 
+
751  using namespace std::chrono;
+
752 
+
753  try
+
754  {
+
755  if (auto val = sec.get("max_unknown_time"))
+
756  MAX_UNKNOWN_TIME =
+
757  seconds{beast::lexicalCastThrow<std::uint32_t>(*val)};
+
758  }
+
759  catch (...)
+
760  {
+
761  Throw<std::runtime_error>(
+
762  "Invalid value 'max_unknown_time' in " SECTION_OVERLAY
+
763  ": must be of the form '<number>' representing seconds.");
+
764  }
+
765 
+
766  if (MAX_UNKNOWN_TIME < seconds{300} || MAX_UNKNOWN_TIME > seconds{1800})
+
767  Throw<std::runtime_error>(
+
768  "Invalid value 'max_unknown_time' in " SECTION_OVERLAY
+
769  ": the time must be between 300 and 1800 seconds, inclusive.");
+
770 
+
771  try
+
772  {
+
773  if (auto val = sec.get("max_diverged_time"))
+
774  MAX_DIVERGED_TIME =
+
775  seconds{beast::lexicalCastThrow<std::uint32_t>(*val)};
+
776  }
+
777  catch (...)
+
778  {
+
779  Throw<std::runtime_error>(
+
780  "Invalid value 'max_diverged_time' in " SECTION_OVERLAY
+
781  ": must be of the form '<number>' representing seconds.");
+
782  }
783 
-
784  if (boost::iequals(match[2], "minutes"))
-
785  AMENDMENT_MAJORITY_TIME = minutes(duration);
-
786  else if (boost::iequals(match[2], "hours"))
-
787  AMENDMENT_MAJORITY_TIME = hours(duration);
-
788  else if (boost::iequals(match[2], "days"))
-
789  AMENDMENT_MAJORITY_TIME = days(duration);
-
790  else if (boost::iequals(match[2], "weeks"))
-
791  AMENDMENT_MAJORITY_TIME = weeks(duration);
-
792 
-
793  if (AMENDMENT_MAJORITY_TIME < minutes(15))
-
794  Throw<std::runtime_error>(
-
795  "Invalid " SECTION_AMENDMENT_MAJORITY_TIME
-
796  ", the minimum amount of time an amendment must hold a "
-
797  "majority is 15 minutes");
-
798  }
-
799 
-
800  if (getSingleSection(secConfig, SECTION_BETA_RPC_API, strTemp, j_))
-
801  BETA_RPC_API = beast::lexicalCastThrow<bool>(strTemp);
-
802 
-
803  // Do not load trusted validator configuration for standalone mode
-
804  if (!RUN_STANDALONE)
-
805  {
-
806  // If a file was explicitly specified, then throw if the
-
807  // path is malformed or if the file does not exist or is
-
808  // not a file.
-
809  // If the specified file is not an absolute path, then look
-
810  // for it in the same directory as the config file.
-
811  // If no path was specified, then look for validators.txt
-
812  // in the same directory as the config file, but don't complain
-
813  // if we can't find it.
-
814  boost::filesystem::path validatorsFile;
+
784  if (MAX_DIVERGED_TIME < seconds{60} || MAX_DIVERGED_TIME > seconds{900})
+
785  {
+
786  Throw<std::runtime_error>(
+
787  "Invalid value 'max_diverged_time' in " SECTION_OVERLAY
+
788  ": the time must be between 60 and 900 seconds, inclusive.");
+
789  }
+
790  }
+
791 
+
792  if (getSingleSection(
+
793  secConfig, SECTION_AMENDMENT_MAJORITY_TIME, strTemp, j_))
+
794  {
+
795  using namespace std::chrono;
+
796  boost::regex const re(
+
797  "^\\s*(\\d+)\\s*(minutes|hours|days|weeks)\\s*(\\s+.*)?$");
+
798  boost::smatch match;
+
799  if (!boost::regex_match(strTemp, match, re))
+
800  Throw<std::runtime_error>(
+
801  "Invalid " SECTION_AMENDMENT_MAJORITY_TIME
+
802  ", must be: [0-9]+ [minutes|hours|days|weeks]");
+
803 
+
804  std::uint32_t duration =
+
805  beast::lexicalCastThrow<std::uint32_t>(match[1].str());
+
806 
+
807  if (boost::iequals(match[2], "minutes"))
+
808  AMENDMENT_MAJORITY_TIME = minutes(duration);
+
809  else if (boost::iequals(match[2], "hours"))
+
810  AMENDMENT_MAJORITY_TIME = hours(duration);
+
811  else if (boost::iequals(match[2], "days"))
+
812  AMENDMENT_MAJORITY_TIME = days(duration);
+
813  else if (boost::iequals(match[2], "weeks"))
+
814  AMENDMENT_MAJORITY_TIME = weeks(duration);
815 
-
816  if (getSingleSection(secConfig, SECTION_VALIDATORS_FILE, strTemp, j_))
-
817  {
-
818  validatorsFile = strTemp;
-
819 
-
820  if (validatorsFile.empty())
-
821  Throw<std::runtime_error>(
-
822  "Invalid path specified in [" SECTION_VALIDATORS_FILE "]");
-
823 
-
824  if (!validatorsFile.is_absolute() && !CONFIG_DIR.empty())
-
825  validatorsFile = CONFIG_DIR / validatorsFile;
-
826 
-
827  if (!boost::filesystem::exists(validatorsFile))
-
828  Throw<std::runtime_error>(
-
829  "The file specified in [" SECTION_VALIDATORS_FILE
-
830  "] "
-
831  "does not exist: " +
-
832  validatorsFile.string());
-
833 
-
834  else if (
-
835  !boost::filesystem::is_regular_file(validatorsFile) &&
-
836  !boost::filesystem::is_symlink(validatorsFile))
-
837  Throw<std::runtime_error>(
-
838  "Invalid file specified in [" SECTION_VALIDATORS_FILE
-
839  "]: " +
-
840  validatorsFile.string());
-
841  }
-
842  else if (!CONFIG_DIR.empty())
-
843  {
-
844  validatorsFile = CONFIG_DIR / validatorsFileName;
-
845 
-
846  if (!validatorsFile.empty())
-
847  {
-
848  if (!boost::filesystem::exists(validatorsFile))
-
849  validatorsFile.clear();
-
850  else if (
-
851  !boost::filesystem::is_regular_file(validatorsFile) &&
-
852  !boost::filesystem::is_symlink(validatorsFile))
-
853  validatorsFile.clear();
-
854  }
-
855  }
+
816  if (AMENDMENT_MAJORITY_TIME < minutes(15))
+
817  Throw<std::runtime_error>(
+
818  "Invalid " SECTION_AMENDMENT_MAJORITY_TIME
+
819  ", the minimum amount of time an amendment must hold a "
+
820  "majority is 15 minutes");
+
821  }
+
822 
+
823  if (getSingleSection(secConfig, SECTION_BETA_RPC_API, strTemp, j_))
+
824  BETA_RPC_API = beast::lexicalCastThrow<bool>(strTemp);
+
825 
+
826  // Do not load trusted validator configuration for standalone mode
+
827  if (!RUN_STANDALONE)
+
828  {
+
829  // If a file was explicitly specified, then throw if the
+
830  // path is malformed or if the file does not exist or is
+
831  // not a file.
+
832  // If the specified file is not an absolute path, then look
+
833  // for it in the same directory as the config file.
+
834  // If no path was specified, then look for validators.txt
+
835  // in the same directory as the config file, but don't complain
+
836  // if we can't find it.
+
837  boost::filesystem::path validatorsFile;
+
838 
+
839  if (getSingleSection(secConfig, SECTION_VALIDATORS_FILE, strTemp, j_))
+
840  {
+
841  validatorsFile = strTemp;
+
842 
+
843  if (validatorsFile.empty())
+
844  Throw<std::runtime_error>(
+
845  "Invalid path specified in [" SECTION_VALIDATORS_FILE "]");
+
846 
+
847  if (!validatorsFile.is_absolute() && !CONFIG_DIR.empty())
+
848  validatorsFile = CONFIG_DIR / validatorsFile;
+
849 
+
850  if (!boost::filesystem::exists(validatorsFile))
+
851  Throw<std::runtime_error>(
+
852  "The file specified in [" SECTION_VALIDATORS_FILE
+
853  "] "
+
854  "does not exist: " +
+
855  validatorsFile.string());
856 
-
857  if (!validatorsFile.empty() &&
-
858  boost::filesystem::exists(validatorsFile) &&
-
859  (boost::filesystem::is_regular_file(validatorsFile) ||
-
860  boost::filesystem::is_symlink(validatorsFile)))
-
861  {
-
862  boost::system::error_code ec;
-
863  auto const data = getFileContents(ec, validatorsFile);
-
864  if (ec)
-
865  {
-
866  Throw<std::runtime_error>(
-
867  "Failed to read '" + validatorsFile.string() + "'." +
-
868  std::to_string(ec.value()) + ": " + ec.message());
-
869  }
-
870 
-
871  auto iniFile = parseIniFile(data, true);
-
872 
-
873  auto entries = getIniFileSection(iniFile, SECTION_VALIDATORS);
-
874 
-
875  if (entries)
-
876  section(SECTION_VALIDATORS).append(*entries);
-
877 
-
878  auto valKeyEntries =
-
879  getIniFileSection(iniFile, SECTION_VALIDATOR_KEYS);
-
880 
-
881  if (valKeyEntries)
-
882  section(SECTION_VALIDATOR_KEYS).append(*valKeyEntries);
-
883 
-
884  auto valSiteEntries =
-
885  getIniFileSection(iniFile, SECTION_VALIDATOR_LIST_SITES);
-
886 
-
887  if (valSiteEntries)
-
888  section(SECTION_VALIDATOR_LIST_SITES).append(*valSiteEntries);
-
889 
-
890  auto valListKeys =
-
891  getIniFileSection(iniFile, SECTION_VALIDATOR_LIST_KEYS);
-
892 
-
893  if (valListKeys)
-
894  section(SECTION_VALIDATOR_LIST_KEYS).append(*valListKeys);
+
857  else if (
+
858  !boost::filesystem::is_regular_file(validatorsFile) &&
+
859  !boost::filesystem::is_symlink(validatorsFile))
+
860  Throw<std::runtime_error>(
+
861  "Invalid file specified in [" SECTION_VALIDATORS_FILE
+
862  "]: " +
+
863  validatorsFile.string());
+
864  }
+
865  else if (!CONFIG_DIR.empty())
+
866  {
+
867  validatorsFile = CONFIG_DIR / validatorsFileName;
+
868 
+
869  if (!validatorsFile.empty())
+
870  {
+
871  if (!boost::filesystem::exists(validatorsFile))
+
872  validatorsFile.clear();
+
873  else if (
+
874  !boost::filesystem::is_regular_file(validatorsFile) &&
+
875  !boost::filesystem::is_symlink(validatorsFile))
+
876  validatorsFile.clear();
+
877  }
+
878  }
+
879 
+
880  if (!validatorsFile.empty() &&
+
881  boost::filesystem::exists(validatorsFile) &&
+
882  (boost::filesystem::is_regular_file(validatorsFile) ||
+
883  boost::filesystem::is_symlink(validatorsFile)))
+
884  {
+
885  boost::system::error_code ec;
+
886  auto const data = getFileContents(ec, validatorsFile);
+
887  if (ec)
+
888  {
+
889  Throw<std::runtime_error>(
+
890  "Failed to read '" + validatorsFile.string() + "'." +
+
891  std::to_string(ec.value()) + ": " + ec.message());
+
892  }
+
893 
+
894  auto iniFile = parseIniFile(data, true);
895 
-
896  if (!entries && !valKeyEntries && !valListKeys)
-
897  Throw<std::runtime_error>(
-
898  "The file specified in [" SECTION_VALIDATORS_FILE
-
899  "] "
-
900  "does not contain a [" SECTION_VALIDATORS
-
901  "], "
-
902  "[" SECTION_VALIDATOR_KEYS
-
903  "] or "
-
904  "[" SECTION_VALIDATOR_LIST_KEYS
-
905  "]"
-
906  " section: " +
-
907  validatorsFile.string());
-
908  }
+
896  auto entries = getIniFileSection(iniFile, SECTION_VALIDATORS);
+
897 
+
898  if (entries)
+
899  section(SECTION_VALIDATORS).append(*entries);
+
900 
+
901  auto valKeyEntries =
+
902  getIniFileSection(iniFile, SECTION_VALIDATOR_KEYS);
+
903 
+
904  if (valKeyEntries)
+
905  section(SECTION_VALIDATOR_KEYS).append(*valKeyEntries);
+
906 
+
907  auto valSiteEntries =
+
908  getIniFileSection(iniFile, SECTION_VALIDATOR_LIST_SITES);
909 
-
910  // Consolidate [validator_keys] and [validators]
-
911  section(SECTION_VALIDATORS)
-
912  .append(section(SECTION_VALIDATOR_KEYS).lines());
-
913 
-
914  if (!section(SECTION_VALIDATOR_LIST_SITES).lines().empty() &&
-
915  section(SECTION_VALIDATOR_LIST_KEYS).lines().empty())
-
916  {
-
917  Throw<std::runtime_error>(
-
918  "[" + std::string(SECTION_VALIDATOR_LIST_KEYS) +
-
919  "] config section is missing");
-
920  }
-
921  }
-
922 
-
923  {
-
924  auto const part = section("features");
-
925  for (auto const& s : part.values())
-
926  {
-
927  if (auto const f = getRegisteredFeature(s))
-
928  features.insert(*f);
-
929  else
-
930  Throw<std::runtime_error>(
-
931  "Unknown feature: " + s + " in config file.");
-
932  }
-
933  }
-
934 
-
935  // This doesn't properly belong here, but check to make sure that the
-
936  // value specified for network_quorum is achievable:
-
937  {
-
938  auto pm = PEERS_MAX;
-
939 
-
940  // FIXME this apparently magic value is actually defined as a constant
-
941  // elsewhere (see defaultMaxPeers) but we handle this check here.
-
942  if (pm == 0)
-
943  pm = 21;
-
944 
-
945  if (NETWORK_QUORUM > pm)
-
946  {
-
947  Throw<std::runtime_error>(
-
948  "The minimum number of required peers (network_quorum) exceeds "
-
949  "the maximum number of allowed peers (peers_max)");
-
950  }
-
951  }
-
952 }
-
953 
-
954 boost::filesystem::path
-
955 Config::getDebugLogFile() const
-
956 {
-
957  auto log_file = DEBUG_LOGFILE;
-
958 
-
959  if (!log_file.empty() && !log_file.is_absolute())
+
910  if (valSiteEntries)
+
911  section(SECTION_VALIDATOR_LIST_SITES).append(*valSiteEntries);
+
912 
+
913  auto valListKeys =
+
914  getIniFileSection(iniFile, SECTION_VALIDATOR_LIST_KEYS);
+
915 
+
916  if (valListKeys)
+
917  section(SECTION_VALIDATOR_LIST_KEYS).append(*valListKeys);
+
918 
+
919  if (!entries && !valKeyEntries && !valListKeys)
+
920  Throw<std::runtime_error>(
+
921  "The file specified in [" SECTION_VALIDATORS_FILE
+
922  "] "
+
923  "does not contain a [" SECTION_VALIDATORS
+
924  "], "
+
925  "[" SECTION_VALIDATOR_KEYS
+
926  "] or "
+
927  "[" SECTION_VALIDATOR_LIST_KEYS
+
928  "]"
+
929  " section: " +
+
930  validatorsFile.string());
+
931  }
+
932 
+
933  // Consolidate [validator_keys] and [validators]
+
934  section(SECTION_VALIDATORS)
+
935  .append(section(SECTION_VALIDATOR_KEYS).lines());
+
936 
+
937  if (!section(SECTION_VALIDATOR_LIST_SITES).lines().empty() &&
+
938  section(SECTION_VALIDATOR_LIST_KEYS).lines().empty())
+
939  {
+
940  Throw<std::runtime_error>(
+
941  "[" + std::string(SECTION_VALIDATOR_LIST_KEYS) +
+
942  "] config section is missing");
+
943  }
+
944  }
+
945 
+
946  {
+
947  auto const part = section("features");
+
948  for (auto const& s : part.values())
+
949  {
+
950  if (auto const f = getRegisteredFeature(s))
+
951  features.insert(*f);
+
952  else
+
953  Throw<std::runtime_error>(
+
954  "Unknown feature: " + s + " in config file.");
+
955  }
+
956  }
+
957 
+
958  // This doesn't properly belong here, but check to make sure that the
+
959  // value specified for network_quorum is achievable:
960  {
-
961  // Unless an absolute path for the log file is specified, the
-
962  // path is relative to the config file directory.
-
963  log_file = boost::filesystem::absolute(log_file, CONFIG_DIR);
-
964  }
-
965 
-
966  if (!log_file.empty())
-
967  {
-
968  auto log_dir = log_file.parent_path();
-
969 
-
970  if (!boost::filesystem::is_directory(log_dir))
-
971  {
-
972  boost::system::error_code ec;
-
973  boost::filesystem::create_directories(log_dir, ec);
-
974 
-
975  // If we fail, we warn but continue so that the calling code can
-
976  // decide how to handle this situation.
-
977  if (ec)
-
978  {
-
979  std::cerr << "Unable to create log file path " << log_dir
-
980  << ": " << ec.message() << '\n';
-
981  }
-
982  }
-
983  }
-
984 
-
985  return log_file;
-
986 }
-
987 
-
988 int
-
989 Config::getValueFor(SizedItem item, std::optional<std::size_t> node) const
-
990 {
-
991  auto const index = static_cast<std::underlying_type_t<SizedItem>>(item);
-
992  assert(index < sizedItems.size());
-
993  assert(!node || *node <= 4);
-
994  return sizedItems.at(index).second.at(node.value_or(NODE_SIZE));
-
995 }
-
996 
-
997 } // namespace ripple
+
961  auto pm = PEERS_MAX;
+
962 
+
963  // FIXME this apparently magic value is actually defined as a constant
+
964  // elsewhere (see defaultMaxPeers) but we handle this check here.
+
965  if (pm == 0)
+
966  pm = 21;
+
967 
+
968  if (NETWORK_QUORUM > pm)
+
969  {
+
970  Throw<std::runtime_error>(
+
971  "The minimum number of required peers (network_quorum) exceeds "
+
972  "the maximum number of allowed peers (peers_max)");
+
973  }
+
974  }
+
975 }
+
976 
+
977 boost::filesystem::path
+
978 Config::getDebugLogFile() const
+
979 {
+
980  auto log_file = DEBUG_LOGFILE;
+
981 
+
982  if (!log_file.empty() && !log_file.is_absolute())
+
983  {
+
984  // Unless an absolute path for the log file is specified, the
+
985  // path is relative to the config file directory.
+
986  log_file = boost::filesystem::absolute(log_file, CONFIG_DIR);
+
987  }
+
988 
+
989  if (!log_file.empty())
+
990  {
+
991  auto log_dir = log_file.parent_path();
+
992 
+
993  if (!boost::filesystem::is_directory(log_dir))
+
994  {
+
995  boost::system::error_code ec;
+
996  boost::filesystem::create_directories(log_dir, ec);
+
997 
+
998  // If we fail, we warn but continue so that the calling code can
+
999  // decide how to handle this situation.
+
1000  if (ec)
+
1001  {
+
1002  std::cerr << "Unable to create log file path " << log_dir
+
1003  << ": " << ec.message() << '\n';
+
1004  }
+
1005  }
+
1006  }
+
1007 
+
1008  return log_file;
+
1009 }
+
1010 
+
1011 int
+
1012 Config::getValueFor(SizedItem item, std::optional<std::size_t> node) const
+
1013 {
+
1014  auto const index = static_cast<std::underlying_type_t<SizedItem>>(item);
+
1015  assert(index < sizedItems.size());
+
1016  assert(!node || *node <= 4);
+
1017  return sizedItems.at(index).second.at(node.value_or(NODE_SIZE));
+
1018 }
+
1019 
+
1020 } // namespace ripple
@ openFinalLimit
Holds a collection of configuration values.
Definition: BasicConfig.h:42
std::optional< int > SWEEP_INTERVAL
Definition: Config.h:229
std::string getFileContents(boost::system::error_code &ec, boost::filesystem::path const &sourcePath, std::optional< std::size_t > maxSize=std::nullopt)
+
STL class.
SizedItem
Definition: Config.h:48
int PATH_SEARCH
Definition: Config.h:180
@@ -1089,7 +1113,7 @@ $(function() {
bool PEER_PRIVATE
Definition: Config.h:157
boost::filesystem::path DEBUG_LOGFILE
Definition: Config.h:88
T emplace(T... args)
-
void setupControl(bool bQuiet, bool bSilent, bool bStandalone)
Definition: Config.cpp:272
+
void setupControl(bool bQuiet, bool bSilent, bool bStandalone)
Definition: Config.cpp:273
@ treeCacheAge
Stream warn() const
Definition: Journal.h:327
T distance(T... args)
@@ -1109,12 +1133,12 @@ $(function() {
bool RUN_STANDALONE
Operate in stand-alone mode.
Definition: Config.h:105
@ ramSizeGB
-
void load()
Definition: Config.cpp:434
+
void load()
Definition: Config.cpp:435
const beast::Journal j_
Definition: Config.h:92
int RELAY_UNTRUSTED_PROPOSALS
Definition: Config.h:154
std::string SSL_VERIFY_FILE
Definition: Config.h:202
-
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition: Config.cpp:456
-
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:989
+
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition: Config.cpp:457
+
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:1012
std::chrono::duration< int, std::ratio_multiply< days::period, std::ratio< 7 > >> weeks
Definition: chrono.h:41
bool FAST_LOAD
Definition: Config.h:277
@@ -1142,13 +1166,14 @@ $(function() {
std::size_t PEERS_IN_MAX
Definition: Config.h:165
static char const *const databaseDirName
Definition: Config.h:74
STL class.
+
@ txnDBCache
int PREFETCH_WORKERS
Definition: Config.h:222
int PATH_SEARCH_OLD
Definition: Config.h:179
std::uint32_t LEDGER_HISTORY
Definition: Config.h:193
-
IniFileSections parseIniFile(std::string const &strInput, const bool bTrim)
Definition: Config.cpp:160
+
IniFileSections parseIniFile(std::string const &strInput, const bool bTrim)
Definition: Config.cpp:161
std::size_t NETWORK_QUORUM
Definition: Config.h:148
-
constexpr std::array< std::pair< SizedItem, std::array< int, 5 > >, 13 > sizedItems
Definition: Config.cpp:113
+
constexpr std::array< std::pair< SizedItem, std::array< int, 5 > >, 13 > sizedItems
Definition: Config.cpp:114
bool VP_REDUCE_RELAY_ENABLE
Definition: Config.h:234
boost::filesystem::path CONFIG_DIR
Definition: Config.h:85
T substr(T... args)
@@ -1157,12 +1182,12 @@ $(function() {
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::unordered_set< uint256, beast::uhash<> > features
Definition: Config.h:263
int PATH_SEARCH_FAST
Definition: Config.h:181
-
bool getSingleSection(IniFileSections &secSource, std::string const &strSection, std::string &strValue, beast::Journal j)
Definition: Config.cpp:221
-
void setup(std::string const &strConf, bool bQuiet, bool bSilent, bool bStandalone)
Definition: Config.cpp:314
+
bool getSingleSection(IniFileSections &secSource, std::string const &strSection, std::string &strValue, beast::Journal j)
Definition: Config.cpp:222
+
void setup(std::string const &strConf, bool bQuiet, bool bSilent, bool bStandalone)
Definition: Config.cpp:315
T endl(T... args)
T clamp(T... args)
-
static std::string getEnvVar(char const *name)
Definition: Config.cpp:256
+
static std::string getEnvVar(char const *name)
Definition: Config.cpp:257
@ treeCacheSize
std::size_t TX_REDUCE_RELAY_MIN_PEERS
Definition: Config.h:255
std::string SERVER_DOMAIN
Definition: Config.h:265
@@ -1170,6 +1195,7 @@ $(function() {
int RELAY_UNTRUSTED_VALIDATIONS
Definition: Config.h:153
@ sweepInterval
bool COMPRESSION
Definition: Config.h:206
+
T count(T... args)
T empty(T... args)
static std::string const & systemName()
@ ledgerSize
@@ -1185,13 +1211,14 @@ $(function() {
bool TX_REDUCE_RELAY_ENABLE
Definition: Config.h:245
std::optional< uint256 > getRegisteredFeature(std::string const &name)
Definition: Feature.cpp:341
bool SILENT
Definition: Config.h:95
-
boost::filesystem::path getDebugLogFile() const
Returns the full path and filename of the debug log file.
Definition: Config.cpp:955
+
boost::filesystem::path getDebugLogFile() const
Returns the full path and filename of the debug log file.
Definition: Config.cpp:978
bool signingEnabled_
Determines if the server will sign a tx, given an account's secret seed.
Definition: Config.h:119
+
T regex_replace(T... args)
bool ELB_SUPPORT
Definition: Config.h:127
static void initializeSSLContext(Config const &config, beast::Journal j)
Definition: HTTPClient.cpp:38
static std::string nodeDatabase()
-
IniFileSections::mapped_type * getIniFileSection(IniFileSections &secSource, std::string const &strSection)
Definition: Config.cpp:208
+
IniFileSections::mapped_type * getIniFileSection(IniFileSections &secSource, std::string const &strSection)
Definition: Config.cpp:209
bool exists(std::string const &name) const
Returns true if a section with the given name exists.
@ ledgerAge
std::chrono::seconds MAX_UNKNOWN_TIME
Definition: Config.h:268
diff --git a/Config_8h_source.html b/Config_8h_source.html index 2792cb0a79..896ed3aea7 100644 --- a/Config_8h_source.html +++ b/Config_8h_source.html @@ -412,7 +412,7 @@ $(function() {
std::optional< std::size_t > VALIDATION_QUORUM
Definition: Config.h:186
bool LEDGER_REPLAY
Definition: Config.h:209
-
Config()
Definition: Config.cpp:266
+
Config()
Definition: Config.cpp:267
@ accountIdCacheSize
static char const *const validatorsFileName
Definition: Config.h:75
@@ -423,7 +423,7 @@ $(function() {
bool PEER_PRIVATE
Definition: Config.h:157
boost::filesystem::path DEBUG_LOGFILE
Definition: Config.h:88
bool silent() const
Definition: Config.h:308
-
void setupControl(bool bQuiet, bool bSilent, bool bStandalone)
Definition: Config.cpp:272
+
void setupControl(bool bQuiet, bool bSilent, bool bStandalone)
Definition: Config.cpp:273
@ treeCacheAge
@ LOAD
Definition: Config.h:133
const std::uint64_t ramSize_
Definition: Config.h:122
@@ -440,13 +440,13 @@ $(function() {
int IO_WORKERS
Definition: Config.h:221
bool RUN_STANDALONE
Operate in stand-alone mode.
Definition: Config.h:105
@ ramSizeGB
-
void load()
Definition: Config.cpp:434
+
void load()
Definition: Config.cpp:435
const beast::Journal j_
Definition: Config.h:92
int RELAY_UNTRUSTED_PROPOSALS
Definition: Config.h:154
bool reporting() const
Definition: Config.h:318
std::string SSL_VERIFY_FILE
Definition: Config.h:202
-
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition: Config.cpp:456
-
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:989
+
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition: Config.cpp:457
+
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:1012
bool FORCE_MULTI_THREAD
Definition: Config.h:225
bool FAST_LOAD
Definition: Config.h:277
Definition: Config.h:69
@@ -493,7 +493,7 @@ $(function() {
@ FRESH
Definition: Config.h:133
std::unordered_set< uint256, beast::uhash<> > features
Definition: Config.h:263
int PATH_SEARCH_FAST
Definition: Config.h:181
-
void setup(std::string const &strConf, bool bQuiet, bool bSilent, bool bStandalone)
Definition: Config.cpp:314
+
void setup(std::string const &strConf, bool bQuiet, bool bSilent, bool bStandalone)
Definition: Config.cpp:315
@ treeCacheSize
std::size_t TX_REDUCE_RELAY_MIN_PEERS
Definition: Config.h:255
std::string SERVER_DOMAIN
Definition: Config.h:265
@@ -514,7 +514,7 @@ $(function() {
bool TX_REDUCE_RELAY_ENABLE
Definition: Config.h:245
bool reportingReadOnly() const
Definition: Config.h:330
bool SILENT
Definition: Config.h:95
-
boost::filesystem::path getDebugLogFile() const
Returns the full path and filename of the debug log file.
Definition: Config.cpp:955
+
boost::filesystem::path getDebugLogFile() const
Returns the full path and filename of the debug log file.
Definition: Config.cpp:978
bool signingEnabled_
Determines if the server will sign a tx, given an account's secret seed.
Definition: Config.h:119
@ LOAD_FILE
Definition: Config.h:133
bool ELB_SUPPORT
Definition: Config.h:127
diff --git a/Config__test_8cpp_source.html b/Config__test_8cpp_source.html index 679afdb2a9..29fccef1fd 100644 --- a/Config__test_8cpp_source.html +++ b/Config__test_8cpp_source.html @@ -910,7 +910,7 @@ $(function() {
845  cfg.loadFromString(toLoad);
846  BEAST_EXPECT(
847  cfg.exists("port_rpc") && cfg.section("port_rpc").lines().empty() &&
-
848  cfg.section("port_rpc").values().empty());
+
848  cfg.section("port_rpc").values().empty());
849  BEAST_EXPECT(
850  cfg.exists(SECTION_IPS) &&
851  cfg.section(SECTION_IPS).lines().size() == 1 &&
@@ -922,309 +922,387 @@ $(function() {
857  }
858 
859  void
-
860  testComments()
+
860  testColons()
861  {
-
862  struct TestCommentData
-
863  {
-
864  std::string_view line;
-
865  std::string_view field;
-
866  std::string_view expect;
-
867  bool had_comment;
-
868  };
-
869 
-
870  std::array<TestCommentData, 13> tests = {
-
871  {{"password = aaaa\\#bbbb", "password", "aaaa#bbbb", false},
-
872  {"password = aaaa#bbbb", "password", "aaaa", true},
-
873  {"password = aaaa #bbbb", "password", "aaaa", true},
-
874  // since the value is all comment, this doesn't parse as k=v :
-
875  {"password = #aaaa #bbbb", "", "password =", true},
-
876  {"password = aaaa\\# #bbbb", "password", "aaaa#", true},
-
877  {"password = aaaa\\##bbbb", "password", "aaaa#", true},
-
878  {"aaaa#bbbb", "", "aaaa", true},
-
879  {"aaaa\\#bbbb", "", "aaaa#bbbb", false},
-
880  {"aaaa\\##bbbb", "", "aaaa#", true},
-
881  {"aaaa #bbbb", "", "aaaa", true},
-
882  {"1 #comment", "", "1", true},
-
883  {"#whole thing is comment", "", "", false},
-
884  {" #whole comment with space", "", "", false}}};
-
885 
-
886  for (auto const& t : tests)
-
887  {
-
888  Section s;
-
889  s.append(t.line.data());
-
890  BEAST_EXPECT(s.had_trailing_comments() == t.had_comment);
-
891  if (t.field.empty())
-
892  {
-
893  BEAST_EXPECTS(s.legacy() == t.expect, s.legacy());
-
894  }
-
895  else
-
896  {
-
897  std::string field;
-
898  BEAST_EXPECTS(set(field, t.field.data(), s), t.line);
-
899  BEAST_EXPECTS(field == t.expect, t.line);
-
900  }
-
901  }
-
902 
-
903  {
-
904  Section s;
-
905  s.append("online_delete = 3000");
-
906  std::uint32_t od = 0;
-
907  BEAST_EXPECT(set(od, "online_delete", s));
-
908  BEAST_EXPECTS(od == 3000, *(s.get<std::string>("online_delete")));
-
909  }
-
910 
-
911  {
-
912  Section s;
-
913  s.append("online_delete = 2000 #my comment on this");
-
914  std::uint32_t od = 0;
-
915  BEAST_EXPECT(set(od, "online_delete", s));
-
916  BEAST_EXPECTS(od == 2000, *(s.get<std::string>("online_delete")));
-
917  }
-
918  }
-
919 
-
920  void
-
921  testGetters()
-
922  {
-
923  using namespace std::string_literals;
-
924  Section s{"MySection"};
-
925  s.append("a_string = mystring");
-
926  s.append("positive_int = 2");
-
927  s.append("negative_int = -3");
-
928  s.append("bool_ish = 1");
-
929 
-
930  {
-
931  auto val_1 = "value 1"s;
-
932  BEAST_EXPECT(set(val_1, "a_string", s));
-
933  BEAST_EXPECT(val_1 == "mystring");
-
934 
-
935  auto val_2 = "value 2"s;
-
936  BEAST_EXPECT(!set(val_2, "not_a_key", s));
-
937  BEAST_EXPECT(val_2 == "value 2");
-
938  BEAST_EXPECT(!set(val_2, "default"s, "not_a_key", s));
-
939  BEAST_EXPECT(val_2 == "default");
-
940 
-
941  auto val_3 = get<std::string>(s, "a_string");
-
942  BEAST_EXPECT(val_3 == "mystring");
-
943  auto val_4 = get<std::string>(s, "not_a_key");
-
944  BEAST_EXPECT(val_4 == "");
-
945  auto val_5 = get<std::string>(s, "not_a_key", "default");
-
946  BEAST_EXPECT(val_5 == "default");
+
862  Config cfg;
+
863  /* NOTE: this string includes some explicit
+
864  * space chars in order to verify proper trimming */
+
865  std::string toLoad(R"(
+
866 [port_rpc])"
+
867  "\x20"
+
868  R"(
+
869 # comment
+
870  # indented comment
+
871 )"
+
872  "\x20\x20"
+
873  R"(
+
874 [ips])"
+
875  "\x20"
+
876  R"(
+
877 r.ripple.com:51235
+
878 
+
879  [ips_fixed])"
+
880  "\x20\x20"
+
881  R"(
+
882  # COMMENT
+
883  s1.ripple.com:51235
+
884  s2.ripple.com 51235
+
885  anotherserversansport
+
886  anotherserverwithport:12
+
887  1.1.1.1:1
+
888  1.1.1.1 1
+
889  12.34.12.123:12345
+
890  12.34.12.123 12345
+
891  ::
+
892  2001:db8::
+
893  ::1
+
894  ::1:12345
+
895  [::1]:12345
+
896  2001:db8:3333:4444:5555:6666:7777:8888:12345
+
897  [2001:db8:3333:4444:5555:6666:7777:8888]:1
+
898 
+
899 
+
900 )");
+
901  cfg.loadFromString(toLoad);
+
902  BEAST_EXPECT(
+
903  cfg.exists("port_rpc") && cfg.section("port_rpc").lines().empty() &&
+
904  cfg.section("port_rpc").values().empty());
+
905  BEAST_EXPECT(
+
906  cfg.exists(SECTION_IPS) &&
+
907  cfg.section(SECTION_IPS).lines().size() == 1 &&
+
908  cfg.section(SECTION_IPS).values().size() == 1);
+
909  BEAST_EXPECT(
+
910  cfg.exists(SECTION_IPS_FIXED) &&
+
911  cfg.section(SECTION_IPS_FIXED).lines().size() == 15 &&
+
912  cfg.section(SECTION_IPS_FIXED).values().size() == 15);
+
913  BEAST_EXPECT(cfg.IPS[0] == "r.ripple.com 51235");
+
914 
+
915  BEAST_EXPECT(cfg.IPS_FIXED[0] == "s1.ripple.com 51235");
+
916  BEAST_EXPECT(cfg.IPS_FIXED[1] == "s2.ripple.com 51235");
+
917  BEAST_EXPECT(cfg.IPS_FIXED[2] == "anotherserversansport");
+
918  BEAST_EXPECT(cfg.IPS_FIXED[3] == "anotherserverwithport 12");
+
919  BEAST_EXPECT(cfg.IPS_FIXED[4] == "1.1.1.1 1");
+
920  BEAST_EXPECT(cfg.IPS_FIXED[5] == "1.1.1.1 1");
+
921  BEAST_EXPECT(cfg.IPS_FIXED[6] == "12.34.12.123 12345");
+
922  BEAST_EXPECT(cfg.IPS_FIXED[7] == "12.34.12.123 12345");
+
923 
+
924  // all ipv6 should be ignored by colon replacer, howsoever formated
+
925  BEAST_EXPECT(cfg.IPS_FIXED[8] == "::");
+
926  BEAST_EXPECT(cfg.IPS_FIXED[9] == "2001:db8::");
+
927  BEAST_EXPECT(cfg.IPS_FIXED[10] == "::1");
+
928  BEAST_EXPECT(cfg.IPS_FIXED[11] == "::1:12345");
+
929  BEAST_EXPECT(cfg.IPS_FIXED[12] == "[::1]:12345");
+
930  BEAST_EXPECT(
+
931  cfg.IPS_FIXED[13] ==
+
932  "2001:db8:3333:4444:5555:6666:7777:8888:12345");
+
933  BEAST_EXPECT(
+
934  cfg.IPS_FIXED[14] == "[2001:db8:3333:4444:5555:6666:7777:8888]:1");
+
935  }
+
936 
+
937  void
+
938  testComments()
+
939  {
+
940  struct TestCommentData
+
941  {
+
942  std::string_view line;
+
943  std::string_view field;
+
944  std::string_view expect;
+
945  bool had_comment;
+
946  };
947 
-
948  auto val_6 = "value 6"s;
-
949  BEAST_EXPECT(get_if_exists(s, "a_string", val_6));
-
950  BEAST_EXPECT(val_6 == "mystring");
-
951 
-
952  auto val_7 = "value 7"s;
-
953  BEAST_EXPECT(!get_if_exists(s, "not_a_key", val_7));
-
954  BEAST_EXPECT(val_7 == "value 7");
-
955  }
-
956 
-
957  {
-
958  int val_1 = 1;
-
959  BEAST_EXPECT(set(val_1, "positive_int", s));
-
960  BEAST_EXPECT(val_1 == 2);
-
961 
-
962  int val_2 = 2;
-
963  BEAST_EXPECT(set(val_2, "negative_int", s));
-
964  BEAST_EXPECT(val_2 == -3);
-
965 
-
966  int val_3 = 3;
-
967  BEAST_EXPECT(!set(val_3, "a_string", s));
-
968  BEAST_EXPECT(val_3 == 3);
-
969 
-
970  auto val_4 = get<int>(s, "positive_int");
-
971  BEAST_EXPECT(val_4 == 2);
-
972  auto val_5 = get<int>(s, "not_a_key");
-
973  BEAST_EXPECT(val_5 == 0);
-
974  auto val_6 = get<int>(s, "not_a_key", 5);
-
975  BEAST_EXPECT(val_6 == 5);
-
976  auto val_7 = get<int>(s, "a_string", 6);
-
977  BEAST_EXPECT(val_7 == 6);
-
978 
-
979  int val_8 = 8;
-
980  BEAST_EXPECT(get_if_exists(s, "positive_int", val_8));
-
981  BEAST_EXPECT(val_8 == 2);
-
982 
-
983  auto val_9 = 9;
-
984  BEAST_EXPECT(!get_if_exists(s, "not_a_key", val_9));
-
985  BEAST_EXPECT(val_9 == 9);
-
986 
-
987  auto val_10 = 10;
-
988  BEAST_EXPECT(!get_if_exists(s, "a_string", val_10));
-
989  BEAST_EXPECT(val_10 == 10);
-
990 
-
991  BEAST_EXPECT(s.get<int>("not_a_key") == std::nullopt);
-
992  try
-
993  {
-
994  s.get<int>("a_string");
-
995  fail();
-
996  }
-
997  catch (boost::bad_lexical_cast&)
-
998  {
-
999  pass();
-
1000  }
-
1001  }
-
1002 
-
1003  {
-
1004  bool flag_1 = false;
-
1005  BEAST_EXPECT(get_if_exists(s, "bool_ish", flag_1));
-
1006  BEAST_EXPECT(flag_1 == true);
+
948  std::array<TestCommentData, 13> tests = {
+
949  {{"password = aaaa\\#bbbb", "password", "aaaa#bbbb", false},
+
950  {"password = aaaa#bbbb", "password", "aaaa", true},
+
951  {"password = aaaa #bbbb", "password", "aaaa", true},
+
952  // since the value is all comment, this doesn't parse as k=v :
+
953  {"password = #aaaa #bbbb", "", "password =", true},
+
954  {"password = aaaa\\# #bbbb", "password", "aaaa#", true},
+
955  {"password = aaaa\\##bbbb", "password", "aaaa#", true},
+
956  {"aaaa#bbbb", "", "aaaa", true},
+
957  {"aaaa\\#bbbb", "", "aaaa#bbbb", false},
+
958  {"aaaa\\##bbbb", "", "aaaa#", true},
+
959  {"aaaa #bbbb", "", "aaaa", true},
+
960  {"1 #comment", "", "1", true},
+
961  {"#whole thing is comment", "", "", false},
+
962  {" #whole comment with space", "", "", false}}};
+
963 
+
964  for (auto const& t : tests)
+
965  {
+
966  Section s;
+
967  s.append(t.line.data());
+
968  BEAST_EXPECT(s.had_trailing_comments() == t.had_comment);
+
969  if (t.field.empty())
+
970  {
+
971  BEAST_EXPECTS(s.legacy() == t.expect, s.legacy());
+
972  }
+
973  else
+
974  {
+
975  std::string field;
+
976  BEAST_EXPECTS(set(field, t.field.data(), s), t.line);
+
977  BEAST_EXPECTS(field == t.expect, t.line);
+
978  }
+
979  }
+
980 
+
981  {
+
982  Section s;
+
983  s.append("online_delete = 3000");
+
984  std::uint32_t od = 0;
+
985  BEAST_EXPECT(set(od, "online_delete", s));
+
986  BEAST_EXPECTS(od == 3000, *(s.get<std::string>("online_delete")));
+
987  }
+
988 
+
989  {
+
990  Section s;
+
991  s.append("online_delete = 2000 #my comment on this");
+
992  std::uint32_t od = 0;
+
993  BEAST_EXPECT(set(od, "online_delete", s));
+
994  BEAST_EXPECTS(od == 2000, *(s.get<std::string>("online_delete")));
+
995  }
+
996  }
+
997 
+
998  void
+
999  testGetters()
+
1000  {
+
1001  using namespace std::string_literals;
+
1002  Section s{"MySection"};
+
1003  s.append("a_string = mystring");
+
1004  s.append("positive_int = 2");
+
1005  s.append("negative_int = -3");
+
1006  s.append("bool_ish = 1");
1007 
-
1008  bool flag_2 = false;
-
1009  BEAST_EXPECT(!get_if_exists(s, "not_a_key", flag_2));
-
1010  BEAST_EXPECT(flag_2 == false);
-
1011  }
-
1012  }
-
1013 
-
1014  void
-
1015  testAmendment()
-
1016  {
-
1017  testcase("amendment");
-
1018  struct ConfigUnit
-
1019  {
-
1020  std::string unit;
-
1021  std::uint32_t numSeconds;
-
1022  std::uint32_t configVal;
-
1023  bool shouldPass;
-
1024  };
+
1008  {
+
1009  auto val_1 = "value 1"s;
+
1010  BEAST_EXPECT(set(val_1, "a_string", s));
+
1011  BEAST_EXPECT(val_1 == "mystring");
+
1012 
+
1013  auto val_2 = "value 2"s;
+
1014  BEAST_EXPECT(!set(val_2, "not_a_key", s));
+
1015  BEAST_EXPECT(val_2 == "value 2");
+
1016  BEAST_EXPECT(!set(val_2, "default"s, "not_a_key", s));
+
1017  BEAST_EXPECT(val_2 == "default");
+
1018 
+
1019  auto val_3 = get<std::string>(s, "a_string");
+
1020  BEAST_EXPECT(val_3 == "mystring");
+
1021  auto val_4 = get<std::string>(s, "not_a_key");
+
1022  BEAST_EXPECT(val_4 == "");
+
1023  auto val_5 = get<std::string>(s, "not_a_key", "default");
+
1024  BEAST_EXPECT(val_5 == "default");
1025 
-
1026  std::vector<ConfigUnit> units = {
-
1027  {"seconds", 1, 15 * 60, false},
-
1028  {"minutes", 60, 14, false},
-
1029  {"minutes", 60, 15, true},
-
1030  {"hours", 3600, 10, true},
-
1031  {"days", 86400, 10, true},
-
1032  {"weeks", 604800, 2, true},
-
1033  {"months", 2592000, 1, false},
-
1034  {"years", 31536000, 1, false}};
-
1035 
-
1036  std::string space = "";
-
1037  for (auto& [unit, sec, val, shouldPass] : units)
-
1038  {
-
1039  Config c;
-
1040  std::string toLoad(R"rippleConfig(
-
1041 [amendment_majority_time]
-
1042 )rippleConfig");
-
1043  toLoad += std::to_string(val) + space + unit;
-
1044  space = space == "" ? " " : "";
-
1045 
-
1046  try
-
1047  {
-
1048  c.loadFromString(toLoad);
-
1049  if (shouldPass)
-
1050  BEAST_EXPECT(
-
1051  c.AMENDMENT_MAJORITY_TIME.count() == val * sec);
-
1052  else
-
1053  fail();
-
1054  }
-
1055  catch (std::runtime_error&)
-
1056  {
-
1057  if (!shouldPass)
-
1058  pass();
-
1059  else
-
1060  fail();
-
1061  }
-
1062  }
-
1063  }
+
1026  auto val_6 = "value 6"s;
+
1027  BEAST_EXPECT(get_if_exists(s, "a_string", val_6));
+
1028  BEAST_EXPECT(val_6 == "mystring");
+
1029 
+
1030  auto val_7 = "value 7"s;
+
1031  BEAST_EXPECT(!get_if_exists(s, "not_a_key", val_7));
+
1032  BEAST_EXPECT(val_7 == "value 7");
+
1033  }
+
1034 
+
1035  {
+
1036  int val_1 = 1;
+
1037  BEAST_EXPECT(set(val_1, "positive_int", s));
+
1038  BEAST_EXPECT(val_1 == 2);
+
1039 
+
1040  int val_2 = 2;
+
1041  BEAST_EXPECT(set(val_2, "negative_int", s));
+
1042  BEAST_EXPECT(val_2 == -3);
+
1043 
+
1044  int val_3 = 3;
+
1045  BEAST_EXPECT(!set(val_3, "a_string", s));
+
1046  BEAST_EXPECT(val_3 == 3);
+
1047 
+
1048  auto val_4 = get<int>(s, "positive_int");
+
1049  BEAST_EXPECT(val_4 == 2);
+
1050  auto val_5 = get<int>(s, "not_a_key");
+
1051  BEAST_EXPECT(val_5 == 0);
+
1052  auto val_6 = get<int>(s, "not_a_key", 5);
+
1053  BEAST_EXPECT(val_6 == 5);
+
1054  auto val_7 = get<int>(s, "a_string", 6);
+
1055  BEAST_EXPECT(val_7 == 6);
+
1056 
+
1057  int val_8 = 8;
+
1058  BEAST_EXPECT(get_if_exists(s, "positive_int", val_8));
+
1059  BEAST_EXPECT(val_8 == 2);
+
1060 
+
1061  auto val_9 = 9;
+
1062  BEAST_EXPECT(!get_if_exists(s, "not_a_key", val_9));
+
1063  BEAST_EXPECT(val_9 == 9);
1064 
-
1065  void
-
1066  testOverlay()
-
1067  {
-
1068  testcase("overlay: unknown time");
-
1069 
-
1070  auto testUnknown =
-
1071  [](std::string value) -> std::optional<std::chrono::seconds> {
-
1072  try
-
1073  {
-
1074  Config c;
-
1075  c.loadFromString("[overlay]\nmax_unknown_time=" + value);
-
1076  return c.MAX_UNKNOWN_TIME;
-
1077  }
-
1078  catch (std::runtime_error&)
-
1079  {
-
1080  return {};
-
1081  }
-
1082  };
-
1083 
-
1084  // Failures
-
1085  BEAST_EXPECT(!testUnknown("none"));
-
1086  BEAST_EXPECT(!testUnknown("0.5"));
-
1087  BEAST_EXPECT(!testUnknown("180 seconds"));
-
1088  BEAST_EXPECT(!testUnknown("9 minutes"));
-
1089 
-
1090  // Below lower bound
-
1091  BEAST_EXPECT(!testUnknown("299"));
-
1092 
-
1093  // In bounds
-
1094  BEAST_EXPECT(testUnknown("300") == std::chrono::seconds{300});
-
1095  BEAST_EXPECT(testUnknown("301") == std::chrono::seconds{301});
-
1096  BEAST_EXPECT(testUnknown("1799") == std::chrono::seconds{1799});
-
1097  BEAST_EXPECT(testUnknown("1800") == std::chrono::seconds{1800});
-
1098 
-
1099  // Above upper bound
-
1100  BEAST_EXPECT(!testUnknown("1801"));
-
1101 
-
1102  testcase("overlay: diverged time");
+
1065  auto val_10 = 10;
+
1066  BEAST_EXPECT(!get_if_exists(s, "a_string", val_10));
+
1067  BEAST_EXPECT(val_10 == 10);
+
1068 
+
1069  BEAST_EXPECT(s.get<int>("not_a_key") == std::nullopt);
+
1070  try
+
1071  {
+
1072  s.get<int>("a_string");
+
1073  fail();
+
1074  }
+
1075  catch (boost::bad_lexical_cast&)
+
1076  {
+
1077  pass();
+
1078  }
+
1079  }
+
1080 
+
1081  {
+
1082  bool flag_1 = false;
+
1083  BEAST_EXPECT(get_if_exists(s, "bool_ish", flag_1));
+
1084  BEAST_EXPECT(flag_1 == true);
+
1085 
+
1086  bool flag_2 = false;
+
1087  BEAST_EXPECT(!get_if_exists(s, "not_a_key", flag_2));
+
1088  BEAST_EXPECT(flag_2 == false);
+
1089  }
+
1090  }
+
1091 
+
1092  void
+
1093  testAmendment()
+
1094  {
+
1095  testcase("amendment");
+
1096  struct ConfigUnit
+
1097  {
+
1098  std::string unit;
+
1099  std::uint32_t numSeconds;
+
1100  std::uint32_t configVal;
+
1101  bool shouldPass;
+
1102  };
1103 
-
1104  // In bounds:
-
1105  auto testDiverged =
-
1106  [](std::string value) -> std::optional<std::chrono::seconds> {
-
1107  try
-
1108  {
-
1109  Config c;
-
1110  c.loadFromString("[overlay]\nmax_diverged_time=" + value);
-
1111  return c.MAX_DIVERGED_TIME;
-
1112  }
-
1113  catch (std::runtime_error&)
-
1114  {
-
1115  return {};
-
1116  }
-
1117  };
-
1118 
-
1119  // Failures
-
1120  BEAST_EXPECT(!testDiverged("none"));
-
1121  BEAST_EXPECT(!testDiverged("0.5"));
-
1122  BEAST_EXPECT(!testDiverged("180 seconds"));
-
1123  BEAST_EXPECT(!testDiverged("9 minutes"));
-
1124 
-
1125  // Below lower bound
-
1126  BEAST_EXPECT(!testDiverged("0"));
-
1127  BEAST_EXPECT(!testDiverged("59"));
-
1128 
-
1129  // In bounds
-
1130  BEAST_EXPECT(testDiverged("60") == std::chrono::seconds{60});
-
1131  BEAST_EXPECT(testDiverged("61") == std::chrono::seconds{61});
-
1132  BEAST_EXPECT(testDiverged("899") == std::chrono::seconds{899});
-
1133  BEAST_EXPECT(testDiverged("900") == std::chrono::seconds{900});
-
1134 
-
1135  // Above upper bound
-
1136  BEAST_EXPECT(!testDiverged("901"));
-
1137  }
-
1138 
-
1139  void
-
1140  run() override
-
1141  {
-
1142  testLegacy();
-
1143  testDbPath();
-
1144  testValidatorKeys();
-
1145  testValidatorsFile();
-
1146  testSetup(false);
-
1147  testSetup(true);
-
1148  testPort();
-
1149  testWhitespace();
-
1150  testComments();
-
1151  testGetters();
-
1152  testAmendment();
-
1153  testOverlay();
-
1154  }
-
1155 };
-
1156 
-
1157 BEAST_DEFINE_TESTSUITE(Config, core, ripple);
-
1158 
-
1159 } // namespace ripple
+
1104  std::vector<ConfigUnit> units = {
+
1105  {"seconds", 1, 15 * 60, false},
+
1106  {"minutes", 60, 14, false},
+
1107  {"minutes", 60, 15, true},
+
1108  {"hours", 3600, 10, true},
+
1109  {"days", 86400, 10, true},
+
1110  {"weeks", 604800, 2, true},
+
1111  {"months", 2592000, 1, false},
+
1112  {"years", 31536000, 1, false}};
+
1113 
+
1114  std::string space = "";
+
1115  for (auto& [unit, sec, val, shouldPass] : units)
+
1116  {
+
1117  Config c;
+
1118  std::string toLoad(R"rippleConfig(
+
1119 [amendment_majority_time]
+
1120 )rippleConfig");
+
1121  toLoad += std::to_string(val) + space + unit;
+
1122  space = space == "" ? " " : "";
+
1123 
+
1124  try
+
1125  {
+
1126  c.loadFromString(toLoad);
+
1127  if (shouldPass)
+
1128  BEAST_EXPECT(
+
1129  c.AMENDMENT_MAJORITY_TIME.count() == val * sec);
+
1130  else
+
1131  fail();
+
1132  }
+
1133  catch (std::runtime_error&)
+
1134  {
+
1135  if (!shouldPass)
+
1136  pass();
+
1137  else
+
1138  fail();
+
1139  }
+
1140  }
+
1141  }
+
1142 
+
1143  void
+
1144  testOverlay()
+
1145  {
+
1146  testcase("overlay: unknown time");
+
1147 
+
1148  auto testUnknown =
+
1149  [](std::string value) -> std::optional<std::chrono::seconds> {
+
1150  try
+
1151  {
+
1152  Config c;
+
1153  c.loadFromString("[overlay]\nmax_unknown_time=" + value);
+
1154  return c.MAX_UNKNOWN_TIME;
+
1155  }
+
1156  catch (std::runtime_error&)
+
1157  {
+
1158  return {};
+
1159  }
+
1160  };
+
1161 
+
1162  // Failures
+
1163  BEAST_EXPECT(!testUnknown("none"));
+
1164  BEAST_EXPECT(!testUnknown("0.5"));
+
1165  BEAST_EXPECT(!testUnknown("180 seconds"));
+
1166  BEAST_EXPECT(!testUnknown("9 minutes"));
+
1167 
+
1168  // Below lower bound
+
1169  BEAST_EXPECT(!testUnknown("299"));
+
1170 
+
1171  // In bounds
+
1172  BEAST_EXPECT(testUnknown("300") == std::chrono::seconds{300});
+
1173  BEAST_EXPECT(testUnknown("301") == std::chrono::seconds{301});
+
1174  BEAST_EXPECT(testUnknown("1799") == std::chrono::seconds{1799});
+
1175  BEAST_EXPECT(testUnknown("1800") == std::chrono::seconds{1800});
+
1176 
+
1177  // Above upper bound
+
1178  BEAST_EXPECT(!testUnknown("1801"));
+
1179 
+
1180  testcase("overlay: diverged time");
+
1181 
+
1182  // In bounds:
+
1183  auto testDiverged =
+
1184  [](std::string value) -> std::optional<std::chrono::seconds> {
+
1185  try
+
1186  {
+
1187  Config c;
+
1188  c.loadFromString("[overlay]\nmax_diverged_time=" + value);
+
1189  return c.MAX_DIVERGED_TIME;
+
1190  }
+
1191  catch (std::runtime_error&)
+
1192  {
+
1193  return {};
+
1194  }
+
1195  };
+
1196 
+
1197  // Failures
+
1198  BEAST_EXPECT(!testDiverged("none"));
+
1199  BEAST_EXPECT(!testDiverged("0.5"));
+
1200  BEAST_EXPECT(!testDiverged("180 seconds"));
+
1201  BEAST_EXPECT(!testDiverged("9 minutes"));
+
1202 
+
1203  // Below lower bound
+
1204  BEAST_EXPECT(!testDiverged("0"));
+
1205  BEAST_EXPECT(!testDiverged("59"));
+
1206 
+
1207  // In bounds
+
1208  BEAST_EXPECT(testDiverged("60") == std::chrono::seconds{60});
+
1209  BEAST_EXPECT(testDiverged("61") == std::chrono::seconds{61});
+
1210  BEAST_EXPECT(testDiverged("899") == std::chrono::seconds{899});
+
1211  BEAST_EXPECT(testDiverged("900") == std::chrono::seconds{900});
+
1212 
+
1213  // Above upper bound
+
1214  BEAST_EXPECT(!testDiverged("901"));
+
1215  }
+
1216 
+
1217  void
+
1218  run() override
+
1219  {
+
1220  testLegacy();
+
1221  testDbPath();
+
1222  testValidatorKeys();
+
1223  testValidatorsFile();
+
1224  testSetup(false);
+
1225  testSetup(true);
+
1226  testPort();
+
1227  testWhitespace();
+
1228  testColons();
+
1229  testComments();
+
1230  testGetters();
+
1231  testAmendment();
+
1232  testOverlay();
+
1233  }
+
1234 };
+
1235 
+
1236 BEAST_DEFINE_TESTSUITE(Config, core, ripple);
+
1237 
+
1238 } // namespace ripple
void testWhitespace()
-
Holds a collection of configuration values.
Definition: BasicConfig.h:42
RippledCfgGuard(beast::unit_test::suite &test, path subDir, path const &dbPath, path const &validatorsFile, bool useCounter=true)
@@ -1252,15 +1330,15 @@ $(function() {
std::vector< std::string > const & values() const
Returns all the values in the section.
Definition: BasicConfig.h:77
~RippledCfgGuard()
bool get_if_exists(Section const &section, std::string const &name, T &v)
Definition: BasicConfig.h:384
-
void append(std::vector< std::string > const &lines)
Append a set of lines to this section.
Definition: BasicConfig.cpp:38
void testLegacy()
path const & file() const
Definition: FileDirGuard.h:164
bool validatorsFileExists() const
-
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition: Config.cpp:456
+
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition: Config.cpp:457
std::string configFile() const
Definition: Config.h:69
STL class.
void testPort()
+
std::vector< std::string > IPS_FIXED
Definition: Config.h:130
bool standalone() const
Definition: Config.h:313
T to_string(T... args)
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
@@ -1282,13 +1360,13 @@ $(function() {
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
FileDirGuard(beast::unit_test::suite &test, path subDir, path file, std::string const &contents, bool useCounter=true, bool create=true)
Definition: FileDirGuard.h:114
bool rmDataDir_
-
void setup(std::string const &strConf, bool bQuiet, bool bSilent, bool bStandalone)
Definition: Config.cpp:314
+
void setup(std::string const &strConf, bool bQuiet, bool bSilent, bool bStandalone)
Definition: Config.cpp:315
T endl(T... args)
void testValidatorsFile()
STL namespace.
-
std::optional< T > get(std::string const &name) const
Definition: BasicConfig.h:138
T empty(T... args)
+
std::vector< std::string > IPS
Definition: Config.h:129
bool fileExists() const
Definition: FileDirGuard.h:170
Write a file in a directory and remove when done.
Definition: FileDirGuard.h:107
auto rmDir(path const &toRm)
Definition: FileDirGuard.h:47
@@ -1303,6 +1381,7 @@ $(function() {
T what(T... args)
bool exists(std::string const &name) const
Returns true if a section with the given name exists.
Section & section(std::string const &name)
Returns the section with the given name.
+
std::chrono::seconds MAX_DIVERGED_TIME
Definition: Config.h:271
Config const & config() const
std::vector< boost::asio::ip::network_v4 > admin_nets_v4
Definition: Port.h:116
diff --git a/Connect_8cpp_source.html b/Connect_8cpp_source.html index 3e0e4bad74..9a33d3a2bb 100644 --- a/Connect_8cpp_source.html +++ b/Connect_8cpp_source.html @@ -130,16 +130,18 @@ $(function() {
59  else
60  iPort = DEFAULT_PEER_PORT;
61 
-
62  auto ip =
-
63  beast::IP::Endpoint::from_string(context.params[jss::ip].asString());
+
62  auto const ip_str = context.params[jss::ip].asString();
+
63  auto ip = beast::IP::Endpoint::from_string(ip_str);
64 
65  if (!is_unspecified(ip))
66  context.app.overlay().connect(ip.at_port(iPort));
67 
-
68  return RPC::makeObjectValue("connecting");
-
69 }
-
70 
-
71 } // namespace ripple
+
68  return RPC::makeObjectValue(
+
69  "attempting connection to IP:" + ip_str +
+
70  " port: " + std::to_string(iPort));
+
71 }
+
72 
+
73 } // namespace ripple
Definition: Context.h:53
@ rpcINVALID_PARAMS
Definition: ErrorCodes.h:84
@@ -150,6 +152,7 @@ $(function() {
bool isConvertibleTo(ValueType other) const
Definition: json_value.cpp:651
virtual Config & config()=0
bool standalone() const
Definition: Config.h:313
+
T to_string(T... args)
Application & app
Definition: Context.h:42
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:932
virtual void connect(beast::IP::Endpoint const &address)=0
Establish a peer connection to the specified endpoint.
diff --git a/Env_8cpp_source.html b/Env_8cpp_source.html index aa594b0681..0bcb409678 100644 --- a/Env_8cpp_source.html +++ b/Env_8cpp_source.html @@ -666,7 +666,7 @@ $(function() {
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:225
std::shared_ptr< SLE const > le(Account const &account) const
Return an account root.
Definition: Env.cpp:213
constexpr std::uint32_t asfDefaultRipple
Definition: TxFlags.h:81
-
std::pair< int, Json::Value > rpcClient(std::vector< std::string > const &args, Config const &config, Logs &logs, std::unordered_map< std::string, std::string > const &headers)
Internal invocation of RPC client.
Definition: RPCCall.cpp:1521
+
std::pair< int, Json::Value > rpcClient(std::vector< std::string > const &args, Config const &config, Logs &logs, std::unordered_map< std::string, std::string > const &headers)
Internal invocation of RPC client.
Definition: RPCCall.cpp:1535
std::unique_ptr< Application > owned
Definition: Env.h:127
Account const & master
Definition: Env.h:121
const SF_AMOUNT sfBalance
diff --git a/LedgerHistory_8cpp_source.html b/LedgerHistory_8cpp_source.html index 459ea4acb8..f71c7d688e 100644 --- a/LedgerHistory_8cpp_source.html +++ b/LedgerHistory_8cpp_source.html @@ -623,7 +623,7 @@ $(function() {
ConsensusValidated m_consensus_validated
std::shared_ptr< Ledger > loadByHash(uint256 const &ledgerHash, Application &app, bool acquire)
Definition: Ledger.cpp:1105
-
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:989
+
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:1012
bool insert(std::shared_ptr< Ledger const > ledger, bool validated)
Track a ledger.
bool isZero() const
Definition: base_uint.h:532
Application & app_
diff --git a/LedgerReplay__test_8cpp_source.html b/LedgerReplay__test_8cpp_source.html index 8c61f133ca..58e527a562 100644 --- a/LedgerReplay__test_8cpp_source.html +++ b/LedgerReplay__test_8cpp_source.html @@ -1713,7 +1713,7 @@ $(function() {
uint256 const & getClosedLedgerHash() const override
virtual void clearFailures() override
const std::set< Peer::id_t > & getPeerIds() const override
get the set of ids of previously added peers
-
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition: Config.cpp:456
+
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition: Config.cpp:457
@ DropAll
boost::asio::ip::address Address
Definition: IPAddress.h:41
diff --git a/Main_8cpp_source.html b/Main_8cpp_source.html index 02f51d6bac..521b50f412 100644 --- a/Main_8cpp_source.html +++ b/Main_8cpp_source.html @@ -915,7 +915,7 @@ $(function() {
bool any_failed() const
@ kInfo
Definition: Journal.h:36
-
int fromCommandLine(Config const &config, const std::vector< std::string > &vCmd, Logs &logs)
Definition: RPCCall.cpp:1672
+
int fromCommandLine(Config const &config, const std::vector< std::string > &vCmd, Logs &logs)
Definition: RPCCall.cpp:1686
std::atomic< bool > envUseIPv4
Definition: envconfig.cpp:34
void setCurrentThreadName(std::string_view name)
Changes the name of the caller thread.
T emplace_back(T... args)
diff --git a/Node_8cpp_source.html b/Node_8cpp_source.html index 4a649b5ea3..04ff230082 100644 --- a/Node_8cpp_source.html +++ b/Node_8cpp_source.html @@ -1474,7 +1474,7 @@ $(function() {
bool isPseudoTx(STObject const &tx)
Check whether a transaction is a pseudo-transaction.
Definition: STTx.cpp:559
std::pair< std::vector< std::shared_ptr< Transaction > >, int > getTxHistory(soci::session &session, Application &app, LedgerIndex startIndex, int quantity, bool count)
getTxHistory Returns given number of most recent transactions starting from given number of entry.
Definition: Node.cpp:616
bool standAlone
Definition: DatabaseCon.h:89
-
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:989
+
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:1012
LockedSociSession checkoutDb()
Definition: DatabaseCon.h:178
uint256 ledgerHash
constexpr std::array< char const *, 1 > LgrDBPragma
Definition: DBInit.h:45
diff --git a/PeerFinder__test_8cpp_source.html b/PeerFinder__test_8cpp_source.html index 51eadb1b84..9711e0fc8f 100644 --- a/PeerFinder__test_8cpp_source.html +++ b/PeerFinder__test_8cpp_source.html @@ -379,7 +379,7 @@ $(function() {
@ success
int out_max() const
Returns the total number of outbound slots.
Definition: Counts.h:103
Manages the count of available connections for the various slots.
Definition: Counts.h:34
-
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition: Config.cpp:456
+
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition: Config.cpp:457
bool onConnected(SlotImp::ptr const &slot, beast::IP::Endpoint const &local_endpoint)
void test_invalid_config()
void stop()
diff --git a/RPCCall_8cpp_source.html b/RPCCall_8cpp_source.html index 0ef569810c..bca5a91026 100644 --- a/RPCCall_8cpp_source.html +++ b/RPCCall_8cpp_source.html @@ -553,1278 +553,1292 @@ $(function() {
482  return jvRequest;
483  }
484 
-
485  // connect <ip> [port]
+
485  // connect <ip[:port]> [port]
486  Json::Value
487  parseConnect(Json::Value const& jvParams)
488  {
489  Json::Value jvRequest(Json::objectValue);
-
490 
-
491  jvRequest[jss::ip] = jvParams[0u].asString();
-
492 
-
493  if (jvParams.size() == 2)
+
490  std::string ip = jvParams[0u].asString();
+
491  if (jvParams.size() == 2)
+
492  {
+
493  jvRequest[jss::ip] = ip;
494  jvRequest[jss::port] = jvParams[1u].asUInt();
-
495 
-
496  return jvRequest;
-
497  }
-
498 
-
499  // deposit_authorized <source_account> <destination_account> [<ledger>]
-
500  Json::Value
-
501  parseDepositAuthorized(Json::Value const& jvParams)
-
502  {
-
503  Json::Value jvRequest(Json::objectValue);
-
504  jvRequest[jss::source_account] = jvParams[0u].asString();
-
505  jvRequest[jss::destination_account] = jvParams[1u].asString();
-
506 
-
507  if (jvParams.size() == 3)
-
508  jvParseLedger(jvRequest, jvParams[2u].asString());
-
509 
+
495  return jvRequest;
+
496  }
+
497 
+
498  // handle case where there is one argument of the form ip:port
+
499  if (std::count(ip.begin(), ip.end(), ':') == 1)
+
500  {
+
501  std::size_t colon = ip.find_last_of(":");
+
502  jvRequest[jss::ip] = std::string{ip, 0, colon};
+
503  jvRequest[jss::port] =
+
504  Json::Value{std::string{ip, colon + 1}}.asUInt();
+
505  return jvRequest;
+
506  }
+
507 
+
508  // default case, no port
+
509  jvRequest[jss::ip] = ip;
510  return jvRequest;
511  }
512 
-
513  // Return an error for attemping to subscribe/unsubscribe via RPC.
+
513  // deposit_authorized <source_account> <destination_account> [<ledger>]
514  Json::Value
-
515  parseEvented(Json::Value const& jvParams)
+
515  parseDepositAuthorized(Json::Value const& jvParams)
516  {
-
517  return rpcError(rpcNO_EVENTS);
-
518  }
-
519 
-
520  // feature [<feature>] [accept|reject]
-
521  Json::Value
-
522  parseFeature(Json::Value const& jvParams)
-
523  {
-
524  Json::Value jvRequest(Json::objectValue);
-
525 
-
526  if (jvParams.size() > 0)
-
527  jvRequest[jss::feature] = jvParams[0u].asString();
-
528 
-
529  if (jvParams.size() > 1)
-
530  {
-
531  auto const action = jvParams[1u].asString();
-
532 
-
533  // This may look reversed, but it's intentional: jss::vetoed
-
534  // determines whether an amendment is vetoed - so "reject" means
-
535  // that jss::vetoed is true.
-
536  if (boost::iequals(action, "reject"))
-
537  jvRequest[jss::vetoed] = Json::Value(true);
-
538  else if (boost::iequals(action, "accept"))
-
539  jvRequest[jss::vetoed] = Json::Value(false);
-
540  else
-
541  return rpcError(rpcINVALID_PARAMS);
-
542  }
-
543 
-
544  return jvRequest;
-
545  }
+
517  Json::Value jvRequest(Json::objectValue);
+
518  jvRequest[jss::source_account] = jvParams[0u].asString();
+
519  jvRequest[jss::destination_account] = jvParams[1u].asString();
+
520 
+
521  if (jvParams.size() == 3)
+
522  jvParseLedger(jvRequest, jvParams[2u].asString());
+
523 
+
524  return jvRequest;
+
525  }
+
526 
+
527  // Return an error for attemping to subscribe/unsubscribe via RPC.
+
528  Json::Value
+
529  parseEvented(Json::Value const& jvParams)
+
530  {
+
531  return rpcError(rpcNO_EVENTS);
+
532  }
+
533 
+
534  // feature [<feature>] [accept|reject]
+
535  Json::Value
+
536  parseFeature(Json::Value const& jvParams)
+
537  {
+
538  Json::Value jvRequest(Json::objectValue);
+
539 
+
540  if (jvParams.size() > 0)
+
541  jvRequest[jss::feature] = jvParams[0u].asString();
+
542 
+
543  if (jvParams.size() > 1)
+
544  {
+
545  auto const action = jvParams[1u].asString();
546 
-
547  // get_counts [<min_count>]
-
548  Json::Value
-
549  parseGetCounts(Json::Value const& jvParams)
-
550  {
-
551  Json::Value jvRequest(Json::objectValue);
-
552 
-
553  if (jvParams.size())
-
554  jvRequest[jss::min_count] = jvParams[0u].asUInt();
-
555 
-
556  return jvRequest;
-
557  }
-
558 
-
559  // sign_for <account> <secret> <json> offline
-
560  // sign_for <account> <secret> <json>
-
561  Json::Value
-
562  parseSignFor(Json::Value const& jvParams)
-
563  {
-
564  bool const bOffline =
-
565  4 == jvParams.size() && jvParams[3u].asString() == "offline";
+
547  // This may look reversed, but it's intentional: jss::vetoed
+
548  // determines whether an amendment is vetoed - so "reject" means
+
549  // that jss::vetoed is true.
+
550  if (boost::iequals(action, "reject"))
+
551  jvRequest[jss::vetoed] = Json::Value(true);
+
552  else if (boost::iequals(action, "accept"))
+
553  jvRequest[jss::vetoed] = Json::Value(false);
+
554  else
+
555  return rpcError(rpcINVALID_PARAMS);
+
556  }
+
557 
+
558  return jvRequest;
+
559  }
+
560 
+
561  // get_counts [<min_count>]
+
562  Json::Value
+
563  parseGetCounts(Json::Value const& jvParams)
+
564  {
+
565  Json::Value jvRequest(Json::objectValue);
566 
-
567  if (3 == jvParams.size() || bOffline)
-
568  {
-
569  Json::Value txJSON;
-
570  Json::Reader reader;
-
571  if (reader.parse(jvParams[2u].asString(), txJSON))
-
572  {
-
573  // sign_for txJSON.
-
574  Json::Value jvRequest{Json::objectValue};
-
575 
-
576  jvRequest[jss::account] = jvParams[0u].asString();
-
577  jvRequest[jss::secret] = jvParams[1u].asString();
-
578  jvRequest[jss::tx_json] = txJSON;
-
579 
-
580  if (bOffline)
-
581  jvRequest[jss::offline] = true;
-
582 
-
583  return jvRequest;
-
584  }
-
585  }
-
586  return rpcError(rpcINVALID_PARAMS);
-
587  }
-
588 
-
589  // json <command> <json>
-
590  Json::Value
-
591  parseJson(Json::Value const& jvParams)
-
592  {
-
593  Json::Reader reader;
-
594  Json::Value jvRequest;
-
595 
-
596  JLOG(j_.trace()) << "RPC method: " << jvParams[0u];
-
597  JLOG(j_.trace()) << "RPC json: " << jvParams[1u];
-
598 
-
599  if (reader.parse(jvParams[1u].asString(), jvRequest))
-
600  {
-
601  if (!jvRequest.isObjectOrNull())
-
602  return rpcError(rpcINVALID_PARAMS);
-
603 
-
604  jvRequest[jss::method] = jvParams[0u];
-
605 
-
606  return jvRequest;
-
607  }
-
608 
-
609  return rpcError(rpcINVALID_PARAMS);
-
610  }
-
611 
-
612  bool
-
613  isValidJson2(Json::Value const& jv)
-
614  {
-
615  if (jv.isArray())
-
616  {
-
617  if (jv.size() == 0)
-
618  return false;
-
619  for (auto const& j : jv)
-
620  {
-
621  if (!isValidJson2(j))
-
622  return false;
-
623  }
-
624  return true;
-
625  }
-
626  if (jv.isObject())
-
627  {
-
628  if (jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0" &&
-
629  jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0" &&
-
630  jv.isMember(jss::id) && jv.isMember(jss::method))
-
631  {
-
632  if (jv.isMember(jss::params) &&
-
633  !(jv[jss::params].isNull() || jv[jss::params].isArray() ||
-
634  jv[jss::params].isObject()))
-
635  return false;
-
636  return true;
+
567  if (jvParams.size())
+
568  jvRequest[jss::min_count] = jvParams[0u].asUInt();
+
569 
+
570  return jvRequest;
+
571  }
+
572 
+
573  // sign_for <account> <secret> <json> offline
+
574  // sign_for <account> <secret> <json>
+
575  Json::Value
+
576  parseSignFor(Json::Value const& jvParams)
+
577  {
+
578  bool const bOffline =
+
579  4 == jvParams.size() && jvParams[3u].asString() == "offline";
+
580 
+
581  if (3 == jvParams.size() || bOffline)
+
582  {
+
583  Json::Value txJSON;
+
584  Json::Reader reader;
+
585  if (reader.parse(jvParams[2u].asString(), txJSON))
+
586  {
+
587  // sign_for txJSON.
+
588  Json::Value jvRequest{Json::objectValue};
+
589 
+
590  jvRequest[jss::account] = jvParams[0u].asString();
+
591  jvRequest[jss::secret] = jvParams[1u].asString();
+
592  jvRequest[jss::tx_json] = txJSON;
+
593 
+
594  if (bOffline)
+
595  jvRequest[jss::offline] = true;
+
596 
+
597  return jvRequest;
+
598  }
+
599  }
+
600  return rpcError(rpcINVALID_PARAMS);
+
601  }
+
602 
+
603  // json <command> <json>
+
604  Json::Value
+
605  parseJson(Json::Value const& jvParams)
+
606  {
+
607  Json::Reader reader;
+
608  Json::Value jvRequest;
+
609 
+
610  JLOG(j_.trace()) << "RPC method: " << jvParams[0u];
+
611  JLOG(j_.trace()) << "RPC json: " << jvParams[1u];
+
612 
+
613  if (reader.parse(jvParams[1u].asString(), jvRequest))
+
614  {
+
615  if (!jvRequest.isObjectOrNull())
+
616  return rpcError(rpcINVALID_PARAMS);
+
617 
+
618  jvRequest[jss::method] = jvParams[0u];
+
619 
+
620  return jvRequest;
+
621  }
+
622 
+
623  return rpcError(rpcINVALID_PARAMS);
+
624  }
+
625 
+
626  bool
+
627  isValidJson2(Json::Value const& jv)
+
628  {
+
629  if (jv.isArray())
+
630  {
+
631  if (jv.size() == 0)
+
632  return false;
+
633  for (auto const& j : jv)
+
634  {
+
635  if (!isValidJson2(j))
+
636  return false;
637  }
-
638  }
-
639  return false;
-
640  }
-
641 
-
642  Json::Value
-
643  parseJson2(Json::Value const& jvParams)
-
644  {
-
645  Json::Reader reader;
-
646  Json::Value jv;
-
647  bool valid_parse = reader.parse(jvParams[0u].asString(), jv);
-
648  if (valid_parse && isValidJson2(jv))
-
649  {
-
650  if (jv.isObject())
-
651  {
-
652  Json::Value jv1{Json::objectValue};
-
653  if (jv.isMember(jss::params))
-
654  {
-
655  auto const& params = jv[jss::params];
-
656  for (auto i = params.begin(); i != params.end(); ++i)
-
657  jv1[i.key().asString()] = *i;
-
658  }
-
659  jv1[jss::jsonrpc] = jv[jss::jsonrpc];
-
660  jv1[jss::ripplerpc] = jv[jss::ripplerpc];
-
661  jv1[jss::id] = jv[jss::id];
-
662  jv1[jss::method] = jv[jss::method];
-
663  return jv1;
-
664  }
-
665  // else jv.isArray()
-
666  Json::Value jv1{Json::arrayValue};
-
667  for (Json::UInt j = 0; j < jv.size(); ++j)
-
668  {
-
669  if (jv[j].isMember(jss::params))
-
670  {
-
671  auto const& params = jv[j][jss::params];
-
672  for (auto i = params.begin(); i != params.end(); ++i)
-
673  jv1[j][i.key().asString()] = *i;
-
674  }
-
675  jv1[j][jss::jsonrpc] = jv[j][jss::jsonrpc];
-
676  jv1[j][jss::ripplerpc] = jv[j][jss::ripplerpc];
-
677  jv1[j][jss::id] = jv[j][jss::id];
-
678  jv1[j][jss::method] = jv[j][jss::method];
-
679  }
-
680  return jv1;
-
681  }
-
682  auto jv_error = rpcError(rpcINVALID_PARAMS);
-
683  if (jv.isMember(jss::jsonrpc))
-
684  jv_error[jss::jsonrpc] = jv[jss::jsonrpc];
-
685  if (jv.isMember(jss::ripplerpc))
-
686  jv_error[jss::ripplerpc] = jv[jss::ripplerpc];
-
687  if (jv.isMember(jss::id))
-
688  jv_error[jss::id] = jv[jss::id];
-
689  return jv_error;
-
690  }
-
691 
-
692  // ledger [id|index|current|closed|validated] [full|tx]
-
693  Json::Value
-
694  parseLedger(Json::Value const& jvParams)
-
695  {
-
696  Json::Value jvRequest(Json::objectValue);
-
697 
-
698  if (!jvParams.size())
-
699  {
-
700  return jvRequest;
-
701  }
-
702 
-
703  jvParseLedger(jvRequest, jvParams[0u].asString());
-
704 
-
705  if (2 == jvParams.size())
-
706  {
-
707  if (jvParams[1u].asString() == "full")
-
708  {
-
709  jvRequest[jss::full] = true;
-
710  }
-
711  else if (jvParams[1u].asString() == "tx")
-
712  {
-
713  jvRequest[jss::transactions] = true;
-
714  jvRequest[jss::expand] = true;
-
715  }
-
716  }
-
717 
-
718  return jvRequest;
-
719  }
-
720 
-
721  // ledger_header <id>|<index>
-
722  Json::Value
-
723  parseLedgerId(Json::Value const& jvParams)
-
724  {
-
725  Json::Value jvRequest(Json::objectValue);
-
726 
-
727  std::string strLedger = jvParams[0u].asString();
-
728 
-
729  if (strLedger.length() == 64)
-
730  {
-
731  jvRequest[jss::ledger_hash] = strLedger;
-
732  }
-
733  else
-
734  {
-
735  jvRequest[jss::ledger_index] =
-
736  beast::lexicalCast<std::uint32_t>(strLedger);
-
737  }
-
738 
-
739  return jvRequest;
-
740  }
-
741 
-
742  // log_level: Get log levels
-
743  // log_level <severity>: Set master log level to the
-
744  // specified severity log_level <partition> <severity>: Set specified
-
745  // partition to specified severity
-
746  Json::Value
-
747  parseLogLevel(Json::Value const& jvParams)
-
748  {
-
749  Json::Value jvRequest(Json::objectValue);
-
750 
-
751  if (jvParams.size() == 1)
-
752  {
-
753  jvRequest[jss::severity] = jvParams[0u].asString();
-
754  }
-
755  else if (jvParams.size() == 2)
-
756  {
-
757  jvRequest[jss::partition] = jvParams[0u].asString();
-
758  jvRequest[jss::severity] = jvParams[1u].asString();
-
759  }
-
760 
-
761  return jvRequest;
-
762  }
-
763 
-
764  // owner_info <account>|<account_public_key> [strict]
-
765  // owner_info <seed>|<pass_phrase>|<key> [<ledger>] [strict]
-
766  // account_info <account>|<account_public_key> [strict]
-
767  // account_info <seed>|<pass_phrase>|<key> [<ledger>] [strict]
-
768  // account_offers <account>|<account_public_key> [<ledger>] [strict]
-
769  Json::Value
-
770  parseAccountItems(Json::Value const& jvParams)
-
771  {
-
772  return parseAccountRaw1(jvParams);
-
773  }
+
638  return true;
+
639  }
+
640  if (jv.isObject())
+
641  {
+
642  if (jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0" &&
+
643  jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0" &&
+
644  jv.isMember(jss::id) && jv.isMember(jss::method))
+
645  {
+
646  if (jv.isMember(jss::params) &&
+
647  !(jv[jss::params].isNull() || jv[jss::params].isArray() ||
+
648  jv[jss::params].isObject()))
+
649  return false;
+
650  return true;
+
651  }
+
652  }
+
653  return false;
+
654  }
+
655 
+
656  Json::Value
+
657  parseJson2(Json::Value const& jvParams)
+
658  {
+
659  Json::Reader reader;
+
660  Json::Value jv;
+
661  bool valid_parse = reader.parse(jvParams[0u].asString(), jv);
+
662  if (valid_parse && isValidJson2(jv))
+
663  {
+
664  if (jv.isObject())
+
665  {
+
666  Json::Value jv1{Json::objectValue};
+
667  if (jv.isMember(jss::params))
+
668  {
+
669  auto const& params = jv[jss::params];
+
670  for (auto i = params.begin(); i != params.end(); ++i)
+
671  jv1[i.key().asString()] = *i;
+
672  }
+
673  jv1[jss::jsonrpc] = jv[jss::jsonrpc];
+
674  jv1[jss::ripplerpc] = jv[jss::ripplerpc];
+
675  jv1[jss::id] = jv[jss::id];
+
676  jv1[jss::method] = jv[jss::method];
+
677  return jv1;
+
678  }
+
679  // else jv.isArray()
+
680  Json::Value jv1{Json::arrayValue};
+
681  for (Json::UInt j = 0; j < jv.size(); ++j)
+
682  {
+
683  if (jv[j].isMember(jss::params))
+
684  {
+
685  auto const& params = jv[j][jss::params];
+
686  for (auto i = params.begin(); i != params.end(); ++i)
+
687  jv1[j][i.key().asString()] = *i;
+
688  }
+
689  jv1[j][jss::jsonrpc] = jv[j][jss::jsonrpc];
+
690  jv1[j][jss::ripplerpc] = jv[j][jss::ripplerpc];
+
691  jv1[j][jss::id] = jv[j][jss::id];
+
692  jv1[j][jss::method] = jv[j][jss::method];
+
693  }
+
694  return jv1;
+
695  }
+
696  auto jv_error = rpcError(rpcINVALID_PARAMS);
+
697  if (jv.isMember(jss::jsonrpc))
+
698  jv_error[jss::jsonrpc] = jv[jss::jsonrpc];
+
699  if (jv.isMember(jss::ripplerpc))
+
700  jv_error[jss::ripplerpc] = jv[jss::ripplerpc];
+
701  if (jv.isMember(jss::id))
+
702  jv_error[jss::id] = jv[jss::id];
+
703  return jv_error;
+
704  }
+
705 
+
706  // ledger [id|index|current|closed|validated] [full|tx]
+
707  Json::Value
+
708  parseLedger(Json::Value const& jvParams)
+
709  {
+
710  Json::Value jvRequest(Json::objectValue);
+
711 
+
712  if (!jvParams.size())
+
713  {
+
714  return jvRequest;
+
715  }
+
716 
+
717  jvParseLedger(jvRequest, jvParams[0u].asString());
+
718 
+
719  if (2 == jvParams.size())
+
720  {
+
721  if (jvParams[1u].asString() == "full")
+
722  {
+
723  jvRequest[jss::full] = true;
+
724  }
+
725  else if (jvParams[1u].asString() == "tx")
+
726  {
+
727  jvRequest[jss::transactions] = true;
+
728  jvRequest[jss::expand] = true;
+
729  }
+
730  }
+
731 
+
732  return jvRequest;
+
733  }
+
734 
+
735  // ledger_header <id>|<index>
+
736  Json::Value
+
737  parseLedgerId(Json::Value const& jvParams)
+
738  {
+
739  Json::Value jvRequest(Json::objectValue);
+
740 
+
741  std::string strLedger = jvParams[0u].asString();
+
742 
+
743  if (strLedger.length() == 64)
+
744  {
+
745  jvRequest[jss::ledger_hash] = strLedger;
+
746  }
+
747  else
+
748  {
+
749  jvRequest[jss::ledger_index] =
+
750  beast::lexicalCast<std::uint32_t>(strLedger);
+
751  }
+
752 
+
753  return jvRequest;
+
754  }
+
755 
+
756  // log_level: Get log levels
+
757  // log_level <severity>: Set master log level to the
+
758  // specified severity log_level <partition> <severity>: Set specified
+
759  // partition to specified severity
+
760  Json::Value
+
761  parseLogLevel(Json::Value const& jvParams)
+
762  {
+
763  Json::Value jvRequest(Json::objectValue);
+
764 
+
765  if (jvParams.size() == 1)
+
766  {
+
767  jvRequest[jss::severity] = jvParams[0u].asString();
+
768  }
+
769  else if (jvParams.size() == 2)
+
770  {
+
771  jvRequest[jss::partition] = jvParams[0u].asString();
+
772  jvRequest[jss::severity] = jvParams[1u].asString();
+
773  }
774 
-
775  Json::Value
-
776  parseAccountCurrencies(Json::Value const& jvParams)
-
777  {
-
778  return parseAccountRaw1(jvParams);
-
779  }
-
780 
-
781  // account_lines <account> <account>|"" [<ledger>]
-
782  Json::Value
-
783  parseAccountLines(Json::Value const& jvParams)
-
784  {
-
785  return parseAccountRaw2(jvParams, jss::peer);
-
786  }
-
787 
-
788  // account_channels <account> <account>|"" [<ledger>]
+
775  return jvRequest;
+
776  }
+
777 
+
778  // owner_info <account>|<account_public_key> [strict]
+
779  // owner_info <seed>|<pass_phrase>|<key> [<ledger>] [strict]
+
780  // account_info <account>|<account_public_key> [strict]
+
781  // account_info <seed>|<pass_phrase>|<key> [<ledger>] [strict]
+
782  // account_offers <account>|<account_public_key> [<ledger>] [strict]
+
783  Json::Value
+
784  parseAccountItems(Json::Value const& jvParams)
+
785  {
+
786  return parseAccountRaw1(jvParams);
+
787  }
+
788 
789  Json::Value
-
790  parseAccountChannels(Json::Value const& jvParams)
+
790  parseAccountCurrencies(Json::Value const& jvParams)
791  {
-
792  return parseAccountRaw2(jvParams, jss::destination_account);
+
792  return parseAccountRaw1(jvParams);
793  }
794 
-
795  // channel_authorize: <private_key> [<key_type>] <channel_id> <drops>
+
795  // account_lines <account> <account>|"" [<ledger>]
796  Json::Value
-
797  parseChannelAuthorize(Json::Value const& jvParams)
+
797  parseAccountLines(Json::Value const& jvParams)
798  {
-
799  Json::Value jvRequest(Json::objectValue);
-
800 
-
801  unsigned int index = 0;
-
802 
-
803  if (jvParams.size() == 4)
-
804  {
-
805  jvRequest[jss::passphrase] = jvParams[index];
-
806  index++;
-
807 
-
808  if (!keyTypeFromString(jvParams[index].asString()))
-
809  return rpcError(rpcBAD_KEY_TYPE);
-
810  jvRequest[jss::key_type] = jvParams[index];
-
811  index++;
-
812  }
-
813  else
-
814  {
-
815  jvRequest[jss::secret] = jvParams[index];
-
816  index++;
-
817  }
-
818 
-
819  {
-
820  // verify the channel id is a valid 256 bit number
-
821  uint256 channelId;
-
822  if (!channelId.parseHex(jvParams[index].asString()))
-
823  return rpcError(rpcCHANNEL_MALFORMED);
-
824  jvRequest[jss::channel_id] = to_string(channelId);
+
799  return parseAccountRaw2(jvParams, jss::peer);
+
800  }
+
801 
+
802  // account_channels <account> <account>|"" [<ledger>]
+
803  Json::Value
+
804  parseAccountChannels(Json::Value const& jvParams)
+
805  {
+
806  return parseAccountRaw2(jvParams, jss::destination_account);
+
807  }
+
808 
+
809  // channel_authorize: <private_key> [<key_type>] <channel_id> <drops>
+
810  Json::Value
+
811  parseChannelAuthorize(Json::Value const& jvParams)
+
812  {
+
813  Json::Value jvRequest(Json::objectValue);
+
814 
+
815  unsigned int index = 0;
+
816 
+
817  if (jvParams.size() == 4)
+
818  {
+
819  jvRequest[jss::passphrase] = jvParams[index];
+
820  index++;
+
821 
+
822  if (!keyTypeFromString(jvParams[index].asString()))
+
823  return rpcError(rpcBAD_KEY_TYPE);
+
824  jvRequest[jss::key_type] = jvParams[index];
825  index++;
826  }
-
827 
-
828  if (!jvParams[index].isString() ||
-
829  !to_uint64(jvParams[index].asString()))
-
830  return rpcError(rpcCHANNEL_AMT_MALFORMED);
-
831  jvRequest[jss::amount] = jvParams[index];
+
827  else
+
828  {
+
829  jvRequest[jss::secret] = jvParams[index];
+
830  index++;
+
831  }
832 
-
833  // If additional parameters are appended, be sure to increment index
-
834  // here
-
835 
-
836  return jvRequest;
-
837  }
-
838 
-
839  // channel_verify <public_key> <channel_id> <drops> <signature>
-
840  Json::Value
-
841  parseChannelVerify(Json::Value const& jvParams)
-
842  {
-
843  std::string const strPk = jvParams[0u].asString();
-
844 
-
845  if (!validPublicKey(strPk))
-
846  return rpcError(rpcPUBLIC_MALFORMED);
-
847 
-
848  Json::Value jvRequest(Json::objectValue);
+
833  {
+
834  // verify the channel id is a valid 256 bit number
+
835  uint256 channelId;
+
836  if (!channelId.parseHex(jvParams[index].asString()))
+
837  return rpcError(rpcCHANNEL_MALFORMED);
+
838  jvRequest[jss::channel_id] = to_string(channelId);
+
839  index++;
+
840  }
+
841 
+
842  if (!jvParams[index].isString() ||
+
843  !to_uint64(jvParams[index].asString()))
+
844  return rpcError(rpcCHANNEL_AMT_MALFORMED);
+
845  jvRequest[jss::amount] = jvParams[index];
+
846 
+
847  // If additional parameters are appended, be sure to increment index
+
848  // here
849 
-
850  jvRequest[jss::public_key] = strPk;
-
851  {
-
852  // verify the channel id is a valid 256 bit number
-
853  uint256 channelId;
-
854  if (!channelId.parseHex(jvParams[1u].asString()))
-
855  return rpcError(rpcCHANNEL_MALFORMED);
-
856  }
-
857  jvRequest[jss::channel_id] = jvParams[1u].asString();
+
850  return jvRequest;
+
851  }
+
852 
+
853  // channel_verify <public_key> <channel_id> <drops> <signature>
+
854  Json::Value
+
855  parseChannelVerify(Json::Value const& jvParams)
+
856  {
+
857  std::string const strPk = jvParams[0u].asString();
858 
-
859  if (!jvParams[2u].isString() || !to_uint64(jvParams[2u].asString()))
-
860  return rpcError(rpcCHANNEL_AMT_MALFORMED);
-
861  jvRequest[jss::amount] = jvParams[2u];
-
862 
-
863  jvRequest[jss::signature] = jvParams[3u].asString();
-
864 
-
865  return jvRequest;
-
866  }
-
867 
-
868  Json::Value
-
869  parseAccountRaw2(Json::Value const& jvParams, char const* const acc2Field)
-
870  {
-
871  std::array<char const* const, 2> accFields{{jss::account, acc2Field}};
-
872  auto const nParams = jvParams.size();
-
873  Json::Value jvRequest(Json::objectValue);
-
874  for (auto i = 0; i < nParams; ++i)
-
875  {
-
876  std::string strParam = jvParams[i].asString();
-
877 
-
878  if (i == 1 && strParam.empty())
-
879  continue;
-
880 
-
881  // Parameters 0 and 1 are accounts
-
882  if (i < 2)
-
883  {
-
884  if (parseBase58<PublicKey>(
-
885  TokenType::AccountPublic, strParam) ||
-
886  parseBase58<AccountID>(strParam) ||
-
887  parseGenericSeed(strParam))
-
888  {
-
889  jvRequest[accFields[i]] = std::move(strParam);
-
890  }
-
891  else
-
892  {
-
893  return rpcError(rpcACT_MALFORMED);
-
894  }
-
895  }
-
896  else
+
859  if (!validPublicKey(strPk))
+
860  return rpcError(rpcPUBLIC_MALFORMED);
+
861 
+
862  Json::Value jvRequest(Json::objectValue);
+
863 
+
864  jvRequest[jss::public_key] = strPk;
+
865  {
+
866  // verify the channel id is a valid 256 bit number
+
867  uint256 channelId;
+
868  if (!channelId.parseHex(jvParams[1u].asString()))
+
869  return rpcError(rpcCHANNEL_MALFORMED);
+
870  }
+
871  jvRequest[jss::channel_id] = jvParams[1u].asString();
+
872 
+
873  if (!jvParams[2u].isString() || !to_uint64(jvParams[2u].asString()))
+
874  return rpcError(rpcCHANNEL_AMT_MALFORMED);
+
875  jvRequest[jss::amount] = jvParams[2u];
+
876 
+
877  jvRequest[jss::signature] = jvParams[3u].asString();
+
878 
+
879  return jvRequest;
+
880  }
+
881 
+
882  Json::Value
+
883  parseAccountRaw2(Json::Value const& jvParams, char const* const acc2Field)
+
884  {
+
885  std::array<char const* const, 2> accFields{{jss::account, acc2Field}};
+
886  auto const nParams = jvParams.size();
+
887  Json::Value jvRequest(Json::objectValue);
+
888  for (auto i = 0; i < nParams; ++i)
+
889  {
+
890  std::string strParam = jvParams[i].asString();
+
891 
+
892  if (i == 1 && strParam.empty())
+
893  continue;
+
894 
+
895  // Parameters 0 and 1 are accounts
+
896  if (i < 2)
897  {
-
898  if (jvParseLedger(jvRequest, strParam))
-
899  return jvRequest;
-
900  return rpcError(rpcLGR_IDX_MALFORMED);
-
901  }
-
902  }
-
903 
-
904  return jvRequest;
-
905  }
-
906 
-
907  // TODO: Get index from an alternate syntax: rXYZ:<index>
-
908  Json::Value
-
909  parseAccountRaw1(Json::Value const& jvParams)
-
910  {
-
911  std::string strIdent = jvParams[0u].asString();
-
912  unsigned int iCursor = jvParams.size();
-
913  bool bStrict = false;
-
914 
-
915  if (iCursor >= 2 && jvParams[iCursor - 1] == jss::strict)
-
916  {
-
917  bStrict = true;
-
918  --iCursor;
-
919  }
+
898  if (parseBase58<PublicKey>(
+
899  TokenType::AccountPublic, strParam) ||
+
900  parseBase58<AccountID>(strParam) ||
+
901  parseGenericSeed(strParam))
+
902  {
+
903  jvRequest[accFields[i]] = std::move(strParam);
+
904  }
+
905  else
+
906  {
+
907  return rpcError(rpcACT_MALFORMED);
+
908  }
+
909  }
+
910  else
+
911  {
+
912  if (jvParseLedger(jvRequest, strParam))
+
913  return jvRequest;
+
914  return rpcError(rpcLGR_IDX_MALFORMED);
+
915  }
+
916  }
+
917 
+
918  return jvRequest;
+
919  }
920 
-
921  if (!parseBase58<PublicKey>(TokenType::AccountPublic, strIdent) &&
-
922  !parseBase58<AccountID>(strIdent) && !parseGenericSeed(strIdent))
-
923  return rpcError(rpcACT_MALFORMED);
-
924 
-
925  // Get info on account.
-
926  Json::Value jvRequest(Json::objectValue);
-
927 
-
928  jvRequest[jss::account] = strIdent;
-
929 
-
930  if (bStrict)
-
931  jvRequest[jss::strict] = 1;
-
932 
-
933  if (iCursor == 2 && !jvParseLedger(jvRequest, jvParams[1u].asString()))
-
934  return rpcError(rpcLGR_IDX_MALFORMED);
-
935 
-
936  return jvRequest;
-
937  }
+
921  // TODO: Get index from an alternate syntax: rXYZ:<index>
+
922  Json::Value
+
923  parseAccountRaw1(Json::Value const& jvParams)
+
924  {
+
925  std::string strIdent = jvParams[0u].asString();
+
926  unsigned int iCursor = jvParams.size();
+
927  bool bStrict = false;
+
928 
+
929  if (iCursor >= 2 && jvParams[iCursor - 1] == jss::strict)
+
930  {
+
931  bStrict = true;
+
932  --iCursor;
+
933  }
+
934 
+
935  if (!parseBase58<PublicKey>(TokenType::AccountPublic, strIdent) &&
+
936  !parseBase58<AccountID>(strIdent) && !parseGenericSeed(strIdent))
+
937  return rpcError(rpcACT_MALFORMED);
938 
-
939  Json::Value
-
940  parseNodeToShard(Json::Value const& jvParams)
-
941  {
-
942  Json::Value jvRequest;
-
943  jvRequest[jss::action] = jvParams[0u].asString();
-
944 
-
945  return jvRequest;
-
946  }
-
947 
-
948  // peer_reservations_add <public_key> [<name>]
-
949  Json::Value
-
950  parsePeerReservationsAdd(Json::Value const& jvParams)
-
951  {
-
952  Json::Value jvRequest;
-
953  jvRequest[jss::public_key] = jvParams[0u].asString();
-
954  if (jvParams.size() > 1)
-
955  {
-
956  jvRequest[jss::description] = jvParams[1u].asString();
-
957  }
-
958  return jvRequest;
-
959  }
-
960 
-
961  // peer_reservations_del <public_key>
-
962  Json::Value
-
963  parsePeerReservationsDel(Json::Value const& jvParams)
-
964  {
-
965  Json::Value jvRequest;
-
966  jvRequest[jss::public_key] = jvParams[0u].asString();
-
967  return jvRequest;
-
968  }
-
969 
-
970  // ripple_path_find <json> [<ledger>]
-
971  Json::Value
-
972  parseRipplePathFind(Json::Value const& jvParams)
-
973  {
-
974  Json::Reader reader;
-
975  Json::Value jvRequest{Json::objectValue};
-
976  bool bLedger = 2 == jvParams.size();
-
977 
-
978  JLOG(j_.trace()) << "RPC json: " << jvParams[0u];
-
979 
-
980  if (reader.parse(jvParams[0u].asString(), jvRequest))
-
981  {
-
982  if (bLedger)
-
983  {
-
984  jvParseLedger(jvRequest, jvParams[1u].asString());
-
985  }
-
986 
-
987  return jvRequest;
-
988  }
-
989 
-
990  return rpcError(rpcINVALID_PARAMS);
-
991  }
-
992 
-
993  // sign/submit any transaction to the network
-
994  //
-
995  // sign <private_key> <json> offline
-
996  // submit <private_key> <json>
-
997  // submit <tx_blob>
-
998  Json::Value
-
999  parseSignSubmit(Json::Value const& jvParams)
-
1000  {
-
1001  Json::Value txJSON;
-
1002  Json::Reader reader;
-
1003  bool const bOffline =
-
1004  3 == jvParams.size() && jvParams[2u].asString() == "offline";
-
1005 
-
1006  if (1 == jvParams.size())
-
1007  {
-
1008  // Submitting tx_blob
-
1009 
-
1010  Json::Value jvRequest{Json::objectValue};
-
1011 
-
1012  jvRequest[jss::tx_blob] = jvParams[0u].asString();
-
1013 
-
1014  return jvRequest;
-
1015  }
-
1016  else if (
-
1017  (2 == jvParams.size() || bOffline) &&
-
1018  reader.parse(jvParams[1u].asString(), txJSON))
-
1019  {
-
1020  // Signing or submitting tx_json.
-
1021  Json::Value jvRequest{Json::objectValue};
-
1022 
-
1023  jvRequest[jss::secret] = jvParams[0u].asString();
-
1024  jvRequest[jss::tx_json] = txJSON;
+
939  // Get info on account.
+
940  Json::Value jvRequest(Json::objectValue);
+
941 
+
942  jvRequest[jss::account] = strIdent;
+
943 
+
944  if (bStrict)
+
945  jvRequest[jss::strict] = 1;
+
946 
+
947  if (iCursor == 2 && !jvParseLedger(jvRequest, jvParams[1u].asString()))
+
948  return rpcError(rpcLGR_IDX_MALFORMED);
+
949 
+
950  return jvRequest;
+
951  }
+
952 
+
953  Json::Value
+
954  parseNodeToShard(Json::Value const& jvParams)
+
955  {
+
956  Json::Value jvRequest;
+
957  jvRequest[jss::action] = jvParams[0u].asString();
+
958 
+
959  return jvRequest;
+
960  }
+
961 
+
962  // peer_reservations_add <public_key> [<name>]
+
963  Json::Value
+
964  parsePeerReservationsAdd(Json::Value const& jvParams)
+
965  {
+
966  Json::Value jvRequest;
+
967  jvRequest[jss::public_key] = jvParams[0u].asString();
+
968  if (jvParams.size() > 1)
+
969  {
+
970  jvRequest[jss::description] = jvParams[1u].asString();
+
971  }
+
972  return jvRequest;
+
973  }
+
974 
+
975  // peer_reservations_del <public_key>
+
976  Json::Value
+
977  parsePeerReservationsDel(Json::Value const& jvParams)
+
978  {
+
979  Json::Value jvRequest;
+
980  jvRequest[jss::public_key] = jvParams[0u].asString();
+
981  return jvRequest;
+
982  }
+
983 
+
984  // ripple_path_find <json> [<ledger>]
+
985  Json::Value
+
986  parseRipplePathFind(Json::Value const& jvParams)
+
987  {
+
988  Json::Reader reader;
+
989  Json::Value jvRequest{Json::objectValue};
+
990  bool bLedger = 2 == jvParams.size();
+
991 
+
992  JLOG(j_.trace()) << "RPC json: " << jvParams[0u];
+
993 
+
994  if (reader.parse(jvParams[0u].asString(), jvRequest))
+
995  {
+
996  if (bLedger)
+
997  {
+
998  jvParseLedger(jvRequest, jvParams[1u].asString());
+
999  }
+
1000 
+
1001  return jvRequest;
+
1002  }
+
1003 
+
1004  return rpcError(rpcINVALID_PARAMS);
+
1005  }
+
1006 
+
1007  // sign/submit any transaction to the network
+
1008  //
+
1009  // sign <private_key> <json> offline
+
1010  // submit <private_key> <json>
+
1011  // submit <tx_blob>
+
1012  Json::Value
+
1013  parseSignSubmit(Json::Value const& jvParams)
+
1014  {
+
1015  Json::Value txJSON;
+
1016  Json::Reader reader;
+
1017  bool const bOffline =
+
1018  3 == jvParams.size() && jvParams[2u].asString() == "offline";
+
1019 
+
1020  if (1 == jvParams.size())
+
1021  {
+
1022  // Submitting tx_blob
+
1023 
+
1024  Json::Value jvRequest{Json::objectValue};
1025 
-
1026  if (bOffline)
-
1027  jvRequest[jss::offline] = true;
-
1028 
-
1029  return jvRequest;
-
1030  }
-
1031 
-
1032  return rpcError(rpcINVALID_PARAMS);
-
1033  }
-
1034 
-
1035  // submit any multisigned transaction to the network
-
1036  //
-
1037  // submit_multisigned <json>
-
1038  Json::Value
-
1039  parseSubmitMultiSigned(Json::Value const& jvParams)
-
1040  {
-
1041  if (1 == jvParams.size())
-
1042  {
-
1043  Json::Value txJSON;
-
1044  Json::Reader reader;
-
1045  if (reader.parse(jvParams[0u].asString(), txJSON))
-
1046  {
-
1047  Json::Value jvRequest{Json::objectValue};
-
1048  jvRequest[jss::tx_json] = txJSON;
-
1049  return jvRequest;
-
1050  }
-
1051  }
-
1052 
-
1053  return rpcError(rpcINVALID_PARAMS);
-
1054  }
-
1055 
-
1056  // transaction_entry <tx_hash> <ledger_hash/ledger_index>
-
1057  Json::Value
-
1058  parseTransactionEntry(Json::Value const& jvParams)
-
1059  {
-
1060  // Parameter count should have already been verified.
-
1061  assert(jvParams.size() == 2);
-
1062 
-
1063  std::string const txHash = jvParams[0u].asString();
-
1064  if (txHash.length() != 64)
-
1065  return rpcError(rpcINVALID_PARAMS);
+
1026  jvRequest[jss::tx_blob] = jvParams[0u].asString();
+
1027 
+
1028  return jvRequest;
+
1029  }
+
1030  else if (
+
1031  (2 == jvParams.size() || bOffline) &&
+
1032  reader.parse(jvParams[1u].asString(), txJSON))
+
1033  {
+
1034  // Signing or submitting tx_json.
+
1035  Json::Value jvRequest{Json::objectValue};
+
1036 
+
1037  jvRequest[jss::secret] = jvParams[0u].asString();
+
1038  jvRequest[jss::tx_json] = txJSON;
+
1039 
+
1040  if (bOffline)
+
1041  jvRequest[jss::offline] = true;
+
1042 
+
1043  return jvRequest;
+
1044  }
+
1045 
+
1046  return rpcError(rpcINVALID_PARAMS);
+
1047  }
+
1048 
+
1049  // submit any multisigned transaction to the network
+
1050  //
+
1051  // submit_multisigned <json>
+
1052  Json::Value
+
1053  parseSubmitMultiSigned(Json::Value const& jvParams)
+
1054  {
+
1055  if (1 == jvParams.size())
+
1056  {
+
1057  Json::Value txJSON;
+
1058  Json::Reader reader;
+
1059  if (reader.parse(jvParams[0u].asString(), txJSON))
+
1060  {
+
1061  Json::Value jvRequest{Json::objectValue};
+
1062  jvRequest[jss::tx_json] = txJSON;
+
1063  return jvRequest;
+
1064  }
+
1065  }
1066 
-
1067  Json::Value jvRequest{Json::objectValue};
-
1068  jvRequest[jss::tx_hash] = txHash;
+
1067  return rpcError(rpcINVALID_PARAMS);
+
1068  }
1069 
-
1070  jvParseLedger(jvRequest, jvParams[1u].asString());
-
1071 
-
1072  // jvParseLedger inserts a "ledger_index" of 0 if it doesn't
-
1073  // find a match.
-
1074  if (jvRequest.isMember(jss::ledger_index) &&
-
1075  jvRequest[jss::ledger_index] == 0)
-
1076  return rpcError(rpcINVALID_PARAMS);
-
1077 
-
1078  return jvRequest;
-
1079  }
+
1070  // transaction_entry <tx_hash> <ledger_hash/ledger_index>
+
1071  Json::Value
+
1072  parseTransactionEntry(Json::Value const& jvParams)
+
1073  {
+
1074  // Parameter count should have already been verified.
+
1075  assert(jvParams.size() == 2);
+
1076 
+
1077  std::string const txHash = jvParams[0u].asString();
+
1078  if (txHash.length() != 64)
+
1079  return rpcError(rpcINVALID_PARAMS);
1080 
-
1081  // tx <transaction_id>
-
1082  Json::Value
-
1083  parseTx(Json::Value const& jvParams)
-
1084  {
-
1085  Json::Value jvRequest{Json::objectValue};
-
1086 
-
1087  if (jvParams.size() == 2 || jvParams.size() == 4)
-
1088  {
-
1089  if (jvParams[1u].asString() == jss::binary)
-
1090  jvRequest[jss::binary] = true;
-
1091  }
-
1092 
-
1093  if (jvParams.size() >= 3)
-
1094  {
-
1095  const auto offset = jvParams.size() == 3 ? 0 : 1;
-
1096 
-
1097  jvRequest[jss::min_ledger] = jvParams[1u + offset].asString();
-
1098  jvRequest[jss::max_ledger] = jvParams[2u + offset].asString();
-
1099  }
+
1081  Json::Value jvRequest{Json::objectValue};
+
1082  jvRequest[jss::tx_hash] = txHash;
+
1083 
+
1084  jvParseLedger(jvRequest, jvParams[1u].asString());
+
1085 
+
1086  // jvParseLedger inserts a "ledger_index" of 0 if it doesn't
+
1087  // find a match.
+
1088  if (jvRequest.isMember(jss::ledger_index) &&
+
1089  jvRequest[jss::ledger_index] == 0)
+
1090  return rpcError(rpcINVALID_PARAMS);
+
1091 
+
1092  return jvRequest;
+
1093  }
+
1094 
+
1095  // tx <transaction_id>
+
1096  Json::Value
+
1097  parseTx(Json::Value const& jvParams)
+
1098  {
+
1099  Json::Value jvRequest{Json::objectValue};
1100 
-
1101  jvRequest[jss::transaction] = jvParams[0u].asString();
-
1102  return jvRequest;
-
1103  }
-
1104 
-
1105  // tx_history <index>
-
1106  Json::Value
-
1107  parseTxHistory(Json::Value const& jvParams)
-
1108  {
-
1109  Json::Value jvRequest{Json::objectValue};
+
1101  if (jvParams.size() == 2 || jvParams.size() == 4)
+
1102  {
+
1103  if (jvParams[1u].asString() == jss::binary)
+
1104  jvRequest[jss::binary] = true;
+
1105  }
+
1106 
+
1107  if (jvParams.size() >= 3)
+
1108  {
+
1109  const auto offset = jvParams.size() == 3 ? 0 : 1;
1110 
-
1111  jvRequest[jss::start] = jvParams[0u].asUInt();
-
1112 
-
1113  return jvRequest;
-
1114  }
-
1115 
-
1116  // validation_create [<pass_phrase>|<seed>|<seed_key>]
-
1117  //
-
1118  // NOTE: It is poor security to specify secret information on the command
-
1119  // line. This information might be saved in the command shell history file
-
1120  // (e.g. .bash_history) and it may be leaked via the process status command
-
1121  // (i.e. ps).
-
1122  Json::Value
-
1123  parseValidationCreate(Json::Value const& jvParams)
-
1124  {
-
1125  Json::Value jvRequest{Json::objectValue};
+
1111  jvRequest[jss::min_ledger] = jvParams[1u + offset].asString();
+
1112  jvRequest[jss::max_ledger] = jvParams[2u + offset].asString();
+
1113  }
+
1114 
+
1115  jvRequest[jss::transaction] = jvParams[0u].asString();
+
1116  return jvRequest;
+
1117  }
+
1118 
+
1119  // tx_history <index>
+
1120  Json::Value
+
1121  parseTxHistory(Json::Value const& jvParams)
+
1122  {
+
1123  Json::Value jvRequest{Json::objectValue};
+
1124 
+
1125  jvRequest[jss::start] = jvParams[0u].asUInt();
1126 
-
1127  if (jvParams.size())
-
1128  jvRequest[jss::secret] = jvParams[0u].asString();
+
1127  return jvRequest;
+
1128  }
1129 
-
1130  return jvRequest;
-
1131  }
-
1132 
-
1133  // wallet_propose [<passphrase>]
-
1134  // <passphrase> is only for testing. Master seeds should only be generated
-
1135  // randomly.
+
1130  // validation_create [<pass_phrase>|<seed>|<seed_key>]
+
1131  //
+
1132  // NOTE: It is poor security to specify secret information on the command
+
1133  // line. This information might be saved in the command shell history file
+
1134  // (e.g. .bash_history) and it may be leaked via the process status command
+
1135  // (i.e. ps).
1136  Json::Value
-
1137  parseWalletPropose(Json::Value const& jvParams)
+
1137  parseValidationCreate(Json::Value const& jvParams)
1138  {
1139  Json::Value jvRequest{Json::objectValue};
1140 
1141  if (jvParams.size())
-
1142  jvRequest[jss::passphrase] = jvParams[0u].asString();
+
1142  jvRequest[jss::secret] = jvParams[0u].asString();
1143 
1144  return jvRequest;
1145  }
1146 
-
1147  // parse gateway balances
-
1148  // gateway_balances [<ledger>] <issuer_account> [ <hotwallet> [ <hotwallet>
-
1149  // ]]
-
1150 
-
1151  Json::Value
-
1152  parseGatewayBalances(Json::Value const& jvParams)
-
1153  {
-
1154  unsigned int index = 0;
-
1155  const unsigned int size = jvParams.size();
-
1156 
-
1157  Json::Value jvRequest{Json::objectValue};
-
1158 
-
1159  std::string param = jvParams[index++].asString();
-
1160  if (param.empty())
-
1161  return RPC::make_param_error("Invalid first parameter");
-
1162 
-
1163  if (param[0] != 'r')
-
1164  {
-
1165  if (param.size() == 64)
-
1166  jvRequest[jss::ledger_hash] = param;
-
1167  else
-
1168  jvRequest[jss::ledger_index] = param;
-
1169 
-
1170  if (size <= index)
-
1171  return RPC::make_param_error("Invalid hotwallet");
+
1147  // wallet_propose [<passphrase>]
+
1148  // <passphrase> is only for testing. Master seeds should only be generated
+
1149  // randomly.
+
1150  Json::Value
+
1151  parseWalletPropose(Json::Value const& jvParams)
+
1152  {
+
1153  Json::Value jvRequest{Json::objectValue};
+
1154 
+
1155  if (jvParams.size())
+
1156  jvRequest[jss::passphrase] = jvParams[0u].asString();
+
1157 
+
1158  return jvRequest;
+
1159  }
+
1160 
+
1161  // parse gateway balances
+
1162  // gateway_balances [<ledger>] <issuer_account> [ <hotwallet> [ <hotwallet>
+
1163  // ]]
+
1164 
+
1165  Json::Value
+
1166  parseGatewayBalances(Json::Value const& jvParams)
+
1167  {
+
1168  unsigned int index = 0;
+
1169  const unsigned int size = jvParams.size();
+
1170 
+
1171  Json::Value jvRequest{Json::objectValue};
1172 
-
1173  param = jvParams[index++].asString();
-
1174  }
-
1175 
-
1176  jvRequest[jss::account] = param;
-
1177 
-
1178  if (index < size)
-
1179  {
-
1180  Json::Value& hotWallets =
-
1181  (jvRequest["hotwallet"] = Json::arrayValue);
-
1182  while (index < size)
-
1183  hotWallets.append(jvParams[index++].asString());
-
1184  }
-
1185 
-
1186  return jvRequest;
-
1187  }
-
1188 
-
1189  // server_info [counters]
-
1190  Json::Value
-
1191  parseServerInfo(Json::Value const& jvParams)
-
1192  {
-
1193  Json::Value jvRequest(Json::objectValue);
-
1194  if (jvParams.size() == 1 && jvParams[0u].asString() == "counters")
-
1195  jvRequest[jss::counters] = true;
-
1196  return jvRequest;
-
1197  }
-
1198 
-
1199 public:
-
1200  //--------------------------------------------------------------------------
-
1201 
-
1202  explicit RPCParser(beast::Journal j) : j_(j)
-
1203  {
-
1204  }
-
1205 
-
1206  //--------------------------------------------------------------------------
-
1207 
-
1208  // Convert a rpc method and params to a request.
-
1209  // <-- { method: xyz, params: [... ] } or { error: ..., ... }
-
1210  Json::Value
-
1211  parseCommand(
-
1212  std::string strMethod,
-
1213  Json::Value jvParams,
-
1214  bool allowAnyCommand)
-
1215  {
-
1216  if (auto stream = j_.trace())
-
1217  {
-
1218  stream << "Method: '" << strMethod << "'";
-
1219  stream << "Params: " << jvParams;
-
1220  }
+
1173  std::string param = jvParams[index++].asString();
+
1174  if (param.empty())
+
1175  return RPC::make_param_error("Invalid first parameter");
+
1176 
+
1177  if (param[0] != 'r')
+
1178  {
+
1179  if (param.size() == 64)
+
1180  jvRequest[jss::ledger_hash] = param;
+
1181  else
+
1182  jvRequest[jss::ledger_index] = param;
+
1183 
+
1184  if (size <= index)
+
1185  return RPC::make_param_error("Invalid hotwallet");
+
1186 
+
1187  param = jvParams[index++].asString();
+
1188  }
+
1189 
+
1190  jvRequest[jss::account] = param;
+
1191 
+
1192  if (index < size)
+
1193  {
+
1194  Json::Value& hotWallets =
+
1195  (jvRequest["hotwallet"] = Json::arrayValue);
+
1196  while (index < size)
+
1197  hotWallets.append(jvParams[index++].asString());
+
1198  }
+
1199 
+
1200  return jvRequest;
+
1201  }
+
1202 
+
1203  // server_info [counters]
+
1204  Json::Value
+
1205  parseServerInfo(Json::Value const& jvParams)
+
1206  {
+
1207  Json::Value jvRequest(Json::objectValue);
+
1208  if (jvParams.size() == 1 && jvParams[0u].asString() == "counters")
+
1209  jvRequest[jss::counters] = true;
+
1210  return jvRequest;
+
1211  }
+
1212 
+
1213 public:
+
1214  //--------------------------------------------------------------------------
+
1215 
+
1216  explicit RPCParser(beast::Journal j) : j_(j)
+
1217  {
+
1218  }
+
1219 
+
1220  //--------------------------------------------------------------------------
1221 
-
1222  struct Command
-
1223  {
-
1224  const char* name;
-
1225  parseFuncPtr parse;
-
1226  int minParams;
-
1227  int maxParams;
-
1228  };
-
1229 
-
1230  static constexpr Command commands[] = {
-
1231  // Request-response methods
-
1232  // - Returns an error, or the request.
-
1233  // - To modify the method, provide a new method in the request.
-
1234  {"account_currencies", &RPCParser::parseAccountCurrencies, 1, 3},
-
1235  {"account_info", &RPCParser::parseAccountItems, 1, 3},
-
1236  {"account_lines", &RPCParser::parseAccountLines, 1, 5},
-
1237  {"account_channels", &RPCParser::parseAccountChannels, 1, 3},
-
1238  {"account_nfts", &RPCParser::parseAccountItems, 1, 5},
-
1239  {"account_objects", &RPCParser::parseAccountItems, 1, 5},
-
1240  {"account_offers", &RPCParser::parseAccountItems, 1, 4},
-
1241  {"account_tx", &RPCParser::parseAccountTransactions, 1, 8},
-
1242  {"book_changes", &RPCParser::parseLedgerId, 1, 1},
-
1243  {"book_offers", &RPCParser::parseBookOffers, 2, 7},
-
1244  {"can_delete", &RPCParser::parseCanDelete, 0, 1},
-
1245  {"channel_authorize", &RPCParser::parseChannelAuthorize, 3, 4},
-
1246  {"channel_verify", &RPCParser::parseChannelVerify, 4, 4},
-
1247  {"connect", &RPCParser::parseConnect, 1, 2},
-
1248  {"consensus_info", &RPCParser::parseAsIs, 0, 0},
-
1249  {"deposit_authorized", &RPCParser::parseDepositAuthorized, 2, 3},
-
1250  {"download_shard", &RPCParser::parseDownloadShard, 2, -1},
-
1251  {"feature", &RPCParser::parseFeature, 0, 2},
-
1252  {"fetch_info", &RPCParser::parseFetchInfo, 0, 1},
-
1253  {"gateway_balances", &RPCParser::parseGatewayBalances, 1, -1},
-
1254  {"get_counts", &RPCParser::parseGetCounts, 0, 1},
-
1255  {"json", &RPCParser::parseJson, 2, 2},
-
1256  {"json2", &RPCParser::parseJson2, 1, 1},
-
1257  {"ledger", &RPCParser::parseLedger, 0, 2},
-
1258  {"ledger_accept", &RPCParser::parseAsIs, 0, 0},
-
1259  {"ledger_closed", &RPCParser::parseAsIs, 0, 0},
-
1260  {"ledger_current", &RPCParser::parseAsIs, 0, 0},
-
1261  // { "ledger_entry", &RPCParser::parseLedgerEntry,
-
1262  // -1, -1 },
-
1263  {"ledger_header", &RPCParser::parseLedgerId, 1, 1},
-
1264  {"ledger_request", &RPCParser::parseLedgerId, 1, 1},
-
1265  {"log_level", &RPCParser::parseLogLevel, 0, 2},
-
1266  {"logrotate", &RPCParser::parseAsIs, 0, 0},
-
1267  {"manifest", &RPCParser::parseManifest, 1, 1},
-
1268  {"node_to_shard", &RPCParser::parseNodeToShard, 1, 1},
-
1269  {"owner_info", &RPCParser::parseAccountItems, 1, 3},
-
1270  {"peers", &RPCParser::parseAsIs, 0, 0},
-
1271  {"ping", &RPCParser::parseAsIs, 0, 0},
-
1272  {"print", &RPCParser::parseAsIs, 0, 1},
-
1273  // { "profile", &RPCParser::parseProfile, 1, 9
-
1274  // },
-
1275  {"random", &RPCParser::parseAsIs, 0, 0},
-
1276  {"peer_reservations_add",
-
1277  &RPCParser::parsePeerReservationsAdd,
-
1278  1,
-
1279  2},
-
1280  {"peer_reservations_del",
-
1281  &RPCParser::parsePeerReservationsDel,
-
1282  1,
-
1283  1},
-
1284  {"peer_reservations_list", &RPCParser::parseAsIs, 0, 0},
-
1285  {"ripple_path_find", &RPCParser::parseRipplePathFind, 1, 2},
-
1286  {"sign", &RPCParser::parseSignSubmit, 2, 3},
-
1287  {"sign_for", &RPCParser::parseSignFor, 3, 4},
-
1288  {"submit", &RPCParser::parseSignSubmit, 1, 3},
-
1289  {"submit_multisigned", &RPCParser::parseSubmitMultiSigned, 1, 1},
-
1290  {"server_info", &RPCParser::parseServerInfo, 0, 1},
-
1291  {"server_state", &RPCParser::parseServerInfo, 0, 1},
-
1292  {"crawl_shards", &RPCParser::parseAsIs, 0, 2},
-
1293  {"stop", &RPCParser::parseAsIs, 0, 0},
-
1294  {"transaction_entry", &RPCParser::parseTransactionEntry, 2, 2},
-
1295  {"tx", &RPCParser::parseTx, 1, 4},
-
1296  {"tx_account", &RPCParser::parseTxAccount, 1, 7},
-
1297  {"tx_history", &RPCParser::parseTxHistory, 1, 1},
-
1298  {"unl_list", &RPCParser::parseAsIs, 0, 0},
-
1299  {"validation_create", &RPCParser::parseValidationCreate, 0, 1},
-
1300  {"validator_info", &RPCParser::parseAsIs, 0, 0},
-
1301  {"version", &RPCParser::parseAsIs, 0, 0},
-
1302  {"wallet_propose", &RPCParser::parseWalletPropose, 0, 1},
-
1303  {"internal", &RPCParser::parseInternal, 1, -1},
-
1304 
-
1305  // Evented methods
-
1306  {"path_find", &RPCParser::parseEvented, -1, -1},
-
1307  {"subscribe", &RPCParser::parseEvented, -1, -1},
-
1308  {"unsubscribe", &RPCParser::parseEvented, -1, -1},
-
1309  };
-
1310 
-
1311  auto const count = jvParams.size();
-
1312 
-
1313  for (auto const& command : commands)
-
1314  {
-
1315  if (strMethod == command.name)
-
1316  {
-
1317  if ((command.minParams >= 0 && count < command.minParams) ||
-
1318  (command.maxParams >= 0 && count > command.maxParams))
-
1319  {
-
1320  JLOG(j_.debug())
-
1321  << "Wrong number of parameters for " << command.name
-
1322  << " minimum=" << command.minParams
-
1323  << " maximum=" << command.maxParams
-
1324  << " actual=" << count;
-
1325 
-
1326  return rpcError(rpcBAD_SYNTAX);
-
1327  }
-
1328 
-
1329  return (this->*(command.parse))(jvParams);
-
1330  }
-
1331  }
-
1332 
-
1333  // The command could not be found
-
1334  if (!allowAnyCommand)
-
1335  return rpcError(rpcUNKNOWN_COMMAND);
-
1336 
-
1337  return parseAsIs(jvParams);
-
1338  }
-
1339 };
-
1340 
-
1341 //------------------------------------------------------------------------------
+
1222  // Convert a rpc method and params to a request.
+
1223  // <-- { method: xyz, params: [... ] } or { error: ..., ... }
+
1224  Json::Value
+
1225  parseCommand(
+
1226  std::string strMethod,
+
1227  Json::Value jvParams,
+
1228  bool allowAnyCommand)
+
1229  {
+
1230  if (auto stream = j_.trace())
+
1231  {
+
1232  stream << "Method: '" << strMethod << "'";
+
1233  stream << "Params: " << jvParams;
+
1234  }
+
1235 
+
1236  struct Command
+
1237  {
+
1238  const char* name;
+
1239  parseFuncPtr parse;
+
1240  int minParams;
+
1241  int maxParams;
+
1242  };
+
1243 
+
1244  static constexpr Command commands[] = {
+
1245  // Request-response methods
+
1246  // - Returns an error, or the request.
+
1247  // - To modify the method, provide a new method in the request.
+
1248  {"account_currencies", &RPCParser::parseAccountCurrencies, 1, 3},
+
1249  {"account_info", &RPCParser::parseAccountItems, 1, 3},
+
1250  {"account_lines", &RPCParser::parseAccountLines, 1, 5},
+
1251  {"account_channels", &RPCParser::parseAccountChannels, 1, 3},
+
1252  {"account_nfts", &RPCParser::parseAccountItems, 1, 5},
+
1253  {"account_objects", &RPCParser::parseAccountItems, 1, 5},
+
1254  {"account_offers", &RPCParser::parseAccountItems, 1, 4},
+
1255  {"account_tx", &RPCParser::parseAccountTransactions, 1, 8},
+
1256  {"book_changes", &RPCParser::parseLedgerId, 1, 1},
+
1257  {"book_offers", &RPCParser::parseBookOffers, 2, 7},
+
1258  {"can_delete", &RPCParser::parseCanDelete, 0, 1},
+
1259  {"channel_authorize", &RPCParser::parseChannelAuthorize, 3, 4},
+
1260  {"channel_verify", &RPCParser::parseChannelVerify, 4, 4},
+
1261  {"connect", &RPCParser::parseConnect, 1, 2},
+
1262  {"consensus_info", &RPCParser::parseAsIs, 0, 0},
+
1263  {"deposit_authorized", &RPCParser::parseDepositAuthorized, 2, 3},
+
1264  {"download_shard", &RPCParser::parseDownloadShard, 2, -1},
+
1265  {"feature", &RPCParser::parseFeature, 0, 2},
+
1266  {"fetch_info", &RPCParser::parseFetchInfo, 0, 1},
+
1267  {"gateway_balances", &RPCParser::parseGatewayBalances, 1, -1},
+
1268  {"get_counts", &RPCParser::parseGetCounts, 0, 1},
+
1269  {"json", &RPCParser::parseJson, 2, 2},
+
1270  {"json2", &RPCParser::parseJson2, 1, 1},
+
1271  {"ledger", &RPCParser::parseLedger, 0, 2},
+
1272  {"ledger_accept", &RPCParser::parseAsIs, 0, 0},
+
1273  {"ledger_closed", &RPCParser::parseAsIs, 0, 0},
+
1274  {"ledger_current", &RPCParser::parseAsIs, 0, 0},
+
1275  // { "ledger_entry", &RPCParser::parseLedgerEntry,
+
1276  // -1, -1 },
+
1277  {"ledger_header", &RPCParser::parseLedgerId, 1, 1},
+
1278  {"ledger_request", &RPCParser::parseLedgerId, 1, 1},
+
1279  {"log_level", &RPCParser::parseLogLevel, 0, 2},
+
1280  {"logrotate", &RPCParser::parseAsIs, 0, 0},
+
1281  {"manifest", &RPCParser::parseManifest, 1, 1},
+
1282  {"node_to_shard", &RPCParser::parseNodeToShard, 1, 1},
+
1283  {"owner_info", &RPCParser::parseAccountItems, 1, 3},
+
1284  {"peers", &RPCParser::parseAsIs, 0, 0},
+
1285  {"ping", &RPCParser::parseAsIs, 0, 0},
+
1286  {"print", &RPCParser::parseAsIs, 0, 1},
+
1287  // { "profile", &RPCParser::parseProfile, 1, 9
+
1288  // },
+
1289  {"random", &RPCParser::parseAsIs, 0, 0},
+
1290  {"peer_reservations_add",
+
1291  &RPCParser::parsePeerReservationsAdd,
+
1292  1,
+
1293  2},
+
1294  {"peer_reservations_del",
+
1295  &RPCParser::parsePeerReservationsDel,
+
1296  1,
+
1297  1},
+
1298  {"peer_reservations_list", &RPCParser::parseAsIs, 0, 0},
+
1299  {"ripple_path_find", &RPCParser::parseRipplePathFind, 1, 2},
+
1300  {"sign", &RPCParser::parseSignSubmit, 2, 3},
+
1301  {"sign_for", &RPCParser::parseSignFor, 3, 4},
+
1302  {"submit", &RPCParser::parseSignSubmit, 1, 3},
+
1303  {"submit_multisigned", &RPCParser::parseSubmitMultiSigned, 1, 1},
+
1304  {"server_info", &RPCParser::parseServerInfo, 0, 1},
+
1305  {"server_state", &RPCParser::parseServerInfo, 0, 1},
+
1306  {"crawl_shards", &RPCParser::parseAsIs, 0, 2},
+
1307  {"stop", &RPCParser::parseAsIs, 0, 0},
+
1308  {"transaction_entry", &RPCParser::parseTransactionEntry, 2, 2},
+
1309  {"tx", &RPCParser::parseTx, 1, 4},
+
1310  {"tx_account", &RPCParser::parseTxAccount, 1, 7},
+
1311  {"tx_history", &RPCParser::parseTxHistory, 1, 1},
+
1312  {"unl_list", &RPCParser::parseAsIs, 0, 0},
+
1313  {"validation_create", &RPCParser::parseValidationCreate, 0, 1},
+
1314  {"validator_info", &RPCParser::parseAsIs, 0, 0},
+
1315  {"version", &RPCParser::parseAsIs, 0, 0},
+
1316  {"wallet_propose", &RPCParser::parseWalletPropose, 0, 1},
+
1317  {"internal", &RPCParser::parseInternal, 1, -1},
+
1318 
+
1319  // Evented methods
+
1320  {"path_find", &RPCParser::parseEvented, -1, -1},
+
1321  {"subscribe", &RPCParser::parseEvented, -1, -1},
+
1322  {"unsubscribe", &RPCParser::parseEvented, -1, -1},
+
1323  };
+
1324 
+
1325  auto const count = jvParams.size();
+
1326 
+
1327  for (auto const& command : commands)
+
1328  {
+
1329  if (strMethod == command.name)
+
1330  {
+
1331  if ((command.minParams >= 0 && count < command.minParams) ||
+
1332  (command.maxParams >= 0 && count > command.maxParams))
+
1333  {
+
1334  JLOG(j_.debug())
+
1335  << "Wrong number of parameters for " << command.name
+
1336  << " minimum=" << command.minParams
+
1337  << " maximum=" << command.maxParams
+
1338  << " actual=" << count;
+
1339 
+
1340  return rpcError(rpcBAD_SYNTAX);
+
1341  }
1342 
-
1343 //
-
1344 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
-
1345 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
-
1346 // unspecified (HTTP errors and contents of 'error').
-
1347 //
-
1348 // 1.0 spec: http://json-rpc.org/wiki/specification
-
1349 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
-
1350 //
-
1351 
-
1352 std::string
-
1353 JSONRPCRequest(
-
1354  std::string const& strMethod,
-
1355  Json::Value const& params,
-
1356  Json::Value const& id)
-
1357 {
-
1358  Json::Value request;
-
1359  request[jss::method] = strMethod;
-
1360  request[jss::params] = params;
-
1361  request[jss::id] = id;
-
1362  return to_string(request) + "\n";
-
1363 }
-
1364 
-
1365 namespace {
-
1366 // Special local exception type thrown when request can't be parsed.
-
1367 class RequestNotParseable : public std::runtime_error
-
1368 {
-
1369  using std::runtime_error::runtime_error; // Inherit constructors
-
1370 };
-
1371 }; // namespace
-
1372 
-
1373 struct RPCCallImp
-
1374 {
-
1375  explicit RPCCallImp() = default;
-
1376 
-
1377  // VFALCO NOTE Is this a to-do comment or a doc comment?
-
1378  // Place the async result somewhere useful.
-
1379  static void
-
1380  callRPCHandler(Json::Value* jvOutput, Json::Value const& jvInput)
-
1381  {
-
1382  (*jvOutput) = jvInput;
-
1383  }
-
1384 
-
1385  static bool
-
1386  onResponse(
-
1387  std::function<void(Json::Value const& jvInput)> callbackFuncP,
-
1388  const boost::system::error_code& ecResult,
-
1389  int iStatus,
-
1390  std::string const& strData,
-
1391  beast::Journal j)
-
1392  {
-
1393  if (callbackFuncP)
-
1394  {
-
1395  // Only care about the result, if we care to deliver it
-
1396  // callbackFuncP.
-
1397 
-
1398  // Receive reply
-
1399  if (strData.empty())
-
1400  Throw<std::runtime_error>("no response from server");
-
1401 
-
1402  // Parse reply
-
1403  JLOG(j.debug()) << "RPC reply: " << strData << std::endl;
-
1404  if (strData.find("Unable to parse request") == 0 ||
-
1405  strData.find(jss::invalid_API_version.c_str()) == 0)
-
1406  Throw<RequestNotParseable>(strData);
-
1407  Json::Reader reader;
-
1408  Json::Value jvReply;
-
1409  if (!reader.parse(strData, jvReply))
-
1410  Throw<std::runtime_error>("couldn't parse reply from server");
+
1343  return (this->*(command.parse))(jvParams);
+
1344  }
+
1345  }
+
1346 
+
1347  // The command could not be found
+
1348  if (!allowAnyCommand)
+
1349  return rpcError(rpcUNKNOWN_COMMAND);
+
1350 
+
1351  return parseAsIs(jvParams);
+
1352  }
+
1353 };
+
1354 
+
1355 //------------------------------------------------------------------------------
+
1356 
+
1357 //
+
1358 // JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
+
1359 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
+
1360 // unspecified (HTTP errors and contents of 'error').
+
1361 //
+
1362 // 1.0 spec: http://json-rpc.org/wiki/specification
+
1363 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
+
1364 //
+
1365 
+
1366 std::string
+
1367 JSONRPCRequest(
+
1368  std::string const& strMethod,
+
1369  Json::Value const& params,
+
1370  Json::Value const& id)
+
1371 {
+
1372  Json::Value request;
+
1373  request[jss::method] = strMethod;
+
1374  request[jss::params] = params;
+
1375  request[jss::id] = id;
+
1376  return to_string(request) + "\n";
+
1377 }
+
1378 
+
1379 namespace {
+
1380 // Special local exception type thrown when request can't be parsed.
+
1381 class RequestNotParseable : public std::runtime_error
+
1382 {
+
1383  using std::runtime_error::runtime_error; // Inherit constructors
+
1384 };
+
1385 }; // namespace
+
1386 
+
1387 struct RPCCallImp
+
1388 {
+
1389  explicit RPCCallImp() = default;
+
1390 
+
1391  // VFALCO NOTE Is this a to-do comment or a doc comment?
+
1392  // Place the async result somewhere useful.
+
1393  static void
+
1394  callRPCHandler(Json::Value* jvOutput, Json::Value const& jvInput)
+
1395  {
+
1396  (*jvOutput) = jvInput;
+
1397  }
+
1398 
+
1399  static bool
+
1400  onResponse(
+
1401  std::function<void(Json::Value const& jvInput)> callbackFuncP,
+
1402  const boost::system::error_code& ecResult,
+
1403  int iStatus,
+
1404  std::string const& strData,
+
1405  beast::Journal j)
+
1406  {
+
1407  if (callbackFuncP)
+
1408  {
+
1409  // Only care about the result, if we care to deliver it
+
1410  // callbackFuncP.
1411 
-
1412  if (!jvReply)
-
1413  Throw<std::runtime_error>(
-
1414  "expected reply to have result, error and id properties");
+
1412  // Receive reply
+
1413  if (strData.empty())
+
1414  Throw<std::runtime_error>("no response from server");
1415 
-
1416  Json::Value jvResult(Json::objectValue);
-
1417 
-
1418  jvResult["result"] = jvReply;
-
1419 
-
1420  (callbackFuncP)(jvResult);
-
1421  }
-
1422 
-
1423  return false;
-
1424  }
+
1416  // Parse reply
+
1417  JLOG(j.debug()) << "RPC reply: " << strData << std::endl;
+
1418  if (strData.find("Unable to parse request") == 0 ||
+
1419  strData.find(jss::invalid_API_version.c_str()) == 0)
+
1420  Throw<RequestNotParseable>(strData);
+
1421  Json::Reader reader;
+
1422  Json::Value jvReply;
+
1423  if (!reader.parse(strData, jvReply))
+
1424  Throw<std::runtime_error>("couldn't parse reply from server");
1425 
-
1426  // Build the request.
-
1427  static void
-
1428  onRequest(
-
1429  std::string const& strMethod,
-
1430  Json::Value const& jvParams,
-
1431  std::unordered_map<std::string, std::string> const& headers,
-
1432  std::string const& strPath,
-
1433  boost::asio::streambuf& sb,
-
1434  std::string const& strHost,
-
1435  beast::Journal j)
-
1436  {
-
1437  JLOG(j.debug()) << "requestRPC: strPath='" << strPath << "'";
-
1438 
-
1439  std::ostream osRequest(&sb);
-
1440  osRequest << createHTTPPost(
-
1441  strHost,
-
1442  strPath,
-
1443  JSONRPCRequest(strMethod, jvParams, Json::Value(1)),
-
1444  headers);
-
1445  }
-
1446 };
-
1447 
-
1448 //------------------------------------------------------------------------------
-
1449 
-
1450 // Used internally by rpcClient.
-
1451 static Json::Value
-
1452 rpcCmdLineToJson(
-
1453  std::vector<std::string> const& args,
-
1454  Json::Value& retParams,
-
1455  beast::Journal j)
-
1456 {
-
1457  Json::Value jvRequest(Json::objectValue);
-
1458 
-
1459  RPCParser rpParser(j);
-
1460  Json::Value jvRpcParams(Json::arrayValue);
+
1426  if (!jvReply)
+
1427  Throw<std::runtime_error>(
+
1428  "expected reply to have result, error and id properties");
+
1429 
+
1430  Json::Value jvResult(Json::objectValue);
+
1431 
+
1432  jvResult["result"] = jvReply;
+
1433 
+
1434  (callbackFuncP)(jvResult);
+
1435  }
+
1436 
+
1437  return false;
+
1438  }
+
1439 
+
1440  // Build the request.
+
1441  static void
+
1442  onRequest(
+
1443  std::string const& strMethod,
+
1444  Json::Value const& jvParams,
+
1445  std::unordered_map<std::string, std::string> const& headers,
+
1446  std::string const& strPath,
+
1447  boost::asio::streambuf& sb,
+
1448  std::string const& strHost,
+
1449  beast::Journal j)
+
1450  {
+
1451  JLOG(j.debug()) << "requestRPC: strPath='" << strPath << "'";
+
1452 
+
1453  std::ostream osRequest(&sb);
+
1454  osRequest << createHTTPPost(
+
1455  strHost,
+
1456  strPath,
+
1457  JSONRPCRequest(strMethod, jvParams, Json::Value(1)),
+
1458  headers);
+
1459  }
+
1460 };
1461 
-
1462  for (int i = 1; i != args.size(); i++)
-
1463  jvRpcParams.append(args[i]);
-
1464 
-
1465  retParams = Json::Value(Json::objectValue);
-
1466 
-
1467  retParams[jss::method] = args[0];
-
1468  retParams[jss::params] = jvRpcParams;
-
1469 
-
1470  jvRequest = rpParser.parseCommand(args[0], jvRpcParams, true);
-
1471 
-
1472  auto insert_api_version = [](Json::Value& jr) {
-
1473  if (jr.isObject() && !jr.isMember(jss::error) &&
-
1474  !jr.isMember(jss::api_version))
-
1475  {
-
1476  jr[jss::api_version] = RPC::apiMaximumSupportedVersion;
-
1477  }
-
1478  };
-
1479 
-
1480  if (jvRequest.isObject())
-
1481  insert_api_version(jvRequest);
-
1482  else if (jvRequest.isArray())
-
1483  std::for_each(jvRequest.begin(), jvRequest.end(), insert_api_version);
-
1484 
-
1485  JLOG(j.trace()) << "RPC Request: " << jvRequest << std::endl;
-
1486  return jvRequest;
-
1487 }
-
1488 
-
1489 Json::Value
-
1490 cmdLineToJSONRPC(std::vector<std::string> const& args, beast::Journal j)
-
1491 {
-
1492  Json::Value jv = Json::Value(Json::objectValue);
-
1493  auto const paramsObj = rpcCmdLineToJson(args, jv, j);
-
1494 
-
1495  // Re-use jv to return our formatted result.
-
1496  jv.clear();
-
1497 
-
1498  // Allow parser to rewrite method.
-
1499  jv[jss::method] = paramsObj.isMember(jss::method)
-
1500  ? paramsObj[jss::method].asString()
-
1501  : args[0];
+
1462 //------------------------------------------------------------------------------
+
1463 
+
1464 // Used internally by rpcClient.
+
1465 static Json::Value
+
1466 rpcCmdLineToJson(
+
1467  std::vector<std::string> const& args,
+
1468  Json::Value& retParams,
+
1469  beast::Journal j)
+
1470 {
+
1471  Json::Value jvRequest(Json::objectValue);
+
1472 
+
1473  RPCParser rpParser(j);
+
1474  Json::Value jvRpcParams(Json::arrayValue);
+
1475 
+
1476  for (int i = 1; i != args.size(); i++)
+
1477  jvRpcParams.append(args[i]);
+
1478 
+
1479  retParams = Json::Value(Json::objectValue);
+
1480 
+
1481  retParams[jss::method] = args[0];
+
1482  retParams[jss::params] = jvRpcParams;
+
1483 
+
1484  jvRequest = rpParser.parseCommand(args[0], jvRpcParams, true);
+
1485 
+
1486  auto insert_api_version = [](Json::Value& jr) {
+
1487  if (jr.isObject() && !jr.isMember(jss::error) &&
+
1488  !jr.isMember(jss::api_version))
+
1489  {
+
1490  jr[jss::api_version] = RPC::apiMaximumSupportedVersion;
+
1491  }
+
1492  };
+
1493 
+
1494  if (jvRequest.isObject())
+
1495  insert_api_version(jvRequest);
+
1496  else if (jvRequest.isArray())
+
1497  std::for_each(jvRequest.begin(), jvRequest.end(), insert_api_version);
+
1498 
+
1499  JLOG(j.trace()) << "RPC Request: " << jvRequest << std::endl;
+
1500  return jvRequest;
+
1501 }
1502 
-
1503  // If paramsObj is not empty, put it in a [params] array.
-
1504  if (paramsObj.begin() != paramsObj.end())
-
1505  {
-
1506  auto& paramsArray = Json::setArray(jv, jss::params);
-
1507  paramsArray.append(paramsObj);
-
1508  }
-
1509  if (paramsObj.isMember(jss::jsonrpc))
-
1510  jv[jss::jsonrpc] = paramsObj[jss::jsonrpc];
-
1511  if (paramsObj.isMember(jss::ripplerpc))
-
1512  jv[jss::ripplerpc] = paramsObj[jss::ripplerpc];
-
1513  if (paramsObj.isMember(jss::id))
-
1514  jv[jss::id] = paramsObj[jss::id];
-
1515  return jv;
-
1516 }
-
1517 
-
1518 //------------------------------------------------------------------------------
-
1519 
-
1520 std::pair<int, Json::Value>
-
1521 rpcClient(
-
1522  std::vector<std::string> const& args,
-
1523  Config const& config,
-
1524  Logs& logs,
-
1525  std::unordered_map<std::string, std::string> const& headers)
-
1526 {
-
1527  static_assert(
-
1528  rpcBAD_SYNTAX == 1 && rpcSUCCESS == 0,
-
1529  "Expect specific rpc enum values.");
-
1530  if (args.empty())
-
1531  return {rpcBAD_SYNTAX, {}}; // rpcBAD_SYNTAX = print usage
-
1532 
-
1533  int nRet = rpcSUCCESS;
-
1534  Json::Value jvOutput;
-
1535  Json::Value jvRequest(Json::objectValue);
-
1536 
-
1537  try
-
1538  {
-
1539  Json::Value jvRpc = Json::Value(Json::objectValue);
-
1540  jvRequest = rpcCmdLineToJson(args, jvRpc, logs.journal("RPCParser"));
-
1541 
-
1542  if (jvRequest.isMember(jss::error))
-
1543  {
-
1544  jvOutput = jvRequest;
-
1545  jvOutput["rpc"] = jvRpc;
-
1546  }
-
1547  else
-
1548  {
-
1549  ServerHandler::Setup setup;
-
1550  try
-
1551  {
-
1552  setup = setup_ServerHandler(
-
1553  config,
-
1554  beast::logstream{logs.journal("HTTPClient").warn()});
-
1555  }
-
1556  catch (std::exception const&)
-
1557  {
-
1558  // ignore any exceptions, so the command
-
1559  // line client works without a config file
-
1560  }
-
1561 
-
1562  if (config.rpc_ip)
-
1563  {
-
1564  setup.client.ip = config.rpc_ip->address().to_string();
-
1565  setup.client.port = config.rpc_ip->port();
-
1566  }
-
1567 
-
1568  Json::Value jvParams(Json::arrayValue);
-
1569 
-
1570  if (!setup.client.admin_user.empty())
-
1571  jvRequest["admin_user"] = setup.client.admin_user;
-
1572 
-
1573  if (!setup.client.admin_password.empty())
-
1574  jvRequest["admin_password"] = setup.client.admin_password;
+
1503 Json::Value
+
1504 cmdLineToJSONRPC(std::vector<std::string> const& args, beast::Journal j)
+
1505 {
+
1506  Json::Value jv = Json::Value(Json::objectValue);
+
1507  auto const paramsObj = rpcCmdLineToJson(args, jv, j);
+
1508 
+
1509  // Re-use jv to return our formatted result.
+
1510  jv.clear();
+
1511 
+
1512  // Allow parser to rewrite method.
+
1513  jv[jss::method] = paramsObj.isMember(jss::method)
+
1514  ? paramsObj[jss::method].asString()
+
1515  : args[0];
+
1516 
+
1517  // If paramsObj is not empty, put it in a [params] array.
+
1518  if (paramsObj.begin() != paramsObj.end())
+
1519  {
+
1520  auto& paramsArray = Json::setArray(jv, jss::params);
+
1521  paramsArray.append(paramsObj);
+
1522  }
+
1523  if (paramsObj.isMember(jss::jsonrpc))
+
1524  jv[jss::jsonrpc] = paramsObj[jss::jsonrpc];
+
1525  if (paramsObj.isMember(jss::ripplerpc))
+
1526  jv[jss::ripplerpc] = paramsObj[jss::ripplerpc];
+
1527  if (paramsObj.isMember(jss::id))
+
1528  jv[jss::id] = paramsObj[jss::id];
+
1529  return jv;
+
1530 }
+
1531 
+
1532 //------------------------------------------------------------------------------
+
1533 
+
1534 std::pair<int, Json::Value>
+
1535 rpcClient(
+
1536  std::vector<std::string> const& args,
+
1537  Config const& config,
+
1538  Logs& logs,
+
1539  std::unordered_map<std::string, std::string> const& headers)
+
1540 {
+
1541  static_assert(
+
1542  rpcBAD_SYNTAX == 1 && rpcSUCCESS == 0,
+
1543  "Expect specific rpc enum values.");
+
1544  if (args.empty())
+
1545  return {rpcBAD_SYNTAX, {}}; // rpcBAD_SYNTAX = print usage
+
1546 
+
1547  int nRet = rpcSUCCESS;
+
1548  Json::Value jvOutput;
+
1549  Json::Value jvRequest(Json::objectValue);
+
1550 
+
1551  try
+
1552  {
+
1553  Json::Value jvRpc = Json::Value(Json::objectValue);
+
1554  jvRequest = rpcCmdLineToJson(args, jvRpc, logs.journal("RPCParser"));
+
1555 
+
1556  if (jvRequest.isMember(jss::error))
+
1557  {
+
1558  jvOutput = jvRequest;
+
1559  jvOutput["rpc"] = jvRpc;
+
1560  }
+
1561  else
+
1562  {
+
1563  ServerHandler::Setup setup;
+
1564  try
+
1565  {
+
1566  setup = setup_ServerHandler(
+
1567  config,
+
1568  beast::logstream{logs.journal("HTTPClient").warn()});
+
1569  }
+
1570  catch (std::exception const&)
+
1571  {
+
1572  // ignore any exceptions, so the command
+
1573  // line client works without a config file
+
1574  }
1575 
-
1576  if (jvRequest.isObject())
-
1577  jvParams.append(jvRequest);
-
1578  else if (jvRequest.isArray())
-
1579  {
-
1580  for (Json::UInt i = 0; i < jvRequest.size(); ++i)
-
1581  jvParams.append(jvRequest[i]);
-
1582  }
+
1576  if (config.rpc_ip)
+
1577  {
+
1578  setup.client.ip = config.rpc_ip->address().to_string();
+
1579  setup.client.port = config.rpc_ip->port();
+
1580  }
+
1581 
+
1582  Json::Value jvParams(Json::arrayValue);
1583 
-
1584  {
-
1585  boost::asio::io_service isService;
-
1586  RPCCall::fromNetwork(
-
1587  isService,
-
1588  setup.client.ip,
-
1589  setup.client.port,
-
1590  setup.client.user,
-
1591  setup.client.password,
-
1592  "",
-
1593  jvRequest.isMember(
-
1594  jss::method) // Allow parser to rewrite method.
-
1595  ? jvRequest[jss::method].asString()
-
1596  : jvRequest.isArray() ? "batch" : args[0],
-
1597  jvParams, // Parsed, execute.
-
1598  setup.client.secure != 0, // Use SSL
-
1599  config.quiet(),
-
1600  logs,
-
1601  std::bind(
-
1602  RPCCallImp::callRPCHandler,
-
1603  &jvOutput,
-
1604  std::placeholders::_1),
-
1605  headers);
-
1606  isService.run(); // This blocks until there are no more
-
1607  // outstanding async calls.
-
1608  }
-
1609  if (jvOutput.isMember("result"))
-
1610  {
-
1611  // Had a successful JSON-RPC 2.0 call.
-
1612  jvOutput = jvOutput["result"];
-
1613 
-
1614  // jvOutput may report a server side error.
-
1615  // It should report "status".
-
1616  }
-
1617  else
-
1618  {
-
1619  // Transport error.
-
1620  Json::Value jvRpcError = jvOutput;
-
1621 
-
1622  jvOutput = rpcError(rpcJSON_RPC);
-
1623  jvOutput["result"] = jvRpcError;
-
1624  }
-
1625 
-
1626  // If had an error, supply invocation in result.
-
1627  if (jvOutput.isMember(jss::error))
-
1628  {
-
1629  jvOutput["rpc"] =
-
1630  jvRpc; // How the command was seen as method + params.
-
1631  jvOutput["request_sent"] =
-
1632  jvRequest; // How the command was translated.
-
1633  }
-
1634  }
+
1584  if (!setup.client.admin_user.empty())
+
1585  jvRequest["admin_user"] = setup.client.admin_user;
+
1586 
+
1587  if (!setup.client.admin_password.empty())
+
1588  jvRequest["admin_password"] = setup.client.admin_password;
+
1589 
+
1590  if (jvRequest.isObject())
+
1591  jvParams.append(jvRequest);
+
1592  else if (jvRequest.isArray())
+
1593  {
+
1594  for (Json::UInt i = 0; i < jvRequest.size(); ++i)
+
1595  jvParams.append(jvRequest[i]);
+
1596  }
+
1597 
+
1598  {
+
1599  boost::asio::io_service isService;
+
1600  RPCCall::fromNetwork(
+
1601  isService,
+
1602  setup.client.ip,
+
1603  setup.client.port,
+
1604  setup.client.user,
+
1605  setup.client.password,
+
1606  "",
+
1607  jvRequest.isMember(
+
1608  jss::method) // Allow parser to rewrite method.
+
1609  ? jvRequest[jss::method].asString()
+
1610  : jvRequest.isArray() ? "batch" : args[0],
+
1611  jvParams, // Parsed, execute.
+
1612  setup.client.secure != 0, // Use SSL
+
1613  config.quiet(),
+
1614  logs,
+
1615  std::bind(
+
1616  RPCCallImp::callRPCHandler,
+
1617  &jvOutput,
+
1618  std::placeholders::_1),
+
1619  headers);
+
1620  isService.run(); // This blocks until there are no more
+
1621  // outstanding async calls.
+
1622  }
+
1623  if (jvOutput.isMember("result"))
+
1624  {
+
1625  // Had a successful JSON-RPC 2.0 call.
+
1626  jvOutput = jvOutput["result"];
+
1627 
+
1628  // jvOutput may report a server side error.
+
1629  // It should report "status".
+
1630  }
+
1631  else
+
1632  {
+
1633  // Transport error.
+
1634  Json::Value jvRpcError = jvOutput;
1635 
-
1636  if (jvOutput.isMember(jss::error))
-
1637  {
-
1638  jvOutput[jss::status] = "error";
-
1639  if (jvOutput.isMember(jss::error_code))
-
1640  nRet = std::stoi(jvOutput[jss::error_code].asString());
-
1641  else if (jvOutput[jss::error].isMember(jss::error_code))
-
1642  nRet =
-
1643  std::stoi(jvOutput[jss::error][jss::error_code].asString());
-
1644  else
-
1645  nRet = rpcBAD_SYNTAX;
-
1646  }
-
1647 
-
1648  // YYY We could have a command line flag for single line output for
-
1649  // scripts. YYY We would intercept output here and simplify it.
-
1650  }
-
1651  catch (RequestNotParseable& e)
-
1652  {
-
1653  jvOutput = rpcError(rpcINVALID_PARAMS);
-
1654  jvOutput["error_what"] = e.what();
-
1655  nRet = rpcINVALID_PARAMS;
-
1656  }
-
1657  catch (std::exception& e)
-
1658  {
-
1659  jvOutput = rpcError(rpcINTERNAL);
-
1660  jvOutput["error_what"] = e.what();
-
1661  nRet = rpcINTERNAL;
-
1662  }
-
1663 
-
1664  return {nRet, std::move(jvOutput)};
-
1665 }
-
1666 
-
1667 //------------------------------------------------------------------------------
-
1668 
-
1669 namespace RPCCall {
-
1670 
-
1671 int
-
1672 fromCommandLine(
-
1673  Config const& config,
-
1674  const std::vector<std::string>& vCmd,
-
1675  Logs& logs)
-
1676 {
-
1677  auto const result = rpcClient(vCmd, config, logs);
-
1678 
-
1679  std::cout << result.second.toStyledString();
+
1636  jvOutput = rpcError(rpcJSON_RPC);
+
1637  jvOutput["result"] = jvRpcError;
+
1638  }
+
1639 
+
1640  // If had an error, supply invocation in result.
+
1641  if (jvOutput.isMember(jss::error))
+
1642  {
+
1643  jvOutput["rpc"] =
+
1644  jvRpc; // How the command was seen as method + params.
+
1645  jvOutput["request_sent"] =
+
1646  jvRequest; // How the command was translated.
+
1647  }
+
1648  }
+
1649 
+
1650  if (jvOutput.isMember(jss::error))
+
1651  {
+
1652  jvOutput[jss::status] = "error";
+
1653  if (jvOutput.isMember(jss::error_code))
+
1654  nRet = std::stoi(jvOutput[jss::error_code].asString());
+
1655  else if (jvOutput[jss::error].isMember(jss::error_code))
+
1656  nRet =
+
1657  std::stoi(jvOutput[jss::error][jss::error_code].asString());
+
1658  else
+
1659  nRet = rpcBAD_SYNTAX;
+
1660  }
+
1661 
+
1662  // YYY We could have a command line flag for single line output for
+
1663  // scripts. YYY We would intercept output here and simplify it.
+
1664  }
+
1665  catch (RequestNotParseable& e)
+
1666  {
+
1667  jvOutput = rpcError(rpcINVALID_PARAMS);
+
1668  jvOutput["error_what"] = e.what();
+
1669  nRet = rpcINVALID_PARAMS;
+
1670  }
+
1671  catch (std::exception& e)
+
1672  {
+
1673  jvOutput = rpcError(rpcINTERNAL);
+
1674  jvOutput["error_what"] = e.what();
+
1675  nRet = rpcINTERNAL;
+
1676  }
+
1677 
+
1678  return {nRet, std::move(jvOutput)};
+
1679 }
1680 
-
1681  return result.first;
-
1682 }
-
1683 
-
1684 //------------------------------------------------------------------------------
-
1685 
-
1686 void
-
1687 fromNetwork(
-
1688  boost::asio::io_service& io_service,
-
1689  std::string const& strIp,
-
1690  const std::uint16_t iPort,
-
1691  std::string const& strUsername,
-
1692  std::string const& strPassword,
-
1693  std::string const& strPath,
-
1694  std::string const& strMethod,
-
1695  Json::Value const& jvParams,
-
1696  const bool bSSL,
-
1697  const bool quiet,
-
1698  Logs& logs,
-
1699  std::function<void(Json::Value const& jvInput)> callbackFuncP,
-
1700  std::unordered_map<std::string, std::string> headers)
-
1701 {
-
1702  auto j = logs.journal("HTTPClient");
-
1703 
-
1704  // Connect to localhost
-
1705  if (!quiet)
-
1706  {
-
1707  JLOG(j.info()) << (bSSL ? "Securely connecting to " : "Connecting to ")
-
1708  << strIp << ":" << iPort << std::endl;
-
1709  }
-
1710 
-
1711  // HTTP basic authentication
-
1712  headers["Authorization"] =
-
1713  std::string("Basic ") + base64_encode(strUsername + ":" + strPassword);
-
1714 
-
1715  // Send request
-
1716 
-
1717  // Number of bytes to try to receive if no
-
1718  // Content-Length header received
-
1719  constexpr auto RPC_REPLY_MAX_BYTES = megabytes(256);
-
1720 
-
1721  using namespace std::chrono_literals;
-
1722  auto constexpr RPC_NOTIFY = 10min;
-
1723 
-
1724  HTTPClient::request(
-
1725  bSSL,
-
1726  io_service,
-
1727  strIp,
-
1728  iPort,
-
1729  std::bind(
-
1730  &RPCCallImp::onRequest,
-
1731  strMethod,
-
1732  jvParams,
-
1733  headers,
-
1734  strPath,
-
1735  std::placeholders::_1,
-
1736  std::placeholders::_2,
-
1737  j),
-
1738  RPC_REPLY_MAX_BYTES,
-
1739  RPC_NOTIFY,
-
1740  std::bind(
-
1741  &RPCCallImp::onResponse,
-
1742  callbackFuncP,
-
1743  std::placeholders::_1,
-
1744  std::placeholders::_2,
-
1745  std::placeholders::_3,
-
1746  j),
-
1747  j);
-
1748 }
-
1749 
-
1750 } // namespace RPCCall
-
1751 
-
1752 } // namespace ripple
+
1681 //------------------------------------------------------------------------------
+
1682 
+
1683 namespace RPCCall {
+
1684 
+
1685 int
+
1686 fromCommandLine(
+
1687  Config const& config,
+
1688  const std::vector<std::string>& vCmd,
+
1689  Logs& logs)
+
1690 {
+
1691  auto const result = rpcClient(vCmd, config, logs);
+
1692 
+
1693  std::cout << result.second.toStyledString();
+
1694 
+
1695  return result.first;
+
1696 }
+
1697 
+
1698 //------------------------------------------------------------------------------
+
1699 
+
1700 void
+
1701 fromNetwork(
+
1702  boost::asio::io_service& io_service,
+
1703  std::string const& strIp,
+
1704  const std::uint16_t iPort,
+
1705  std::string const& strUsername,
+
1706  std::string const& strPassword,
+
1707  std::string const& strPath,
+
1708  std::string const& strMethod,
+
1709  Json::Value const& jvParams,
+
1710  const bool bSSL,
+
1711  const bool quiet,
+
1712  Logs& logs,
+
1713  std::function<void(Json::Value const& jvInput)> callbackFuncP,
+
1714  std::unordered_map<std::string, std::string> headers)
+
1715 {
+
1716  auto j = logs.journal("HTTPClient");
+
1717 
+
1718  // Connect to localhost
+
1719  if (!quiet)
+
1720  {
+
1721  JLOG(j.info()) << (bSSL ? "Securely connecting to " : "Connecting to ")
+
1722  << strIp << ":" << iPort << std::endl;
+
1723  }
+
1724 
+
1725  // HTTP basic authentication
+
1726  headers["Authorization"] =
+
1727  std::string("Basic ") + base64_encode(strUsername + ":" + strPassword);
+
1728 
+
1729  // Send request
+
1730 
+
1731  // Number of bytes to try to receive if no
+
1732  // Content-Length header received
+
1733  constexpr auto RPC_REPLY_MAX_BYTES = megabytes(256);
+
1734 
+
1735  using namespace std::chrono_literals;
+
1736  auto constexpr RPC_NOTIFY = 10min;
+
1737 
+
1738  HTTPClient::request(
+
1739  bSSL,
+
1740  io_service,
+
1741  strIp,
+
1742  iPort,
+
1743  std::bind(
+
1744  &RPCCallImp::onRequest,
+
1745  strMethod,
+
1746  jvParams,
+
1747  headers,
+
1748  strPath,
+
1749  std::placeholders::_1,
+
1750  std::placeholders::_2,
+
1751  j),
+
1752  RPC_REPLY_MAX_BYTES,
+
1753  RPC_NOTIFY,
+
1754  std::bind(
+
1755  &RPCCallImp::onResponse,
+
1756  callbackFuncP,
+
1757  std::placeholders::_1,
+
1758  std::placeholders::_2,
+
1759  std::placeholders::_3,
+
1760  j),
+
1761  j);
+
1762 }
+
1763 
+
1764 } // namespace RPCCall
+
1765 
+
1766 } // namespace ripple
Json::Value parseAsIs(Json::Value const &jvParams)
Definition: RPCCall.cpp:175
T for_each(T... args)
-
Json::Value parseTxHistory(Json::Value const &jvParams)
Definition: RPCCall.cpp:1107
+
Json::Value parseTxHistory(Json::Value const &jvParams)
Definition: RPCCall.cpp:1121
std::string user
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition: Slice.h:241
T bind(T... args)
@@ -1837,13 +1851,13 @@ $(function() {
Json::Value parseInternal(Json::Value const &jvParams)
Definition: RPCCall.cpp:216
STL class.
Manages partitions for logging.
Definition: Log.h:48
-
Json::Value parseChannelVerify(Json::Value const &jvParams)
Definition: RPCCall.cpp:841
-
Json::Value parseFeature(Json::Value const &jvParams)
Definition: RPCCall.cpp:522
+
Json::Value parseChannelVerify(Json::Value const &jvParams)
Definition: RPCCall.cpp:855
+
Json::Value parseFeature(Json::Value const &jvParams)
Definition: RPCCall.cpp:536
Stream trace() const
Severity stream access functions.
Definition: Journal.h:309
-
Json::Value parseAccountLines(Json::Value const &jvParams)
Definition: RPCCall.cpp:783
-
Json::Value parseAccountRaw2(Json::Value const &jvParams, char const *const acc2Field)
Definition: RPCCall.cpp:869
+
Json::Value parseAccountLines(Json::Value const &jvParams)
Definition: RPCCall.cpp:797
+
Json::Value parseAccountRaw2(Json::Value const &jvParams, char const *const acc2Field)
Definition: RPCCall.cpp:883
Json::Value parseCanDelete(Json::Value const &jvParams)
Definition: RPCCall.cpp:469
-
Definition: RPCCall.cpp:1373
+
Definition: RPCCall.cpp:1387
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
bool secure
@@ -1858,9 +1872,9 @@ $(function() {
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:104
Json::Value parseFetchInfo(Json::Value const &jvParams)
Definition: RPCCall.cpp:252
-
Json::Value parseJson2(Json::Value const &jvParams)
Definition: RPCCall.cpp:643
+
Json::Value parseJson2(Json::Value const &jvParams)
Definition: RPCCall.cpp:657
bool isNull() const
isNull() tests to see if this field is null.
Definition: json_value.cpp:967
-
RPCParser(beast::Journal j)
Definition: RPCCall.cpp:1202
+
RPCParser(beast::Journal j)
Definition: RPCCall.cpp:1216
std::uint16_t port
const_iterator end() const
@@ -1869,117 +1883,122 @@ $(function() {
static bool jvParseLedger(Json::Value &jvRequest, std::string const &strLedger)
Definition: RPCCall.cpp:99
Json::Value parseManifest(Json::Value const &jvParams)
Definition: RPCCall.cpp:232
T find_first_not_of(T... args)
-
static void callRPCHandler(Json::Value *jvOutput, Json::Value const &jvInput)
Definition: RPCCall.cpp:1380
+
static void callRPCHandler(Json::Value *jvOutput, Json::Value const &jvInput)
Definition: RPCCall.cpp:1394
-
Json::Value parseChannelAuthorize(Json::Value const &jvParams)
Definition: RPCCall.cpp:797
-
Json::Value parseAccountItems(Json::Value const &jvParams)
Definition: RPCCall.cpp:770
+
Json::Value parseChannelAuthorize(Json::Value const &jvParams)
Definition: RPCCall.cpp:811
+
Json::Value parseAccountItems(Json::Value const &jvParams)
Definition: RPCCall.cpp:784
static Json::Value jvParseCurrencyIssuer(std::string const &strCurrencyIssuer)
Definition: RPCCall.cpp:122
bool quiet() const
Definition: Config.h:303
-
Json::Value parseSubmitMultiSigned(Json::Value const &jvParams)
Definition: RPCCall.cpp:1039
+
Json::Value parseSubmitMultiSigned(Json::Value const &jvParams)
Definition: RPCCall.cpp:1053
const beast::Journal j_
Definition: RPCCall.cpp:94
std::string ip
-
Json::Value parsePeerReservationsAdd(Json::Value const &jvParams)
Definition: RPCCall.cpp:950
+
Json::Value parsePeerReservationsAdd(Json::Value const &jvParams)
Definition: RPCCall.cpp:964
ServerHandler::Setup setup_ServerHandler(Config const &config, std::ostream &&log)
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
Definition: PublicKey.cpp:207
-
static void onRequest(std::string const &strMethod, Json::Value const &jvParams, std::unordered_map< std::string, std::string > const &headers, std::string const &strPath, boost::asio::streambuf &sb, std::string const &strHost, beast::Journal j)
Definition: RPCCall.cpp:1428
+
static void onRequest(std::string const &strMethod, Json::Value const &jvParams, std::unordered_map< std::string, std::string > const &headers, std::string const &strPath, boost::asio::streambuf &sb, std::string const &strHost, beast::Journal j)
Definition: RPCCall.cpp:1442
-
Json::Value parseGatewayBalances(Json::Value const &jvParams)
Definition: RPCCall.cpp:1152
+
Json::Value parseGatewayBalances(Json::Value const &jvParams)
Definition: RPCCall.cpp:1166
bool isRpcError(Json::Value jvResult)
Definition: RPCErr.cpp:38
T stoi(T... args)
@ rpcSUCCESS
Definition: ErrorCodes.h:44
-
Json::Value parseAccountRaw1(Json::Value const &jvParams)
Definition: RPCCall.cpp:909
+
Json::Value parseAccountRaw1(Json::Value const &jvParams)
Definition: RPCCall.cpp:923
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:882
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
TokenType
Definition: tokens.h:29
-
Json::Value parseServerInfo(Json::Value const &jvParams)
Definition: RPCCall.cpp:1191
+
Json::Value parseServerInfo(Json::Value const &jvParams)
Definition: RPCCall.cpp:1205
Definition: Config.h:69
-
Json::Value parseAccountCurrencies(Json::Value const &jvParams)
Definition: RPCCall.cpp:776
+
Json::Value parseAccountCurrencies(Json::Value const &jvParams)
Definition: RPCCall.cpp:790
STL class.
-
Json::Value parseLogLevel(Json::Value const &jvParams)
Definition: RPCCall.cpp:747
+
Json::Value parseLogLevel(Json::Value const &jvParams)
Definition: RPCCall.cpp:761
Json::Value parseBookOffers(Json::Value const &jvParams)
Definition: RPCCall.cpp:412
Json::Value(RPCParser::*)(Json::Value const &jvParams) parseFuncPtr
Definition: RPCCall.cpp:172
constexpr auto megabytes(T value) noexcept
Definition: ByteUtilities.h:34
std::optional< std::uint64_t > to_uint64(std::string const &s)
Json::Value parseTxAccount(Json::Value const &jvParams)
Definition: RPCCall.cpp:340
@ rpcPUBLIC_MALFORMED
Definition: ErrorCodes.h:117
-
Json::Value parseTx(Json::Value const &jvParams)
Definition: RPCCall.cpp:1083
+
Json::Value parseTx(Json::Value const &jvParams)
Definition: RPCCall.cpp:1097
+
T find_last_of(T... args)
UInt size() const
Number of values in array or object.
Definition: json_value.cpp:706
client_t client
Definition: Journal.h:428
STL class.
@ rpcNO_EVENTS
Definition: ErrorCodes.h:54
-
Json::Value parseCommand(std::string strMethod, Json::Value jvParams, bool allowAnyCommand)
Definition: RPCCall.cpp:1211
+
Json::Value parseCommand(std::string strMethod, Json::Value jvParams, bool allowAnyCommand)
Definition: RPCCall.cpp:1225
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:932
A generic endpoint for log messages.
Definition: Journal.h:58
-
Json::Value parseWalletPropose(Json::Value const &jvParams)
Definition: RPCCall.cpp:1137
+
Json::Value parseWalletPropose(Json::Value const &jvParams)
Definition: RPCCall.cpp:1151
-
Json::Value parseLedger(Json::Value const &jvParams)
Definition: RPCCall.cpp:694
+
Json::Value parseLedger(Json::Value const &jvParams)
Definition: RPCCall.cpp:708
std::optional< Seed > parseGenericSeed(std::string const &str, bool rfc1751)
Attempt to parse a string as a seed.
Definition: Seed.cpp:90
-
Json::Value parseRipplePathFind(Json::Value const &jvParams)
Definition: RPCCall.cpp:972
+
Json::Value parseRipplePathFind(Json::Value const &jvParams)
Definition: RPCCall.cpp:986
Json::Value parseAccountTransactions(Json::Value const &jvParams)
Definition: RPCCall.cpp:266
-
Json::Value parseValidationCreate(Json::Value const &jvParams)
Definition: RPCCall.cpp:1123
+
Json::Value parseValidationCreate(Json::Value const &jvParams)
Definition: RPCCall.cpp:1137
@ rpcINTERNAL
Definition: ErrorCodes.h:130
bool isArray() const
Json::Value & setArray(Json::Value &, Json::StaticString const &key)
Add a new subarray at a named key in a Json object.
Definition: Object.h:414
@ rpcCHANNEL_AMT_MALFORMED
Definition: ErrorCodes.h:101
STL class.
-
int fromCommandLine(Config const &config, const std::vector< std::string > &vCmd, Logs &logs)
Definition: RPCCall.cpp:1672
-
Json::Value parseEvented(Json::Value const &jvParams)
Definition: RPCCall.cpp:515
+
int fromCommandLine(Config const &config, const std::vector< std::string > &vCmd, Logs &logs)
Definition: RPCCall.cpp:1686
+
Json::Value parseEvented(Json::Value const &jvParams)
Definition: RPCCall.cpp:529
std::string admin_password
RPCCallImp()=default
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
-
std::string JSONRPCRequest(std::string const &strMethod, Json::Value const &params, Json::Value const &id)
Definition: RPCCall.cpp:1353
+
std::string JSONRPCRequest(std::string const &strMethod, Json::Value const &params, Json::Value const &id)
Definition: RPCCall.cpp:1367
T endl(T... args)
@ rpcACT_MALFORMED
Definition: ErrorCodes.h:90
beast::Journal journal(std::string const &name)
Definition: Log.cpp:144
@ rpcBAD_SYNTAX
Definition: ErrorCodes.h:46
void clear()
Remove all object members and array elements.
Definition: json_value.cpp:753
@ rpcUNKNOWN_COMMAND
Definition: ErrorCodes.h:85
-
Json::Value cmdLineToJSONRPC(std::vector< std::string > const &args, beast::Journal j)
Given a rippled command line, return the corresponding JSON.
Definition: RPCCall.cpp:1490
+
Json::Value cmdLineToJSONRPC(std::vector< std::string > const &args, beast::Journal j)
Given a rippled command line, return the corresponding JSON.
Definition: RPCCall.cpp:1504
Json::Value parseDownloadShard(Json::Value const &jvParams)
Definition: RPCCall.cpp:186
-
Json::Value parseDepositAuthorized(Json::Value const &jvParams)
Definition: RPCCall.cpp:501
-
static Json::Value rpcCmdLineToJson(std::vector< std::string > const &args, Json::Value &retParams, beast::Journal j)
Definition: RPCCall.cpp:1452
+
Json::Value parseDepositAuthorized(Json::Value const &jvParams)
Definition: RPCCall.cpp:515
+
static Json::Value rpcCmdLineToJson(std::vector< std::string > const &args, Json::Value &retParams, beast::Journal j)
Definition: RPCCall.cpp:1466
+
T begin(T... args)
UInt asUInt() const
Definition: json_value.cpp:545
-
static bool onResponse(std::function< void(Json::Value const &jvInput)> callbackFuncP, const boost::system::error_code &ecResult, int iStatus, std::string const &strData, beast::Journal j)
Definition: RPCCall.cpp:1386
-
std::pair< int, Json::Value > rpcClient(std::vector< std::string > const &args, Config const &config, Logs &logs, std::unordered_map< std::string, std::string > const &headers)
Internal invocation of RPC client.
Definition: RPCCall.cpp:1521
+
static bool onResponse(std::function< void(Json::Value const &jvInput)> callbackFuncP, const boost::system::error_code &ecResult, int iStatus, std::string const &strData, beast::Journal j)
Definition: RPCCall.cpp:1400
+
std::pair< int, Json::Value > rpcClient(std::vector< std::string > const &args, Config const &config, Logs &logs, std::unordered_map< std::string, std::string > const &headers)
Internal invocation of RPC client.
Definition: RPCCall.cpp:1535
@ AccountPublic
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
Definition: json_reader.cpp:74
constexpr unsigned int apiMaximumSupportedVersion
Definition: RPCHelpers.h:244
-
Json::Value parseLedgerId(Json::Value const &jvParams)
Definition: RPCCall.cpp:723
+
Json::Value parseLedgerId(Json::Value const &jvParams)
Definition: RPCCall.cpp:737
@ rpcLGR_IDX_MALFORMED
Definition: ErrorCodes.h:113
@ rpcCHANNEL_MALFORMED
Definition: ErrorCodes.h:100
+
T count(T... args)
T empty(T... args)
-
Json::Value parseGetCounts(Json::Value const &jvParams)
Definition: RPCCall.cpp:549
+
Json::Value parseGetCounts(Json::Value const &jvParams)
Definition: RPCCall.cpp:563
@ NodePublic
static std::string const & systemName()
static void request(bool bSSL, boost::asio::io_service &io_service, std::string strSite, const unsigned short port, std::function< void(boost::asio::streambuf &sb, std::string const &strHost)> build, std::size_t responseMax, std::chrono::seconds timeout, std::function< bool(const boost::system::error_code &ecResult, int iStatus, std::string const &strData)> complete, beast::Journal &j)
Definition: HTTPClient.cpp:585
T str(T... args)
Stream debug() const
Definition: Journal.h:315
+
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Int asInt() const
Definition: json_value.cpp:503
-
bool isValidJson2(Json::Value const &jv)
Definition: RPCCall.cpp:613
-
void fromNetwork(boost::asio::io_service &io_service, std::string const &strIp, const std::uint16_t iPort, std::string const &strUsername, std::string const &strPassword, std::string const &strPath, std::string const &strMethod, Json::Value const &jvParams, const bool bSSL, const bool quiet, Logs &logs, std::function< void(Json::Value const &jvInput)> callbackFuncP, std::unordered_map< std::string, std::string > headers)
Definition: RPCCall.cpp:1687
+
bool isValidJson2(Json::Value const &jv)
Definition: RPCCall.cpp:627
+
T end(T... args)
+
void fromNetwork(boost::asio::io_service &io_service, std::string const &strIp, const std::uint16_t iPort, std::string const &strUsername, std::string const &strPassword, std::string const &strPath, std::string const &strMethod, Json::Value const &jvParams, const bool bSSL, const bool quiet, Logs &logs, std::function< void(Json::Value const &jvInput)> callbackFuncP, std::unordered_map< std::string, std::string > headers)
Definition: RPCCall.cpp:1701
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:496
-
Json::Value parseJson(Json::Value const &jvParams)
Definition: RPCCall.cpp:591
+
Json::Value parseJson(Json::Value const &jvParams)
Definition: RPCCall.cpp:605
Json::Value make_param_error(std::string const &message)
Returns a new json object that indicates invalid parameters.
Definition: ErrorCodes.h:250
-
Json::Value parseSignFor(Json::Value const &jvParams)
Definition: RPCCall.cpp:562
+
Json::Value parseSignFor(Json::Value const &jvParams)
Definition: RPCCall.cpp:576
std::string password
-
Json::Value parseNodeToShard(Json::Value const &jvParams)
Definition: RPCCall.cpp:940
+
Json::Value parseNodeToShard(Json::Value const &jvParams)
Definition: RPCCall.cpp:954
const_iterator begin() const
-
Json::Value parsePeerReservationsDel(Json::Value const &jvParams)
Definition: RPCCall.cpp:963
+
Json::Value parsePeerReservationsDel(Json::Value const &jvParams)
Definition: RPCCall.cpp:977
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
-
Json::Value parseAccountChannels(Json::Value const &jvParams)
Definition: RPCCall.cpp:790
+
Json::Value parseAccountChannels(Json::Value const &jvParams)
Definition: RPCCall.cpp:804
bool isObjectOrNull() const
Definition: RPCCall.cpp:91
@ rpcNOT_SYNCED
Definition: ErrorCodes.h:67
T what(T... args)
-
Json::Value parseTransactionEntry(Json::Value const &jvParams)
Definition: RPCCall.cpp:1058
+
Json::Value parseTransactionEntry(Json::Value const &jvParams)
Definition: RPCCall.cpp:1072
Represents a JSON value.
Definition: json_value.h:145
-
Json::Value parseSignSubmit(Json::Value const &jvParams)
Definition: RPCCall.cpp:999
+
Json::Value parseSignSubmit(Json::Value const &jvParams)
Definition: RPCCall.cpp:1013
std::optional< beast::IP::Endpoint > rpc_ip
Definition: Config.h:261
@ rpcBAD_KEY_TYPE
Definition: ErrorCodes.h:133
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:469
diff --git a/RPCCall_8h_source.html b/RPCCall_8h_source.html index eb8b948b54..371cc85fd2 100644 --- a/RPCCall_8h_source.html +++ b/RPCCall_8h_source.html @@ -157,11 +157,11 @@ $(function() {
A generic endpoint for log messages.
Definition: Journal.h:58
-
int fromCommandLine(Config const &config, const std::vector< std::string > &vCmd, Logs &logs)
Definition: RPCCall.cpp:1672
+
int fromCommandLine(Config const &config, const std::vector< std::string > &vCmd, Logs &logs)
Definition: RPCCall.cpp:1686
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
-
Json::Value cmdLineToJSONRPC(std::vector< std::string > const &args, beast::Journal j)
Given a rippled command line, return the corresponding JSON.
Definition: RPCCall.cpp:1490
-
std::pair< int, Json::Value > rpcClient(std::vector< std::string > const &args, Config const &config, Logs &logs, std::unordered_map< std::string, std::string > const &headers)
Internal invocation of RPC client.
Definition: RPCCall.cpp:1521
-
void fromNetwork(boost::asio::io_service &io_service, std::string const &strIp, const std::uint16_t iPort, std::string const &strUsername, std::string const &strPassword, std::string const &strPath, std::string const &strMethod, Json::Value const &jvParams, const bool bSSL, const bool quiet, Logs &logs, std::function< void(Json::Value const &jvInput)> callbackFuncP, std::unordered_map< std::string, std::string > headers)
Definition: RPCCall.cpp:1687
+
Json::Value cmdLineToJSONRPC(std::vector< std::string > const &args, beast::Journal j)
Given a rippled command line, return the corresponding JSON.
Definition: RPCCall.cpp:1504
+
std::pair< int, Json::Value > rpcClient(std::vector< std::string > const &args, Config const &config, Logs &logs, std::unordered_map< std::string, std::string > const &headers)
Internal invocation of RPC client.
Definition: RPCCall.cpp:1535
+
void fromNetwork(boost::asio::io_service &io_service, std::string const &strIp, const std::uint16_t iPort, std::string const &strUsername, std::string const &strPassword, std::string const &strPath, std::string const &strMethod, Json::Value const &jvParams, const bool bSSL, const bool quiet, Logs &logs, std::function< void(Json::Value const &jvInput)> callbackFuncP, std::unordered_map< std::string, std::string > headers)
Definition: RPCCall.cpp:1701
Represents a JSON value.
Definition: json_value.h:145
diff --git a/RPCCall__test_8cpp_source.html b/RPCCall__test_8cpp_source.html index 1ddb61c595..67c156412e 100644 --- a/RPCCall__test_8cpp_source.html +++ b/RPCCall__test_8cpp_source.html @@ -6655,7 +6655,7 @@ $(function() {
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Exception
-
Json::Value cmdLineToJSONRPC(std::vector< std::string > const &args, beast::Journal j)
Given a rippled command line, return the corresponding JSON.
Definition: RPCCall.cpp:1490
+
Json::Value cmdLineToJSONRPC(std::vector< std::string > const &args, beast::Journal j)
Given a rippled command line, return the corresponding JSON.
Definition: RPCCall.cpp:1504
char const *const exp
char const *const description
T begin(T... args)
diff --git a/RPCSub_8cpp_source.html b/RPCSub_8cpp_source.html index a840273f11..a1dda27cb4 100644 --- a/RPCSub_8cpp_source.html +++ b/RPCSub_8cpp_source.html @@ -358,7 +358,7 @@ $(function() {
Stream debug() const
Definition: Journal.h:315
T make_pair(T... args)
std::string domain
-
void fromNetwork(boost::asio::io_service &io_service, std::string const &strIp, const std::uint16_t iPort, std::string const &strUsername, std::string const &strPassword, std::string const &strPath, std::string const &strMethod, Json::Value const &jvParams, const bool bSSL, const bool quiet, Logs &logs, std::function< void(Json::Value const &jvInput)> callbackFuncP, std::unordered_map< std::string, std::string > headers)
Definition: RPCCall.cpp:1687
+
void fromNetwork(boost::asio::io_service &io_service, std::string const &strIp, const std::uint16_t iPort, std::string const &strUsername, std::string const &strPassword, std::string const &strPath, std::string const &strMethod, Json::Value const &jvParams, const bool bSSL, const bool quiet, Logs &logs, std::function< void(Json::Value const &jvInput)> callbackFuncP, std::unordered_map< std::string, std::string > headers)
Definition: RPCCall.cpp:1701
const beast::Journal j_
Definition: RPCSub.cpp:204
RPCSubImp(InfoSub::Source &source, boost::asio::io_service &io_service, JobQueue &jobQueue, std::string const &strUrl, std::string const &strUsername, std::string const &strPassword, Logs &logs)
Definition: RPCSub.cpp:34
T ref(T... args)
diff --git a/SHAMapStoreImp_8cpp_source.html b/SHAMapStoreImp_8cpp_source.html index 6965d83660..aff812d1fa 100644 --- a/SHAMapStoreImp_8cpp_source.html +++ b/SHAMapStoreImp_8cpp_source.html @@ -869,7 +869,7 @@ $(function() {
bool reporting() const
Definition: Config.h:318
std::chrono::seconds recoveryWaitTime_
If the node is out of sync during an online_delete healthWait() call, sleep the thread for this time,...
bool stop_
-
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:989
+
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:1012
virtual LedgerMaster & getLedgerMaster()=0
Definition: Config.h:69
bool advisoryDelete_
diff --git a/UnitaryShard_8cpp_source.html b/UnitaryShard_8cpp_source.html index 54a18c0505..ec0da567dd 100644 --- a/UnitaryShard_8cpp_source.html +++ b/UnitaryShard_8cpp_source.html @@ -420,7 +420,7 @@ $(function() {
LedgerInfo const & info() const override
Returns information about the ledger.
Definition: Ledger.h:148
T time_since_epoch(T... args)
bool isPseudoTx(STObject const &tx)
Check whether a transaction is a pseudo-transaction.
Definition: STTx.cpp:559
-
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:989
+
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:1012
constexpr std::array< char const *, 1 > LgrDBPragma
Definition: DBInit.h:45
Definition: Config.h:69
int closeFlags
Definition: ReadView.h:105
diff --git a/Version__test_8cpp_source.html b/Version__test_8cpp_source.html index 9dd58e728a..73411b906c 100644 --- a/Version__test_8cpp_source.html +++ b/Version__test_8cpp_source.html @@ -367,7 +367,7 @@ $(function() {
unsigned int getAPIVersionNumber(Json::Value const &jv, bool betaEnabled)
Retrieve the api version number from the json value.
Definition: RPCHelpers.cpp:934
void testBatchFail()
constexpr unsigned int apiBetaVersion
Definition: RPCHelpers.h:245
-
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition: Config.cpp:456
+
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition: Config.cpp:457
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
Definition: Config.h:69
void testConfig()
diff --git a/classripple_1_1Config.html b/classripple_1_1Config.html index 40e5549b51..cb7d90fd2d 100644 --- a/classripple_1_1Config.html +++ b/classripple_1_1Config.html @@ -412,7 +412,7 @@ Private Attributes
-

Definition at line 266 of file Config.cpp.

+

Definition at line 267 of file Config.cpp.

@@ -434,7 +434,7 @@ Private Attributes

Returns the full path and filename of the debug log file.

-

Definition at line 955 of file Config.cpp.

+

Definition at line 978 of file Config.cpp.

@@ -461,7 +461,7 @@ Private Attributes
-

Definition at line 434 of file Config.cpp.

+

Definition at line 435 of file Config.cpp.

@@ -503,7 +503,7 @@ Private Attributes
-

Definition at line 314 of file Config.cpp.

+

Definition at line 315 of file Config.cpp.

@@ -539,7 +539,7 @@ Private Attributes
-

Definition at line 272 of file Config.cpp.

+

Definition at line 273 of file Config.cpp.

@@ -567,7 +567,7 @@ Private Attributes -

Definition at line 456 of file Config.cpp.

+

Definition at line 457 of file Config.cpp.

@@ -767,7 +767,7 @@ Private Attributes
Returns
The value for the requested item.
Note
The defaults are selected so as to be reasonable, but the node size is an imprecise metric that combines multiple aspects of the underlying system; this means that we can't provide optimal defaults in the code for every case.
-

Definition at line 989 of file Config.cpp.

+

Definition at line 1012 of file Config.cpp.

diff --git a/classripple_1_1Config__test-members.html b/classripple_1_1Config__test-members.html index d869d9d6ec..96a8be4910 100644 --- a/classripple_1_1Config__test-members.html +++ b/classripple_1_1Config__test-members.html @@ -81,16 +81,17 @@ $(function() { path typedefripple::Config_testprivate run() overrideripple::Config_test testAmendment()ripple::Config_test - testComments()ripple::Config_test - testDbPath()ripple::Config_test - testGetters()ripple::Config_test - testLegacy()ripple::Config_test - testOverlay()ripple::Config_test - testPort()ripple::Config_test - testSetup(bool explicitPath)ripple::Config_test - testValidatorKeys()ripple::Config_test - testValidatorsFile()ripple::Config_test - testWhitespace()ripple::Config_test + testColons()ripple::Config_test + testComments()ripple::Config_test + testDbPath()ripple::Config_test + testGetters()ripple::Config_test + testLegacy()ripple::Config_test + testOverlay()ripple::Config_test + testPort()ripple::Config_test + testSetup(bool explicitPath)ripple::Config_test + testValidatorKeys()ripple::Config_test + testValidatorsFile()ripple::Config_test + testWhitespace()ripple::Config_test