From d4cf271526e8f09428d314b00b5c16467382c957 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Thu, 9 Aug 2018 00:05:28 -0700 Subject: [PATCH] chainntnfs: track best block in btcd and bitcoind --- chainntnfs/bitcoindnotify/bitcoind.go | 25 +++++++++++++++---------- chainntnfs/btcdnotify/btcd.go | 23 +++++++++++++---------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/chainntnfs/bitcoindnotify/bitcoind.go b/chainntnfs/bitcoindnotify/bitcoind.go index cf367217..4ebd4650 100644 --- a/chainntnfs/bitcoindnotify/bitcoind.go +++ b/chainntnfs/bitcoindnotify/bitcoind.go @@ -74,6 +74,8 @@ type BitcoindNotifier struct { blockEpochClients map[uint64]*blockEpochRegistration + bestBlock chainntnfs.BlockEpoch + wg sync.WaitGroup quit chan struct{} } @@ -119,7 +121,7 @@ func (b *BitcoindNotifier) Start() error { return err } - _, currentHeight, err := b.chainConn.GetBestBlock() + currentHash, currentHeight, err := b.chainConn.GetBestBlock() if err != nil { return err } @@ -127,8 +129,13 @@ func (b *BitcoindNotifier) Start() error { b.txConfNotifier = chainntnfs.NewTxConfNotifier( uint32(currentHeight), reorgSafetyLimit) + b.bestBlock = chainntnfs.BlockEpoch{ + Height: currentHeight, + Hash: currentHash, + } + b.wg.Add(1) - go b.notificationDispatcher(currentHeight) + go b.notificationDispatcher() return nil } @@ -174,7 +181,7 @@ type blockNtfn struct { // notificationDispatcher is the primary goroutine which handles client // notification registrations, as well as notification dispatches. -func (b *BitcoindNotifier) notificationDispatcher(bestHeight int32) { +func (b *BitcoindNotifier) notificationDispatcher() { out: for { select { @@ -235,7 +242,7 @@ out: "subscription: txid=%v, numconfs=%v", msg.TxID, msg.NumConfirmations) - currentHeight := uint32(bestHeight) + currentHeight := uint32(b.bestBlock.Height) // Look up whether the transaction is already // included in the active chain. We'll do this @@ -270,19 +277,18 @@ out: b.blockEpochClients[msg.epochID] = msg case chain.RelevantTx: - b.handleRelevantTx(msg, bestHeight) + b.handleRelevantTx(msg, b.bestBlock.Height) } case ntfn := <-b.chainConn.Notifications(): switch item := ntfn.(type) { case chain.BlockConnected: - if item.Height != bestHeight+1 { + if item.Height != b.bestBlock.Height+1 { chainntnfs.Log.Warnf("Received blocks out of order: "+ "current height=%d, new height=%d", bestHeight, item.Height) continue } - bestHeight = item.Height rawBlock, err := b.chainConn.GetBlock(&item.Hash) if err != nil { @@ -304,14 +310,13 @@ out: continue case chain.BlockDisconnected: - if item.Height != bestHeight { + if item.Height != b.bestBlock.Height { chainntnfs.Log.Warnf("Received blocks "+ "out of order: current height="+ "%d, disconnected height=%d", bestHeight, item.Height) continue } - bestHeight = item.Height - 1 chainntnfs.Log.Infof("Block disconnected from "+ "main chain: height=%v, sha=%v", @@ -324,7 +329,7 @@ out: } case chain.RelevantTx: - b.handleRelevantTx(item, bestHeight) + b.handleRelevantTx(item, b.bestBlock.Height) } case <-b.quit: diff --git a/chainntnfs/btcdnotify/btcd.go b/chainntnfs/btcdnotify/btcd.go index 5f45cf0f..85155e61 100644 --- a/chainntnfs/btcdnotify/btcd.go +++ b/chainntnfs/btcdnotify/btcd.go @@ -78,6 +78,8 @@ type BtcdNotifier struct { blockEpochClients map[uint64]*blockEpochRegistration + bestBlock chainntnfs.BlockEpoch + chainUpdates *chainntnfs.ConcurrentQueue txUpdates *chainntnfs.ConcurrentQueue @@ -142,7 +144,7 @@ func (b *BtcdNotifier) Start() error { return err } - _, currentHeight, err := b.chainConn.GetBestBlock() + currentHash, currentHeight, err := b.chainConn.GetBestBlock() if err != nil { return err } @@ -150,11 +152,16 @@ func (b *BtcdNotifier) Start() error { b.txConfNotifier = chainntnfs.NewTxConfNotifier( uint32(currentHeight), reorgSafetyLimit) + b.bestBlock = chainntnfs.BlockEpoch{ + Height: currentHeight, + Hash: currentHash, + } + b.chainUpdates.Start() b.txUpdates.Start() b.wg.Add(1) - go b.notificationDispatcher(currentHeight) + go b.notificationDispatcher() return nil } @@ -244,7 +251,7 @@ func (b *BtcdNotifier) onRedeemingTx(tx *btcutil.Tx, details *btcjson.BlockDetai // notificationDispatcher is the primary goroutine which handles client // notification registrations, as well as notification dispatches. -func (b *BtcdNotifier) notificationDispatcher(currentHeight int32) { +func (b *BtcdNotifier) notificationDispatcher() { out: for { select { @@ -304,7 +311,7 @@ out: "subscription: txid=%v, numconfs=%v", msg.TxID, msg.NumConfirmations) - bestHeight := uint32(currentHeight) + bestHeight := uint32(b.bestBlock.Height) // Look up whether the transaction is already // included in the active chain. We'll do this @@ -342,15 +349,13 @@ out: case item := <-b.chainUpdates.ChanOut(): update := item.(*chainUpdate) if update.connect { - if update.blockHeight != currentHeight+1 { + if update.blockHeight != b.bestBlock.Height+1 { chainntnfs.Log.Warnf("Received blocks out of order: "+ "current height=%d, new height=%d", currentHeight, update.blockHeight) continue } - currentHeight = update.blockHeight - rawBlock, err := b.chainConn.GetBlock(update.blockHash) if err != nil { chainntnfs.Log.Errorf("Unable to get block: %v", err) @@ -374,15 +379,13 @@ out: continue } - if update.blockHeight != currentHeight { + if update.blockHeight != b.bestBlock.Height { chainntnfs.Log.Warnf("Received blocks out of order: "+ "current height=%d, disconnected height=%d", currentHeight, update.blockHeight) continue } - currentHeight = update.blockHeight - 1 - chainntnfs.Log.Infof("Block disconnected from main chain: "+ "height=%v, sha=%v", update.blockHeight, update.blockHash)