Skip to content

Commit 03c5629

Browse files
committed
Fixed channel integration tests and Router use of UnwatchTxConfirmed
- Fixup tests to generate enough blocks to deeply confirm a channel has closed once before waiting for the channel to close. - Fixup so Router does not send `UnwatchTxConfirmed` only for the spending txs that will never confirm. Channel also has a `WatchTxConfirmed` event that may trigger later and should not be removed.
1 parent 0f250b1 commit 03c5629

File tree

3 files changed

+15
-28
lines changed

3 files changed

+15
-28
lines changed

eclair-core/src/main/scala/fr/acinq/eclair/router/Router.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ class Router(val nodeParams: NodeParams, watcher: typed.ActorRef[ZmqWatcher.Comm
269269

270270
case Event(WatchTxConfirmedTriggered(_, _, spendingTx), d) =>
271271
d.spentChannels.get(spendingTx.txid) match {
272-
case Some(shortChannelId) => stay() using Validation.handleChannelSpent(d, watcher, nodeParams.db.network, shortChannelId)
272+
case Some(shortChannelId) => stay() using Validation.handleChannelSpent(d, watcher, nodeParams.db.network, spendingTx.txid, shortChannelId)
273273
case None => stay()
274274
}
275275

eclair-core/src/main/scala/fr/acinq/eclair/router/Validation.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ object Validation {
267267
} else d1
268268
}
269269

270-
def handleChannelSpent(d: Data, watcher: typed.ActorRef[ZmqWatcher.Command], db: NetworkDb, shortChannelId: RealShortChannelId)(implicit ctx: ActorContext, log: LoggingAdapter): Data = {
270+
def handleChannelSpent(d: Data, watcher: typed.ActorRef[ZmqWatcher.Command], db: NetworkDb, spendingTxId: TxId, shortChannelId: RealShortChannelId)(implicit ctx: ActorContext, log: LoggingAdapter): Data = {
271271
implicit val sender: ActorRef = ctx.self // necessary to preserve origin when sending messages to other actors
272272
val lostChannel = d.channels.get(shortChannelId).orElse(d.prunedChannels.get(shortChannelId)).get
273273
log.info("funding tx for channelId={} was spent", shortChannelId)
@@ -294,7 +294,8 @@ object Validation {
294294
// we will re-add a spliced channel as a new channel later when we receive the announcement
295295
watcher ! UnwatchExternalChannelSpent(lostChannel.fundingTxId, outputIndex(lostChannel.ann.shortChannelId))
296296
val spendingTxs = d.spentChannels.filter(_._2 == shortChannelId).keySet
297-
spendingTxs.foreach(txId => watcher ! UnwatchTxConfirmed(txId))
297+
// stop watching the spending txs that will never confirm, but continue to watch the tx that spends the parent channel
298+
(spendingTxs - spendingTxId).foreach(txId => watcher ! UnwatchTxConfirmed(txId))
298299
val spentChannels1 = d.spentChannels -- spendingTxs
299300
d.copy(nodes = d.nodes -- lostNodes, channels = channels1, prunedChannels = prunedChannels1, graphWithBalances = graphWithBalances1, spentChannels = spentChannels1)
300301
}

eclair-core/src/test/scala/fr/acinq/eclair/integration/ChannelIntegrationSpec.scala

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -194,14 +194,11 @@ abstract class ChannelIntegrationSpec extends IntegrationSpec {
194194
val receivedByF = listReceivedByAddress(finalAddressF)
195195
(receivedByF diff previouslyReceivedByF).size == expectedTxCountF && (receivedByC diff previouslyReceivedByC).size == expectedTxCountC
196196
}, max = 30 seconds, interval = 1 second)
197-
// we generate blocks to make txs confirm
198-
generateBlocks(2, Some(minerAddress))
197+
// we generate enough blocks for the channel to be deeply confirmed
198+
generateBlocks(12, Some(minerAddress))
199199
// and we wait for the channel to close
200200
awaitCond(stateListenerC.expectMsgType[ChannelStateChanged](max = 60 seconds).currentState == CLOSED, max = 60 seconds)
201201
awaitCond(stateListenerF.expectMsgType[ChannelStateChanged](max = 60 seconds).currentState == CLOSED, max = 60 seconds)
202-
203-
// generate enough blocks so the router will know the channel has been closed and not spliced
204-
generateBlocks(12)
205202
awaitAnnouncements(1)
206203
}
207204

@@ -238,14 +235,11 @@ abstract class ChannelIntegrationSpec extends IntegrationSpec {
238235
val receivedByF = listReceivedByAddress(finalAddressF, sender)
239236
(receivedByF diff previouslyReceivedByF).size == expectedTxCountF && (receivedByC diff previouslyReceivedByC).size == expectedTxCountC
240237
}, max = 30 seconds, interval = 1 second)
241-
// we generate blocks to make txs confirm
242-
generateBlocks(2, Some(minerAddress))
238+
// we generate enough blocks for the channel to be deeply confirmed
239+
generateBlocks(12, Some(minerAddress))
243240
// and we wait for the channel to close
244241
awaitCond(stateListenerC.expectMsgType[ChannelStateChanged](max = 60 seconds).currentState == CLOSED, max = 60 seconds)
245242
awaitCond(stateListenerF.expectMsgType[ChannelStateChanged](max = 60 seconds).currentState == CLOSED, max = 60 seconds)
246-
247-
// generate enough blocks so the router will know the channel has been closed and not spliced
248-
generateBlocks(12)
249243
awaitAnnouncements(1)
250244
}
251245

