1#include <xrpld/app/main/Application.h> 
    2#include <xrpld/app/misc/LoadFeeTrack.h> 
    3#include <xrpld/app/misc/NetworkOPs.h> 
    4#include <xrpld/app/paths/AccountCurrencies.h> 
    5#include <xrpld/app/paths/PathRequest.h> 
    6#include <xrpld/app/paths/PathRequests.h> 
    7#include <xrpld/app/paths/RippleCalc.h> 
    8#include <xrpld/app/paths/detail/PathfinderUtils.h> 
    9#include <xrpld/core/Config.h> 
   10#include <xrpld/rpc/detail/Tuning.h> 
   12#include <xrpl/basics/Log.h> 
   13#include <xrpl/beast/core/LexicalCast.h> 
   14#include <xrpl/protocol/ErrorCodes.h> 
   15#include <xrpl/protocol/RPCErr.h> 
   16#include <xrpl/protocol/UintTypes.h> 
   32    , wpSubscriber(subscriber)
 
   33    , consumer_(subscriber->getConsumer())
 
   34    , jvStatus(
Json::objectValue)
 
   40    , created_(
std::chrono::steady_clock::now())
 
 
   55    , fCompletion(completion)
 
   57    , jvStatus(
Json::objectValue)
 
   63    , created_(
std::chrono::steady_clock::now())
 
 
   91        << 
iIdentifier << 
" complete:" << fast << full << 
" total:" 
   92        << duration_cast<milliseconds>(steady_clock::now() - 
created_).count()
 
 
  143        mInProgress, 
