@@ -20,6 +20,7 @@ import (
20
20
"github.com/lightninglabs/loop/loopdb"
21
21
"github.com/lightninglabs/loop/swap"
22
22
"github.com/lightninglabs/loop/utils"
23
+ "github.com/lightningnetwork/lnd/chainntnfs"
23
24
"github.com/lightningnetwork/lnd/clock"
24
25
"github.com/lightningnetwork/lnd/input"
25
26
"github.com/lightningnetwork/lnd/lntypes"
@@ -280,6 +281,8 @@ type addSweepsRequest struct {
280
281
parentBatch * dbBatch
281
282
}
282
283
284
+ // SpendDetail is a notification that is send to the user of sweepbatcher when
285
+ // a batch gets the first confirmation.
283
286
type SpendDetail struct {
284
287
// Tx is the transaction that spent the outpoint.
285
288
Tx * wire.MsgTx
@@ -291,6 +294,19 @@ type SpendDetail struct {
291
294
OnChainFeePortion btcutil.Amount
292
295
}
293
296
297
+ // ConfDetail is a notification that is send to the user of sweepbatcher when
298
+ // a batch is fully confirmed, i.e. gets batchConfHeight confirmations.
299
+ type ConfDetail struct {
300
+ // TxConfirmation has data about the confirmation of the transaction.
301
+ * chainntnfs.TxConfirmation
302
+
303
+ // OnChainFeePortion is the fee portion that was paid to get this sweep
304
+ // confirmed on chain. This is the difference between the value of the
305
+ // outpoint and the value of all sweeps that were included in the batch
306
+ // divided by the number of sweeps.
307
+ OnChainFeePortion btcutil.Amount
308
+ }
309
+
294
310
// SpendNotifier is a notifier that is used to notify the requester of a sweep
295
311
// that the sweep was successful.
296
312
type SpendNotifier struct {
@@ -300,6 +316,14 @@ type SpendNotifier struct {
300
316
// SpendErrChan is a channel where spend errors are received.
301
317
SpendErrChan chan <- error
302
318
319
+ // ConfChan is a channel where the confirmation details are received.
320
+ // This channel is optional.
321
+ ConfChan chan <- * ConfDetail
322
+
323
+ // ConfErrChan is a channel where confirmation errors are received.
324
+ // This channel is optional.
325
+ ConfErrChan chan <- error
326
+
303
327
// QuitChan is a channel that can be closed to stop the notifier.
304
328
QuitChan <- chan bool
305
329
}
@@ -1114,7 +1138,9 @@ func (b *Batcher) FetchUnconfirmedBatches(ctx context.Context) ([]*batch,
1114
1138
}
1115
1139
1116
1140
// monitorSpendAndNotify monitors the spend of a specific outpoint and writes
1117
- // the response back to the response channel.
1141
+ // the response back to the response channel. It is called if the batch is fully
1142
+ // confirmed and we just need to deliver the data back to the caller though
1143
+ // SpendNotifier.
1118
1144
func (b * Batcher ) monitorSpendAndNotify (ctx context.Context , sweep * sweep ,
1119
1145
parentBatchID int32 , notifier * SpendNotifier ) error {
1120
1146
@@ -1172,6 +1198,16 @@ func (b *Batcher) monitorSpendAndNotify(ctx context.Context, sweep *sweep,
1172
1198
select {
1173
1199
// Try to write the update to the notification channel.
1174
1200
case notifier .SpendChan <- spendDetail :
1201
+ err := b .monitorConfAndNotify (
1202
+ ctx , sweep , notifier , spendTx ,
1203
+ onChainFeePortion ,
1204
+ )
1205
+ if err != nil {
1206
+ b .writeToErrChan (
1207
+ ctx , fmt .Errorf ("monitor conf " +
1208
+ "failed: %w" , err ),
1209
+ )
1210
+ }
1175
1211
1176
1212
// If a quit signal was provided by the swap, continue.
1177
1213
case <- notifier .QuitChan :
@@ -1215,6 +1251,84 @@ func (b *Batcher) monitorSpendAndNotify(ctx context.Context, sweep *sweep,
1215
1251
return nil
1216
1252
}
1217
1253
1254
+ // monitorConfAndNotify monitors the confirmation of a specific transaction and
1255
+ // writes the response back to the response channel. It is called if the batch
1256
+ // is fully confirmed and we just need to deliver the data back to the caller
1257
+ // though SpendNotifier.
1258
+ func (b * Batcher ) monitorConfAndNotify (ctx context.Context , sweep * sweep ,
1259
+ notifier * SpendNotifier , spendTx * wire.MsgTx ,
1260
+ onChainFeePortion btcutil.Amount ) error {
1261
+
1262
+ // If confirmation notifications were not requested, stop.
1263
+ if notifier .ConfChan == nil && notifier .ConfErrChan == nil {
1264
+ return nil
1265
+ }
1266
+
1267
+ batchTxid := spendTx .TxHash ()
1268
+
1269
+ if len (spendTx .TxOut ) != 1 {
1270
+ return fmt .Errorf ("unexpected number of outputs in batch: %d, " +
1271
+ "want %d" , len (spendTx .TxOut ), 1 )
1272
+ }
1273
+ batchPkScript := spendTx .TxOut [0 ].PkScript
1274
+
1275
+ reorgChan := make (chan struct {})
1276
+
1277
+ confCtx , cancel := context .WithCancel (ctx )
1278
+
1279
+ confChan , errChan , err := b .chainNotifier .RegisterConfirmationsNtfn (
1280
+ confCtx , & batchTxid , batchPkScript , batchConfHeight ,
1281
+ sweep .initiationHeight , lndclient .WithReOrgChan (reorgChan ),
1282
+ )
1283
+ if err != nil {
1284
+ cancel ()
1285
+ return err
1286
+ }
1287
+
1288
+ b .wg .Add (1 )
1289
+ go func () {
1290
+ defer cancel ()
1291
+ defer b .wg .Done ()
1292
+
1293
+ select {
1294
+ case conf := <- confChan :
1295
+ if notifier .ConfChan != nil {
1296
+ confDetail := & ConfDetail {
1297
+ TxConfirmation : conf ,
1298
+ OnChainFeePortion : onChainFeePortion ,
1299
+ }
1300
+
1301
+ select {
1302
+ case notifier .ConfChan <- confDetail :
1303
+ case <- notifier .QuitChan :
1304
+ case <- ctx .Done ():
1305
+ }
1306
+ }
1307
+
1308
+ case err := <- errChan :
1309
+ if notifier .ConfErrChan != nil {
1310
+ select {
1311
+ case notifier .ConfErrChan <- err :
1312
+ case <- notifier .QuitChan :
1313
+ case <- ctx .Done ():
1314
+ }
1315
+ }
1316
+
1317
+ b .writeToErrChan (ctx , fmt .Errorf ("confirmations " +
1318
+ "monitoring error: %w" , err ))
1319
+
1320
+ case <- reorgChan :
1321
+ // A re-org has been detected, but the batch is fully
1322
+ // confirmed and this is unexpected. Crash the batcher.
1323
+ b .writeToErrChan (ctx , fmt .Errorf ("unexpected reorg" ))
1324
+
1325
+ case <- ctx .Done ():
1326
+ }
1327
+ }()
1328
+
1329
+ return nil
1330
+ }
1331
+
1218
1332
func (b * Batcher ) writeToErrChan (ctx context.Context , err error ) {
1219
1333
select {
1220
1334
case b .errChan <- err :
0 commit comments