Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ba436a6
expand the pathing tables to look at different routes, as logic X->XR…
shortthefomo Mar 9, 2026
eb1cb7b
Merge branch 'develop' into pathing-fix-nonXRP-to-XRP
shortthefomo Mar 9, 2026
8e49884
resolve the cost ordering
shortthefomo Mar 9, 2026
c039a85
Merge branch 'pathing-fix-nonXRP-to-XRP' of https://github.com/shortt…
shortthefomo Mar 9, 2026
f360a98
remove unwanted copy error in comment and account for fullLiquidityPa…
shortthefomo Mar 9, 2026
a71924c
fix formatting complaints
shortthefomo Mar 10, 2026
f09a131
less hops better perfomance for simialr result.
shortthefomo Mar 11, 2026
05f1bea
remove duplicate and kept the shallower weigth as it was to far down …
shortthefomo Mar 11, 2026
5814b02
add tests for max_paths_ ceiling
shortthefomo Mar 11, 2026
ebe963f
address test issues
shortthefomo Mar 12, 2026
55906b4
Merge branch 'develop' into pathing-fix-nonXRP-to-XRP
shortthefomo Mar 25, 2026
90aa066
Merge branch 'develop' into pathing-fix-nonXRP-to-XRP
shortthefomo Mar 26, 2026
94bd7ae
upstream refactoring fix includes
shortthefomo Mar 26, 2026
cfef131
Merge branch 'develop' into pathing-fix-nonXRP-to-XRP
shortthefomo Mar 27, 2026
391fe2e
fix build errors due to upstream changes
shortthefomo Mar 27, 2026
4908468
Merge branch 'develop' into pathing-fix-nonXRP-to-XRP
shortthefomo Apr 1, 2026
8f6e818
expand the pathing tables to look at different routes, as logic X->XR…
shortthefomo Mar 9, 2026
c659fb8
resolve the cost ordering
shortthefomo Mar 9, 2026
b8e04e6
remove unwanted copy error in comment and account for fullLiquidityPa…
shortthefomo Mar 9, 2026
63d254e
fix formatting complaints
shortthefomo Mar 10, 2026
1db0241
less hops better perfomance for simialr result.
shortthefomo Mar 11, 2026
69e28bd
remove duplicate and kept the shallower weigth as it was to far down …
shortthefomo Mar 11, 2026
f8b675e
add tests for max_paths_ ceiling
shortthefomo Mar 11, 2026
01fb4cb
address test issues
shortthefomo Mar 12, 2026
9b399b4
upstream refactoring fix includes
shortthefomo Mar 26, 2026
630fa6b
fix build errors due to upstream changes
shortthefomo Mar 27, 2026
efb42e0
fix: rename RippleLineCache to AssetCache to match upstream
shortthefomo Apr 14, 2026
f19c2f7
Merge remote-tracking branch 'upstream/develop' into pathing-fix-rebuild
shortthefomo May 19, 2026
1c52832
refactor: Align identifier naming with develop
shortthefomo May 19, 2026
362775e
Merge remote-tracking branch 'upstream/develop' into pathing-fix-nonX…
shortthefomo May 19, 2026
ab5c1a1
merge develop into branch and fix up stream changes
shortthefomo Jun 3, 2026
68afe87
resolve conflict
shortthefomo Jun 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
297 changes: 297 additions & 0 deletions src/test/app/Path_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@
#include <test/jtx/trust.h>
#include <test/jtx/txflags.h>

#include <xrpld/rpc/detail/Pathfinder.h>
#include <xrpld/rpc/detail/AssetCache.h>
#include <xrpld/core/Config.h>
#include <xrpld/rpc/detail/Pathfinder.h>
#include <xrpld/rpc/detail/RippleLineCache.h>
#include <xrpld/rpc/RPCHandler.h>
#include <xrpld/rpc/Role.h>
#include <xrpld/rpc/detail/Tuning.h>
Expand Down Expand Up @@ -685,6 +689,292 @@ class Path_test : public beast::unit_test::Suite
BEAST_EXPECT(equal(sa, Account("alice")["USD"](5)));
}

