feat(graph): detect negative-weight edges in PaymentGraphChecker - #830
Open
woahwhattheheck wants to merge 2 commits into
Open
feat(graph): detect negative-weight edges in PaymentGraphChecker#830woahwhattheheck wants to merge 2 commits into
woahwhattheheck wants to merge 2 commits into
Conversation
A negative hop weight is treated as adding funds by a greedy traversal, so a route containing one can be repeated for unbounded extraction. checkGraph() now reports every edge with a negative weight, naming source and target. Zero-weight edges stay valid: they are legitimate pass-through hops.
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #773.
PaymentGraphCheckervalidated reachability but had no notion of edgeweight, so a negative-weight hop passed through unnoticed. A greedy traversal
treats a negative hop as if it adds funds, which makes a route containing
one repeatable for unbounded extraction.
Changes
src/graph/PaymentGraphChecker.ts:checkGraph(graph)— returns{ valid, issues }, reporting every edge whoseweight is negative. Each issue carries
code,from,to,weight, and amessage naming the offending edge as
from -> to.PaymentGraphEdge,PaymentGraph,NegativeEdgeWeightIssue,GraphValidationResult.Zero-weight edges remain valid — they are legitimate pass-through hops, so the
check is strictly
weight < 0, notweight <= 0.Two details worth calling out:
numberandbigintweights are both handled. Amounts elsewhere in theSDK are
bigint(Recipient.amount,Invoice.funded), but graph weightsare natural to express as plain numbers, so
checkGraphaccepts either andcompares against the matching zero.
list means a caller fixing a malformed graph sees every problem in one pass.
checkGraphaccepts either{ edges }or a barePaymentGraphEdge[], sincethe issue did not pin the shape and both read naturally at a call site.
Validation
npx vitest run test/paymentGraphChecker.test.ts— 15/15 passing (the 7pre-existing cases plus 8 new ones covering: positive weights accepted,
zero weights accepted, empty graph, a single negative edge, the message
naming source and target, negative
bigint, multiple offenders reported inedge order, and the bare-array form).
npx tsc --noEmitreports 210 errors on this branch and 210 on unmodifiedmain— identical, so this change adds none, and zero are insrc/graph/PaymentGraphChecker.ts. That baseline is pre-existing (missingexported members in
types.js/priceOracle.js/soroban/footprint.jsandnoUncheckedIndexedAccessnullability) and is not a prerequisite here; Imention it only so the red
lintisn't read as coming from this PR.