@@ -12,6 +12,7 @@ import (
1212 "github.com/btcsuite/btcd/txscript"
1313 "github.com/btcsuite/btcd/wire"
1414 "github.com/lightningnetwork/lnd/chainreg"
15+ "github.com/lightningnetwork/lnd/fn"
1516 "github.com/lightningnetwork/lnd/funding"
1617 "github.com/lightningnetwork/lnd/input"
1718 "github.com/lightningnetwork/lnd/labels"
@@ -1250,3 +1251,211 @@ func deriveFundingShim(ht *lntest.HarnessTest, carol, dave *node.HarnessNode,
12501251
12511252 return fundingShim , chanPoint
12521253}
1254+
1255+ // testChannelFundingWithUnstableUtxos tests channel openings with restricted
1256+ // utxo selection. Internal wallet utxos might be restricted due to another
1257+ // subsystems still using it therefore it would be unsecure to use them for
1258+ // channel openings. This test focuses on unconfirmed utxos which are still
1259+ // being used by the sweeper subsystem hence should only be used when confirmed.
1260+ func testChannelFundingWithUnstableUtxos (ht * lntest.HarnessTest ) {
1261+ // Select funding amt below wumbo size because we later use fundMax to
1262+ // open a channel with the total balance.
1263+ fundingAmt := btcutil .Amount (3_000_000 )
1264+
1265+ // We use STATIC_REMOTE_KEY channels because anchor sweeps would
1266+ // interfere and create additional utxos.
1267+ // Although its the current default we explicitly signal it.
1268+ cType := lnrpc .CommitmentType_STATIC_REMOTE_KEY
1269+
1270+ // First, we'll create two new nodes that we'll use to open channel
1271+ // between for this test.
1272+ carol := ht .NewNode ("carol" , nil )
1273+ // We'll attempt at max 2 pending channels, so Dave will need to accept
1274+ // two pending ones.
1275+ dave := ht .NewNode ("dave" , []string {
1276+ "--maxpendingchannels=2" ,
1277+ })
1278+ ht .EnsureConnected (carol , dave )
1279+
1280+ // Fund Carol's wallet with a confirmed utxo.
1281+ ht .FundCoins (fundingAmt , carol )
1282+
1283+ // Now spend the coins to create an unconfirmed transaction. This is
1284+ // necessary to test also the neutrino behaviour. For neutrino nodes
1285+ // only unconfirmed transactions originating from this node will be
1286+ // recognized as unconfirmed.
1287+ req := & lnrpc.NewAddressRequest {Type : AddrTypeTaprootPubkey }
1288+ resp := carol .RPC .NewAddress (req )
1289+
1290+ sendCoinsResp := carol .RPC .SendCoins (& lnrpc.SendCoinsRequest {
1291+ Addr : resp .Address ,
1292+ SendAll : true ,
1293+ SatPerVbyte : 1 ,
1294+ })
1295+
1296+ walletUtxo := ht .AssertNumUTXOsUnconfirmed (carol , 1 )[0 ]
1297+ require .EqualValues (ht , sendCoinsResp .Txid , walletUtxo .Outpoint .TxidStr )
1298+
1299+ // We will attempt to open 2 channels at a time.
1300+ chanSize := btcutil .Amount (walletUtxo .AmountSat / 3 )
1301+
1302+ // Open a channel to dave with an unconfirmed utxo. Although this utxo
1303+ // is unconfirmed it can be used to open a channel because it did not
1304+ // originated from the sweeper subsystem.
1305+ update := ht .OpenChannelAssertPending (carol , dave ,
1306+ lntest.OpenChannelParams {
1307+ Amt : chanSize ,
1308+ SpendUnconfirmed : true ,
1309+ CommitmentType : cType ,
1310+ })
1311+ chanPoint1 := lntest .ChanPointFromPendingUpdate (update )
1312+
1313+ // Verify that both nodes know about the channel.
1314+ ht .AssertNumPendingOpenChannels (carol , 1 )
1315+ ht .AssertNumPendingOpenChannels (dave , 1 )
1316+
1317+ // We open another channel on the fly, funds are unconfirmed but because
1318+ // the tx was not created by the sweeper we can use it and open another
1319+ // channel. This is a common use case when opening zeroconf channels,
1320+ // so unconfirmed utxos originated from prior channel opening are safe
1321+ // to use because channel opening should not be RBFed, at least not for
1322+ // now.
1323+ update = ht .OpenChannelAssertPending (carol , dave ,
1324+ lntest.OpenChannelParams {
1325+ Amt : chanSize ,
1326+ SpendUnconfirmed : true ,
1327+ CommitmentType : cType ,
1328+ })
1329+
1330+ chanPoint2 := lntest .ChanPointFromPendingUpdate (update )
1331+
1332+ ht .AssertNumPendingOpenChannels (carol , 2 )
1333+ ht .AssertNumPendingOpenChannels (dave , 2 )
1334+
1335+ // We expect the initial funding tx to confirm and also the two
1336+ // unconfirmed channel openings.
1337+ ht .MineBlocksAndAssertNumTxes (1 , 3 )
1338+
1339+ // Now we create an unconfirmed utxo which originated from the sweeper
1340+ // subsystem and hence is not safe to use for channel openings. We do
1341+ // that by dave force-closing the channel. Which let's carol sweep its
1342+ // to_remote output which is not encumbered by any relative locktime.
1343+ ht .CloseChannelAssertPending (dave , chanPoint2 , true )
1344+ // Mine the force close commitment transaction.
1345+ ht .MineBlocksAndAssertNumTxes (1 , 1 )
1346+
1347+ // Mine one block to trigger the sweep transaction.
1348+ ht .MineEmptyBlocks (1 )
1349+
1350+ // We need to wait for carol initiating the sweep of the to_remote
1351+ // output of chanPoint2.
1352+ utxos := ht .AssertNumUTXOsUnconfirmed (carol , 1 )
1353+
1354+ // We filter for the unconfirmed utxo and try to open a channel with
1355+ // that utxo.
1356+ utxoOpt := fn .Find (func (u * lnrpc.Utxo ) bool {
1357+ return u .Confirmations == 0
1358+ }, utxos )
1359+ fundingUtxo := utxoOpt .UnwrapOrFail (ht .T )
1360+
1361+ // Now try to open the channel with this utxo and expect an error.
1362+ expectedErr := fmt .Errorf ("outpoint already spent or " +
1363+ "locked by another subsystem: %s:%d" ,
1364+ fundingUtxo .Outpoint .TxidStr ,
1365+ fundingUtxo .Outpoint .OutputIndex )
1366+
1367+ ht .OpenChannelAssertErr (carol , dave ,
1368+ lntest.OpenChannelParams {
1369+ FundMax : true ,
1370+ SpendUnconfirmed : true ,
1371+ Outpoints : []* lnrpc.OutPoint {
1372+ fundingUtxo .Outpoint ,
1373+ },
1374+ }, expectedErr )
1375+
1376+ // The channel opening failed because the utxo was unconfirmed and
1377+ // originated from the sweeper subsystem. Now we confirm the
1378+ // to_remote sweep and expect the channel opening to work.
1379+ ht .MineBlocksAndAssertNumTxes (1 , 1 )
1380+
1381+ // Try opening the channel with the same utxo (now confirmed) again.
1382+ update = ht .OpenChannelAssertPending (carol , dave ,
1383+ lntest.OpenChannelParams {
1384+ FundMax : true ,
1385+ SpendUnconfirmed : true ,
1386+ Outpoints : []* lnrpc.OutPoint {
1387+ fundingUtxo .Outpoint ,
1388+ },
1389+ })
1390+
1391+ chanPoint3 := lntest .ChanPointFromPendingUpdate (update )
1392+ ht .AssertNumPendingOpenChannels (carol , 1 )
1393+ ht .AssertNumPendingOpenChannels (dave , 1 )
1394+
1395+ // We expect chanPoint3 to confirm.
1396+ ht .MineBlocksAndAssertNumTxes (1 , 1 )
1397+
1398+ // Force Close the channel and test the opening flow without preselected
1399+ // utxos.
1400+ // Before we tested the channel funding with a selected coin, now we
1401+ // want to make sure that our internal coin selection also adheres to
1402+ // the restictions of unstable utxos.
1403+ // We create the unconfirmed sweeper originating utxo just like before
1404+ // by force-closing a channel from dave's side.
1405+ ht .CloseChannelAssertPending (dave , chanPoint3 , true )
1406+ ht .MineBlocksAndAssertNumTxes (1 , 1 )
1407+
1408+ // Mine one block to trigger the sweep transaction.
1409+ ht .MineEmptyBlocks (1 )
1410+
1411+ // Wait for the to_remote sweep tx to show up in carol's wallet.
1412+ ht .AssertNumUTXOsUnconfirmed (carol , 1 )
1413+
1414+ // Calculate the maximum amount our wallet has for the channel funding
1415+ // so that we will use all utxos.
1416+ carolBalance := carol .RPC .WalletBalance ()
1417+
1418+ // Now calculate the fee for the channel opening transaction. We don't
1419+ // have to keep a channel reserve because we are using STATIC_REMOTE_KEY
1420+ // channels.
1421+ // NOTE: The TotalBalance includes the unconfirmed balance as well.
1422+ chanSize = btcutil .Amount (carolBalance .TotalBalance ) -
1423+ fundingFee (2 , false )
1424+
1425+ // We are trying to open a channel with the maximum amount and expect it
1426+ // to fail because one of the utxos cannot be used because it is
1427+ // unstable.
1428+ expectedErr = fmt .Errorf ("not enough witness outputs to create " +
1429+ "funding transaction" )
1430+
1431+ ht .OpenChannelAssertErr (carol , dave ,
1432+ lntest.OpenChannelParams {
1433+ Amt : chanSize ,
1434+ SpendUnconfirmed : true ,
1435+ CommitmentType : cType ,
1436+ }, expectedErr )
1437+
1438+ // Confirm the to_remote sweep utxo.
1439+ ht .MineBlocksAndAssertNumTxes (1 , 1 )
1440+
1441+ ht .AssertNumUTXOsConfirmed (carol , 2 )
1442+
1443+ // Now after the sweep utxo is confirmed it is stable and can be used
1444+ // for channel openings again.
1445+ update = ht .OpenChannelAssertPending (carol , dave ,
1446+ lntest.OpenChannelParams {
1447+ Amt : chanSize ,
1448+ SpendUnconfirmed : true ,
1449+ CommitmentType : cType ,
1450+ })
1451+ chanPoint4 := lntest .ChanPointFromPendingUpdate (update )
1452+
1453+ // Verify that both nodes know about the channel.
1454+ ht .AssertNumPendingOpenChannels (carol , 1 )
1455+ ht .AssertNumPendingOpenChannels (dave , 1 )
1456+
1457+ ht .MineBlocksAndAssertNumTxes (1 , 1 )
1458+
1459+ ht .CloseChannel (carol , chanPoint1 )
1460+ ht .CloseChannel (carol , chanPoint4 )
1461+ }
0 commit comments