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 
961  auto const& p = params[jss::type];
962  if (!p.isString())
963  {
964  result.first = RPC::Status{
965  rpcINVALID_PARAMS, "Invalid field 'type', not string."};
966  assert(result.first.type() == RPC::Status::Type::error_code_i);
967  return result;
968  }
969 
970  auto const filter = p.asString();
971  auto iter = std::find_if(
972  types.begin(), types.end(), [&filter](decltype(types.front())& t) {
973  return t.first == filter;
974  });
975  if (iter == types.end())
976  {
977  result.first =
978  RPC::Status{rpcINVALID_PARAMS, "Invalid field 'type'."};
979  assert(result.first.type() == RPC::Status::Type::error_code_i);
980  return result;
981  }
982  result.second = iter->second;
983  }
984  return result;
985 }
986 
987 beast::SemanticVersion const firstVersion("1.0.0");
988 beast::SemanticVersion const goodVersion("1.0.0");
989 beast::SemanticVersion const lastVersion("1.0.0");
990 
991 unsigned int
992 getAPIVersionNumber(Json::Value const& jv, bool betaEnabled)
993 {
994  static Json::Value const minVersion(RPC::apiMinimumSupportedVersion);
995  static Json::Value const invalidVersion(RPC::apiInvalidVersion);
996 
997  Json::Value const maxVersion(
999  Json::Value requestedVersion(RPC::apiVersionIfUnspecified);
1000  if (jv.isObject())
1001  {
1002  requestedVersion = jv.get(jss::api_version, requestedVersion);
1003  }
1004  if (!(requestedVersion.isInt() || requestedVersion.isUInt()) ||
1005  requestedVersion < minVersion || requestedVersion > maxVersion)
1006  {
1007  requestedVersion = invalidVersion;
1008  }
1009  return requestedVersion.asUInt();
1010 }
1011 
1014 {
1015  if (context.app.config().reporting())
1017 
1018  auto const hasHash = context.params.isMember(jss::ledger_hash);
1019  auto const hasIndex = context.params.isMember(jss::ledger_index);
1020  std::uint32_t ledgerIndex = 0;
1021 
1022  auto& ledgerMaster = context.app.getLedgerMaster();
1023  LedgerHash ledgerHash;
1024 
1025  if ((hasHash && hasIndex) || !(hasHash || hasIndex))
1026  {
1027  return RPC::make_param_error(
1028  "Exactly one of ledger_hash and ledger_index can be set.");
1029  }
1030 
1032 
1033  if (hasHash)
1034  {
1035  auto const& jsonHash = context.params[jss::ledger_hash];
1036  if (!jsonHash.isString() || !ledgerHash.parseHex(jsonHash.asString()))
1037  return RPC::invalid_field_error(jss::ledger_hash);
1038  }
1039  else
1040  {
1041  auto const& jsonIndex = context.params[jss::ledger_index];
1042  if (!jsonIndex.isInt())
1043  return RPC::invalid_field_error(jss::ledger_index);
1044 
1045  // We need a validated ledger to get the hash from the sequence
1046  if (ledgerMaster.getValidatedLedgerAge() >
1048  {
1049  if (context.apiVersion == 1)
1050  return rpcError(rpcNO_CURRENT);
1051  return rpcError(rpcNOT_SYNCED);
1052  }
1053 
1054  ledgerIndex = jsonIndex.asInt();
1055  auto ledger = ledgerMaster.getValidatedLedger();
1056 
1057  if (ledgerIndex >= ledger->info().seq)
1058  return RPC::make_param_error("Ledger index too large");
1059  if (ledgerIndex <= 0)
1060  return RPC::make_param_error("Ledger index too small");
1061 
1062  auto const j = context.app.journal("RPCHandler");
1063  // Try to get the hash of the desired ledger from the validated
1064  // ledger
1065  auto neededHash = hashOfSeq(*ledger, ledgerIndex, j);
1066  if (!neededHash)
1067  {
1068  // Find a ledger more likely to have the hash of the desired
1069  // ledger
1070  auto const refIndex = getCandidateLedger(ledgerIndex);
1071  auto refHash = hashOfSeq(*ledger, refIndex, j);
1072  assert(refHash);
1073 
1074  ledger = ledgerMaster.getLedgerByHash(*refHash);
1075  if (!ledger)
1076  {
1077  // We don't have the ledger we need to figure out which
1078  // ledger they want. Try to get it.
1079 
1080  if (auto il = context.app.getInboundLedgers().acquire(
1081  *refHash, refIndex, InboundLedger::Reason::GENERIC))
1082  {
1083  Json::Value jvResult = RPC::make_error(
1085  "acquiring ledger containing requested index");
1086  jvResult[jss::acquiring] =
1087  getJson(LedgerFill(*il, &context));
1088  return jvResult;
1089  }
1090 
1091  if (auto il = context.app.getInboundLedgers().find(*refHash))
1092  {
1093  Json::Value jvResult = RPC::make_error(
1095  "acquiring ledger containing requested index");
1096  jvResult[jss::acquiring] = il->getJson(0);
1097  return jvResult;
1098  }
1099 
1100  // Likely the app is shutting down
1101  return Json::Value();
1102  }
1103 
1104  neededHash = hashOfSeq(*ledger, ledgerIndex, j);
1105  }
1106  assert(neededHash);
1107  ledgerHash = neededHash ? *neededHash : beast::zero; // kludge
1108  }
1109 
1110  // Try to get the desired ledger
1111  // Verify all nodes even if we think we have it
1112  auto ledger = context.app.getInboundLedgers().acquire(
1113  ledgerHash, ledgerIndex, InboundLedger::Reason::GENERIC);
1114 
1115  // In standalone mode, accept the ledger from the ledger cache
1116  if (!ledger && context.app.config().standalone())
1117  ledger = ledgerMaster.getLedgerByHash(ledgerHash);
1118 
1119  if (ledger)
1120  return ledger;
1121 
1122  if (auto il = context.app.getInboundLedgers().find(ledgerHash))
1123  return il->getJson(0);
1124 
1125  return RPC::make_error(
1126  rpcNOT_READY, "findCreate failed to return an inbound ledger");
1127 }
1128 
1131 {
1132  using enum RPC::SubmitSync;
1133  if (params.isMember(jss::sync_mode))
1134  {
1135  std::string const syncMode = params[jss::sync_mode].asString();
1136  if (syncMode == "async")
1137  return async;
1138  else if (syncMode == "wait")
1139  return wait;
1140  else if (syncMode != "sync")
1141  return Unexpected(RPC::make_error(
1143  "sync_mode parameter must be one of \"sync\", \"async\", or "
1144  "\"wait\"."));
1145  }
1146  return sync;
1147 }
1148 
1149 } // namespace RPC
1150 } // 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:234
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:312
ripple::RPC::apiVersionIfUnspecified
constexpr unsigned int apiVersionIfUnspecified
Definition: RPCHelpers.h:235
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::RPC::SubmitSync
SubmitSync
Possible values for defining synchronous behavior of the transaction submission API.
Definition: SubmitSync.h:36
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:208
Json::Value::isObject
bool isObject() const
Definition: json_value.cpp:1027
ripple::RPC::goodVersion
const beast::SemanticVersion goodVersion("1.0.0")
Definition: RPCHelpers.h:209
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:207
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.
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:131
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:992
std::vector
STL class.
std::find
T find(T... args)
std::optional::value_or
T value_or(T... args)
ripple::Unexpected
Unexpected(E(&)[N]) -> Unexpected< E const * >
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
ripple::keylet::child
Keylet child(uint256 const &key) noexcept
Any item that can be in an owner dir.
Definition: Indexes.cpp:148
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:571
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:1013
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:239
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:330
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:264
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::RPC::keypairForSignature
std::pair< PublicKey, SecretKey > keypairForSignature(Json::Value const &params, Json::Value &error, unsigned int apiVersion)
Definition: RPCHelpers.cpp:796
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:341
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:351
ripple::Expected
Definition: Expected.h:132
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:196
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:318
ripple::Config::standalone
bool standalone() const
Definition: Config.h:346
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:349
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::RPC::SubmitSync::sync
@ sync
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:45
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:294
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:236
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:607
ripple::RPC::SubmitSync::wait
@ wait
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: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: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::getSubmitSyncMode
ripple::Expected< RPC::SubmitSync, Json::Value > getSubmitSyncMode(Json::Value const &params)
Helper to parse submit_mode parameter to RPC submit.
Definition: RPCHelpers.cpp:1130
ripple::RPC::apiMaximumSupportedVersion
constexpr unsigned int apiMaximumSupportedVersion
Definition: RPCHelpers.h:237
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: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: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:277
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:252
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:210
ripple::RPC::invalid_field_error
Json::Value invalid_field_error(std::string const &name)
Definition: ErrorCodes.h:306
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:180
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