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 
464  Currency const& currency,
465  STAmount const& dst_amount,
466  int const level)
467 {
468  auto i = currency_map.find(currency);
469  if (i != currency_map.end())
470  return i->second;
471  auto pathfinder = std::make_unique<Pathfinder>(
472  cache,
473  *raSrcAccount,
474  *raDstAccount,
475  currency,
476  std::nullopt,
477  dst_amount,
478  saSendMax,
479  app_);
480  if (pathfinder->findPaths(level))
481  pathfinder->computePathRanks(max_paths_);
482  else
483  pathfinder.reset(); // It's a bad request - clear it.
484  return currency_map[currency] = std::move(pathfinder);
485 }
486 
487 bool
490  int const level,
491  Json::Value& jvArray)
492 {
493  auto sourceCurrencies = sciSourceCurrencies;
494  if (sourceCurrencies.empty() && saSendMax)
495  {
496  sourceCurrencies.insert(saSendMax->issue());
497  }
498  if (sourceCurrencies.empty())
499  {
500  auto currencies = accountSourceCurrencies(*raSrcAccount, cache, true);
501  bool const sameAccount = *raSrcAccount == *raDstAccount;
502  for (auto const& c : currencies)
503  {
504  if (!sameAccount || c != saDstAmount.getCurrency())
505  {
506  if (sourceCurrencies.size() >= RPC::Tuning::max_auto_src_cur)
507  return false;
508  sourceCurrencies.insert(
509  {c, c.isZero() ? xrpAccount() : *raSrcAccount});
510  }
511  }
512  }
513 
514  auto const dst_amount = convertAmount(saDstAmount, convert_all_);
516  for (auto const& issue : sourceCurrencies)
517  {
518  JLOG(m_journal.debug())
519  << iIdentifier
520  << " Trying to find paths: " << STAmount(issue, 1).getFullText();
521 
522  auto& pathfinder = getPathFinder(
523  cache, currency_map, issue.currency, dst_amount, level);
524  if (!pathfinder)
525  {
526  assert(false);
527  JLOG(m_journal.debug()) << iIdentifier << " No paths found";
528  continue;
529  }
530 
531  STPath fullLiquidityPath;
532  auto ps = pathfinder->getBestPaths(
533  max_paths_, fullLiquidityPath, mContext[issue], issue.account);
534  mContext[issue] = ps;
535 
536  auto& sourceAccount = !isXRP(issue.account)
537  ? issue.account
538  : isXRP(issue.currency) ? xrpAccount() : *raSrcAccount;
539  STAmount saMaxAmount = saSendMax.value_or(
540  STAmount({issue.currency, sourceAccount}, 1u, 0, true));
541 
542  JLOG(m_journal.debug())
543  << iIdentifier << " Paths found, calling rippleCalc";
544 
545  path::RippleCalc::Input rcInput;
546  if (convert_all_)
547  rcInput.partialPaymentAllowed = true;
548  auto sandbox =
549  std::make_unique<PaymentSandbox>(&*cache->getLedger(), tapNONE);
551  *sandbox,
552  saMaxAmount, // --> Amount to send is unlimited
553  // to get an estimate.
554  dst_amount, // --> Amount to deliver.
555  *raDstAccount, // --> Account to deliver to.
556  *raSrcAccount, // --> Account sending from.
557  ps, // --> Path set.
558  app_.logs(),
559  &rcInput);
560 
561  if (!convert_all_ && !fullLiquidityPath.empty() &&
562  (rc.result() == terNO_LINE || rc.result() == tecPATH_PARTIAL))
563  {
564  JLOG(m_journal.debug())
565  << iIdentifier << " Trying with an extra path element";
566 
567  ps.push_back(fullLiquidityPath);
568  sandbox =
569  std::make_unique<PaymentSandbox>(&*cache->getLedger(), tapNONE);
571  *sandbox,
572  saMaxAmount, // --> Amount to send is unlimited
573  // to get an estimate.
574  dst_amount, // --> Amount to deliver.
575  *raDstAccount, // --> Account to deliver to.
576  *raSrcAccount, // --> Account sending from.
577  ps, // --> Path set.
578  app_.logs());
579 
580  if (rc.result() != tesSUCCESS)
581  {
582  JLOG(m_journal.warn())
583  << iIdentifier << " Failed with covering path "
584  << transHuman(rc.result());
585  }
586  else
587  {
588  JLOG(m_journal.debug())
589  << iIdentifier << " Extra path element gives "
590  << transHuman(rc.result());
591  }
592  }
593 
594  if (rc.result() == tesSUCCESS)
595  {
597  rc.actualAmountIn.setIssuer(sourceAccount);
598  jvEntry[jss::source_amount] =
599  rc.actualAmountIn.getJson(JsonOptions::none);
600  jvEntry[jss::paths_computed] = ps.getJson(JsonOptions::none);
601 
602  if (convert_all_)
603  jvEntry[jss::destination_amount] =
604  rc.actualAmountOut.getJson(JsonOptions::none);
605 
606  if (hasCompletion())
607  {
608  // Old ripple_path_find API requires this
609  jvEntry[jss::paths_canonical] = Json::arrayValue;
610  }
611 
612  jvArray.append(jvEntry);
613  }
614  else
615  {
616  JLOG(m_journal.debug()) << iIdentifier << " rippleCalc returns "
617  << transHuman(rc.result());
618  }
619  }
620 
621  /* The resource fee is based on the number of source currencies used.
622  The minimum cost is 50 and the maximum is 400. The cost increases
623  after four source currencies, 50 - (4 * 4) = 34.
624  */
625  int const size = sourceCurrencies.size();
626  consumer_.charge({std::clamp(size * size + 34, 50, 400), "path update"});
627  return true;
628 }
629 
632 {
633  using namespace std::chrono;
634  JLOG(m_journal.debug())
635  << iIdentifier << " update " << (fast ? "fast" : "normal");
636 
637  {
639 
640  if (!isValid(cache))
641  return jvStatus;
642  }
643 
644  Json::Value newStatus = Json::objectValue;
645 
646  if (hasCompletion())
647  {
648  // Old ripple_path_find API gives destination_currencies
649  auto& destCurrencies =
650  (newStatus[jss::destination_currencies] = Json::arrayValue);
651  auto usCurrencies = accountDestCurrencies(*raDstAccount, cache, true);
652  for (auto const& c : usCurrencies)
653  destCurrencies.append(to_string(c));
654  }
655 
656  newStatus[jss::source_account] =
658  newStatus[jss::destination_account] =
660  newStatus[jss::destination_amount] = saDstAmount.getJson(JsonOptions::none);
661  newStatus[jss::full_reply] = !fast;
662 
663  if (jvId)
664  newStatus[jss::id] = jvId;
665 
666  bool loaded = app_.getFeeTrack().isLoadedLocal();
667 
668  if (iLevel == 0)
669  {
670  // first pass
671  if (loaded || fast)
673  else
675  }
676  else if ((iLevel == app_.config().PATH_SEARCH_FAST) && !fast)
677  {
678  // leaving fast pathfinding
680  if (loaded && (iLevel > app_.config().PATH_SEARCH_FAST))
681  --iLevel;
682  }
683  else if (bLastSuccess)
684  {
685  // decrement, if possible
686  if (iLevel > app_.config().PATH_SEARCH ||
687  (loaded && (iLevel > app_.config().PATH_SEARCH_FAST)))
688  --iLevel;
689  }
690  else
691  {
692  // adjust as needed
693  if (!loaded && (iLevel < app_.config().PATH_SEARCH_MAX))
694  ++iLevel;
695  if (loaded && (iLevel > app_.config().PATH_SEARCH_FAST))
696  --iLevel;
697  }
698 
699  JLOG(m_journal.debug()) << iIdentifier << " processing at level " << iLevel;
700 
701  Json::Value jvArray = Json::arrayValue;
702  if (findPaths(cache, iLevel, jvArray))
703  {
704  bLastSuccess = jvArray.size() != 0;
705  newStatus[jss::alternatives] = std::move(jvArray);
706  }
707  else
708  {
709  bLastSuccess = false;
710  newStatus = rpcError(rpcINTERNAL);
711  }
712 
713  if (fast && quick_reply_ == steady_clock::time_point{})
714  {
715  quick_reply_ = steady_clock::now();
716  mOwner.reportFast(duration_cast<milliseconds>(quick_reply_ - created_));
717  }
718  else if (!fast && full_reply_ == steady_clock::time_point{})
719  {
720  full_reply_ = steady_clock::now();
721  mOwner.reportFull(duration_cast<milliseconds>(full_reply_ - created_));
722  }
723 
724  {
726  jvStatus = newStatus;
727  }
728 
729  return newStatus;
730 }
731 
734 {
735  return wpSubscriber.lock();
736 }
737 
738 } // namespace ripple
ripple::PathRequest::doClose
Json::Value doClose(Json::Value const &)
Definition: PathRequest.cpp:444
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:103
ripple::systemCurrencyCode
static std::string const & systemCurrencyCode()
Definition: SystemParameters.h:54
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:951
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:148
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)
Definition: PathRequest.cpp:461
ripple::Config::PATH_SEARCH
int PATH_SEARCH
Definition: Config.h:165
ripple::base_uint::isNonZero
bool isNonZero() const
Definition: base_uint.h:516
ripple::PathRequest::mLastIndex
LedgerIndex mLastIndex
Definition: PathRequest.h:153
ripple::terNO_LINE
@ terNO_LINE
Definition: TER.h:195
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:144
ripple::accountDestCurrencies
hash_set< Currency > accountDestCurrencies(AccountID const &account, std::shared_ptr< RippleLineCache > const &lrCache, bool includeXRP)
Definition: AccountCurrencies.cpp:64
ripple::STAmount::getJson
Json::Value getJson(JsonOptions) const override
Definition: STAmount.cpp:596
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:29
ripple::PathRequest::jvStatus
Json::Value jvStatus
Definition: PathRequest.h:139
std::optional::emplace
T emplace(T... args)
ripple::PathRequest::convert_all_
bool convert_all_
Definition: PathRequest.h:150
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
std::lock_guard
STL class.
tuple
ripple::PathRequest::full_reply_
std::chrono::steady_clock::time_point full_reply_
Definition: PathRequest.h:163
ripple::PathRequest::mIndexLock
std::recursive_mutex mIndexLock
Definition: PathRequest.h:152
std::function
ripple::PathRequest::consumer_
Resource::Consumer & consumer_
Definition: PathRequest.h:136
ripple::tapNONE
@ tapNONE
Definition: ApplyView.h:30
ripple::PathRequest::fCompletion
std::function< void(void)> fCompletion
Definition: PathRequest.h:135
ripple::Application::accountIDCache
virtual AccountIDCache const & accountIDCache() const =0
ripple::PathRequest::raDstAccount
std::optional< AccountID > raDstAccount
Definition: PathRequest.h:143
ripple::Config::PATH_SEARCH_MAX
int PATH_SEARCH_MAX
Definition: Config.h:167
ripple::Application::getFeeTrack
virtual LoadFeeTrack & getFeeTrack()=0
ripple::PathRequest::quick_reply_
std::chrono::steady_clock::time_point quick_reply_
Definition: PathRequest.h:162
ripple::base_uint< 160, detail::CurrencyTag >
ripple::LoadFeeTrack::isLoadedLocal
bool isLoadedLocal() const
Definition: LoadFeeTrack.h:123
ripple::STAmount::getFullText
std::string getFullText() const override
Definition: STAmount.cpp:489
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:511
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:165
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:130
ripple::PathRequest::sciSourceCurrencies
std::set< Issue > sciSourceCurrencies
Definition: PathRequest.h:147
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:75
ripple::JsonOptions::none
@ none
ripple::Application::config
virtual Config & config()=0
ripple::PathRequest::getSubscriber
InfoSub::pointer getSubscriber()
Definition: PathRequest.cpp:733
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:157
ripple::rpcSRC_ISR_MALFORMED
@ rpcSRC_ISR_MALFORMED
Definition: ErrorCodes.h:125
ripple::STAmount
Definition: STAmount.h:43
ripple::xrpAccount
AccountID const & xrpAccount()
Compute AccountID from public key.
Definition: AccountID.cpp:90
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::findPaths
bool findPaths(std::shared_ptr< RippleLineCache > const &, int const, Json::Value &)
Finds and sets a PathSet in the JSON argument.
Definition: PathRequest.cpp:488
ripple::PathRequest::app_
Application & app_
Definition: PathRequest.h:127
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:244
ripple::PathRequest::raSrcAccount
std::optional< AccountID > raSrcAccount
Definition: PathRequest.h:142
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::rpcError
Json::Value rpcError(int iError, Json::Value jvResult)
Definition: RPCErr.cpp:29
ripple::transHuman
std::string transHuman(TER code)
Definition: TER.cpp:205
ripple::STAmount::getCurrency
Currency const & getCurrency() const
Definition: STAmount.h:205
ripple::lsfRequireDestTag
@ lsfRequireDestTag
Definition: LedgerFormats.h:212
ripple::STAmount::getIssuer
AccountID const & getIssuer() const
Definition: STAmount.h:210
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::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:183
ripple::STPath::empty
bool empty() const
Definition: STPathSet.h:228
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:166
ripple::PathRequest::mLock
std::recursive_mutex mLock
Definition: PathRequest.h:130
ripple::PathRequest::created_
const std::chrono::steady_clock::time_point created_
Definition: PathRequest.h:161
std::clamp
T clamp(T... args)
ripple::PathRequest::doUpdate
Json::Value doUpdate(std::shared_ptr< RippleLineCache > const &, bool fast)
Definition: PathRequest.cpp:631
ripple::PathRequest::wpSubscriber
std::weak_ptr< InfoSub > wpSubscriber
Definition: PathRequest.h:134
ripple::PathRequest::doStatus
Json::Value doStatus(Json::Value const &)
Definition: PathRequest.cpp:453
ripple::STAmount::issue
Issue const & issue() const
Definition: STAmount.h:198
ripple::PathRequest::iIdentifier
int iIdentifier
Definition: PathRequest.h:159
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:78
ripple::Resource::Consumer
An endpoint that consumes resources.
Definition: Consumer.h:33
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:38
ripple::lsfDisallowXRP
@ lsfDisallowXRP
Definition: LedgerFormats.h:216
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:145
ripple::PathRequest::jvId
Json::Value jvId
Definition: PathRequest.h:138
ripple::Resource::Consumer::charge
Disposition charge(Charge const &fee)
Apply a load charge to the consumer.
Definition: Consumer.cpp:99
ripple::PathRequest::mOwner
PathRequests & mOwner
Definition: PathRequest.h:132
std::unique_ptr
STL class.
ripple::STPath
Definition: STPathSet.h:212
ripple::PathRequest::needsUpdate
bool needsUpdate(bool newOnly, LedgerIndex index)
Definition: PathRequest.cpp:125
std::unordered_map
STL class.
ripple::PathRequest::m_journal
beast::Journal m_journal
Definition: PathRequest.h:128
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:217
ripple::PathRequest::parseJson
int parseJson(Json::Value const &)
Definition: PathRequest.cpp:274
ripple::PathRequest::iLevel
int iLevel
Definition: PathRequest.h:156
ripple::PathRequest::mInProgress
bool mInProgress
Definition: PathRequest.h:154
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::rpcSENDMAX_MALFORMED
@ rpcSENDMAX_MALFORMED
Definition: ErrorCodes.h:119
ripple::AccountIDCache::toBase58
std::string toBase58(AccountID const &) const
Return ripple::toBase58 for the AccountID.
Definition: AccountID.cpp:134
ripple::to_issuer
bool to_issuer(AccountID &, std::string const &)
Convert hex or base58 string to AccountID.
Definition: AccountID.cpp:104
ripple::convertAmount
STAmount convertAmount(STAmount const &amt, bool all)
Definition: PathfinderUtils.h:37
std::chrono