Skip to content

refactor: Pathfinding 2.0 using Dijkstra's Algorithm - #7392

Closed
shortthefomo wants to merge 25 commits into
XRPLF:developfrom
shortthefomo:pathfinding-2
Closed

refactor: Pathfinding 2.0 using Dijkstra's Algorithm#7392
shortthefomo wants to merge 25 commits into
XRPLF:developfrom
shortthefomo:pathfinding-2

Conversation

@shortthefomo

@shortthefomo shortthefomo commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

High Level Overview of Change

XLS: XRPLF/XRPL-Standards#561

Replaces the existing BFS-based Pathfinder with a new graph-based pathfinding engine (GraphPathfinder + PayGraph) that uses Dijkstra/Yen's K-Shortest algorithm on a persistent, incrementally-updated asset-exchange graph.

The new engine is dramatically faster: the asset graph on mainnet has ~500 vertices and ~1,000 edges — small enough that Yen's K-Shortest runs in microseconds rather than the milliseconds-to-seconds of the previous BFS over the full account+asset space.

Related: pathfinding 2.0 using Dijkstra's Algorithm.

Context of Change

Previous implementation: Pathfinder performs BFS over a combined account+asset graph with O(A^D) fanout (A ≈ 20 trust-line neighbours, D ≈ 7 hops) before any pruning, then calls rippleCalculate on up to 1,000 candidates. This is CPU-intensive and latency-sensitive, especially for multi-hop cross-currency payments.

