funding: persist ConfirmationHeight upon first funding confirmation

This change ensures that a channel's ConfirmationHeight is recorded in the
database once its funding transaction receives its initial confirmation.
By doing so, we establish a reliable reference point to monitor the
channel's progress toward the required confirmation depth.

Signed-off-by: Nishant Bansal <nishant.bansal.282003@gmail.com>
This commit is contained in:
Nishant Bansal committed 2025-09-11 18:26:42 +05:30
1 parent 222f49c593
commit ede08a8883
2 files changed
+325 -105

No files matched your search

+128 -24
View File
@@ -3064,7 +3064,8 @@ func makeFundingScript(channel *channeldb.OpenChannel) ([]byte, error) {
// process once the funding transaction has been broadcast. The primary
// function of waitForFundingConfirmation is to wait for blockchain
// confirmation, and then to notify the other systems that must be notified
// when a channel has become active for lightning transactions.
// when a channel has become active for lightning transactions. It also updates
// the channel’s opening transaction block height in the database.
// The wait can be canceled by closing the cancelChan. In case of success,
// a *lnwire.ShortChannelID will be passed to confChan.
//
@@ -3108,34 +3109,135 @@ func (f *Manager) waitForFundingConfirmation(
log.Infof("Waiting for funding tx (%v) to reach %v confirmations",
txid, numConfs)
var confDetails *chainntnfs.TxConfirmation
var ok bool
// Wait until the specified number of confirmations has been reached,
// we get a cancel signal, or the wallet signals a shutdown.
select {
case confDetails, ok = <-confNtfn.Confirmed:
// fallthrough
for {
select {
case updDetails, ok := <-confNtfn.Updates:
if !ok {
log.Warnf("ChainNotifier shutting down, "+
"cannot process updates for "+
"ChannelPoint(%v)",
completeChan.FundingOutpoint)
case <-cancelChan:
log.Warnf("canceled waiting for funding confirmation, "+
"stopping funding flow for ChannelPoint(%v)",
completeChan.FundingOutpoint)
return
return
}
case <-f.quit:
log.Warnf("fundingManager shutting down, stopping funding "+
"flow for ChannelPoint(%v)",
completeChan.FundingOutpoint)
return
log.Debugf("funding tx %s received confirmation in "+
"block %d, %d confirmations left", txid,
updDetails.BlockHeight, updDetails.NumConfsLeft)
// Only update the ConfirmationHeight the first time a
// confirmation is received, since on subsequent
// confirmations the block height will remain the same.
if completeChan.ConfirmationHeight == 0 {
err := completeChan.MarkConfirmationHeight(
updDetails.BlockHeight,
)
if err != nil {
log.Errorf("failed to update "+
"confirmed state for "+
"ChannelPoint(%v): %v",
completeChan.FundingOutpoint,
err)
return
}
}
case _, ok := <-confNtfn.NegativeConf:
if !ok {
log.Warnf("ChainNotifier shutting down, "+
"cannot track negative confirmations "+
"for ChannelPoint(%v)",
completeChan.FundingOutpoint)
return
}
log.Warnf("funding tx %s was reorged out; channel "+
"point: %s", txid, completeChan.FundingOutpoint)
// Reset the confirmation height to 0 because the
// funding transaction was reorged out.
err := completeChan.MarkConfirmationHeight(uint32(0))
if err != nil {
log.Errorf("failed to update state for "+
"ChannelPoint(%v): %v",
completeChan.FundingOutpoint, err)
return
}
case confDetails, ok := <-confNtfn.Confirmed:
if !ok {
log.Warnf("ChainNotifier shutting down, "+
"cannot complete funding flow for "+
"ChannelPoint(%v)",
completeChan.FundingOutpoint)
return
}
log.Debugf("funding tx %s for ChannelPoint(%v) "+
"confirmed in block %d", txid,
completeChan.FundingOutpoint,
confDetails.BlockHeight)
// In the case of requiring a single confirmation, it
// can happen that the `Confirmed` channel is read
// from first, in which case the confirmation height
// will not be set. If this happens, we take the
// confirmation height from the `Confirmed` channel.
if completeChan.ConfirmationHeight == 0 {
err := completeChan.MarkConfirmationHeight(
confDetails.BlockHeight,
)
if err != nil {
log.Errorf("failed to update "+
"confirmed state for "+
"ChannelPoint(%v): %v",
completeChan.FundingOutpoint,
err)
return
}
}
err := f.handleConfirmation(
confDetails, completeChan, confChan,
)
if err != nil {
log.Errorf("Error handling confirmation for "+
"ChannelPoint(%v), txid=%v: %v",
completeChan.FundingOutpoint, txid, err)
}
return
case <-cancelChan:
log.Warnf("canceled waiting for funding confirmation, "+
"stopping funding flow for ChannelPoint(%v)",
completeChan.FundingOutpoint)
return
case <-f.quit:
log.Warnf("fundingManager shutting down, stopping "+
"funding flow for ChannelPoint(%v)",
completeChan.FundingOutpoint)
return
}
}
}
if !ok {
log.Warnf("ChainNotifier shutting down, cannot complete "+
"funding flow for ChannelPoint(%v)",
completeChan.FundingOutpoint)
return
}
// handleConfirmation is a helper function that constructs a ShortChannelID
// based on the confirmation details and sends this information, along with the
// funding transaction, to the provided confirmation channel.
func (f *Manager) handleConfirmation(confDetails *chainntnfs.TxConfirmation,
completeChan *channeldb.OpenChannel,
confChan chan<- *confirmedChannel) error {
fundingPoint := completeChan.FundingOutpoint
log.Infof("ChannelPoint(%v) is now active: ChannelID(%v)",
@@ -3156,8 +3258,10 @@ func (f *Manager) waitForFundingConfirmation(
fundingTx: confDetails.Tx,
}:
case <-f.quit:
return
return fmt.Errorf("manager shutting down")
}
return nil
}
// waitForTimeout will close the timeout channel if MaxWaitNumBlocksFundingConf