Not to remove TD records on failed blocks (#2155)

* Not to remove TD records on failed blocks

* Commit tx when stopped

* Not to mess up stageloop commits

* Stop

* Fix header unwinds

Co-authored-by: Alex Sharp <alexsharp@Alexs-MacBook-Pro.local>
This commit is contained in:
ledgerwatch 2021-06-13 21:48:40 +01:00 committed by GitHub
parent 89edfe39db
commit c4cfd84b6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 25 deletions

View File

@ -1,7 +1,6 @@
package stagedsync
import (
"bytes"
"context"
"encoding/binary"
"fmt"
@ -260,7 +259,7 @@ func HeadersUnwind(u *UnwindState, s *StageState, tx ethdb.RwTx, cfg HeadersCfg)
if hash, err = rawdb.ReadCanonicalHash(tx, blockHeight); err != nil {
return err
}
rawdb.DeleteTd(tx, hash, blockHeight)
cfg.hd.BadHeaders[hash] = struct{}{}
}
if err = rawdb.DeleteCanonicalHash(tx, blockHeight); err != nil {
return err
@ -274,25 +273,23 @@ func HeadersUnwind(u *UnwindState, s *StageState, tx ethdb.RwTx, cfg HeadersCfg)
return cErr
}
defer tdCursor.Close()
var lastK, k, v []byte
lastK, v, err = tdCursor.Last()
var k, v []byte
k, v, err = tdCursor.Last()
if err != nil {
return err
}
if len(lastK) != 40 {
return fmt.Errorf("key in TD table has to be 40 bytes long: %x", lastK)
}
k = lastK
var maxTd big.Int
var maxHash common.Hash
copy(maxHash[:], lastK[8:])
var maxNum uint64 = binary.BigEndian.Uint64(lastK[:8])
if k != nil {
if err = rlp.DecodeBytes(v, &maxTd); err != nil {
return err
var maxNum uint64 = 0
for ; err == nil && k != nil; k, v, err = tdCursor.Prev() {
if len(k) != 40 {
return fmt.Errorf("key in TD table has to be 40 bytes long: %x", k)
}
var hash common.Hash
copy(hash[:], k[8:])
if _, bad := cfg.hd.BadHeaders[hash]; bad {
continue
}
}
for ; err == nil && k != nil && len(k) == 40 && bytes.Equal(k[:8], lastK[:8]); k, v, err = tdCursor.Prev() {
var td big.Int
if err = rlp.DecodeBytes(v, &td); err != nil {
return err
@ -306,14 +303,19 @@ func HeadersUnwind(u *UnwindState, s *StageState, tx ethdb.RwTx, cfg HeadersCfg)
if err != nil {
return err
}
if maxNum == 0 {
// Read genesis hash
if maxHash, err = rawdb.ReadCanonicalHash(tx, 0); err != nil {
return err
}
}
if err = rawdb.WriteHeadHeaderHash(tx, maxHash); err != nil {
return err
}
if err = s.DoneAndUpdate(tx, maxNum); err != nil {
return err
}
}
if err = u.Skip(tx); err != nil {
} else if err = u.Skip(tx); err != nil {
return err
}
if !useExternalTx {

View File

@ -3,7 +3,6 @@ package stages
import (
"context"
"crypto/ecdsa"
"errors"
"fmt"
"math/big"
"os"
@ -374,15 +373,19 @@ func (ms *MockSentry) InsertChain(chain *core.ChainPack) error {
initialCycle := false
highestSeenHeader := uint64(chain.TopBlock.NumberU64())
if err := StageLoopStep(ms.Ctx, ms.DB, ms.Sync, highestSeenHeader, ms.ChainConfig, notifier, initialCycle, nil, ms.UpdateHead, nil); err != nil {
if !errors.Is(err, common.ErrStopped) {
return err
}
return err
}
// Check if the latest header was imported or rolled back
if td, tdErr := rawdb.ReadTd(ethdb.NewObjectDatabase(ms.DB), chain.TopBlock.Hash(), chain.TopBlock.NumberU64()); tdErr != nil {
return tdErr
} else if td == nil {
return fmt.Errorf("did not import block %d %x", chain.TopBlock.NumberU64(), chain.TopBlock.Hash())
if err = ms.DB.View(ms.Ctx, func(tx ethdb.Tx) error {
if rawdb.ReadHeader(tx, chain.TopBlock.Hash(), chain.TopBlock.NumberU64()) == nil {
return fmt.Errorf("did not import block %d %x", chain.TopBlock.NumberU64(), chain.TopBlock.Hash())
}
return nil
}); err != nil {
return err
}
if _, bad := ms.downloader.Hd.BadHeaders[chain.TopBlock.Hash()]; bad {
return fmt.Errorf("block %d %x was invalid", chain.TopBlock.NumberU64(), chain.TopBlock.Hash())
}
return nil
}