Browse Source

Merge pull request #2044 from wpaulino/enable-height-hint-cache

chainntnfs: re-enable height hint cache
master
Olaoluwa Osuntokun 6 years ago committed by GitHub
parent
commit
c3546c280d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 23
      chainntnfs/bitcoindnotify/bitcoind.go
  2. 2
      chainntnfs/bitcoindnotify/bitcoind_test.go
  3. 22
      chainntnfs/btcdnotify/btcd.go
  4. 2
      chainntnfs/btcdnotify/btcd_test.go
  5. 34
      chainntnfs/height_hint_cache.go
  6. 81
      chainntnfs/height_hint_cache_test.go
  7. 2
      chainntnfs/interface_test.go
  8. 18
      chainntnfs/neutrinonotify/neutrino.go
  9. 44
      chainntnfs/txnotifier.go
  10. 116
      chainntnfs/txnotifier_test.go
  11. 4
      chainregistry.go
  12. 2
      lnwallet/interface_test.go

23
chainntnfs/bitcoindnotify/bitcoind.go

@ -568,14 +568,19 @@ func (b *BitcoindNotifier) confDetailsManually(txid *chainhash.Hash,
// transactions included this block will processed to either send notifications
// now or after numConfirmations confs.
func (b *BitcoindNotifier) handleBlockConnected(block chainntnfs.BlockEpoch) error {
// First, we'll fetch the raw block as we'll need to gather all the
// transactions to determine whether any are relevant to our registered
// clients.
rawBlock, err := b.chainConn.GetBlock(block.Hash)
if err != nil {
return fmt.Errorf("unable to get block: %v", err)
}
txns := btcutil.NewBlock(rawBlock).Transactions()
err = b.txNotifier.ConnectTip(
block.Hash, uint32(block.Height), txns)
// We'll then extend the txNotifier's height with the information of
// this new block, which will handle all of the notification logic for
// us.
err = b.txNotifier.ConnectTip(block.Hash, uint32(block.Height), txns)
if err != nil {
return fmt.Errorf("unable to connect tip: %v", err)
}
@ -583,15 +588,15 @@ func (b *BitcoindNotifier) handleBlockConnected(block chainntnfs.BlockEpoch) err
chainntnfs.Log.Infof("New block: height=%v, sha=%v", block.Height,
block.Hash)
// We want to set the best block before dispatching notifications so
// if any subscribers make queries based on their received block epoch,
// our state is fully updated in time.
// Now that we've guaranteed the new block extends the txNotifier's
// current tip, we'll proceed to dispatch notifications to all of our
// registered clients whom have had notifications fulfilled. Before
// doing so, we'll make sure update our in memory state in order to
// satisfy any client requests based upon the new block.
b.bestBlock = block
// Lastly we'll notify any subscribed clients of the block.
b.notifyBlockEpochs(block.Height, block.Hash)
return nil
return b.txNotifier.NotifyHeight(uint32(block.Height))
}
// notifyBlockEpochs notifies all registered block epoch clients of the newly

2
chainntnfs/bitcoindnotify/bitcoind_test.go

@ -25,7 +25,7 @@ func initHintCache(t *testing.T) *chainntnfs.HeightHintCache {
if err != nil {
t.Fatalf("unable to create db: %v", err)
}
hintCache, err := chainntnfs.NewHeightHintCache(db, true)
hintCache, err := chainntnfs.NewHeightHintCache(db)
if err != nil {
t.Fatalf("unable to create hint cache: %v", err)
}

22
chainntnfs/btcdnotify/btcd.go

@ -622,14 +622,13 @@ func (b *BtcdNotifier) confDetailsManually(txid *chainhash.Hash, startHeight,
// TODO(halseth): this is reusing the neutrino notifier implementation, unify
// them.
func (b *BtcdNotifier) handleBlockConnected(epoch chainntnfs.BlockEpoch) error {
// First process the block for our internal state. A new block has
// been connected to the main chain. Send out any N confirmation
// notifications which may have been triggered by this new block.
// First, we'll fetch the raw block as we'll need to gather all the
// transactions to determine whether any are relevant to our registered
// clients.
rawBlock, err := b.chainConn.GetBlock(epoch.Hash)
if err != nil {
return fmt.Errorf("unable to get block: %v", err)
}
newBlock := &filteredBlock{
hash: *epoch.Hash,
height: uint32(epoch.Height),
@ -637,6 +636,9 @@ func (b *BtcdNotifier) handleBlockConnected(epoch chainntnfs.BlockEpoch) error {
connect: true,
}
// We'll then extend the txNotifier's height with the information of
// this new block, which will handle all of the notification logic for
// us.
err = b.txNotifier.ConnectTip(
&newBlock.hash, newBlock.height, newBlock.txns,
)
@ -647,13 +649,15 @@ func (b *BtcdNotifier) handleBlockConnected(epoch chainntnfs.BlockEpoch) error {
chainntnfs.Log.Infof("New block: height=%v, sha=%v", epoch.Height,
epoch.Hash)
// We want to set the best block before dispatching notifications so if
// any subscribers make queries based on their received block epoch, our
// state is fully updated in time.
// Now that we've guaranteed the new block extends the txNotifier's
// current tip, we'll proceed to dispatch notifications to all of our
// registered clients whom have had notifications fulfilled. Before
// doing so, we'll make sure update our in memory state in order to
// satisfy any client requests based upon the new block.
b.bestBlock = epoch
b.notifyBlockEpochs(int32(newBlock.height), &newBlock.hash)
return nil
b.notifyBlockEpochs(epoch.Height, epoch.Hash)
return b.txNotifier.NotifyHeight(uint32(epoch.Height))
}
// notifyBlockEpochs notifies all registered block epoch clients of the newly

2
chainntnfs/btcdnotify/btcd_test.go

@ -23,7 +23,7 @@ func initHintCache(t *testing.T) *chainntnfs.HeightHintCache {
if err != nil {
t.Fatalf("unable to create db: %v", err)
}
hintCache, err := chainntnfs.NewHeightHintCache(db, true)
hintCache, err := chainntnfs.NewHeightHintCache(db)
if err != nil {
t.Fatalf("unable to create hint cache: %v", err)
}

34
chainntnfs/height_hint_cache.go

@ -85,8 +85,7 @@ type ConfirmHintCache interface {
// ConfirmHintCache interfaces backed by a channeldb DB instance where the hints
// will be stored.
type HeightHintCache struct {
db *channeldb.DB
disabled bool
db *channeldb.DB
}
// Compile-time checks to ensure HeightHintCache satisfies the SpendHintCache
@ -95,11 +94,8 @@ var _ SpendHintCache = (*HeightHintCache)(nil)
var _ ConfirmHintCache = (*HeightHintCache)(nil)
// NewHeightHintCache returns a new height hint cache backed by a database.
func NewHeightHintCache(db *channeldb.DB, disable bool) (*HeightHintCache, error) {
cache := &HeightHintCache{
db: db,
disabled: disable,
}
func NewHeightHintCache(db *channeldb.DB) (*HeightHintCache, error) {
cache := &HeightHintCache{db}
if err := cache.initBuckets(); err != nil {
return nil, err
}
@ -123,10 +119,6 @@ func (c *HeightHintCache) initBuckets() error {
// CommitSpendHint commits a spend hint for the outpoints to the cache.
func (c *HeightHintCache) CommitSpendHint(height uint32, ops ...wire.OutPoint) error {
if c.disabled {
return nil
}
if len(ops) == 0 {
return nil
}
@ -165,10 +157,6 @@ func (c *HeightHintCache) CommitSpendHint(height uint32, ops ...wire.OutPoint) e
// ErrSpendHintNotFound is returned if a spend hint does not exist within the
// cache for the outpoint.
func (c *HeightHintCache) QuerySpendHint(op wire.OutPoint) (uint32, error) {
if c.disabled {
return 0, ErrSpendHintNotFound
}
var hint uint32
err := c.db.View(func(tx *bolt.Tx) error {
spendHints := tx.Bucket(spendHintBucket)
@ -197,10 +185,6 @@ func (c *HeightHintCache) QuerySpendHint(op wire.OutPoint) (uint32, error) {
// PurgeSpendHint removes the spend hint for the outpoints from the cache.
func (c *HeightHintCache) PurgeSpendHint(ops ...wire.OutPoint) error {
if c.disabled {
return nil
}
if len(ops) == 0 {
return nil
}
@ -232,10 +216,6 @@ func (c *HeightHintCache) PurgeSpendHint(ops ...wire.OutPoint) error {
// CommitConfirmHint commits a confirm hint for the transactions to the cache.
func (c *HeightHintCache) CommitConfirmHint(height uint32, txids ...chainhash.Hash) error {
if c.disabled {
return nil
}
if len(txids) == 0 {
return nil
}
@ -274,10 +254,6 @@ func (c *HeightHintCache) CommitConfirmHint(height uint32, txids ...chainhash.Ha
// ErrConfirmHintNotFound is returned if a confirm hint does not exist within
// the cache for the transaction hash.
func (c *HeightHintCache) QueryConfirmHint(txid chainhash.Hash) (uint32, error) {
if c.disabled {
return 0, ErrConfirmHintNotFound
}
var hint uint32
err := c.db.View(func(tx *bolt.Tx) error {
confirmHints := tx.Bucket(confirmHintBucket)
@ -307,10 +283,6 @@ func (c *HeightHintCache) QueryConfirmHint(txid chainhash.Hash) (uint32, error)
// PurgeConfirmHint removes the confirm hint for the transactions from the
// cache.
func (c *HeightHintCache) PurgeConfirmHint(txids ...chainhash.Hash) error {
if c.disabled {
return nil
}
if len(txids) == 0 {
return nil
}

81
chainntnfs/height_hint_cache_test.go

@ -10,7 +10,7 @@ import (
"github.com/lightningnetwork/lnd/channeldb"
)
func initHintCache(t *testing.T, disable bool) *HeightHintCache {
func initHintCache(t *testing.T) *HeightHintCache {
t.Helper()
tempDir, err := ioutil.TempDir("", "kek")
@ -21,7 +21,7 @@ func initHintCache(t *testing.T, disable bool) *HeightHintCache {
if err != nil {
t.Fatalf("unable to create db: %v", err)
}
hintCache, err := NewHeightHintCache(db, disable)
hintCache, err := NewHeightHintCache(db)
if err != nil {
t.Fatalf("unable to create hint cache: %v", err)
}
@ -34,7 +34,7 @@ func initHintCache(t *testing.T, disable bool) *HeightHintCache {
func TestHeightHintCacheConfirms(t *testing.T) {
t.Parallel()
hintCache := initHintCache(t, false)
hintCache := initHintCache(t)
// Querying for a transaction hash not found within the cache should
// return an error indication so.
@ -93,7 +93,7 @@ func TestHeightHintCacheConfirms(t *testing.T) {
func TestHeightHintCacheSpends(t *testing.T) {
t.Parallel()
hintCache := initHintCache(t, false)
hintCache := initHintCache(t)
// Querying for an outpoint not found within the cache should return an
// error indication so.
@ -146,76 +146,3 @@ func TestHeightHintCacheSpends(t *testing.T) {
}
}
}
// TestHeightHintCacheDisabled asserts that a disabled height hint cache never
// returns spend or confirm hints that are committed.
func TestHeightHintCacheDisabled(t *testing.T) {
t.Parallel()
const height uint32 = 100
// Create a disabled height hint cache.
hintCache := initHintCache(t, true)
// Querying a disabled cache w/ no spend hint should return not found.
var outpoint wire.OutPoint
_, err := hintCache.QuerySpendHint(outpoint)
if err != ErrSpendHintNotFound {
t.Fatalf("expected ErrSpendHintNotFound, got: %v", err)
}
// Commit a spend hint to the disabled cache, which should be a noop.
if err := hintCache.CommitSpendHint(height, outpoint); err != nil {
t.Fatalf("unable to commit spend hint: %v", err)
}
// Querying a disabled cache after commit noop should return not found.
_, err = hintCache.QuerySpendHint(outpoint)
if err != ErrSpendHintNotFound {
t.Fatalf("expected ErrSpendHintNotFound, got: %v", err)
}
// Reenable the cache, this time actually committing a spend hint.
hintCache.disabled = false
if err := hintCache.CommitSpendHint(height, outpoint); err != nil {
t.Fatalf("unable to commit spend hint: %v", err)
}
// Disable the cache again, spend hint should not be found.
hintCache.disabled = true
_, err = hintCache.QuerySpendHint(outpoint)
if err != ErrSpendHintNotFound {
t.Fatalf("expected ErrSpendHintNotFound, got: %v", err)
}
// Querying a disabled cache w/ no conf hint should return not found.
var txid chainhash.Hash
_, err = hintCache.QueryConfirmHint(txid)
if err != ErrConfirmHintNotFound {
t.Fatalf("expected ErrConfirmHintNotFound, got: %v", err)
}
// Commit a conf hint to the disabled cache, which should be a noop.
if err := hintCache.CommitConfirmHint(height, txid); err != nil {
t.Fatalf("unable to commit spend hint: %v", err)
}
// Querying a disabled cache after commit noop should return not found.
_, err = hintCache.QueryConfirmHint(txid)
if err != ErrConfirmHintNotFound {
t.Fatalf("expected ErrConfirmHintNotFound, got: %v", err)
}
// Reenable the cache, this time actually committing a conf hint.
hintCache.disabled = false
if err := hintCache.CommitConfirmHint(height, txid); err != nil {
t.Fatalf("unable to commit spend hint: %v", err)
}
// Disable the cache again, conf hint should not be found.
hintCache.disabled = true
_, err = hintCache.QueryConfirmHint(txid)
if err != ErrConfirmHintNotFound {
t.Fatalf("expected ErrConfirmHintNotFound, got: %v", err)
}
}

2
chainntnfs/interface_test.go

@ -1758,7 +1758,7 @@ func TestInterfaces(t *testing.T) {
if err != nil {
t.Fatalf("unable to create db: %v", err)
}
hintCache, err := chainntnfs.NewHeightHintCache(db, true)
hintCache, err := chainntnfs.NewHeightHintCache(db)
if err != nil {
t.Fatalf("unable to create height hint cache: %v", err)
}

18
chainntnfs/neutrinonotify/neutrino.go

@ -542,9 +542,8 @@ func (n *NeutrinoNotifier) historicalConfDetails(targetHash *chainhash.Hash,
// transactions included this block will processed to either send notifications
// now or after numConfirmations confs.
func (n *NeutrinoNotifier) handleBlockConnected(newBlock *filteredBlock) error {
// First process the block for our internal state. A new block has
// been connected to the main chain. Send out any N confirmation
// notifications which may have been triggered by this new block.
// We'll extend the txNotifier's height with the information of this new
// block, which will handle all of the notification logic for us.
err := n.txNotifier.ConnectTip(
&newBlock.hash, newBlock.height, newBlock.txns,
)
@ -555,16 +554,15 @@ func (n *NeutrinoNotifier) handleBlockConnected(newBlock *filteredBlock) error {
chainntnfs.Log.Infof("New block: height=%v, sha=%v", newBlock.height,
newBlock.hash)
// We want to set the best block before dispatching notifications
// so if any subscribers make queries based on their received
// block epoch, our state is fully updated in time.
// Now that we've guaranteed the new block extends the txNotifier's
// current tip, we'll proceed to dispatch notifications to all of our
// registered clients whom have had notifications fulfilled. Before
// doing so, we'll make sure update our in memory state in order to
// satisfy any client requests based upon the new block.
n.bestHeight = newBlock.height
// With all persistent changes committed, notify any subscribed clients
// of the block.
n.notifyBlockEpochs(int32(newBlock.height), &newBlock.hash)
return nil
return n.txNotifier.NotifyHeight(newBlock.height)
}
// getFilteredBlock is a utility to retrieve the full filtered block from a block epoch.

44
chainntnfs/txnotifier.go

@ -887,9 +887,13 @@ func (n *TxNotifier) dispatchSpendDetails(ntfn *SpendNtfn, details *SpendDetail)
// confirmation registration for.
//
// In the event that the transaction is relevant, a confirmation/spend
// notification will be dispatched to the relevant clients. Confirmation
// notifications will only be dispatched for transactions that have met the
// required number of confirmations required by the client.
// notification will be queued for dispatch to the relevant clients.
// Confirmation notifications will only be dispatched for transactions that have
// met the required number of confirmations required by the client.
//
// NOTE: In order to actually dispatch the relevant transaction notifications to
// clients, NotifyHeight must be called with the same block height in order to
// maintain correctness.
func (n *TxNotifier) ConnectTip(blockHash *chainhash.Hash, blockHeight uint32,
txns []*btcutil.Tx) error {
@ -1017,14 +1021,24 @@ func (n *TxNotifier) ConnectTip(blockHash *chainhash.Hash, blockHeight uint32,
}
}
// Now that we've determined which transactions were confirmed and which
// outpoints were spent within the new block, we can update their
// entries in their respective caches, along with all of our unconfirmed
// transactions and unspent outpoints.
// Finally, now that we've determined which transactions were confirmed
// and which outpoints were spent within the new block, we can update
// their entries in their respective caches, along with all of our
// unconfirmed transactions and unspent outpoints.
n.updateHints(blockHeight)
// Next, we'll dispatch an update to all of the notification clients for
// our watched transactions with the number of confirmations left at
return nil
}
// NotifyHeight dispatches confirmation and spend notifications to the clients
// who registered for a notification which has been fulfilled at the passed
// height.
func (n *TxNotifier) NotifyHeight(height uint32) error {
n.Lock()
defer n.Unlock()
// First, we'll dispatch an update to all of the notification clients
// for our watched transactions with the number of confirmations left at
// this new height.
for _, txHashes := range n.txsByInitialHeight {
for txHash := range txHashes {
@ -1032,7 +1046,7 @@ func (n *TxNotifier) ConnectTip(blockHash *chainhash.Hash, blockHeight uint32,
for _, ntfn := range confSet.ntfns {
txConfHeight := confSet.details.BlockHeight +
ntfn.NumConfirmations - 1
numConfsLeft := txConfHeight - blockHeight
numConfsLeft := txConfHeight - height
// Since we don't clear notifications until
// transactions are no longer under the risk of
@ -1054,7 +1068,7 @@ func (n *TxNotifier) ConnectTip(blockHash *chainhash.Hash, blockHeight uint32,
// Then, we'll dispatch notifications for all the transactions that have
// become confirmed at this new block height.
for ntfn := range n.ntfnsByConfirmHeight[blockHeight] {
for ntfn := range n.ntfnsByConfirmHeight[height] {
confSet := n.confNotifications[*ntfn.TxID]
Log.Infof("Dispatching %v conf notification for %v",
@ -1067,11 +1081,11 @@ func (n *TxNotifier) ConnectTip(blockHash *chainhash.Hash, blockHeight uint32,
return ErrTxNotifierExiting
}
}
delete(n.ntfnsByConfirmHeight, blockHeight)
delete(n.ntfnsByConfirmHeight, height)
// We'll also dispatch spend notifications for all the outpoints that
// were spent at this new block height.
for op := range n.opsBySpendHeight[blockHeight] {
for op := range n.opsBySpendHeight[height] {
spendSet := n.spendNotifications[op]
for _, ntfn := range spendSet.ntfns {
err := n.dispatchSpendDetails(ntfn, spendSet.details)
@ -1084,8 +1098,8 @@ func (n *TxNotifier) ConnectTip(blockHash *chainhash.Hash, blockHeight uint32,
// Finally, we'll clear the entries from our set of notifications for
// transactions and outpoints that are no longer under the risk of being
// reorged out of the chain.
if blockHeight >= n.reorgSafetyLimit {
matureBlockHeight := blockHeight - n.reorgSafetyLimit
if height >= n.reorgSafetyLimit {
matureBlockHeight := height - n.reorgSafetyLimit
for tx := range n.txsByInitialHeight[matureBlockHeight] {
delete(n.confNotifications, tx)
}

116
chainntnfs/txnotifier_test.go

@ -165,12 +165,13 @@ func TestTxNotifierFutureConfDispatch(t *testing.T) {
Transactions: []*wire.MsgTx{&tx1, &tx2, &tx3},
})
err := n.ConnectTip(
block1.Hash(), 11, block1.Transactions(),
)
err := n.ConnectTip(block1.Hash(), 11, block1.Transactions())
if err != nil {
t.Fatalf("Failed to connect block: %v", err)
}
if err := n.NotifyHeight(11); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
// We should only receive one update for tx1 since it only requires
// one confirmation and it already met it.
@ -232,6 +233,9 @@ func TestTxNotifierFutureConfDispatch(t *testing.T) {
if err != nil {
t.Fatalf("Failed to connect block: %v", err)
}
if err := n.NotifyHeight(12); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
// We should not receive any event notifications for tx1 since it has
// already been confirmed.
@ -388,6 +392,9 @@ func TestTxNotifierHistoricalConfDispatch(t *testing.T) {
if err != nil {
t.Fatalf("Failed to connect block: %v", err)
}
if err := n.NotifyHeight(11); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
// We should not receive any event notifications for tx1 since it has
// already been confirmed.
@ -462,6 +469,9 @@ func TestTxNotifierFutureSpendDispatch(t *testing.T) {
if err != nil {
t.Fatalf("unable to connect block: %v", err)
}
if err := n.NotifyHeight(11); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
expectedSpendDetails := &chainntnfs.SpendDetail{
SpentOutPoint: &ntfn.OutPoint,
@ -491,6 +501,9 @@ func TestTxNotifierFutureSpendDispatch(t *testing.T) {
if err != nil {
t.Fatalf("unable to connect block: %v", err)
}
if err := n.NotifyHeight(12); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
select {
case <-ntfn.Event.Spend:
@ -570,6 +583,9 @@ func TestTxNotifierHistoricalSpendDispatch(t *testing.T) {
if err != nil {
t.Fatalf("unable to connect block: %v", err)
}
if err := n.NotifyHeight(startingHeight + 1); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
select {
case <-ntfn.Event.Spend:
@ -931,6 +947,9 @@ func TestTxNotifierCancelSpend(t *testing.T) {
if err != nil {
t.Fatalf("unable to connect block: %v", err)
}
if err := n.NotifyHeight(startingHeight + 1); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
// The first request should still be active, so we should receive a
// spend notification with the correct spending details.
@ -1024,22 +1043,28 @@ func TestTxNotifierConfReorg(t *testing.T) {
block1 := btcutil.NewBlock(&wire.MsgBlock{
Transactions: []*wire.MsgTx{&tx1},
})
err := n.ConnectTip(nil, 8, block1.Transactions())
if err != nil {
if err := n.ConnectTip(nil, 8, block1.Transactions()); err != nil {
t.Fatalf("Failed to connect block: %v", err)
}
err = n.ConnectTip(nil, 9, nil)
if err != nil {
if err := n.NotifyHeight(8); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
if err := n.ConnectTip(nil, 9, nil); err != nil {
t.Fatalf("Failed to connect block: %v", err)
}
if err := n.NotifyHeight(9); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
block2 := btcutil.NewBlock(&wire.MsgBlock{
Transactions: []*wire.MsgTx{&tx2, &tx3},
})
err = n.ConnectTip(nil, 10, block2.Transactions())
if err != nil {
if err := n.ConnectTip(nil, 10, block2.Transactions()); err != nil {
t.Fatalf("Failed to connect block: %v", err)
}
if err := n.NotifyHeight(10); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
// We should receive two updates for tx1 since it requires two
// confirmations and it has already met them.
@ -1093,20 +1118,23 @@ func TestTxNotifierConfReorg(t *testing.T) {
// The block that included tx2 and tx3 is disconnected and two next
// blocks without them are connected.
err = n.DisconnectTip(10)
if err != nil {
if err := n.DisconnectTip(10); err != nil {
t.Fatalf("Failed to connect block: %v", err)
}
err = n.ConnectTip(nil, 10, nil)
if err != nil {
if err := n.ConnectTip(nil, 10, nil); err != nil {
t.Fatalf("Failed to connect block: %v", err)
}
if err := n.NotifyHeight(10); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
err = n.ConnectTip(nil, 11, nil)
if err != nil {
if err := n.ConnectTip(nil, 11, nil); err != nil {
t.Fatalf("Failed to connect block: %v", err)
}
if err := n.NotifyHeight(11); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
select {
case reorgDepth := <-ntfn2.Event.NegativeConf:
@ -1151,15 +1179,21 @@ func TestTxNotifierConfReorg(t *testing.T) {
})
block4 := btcutil.NewBlock(&wire.MsgBlock{})
err = n.ConnectTip(block3.Hash(), 12, block3.Transactions())
err := n.ConnectTip(block3.Hash(), 12, block3.Transactions())
if err != nil {
t.Fatalf("Failed to connect block: %v", err)
}
if err := n.NotifyHeight(12); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
err = n.ConnectTip(block4.Hash(), 13, block4.Transactions())
if err != nil {
t.Fatalf("Failed to connect block: %v", err)
}
if err := n.NotifyHeight(13); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
// We should only receive one update for tx2 since it only requires
// one confirmation and it already met it.
@ -1293,12 +1327,13 @@ func TestTxNotifierSpendReorg(t *testing.T) {
block1 := btcutil.NewBlock(&wire.MsgBlock{
Transactions: []*wire.MsgTx{spendTx1},
})
err := n.ConnectTip(
block1.Hash(), startingHeight+1, block1.Transactions(),
)
err := n.ConnectTip(block1.Hash(), startingHeight+1, block1.Transactions())
if err != nil {
t.Fatalf("unable to connect block: %v", err)
}
if err := n.NotifyHeight(startingHeight + 1); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
// We should receive a spend notification for the first outpoint with
// its correct spending details.
@ -1322,12 +1357,13 @@ func TestTxNotifierSpendReorg(t *testing.T) {
block2 := btcutil.NewBlock(&wire.MsgBlock{
Transactions: []*wire.MsgTx{spendTx2},
})
err = n.ConnectTip(
block2.Hash(), startingHeight+2, block2.Transactions(),
)
err = n.ConnectTip(block2.Hash(), startingHeight+2, block2.Transactions())
if err != nil {
t.Fatalf("unable to connect block: %v", err)
}
if err := n.NotifyHeight(startingHeight + 2); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
// We should not receive another spend notification for the first
// outpoint.
@ -1381,6 +1417,9 @@ func TestTxNotifierSpendReorg(t *testing.T) {
if err != nil {
t.Fatalf("unable to disconnect block: %v", err)
}
if err := n.NotifyHeight(startingHeight + 2); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
// We shouldn't receive notifications for either of the outpoints.
select {
@ -1403,6 +1442,9 @@ func TestTxNotifierSpendReorg(t *testing.T) {
if err != nil {
t.Fatalf("unable to connect block: %v", err)
}
if err := n.NotifyHeight(startingHeight + 3); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
// We should now receive a spend notification once again for the second
// outpoint containing the new spend details.
@ -1489,12 +1531,13 @@ func TestTxNotifierConfirmHintCache(t *testing.T) {
Transactions: []*wire.MsgTx{&txDummy},
})
err = n.ConnectTip(
block1.Hash(), txDummyHeight, block1.Transactions(),
)
err = n.ConnectTip(block1.Hash(), txDummyHeight, block1.Transactions())
if err != nil {
t.Fatalf("Failed to connect block: %v", err)
}
if err := n.NotifyHeight(txDummyHeight); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
// Since UpdateConfDetails has not been called for either transaction,
// the height hints should remain unchanged. This simulates blocks
@ -1529,12 +1572,13 @@ func TestTxNotifierConfirmHintCache(t *testing.T) {
Transactions: []*wire.MsgTx{&tx1},
})
err = n.ConnectTip(
block2.Hash(), tx1Height, block2.Transactions(),
)
err = n.ConnectTip(block2.Hash(), tx1Height, block2.Transactions())
if err != nil {
t.Fatalf("Failed to connect block: %v", err)
}
if err := n.NotifyHeight(tx1Height); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
// Now that both notifications are waiting at tip for confirmations,
// they should have their height hints updated to the latest block
@ -1563,12 +1607,13 @@ func TestTxNotifierConfirmHintCache(t *testing.T) {
Transactions: []*wire.MsgTx{&tx2},
})
err = n.ConnectTip(
block3.Hash(), tx2Height, block3.Transactions(),
)
err = n.ConnectTip(block3.Hash(), tx2Height, block3.Transactions())
if err != nil {
t.Fatalf("Failed to connect block: %v", err)
}
if err := n.NotifyHeight(tx2Height); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
// The height hint for the first transaction should remain the same.
hint, err = hintCache.QueryConfirmHint(tx1Hash)
@ -1682,6 +1727,9 @@ func TestTxNotifierSpendHintCache(t *testing.T) {
if err != nil {
t.Fatalf("unable to connect block: %v", err)
}
if err := n.NotifyHeight(dummyHeight); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
// Since we haven't called UpdateSpendDetails on any of the test
// outpoints, this implies that there is a still a pending historical
@ -1720,6 +1768,9 @@ func TestTxNotifierSpendHintCache(t *testing.T) {
if err != nil {
t.Fatalf("unable to connect block: %v", err)
}
if err := n.NotifyHeight(op1Height); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
// Both outpoints should have their spend hints reflect the height of
// the new block being connected due to the first outpoint being spent
@ -1749,6 +1800,9 @@ func TestTxNotifierSpendHintCache(t *testing.T) {
if err != nil {
t.Fatalf("unable to connect block: %v", err)
}
if err := n.NotifyHeight(op2Height); err != nil {
t.Fatalf("unable to dispatch notifications: %v", err)
}
// Only the second outpoint should have its spend hint updated due to
// being spent within the new block. The first outpoint's spend hint

4
chainregistry.go

@ -181,8 +181,8 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
cleanUp func()
)
// Initialize disabled height hint cache within the chain directory.
hintCache, err := chainntnfs.NewHeightHintCache(chanDB, true)
// Initialize the height hint cache within the chain directory.
hintCache, err := chainntnfs.NewHeightHintCache(chanDB)
if err != nil {
return nil, nil, fmt.Errorf("unable to initialize height hint "+
"cache: %v", err)

2
lnwallet/interface_test.go

@ -2153,7 +2153,7 @@ func TestLightningWallet(t *testing.T) {
if err != nil {
t.Fatalf("unable to create db: %v", err)
}
hintCache, err := chainntnfs.NewHeightHintCache(db, true)
hintCache, err := chainntnfs.NewHeightHintCache(db)
if err != nil {
t.Fatalf("unable to create height hint cache: %v", err)
}

Loading…
Cancel
Save