mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-02 16:35:49 +00:00
Fix path finding for XRP dst and sendmax:
* Fix bug where incorrect max amount was set for XRP * Fix bug where incorrect source currencies were set when XRP was the dst and a sendmax amount was set
This commit is contained in:
@@ -24,15 +24,18 @@
|
||||
#include <ripple/app/paths/PathRequest.h>
|
||||
#include <ripple/app/paths/PathRequests.h>
|
||||
#include <ripple/app/paths/RippleCalc.h>
|
||||
#include <ripple/app/paths/impl/PathfinderUtils.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/beast/core/LexicalCast.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/net/RPCErr.h>
|
||||
#include <ripple/protocol/ErrorCodes.h>
|
||||
#include <ripple/protocol/UintTypes.h>
|
||||
|
||||
#include <ripple/rpc/impl/Tuning.h>
|
||||
#include <boost/algorithm/clamp.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace ripple {
|
||||
@@ -489,6 +492,10 @@ PathRequest::findPaths(
|
||||
Json::Value& jvArray)
|
||||
{
|
||||
auto sourceCurrencies = sciSourceCurrencies;
|
||||
if (sourceCurrencies.empty() && saSendMax)
|
||||
{
|
||||
sourceCurrencies.insert(saSendMax->issue());
|
||||
}
|
||||
if (sourceCurrencies.empty())
|
||||
{
|
||||
auto currencies = accountSourceCurrencies(*raSrcAccount, cache, true);
|
||||
@@ -505,10 +512,7 @@ PathRequest::findPaths(
|
||||
}
|
||||
}
|
||||
|
||||
auto const dst_amount = convert_all_
|
||||
? STAmount(
|
||||
saDstAmount.issue(), STAmount::cMaxValue, STAmount::cMaxOffset)
|
||||
: saDstAmount;
|
||||
auto const dst_amount = convertAmount(saDstAmount, convert_all_);
|
||||
hash_map<Currency, std::unique_ptr<Pathfinder>> currency_map;
|
||||
for (auto const& issue : sourceCurrencies)
|
||||
{
|
||||
|
||||
@@ -23,11 +23,13 @@
|
||||
#include <ripple/app/paths/RippleCalc.h>
|
||||
#include <ripple/app/paths/RippleLineCache.h>
|
||||
#include <ripple/app/paths/Tuning.h>
|
||||
#include <ripple/app/paths/impl/PathfinderUtils.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/core/JobQueue.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
#include <ripple/ledger/PaymentSandbox.h>
|
||||
|
||||
#include <tuple>
|
||||
|
||||
/*
|
||||
@@ -143,6 +145,13 @@ pathTypeToString(Pathfinder::PathType const& type)
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Return the smallest amount of useful liquidity for a given amount, and the
|
||||
// total number of paths we have to evaluate.
|
||||
STAmount
|
||||
smallestUsefulAmount(STAmount const& amount, int maxPaths)
|
||||
{
|
||||
return divide(amount, STAmount(maxPaths + 2), amount.issue());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Pathfinder::Pathfinder(
|
||||
@@ -169,12 +178,7 @@ Pathfinder::Pathfinder(
|
||||
1u,
|
||||
0,
|
||||
true)))
|
||||
, convert_all_(
|
||||
mDstAmount ==
|
||||
STAmount(
|
||||
mDstAmount.issue(),
|
||||
STAmount::cMaxValue,
|
||||
STAmount::cMaxOffset))
|
||||
, convert_all_(convertAllCheck(mDstAmount))
|
||||
, mLedger(cache->getLedger())
|
||||
, mRLCache(cache)
|
||||
, app_(app)
|
||||
@@ -395,25 +399,10 @@ Pathfinder::getPathLiquidity(
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Return the smallest amount of useful liquidity for a given amount, and the
|
||||
// total number of paths we have to evaluate.
|
||||
STAmount
|
||||
smallestUsefulAmount(STAmount const& amount, int maxPaths)
|
||||
{
|
||||
return divide(amount, STAmount(maxPaths + 2), amount.issue());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void
|
||||
Pathfinder::computePathRanks(int maxPaths)
|
||||
{
|
||||
mRemainingAmount = convert_all_
|
||||
? STAmount(
|
||||
mDstAmount.issue(), STAmount::cMaxValue, STAmount::cMaxOffset)
|
||||
: mDstAmount;
|
||||
mRemainingAmount = convertAmount(mDstAmount, convert_all_);
|
||||
|
||||
// Must subtract liquidity in default path from remaining amount.
|
||||
try
|
||||
@@ -496,19 +485,17 @@ Pathfinder::rankPaths(
|
||||
rankedPaths.clear();
|
||||
rankedPaths.reserve(paths.size());
|
||||
|
||||
STAmount saMinDstAmount;
|
||||
if (convert_all_)
|
||||
{
|
||||
auto const saMinDstAmount = [&]() -> STAmount {
|
||||
if (!convert_all_)
|
||||
{
|
||||
// Ignore paths that move only very small amounts.
|
||||
return smallestUsefulAmount(mDstAmount, maxPaths);
|
||||
}
|
||||
|
||||
// On convert_all_ partialPaymentAllowed will be set to true
|
||||
// and requiring a huge amount will find the highest liquidity.
|
||||
saMinDstAmount = STAmount(
|
||||
mDstAmount.issue(), STAmount::cMaxValue, STAmount::cMaxOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ignore paths that move only very small amounts.
|
||||
saMinDstAmount = smallestUsefulAmount(mDstAmount, maxPaths);
|
||||
}
|
||||
return largestAmount(mDstAmount);
|
||||
}();
|
||||
|
||||
for (int i = 0; i < paths.size(); ++i)
|
||||
{
|
||||
|
||||
53
src/ripple/app/paths/impl/PathfinderUtils.h
Normal file
53
src/ripple/app/paths/impl/PathfinderUtils.h
Normal file
@@ -0,0 +1,53 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2020 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_PATH_IMPL_PATHFINDERUTILS_H_INCLUDED
|
||||
#define RIPPLE_PATH_IMPL_PATHFINDERUTILS_H_INCLUDED
|
||||
|
||||
#include <ripple/protocol/STAmount.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
inline STAmount
|
||||
largestAmount(STAmount const& amt)
|
||||
{
|
||||
if (amt.native())
|
||||
return INITIAL_XRP;
|
||||
|
||||
return STAmount(amt.issue(), STAmount::cMaxValue, STAmount::cMaxOffset);
|
||||
}
|
||||
|
||||
inline STAmount
|
||||
convertAmount(STAmount const& amt, bool all)
|
||||
{
|
||||
if (!all)
|
||||
return amt;
|
||||
|
||||
return largestAmount(amt);
|
||||
};
|
||||
|
||||
inline bool
|
||||
convertAllCheck(STAmount const& a)
|
||||
{
|
||||
return a == largestAmount(a);
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
@@ -1303,6 +1303,65 @@ public:
|
||||
BEAST_EXPECT(same(st, stpath(M1, G2), stpath(IPE(G2["HKD"]), G2)));
|
||||
}
|
||||
|
||||
void
|
||||
receive_max()
|
||||
{
|
||||
testcase("Receive max");
|
||||
using namespace jtx;
|
||||
auto const alice = Account("alice");
|
||||
auto const bob = Account("bob");
|
||||
auto const charlie = Account("charlie");
|
||||
auto const gw = Account("gw");
|
||||
auto const USD = gw["USD"];
|
||||
{
|
||||
// XRP -> IOU receive max
|
||||
Env env(*this);
|
||||
env.fund(XRP(10000), alice, bob, charlie, gw);
|
||||
env.close();
|
||||
env.trust(USD(100), alice, bob, charlie);
|
||||
env.close();
|
||||
env(pay(gw, charlie, USD(10)));
|
||||
env.close();
|
||||
env(offer(charlie, XRP(10), USD(10)));
|
||||
env.close();
|
||||
auto [st, sa, da] =
|
||||
find_paths(env, alice, bob, USD(-1), XRP(100).value());
|
||||
BEAST_EXPECT(sa == XRP(10));
|
||||
BEAST_EXPECT(equal(da, USD(10)));
|
||||
if (BEAST_EXPECT(st.size() == 1 && st[0].size() == 1))
|
||||
{
|
||||
auto const& pathElem = st[0][0];
|
||||
BEAST_EXPECT(
|
||||
pathElem.isOffer() && pathElem.getIssuerID() == gw.id() &&
|
||||
pathElem.getCurrency() == USD.currency);
|
||||
}
|
||||
}
|
||||
{
|
||||
// IOU -> XRP receive max
|
||||
Env env(*this);
|
||||
env.fund(XRP(10000), alice, bob, charlie, gw);
|
||||
env.close();
|
||||
env.trust(USD(100), alice, bob, charlie);
|
||||
env.close();
|
||||
env(pay(gw, alice, USD(10)));
|
||||
env.close();
|
||||
env(offer(charlie, USD(10), XRP(10)));
|
||||
env.close();
|
||||
auto [st, sa, da] =
|
||||
find_paths(env, alice, bob, drops(-1), USD(100).value());
|
||||
BEAST_EXPECT(sa == USD(10));
|
||||
BEAST_EXPECT(equal(da, XRP(10)));
|
||||
if (BEAST_EXPECT(st.size() == 1 && st[0].size() == 1))
|
||||
{
|
||||
auto const& pathElem = st[0][0];
|
||||
BEAST_EXPECT(
|
||||
pathElem.isOffer() &&
|
||||
pathElem.getIssuerID() == xrpAccount() &&
|
||||
pathElem.getCurrency() == xrpCurrency());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
@@ -1325,6 +1384,7 @@ public:
|
||||
trust_auto_clear_trust_normal_clear();
|
||||
trust_auto_clear_trust_auto_clear();
|
||||
xrp_to_xrp();
|
||||
receive_max();
|
||||
|
||||
// The following path_find_NN tests are data driven tests
|
||||
// that were originally implemented in js/coffee and migrated
|
||||
|
||||
Reference in New Issue
Block a user