180dffd154
In this commit, we modify the logic within RegisterSpendNtfn for the BitcoindNotifier to account for the recent changes made to the TxNotifier. Since it is now able to handle spend notification registration and dispatch, we can bypass all the current logic within the BitcoindNotifier and interact directly with the TxNotifier instead. The most notable changes include the following: 1. We'll only attempt a historical rescan if the TxNotifier tells us so. 2. We'll dispatch the historical rescan within the main goroutine to prevent WaitGroup panics, due to the asynchronous nature of the notifier.
81 lines
2.1 KiB
Go
81 lines
2.1 KiB
Go
// +build dev
|
|
|
|
package bitcoindnotify
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
|
"github.com/btcsuite/btcwallet/chain"
|
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
|
)
|
|
|
|
// UnsafeStart starts the notifier with a specified best height and optional
|
|
// best hash. Its bestBlock and txNotifier are initialized with bestHeight and
|
|
// optionally bestHash. The parameter generateBlocks is necessary for the
|
|
// bitcoind notifier to ensure we drain all notifications up to syncHeight,
|
|
// since if they are generated ahead of UnsafeStart the chainConn may start up
|
|
// with an outdated best block and miss sending ntfns. Used for testing.
|
|
func (b *BitcoindNotifier) UnsafeStart(bestHeight int32, bestHash *chainhash.Hash,
|
|
syncHeight int32, generateBlocks func() error) error {
|
|
|
|
// Connect to bitcoind, and register for notifications on connected,
|
|
// and disconnected blocks.
|
|
if err := b.chainConn.Start(); err != nil {
|
|
return err
|
|
}
|
|
if err := b.chainConn.NotifyBlocks(); err != nil {
|
|
return err
|
|
}
|
|
|
|
b.txNotifier = chainntnfs.NewTxNotifier(
|
|
uint32(bestHeight), reorgSafetyLimit, b.confirmHintCache,
|
|
b.spendHintCache,
|
|
)
|
|
|
|
if generateBlocks != nil {
|
|
// Ensure no block notifications are pending when we start the
|
|
// notification dispatcher goroutine.
|
|
|
|
// First generate the blocks, then drain the notifications
|
|
// for the generated blocks.
|
|
if err := generateBlocks(); err != nil {
|
|
return err
|
|
}
|
|
|
|
timeout := time.After(60 * time.Second)
|
|
loop:
|
|
for {
|
|
select {
|
|
case ntfn := <-b.chainConn.Notifications():
|
|
switch update := ntfn.(type) {
|
|
case chain.BlockConnected:
|
|
if update.Height >= syncHeight {
|
|
break loop
|
|
}
|
|
}
|
|
case <-timeout:
|
|
return fmt.Errorf("unable to catch up to height %d",
|
|
syncHeight)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Run notificationDispatcher after setting the notifier's best block
|
|
// to avoid a race condition.
|
|
b.bestBlock = chainntnfs.BlockEpoch{Height: bestHeight, Hash: bestHash}
|
|
if bestHash == nil {
|
|
hash, err := b.chainConn.GetBlockHash(int64(bestHeight))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b.bestBlock.Hash = hash
|
|
}
|
|
|
|
b.wg.Add(1)
|
|
go b.notificationDispatcher()
|
|
|
|
return nil
|
|
}
|