Skip to content

Commit

Permalink
Include empty paths in path finding response (#4137)
Browse files Browse the repository at this point in the history
  • Loading branch information
tamirms authored Dec 10, 2021
1 parent 6c6503e commit e80796c
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 27 deletions.
82 changes: 56 additions & 26 deletions exp/orderbook/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -692,8 +692,37 @@ func (graph *OrderBookGraph) FindPaths(
validateSourceBalance bool,
maxAssetsPerPath int,
includePools bool,
) ([]Path, uint32, error) {
paths, lastLedger, err := graph.findPathsWithLock(
ctx, maxPathLength, destinationAsset, destinationAmount, sourceAccountID, sourceAssets, sourceAssetBalances,
validateSourceBalance, includePools,
)
if err != nil {
return nil, lastLedger, errors.Wrap(err, "could not determine paths")
}

paths, err = sortAndFilterPaths(
paths,
maxAssetsPerPath,
sortBySourceAsset,
)
return paths, lastLedger, err
}

func (graph *OrderBookGraph) findPathsWithLock(
ctx context.Context,
maxPathLength int,
destinationAsset xdr.Asset,
destinationAmount xdr.Int64,
sourceAccountID *xdr.AccountId,
sourceAssets []xdr.Asset,
sourceAssetBalances []xdr.Int64,
validateSourceBalance bool,
includePools bool,
) ([]Path, uint32, error) {
graph.lock.RLock()
defer graph.lock.RUnlock()

destinationAssetString := destinationAsset.String()
sourceAssetsMap := make(map[int32]xdr.Int64, len(sourceAssets))
for i, sourceAsset := range sourceAssets {
Expand All @@ -706,7 +735,6 @@ func (graph *OrderBookGraph) FindPaths(
}
destinationAssetID, ok := graph.assetStringToID[destinationAssetString]
if !ok || len(sourceAssetsMap) == 0 {
graph.lock.RUnlock()
return []Path{}, graph.lastLedger, nil
}
searchState := &sellingGraphSearchState{
Expand All @@ -726,18 +754,7 @@ func (graph *OrderBookGraph) FindPaths(
destinationAssetID,
destinationAmount,
)
lastLedger := graph.lastLedger
graph.lock.RUnlock()
if err != nil {
return nil, lastLedger, errors.Wrap(err, "could not determine paths")
}

paths, err := sortAndFilterPaths(
searchState.paths,
maxAssetsPerPath,
sortBySourceAsset,
)
return paths, lastLedger, err
return searchState.paths, graph.lastLedger, err
}

type sortablePaths struct {
Expand Down Expand Up @@ -773,8 +790,33 @@ func (graph *OrderBookGraph) FindFixedPaths(
destinationAssets []xdr.Asset,
maxAssetsPerPath int,
includePools bool,
) ([]Path, uint32, error) {
paths, lastLedger, err := graph.findFixedPathsWithLock(
ctx, maxPathLength, sourceAsset, amountToSpend, destinationAssets, includePools,
)
if err != nil {
return nil, lastLedger, errors.Wrap(err, "could not determine paths")
}

paths, err = sortAndFilterPaths(
paths,
maxAssetsPerPath,
sortByDestinationAsset,
)
return paths, lastLedger, err
}

func (graph *OrderBookGraph) findFixedPathsWithLock(
ctx context.Context,
maxPathLength int,
sourceAsset xdr.Asset,
amountToSpend xdr.Int64,
destinationAssets []xdr.Asset,
includePools bool,
) ([]Path, uint32, error) {
graph.lock.RLock()
defer graph.lock.RUnlock()

target := make(map[int32]bool, len(destinationAssets))
for _, destinationAsset := range destinationAssets {
destinationAssetString := destinationAsset.String()
Expand All @@ -788,7 +830,6 @@ func (graph *OrderBookGraph) FindFixedPaths(
sourceAssetString := sourceAsset.String()
sourceAssetID, ok := graph.assetStringToID[sourceAssetString]
if !ok || len(target) == 0 {
graph.lock.RUnlock()
return []Path{}, graph.lastLedger, nil
}
searchState := &buyingGraphSearchState{
Expand All @@ -806,18 +847,7 @@ func (graph *OrderBookGraph) FindFixedPaths(
sourceAssetID,
amountToSpend,
)
lastLedger := graph.lastLedger
graph.lock.RUnlock()
if err != nil {
return nil, lastLedger, errors.Wrap(err, "could not determine paths")
}

paths, err := sortAndFilterPaths(
searchState.paths,
maxAssetsPerPath,
sortByDestinationAsset,
)
return paths, lastLedger, err
return searchState.paths, graph.lastLedger, err
}

// compareSourceAsset will group payment paths by `SourceAsset`
Expand Down
22 changes: 21 additions & 1 deletion exp/orderbook/graph_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1579,10 +1579,12 @@ func TestFindPaths(t *testing.T) {
[]xdr.Asset{
yenAsset,
usdAsset,
nativeAsset,
},
[]xdr.Int64{
100000,
60000,
100000,
},
true,
5,
Expand Down Expand Up @@ -1618,6 +1620,15 @@ func TestFindPaths(t *testing.T) {
DestinationAsset: nativeAsset.String(),
DestinationAmount: 20,
},
// include the empty path where xlm is transferred without any
// conversions
{
SourceAmount: 20,
SourceAsset: nativeAsset.String(),
InteriorNodes: []string{},
DestinationAsset: nativeAsset.String(),
DestinationAmount: 20,
},
}

assert.NoError(t, err)
Expand Down Expand Up @@ -1873,7 +1884,7 @@ func TestFindPathsStartingAt(t *testing.T) {
5,
yenAsset,
5,
[]xdr.Asset{nativeAsset, usdAsset},
[]xdr.Asset{nativeAsset, usdAsset, yenAsset},
5,
true,
)
Expand All @@ -1895,6 +1906,15 @@ func TestFindPathsStartingAt(t *testing.T) {
DestinationAsset: usdAsset.String(),
DestinationAmount: 20,
},
// include the empty path where yen is transferred without any
// conversions
{
SourceAmount: 5,
SourceAsset: yenAsset.String(),
InteriorNodes: []string{},
DestinationAsset: yenAsset.String(),
DestinationAmount: 5,
},
{
SourceAmount: 5,
SourceAsset: yenAsset.String(),
Expand Down
11 changes: 11 additions & 0 deletions exp/orderbook/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,17 @@ func search(
asset: sourceAsset,
prev: nil,
}
// Simple payments (e.g. payments where an asset is transferred from
// one account to another without any conversions into another asset)
// are also valid path payments. If the source asset is a valid
// destination asset we include the empty path in the response.
if state.includePath(sourceAsset, sourceAssetAmount) {
state.appendToPaths(
[]int32{sourceAsset},
sourceAsset,
sourceAssetAmount,
)
}

for i := 0; i < maxPathLength; i++ {
updatedAssets = updatedAssets[:0]
Expand Down

0 comments on commit e80796c

Please sign in to comment.