Staged Sync: check trie root hash stage (#490)

This commit is contained in:
Igor Mandrigin 2020-04-27 16:27:37 +03:00 committed by GitHub
parent ccc0c4eeb8
commit c516110121
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 66 additions and 16 deletions

View File

@ -36,7 +36,9 @@ func (d *Downloader) doStagedSyncWithFetchers(p *peerConnection, headersFetchers
/*
* Stage 3. Execute block bodies w/o calculating trie roots
*/
if err = d.spawnExecuteBlocksStage(); err != nil {
syncHeadNumber := uint64(0)
syncHeadNumber, err = d.spawnExecuteBlocksStage()
if err != nil {
return err
}
@ -44,7 +46,10 @@ func (d *Downloader) doStagedSyncWithFetchers(p *peerConnection, headersFetchers
// Further stages go there
log.Info("Sync stage 4/4. Validating final hash")
log.Info("Sync stage 4/4. Validating final hash... NOT IMPLEMENTED")
if err = d.spawnCheckFinalHashStage(syncHeadNumber); err != nil {
return err
}
log.Info("Sync stage 4/4. Validating final hash... Complete!")
return err
}

View File

@ -6,13 +6,13 @@ import (
"github.com/ledgerwatch/turbo-geth/log"
)
func (d *Downloader) spawnExecuteBlocksStage() error {
origin, err := GetStageProgress(d.stateDB, Execution)
func (d *Downloader) spawnExecuteBlocksStage() (uint64, error) {
lastProcessedBlockNumber, err := GetStageProgress(d.stateDB, Execution)
if err != nil {
return err
return 0, err
}
currentBlockNumber := origin + 1
nextBlockNumber := lastProcessedBlockNumber + 1
mutation := d.stateDB.NewBatch()
defer func() {
@ -25,37 +25,38 @@ func (d *Downloader) spawnExecuteBlocksStage() error {
var incarnationMap = make(map[common.Address]uint64)
for {
block := d.blockchain.GetBlockByNumber(currentBlockNumber)
block := d.blockchain.GetBlockByNumber(nextBlockNumber)
if block == nil {
break
}
stateReader := state.NewDbStateReader(mutation)
stateWriter := state.NewDbStateWriter(mutation, currentBlockNumber, incarnationMap)
stateWriter := state.NewDbStateWriter(mutation, nextBlockNumber, incarnationMap)
if currentBlockNumber%1000 == 0 {
log.Info("Executed blocks:", "blockNumber", currentBlockNumber)
if nextBlockNumber%1000 == 0 {
log.Info("Executed blocks:", "blockNumber", nextBlockNumber)
}
// where the magic happens
err = d.blockchain.ExecuteBlockEuphemerally(block, stateReader, stateWriter)
if err != nil {
return err
return 0, err
}
if err = SaveStageProgress(mutation, Execution, currentBlockNumber); err != nil {
return err
if err = SaveStageProgress(mutation, Execution, nextBlockNumber); err != nil {
return 0, err
}
currentBlockNumber++
nextBlockNumber++
if mutation.BatchSize() >= mutation.IdealBatchSize() {
if _, err = mutation.Commit(); err != nil {
return err
return 0, err
}
mutation = d.stateDB.NewBatch()
incarnationMap = make(map[common.Address]uint64)
}
}
return nil
return nextBlockNumber - 1 /* the last processed block */, nil
}

View File

@ -0,0 +1,43 @@
package downloader
import (
"github.com/ledgerwatch/turbo-geth/log"
"github.com/ledgerwatch/turbo-geth/trie"
"github.com/pkg/errors"
)
func (d *Downloader) spawnCheckFinalHashStage(syncHeadNumber uint64) error {
hashProgress, err := GetStageProgress(d.stateDB, HashCheck)
if err != nil {
return err
}
if hashProgress == syncHeadNumber {
// we already did hash check for this block
// we don't do the obvious `if hashProgress > syncHeadNumber` to support reorgs more naturally
return nil
}
syncHeadBlock := d.blockchain.GetBlockByNumber(syncHeadNumber)
// make sure that we won't write the the real DB
// should never be commited
euphemeralMutation := d.stateDB.NewBatch()
blockNr := syncHeadBlock.Header().Number.Uint64()
tr := trie.New(syncHeadBlock.Root())
// making resolve request for the trie root, so we only get a hash
rr := tr.NewResolveRequest(nil, []byte{}, 0, tr.Root())
log.Info("Validating root hash", "block", blockNr, "blockRoot", syncHeadBlock.Root().Hex())
resolver := trie.NewResolver(0, true, blockNr)
resolver.AddRequest(rr)
err = resolver.ResolveStateful(euphemeralMutation, blockNr, false)
if err != nil {
return errors.Wrap(err, "checking root hash failed")
}
return SaveStageProgress(d.stateDB, HashCheck, blockNr)
}

View File

@ -31,6 +31,7 @@ const (
Headers SyncStage = iota // Headers are downloaded, their Proof-Of-Work validity and chaining is verified
Bodies // Block bodies are downloaded, TxHash and UncleHash are getting verified, "From" recovered from signatures
Execution // Executing each block w/o buildinf a trie
HashCheck // Checking the root hash
Finish // Nominal stage after all other stages
)