diff --git a/.changeset/nervous-humans-march.md b/.changeset/nervous-humans-march.md new file mode 100644 index 0000000000..43c7a08683 --- /dev/null +++ b/.changeset/nervous-humans-march.md @@ -0,0 +1,5 @@ +--- +"ccip": patch +--- + +Added tests and cleanup of liquidity graph #changed diff --git a/core/services/ocr2/plugins/liquiditymanager/graph/graph.go b/core/services/ocr2/plugins/liquiditymanager/graph/graph.go index 287272a9d1..7523a75cc9 100644 --- a/core/services/ocr2/plugins/liquiditymanager/graph/graph.go +++ b/core/services/ocr2/plugins/liquiditymanager/graph/graph.go @@ -10,9 +10,8 @@ import ( // GraphWriter provides write access to the liquidity graph. type GraphWriter interface { + // Add adds new data and connection to the graph. Add(from, to Data) error - // AddEdges adds a list of edges to the graph. - AddEdges(edges []models.Edge) error // SetLiquidity sets the liquidity of the provided network. SetLiquidity(n models.NetworkSelector, liquidity *big.Int) bool } diff --git a/core/services/ocr2/plugins/liquiditymanager/graph/reader_test.go b/core/services/ocr2/plugins/liquiditymanager/graph/reader_test.go new file mode 100644 index 0000000000..58721e9081 --- /dev/null +++ b/core/services/ocr2/plugins/liquiditymanager/graph/reader_test.go @@ -0,0 +1,182 @@ +package graph + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/liquiditymanager/models" +) + +func TestGrpah_NodeReaderGetters(t *testing.T) { + g := NewGraph() + + data1 := Data{ + Liquidity: big.NewInt(1), + TokenAddress: models.Address(common.HexToAddress("0x11")), + LiquidityManagerAddress: models.Address(common.HexToAddress("0x12")), + XChainLiquidityManagers: map[models.NetworkSelector]XChainLiquidityManagerData{}, + ConfigDigest: models.ConfigDigest{ + ConfigDigest: [32]byte{1}, + }, + NetworkSelector: models.NetworkSelector(1), + } + require.True(t, g.(GraphTest).AddNetwork(models.NetworkSelector(1), data1)) + + tests := []struct { + name string + net models.NetworkSelector + data *Data + }{ + { + name: "happy path", + net: models.NetworkSelector(1), + data: &data1, + }, + { + name: "not exist", + net: models.NetworkSelector(333), + data: nil, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + liq, err := g.GetLiquidity(tc.net) + if tc.data == nil { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tc.data.Liquidity, liq) + } + + tokenAddr, err := g.GetTokenAddress(tc.net) + if tc.data == nil { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tc.data.TokenAddress, tokenAddr) + } + + liqManagerAddr, err := g.GetLiquidityManagerAddress(tc.net) + if tc.data == nil { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tc.data.LiquidityManagerAddress, liqManagerAddr) + } + + xChainData, err := g.GetXChainLiquidityManagerData(tc.net) + if tc.data == nil { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tc.data.XChainLiquidityManagers, xChainData) + } + + data, err := g.GetData(tc.net) + if tc.data == nil { + require.Error(t, err) + } else { + require.NoError(t, err) + require.True(t, tc.data.Equals(data)) + } + }) + } +} + +func TestGraph_FindPath(t *testing.T) { + g := NewGraph() + + data1 := Data{ + Liquidity: big.NewInt(1), + TokenAddress: models.Address(common.HexToAddress("0x11")), + LiquidityManagerAddress: models.Address(common.HexToAddress("0x12")), + XChainLiquidityManagers: map[models.NetworkSelector]XChainLiquidityManagerData{}, + ConfigDigest: models.ConfigDigest{ + ConfigDigest: [32]byte{1}, + }, + NetworkSelector: models.NetworkSelector(1), + } + require.True(t, g.(GraphTest).AddNetwork(models.NetworkSelector(1), data1)) + + data2 := Data{ + Liquidity: big.NewInt(2), + TokenAddress: models.Address(common.HexToAddress("0x21")), + LiquidityManagerAddress: models.Address(common.HexToAddress("0x22")), + XChainLiquidityManagers: map[models.NetworkSelector]XChainLiquidityManagerData{}, + ConfigDigest: models.ConfigDigest{ + ConfigDigest: [32]byte{2}, + }, + NetworkSelector: models.NetworkSelector(2), + } + require.True(t, g.(GraphTest).AddNetwork(models.NetworkSelector(2), data2)) + + data3 := Data{ + Liquidity: big.NewInt(3), + TokenAddress: models.Address(common.HexToAddress("0x31")), + LiquidityManagerAddress: models.Address(common.HexToAddress("0x32")), + XChainLiquidityManagers: map[models.NetworkSelector]XChainLiquidityManagerData{}, + ConfigDigest: models.ConfigDigest{ + ConfigDigest: [32]byte{3}, + }, + NetworkSelector: models.NetworkSelector(3), + } + require.True(t, g.(GraphTest).AddNetwork(models.NetworkSelector(3), data3)) + + require.NoError(t, g.(GraphTest).AddConnection(models.NetworkSelector(1), models.NetworkSelector(2))) + require.NoError(t, g.(GraphTest).AddConnection(models.NetworkSelector(2), models.NetworkSelector(3))) + + tests := []struct { + name string + from models.NetworkSelector + to models.NetworkSelector + maxEdges int + want []models.NetworkSelector + }{ + { + name: "happy path 2 edges", + from: models.NetworkSelector(1), + to: models.NetworkSelector(3), + maxEdges: 2, + want: []models.NetworkSelector{models.NetworkSelector(2), models.NetworkSelector(3)}, + }, + { + name: "happy path 1 edge", + from: models.NetworkSelector(1), + to: models.NetworkSelector(2), + maxEdges: 1, + want: []models.NetworkSelector{models.NetworkSelector(2)}, + }, + { + name: "not enough edges", + from: models.NetworkSelector(1), + to: models.NetworkSelector(3), + maxEdges: 1, + want: []models.NetworkSelector{}, + }, + { + name: "no path", + from: models.NetworkSelector(2), + to: models.NetworkSelector(10), + want: []models.NetworkSelector{}, + }, + { + name: "same node", + from: models.NetworkSelector(1), + to: models.NetworkSelector(1), + want: []models.NetworkSelector{}, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + path := g.FindPath(tc.from, tc.to, tc.maxEdges, func(nodes ...Data) bool { + return true + }) + require.Equal(t, tc.want, path) + }) + } +} diff --git a/core/services/ocr2/plugins/liquiditymanager/graph/writer.go b/core/services/ocr2/plugins/liquiditymanager/graph/writer.go index 2da8207d0d..1d0ee45d59 100644 --- a/core/services/ocr2/plugins/liquiditymanager/graph/writer.go +++ b/core/services/ocr2/plugins/liquiditymanager/graph/writer.go @@ -20,18 +20,6 @@ func (g *liquidityGraph) Add(from, to Data) error { return nil } -func (g *liquidityGraph) AddEdges(edges []models.Edge) error { - g.lock.Lock() - defer g.lock.Unlock() - - for _, edge := range edges { - if err := g.addConnection(edge.Source, edge.Dest); err != nil { - return fmt.Errorf("add connection %d -> %d: %w", edge.Source, edge.Dest, err) - } - } - return nil -} - func (g *liquidityGraph) SetLiquidity(n models.NetworkSelector, liquidity *big.Int) bool { g.lock.Lock() defer g.lock.Unlock()