<<<<<<< HEAD
Json::Value
six_path_append_request_result()
=======
json::Value
sixPathAppendRequestResult()
>>>>>>> 362775e809fd6980492750b09a40fed7d205a9af
{
using namespace jtx;
Env env = pathTestEnv();

<<<<<<< HEAD
Account A1{"A1"};
Account A2{"A2"};
Account G1{"G1"};
Account G2{"G2"};
Account M1{"M1"};
Account M2{"M2"};
Account M3{"M3"};
Account M4{"M4"};
Account M5{"M5"};
Account M6{"M6"};
Account MM{"MM"};

env.fund(XRP(1000), A1, A2, G1, G2, M1, M2, M3, M4, M5, M6, MM);
env.close();

env.trust(G1["HKD"](2000), A1);
env.trust(G2["HKD"](2000), A2);

env.trust(G1["HKD"](100000), M1, M2, M3, M4, M5, M6, MM);
env.trust(G2["HKD"](100000), M1, M2, M3, M4, M5, M6, MM);
env.close();

env(pay(G1, A1, G1["HKD"](1000)));

env(pay(G1, M1, G1["HKD"](10)));
env(pay(G1, M2, G1["HKD"](10)));
env(pay(G1, M3, G1["HKD"](10)));
env(pay(G1, M4, G1["HKD"](10)));
env(pay(G1, M5, G1["HKD"](10)));
env(pay(G1, M6, G1["HKD"](10)));
env(pay(G1, MM, G1["HKD"](1000)));

env(pay(G2, M1, G2["HKD"](10)));
env(pay(G2, M2, G2["HKD"](10)));
env(pay(G2, M3, G2["HKD"](10)));
env(pay(G2, M4, G2["HKD"](10)));
env(pay(G2, M5, G2["HKD"](10)));
env(pay(G2, M6, G2["HKD"](10)));
env(pay(G2, MM, G2["HKD"](1000)));
env.close();

env(offer(MM, G1["HKD"](1000), G2["HKD"](100)));
env.close();

return find_paths_request(env, A1, A2, A2["HKD"](60), std::nullopt, G1["HKD"].currency);
}

void
pathfind_paths_computed_never_exceeds_six()
{
testcase("pathfind paths_computed never exceeds six");

auto const result = six_path_append_request_result();
=======
Account const a1{"A1"};
Account const a2{"A2"};
Account const g1{"G1"};
Account const g2{"G2"};
Account const m1{"M1"};
Account const m2{"M2"};
Account const m3{"M3"};
Account const m4{"M4"};
Account const m5{"M5"};
Account const m6{"M6"};
Account const mm{"MM"};

env.fund(XRP(1000), a1, a2, g1, g2, m1, m2, m3, m4, m5, m6, mm);
env.close();

env.trust(g1["HKD"](2000), a1);
env.trust(g2["HKD"](2000), a2);

env.trust(g1["HKD"](100000), m1, m2, m3, m4, m5, m6, mm);
env.trust(g2["HKD"](100000), m1, m2, m3, m4, m5, m6, mm);
env.close();

env(pay(g1, a1, g1["HKD"](1000)));

env(pay(g1, m1, g1["HKD"](10)));
env(pay(g1, m2, g1["HKD"](10)));
env(pay(g1, m3, g1["HKD"](10)));
env(pay(g1, m4, g1["HKD"](10)));
env(pay(g1, m5, g1["HKD"](10)));
env(pay(g1, m6, g1["HKD"](10)));
env(pay(g1, mm, g1["HKD"](1000)));

env(pay(g2, m1, g2["HKD"](10)));
env(pay(g2, m2, g2["HKD"](10)));
env(pay(g2, m3, g2["HKD"](10)));
env(pay(g2, m4, g2["HKD"](10)));
env(pay(g2, m5, g2["HKD"](10)));
env(pay(g2, m6, g2["HKD"](10)));
env(pay(g2, mm, g2["HKD"](1000)));
env.close();

env(offer(mm, g1["HKD"](1000), g2["HKD"](100)));
env.close();

return findPathsRequest(env, a1, a2, a2["HKD"](60), std::nullopt, g1["HKD"].currency);
}

