Skip to content

Commit 8113c34

Browse files
committed
liquidity: add failed loop in swaps to swap traffic
1 parent 965b99d commit 8113c34

File tree

2 files changed

+200
-6
lines changed

2 files changed

+200
-6
lines changed

liquidity/liquidity.go

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,17 +1084,28 @@ func (m *Manager) currentSwapTraffic(loopOut []*loopdb.LoopOut,
10841084
}
10851085

10861086
for _, in := range loopIn {
1087-
// Skip completed swaps, they can't affect our channel balances.
1088-
if in.State().State.Type() != loopdb.StateTypePending {
1089-
continue
1090-
}
1091-
10921087
// Skip over swaps that may come through any peer.
10931088
if in.Contract.LastHop == nil {
10941089
continue
10951090
}
10961091

1097-
traffic.ongoingLoopIn[*in.Contract.LastHop] = true
1092+
pubkey := *in.Contract.LastHop
1093+
1094+
switch {
1095+
// Include any pending swaps in our ongoing set of swaps.
1096+
case in.State().State.Type() == loopdb.StateTypePending:
1097+
traffic.ongoingLoopIn[pubkey] = true
1098+
1099+
// If a swap failed with an on-chain timeout, the server could
1100+
// not route to us. We add it to our backoff list so that
1101+
// there's some time for routing conditions to improve.
1102+
case in.State().State == loopdb.StateFailTimeout:
1103+
failedAt := in.LastUpdate().Time
1104+
1105+
if failedAt.After(failureCutoff) {
1106+
traffic.failedLoopIn[pubkey] = failedAt
1107+
}
1108+
}
10981109
}
10991110

11001111
return traffic
@@ -1105,13 +1116,15 @@ type swapTraffic struct {
11051116
ongoingLoopOut map[lnwire.ShortChannelID]bool
11061117
ongoingLoopIn map[route.Vertex]bool
11071118
failedLoopOut map[lnwire.ShortChannelID]time.Time
1119+
failedLoopIn map[route.Vertex]time.Time
11081120
}
11091121

11101122
func newSwapTraffic() *swapTraffic {
11111123
return &swapTraffic{
11121124
ongoingLoopOut: make(map[lnwire.ShortChannelID]bool),
11131125
ongoingLoopIn: make(map[route.Vertex]bool),
11141126
failedLoopOut: make(map[lnwire.ShortChannelID]time.Time),
1127+
failedLoopIn: make(map[route.Vertex]time.Time),
11151128
}
11161129
}
11171130

