Update for recent btcchain ProcessBlock API change.

Now that the ProcessBlock function returns whether or not the block was an
orphan, the code which requests the parent blocks from the peer that sent
them has been moved to directly after the call to it.

This makes the handling more obvious and has allowed removal of the
blockPeer map which was kept so the notification handler could identify
which peer to request the blocks from.

ok @jrick
This commit is contained in:
Dave Collins 2014-06-25 15:54:19 -05:00
parent 35d555d541
commit 21872ecdaa
2 changed files with 25 additions and 39 deletions

View file

@ -162,7 +162,6 @@ type blockManager struct {
started int32 started int32
shutdown int32 shutdown int32
blockChain *btcchain.BlockChain blockChain *btcchain.BlockChain
blockPeer map[btcwire.ShaHash]*peer
requestedTxns map[btcwire.ShaHash]bool requestedTxns map[btcwire.ShaHash]bool
requestedBlocks map[btcwire.ShaHash]bool requestedBlocks map[btcwire.ShaHash]bool
receivedLogBlocks int64 receivedLogBlocks int64
@ -552,10 +551,6 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) {
} }
} }
// Keep track of which peer the block was sent from so the notification
// handler can request the parent blocks from the appropriate peer.
b.blockPeer[*blockSha] = bmsg.peer
// When in headers-first mode, if the block matches the hash of the // When in headers-first mode, if the block matches the hash of the
// first header in the list of headers that are being fetched, it's // first header in the list of headers that are being fetched, it's
// eligible for less validation since the headers have already been // eligible for less validation since the headers have already been
@ -588,10 +583,8 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) {
// Process the block to include validation, best chain selection, orphan // Process the block to include validation, best chain selection, orphan
// handling, etc. // handling, etc.
err := b.blockChain.ProcessBlock(bmsg.block, fastAdd) isOrphan, err := b.blockChain.ProcessBlock(bmsg.block, fastAdd)
if err != nil { if err != nil {
delete(b.blockPeer, *blockSha)
// When the error is a rule error, it means the block was simply // When the error is a rule error, it means the block was simply
// rejected as opposed to something actually going wrong, so log // rejected as opposed to something actually going wrong, so log
// it as such. Otherwise, something really did go wrong, so log // it as such. Otherwise, something really did go wrong, so log
@ -605,11 +598,20 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) {
return return
} }
// When the block is not an orphan, don't keep track of the peer that // Request the parents for the orphan block from the peer that sent it.
// sent it any longer, log information about it, and update the chain if isOrphan {
// state. orphanRoot := b.blockChain.GetOrphanRoot(blockSha)
if !b.blockChain.IsKnownOrphan(blockSha) { locator, err := b.blockChain.LatestBlockLocator()
delete(b.blockPeer, *blockSha) if err != nil {
bmgrLog.Warnf("Failed to get block locator for the "+
"latest block: %v", err)
} else {
bmsg.peer.PushGetBlocksMsg(locator, orphanRoot)
}
} else {
// When the block is not an orphan, log information about it and
// update the chain state.
b.logBlockHeight(bmsg.block) b.logBlockHeight(bmsg.block)
// Query the db for the latest best block since the block // Query the db for the latest best block since the block
@ -1026,7 +1028,8 @@ out:
} }
case processBlockMsg: case processBlockMsg:
err := b.blockChain.ProcessBlock(msg.block, false) isOrphan, err := b.blockChain.ProcessBlock(
msg.block, false)
if err != nil { if err != nil {
msg.reply <- processBlockResponse{ msg.reply <- processBlockResponse{
isOrphan: false, isOrphan: false,
@ -1040,11 +1043,9 @@ out:
newestSha, newestHeight, _ := b.server.db.NewestSha() newestSha, newestHeight, _ := b.server.db.NewestSha()
b.updateChainState(newestSha, newestHeight) b.updateChainState(newestSha, newestHeight)
blockSha, _ := msg.block.Sha()
msg.reply <- processBlockResponse{ msg.reply <- processBlockResponse{
isOrphan: b.blockChain.IsKnownOrphan( isOrphan: isOrphan,
blockSha), err: nil,
err: nil,
} }
case isCurrentMsg: case isCurrentMsg:
@ -1068,25 +1069,6 @@ out:
// as request orphan block parents and relay accepted blocks to connected peers. // as request orphan block parents and relay accepted blocks to connected peers.
func (b *blockManager) handleNotifyMsg(notification *btcchain.Notification) { func (b *blockManager) handleNotifyMsg(notification *btcchain.Notification) {
switch notification.Type { switch notification.Type {
// An orphan block has been accepted by the block chain. Request
// its parents from the peer that sent it.
case btcchain.NTOrphanBlock:
orphanHash := notification.Data.(*btcwire.ShaHash)
if peer, exists := b.blockPeer[*orphanHash]; exists {
orphanRoot := b.blockChain.GetOrphanRoot(orphanHash)
locator, err := b.blockChain.LatestBlockLocator()
if err != nil {
bmgrLog.Errorf("Failed to get block locator "+
"for the latest block: %v", err)
break
}
peer.PushGetBlocksMsg(locator, orphanRoot)
delete(b.blockPeer, *orphanRoot)
} else {
bmgrLog.Warnf("Notification for orphan %v with no peer",
orphanHash)
}
// A block has been accepted into the block chain. Relay it to other // A block has been accepted into the block chain. Relay it to other
// peers. // peers.
case btcchain.NTBlockAccepted: case btcchain.NTBlockAccepted:
@ -1320,7 +1302,6 @@ func newBlockManager(s *server) (*blockManager, error) {
bm := blockManager{ bm := blockManager{
server: s, server: s,
blockPeer: make(map[btcwire.ShaHash]*peer),
requestedTxns: make(map[btcwire.ShaHash]bool), requestedTxns: make(map[btcwire.ShaHash]bool),
requestedBlocks: make(map[btcwire.ShaHash]bool), requestedBlocks: make(map[btcwire.ShaHash]bool),
lastBlockLogTime: time.Now(), lastBlockLogTime: time.Now(),

View file

@ -120,9 +120,14 @@ func (bi *blockImporter) processBlock(serializedBlock []byte) (bool, error) {
// Ensure the blocks follows all of the chain rules and match up to the // Ensure the blocks follows all of the chain rules and match up to the
// known checkpoints. // known checkpoints.
if err := bi.chain.ProcessBlock(block, true); err != nil { isOrphan, err := bi.chain.ProcessBlock(block, true)
if err != nil {
return false, err return false, err
} }
if isOrphan {
return false, fmt.Errorf("import file contains an orphan "+
"block: %v", blockSha)
}
return true, nil return true, nil
} }