Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 31 additions & 12 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,23 @@ func (bc *BlockChain) loadLastState() error {
return bc.Reset()
}
// Make sure the entire head block is available
currentBlock := bc.GetBlockByHash(head)
currentHeader := bc.GetHeaderByHash(head)
if currentHeader == nil {
// Corrupt or empty database, init from scratch
log.Warn("Head header missing, resetting chain", "hash", head)
return bc.Reset()
}

var currentBlock *types.Block
if cmp := currentHeader.Number.Cmp(new(big.Int)); cmp == 1 {
// Make sure the entire head block is available.
currentBlock = bc.GetBlockByHash(head)
} else if cmp == 0 {
// On a pruned node the block body might not be available. But a pruned
// block should never be the head block. The only exception is when, as
// a last resort, chain is reset to genesis.
currentBlock = bc.genesisBlock
}
if currentBlock == nil {
// Corrupt or empty database, init from scratch
log.Warn("Head block missing, resetting chain", "hash", head)
Expand All @@ -497,7 +513,6 @@ func (bc *BlockChain) loadLastState() error {
headBlockGauge.Update(int64(currentBlock.NumberU64()))

// Restore the last known head header
currentHeader := currentBlock.Header()
if head := rawdb.ReadHeadHeaderHash(bc.db); head != (common.Hash{}) {
if header := bc.GetHeaderByHash(head); header != nil {
currentHeader = header
Expand Down Expand Up @@ -609,11 +624,13 @@ func (bc *BlockChain) SetHead(head uint64) error {
}
// Send chain head event to update the transaction pool
if block := bc.CurrentBlock(); block == nil {
// This should never happen. In practice, previously currentBlock
// contained the entire block whereas now only a "marker", so there
// is an ever so slight chance for a race we should handle.
log.Error("Current block not found in database", "block", block.Number(), "hash", block.Hash())
return fmt.Errorf("current block missing: #%d [%x..]", block.Number(), block.Hash().Bytes()[:4])
if block.Number().Uint64() > 0 {
// This should never happen. In practice, previously currentBlock
// contained the entire block whereas now only a "marker", so there
// is an ever so slight chance for a race we should handle.
log.Error("Current block not found in database", "block", block.Number(), "hash", block.Hash())
return fmt.Errorf("current block missing: #%d [%x..]", block.Number(), block.Hash().Bytes()[:4])
}
} else {
bc.chainHeadFeed.Send(ChainHeadEvent{Header: block.Header()})
}
Expand All @@ -630,11 +647,13 @@ func (bc *BlockChain) SetHeadWithTimestamp(timestamp uint64) error {
}
// Send chain head event to update the transaction pool
if block := bc.CurrentBlock(); block == nil {
// This should never happen. In practice, previously currentBlock
// contained the entire block whereas now only a "marker", so there
// is an ever so slight chance for a race we should handle.
log.Error("Current block not found in database", "block", block.Number(), "hash", block.Hash())
return fmt.Errorf("current block missing: #%d [%x..]", block.Number(), block.Hash().Bytes()[:4])
if block.Number().Uint64() > 0 {
// This should never happen. In practice, previously currentBlock
// contained the entire block whereas now only a "marker", so there
// is an ever so slight chance for a race we should handle.
log.Error("Current block not found in database", "block", block.Number(), "hash", block.Hash())
return fmt.Errorf("current block missing: #%d [%x..]", block.Number(), block.Hash().Bytes()[:4])
}
} else {
bc.chainHeadFeed.Send(ChainHeadEvent{Header: block.Header()})
}
Expand Down
19 changes: 16 additions & 3 deletions core/txindexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,16 +196,29 @@ func (indexer *txIndexer) repair(head uint64) {
}
}

// resolveHead resolves the block number of the current chain head.
func (indexer *txIndexer) resolveHead() uint64 {
headBlockHash := rawdb.ReadHeadBlockHash(indexer.db)
if headBlockHash == (common.Hash{}) {
return 0
}
headBlockNumber := rawdb.ReadHeaderNumber(indexer.db, headBlockHash)
if headBlockNumber == nil {
return 0
}
return *headBlockNumber
}

// loop is the scheduler of the indexer, assigning indexing/unindexing tasks depending
// on the received chain event.
func (indexer *txIndexer) loop(chain *BlockChain) {
defer close(indexer.closed)

// Listening to chain events and manipulate the transaction indexes.
var (
stop chan struct{} // Non-nil if background routine is active
done chan struct{} // Non-nil if background routine is active
head = rawdb.ReadHeadBlock(indexer.db).NumberU64() // The latest announced chain head
stop chan struct{} // Non-nil if background routine is active
done chan struct{} // Non-nil if background routine is active
head = indexer.resolveHead() // The latest announced chain head

headCh = make(chan ChainHeadEvent)
sub = chain.SubscribeChainHeadEvent(headCh)
Expand Down