From fb9f19334935fde694ed567c30af4baa2aa0786b Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Mon, 18 Jul 2022 03:04:02 +0200 Subject: [PATCH] fixed Two Block PoW Re-org to Higher-Height Chain (#4730) Co-authored-by: giuliorebuffo --- eth/stagedsync/stage_headers.go | 11 ++++++++++ turbo/engineapi/fork_validator.go | 7 +++++++ turbo/stages/stageloop.go | 35 ++++++++++++++++--------------- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/eth/stagedsync/stage_headers.go b/eth/stagedsync/stage_headers.go index bf6ad576a4c..3f2996bf937 100644 --- a/eth/stagedsync/stage_headers.go +++ b/eth/stagedsync/stage_headers.go @@ -667,6 +667,8 @@ func schedulePoSDownload( func verifyAndSaveDownloadedPoSHeaders(tx kv.RwTx, cfg HeadersCfg, headerInserter *headerdownload.HeaderInserter) { var lastValidHash common.Hash var badChainError error + var foundPow bool + headerLoadFunc := func(key, value []byte, _ etl.CurrentTableReader, _ etl.LoadNextFunc) error { var h types.Header if err := rlp.DecodeBytes(value, &h); err != nil { @@ -683,6 +685,15 @@ func verifyAndSaveDownloadedPoSHeaders(tx kv.RwTx, cfg HeadersCfg, headerInserte cfg.hd.ReportBadHeaderPoS(h.Hash(), lastValidHash) return nil } + // If we are in PoW range then block validation is not required anymore. + if foundPow { + return headerInserter.FeedHeaderPoS(tx, &h, h.Hash()) + } + + foundPow = h.Difficulty.Cmp(common.Big0) != 0 + if foundPow { + return headerInserter.FeedHeaderPoS(tx, &h, h.Hash()) + } // Validate state if possible (bodies will be retrieved through body download) _, _, validationError, criticalError := cfg.forkValidator.ValidatePayload(tx, &h, nil, false) if criticalError != nil { diff --git a/turbo/engineapi/fork_validator.go b/turbo/engineapi/fork_validator.go index 91b87b31087..ae83190cd4b 100644 --- a/turbo/engineapi/fork_validator.go +++ b/turbo/engineapi/fork_validator.go @@ -15,6 +15,7 @@ package engineapi import ( "bytes" + "fmt" "github.com/ledgerwatch/erigon-lib/gointerfaces/remote" "github.com/ledgerwatch/erigon-lib/kv" @@ -130,6 +131,7 @@ func (fv *ForkValidator) ValidatePayload(tx kv.RwTx, header *types.Header, body // if the block is not in range of maxForkDepth from head then we do not validate it. if abs64(int64(fv.currentHeight)-header.Number.Int64()) > maxForkDepth { status = remote.EngineStatus_ACCEPTED + fmt.Println("not in range") return } // Let's assemble the side fork backwards @@ -137,6 +139,7 @@ func (fv *ForkValidator) ValidatePayload(tx kv.RwTx, header *types.Header, body currentHash := header.ParentHash foundCanonical, criticalError = rawdb.IsCanonicalHash(tx, currentHash) if criticalError != nil { + fmt.Println("critical") return } @@ -160,6 +163,10 @@ func (fv *ForkValidator) ValidatePayload(tx kv.RwTx, header *types.Header, body } unwindPoint = sb.header.Number.Uint64() - 1 } + // Do not set an unwind point if we are already there. + if unwindPoint == fv.currentHeight { + unwindPoint = 0 + } // if it is not canonical we validate it in memory and discard it aferwards. batch := memdb.NewMemoryBatch(tx) defer batch.Close() diff --git a/turbo/stages/stageloop.go b/turbo/stages/stageloop.go index 8a0caa5451f..5280dc8b7e3 100644 --- a/turbo/stages/stageloop.go +++ b/turbo/stages/stageloop.go @@ -262,25 +262,26 @@ func StateStep(ctx context.Context, batch kv.RwTx, stateSync *stagedsync.Sync, h if err = stateSync.RunUnwind(nil, batch); err != nil { return err } - // Once we unwond we can start constructing the chain (assumption: len(headersChain) == len(bodiesChain)) - for i := range headersChain { - currentHeader := headersChain[i] - currentBody := bodiesChain[i] - currentHeight := headersChain[i].Number.Uint64() - currentHash := headersChain[i].Hash() - // Prepare memory state for block execution - if err = rawdb.WriteRawBodyIfNotExists(batch, currentHash, currentHeight, currentBody); err != nil { - return err - } - rawdb.WriteHeader(batch, currentHeader) - if err = rawdb.WriteHeaderNumber(batch, currentHash, currentHeight); err != nil { - return err - } - if err = rawdb.WriteCanonicalHash(batch, currentHash, currentHeight); err != nil { - return err - } + } + // Once we unwond we can start constructing the chain (assumption: len(headersChain) == len(bodiesChain)) + for i := range headersChain { + currentHeader := headersChain[i] + currentBody := bodiesChain[i] + currentHeight := headersChain[i].Number.Uint64() + currentHash := headersChain[i].Hash() + // Prepare memory state for block execution + if err = rawdb.WriteRawBodyIfNotExists(batch, currentHash, currentHeight, currentBody); err != nil { + return err + } + rawdb.WriteHeader(batch, currentHeader) + if err = rawdb.WriteHeaderNumber(batch, currentHash, currentHeight); err != nil { + return err + } + if err = rawdb.WriteCanonicalHash(batch, currentHash, currentHeight); err != nil { + return err } } + // If we did not specify header or body we stop here if header == nil { return nil