mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-08-31 08:02:25 +02:00
contractcourt: register conf notification once and cancel when confirmed
This commit is contained in:
@@ -224,13 +224,6 @@ type chainWatcher struct {
|
|||||||
// the current state number on the commitment transactions.
|
// the current state number on the commitment transactions.
|
||||||
stateHintObfuscator [lnwallet.StateHintSize]byte
|
stateHintObfuscator [lnwallet.StateHintSize]byte
|
||||||
|
|
||||||
// fundingPkScript is the pkScript of the funding output.
|
|
||||||
fundingPkScript []byte
|
|
||||||
|
|
||||||
// heightHint is the height hint used to checkpoint scans on chain for
|
|
||||||
// conf/spend events.
|
|
||||||
heightHint uint32
|
|
||||||
|
|
||||||
// All the fields below are protected by this mutex.
|
// All the fields below are protected by this mutex.
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
|
||||||
@@ -245,6 +238,18 @@ type chainWatcher struct {
|
|||||||
// fundingSpendNtfn is the spending notification subscription for the
|
// fundingSpendNtfn is the spending notification subscription for the
|
||||||
// funding outpoint.
|
// funding outpoint.
|
||||||
fundingSpendNtfn *chainntnfs.SpendEvent
|
fundingSpendNtfn *chainntnfs.SpendEvent
|
||||||
|
|
||||||
|
// fundingConfirmedNtfn is the confirmation notification subscription
|
||||||
|
// for the funding outpoint. This is only created if the channel is
|
||||||
|
// both taproot and pending confirmation.
|
||||||
|
//
|
||||||
|
// For taproot pkscripts, `RegisterSpendNtfn` will only notify on the
|
||||||
|
// outpoint being spent and not the outpoint+pkscript due to
|
||||||
|
// `ComputePkScript` being unable to compute the pkscript if a key
|
||||||
|
// spend is used. We need to add a `RegisterConfirmationsNtfn` here to
|
||||||
|
// ensure that the outpoint+pkscript pair is confirmed before calling
|
||||||
|
// `RegisterSpendNtfn`.
|
||||||
|
fundingConfirmedNtfn *chainntnfs.ConfirmationEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
// newChainWatcher returns a new instance of a chainWatcher for a channel given
|
// newChainWatcher returns a new instance of a chainWatcher for a channel given
|
||||||
@@ -292,11 +297,24 @@ func newChainWatcher(cfg chainWatcherConfig) (*chainWatcher, error) {
|
|||||||
stateHintObfuscator: stateHint,
|
stateHintObfuscator: stateHint,
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
clientSubscriptions: make(map[uint64]*ChainEventSubscription),
|
clientSubscriptions: make(map[uint64]*ChainEventSubscription),
|
||||||
fundingPkScript: fundingPkScript,
|
|
||||||
heightHint: heightHint,
|
|
||||||
fundingSpendNtfn: spendNtfn,
|
fundingSpendNtfn: spendNtfn,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this is a pending taproot channel, we need to register for a
|
||||||
|
// confirmation notification of the funding tx. Check the docs in
|
||||||
|
// `fundingConfirmedNtfn` for details.
|
||||||
|
if c.cfg.chanState.IsPending && c.cfg.chanState.ChanType.IsTaproot() {
|
||||||
|
confNtfn, err := cfg.notifier.RegisterConfirmationsNtfn(
|
||||||
|
&chanState.FundingOutpoint.Hash, fundingPkScript, 1,
|
||||||
|
heightHint,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.fundingConfirmedNtfn = confNtfn
|
||||||
|
}
|
||||||
|
|
||||||
// Mount the block consumer.
|
// Mount the block consumer.
|
||||||
c.BeatConsumer = chainio.NewBeatConsumer(c.quit, c.Name())
|
c.BeatConsumer = chainio.NewBeatConsumer(c.quit, c.Name())
|
||||||
|
|
||||||
@@ -1472,28 +1490,24 @@ func (c *chainWatcher) checkFundingSpend() *chainntnfs.SpendDetail {
|
|||||||
// chanPointConfirmed checks whether the given channel point has confirmed.
|
// chanPointConfirmed checks whether the given channel point has confirmed.
|
||||||
// This is used to ensure that the funding output has confirmed on chain before
|
// This is used to ensure that the funding output has confirmed on chain before
|
||||||
// we proceed with the rest of the close observer logic for taproot channels.
|
// we proceed with the rest of the close observer logic for taproot channels.
|
||||||
|
// Check the docs in `fundingConfirmedNtfn` for details.
|
||||||
func (c *chainWatcher) chanPointConfirmed() bool {
|
func (c *chainWatcher) chanPointConfirmed() bool {
|
||||||
op := c.cfg.chanState.FundingOutpoint
|
op := c.cfg.chanState.FundingOutpoint
|
||||||
confNtfn, err := c.cfg.notifier.RegisterConfirmationsNtfn(
|
|
||||||
&op.Hash, c.fundingPkScript, 1, c.heightHint,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Unable to register for conf: %v", err)
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case _, ok := <-confNtfn.Confirmed:
|
case _, ok := <-c.fundingConfirmedNtfn.Confirmed:
|
||||||
// If the channel was closed, then this means that the notifier
|
// If the channel was closed, then this means that the notifier
|
||||||
// exited, so we will as well.
|
// exited, so we will as well.
|
||||||
if !ok {
|
if !ok {
|
||||||
// Check the docs in `fundingConfirmedNtfn` for details.
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Taproot ChannelPoint(%v) confirmed", op)
|
log.Debugf("Taproot ChannelPoint(%v) confirmed", op)
|
||||||
|
|
||||||
|
// The channel point has confirmed on chain. We now cancel the
|
||||||
|
// subscription.
|
||||||
|
c.fundingConfirmedNtfn.Cancel()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -1510,9 +1524,11 @@ func (c *chainWatcher) handleBlockbeat(beat chainio.Blockbeat) {
|
|||||||
// Notify the chain watcher has processed the block.
|
// Notify the chain watcher has processed the block.
|
||||||
defer c.NotifyBlockProcessed(beat, nil)
|
defer c.NotifyBlockProcessed(beat, nil)
|
||||||
|
|
||||||
// If this is a taproot channel, before we proceed, we want to ensure
|
// If we have a fundingConfirmedNtfn, it means this is a taproot
|
||||||
// that the expected funding output has confirmed on chain.
|
// channel that is pending, before we proceed, we want to ensure that
|
||||||
if c.cfg.chanState.IsPending && c.cfg.chanState.ChanType.IsTaproot() {
|
// the expected funding output has confirmed on chain. Check the docs
|
||||||
|
// in `fundingConfirmedNtfn` for details.
|
||||||
|
if c.fundingConfirmedNtfn != nil {
|
||||||
// If the funding output hasn't confirmed in this block, we
|
// If the funding output hasn't confirmed in this block, we
|
||||||
// will check it again in the next block.
|
// will check it again in the next block.
|
||||||
if !c.chanPointConfirmed() {
|
if !c.chanPointConfirmed() {
|
||||||
|
Reference in New Issue
Block a user