rippled
PathRequest.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/app/main/Application.h>
21 #include <ripple/app/misc/LoadFeeTrack.h>
22 #include <ripple/app/misc/NetworkOPs.h>
23 #include <ripple/app/paths/AccountCurrencies.h>
24 #include <ripple/app/paths/PathRequest.h>
25 #include <ripple/app/paths/PathRequests.h>
26 #include <ripple/app/paths/RippleCalc.h>
27 #include <ripple/app/paths/impl/PathfinderUtils.h>
28 #include <ripple/basics/Log.h>
29 #include <ripple/beast/core/LexicalCast.h>
30 #include <ripple/core/Config.h>
31 #include <ripple/net/RPCErr.h>
32 #include <ripple/protocol/ErrorCodes.h>
33 #include <ripple/protocol/UintTypes.h>
34 
35 #include <ripple/rpc/impl/Tuning.h>
36 #include <optional>
37 
38 #include <tuple>
39 
40 namespace ripple {
41 
43  Application& app,
44  const std::shared_ptr<InfoSub>& subscriber,
45  int id,
46  PathRequests& owner,
47  beast::Journal journal)
48  : app_(app)
49  , m_journal(journal)
50  , mOwner(owner)
51  , wpSubscriber(subscriber)
52  , consumer_(subscriber->getConsumer())
53  , jvStatus(Json::objectValue)
54  , mLastIndex(0)
55  , mInProgress(false)
56  , iLevel(0)
57  , bLastSuccess(false)
58  , iIdentifier(id)
59  , created_(std::chrono::steady_clock::now())
60 {
61  JLOG(m_journal.debug()) << iIdentifier << " created";
62 }
63 
65  Application& app,
66  std::function<void(void)> const& completion,
67  Resource::Consumer& consumer,
68  int id,
69  PathRequests& owner,
70  beast::Journal journal)
71  : app_(app)
72  , m_journal(journal)
73  , mOwner(owner)
74  , fCompletion(completion)
75  , consumer_(consumer)
76  , jvStatus(Json::objectValue)
77  , mLastIndex(0)
78  , mInProgress(false)
79  , iLevel(0)
80  , bLastSuccess(false)
81  , iIdentifier(id)
82  , created_(std::chrono::steady_clock::now())
83 {
84  JLOG(m_journal.debug()) << iIdentifier << " created";
85 }
86 
88 {
89  using namespace std::chrono;
90  auto stream = m_journal.info();
91  if (!stream)
92  return;
93 
94  std::string fast, full;
95  if (quick_reply_ != steady_clock::time_point{})
96  {
97  fast = " fast:";
98  fast += std::to_string(
99  duration_cast<milliseconds>(quick_reply_ - created_).count());
100  fast += "ms";
101  }
102  if (full_reply_ != steady_clock::time_point{})
103  {
104  full = " full:";
105  full += std::to_string(
106  duration_cast<milliseconds>(full_reply_ - created_).count());
107  full += "ms";
108  }
109  stream
110  << iIdentifier << " complete:" << fast << full << " total:"
111  << duration_cast<milliseconds>(steady_clock::now() - created_).count()
112  << "ms";
113 }
114 
115 bool
117 {
119 
120  // does this path request still need its first full path
121  return mLastIndex == 0;
122 }
123 
124 bool
126 {
128 
129  if (mInProgress)
130  {
131  // Another thread is handling this
132  return false;
133  }
134 
135  if (newOnly && (mLastIndex != 0))
136  {
137  // Only handling new requests, this isn't new
138  return false;
139  }
140 
141  if (mLastIndex >= index)
142  {
143  return false;
144  }
145 
146  mInProgress = true;
147  return true;
148 }
149 
150 bool
152 {
153  return bool(fCompletion);
154 }
155 
156 void
158 {
160 
161  assert(mInProgress);
162  mInProgress = false;
163 
164  if (fCompletion)
165  {
166  fCompletion();
168  }
169 }
170 
171 bool
173 {
174  if (!raSrcAccount || !raDstAccount)
175  return false;
176 
177  if (!convert_all_ && (saSendMax || saDstAmount <= beast::zero))
178  {
179  // If send max specified, dst amt must be -1.
181  return false;
182  }
183 
184  auto const& lrLedger = crCache->getLedger();
185 
186  if (!lrLedger->exists(keylet::account(*raSrcAccount)))
187  {
188  // Source account does not exist.
190  return false;
191  }
192 
193  auto const sleDest = lrLedger->read(keylet::account(*raDstAccount));
194 
195  Json::Value& jvDestCur =
196  (jvStatus[jss::destination_currencies] = Json::arrayValue);
197 
198  if (!sleDest)
199  {
200  jvDestCur.append(Json::Value(systemCurrencyCode()));
201  if (!saDstAmount.native())
202  {
203  // Only XRP can be send to a non-existent account.
205  return false;
206  }
207 
208  if (!convert_all_ &&
209  saDstAmount < STAmount(lrLedger->fees().accountReserve(0)))
210  {
211  // Payment must meet reserve.
213  return false;
214  }
215  }
216  else
217  {
218  bool const disallowXRP(sleDest->getFlags() & lsfDisallowXRP);
219 
220  auto usDestCurrID =
221  accountDestCurrencies(*raDstAccount, crCache, !disallowXRP);
222 
223  for (auto const& currency : usDestCurrID)
224  jvDestCur.append(to_string(currency));
225  jvStatus[jss::destination_tag] =
226  (sleDest->getFlags() & lsfRequireDestTag);
227  }
228 
229  jvStatus[jss::ledger_hash] = to_string(lrLedger->info().hash);
230  jvStatus[jss::ledger_index] = lrLedger->seq();
231  return true;
232 }
233 
234 /* If this is a normal path request, we want to run it once "fast" now
235  to give preliminary results.
236 
237  If this is a legacy path request, we are only going to run it once,
238  and we can't run it in full now, so we don't want to run it at all.
239 
240  If there's an error, we need to be sure to return it to the caller
241  in all cases.
242 */
246  Json::Value const& value)
247 {
248  bool valid = false;
249 
250  if (parseJson(value) != PFR_PJ_INVALID)
251  {
252  valid = isValid(cache);
253  if (!hasCompletion() && valid)
254  doUpdate(cache, true);
255  }
256 
257  if (auto stream = m_journal.debug())
258  {
259  if (valid)
260  {
261  stream << iIdentifier << " valid: " << toBase58(*raSrcAccount);
262  stream << iIdentifier << " deliver: " << saDstAmount.getFullText();
263  }
264  else
265  {
266  stream << iIdentifier << " invalid";
267  }
268  }
269 
270  return {valid, jvStatus};
271 }
272 
273 int
275 {
276  if (!jvParams.isMember(jss::source_account))
277  {
279  return PFR_PJ_INVALID;
280  }
281 
282  if (!jvParams.isMember(jss::destination_account))
283  {
285  return PFR_PJ_INVALID;
286  }
287 
288  if (!jvParams.isMember(jss::destination_amount))
289  {
291  return PFR_PJ_INVALID;
292  }
293 
294  raSrcAccount =
295  parseBase58<AccountID>(jvParams[jss::source_account].asString());
296  if (!raSrcAccount)
297  {
299  return PFR_PJ_INVALID;
300  }
301 
302  raDstAccount =
303  parseBase58<AccountID>(jvParams[jss::destination_account].asString());
304  if (!raDstAccount)
305  {
307  return PFR_PJ_INVALID;
308  }
309 
310  if (!amountFromJsonNoThrow(saDstAmount, jvParams[jss::destination_amount]))
311  {
313  return PFR_PJ_INVALID;
314  }
315 
316  convert_all_ = saDstAmount == STAmount(saDstAmount.issue(), 1u, 0, true);
317 
318  if ((saDstAmount.getCurrency().isZero() &&
321  (!convert_all_ && saDstAmount <= beast::zero))
322  {
324  return PFR_PJ_INVALID;
325  }
326 
327  if (jvParams.isMember(jss::send_max))
328  {
329  // Send_max requires destination amount to be -1.
330  if (!convert_all_)
331  {
333  return PFR_PJ_INVALID;
334  }
335 
336  saSendMax.emplace();
337  if (!amountFromJsonNoThrow(*saSendMax, jvParams[jss::send_max]) ||
338  (saSendMax->getCurrency().isZero() &&
339  saSendMax->getIssuer().isNonZero()) ||
340  (saSendMax->getCurrency() == badCurrency()) ||
341  (*saSendMax <= beast::zero &&
342  *saSendMax != STAmount(saSendMax->issue(), 1u, 0, true)))
343  {
345  return PFR_PJ_INVALID;
346  }
347  }
348 
349  if (jvParams.isMember(jss::source_currencies))
350  {
351  Json::Value const& jvSrcCurrencies = jvParams[jss::source_currencies];
352  if (!jvSrcCurrencies.isArray() || jvSrcCurrencies.size() == 0 ||
353  jvSrcCurrencies.size() > RPC::Tuning::max_src_cur)
354  {
356  return PFR_PJ_INVALID;
357  }
358 
359  sciSourceCurrencies.clear();
360 
361  for (auto const& c : jvSrcCurrencies)
362  {
363  // Mandatory currency
364  Currency srcCurrencyID;
365  if (!c.isObject() || !c.isMember(jss::currency) ||
366  !c[jss::currency].isString() ||
367  !to_currency(srcCurrencyID, c[jss::currency].asString()))
368  {
370  return PFR_PJ_INVALID;
371  }
372 
373  // Optional issuer
374  AccountID srcIssuerID;
375  if (c.isMember(jss::issuer) &&
376  (!c[jss::issuer].isString() ||
377  !to_issuer(srcIssuerID, c[jss::issuer].asString())))
378  {
380  return PFR_PJ_INVALID;
381  }
382 
383  if (srcCurrencyID.isZero())
384  {
385  if (srcIssuerID.isNonZero())
386  {
388  return PFR_PJ_INVALID;
389  }
390  }
391  else if (srcIssuerID.isZero())
392  {
393  srcIssuerID = *raSrcAccount;
394  }
395 
396  if (saSendMax)
397  {
398  // If the currencies don't match, ignore the source currency.
399  if (srcCurrencyID == saSendMax->getCurrency())
400  {
401  // If neither is the source and they are not equal, then the
402  // source issuer is illegal.
403  if (srcIssuerID != *raSrcAccount &&
404  saSendMax->getIssuer() != *raSrcAccount &&
405  srcIssuerID != saSendMax->getIssuer())
406  {
408  return PFR_PJ_INVALID;
409  }
410 
411  // If both are the source, use the source.
412  // Otherwise, use the one that's not the source.
413  if (srcIssuerID != *raSrcAccount)
414  {
415  sciSourceCurrencies.insert(
416  {srcCurrencyID, srcIssuerID});
417  }
418  else if (saSendMax->getIssuer() != *raSrcAccount)
419  {
420  sciSourceCurrencies.insert(
421  {srcCurrencyID, saSendMax->getIssuer()});
422  }
423  else
424  {
425  sciSourceCurrencies.insert(
426  {srcCurrencyID, *raSrcAccount});
427  }
428  }
429  }
430  else
431  {
432  sciSourceCurrencies.insert({srcCurrencyID, srcIssuerID});
433  }
434  }
435  }
436 
437  if (jvParams.isMember(jss::id))
438  jvId = jvParams[jss::id];
439 
440  return PFR_PJ_NOCHANGE;
441 }
442 
445 {
446  JLOG(m_journal.debug()) << iIdentifier << " closed";
448  jvStatus[jss::closed] = true;
449  return jvStatus;
450 }
451 
454 {
456  jvStatus[jss::status] = jss::success;
457  return jvStatus;
458 }
459 
460 void
462 {
463  JLOG(m_journal.info()) << iIdentifier << " aborting early";
464 }
465 
470  Currency const& currency,
471  STAmount const& dst_amount,
472  int const level,
473  std::function<bool(void)> const& continueCallback)
474 {
475  auto i = currency_map.find(currency);
476  if (i != currency_map.end())
477  return i->second;
478  auto pathfinder = std::make_unique<Pathfinder>(
479  cache,
480  *raSrcAccount,
481  *raDstAccount,
482  currency,
483  std::nullopt,
484  dst_amount,
485  saSendMax,
486  app_);
487  if (pathfinder->findPaths(level, continueCallback))
488  pathfinder->computePathRanks(max_paths_, continueCallback);
489  else
490  pathfinder.reset(); // It's a bad request - clear it.
491  return currency_map[currency] = std::move(pathfinder);
492 }
493 
494 bool
497  int const level,
498  Json::Value& jvArray,
499  std::function<bool(void)> const& continueCallback)
500 {
501  auto sourceCurrencies = sciSourceCurrencies;
502  if (sourceCurrencies.empty() && saSendMax)
503  {
504  sourceCurrencies.insert(saSendMax->issue());
505  }
506  if (sourceCurrencies.empty())
507  {
508  auto currencies = accountSourceCurrencies(*raSrcAccount, cache, true);
509  bool const sameAccount = *raSrcAccount == *raDstAccount;
510  for (auto const& c : currencies)
511  {
512  if (!sameAccount || c != saDstAmount.getCurrency())
513  {
514  if (sourceCurrencies.size() >= RPC::Tuning::max_auto_src_cur)
515  return false;
516  sourceCurrencies.insert(
517  {c, c.isZero() ? xrpAccount() : *raSrcAccount});
518  }
519  }
520  }
521 
522  auto const dst_amount = convertAmount(saDstAmount, convert_all_);
524  for (auto const& issue : sourceCurrencies)
525  {
526  if (continueCallback && !continueCallback())
527  break;
528  JLOG(m_journal.debug())
529  << iIdentifier
530  << " Trying to find paths: " << STAmount(issue, 1).getFullText();
531 
532  auto& pathfinder = getPathFinder(
533  cache,
534  currency_map,
535  issue.currency,
536  dst_amount,
537  level,
538  continueCallback);
539  if (!pathfinder)
540  {
541  assert(continueCallback && !continueCallback());
542  JLOG(m_journal.debug()) << iIdentifier << " No paths found";
543  continue;
544  }
545 
546  STPath fullLiquidityPath;
547  auto ps = pathfinder->getBestPaths(
548  max_paths_,
549  fullLiquidityPath,
550  mContext[issue],
551  issue.account,
552  continueCallback);
553  mContext[issue] = ps;
554 
555  auto const& sourceAccount = [&] {
556  if (!isXRP(issue.account))
557  return issue.account;
558 
559  if (isXRP(issue.currency))
560  return xrpAccount();
561 
562  return *raSrcAccount;
563  }();
564 
565  STAmount saMaxAmount = saSendMax.value_or(
566  STAmount({issue.currency, sourceAccount}, 1u, 0, true));
567 
568  JLOG(m_journal.debug())
569  << iIdentifier << " Paths found, calling rippleCalc";
570 
571  path::RippleCalc::Input rcInput;
572  if (convert_all_)
573  rcInput.partialPaymentAllowed = true;
574  auto sandbox =
575  std::make_unique<PaymentSandbox>(&*cache->getLedger(), tapNONE);
577  *sandbox,
578  saMaxAmount, // --> Amount to send is unlimited
579  // to get an estimate.
580  dst_amount, // --> Amount to deliver.
581  *raDstAccount, // --> Account to deliver to.
582  *raSrcAccount, // --> Account sending from.
583  ps, // --> Path set.
584  app_.logs(),
585  &rcInput);
586 
587  if (!convert_all_ && !fullLiquidityPath.empty() &&
588  (rc.result() == terNO_LINE || rc.result() == tecPATH_PARTIAL))
589  {
590  JLOG(m_journal.debug())
591  << iIdentifier << " Trying with an extra path element";
592 
593  ps.push_back(fullLiquidityPath);
594  sandbox =
595  std::make_unique<PaymentSandbox>(&*cache->getLedger(), tapNONE);
597  *sandbox,
598  saMaxAmount, // --> Amount to send is unlimited
599  // to get an estimate.
600  dst_amount, // --> Amount to deliver.
601  *raDstAccount, // --> Account to deliver to.
602  *raSrcAccount, // --> Account sending from.
603  ps, // --> Path set.
604  app_.logs());
605 
606  if (rc.result() != tesSUCCESS)
607  {
608  JLOG(m_journal.warn())
609  << iIdentifier << " Failed with covering path "
610  << transHuman(rc.result());
611  }
612  else
613  {
614  JLOG(m_journal.debug())
615  << iIdentifier << " Extra path element gives "
616  << transHuman(rc.result());
617  }
618  }
619 
620  if (rc.result() == tesSUCCESS)
621  {
623  rc.actualAmountIn.setIssuer(sourceAccount);
624  jvEntry[jss::source_amount] =
625  rc.actualAmountIn.getJson(JsonOptions::none);
626  jvEntry[jss::paths_computed] = ps.getJson(JsonOptions::none);
627 
628  if (convert_all_)
629  jvEntry[jss::destination_amount] =
630  rc.actualAmountOut.getJson(JsonOptions::none);
631 
632  if (hasCompletion())
633  {
634  // Old ripple_path_find API requires this
635  jvEntry[jss::paths_canonical] = Json::arrayValue;
636  }
637 
638  jvArray.append(jvEntry);
639  }
640  else
641  {
642  JLOG(m_journal.debug()) << iIdentifier << " rippleCalc returns "
643  << transHuman(rc.result());
644  }
645  }
646 
647  /* The resource fee is based on the number of source currencies used.
648  The minimum cost is 50 and the maximum is 400. The cost increases
649  after four source currencies, 50 - (4 * 4) = 34.
650  */
651  int const size = sourceCurrencies.size();
652  consumer_.charge({std::clamp(size * size + 34, 50, 400), "path update"});
653  return true;
654 }
655 
659  bool fast,
660  std::function<bool(void)> const& continueCallback)
661 {
662  using namespace std::chrono;
663  JLOG(m_journal.debug())
664  << iIdentifier << " update " << (fast ? "fast" : "normal");
665 
666  {
668 
669  if (!isValid(cache))
670  return jvStatus;
671  }
672 
673  Json::Value newStatus = Json::objectValue;
674 
675  if (hasCompletion())
676  {
677  // Old ripple_path_find API gives destination_currencies
678  auto& destCurrencies =
679  (newStatus[jss::destination_currencies] = Json::arrayValue);
680  auto usCurrencies = accountDestCurrencies(*raDstAccount, cache, true);
681  for (auto const& c : usCurrencies)
682  destCurrencies.append(to_string(c));
683  }
684 
685  newStatus[jss::source_account] = toBase58(*raSrcAccount);
686  newStatus[jss::destination_account] = toBase58(*raDstAccount);
687  newStatus[jss::destination_amount] = saDstAmount.getJson(JsonOptions::none);
688  newStatus[jss::full_reply] = !fast;
689 
690  if (jvId)
691  newStatus[jss::id] = jvId;
692 
693  bool loaded = app_.getFeeTrack().isLoadedLocal();
694 
695  if (iLevel == 0)
696  {
697  // first pass
698  if (loaded || fast)
700  else
702  }
703  else if ((iLevel == app_.config().PATH_SEARCH_FAST) && !fast)
704  {
705  // leaving fast pathfinding
707  if (loaded && (iLevel > app_.config().PATH_SEARCH_FAST))
708  --iLevel;
709  }
710  else if (bLastSuccess)
711  {
712  // decrement, if possible
713  if (iLevel > app_.config().PATH_SEARCH ||
714  (loaded && (iLevel > app_.config().PATH_SEARCH_FAST)))
715  --iLevel;
716  }
717  else
718  {
719  // adjust as needed
720  if (!loaded && (iLevel < app_.config().PATH_SEARCH_MAX))
721  ++iLevel;
722  if (loaded && (iLevel > app_.config().PATH_SEARCH_FAST))
723  --iLevel;
724  }
725 
726  JLOG(m_journal.debug()) << iIdentifier << " processing at level " << iLevel;
727 
728  Json::Value jvArray = Json::arrayValue;
729  if (findPaths(cache, iLevel, jvArray, continueCallback))
730  {
731  bLastSuccess = jvArray.size() != 0;
732  newStatus[jss::alternatives] = std::move(jvArray);
733  }
734  else
735  {
736  bLastSuccess = false;
737  newStatus = rpcError(rpcINTERNAL);
738  }
739 
740  if (fast && quick_reply_ == steady_clock::time_point{})
741  {
742  quick_reply_ = steady_clock::now();
743  mOwner.reportFast(duration_cast<milliseconds>(quick_reply_ - created_));
744  }
745  else if (!fast && full_reply_ == steady_clock::time_point{})
746  {
747  full_reply_ = steady_clock::now();
748  mOwner.reportFull(duration_cast<milliseconds>(full_reply_ - created_));
749  }
750 
751  {
753  jvStatus = newStatus;
754  }
755 
756  JLOG(m_journal.debug())
757  << iIdentifier << " update finished " << (fast ? "fast" : "normal");
758  return newStatus;
759 }
760 
763 {
764  return wpSubscriber.lock();
765 }
766 
767 } // namespace ripple
ripple::badCurrency
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
Definition: UintTypes.cpp:135
ripple::Application
Definition: Application.h:115
ripple::systemCurrencyCode
static std::string const & systemCurrencyCode()
Definition: SystemParameters.h:62
ripple::to_currency
bool to_currency(Currency &currency, std::string const &code)
Tries to convert a string to a Currency, returns true on success.
Definition: UintTypes.cpp:80
ripple::amountFromJsonNoThrow
bool amountFromJsonNoThrow(STAmount &result, Json::Value const &jvSource)
Definition: STAmount.cpp:1034
std::weak_ptr::lock
T lock(T... args)
ripple::rpcDST_AMT_MALFORMED
@ rpcDST_AMT_MALFORMED
Definition: ErrorCodes.h:106
std::string
STL class.
std::shared_ptr< InfoSub >
ripple::PathRequest::mContext
std::map< Issue, STPathSet > mContext
Definition: PathRequest.h:156
ripple::rpcError
Json::Value rpcError(int iError)
Definition: RPCErr.cpp:29
ripple::Config::PATH_SEARCH
int PATH_SEARCH
Definition: Config.h:201
ripple::base_uint::isNonZero
bool isNonZero() const
Definition: base_uint.h:537
ripple::PathRequest::mLastIndex
LedgerIndex mLastIndex
Definition: PathRequest.h:161
ripple::STAmount::issue
Issue const & issue() const
Definition: STAmount.h:347
ripple::terNO_LINE
@ terNO_LINE
Definition: TER.h:200
ripple::PathRequest::getPathFinder
std::unique_ptr< Pathfinder > const & getPathFinder(std::shared_ptr< RippleLineCache > const &, hash_map< Currency, std::unique_ptr< Pathfinder >> &, Currency const &, STAmount const &, int const, std::function< bool(void)> const &)
Definition: PathRequest.cpp:467
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
ripple::rpcSRC_ACT_NOT_FOUND
@ rpcSRC_ACT_NOT_FOUND
Definition: ErrorCodes.h:122
std::pair
ripple::PathRequest::saDstAmount
STAmount saDstAmount
Definition: PathRequest.h:152
ripple::accountDestCurrencies
hash_set< Currency > accountDestCurrencies(AccountID const &account, std::shared_ptr< RippleLineCache > const &lrCache, bool includeXRP)
Definition: AccountCurrencies.cpp:61
ripple::STAmount::getJson
Json::Value getJson(JsonOptions) const override
Definition: STAmount.cpp:655
std::optional::value_or
T value_or(T... args)
ripple::path::RippleCalc::Input
Definition: RippleCalc.h:46
ripple::toBase58
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:104
ripple::PathRequest::jvStatus
Json::Value jvStatus
Definition: PathRequest.h:147
std::optional::emplace
T emplace(T... args)
ripple::PathRequest::convert_all_
bool convert_all_
Definition: PathRequest.h:158
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
std::lock_guard
STL class.
tuple
ripple::PathRequest::doAborting
void doAborting() const
Definition: PathRequest.cpp:461
ripple::PathRequest::full_reply_
std::chrono::steady_clock::time_point full_reply_
Definition: PathRequest.h:171
ripple::PathRequest::mIndexLock
std::recursive_mutex mIndexLock
Definition: PathRequest.h:160
std::function
ripple::PathRequest::consumer_
Resource::Consumer & consumer_
Definition: PathRequest.h:144
ripple::tapNONE
@ tapNONE
Definition: ApplyView.h:30
ripple::PathRequest::fCompletion
std::function< void(void)> fCompletion
Definition: PathRequest.h:143
ripple::PathRequest::raDstAccount
std::optional< AccountID > raDstAccount
Definition: PathRequest.h:151
ripple::Config::PATH_SEARCH_MAX
int PATH_SEARCH_MAX
Definition: Config.h:203
ripple::PathRequest::doStatus
Json::Value doStatus(Json::Value const &) override
Definition: PathRequest.cpp:453
ripple::PathRequest::doUpdate
Json::Value doUpdate(std::shared_ptr< RippleLineCache > const &, bool fast, std::function< bool(void)> const &continueCallback={})
Definition: PathRequest.cpp:657
ripple::Application::getFeeTrack
virtual LoadFeeTrack & getFeeTrack()=0
ripple::STAmount::getIssuer
AccountID const & getIssuer() const
Definition: STAmount.h:359
ripple::PathRequest::quick_reply_
std::chrono::steady_clock::time_point quick_reply_
Definition: PathRequest.h:170
ripple::base_uint< 160, detail::CurrencyTag >
ripple::LoadFeeTrack::isLoadedLocal
bool isLoadedLocal() const
Definition: LoadFeeTrack.h:126
ripple::STAmount::getFullText
std::string getFullText() const override
Definition: STAmount.cpp:548
Json
JSON (JavaScript Object Notation).
Definition: json_reader.cpp:27
Json::Value::append
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:882
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::PathRequest::PathRequest
PathRequest(Application &app, std::shared_ptr< InfoSub > const &subscriber, int id, PathRequests &, beast::Journal journal)
Definition: PathRequest.cpp:42
ripple::PathRequest::max_paths_
static unsigned const int max_paths_
Definition: PathRequest.h:173
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:133
ripple::PathRequest::sciSourceCurrencies
std::set< Issue > sciSourceCurrencies
Definition: PathRequest.h:155
ripple::PathRequest::~PathRequest
~PathRequest()
Definition: PathRequest.cpp:87
ripple::rpcSRC_ACT_MISSING
@ rpcSRC_ACT_MISSING
Definition: ErrorCodes.h:121
ripple::RPC::Tuning::max_src_cur
static constexpr int max_src_cur
Maximum number of source currencies allowed in a path find request.
Definition: rpc/impl/Tuning.h:81
ripple::JsonOptions::none
@ none
ripple::Application::config
virtual Config & config()=0
ripple::rpcACT_NOT_FOUND
@ rpcACT_NOT_FOUND
Definition: ErrorCodes.h:70
std::to_string
T to_string(T... args)
ripple::PathRequest::bLastSuccess
bool bLastSuccess
Definition: PathRequest.h:165
ripple::rpcSRC_ISR_MALFORMED
@ rpcSRC_ISR_MALFORMED
Definition: ErrorCodes.h:125
ripple::STAmount
Definition: STAmount.h:45
ripple::xrpAccount
AccountID const & xrpAccount()
Compute AccountID from public key.
Definition: AccountID.cpp:168
beast::Journal::info
Stream info() const
Definition: Journal.h:321
Json::Value::size
UInt size() const
Number of values in array or object.
Definition: json_value.cpp:706
ripple::Application::logs
virtual Logs & logs()=0
ripple::PathRequest::app_
Application & app_
Definition: PathRequest.h:135
ripple::isXRP
bool isXRP(AccountID const &c)
Definition: AccountID.h:89
Json::Value::isMember
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:932
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::uint32_t
ripple::tecPATH_PARTIAL
@ tecPATH_PARTIAL
Definition: TER.h:249
ripple::PathRequest::raSrcAccount
std::optional< AccountID > raSrcAccount
Definition: PathRequest.h:150
ripple::rpcDST_ACT_MALFORMED
@ rpcDST_ACT_MALFORMED
Definition: ErrorCodes.h:103
ripple::PathRequest::isValid
bool isValid(std::shared_ptr< RippleLineCache > const &crCache)
Definition: PathRequest.cpp:172
ripple::transHuman
std::string transHuman(TER code)
Definition: TER.cpp:219
ripple::lsfRequireDestTag
@ lsfRequireDestTag
Definition: LedgerFormats.h:224
ripple::PathRequest::updateComplete
void updateComplete()
Definition: PathRequest.cpp:157
ripple::rpcINTERNAL
@ rpcINTERNAL
Definition: ErrorCodes.h:130
Json::Value::isArray
bool isArray() const
Definition: json_value.cpp:1015
ripple::PathRequest::doClose
Json::Value doClose() override
Definition: PathRequest.cpp:444
ripple::PathRequest::doCreate
std::pair< bool, Json::Value > doCreate(std::shared_ptr< RippleLineCache > const &, Json::Value const &)
Definition: PathRequest.cpp:244
ripple::rpcSRC_ACT_MALFORMED
@ rpcSRC_ACT_MALFORMED
Definition: ErrorCodes.h:120
ripple::STAmount::native
bool native() const noexcept
Definition: STAmount.h:329
ripple::STPath::empty
bool empty() const
Definition: STPathSet.h:399
ripple::PathRequest::findPaths
bool findPaths(std::shared_ptr< RippleLineCache > const &, int const, Json::Value &, std::function< bool(void)> const &)
Finds and sets a PathSet in the JSON argument.
Definition: PathRequest.cpp:495
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::PathRequests::reportFast
void reportFast(std::chrono::milliseconds ms)
Definition: PathRequests.h:90
ripple::Config::PATH_SEARCH_FAST
int PATH_SEARCH_FAST
Definition: Config.h:202
ripple::PathRequest::mLock
std::recursive_mutex mLock
Definition: PathRequest.h:138
ripple::PathRequest::created_
const std::chrono::steady_clock::time_point created_
Definition: PathRequest.h:169
std::clamp
T clamp(T... args)
ripple::PathRequest::wpSubscriber
std::weak_ptr< InfoSub > wpSubscriber
Definition: PathRequest.h:142
std
STL namespace.
ripple::PathRequest::isNew
bool isNew()
Definition: PathRequest.cpp:116
ripple::RPC::Tuning::max_auto_src_cur
static constexpr int max_auto_src_cur
Maximum number of auto source currencies in a path find request.
Definition: rpc/impl/Tuning.h:84
ripple::Resource::Consumer
An endpoint that consumes resources.
Definition: Consumer.h:34
ripple::path::RippleCalc::rippleCalculate
static Output rippleCalculate(PaymentSandbox &view, STAmount const &saMaxAmountReq, STAmount const &saDstAmountReq, AccountID const &uDstAccountID, AccountID const &uSrcAccountID, STPathSet const &spsPaths, Logs &l, Input const *const pInputs=nullptr)
Definition: RippleCalc.cpp:31
ripple::PathRequests::reportFull
void reportFull(std::chrono::milliseconds ms)
Definition: PathRequests.h:96
ripple::path::RippleCalc::Input::partialPaymentAllowed
bool partialPaymentAllowed
Definition: RippleCalc.h:50
ripple::rpcDST_AMT_MISSING
@ rpcDST_AMT_MISSING
Definition: ErrorCodes.h:107
optional
beast::Journal::debug
Stream debug() const
Definition: Journal.h:315
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::lsfDisallowXRP
@ lsfDisallowXRP
Definition: LedgerFormats.h:228
ripple::accountSourceCurrencies
hash_set< Currency > accountSourceCurrencies(AccountID const &account, std::shared_ptr< RippleLineCache > const &lrCache, bool includeXRP)
Definition: AccountCurrencies.cpp:25
ripple::rpcSRC_CUR_MALFORMED
@ rpcSRC_CUR_MALFORMED
Definition: ErrorCodes.h:124
ripple::PathRequests
Definition: PathRequests.h:33
ripple::PathRequest::hasCompletion
bool hasCompletion()
Definition: PathRequest.cpp:151
ripple::rpcDST_ACT_MISSING
@ rpcDST_ACT_MISSING
Definition: ErrorCodes.h:104
ripple::PathRequest::saSendMax
std::optional< STAmount > saSendMax
Definition: PathRequest.h:153
ripple::PathRequest::jvId
Json::Value jvId
Definition: PathRequest.h:146
ripple::Resource::Consumer::charge
Disposition charge(Charge const &fee)
Apply a load charge to the consumer.
Definition: Consumer.cpp:99
ripple::PathRequest::iIdentifier
const int iIdentifier
Definition: PathRequest.h:167
ripple::PathRequest::mOwner
PathRequests & mOwner
Definition: PathRequest.h:140
std::unique_ptr
STL class.
ripple::STPath
Definition: STPathSet.h:118
ripple::PathRequest::needsUpdate
bool needsUpdate(bool newOnly, LedgerIndex index)
Definition: PathRequest.cpp:125
std::unordered_map
STL class.
ripple::STAmount::getCurrency
Currency const & getCurrency() const
Definition: STAmount.h:353
ripple::PathRequest::getSubscriber
InfoSub::pointer getSubscriber() const
Definition: PathRequest.cpp:762
ripple::PathRequest::m_journal
beast::Journal m_journal
Definition: PathRequest.h:136
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:222
ripple::PathRequest::parseJson
int parseJson(Json::Value const &)
Definition: PathRequest.cpp:274
ripple::PathRequest::iLevel
int iLevel
Definition: PathRequest.h:164
ripple::PathRequest::mInProgress
bool mInProgress
Definition: PathRequest.h:162
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::rpcSENDMAX_MALFORMED
@ rpcSENDMAX_MALFORMED
Definition: ErrorCodes.h:119
ripple::to_issuer
bool to_issuer(AccountID &, std::string const &)
Convert hex or base58 string to AccountID.
Definition: AccountID.cpp:182
ripple::convertAmount
STAmount convertAmount(STAmount const &amt, bool all)
Definition: PathfinderUtils.h:37
std::chrono