"ripple::PathRequest::updateComplete : in progress");
 
 
  166    auto const& lrLedger = crCache->getLedger();
 
  204        for (
auto const& currency : usDestCurrID)
 
  211    jvStatus[jss::ledger_index] = lrLedger->seq();
 
 
  257    if (!jvParams.
isMember(jss::source_account))
 
  260        return PFR_PJ_INVALID;
 
  263    if (!jvParams.
isMember(jss::destination_account))
 
  266        return PFR_PJ_INVALID;
 
  269    if (!jvParams.
isMember(jss::destination_amount))
 
  272        return PFR_PJ_INVALID;
 
  276        parseBase58<AccountID>(jvParams[jss::source_account].asString());
 
  280        return PFR_PJ_INVALID;
 
  284        parseBase58<AccountID>(jvParams[jss::destination_account].asString());
 
  288        return PFR_PJ_INVALID;
 
  294        return PFR_PJ_INVALID;
 
  305        return PFR_PJ_INVALID;
 
  308    if (jvParams.
isMember(jss::send_max))
 
  314            return PFR_PJ_INVALID;
 
  326            return PFR_PJ_INVALID;
 
  330    if (jvParams.
isMember(jss::source_currencies))
 
  332        Json::Value const& jvSrcCurrencies = jvParams[jss::source_currencies];
 
  333        if (!jvSrcCurrencies.
isArray() || jvSrcCurrencies.
size() == 0 ||
 
  337            return PFR_PJ_INVALID;
 
  342        for (
auto const& c : jvSrcCurrencies)
 
  346            if (!c.isObject() || !c.isMember(jss::currency) ||
 
  347                !c[jss::currency].isString() ||
 
  348                !
to_currency(srcCurrencyID, c[jss::currency].asString()))
 
  351                return PFR_PJ_INVALID;
 
  356            if (c.isMember(jss::issuer) &&
 
  357                (!c[jss::issuer].isString() ||
 
  358                 !
to_issuer(srcIssuerID, c[jss::issuer].asString())))
 
  361                return PFR_PJ_INVALID;
 
  364            if (srcCurrencyID.
isZero())
 
  369                    return PFR_PJ_INVALID;
 
  372            else if (srcIssuerID.
isZero())
 
  380                if (srcCurrencyID == 
saSendMax->getCurrency())
 
  389                        return PFR_PJ_INVALID;
 
  397                            {srcCurrencyID, srcIssuerID});
 
  402                            {srcCurrencyID, 
saSendMax->getIssuer()});
 
  419        jvId = jvParams[jss::id];
 
  424        if (!jvParams[jss::domain].isString() ||
 
  428            return PFR_PJ_INVALID;
 
  436    return PFR_PJ_NOCHANGE;
 
 
  452    jvStatus[jss::status] = jss::success;
 
 
  471    auto i = currency_map.find(currency);
 
  472    if (i != currency_map.end())
 
  484    if (pathfinder->findPaths(level, continueCallback))
 
  485        pathfinder->computePathRanks(
max_paths_, continueCallback);
 
  488    return currency_map[currency] = std::move(pathfinder);
 
 
  499    if (sourceCurrencies.empty() && 
saSendMax)
 
  501        sourceCurrencies.insert(
saSendMax->issue());
 
  503    if (sourceCurrencies.empty())
 
  507        for (
auto const& c : currencies)
 
  513                sourceCurrencies.insert(
 
  521    for (
auto const& issue : sourceCurrencies)
 
  523        if (continueCallback && !continueCallback())
 
  543        auto ps = pathfinder->getBestPaths(
 
  551        auto const& sourceAccount = [&] {
 
  552            if (!
isXRP(issue.account))
 
  553                return issue.account;
 
  555            if (
isXRP(issue.currency))
 
  565            << 
iIdentifier << 
" Paths found, calling rippleCalc";
 
  588                << 
iIdentifier << 
" Trying with an extra path element";
 
  590            ps.push_back(fullLiquidityPath);
 
  621            rc.actualAmountIn.setIssuer(sourceAccount);
 
  622            jvEntry[jss::source_amount] =
 
  627                jvEntry[jss::destination_amount] =
 
  649    int const size = sourceCurrencies.size();
 
 
  662        << 
iIdentifier << 
" update " << (fast ? 
"fast" : 
"normal");
 
  676        auto& destCurrencies =
 
  679        for (
auto const& c : usCurrencies)
 
  686    newStatus[jss::full_reply] = !fast;
 
  689        newStatus[jss::id] = 
jvId;
 
  730        newStatus[jss::alternatives] = std::move(jvArray);
 
  743    else if (!fast && 
full_reply_ == steady_clock::time_point{})
 
  755        << 
iIdentifier << 
" update finished " << (fast ? 
"fast" : 
"normal");
 
 
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
 
virtual LoadFeeTrack & getFeeTrack()=0
 
A currency issued by an account.
 
bool isLoadedLocal() const
 
std::optional< STAmount > saSendMax
 
std::function< void(void)> fCompletion
 
static unsigned int const max_paths_
 
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.
 
Json::Value doClose() override
 
std::weak_ptr< InfoSub > wpSubscriber
 
Json::Value doStatus(Json::Value const &) override
 
std::set< Issue > sciSourceCurrencies
 
int parseJson(Json::Value const &)
 
bool needsUpdate(bool newOnly, LedgerIndex index)
 
PathRequest(Application &app, std::shared_ptr< InfoSub > const &subscriber, int id, PathRequests &, beast::Journal journal)
 
std::recursive_mutex mLock
 
std::recursive_mutex mIndexLock
 
Resource::Consumer & consumer_
 
std::optional< AccountID > raSrcAccount
 
InfoSub::pointer getSubscriber() const
 
std::optional< uint256 > domain
 
Json::Value doUpdate(std::shared_ptr< RippleLineCache > const &, bool fast, std::function< bool(void)> const &continueCallback={})
 
std::chrono::steady_clock::time_point full_reply_
 
std::pair< bool, Json::Value > doCreate(std::shared_ptr< RippleLineCache > const &, Json::Value const &)
 
std::chrono::steady_clock::time_point quick_reply_
 
std::map< Issue, STPathSet > mContext
 
std::optional< AccountID > raDstAccount
 
std::chrono::steady_clock::time_point const created_
 
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 &)
 
bool isValid(std::shared_ptr< RippleLineCache > const &crCache)
 
void reportFast(std::chrono::milliseconds ms)
 
void reportFull(std::chrono::milliseconds ms)
 
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
 
Currency const & getCurrency() const
 
AccountID const & getIssuer() const
 
Issue const & issue() const
 
std::string getFullText() const override
 
bool native() const noexcept
 
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, Logs &l, 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_src_cur
Maximum number of source currencies allowed in a path find request.
 
static int constexpr max_auto_src_cur
Maximum number of auto source currencies 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.
 
std::string transHuman(TER code)
 
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
 
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
 
STAmount convertAmount(STAmount const &amt, bool all)
 
bool isXRP(AccountID const &c)
 
AccountID const & xrpAccount()
Compute AccountID from public key.
 
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)
 
hash_set< Currency > accountSourceCurrencies(AccountID const &account, std::shared_ptr< RippleLineCache > const &lrCache, bool includeXRP)
 
static std::string const & systemCurrencyCode()
 
Json::Value rpcError(int iError)
 
bool amountFromJsonNoThrow(STAmount &result, Json::Value const &jvSource)
 
std::string to_string(base_uint< Bits, Tag > const &a)
 
bool to_currency(Currency &, std::string const &)
Tries to convert a string to a Currency, returns true on success.