core: fix chain indexer reorg bug (#19748)
* core: fix chain indexer reorg bug * core: prevent reverting valid section when reorg happens
This commit is contained in:
		
				
					committed by
					
						
						Péter Szilágyi
					
				
			
			
				
	
			
			
			
						parent
						
							de6facb966
						
					
				
				
					commit
					32273df0ea
				
			@@ -244,7 +244,7 @@ func (c *ChainIndexer) newHead(head uint64, reorg bool) {
 | 
				
			|||||||
	// If a reorg happened, invalidate all sections until that point
 | 
						// If a reorg happened, invalidate all sections until that point
 | 
				
			||||||
	if reorg {
 | 
						if reorg {
 | 
				
			||||||
		// Revert the known section number to the reorg point
 | 
							// Revert the known section number to the reorg point
 | 
				
			||||||
		known := head / c.sectionSize
 | 
							known := (head + 1) / c.sectionSize
 | 
				
			||||||
		stored := known
 | 
							stored := known
 | 
				
			||||||
		if known < c.checkpointSections {
 | 
							if known < c.checkpointSections {
 | 
				
			||||||
			known = 0
 | 
								known = 0
 | 
				
			||||||
@@ -324,6 +324,7 @@ func (c *ChainIndexer) updateLoop() {
 | 
				
			|||||||
					updated = time.Now()
 | 
										updated = time.Now()
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				// Cache the current section count and head to allow unlocking the mutex
 | 
									// Cache the current section count and head to allow unlocking the mutex
 | 
				
			||||||
 | 
									c.verifyLastHead()
 | 
				
			||||||
				section := c.storedSections
 | 
									section := c.storedSections
 | 
				
			||||||
				var oldHead common.Hash
 | 
									var oldHead common.Hash
 | 
				
			||||||
				if section > 0 {
 | 
									if section > 0 {
 | 
				
			||||||
@@ -343,8 +344,8 @@ func (c *ChainIndexer) updateLoop() {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				c.lock.Lock()
 | 
									c.lock.Lock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// If processing succeeded and no reorgs occcurred, mark the section completed
 | 
									// If processing succeeded and no reorgs occurred, 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.setSectionHead(section, newHead)
 | 
				
			||||||
					c.setValidSections(section + 1)
 | 
										c.setValidSections(section + 1)
 | 
				
			||||||
					if c.storedSections == c.knownSections && updating {
 | 
										if c.storedSections == c.knownSections && updating {
 | 
				
			||||||
@@ -359,6 +360,7 @@ func (c *ChainIndexer) updateLoop() {
 | 
				
			|||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					// If processing failed, don't retry until further notification
 | 
										// If processing failed, don't retry until further notification
 | 
				
			||||||
					c.log.Debug("Chain index processing failed", "section", section, "err", err)
 | 
										c.log.Debug("Chain index processing failed", "section", section, "err", err)
 | 
				
			||||||
 | 
										c.verifyLastHead()
 | 
				
			||||||
					c.knownSections = c.storedSections
 | 
										c.knownSections = c.storedSections
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -412,6 +414,18 @@ func (c *ChainIndexer) processSection(section uint64, lastHead common.Hash) (com
 | 
				
			|||||||
	return lastHead, nil
 | 
						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
 | 
					// Sections returns the number of processed sections maintained by the indexer
 | 
				
			||||||
// and also the information about the last header indexed for potential canonical
 | 
					// and also the information about the last header indexed for potential canonical
 | 
				
			||||||
// verifications.
 | 
					// verifications.
 | 
				
			||||||
@@ -419,6 +433,7 @@ func (c *ChainIndexer) Sections() (uint64, uint64, common.Hash) {
 | 
				
			|||||||
	c.lock.Lock()
 | 
						c.lock.Lock()
 | 
				
			||||||
	defer c.lock.Unlock()
 | 
						defer c.lock.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c.verifyLastHead()
 | 
				
			||||||
	return c.storedSections, c.storedSections*c.sectionSize - 1, c.SectionHead(c.storedSections - 1)
 | 
						return c.storedSections, c.storedSections*c.sectionSize - 1, c.SectionHead(c.storedSections - 1)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user