From 48c9d284c17d444b2b13aae857883ed58d22eb3e Mon Sep 17 00:00:00 2001 From: Zsolt Felfoldi Date: Thu, 20 Jun 2019 23:33:42 +0200 Subject: [PATCH 1/2] core: fix chain indexer reorg bug --- core/chain_indexer.go | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/core/chain_indexer.go b/core/chain_indexer.go index 26538260cce6..f91e3fd9093d 100644 --- a/core/chain_indexer.go +++ b/core/chain_indexer.go @@ -323,6 +323,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 { @@ -342,8 +343,8 @@ 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 processing succeeded and no reorgs occurred, mark the section completed + if err == nil && (section == 0 || oldHead == c.SectionHead(section-1)) { c.setSectionHead(section, newHead) c.setValidSections(section + 1) if c.storedSections == c.knownSections && updating { @@ -358,6 +359,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 } } @@ -411,6 +413,18 @@ 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) == rawdb.ReadCanonicalHash(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. @@ -418,6 +432,7 @@ 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) } From 7f782b136ee470f0e14ba67f5f0c7ed6aec3b9a7 Mon Sep 17 00:00:00 2001 From: rjl493456442 Date: Thu, 27 Jun 2019 16:54:19 +0800 Subject: [PATCH 2/2] core: prevent reverting valid section when reorg happens --- core/chain_indexer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/chain_indexer.go b/core/chain_indexer.go index f91e3fd9093d..455f9f093a52 100644 --- a/core/chain_indexer.go +++ b/core/chain_indexer.go @@ -243,7 +243,7 @@ func (c *ChainIndexer) newHead(head uint64, reorg bool) { // If a reorg happened, invalidate all sections until that point if reorg { // Revert the known section number to the reorg point - known := head / c.sectionSize + known := (head + 1) / c.sectionSize stored := known if known < c.checkpointSections { known = 0