@@ -236,8 +236,6 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
236236 var announcementSigsStash = Map .empty[RealShortChannelId , AnnouncementSignatures ]
237237 // we record the announcement_signatures messages we already sent to avoid unnecessary retransmission
238238 var announcementSigsSent = Set .empty[RealShortChannelId ]
239- // we keep track of the splice_locked we sent after channel_reestablish and it's funding tx index to avoid sending it again
240- private var spliceLockedSent = Map .empty[TxId , Long ]
241239
242240 private def trimAnnouncementSigsStashIfNeeded (): Unit = {
243241 if (announcementSigsStash.size >= 10 ) {
@@ -249,17 +247,6 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
249247 }
250248 }
251249
252- private def trimSpliceLockedSentIfNeeded (): Unit = {
253- if (spliceLockedSent.size >= 10 ) {
254- // We shouldn't store an unbounded number of splice_locked: on long-lived connections where we do a lot of splice
255- // transactions, we only need to keep track of the most recent ones.
256- val oldestFundingTxId = spliceLockedSent.toSeq
257- .sortBy { case (_, fundingTxIndex) => fundingTxIndex }
258- .map { case (fundingTxId, _) => fundingTxId }.head
259- spliceLockedSent -= oldestFundingTxId
260- }
261- }
262-
263250 val txPublisher = txPublisherFactory.spawnTxPublisher(context, remoteNodeId)
264251
265252 // this will be used to detect htlc timeouts
@@ -1427,8 +1414,6 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
14271414 watchFundingConfirmed(w.tx.txid, Some (nodeParams.channelConf.minDepth), delay_opt = None )
14281415 maybeEmitEventsPostSplice(d.aliases, d.commitments, commitments1, d.lastAnnouncement_opt)
14291416 maybeUpdateMaxHtlcAmount(d.channelUpdate.htlcMaximumMsat, commitments1)
1430- spliceLockedSent += (commitment.fundingTxId -> commitment.fundingTxIndex)
1431- trimSpliceLockedSentIfNeeded()
14321417 stay() using d.copy(commitments = commitments1) storing() sending SpliceLocked (d.channelId, w.tx.txid)
14331418 case Left (_) => stay()
14341419 }
@@ -1439,11 +1424,7 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
14391424 // We check if this commitment was already locked before receiving the event (which happens when using 0-conf
14401425 // or for the initial funding transaction). If it was previously not locked, we must send splice_locked now.
14411426 val previouslyNotLocked = d.commitments.all.exists(c => c.fundingTxId == commitment.fundingTxId && c.localFundingStatus.isInstanceOf [LocalFundingStatus .NotLocked ])
1442- val spliceLocked_opt = if (previouslyNotLocked) {
1443- spliceLockedSent += (commitment.fundingTxId -> commitment.fundingTxIndex)
1444- trimSpliceLockedSentIfNeeded()
1445- Some (SpliceLocked (d.channelId, w.tx.txid))
1446- } else None
1427+ val spliceLocked_opt = if (previouslyNotLocked) Some (SpliceLocked (d.channelId, w.tx.txid)) else None
14471428 // If the channel is public and we've received the remote splice_locked, we send our announcement_signatures
14481429 // in order to generate the channel_announcement.
14491430 val remoteLocked = commitment.fundingTxIndex == 0 || d.commitments.all.exists(c => c.fundingTxId == commitment.fundingTxId && c.remoteFundingStatus == RemoteFundingStatus .Locked )
@@ -1466,21 +1447,6 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
14661447 case Event (msg : SpliceLocked , d : DATA_NORMAL ) =>
14671448 d.commitments.updateRemoteFundingStatus(msg.fundingTxId, d.lastAnnouncedFundingTxId_opt) match {
14681449 case Right ((commitments1, commitment)) =>
1469- // If we have both already sent splice_locked for this commitment, then we are receiving splice_locked
1470- // again after a reconnection and must retransmit our splice_locked and new announcement_signatures. Nodes
1471- // retransmit splice_locked after a reconnection when they have received splice_locked but NOT matching signatures
1472- // before the last disconnect. If a matching splice_locked has already been sent since reconnecting, then do not
1473- // retransmit splice_locked to avoid a loop.
1474- // NB: It is important both nodes retransmit splice_locked after reconnecting to ensure new Taproot nonces
1475- // are exchanged for channel announcements.
1476- val isLatestLocked = d.commitments.lastLocalLocked_opt.exists(_.fundingTxId == msg.fundingTxId) && d.commitments.lastRemoteLocked_opt.exists(_.fundingTxId == msg.fundingTxId)
1477- val spliceLocked_opt = if (d.commitments.announceChannel && isLatestLocked && ! spliceLockedSent.contains(commitment.fundingTxId)) {
1478- spliceLockedSent += (commitment.fundingTxId -> commitment.fundingTxIndex)
1479- trimSpliceLockedSentIfNeeded()
1480- Some (SpliceLocked (d.channelId, commitment.fundingTxId))
1481- } else {
1482- None
1483- }
14841450 // If the commitment is confirmed, we were waiting to receive the remote splice_locked before sending our announcement_signatures.
14851451 val localAnnSigs_opt = commitment.signAnnouncement(nodeParams, commitments1.channelParams, channelKeys.fundingKey(commitment.fundingTxIndex)) match {
14861452 case Some (localAnnSigs) if ! announcementSigsSent.contains(localAnnSigs.shortChannelId) =>
@@ -1493,7 +1459,7 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
14931459 }
14941460 maybeEmitEventsPostSplice(d.aliases, d.commitments, commitments1, d.lastAnnouncement_opt)
14951461 maybeUpdateMaxHtlcAmount(d.channelUpdate.htlcMaximumMsat, commitments1)
1496- stay() using d.copy(commitments = commitments1) storing() sending spliceLocked_opt.toSeq ++ localAnnSigs_opt.toSeq
1462+ stay() using d.copy(commitments = commitments1) storing() sending localAnnSigs_opt.toSeq
14971463 case Left (_) => stay()
14981464 }
14991465
@@ -2394,8 +2360,14 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
23942360 }
23952361 val remoteFeatures = d.commitments.remoteChannelParams.initFeatures
23962362 val lastFundingLockedTlvs : Set [ChannelReestablishTlv ] = if (remoteFeatures.hasFeature(Features .Splicing ) || remoteFeatures.unknown.contains(UnknownFeature (154 )) || remoteFeatures.unknown.contains(UnknownFeature (155 ))) {
2397- d.commitments.lastLocalLocked_opt.map(c => ChannelReestablishTlv .MyCurrentFundingLockedTlv (c.fundingTxId)).toSet ++
2398- d.commitments.lastRemoteLocked_opt.map(c => ChannelReestablishTlv .YourLastFundingLockedTlv (c.fundingTxId)).toSet
2363+ d.commitments.lastLocalLocked_opt.map(c => {
2364+ // We ask our peer to retransmit their announcement_signatures if we haven't already announced that splice.
2365+ val retransmitAnnSigs = d match {
2366+ case d : DATA_NORMAL if d.commitments.announceChannel => ! d.lastAnnouncedFundingTxId_opt.contains(c.fundingTxId)
2367+ case _ => false
2368+ }
2369+ ChannelReestablishTlv .MyCurrentFundingLockedTlv (c.fundingTxId, retransmitAnnSigs)
2370+ }).toSet
23992371 } else Set .empty
24002372
24012373 val channelReestablish = ChannelReestablish (
@@ -2522,22 +2494,18 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
25222494 // We only send channel_ready for initial funding transactions.
25232495 case Some (c) if c.fundingTxIndex != 0 => ()
25242496 case Some (c) =>
2525- val remoteFeatures = d.commitments.remoteChannelParams.initFeatures
2526- val remoteSpliceSupport = remoteFeatures.hasFeature(Features .Splicing ) || remoteFeatures.unknown.contains(UnknownFeature (154 )) || remoteFeatures.unknown.contains(UnknownFeature (155 ))
2527- // If our peer has not received our channel_ready, we retransmit it.
2528- val notReceivedByRemote = remoteSpliceSupport && channelReestablish.yourLastFundingLocked_opt.isEmpty
25292497 // If next_local_commitment_number is 1 in both the channel_reestablish it sent and received, then the node
25302498 // MUST retransmit channel_ready, otherwise it MUST NOT
2531- val notReceivedByRemoteLegacy = ! remoteSpliceSupport && channelReestablish.nextLocalCommitmentNumber == 1 && c.localCommit.index == 0
2499+ val notReceivedByRemote = channelReestablish.nextLocalCommitmentNumber == 1 && c.localCommit.index == 0
25322500 // If this is a public channel and we haven't announced the channel, we retransmit our channel_ready and
25332501 // will also send announcement_signatures.
25342502 val notAnnouncedYet = d.commitments.announceChannel && c.shortChannelId_opt.nonEmpty && d.lastAnnouncement_opt.isEmpty
2535- if (notAnnouncedYet || notReceivedByRemote || notReceivedByRemoteLegacy ) {
2503+ if (notAnnouncedYet || notReceivedByRemote) {
25362504 log.debug(" re-sending channel_ready" )
25372505 val nextPerCommitmentPoint = channelKeys.commitmentPoint(1 )
25382506 sendQueue = sendQueue :+ ChannelReady (d.commitments.channelId, nextPerCommitmentPoint)
25392507 }
2540- if (notAnnouncedYet) {
2508+ if (notAnnouncedYet || channelReestablish.retransmitAnnSigs ) {
25412509 // The funding transaction is confirmed, so we've already sent our announcement_signatures.
25422510 // We haven't announced the channel yet, which means we haven't received our peer's announcement_signatures.
25432511 // We retransmit our announcement_signatures to let our peer know that we're ready to announce the channel.
@@ -2600,23 +2568,19 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
26002568 // We then clean up unsigned updates that haven't been received before the disconnection.
26012569 .discardUnsignedUpdates()
26022570
2571+ // We retransmit our latest announcement_signatures if our peer requests it.
26032572 commitments1.lastLocalLocked_opt match {
26042573 case None => ()
2605- // We only send splice_locked for splice transactions.
2574+ // This retransmit mechanism is only available for splice transactions.
26062575 case Some (c) if c.fundingTxIndex == 0 => ()
26072576 case Some (c) =>
2608- // If our peer has not received our splice_locked, we retransmit it.
2609- val notReceivedByRemote = ! channelReestablish.yourLastFundingLocked_opt.contains(c.fundingTxId)
2610- // If this is a public channel and we haven't announced the splice, we retransmit our splice_locked and
2611- // will exchange announcement_signatures afterwards.
2612- val notAnnouncedYet = commitments1.announceChannel && d.lastAnnouncement_opt.forall(ann => ! c.shortChannelId_opt.contains(ann.shortChannelId))
2613- if (notReceivedByRemote || notAnnouncedYet) {
2614- // Retransmission of local announcement_signatures for splices are done when receiving splice_locked, no need
2615- // to retransmit here.
2616- log.debug(" re-sending splice_locked for fundingTxId={}" , c.fundingTxId)
2617- spliceLockedSent += (c.fundingTxId -> c.fundingTxIndex)
2618- trimSpliceLockedSentIfNeeded()
2619- sendQueue = sendQueue :+ SpliceLocked (d.channelId, c.fundingTxId)
2577+ if (channelReestablish.retransmitAnnSigs && d.commitments.announceChannel) {
2578+ val localAnnSigs = c.signAnnouncement(nodeParams, d.commitments.channelParams, channelKeys.fundingKey(c.fundingTxIndex))
2579+ localAnnSigs.foreach(annSigs => {
2580+ log.debug(" re-sending announcement_signatures for fundingTxId={}" , c.fundingTxId)
2581+ announcementSigsSent += annSigs.shortChannelId
2582+ sendQueue = sendQueue :+ annSigs
2583+ })
26202584 }
26212585 }
26222586
@@ -3108,7 +3072,6 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
31083072 case _ -> OFFLINE =>
31093073 announcementSigsStash = Map .empty
31103074 announcementSigsSent = Set .empty
3111- spliceLockedSent = Map .empty[TxId , Long ]
31123075 }
31133076
31143077 /*
0 commit comments