lnwallet: add ability to cancel the channel's closeObserver
This commit adds the ability to cancel a channel’s internal closeObserver goroutine by adding a new public facing Stop method. Additionally, we now make passing a ChainNotifier interface completely optional. If the ChainNotifier isn’t passed in as a constructor, then the closeObserver goroutine will never be launched. This new feature lets the caller ensure that only a single closeObsever for any given channels exists.
This commit is contained in:
parent
f4b403679b
commit
62bcd59db4
@ -441,11 +441,8 @@ type LightningChannel struct {
|
|||||||
// channel.
|
// channel.
|
||||||
RemoteFundingKey *btcec.PublicKey
|
RemoteFundingKey *btcec.PublicKey
|
||||||
|
|
||||||
started int32
|
|
||||||
shutdown int32
|
shutdown int32
|
||||||
|
quit chan struct{}
|
||||||
quit chan struct{}
|
|
||||||
wg sync.WaitGroup
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLightningChannel creates a new, active payment channel given an
|
// NewLightningChannel creates a new, active payment channel given an
|
||||||
@ -477,6 +474,7 @@ func NewLightningChannel(signer Signer, events chainntnfs.ChainNotifier,
|
|||||||
ContractBreach: make(chan *BreachRetribution, 1),
|
ContractBreach: make(chan *BreachRetribution, 1),
|
||||||
LocalFundingKey: state.OurMultiSigKey,
|
LocalFundingKey: state.OurMultiSigKey,
|
||||||
RemoteFundingKey: state.TheirMultiSigKey,
|
RemoteFundingKey: state.TheirMultiSigKey,
|
||||||
|
quit: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize both of our chains the current un-revoked commitment for
|
// Initialize both of our chains the current un-revoked commitment for
|
||||||
@ -519,19 +517,25 @@ func NewLightningChannel(signer Signer, events chainntnfs.ChainNotifier,
|
|||||||
InputIndex: 0,
|
InputIndex: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register for a notification to be dispatched if the funding outpoint
|
// We'll only launch a close observer if the ChainNotifier
|
||||||
// has been spent. This indicates that either us or the remote party
|
// implementation is non-nil. Passing a nil value indicates that the
|
||||||
// has broadcasted a commitment transaction on-chain.
|
// channel shouldn't be actively watched for.
|
||||||
fundingOut := &lc.fundingTxIn.PreviousOutPoint
|
if lc.channelEvents != nil {
|
||||||
channelCloseNtfn, err := lc.channelEvents.RegisterSpendNtfn(fundingOut)
|
// Register for a notification to be dispatched if the funding
|
||||||
if err != nil {
|
// outpoint has been spent. This indicates that either us or
|
||||||
return nil, err
|
// the remote party has broadcasted a commitment transaction
|
||||||
}
|
// on-chain.
|
||||||
|
fundingOut := &lc.fundingTxIn.PreviousOutPoint
|
||||||
|
channelCloseNtfn, err := lc.channelEvents.RegisterSpendNtfn(fundingOut)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Launch the close observer which will vigilantly watch the network
|
// Launch the close observer which will vigilantly watch the
|
||||||
// for any broadcasts the current or prior commitment transactions,
|
// network for any broadcasts the current or prior commitment
|
||||||
// taking action accordingly.
|
// transactions, taking action accordingly.
|
||||||
go lc.closeObserver(channelCloseNtfn)
|
go lc.closeObserver(channelCloseNtfn)
|
||||||
|
}
|
||||||
|
|
||||||
return lc, nil
|
return lc, nil
|
||||||
}
|
}
|
||||||
@ -682,10 +686,25 @@ func newBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
|
|||||||
//
|
//
|
||||||
// NOTE: This MUST be run as a goroutine.
|
// NOTE: This MUST be run as a goroutine.
|
||||||
func (lc *LightningChannel) closeObserver(channelCloseNtfn *chainntnfs.SpendEvent) {
|
func (lc *LightningChannel) closeObserver(channelCloseNtfn *chainntnfs.SpendEvent) {
|
||||||
|
walletLog.Infof("Close observer for ChannelPoint(%v) active",
|
||||||
|
lc.channelState.ChanID)
|
||||||
|
|
||||||
|
var (
|
||||||
|
commitSpend *chainntnfs.SpendDetail
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
|
||||||
|
select {
|
||||||
// If the daemon is shutting down, then this notification channel will
|
// If the daemon is shutting down, then this notification channel will
|
||||||
// be closed, so check the second read-value to avoid a false positive.
|
// be closed, so check the second read-value to avoid a false positive.
|
||||||
commitSpend, ok := <-channelCloseNtfn.Spend
|
case commitSpend, ok = <-channelCloseNtfn.Spend:
|
||||||
if !ok {
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, we've be signalled to bail out early by the
|
||||||
|
// caller/maintainer of this channel.
|
||||||
|
case <-lc.quit:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -769,6 +788,16 @@ func (lc *LightningChannel) closeObserver(channelCloseNtfn *chainntnfs.SpendEven
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stop gracefully shuts down any active goroutines spawned by the
|
||||||
|
// LightningChannel during regular duties.
|
||||||
|
func (lc *LightningChannel) Stop() {
|
||||||
|
if !atomic.CompareAndSwapInt32(&lc.shutdown, 0, 1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
close(lc.quit)
|
||||||
|
}
|
||||||
|
|
||||||
// restoreStateLogs runs through the current locked-in HTLCs from the point of
|
// restoreStateLogs runs through the current locked-in HTLCs from the point of
|
||||||
// view of the channel and insert corresponding log entries (both local and
|
// view of the channel and insert corresponding log entries (both local and
|
||||||
// remote) for each HTLC read from disk. This method is required sync the
|
// remote) for each HTLC read from disk. This method is required sync the
|
||||||
|
Loading…
Reference in New Issue
Block a user