liquidity/liquidity_test.go

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1817,3 +1817,184 @@ func testSuggestSwaps(t *testing.T, setup *testSuggestSwapsSetup,
18171817
require.Equal(t, expectedErr, err)
18181818
require.Equal(t, expected, actual)
18191819
}
1820+
1821+
// TestCurrentTraffic tests recording of our current set of ongoing swaps.
1822+
func TestCurrentTraffic(t *testing.T) {
1823+
var (
1824+
backoff = time.Hour * 5
1825+
withinBackoff = testTime.Add(time.Hour * -1)
1826+
outsideBackoff = testTime.Add(backoff * -2)
1827+
1828+
success = []*loopdb.LoopEvent{
1829+
{
1830+
SwapStateData: loopdb.SwapStateData{
1831+
State: loopdb.StateSuccess,
1832+
},
1833+
},
1834+
}
1835+
1836+
failedInBackoff = []*loopdb.LoopEvent{
1837+
{
1838+
SwapStateData: loopdb.SwapStateData{
1839+
State: loopdb.StateFailOffchainPayments,
1840+
},
1841+
Time: withinBackoff,
1842+
},
1843+
}
1844+
1845+
failedOutsideBackoff = []*loopdb.LoopEvent{
1846+
{
1847+
SwapStateData: loopdb.SwapStateData{
1848+
State: loopdb.StateFailOffchainPayments,
1849+
},
1850+
Time: outsideBackoff,
1851+
},
1852+
}
1853+
1854+
failedTimeoutInBackoff = []*loopdb.LoopEvent{
1855+
{
1856+
SwapStateData: loopdb.SwapStateData{
1857+
State: loopdb.StateFailTimeout,
1858+
},
1859+
Time: withinBackoff,
1860+
},
1861+
}
1862+
1863+
failedTimeoutOutsideBackoff = []*loopdb.LoopEvent{
1864+
{
1865+
SwapStateData: loopdb.SwapStateData{
1866+
State: loopdb.StateFailTimeout,
1867+
},
1868+
Time: outsideBackoff,
1869+
},
1870+
}
1871+
)
1872+
1873+
tests := []struct {
1874+
name string
1875+
loopOut []*loopdb.LoopOut
1876+
loopIn []*loopdb.LoopIn
1877+
expected *swapTraffic
1878+
}{
1879+
{
1880+
name: "completed swaps ignored",
1881+
loopOut: []*loopdb.LoopOut{
1882+
{
1883+
Loop: loopdb.Loop{
1884+
Events: success,
1885+
},
1886+
Contract: &loopdb.LoopOutContract{},
1887+
},
1888+
},
1889+
loopIn: []*loopdb.LoopIn{
1890+
{
1891+
Loop: loopdb.Loop{
1892+
Events: success,
1893+
},
1894+
Contract: &loopdb.LoopInContract{},
1895+
},
1896+
},
1897+
expected: newSwapTraffic(),
1898+
},
1899+
{
1900+
// No events indicates that the swap is still pending.
1901+
name: "pending swaps included",
1902+
loopOut: []*loopdb.LoopOut{
1903+
{
1904+
Contract: &loopdb.LoopOutContract{
1905+
OutgoingChanSet: []uint64{
1906+
chanID1.ToUint64(),
1907+
},
1908+
},
1909+
},
1910+
},
1911+
loopIn: []*loopdb.LoopIn{
1912+
{
1913+
Contract: &loopdb.LoopInContract{
1914+
LastHop: &peer2,
1915+
},
1916+
},
1917+
},
1918+
expected: &swapTraffic{
1919+
ongoingLoopOut: map[lnwire.ShortChannelID]bool{
1920+
chanID1: true,
1921+
},
1922+
ongoingLoopIn: map[route.Vertex]bool{
1923+
peer2: true,
1924+
},
1925+
// Make empty maps so that we can assert equal.
1926+
failedLoopOut: make(
1927+
map[lnwire.ShortChannelID]time.Time,
1928+
),
1929+
failedLoopIn: make(map[route.Vertex]time.Time),
1930+
},
1931+
},
1932+
{
1933+
name: "failure backoff included",
1934+
loopOut: []*loopdb.LoopOut{
1935+
{
1936+
Contract: &loopdb.LoopOutContract{
1937+
OutgoingChanSet: []uint64{
1938+
chanID1.ToUint64(),
1939+
},
1940+
},
1941+
Loop: loopdb.Loop{
1942+
Events: failedInBackoff,
1943+
},
1944+
},
1945+
{
1946+
Contract: &loopdb.LoopOutContract{
1947+
OutgoingChanSet: []uint64{
1948+
chanID2.ToUint64(),
1949+
},
1950+
},
1951+
Loop: loopdb.Loop{
1952+
Events: failedOutsideBackoff,
1953+
},
1954+
},
1955+
},
1956+
loopIn: []*loopdb.LoopIn{
1957+
{
1958+
Contract: &loopdb.LoopInContract{
1959+
LastHop: &peer1,
1960+
},
1961+
Loop: loopdb.Loop{
1962+
Events: failedTimeoutInBackoff,
1963+
},
1964+
},
1965+
{
1966+
Contract: &loopdb.LoopInContract{
1967+
LastHop: &peer2,
1968+
},
1969+
Loop: loopdb.Loop{
1970+
Events: failedTimeoutOutsideBackoff,
1971+
},
1972+
},
1973+
},
1974+
expected: &swapTraffic{
1975+
ongoingLoopOut: make(
1976+
map[lnwire.ShortChannelID]bool,
1977+
),
1978+
ongoingLoopIn: make(map[route.Vertex]bool),
1979+
failedLoopOut: map[lnwire.ShortChannelID]time.Time{
1980+
chanID1: withinBackoff,
1981+
},
1982+
failedLoopIn: map[route.Vertex]time.Time{
1983+
peer1: withinBackoff,
1984+
},
1985+
},
1986+
},
1987+
}
1988+
1989+
for _, testCase := range tests {
1990+
cfg, _ := newTestConfig()
1991+
m := NewManager(cfg)
1992+
1993+
params := m.GetParameters()
1994+
params.FailureBackOff = backoff
1995+
require.NoError(t, m.SetParameters(context.Background(), params))
1996+
1997+
actual := m.currentSwapTraffic(testCase.loopOut, testCase.loopIn)
1998+
require.Equal(t, testCase.expected, actual)
1999+
}
2000+
}

0 commit comments

Comments
 (0)