Skip to content

Commit fde052d

Browse files
committed
Expose lastAnnouncedFundingTxId_opt
And make past codecs decode-only.
1 parent 36074f5 commit fde052d

File tree

8 files changed

+29
-51
lines changed

8 files changed

+29
-51
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,7 @@ final case class DATA_NORMAL(commitments: Commitments,
632632
closingFeerates: Option[ClosingFeerates],
633633
spliceStatus: SpliceStatus) extends ChannelDataWithCommitments {
634634
val lastAnnouncedCommitment_opt: Option[AnnouncedCommitment] = lastAnnouncement_opt.flatMap(ann => commitments.resolveCommitment(ann.shortChannelId).map(c => AnnouncedCommitment(c, ann)))
635+
val lastAnnouncedFundingTxId_opt: Option[TxId] = lastAnnouncedCommitment_opt.map(_.fundingTxId)
635636
val isNegotiatingQuiescence: Boolean = spliceStatus.isNegotiatingQuiescence
636637
val isQuiescent: Boolean = spliceStatus.isQuiescent
637638
}

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

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,32 +1225,32 @@ case class Commitments(params: ChannelParams,
12251225
* @param updateMethod This method is tricky: it passes the fundingTxIndex of the commitment corresponding to the
12261226
* fundingTxId, because in the remote case we may update several commitments.
12271227
*/
1228-
private def updateFundingStatus(fundingTxId: TxId, lastAnnounced_opt: Option[AnnouncedCommitment], updateMethod: Long => PartialFunction[Commitment, Commitment])(implicit log: LoggingAdapter): Either[Commitments, (Commitments, Commitment)] = {
1228+
private def updateFundingStatus(fundingTxId: TxId, lastAnnouncedFundingTxId_opt: Option[TxId], updateMethod: Long => PartialFunction[Commitment, Commitment])(implicit log: LoggingAdapter): Either[Commitments, (Commitments, Commitment)] = {
12291229
all.find(_.fundingTxId == fundingTxId) match {
12301230
case Some(commitment) =>
12311231
val commitments1 = copy(
12321232
active = active.map(updateMethod(commitment.fundingTxIndex)),
12331233
inactive = inactive.map(updateMethod(commitment.fundingTxIndex))
12341234
)
12351235
val commitment1 = commitments1.all.find(_.fundingTxId == fundingTxId).get // NB: this commitment might be pruned at the next line
1236-
val commitments2 = commitments1.deactivateCommitments().pruneCommitments(lastAnnounced_opt)
1236+
val commitments2 = commitments1.deactivateCommitments().pruneCommitments(lastAnnouncedFundingTxId_opt)
12371237
Right(commitments2, commitment1)
12381238
case None =>
12391239
log.warning(s"fundingTxId=$fundingTxId doesn't match any of our funding txs")
12401240
Left(this)
12411241
}
12421242
}
12431243

1244-
def updateLocalFundingStatus(fundingTxId: TxId, status: LocalFundingStatus, lastAnnounced_opt: Option[AnnouncedCommitment])(implicit log: LoggingAdapter): Either[Commitments, (Commitments, Commitment)] =
1245-
updateFundingStatus(fundingTxId, lastAnnounced_opt, _ => {
1244+
def updateLocalFundingStatus(fundingTxId: TxId, status: LocalFundingStatus, lastAnnouncedFundingTxId_opt: Option[TxId])(implicit log: LoggingAdapter): Either[Commitments, (Commitments, Commitment)] =
1245+
updateFundingStatus(fundingTxId, lastAnnouncedFundingTxId_opt, _ => {
12461246
case c if c.fundingTxId == fundingTxId =>
12471247
log.info(s"setting localFundingStatus=${status.getClass.getSimpleName} for fundingTxId=${c.fundingTxId} fundingTxIndex=${c.fundingTxIndex}")
12481248
c.copy(localFundingStatus = status)
12491249
case c => c
12501250
})
12511251

1252-
def updateRemoteFundingStatus(fundingTxId: TxId, lastAnnounced_opt: Option[AnnouncedCommitment])(implicit log: LoggingAdapter): Either[Commitments, (Commitments, Commitment)] =
1253-
updateFundingStatus(fundingTxId, lastAnnounced_opt, fundingTxIndex => {
1252+
def updateRemoteFundingStatus(fundingTxId: TxId, lastAnnouncedFundingTxId_opt: Option[TxId])(implicit log: LoggingAdapter): Either[Commitments, (Commitments, Commitment)] =
1253+
updateFundingStatus(fundingTxId, lastAnnouncedFundingTxId_opt, fundingTxIndex => {
12541254
// all funding older than this one are considered locked
12551255
case c if c.fundingTxId == fundingTxId || c.fundingTxIndex < fundingTxIndex =>
12561256
log.info(s"setting remoteFundingStatus=${RemoteFundingStatus.Locked.getClass.getSimpleName} for fundingTxId=${c.fundingTxId} fundingTxIndex=${c.fundingTxIndex}")
@@ -1300,12 +1300,12 @@ case class Commitments(params: ChannelParams,
13001300
* We can prune commitments in two cases:
13011301
* - their funding tx has been permanently double-spent by the funding tx of a concurrent commitment (happens when using RBF)
13021302
* - their funding tx has been permanently spent by a splice tx
1303-
*
1303+
*
13041304
* But we need to keep our last announced commitment if the channel is public, even if it has been permanently spent
13051305
* by a newer splice tx that hasn't been announced yet, otherwise we won't know which short_channel_id to use when
13061306
* creating channel_updates.
13071307
*/
1308-
private def pruneCommitments(lastAnnounced_opt: Option[AnnouncedCommitment])(implicit log: LoggingAdapter): Commitments = {
1308+
private def pruneCommitments(lastAnnouncedFundingTxId_opt: Option[TxId])(implicit log: LoggingAdapter): Commitments = {
13091309
all
13101310
.filter(_.localFundingStatus.isInstanceOf[LocalFundingStatus.ConfirmedFundingTx])
13111311
.sortBy(_.fundingTxIndex)
@@ -1317,7 +1317,8 @@ case class Commitments(params: ChannelParams,
13171317
// If the most recently confirmed commitment isn't announced yet, we cannot prune the last commitment we
13181318
// announced, because our channel updates are based on its announcement (and its short_channel_id).
13191319
// If we never announced the channel, we don't need to announce old commitments, we will directly announce the last one.
1320-
val pruningIndex = lastAnnounced_opt.map(_.fundingTxIndex).getOrElse(lastConfirmed.fundingTxIndex)
1320+
val lastAnnouncedFundingTxIndex_opt = lastAnnouncedFundingTxId_opt.flatMap(txId => all.find(_.fundingTxId == txId).map(_.fundingTxIndex))
1321+
val pruningIndex = lastAnnouncedFundingTxIndex_opt.getOrElse(lastConfirmed.fundingTxIndex)
13211322
// We can prune all RBF candidates, and commitments that came before the last announced one.
13221323
inactive.filter(c => c.fundingTxIndex < pruningIndex || (c.fundingTxIndex == lastConfirmed.fundingTxIndex && c.fundingTxId != lastConfirmed.fundingTxId))
13231324
} else {

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,7 +1297,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
12971297
stay() sending Error(d.channelId, InvalidFundingSignature(d.channelId, Some(fundingTx.txId)).getMessage)
12981298
case Right(fundingTx) =>
12991299
val dfu1 = dfu.copy(sharedTx = fundingTx)
1300-
d.commitments.updateLocalFundingStatus(msg.txId, dfu1, d.lastAnnouncedCommitment_opt) match {
1300+
d.commitments.updateLocalFundingStatus(msg.txId, dfu1, d.lastAnnouncedFundingTxId_opt) match {
13011301
case Right((commitments1, _)) =>
13021302
log.info("publishing funding tx for channelId={} fundingTxId={}", d.channelId, fundingTx.signedTx.txid)
13031303
Metrics.recordSplice(dfu.fundingParams, fundingTx.tx)
@@ -1332,7 +1332,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
13321332

13331333
case Event(w: WatchPublishedTriggered, d: DATA_NORMAL) =>
13341334
val fundingStatus = LocalFundingStatus.ZeroconfPublishedFundingTx(w.tx, d.commitments.localFundingSigs(w.tx.txid), d.commitments.liquidityPurchase(w.tx.txid))
1335-
d.commitments.updateLocalFundingStatus(w.tx.txid, fundingStatus, d.lastAnnouncedCommitment_opt) match {
1335+
d.commitments.updateLocalFundingStatus(w.tx.txid, fundingStatus, d.lastAnnouncedFundingTxId_opt) match {
13361336
case Right((commitments1, _)) =>
13371337
watchFundingConfirmed(w.tx.txid, Some(nodeParams.channelConf.minDepthFunding), delay_opt = None)
13381338
maybeEmitEventsPostSplice(d.aliases, d.commitments, commitments1, d.lastAnnouncement_opt)
@@ -1368,7 +1368,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
13681368
}
13691369

13701370
case Event(msg: SpliceLocked, d: DATA_NORMAL) =>
1371-
d.commitments.updateRemoteFundingStatus(msg.fundingTxId, d.lastAnnouncedCommitment_opt) match {
1371+
d.commitments.updateRemoteFundingStatus(msg.fundingTxId, d.lastAnnouncedFundingTxId_opt) match {
13721372
case Right((commitments1, commitment)) =>
13731373
// If the commitment is confirmed, we were waiting to receive the remote splice_locked before sending our announcement_signatures.
13741374
val localAnnSigs_opt = if (d.commitments.announceChannel) commitment.signAnnouncement(nodeParams, commitments1.params) else None
@@ -2537,11 +2537,11 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
25372537
stay()
25382538
} else {
25392539
val fundingStatus = LocalFundingStatus.ZeroconfPublishedFundingTx(w.tx, d.commitments.localFundingSigs(w.tx.txid), d.commitments.liquidityPurchase(w.tx.txid))
2540-
val lastAnnouncedCommitment_opt = d match {
2541-
case d: DATA_NORMAL => d.lastAnnouncedCommitment_opt
2540+
val lastAnnouncedFundingTxId_opt = d match {
2541+
case d: DATA_NORMAL => d.lastAnnouncedFundingTxId_opt
25422542
case _ => None
25432543
}
2544-
d.commitments.updateLocalFundingStatus(w.tx.txid, fundingStatus, lastAnnouncedCommitment_opt) match {
2544+
d.commitments.updateLocalFundingStatus(w.tx.txid, fundingStatus, lastAnnouncedFundingTxId_opt) match {
25452545
case Right((commitments1, _)) =>
25462546
log.info("zero-conf funding txid={} has been published", w.tx.txid)
25472547
watchFundingConfirmed(w.tx.txid, Some(nodeParams.channelConf.minDepthFunding), delay_opt = None)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ trait ChannelOpenDualFunded extends DualFundingHandlers with ErrorHandlers {
724724
case Event(w: WatchPublishedTriggered, d: DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED) =>
725725
log.info("funding txid={} was successfully published for zero-conf channelId={}", w.tx.txid, d.channelId)
726726
val fundingStatus = LocalFundingStatus.ZeroconfPublishedFundingTx(w.tx, d.commitments.localFundingSigs(w.tx.txid), d.commitments.liquidityPurchase(w.tx.txid))
727-
d.commitments.updateLocalFundingStatus(w.tx.txid, fundingStatus, lastAnnounced_opt = None) match {
727+
d.commitments.updateLocalFundingStatus(w.tx.txid, fundingStatus, lastAnnouncedFundingTxId_opt = None) match {
728728
case Right((commitments1, _)) =>
729729
// we still watch the funding tx for confirmation even if we can use the zero-conf channel right away
730730
watchFundingConfirmed(w.tx.txid, Some(nodeParams.channelConf.minDepthFunding), delay_opt = None)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ trait ChannelOpenSingleFunded extends SingleFundingHandlers with ErrorHandlers {
392392

393393
case Event(w: WatchPublishedTriggered, d: DATA_WAIT_FOR_FUNDING_CONFIRMED) =>
394394
val fundingStatus = LocalFundingStatus.ZeroconfPublishedFundingTx(w.tx, None, None)
395-
d.commitments.updateLocalFundingStatus(w.tx.txid, fundingStatus, lastAnnounced_opt = None) match {
395+
d.commitments.updateLocalFundingStatus(w.tx.txid, fundingStatus, lastAnnouncedFundingTxId_opt = None) match {
396396
case Right((commitments1, _)) =>
397397
log.info("funding txid={} was successfully published for zero-conf channelId={}", w.tx.txid, d.channelId)
398398
// we still watch the funding tx for confirmation even if we can use the zero-conf channel right away

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,11 @@ trait CommonFundingHandlers extends CommonHandlers {
9292
// previous funding transaction. Our peer cannot publish the corresponding revoked commitments anymore, so we can
9393
// clean-up the htlc data that we were storing for the matching penalty transactions.
9494
context.system.eventStream.publish(RevokedHtlcInfoCleaner.ForgetHtlcInfos(d.channelId, beforeCommitIndex = c.firstRemoteCommitIndex))
95-
val lastAnnouncedCommitment_opt = d match {
96-
case d: DATA_NORMAL => d.lastAnnouncedCommitment_opt
95+
val lastAnnouncedFundingTxId_opt = d match {
96+
case d: DATA_NORMAL => d.lastAnnouncedFundingTxId_opt
9797
case _ => None
9898
}
99-
d.commitments.updateLocalFundingStatus(w.tx.txid, fundingStatus, lastAnnouncedCommitment_opt).map {
99+
d.commitments.updateLocalFundingStatus(w.tx.txid, fundingStatus, lastAnnouncedFundingTxId_opt).map {
100100
case (commitments1, commitment) =>
101101
// First of all, we watch the funding tx that is now confirmed.
102102
// Children splice transactions may already spend that confirmed funding transaction.

eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/version4/ChannelCodecs4.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,7 @@ private[channel] object ChannelCodecs4 {
652652
("real_opt" | optional(bool8, realshortchannelid)) ::
653653
("localAlias" | discriminated[Alias].by(uint16).typecase(1, alias)) ::
654654
("remoteAlias_opt" | optional(bool8, alias))
655-
).as[ChannelTypes4.ShortIds]
655+
).as[ChannelTypes4.ShortIds].decodeOnly
656656

657657
val DATA_WAIT_FOR_FUNDING_CONFIRMED_00_Codec: Codec[DATA_WAIT_FOR_FUNDING_CONFIRMED] = (
658658
("commitments" | commitmentsCodecWithoutFirstRemoteCommitIndex) ::
@@ -668,11 +668,11 @@ private[channel] object ChannelCodecs4 {
668668

669669
val DATA_WAIT_FOR_CHANNEL_READY_01_Codec: Codec[DATA_WAIT_FOR_CHANNEL_READY] = (
670670
("commitments" | commitmentsCodecWithoutFirstRemoteCommitIndex) ::
671-
("shortIds" | shortids)).as[ChannelTypes4.DATA_WAIT_FOR_CHANNEL_READY_0b].xmap(d => d.migrate(), d => ChannelTypes4.DATA_WAIT_FOR_CHANNEL_READY_0b.from(d))
671+
("shortIds" | shortids)).as[ChannelTypes4.DATA_WAIT_FOR_CHANNEL_READY_0b].map(_.migrate()).decodeOnly
672672

673673
val DATA_WAIT_FOR_CHANNEL_READY_0b_Codec: Codec[DATA_WAIT_FOR_CHANNEL_READY] = (
674674
("commitments" | versionedCommitmentsCodec) ::
675-
("shortIds" | shortids)).as[ChannelTypes4.DATA_WAIT_FOR_CHANNEL_READY_0b].xmap(d => d.migrate(), d => ChannelTypes4.DATA_WAIT_FOR_CHANNEL_READY_0b.from(d))
675+
("shortIds" | shortids)).as[ChannelTypes4.DATA_WAIT_FOR_CHANNEL_READY_0b].map(_.migrate()).decodeOnly
676676

677677
val DATA_WAIT_FOR_CHANNEL_READY_15_Codec: Codec[DATA_WAIT_FOR_CHANNEL_READY] = (
678678
("commitments" | versionedCommitmentsCodec) ::
@@ -714,11 +714,11 @@ private[channel] object ChannelCodecs4 {
714714

715715
val DATA_WAIT_FOR_DUAL_FUNDING_READY_03_Codec: Codec[DATA_WAIT_FOR_DUAL_FUNDING_READY] = (
716716
("commitments" | commitmentsCodecWithoutFirstRemoteCommitIndex) ::
717-
("shortIds" | shortids)).as[ChannelTypes4.DATA_WAIT_FOR_DUAL_FUNDING_READY_0d].xmap(d => d.migrate(), d => ChannelTypes4.DATA_WAIT_FOR_DUAL_FUNDING_READY_0d.from(d))
717+
("shortIds" | shortids)).as[ChannelTypes4.DATA_WAIT_FOR_DUAL_FUNDING_READY_0d].map(_.migrate()).decodeOnly
718718

719719
val DATA_WAIT_FOR_DUAL_FUNDING_READY_0d_Codec: Codec[DATA_WAIT_FOR_DUAL_FUNDING_READY] = (
720720
("commitments" | versionedCommitmentsCodec) ::
721-
("shortIds" | shortids)).as[ChannelTypes4.DATA_WAIT_FOR_DUAL_FUNDING_READY_0d].xmap(d => d.migrate(), d => ChannelTypes4.DATA_WAIT_FOR_DUAL_FUNDING_READY_0d.from(d))
721+
("shortIds" | shortids)).as[ChannelTypes4.DATA_WAIT_FOR_DUAL_FUNDING_READY_0d].map(_.migrate()).decodeOnly
722722

723723
val DATA_WAIT_FOR_DUAL_FUNDING_READY_16_Codec: Codec[DATA_WAIT_FOR_DUAL_FUNDING_READY] = (
724724
("commitments" | versionedCommitmentsCodec) ::
@@ -732,7 +732,7 @@ private[channel] object ChannelCodecs4 {
732732
("localShutdown" | optional(bool8, lengthDelimited(shutdownCodec))) ::
733733
("remoteShutdown" | optional(bool8, lengthDelimited(shutdownCodec))) ::
734734
("closingFeerates" | optional(bool8, closingFeeratesCodec)) ::
735-
("spliceStatus" | spliceStatusCodec)).as[ChannelTypes4.DATA_NORMAL_0e].xmap(d => d.migrate(), d => ChannelTypes4.DATA_NORMAL_0e.from(d))
735+
("spliceStatus" | spliceStatusCodec)).as[ChannelTypes4.DATA_NORMAL_0e].map(_.migrate()).decodeOnly
736736

737737
val DATA_NORMAL_0e_Codec: Codec[DATA_NORMAL] = (
738738
("commitments" | versionedCommitmentsCodec) ::
@@ -742,7 +742,7 @@ private[channel] object ChannelCodecs4 {
742742
("localShutdown" | optional(bool8, lengthDelimited(shutdownCodec))) ::
743743
("remoteShutdown" | optional(bool8, lengthDelimited(shutdownCodec))) ::
744744
("closingFeerates" | optional(bool8, closingFeeratesCodec)) ::
745-
("spliceStatus" | spliceStatusCodec)).as[ChannelTypes4.DATA_NORMAL_0e].xmap(d => d.migrate(), d => ChannelTypes4.DATA_NORMAL_0e.from(d))
745+
("spliceStatus" | spliceStatusCodec)).as[ChannelTypes4.DATA_NORMAL_0e].map(_.migrate()).decodeOnly
746746

747747
val DATA_NORMAL_14_Codec: Codec[DATA_NORMAL] = (
748748
("commitments" | versionedCommitmentsCodec) ::

eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/version4/ChannelTypes4.scala

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,6 @@ private[channel] object ChannelTypes4 {
4545
}
4646
}
4747

48-
object DATA_NORMAL_0e {
49-
// shouldn't be used since we only decode old data and never encode it
50-
def from(d: DATA_NORMAL): DATA_NORMAL_0e = {
51-
val shortIds = ShortIds(d.lastAnnouncement_opt.map(_.shortChannelId), d.aliases.localAlias, d.aliases.remoteAlias_opt)
52-
DATA_NORMAL_0e(d.commitments, shortIds, d.lastAnnouncement_opt, d.channelUpdate, d.localShutdown, d.remoteShutdown, d.closingFeerates, d.spliceStatus)
53-
}
54-
}
55-
5648
case class DATA_WAIT_FOR_CHANNEL_READY_0b(commitments: Commitments, shortIds: ShortIds) {
5749
def migrate(): DATA_WAIT_FOR_CHANNEL_READY = {
5850
val commitments1 = commitments.copy(
@@ -64,14 +56,6 @@ private[channel] object ChannelTypes4 {
6456
}
6557
}
6658

67-
object DATA_WAIT_FOR_CHANNEL_READY_0b {
68-
// shouldn't be used since we only decode old data and never encode it
69-
def from(d: DATA_WAIT_FOR_CHANNEL_READY): DATA_WAIT_FOR_CHANNEL_READY_0b = {
70-
val shortIds = ShortIds(None, d.aliases.localAlias, d.aliases.remoteAlias_opt)
71-
DATA_WAIT_FOR_CHANNEL_READY_0b(d.commitments, shortIds)
72-
}
73-
}
74-
7559
case class DATA_WAIT_FOR_DUAL_FUNDING_READY_0d(commitments: Commitments, shortIds: ShortIds) {
7660
def migrate(): DATA_WAIT_FOR_DUAL_FUNDING_READY = {
7761
val commitments1 = commitments.copy(
@@ -83,14 +67,6 @@ private[channel] object ChannelTypes4 {
8367
}
8468
}
8569

86-
object DATA_WAIT_FOR_DUAL_FUNDING_READY_0d {
87-
// shouldn't be used since we only decode old data and never encode it
88-
def from(d: DATA_WAIT_FOR_DUAL_FUNDING_READY): DATA_WAIT_FOR_DUAL_FUNDING_READY_0d = {
89-
val shortIds = ShortIds(None, d.aliases.localAlias, d.aliases.remoteAlias_opt)
90-
DATA_WAIT_FOR_DUAL_FUNDING_READY_0d(d.commitments, shortIds)
91-
}
92-
}
93-
9470
private def setScidIfMatches(c: Commitment, shortIds: ShortIds): Commitment = {
9571
c.localFundingStatus match {
9672
// We didn't support splicing on public channels in this version: the scid (if available) is for the initial

0 commit comments

Comments
 (0)