@@ -29,9 +29,9 @@ import fr.acinq.eclair.blockchain._
2929import fr .acinq .eclair .blockchain .bitcoind .ZmqWatcher
3030import fr .acinq .eclair .blockchain .bitcoind .ZmqWatcher ._
3131import fr .acinq .eclair .blockchain .bitcoind .rpc .BitcoinCoreClient
32+ import fr .acinq .eclair .channel .Commitments .PostRevocationAction
3233import fr .acinq .eclair .channel .Helpers .Syncing .SyncResult
3334import fr .acinq .eclair .channel .Helpers .{Closing , Syncing , getRelayFees , scidForChannelUpdate }
34- import fr .acinq .eclair .channel .Commitments .PostRevocationAction
3535import fr .acinq .eclair .channel .Monitoring .Metrics .ProcessMessage
3636import fr .acinq .eclair .channel .Monitoring .{Metrics , Tags }
3737import fr .acinq .eclair .channel ._
@@ -1072,30 +1072,30 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
10721072 case Event (BITCOIN_FUNDING_TIMEOUT , d : DATA_CLOSING ) => handleFundingTimeout(d)
10731073
10741074 case Event (w : WatchFundingConfirmedTriggered , d : DATA_CLOSING ) =>
1075- val commitments1 = d.commitments.updateLocalFundingStatus(w.tx.txid, LocalFundingStatus . ConfirmedFundingTx (w.tx))
1076- if (d.commitments.latest.fundingTxId == w.tx.txid) {
1077- // The best funding tx candidate has been confirmed, alternative commitments have been pruned
1078- stay() using d.copy( commitments = commitments1) storing()
1079- } else {
1080- // This is a corner case where:
1081- // - we are using dual funding
1082- // - *and* the funding tx was RBF-ed
1083- // - *and* we went to CLOSING before any funding tx got confirmed (probably due to a local or remote error)
1084- // - *and* an older version of the funding tx confirmed and reached min depth (it won't be re-orged out )
1085- //
1086- // This means that:
1087- // - the whole current commitment tree has been double-spent and can safely be forgotten
1088- // - from now on, we only need to keep track of the commitment associated to the funding tx that got confirmed
1089- //
1090- // Force-closing is our only option here, if we are in this state the channel was closing and it is too late
1091- // to negotiate a mutual close.
1092- log.info( " channelId={} was confirmed at blockHeight={} txIndex={} with a previous funding txid={} " , d.channelId, w.blockHeight, w.txIndex, w.tx.txid)
1093- watchFundingSpent(commitments1.latest.commitment )
1094- context.system.eventStream.publish( TransactionConfirmed (d.channelId, remoteNodeId, w.tx))
1095- val commitTx = commitments1.latest.fullySignedLocalCommitTx(keyManager).tx
1096- val localCommitPublished = Closing . LocalClose .claimCommitTxOutputs(keyManager, commitments1.latest, commitTx, nodeParams.currentBlockHeight, nodeParams.onChainFeeConf, d.finalScriptPubKey )
1097- val d1 = DATA_CLOSING (commitments1, d.waitingSince, d.finalScriptPubKey, mutualCloseProposed = Nil , localCommitPublished = Some (localCommitPublished))
1098- stay() using d1 storing() calling doPublish(localCommitPublished, commitments1.latest )
1075+ acceptFundingTxConfirmed(w, d) match {
1076+ case Right ((commitments1, _)) =>
1077+ if (d. commitments.latest.fundingTxId == w.tx.txid) {
1078+ // The best funding tx candidate has been confirmed, alternative commitments have been pruned
1079+ stay() using d.copy(commitments = commitments1) storing()
1080+ } else {
1081+ // This is a corner case where:
1082+ // - we are using dual funding
1083+ // - *and* the funding tx was RBF-ed
1084+ // - *and* we went to CLOSING before any funding tx got confirmed (probably due to a local or remote error )
1085+ // - *and* an older version of the funding tx confirmed and reached min depth (it won't be re-orged out)
1086+ //
1087+ // This means that:
1088+ // - the whole current commitment tree has been double-spent and can safely be forgotten
1089+ // - from now on, we only need to keep track of the commitment associated to the funding tx that got confirmed
1090+ //
1091+ // Force-closing is our only option here, if we are in this state the channel was closing and it is too late
1092+ // to negotiate a mutual close.
1093+ log.info( " channelId={} was confirmed at blockHeight={} txIndex={} with a previous funding txid={} " , d.channelId, w.blockHeight, w.txIndex, w.tx.txid )
1094+ val commitment = commitments1.latest
1095+ val d1 = d.copy(commitments = commitments1)
1096+ spendLocalCurrent(d1 )
1097+ }
1098+ case Left (_) => stay( )
10991099 }
11001100
11011101 case Event (WatchFundingSpentTriggered (tx), d : DATA_CLOSING ) =>
@@ -1563,52 +1563,58 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder with
15631563 case Event (TickChannelOpenTimeout , _) => stay()
15641564
15651565 case Event (w : WatchPublishedTriggered , d : PersistentChannelData ) =>
1566- log.info(s " zero-conf funding txid= ${w.tx.txid} has been published " )
15671566 val fundingStatus = LocalFundingStatus .ZeroconfPublishedFundingTx (w.tx)
1568- val commitments1 = d.commitments.updateLocalFundingStatus(w.tx.txid, fundingStatus)
1569- watchFundingConfirmed(w.tx.txid, Some (nodeParams.channelConf.minDepthBlocks))
1570- val d1 = d match {
1571- // NB: we discard remote's stashed channel_ready, they will send it back at reconnection
1572- case d : DATA_WAIT_FOR_FUNDING_CONFIRMED =>
1573- val realScidStatus = RealScidStatus .Unknown
1574- val shortIds = createShortIds(d.channelId, realScidStatus)
1575- DATA_WAIT_FOR_CHANNEL_READY (commitments1, shortIds)
1576- case d : DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED =>
1577- val realScidStatus = RealScidStatus .Unknown
1578- val shortIds = createShortIds(d.channelId, realScidStatus)
1579- DATA_WAIT_FOR_DUAL_FUNDING_READY (commitments1, shortIds)
1580- case d : DATA_WAIT_FOR_CHANNEL_READY => d.copy(commitments = commitments1)
1581- case d : DATA_WAIT_FOR_DUAL_FUNDING_READY => d.copy(commitments = commitments1)
1582- case d : DATA_NORMAL => d.copy(commitments = commitments1)
1583- case d : DATA_SHUTDOWN => d.copy(commitments = commitments1)
1584- case d : DATA_NEGOTIATING => d.copy(commitments = commitments1)
1585- case d : DATA_WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT => d.copy(commitments = commitments1)
1586- case d : DATA_CLOSING => d.copy(commitments = commitments1)
1587- }
1588- stay() using d1 storing()
1567+ d.commitments.updateLocalFundingStatus(w.tx.txid, fundingStatus) match {
1568+ case Right ((commitments1, _)) =>
1569+ log.info(s " zero-conf funding txid= ${w.tx.txid} has been published " )
1570+ watchFundingConfirmed(w.tx.txid, Some (nodeParams.channelConf.minDepthBlocks))
1571+ val d1 = d match {
1572+ // NB: we discard remote's stashed channel_ready, they will send it back at reconnection
1573+ case d : DATA_WAIT_FOR_FUNDING_CONFIRMED =>
1574+ val realScidStatus = RealScidStatus .Unknown
1575+ val shortIds = createShortIds(d.channelId, realScidStatus)
1576+ DATA_WAIT_FOR_CHANNEL_READY (commitments1, shortIds)
1577+ case d : DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED =>
1578+ val realScidStatus = RealScidStatus .Unknown
1579+ val shortIds = createShortIds(d.channelId, realScidStatus)
1580+ DATA_WAIT_FOR_DUAL_FUNDING_READY (commitments1, shortIds)
1581+ case d : DATA_WAIT_FOR_CHANNEL_READY => d.copy(commitments = commitments1)
1582+ case d : DATA_WAIT_FOR_DUAL_FUNDING_READY => d.copy(commitments = commitments1)
1583+ case d : DATA_NORMAL => d.copy(commitments = commitments1)
1584+ case d : DATA_SHUTDOWN => d.copy(commitments = commitments1)
1585+ case d : DATA_NEGOTIATING => d.copy(commitments = commitments1)
1586+ case d : DATA_WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT => d.copy(commitments = commitments1)
1587+ case d : DATA_CLOSING => d.copy(commitments = commitments1)
1588+ }
1589+ stay() using d1 storing()
1590+ case Left (_) => stay()
1591+ }
15891592
15901593 case Event (w : WatchFundingConfirmedTriggered , d : PersistentChannelData ) =>
1591- log.info(s " funding txid= ${w.tx.txid} has been confirmed " )
1592- val commitments1 = acceptFundingTxConfirmed(w, d)
1593- val d1 = d match {
1594- // NB: we discard remote's stashed channel_ready, they will send it back at reconnection
1595- case d : DATA_WAIT_FOR_FUNDING_CONFIRMED =>
1596- val realScidStatus = RealScidStatus .Temporary (RealShortChannelId (w.blockHeight, w.txIndex, commitments1.latest.commitInput.outPoint.index.toInt))
1597- val shortIds = createShortIds(d.channelId, realScidStatus)
1598- DATA_WAIT_FOR_CHANNEL_READY (commitments1, shortIds)
1599- case d : DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED =>
1600- val realScidStatus = RealScidStatus .Temporary (RealShortChannelId (w.blockHeight, w.txIndex, commitments1.latest.commitInput.outPoint.index.toInt))
1601- val shortIds = createShortIds(d.channelId, realScidStatus)
1602- DATA_WAIT_FOR_DUAL_FUNDING_READY (commitments1, shortIds)
1603- case d : DATA_WAIT_FOR_CHANNEL_READY => d.copy(commitments = commitments1)
1604- case d : DATA_WAIT_FOR_DUAL_FUNDING_READY => d.copy(commitments = commitments1)
1605- case d : DATA_NORMAL => d.copy(commitments = commitments1)
1606- case d : DATA_SHUTDOWN => d.copy(commitments = commitments1)
1607- case d : DATA_NEGOTIATING => d.copy(commitments = commitments1)
1608- case d : DATA_WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT => d.copy(commitments = commitments1)
1609- case d : DATA_CLOSING => d // there is a dedicated handler in CLOSING state
1610- }
1611- stay() using d1 storing()
1594+ acceptFundingTxConfirmed(w, d) match {
1595+ case Right ((commitments1, commitment)) =>
1596+ log.info(s " funding txid= ${w.tx.txid} has been confirmed " )
1597+ val d1 = d match {
1598+ // NB: we discard remote's stashed channel_ready, they will send it back at reconnection
1599+ case d : DATA_WAIT_FOR_FUNDING_CONFIRMED =>
1600+ val realScidStatus = RealScidStatus .Temporary (RealShortChannelId (w.blockHeight, w.txIndex, commitment.commitInput.outPoint.index.toInt))
1601+ val shortIds = createShortIds(d.channelId, realScidStatus)
1602+ DATA_WAIT_FOR_CHANNEL_READY (commitments1, shortIds)
1603+ case d : DATA_WAIT_FOR_DUAL_FUNDING_CONFIRMED =>
1604+ val realScidStatus = RealScidStatus .Temporary (RealShortChannelId (w.blockHeight, w.txIndex, commitment.commitInput.outPoint.index.toInt))
1605+ val shortIds = createShortIds(d.channelId, realScidStatus)
1606+ DATA_WAIT_FOR_DUAL_FUNDING_READY (commitments1, shortIds)
1607+ case d : DATA_WAIT_FOR_CHANNEL_READY => d.copy(commitments = commitments1)
1608+ case d : DATA_WAIT_FOR_DUAL_FUNDING_READY => d.copy(commitments = commitments1)
1609+ case d : DATA_NORMAL => d.copy(commitments = commitments1)
1610+ case d : DATA_SHUTDOWN => d.copy(commitments = commitments1)
1611+ case d : DATA_NEGOTIATING => d.copy(commitments = commitments1)
1612+ case d : DATA_WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT => d.copy(commitments = commitments1)
1613+ case d : DATA_CLOSING => d // there is a dedicated handler in CLOSING state
1614+ }
1615+ stay() using d1 storing()
1616+ case Left (_) => stay()
1617+ }
16121618
16131619 case Event (WatchFundingSpentTriggered (tx), d : DATA_NEGOTIATING ) if d.closingTxProposed.flatten.exists(_.unsignedTx.tx.txid == tx.txid) =>
16141620 // they can publish a closing tx with any sig we sent them, even if we are not done negotiating
0 commit comments