forked from cerc-io/plugeth
eth/downloader: prevent pivot moves after state commit (#28126)
This commit is contained in:
parent
48fdb79de5
commit
4fa3db49a1
@ -1606,17 +1606,30 @@ func (d *Downloader) processSnapSyncContent() error {
|
|||||||
|
|
||||||
// To cater for moving pivot points, track the pivot block and subsequently
|
// To cater for moving pivot points, track the pivot block and subsequently
|
||||||
// accumulated download results separately.
|
// accumulated download results separately.
|
||||||
|
//
|
||||||
|
// These will be nil up to the point where we reach the pivot, and will only
|
||||||
|
// be set temporarily if the synced blocks are piling up, but the pivot is
|
||||||
|
// still busy downloading. In that case, we need to occasionally check for
|
||||||
|
// pivot moves, so need to unblock the loop. These fields will accumulate
|
||||||
|
// the results in the meantime.
|
||||||
|
//
|
||||||
|
// Note, there's no issue with memory piling up since after 64 blocks the
|
||||||
|
// pivot will forcefully move so these accumulators will be dropped.
|
||||||
var (
|
var (
|
||||||
oldPivot *fetchResult // Locked in pivot block, might change eventually
|
oldPivot *fetchResult // Locked in pivot block, might change eventually
|
||||||
oldTail []*fetchResult // Downloaded content after the pivot
|
oldTail []*fetchResult // Downloaded content after the pivot
|
||||||
)
|
)
|
||||||
for {
|
for {
|
||||||
// Wait for the next batch of downloaded data to be available, and if the pivot
|
// Wait for the next batch of downloaded data to be available. If we have
|
||||||
// block became stale, move the goalpost
|
// not yet reached the pivot point, wait blockingly as there's no need to
|
||||||
results := d.queue.Results(oldPivot == nil) // Block if we're not monitoring pivot staleness
|
// spin-loop check for pivot moves. If we reached the pivot but have not
|
||||||
|
// yet processed it, check for results async, so we might notice pivot
|
||||||
|
// moves while state syncing. If the pivot was passed fully, block again
|
||||||
|
// as there's no more reason to check for pivot moves at all.
|
||||||
|
results := d.queue.Results(oldPivot == nil)
|
||||||
if len(results) == 0 {
|
if len(results) == 0 {
|
||||||
// If pivot sync is done, stop
|
// If pivot sync is done, stop
|
||||||
if oldPivot == nil {
|
if d.committed.Load() {
|
||||||
d.reportSnapSyncProgress(true)
|
d.reportSnapSyncProgress(true)
|
||||||
return sync.Cancel()
|
return sync.Cancel()
|
||||||
}
|
}
|
||||||
@ -1639,21 +1652,23 @@ func (d *Downloader) processSnapSyncContent() error {
|
|||||||
pivot := d.pivotHeader
|
pivot := d.pivotHeader
|
||||||
d.pivotLock.RUnlock()
|
d.pivotLock.RUnlock()
|
||||||
|
|
||||||
if oldPivot == nil {
|
if oldPivot == nil { // no results piling up, we can move the pivot
|
||||||
if pivot.Root != sync.root {
|
if !d.committed.Load() { // not yet passed the pivot, we can move the pivot
|
||||||
sync.Cancel()
|
if pivot.Root != sync.root { // pivot position changed, we can move the pivot
|
||||||
sync = d.syncState(pivot.Root)
|
sync.Cancel()
|
||||||
|
sync = d.syncState(pivot.Root)
|
||||||
|
|
||||||
go closeOnErr(sync)
|
go closeOnErr(sync)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else { // results already piled up, consume before handling pivot move
|
||||||
results = append(append([]*fetchResult{oldPivot}, oldTail...), results...)
|
results = append(append([]*fetchResult{oldPivot}, oldTail...), results...)
|
||||||
}
|
}
|
||||||
// Split around the pivot block and process the two sides via snap/full sync
|
// Split around the pivot block and process the two sides via snap/full sync
|
||||||
if !d.committed.Load() {
|
if !d.committed.Load() {
|
||||||
latest := results[len(results)-1].Header
|
latest := results[len(results)-1].Header
|
||||||
// If the height is above the pivot block by 2 sets, it means the pivot
|
// If the height is above the pivot block by 2 sets, it means the pivot
|
||||||
// become stale in the network and it was garbage collected, move to a
|
// become stale in the network, and it was garbage collected, move to a
|
||||||
// new pivot.
|
// new pivot.
|
||||||
//
|
//
|
||||||
// Note, we have `reorgProtHeaderDelay` number of blocks withheld, Those
|
// Note, we have `reorgProtHeaderDelay` number of blocks withheld, Those
|
||||||
|
Loading…
Reference in New Issue
Block a user