New implementation:

  1. PayGraph — a persistent, process-lifetime asset-exchange graph.

    • Vertices = distinct assets (IOU {currency, issuer}, MPT IDs, XRP)
    • Edges = order books and AMM pools between asset pairs
    • Built eagerly when the OrderBookDB signals "ready" (so the first request after startup never pays for the initial walk) and updated incrementally on each ledger close via applyLedgerDelta() — typically patching fewer than 100 edges in a few microseconds by re-querying top-of-book for changed books only.
    • Uses a copy-on-write snapshot model (std::atomic<shared_ptr<Snapshot>>): pathfinder threads take a snapshot and hold zero locks during search; the ledger-close thread publishes a new snapshot atomically.
  2. GraphPathfinder — drop-in replacement for Pathfinder.

    • Runs Yen's K-Shortest Paths on the PayGraph snapshot in O((V+E) log V).
    • Oversamples by 3× (asks Yen's for kMaxK * 3 = 18 candidates per asset pair) so the ranking stage has spares to fall back on when a candidate fails rippleCalculate (thin order books, AMM overflow, etc).
    • Materialises each abstract path into a concrete STPath (book nodes only; the XRPL payment engine handles trust-line rippling implicitly).
    • Ranks via rippleCalculate, returning at most kMaxK = 6 viable paths. Early-exits ranking once kMaxK succeed and 3 consecutive failures follow, so wasted work is bounded.
    • Plugs into the existing PathRequest / PathRequestManager progressive-refinement WebSocket pipeline unchanged.
  3. PayGraphDelta — extracts the set of changed order books from transaction metadata (ltOFFER, ltAMM changes) to drive applyLedgerDelta().

  4. Configuration changes:

    • [path_search] is now a boolean flag (0 = disabled [default], 1 = enabled). The old aggressiveness scale (path_search_fast, path_search_max, path_search_old) is removed.
  5. OrderBookDB — added getAllTakerPaysAssets() to support initial graph population.

API Impact

  • Public API: New feature (the engine is transparent to callers; path_find / ripple_path_find response shape is unchanged)
  • Public API: Breaking change
  • libxrpl change
  • Peer protocol change

OrderBookDB.h (part of libxrpl) gains a new pure virtual method getAllTakerPaysAssets(). Dependents that subclass OrderBookDB will need to implement it.

Before / After

Before:

  • path_find triggers BFS over account+asset graph: O(A^D) node expansions, up to ~1,000 rippleCalculate calls per update tick.
  • Path search aggressiveness tuned via path_search (2), path_search_fast (2), path_search_max (3), path_search_old (2).
  • Pathfinding enabled by default.

After:

  • path_find runs Yen's K-Shortest on the tiny asset graph (μs), materialises ≤18 candidates, calls rippleCalculate until 6 succeed (bounded early-exit on consecutive failures).
  • Path search is a simple on/off flag (path_search = 1 to enable). Off by default.
  • Graph update on ledger close: O(changed_books) edge patches, no SHAMap walk.
  • Pathfinder threads hold zero locks during search (snapshot model).

Test Plan

  • All units tests pass there are pathing tests in multiple places failures have been addressed.
  • 57 new unit tests added on top of the existing path finding tests that preexisted.
  • Existing path-finding unit tests (Path_test.cpp, PathMPT_test.cpp) updated to compile against the new engine interface.
  • Manually verified against mainnet: path_find WebSocket subscription returns alternatives with paths within the first update tick after ledger close, and consistently returns the requested number of paths (6) for liquid pairs like XRP→RLUSD.
  • ripple_path_find (synchronous RPC) confirmed working end-to-end.

@shortthefomo
shortthefomo marked this pull request as draft June 3, 2026 05:11
@shortthefomo
shortthefomo marked this pull request as ready for review June 3, 2026 15:02
@shortthefomo shortthefomo changed the title pathfinding 2.0 using Dijkstra's Algorithm refactor: Pathfinding 2.0 using Dijkstra's Algorithm Jun 3, 2026
@codecov

codecov Bot commented Jun 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 77.43764% with 199 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.2%. Comparing base (96b2c09) to head (a87f061).
⚠️ Report is 3 commits behind head on develop.

Files with missing lines Patch % Lines
src/xrpld/rpc/detail/PayGraph.cpp 72.0% 70 Missing ⚠️
src/xrpld/rpc/detail/GraphPathfinder.cpp 85.6% 64 Missing ⚠️
src/xrpld/rpc/detail/PayGraphDelta.h 20.5% 31 Missing ⚠️
src/xrpld/rpc/detail/PathRequest.cpp 77.8% 12 Missing ⚠️
src/xrpld/rpc/detail/PathRequestManager.cpp 65.7% 12 Missing ⚠️
src/xrpld/core/detail/Config.cpp 56.5% 10 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##           develop   #7392     +/-   ##
=========================================
- Coverage     82.4%   82.2%   -0.2%     
=========================================
  Files         1011    1014      +3     
  Lines        76544   76734    +190     
  Branches      7322    7381     +59     
=========================================
+ Hits         63061   63096     +35     
- Misses       13483   13638    +155     
Files with missing lines Coverage Δ
include/xrpl/ledger/OrderBookDB.h 100.0% <ø> (ø)
src/xrpld/app/ledger/LedgerMaster.h 71.4% <ø> (ø)
src/xrpld/app/ledger/OrderBookDBImpl.cpp 71.8% <100.0%> (-5.8%) ⬇️
src/xrpld/app/ledger/detail/LedgerMaster.cpp 42.9% <100.0%> (+0.1%) ⬆️
src/xrpld/app/main/Application.cpp 70.5% <100.0%> (-<0.1%) ⬇️
src/xrpld/core/Config.h 87.5% <ø> (ø)
src/xrpld/core/ConfigSections.h 100.0% <ø> (ø)
src/xrpld/rpc/detail/GraphPathfinder.h 100.0% <100.0%> (ø)
src/xrpld/rpc/detail/PathRequestManager.h 100.0% <100.0%> (ø)
src/xrpld/rpc/detail/PayGraph.h 100.0% <100.0%> (ø)
... and 9 more

... and 12 files with indirect coverage changes

Impacted file tree graph

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown

This PR has conflicts, please resolve them in order for the PR to be reviewed.

@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown

⚠️ This PR contains unsigned commits. To get your PR merged, please sign them. ⚠️

If only the most recent commit is unsigned, you can run:

  1. Amend the commit: git commit --amend --no-edit -n -S
  2. Overwrite the commit: git push --force-with-lease

If multiple commits are unsigned, you can run:

  1. Go into interactive rebase mode: git rebase --interactive HEAD~<NUM_OF_COMMITS>, where NUM_OF_COMMITS is the number of most recent commits that will be available to edit.
  2. Change "pick" to "edit" for the commits you need to sign, and then save and exit.
  3. For each commit, run: git commit --amend --no-edit -n -S
  4. Continue the rebase: git rebase --continue
  5. Overwrite the commit(s): git push --force-with-lease

If you're new to commit signing, there are different ways to set it up:

Sign commits with gpg

Follow the steps below to set up commit signing with gpg:

  1. Generate a GPG key
  2. Add the GPG key to your GitHub account
  3. Configure git to use your GPG key for commit signing
Sign commits with ssh-agent

Follow the steps below to set up commit signing with ssh-agent:

  1. Generate an SSH key and add it to ssh-agent
  2. Add the SSH key to your GitHub account
  3. Configure git to use your SSH key for commit signing
Sign commits with 1Password

You can also sign commits using 1Password, which lets you sign commits with biometrics without the signing key leaving the local 1Password process.
See use 1Password to sign your commits.

@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown

All conflicts have been resolved. Assigned reviewers can now start or resume their review.

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown

This PR has conflicts, please resolve them in order for the PR to be reviewed.

shortthefomo and others added 5 commits July 5, 2026 22:08
Resolved merge conflicts by keeping pathfinding-2 (HEAD) changes where
conflicts occurred, while incorporating develop features that don't
overlap:

- .cspell.config.yaml: Added 'decryptor' and 'summands' words from develop
- OrderBookDB.h: Kept pathfinding methods (getAllTakerPaysAssets, processTxn,
  getBookListeners, makeBookListeners) and added affectedBooks function from develop
- ConfigSections.h: Kept HEAD version with SECTION_PATH_WORKERS
- Config.cpp, PathRequest.h, PathRequestManager.h: Kept HEAD versions
- Pathfinder.cpp, Pathfinder.h: Deleted as they were removed in HEAD

This preserves pathfinding features while integrating compatible develop changes.
…tes compose multiplicatively via log-space edge weights

fix, Top-of-book weights would ignore liquidity depth and exchange rates compose multiplicatively via log-space edge weights
Resolve conflict by keeping Pathfinder.h deleted: pathfinding-2 uses
GraphPathfinder as the replacement; develop only had style updates to the
old Pathfinder header.
@github-actions

Copy link
Copy Markdown

All conflicts have been resolved. Assigned reviewers can now start or resume their review.

Comment thread src/libxrpl/tx/paths/BookStep.cpp Outdated
@github-actions

Copy link
Copy Markdown

This PR has conflicts, please resolve them in order for the PR to be reviewed.

@shortthefomo

Copy link
Copy Markdown
Contributor Author

#7962 is the better approach

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant