diff --git a/blockchain/chain_indexer.go b/blockchain/chain_indexer.go index d908a0d5..7562f385 100644 --- a/blockchain/chain_indexer.go +++ b/blockchain/chain_indexer.go @@ -256,6 +256,7 @@ func (c *ChainIndexer) updateLoop() { updated = time.Now() } // Cache the current section count and head to allow unlocking the mutex + c.verifyLastHead() section := c.storedSections var oldHead common.Hash if section > 0 { @@ -270,7 +271,7 @@ func (c *ChainIndexer) updateLoop() { c.lock.Lock() // If processing succeeded and no reorgs occcurred, mark the section completed - if err == nil && oldHead == c.sectionHead(section-1) { + if err == nil && (section == 0||oldHead == c.sectionHead(section-1)) { c.setSectionHead(section, newHead) c.setValidSections(section + 1) if c.storedSections == c.knownSections && updating { @@ -286,6 +287,7 @@ func (c *ChainIndexer) updateLoop() { } else { // If processing failed, don't retry until further notification c.log.Debug("Chain index processing failed", "section", section, "err", err) + c.verifyLastHead() c.knownSections = c.storedSections } } @@ -334,13 +336,27 @@ func (c *ChainIndexer) processSection(section uint64, lastHead common.Hash) (com return lastHead, nil } + + +// verifyLastHead compares last stored section head with the corresponding block hash in the +// actual canonical chain and rolls back reorged sections if necessary to ensure that stored +// sections are all valid +func (c *ChainIndexer) verifyLastHead() { + for c.storedSections > 0 { + if c.sectionHead(c.storedSections-1) == GetCanonicalHash(c.chainDb, c.storedSections*c.sectionSize-1) { + return + } + c.setValidSections(c.storedSections - 1) + } +} + // Sections returns the number of processed sections maintained by the indexer // and also the information about the last header indexed for potential canonical // verifications. func (c *ChainIndexer) Sections() (uint64, uint64, common.Hash) { c.lock.Lock() defer c.lock.Unlock() - + c.verifyLastHead() return c.storedSections, c.storedSections*c.sectionSize - 1, c.sectionHead(c.storedSections - 1) }