void
pathfindPathsComputedNeverExceedsSix()
{
testcase("pathfind paths_computed never exceeds six");

auto const result = sixPathAppendRequestResult();
>>>>>>> 362775e809fd6980492750b09a40fed7d205a9af
BEAST_EXPECT(result.isMember(jss::alternatives));
if (!result.isMember(jss::alternatives))
return;

BEAST_EXPECT(result[jss::alternatives].isArray());
if (!result[jss::alternatives].isArray())
return;

bool sawPathsComputed = false;
for (auto const& alt : result[jss::alternatives])
{
if (!alt.isMember(jss::paths_computed))
continue;
Comment thread
shortthefomo marked this conversation as resolved.
sawPathsComputed = true;
BEAST_EXPECT(alt[jss::paths_computed].isArray());
if (alt[jss::paths_computed].isArray())
BEAST_EXPECT(alt[jss::paths_computed].size() <= 6);
}
BEAST_EXPECT(sawPathsComputed);
}

void
<<<<<<< HEAD
pathfind_can_return_six_paths_with_append()
=======
pathfindCanReturnSixPathsWithAppend()
>>>>>>> 362775e809fd6980492750b09a40fed7d205a9af
{
testcase("pathfind can return six paths with append");
using namespace jtx;
Env env = pathTestEnv();

<<<<<<< HEAD
Account A1{"A1"};
Account A2{"A2"};
Account G1{"G1"};
Account G2{"G2"};
Account M1{"M1"};
Account M2{"M2"};
Account M3{"M3"};
Account M4{"M4"};
Account M5{"M5"};
Account M6{"M6"};
Account MM{"MM"};

env.fund(XRP(1000), A1, A2, G1, G2, M1, M2, M3, M4, M5, M6, MM);
env.close();

env.trust(G1["HKD"](2000), A1);
env.trust(G2["HKD"](2000), A2);

env.trust(G1["HKD"](100000), M1, M2, M3, M4, M5, M6, MM);
env.trust(G2["HKD"](100000), M1, M2, M3, M4, M5, M6, MM);
env.close();

env(pay(G1, A1, G1["HKD"](1000)));

env(pay(G1, M1, G1["HKD"](10)));
env(pay(G1, M2, G1["HKD"](10)));
env(pay(G1, M3, G1["HKD"](10)));
env(pay(G1, M4, G1["HKD"](10)));
env(pay(G1, M5, G1["HKD"](10)));
env(pay(G1, M6, G1["HKD"](10)));
env(pay(G1, MM, G1["HKD"](1000)));

env(pay(G2, M1, G2["HKD"](10)));
env(pay(G2, M2, G2["HKD"](10)));
env(pay(G2, M3, G2["HKD"](10)));
env(pay(G2, M4, G2["HKD"](10)));
env(pay(G2, M5, G2["HKD"](10)));
env(pay(G2, M6, G2["HKD"](10)));
env(pay(G2, MM, G2["HKD"](1000)));
env.close();

env(offer(MM, G1["HKD"](1000), G2["HKD"](100)));
env.close();

auto cache =
std::make_shared<RippleLineCache>(env.current(), env.app().getJournal("RippleLineCache"));
Pathfinder pf(
cache,
A1.id(),
A2.id(),
G1["HKD"].currency,
std::nullopt,
A2["HKD"](60),
=======
Account const a1{"A1"};
Account const a2{"A2"};
Account const g1{"G1"};
Account const g2{"G2"};
Account const m1{"M1"};
Account const m2{"M2"};
Account const m3{"M3"};
Account const m4{"M4"};
Account const m5{"M5"};
Account const m6{"M6"};
Account const mm{"MM"};

env.fund(XRP(1000), a1, a2, g1, g2, m1, m2, m3, m4, m5, m6, mm);
env.close();

env.trust(g1["HKD"](2000), a1);
env.trust(g2["HKD"](2000), a2);

env.trust(g1["HKD"](100000), m1, m2, m3, m4, m5, m6, mm);
env.trust(g2["HKD"](100000), m1, m2, m3, m4, m5, m6, mm);
env.close();

env(pay(g1, a1, g1["HKD"](1000)));

env(pay(g1, m1, g1["HKD"](10)));
env(pay(g1, m2, g1["HKD"](10)));
env(pay(g1, m3, g1["HKD"](10)));
env(pay(g1, m4, g1["HKD"](10)));
env(pay(g1, m5, g1["HKD"](10)));
env(pay(g1, m6, g1["HKD"](10)));
env(pay(g1, mm, g1["HKD"](1000)));

env(pay(g2, m1, g2["HKD"](10)));
env(pay(g2, m2, g2["HKD"](10)));
env(pay(g2, m3, g2["HKD"](10)));
env(pay(g2, m4, g2["HKD"](10)));
env(pay(g2, m5, g2["HKD"](10)));
env(pay(g2, m6, g2["HKD"](10)));
env(pay(g2, mm, g2["HKD"](1000)));
env.close();

env(offer(mm, g1["HKD"](1000), g2["HKD"](100)));
env.close();

auto cache =
std::make_shared<AssetCache>(env.current(), env.app().getJournal("AssetCache"));
Pathfinder pf(
cache,
a1.id(),
a2.id(),
g1["HKD"].currency,
std::nullopt,
a2["HKD"](60),
>>>>>>> 362775e809fd6980492750b09a40fed7d205a9af
std::nullopt,
std::nullopt,
env.app());

BEAST_EXPECT(pf.findPaths(7));
pf.computePathRanks(5);

STPath fullLiquidityPath;
<<<<<<< HEAD
auto bestPaths = pf.getBestPaths(5, fullLiquidityPath, STPathSet{}, A1.id());
=======
auto bestPaths = pf.getBestPaths(5, fullLiquidityPath, STPathSet{}, a1.id());
>>>>>>> 362775e809fd6980492750b09a40fed7d205a9af
BEAST_EXPECT(bestPaths.size() == 5);
BEAST_EXPECT(!fullLiquidityPath.empty());

if (!fullLiquidityPath.empty())
<<<<<<< HEAD
bestPaths.push_back(fullLiquidityPath);
=======
bestPaths.pushBack(fullLiquidityPath);
>>>>>>> 362775e809fd6980492750b09a40fed7d205a9af
BEAST_EXPECT(bestPaths.size() == 6);
}

void
issuesPathNegativeIssue(bool const domainEnabled)
{
Expand Down Expand Up @@ -1907,6 +2197,13 @@ class Path_test : public beast::unit_test::Suite

hybridOfferPath();
ammDomainPath();
<<<<<<< HEAD
pathfind_paths_computed_never_exceeds_six();
pathfind_can_return_six_paths_with_append();
=======
pathfindPathsComputedNeverExceedsSix();
pathfindCanReturnSixPathsWithAppend();
>>>>>>> 362775e809fd6980492750b09a40fed7d205a9af
}
};

Expand Down
7 changes: 4 additions & 3 deletions src/xrpld/rpc/detail/Pathfinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1406,11 +1406,12 @@ Pathfinder::initPathTable()

fillPaths(
PaymentType::NonXrpToXrp,
{{1, "sxd"}, // gateway buys XRP
{2, "saxd"}, // source -> gateway -> book(XRP) -> dest
{{1, "sxd"}, // gateway buys XRP
{2, "saxd"}, // source -> gateway -> book(XRP) -> dest
{5, "sabxd"}, // source -> gateway -> book -> book(XRP) -> dest
{6, "saaxd"},
{7, "sbxd"},
{8, "sabxd"},
{8, "sabbxd"}, // source -> gateway -> book -> book -> book(XRP) -> dest
Comment thread
shortthefomo marked this conversation as resolved.
Comment thread
shortthefomo marked this conversation as resolved.
{9, "sabaxd"}});

// non-XRP to non-XRP (same currency)
Expand Down