@@ -207,7 +207,7 @@ func TestAutoLoopEnabled(t *testing.T) {
207207 Events : []* loopdb.LoopEvent {
208208 {
209209 SwapStateData : loopdb.SwapStateData {
210- State : loopdb .StateInitiated ,
210+ State : loopdb .StateSuccess ,
211211 },
212212 },
213213 },
@@ -472,7 +472,7 @@ func TestAutoloopAddress(t *testing.T) {
472472 Events : []* loopdb.LoopEvent {
473473 {
474474 SwapStateData : loopdb.SwapStateData {
475- State : loopdb .StateHtlcPublished ,
475+ State : loopdb .StateSuccess ,
476476 },
477477 },
478478 },
@@ -647,7 +647,7 @@ func TestCompositeRules(t *testing.T) {
647647 Events : []* loopdb.LoopEvent {
648648 {
649649 SwapStateData : loopdb.SwapStateData {
650- State : loopdb .StateHtlcPublished ,
650+ State : loopdb .StateSuccess ,
651651 },
652652 },
653653 },
@@ -984,7 +984,7 @@ func TestAutoloopBothTypes(t *testing.T) {
984984 Events : []* loopdb.LoopEvent {
985985 {
986986 SwapStateData : loopdb.SwapStateData {
987- State : loopdb .StateHtlcPublished ,
987+ State : loopdb .SwapState ( loopdb . StateSuccess ) ,
988988 },
989989 },
990990 },
@@ -1162,15 +1162,28 @@ func TestAutoLoopRecurringBudget(t *testing.T) {
11621162 },
11631163 },
11641164 }
1165+
1166+ singleLoopOut = & loopdb.LoopOut {
1167+ Loop : loopdb.Loop {
1168+ Events : []* loopdb.LoopEvent {
1169+ {
1170+ SwapStateData : loopdb.SwapStateData {
1171+ State : loopdb .SwapState (loopdb .StateSuccess ),
1172+ },
1173+ },
1174+ },
1175+ },
1176+ }
11651177 )
11661178
11671179 // Tick our autolooper with no existing swaps, we expect a loop out
11681180 // swap to be dispatched on first channel.
11691181 step := & autoloopStep {
1170- minAmt : 1 ,
1171- maxAmt : amt + 1 ,
1172- quotesOut : quotes1 ,
1173- expectedOut : loopOuts1 ,
1182+ minAmt : 1 ,
1183+ maxAmt : amt + 1 ,
1184+ quotesOut : quotes1 ,
1185+ expectedOut : loopOuts1 ,
1186+ existingOutSingle : singleLoopOut ,
11741187 }
11751188 c .autoloop (step )
11761189
@@ -1188,11 +1201,12 @@ func TestAutoLoopRecurringBudget(t *testing.T) {
11881201 }
11891202
11901203 step = & autoloopStep {
1191- minAmt : 1 ,
1192- maxAmt : amt + 1 ,
1193- quotesOut : quotes2 ,
1194- existingOut : existing ,
1195- expectedOut : nil ,
1204+ minAmt : 1 ,
1205+ maxAmt : amt + 1 ,
1206+ quotesOut : quotes2 ,
1207+ existingOut : existing ,
1208+ expectedOut : nil ,
1209+ existingOutSingle : singleLoopOut ,
11961210 }
11971211 // Tick again, we should expect no loop outs because our budget would be
11981212 // exceeded.
@@ -1222,11 +1236,12 @@ func TestAutoLoopRecurringBudget(t *testing.T) {
12221236 c .testClock .SetTime (testTime .Add (time .Hour * 25 ))
12231237
12241238 step = & autoloopStep {
1225- minAmt : 1 ,
1226- maxAmt : amt + 1 ,
1227- quotesOut : quotes2 ,
1228- existingOut : existing2 ,
1229- expectedOut : loopOuts2 ,
1239+ minAmt : 1 ,
1240+ maxAmt : amt + 1 ,
1241+ quotesOut : quotes2 ,
1242+ existingOut : existing2 ,
1243+ expectedOut : loopOuts2 ,
1244+ existingOutSingle : singleLoopOut ,
12301245 }
12311246
12321247 // Tick again, we should expect a loop out to occur on the 2nd channel.
@@ -1235,6 +1250,177 @@ func TestAutoLoopRecurringBudget(t *testing.T) {
12351250 c .stop ()
12361251}
12371252
1253+ // TestEasyAutoloop tests that the easy autoloop logic works as expected. This
1254+ // involves testing that channels are correctly selected and that the balance
1255+ // target is successfully met.
1256+ func TestEasyAutoloop (t * testing.T ) {
1257+ defer test .Guard (t )
1258+
1259+ // We need to change the default channels we use for tests so that they
1260+ // have different local balances in order to know which one is going to
1261+ // be selected by easy autoloop.
1262+ easyChannel1 := lndclient.ChannelInfo {
1263+ Active : true ,
1264+ ChannelID : chanID1 .ToUint64 (),
1265+ PubKeyBytes : peer1 ,
1266+ LocalBalance : 95000 ,
1267+ RemoteBalance : 0 ,
1268+ Capacity : 100000 ,
1269+ }
1270+
1271+ easyChannel2 := lndclient.ChannelInfo {
1272+ Active : true ,
1273+ ChannelID : chanID1 .ToUint64 (),
1274+ PubKeyBytes : peer1 ,
1275+ LocalBalance : 75000 ,
1276+ RemoteBalance : 0 ,
1277+ Capacity : 100000 ,
1278+ }
1279+
1280+ var (
1281+ channels = []lndclient.ChannelInfo {
1282+ easyChannel1 , easyChannel2 ,
1283+ }
1284+
1285+ params = Parameters {
1286+ Autoloop : true ,
1287+ AutoFeeBudget : 36000 ,
1288+ AutoFeeRefreshPeriod : time .Hour * 3 ,
1289+ AutoloopBudgetLastRefresh : testBudgetStart ,
1290+ MaxAutoInFlight : 2 ,
1291+ FailureBackOff : time .Hour ,
1292+ SweepConfTarget : 10 ,
1293+ HtlcConfTarget : defaultHtlcConfTarget ,
1294+ EasyAutoloop : true ,
1295+ EasyAutoloopTarget : 75000 ,
1296+ FeeLimit : defaultFeePortion (),
1297+ }
1298+ )
1299+
1300+ c := newAutoloopTestCtx (t , params , channels , testRestrictions )
1301+ c .start ()
1302+
1303+ var (
1304+ maxAmt = 50000
1305+
1306+ chan1Swap = & loop.OutRequest {
1307+ Amount : btcutil .Amount (maxAmt ),
1308+ OutgoingChanSet : loopdb.ChannelSet {easyChannel1 .ChannelID },
1309+ Label : labels .AutoloopLabel (swap .TypeOut ),
1310+ Initiator : autoloopSwapInitiator ,
1311+ }
1312+
1313+ quotesOut1 = []quoteRequestResp {
1314+ {
1315+ request : & loop.LoopOutQuoteRequest {
1316+ Amount : btcutil .Amount (maxAmt ),
1317+ },
1318+ quote : & loop.LoopOutQuote {
1319+ SwapFee : 1 ,
1320+ PrepayAmount : 1 ,
1321+ MinerFee : 1 ,
1322+ },
1323+ },
1324+ }
1325+
1326+ loopOut1 = []loopOutRequestResp {
1327+ {
1328+ request : chan1Swap ,
1329+ response : & loop.LoopOutSwapInfo {
1330+ SwapHash : lntypes.Hash {1 },
1331+ },
1332+ },
1333+ }
1334+ )
1335+
1336+ // We expected one max size swap to be dispatched on our channel with
1337+ // the biggest local balance.
1338+ step := & easyAutoloopStep {
1339+ minAmt : 1 ,
1340+ maxAmt : 50000 ,
1341+ quotesOut : quotesOut1 ,
1342+ expectedOut : loopOut1 ,
1343+ }
1344+
1345+ c .easyautoloop (step , false )
1346+ c .stop ()
1347+
1348+ // In order to reflect the change on the channel balances we create a
1349+ // new context and restart the autolooper.
1350+ easyChannel1 .LocalBalance -= chan1Swap .Amount
1351+ channels = []lndclient.ChannelInfo {
1352+ easyChannel1 , easyChannel2 ,
1353+ }
1354+
1355+ c = newAutoloopTestCtx (t , params , channels , testRestrictions )
1356+ c .start ()
1357+
1358+ var (
1359+ amt2 = 45_000
1360+
1361+ chan2Swap = & loop.OutRequest {
1362+ Amount : btcutil .Amount (amt2 ),
1363+ OutgoingChanSet : loopdb.ChannelSet {easyChannel2 .ChannelID },
1364+ Label : labels .AutoloopLabel (swap .TypeOut ),
1365+ Initiator : autoloopSwapInitiator ,
1366+ }
1367+
1368+ quotesOut2 = []quoteRequestResp {
1369+ {
1370+ request : & loop.LoopOutQuoteRequest {
1371+ Amount : btcutil .Amount (amt2 ),
1372+ },
1373+ quote : & loop.LoopOutQuote {
1374+ SwapFee : 1 ,
1375+ PrepayAmount : 1 ,
1376+ MinerFee : 1 ,
1377+ },
1378+ },
1379+ }
1380+
1381+ loopOut2 = []loopOutRequestResp {
1382+ {
1383+ request : chan2Swap ,
1384+ response : & loop.LoopOutSwapInfo {
1385+ SwapHash : lntypes.Hash {1 },
1386+ },
1387+ },
1388+ }
1389+ )
1390+
1391+ // We expect a swap of size 45_000 to be dispatched in order to meet the
1392+ // defined target of 75_000.
1393+ step = & easyAutoloopStep {
1394+ minAmt : 1 ,
1395+ maxAmt : 50000 ,
1396+ quotesOut : quotesOut2 ,
1397+ expectedOut : loopOut2 ,
1398+ }
1399+
1400+ c .easyautoloop (step , false )
1401+ c .stop ()
1402+
1403+ // In order to reflect the change on the channel balances we create a
1404+ // new context and restart the autolooper.
1405+ easyChannel2 .LocalBalance -= btcutil .Amount (amt2 )
1406+ channels = []lndclient.ChannelInfo {
1407+ easyChannel1 , easyChannel2 ,
1408+ }
1409+
1410+ c = newAutoloopTestCtx (t , params , channels , testRestrictions )
1411+ c .start ()
1412+
1413+ // We have met the target of 75_000 so we don't expect any action from
1414+ // easy autoloop. That's why we set noop to true in the call below.
1415+ step = & easyAutoloopStep {
1416+ minAmt : 1 ,
1417+ maxAmt : 50000 ,
1418+ }
1419+
1420+ c .easyautoloop (step , true )
1421+ c .stop ()
1422+ }
1423+
12381424// existingSwapFromRequest is a helper function which returns the db
12391425// representation of a loop out request with the event set provided.
12401426func existingSwapFromRequest (request * loop.OutRequest , initTime time.Time ,
0 commit comments