fix: address race condition during EuclidV2 header chain verification (#1186)

This commit is contained in:
Péter Garamvölgyi 2025-05-14 15:34:00 +02:00 committed by GitHub
parent 0b6f8f1889
commit 2500647c49
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 30 additions and 5 deletions

View file

@ -59,6 +59,31 @@ func (ue *UpgradableEngine) VerifyHeader(chain consensus.ChainHeaderReader, head
return ue.chooseEngine(header.Time).VerifyHeader(chain, header, seal) return ue.chooseEngine(header.Time).VerifyHeader(chain, header, seal)
} }
func waitForHeader(chain consensus.ChainHeaderReader, header *types.Header) {
hash, number := header.Hash(), header.Number.Uint64()
// poll every 2 seconds, should succeed after a few tries
ticker := time.NewTicker(2 * time.Second)
defer ticker.Stop()
// we give up after 2 minutes
timeout := time.After(120 * time.Second)
for {
select {
case <-ticker.C:
// try reading from chain, if the header is present then we are ready
if h := chain.GetHeader(hash, number); h != nil {
return
}
case <-timeout:
log.Warn("Unable to find last pre-EuclidV2 header in chain", "hash", hash.Hex(), "number", number)
return
}
}
}
// VerifyHeaders verifies a batch of headers concurrently. In our use-case, // VerifyHeaders verifies a batch of headers concurrently. In our use-case,
// headers can only be all system, all clique, or start with clique and then switch once to system. // headers can only be all system, all clique, or start with clique and then switch once to system.
func (ue *UpgradableEngine) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { func (ue *UpgradableEngine) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
@ -124,10 +149,10 @@ func (ue *UpgradableEngine) VerifyHeaders(chain consensus.ChainHeaderReader, hea
} }
} }
// Not sure why we need this here, but without this we get err="unknown ancestor" // `VerifyHeader` will try to call `chain.GetHeader`, which will race with `InsertHeaderChain`.
// at the 1st Euclid block. It seems that `VerifyHeaders` start processing the next // This might result in "unknown ancestor" header validation error.
// header before the previous one was written into `chain`. // This should be temporary, so we solve this by waiting here.
time.Sleep(2 * time.Second) waitForHeader(chain, cliqueHeaders[len(cliqueHeaders)-1])
// Verify system contract headers. // Verify system contract headers.
log.Info("Start EuclidV2 transition verification in SystemContract section", "startBlockNumber", systemHeaders[0].Number, "endBlockNumber", systemHeaders[len(systemHeaders)-1].Number) log.Info("Start EuclidV2 transition verification in SystemContract section", "startBlockNumber", systemHeaders[0].Number, "endBlockNumber", systemHeaders[len(systemHeaders)-1].Number)

View file

@ -24,7 +24,7 @@ import (
const ( const (
VersionMajor = 5 // Major version component of the current release VersionMajor = 5 // Major version component of the current release
VersionMinor = 8 // Minor version component of the current release VersionMinor = 8 // Minor version component of the current release
VersionPatch = 45 // Patch version component of the current release VersionPatch = 46 // Patch version component of the current release
VersionMeta = "mainnet" // Version metadata to append to the version string VersionMeta = "mainnet" // Version metadata to append to the version string
) )