@@ -294,14 +288,11 @@ abstract class ChannelIntegrationSpec extends IntegrationSpec {
294288
val receivedByF = listReceivedByAddress(finalAddressF, sender)
295289
(receivedByF diff previouslyReceivedByF).size == expectedTxCountF && (receivedByC diff previouslyReceivedByC).size == expectedTxCountC
296290
}, max = 30 seconds, interval = 1 second)
297-
// we generate blocks to make txs confirm
298-
generateBlocks(2, Some(minerAddress))
291+
// we generate enough blocks for the channel to be deeply confirmed
292+
generateBlocks(12, Some(minerAddress))
299293
// and we wait for the channel to close
300294
awaitCond(stateListenerC.expectMsgType[ChannelStateChanged](max = 60 seconds).currentState == CLOSED, max = 60 seconds)
301295
awaitCond(stateListenerF.expectMsgType[ChannelStateChanged](max = 60 seconds).currentState == CLOSED, max = 60 seconds)
302-
303-
// generate enough blocks so the router will know the channel has been closed and not spliced
304-
generateBlocks(12)
305296
awaitAnnouncements(1)
306297
}
307298

@@ -353,14 +344,11 @@ abstract class ChannelIntegrationSpec extends IntegrationSpec {
353344
val receivedByF = listReceivedByAddress(finalAddressF, sender)
354345
(receivedByF diff previouslyReceivedByF).size == expectedTxCountF && (receivedByC diff previouslyReceivedByC).size == expectedTxCountC
355346
}, max = 30 seconds, interval = 1 second)
356-
// we generate blocks to make tx confirm
357-
generateBlocks(2, Some(minerAddress))
347+
// we generate enough blocks for the channel to be deeply confirmed
348+
generateBlocks(12, Some(minerAddress))
358349
// and we wait for the channel to close
359350
awaitCond(stateListenerC.expectMsgType[ChannelStateChanged](max = 60 seconds).currentState == CLOSED, max = 60 seconds)
360351
awaitCond(stateListenerF.expectMsgType[ChannelStateChanged](max = 60 seconds).currentState == CLOSED, max = 60 seconds)
361-
362-
// generate enough blocks so the router will know the channel has been closed and not spliced
363-
generateBlocks(12)
364352
awaitAnnouncements(1)
365353
}
366354

@@ -599,15 +587,13 @@ class StandardChannelIntegrationSpec extends ChannelIntegrationSpec {
599587
bitcoinClient.getMempool().pipeTo(sender.ref)
600588
sender.expectMsgType[Seq[Transaction]].exists(_.txIn.head.outPoint.txid == fundingOutpoint.txid)
601589
}, max = 20 seconds, interval = 1 second)
602-
generateBlocks(3)
590+
// we generate enough blocks for the channel to be deeply confirmed
591+
generateBlocks(12)
603592
awaitCond(stateListener.expectMsgType[ChannelStateChanged](max = 60 seconds).currentState == CLOSED, max = 60 seconds)
604593

605-
bitcoinClient.lookForSpendingTx(None, fundingOutpoint.txid, fundingOutpoint.index.toInt, limit = 10).pipeTo(sender.ref)
594+
bitcoinClient.lookForSpendingTx(None, fundingOutpoint.txid, fundingOutpoint.index.toInt, limit = 12).pipeTo(sender.ref)
606595
val closingTx = sender.expectMsgType[Transaction]
607596
assert(closingTx.txOut.map(_.publicKeyScript).toSet == Set(finalPubKeyScriptC, finalPubKeyScriptF))
608-
609-
// generate enough blocks so the router will know the channel has been closed and not spliced
610-
generateBlocks(12)
611597
awaitAnnouncements(1)
612598
}
613599

0 commit comments

Comments
 (0)