rippled
RPCHelpers.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-2014 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/app/ledger/LedgerMaster.h>
21 #include <ripple/app/ledger/LedgerToJson.h>
22 #include <ripple/app/ledger/OpenLedger.h>
23 #include <ripple/app/misc/Transaction.h>
24 #include <ripple/app/paths/TrustLine.h>
25 #include <ripple/app/rdb/RelationalDatabase.h>
26 #include <ripple/app/tx/impl/details/NFTokenUtils.h>
27 #include <ripple/ledger/View.h>
28 #include <ripple/net/RPCErr.h>
29 #include <ripple/protocol/AccountID.h>
30 #include <ripple/protocol/Feature.h>
31 #include <ripple/rpc/Context.h>
32 #include <ripple/rpc/DeliveredAmount.h>
33 #include <ripple/rpc/impl/RPCHelpers.h>
34 #include <boost/algorithm/string/case_conv.hpp>
35 
36 #include <ripple/resource/Fees.h>
37 
38 namespace ripple {
39 namespace RPC {
40 
43 {
45 
46  auto const publicKey =
47  parseBase58<PublicKey>(TokenType::AccountPublic, account);
48 
49  if (publicKey)
50  result = calcAccountID(*publicKey);
51  else
52  result = parseBase58<AccountID>(account);
53 
54  return result;
55 }
56 
59  AccountID& result,
60  std::string const& strIdent,
61  bool bStrict)
62 {
63  if (auto accountID = accountFromStringStrict(strIdent))
64  {
65  result = *accountID;
66  return rpcSUCCESS;
67  }
68 
69  if (bStrict)
70  return rpcACT_MALFORMED;
71 
72  // We allow the use of the seeds which is poor practice
73  // and merely for debugging convenience.
74  auto const seed = parseGenericSeed(strIdent);
75 
76  if (!seed)
77  return rpcBAD_SEED;
78 
79  auto const keypair = generateKeyPair(KeyType::secp256k1, *seed);
80 
81  result = calcAccountID(keypair.first);
82  return rpcSUCCESS;
83 }
84 
86 accountFromString(AccountID& result, std::string const& strIdent, bool bStrict)
87 {
88  error_code_i code = accountFromStringWithCode(result, strIdent, bStrict);
89  if (code != rpcSUCCESS)
90  return rpcError(code);
91  else
92  return Json::objectValue;
93 }
94 
96 getStartHint(std::shared_ptr<SLE const> const& sle, AccountID const& accountID)
97 {
98  if (sle->getType() == ltRIPPLE_STATE)
99  {
100  if (sle->getFieldAmount(sfLowLimit).getIssuer() == accountID)
101  return sle->getFieldU64(sfLowNode);
102  else if (sle->getFieldAmount(sfHighLimit).getIssuer() == accountID)
103  return sle->getFieldU64(sfHighNode);
104  }
105 
106  if (!sle->isFieldPresent(sfOwnerNode))
107  return 0;
108 
109  return sle->getFieldU64(sfOwnerNode);
110 }
111 
112 bool
114  ReadView const& ledger,
115  std::shared_ptr<SLE const> const& sle,
116  AccountID const& accountID)
117 {
118  if (sle->getType() == ltRIPPLE_STATE)
119  {
120  return (sle->getFieldAmount(sfLowLimit).getIssuer() == accountID) ||
121  (sle->getFieldAmount(sfHighLimit).getIssuer() == accountID);
122  }
123  else if (sle->isFieldPresent(sfAccount))
124  {
125  // If there's an sfAccount present, also test the sfDestination, if
126  // present. This will match objects such as Escrows (ltESCROW), Payment
127  // Channels (ltPAYCHAN), and Checks (ltCHECK) because those are added to
128  // the Destination account's directory. It intentionally EXCLUDES
129  // NFToken Offers (ltNFTOKEN_OFFER). NFToken Offers are NOT added to the
130  // Destination account's directory.
131  return sle->getAccountID(sfAccount) == accountID ||
132  (sle->isFieldPresent(sfDestination) &&
133  sle->getAccountID(sfDestination) == accountID);
134  }
135  else if (sle->getType() == ltSIGNER_LIST)
136  {
137  Keylet const accountSignerList = keylet::signers(accountID);
138  return sle->key() == accountSignerList.key;
139  }
140  else if (sle->getType() == ltNFTOKEN_OFFER)
141  {
142  // Do not check the sfDestination field. NFToken Offers are NOT added to
143  // the Destination account's directory.
144  return sle->getAccountID(sfOwner) == accountID;
145  }
146 
147  return false;
148 }
149 
150 bool
152  ReadView const& ledger,
153  AccountID const& account,
154  std::optional<std::vector<LedgerEntryType>> const& typeFilter,
155  uint256 dirIndex,
156  uint256 const& entryIndex,
157  std::uint32_t const limit,
158  Json::Value& jvResult)
159 {
160  auto const root = keylet::ownerDir(account);
161  auto found = false;
162 
163  if (dirIndex.isZero())
164  {
165  dirIndex = root.key;
166  found = true;
167  }
168 
169  auto dir = ledger.read({ltDIR_NODE, dirIndex});
170  if (!dir)
171  return false;
172 
173  std::uint32_t i = 0;
174  auto& jvObjects = (jvResult[jss::account_objects] = Json::arrayValue);
175  for (;;)
176  {
177  auto const& entries = dir->getFieldV256(sfIndexes);
178  auto iter = entries.begin();
179 
180  if (!found)
181  {
182  iter = std::find(iter, entries.end(), entryIndex);
183  if (iter == entries.end())
184  return false;
185 
186  found = true;
187  }
188 
189  for (; iter != entries.end(); ++iter)
190  {
191  auto const sleNode = ledger.read(keylet::child(*iter));
192 
193  auto typeMatchesFilter =
194  [](std::vector<LedgerEntryType> const& typeFilter,
195  LedgerEntryType ledgerType) {
196  auto it = std::find(
197  typeFilter.begin(), typeFilter.end(), ledgerType);
198  return it != typeFilter.end();
199  };
200 
201  if (!typeFilter.has_value() ||
202  typeMatchesFilter(typeFilter.value(), sleNode->getType()))
203  {
204  jvObjects.append(sleNode->getJson(JsonOptions::none));
205  }
206 
207  if (++i == limit)
208  {
209  if (++iter != entries.end())
210  {
211  jvResult[jss::limit] = limit;
212  jvResult[jss::marker] =
213  to_string(dirIndex) + ',' + to_string(*iter);
214  return true;
215  }
216 
217  break;
218  }
219  }
220 
221  auto const nodeIndex = dir->getFieldU64(sfIndexNext);
222  if (nodeIndex == 0)
223  return true;
224 
225  dirIndex = keylet::page(root, nodeIndex).key;
226  dir = ledger.read({ltDIR_NODE, dirIndex});
227  if (!dir)
228  return true;
229 
230  if (i == limit)
231  {
232  auto const& e = dir->getFieldV256(sfIndexes);
233  if (!e.empty())
234  {
235  jvResult[jss::limit] = limit;
236  jvResult[jss::marker] =
237  to_string(dirIndex) + ',' + to_string(*e.begin());
238  }
239 
240  return true;
241  }
242  }
243 }
244 
245 namespace {
246 
247 bool
248 isValidatedOld(LedgerMaster& ledgerMaster, bool standaloneOrReporting)
249 {
250  if (standaloneOrReporting)
251  return false;
252 
253  return ledgerMaster.getValidatedLedgerAge() > Tuning::maxValidatedLedgerAge;
254 }
255 
256 template <class T>
257 Status
258 ledgerFromRequest(T& ledger, JsonContext& context)
259 {
260  ledger.reset();
261 
262  auto& params = context.params;
263 
264  auto indexValue = params[jss::ledger_index];
265  auto hashValue = params[jss::ledger_hash];
266 
267  // We need to support the legacy "ledger" field.
268  auto& legacyLedger = params[jss::ledger];
269  if (legacyLedger)
270  {
271  if (legacyLedger.asString().size() > 12)
272  hashValue = legacyLedger;
273  else
274  indexValue = legacyLedger;
275  }
276 
277  if (hashValue)
278  {
279  if (!hashValue.isString())
280  return {rpcINVALID_PARAMS, "ledgerHashNotString"};
281 
282  uint256 ledgerHash;
283  if (!ledgerHash.parseHex(hashValue.asString()))
284  return {rpcINVALID_PARAMS, "ledgerHashMalformed"};
285  return getLedger(ledger, ledgerHash, context);
286  }
287 
288  auto const index = indexValue.asString();
289 
290  if (index == "current" ||
291  (index.empty() && !context.app.config().reporting()))
292  return getLedger(ledger, LedgerShortcut::CURRENT, context);
293 
294  if (index == "validated" ||
295  (index.empty() && context.app.config().reporting()))
296  return getLedger(ledger, LedgerShortcut::VALIDATED, context);
297 
298  if (index == "closed")
299  return getLedger(ledger, LedgerShortcut::CLOSED, context);
300 
301  std::uint32_t iVal;
302  if (beast::lexicalCastChecked(iVal, index))
303  return getLedger(ledger, iVal, context);
304 
305  return {rpcINVALID_PARAMS, "ledgerIndexMalformed"};
306 }
307 } // namespace
308 
309 template <class T, class R>
310 Status
311 ledgerFromRequest(T& ledger, GRPCContext<R>& context)
312 {
313  R& request = context.params;
314  return ledgerFromSpecifier(ledger, request.ledger(), context);
315 }
316 
317 // explicit instantiation of above function
318 template Status
319 ledgerFromRequest<>(
321  GRPCContext<org::xrpl::rpc::v1::GetLedgerEntryRequest>&);
322 
323 // explicit instantiation of above function
324 template Status
325 ledgerFromRequest<>(
327  GRPCContext<org::xrpl::rpc::v1::GetLedgerDataRequest>&);
328 
329 // explicit instantiation of above function
330 template Status
331 ledgerFromRequest<>(
333  GRPCContext<org::xrpl::rpc::v1::GetLedgerRequest>&);
334 
335 template <class T>
336 Status
338  T& ledger,
339  org::xrpl::rpc::v1::LedgerSpecifier const& specifier,
340  Context& context)
341 {
342  ledger.reset();
343 
344  using LedgerCase = org::xrpl::rpc::v1::LedgerSpecifier::LedgerCase;
345  LedgerCase ledgerCase = specifier.ledger_case();
346  switch (ledgerCase)
347  {
348  case LedgerCase::kHash: {
349  if (auto hash = uint256::fromVoidChecked(specifier.hash()))
350  {
351  return getLedger(ledger, *hash, context);
352  }
353  return {rpcINVALID_PARAMS, "ledgerHashMalformed"};
354  }
355  case LedgerCase::kSequence:
356  return getLedger(ledger, specifier.sequence(), context);
357  case LedgerCase::kShortcut:
358  [[fallthrough]];
359  case LedgerCase::LEDGER_NOT_SET: {
360  auto const shortcut = specifier.shortcut();
361  // note, unspecified defaults to validated in reporting mode
362  if (shortcut ==
363  org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED ||
364  (shortcut ==
365  org::xrpl::rpc::v1::LedgerSpecifier::
366  SHORTCUT_UNSPECIFIED &&
367  context.app.config().reporting()))
368  {
369  return getLedger(ledger, LedgerShortcut::VALIDATED, context);
370  }
371  else
372  {
373  if (shortcut ==
374  org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CURRENT ||
375  shortcut ==
376  org::xrpl::rpc::v1::LedgerSpecifier::
377  SHORTCUT_UNSPECIFIED)
378  {
379  return getLedger(ledger, LedgerShortcut::CURRENT, context);
380  }
381  else if (
382  shortcut ==
383  org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CLOSED)
384  {
385  return getLedger(ledger, LedgerShortcut::CLOSED, context);
386  }
387  }
388  }
389  }
390 
391  return Status::OK;
392 }
393 
394 template <class T>
395 Status
396 getLedger(T& ledger, uint256 const& ledgerHash, Context& context)
397 {
398  ledger = context.ledgerMaster.getLedgerByHash(ledgerHash);
399  if (ledger == nullptr)
400  return {rpcLGR_NOT_FOUND, "ledgerNotFound"};
401  return Status::OK;
402 }
403 
404 template <class T>
405 Status
406 getLedger(T& ledger, uint32_t ledgerIndex, Context& context)
407 {
408  ledger = context.ledgerMaster.getLedgerBySeq(ledgerIndex);
409  if (ledger == nullptr)
410  {
411  if (context.app.config().reporting())
412  return {rpcLGR_NOT_FOUND, "ledgerNotFound"};
413  auto cur = context.ledgerMaster.getCurrentLedger();
414  if (cur->info().seq == ledgerIndex)
415  {
416  ledger = cur;
417  }
418  }
419 
420  if (ledger == nullptr)
421  return {rpcLGR_NOT_FOUND, "ledgerNotFound"};
422 
423  if (ledger->info().seq > context.ledgerMaster.getValidLedgerIndex() &&
424  isValidatedOld(context.ledgerMaster, context.app.config().standalone()))
425  {
426  ledger.reset();
427  if (context.apiVersion == 1)
428  return {rpcNO_NETWORK, "InsufficientNetworkMode"};
429  return {rpcNOT_SYNCED, "notSynced"};
430  }
431 
432  return Status::OK;
433 }
434 
435 template <class T>
436 Status
437 getLedger(T& ledger, LedgerShortcut shortcut, Context& context)
438 {
439  if (isValidatedOld(
440  context.ledgerMaster,
441  context.app.config().standalone() ||
442  context.app.config().reporting()))
443  {
444  if (context.apiVersion == 1)
445  return {rpcNO_NETWORK, "InsufficientNetworkMode"};
446  return {rpcNOT_SYNCED, "notSynced"};
447  }
448 
449  if (shortcut == LedgerShortcut::VALIDATED)
450  {
451  ledger = context.ledgerMaster.getValidatedLedger();
452  if (ledger == nullptr)
453  {
454  if (context.apiVersion == 1)
455  return {rpcNO_NETWORK, "InsufficientNetworkMode"};
456  return {rpcNOT_SYNCED, "notSynced"};
457  }
458 
459  assert(!ledger->open());
460  }
461  else
462  {
463  if (shortcut == LedgerShortcut::CURRENT)
464  {
465  if (context.app.config().reporting())
466  return {
468  "Reporting does not track current ledger"};
469  ledger = context.ledgerMaster.getCurrentLedger();
470  assert(ledger->open());
471  }
472  else if (shortcut == LedgerShortcut::CLOSED)
473  {
474  if (context.app.config().reporting())
475  return {
476  rpcLGR_NOT_FOUND, "Reporting does not track closed ledger"};
477  ledger = context.ledgerMaster.getClosedLedger();
478  assert(!ledger->open());
479  }
480  else
481  {
482  return {rpcINVALID_PARAMS, "ledgerIndexMalformed"};
483  }
484 
485  if (ledger == nullptr)
486  {
487  if (context.apiVersion == 1)
488  return {rpcNO_NETWORK, "InsufficientNetworkMode"};
489  return {rpcNOT_SYNCED, "notSynced"};
490  }
491 
492  static auto const minSequenceGap = 10;
493 
494  if (ledger->info().seq + minSequenceGap <
496  {
497  ledger.reset();
498  if (context.apiVersion == 1)
499  return {rpcNO_NETWORK, "InsufficientNetworkMode"};
500  return {rpcNOT_SYNCED, "notSynced"};
501  }
502  }
503  return Status::OK;
504 }
505 
506 // Explicit instantiaion of above three functions
507 template Status
508 getLedger<>(std::shared_ptr<ReadView const>&, uint32_t, Context&);
509 
510 template Status
511 getLedger<>(
513  LedgerShortcut shortcut,
514  Context&);
515 
516 template Status
517 getLedger<>(std::shared_ptr<ReadView const>&, uint256 const&, Context&);
518 
519 bool
521  LedgerMaster& ledgerMaster,
522  ReadView const& ledger,
523  Application& app)
524 {
525  if (app.config().reporting())
526  return true;
527 
528  if (ledger.open())
529  return false;
530 
531  if (ledger.info().validated)
532  return true;
533 
534  auto seq = ledger.info().seq;
535  try
536  {
537  // Use the skip list in the last validated ledger to see if ledger
538  // comes before the last validated ledger (and thus has been
539  // validated).
540  auto hash =
541  ledgerMaster.walkHashBySeq(seq, InboundLedger::Reason::GENERIC);
542 
543  if (!hash || ledger.info().hash != *hash)
544  {
545  // This ledger's hash is not the hash of the validated ledger
546  if (hash)
547  {
548  assert(hash->isNonZero());
549  uint256 valHash =
551  if (valHash == ledger.info().hash)
552  {
553  // SQL database doesn't match ledger chain
554  ledgerMaster.clearLedger(seq);
555  }
556  }
557  return false;
558  }
559  }
560  catch (SHAMapMissingNode const& mn)
561  {
562  auto stream = app.journal("RPCHandler").warn();
563  JLOG(stream) << "Ledger #" << seq << ": " << mn.what();
564  return false;
565  }
566 
567  // Mark ledger as validated to save time if we see it again.
568  ledger.info().validated = true;
569  return true;
570 }
571 
572 // The previous version of the lookupLedger command would accept the
573 // "ledger_index" argument as a string and silently treat it as a request to
574 // return the current ledger which, while not strictly wrong, could cause a lot
575 // of confusion.
576 //
577 // The code now robustly validates the input and ensures that the only possible
578 // values for the "ledger_index" parameter are the index of a ledger passed as
579 // an integer or one of the strings "current", "closed" or "validated".
580 // Additionally, the code ensures that the value passed in "ledger_hash" is a
581 // string and a valid hash. Invalid values will return an appropriate error
582 // code.
583 //
584 // In the absence of the "ledger_hash" or "ledger_index" parameters, the code
585 // assumes that "ledger_index" has the value "current".
586 //
587 // Returns a Json::objectValue. If there was an error, it will be in that
588 // return value. Otherwise, the object contains the field "validated" and
589 // optionally the fields "ledger_hash", "ledger_index" and
590 // "ledger_current_index", if they are defined.
591 Status
594  JsonContext& context,
595  Json::Value& result)
596 {
597  if (auto status = ledgerFromRequest(ledger, context))
598  return status;
599 
600  auto& info = ledger->info();
601 
602  if (!ledger->open())
603  {
604  result[jss::ledger_hash] = to_string(info.hash);
605  result[jss::ledger_index] = info.seq;
606  }
607  else
608  {
609  result[jss::ledger_current_index] = info.seq;
610  }
611 
612  result[jss::validated] =
613  isValidated(context.ledgerMaster, *ledger, context.app);
614  return Status::OK;
615 }
616 
619 {
620  Json::Value result;
621  if (auto status = lookupLedger(ledger, context, result))
622  status.inject(result);
623 
624  return result;
625 }
626 
629 {
630  hash_set<AccountID> result;
631  for (auto const& jv : jvArray)
632  {
633  if (!jv.isString())
634  return hash_set<AccountID>();
635  auto const id = parseBase58<AccountID>(jv.asString());
636  if (!id)
637  return hash_set<AccountID>();
638  result.insert(*id);
639  }
640  return result;
641 }
642 
643 void
644 injectSLE(Json::Value& jv, SLE const& sle)
645 {
646  jv = sle.getJson(JsonOptions::none);
647  if (sle.getType() == ltACCOUNT_ROOT)
648  {
649  if (sle.isFieldPresent(sfEmailHash))
650  {
651  auto const& hash = sle.getFieldH128(sfEmailHash);
652  Blob const b(hash.begin(), hash.end());
653  std::string md5 = strHex(makeSlice(b));
654  boost::to_lower(md5);
655  // VFALCO TODO Give a name and move this constant
656  // to a more visible location. Also
657  // shouldn't this be https?
658  jv[jss::urlgravatar] =
659  str(boost::format("http://www.gravatar.com/avatar/%s") % md5);
660  }
661  }
662  else
663  {
664  jv[jss::Invalid] = true;
665  }
666 }
667 
670  unsigned int& limit,
671  Tuning::LimitRange const& range,
672  JsonContext const& context)
673 {
674  limit = range.rdefault;
675  if (auto const& jvLimit = context.params[jss::limit])
676  {
677  if (!(jvLimit.isUInt() || (jvLimit.isInt() && jvLimit.asInt() >= 0)))
678  return RPC::expected_field_error(jss::limit, "unsigned integer");
679 
680  limit = jvLimit.asUInt();
681  if (!isUnlimited(context.role))
682  limit = std::max(range.rmin, std::min(range.rmax, limit));
683  }
684  return std::nullopt;
685 }
686 
689 {
690  // ripple-lib encodes seed used to generate an Ed25519 wallet in a
691  // non-standard way. While rippled never encode seeds that way, we
692  // try to detect such keys to avoid user confusion.
693  if (!value.isString())
694  return std::nullopt;
695 
696  auto const result = decodeBase58Token(value.asString(), TokenType::None);
697 
698  if (result.size() == 18 &&
699  static_cast<std::uint8_t>(result[0]) == std::uint8_t(0xE1) &&
700  static_cast<std::uint8_t>(result[1]) == std::uint8_t(0x4B))
701  return Seed(makeSlice(result.substr(2)));
702 
703  return std::nullopt;
704 }
705 
707 getSeedFromRPC(Json::Value const& params, Json::Value& error)
708 {
709  using string_to_seed_t =
711  using seed_match_t = std::pair<char const*, string_to_seed_t>;
712 
713  static seed_match_t const seedTypes[]{
714  {jss::passphrase.c_str(),
715  [](std::string const& s) { return parseGenericSeed(s); }},
716  {jss::seed.c_str(),
717  [](std::string const& s) { return parseBase58<Seed>(s); }},
718  {jss::seed_hex.c_str(), [](std::string const& s) {
719  uint128 i;
720  if (i.parseHex(s))
721  return std::optional<Seed>(Slice(i.data(), i.size()));
722  return std::optional<Seed>{};
723  }}};
724 
725  // Identify which seed type is in use.
726  seed_match_t const* seedType = nullptr;
727  int count = 0;
728  for (auto const& t : seedTypes)
729  {
730  if (params.isMember(t.first))
731  {
732  ++count;
733  seedType = &t;
734  }
735  }
736 
737  if (count != 1)
738  {
739  error = RPC::make_param_error(
740  "Exactly one of the following must be specified: " +
741  std::string(jss::passphrase) + ", " + std::string(jss::seed) +
742  " or " + std::string(jss::seed_hex));
743  return std::nullopt;
744  }
745 
746  // Make sure a string is present
747  auto const& param = params[seedType->first];
748  if (!param.isString())
749  {
750  error = RPC::expected_field_error(seedType->first, "string");
751  return std::nullopt;
752  }
753 
754  auto const fieldContents = param.asString();
755 
756  // Convert string to seed.
757  std::optional<Seed> seed = seedType->second(fieldContents);
758 
759  if (!seed)
760  error = rpcError(rpcBAD_SEED);
761 
762  return seed;
763 }
764 
767 {
768  bool const has_key_type = params.isMember(jss::key_type);
769 
770  // All of the secret types we allow, but only one at a time.
771  static char const* const secretTypes[]{
772  jss::passphrase.c_str(),
773  jss::secret.c_str(),
774  jss::seed.c_str(),
775  jss::seed_hex.c_str()};
776 
777  // Identify which secret type is in use.
778  char const* secretType = nullptr;
779  int count = 0;
780  for (auto t : secretTypes)
781  {
782  if (params.isMember(t))
783  {
784  ++count;
785  secretType = t;
786  }
787  }
788 
789  if (count == 0 || secretType == nullptr)
790  {
791  error = RPC::missing_field_error(jss::secret);
792  return {};
793  }
794 
795  if (count > 1)
796  {
797  error = RPC::make_param_error(
798  "Exactly one of the following must be specified: " +
799  std::string(jss::passphrase) + ", " + std::string(jss::secret) +
800  ", " + std::string(jss::seed) + " or " +
801  std::string(jss::seed_hex));
802  return {};
803  }
804 
805  std::optional<KeyType> keyType;
806  std::optional<Seed> seed;
807 
808  if (has_key_type)
809  {
810  if (!params[jss::key_type].isString())
811  {
812  error = RPC::expected_field_error(jss::key_type, "string");
813  return {};
814  }
815 
816  keyType = keyTypeFromString(params[jss::key_type].asString());
817 
818  if (!keyType)
819  {
820  error = RPC::invalid_field_error(jss::key_type);
821  return {};
822  }
823 
824  // using strcmp as pointers may not match (see
825  // https://developercommunity.visualstudio.com/t/assigning-constexpr-char--to-static-cha/10021357?entry=problem)
826  if (strcmp(secretType, jss::secret.c_str()) == 0)
827  {
828  error = RPC::make_param_error(
829  "The secret field is not allowed if " +
830  std::string(jss::key_type) + " is used.");
831  return {};
832  }
833  }
834 
835  // ripple-lib encodes seed used to generate an Ed25519 wallet in a
836  // non-standard way. While we never encode seeds that way, we try
837  // to detect such keys to avoid user confusion.
838  // using strcmp as pointers may not match (see
839  // https://developercommunity.visualstudio.com/t/assigning-constexpr-char--to-static-cha/10021357?entry=problem)
840  if (strcmp(secretType, jss::seed_hex.c_str()) != 0)
841  {
842  seed = RPC::parseRippleLibSeed(params[secretType]);
843 
844  if (seed)
845  {
846  // If the user passed in an Ed25519 seed but *explicitly*
847  // requested another key type, return an error.
849  {
850  error = RPC::make_error(
851  rpcBAD_SEED, "Specified seed is for an Ed25519 wallet.");
852  return {};
853  }
854 
855  keyType = KeyType::ed25519;
856  }
857  }
858 
859  if (!keyType)
860  keyType = KeyType::secp256k1;
861 
862  if (!seed)
863  {
864  if (has_key_type)
865  seed = getSeedFromRPC(params, error);
866  else
867  {
868  if (!params[jss::secret].isString())
869  {
870  error = RPC::expected_field_error(jss::secret, "string");
871  return {};
872  }
873 
874  seed = parseGenericSeed(params[jss::secret].asString());
875  }
876  }
877 
878  if (!seed)
879  {
880  if (!contains_error(error))
881  {
882  error = RPC::make_error(
884  }
885 
886  return {};
887  }
888 
889  if (keyType != KeyType::secp256k1 && keyType != KeyType::ed25519)
890  LogicError("keypairForSignature: invalid key type");
891 
892  return generateKeyPair(*keyType, *seed);
893 }
894 
897 {
899  if (params.isMember(jss::type))
900  {
902  types{
903  {{jss::account, ltACCOUNT_ROOT},
904  {jss::amendments, ltAMENDMENTS},
905  {jss::check, ltCHECK},
906  {jss::deposit_preauth, ltDEPOSIT_PREAUTH},
907  {jss::directory, ltDIR_NODE},
908  {jss::escrow, ltESCROW},
909  {jss::fee, ltFEE_SETTINGS},
910  {jss::hashes, ltLEDGER_HASHES},
911  {jss::offer, ltOFFER},
912  {jss::payment_channel, ltPAYCHAN},
913  {jss::signer_list, ltSIGNER_LIST},
914  {jss::state, ltRIPPLE_STATE},
915  {jss::ticket, ltTICKET},
916  {jss::nft_offer, ltNFTOKEN_OFFER}}};
917 
918  auto const& p = params[jss::type];
919  if (!p.isString())
920  {
921  result.first = RPC::Status{
922  rpcINVALID_PARAMS, "Invalid field 'type', not string."};
923  assert(result.first.type() == RPC::Status::Type::error_code_i);
924  return result;
925  }
926 
927  auto const filter = p.asString();
928  auto iter = std::find_if(
929  types.begin(), types.end(), [&filter](decltype(types.front())& t) {
930  return t.first == filter;
931  });
932  if (iter == types.end())
933  {
934  result.first =
935  RPC::Status{rpcINVALID_PARAMS, "Invalid field 'type'."};
936  assert(result.first.type() == RPC::Status::Type::error_code_i);
937  return result;
938  }
939  result.second = iter->second;
940  }
941  return result;
942 }
943 
944 beast::SemanticVersion const firstVersion("1.0.0");
945 beast::SemanticVersion const goodVersion("1.0.0");
946 beast::SemanticVersion const lastVersion("1.0.0");
947 
948 unsigned int
949 getAPIVersionNumber(Json::Value const& jv, bool betaEnabled)
950 {
951  static Json::Value const minVersion(RPC::apiMinimumSupportedVersion);
952  static Json::Value const invalidVersion(RPC::apiInvalidVersion);
953 
954  Json::Value const maxVersion(
956  Json::Value requestedVersion(RPC::apiVersionIfUnspecified);
957  if (jv.isObject())
958  {
959  requestedVersion = jv.get(jss::api_version, requestedVersion);
960  }
961  if (!(requestedVersion.isInt() || requestedVersion.isUInt()) ||
962  requestedVersion < minVersion || requestedVersion > maxVersion)
963  {
964  requestedVersion = invalidVersion;
965  }
966  return requestedVersion.asUInt();
967 }
968 
971 {
972  if (context.app.config().reporting())
974 
975  auto const hasHash = context.params.isMember(jss::ledger_hash);
976  auto const hasIndex = context.params.isMember(jss::ledger_index);
977  std::uint32_t ledgerIndex = 0;
978 
979  auto& ledgerMaster = context.app.getLedgerMaster();
980  LedgerHash ledgerHash;
981 
982  if ((hasHash && hasIndex) || !(hasHash || hasIndex))
983  {
984  return RPC::make_param_error(
985  "Exactly one of ledger_hash and ledger_index can be set.");
986  }
987 
989 
990  if (hasHash)
991  {
992  auto const& jsonHash = context.params[jss::ledger_hash];
993  if (!jsonHash.isString() || !ledgerHash.parseHex(jsonHash.asString()))
994  return RPC::invalid_field_error(jss::ledger_hash);
995  }
996  else
997  {
998  auto const& jsonIndex = context.params[jss::ledger_index];
999  if (!jsonIndex.isInt())
1000  return RPC::invalid_field_error(jss::ledger_index);
1001 
1002  // We need a validated ledger to get the hash from the sequence
1003  if (ledgerMaster.getValidatedLedgerAge() >
1005  {
1006  if (context.apiVersion == 1)
1007  return rpcError(rpcNO_CURRENT);
1008  return rpcError(rpcNOT_SYNCED);
1009  }
1010 
1011  ledgerIndex = jsonIndex.asInt();
1012  auto ledger = ledgerMaster.getValidatedLedger();
1013 
1014  if (ledgerIndex >= ledger->info().seq)
1015  return RPC::make_param_error("Ledger index too large");
1016  if (ledgerIndex <= 0)
1017  return RPC::make_param_error("Ledger index too small");
1018 
1019  auto const j = context.app.journal("RPCHandler");
1020  // Try to get the hash of the desired ledger from the validated ledger
1021  auto neededHash = hashOfSeq(*ledger, ledgerIndex, j);
1022  if (!neededHash)
1023  {
1024  // Find a ledger more likely to have the hash of the desired ledger
1025  auto const refIndex = getCandidateLedger(ledgerIndex);
1026  auto refHash = hashOfSeq(*ledger, refIndex, j);
1027  assert(refHash);
1028 
1029  ledger = ledgerMaster.getLedgerByHash(*refHash);
1030  if (!ledger)
1031  {
1032  // We don't have the ledger we need to figure out which ledger
1033  // they want. Try to get it.
1034 
1035  if (auto il = context.app.getInboundLedgers().acquire(
1036  *refHash, refIndex, InboundLedger::Reason::GENERIC))
1037  {
1038  Json::Value jvResult = RPC::make_error(
1040  "acquiring ledger containing requested index");
1041  jvResult[jss::acquiring] =
1042  getJson(LedgerFill(*il, &context));
1043  return jvResult;
1044  }
1045 
1046  if (auto il = context.app.getInboundLedgers().find(*refHash))
1047  {
1048  Json::Value jvResult = RPC::make_error(
1050  "acquiring ledger containing requested index");
1051  jvResult[jss::acquiring] = il->getJson(0);
1052  return jvResult;
1053  }
1054 
1055  // Likely the app is shutting down
1056  return Json::Value();
1057  }
1058 
1059  neededHash = hashOfSeq(*ledger, ledgerIndex, j);
1060  }
1061  assert(neededHash);
1062  ledgerHash = neededHash ? *neededHash : beast::zero; // kludge
1063  }
1064 
1065  // Try to get the desired ledger
1066  // Verify all nodes even if we think we have it
1067  auto ledger = context.app.getInboundLedgers().acquire(
1068  ledgerHash, ledgerIndex, InboundLedger::Reason::GENERIC);
1069 
1070  // In standalone mode, accept the ledger from the ledger cache
1071  if (!ledger && context.app.config().standalone())
1072  ledger = ledgerMaster.getLedgerByHash(ledgerHash);
1073 
1074  if (ledger)
1075  return ledger;
1076 
1077  if (auto il = context.app.getInboundLedgers().find(ledgerHash))
1078  return il->getJson(0);
1079 
1080  return RPC::make_error(
1081  rpcNOT_READY, "findCreate failed to return an inbound ledger");
1082 }
1083 } // namespace RPC
1084 } // namespace ripple
Json::Value::isInt
bool isInt() const
Definition: json_value.cpp:979
ripple::ReadView::info
virtual LedgerInfo const & info() const =0
Returns information about the ledger.
ripple::RPC::apiInvalidVersion
constexpr unsigned int apiInvalidVersion
API version numbers used in later API versions.
Definition: RPCHelpers.h:241
ripple::sfIndexNext
const SF_UINT64 sfIndexNext
ripple::keylet::ownerDir
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition: Indexes.cpp:303
ripple::Application
Definition: Application.h:115
ripple::RPC::apiVersionIfUnspecified
constexpr unsigned int apiVersionIfUnspecified
Definition: RPCHelpers.h:242
ripple::rpcNO_NETWORK
@ rpcNO_NETWORK
Definition: ErrorCodes.h:66
ripple::RPC::JsonContext
Definition: Context.h:53
ripple::HashPrefix::ledgerMaster
@ ledgerMaster
ledger master data for signing
ripple::ltTICKET
@ ltTICKET
A ledger object which describes a ticket.
Definition: LedgerFormats.h:80
ripple::makeSlice
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
ripple::Keylet
A pair of SHAMap key and LedgerEntryType.
Definition: Keylet.h:38
ripple::STLedgerEntry::getJson
Json::Value getJson(JsonOptions options) const override
Definition: STLedgerEntry.cpp:117
ripple::STLedgerEntry
Definition: STLedgerEntry.h:30
ripple::RPC::firstVersion
const beast::SemanticVersion firstVersion("1.0.0")
API version numbers used in API version 1.
Definition: RPCHelpers.h:215
Json::Value::isObject
bool isObject() const
Definition: json_value.cpp:1027
ripple::RPC::goodVersion
const beast::SemanticVersion goodVersion("1.0.0")
Definition: RPCHelpers.h:216
std::string
STL class.
std::shared_ptr
STL class.
ripple::rpcINVALID_PARAMS
@ rpcINVALID_PARAMS
Definition: ErrorCodes.h:84
Json::Value::isString
bool isString() const
Definition: json_value.cpp:1009
ripple::rpcError
Json::Value rpcError(int iError)
Definition: RPCErr.cpp:29
ripple::ltANY
@ ltANY
A special type, matching any ledger entry type.
Definition: LedgerFormats.h:176
ripple::sfOwnerNode
const SF_UINT64 sfOwnerNode
ripple::sfDestination
const SF_ACCOUNT sfDestination
ripple::ltLEDGER_HASHES
@ ltLEDGER_HASHES
A ledger object that contains a list of ledger hashes.
Definition: LedgerFormats.h:102
ripple::Slice
An immutable linear range of bytes.
Definition: Slice.h:44
std::unordered_set
STL class.
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
ripple::RPC::injectSLE
void injectSLE(Json::Value &jv, SLE const &sle)
Inject JSON describing ledger entry.
Definition: RPCHelpers.cpp:644
std::pair
ripple::RPC::LedgerShortcut
LedgerShortcut
Definition: RPCHelpers.h:129
ripple::LedgerInfo::hash
uint256 hash
Definition: ReadView.h:91
ripple::sfOwner
const SF_ACCOUNT sfOwner
ripple::LedgerMaster
Definition: LedgerMaster.h:70
ripple::LedgerMaster::getValidLedgerIndex
LedgerIndex getValidLedgerIndex()
Definition: LedgerMaster.cpp:213
ripple::RPC::Context::loadType
Resource::Charge & loadType
Definition: Context.h:43
Json::Value::get
Value get(UInt index, const Value &defaultValue) const
If the array contains at least index+1 elements, returns the element value, otherwise returns default...
Definition: json_value.cpp:834
ripple::keyTypeFromString
std::optional< KeyType > keyTypeFromString(std::string const &s)
Definition: KeyType.h:34
ripple::InboundLedger::Reason::GENERIC
@ GENERIC
ripple::RPC::getAPIVersionNumber
unsigned int getAPIVersionNumber(Json::Value const &jv, bool betaEnabled)
Retrieve the api version number from the json value.
Definition: RPCHelpers.cpp:949
std::vector
STL class.
std::find
T find(T... args)
std::optional::value_or
T value_or(T... args)
ripple::ltSIGNER_LIST
@ ltSIGNER_LIST
A ledger object which contains a signer list for an account.
Definition: LedgerFormats.h:86
ripple::rpcNOT_READY
@ rpcNOT_READY
Definition: ErrorCodes.h:60
ripple::RPC::Context::ledgerMaster
LedgerMaster & ledgerMaster
Definition: Context.h:45
ripple::decodeBase58Token
std::string decodeBase58Token(std::string const &s, TokenType type)
Decode a token of given type encoded using Base58Check and the XRPL alphabet.
Definition: tokens.cpp:223
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
ripple::keylet::child
Keylet child(uint256 const &key) noexcept
Any item that can be in an owner dir.
Definition: Indexes.cpp:139
ripple::RPC::readLimitField
std::optional< Json::Value > readLimitField(unsigned int &limit, Tuning::LimitRange const &range, JsonContext const &context)
Retrieve the limit value from a JsonContext, or set a default - then restrict the limit by max and mi...
Definition: RPCHelpers.cpp:669
ripple::STObject::getFieldH128
uint128 getFieldH128(SField const &field) const
Definition: STObject.cpp:571
ripple::LedgerMaster::getLedgerByHash
std::shared_ptr< Ledger const > getLedgerByHash(uint256 const &hash)
Definition: LedgerMaster.cpp:1852
beast::SemanticVersion
A Semantic Version number.
Definition: SemanticVersion.h:35
std::function
ripple::LedgerInfo::seq
LedgerIndex seq
Definition: ReadView.h:83
ripple::ltCHECK
@ ltCHECK
A ledger object which describes a check.
Definition: LedgerFormats.h:136
ripple::RPC::Context::role
Role role
Definition: Context.h:47
ripple::ltFEE_SETTINGS
@ ltFEE_SETTINGS
The ledger object which lists the network's fee settings.
Definition: LedgerFormats.h:118
ripple::base_uint< 256 >::fromVoidChecked
static std::optional< base_uint > fromVoidChecked(T const &from)
Definition: base_uint.h:319
ripple::RPC::getLedgerByContext
std::variant< std::shared_ptr< Ledger const >, Json::Value > getLedgerByContext(RPC::JsonContext &context)
Return a ledger based on ledger_hash or ledger_index, or an RPC error.
Definition: RPCHelpers.cpp:970
ripple::TokenType::None
@ None
ripple::rpcLGR_NOT_FOUND
@ rpcLGR_NOT_FOUND
Definition: ErrorCodes.h:72
ripple::RPC::apiBetaVersion
constexpr unsigned int apiBetaVersion
Definition: RPCHelpers.h:245
ripple::rpcREPORTING_UNSUPPORTED
@ rpcREPORTING_UNSUPPORTED
Definition: ErrorCodes.h:141
ripple::base_uint::data
pointer data()
Definition: base_uint.h:122
ripple::RPC::lookupLedger
Status lookupLedger(std::shared_ptr< ReadView const > &ledger, JsonContext &context, Json::Value &result)
Look up a ledger from a request and fill a Json::Result with the data representing a ledger.
Definition: RPCHelpers.cpp:592
ripple::generateKeyPair
std::pair< PublicKey, SecretKey > generateKeyPair(KeyType type, Seed const &seed)
Generate a key pair deterministically.
Definition: SecretKey.cpp:351
ripple::error_code_i
error_code_i
Definition: ErrorCodes.h:40
ripple::RPC::expected_field_error
Json::Value expected_field_error(std::string const &name, std::string const &type)
Definition: ErrorCodes.h:328
ripple::Application::getInboundLedgers
virtual InboundLedgers & getInboundLedgers()=0
ripple::base_uint::size
constexpr static std::size_t size()
Definition: base_uint.h:519
ripple::ltDIR_NODE
@ ltDIR_NODE
A ledger object which contains a list of object identifiers.
Definition: LedgerFormats.h:66
ripple::SHAMapMissingNode
Definition: SHAMapMissingNode.h:55
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:550
ripple::RPC::missing_field_error
Json::Value missing_field_error(std::string const &name)
Definition: ErrorCodes.h:262
ripple::sfIndexes
const SF_VECTOR256 sfIndexes
ripple::KeyType::ed25519
@ ed25519
ripple::sfLowNode
const SF_UINT64 sfLowNode
ripple::Keylet::key
uint256 key
Definition: Keylet.h:40
ripple::base_uint< 160, detail::AccountIDTag >
ripple::ltAMENDMENTS
@ ltAMENDMENTS
The ledger object which lists details about amendments on the network.
Definition: LedgerFormats.h:110
ripple::sfLowLimit
const SF_AMOUNT sfLowLimit
ripple::RPC::parseRippleLibSeed
std::optional< Seed > parseRippleLibSeed(Json::Value const &value)
Definition: RPCHelpers.cpp:688
ripple::RPC::Status::OK
static constexpr Code OK
Definition: Status.h:46
ripple::rpcSUCCESS
@ rpcSUCCESS
Definition: ErrorCodes.h:44
ripple::ltOFFER
@ ltOFFER
A ledger object which describes an offer on the DEX.
Definition: LedgerFormats.h:92
ripple::Config::reporting
bool reporting() const
Definition: Config.h:318
ripple::base_uint::isZero
bool isZero() const
Definition: base_uint.h:532
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
ripple::RPC::contains_error
bool contains_error(Json::Value const &json)
Returns true if the json contains an rpc error specification.
Definition: ErrorCodes.cpp:194
ripple::RPC::accountFromStringWithCode
error_code_i accountFromStringWithCode(AccountID &result, std::string const &strIdent, bool bStrict)
Decode account ID from string.
Definition: RPCHelpers.cpp:58
ripple::Application::getLedgerMaster
virtual LedgerMaster & getLedgerMaster()=0
ripple::InboundLedgers::acquire
virtual std::shared_ptr< Ledger const > acquire(uint256 const &hash, std::uint32_t seq, InboundLedger::Reason)=0
ripple::ltESCROW
@ ltESCROW
A ledger object describing a single escrow.
Definition: LedgerFormats.h:124
ripple::RelationalDatabase::getHashByIndex
virtual uint256 getHashByIndex(LedgerIndex ledgerIndex)=0
getHashByIndex Returns the hash of the ledger with the given sequence.
ripple::JsonOptions::none
@ none
ripple::Application::config
virtual Config & config()=0
ripple::ltNFTOKEN_OFFER
@ ltNFTOKEN_OFFER
A ledger object which identifies an offer to buy or sell an NFT.
Definition: LedgerFormats.h:162
ripple::rpcBAD_SEED
@ rpcBAD_SEED
Definition: ErrorCodes.h:99
ripple::keylet::page
Keylet page(uint256 const &key, std::uint64_t index) noexcept
A page in a directory.
Definition: Indexes.cpp:309
ripple::Config::standalone
bool standalone() const
Definition: Config.h:313
ripple::RPC::GRPCContext
Definition: Context.h:70
ripple::calcAccountID
AccountID calcAccountID(PublicKey const &pk)
Definition: AccountID.cpp:158
ripple::Application::getRelationalDatabase
virtual RelationalDatabase & getRelationalDatabase()=0
std::array
STL class.
ripple::RPC::Status::Type::error_code_i
@ error_code_i
ripple::ltDEPOSIT_PREAUTH
@ ltDEPOSIT_PREAUTH
A ledger object which describes a deposit preauthorization.
Definition: LedgerFormats.h:142
ripple::RPC::Context::app
Application & app
Definition: Context.h:42
ripple::hashOfSeq
std::optional< uint256 > hashOfSeq(ReadView const &ledger, LedgerIndex seq, beast::Journal journal)
Return the hash of a ledger by sequence.
Definition: View.cpp:644
ripple::LedgerMaster::getLedgerBySeq
std::shared_ptr< Ledger const > getLedgerBySeq(std::uint32_t index)
Definition: LedgerMaster.cpp:1816
Json::Value::isMember
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:932
ripple::rpcNO_CURRENT
@ rpcNO_CURRENT
Definition: ErrorCodes.h:65
std::uint64_t
ripple::sfHighLimit
const SF_AMOUNT sfHighLimit
ripple::parseGenericSeed
std::optional< Seed > parseGenericSeed(std::string const &str, bool rfc1751)
Attempt to parse a string as a seed.
Definition: Seed.cpp:90
ripple::range
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
Definition: RangeSet.h:53
ripple::STLedgerEntry::getType
LedgerEntryType getType() const
Definition: STLedgerEntry.h:119
ripple::LedgerMaster::getCurrentLedger
std::shared_ptr< ReadView const > getCurrentLedger()
Definition: LedgerMaster.cpp:1652
ripple::ReadView::read
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
ripple::RPC::Status
Status represents the results of an operation that might fail.
Definition: Status.h:39
ripple::KeyType::secp256k1
@ secp256k1
std::min
T min(T... args)
ripple::isUnlimited
bool isUnlimited(Role const &role)
ADMIN and IDENTIFIED roles shall have unlimited resources.
Definition: Role.cpp:124
ripple::sfEmailHash
const SF_UINT128 sfEmailHash
ripple::NodeStore::Status
Status
Return codes from Backend operations.
Definition: nodestore/Types.h:44
ripple::getJson
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
Definition: LedgerToJson.cpp:291
ripple::LedgerMaster::getClosedLedger
std::shared_ptr< Ledger const > getClosedLedger()
Definition: LedgerMaster.h:98
ripple::RPC::invalid_field_message
std::string invalid_field_message(std::string const &name)
Definition: ErrorCodes.h:292
ripple::RPC::GRPCContext::params
RequestType params
Definition: Context.h:72
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:125
ripple::RPC::apiMinimumSupportedVersion
constexpr unsigned int apiMinimumSupportedVersion
Definition: RPCHelpers.h:243
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::Application::journal
virtual beast::Journal journal(std::string const &name)=0
ripple::RPC::isValidated
bool isValidated(LedgerMaster &ledgerMaster, ReadView const &ledger, Application &app)
Definition: RPCHelpers.cpp:520
ripple::rpcACT_MALFORMED
@ rpcACT_MALFORMED
Definition: ErrorCodes.h:90
ripple::RPC::getLedger
Status getLedger(T &ledger, uint256 const &ledgerHash, Context &context)
Get ledger by hash If there is no error in the return value, the ledger pointer will have been filled...
Definition: RPCHelpers.cpp:396
ripple::Seed
Seeds are used to generate deterministic secret keys.
Definition: Seed.h:32
ripple::LedgerEntryType
LedgerEntryType
Identifiers for on-ledger objects.
Definition: LedgerFormats.h:53
beast::lexicalCastChecked
bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
Definition: LexicalCast.h:266
ripple::RPC::chooseLedgerEntryType
std::pair< RPC::Status, LedgerEntryType > chooseLedgerEntryType(Json::Value const &params)
Definition: RPCHelpers.cpp:896
std::vector::begin
T begin(T... args)
ripple::LogicError
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
Definition: contract.cpp:48
ripple::ltACCOUNT_ROOT
@ ltACCOUNT_ROOT
A ledger object which describes an account.
Definition: LedgerFormats.h:59
ripple::STObject::isFieldPresent
bool isFieldPresent(SField const &field) const
Definition: STObject.cpp:428
std::unordered_set::insert
T insert(T... args)
ripple::RPC::getStartHint
std::uint64_t getStartHint(std::shared_ptr< SLE const > const &sle, AccountID const &accountID)
Gets the start hint for traversing account objects.
Definition: RPCHelpers.cpp:96
Json::Value::asUInt
UInt asUInt() const
Definition: json_value.cpp:545
Json::Value::isUInt
bool isUInt() const
Definition: json_value.cpp:985
ripple::RPC::keypairForSignature
std::pair< PublicKey, SecretKey > keypairForSignature(Json::Value const &params, Json::Value &error)
Definition: RPCHelpers.cpp:766
ripple::RPC::getSeedFromRPC
std::optional< Seed > getSeedFromRPC(Json::Value const &params, Json::Value &error)
Definition: RPCHelpers.cpp:707
ripple::RPC::Context::apiVersion
unsigned int apiVersion
Definition: Context.h:50
ripple::TokenType::AccountPublic
@ AccountPublic
ripple::RPC::apiMaximumSupportedVersion
constexpr unsigned int apiMaximumSupportedVersion
Definition: RPCHelpers.h:244
ripple::LedgerMaster::getValidatedLedger
std::shared_ptr< Ledger const > getValidatedLedger()
Definition: LedgerMaster.cpp:1662
ripple::RPC::ledgerFromSpecifier
Status ledgerFromSpecifier(T &ledger, org::xrpl::rpc::v1::LedgerSpecifier const &specifier, Context &context)
Definition: RPCHelpers.cpp:337
std::optional
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::sfAccount
const SF_ACCOUNT sfAccount
ripple::ltRIPPLE_STATE
@ ltRIPPLE_STATE
A ledger object which describes a bidirectional trust line.
Definition: LedgerFormats.h:74
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:30
std::vector::end
T end(T... args)
ripple::RPC::parseAccountIds
hash_set< AccountID > parseAccountIds(Json::Value const &jvArray)
Definition: RPCHelpers.cpp:628
std::max
T max(T... args)
ripple::base_uint::parseHex
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:496
ripple::getCandidateLedger
LedgerIndex getCandidateLedger(LedgerIndex requested)
Find a ledger index from which we could easily get the requested ledger.
Definition: View.h:219
ripple::RPC::Tuning::LimitRange
Represents RPC limit parameter values that have a min, default and max.
Definition: rpc/impl/Tuning.h:31
ripple::keylet::signers
static Keylet signers(AccountID const &account, std::uint32_t page) noexcept
Definition: Indexes.cpp:268
ripple::RPC::make_param_error
Json::Value make_param_error(std::string const &message)
Returns a new json object that indicates invalid parameters.
Definition: ErrorCodes.h:250
ripple::LedgerInfo::validated
bool validated
Definition: ReadView.h:101
ripple::RPC::accountFromStringStrict
std::optional< AccountID > accountFromStringStrict(std::string const &account)
Get an AccountID from an account ID or public key.
Definition: RPCHelpers.cpp:42
ripple::LedgerFill
Definition: LedgerToJson.h:33
ripple::ReadView::open
virtual bool open() const =0
Returns true if this reflects an open ledger.
ripple::RPC::JsonContext::params
Json::Value params
Definition: Context.h:64
ripple::RPC::lastVersion
const beast::SemanticVersion lastVersion("1.0.0")
Definition: RPCHelpers.h:217
ripple::RPC::invalid_field_error
Json::Value invalid_field_error(std::string const &name)
Definition: ErrorCodes.h:304
ripple::sfHighNode
const SF_UINT64 sfHighNode
ripple::RPC::Context
The context of information needed to call an RPC.
Definition: Context.h:39
ripple::RPC::ledgerFromRequest
Status ledgerFromRequest(T &ledger, GRPCContext< R > &context)
Definition: RPCHelpers.cpp:311
ripple::Resource::feeHighBurdenRPC
const Charge feeHighBurdenRPC
ripple::RPC::accountFromString
Json::Value accountFromString(AccountID &result, std::string const &strIdent, bool bStrict)
Definition: RPCHelpers.cpp:86
ripple::RPC::make_error
Json::Value make_error(error_code_i code)
Returns a new json object that reflects the error code.
Definition: ErrorCodes.cpp:178
ripple::RPC::Tuning::maxValidatedLedgerAge
constexpr auto maxValidatedLedgerAge
Definition: rpc/impl/Tuning.h:65
ripple::rpcNOT_SYNCED
@ rpcNOT_SYNCED
Definition: ErrorCodes.h:67
ripple::RPC::isRelatedToAccount
bool isRelatedToAccount(ReadView const &ledger, std::shared_ptr< SLE const > const &sle, AccountID const &accountID)
Tests if a SLE is owned by accountID.
Definition: RPCHelpers.cpp:113
std::runtime_error::what
T what(T... args)
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::ltPAYCHAN
@ ltPAYCHAN
A ledger object describing a single unidirectional XRP payment channel.
Definition: LedgerFormats.h:130
ripple::InboundLedgers::find
virtual std::shared_ptr< InboundLedger > find(LedgerHash const &hash)=0
ripple::RPC::getAccountObjects
bool getAccountObjects(ReadView const &ledger, AccountID const &account, std::optional< std::vector< LedgerEntryType >> const &typeFilter, uint256 dirIndex, uint256 const &entryIndex, std::uint32_t const limit, Json::Value &jvResult)
Gathers all objects for an account in a ledger.
Definition: RPCHelpers.cpp:151
std::variant
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:469
ripple::root
Number root(Number f, unsigned d)
Definition: Number.cpp:624