1#include <xrpld/app/main/Application.h>
2#include <xrpld/core/Config.h>
3#include <xrpld/rpc/detail/AccountCurrencies.h>
4#include <xrpld/rpc/detail/PathRequest.h>
5#include <xrpld/rpc/detail/PathRequestManager.h>
6#include <xrpld/rpc/detail/PathfinderUtils.h>
7#include <xrpld/rpc/detail/Tuning.h>
9#include <xrpl/beast/core/LexicalCast.h>
10#include <xrpl/protocol/ErrorCodes.h>
11#include <xrpl/protocol/RPCErr.h>
12#include <xrpl/protocol/UintTypes.h>
13#include <xrpl/server/LoadFeeTrack.h>
14#include <xrpl/server/NetworkOPs.h>
15#include <xrpl/tx/paths/RippleCalc.h>
31 , wpSubscriber(subscriber)
32 , consumer_(subscriber->getConsumer())
33 , jvStatus(
Json::objectValue)
39 , created_(
std::chrono::steady_clock::now())
54 , fCompletion(completion)
56 , jvStatus(
Json::objectValue)
62 , created_(
std::chrono::steady_clock::now())
88 <<
" total:" << duration_cast<milliseconds>(steady_clock::now() -
created_).count()
138 XRPL_ASSERT(
mInProgress,
"xrpl::PathRequest::updateComplete : in progress");
161 auto const& lrLedger = crCache->getLedger();
193 bool const disallowXRP((sleDest->getFlags() & lsfDisallowXRP) != 0u);
197 for (
auto const& currency : usDestCurrID)
199 jvStatus[jss::destination_tag] = (sleDest->getFlags() & lsfRequireDestTag);
203 jvStatus[jss::ledger_index] = lrLedger->seq();
247 if (!jvParams.
isMember(jss::source_account))
250 return PFR_PJ_INVALID;
253 if (!jvParams.
isMember(jss::destination_account))
256 return PFR_PJ_INVALID;
259 if (!jvParams.
isMember(jss::destination_amount))
262 return PFR_PJ_INVALID;
265 raSrcAccount = parseBase58<AccountID>(jvParams[jss::source_account].asString());
269 return PFR_PJ_INVALID;
272 raDstAccount = parseBase58<AccountID>(jvParams[jss::destination_account].asString());
276 return PFR_PJ_INVALID;
282 return PFR_PJ_INVALID;
292 return PFR_PJ_INVALID;
295 if (jvParams.
isMember(jss::send_max))
301 return PFR_PJ_INVALID;
311 return PFR_PJ_INVALID;
315 if (jvParams.
isMember(jss::source_currencies))
317 Json::Value const& jvSrcCurrencies = jvParams[jss::source_currencies];
318 if (!jvSrcCurrencies.
isArray() || jvSrcCurrencies.
size() == 0 ||
322 return PFR_PJ_INVALID;
327 for (
auto const& c : jvSrcCurrencies)
331 if (!c.isObject() || !c.isMember(jss::currency) || !c[jss::currency].isString() ||
332 !
to_currency(srcCurrencyID, c[jss::currency].asString()))
335 return PFR_PJ_INVALID;
340 if (c.isMember(jss::issuer) &&
341 (!c[jss::issuer].isString() || !
to_issuer(srcIssuerID, c[jss::issuer].asString())))
344 return PFR_PJ_INVALID;
347 if (srcCurrencyID.
isZero())
352 return PFR_PJ_INVALID;
355 else if (srcIssuerID.
isZero())
363 if (srcCurrencyID ==
saSendMax->getCurrency())
371 return PFR_PJ_INVALID;
398 jvId = jvParams[jss::id];
403 if (!jvParams[jss::domain].isString() || !num.
parseHex(jvParams[jss::domain].
asString()))
406 return PFR_PJ_INVALID;
412 return PFR_PJ_NOCHANGE;
428 jvStatus[jss::status] = jss::success;
447 auto i = currency_map.find(currency);
448 if (i != currency_map.end())
460 if (pathfinder->findPaths(level, continueCallback))
462 pathfinder->computePathRanks(
max_paths_, continueCallback);
468 return currency_map[currency] = std::move(pathfinder);
479 if (sourceCurrencies.empty() &&
saSendMax)
481 sourceCurrencies.insert(
saSendMax->issue());
483 if (sourceCurrencies.empty())
487 for (
auto const& c : currencies)
500 for (
auto const& issue : sourceCurrencies)
502 if (continueCallback && !continueCallback())
508 getPathFinder(cache, currency_map, issue.currency, dst_amount, level, continueCallback);
516 auto ps = pathfinder->getBestPaths(
520 auto const& sourceAccount = [&] {
521 if (!
isXRP(issue.account))
522 return issue.account;
524 if (
isXRP(issue.currency))
556 ps.push_back(fullLiquidityPath);
584 rc.actualAmountIn.setIssuer(sourceAccount);
589 jvEntry[jss::destination_amount] = rc.actualAmountOut.getJson(
JsonOptions::none);
610 int const size = sourceCurrencies.size();
636 auto& destCurrencies = (newStatus[jss::destination_currencies] =
Json::arrayValue);
638 for (
auto const& c : usCurrencies)
645 newStatus[jss::full_reply] = !fast;
648 newStatus[jss::id] =
jvId;
693 newStatus[jss::alternatives] = std::move(jvArray);
706 else if (!fast &&
full_reply_ == steady_clock::time_point{})
Value & append(Value const &value)
Append value to array at the end.
UInt size() const
Number of values in array or object.
std::string asString() const
Returns the unquoted string value.
bool isMember(char const *key) const
Return true if the object has a member named key.
A generic endpoint for log messages.
virtual Config & config()=0
A currency issued by an account.
bool isLoadedLocal() const
void reportFull(std::chrono::milliseconds ms)
void reportFast(std::chrono::milliseconds ms)
Json::Value doUpdate(std::shared_ptr< RippleLineCache > const &, bool fast, std::function< bool(void)> const &continueCallback={})
std::optional< AccountID > raDstAccount
PathRequest(Application &app, std::shared_ptr< InfoSub > const &subscriber, int id, PathRequestManager &, beast::Journal journal)
Json::Value doClose() override
std::map< Issue, STPathSet > mContext
std::optional< uint256 > domain
Resource::Consumer & consumer_
std::optional< STAmount > saSendMax
int parseJson(Json::Value const &)
static unsigned int const max_paths_
std::chrono::steady_clock::time_point const created_
bool needsUpdate(bool newOnly, LedgerIndex index)
std::weak_ptr< InfoSub > wpSubscriber
InfoSub::pointer getSubscriber() const
std::recursive_mutex mIndexLock
Json::Value doStatus(Json::Value const &) override
std::pair< bool, Json::Value > doCreate(std::shared_ptr< RippleLineCache > const &, Json::Value const &)
PathRequestManager & mOwner
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.
std::chrono::steady_clock::time_point full_reply_
std::set< Issue > sciSourceCurrencies
bool isValid(std::shared_ptr< RippleLineCache > const &crCache)
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 &)
std::chrono::steady_clock::time_point quick_reply_
std::recursive_mutex mLock
std::function< void(void)> fCompletion
std::optional< AccountID > raSrcAccount
An endpoint that consumes resources.
Disposition charge(Charge const &fee, std::string const &context={})
Apply a load charge to the consumer.
Json::Value getJson(JsonOptions=JsonOptions::none) const override
std::string getFullText() const override
Issue const & issue() const
Currency const & getCurrency() const
bool native() const noexcept
AccountID const & getIssuer() const
virtual LoadFeeTrack & getFeeTrack()=0
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
static Output rippleCalculate(PaymentSandbox &view, STAmount const &saMaxAmountReq, STAmount const &saDstAmountReq, AccountID const &uDstAccountID, AccountID const &uSrcAccountID, STPathSet const &spsPaths, std::optional< uint256 > const &domainID, ServiceRegistry ®istry, Input const *const pInputs=nullptr)
JSON (JavaScript Object Notation).
@ arrayValue
array value (ordered list)
@ objectValue
object value (collection of name/value pairs).
static int constexpr max_auto_src_cur
Maximum number of auto source currencies in a path find request.
static int constexpr max_src_cur
Maximum number of source currencies allowed in a path find request.
TER valid(STTx const &tx, ReadView const &view, AccountID const &src, beast::Journal j)
Keylet account(AccountID const &id) noexcept
AccountID root.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
STAmount convertAmount(STAmount const &amt, bool all)
bool isXRP(AccountID const &c)
std::string to_string(base_uint< Bits, Tag > const &a)
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
std::string transHuman(TER code)
hash_set< Currency > accountSourceCurrencies(AccountID const &account, std::shared_ptr< RippleLineCache > const &lrCache, bool includeXRP)
bool amountFromJsonNoThrow(STAmount &result, Json::Value const &jvSource)
Json::Value rpcError(error_code_i iError)
bool to_issuer(AccountID &, std::string const &)
Convert hex or base58 string to AccountID.
hash_set< Currency > accountDestCurrencies(AccountID const &account, std::shared_ptr< RippleLineCache > const &lrCache, bool includeXRP)
bool isTesSuccess(TER x) noexcept
AccountID const & xrpAccount()
Compute AccountID from public key.
static std::string const & systemCurrencyCode()
bool to_currency(Currency &, std::string const &)
Tries to convert a string to a Currency, returns true on success.
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...