Skip to content

Commit 93dab90

Browse files
committed
Re-work retransmission on reestablish
We introduce a `retransmit_flags` field to `my_current_funding_locked` and `next_funding` to ask our peer to retransmit `commitment_signed` or `announcement_signatures` if we're expecting them. With this change, we don't need to retransmit `splice_locked` on reconnection anymore to trigger the exchange of `announcement_signatures`. We don't need to retransmit it to let our peer know that we've seen enough confirmations for the splice either, since `my_current_funding_locked` implies that. This allows us to completely remove retransmission of `splice_locked` on reconnection, and also get rid of the `your_last_funding_locked` TLV, which greatly simplifies the reconnection logic. We do keep them for backwards-compatibility with existing Phoenix users though, but we'll be able to clean it up once they have updated. Note that this works with taproot channels since we will simply provide nonces in `channel_reestablish` when we need our peer to send announcement signatures (not supported yet since taproot channels are never announced). We rollback using the `next_commitment_number` to let our peer know that we haven't received their `commit_sig` and instead use the retransmit flags added to the `next_funding` TLV, unless our peer is using the legacy splicing protocol.
1 parent 575f5df commit 93dab90

12 files changed

Lines changed: 632 additions & 255 deletions

eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ case class ChannelParams(channelId: ByteVector32,
3333
val remoteNodeId: PublicKey = remoteParams.nodeId
3434
// If we've set the 0-conf feature bit for this peer, we will always use 0-conf with them.
3535
val zeroConf: Boolean = localParams.initFeatures.hasFeature(Features.ZeroConf)
36+
// TODO: we keep supporting the legacy splicing protocol for non-upgraded Phoenix users.
37+
lazy val useLegacySpliceProtocol = remoteParams.initFeatures.hasFeature(Features.SplicePrototype)
3638

3739
/** We update local/global features at reconnection. */
3840
def updateFeatures(localInit: Init, remoteInit: Init): ChannelParams = copy(

eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala

Lines changed: 130 additions & 64 deletions
Large diffs are not rendered by default.

eclair-core/src/main/scala/fr/acinq/eclair/channel/fund/InteractiveTxBuilder.scala

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,10 +1206,14 @@ object InteractiveTxSigningSession {
12061206
liquidityPurchase_opt: Option[LiquidityAds.PurchaseBasicInfo]) extends InteractiveTxSigningSession {
12071207
val fundingTxId: TxId = fundingTx.txId
12081208
val localCommitIndex: Long = localCommit.fold(_.index, _.index)
1209-
// This value tells our peer whether we need them to retransmit their commit_sig on reconnection or not.
1210-
val nextLocalCommitmentNumber: Long = localCommit match {
1211-
case Left(unsignedCommit) => unsignedCommit.index
1212-
case Right(commit) => commit.index + 1
1209+
// If we haven't received the remote commit_sig, we will request a retransmission on reconnection.
1210+
val retransmitRemoteCommitSig: Boolean = localCommit.isLeft
1211+
1212+
// For the legacy splice protocol, we use the next_commitment_number to let our peer know whether they needed to
1213+
// retransmit commit_sig or not. We're now using an explicit bit instead, but need to maintain backwards-compatibility.
1214+
def nextLocalCommitmentNumber(useLegacySpliceProtocol: Boolean): Long = localCommit match {
1215+
case Left(unsignedCommit) if useLegacySpliceProtocol => unsignedCommit.index
1216+
case _ => localCommitIndex + 1
12131217
}
12141218

12151219
def localFundingKey(channelKeys: ChannelKeys): PrivateKey = channelKeys.fundingKey(fundingTxIndex)

eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/ChannelTlv.scala

Lines changed: 63 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
package fr.acinq.eclair.wire.protocol
1818

1919
import fr.acinq.bitcoin.scalacompat.Musig2.IndividualNonce
20-
import fr.acinq.bitcoin.scalacompat.{ByteVector32, ByteVector64, Satoshi, TxId}
20+
import fr.acinq.bitcoin.scalacompat.{ByteVector32, ByteVector64, Satoshi, TxHash, TxId}
2121
import fr.acinq.eclair.channel.ChannelSpendSignature.PartialSignatureWithNonce
2222
import fr.acinq.eclair.channel.{ChannelType, ChannelTypes}
2323
import fr.acinq.eclair.wire.protocol.CommonCodecs._
@@ -255,17 +255,48 @@ sealed trait ChannelReestablishTlv extends Tlv
255255

256256
object ChannelReestablishTlv {
257257

258+
/** TODO: replaced by [[NextFundingTlv]], remove once Phoenix users have upgraded. */
259+
case class ExperimentalNextFundingTlv(txId: TxId) extends ChannelReestablishTlv
260+
261+
/**
262+
* We unfortunately have a conflict between the splicing protocol we use for Phoenix and the official one.
263+
* The official protocol uses TLV = 1 for the next_funding TLV, which should be implemented by [[NextFundingTlv]]
264+
* (which is commented out below).
265+
* The splicing protocol used for Phoenix also uses TLV = 1, but for a different TLV that was removed from the
266+
* official splicing protocol (your_last_funding_locked), which contained the txid of the last [[ChannelReady]] or
267+
* [[SpliceLocked]] message received before disconnecting, if any.
268+
*
269+
* To guarantee backwards-compatibility, we create a TLV field that may contain both options. When using the official
270+
* splicing protocol, it will contain 33 bytes (a txid and a bitfield), while when using the legacy protocol it only
271+
* contains a txid, which lets us easily distinguish the two.
272+
*
273+
* TODO: once we can remove support for Phoenix users with the legacy splicing protocol, this should just be replaced
274+
* by [[NextFundingTlv]] which is commented out below and should be uncommented.
275+
*/
276+
case class NextFundingOrExperimentalYourLastFundingLockedTlv(data: ByteVector) extends ChannelReestablishTlv {
277+
val isOfficial: Boolean = data.size == 33
278+
val txId: TxId = TxId(TxHash(ByteVector32(data.take(32))))
279+
// NB: this is only used for the official splicing protocol.
280+
val retransmitCommitSig: Boolean = if (isOfficial) (data.last.toInt % 2) == 1 else false
281+
}
282+
258283
/**
259284
* When disconnected in the middle of an interactive-tx session, this field is used to request a retransmission of
260285
* [[TxSignatures]] for the given [[txId]].
286+
*
287+
* @param txId the txid of the partially signed funding transaction.
288+
* @param retransmitCommitSig true if [[CommitSig]] must be retransmitted before [[TxSignatures]].
261289
*/
262-
case class NextFundingTlv(txId: TxId) extends ChannelReestablishTlv
290+
// case class NextFundingTlv(txId: TxId, retransmitCommitSig: Boolean) extends ChannelReestablishTlv
263291

264-
/** The txid of the last [[ChannelReady]] or [[SpliceLocked]] message received before disconnecting, if any. */
265-
case class YourLastFundingLockedTlv(txId: TxId) extends ChannelReestablishTlv
292+
/** TODO: replaced by [[MyCurrentFundingLockedTlv]], remove once Phoenix users have upgraded. */
293+
case class ExperimentalMyCurrentFundingLockedTlv(txId: TxId) extends ChannelReestablishTlv
266294

267-
/** The txid of our latest outgoing [[ChannelReady]] or [[SpliceLocked]] for this channel. */
268-
case class MyCurrentFundingLockedTlv(txId: TxId) extends ChannelReestablishTlv
295+
/**
296+
* @param txId the txid of our latest outgoing [[ChannelReady]] or [[SpliceLocked]] for this channel.
297+
* @param retransmitAnnSigs true if [[AnnouncementSignatures]] must be retransmitted.
298+
*/
299+
case class MyCurrentFundingLockedTlv(txId: TxId, retransmitAnnSigs: Boolean) extends ChannelReestablishTlv
269300

270301
/**
271302
* When disconnected during an interactive tx session, we'll include a verification nonce for our *current* commitment
@@ -280,16 +311,31 @@ object ChannelReestablishTlv {
280311
*/
281312
case class NextLocalNoncesTlv(nonces: Seq[(TxId, IndividualNonce)]) extends ChannelReestablishTlv
282313

283-
object NextFundingTlv {
284-
val codec: Codec[NextFundingTlv] = tlvField(txIdAsHash)
314+
object ExperimentalNextFundingTlv {
315+
val codec: Codec[ExperimentalNextFundingTlv] = tlvField(txIdAsHash)
316+
}
317+
318+
// object NextFundingTlv {
319+
// val codec: Codec[NextFundingTlv] = tlvField(("next_funding_txid" | txIdAsHash) :: ("retransmit_flags" | (ignore(7) :: bool)))
320+
// }
321+
322+
object NextFundingOrExperimentalYourLastFundingLockedTlv {
323+
def asNextFunding(txId: TxId, retransmitCommitSig: Boolean): NextFundingOrExperimentalYourLastFundingLockedTlv = {
324+
val retransmitFlags = if (retransmitCommitSig) ByteVector.fromValidHex("01") else ByteVector.fromValidHex("00")
325+
NextFundingOrExperimentalYourLastFundingLockedTlv(TxHash(txId).value ++ retransmitFlags)
326+
}
327+
328+
def asExperimentalYourLastFundingLocked(txId: TxId): NextFundingOrExperimentalYourLastFundingLockedTlv = NextFundingOrExperimentalYourLastFundingLockedTlv(TxHash(txId).value)
329+
330+
val codec: Codec[NextFundingOrExperimentalYourLastFundingLockedTlv] = tlvField(bytes)
285331
}
286332

287-
object YourLastFundingLockedTlv {
288-
val codec: Codec[YourLastFundingLockedTlv] = tlvField("your_last_funding_locked_txid" | txIdAsHash)
333+
object ExperimentalMyCurrentFundingLockedTlv {
334+
val codec: Codec[ExperimentalMyCurrentFundingLockedTlv] = tlvField("my_current_funding_locked_txid" | txIdAsHash)
289335
}
290336

291337
object MyCurrentFundingLockedTlv {
292-
val codec: Codec[MyCurrentFundingLockedTlv] = tlvField("my_current_funding_locked_txid" | txIdAsHash)
338+
val codec: Codec[MyCurrentFundingLockedTlv] = tlvField(("my_current_funding_locked_txid" | txIdAsHash) :: ("retransmit_flags" | (ignore(7) :: bool)))
293339
}
294340

295341
object CurrentCommitNonceTlv {
@@ -301,9 +347,12 @@ object ChannelReestablishTlv {
301347
}
302348

303349
val channelReestablishTlvCodec: Codec[TlvStream[ChannelReestablishTlv]] = tlvStream(discriminated[ChannelReestablishTlv].by(varint)
304-
.typecase(UInt64(0), NextFundingTlv.codec)
305-
.typecase(UInt64(1), YourLastFundingLockedTlv.codec)
306-
.typecase(UInt64(3), MyCurrentFundingLockedTlv.codec)
350+
.typecase(UInt64(0), ExperimentalNextFundingTlv.codec)
351+
// TODO: replace with the commented line below when removing support for the legacy splicing protocol.
352+
.typecase(UInt64(1), NextFundingOrExperimentalYourLastFundingLockedTlv.codec)
353+
// .typecase(UInt64(1), NextFundingTlv.codec)
354+
.typecase(UInt64(3), ExperimentalMyCurrentFundingLockedTlv.codec)
355+
.typecase(UInt64(5), MyCurrentFundingLockedTlv.codec)
307356
.typecase(UInt64(22), NextLocalNoncesTlv.codec)
308357
.typecase(UInt64(24), CurrentCommitNonceTlv.codec)
309358
)

eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/LightningMessageTypes.scala

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,17 @@ case class ChannelReestablish(channelId: ByteVector32,
212212
yourLastPerCommitmentSecret: PrivateKey,
213213
myCurrentPerCommitmentPoint: PublicKey,
214214
tlvStream: TlvStream[ChannelReestablishTlv] = TlvStream.empty) extends ChannelMessage with HasChannelId {
215-
val nextFundingTxId_opt: Option[TxId] = tlvStream.get[ChannelReestablishTlv.NextFundingTlv].map(_.txId)
216-
val myCurrentFundingLocked_opt: Option[TxId] = tlvStream.get[ChannelReestablishTlv.MyCurrentFundingLockedTlv].map(_.txId)
217-
val yourLastFundingLocked_opt: Option[TxId] = tlvStream.get[ChannelReestablishTlv.YourLastFundingLockedTlv].map(_.txId)
215+
val nextFundingTxId_opt: Option[TxId] = tlvStream.get[ChannelReestablishTlv.NextFundingOrExperimentalYourLastFundingLockedTlv] match {
216+
case Some(tlv) if tlv.isOfficial => Some(tlv.txId)
217+
case _ => tlvStream.get[ChannelReestablishTlv.ExperimentalNextFundingTlv].map(_.txId)
218+
}
219+
val retransmitInteractiveTxCommitSig: Boolean = tlvStream.get[ChannelReestablishTlv.NextFundingOrExperimentalYourLastFundingLockedTlv].exists(_.retransmitCommitSig)
220+
val myCurrentFundingLocked_opt: Option[TxId] = tlvStream.get[ChannelReestablishTlv.MyCurrentFundingLockedTlv].map(_.txId).orElse(tlvStream.get[ChannelReestablishTlv.ExperimentalMyCurrentFundingLockedTlv].map(_.txId))
221+
val yourLastFundingLocked_opt: Option[TxId] = tlvStream.get[ChannelReestablishTlv.NextFundingOrExperimentalYourLastFundingLockedTlv] match {
222+
case Some(tlv) if !tlv.isOfficial => Some(tlv.txId)
223+
case _ => None
224+
}
225+
val retransmitAnnSigs: Boolean = tlvStream.get[ChannelReestablishTlv.MyCurrentFundingLockedTlv].exists(_.retransmitAnnSigs)
218226
val nextCommitNonces: Map[TxId, IndividualNonce] = tlvStream.get[ChannelReestablishTlv.NextLocalNoncesTlv].map(_.nonces.toMap).getOrElse(Map.empty)
219227
val currentCommitNonce_opt: Option[IndividualNonce] = tlvStream.get[ChannelReestablishTlv.CurrentCommitNonceTlv].map(_.nonce)
220228
}

eclair-core/src/test/scala/fr/acinq/eclair/channel/RestoreSpec.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import fr.acinq.eclair.channel.fsm.Channel
99
import fr.acinq.eclair.channel.states.ChannelStateTestsBase
1010
import fr.acinq.eclair.channel.states.ChannelStateTestsBase.FakeTxPublisherFactory
1111
import fr.acinq.eclair.router.Announcements
12-
import fr.acinq.eclair.wire.protocol.{ChannelReestablish, ChannelUpdate, Init}
12+
import fr.acinq.eclair.wire.protocol.{ChannelReady, ChannelReestablish, ChannelUpdate, Init}
1313
import fr.acinq.eclair.{TestKitBaseClass, _}
1414
import org.scalatest.Outcome
1515
import org.scalatest.funsuite.FixtureAnyFunSuiteLike
@@ -130,6 +130,9 @@ class RestoreSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with Chan
130130
assert(cup.channelUpdate.feeProportionalMillionths == newConfig.relayParams.privateChannelFees.feeProportionalMillionths)
131131
assert(cup.channelUpdate.cltvExpiryDelta == newConfig.channelConf.expiryDelta)
132132

133+
alice2bob.ignoreMsg { case _: ChannelReady => true }
134+
bob2alice.ignoreMsg { case _: ChannelReady => true }
135+
133136
newAlice ! INPUT_RECONNECTED(alice2bob.ref, aliceInit, bobInit)
134137
bob ! INPUT_RECONNECTED(bob2alice.ref, bobInit, aliceInit)
135138
alice2bob.expectMsgType[ChannelReestablish]

eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForDualFundingSignedStateSpec.scala

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -486,13 +486,15 @@ class WaitForDualFundingSignedStateSpec extends TestKitBaseClass with FixtureAny
486486

487487
alice ! INPUT_RECONNECTED(bob, aliceInit, bobInit)
488488
val channelReestablishAlice = alice2bob.expectMsgType[ChannelReestablish]
489-
assert(channelReestablishAlice.nextLocalCommitmentNumber == 0)
489+
assert(channelReestablishAlice.nextLocalCommitmentNumber == 1)
490+
assert(channelReestablishAlice.retransmitInteractiveTxCommitSig)
490491
assert(channelReestablishAlice.currentCommitNonce_opt.nonEmpty)
491492
assert(channelReestablishAlice.nextCommitNonces.contains(fundingTxId))
492493

493494
bob ! INPUT_RECONNECTED(alice, bobInit, aliceInit)
494495
val channelReestablishBob = bob2alice.expectMsgType[ChannelReestablish]
495-
assert(channelReestablishBob.nextLocalCommitmentNumber == 0)
496+
assert(channelReestablishBob.nextLocalCommitmentNumber == 1)
497+
assert(channelReestablishBob.retransmitInteractiveTxCommitSig)
496498
assert(channelReestablishBob.currentCommitNonce_opt.nonEmpty)
497499
assert(channelReestablishBob.nextCommitNonces.contains(fundingTxId))
498500

@@ -591,12 +593,14 @@ class WaitForDualFundingSignedStateSpec extends TestKitBaseClass with FixtureAny
591593
assert(channelReestablishAlice.nextCommitNonces.contains(fundingTx.txid))
592594
assert(channelReestablishAlice.nextCommitNonces.get(fundingTx.txid) != channelReestablishAlice.currentCommitNonce_opt)
593595
assert(channelReestablishAlice.nextFundingTxId_opt.contains(fundingTx.txid))
594-
assert(channelReestablishAlice.nextLocalCommitmentNumber == 0)
596+
assert(channelReestablishAlice.retransmitInteractiveTxCommitSig)
597+
assert(channelReestablishAlice.nextLocalCommitmentNumber == 1)
595598
alice2bob.forward(bob, channelReestablishAlice)
596599
val channelReestablishBob = bob2alice.expectMsgType[ChannelReestablish]
597600
assert(channelReestablishBob.currentCommitNonce_opt.isEmpty)
598601
assert(channelReestablishBob.nextCommitNonces.get(fundingTx.txid) == channelReadyB.nextCommitNonce_opt)
599602
assert(channelReestablishBob.nextFundingTxId_opt.isEmpty)
603+
assert(!channelReestablishBob.retransmitInteractiveTxCommitSig)
600604
assert(channelReestablishBob.nextLocalCommitmentNumber == 1)
601605
bob2alice.forward(alice, channelReestablishBob)
602606

@@ -734,14 +738,14 @@ class WaitForDualFundingSignedStateSpec extends TestKitBaseClass with FixtureAny
734738
alice ! INPUT_RECONNECTED(bob, aliceInit, bobInit)
735739
bob ! INPUT_RECONNECTED(alice, bobInit, aliceInit)
736740
val channelReestablishAlice = alice2bob.expectMsgType[ChannelReestablish]
737-
val nextLocalCommitmentNumberAlice = if (aliceExpectsCommitSig) 0 else 1
738741
assert(channelReestablishAlice.nextFundingTxId_opt.contains(fundingTxId))
739-
assert(channelReestablishAlice.nextLocalCommitmentNumber == nextLocalCommitmentNumberAlice)
742+
assert(channelReestablishAlice.retransmitInteractiveTxCommitSig == aliceExpectsCommitSig)
743+
assert(channelReestablishAlice.nextLocalCommitmentNumber == 1)
740744
alice2bob.forward(bob, channelReestablishAlice)
741745
val channelReestablishBob = bob2alice.expectMsgType[ChannelReestablish]
742-
val nextLocalCommitmentNumberBob = if (bobExpectsCommitSig) 0 else 1
743746
assert(channelReestablishBob.nextFundingTxId_opt.contains(fundingTxId))
744-
assert(channelReestablishBob.nextLocalCommitmentNumber == nextLocalCommitmentNumberBob)
747+
assert(channelReestablishBob.retransmitInteractiveTxCommitSig == bobExpectsCommitSig)
748+
assert(channelReestablishBob.nextLocalCommitmentNumber == 1)
745749
bob2alice.forward(alice, channelReestablishBob)
746750

747751
// When using taproot, we must provide nonces for the partial signatures.

eclair-core/src/test/scala/fr/acinq/eclair/channel/states/c/WaitForDualFundingConfirmedStateSpec.scala

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -960,8 +960,10 @@ class WaitForDualFundingConfirmedStateSpec extends TestKitBaseClass with Fixture
960960

961961
val (channelReestablishAlice, channelReestablishBob) = reconnectRbf(f)
962962
assert(channelReestablishAlice.nextFundingTxId_opt.contains(rbfTxId))
963-
assert(channelReestablishAlice.nextLocalCommitmentNumber == 0)
963+
assert(channelReestablishAlice.retransmitInteractiveTxCommitSig)
964+
assert(channelReestablishAlice.nextLocalCommitmentNumber == 1)
964965
assert(channelReestablishBob.nextFundingTxId_opt.isEmpty)
966+
assert(!channelReestablishBob.retransmitInteractiveTxCommitSig)
965967
assert(channelReestablishBob.nextLocalCommitmentNumber == 1)
966968
commitmentFormat match {
967969
case _: SegwitV0CommitmentFormat => ()
@@ -1008,9 +1010,11 @@ class WaitForDualFundingConfirmedStateSpec extends TestKitBaseClass with Fixture
10081010

10091011
val (channelReestablishAlice, channelReestablishBob) = reconnectRbf(f)
10101012
assert(channelReestablishAlice.nextFundingTxId_opt.contains(rbfTxId))
1013+
assert(!channelReestablishAlice.retransmitInteractiveTxCommitSig)
10111014
assert(channelReestablishAlice.nextLocalCommitmentNumber == 1)
10121015
assert(channelReestablishBob.nextFundingTxId_opt.contains(rbfTxId))
1013-
assert(channelReestablishBob.nextLocalCommitmentNumber == 0)
1016+
assert(channelReestablishBob.retransmitInteractiveTxCommitSig)
1017+
assert(channelReestablishBob.nextLocalCommitmentNumber == 1)
10141018
commitmentFormat match {
10151019
case _: SegwitV0CommitmentFormat => ()
10161020
case _: TaprootCommitmentFormat =>
@@ -1069,8 +1073,10 @@ class WaitForDualFundingConfirmedStateSpec extends TestKitBaseClass with Fixture
10691073

10701074
val (channelReestablishAlice, channelReestablishBob) = reconnectRbf(f)
10711075
assert(channelReestablishAlice.nextFundingTxId_opt.contains(rbfTxId))
1072-
assert(channelReestablishAlice.nextLocalCommitmentNumber == 0)
1076+
assert(channelReestablishAlice.retransmitInteractiveTxCommitSig)
1077+
assert(channelReestablishAlice.nextLocalCommitmentNumber == 1)
10731078
assert(channelReestablishBob.nextFundingTxId_opt.contains(rbfTxId))
1079+
assert(!channelReestablishBob.retransmitInteractiveTxCommitSig)
10741080
assert(channelReestablishBob.nextLocalCommitmentNumber == 1)
10751081
commitmentFormat match {
10761082
case _: SegwitV0CommitmentFormat => ()
@@ -1137,7 +1143,8 @@ class WaitForDualFundingConfirmedStateSpec extends TestKitBaseClass with Fixture
11371143
bob ! INPUT_RECONNECTED(alice, bobInit, aliceInit)
11381144
val channelReestablishAlice = alice2bob.expectMsgType[ChannelReestablish]
11391145
assert(channelReestablishAlice.nextFundingTxId_opt.nonEmpty)
1140-
assert(channelReestablishAlice.nextLocalCommitmentNumber == 0)
1146+
assert(channelReestablishAlice.retransmitInteractiveTxCommitSig)
1147+
assert(channelReestablishAlice.nextLocalCommitmentNumber == 1)
11411148
assert(channelReestablishAlice.currentCommitNonce_opt.nonEmpty)
11421149
bob2alice.expectMsgType[ChannelReestablish]
11431150
alice2bob.forward(bob, channelReestablishAlice.copy(tlvStream = TlvStream(channelReestablishAlice.tlvStream.records.filterNot(_.isInstanceOf[ChannelReestablishTlv.CurrentCommitNonceTlv]))))

eclair-core/src/test/scala/fr/acinq/eclair/channel/states/c/WaitForDualFundingReadyStateSpec.scala

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -238,18 +238,16 @@ class WaitForDualFundingReadyStateSpec extends TestKitBaseClass with FixtureAnyF
238238
val bobInit = Init(TestConstants.Bob.nodeParams.features.initFeatures())
239239
alice ! INPUT_RECONNECTED(alice2bob.ref, aliceInit, bobInit)
240240
bob ! INPUT_RECONNECTED(bob2alice.ref, bobInit, aliceInit)
241-
alice2bob.expectMsgType[ChannelReestablish]
241+
assert(alice2bob.expectMsgType[ChannelReestablish].retransmitAnnSigs)
242242
alice2bob.forward(bob)
243-
bob2alice.expectMsgType[ChannelReestablish]
243+
assert(!bob2alice.expectMsgType[ChannelReestablish].retransmitAnnSigs)
244244
bob2alice.forward(alice)
245-
// Bob does not retransmit channel_ready and announcement_signatures because he has already received both of them from Alice.
246-
bob2alice.expectNoMessage(100 millis)
247-
// Alice has already received Bob's channel_ready, but not its announcement_signatures.
248-
// She retransmits channel_ready and Bob will retransmit its announcement_signatures in response.
249245
alice2bob.expectMsgType[ChannelReady]
250246
alice2bob.forward(bob)
251247
alice2bob.expectMsgType[AnnouncementSignatures]
252248
alice2bob.forward(bob)
249+
bob2alice.expectMsgType[ChannelReady]
250+
bob2alice.forward(alice)
253251
bob2alice.expectMsgType[AnnouncementSignatures]
254252
bob2alice.forward(alice)
255253
awaitCond(alice.stateData.asInstanceOf[DATA_NORMAL].lastAnnouncement_opt.nonEmpty)

0 commit comments

Comments
 (0)