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/basics/Log.h>
28 #include <ripple/beast/core/LexicalCast.h>
29 #include <ripple/core/Config.h>
30 #include <ripple/net/RPCErr.h>
31 #include <ripple/protocol/ErrorCodes.h>
32 #include <ripple/protocol/UintTypes.h>
33 #include <ripple/rpc/impl/Tuning.h>
34 #include <boost/algorithm/clamp.hpp>
35 #include <boost/optional.hpp>
36 #include <tuple>
37 
38 namespace ripple {
39 
41  Application& app,
42  const std::shared_ptr<InfoSub>& subscriber,
43  int id,
44  PathRequests& owner,
45  beast::Journal journal)
46  : app_(app)
47  , m_journal(journal)
48  , mOwner(owner)
49  , wpSubscriber(subscriber)
50  , consumer_(subscriber->getConsumer())
51  , jvStatus(Json::objectValue)
52  , mLastIndex(0)
53  , mInProgress(false)
54  , iLevel(0)
55  , bLastSuccess(false)
56  , iIdentifier(id)
57  , created_(std::chrono::steady_clock::now())
58 {
59  JLOG(m_journal.debug()) << iIdentifier << " created";
60 }
61 
63  Application& app,
64  std::function<void(void)> const& completion,
65  Resource::Consumer& consumer,
66  int id,
67  PathRequests& owner,
68  beast::Journal journal)
69  : app_(app)
70  , m_journal(journal)
71  , mOwner(owner)
72  , fCompletion(completion)
73  , consumer_(consumer)
74  , jvStatus(Json::objectValue)
75  , mLastIndex(0)
76  , mInProgress(false)
77  , iLevel(0)
78  , bLastSuccess(false)
79  , iIdentifier(id)
80  , created_(std::chrono::steady_clock::now())
81 {
82  JLOG(m_journal.debug()) << iIdentifier << " created";
83 }
84 
86 {
87  using namespace std::chrono;
88  auto stream = m_journal.info();
89  if (!stream)
90  return;
91 
92  std::string fast, full;
93  if (quick_reply_ != steady_clock::time_point{})
94  {
95  fast = " fast:";
96  fast += std::to_string(
97  duration_cast<milliseconds>(quick_reply_ - created_).count());
98  fast += "ms";
99  }
100  if (full_reply_ != steady_clock::time_point{})
101  {
102  full = " full:";
103  full += std::to_string(
104  duration_cast<milliseconds>(full_reply_ - created_).count());
105  full += "ms";
106  }
107  stream
108  << iIdentifier << " complete:" << fast << full << " total:"
109  << duration_cast<milliseconds>(steady_clock::now() - created_).count()
110  << "ms";
111 }
112 
113 bool
115 {
117 
118  // does this path request still need its first full path
119  return mLastIndex == 0;
120 }
121 
122 bool
124 {
126 
127  if (mInProgress)
128  {
129  // Another thread is handling this
130  return false;
131  }
132 
133  if (newOnly && (mLastIndex != 0))
134  {
135  // Only handling new requests, this isn't new
136  return false;
137  }
138 
139  if (mLastIndex >= index)
140  {
141  return false;
142  }
143 
144  mInProgress = true;
145  return true;
146 }
147 
148 bool
150 {
151  return bool(fCompletion);
152 }
153 
154 void
156 {
158 
159  assert(mInProgress);
160  mInProgress = false;
161 
162  if (fCompletion)
163  {
164  fCompletion();
166  }
167 }
168 
169 bool
171 {
172  if (!raSrcAccount || !raDstAccount)
173  return false;
174 
175  if (!convert_all_ && (saSendMax || saDstAmount <= beast::zero))
176  {
177  // If send max specified, dst amt must be -1.
179  return false;
180  }
181 
182  auto const& lrLedger = crCache->getLedger();
183 
184  if (!lrLedger->exists(keylet::account(*raSrcAccount)))
185  {
186  // Source account does not exist.
188  return false;
189  }
190 
191  auto const sleDest = lrLedger->read(keylet::account(*raDstAccount));
192 
193  Json::Value& jvDestCur =
194  (jvStatus[jss::destination_currencies] = Json::arrayValue);
195 
196  if (!sleDest)
197  {
198  jvDestCur.append(Json::Value(systemCurrencyCode()));
199  if (!saDstAmount.native())
200  {
201  // Only XRP can be send to a non-existent account.
203  return false;
204  }
205 
206  if (!convert_all_ &&
207  saDstAmount < STAmount(lrLedger->fees().accountReserve(0)))
208  {
209  // Payment must meet reserve.
211  return false;
212  }
213  }
214  else
215  {
216  bool const disallowXRP(sleDest->getFlags() & lsfDisallowXRP);
217 
218  auto usDestCurrID =
219  accountDestCurrencies(*raDstAccount, crCache, !disallowXRP);
220 
221  for (auto const& currency : usDestCurrID)
222  jvDestCur.append(to_string(currency));
223  jvStatus[jss::destination_tag] =
224  (sleDest->getFlags() & lsfRequireDestTag);
225  }
226 
227  jvStatus[jss::ledger_hash] = to_string(lrLedger->info().hash);
228  jvStatus[jss::ledger_index] = lrLedger->seq();
229  return true;
230 }
231 
232 /* If this is a normal path request, we want to run it once "fast" now
233  to give preliminary results.
234 
235  If this is a legacy path request, we are only going to run it once,
236  and we can't run it in full now, so we don't want to run it at all.
237 
238  If there's an error, we need to be sure to return it to the caller
239  in all cases.
240 */
244  Json::Value const& value)
245 {
246  bool valid = false;
247 
248  if (parseJson(value) != PFR_PJ_INVALID)
249  {
250  valid = isValid(cache);
251  if (!hasCompletion() && valid)
252  doUpdate(cache, true);
253  }
254 
255  if (auto stream = m_journal.debug())
256  {
257  if (valid)
258  {
259  stream << iIdentifier << " valid: " << toBase58(*raSrcAccount);
260  stream << iIdentifier << " deliver: " << saDstAmount.getFullText();
261  }
262  else
263  {
264  stream << iIdentifier << " invalid";
265  }
266  }
267 
268  return {valid, jvStatus};
269 }
270 
271 int
273 {
274  if (!jvParams.isMember(jss::source_account))
275  {
277  return PFR_PJ_INVALID;
278  }
279 
280  if (!jvParams.isMember(jss::destination_account))
281  {
283  return PFR_PJ_INVALID;
284  }
285 
286  if (!jvParams.isMember(jss::destination_amount))
287  {
289  return PFR_PJ_INVALID;
290  }
291 
292  raSrcAccount =
293  parseBase58<AccountID>(jvParams[jss::source_account].asString());
294  if (!raSrcAccount)
295  {
297  return PFR_PJ_INVALID;
298  }
299 
300  raDstAccount =
301  parseBase58<AccountID>(jvParams[jss::destination_account].asString());
302  if (!raDstAccount)
303  {
305  return PFR_PJ_INVALID;
306  }
307 
308  if (!amountFromJsonNoThrow(saDstAmount, jvParams[jss::destination_amount]))
309  {
311  return PFR_PJ_INVALID;
312  }
313 
314  convert_all_ = saDstAmount == STAmount(saDstAmount.issue(), 1u, 0, true);
315 
316  if ((saDstAmount.getCurrency().isZero() &&
319  (!convert_all_ && saDstAmount <= beast::zero))
320  {
322  return PFR_PJ_INVALID;
323  }
324 
325  if (jvParams.isMember(jss::send_max))
326  {
327  // Send_max requires destination amount to be -1.
328  if (!convert_all_)
329  {
331  return PFR_PJ_INVALID;
332  }
333 
334  saSendMax.emplace();
335  if (!amountFromJsonNoThrow(*saSendMax, jvParams[jss::send_max]) ||
336  (saSendMax->getCurrency().isZero() &&
337  saSendMax->getIssuer().isNonZero()) ||
338  (saSendMax->getCurrency() == badCurrency()) ||
339  (*saSendMax <= beast::zero &&
340  *saSendMax != STAmount(saSendMax->issue(), 1u, 0, true)))
341  {
343  return PFR_PJ_INVALID;
344  }
345  }
346 
347  if (jvParams.isMember(jss::source_currencies))
348  {
349  Json::Value const& jvSrcCurrencies = jvParams[jss::source_currencies];
350  if (!jvSrcCurrencies.isArray() || jvSrcCurrencies.size() == 0 ||
351  jvSrcCurrencies.size() > RPC::Tuning::max_src_cur)
352  {
354  return PFR_PJ_INVALID;
355  }
356 
357  sciSourceCurrencies.clear();
358 
359  for (auto const& c : jvSrcCurrencies)
360  {
361  // Mandatory currency
362  Currency srcCurrencyID;
363  if (!c.isObject() || !c.isMember(jss::currency) ||
364  !c[jss::currency].isString() ||
365  !to_currency(srcCurrencyID, c[jss::currency].asString()))
366  {
368  return PFR_PJ_INVALID;
369  }
370 
371  // Optional issuer
372  AccountID srcIssuerID;
373  if (c.isMember(jss::issuer) &&
374  (!c[jss::issuer].isString() ||
375  !to_issuer(srcIssuerID, c[jss::issuer].asString())))
376  {
378  return PFR_PJ_INVALID;
379  }
380 
381  if (srcCurrencyID.isZero())
382  {
383  if (srcIssuerID.isNonZero())
384  {
386  return PFR_PJ_INVALID;
387  }
388  }
389  else if (srcIssuerID.isZero())
390  {
391  srcIssuerID = *raSrcAccount;
392  }
393 
394  if (saSendMax)
395  {
396  // If the currencies don't match, ignore the source currency.
397  if (srcCurrencyID == saSendMax->getCurrency())
398  {
399  // If neither is the source and they are not equal, then the
400  // source issuer is illegal.
401  if (srcIssuerID != *raSrcAccount &&
402  saSendMax->getIssuer() != *raSrcAccount &&
403  srcIssuerID != saSendMax->getIssuer())
404  {
406  return PFR_PJ_INVALID;
407  }
408 
409  // If both are the source, use the source.
410  // Otherwise, use the one that's not the source.
411  if (srcIssuerID != *raSrcAccount)
412  {
413  sciSourceCurrencies.insert(
414  {srcCurrencyID, srcIssuerID});
415  }
416  else if (saSendMax->getIssuer() != *raSrcAccount)
417  {
418  sciSourceCurrencies.insert(
419  {srcCurrencyID, saSendMax->getIssuer()});
420  }
421  else
422  {
423  sciSourceCurrencies.insert(
424  {srcCurrencyID, *raSrcAccount});
425  }
426  }
427  }
428  else
429  {
430  sciSourceCurrencies.insert({srcCurrencyID, srcIssuerID});
431  }
432  }
433  }
434 
435  if (jvParams.isMember(jss::id))
436  jvId = jvParams[jss::id];
437 
438  return PFR_PJ_NOCHANGE;
439 }
440 
443 {
444  JLOG(m_journal.debug()) << iIdentifier << " closed";
446  jvStatus[jss::closed] = true;
447  return jvStatus;
448 }
449 
452 {
454  jvStatus[jss::status] = jss::success;
455  return jvStatus;
456 }
457 
462  Currency const& currency,
463  STAmount const& dst_amount,
464  int const level)
465 {
466  auto i = currency_map.find(currency);
467  if (i != currency_map.end())
468  return i->second;
469  auto pathfinder = std::make_unique<Pathfinder>(
470  cache,
471  *raSrcAccount,
472  *raDstAccount,
473  currency,
474  boost::none,
475  dst_amount,
476  saSendMax,
477  app_);
478  if (pathfinder->findPaths(level))
479  pathfinder->computePathRanks(max_paths_);
480  else
481  pathfinder.reset(); // It's a bad request - clear it.
482  return currency_map[currency] = std::move(pathfinder);
483 }
484 
485 bool
488  int const level,
489  Json::Value& jvArray)
490 {
491  auto sourceCurrencies = sciSourceCurrencies;
492  if (sourceCurrencies.empty())
493  {
494  auto currencies = accountSourceCurrencies(*raSrcAccount, cache, true);
495  bool const sameAccount = *raSrcAccount == *raDstAccount;
496  for (auto const& c : currencies)
497  {
498  if (!sameAccount || c != saDstAmount.getCurrency())
499  {
500  if (sourceCurrencies.size() >= RPC::Tuning::max_auto_src_cur)
501  return false;
502  sourceCurrencies.insert(
503  {c, c.isZero() ? xrpAccount() : *raSrcAccount});
504  }
505  }
506  }
507 
508  auto const dst_amount = convert_all_
509  ? STAmount(
511  : saDstAmount;
513  for (auto const& issue : sourceCurrencies)
514  {
515  JLOG(m_journal.debug())
516  << iIdentifier
517  << " Trying to find paths: " << STAmount(issue, 1).getFullText();
518 
519  auto& pathfinder = getPathFinder(
520  cache, currency_map, issue.currency, dst_amount, level);
521  if (!pathfinder)
522  {
523  assert(false);
524  JLOG(m_journal.debug()) << iIdentifier << " No paths found";
525  continue;
526  }
527 
528  STPath fullLiquidityPath;
529  auto ps = pathfinder->getBestPaths(
530  max_paths_, fullLiquidityPath, mContext[issue], issue.account);
531  mContext[issue] = ps;
532 
533  auto& sourceAccount = !isXRP(issue.account)
534  ? issue.account
535  : isXRP(issue.currency) ? xrpAccount() : *raSrcAccount;
536  STAmount saMaxAmount = saSendMax.value_or(
537  STAmount({issue.currency, sourceAccount}, 1u, 0, true));
538 
539  JLOG(m_journal.debug())
540  << iIdentifier << " Paths found, calling rippleCalc";
541 
542  path::RippleCalc::Input rcInput;
543  if (convert_all_)
544  rcInput.partialPaymentAllowed = true;
545  auto sandbox =
546  std::make_unique<PaymentSandbox>(&*cache->getLedger(), tapNONE);
548  *sandbox,
549  saMaxAmount, // --> Amount to send is unlimited
550  // to get an estimate.
551  dst_amount, // --> Amount to deliver.
552  *raDstAccount, // --> Account to deliver to.
553  *raSrcAccount, // --> Account sending from.
554  ps, // --> Path set.
555  app_.logs(),
556  &rcInput);
557 
558  if (!convert_all_ && !fullLiquidityPath.empty() &&
559  (rc.result() == terNO_LINE || rc.result() == tecPATH_PARTIAL))
560  {
561  JLOG(m_journal.debug())
562  << iIdentifier << " Trying with an extra path element";
563 
564  ps.push_back(fullLiquidityPath);
565  sandbox =
566  std::make_unique<PaymentSandbox>(&*cache->getLedger(), tapNONE);
568  *sandbox,
569  saMaxAmount, // --> Amount to send is unlimited
570  // to get an estimate.
571  dst_amount, // --> Amount to deliver.
572  *raDstAccount, // --> Account to deliver to.
573  *raSrcAccount, // --> Account sending from.
574  ps, // --> Path set.
575  app_.logs());
576 
577  if (rc.result() != tesSUCCESS)
578  {
579  JLOG(m_journal.warn())
580  << iIdentifier << " Failed with covering path "
581  << transHuman(rc.result());
582  }
583  else
584  {
585  JLOG(m_journal.debug())
586  << iIdentifier << " Extra path element gives "
587  << transHuman(rc.result());
588  }
589  }
590 
591  if (rc.result() == tesSUCCESS)
592  {
594  rc.actualAmountIn.setIssuer(sourceAccount);
595  jvEntry[jss::source_amount] =
596  rc.actualAmountIn.getJson(JsonOptions::none);
597  jvEntry[jss::paths_computed] = ps.getJson(JsonOptions::none);
598 
599  if (convert_all_)
600  jvEntry[jss::destination_amount] =
601  rc.actualAmountOut.getJson(JsonOptions::none);
602 
603  if (hasCompletion())
604  {
605  // Old ripple_path_find API requires this
606  jvEntry[jss::paths_canonical] = Json::arrayValue;
607  }
608 
609  jvArray.append(jvEntry);
610  }
611  else
612  {
613  JLOG(m_journal.debug()) << iIdentifier << " rippleCalc returns "
614  << transHuman(rc.result());
615  }
616  }
617 
618  /* The resource fee is based on the number of source currencies used.
619  The minimum cost is 50 and the maximum is 400. The cost increases
620  after four source currencies, 50 - (4 * 4) = 34.
621  */
622  int const size = sourceCurrencies.size();
624  {boost::algorithm::clamp(size * size + 34, 50, 400), "path update"});
625  return true;
626 }
627 
630 {
631  using namespace std::chrono;
632  JLOG(m_journal.debug())
633  << iIdentifier << " update " << (fast ? "fast" : "normal");
634 
635  {
637 
638  if (!isValid(cache))
639  return jvStatus;
640  }
641 
642  Json::Value newStatus = Json::objectValue;
643 
644  if (hasCompletion())
645  {
646  // Old ripple_path_find API gives destination_currencies
647  auto& destCurrencies =
648  (newStatus[jss::destination_currencies] = Json::arrayValue);
649  auto usCurrencies = accountDestCurrencies(*raDstAccount, cache, true);
650  for (auto const& c : usCurrencies)
651  destCurrencies.append(to_string(c));
652  }
653 
654  newStatus[jss::source_account] =
656  newStatus[jss::destination_account] =
658  newStatus[jss::destination_amount] = saDstAmount.getJson(JsonOptions::none);
659  newStatus[jss::full_reply] = !fast;
660 
661  if (jvId)
662  newStatus[jss::id] = jvId;
663 
664  bool loaded = app_.getFeeTrack().isLoadedLocal();
665 
666  if (iLevel == 0)
667  {
668  // first pass
669  if (loaded || fast)
671  else
673  }
674  else if ((iLevel == app_.config().PATH_SEARCH_FAST) && !fast)
675  {
676  // leaving fast pathfinding
678  if (loaded && (iLevel > app_.config().PATH_SEARCH_FAST))
679  --iLevel;
680  }
681  else if (bLastSuccess)
682  {
683  // decrement, if possible
684  if (iLevel > app_.config().PATH_SEARCH ||
685  (loaded && (iLevel > app_.config().PATH_SEARCH_FAST)))
686  --iLevel;
687  }
688  else
689  {
690  // adjust as needed
691  if (!loaded && (iLevel < app_.config().PATH_SEARCH_MAX))
692  ++iLevel;
693  if (loaded && (iLevel > app_.config().PATH_SEARCH_FAST))
694  --iLevel;
695  }
696 
697  JLOG(m_journal.debug()) << iIdentifier << " processing at level " << iLevel;
698 
699  Json::Value jvArray = Json::arrayValue;
700  if (findPaths(cache, iLevel, jvArray))
701  {
702  bLastSuccess = jvArray.size() != 0;
703  newStatus[jss::alternatives] = std::move(jvArray);
704  }
705  else
706  {
707  bLastSuccess = false;
708  newStatus = rpcError(rpcINTERNAL);
709  }
710 
711  if (fast && quick_reply_ == steady_clock::time_point{})
712  {
713  quick_reply_ = steady_clock::now();
714  mOwner.reportFast(duration_cast<milliseconds>(quick_reply_ - created_));
715  }
716  else if (!fast && full_reply_ == steady_clock::time_point{})
717  {
718  full_reply_ = steady_clock::now();
719  mOwner.reportFull(duration_cast<milliseconds>(full_reply_ - created_));
720  }
721 
722  {
724  jvStatus = newStatus;
725  }
726 
727  return newStatus;
728 }
729 
732 {
733  return wpSubscriber.lock();
734 }
735 
736 } // namespace ripple
ripple::PathRequest::doClose
Json::Value doClose(Json::Value const &)
Definition: PathRequest.cpp:442
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:138
ripple::Application
Definition: Application.h:97
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:83
ripple::amountFromJsonNoThrow
bool amountFromJsonNoThrow(STAmount &result, Json::Value const &jvSource)
Definition: STAmount.cpp:931
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:459
ripple::Config::PATH_SEARCH
int PATH_SEARCH
Definition: Config.h:157
ripple::base_uint::isNonZero
bool isNonZero() const
Definition: base_uint.h:444
ripple::PathRequest::mLastIndex
LedgerIndex mLastIndex
Definition: PathRequest.h:153
ripple::terNO_LINE
@ terNO_LINE
Definition: TER.h:194
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:594
ripple::PathRequest::raDstAccount
boost::optional< AccountID > raDstAccount
Definition: PathRequest.h:143
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
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::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:42
ripple::PathRequest::consumer_
Resource::Consumer & consumer_
Definition: PathRequest.h:136
ripple::tapNONE
@ tapNONE
Definition: ApplyView.h:31
ripple::PathRequest::fCompletion
std::function< void(void)> fCompletion
Definition: PathRequest.h:135
ripple::Application::accountIDCache
virtual AccountIDCache const & accountIDCache() const =0
ripple::Config::PATH_SEARCH_MAX
int PATH_SEARCH_MAX
Definition: Config.h:159
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:487
Json
JSON (JavaScript Object Notation).
Definition: json_reader.cpp:26
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:439
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:40
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:134
ripple::PathRequest::sciSourceCurrencies
std::set< Issue > sciSourceCurrencies
Definition: PathRequest.h:147
ripple::PathRequest::~PathRequest
~PathRequest()
Definition: PathRequest.cpp:85
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:731
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:42
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:486
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:243
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:170
ripple::rpcError
Json::Value rpcError(int iError, Json::Value jvResult)
Definition: RPCErr.cpp:29
ripple::transHuman
std::string transHuman(TER code)
Definition: TER.cpp:204
ripple::STAmount::getCurrency
Currency const & getCurrency() const
Definition: STAmount.h:204
ripple::lsfRequireDestTag
@ lsfRequireDestTag
Definition: LedgerFormats.h:104
ripple::STAmount::getIssuer
AccountID const & getIssuer() const
Definition: STAmount.h:209
ripple::PathRequest::updateComplete
void updateComplete()
Definition: PathRequest.cpp:155
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:242
ripple::rpcSRC_ACT_MALFORMED
@ rpcSRC_ACT_MALFORMED
Definition: ErrorCodes.h:120
ripple::STAmount::native
bool native() const noexcept
Definition: STAmount.h:182
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:158
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
ripple::PathRequest::doUpdate
Json::Value doUpdate(std::shared_ptr< RippleLineCache > const &, bool fast)
Definition: PathRequest.cpp:629
ripple::PathRequest::wpSubscriber
std::weak_ptr< InfoSub > wpSubscriber
Definition: PathRequest.h:134
ripple::PathRequest::doStatus
Json::Value doStatus(Json::Value const &)
Definition: PathRequest.cpp:451
ripple::STAmount::issue
Issue const & issue() const
Definition: STAmount.h:197
ripple::PathRequest::iIdentifier
int iIdentifier
Definition: PathRequest.h:159
std
STL namespace.
ripple::PathRequest::isNew
bool isNew()
Definition: PathRequest.cpp:114
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:32
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
beast::Journal::debug
Stream debug() const
Definition: Journal.h:315
ripple::PathRequest::saSendMax
boost::optional< STAmount > saSendMax
Definition: PathRequest.h:145
ripple::lsfDisallowXRP
@ lsfDisallowXRP
Definition: LedgerFormats.h:108
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:149
ripple::rpcDST_ACT_MISSING
@ rpcDST_ACT_MISSING
Definition: ErrorCodes.h:104
ripple::STAmount::cMaxOffset
static const int cMaxOffset
Definition: STAmount.h:60
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:123
std::unordered_map
STL class.
ripple::PathRequest::m_journal
beast::Journal m_journal
Definition: PathRequest.h:128
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:216
ripple::PathRequest::parseJson
int parseJson(Json::Value const &)
Definition: PathRequest.cpp:272
ripple::STAmount::cMaxValue
static const std::uint64_t cMaxValue
Definition: STAmount.h:64
ripple::PathRequest::iLevel
int iLevel
Definition: PathRequest.h:156
ripple::PathRequest::mInProgress
bool mInProgress
Definition: PathRequest.h:154
ripple::PathRequest::raSrcAccount
boost::optional< AccountID > raSrcAccount
Definition: PathRequest.h:142
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
std::chrono