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/paths/AccountCurrencies.h>
21 #include <ripple/app/paths/RippleCalc.h>
22 #include <ripple/app/paths/PathRequest.h>
23 #include <ripple/app/paths/PathRequests.h>
24 #include <ripple/app/main/Application.h>
25 #include <ripple/app/misc/LoadFeeTrack.h>
26 #include <ripple/app/misc/NetworkOPs.h>
27 #include <ripple/basics/Log.h>
28 #include <ripple/core/Config.h>
29 #include <ripple/net/RPCErr.h>
30 #include <ripple/protocol/ErrorCodes.h>
31 #include <ripple/protocol/UintTypes.h>
32 #include <ripple/rpc/impl/Tuning.h>
33 #include <ripple/beast/core/LexicalCast.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())
60  << iIdentifier << " created";
61 }
62 
64  Application& app,
65  std::function <void(void)> const& completion,
66  Resource::Consumer& consumer,
67  int id,
68  PathRequests& owner,
69  beast::Journal journal)
70  : app_ (app)
71  , m_journal (journal)
72  , mOwner (owner)
73  , fCompletion (completion)
74  , consumer_ (consumer)
75  , jvStatus (Json::objectValue)
76  , mLastIndex (0)
77  , mInProgress (false)
78  , iLevel (0)
79  , bLastSuccess (false)
80  , iIdentifier (id)
81  , created_ (std::chrono::steady_clock::now())
82 {
83  JLOG(m_journal.debug())
84  << 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 << iIdentifier << " complete:" << fast << full <<
110  " total:" << duration_cast<milliseconds>(steady_clock::now() -
111  created_).count() << "ms";
112 }
113 
115 {
117 
118  // does this path request still need its first full path
119  return mLastIndex == 0;
120 }
121 
122 bool PathRequest::needsUpdate (bool newOnly, LedgerIndex index)
123 {
125 
126  if (mInProgress)
127  {
128  // Another thread is handling this
129  return false;
130  }
131 
132  if (newOnly && (mLastIndex != 0))
133  {
134  // Only handling new requests, this isn't new
135  return false;
136  }
137 
138  if (mLastIndex >= index)
139  {
140  return false;
141  }
142 
143  mInProgress = true;
144  return true;
145 }
146 
148 {
149  return bool (fCompletion);
150 }
151 
153 {
155 
156  assert (mInProgress);
157  mInProgress = false;
158 
159  if (fCompletion)
160  {
161  fCompletion();
163  }
164 }
165 
167 {
168  if (! raSrcAccount || ! raDstAccount)
169  return false;
170 
171  if (! convert_all_ && (saSendMax || saDstAmount <= beast::zero))
172  {
173  // If send max specified, dst amt must be -1.
175  return false;
176  }
177 
178  auto const& lrLedger = crCache->getLedger();
179 
180  if (! lrLedger->exists(keylet::account(*raSrcAccount)))
181  {
182  // Source account does not exist.
184  return false;
185  }
186 
187  auto const sleDest = lrLedger->read(
189 
190  Json::Value& jvDestCur =
191  (jvStatus[jss::destination_currencies] = Json::arrayValue);
192 
193  if (! sleDest)
194  {
195  jvDestCur.append (Json::Value (systemCurrencyCode()));
196  if (! saDstAmount.native ())
197  {
198  // Only XRP can be send to a non-existent account.
200  return false;
201  }
202 
203  if (! convert_all_ && saDstAmount <
204  STAmount (lrLedger->fees().accountReserve (0)))
205  {
206  // Payment must meet reserve.
208  return false;
209  }
210  }
211  else
212  {
213  bool const disallowXRP (
214  sleDest->getFlags() & lsfDisallowXRP);
215 
216  auto usDestCurrID = accountDestCurrencies (
217  *raDstAccount, crCache, ! disallowXRP);
218 
219  for (auto const& currency : usDestCurrID)
220  jvDestCur.append (to_string (currency));
221  jvStatus[jss::destination_tag] =
222  (sleDest->getFlags() & lsfRequireDestTag);
223  }
224 
225  jvStatus[jss::ledger_hash] = to_string (lrLedger->info().hash);
226  jvStatus[jss::ledger_index] = lrLedger->seq();
227  return true;
228 }
229 
230 /* If this is a normal path request, we want to run it once "fast" now
231  to give preliminary results.
232 
233  If this is a legacy path request, we are only going to run it once,
234  and we can't run it in full now, so we don't want to run it at all.
235 
236  If there's an error, we need to be sure to return it to the caller
237  in all cases.
238 */
242  Json::Value const& value)
243 {
244  bool valid = false;
245 
246  if (parseJson (value) != PFR_PJ_INVALID)
247  {
248  valid = isValid (cache);
249  if (! hasCompletion() && valid)
250  doUpdate(cache, true);
251  }
252 
253  if (auto stream = m_journal.debug())
254  {
255  if (valid)
256  {
257  stream << iIdentifier <<
258  " valid: " << toBase58(*raSrcAccount);
259  stream << iIdentifier <<
260  " deliver: " << saDstAmount.getFullText ();
261  }
262  else
263  {
264  stream << iIdentifier << " invalid";
265  }
266  }
267 
268  return { valid, jvStatus };
269 }
270 
271 int PathRequest::parseJson (Json::Value const& jvParams)
272 {
273  if (! jvParams.isMember(jss::source_account))
274  {
276  return PFR_PJ_INVALID;
277  }
278 
279  if (! jvParams.isMember(jss::destination_account))
280  {
282  return PFR_PJ_INVALID;
283  }
284 
285  if (! jvParams.isMember(jss::destination_amount))
286  {
288  return PFR_PJ_INVALID;
289  }
290 
291  raSrcAccount = parseBase58<AccountID>(
292  jvParams[jss::source_account].asString());
293  if (! raSrcAccount)
294  {
296  return PFR_PJ_INVALID;
297  }
298 
299  raDstAccount = parseBase58<AccountID>(
300  jvParams[jss::destination_account].asString());
301  if (! raDstAccount)
302  {
304  return PFR_PJ_INVALID;
305  }
306 
307  if (! amountFromJsonNoThrow (
308  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 () &&
318  (saDstAmount.getCurrency () == badCurrency ()) ||
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(
336  *saSendMax, jvParams[jss::send_max]) ||
337  (saSendMax->getCurrency().isZero() &&
338  saSendMax->getIssuer().isNonZero()) ||
339  (saSendMax->getCurrency() == badCurrency()) ||
340  (*saSendMax <= beast::zero &&
341  *saSendMax != STAmount(saSendMax->issue(), 1u, 0, true)))
342  {
344  return PFR_PJ_INVALID;
345  }
346  }
347 
348  if (jvParams.isMember (jss::source_currencies))
349  {
350  Json::Value const& jvSrcCurrencies = jvParams[jss::source_currencies];
351  if (! jvSrcCurrencies.isArray() || jvSrcCurrencies.size() == 0 ||
352  jvSrcCurrencies.size() > RPC::Tuning::max_src_cur)
353  {
355  return PFR_PJ_INVALID;
356  }
357 
358  sciSourceCurrencies.clear ();
359 
360  for (auto const& c : jvSrcCurrencies)
361  {
362  // Mandatory currency
363  Currency srcCurrencyID;
364  if (! c.isObject() ||
365  ! 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 
444 {
445  JLOG(m_journal.debug()) << iIdentifier << " closed";
446  std::lock_guard sl (mLock);
447  jvStatus[jss::closed] = true;
448  return jvStatus;
449 }
450 
452 {
453  std::lock_guard sl (mLock);
454  jvStatus[jss::status] = jss::success;
455  return jvStatus;
456 }
457 
461  Currency const& currency, STAmount const& dst_amount,
462  int const level)
463 {
464  auto i = currency_map.find(currency);
465  if (i != currency_map.end())
466  return i->second;
467  auto pathfinder = std::make_unique<Pathfinder>(
468  cache, *raSrcAccount, *raDstAccount, currency,
469  boost::none, dst_amount, saSendMax, app_);
470  if (pathfinder->findPaths(level))
471  pathfinder->computePathRanks(max_paths_);
472  else
473  pathfinder.reset(); // It's a bad request - clear it.
474  return currency_map[currency] = std::move(pathfinder);
475 }
476 
477 bool
479  int const level, Json::Value& jvArray)
480 {
481  auto sourceCurrencies = sciSourceCurrencies;
482  if (sourceCurrencies.empty ())
483  {
484  auto currencies = accountSourceCurrencies(*raSrcAccount, cache, true);
485  bool const sameAccount = *raSrcAccount == *raDstAccount;
486  for (auto const& c : currencies)
487  {
488  if (! sameAccount || c != saDstAmount.getCurrency())
489  {
490  if (sourceCurrencies.size() >= RPC::Tuning::max_auto_src_cur)
491  return false;
492  sourceCurrencies.insert(
493  {c, c.isZero() ? xrpAccount() : *raSrcAccount});
494  }
495  }
496  }
497 
498  auto const dst_amount = convert_all_ ?
500  : saDstAmount;
502  for (auto const& issue : sourceCurrencies)
503  {
504  JLOG(m_journal.debug())
505  << iIdentifier
506  << " Trying to find paths: "
507  << STAmount(issue, 1).getFullText();
508 
509  auto& pathfinder = getPathFinder(cache, currency_map,
510  issue.currency, dst_amount, level);
511  if (! pathfinder)
512  {
513  assert(false);
514  JLOG(m_journal.debug()) << iIdentifier << " No paths found";
515  continue;
516  }
517 
518  STPath fullLiquidityPath;
519  auto ps = pathfinder->getBestPaths(max_paths_,
520  fullLiquidityPath, mContext[issue], issue.account);
521  mContext[issue] = ps;
522 
523  auto& sourceAccount = ! isXRP(issue.account)
524  ? issue.account
525  : isXRP(issue.currency)
526  ? xrpAccount()
527  : *raSrcAccount;
528  STAmount saMaxAmount = saSendMax.value_or(
529  STAmount({issue.currency, sourceAccount}, 1u, 0, true));
530 
531  JLOG(m_journal.debug()) << iIdentifier
532  << " Paths found, calling rippleCalc";
533 
534  path::RippleCalc::Input rcInput;
535  if (convert_all_)
536  rcInput.partialPaymentAllowed = true;
537  auto sandbox = std::make_unique<PaymentSandbox>
538  (&*cache->getLedger(), tapNONE);
540  *sandbox,
541  saMaxAmount, // --> Amount to send is unlimited
542  // to get an estimate.
543  dst_amount, // --> Amount to deliver.
544  *raDstAccount, // --> Account to deliver to.
545  *raSrcAccount, // --> Account sending from.
546  ps, // --> Path set.
547  app_.logs(),
548  &rcInput);
549 
550  if (! convert_all_ &&
551  ! fullLiquidityPath.empty() &&
552  (rc.result() == terNO_LINE || rc.result() == tecPATH_PARTIAL))
553  {
554  JLOG(m_journal.debug()) << iIdentifier
555  << " Trying with an extra path element";
556 
557  ps.push_back(fullLiquidityPath);
558  sandbox = std::make_unique<PaymentSandbox>
559  (&*cache->getLedger(), tapNONE);
561  *sandbox,
562  saMaxAmount, // --> Amount to send is unlimited
563  // to get an estimate.
564  dst_amount, // --> Amount to deliver.
565  *raDstAccount, // --> Account to deliver to.
566  *raSrcAccount, // --> Account sending from.
567  ps, // --> Path set.
568  app_.logs());
569 
570  if (rc.result() != tesSUCCESS)
571  {
572  JLOG(m_journal.warn()) << iIdentifier
573  << " Failed with covering path "
574  << transHuman(rc.result());
575  }
576  else
577  {
578  JLOG(m_journal.debug()) << iIdentifier
579  << " Extra path element gives "
580  << transHuman(rc.result());
581  }
582  }
583 
584  if (rc.result () == tesSUCCESS)
585  {
586  Json::Value jvEntry (Json::objectValue);
587  rc.actualAmountIn.setIssuer (sourceAccount);
588  jvEntry[jss::source_amount] =
589  rc.actualAmountIn.getJson (JsonOptions::none);
590  jvEntry[jss::paths_computed] = ps.getJson(JsonOptions::none);
591 
592  if (convert_all_)
593  jvEntry[jss::destination_amount] =
594  rc.actualAmountOut.getJson(JsonOptions::none);
595 
596  if (hasCompletion ())
597  {
598  // Old ripple_path_find API requires this
599  jvEntry[jss::paths_canonical] = Json::arrayValue;
600  }
601 
602  jvArray.append (jvEntry);
603  }
604  else
605  {
606  JLOG(m_journal.debug()) << iIdentifier << " rippleCalc returns "
607  << transHuman(rc.result());
608  }
609  }
610 
611  /* The resource fee is based on the number of source currencies used.
612  The minimum cost is 50 and the maximum is 400. The cost increases
613  after four source currencies, 50 - (4 * 4) = 34.
614  */
615  int const size = sourceCurrencies.size();
616  consumer_.charge({boost::algorithm::clamp(size * size + 34, 50, 400),
617  "path update"});
618  return true;
619 }
620 
622  std::shared_ptr<RippleLineCache> const& cache, bool fast)
623 {
624  using namespace std::chrono;
625  JLOG(m_journal.debug()) << iIdentifier
626  << " update " << (fast ? "fast" : "normal");
627 
628  {
629  std::lock_guard sl (mLock);
630 
631  if (!isValid (cache))
632  return jvStatus;
633  }
634 
635  Json::Value newStatus = Json::objectValue;
636 
637  if (hasCompletion ())
638  {
639  // Old ripple_path_find API gives destination_currencies
640  auto& destCurrencies = (newStatus[jss::destination_currencies] = Json::arrayValue);
641  auto usCurrencies = accountDestCurrencies (*raDstAccount, cache, true);
642  for (auto const& c : usCurrencies)
643  destCurrencies.append (to_string (c));
644  }
645 
646  newStatus[jss::source_account] = app_.accountIDCache().toBase58(*raSrcAccount);
647  newStatus[jss::destination_account] = app_.accountIDCache().toBase58(*raDstAccount);
648  newStatus[jss::destination_amount] =
650  newStatus[jss::full_reply] = ! fast;
651 
652  if (jvId)
653  newStatus[jss::id] = jvId;
654 
655  bool loaded = app_.getFeeTrack().isLoadedLocal();
656 
657  if (iLevel == 0)
658  {
659  // first pass
660  if (loaded || fast)
662  else
664  }
665  else if ((iLevel == app_.config().PATH_SEARCH_FAST) && !fast)
666  {
667  // leaving fast pathfinding
669  if (loaded && (iLevel > app_.config().PATH_SEARCH_FAST))
670  --iLevel;
671  }
672  else if (bLastSuccess)
673  {
674  // decrement, if possible
675  if (iLevel > app_.config().PATH_SEARCH ||
676  (loaded && (iLevel > app_.config().PATH_SEARCH_FAST)))
677  --iLevel;
678  }
679  else
680  {
681  // adjust as needed
682  if (!loaded && (iLevel < app_.config().PATH_SEARCH_MAX))
683  ++iLevel;
684  if (loaded && (iLevel > app_.config().PATH_SEARCH_FAST))
685  --iLevel;
686  }
687 
688  JLOG(m_journal.debug()) << iIdentifier
689  << " processing at level " << iLevel;
690 
691  Json::Value jvArray = Json::arrayValue;
692  if (findPaths(cache, iLevel, jvArray))
693  {
694  bLastSuccess = jvArray.size() != 0;
695  newStatus[jss::alternatives] = std::move (jvArray);
696  }
697  else
698  {
699  bLastSuccess = false;
700  newStatus = rpcError(rpcINTERNAL);
701  }
702 
703  if (fast && quick_reply_ == steady_clock::time_point{})
704  {
705  quick_reply_ = steady_clock::now();
706  mOwner.reportFast(duration_cast<milliseconds>(quick_reply_ - created_));
707  }
708  else if (! fast && full_reply_ == steady_clock::time_point{})
709  {
710  full_reply_ = steady_clock::now();
711  mOwner.reportFull(duration_cast<milliseconds>(full_reply_ - created_));
712  }
713 
714  {
716  jvStatus = newStatus;
717  }
718 
719  return newStatus;
720 }
721 
723 {
724  return wpSubscriber.lock ();
725 }
726 
727 } // ripple
ripple::PathRequest::doClose
Json::Value doClose(Json::Value const &)
Definition: PathRequest.cpp:443
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:123
ripple::Application
Definition: Application.h:85
ripple::systemCurrencyCode
static std::string const & systemCurrencyCode()
Definition: SystemParameters.h:57
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:67
ripple::amountFromJsonNoThrow
bool amountFromJsonNoThrow(STAmount &result, Json::Value const &jvSource)
Definition: STAmount.cpp:911
ripple::rpcDST_AMT_MALFORMED
@ rpcDST_AMT_MALFORMED
Definition: ErrorCodes.h:107
std::string
STL class.
std::shared_ptr< InfoSub >
ripple::PathRequest::mContext
std::map< Issue, STPathSet > mContext
Definition: PathRequest.h:142
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:153
ripple::base_uint::isNonZero
bool isNonZero() const
Definition: base_uint.h:430
ripple::PathRequest::mLastIndex
LedgerIndex mLastIndex
Definition: PathRequest.h:147
ripple::terNO_LINE
@ terNO_LINE
Definition: TER.h:197
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:44
ripple::rpcSRC_ACT_NOT_FOUND
@ rpcSRC_ACT_NOT_FOUND
Definition: ErrorCodes.h:123
std::pair
ripple::PathRequest::saDstAmount
STAmount saDstAmount
Definition: PathRequest.h:138
ripple::accountDestCurrencies
hash_set< Currency > accountDestCurrencies(AccountID const &account, std::shared_ptr< RippleLineCache > const &lrCache, bool includeXRP)
Definition: AccountCurrencies.cpp:62
ripple::STAmount::getJson
Json::Value getJson(JsonOptions) const override
Definition: STAmount.cpp:582
ripple::PathRequest::raDstAccount
boost::optional< AccountID > raDstAccount
Definition: PathRequest.h:137
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:133
ripple::PathRequest::convert_all_
bool convert_all_
Definition: PathRequest.h:144
beast::Journal::warn
Stream warn() const
Definition: Journal.h:302
std::lock_guard
STL class.
tuple
ripple::PathRequest::full_reply_
std::chrono::steady_clock::time_point full_reply_
Definition: PathRequest.h:157
ripple::PathRequest::mIndexLock
std::recursive_mutex mIndexLock
Definition: PathRequest.h:146
std::function
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:41
ripple::PathRequest::consumer_
Resource::Consumer & consumer_
Definition: PathRequest.h:130
ripple::tapNONE
@ tapNONE
Definition: ApplyView.h:33
ripple::Application::accountIDCache
virtual AccountIDCache const & accountIDCache() const =0
ripple::Config::PATH_SEARCH_MAX
int PATH_SEARCH_MAX
Definition: Config.h:155
ripple::Application::getFeeTrack
virtual LoadFeeTrack & getFeeTrack()=0
ripple::PathRequest::quick_reply_
std::chrono::steady_clock::time_point quick_reply_
Definition: PathRequest.h:156
ripple::base_uint< 160, detail::CurrencyTag >
ripple::LoadFeeTrack::isLoadedLocal
bool isLoadedLocal() const
Definition: LoadFeeTrack.h:113
ripple::STAmount::getFullText
std::string getFullText() const override
Definition: STAmount.cpp:469
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:907
ripple::base_uint::isZero
bool isZero() const
Definition: base_uint.h:429
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:45
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:159
ripple::PathRequest::sciSourceCurrencies
std::set< Issue > sciSourceCurrencies
Definition: PathRequest.h:141
ripple::PathRequest::~PathRequest
~PathRequest()
Definition: PathRequest.cpp:87
ripple::keylet::account
static const account_t account
Definition: Indexes.h:116
ripple::rpcSRC_ACT_MISSING
@ rpcSRC_ACT_MISSING
Definition: ErrorCodes.h:122
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:74
ripple::JsonOptions::none
@ none
ripple::Application::config
virtual Config & config()=0
ripple::PathRequest::getSubscriber
InfoSub::pointer getSubscriber()
Definition: PathRequest.cpp:722
ripple::rpcACT_NOT_FOUND
@ rpcACT_NOT_FOUND
Definition: ErrorCodes.h:71
std::to_string
T to_string(T... args)
ripple::PathRequest::bLastSuccess
bool bLastSuccess
Definition: PathRequest.h:151
ripple::rpcSRC_ISR_MALFORMED
@ rpcSRC_ISR_MALFORMED
Definition: ErrorCodes.h:126
ripple::STAmount
Definition: STAmount.h:42
ripple::xrpAccount
AccountID const & xrpAccount()
Compute AccountID from public key.
Definition: AccountID.cpp:149
beast::Journal::info
Stream info() const
Definition: Journal.h:297
Json::Value::size
UInt size() const
Number of values in array or object.
Definition: json_value.cpp:720
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:478
ripple::PathRequest::app_
Application & app_
Definition: PathRequest.h:121
ripple::isXRP
bool isXRP(AccountID const &c)
Definition: AccountID.h:121
Json::Value::isMember
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:961
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:60
std::uint32_t
ripple::tecPATH_PARTIAL
@ tecPATH_PARTIAL
Definition: TER.h:247
ripple::rpcDST_ACT_MALFORMED
@ rpcDST_ACT_MALFORMED
Definition: ErrorCodes.h:104
ripple::PathRequest::isValid
bool isValid(std::shared_ptr< RippleLineCache > const &crCache)
Definition: PathRequest.cpp:166
ripple::rpcError
Json::Value rpcError(int iError, Json::Value jvResult)
Definition: RPCErr.cpp:28
ripple::PathRequest::fCompletion
std::function< void(void)> fCompletion
Definition: PathRequest.h:129
ripple::transHuman
std::string transHuman(TER code)
Definition: TER.cpp:191
ripple::STAmount::getCurrency
Currency const & getCurrency() const
Definition: STAmount.h:159
ripple::lsfRequireDestTag
@ lsfRequireDestTag
Definition: LedgerFormats.h:133
ripple::STAmount::getIssuer
AccountID const & getIssuer() const
Definition: STAmount.h:160
ripple::PathRequest::updateComplete
void updateComplete()
Definition: PathRequest.cpp:152
ripple::rpcINTERNAL
@ rpcINTERNAL
Definition: ErrorCodes.h:131
Json::Value::isArray
bool isArray() const
Definition: json_value.cpp:1056
ripple::PathRequest::doCreate
std::pair< bool, Json::Value > doCreate(std::shared_ptr< RippleLineCache > const &, Json::Value const &)
Definition: PathRequest.cpp:240
ripple::rpcSRC_ACT_MALFORMED
@ rpcSRC_ACT_MALFORMED
Definition: ErrorCodes.h:121
ripple::STAmount::native
bool native() const noexcept
Definition: STAmount.h:153
ripple::STPath::empty
bool empty() const
Definition: STPathSet.h:220
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:82
ripple::Config::PATH_SEARCH_FAST
int PATH_SEARCH_FAST
Definition: Config.h:154
ripple::PathRequest::mLock
std::recursive_mutex mLock
Definition: PathRequest.h:124
ripple::PathRequest::created_
const std::chrono::steady_clock::time_point created_
Definition: PathRequest.h:155
ripple::PathRequest::doUpdate
Json::Value doUpdate(std::shared_ptr< RippleLineCache > const &, bool fast)
Definition: PathRequest.cpp:621
ripple::PathRequest::wpSubscriber
std::weak_ptr< InfoSub > wpSubscriber
Definition: PathRequest.h:128
ripple::PathRequest::doStatus
Json::Value doStatus(Json::Value const &)
Definition: PathRequest.cpp:451
ripple::STAmount::issue
Issue const & issue() const
Definition: STAmount.h:156
ripple::PathRequest::iIdentifier
int iIdentifier
Definition: PathRequest.h:153
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:77
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:87
ripple::path::RippleCalc::Input::partialPaymentAllowed
bool partialPaymentAllowed
Definition: RippleCalc.h:50
ripple::rpcDST_AMT_MISSING
@ rpcDST_AMT_MISSING
Definition: ErrorCodes.h:108
beast::Journal::debug
Stream debug() const
Definition: Journal.h:292
ripple::PathRequest::saSendMax
boost::optional< STAmount > saSendMax
Definition: PathRequest.h:139
ripple::lsfDisallowXRP
@ lsfDisallowXRP
Definition: LedgerFormats.h:135
ripple::accountSourceCurrencies
hash_set< Currency > accountSourceCurrencies(AccountID const &account, std::shared_ptr< RippleLineCache > const &lrCache, bool includeXRP)
Definition: AccountCurrencies.cpp:24
ripple::rpcSRC_CUR_MALFORMED
@ rpcSRC_CUR_MALFORMED
Definition: ErrorCodes.h:125
ripple::PathRequests
Definition: PathRequests.h:33
ripple::PathRequest::hasCompletion
bool hasCompletion()
Definition: PathRequest.cpp:147
ripple::rpcDST_ACT_MISSING
@ rpcDST_ACT_MISSING
Definition: ErrorCodes.h:105
ripple::STAmount::cMaxOffset
static const int cMaxOffset
Definition: STAmount.h:61
ripple::PathRequest::jvId
Json::Value jvId
Definition: PathRequest.h:132
ripple::Resource::Consumer::charge
Disposition charge(Charge const &fee)
Apply a load charge to the consumer.
Definition: Consumer.cpp:98
ripple::PathRequest::mOwner
PathRequests & mOwner
Definition: PathRequest.h:126
std::unique_ptr
STL class.
ripple::STPath
Definition: STPathSet.h:205
ripple::PathRequest::needsUpdate
bool needsUpdate(bool newOnly, LedgerIndex index)
Definition: PathRequest.cpp:122
std::unordered_map
STL class.
ripple::PathRequest::m_journal
beast::Journal m_journal
Definition: PathRequest.h:122
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:219
ripple::PathRequest::parseJson
int parseJson(Json::Value const &)
Definition: PathRequest.cpp:271
ripple::STAmount::cMaxValue
static const std::uint64_t cMaxValue
Definition: STAmount.h:65
ripple::PathRequest::iLevel
int iLevel
Definition: PathRequest.h:150
ripple::PathRequest::mInProgress
bool mInProgress
Definition: PathRequest.h:148
ripple::PathRequest::raSrcAccount
boost::optional< AccountID > raSrcAccount
Definition: PathRequest.h:136
Json::Value
Represents a JSON value.
Definition: json_value.h:141
ripple::rpcSENDMAX_MALFORMED
@ rpcSENDMAX_MALFORMED
Definition: ErrorCodes.h:120
ripple::AccountIDCache::toBase58
std::string toBase58(AccountID const &) const
Return ripple::toBase58 for the AccountID.
Definition: AccountID.cpp:199
ripple::to_issuer
bool to_issuer(AccountID &, std::string const &)
Convert hex or base58 string to AccountID.
Definition: AccountID.cpp:163
std::chrono