mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
core: fix beyondRoot condition
This commit is contained in:
parent
c6b0eb75fa
commit
60fb704da4
1 changed files with 22 additions and 18 deletions
|
|
@ -696,20 +696,17 @@ func (bc *BlockChain) rewindHashHead(root common.Hash) (*types.Header, uint64) {
|
||||||
// rewindPathHead implements the logic of rewindHead in the context of path scheme.
|
// rewindPathHead implements the logic of rewindHead in the context of path scheme.
|
||||||
func (bc *BlockChain) rewindPathHead(root common.Hash) (*types.Header, uint64) {
|
func (bc *BlockChain) rewindPathHead(root common.Hash) (*types.Header, uint64) {
|
||||||
var (
|
var (
|
||||||
headBlock = bc.CurrentBlock() // Head block of the chain
|
head = bc.CurrentBlock() // Head block of the chain
|
||||||
pivot = rawdb.ReadLastPivotNumber(bc.db) // Associated block number of pivot block
|
pivot = rawdb.ReadLastPivotNumber(bc.db) // Associated block number of pivot block
|
||||||
rootNumber uint64 // Associated block number of requested root
|
rootNumber uint64 // Associated block number of requested root
|
||||||
|
|
||||||
|
// BeyondRoot represents whether the requested root is already crossed.
|
||||||
|
// The flag value is set to true if the root is empty.
|
||||||
|
beyondRoot = root == common.Hash{}
|
||||||
|
|
||||||
start = time.Now() // Timestamp the rewinding is restarted
|
start = time.Now() // Timestamp the rewinding is restarted
|
||||||
logged = time.Now() // Timestamp last progress log was printed
|
logged = time.Now() // Timestamp last progress log was printed
|
||||||
)
|
)
|
||||||
// BeyondRoot represents whether the requested root is already crossed.
|
|
||||||
// The flag value is set to true if the root is empty, or reaching the
|
|
||||||
// root is deemed impossible.
|
|
||||||
beyondRoot := root == common.Hash{}
|
|
||||||
if !beyondRoot && !bc.HasState(root) && !bc.stateRecoverable(root) {
|
|
||||||
beyondRoot = true
|
|
||||||
}
|
|
||||||
// Rewind the head block tag until an available state is found.
|
// Rewind the head block tag until an available state is found.
|
||||||
for {
|
for {
|
||||||
logger := log.Trace
|
logger := log.Trace
|
||||||
|
|
@ -717,34 +714,41 @@ func (bc *BlockChain) rewindPathHead(root common.Hash) (*types.Header, uint64) {
|
||||||
logged = time.Now()
|
logged = time.Now()
|
||||||
logger = log.Info
|
logger = log.Info
|
||||||
}
|
}
|
||||||
logger("Block state missing, rewinding further", "number", headBlock.Number, "hash", headBlock.Hash(), "elapsed", common.PrettyDuration(time.Since(start)))
|
logger("Block state missing, rewinding further", "number", head.Number, "hash", head.Hash(), "elapsed", common.PrettyDuration(time.Since(start)))
|
||||||
|
|
||||||
// If a root threshold was requested but not yet crossed, check
|
// If a root threshold was requested but not yet crossed, check
|
||||||
if !beyondRoot && headBlock.Root == root {
|
if !beyondRoot && head.Root == root {
|
||||||
beyondRoot, rootNumber = true, headBlock.Number.Uint64()
|
beyondRoot, rootNumber = true, head.Number.Uint64()
|
||||||
|
}
|
||||||
|
// If the root threshold hasn't been crossed but the available
|
||||||
|
// state is found, disable root searching if it's regarded
|
||||||
|
// impossible to reach.
|
||||||
|
if !beyondRoot && bc.HasState(head.Root) {
|
||||||
|
beyondRoot = !bc.HasState(root) && !bc.stateRecoverable(root)
|
||||||
}
|
}
|
||||||
// Check if the associated state is available or recoverable if
|
// Check if the associated state is available or recoverable if
|
||||||
// the requested root has already been crossed.
|
// the requested root has already been crossed.
|
||||||
if beyondRoot && (bc.HasState(headBlock.Root) || bc.stateRecoverable(headBlock.Root)) {
|
if beyondRoot && (bc.HasState(head.Root) || bc.stateRecoverable(head.Root)) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// If pivot block is reached, return the genesis block as the
|
// If pivot block is reached, return the genesis block as the
|
||||||
// new chain head. Theoretically there must be a persistent
|
// new chain head. Theoretically there must be a persistent
|
||||||
// state before or at the pivot block, prevent endless rewinding
|
// state before or at the pivot block, prevent endless rewinding
|
||||||
// towards the genesis just in case.
|
// towards the genesis just in case.
|
||||||
if pivot != nil && *pivot >= headBlock.Number.Uint64() {
|
if pivot != nil && *pivot >= head.Number.Uint64() {
|
||||||
log.Info("Pivot block reached, resetting to genesis", "number", headBlock.Number, "hash", headBlock.Hash())
|
log.Info("Pivot block reached, resetting to genesis", "number", head.Number, "hash", head.Hash())
|
||||||
return bc.genesisBlock.Header(), rootNumber
|
return bc.genesisBlock.Header(), rootNumber
|
||||||
}
|
}
|
||||||
headBlock = bc.GetHeader(headBlock.ParentHash, headBlock.Number.Uint64()-1) // Keep rewinding
|
head = bc.GetHeader(head.ParentHash, head.Number.Uint64()-1) // Keep rewinding
|
||||||
}
|
}
|
||||||
// Recover if the target state if it's not available yet.
|
// Recover if the target state if it's not available yet.
|
||||||
if !bc.HasState(headBlock.Root) {
|
if !bc.HasState(head.Root) {
|
||||||
if err := bc.triedb.Recover(headBlock.Root); err != nil {
|
if err := bc.triedb.Recover(head.Root); err != nil {
|
||||||
log.Crit("Failed to rollback state", "err", err)
|
log.Crit("Failed to rollback state", "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return headBlock, rootNumber
|
log.Info("Rewound to block with state", "number", head.Number, "hash", head.Hash())
|
||||||
|
return head, rootNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
// rewindHead searches the available states in the database and returns the associated
|
// rewindHead searches the available states in the database and returns the associated
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue