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/protocol/nftPageMask.h>
32 #include <ripple/resource/Fees.h>
33 #include <ripple/rpc/Context.h>
34 #include <ripple/rpc/DeliveredAmount.h>
35 #include <ripple/rpc/impl/RPCHelpers.h>
36 #include <boost/algorithm/string/case_conv.hpp>
37 #include <regex>
38 
39 namespace ripple {
40 namespace RPC {
41 
44 {
46 
47  auto const publicKey =
48  parseBase58<PublicKey>(TokenType::AccountPublic, account);
49 
50  if (publicKey)
51  result = calcAccountID(*publicKey);
52  else
53  result = parseBase58<AccountID>(account);
54 
55  return result;
56 }
57 
60  AccountID& result,
61  std::string const& strIdent,
62  bool bStrict)
63 {
64  if (auto accountID = accountFromStringStrict(strIdent))
65  {
66  result = *accountID;
67  return rpcSUCCESS;
68  }
69 
70  if (bStrict)
71  return rpcACT_MALFORMED;
72 
73  // We allow the use of the seeds which is poor practice
74  // and merely for debugging convenience.
75  auto const seed = parseGenericSeed(strIdent);
76 
77  if (!seed)
78  return rpcBAD_SEED;
79 
80  auto const keypair = generateKeyPair(KeyType::secp256k1, *seed);
81 
82  result = calcAccountID(keypair.first);
83  return rpcSUCCESS;
84 }
85 
87 accountFromString(AccountID& result, std::string const& strIdent, bool bStrict)
88 {
89  error_code_i code = accountFromStringWithCode(result, strIdent, bStrict);
90  if (code != rpcSUCCESS)
91  return rpcError(code);
92  else
93  return Json::objectValue;
94 }
95 
97 getStartHint(std::shared_ptr<SLE const> const& sle, AccountID const& accountID)
98 {
99  if (sle->getType() == ltRIPPLE_STATE)
100  {
101  if (sle->getFieldAmount(sfLowLimit).getIssuer() == accountID)
102  return sle->getFieldU64(sfLowNode);
103  else if (sle->getFieldAmount(sfHighLimit).getIssuer() == accountID)
104  return sle->getFieldU64(sfHighNode);
105  }
106 
107  if (!sle->isFieldPresent(sfOwnerNode))
108  return 0;
109 
110  return sle->getFieldU64(sfOwnerNode);
111 }
112 
113 bool
115  ReadView const& ledger,
116  std::shared_ptr<SLE const> const& sle,
117  AccountID const& accountID)
118 {
119  if (sle->getType() == ltRIPPLE_STATE)
120  {
121  return (sle->getFieldAmount(sfLowLimit).getIssuer() == accountID) ||
122  (sle->getFieldAmount(sfHighLimit).getIssuer() == accountID);
123  }
124  else if (sle->isFieldPresent(sfAccount))
125  {
126  // If there's an sfAccount present, also test the sfDestination, if
127  // present. This will match objects such as Escrows (ltESCROW), Payment
128  // Channels (ltPAYCHAN), and Checks (ltCHECK) because those are added to
129  // the Destination account's directory. It intentionally EXCLUDES
130  // NFToken Offers (ltNFTOKEN_OFFER). NFToken Offers are NOT added to the
131  // Destination account's directory.
132  return sle->getAccountID(sfAccount) == accountID ||
133  (sle->isFieldPresent(sfDestination) &&
134  sle->getAccountID(sfDestination) == accountID);
135  }
136  else if (sle->getType() == ltSIGNER_LIST)
137  {
138  Keylet const accountSignerList = keylet::signers(accountID);
139  return sle->key() == accountSignerList.key;
140  }
141  else if (sle->getType() == ltNFTOKEN_OFFER)
142  {
143  // Do not check the sfDestination field. NFToken Offers are NOT added to
144  // the Destination account's directory.
145  return sle->getAccountID(sfOwner) == accountID;
146  }
147 
148  return false;
149 }
150 
151 bool
153  ReadView const& ledger,
154  AccountID const& account,
155  std::optional<std::vector<LedgerEntryType>> const& typeFilter,
156  uint256 dirIndex,
157  uint256 entryIndex,
158  std::uint32_t const limit,
159  Json::Value& jvResult)
160 {
161  auto typeMatchesFilter = [](std::vector<LedgerEntryType> const& typeFilter,
162  LedgerEntryType ledgerType) {
163  auto it = std::find(typeFilter.begin(), typeFilter.end(), ledgerType);
164  return it != typeFilter.end();
165  };
166 
167  // if dirIndex != 0, then all NFTs have already been returned. only
168  // iterate NFT pages if the filter says so AND dirIndex == 0
169  bool iterateNFTPages =
170  (!typeFilter.has_value() ||
171  typeMatchesFilter(typeFilter.value(), ltNFTOKEN_PAGE)) &&
172  dirIndex == beast::zero;
173 
174  Keylet const firstNFTPage = keylet::nftpage_min(account);
175 
176  // we need to check the marker to see if it is an NFTTokenPage index.
177  if (iterateNFTPages && entryIndex != beast::zero)
178  {
179  // if it is we will try to iterate the pages up to the limit
180  // and then change over to the owner directory
181 
182  if (firstNFTPage.key != (entryIndex & ~nft::pageMask))
183  iterateNFTPages = false;
184  }
185 
186  auto& jvObjects = (jvResult[jss::account_objects] = Json::arrayValue);
187 
188  // this is a mutable version of limit, used to seemlessly switch
189  // to iterating directory entries when nftokenpages are exhausted
190  uint32_t mlimit = limit;
191 
192  // iterate NFTokenPages preferentially
193  if (iterateNFTPages)
194  {
195  Keylet const first = entryIndex == beast::zero
196  ? firstNFTPage
197  : Keylet{ltNFTOKEN_PAGE, entryIndex};
198 
199  Keylet const last = keylet::nftpage_max(account);
200 
201  // current key
202  uint256 ck = ledger.succ(first.key, last.key.next()).value_or(last.key);
203 
204  // current page
205  auto cp = ledger.read(Keylet{ltNFTOKEN_PAGE, ck});
206 
207  while (cp)
208  {
209  jvObjects.append(cp->getJson(JsonOptions::none));
210  auto const npm = (*cp)[~sfNextPageMin];
211  if (npm)
212  cp = ledger.read(Keylet(ltNFTOKEN_PAGE, *npm));
213  else
214  cp = nullptr;
215 
216  if (--mlimit == 0)
217  {
218  if (cp)
219  {
220  jvResult[jss::limit] = limit;
221  jvResult[jss::marker] = std::string("0,") + to_string(ck);
222  return true;
223  }
224  }
225 
226  if (!npm)
227  break;
228 
229  ck = *npm;
230  }
231 
232  // if execution reaches here then we're about to transition
233  // to iterating the root directory (and the conventional
234  // behaviour of this RPC function.) Therefore we should
235  // zero entryIndex so as not to terribly confuse things.
236  entryIndex = beast::zero;
237  }
238 
239  auto const root = keylet::ownerDir(account);
240  auto found = false;
241 
242  if (dirIndex.isZero())
243  {
244  dirIndex = root.key;
245  found = true;
246  }
247 
248  auto dir = ledger.read({ltDIR_NODE, dirIndex});
249  if (!dir)
250  {
251  // it's possible the user had nftoken pages but no
252  // directory entries
253  return mlimit < limit;
254  }
255 
256  std::uint32_t i = 0;
257  for (;;)
258  {
259  auto const& entries = dir->getFieldV256(sfIndexes);
260  auto iter = entries.begin();
261 
262  if (!found)
263  {
264  iter = std::find(iter, entries.end(), entryIndex);
265  if (iter == entries.end())
266  return false;
267 
268  found = true;
269  }
270 
271  // it's possible that the returned NFTPages exactly filled the
272  // response. Check for that condition.
273  if (i == mlimit && mlimit < limit)
274  {
275  jvResult[jss::limit] = limit;
276  jvResult[jss::marker] =
277  to_string(dirIndex) + ',' + to_string(*iter);
278  return true;
279  }
280 
281  for (; iter != entries.end(); ++iter)
282  {
283  auto const sleNode = ledger.read(keylet::child(*iter));
284 
285  if (!typeFilter.has_value() ||
286  typeMatchesFilter(typeFilter.value(), sleNode->getType()))
287  {
288  jvObjects.append(sleNode->getJson(JsonOptions::none));
289  }
290 
291  if (++i == mlimit)
292  {
293  if (++iter != entries.end())
294  {
295  jvResult[jss::limit] = limit;
296  jvResult[jss::marker] =
297  to_string(dirIndex) + ',' + to_string(*iter);
298  return true;
299  }
300 
301  break;
302  }
303  }
304 
305  auto const nodeIndex = dir->getFieldU64(sfIndexNext);
306  if (nodeIndex == 0)
307  return true;
308 
309  dirIndex = keylet::page(root, nodeIndex).key;
310  dir = ledger.read({ltDIR_NODE, dirIndex});
311  if (!dir)
312  return true;
313 
314  if (i == mlimit)
315  {
316  auto const& e = dir->getFieldV256(sfIndexes);
317  if (!e.empty())
318  {
319  jvResult[jss::limit] = limit;
320  jvResult[jss::marker] =
321  to_string(dirIndex) + ',' + to_string(*e.begin());
322  }
323 
324  return true;
325  }
326  }
327 }
328 
329 namespace {
330 
331 bool
332 isValidatedOld(LedgerMaster& ledgerMaster, bool standaloneOrReporting)
333 {
334  if (standaloneOrReporting)
335  return false;
336 
337  return ledgerMaster.getValidatedLedgerAge() > Tuning::maxValidatedLedgerAge;
338 }
339 
340 template <class T>
341 Status
342 ledgerFromRequest(T& ledger, JsonContext& context)
343 {
344  ledger.reset();
345 
346  auto& params = context.params;
347 
348  auto indexValue = params[jss::ledger_index];
349  auto hashValue = params[jss::ledger_hash];
350 
351  // We need to support the legacy "ledger" field.
352  auto& legacyLedger = params[jss::ledger];
353  if (legacyLedger)
354  {
355  if (legacyLedger.asString().size() > 12)
356  hashValue = legacyLedger;
357  else
358  indexValue = legacyLedger;
359  }
360 
361  if (hashValue)
362  {
363  if (!hashValue.isString())
364  return {rpcINVALID_PARAMS, "ledgerHashNotString"};
365 
366  uint256 ledgerHash;
367  if (!ledgerHash.parseHex(hashValue.asString()))
368  return {rpcINVALID_PARAMS, "ledgerHashMalformed"};
369  return getLedger(ledger, ledgerHash, context);
370  }
371 
372  auto const index = indexValue.asString();
373 
374  if (index == "current" ||
375  (index.empty() && !context.app.config().reporting()))
376  return getLedger(ledger, LedgerShortcut::CURRENT, context);
377 
378  if (index == "validated" ||
379  (index.empty() && context.app.config().reporting()))
380  return getLedger(ledger, LedgerShortcut::VALIDATED, context);
381 
382  if (index == "closed")
383  return getLedger(ledger, LedgerShortcut::CLOSED, context);
384 
385  std::uint32_t iVal;
386  if (beast::lexicalCastChecked(iVal, index))
387  return getLedger(ledger, iVal, context);
388 
389  return {rpcINVALID_PARAMS, "ledgerIndexMalformed"};
390 }
391 } // namespace
392 
393 template <class T, class R>
394 Status
395 ledgerFromRequest(T& ledger, GRPCContext<R>& context)
396 {
397  R& request = context.params;
398  return ledgerFromSpecifier(ledger, request.ledger(), context);
399 }
400 
401 // explicit instantiation of above function
402 template Status
403 ledgerFromRequest<>(
405  GRPCContext<org::xrpl::rpc::v1::GetLedgerEntryRequest>&);
406 
407 // explicit instantiation of above function
408 template Status
409 ledgerFromRequest<>(
411  GRPCContext<org::xrpl::rpc::v1::GetLedgerDataRequest>&);
412 
413 // explicit instantiation of above function
414 template Status
415 ledgerFromRequest<>(
417  GRPCContext<org::xrpl::rpc::v1::GetLedgerRequest>&);
418 
419 template <class T>
420 Status
422  T& ledger,
423  org::xrpl::rpc::v1::LedgerSpecifier const& specifier,
424  Context& context)
425 {
426  ledger.reset();
427 
428  using LedgerCase = org::xrpl::rpc::v1::LedgerSpecifier::LedgerCase;
429  LedgerCase ledgerCase = specifier.ledger_case();
430  switch (ledgerCase)
431  {
432  case LedgerCase::kHash: {
433  if (auto hash = uint256::fromVoidChecked(specifier.hash()))
434  {
435  return getLedger(ledger, *hash, context);
436  }
437  return {rpcINVALID_PARAMS, "ledgerHashMalformed"};
438  }
439  case LedgerCase::kSequence:
440  return getLedger(ledger, specifier.sequence(), context);
441  case LedgerCase::kShortcut:
442  [[fallthrough]];
443  case LedgerCase::LEDGER_NOT_SET: {
444  auto const shortcut = specifier.shortcut();
445  // note, unspecified defaults to validated in reporting mode
446  if (shortcut ==
447  org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED ||
448  (shortcut ==
449  org::xrpl::rpc::v1::LedgerSpecifier::
450  SHORTCUT_UNSPECIFIED &&
451  context.app.config().reporting()))
452  {
453  return getLedger(ledger, LedgerShortcut::VALIDATED, context);
454  }
455  else
456  {
457  if (shortcut ==
458  org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CURRENT ||
459  shortcut ==
460  org::xrpl::rpc::v1::LedgerSpecifier::
461  SHORTCUT_UNSPECIFIED)
462  {
463  return getLedger(ledger, LedgerShortcut::CURRENT, context);
464  }
465  else if (
466  shortcut ==
467  org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CLOSED)
468  {
469  return getLedger(ledger, LedgerShortcut::CLOSED, context);
470  }
471  }
472  }
473  }
474 
475  return Status::OK;
476 }
477 
478 template <class T>
479 Status
480 getLedger(T& ledger, uint256 const& ledgerHash, Context& context)
481 {
482  ledger = context.ledgerMaster.getLedgerByHash(ledgerHash);
483  if (ledger == nullptr)
484  return {rpcLGR_NOT_FOUND, "ledgerNotFound"};
485  return Status::OK;
486 }
487 
488 template <class T>
489 Status
490 getLedger(T& ledger, uint32_t ledgerIndex, Context& context)
491 {
492  ledger = context.ledgerMaster.getLedgerBySeq(ledgerIndex);
493  if (ledger == nullptr)
494  {
495  if (context.app.config().reporting())
496  return {rpcLGR_NOT_FOUND, "ledgerNotFound"};
497  auto cur = context.ledgerMaster.getCurrentLedger();
498  if (cur->info().seq == ledgerIndex)
499  {
500  ledger = cur;
501  }
502  }
503 
504  if (ledger == nullptr)
505  return {rpcLGR_NOT_FOUND, "ledgerNotFound"};
506 
507  if (ledger->info().seq > context.ledgerMaster.getValidLedgerIndex() &&
508  isValidatedOld(context.ledgerMaster, context.app.config().standalone()))
509  {
510  ledger.reset();
511  if (context.apiVersion == 1)
512  return {rpcNO_NETWORK, "InsufficientNetworkMode"};
513  return {rpcNOT_SYNCED, "notSynced"};
514  }
515 
516  return Status::OK;
517 }
518 
519 template <class T>
520 Status
521 getLedger(T& ledger, LedgerShortcut shortcut, Context& context)
522 {
523  if (isValidatedOld(
524  context.ledgerMaster,
525  context.app.config().standalone() ||
526  context.app.config().reporting()))
527  {
528  if (context.apiVersion == 1)
529  return {rpcNO_NETWORK, "InsufficientNetworkMode"};
530  return {rpcNOT_SYNCED, "notSynced"};
531  }
532 
533  if (shortcut == LedgerShortcut::VALIDATED)
534  {
535  ledger = context.ledgerMaster.getValidatedLedger();
536  if (ledger == nullptr)
537  {
538  if (context.apiVersion == 1)
539  return {rpcNO_NETWORK, "InsufficientNetworkMode"};
540  return {rpcNOT_SYNCED, "notSynced"};
541  }
542 
543  assert(!ledger->open());
544  }
545  else
546  {
547  if (shortcut == LedgerShortcut::CURRENT)
548  {
549  if (context.app.config().reporting())
550  return {
552  "Reporting does not track current ledger"};
553  ledger = context.ledgerMaster.getCurrentLedger();
554  assert(ledger->open());
555  }
556  else if (shortcut == LedgerShortcut::CLOSED)
557  {
558  if (context.app.config().reporting())
559  return {
560  rpcLGR_NOT_FOUND, "Reporting does not track closed ledger"};
561  ledger = context.ledgerMaster.getClosedLedger();
562  assert(!ledger->open());
563  }
564  else
565  {
566  return {rpcINVALID_PARAMS, "ledgerIndexMalformed"};
567  }
568 
569  if (ledger == nullptr)
570  {
571  if (context.apiVersion == 1)
572  return {rpcNO_NETWORK, "InsufficientNetworkMode"};
573  return {rpcNOT_SYNCED, "notSynced"};
574  }
575 
576  static auto const minSequenceGap = 10;
577 
578  if (ledger->info().seq + minSequenceGap <
580  {
581  ledger.reset();
582  if (context.apiVersion == 1)
583  return {rpcNO_NETWORK, "InsufficientNetworkMode"};
584  return {rpcNOT_SYNCED, "notSynced"};
585  }
586  }
587  return Status::OK;
588 }
589 
590 // Explicit instantiaion of above three functions
591 template Status
592 getLedger<>(std::shared_ptr<ReadView const>&, uint32_t, Context&);
593 
594 template Status
595 getLedger<>(
597  LedgerShortcut shortcut,
598  Context&);
599 
600 template Status
601 getLedger<>(std::shared_ptr<ReadView const>&, uint256 const&, Context&);
602 
603 // The previous version of the lookupLedger command would accept the
604 // "ledger_index" argument as a string and silently treat it as a request to
605 // return the current ledger which, while not strictly wrong, could cause a lot
606 // of confusion.
607 //
608 // The code now robustly validates the input and ensures that the only possible
609 // values for the "ledger_index" parameter are the index of a ledger passed as
610 // an integer or one of the strings "current", "closed" or "validated".
611 // Additionally, the code ensures that the value passed in "ledger_hash" is a
612 // string and a valid hash. Invalid values will return an appropriate error
613 // code.
614 //
615 // In the absence of the "ledger_hash" or "ledger_index" parameters, the code
616 // assumes that "ledger_index" has the value "current".
617 //
618 // Returns a Json::objectValue. If there was an error, it will be in that
619 // return value. Otherwise, the object contains the field "validated" and
620 // optionally the fields "ledger_hash", "ledger_index" and
621 // "ledger_current_index", if they are defined.
622 Status
625  JsonContext& context,
626  Json::Value& result)
627 {
628  if (auto status = ledgerFromRequest(ledger, context))
629  return status;
630 
631  auto& info = ledger->info();
632 
633  if (!ledger->open())
634  {
635  result[jss::ledger_hash] = to_string(info.hash);
636  result[jss::ledger_index] = info.seq;
637  }
638  else
639  {
640  result[jss::ledger_current_index] = info.seq;
641  }
642 
643  result[jss::validated] = context.ledgerMaster.isValidated(*ledger);
644  return Status::OK;
645 }
646 
649 {
650  Json::Value result;
651  if (auto status = lookupLedger(ledger, context, result))
652  status.inject(result);
653 
654  return result;
655 }
656 
659 {
660  hash_set<AccountID> result;
661  for (auto const& jv : jvArray)
662  {
663  if (!jv.isString())
664  return hash_set<AccountID>();
665  auto const id = parseBase58<AccountID>(jv.asString());
666  if (!id)
667  return hash_set<AccountID>();
668  result.insert(*id);
669  }
670  return result;
671 }
672 
673 void
674 injectSLE(Json::Value& jv, SLE const& sle)
675 {
676  jv = sle.getJson(JsonOptions::none);
677  if (sle.getType() == ltACCOUNT_ROOT)
678  {
679  if (sle.isFieldPresent(sfEmailHash))
680  {
681  auto const& hash = sle.getFieldH128(sfEmailHash);
682  Blob const b(hash.begin(), hash.end());
683  std::string md5 = strHex(makeSlice(b));
684  boost::to_lower(md5);
685  // VFALCO TODO Give a name and move this constant
686  // to a more visible location. Also
687  // shouldn't this be https?
688  jv[jss::urlgravatar] =
689  str(boost::format("http://www.gravatar.com/avatar/%s") % md5);
690  }
691  }
692  else
693  {
694  jv[jss::Invalid] = true;
695  }
696 }
697 
700  unsigned int& limit,
701  Tuning::LimitRange const& range,
702  JsonContext const& context)
703 {
704  limit = range.rdefault;
705  if (auto const& jvLimit = context.params[jss::limit])
706  {
707  if (!(jvLimit.isUInt() || (jvLimit.isInt() && jvLimit.asInt() >= 0)))
708  return RPC::expected_field_error(jss::limit, "unsigned integer");
709 
710  limit = jvLimit.asUInt();
711  if (!isUnlimited(context.role))
712  limit = std::max(range.rmin, std::min(range.rmax, limit));
713  }
714  return std::nullopt;
715 }
716 
719 {
720  // ripple-lib encodes seed used to generate an Ed25519 wallet in a
721  // non-standard way. While rippled never encode seeds that way, we
722  // try to detect such keys to avoid user confusion.
723  if (!value.isString())
724  return std::nullopt;
725 
726  auto const result = decodeBase58Token(value.asString(), TokenType::None);
727 
728  if (result.size() == 18 &&
729  static_cast<std::uint8_t>(result[0]) == std::uint8_t(0xE1) &&
730  static_cast<std::uint8_t>(result[1]) == std::uint8_t(0x4B))
731  return Seed(makeSlice(result.substr(2)));
732 
733  return std::nullopt;
734 }
735 
737 getSeedFromRPC(Json::Value const& params, Json::Value& error)
738 {
739  using string_to_seed_t =
741  using seed_match_t = std::pair<char const*, string_to_seed_t>;
742 
743  static seed_match_t const seedTypes[]{
744  {jss::passphrase.c_str(),
745  [](std::string const& s) { return parseGenericSeed(s); }},
746  {jss::seed.c_str(),
747  [](std::string const& s) { return parseBase58<Seed>(s); }},
748  {jss::seed_hex.c_str(), [](std::string const& s) {
749  uint128 i;
750  if (i.parseHex(s))
751  return std::optional<Seed>(Slice(i.data(), i.size()));
752  return std::optional<Seed>{};
753  }}};
754 
755  // Identify which seed type is in use.
756  seed_match_t const* seedType = nullptr;
757  int count = 0;
758  for (auto const& t : seedTypes)
759  {
760  if (params.isMember(t.first))
761  {
762  ++count;
763  seedType = &t;
764  }
765  }
766 
767  if (count != 1)
768  {
769  error = RPC::make_param_error(
770  "Exactly one of the following must be specified: " +
771  std::string(jss::passphrase) + ", " + std::string(jss::seed) +
772  " or " + std::string(jss::seed_hex));
773  return std::nullopt;
774  }
775 
776  // Make sure a string is present
777  auto const& param = params[seedType->first];
778  if (!param.isString())
779  {
780  error = RPC::expected_field_error(seedType->first, "string");
781  return std::nullopt;
782  }
783 
784  auto const fieldContents = param.asString();
785 
786  // Convert string to seed.
787  std::optional<Seed> seed = seedType->second(fieldContents);
788 
789  if (!seed)
790  error = rpcError(rpcBAD_SEED);
791 
792  return seed;
793 }
794 
797  Json::Value const& params,
798  Json::Value& error,
799  unsigned int apiVersion)
800 {
801  bool const has_key_type = params.isMember(jss::key_type);
802 
803  // All of the secret types we allow, but only one at a time.
804  static char const* const secretTypes[]{
805  jss::passphrase.c_str(),
806  jss::secret.c_str(),
807  jss::seed.c_str(),
808  jss::seed_hex.c_str()};
809 
810  // Identify which secret type is in use.
811  char const* secretType = nullptr;
812  int count = 0;
813  for (auto t : secretTypes)
814  {
815  if (params.isMember(t))
816  {
817  ++count;
818  secretType = t;
819  }
820  }
821 
822  if (count == 0 || secretType == nullptr)
823  {
824  error = RPC::missing_field_error(jss::secret);
825  return {};
826  }
827 
828  if (count > 1)
829  {
830  error = RPC::make_param_error(
831  "Exactly one of the following must be specified: " +
832  std::string(jss::passphrase) + ", " + std::string(jss::secret) +
833  ", " + std::string(jss::seed) + " or " +
834  std::string(jss::seed_hex));
835  return {};
836  }
837 
838  std::optional<KeyType> keyType;
839  std::optional<Seed> seed;
840 
841  if (has_key_type)
842  {
843  if (!params[jss::key_type].isString())
844  {
845  error = RPC::expected_field_error(jss::key_type, "string");
846  return {};
847  }
848 
849  keyType = keyTypeFromString(params[jss::key_type].asString());
850 
851  if (!keyType)
852  {
853  if (apiVersion > 1u)
855  else
856  error = RPC::invalid_field_error(jss::key_type);
857  return {};
858  }
859 
860  // using strcmp as pointers may not match (see
861  // https://developercommunity.visualstudio.com/t/assigning-constexpr-char--to-static-cha/10021357?entry=problem)
862  if (strcmp(secretType, jss::secret.c_str()) == 0)
863  {
864  error = RPC::make_param_error(
865  "The secret field is not allowed if " +
866  std::string(jss::key_type) + " is used.");
867  return {};
868  }
869  }
870 
871  // ripple-lib encodes seed used to generate an Ed25519 wallet in a
872  // non-standard way. While we never encode seeds that way, we try
873  // to detect such keys to avoid user confusion.
874  // using strcmp as pointers may not match (see
875  // https://developercommunity.visualstudio.com/t/assigning-constexpr-char--to-static-cha/10021357?entry=problem)
876  if (strcmp(secretType, jss::seed_hex.c_str()) != 0)
877  {
878  seed = RPC::parseRippleLibSeed(params[secretType]);
879 
880  if (seed)
881  {
882  // If the user passed in an Ed25519 seed but *explicitly*
883  // requested another key type, return an error.
885  {
886  error = RPC::make_error(
887  rpcBAD_SEED, "Specified seed is for an Ed25519 wallet.");
888  return {};
889  }
890 
891  keyType = KeyType::ed25519;
892  }
893  }
894 
895  if (!keyType)
896  keyType = KeyType::secp256k1;
897 
898  if (!seed)
899  {
900  if (has_key_type)
901  seed = getSeedFromRPC(params, error);
902  else
903  {
904  if (!params[jss::secret].isString())
905  {
906  error = RPC::expected_field_error(jss::secret, "string");
907  return {};
908  }
909 
910  seed = parseGenericSeed(params[jss::secret].asString());
911  }
912  }
913 
914  if (!seed)
915  {
916  if (!contains_error(error))
917  {
918  error = RPC::make_error(
920  }
921 
922  return {};
923  }
924 
925  if (keyType != KeyType::secp256k1 && keyType != KeyType::ed25519)
926  LogicError("keypairForSignature: invalid key type");
927 
928  return generateKeyPair(*keyType, *seed);
929 }
930 
933 {
935  if (params.isMember(jss::type))
936  {
938  types{
939  {{jss::account, ltACCOUNT_ROOT},
940  {jss::amendments, ltAMENDMENTS},
941  {jss::check, ltCHECK},
942  {jss::deposit_preauth, ltDEPOSIT_PREAUTH},
943  {jss::directory, ltDIR_NODE},
944  {jss::escrow, ltESCROW},
945  {jss::fee, ltFEE_SETTINGS},
946  {jss::hashes, ltLEDGER_HASHES},
947  {jss::offer, ltOFFER},
948  {jss::payment_channel, ltPAYCHAN},
949  {jss::signer_list, ltSIGNER_LIST},
950  {jss::state, ltRIPPLE_STATE},
951  {jss::ticket, ltTICKET},
952  {jss::nft_offer, ltNFTOKEN_OFFER},
953  {jss::nft_page, ltNFTOKEN_PAGE},
954  {jss::amm, ltAMM},
955  {jss::bridge, ltBRIDGE},
956  {jss::xchain_owned_claim_id, ltXCHAIN_OWNED_CLAIM_ID},
957  {jss::xchain_owned_create_account_claim_id,
959  {jss::did, ltDID},
960  {jss::oracle, ltORACLE}}};
961 
962  auto const& p = params[jss::type];
963  if (!p.isString())
964  {
965  result.first = RPC::Status{
966  rpcINVALID_PARAMS, "Invalid field 'type', not string."};
967  assert(result.first.type() == RPC::Status::Type::error_code_i);
968  return result;
969  }
970 
971  auto const filter = p.asString();
972  auto iter = std::find_if(
973  types.begin(), types.end(), [&filter](decltype(types.front())& t) {
974  return t.first == filter;
975  });
976  if (iter == types.end())
977  {
978  result.first =
979  RPC::Status{rpcINVALID_PARAMS, "Invalid field 'type'."};
980  assert(result.first.type() == RPC::Status::Type::error_code_i);
981  return result;
982  }
983  result.second = iter->second;
984  }
985  return result;
986 }
987 
988 beast::SemanticVersion const firstVersion("1.0.0");
989 beast::SemanticVersion const goodVersion("1.0.0");
990 beast::SemanticVersion const lastVersion("1.0.0");
991 
992 unsigned int
993 getAPIVersionNumber(Json::Value const& jv, bool betaEnabled)
994 {
995  static Json::Value const minVersion(RPC::apiMinimumSupportedVersion);
996  static Json::Value const invalidVersion(RPC::apiInvalidVersion);
997 
998  Json::Value const maxVersion(
1000  Json::Value requestedVersion(RPC::apiVersionIfUnspecified);
1001  if (jv.isObject())
1002  {
1003  requestedVersion = jv.get(jss::api_version, requestedVersion);
1004  }
1005  if (!(requestedVersion.isInt() || requestedVersion.isUInt()) ||
1006  requestedVersion < minVersion || requestedVersion > maxVersion)
1007  {
1008  requestedVersion = invalidVersion;
1009  }
1010  return requestedVersion.asUInt();
1011 }
1012 
1015 {
1016  if (context.app.config().reporting())
1018 
1019  auto const hasHash = context.params.isMember(jss::ledger_hash);
1020  auto const hasIndex = context.params.isMember(jss::ledger_index);
1021  std::uint32_t ledgerIndex = 0;
1022 
1023  auto& ledgerMaster = context.app.getLedgerMaster();
1024  LedgerHash ledgerHash;
1025 
1026  if ((hasHash && hasIndex) || !(hasHash || hasIndex))
1027  {
1028  return RPC::make_param_error(
1029  "Exactly one of ledger_hash and ledger_index can be set.");
1030  }
1031 
1033 
1034  if (hasHash)
1035  {
1036  auto const& jsonHash = context.params[jss::ledger_hash];
1037  if (!jsonHash.isString() || !ledgerHash.parseHex(jsonHash.asString()))
1038  return RPC::invalid_field_error(jss::ledger_hash);
1039  }
1040  else
1041  {
1042  auto const& jsonIndex = context.params[jss::ledger_index];
1043  if (!jsonIndex.isInt())
1044  return RPC::invalid_field_error(jss::ledger_index);
1045 
1046  // We need a validated ledger to get the hash from the sequence
1047  if (ledgerMaster.getValidatedLedgerAge() >
1049  {
1050  if (context.apiVersion == 1)
1051  return rpcError(rpcNO_CURRENT);
1052  return rpcError(rpcNOT_SYNCED);
1053  }
1054 
1055  ledgerIndex = jsonIndex.asInt();
1056  auto ledger = ledgerMaster.getValidatedLedger();
1057 
1058  if (ledgerIndex >= ledger->info().seq)
1059  return RPC::make_param_error("Ledger index too large");
1060  if (ledgerIndex <= 0)
1061  return RPC::make_param_error("Ledger index too small");
1062 
1063  auto const j = context.app.journal("RPCHandler");
1064  // Try to get the hash of the desired ledger from the validated
1065  // ledger
1066  auto neededHash = hashOfSeq(*ledger, ledgerIndex, j);
1067  if (!neededHash)
1068  {
1069  // Find a ledger more likely to have the hash of the desired
1070  // ledger
1071  auto const refIndex = getCandidateLedger(ledgerIndex);
1072  auto refHash = hashOfSeq(*ledger, refIndex, j);
1073  assert(refHash);
1074 
1075  ledger = ledgerMaster.getLedgerByHash(*refHash);
1076  if (!ledger)
1077  {
1078  // We don't have the ledger we need to figure out which
1079  // ledger they want. Try to get it.
1080 
1081  if (auto il = context.app.getInboundLedgers().acquire(
1082  *refHash, refIndex, InboundLedger::Reason::GENERIC))
1083  {
1084  Json::Value jvResult = RPC::make_error(
1086  "acquiring ledger containing requested index");
1087  jvResult[jss::acquiring] =
1088  getJson(LedgerFill(*il, &context));
1089  return jvResult;
1090  }
1091 
1092  if (auto il = context.app.getInboundLedgers().find(*refHash))
1093  {
1094  Json::Value jvResult = RPC::make_error(
1096  "acquiring ledger containing requested index");
1097  jvResult[jss::acquiring] = il->getJson(0);
1098  return jvResult;
1099  }
1100 
1101  // Likely the app is shutting down
1102  return Json::Value();
1103  }
1104 
1105  neededHash = hashOfSeq(*ledger, ledgerIndex, j);
1106  }
1107  assert(neededHash);
1108  ledgerHash = neededHash ? *neededHash : beast::zero; // kludge
1109  }
1110 
1111  // Try to get the desired ledger
1112  // Verify all nodes even if we think we have it
1113  auto ledger = context.app.getInboundLedgers().acquire(
1114  ledgerHash, ledgerIndex, InboundLedger::Reason::GENERIC);
1115 
1116  // In standalone mode, accept the ledger from the ledger cache
1117  if (!ledger && context.app.config().standalone())
1118  ledger = ledgerMaster.getLedgerByHash(ledgerHash);
1119 
1120  if (ledger)
1121  return ledger;
1122 
1123  if (auto il = context.app.getInboundLedgers().find(ledgerHash))
1124  return il->getJson(0);
1125 
1126  return RPC::make_error(
1127  rpcNOT_READY, "findCreate failed to return an inbound ledger");
1128 }
1129 } // namespace RPC
1130 } // namespace ripple
Json::Value::isInt
bool isInt() const
Definition: json_value.cpp:979
ripple::RPC::apiInvalidVersion
constexpr unsigned int apiInvalidVersion
API version numbers used in later API versions.
Definition: RPCHelpers.h:232
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:313
ripple::RPC::apiVersionIfUnspecified
constexpr unsigned int apiVersionIfUnspecified
Definition: RPCHelpers.h:233
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
regex
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:206
Json::Value::isObject
bool isObject() const
Definition: json_value.cpp:1027
ripple::RPC::goodVersion
const beast::SemanticVersion goodVersion("1.0.0")
Definition: RPCHelpers.h:207
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:212
ripple::ltORACLE
@ ltORACLE
A ledger object which tracks Oracle.
Definition: LedgerFormats.h:198
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:109
ripple::Slice
An immutable linear range of bytes.
Definition: Slice.h:44
std::unordered_set
STL class.
ripple::RPC::keypairForSignature
std::optional< std::pair< PublicKey, SecretKey > > keypairForSignature(Json::Value const &params, Json::Value &error, unsigned int apiVersion)
Definition: RPCHelpers.cpp:796
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:674
std::pair
ripple::RPC::LedgerShortcut
LedgerShortcut
Definition: RPCHelpers.h:129
ripple::sfOwner
const SF_ACCOUNT sfOwner
ripple::LedgerMaster
Definition: LedgerMaster.h:70
ripple::RPC::getAccountObjects
bool getAccountObjects(ReadView const &ledger, AccountID const &account, std::optional< std::vector< LedgerEntryType >> const &typeFilter, uint256 dirIndex, uint256 entryIndex, std::uint32_t const limit, Json::Value &jvResult)
Gathers all objects for an account in a ledger.
Definition: RPCHelpers.cpp:152
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:993
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)
Definition: tokens.cpp:205
ripple::keylet::child
Keylet child(uint256 const &key) noexcept
Any item that can be in an owner dir.
Definition: Indexes.cpp:149
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:699
ripple::STObject::getFieldH128
uint128 getFieldH128(SField const &field) const
Definition: STObject.cpp:587
ripple::LedgerMaster::getLedgerByHash
std::shared_ptr< Ledger const > getLedgerByHash(uint256 const &hash)
Definition: LedgerMaster.cpp:1907
beast::SemanticVersion
A Semantic Version number.
Definition: SemanticVersion.h:35
ripple::base_uint::next
base_uint next() const
Definition: base_uint.h:448
std::function
ripple::ltCHECK
@ ltCHECK
A ledger object which describes a check.
Definition: LedgerFormats.h:155
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:137
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:1014
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:237
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:623
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:334
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::nft::pageMask
constexpr uint256 pageMask(std::string_view("0000000000000000000000000000000000000000ffffffffffffffffffffffff"))
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:268
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:117
ripple::sfLowLimit
const SF_AMOUNT sfLowLimit
ripple::keylet::nftpage_min
Keylet nftpage_min(AccountID const &owner)
NFT page keylets.
Definition: Indexes.cpp:342
ripple::RPC::parseRippleLibSeed
std::optional< Seed > parseRippleLibSeed(Json::Value const &value)
Definition: RPCHelpers.cpp:718
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:350
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:197
ripple::RPC::accountFromStringWithCode
error_code_i accountFromStringWithCode(AccountID &result, std::string const &strIdent, bool bStrict)
Decode account ID from string.
Definition: RPCHelpers.cpp:59
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:143
ripple::ltDID
@ ltDID
The ledger object which tracks the DID.
Definition: LedgerFormats.h:193
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:181
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:319
ripple::Config::standalone
bool standalone() const
Definition: Config.h:345
ripple::RPC::GRPCContext
Definition: Context.h:70
ripple::calcAccountID
AccountID calcAccountID(PublicKey const &pk)
Definition: AccountID.cpp:158
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:161
ripple::RPC::Context::app
Application & app
Definition: Context.h:42
ripple::keylet::nftpage_max
Keylet nftpage_max(AccountID const &owner)
A keylet for the owner's last possible NFT page.
Definition: Indexes.cpp:350
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:661
ripple::LedgerMaster::getLedgerBySeq
std::shared_ptr< Ledger const > getLedgerBySeq(std::uint32_t index)
Definition: LedgerMaster.cpp:1871
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::ReadView::succ
virtual std::optional< key_type > succ(key_type const &key, std::optional< key_type > const &last=std::nullopt) const =0
Return the key of the next state item.
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:54
ripple::STLedgerEntry::getType
LedgerEntryType getType() const
Definition: STLedgerEntry.h:119
ripple::LedgerMaster::getCurrentLedger
std::shared_ptr< ReadView const > getCurrentLedger()
Definition: LedgerMaster.cpp:1707
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:357
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:298
ripple::RPC::GRPCContext::params
RequestType params
Definition: Context.h:72
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:54
ripple::ltNFTOKEN_PAGE
@ ltNFTOKEN_PAGE
A ledger object which contains a list of NFTs.
Definition: LedgerFormats.h:175
ripple::RPC::apiMinimumSupportedVersion
constexpr unsigned int apiMinimumSupportedVersion
Definition: RPCHelpers.h:234
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::JsonOptions::none
@ none
Definition: STBase.h:42
ripple::ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID
@ ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID
A claim id for a cross chain create account transaction.
Definition: LedgerFormats.h:129
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:480
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
ripple::ltBRIDGE
@ ltBRIDGE
The ledger object which lists details about sidechains.
Definition: LedgerFormats.h:99
ripple::LedgerMaster::isValidated
bool isValidated(ReadView const &ledger)
Definition: LedgerMaster.cpp:602
beast::lexicalCastChecked
bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
Definition: LexicalCast.h:164
ripple::RPC::chooseLedgerEntryType
std::pair< RPC::Status, LedgerEntryType > chooseLedgerEntryType(Json::Value const &params)
Definition: RPCHelpers.cpp:932
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:47
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:444
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:97
Json::Value::asUInt
UInt asUInt() const
Definition: json_value.cpp:545
Json::Value::isUInt
bool isUInt() const
Definition: json_value.cpp:985
ripple::RPC::getSeedFromRPC
std::optional< Seed > getSeedFromRPC(Json::Value const &params, Json::Value &error)
Definition: RPCHelpers.cpp:737
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:235
ripple::LedgerMaster::getValidatedLedger
std::shared_ptr< Ledger const > getValidatedLedger()
Definition: LedgerMaster.cpp:1717
ripple::RPC::ledgerFromSpecifier
Status ledgerFromSpecifier(T &ledger, org::xrpl::rpc::v1::LedgerSpecifier const &specifier, Context &context)
Definition: RPCHelpers.cpp:421
ripple::sfNextPageMin
const SF_UINT256 sfNextPageMin
ripple::ltXCHAIN_OWNED_CLAIM_ID
@ ltXCHAIN_OWNED_CLAIM_ID
A claim id for a cross chain transaction.
Definition: LedgerFormats.h:123
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:38
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:658
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:252
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:278
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:256
ripple::RPC::accountFromStringStrict
std::optional< AccountID > accountFromStringStrict(std::string const &account)
Get an AccountID from an account ID or public key.
Definition: RPCHelpers.cpp:43
ripple::LedgerFill
Definition: LedgerToJson.h:36
ripple::RPC::JsonContext::params
Json::Value params
Definition: Context.h:64
ripple::RPC::lastVersion
const beast::SemanticVersion lastVersion("1.0.0")
Definition: RPCHelpers.h:208
ripple::RPC::invalid_field_error
Json::Value invalid_field_error(std::string const &name)
Definition: ErrorCodes.h:310
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:395
ripple::Resource::feeHighBurdenRPC
const Charge feeHighBurdenRPC
ripple::ltAMM
@ ltAMM
The ledger object which tracks the AMM.
Definition: LedgerFormats.h:187
ripple::RPC::accountFromString
Json::Value accountFromString(AccountID &result, std::string const &strIdent, bool bStrict)
Definition: RPCHelpers.cpp:87
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:181
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:114
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:149
ripple::InboundLedgers::find
virtual std::shared_ptr< InboundLedger > find(LedgerHash const &hash)=0
std::variant
ripple::rpcBAD_KEY_TYPE
@ rpcBAD_KEY_TYPE
Definition: ErrorCodes.h:133
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