You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(core): store gap snapshot before writeHeadBlock to close crash window
UpdateMasternodes (called via UpdateM1) was invoked after writeHeadBlock,
leaving a window where the node head pointed to a gap block but no
corresponding snapshot existed in the database. If the process was killed
or restarted during the lengthy per-candidate EVM calls in UpdateM1, the
snapshot would never be written. On the next boot the node would load the
gap block as its head, then fail with:
Cannot find snapshot from last gap block err="leveldb: not found"
on every block in the following epoch, silently dropping out of consensus.
Fix: add updateM1ForBlock(block, statedb) which reads candidates and stakes
directly from the committed state trie (same as downloader.generateSnapshot)
without depending on bc.CurrentBlock() or bc.CurrentHeader(). Both the
canonical-chain path (writeBlockWithState) and the reorg path (reorg) now
call updateM1ForBlock with bc.StateAt(block.Root()) before writeHeadBlock,
so the snapshot is durable before the head markers are persisted.
The original UpdateM1 is retained unchanged for external callers and tests.
log.Crit("Fail to update masternodes during writeBlockWithState", "number", block.Number, "hash", block.Hash().Hex(), "err", err)
1694
+
gapState, stateErr:=bc.StateAt(block.Root())
1695
+
ifstateErr!=nil {
1696
+
log.Warn("Fail to open gap block state during writeBlockWithState, fallback to contract reads", "number", block.NumberU64(), "hash", block.Hash().Hex(), "err", stateErr)
returnNonStatTy, fmt.Errorf("failed to update masternodes during writeBlockWithState at block %d (%s): %w", block.NumberU64(), block.Hash().Hex(), err)
1693
1700
}
1694
1701
}
1702
+
// WriteBlock has already been called, no need to write again
log.Crit("Fail to update masternodes during reorg", "number", block.Number, "hash", block.Hash().Hex(), "err", err)
2603
+
gapState, stateErr:=bc.StateAt(block.Root())
2604
+
ifstateErr!=nil {
2605
+
log.Warn("Fail to open gap block state during reorg, fallback to contract reads", "number", block.NumberU64(), "hash", block.Hash().Hex(), "err", stateErr)
0 commit comments