Skip to content
This repository has been archived by the owner on Oct 18, 2023. It is now read-only.

Commit

Permalink
fixed Two Block PoW Re-org to Higher-Height Chain (ledgerwatch#4730)
Browse files Browse the repository at this point in the history
Co-authored-by: giuliorebuffo <giuliorebuffo@system76-pc.localdomain>
  • Loading branch information
Giulio2002 and giuliorebuffo committed Jul 18, 2022
1 parent 8a754cd commit fb9f193
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 17 deletions.
11 changes: 11 additions & 0 deletions eth/stagedsync/stage_headers.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
7 changes: 7 additions & 0 deletions turbo/engineapi/fork_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package engineapi

import (
"bytes"
"fmt"

"github.com/ledgerwatch/erigon-lib/gointerfaces/remote"
"github.com/ledgerwatch/erigon-lib/kv"
Expand Down Expand Up @@ -130,13 +131,15 @@ 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
var foundCanonical bool
currentHash := header.ParentHash
foundCanonical, criticalError = rawdb.IsCanonicalHash(tx, currentHash)
if criticalError != nil {
fmt.Println("critical")
return
}

Expand All @@ -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()
Expand Down
35 changes: 18 additions & 17 deletions turbo/stages/stageloop.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit fb9f193

Please sign in to comment.