@@ -1230,7 +1230,7 @@ func testPresigned_presigned_group_with_change(t *testing.T,
12301230 presignedHelper .SetOutpointOnline (op1 , true )
12311231 presignedHelper .SetOutpointOnline (op2 , true )
12321232
1233- // An attempt to presign must fail.
1233+ // An attempt to presign shouldn't fail.
12341234 err = batcher .PresignSweepsGroup (
12351235 ctx , group1 , sweepTimeout , destAddr , change ,
12361236 )
@@ -1268,6 +1268,134 @@ func testPresigned_presigned_group_with_change(t *testing.T,
12681268 require .NoError (t , lnd .NotifyHeight (601 ))
12691269}
12701270
1271+ // testPresigned_presigned_group_with_identical_change_pkscript tests passing multiple sweeps to
1272+ // the method PresignSweepsGroup. It tests that a change output of a primary
1273+ // deposit sweep is properly added to the presigned transaction.
1274+ func testPresigned_presigned_group_with_identical_change_pkscript (t * testing.T ,
1275+ batcherStore testBatcherStore ) {
1276+
1277+ defer test .Guard (t )()
1278+
1279+ batchPkScript , err := txscript .PayToAddrScript (destAddr )
1280+ require .NoError (t , err )
1281+
1282+ lnd := test .NewMockLnd ()
1283+
1284+ ctx , cancel := context .WithCancel (context .Background ())
1285+ defer cancel ()
1286+
1287+ customFeeRate := func (_ context.Context , _ lntypes.Hash ,
1288+ _ wire.OutPoint ) (chainfee.SatPerKWeight , error ) {
1289+
1290+ return chainfee .SatPerKWeight (10_000 ), nil
1291+ }
1292+
1293+ presignedHelper := newMockPresignedHelper ()
1294+
1295+ batcher := NewBatcher (
1296+ lnd .WalletKit , lnd .ChainNotifier , lnd .Signer ,
1297+ testMuSig2SignSweep , testVerifySchnorrSig , lnd .ChainParams ,
1298+ batcherStore , presignedHelper ,
1299+ WithCustomFeeRate (customFeeRate ),
1300+ WithPresignedHelper (presignedHelper ),
1301+ )
1302+
1303+ go func () {
1304+ err := batcher .Run (ctx )
1305+ checkBatcherError (t , err )
1306+ }()
1307+
1308+ // Create two swaps of a single sweep
1309+ swapHash1 := lntypes.Hash {1 , 1 , 1 }
1310+ swapHash2 := lntypes.Hash {2 , 2 , 2 }
1311+ op1 := wire.OutPoint {
1312+ Hash : chainhash.Hash {1 , 1 },
1313+ Index : 1 ,
1314+ }
1315+ op2 := wire.OutPoint {
1316+ Hash : chainhash.Hash {2 , 2 },
1317+ Index : 2 ,
1318+ }
1319+ group1 := []Input {
1320+ {
1321+ Outpoint : op1 ,
1322+ Value : 1_000_000 ,
1323+ },
1324+ }
1325+ change1 := & wire.TxOut {
1326+ Value : 500_000 ,
1327+ PkScript : []byte {0xaf , 0xfe },
1328+ }
1329+ group2 := []Input {
1330+ {
1331+ Outpoint : op2 ,
1332+ Value : 2_000_000 ,
1333+ },
1334+ }
1335+ change2 := & wire.TxOut {
1336+ Value : 600_000 ,
1337+ PkScript : []byte {0xaf , 0xfe },
1338+ }
1339+
1340+ presignedHelper .setChangeForPrimaryDeposit (op1 , change1 )
1341+ presignedHelper .setChangeForPrimaryDeposit (op2 , change2 )
1342+
1343+ // Enable only one of the sweeps.
1344+ presignedHelper .SetOutpointOnline (op1 , true )
1345+ presignedHelper .SetOutpointOnline (op2 , true )
1346+
1347+ // An attempt to presign group1 shouldn't fail.
1348+ err = batcher .PresignSweepsGroup (
1349+ ctx , group1 , sweepTimeout , destAddr , change1 ,
1350+ )
1351+ require .NoError (t , err )
1352+
1353+ // Add the sweep, triggering the publishing attempt.
1354+ err = batcher .AddSweep (ctx , & SweepRequest {
1355+ SwapHash : swapHash1 ,
1356+ Inputs : group1 ,
1357+ Notifier : & dummyNotifier ,
1358+ })
1359+ require .NoError (t , err )
1360+
1361+ // Since a batch was created we check that it registered for its primary
1362+ // sweep's spend.
1363+ <- lnd .RegisterSpendChannel
1364+
1365+ // An attempt to presign group2 shouldn't fail.
1366+ err = batcher .PresignSweepsGroup (
1367+ ctx , group2 , sweepTimeout , destAddr , change2 ,
1368+ )
1369+ require .NoError (t , err )
1370+
1371+ // Add the sweep, triggering the publishing attempt.
1372+ err = batcher .AddSweep (ctx , & SweepRequest {
1373+ SwapHash : swapHash2 ,
1374+ Inputs : group2 ,
1375+ Notifier : & dummyNotifier ,
1376+ })
1377+ require .NoError (t , err )
1378+
1379+ // Wait for a transactions to be published.
1380+ tx := <- lnd .TxPublishChannel
1381+ require .Len (t , tx .TxIn , 2 )
1382+ require .Len (t , tx .TxOut , 2 )
1383+ require .ElementsMatch (
1384+ t , []wire.OutPoint {op1 , op2 },
1385+ []wire.OutPoint {
1386+ tx .TxIn [0 ].PreviousOutPoint ,
1387+ tx .TxIn [1 ].PreviousOutPoint ,
1388+ },
1389+ )
1390+ require .Equal (t , int64 (1_893_300 ), tx .TxOut [0 ].Value )
1391+ require .Equal (t , change1 .Value + change2 .Value , tx .TxOut [1 ].Value )
1392+ require .Equal (t , batchPkScript , tx .TxOut [0 ].PkScript )
1393+ require .Equal (t , change1 .PkScript , tx .TxOut [1 ].PkScript )
1394+
1395+ // Mine a blocks to trigger republishing.
1396+ require .NoError (t , lnd .NotifyHeight (601 ))
1397+ }
1398+
12711399// testPresigned_presigned_group_with_dust_main_output passes a dust main output
12721400// and a change output to PresignSweepsGroup. It will fail because of the dust
12731401// main output. Note that the min relay fee is set low enough to pass the
@@ -2224,6 +2352,10 @@ func TestPresigned(t *testing.T) {
22242352 testPresigned_presigned_group_with_change (t , NewStoreMock ())
22252353 })
22262354
2355+ t .Run ("identical change pkscript" , func (t * testing.T ) {
2356+ testPresigned_presigned_group_with_identical_change_pkscript (t , NewStoreMock ())
2357+ })
2358+
22272359 t .Run ("dust_main_output" , func (t * testing.T ) {
22282360 testPresigned_presigned_group_with_dust_main_output (
22292361 t , NewStoreMock (),
0 commit comments